[1/3] MIPS: __delay CPU_DADDI_WORKAROUNDS bug fix

Message ID alpine.LFD.2.11.1404010020510.27402@eddie.linux-mips.org
State Accepted
Delegated to: Ralf Baechle
Headers show

Commit Message

Maciej W. Rozycki March 31, 2014, 11:57 p.m.
With CPU_DADDI_WORKAROUNDS enabled __delay assembles with a macro in a 
branch delay slot:

{standard input}: Assembler messages:
{standard input}:18: Warning: Macro instruction expanded into multiple 
instructions in a branch delay slot

and broken code results:

0000000000000000 <__delay>:
   0:	1480ffff 	bnez	a0,0 <__delay>
   4:	24010001 	li	at,1
   8:	0081202f 	dsubu	a0,a0,at
   c:	03e00008 	jr	ra
  10:	00000000 	nop
  14:	00000000 	nop

Consequently the function loops indefinitely, showing up prominently as a 
hang in the delay loop calibration at bootstrap.

This change corrects the problem by forcing the immediate 1 into a 
register while keeping code produced identical where CPU_DADDI_WORKAROUNDS 
is disabled.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-delay-nodaddi-fix.patch

Comments

Matt Turner April 3, 2014, 3:05 a.m. | #1
On Mon, Mar 31, 2014 at 4:57 PM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> linux-mips-delay-nodaddi-fix.patch
> Index: linux-20140329-4maxp64/arch/mips/lib/delay.c
> ===================================================================
> --- linux-20140329-4maxp64.orig/arch/mips/lib/delay.c
> +++ linux-20140329-4maxp64/arch/mips/lib/delay.c

No comments about the patch. I'm simply curious why you don't use git?
Maciej W. Rozycki April 8, 2014, 2:43 p.m. | #2
On Wed, 2 Apr 2014, Matt Turner wrote:

> No comments about the patch. I'm simply curious why you don't use git?

 The tools I use work just fine for me, I don't feel compelled to switch.

  Maciej

Patch

Index: linux-20140329-4maxp64/arch/mips/lib/delay.c
===================================================================
--- linux-20140329-4maxp64.orig/arch/mips/lib/delay.c
+++ linux-20140329-4maxp64/arch/mips/lib/delay.c
@@ -6,7 +6,7 @@ 
  * Copyright (C) 1994 by Waldorf Electronics
  * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2007  Maciej W. Rozycki
+ * Copyright (C) 2007, 2014 Maciej W. Rozycki
  */
 #include <linux/module.h>
 #include <linux/param.h>
@@ -15,6 +15,12 @@ 
 #include <asm/compiler.h>
 #include <asm/war.h>
 
+#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
+#define GCC_DADDI_IMM_ASM() "I"
+#else
+#define GCC_DADDI_IMM_ASM() "r"
+#endif
+
 void __delay(unsigned long loops)
 {
 	__asm__ __volatile__ (
@@ -22,13 +28,13 @@  void __delay(unsigned long loops)
 	"	.align	3					\n"
 	"1:	bnez	%0, 1b					\n"
 #if BITS_PER_LONG == 32
-	"	subu	%0, 1					\n"
+	"	subu	%0, %1					\n"
 #else
-	"	dsubu	%0, 1					\n"
+	"	dsubu	%0, %1					\n"
 #endif
 	"	.set	reorder					\n"
 	: "=r" (loops)
-	: "0" (loops));
+	: GCC_DADDI_IMM_ASM() (1), "0" (loops));
 }
 EXPORT_SYMBOL(__delay);