Skip to content

Commit

Permalink
MIPS: __delay CPU_DADDI_WORKAROUNDS bug fix
Browse files Browse the repository at this point in the history
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>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6669/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Maciej W. Rozycki authored and Ralf Baechle committed May 12, 2014
1 parent 824122a commit 2db4bc3
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions arch/mips/lib/delay.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -15,20 +15,26 @@
#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__ (
" .set noreorder \n"
" .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);

Expand Down

0 comments on commit 2db4bc3

Please sign in to comment.