summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0204-net-Have-__napi_schedule_irqoff-disable-interrupts-o.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches-rt/0204-net-Have-__napi_schedule_irqoff-disable-interrupts-o.patch77
1 files changed, 77 insertions, 0 deletions
diff --git a/debian/patches-rt/0204-net-Have-__napi_schedule_irqoff-disable-interrupts-o.patch b/debian/patches-rt/0204-net-Have-__napi_schedule_irqoff-disable-interrupts-o.patch
new file mode 100644
index 000000000..5a4aed73f
--- /dev/null
+++ b/debian/patches-rt/0204-net-Have-__napi_schedule_irqoff-disable-interrupts-o.patch
@@ -0,0 +1,77 @@
+From 2faaff72af2ce49a00236dbfe09246e3099229ec Mon Sep 17 00:00:00 2001
+From: Steven Rostedt <rostedt@goodmis.org>
+Date: Tue, 6 Dec 2016 17:50:30 -0500
+Subject: [PATCH 204/347] net: Have __napi_schedule_irqoff() disable interrupts
+ on RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.246-rt110.tar.xz
+
+A customer hit a crash where the napi sd->poll_list became corrupted.
+The customer had the bnx2x driver, which does a
+__napi_schedule_irqoff() in its interrupt handler. Unfortunately, when
+running with CONFIG_PREEMPT_RT_FULL, this interrupt handler is run as a
+thread and is preemptable. The call to ____napi_schedule() must be done
+with interrupts disabled to protect the per cpu softnet_data's
+"poll_list, which is protected by disabling interrupts (disabling
+preemption is enough when all interrupts are threaded and
+local_bh_disable() can't preempt)."
+
+As bnx2x isn't the only driver that does this, the safest thing to do
+is to make __napi_schedule_irqoff() call __napi_schedule() instead when
+CONFIG_PREEMPT_RT_FULL is enabled, which will call local_irq_save()
+before calling ____napi_schedule().
+
+Cc: stable-rt@vger.kernel.org
+Signed-off-by: Steven Rostedt (Red Hat) <rostedt@goodmis.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/netdevice.h | 12 ++++++++++++
+ net/core/dev.c | 2 ++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index dfec34087039..c4713217b20e 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -423,7 +423,19 @@ typedef enum rx_handler_result rx_handler_result_t;
+ typedef rx_handler_result_t rx_handler_func_t(struct sk_buff **pskb);
+
+ void __napi_schedule(struct napi_struct *n);
++
++/*
++ * When PREEMPT_RT_FULL is defined, all device interrupt handlers
++ * run as threads, and they can also be preempted (without PREEMPT_RT
++ * interrupt threads can not be preempted). Which means that calling
++ * __napi_schedule_irqoff() from an interrupt handler can be preempted
++ * and can corrupt the napi->poll_list.
++ */
++#ifdef CONFIG_PREEMPT_RT_FULL
++#define __napi_schedule_irqoff(n) __napi_schedule(n)
++#else
+ void __napi_schedule_irqoff(struct napi_struct *n);
++#endif
+
+ static inline bool napi_disable_pending(struct napi_struct *n)
+ {
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 7c59fa4d3ecf..e65dc7a7cc13 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -5953,6 +5953,7 @@ bool napi_schedule_prep(struct napi_struct *n)
+ }
+ EXPORT_SYMBOL(napi_schedule_prep);
+
++#ifndef CONFIG_PREEMPT_RT_FULL
+ /**
+ * __napi_schedule_irqoff - schedule for receive
+ * @n: entry to schedule
+@@ -5971,6 +5972,7 @@ void __napi_schedule_irqoff(struct napi_struct *n)
+ __napi_schedule(n);
+ }
+ EXPORT_SYMBOL(__napi_schedule_irqoff);
++#endif
+
+ bool napi_complete_done(struct napi_struct *n, int work_done)
+ {
+--
+2.36.1
+