aboutsummaryrefslogtreecommitdiff
path: root/arch/blackfin/kernel/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/entry.S')
-rw-r--r--arch/blackfin/kernel/entry.S24
1 files changed, 22 insertions, 2 deletions
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index a9cfba9946b..3f8769b7db5 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -43,8 +43,28 @@
ENTRY(_ret_from_fork)
#ifdef CONFIG_IPIPE
- [--sp] = reti; /* IRQs on. */
- SP += 4;
+ /*
+ * Hw IRQs are off on entry, and we don't want the scheduling tail
+ * code to starve high priority domains from interrupts while it
+ * runs. Therefore we first stall the root stage to have the
+ * virtual interrupt state reflect IMASK.
+ */
+ p0.l = ___ipipe_root_status;
+ p0.h = ___ipipe_root_status;
+ r4 = [p0];
+ bitset(r4, 0);
+ [p0] = r4;
+ /*
+ * Then we may enable hw IRQs, allowing preemption from high
+ * priority domains. schedule_tail() will do local_irq_enable()
+ * since Blackfin does not define __ARCH_WANT_UNLOCKED_CTXSW, so
+ * there is no need to unstall the root domain by ourselves
+ * afterwards.
+ */
+ p0.l = _bfin_irq_flags;
+ p0.h = _bfin_irq_flags;
+ r4 = [p0];
+ sti r4;
#endif /* CONFIG_IPIPE */
SP += -12;
call _schedule_tail;