Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2db4bc34 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle
Browse files

MIPS: __delay CPU_DADDI_WORKAROUNDS bug fix



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: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6669/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 824122a3
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -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);