[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