aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2020-10-13 22:35:27 +0200
committerHeiko Carstens <hca@linux.ibm.com>2020-11-09 11:20:58 +0100
commit85cde0192a983b227341be11af2c3625d39bc374 (patch)
tree5f2ad53b6f1cc90058350ebe04f7e342b509ca09
parents390/head: set io/ext handlers to disabled wait (diff)
downloadlinux-dev-85cde0192a983b227341be11af2c3625d39bc374.tar.xz
linux-dev-85cde0192a983b227341be11af2c3625d39bc374.zip
s390/udelay: make it work for the early code
Currently udelay relies on working EXT interrupts handler, which is not the case during early startup. In such cases udelay_simple() has to be used instead. To avoid mistakes of calling udelay too early, which could happen from the common code as well - make udelay work for the early code by introducing static branch and redirecting all udelay calls to udelay_simple until EXT interrupts handler is fully initialized and async stack is allocated. Reviewed-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
-rw-r--r--arch/s390/include/asm/delay.h1
-rw-r--r--arch/s390/kernel/setup.c1
-rw-r--r--arch/s390/lib/delay.c13
3 files changed, 15 insertions, 0 deletions
diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h
index 898323fd93d2..4a08379cd1eb 100644
--- a/arch/s390/include/asm/delay.h
+++ b/arch/s390/include/asm/delay.h
@@ -13,6 +13,7 @@
#ifndef _S390_DELAY_H
#define _S390_DELAY_H
+void udelay_enable(void);
void __ndelay(unsigned long long nsecs);
void __udelay(unsigned long long usecs);
void udelay_simple(unsigned long long usecs);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 4d843e64496f..2076415aee4b 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -336,6 +336,7 @@ int __init arch_early_irq_init(void)
if (!stack)
panic("Couldn't allocate async stack");
S390_lowcore.async_stack = stack + STACK_INIT_OFFSET;
+ udelay_enable();
return 0;
}
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index daca7bad66de..1734a5c19834 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -13,11 +13,19 @@
#include <linux/export.h>
#include <linux/irqflags.h>
#include <linux/interrupt.h>
+#include <linux/jump_label.h>
#include <linux/irq.h>
#include <asm/vtimer.h>
#include <asm/div64.h>
#include <asm/idle.h>
+static DEFINE_STATIC_KEY_FALSE(udelay_ready);
+
+void __init udelay_enable(void)
+{
+ static_branch_enable(&udelay_ready);
+}
+
void __delay(unsigned long loops)
{
/*
@@ -77,6 +85,11 @@ void __udelay(unsigned long long usecs)
{
unsigned long flags;
+ if (!static_branch_likely(&udelay_ready)) {
+ udelay_simple(usecs);
+ return;
+ }
+
preempt_disable();
local_irq_save(flags);
if (in_irq()) {