[PATCH] no-spin-after-disable
Chris Wilson
chris at chris-wilson.co.uk
Sat Mar 17 09:49:28 UTC 2018
---
include/linux/interrupt.h | 4 ++++
kernel/softirq.c | 13 +++++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 69c238210325..cc268b54b3ac 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -607,10 +607,14 @@ static inline void tasklet_disable(struct tasklet_struct *t)
smp_mb();
}
+extern void __tasklet_reschedule(struct tasklet_struct *t);
+
static inline void tasklet_enable(struct tasklet_struct *t)
{
smp_mb__before_atomic();
atomic_dec(&t->count);
+ if (test_bit(TASKLET_STATE_SCHED, &t->state))
+ __tasklet_reschedule(t);
}
extern void tasklet_kill(struct tasklet_struct *t);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 24d243ef8e71..f5bbbd9e89ba 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -460,6 +460,16 @@ struct tasklet_head {
static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
+void __tasklet_reschedule(struct tasklet_struct *t)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ or_softirq_pending(BIT(HI_SOFTIRQ) | BIT(TASKLET_SOFTIRQ));
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__tasklet_reschedule);
+
void __tasklet_schedule(struct tasklet_struct *t)
{
unsigned long flags;
@@ -517,7 +527,6 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
t->next = NULL;
*__this_cpu_read(tasklet_vec.tail) = t;
__this_cpu_write(tasklet_vec.tail, &(t->next));
- __raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_enable();
}
}
@@ -553,7 +562,6 @@ static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
t->next = NULL;
*__this_cpu_read(tasklet_hi_vec.tail) = t;
__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
- __raise_softirq_irqoff(HI_SOFTIRQ);
local_irq_enable();
}
}
@@ -576,6 +584,7 @@ void tasklet_kill(struct tasklet_struct *t)
while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
do {
+ __tasklet_reschedule(t);
yield();
} while (test_bit(TASKLET_STATE_SCHED, &t->state));
}
--
2.16.2
More information about the Intel-gfx-trybot
mailing list