diff options
2 files changed, 57 insertions, 4 deletions
diff --git a/target/linux/generic/backport-5.10/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch b/target/linux/generic/backport-5.10/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch new file mode 100644 index 0000000000..4b83641291 --- /dev/null +++ b/target/linux/generic/backport-5.10/604-v5.12-net-fix-hangup-on-napi_disable-for-threaded-napi.patch @@ -0,0 +1,53 @@ +From: Paolo Abeni <pabeni@redhat.com> +Date: Fri, 9 Apr 2021 17:24:17 +0200 +Subject: [PATCH] net: fix hangup on napi_disable for threaded napi + +napi_disable() is subject to an hangup, when the threaded +mode is enabled and the napi is under heavy traffic. + +If the relevant napi has been scheduled and the napi_disable() +kicks in before the next napi_threaded_wait() completes - so +that the latter quits due to the napi_disable_pending() condition, +the existing code leaves the NAPI_STATE_SCHED bit set and the +napi_disable() loop waiting for such bit will hang. + +This patch addresses the issue by dropping the NAPI_STATE_DISABLE +bit test in napi_thread_wait(). The later napi_threaded_poll() +iteration will take care of clearing the NAPI_STATE_SCHED. + +This also addresses a related problem reported by Jakub: +before this patch a napi_disable()/napi_enable() pair killed +the napi thread, effectively disabling the threaded mode. +On the patched kernel napi_disable() simply stops scheduling +the relevant thread. + +v1 -> v2: + - let the main napi_thread_poll() loop clear the SCHED bit + +Reported-by: Jakub Kicinski <kuba@kernel.org> +Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Reviewed-by: Eric Dumazet <edumazet@google.com> +Link: https://lore.kernel.org/r/883923fa22745a9589e8610962b7dc59df09fb1f.1617981844.git.pabeni@redhat.com +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -6951,7 +6951,7 @@ static int napi_thread_wait(struct napi_ + + set_current_state(TASK_INTERRUPTIBLE); + +- while (!kthread_should_stop() && !napi_disable_pending(napi)) { ++ while (!kthread_should_stop()) { + /* Testing SCHED_THREADED bit here to make sure the current + * kthread owns this napi and could poll on this napi. + * Testing SCHED bit is not enough because SCHED bit might be +@@ -6969,6 +6969,7 @@ static int napi_thread_wait(struct napi_ + set_current_state(TASK_INTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); ++ + return -1; + } + diff --git a/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 8b5ec9c305..3b485e3cc9 100644 --- a/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> if (netif_elide_gro(skb->dev)) goto normal; -@@ -7986,6 +7989,48 @@ static void __netdev_adjacent_dev_unlink +@@ -7987,6 +7990,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -8037,6 +8082,7 @@ static int __netdev_upper_dev_link(struc +@@ -8038,6 +8083,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -99,7 +99,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -8133,6 +8179,7 @@ static void __netdev_upper_dev_unlink(st +@@ -8134,6 +8180,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8919,6 +8966,7 @@ int dev_set_mac_address(struct net_devic +@@ -8920,6 +8967,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; |