Commit 85cde019 authored by Vasily Gorbik's avatar Vasily Gorbik Committed by Heiko Carstens

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: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 13b5bd8a
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#ifndef _S390_DELAY_H #ifndef _S390_DELAY_H
#define _S390_DELAY_H #define _S390_DELAY_H
void udelay_enable(void);
void __ndelay(unsigned long long nsecs); void __ndelay(unsigned long long nsecs);
void __udelay(unsigned long long usecs); void __udelay(unsigned long long usecs);
void udelay_simple(unsigned long long usecs); void udelay_simple(unsigned long long usecs);
......
...@@ -336,6 +336,7 @@ int __init arch_early_irq_init(void) ...@@ -336,6 +336,7 @@ int __init arch_early_irq_init(void)
if (!stack) if (!stack)
panic("Couldn't allocate async stack"); panic("Couldn't allocate async stack");
S390_lowcore.async_stack = stack + STACK_INIT_OFFSET; S390_lowcore.async_stack = stack + STACK_INIT_OFFSET;
udelay_enable();
return 0; return 0;
} }
......
...@@ -13,11 +13,19 @@ ...@@ -13,11 +13,19 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/irqflags.h> #include <linux/irqflags.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jump_label.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <asm/vtimer.h> #include <asm/vtimer.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <asm/idle.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) void __delay(unsigned long loops)
{ {
/* /*
...@@ -77,6 +85,11 @@ void __udelay(unsigned long long usecs) ...@@ -77,6 +85,11 @@ void __udelay(unsigned long long usecs)
{ {
unsigned long flags; unsigned long flags;
if (!static_branch_likely(&udelay_ready)) {
udelay_simple(usecs);
return;
}
preempt_disable(); preempt_disable();
local_irq_save(flags); local_irq_save(flags);
if (in_irq()) { if (in_irq()) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment