From: Sasha Levin Date: Sun, 15 Jun 2025 13:01:13 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v6.6.94~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f7b99dc619ee57d1258049f5863e5761f6e3a2f;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/ath10k-add-atomic-protection-for-device-recovery.patch b/queue-5.10/ath10k-add-atomic-protection-for-device-recovery.patch new file mode 100644 index 0000000000..76213cbdec --- /dev/null +++ b/queue-5.10/ath10k-add-atomic-protection-for-device-recovery.patch @@ -0,0 +1,203 @@ +From 12343689d916e60dcc28ca7e22f8afbf15a49a85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Sep 2020 04:13:06 +0000 +Subject: ath10k: add atomic protection for device recovery + +From: Wen Gong + +[ Upstream commit 5dadbe4e3718fb2214199b6dc7af1077fe14bf32 ] + +When it has more than one restart_work queued meanwhile, the 2nd +restart_work is very easy to break the 1st restart work and lead +recovery fail. + +Add a flag to allow only one restart work running untill +device successfully recovered. + +It already has flag ATH10K_FLAG_CRASH_FLUSH, but it can not use this +flag again, because it is clear in ath10k_core_start. The function +ieee80211_reconfig(called by ieee80211_restart_work) of mac80211 do +many things and drv_start(call to ath10k_core_start) is 1st thing, +when drv_start complete, it does not mean restart complete. So it +add new flag and clear it in ath10k_reconfig_complete, because it +is the last thing called from drv_reconfig_complete of function +ieee80211_reconfig, after it, the restart process finished. + +Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 + +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/010101746bead6a0-d5e97c66-dedd-4b92-810e-c2e4840fafc9-000000@us-west-2.amazonses.com +Stable-dep-of: 1650d32b92b0 ("ath10k: snoc: fix unbalanced IRQ enable in crash recovery") +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/core.c | 11 +++++++++++ + drivers/net/wireless/ath/ath10k/core.h | 4 ++++ + drivers/net/wireless/ath/ath10k/debug.c | 6 +++--- + drivers/net/wireless/ath/ath10k/mac.c | 1 + + drivers/net/wireless/ath/ath10k/pci.c | 2 +- + drivers/net/wireless/ath/ath10k/sdio.c | 6 +++--- + drivers/net/wireless/ath/ath10k/snoc.c | 2 +- + drivers/net/wireless/ath/ath10k/wmi.c | 2 +- + 8 files changed, 25 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index d03a36c45f9f3..8ce5fbfcee972 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -2292,6 +2292,17 @@ static int ath10k_init_hw_params(struct ath10k *ar) + return 0; + } + ++void ath10k_core_start_recovery(struct ath10k *ar) ++{ ++ if (test_and_set_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags)) { ++ ath10k_warn(ar, "already restarting\n"); ++ return; ++ } ++ ++ queue_work(ar->workqueue, &ar->restart_work); ++} ++EXPORT_SYMBOL(ath10k_core_start_recovery); ++ + static void ath10k_core_restart(struct work_struct *work) + { + struct ath10k *ar = container_of(work, struct ath10k, restart_work); +diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h +index b50ab9e229dc5..b471c0ccf006b 100644 +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -857,6 +857,9 @@ enum ath10k_dev_flags { + + /* Per Station statistics service */ + ATH10K_FLAG_PEER_STATS, ++ ++ /* Indicates that ath10k device is during recovery process and not complete */ ++ ATH10K_FLAG_RESTARTING, + }; + + enum ath10k_cal_mode { +@@ -1312,6 +1315,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, + const struct ath10k_fw_components *fw_components); + int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); + void ath10k_core_stop(struct ath10k *ar); ++void ath10k_core_start_recovery(struct ath10k *ar); + int ath10k_core_register(struct ath10k *ar, + const struct ath10k_bus_params *bus_params); + void ath10k_core_unregister(struct ath10k *ar); +diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c +index ab737177a86bf..64d48d8cce50c 100644 +--- a/drivers/net/wireless/ath/ath10k/debug.c ++++ b/drivers/net/wireless/ath/ath10k/debug.c +@@ -583,7 +583,7 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, + ret = ath10k_debug_fw_assert(ar); + } else if (!strcmp(buf, "hw-restart")) { + ath10k_info(ar, "user requested hw restart\n"); +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + ret = 0; + } else { + ret = -EINVAL; +@@ -2005,7 +2005,7 @@ static ssize_t ath10k_write_btcoex(struct file *file, + } + } else { + ath10k_info(ar, "restarting firmware due to btcoex change"); +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + } + + if (val) +@@ -2136,7 +2136,7 @@ static ssize_t ath10k_write_peer_stats(struct file *file, + + ath10k_info(ar, "restarting firmware due to Peer stats change"); + +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + ret = count; + + exit: +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index 323b6763cb0f5..5dd0239e9d51b 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -7969,6 +7969,7 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw, + ath10k_info(ar, "device successfully recovered\n"); + ar->state = ATH10K_STATE_ON; + ieee80211_wake_queues(ar->hw); ++ clear_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags); + } + + mutex_unlock(&ar->conf_mutex); +diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c +index 2c8f04b415c71..83ef0517f0991 100644 +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -1774,7 +1774,7 @@ static void ath10k_pci_fw_dump_work(struct work_struct *work) + + mutex_unlock(&ar->dump_mutex); + +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + } + + static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) +diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c +index 418e40560f59f..2ccbb6b4f1b5b 100644 +--- a/drivers/net/wireless/ath/ath10k/sdio.c ++++ b/drivers/net/wireless/ath/ath10k/sdio.c +@@ -562,7 +562,7 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar, + ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH); + ret = -ENOMEM; + +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + ath10k_warn(ar, "exceeds length, start recovery\n"); + + goto err; +@@ -961,7 +961,7 @@ static int ath10k_sdio_mbox_read_int_status(struct ath10k *ar, + ret = ath10k_sdio_read(ar, MBOX_HOST_INT_STATUS_ADDRESS, + irq_proc_reg, sizeof(*irq_proc_reg)); + if (ret) { +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + ath10k_warn(ar, "read int status fail, start recovery\n"); + goto out; + } +@@ -2505,7 +2505,7 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) + + ath10k_sdio_enable_intrs(ar); + +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + } + + static int ath10k_sdio_probe(struct sdio_func *func, +diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c +index f7ee1032b1729..ee5b16d79f14f 100644 +--- a/drivers/net/wireless/ath/ath10k/snoc.c ++++ b/drivers/net/wireless/ath/ath10k/snoc.c +@@ -1315,7 +1315,7 @@ int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type) + switch (type) { + case ATH10K_QMI_EVENT_FW_READY_IND: + if (test_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags)) { +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + break; + } + +diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c +index dc5d9f9be34f0..c9a74f3e2e601 100644 +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -1957,7 +1957,7 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) + if (ret == -EAGAIN) { + ath10k_warn(ar, "wmi command %d timeout, restarting hardware\n", + cmd_id); +- queue_work(ar->workqueue, &ar->restart_work); ++ ath10k_core_start_recovery(ar); + } + + return ret; +-- +2.39.5 + diff --git a/queue-5.10/ath10k-prevent-deinitializing-napi-twice.patch b/queue-5.10/ath10k-prevent-deinitializing-napi-twice.patch new file mode 100644 index 0000000000..7cf4337337 --- /dev/null +++ b/queue-5.10/ath10k-prevent-deinitializing-napi-twice.patch @@ -0,0 +1,380 @@ +From 1f8571913f29bc9e8c4a1c1187bc40c722262dcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Dec 2020 08:35:04 +0200 +Subject: ath10k: prevent deinitializing NAPI twice + +From: Wen Gong + +[ Upstream commit e2f8b74e58cb1560c1399ba94a470b770e858259 ] + +It happened "Kernel panic - not syncing: hung_task: blocked tasks" when +test simulate crash and ifconfig down/rmmod meanwhile. + +Test steps: + +1.Test commands, either can reproduce the hang for PCIe, SDIO and SNOC. +echo soft > /sys/kernel/debug/ieee80211/phy0/ath10k/simulate_fw_crash;sleep 0.05;ifconfig wlan0 down +echo soft > /sys/kernel/debug/ieee80211/phy0/ath10k/simulate_fw_crash;rmmod ath10k_sdio +echo hw-restart > /sys/kernel/debug/ieee80211/phy0/ath10k/simulate_fw_crash;rmmod ath10k_pci + +2. dmesg: +[ 5622.548630] ath10k_sdio mmc1:0001:1: simulating soft firmware crash +[ 5622.655995] ieee80211 phy0: Hardware restart was requested +[ 5776.355164] INFO: task shill:1572 blocked for more than 122 seconds. +[ 5776.355687] INFO: task kworker/1:2:24437 blocked for more than 122 seconds. +[ 5776.359812] Kernel panic - not syncing: hung_task: blocked tasks +[ 5776.359836] CPU: 1 PID: 55 Comm: khungtaskd Tainted: G W 4.19.86 #137 +[ 5776.359846] Hardware name: MediaTek krane sku176 board (DT) +[ 5776.359855] Call trace: +[ 5776.359868] dump_backtrace+0x0/0x170 +[ 5776.359881] show_stack+0x20/0x2c +[ 5776.359896] dump_stack+0xd4/0x10c +[ 5776.359916] panic+0x12c/0x29c +[ 5776.359937] hung_task_panic+0x0/0x50 +[ 5776.359953] kthread+0x120/0x130 +[ 5776.359965] ret_from_fork+0x10/0x18 +[ 5776.359986] SMP: stopping secondary CPUs +[ 5776.360012] Kernel Offset: 0x141ea00000 from 0xffffff8008000000 +[ 5776.360026] CPU features: 0x0,2188200c +[ 5776.360035] Memory Limit: none + +command "ifconfig wlan0 down" or "rmmod ath10k_sdio" will be blocked +callstack of ifconfig: +[<0>] __switch_to+0x120/0x13c +[<0>] msleep+0x28/0x38 +[<0>] ath10k_sdio_hif_stop+0x24c/0x294 [ath10k_sdio] +[<0>] ath10k_core_stop+0x50/0x78 [ath10k_core] +[<0>] ath10k_halt+0x120/0x178 [ath10k_core] +[<0>] ath10k_stop+0x4c/0x8c [ath10k_core] +[<0>] drv_stop+0xe0/0x1e4 [mac80211] +[<0>] ieee80211_stop_device+0x48/0x54 [mac80211] +[<0>] ieee80211_do_stop+0x678/0x6f8 [mac80211] +[<0>] ieee80211_stop+0x20/0x30 [mac80211] +[<0>] __dev_close_many+0xb8/0x11c +[<0>] __dev_change_flags+0xe0/0x1d0 +[<0>] dev_change_flags+0x30/0x6c +[<0>] devinet_ioctl+0x370/0x564 +[<0>] inet_ioctl+0xdc/0x304 +[<0>] sock_do_ioctl+0x50/0x288 +[<0>] compat_sock_ioctl+0x1b4/0x1aac +[<0>] __se_compat_sys_ioctl+0x100/0x26fc +[<0>] __arm64_compat_sys_ioctl+0x20/0x2c +[<0>] el0_svc_common+0xa4/0x154 +[<0>] el0_svc_compat_handler+0x2c/0x38 +[<0>] el0_svc_compat+0x8/0x18 +[<0>] 0xffffffffffffffff + +callstack of rmmod: +[<0>] __switch_to+0x120/0x13c +[<0>] msleep+0x28/0x38 +[<0>] ath10k_sdio_hif_stop+0x294/0x31c [ath10k_sdio] +[<0>] ath10k_core_stop+0x50/0x78 [ath10k_core] +[<0>] ath10k_halt+0x120/0x178 [ath10k_core] +[<0>] ath10k_stop+0x4c/0x8c [ath10k_core] +[<0>] drv_stop+0xe0/0x1e4 [mac80211] +[<0>] ieee80211_stop_device+0x48/0x54 [mac80211] +[<0>] ieee80211_do_stop+0x678/0x6f8 [mac80211] +[<0>] ieee80211_stop+0x20/0x30 [mac80211] +[<0>] __dev_close_many+0xb8/0x11c +[<0>] dev_close_many+0x70/0x100 +[<0>] dev_close+0x4c/0x80 +[<0>] cfg80211_shutdown_all_interfaces+0x50/0xcc [cfg80211] +[<0>] ieee80211_remove_interfaces+0x58/0x1a0 [mac80211] +[<0>] ieee80211_unregister_hw+0x40/0x100 [mac80211] +[<0>] ath10k_mac_unregister+0x1c/0x44 [ath10k_core] +[<0>] ath10k_core_unregister+0x38/0x7c [ath10k_core] +[<0>] ath10k_sdio_remove+0x8c/0xd0 [ath10k_sdio] +[<0>] sdio_bus_remove+0x48/0x108 +[<0>] device_release_driver_internal+0x138/0x1ec +[<0>] driver_detach+0x6c/0xa8 +[<0>] bus_remove_driver+0x78/0xa8 +[<0>] driver_unregister+0x30/0x50 +[<0>] sdio_unregister_driver+0x28/0x34 +[<0>] cleanup_module+0x14/0x6bc [ath10k_sdio] +[<0>] __arm64_sys_delete_module+0x1e0/0x22c +[<0>] el0_svc_common+0xa4/0x154 +[<0>] el0_svc_compat_handler+0x2c/0x38 +[<0>] el0_svc_compat+0x8/0x18 +[<0>] 0xffffffffffffffff + +SNOC: +[ 647.156863] Call trace: +[ 647.162166] [] __switch_to+0x120/0x13c +[ 647.164512] [] __schedule+0x5ec/0x798 +[ 647.170062] [] schedule+0x74/0x94 +[ 647.175050] [] schedule_timeout+0x314/0x42c +[ 647.179874] [] schedule_timeout_uninterruptible+0x34/0x40 +[ 647.185780] [] msleep+0x28/0x38 +[ 647.192546] [] ath10k_snoc_hif_stop+0x4c/0x1e0 [ath10k_snoc] +[ 647.197439] [] ath10k_core_stop+0x50/0x7c [ath10k_core] +[ 647.204652] [] ath10k_halt+0x114/0x16c [ath10k_core] +[ 647.211420] [] ath10k_stop+0x4c/0x88 [ath10k_core] +[ 647.217865] [] drv_stop+0x110/0x244 [mac80211] +[ 647.224367] [] ieee80211_stop_device+0x48/0x54 [mac80211] +[ 647.230359] [] ieee80211_do_stop+0x6a4/0x73c [mac80211] +[ 647.237033] [] ieee80211_stop+0x20/0x30 [mac80211] +[ 647.243942] [] __dev_close_many+0xa0/0xfc +[ 647.250435] [] dev_close_many+0x70/0x100 +[ 647.255651] [] dev_close+0x4c/0x80 +[ 647.261244] [] cfg80211_shutdown_all_interfaces+0x44/0xcc [cfg80211] +[ 647.266383] [] ieee80211_remove_interfaces+0x58/0x1b4 [mac80211] +[ 647.274128] [] ieee80211_unregister_hw+0x50/0x120 [mac80211] +[ 647.281659] [] ath10k_mac_unregister+0x1c/0x44 [ath10k_core] +[ 647.288839] [] ath10k_core_unregister+0x48/0x90 [ath10k_core] +[ 647.296027] [] ath10k_snoc_remove+0x5c/0x150 [ath10k_snoc] +[ 647.303229] [] platform_drv_remove+0x28/0x50 +[ 647.310517] [] device_release_driver_internal+0x114/0x1b8 +[ 647.316257] [] driver_detach+0x6c/0xa8 +[ 647.323021] [] bus_remove_driver+0x78/0xa8 +[ 647.328571] [] driver_unregister+0x30/0x50 +[ 647.334213] [] platform_driver_unregister+0x1c/0x28 +[ 647.339876] [] cleanup_module+0x1c/0x120 [ath10k_snoc] +[ 647.346196] [] SyS_delete_module+0x1dc/0x22c + +PCIe: +[ 615.392770] rmmod D 0 3523 3458 0x00000080 +[ 615.392777] Call Trace: +[ 615.392784] __schedule+0x617/0x7d3 +[ 615.392791] ? __mod_timer+0x263/0x35c +[ 615.392797] schedule+0x62/0x72 +[ 615.392803] schedule_timeout+0x8d/0xf3 +[ 615.392809] ? run_local_timers+0x6b/0x6b +[ 615.392814] msleep+0x1b/0x22 +[ 615.392824] ath10k_pci_hif_stop+0x68/0xd6 [ath10k_pci] +[ 615.392844] ath10k_core_stop+0x44/0x67 [ath10k_core] +[ 615.392859] ath10k_halt+0x102/0x153 [ath10k_core] +[ 615.392873] ath10k_stop+0x38/0x75 [ath10k_core] +[ 615.392893] drv_stop+0x9a/0x13c [mac80211] +[ 615.392915] ieee80211_do_stop+0x772/0x7cd [mac80211] +[ 615.392937] ieee80211_stop+0x1a/0x1e [mac80211] +[ 615.392945] __dev_close_many+0x9e/0xf0 +[ 615.392952] dev_close_many+0x62/0xe8 +[ 615.392958] dev_close+0x54/0x7d +[ 615.392975] cfg80211_shutdown_all_interfaces+0x6e/0xa5 [cfg80211] +[ 615.393021] ieee80211_remove_interfaces+0x52/0x1aa [mac80211] +[ 615.393049] ieee80211_unregister_hw+0x54/0x136 [mac80211] +[ 615.393068] ath10k_mac_unregister+0x19/0x4a [ath10k_core] +[ 615.393091] ath10k_core_unregister+0x39/0x7e [ath10k_core] +[ 615.393104] ath10k_pci_remove+0x3d/0x7f [ath10k_pci] +[ 615.393117] pci_device_remove+0x41/0xa6 +[ 615.393129] device_release_driver_internal+0x123/0x1ec +[ 615.393140] driver_detach+0x60/0x90 +[ 615.393152] bus_remove_driver+0x72/0x9f +[ 615.393164] pci_unregister_driver+0x1e/0x87 +[ 615.393177] SyS_delete_module+0x1d7/0x277 +[ 615.393188] do_syscall_64+0x6b/0xf7 +[ 615.393199] entry_SYSCALL_64_after_hwframe+0x41/0xa6 + +The test command run simulate_fw_crash firstly and it call into +ath10k_sdio_hif_stop from ath10k_core_restart, then napi_disable +is called and bit NAPI_STATE_SCHED is set. After that, function +ath10k_sdio_hif_stop is called again from ath10k_stop by command +"ifconfig wlan0 down" or "rmmod ath10k_sdio", then command blocked. + +It is blocked by napi_synchronize, napi_disable will set bit with +NAPI_STATE_SCHED, and then napi_synchronize will enter dead loop +becuase bit NAPI_STATE_SCHED is set by napi_disable. + +function of napi_synchronize +static inline void napi_synchronize(const struct napi_struct *n) +{ + if (IS_ENABLED(CONFIG_SMP)) + while (test_bit(NAPI_STATE_SCHED, &n->state)) + msleep(1); + else + barrier(); +} + +function of napi_disable +void napi_disable(struct napi_struct *n) +{ + might_sleep(); + set_bit(NAPI_STATE_DISABLE, &n->state); + + while (test_and_set_bit(NAPI_STATE_SCHED, &n->state)) + msleep(1); + while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state)) + msleep(1); + + hrtimer_cancel(&n->timer); + + clear_bit(NAPI_STATE_DISABLE, &n->state); +} + +Add flag for it avoid the hang and crash. + +Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 +Tested-on: WCN3990 hw1.0 SNOC hw1.0 WLAN.HL.3.1-01307.1-QCAHLSWMTPL-2 + +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1598617348-2325-1-git-send-email-wgong@codeaurora.org +Stable-dep-of: 1650d32b92b0 ("ath10k: snoc: fix unbalanced IRQ enable in crash recovery") +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/ahb.c | 5 ++--- + drivers/net/wireless/ath/ath10k/core.c | 25 +++++++++++++++++++++++++ + drivers/net/wireless/ath/ath10k/core.h | 5 +++++ + drivers/net/wireless/ath/ath10k/pci.c | 7 ++++--- + drivers/net/wireless/ath/ath10k/sdio.c | 5 ++--- + drivers/net/wireless/ath/ath10k/snoc.c | 6 +++--- + 6 files changed, 41 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c +index 05a61975c83f4..869524852fbaa 100644 +--- a/drivers/net/wireless/ath/ath10k/ahb.c ++++ b/drivers/net/wireless/ath/ath10k/ahb.c +@@ -626,7 +626,7 @@ static int ath10k_ahb_hif_start(struct ath10k *ar) + { + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n"); + +- napi_enable(&ar->napi); ++ ath10k_core_napi_enable(ar); + ath10k_ce_enable_interrupts(ar); + ath10k_pci_enable_legacy_irq(ar); + +@@ -644,8 +644,7 @@ static void ath10k_ahb_hif_stop(struct ath10k *ar) + ath10k_ahb_irq_disable(ar); + synchronize_irq(ar_ahb->irq); + +- napi_synchronize(&ar->napi); +- napi_disable(&ar->napi); ++ ath10k_core_napi_sync_disable(ar); + + ath10k_pci_flush(ar); + } +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index 8ce5fbfcee972..a2a52c6276729 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -2303,6 +2303,31 @@ void ath10k_core_start_recovery(struct ath10k *ar) + } + EXPORT_SYMBOL(ath10k_core_start_recovery); + ++void ath10k_core_napi_enable(struct ath10k *ar) ++{ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (test_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags)) ++ return; ++ ++ napi_enable(&ar->napi); ++ set_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags); ++} ++EXPORT_SYMBOL(ath10k_core_napi_enable); ++ ++void ath10k_core_napi_sync_disable(struct ath10k *ar) ++{ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ if (!test_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags)) ++ return; ++ ++ napi_synchronize(&ar->napi); ++ napi_disable(&ar->napi); ++ clear_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags); ++} ++EXPORT_SYMBOL(ath10k_core_napi_sync_disable); ++ + static void ath10k_core_restart(struct work_struct *work) + { + struct ath10k *ar = container_of(work, struct ath10k, restart_work); +diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h +index b471c0ccf006b..30c01f18b3d2d 100644 +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -860,6 +860,9 @@ enum ath10k_dev_flags { + + /* Indicates that ath10k device is during recovery process and not complete */ + ATH10K_FLAG_RESTARTING, ++ ++ /* protected by conf_mutex */ ++ ATH10K_FLAG_NAPI_ENABLED, + }; + + enum ath10k_cal_mode { +@@ -1300,6 +1303,8 @@ static inline bool ath10k_peer_stats_enabled(struct ath10k *ar) + + extern unsigned long ath10k_coredump_mask; + ++void ath10k_core_napi_sync_disable(struct ath10k *ar); ++void ath10k_core_napi_enable(struct ath10k *ar); + struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, + enum ath10k_bus bus, + enum ath10k_hw_rev hw_rev, +diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c +index 83ef0517f0991..24ae59c572066 100644 +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -1958,7 +1958,7 @@ static int ath10k_pci_hif_start(struct ath10k *ar) + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n"); + +- napi_enable(&ar->napi); ++ ath10k_core_napi_enable(ar); + + ath10k_pci_irq_enable(ar); + ath10k_pci_rx_post(ar); +@@ -2076,8 +2076,9 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) + + ath10k_pci_irq_disable(ar); + ath10k_pci_irq_sync(ar); +- napi_synchronize(&ar->napi); +- napi_disable(&ar->napi); ++ ++ ath10k_core_napi_sync_disable(ar); ++ + cancel_work_sync(&ar_pci->dump_work); + + /* Most likely the device has HTT Rx ring configured. The only way to +diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c +index 2ccbb6b4f1b5b..7cb1bc8d6e01c 100644 +--- a/drivers/net/wireless/ath/ath10k/sdio.c ++++ b/drivers/net/wireless/ath/ath10k/sdio.c +@@ -1863,7 +1863,7 @@ static int ath10k_sdio_hif_start(struct ath10k *ar) + struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar); + int ret; + +- napi_enable(&ar->napi); ++ ath10k_core_napi_enable(ar); + + /* Sleep 20 ms before HIF interrupts are disabled. + * This will give target plenty of time to process the BMI done +@@ -1990,8 +1990,7 @@ static void ath10k_sdio_hif_stop(struct ath10k *ar) + + spin_unlock_bh(&ar_sdio->wr_async_lock); + +- napi_synchronize(&ar->napi); +- napi_disable(&ar->napi); ++ ath10k_core_napi_sync_disable(ar); + } + + #ifdef CONFIG_PM +diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c +index ee5b16d79f14f..513794099f03f 100644 +--- a/drivers/net/wireless/ath/ath10k/snoc.c ++++ b/drivers/net/wireless/ath/ath10k/snoc.c +@@ -923,8 +923,7 @@ static void ath10k_snoc_hif_stop(struct ath10k *ar) + if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) + ath10k_snoc_irq_disable(ar); + +- napi_synchronize(&ar->napi); +- napi_disable(&ar->napi); ++ ath10k_core_napi_sync_disable(ar); + ath10k_snoc_buffer_cleanup(ar); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n"); + } +@@ -934,7 +933,8 @@ static int ath10k_snoc_hif_start(struct ath10k *ar) + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + + bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX); +- napi_enable(&ar->napi); ++ ++ ath10k_core_napi_enable(ar); + ath10k_snoc_irq_enable(ar); + ath10k_snoc_rx_post(ar); + +-- +2.39.5 + diff --git a/queue-5.10/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch b/queue-5.10/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch new file mode 100644 index 0000000000..c1d8842e9e --- /dev/null +++ b/queue-5.10/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch @@ -0,0 +1,49 @@ +From cd047050049189a2f80b9e513c47a3d4f88ef019 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 20:50:27 +0000 +Subject: ath10k: snoc: fix unbalanced IRQ enable in crash recovery + +From: Caleb Connolly + +[ Upstream commit 1650d32b92b01db03a1a95d69ee74fcbc34d4b00 ] + +In ath10k_snoc_hif_stop() we skip disabling the IRQs in the crash +recovery flow, but we still unconditionally call enable again in +ath10k_snoc_hif_start(). + +We can't check the ATH10K_FLAG_CRASH_FLUSH bit since it is cleared +before hif_start() is called, so instead check the +ATH10K_SNOC_FLAG_RECOVERY flag and skip enabling the IRQs during crash +recovery. + +This fixes unbalanced IRQ enable splats that happen after recovering from +a crash. + +Fixes: 0e622f67e041 ("ath10k: add support for WCN3990 firmware crash recovery") +Signed-off-by: Caleb Connolly +Tested-by: Loic Poulain +Link: https://patch.msgid.link/20250318205043.1043148-1-caleb.connolly@linaro.org +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/snoc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c +index 513794099f03f..616fcaed061f9 100644 +--- a/drivers/net/wireless/ath/ath10k/snoc.c ++++ b/drivers/net/wireless/ath/ath10k/snoc.c +@@ -935,7 +935,9 @@ static int ath10k_snoc_hif_start(struct ath10k *ar) + bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX); + + ath10k_core_napi_enable(ar); +- ath10k_snoc_irq_enable(ar); ++ /* IRQs are left enabled when we restart due to a firmware crash */ ++ if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags)) ++ ath10k_snoc_irq_enable(ar); + ath10k_snoc_rx_post(ar); + + clear_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags); +-- +2.39.5 + diff --git a/queue-5.10/bpf-clean-up-sockmap-related-kconfigs.patch b/queue-5.10/bpf-clean-up-sockmap-related-kconfigs.patch new file mode 100644 index 0000000000..3843603f7e --- /dev/null +++ b/queue-5.10/bpf-clean-up-sockmap-related-kconfigs.patch @@ -0,0 +1,527 @@ +From 37fb54086c377b10c2956adcc322372172bead6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Feb 2021 10:49:26 -0800 +Subject: bpf: Clean up sockmap related Kconfigs + +From: Cong Wang + +[ Upstream commit 887596095ec2a9ea39ffcf98f27bf2e77c5eb512 ] + +As suggested by John, clean up sockmap related Kconfigs: + +Reduce the scope of CONFIG_BPF_STREAM_PARSER down to TCP stream +parser, to reflect its name. + +Make the rest sockmap code simply depend on CONFIG_BPF_SYSCALL +and CONFIG_INET, the latter is still needed at this point because +of TCP/UDP proto update. And leave CONFIG_NET_SOCK_MSG untouched, +as it is used by non-sockmap cases. + +Signed-off-by: Cong Wang +Signed-off-by: Alexei Starovoitov +Reviewed-by: Lorenz Bauer +Acked-by: John Fastabend +Acked-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/20210223184934.6054-2-xiyou.wangcong@gmail.com +Stable-dep-of: 2660a544fdc0 ("net: Fix TOCTOU issue in sk_is_readable()") +Signed-off-by: Sasha Levin +--- + include/linux/bpf.h | 26 ++++--- + include/linux/bpf_types.h | 6 +- + include/linux/skmsg.h | 18 +++++ + include/net/tcp.h | 16 +++-- + include/net/udp.h | 4 +- + init/Kconfig | 1 + + net/Kconfig | 6 +- + net/core/Makefile | 6 +- + net/core/skmsg.c | 145 +++++++++++++++++++++----------------- + net/core/sock_map.c | 2 + + net/ipv4/Makefile | 2 +- + net/ipv4/tcp_bpf.c | 4 +- + 12 files changed, 133 insertions(+), 103 deletions(-) + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 340f4fef5b5ab..5d5d0bc7ca50b 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -1793,7 +1793,7 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map) + } + #endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */ + +-#if defined(CONFIG_BPF_STREAM_PARSER) ++#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) + int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, + struct bpf_prog *old, u32 which); + int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog); +@@ -1802,7 +1802,18 @@ int sock_map_update_elem_sys(struct bpf_map *map, void *key, void *value, u64 fl + void sock_map_unhash(struct sock *sk); + void sock_map_destroy(struct sock *sk); + void sock_map_close(struct sock *sk, long timeout); ++ ++void bpf_sk_reuseport_detach(struct sock *sk); ++int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, void *key, ++ void *value); ++int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key, ++ void *value, u64 map_flags); + #else ++static inline void bpf_sk_reuseport_detach(struct sock *sk) ++{ ++} ++ ++#ifdef CONFIG_BPF_SYSCALL + static inline int sock_map_prog_update(struct bpf_map *map, + struct bpf_prog *prog, + struct bpf_prog *old, u32 which) +@@ -1827,20 +1838,7 @@ static inline int sock_map_update_elem_sys(struct bpf_map *map, void *key, void + { + return -EOPNOTSUPP; + } +-#endif /* CONFIG_BPF_STREAM_PARSER */ + +-#if defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) +-void bpf_sk_reuseport_detach(struct sock *sk); +-int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, void *key, +- void *value); +-int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key, +- void *value, u64 map_flags); +-#else +-static inline void bpf_sk_reuseport_detach(struct sock *sk) +-{ +-} +- +-#ifdef CONFIG_BPF_SYSCALL + static inline int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, + void *key, void *value) + { +diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h +index a8137bb6dd3c2..2bb5801b58877 100644 +--- a/include/linux/bpf_types.h ++++ b/include/linux/bpf_types.h +@@ -103,10 +103,6 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_HASH_OF_MAPS, htab_of_maps_map_ops) + BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops) + BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP_HASH, dev_map_hash_ops) + BPF_MAP_TYPE(BPF_MAP_TYPE_SK_STORAGE, sk_storage_map_ops) +-#if defined(CONFIG_BPF_STREAM_PARSER) +-BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops) +-BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops) +-#endif + #ifdef CONFIG_BPF_LSM + BPF_MAP_TYPE(BPF_MAP_TYPE_INODE_STORAGE, inode_storage_map_ops) + #endif +@@ -115,6 +111,8 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops) + BPF_MAP_TYPE(BPF_MAP_TYPE_XSKMAP, xsk_map_ops) + #endif + #ifdef CONFIG_INET ++BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops) ++BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops) + BPF_MAP_TYPE(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, reuseport_array_ops) + #endif + #endif +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 49db90cfe375f..e9e9fabbfedd8 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -71,7 +71,9 @@ struct sk_psock_link { + }; + + struct sk_psock_parser { ++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) + struct strparser strp; ++#endif + bool enabled; + void (*saved_data_ready)(struct sock *sk); + }; +@@ -307,9 +309,25 @@ static inline void sk_psock_report_error(struct sk_psock *psock, int err) + + struct sk_psock *sk_psock_init(struct sock *sk, int node); + ++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) + int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock); + void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock); + void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock); ++#else ++static inline int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) ++{ ++} ++ ++static inline void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) ++{ ++} ++#endif ++ + void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock); + void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock); + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 41f535dcaa3f9..4c87936a33d6d 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2274,25 +2274,27 @@ void tcp_update_ulp(struct sock *sk, struct proto *p, + __MODULE_INFO(alias, alias_userspace, name); \ + __MODULE_INFO(alias, alias_tcp_ulp, "tcp-ulp-" name) + ++#ifdef CONFIG_NET_SOCK_MSG + struct sk_msg; + struct sk_psock; + +-#ifdef CONFIG_BPF_STREAM_PARSER ++#ifdef CONFIG_BPF_SYSCALL + struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock); + void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); +-#else +-static inline void tcp_bpf_clone(const struct sock *sk, struct sock *newsk) +-{ +-} +-#endif /* CONFIG_BPF_STREAM_PARSER */ ++#endif /* CONFIG_BPF_SYSCALL */ + +-#ifdef CONFIG_NET_SOCK_MSG + int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, u32 bytes, + int flags); + int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock, + struct msghdr *msg, int len, int flags); + #endif /* CONFIG_NET_SOCK_MSG */ + ++#if !defined(CONFIG_BPF_SYSCALL) || !defined(CONFIG_NET_SOCK_MSG) ++static inline void tcp_bpf_clone(const struct sock *sk, struct sock *newsk) ++{ ++} ++#endif ++ + #ifdef CONFIG_CGROUP_BPF + static inline void bpf_skops_init_skb(struct bpf_sock_ops_kern *skops, + struct sk_buff *skb, +diff --git a/include/net/udp.h b/include/net/udp.h +index e2550a4547a70..db599b15b6304 100644 +--- a/include/net/udp.h ++++ b/include/net/udp.h +@@ -514,9 +514,9 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk, + return segs; + } + +-#ifdef CONFIG_BPF_STREAM_PARSER ++#ifdef CONFIG_BPF_SYSCALL + struct sk_psock; + struct proto *udp_bpf_get_proto(struct sock *sk, struct sk_psock *psock); +-#endif /* BPF_STREAM_PARSER */ ++#endif + + #endif /* _UDP_H */ +diff --git a/init/Kconfig b/init/Kconfig +index 233166e54df35..a6a4eaec73c88 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1720,6 +1720,7 @@ config BPF_SYSCALL + select BPF + select IRQ_WORK + select TASKS_TRACE_RCU ++ select NET_SOCK_MSG if INET + default n + help + Enable the bpf() system call that allows to manipulate eBPF +diff --git a/net/Kconfig b/net/Kconfig +index a22c3fb885647..b0e834410a309 100644 +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -311,13 +311,9 @@ config BPF_STREAM_PARSER + select STREAM_PARSER + select NET_SOCK_MSG + help +- Enabling this allows a stream parser to be used with ++ Enabling this allows a TCP stream parser to be used with + BPF_MAP_TYPE_SOCKMAP. + +- BPF_MAP_TYPE_SOCKMAP provides a map type to use with network sockets. +- It can be used to enforce socket policy, implement socket redirects, +- etc. +- + config NET_FLOW_LIMIT + bool + depends on RPS +diff --git a/net/core/Makefile b/net/core/Makefile +index 3e2c378e5f317..0c2233c826fd5 100644 +--- a/net/core/Makefile ++++ b/net/core/Makefile +@@ -16,7 +16,6 @@ obj-y += dev.o dev_addr_lists.o dst.o netevent.o \ + obj-y += net-sysfs.o + obj-$(CONFIG_PAGE_POOL) += page_pool.o + obj-$(CONFIG_PROC_FS) += net-procfs.o +-obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o + obj-$(CONFIG_NET_PKTGEN) += pktgen.o + obj-$(CONFIG_NETPOLL) += netpoll.o + obj-$(CONFIG_FIB_RULES) += fib_rules.o +@@ -28,10 +27,13 @@ obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o + obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o + obj-$(CONFIG_LWTUNNEL) += lwtunnel.o + obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o +-obj-$(CONFIG_BPF_STREAM_PARSER) += sock_map.o + obj-$(CONFIG_DST_CACHE) += dst_cache.o + obj-$(CONFIG_HWBM) += hwbm.o + obj-$(CONFIG_NET_DEVLINK) += devlink.o + obj-$(CONFIG_GRO_CELLS) += gro_cells.o + obj-$(CONFIG_FAILOVER) += failover.o ++ifeq ($(CONFIG_INET),y) ++obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o ++obj-$(CONFIG_BPF_SYSCALL) += sock_map.o ++endif + obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 890e16bbc0720..8680cdfbdb9da 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -664,15 +664,15 @@ static void sk_psock_link_destroy(struct sk_psock *psock) + } + } + ++static void sk_psock_done_strp(struct sk_psock *psock); ++ + static void sk_psock_destroy_deferred(struct work_struct *gc) + { + struct sk_psock *psock = container_of(gc, struct sk_psock, gc); + + /* No sk_callback_lock since already detached. */ + +- /* Parser has been stopped */ +- if (psock->progs.skb_parser) +- strp_done(&psock->parser.strp); ++ sk_psock_done_strp(psock); + + cancel_work_sync(&psock->work); + +@@ -769,14 +769,6 @@ static int sk_psock_bpf_run(struct sk_psock *psock, struct bpf_prog *prog, + return bpf_prog_run_pin_on_cpu(prog, skb); + } + +-static struct sk_psock *sk_psock_from_strp(struct strparser *strp) +-{ +- struct sk_psock_parser *parser; +- +- parser = container_of(strp, struct sk_psock_parser, strp); +- return container_of(parser, struct sk_psock, parser); +-} +- + static void sk_psock_skb_redirect(struct sk_buff *skb) + { + struct sk_psock *psock_other; +@@ -880,6 +872,24 @@ static void sk_psock_verdict_apply(struct sk_psock *psock, + } + } + ++static void sk_psock_write_space(struct sock *sk) ++{ ++ struct sk_psock *psock; ++ void (*write_space)(struct sock *sk) = NULL; ++ ++ rcu_read_lock(); ++ psock = sk_psock(sk); ++ if (likely(psock)) { ++ if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) ++ schedule_work(&psock->work); ++ write_space = psock->saved_write_space; ++ } ++ rcu_read_unlock(); ++ if (write_space) ++ write_space(sk); ++} ++ ++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) + static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb) + { + struct sk_psock *psock; +@@ -912,6 +922,14 @@ static int sk_psock_strp_read_done(struct strparser *strp, int err) + return err; + } + ++static struct sk_psock *sk_psock_from_strp(struct strparser *strp) ++{ ++ struct sk_psock_parser *parser; ++ ++ parser = container_of(strp, struct sk_psock_parser, strp); ++ return container_of(parser, struct sk_psock, parser); ++} ++ + static int sk_psock_strp_parse(struct strparser *strp, struct sk_buff *skb) + { + struct sk_psock *psock = sk_psock_from_strp(strp); +@@ -948,6 +966,56 @@ static void sk_psock_strp_data_ready(struct sock *sk) + rcu_read_unlock(); + } + ++int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) ++{ ++ static const struct strp_callbacks cb = { ++ .rcv_msg = sk_psock_strp_read, ++ .read_sock_done = sk_psock_strp_read_done, ++ .parse_msg = sk_psock_strp_parse, ++ }; ++ ++ psock->parser.enabled = false; ++ return strp_init(&psock->parser.strp, sk, &cb); ++} ++ ++void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) ++{ ++ struct sk_psock_parser *parser = &psock->parser; ++ ++ if (parser->enabled) ++ return; ++ ++ parser->saved_data_ready = sk->sk_data_ready; ++ sk->sk_data_ready = sk_psock_strp_data_ready; ++ sk->sk_write_space = sk_psock_write_space; ++ parser->enabled = true; ++} ++ ++void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) ++{ ++ struct sk_psock_parser *parser = &psock->parser; ++ ++ if (!parser->enabled) ++ return; ++ ++ sk->sk_data_ready = parser->saved_data_ready; ++ parser->saved_data_ready = NULL; ++ strp_stop(&parser->strp); ++ parser->enabled = false; ++} ++ ++static void sk_psock_done_strp(struct sk_psock *psock) ++{ ++ /* Parser has been stopped */ ++ if (psock->progs.skb_parser) ++ strp_done(&psock->parser.strp); ++} ++#else ++static void sk_psock_done_strp(struct sk_psock *psock) ++{ ++} ++#endif /* CONFIG_BPF_STREAM_PARSER */ ++ + static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb, + unsigned int offset, size_t orig_len) + { +@@ -1000,35 +1068,6 @@ static void sk_psock_verdict_data_ready(struct sock *sk) + sock->ops->read_sock(sk, &desc, sk_psock_verdict_recv); + } + +-static void sk_psock_write_space(struct sock *sk) +-{ +- struct sk_psock *psock; +- void (*write_space)(struct sock *sk) = NULL; +- +- rcu_read_lock(); +- psock = sk_psock(sk); +- if (likely(psock)) { +- if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) +- schedule_work(&psock->work); +- write_space = psock->saved_write_space; +- } +- rcu_read_unlock(); +- if (write_space) +- write_space(sk); +-} +- +-int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) +-{ +- static const struct strp_callbacks cb = { +- .rcv_msg = sk_psock_strp_read, +- .read_sock_done = sk_psock_strp_read_done, +- .parse_msg = sk_psock_strp_parse, +- }; +- +- psock->parser.enabled = false; +- return strp_init(&psock->parser.strp, sk, &cb); +-} +- + void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) + { + struct sk_psock_parser *parser = &psock->parser; +@@ -1042,32 +1081,6 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) + parser->enabled = true; + } + +-void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) +-{ +- struct sk_psock_parser *parser = &psock->parser; +- +- if (parser->enabled) +- return; +- +- parser->saved_data_ready = sk->sk_data_ready; +- sk->sk_data_ready = sk_psock_strp_data_ready; +- sk->sk_write_space = sk_psock_write_space; +- parser->enabled = true; +-} +- +-void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) +-{ +- struct sk_psock_parser *parser = &psock->parser; +- +- if (!parser->enabled) +- return; +- +- sk->sk_data_ready = parser->saved_data_ready; +- parser->saved_data_ready = NULL; +- strp_stop(&parser->strp); +- parser->enabled = false; +-} +- + void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) + { + struct sk_psock_parser *parser = &psock->parser; +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index d334a2ccd5238..3a9e0046a7803 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -1506,9 +1506,11 @@ int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, + case BPF_SK_MSG_VERDICT: + pprog = &progs->msg_parser; + break; ++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) + case BPF_SK_SKB_STREAM_PARSER: + pprog = &progs->skb_parser; + break; ++#endif + case BPF_SK_SKB_STREAM_VERDICT: + pprog = &progs->skb_verdict; + break; +diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile +index 5b77a46885b95..bbdd9c44f14e3 100644 +--- a/net/ipv4/Makefile ++++ b/net/ipv4/Makefile +@@ -62,7 +62,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o + obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o + obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o + obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o +-obj-$(CONFIG_BPF_STREAM_PARSER) += udp_bpf.o ++obj-$(CONFIG_BPF_SYSCALL) += udp_bpf.o + obj-$(CONFIG_NETLABEL) += cipso_ipv4.o + + obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 804464beb3439..9765fda6cc378 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -232,7 +232,7 @@ int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, + } + EXPORT_SYMBOL_GPL(tcp_bpf_sendmsg_redir); + +-#ifdef CONFIG_BPF_STREAM_PARSER ++#ifdef CONFIG_BPF_SYSCALL + static bool tcp_bpf_stream_read(const struct sock *sk) + { + struct sk_psock *psock; +@@ -646,4 +646,4 @@ void tcp_bpf_clone(const struct sock *sk, struct sock *newsk) + if (is_insidevar(prot, tcp_bpf_prots)) + newsk->sk_prot = sk->sk_prot_creator; + } +-#endif /* CONFIG_BPF_STREAM_PARSER */ ++#endif /* CONFIG_BPF_SYSCALL */ +-- +2.39.5 + diff --git a/queue-5.10/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch b/queue-5.10/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch new file mode 100644 index 0000000000..879249002b --- /dev/null +++ b/queue-5.10/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch @@ -0,0 +1,44 @@ +From 954b55966b97ace9035d6ea0d53369c5b08b7ce3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 May 2025 10:31:52 +0200 +Subject: i40e: retry VFLR handling if there is ongoing VF reset + +From: Robert Malz + +[ Upstream commit fb4e9239e029954a37a00818b21e837cebf2aa10 ] + +When a VFLR interrupt is received during a VF reset initiated from a +different source, the VFLR may be not fully handled. This can +leave the VF in an undefined state. +To address this, set the I40E_VFLR_EVENT_PENDING bit again during VFLR +handling if the reset is not yet complete. This ensures the driver +will properly complete the VF reset in such scenarios. + +Fixes: 52424f974bc5 ("i40e: Fix VF hang when reset is triggered on another VF") +Signed-off-by: Robert Malz +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +index 68e39a38e7588..852ece241a278 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +@@ -4170,7 +4170,10 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) + reg = rd32(hw, I40E_GLGEN_VFLRSTAT(reg_idx)); + if (reg & BIT(bit_idx)) + /* i40e_reset_vf will clear the bit in GLGEN_VFLRSTAT */ +- i40e_reset_vf(vf, true); ++ if (!i40e_reset_vf(vf, true)) { ++ /* At least one VF did not finish resetting, retry next time */ ++ set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); ++ } + } + + return 0; +-- +2.39.5 + diff --git a/queue-5.10/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch b/queue-5.10/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch new file mode 100644 index 0000000000..716bd029cf --- /dev/null +++ b/queue-5.10/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch @@ -0,0 +1,55 @@ +From 31ea75def5b2e9b5603d6058299292aaef6241f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 May 2025 10:31:51 +0200 +Subject: i40e: return false from i40e_reset_vf if reset is in progress + +From: Robert Malz + +[ Upstream commit a2c90d63b71223d69a813333c1abf4fdacddbbe5 ] + +The function i40e_vc_reset_vf attempts, up to 20 times, to handle a +VF reset request, using the return value of i40e_reset_vf as an indicator +of whether the reset was successfully triggered. Currently, i40e_reset_vf +always returns true, which causes new reset requests to be ignored if a +different VF reset is already in progress. + +This patch updates the return value of i40e_reset_vf to reflect when +another VF reset is in progress, allowing the caller to properly use +the retry mechanism. + +Fixes: 52424f974bc5 ("i40e: Fix VF hang when reset is triggered on another VF") +Signed-off-by: Robert Malz +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +index 4f23243bbfbb6..68e39a38e7588 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +@@ -1495,8 +1495,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) + * @vf: pointer to the VF structure + * @flr: VFLR was issued or not + * +- * Returns true if the VF is in reset, resets successfully, or resets +- * are disabled and false otherwise. ++ * Return: True if reset was performed successfully or if resets are disabled. ++ * False if reset is already in progress. + **/ + bool i40e_reset_vf(struct i40e_vf *vf, bool flr) + { +@@ -1515,7 +1515,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) + + /* If VF is being reset already we don't need to continue. */ + if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) +- return true; ++ return false; + + i40e_trigger_vf_reset(vf, flr); + +-- +2.39.5 + diff --git a/queue-5.10/macsec-macsec-sci-assignment-for-es-0.patch b/queue-5.10/macsec-macsec-sci-assignment-for-es-0.patch new file mode 100644 index 0000000000..5010c26d40 --- /dev/null +++ b/queue-5.10/macsec-macsec-sci-assignment-for-es-0.patch @@ -0,0 +1,128 @@ +From 461e592e9fe270c37ae018cd5b799a9a53d74845 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 09:26:26 +0200 +Subject: macsec: MACsec SCI assignment for ES = 0 + +From: Carlos Fernandez + +[ Upstream commit d9816ec74e6d6aa29219d010bba3f780ba1d9d75 ] + +According to 802.1AE standard, when ES and SC flags in TCI are zero, +used SCI should be the current active SC_RX. Current code uses the +header MAC address. Without this patch, when ES flag is 0 (using a +bridge or switch), header MAC will not fit the SCI and MACSec frames +will be discarted. + +In order to test this issue, MACsec link should be stablished between +two interfaces, setting SC and ES flags to zero and a port identifier +different than one. For example, using ip macsec tools: + +ip link add link $ETH0 macsec0 type macsec port 11 send_sci off +end_station off +ip macsec add macsec0 tx sa 0 pn 2 on key 01 $ETH1_KEY +ip macsec add macsec0 rx port 11 address $ETH1_MAC +ip macsec add macsec0 rx port 11 address $ETH1_MAC sa 0 pn 2 on key 02 +ip link set dev macsec0 up + +ip link add link $ETH1 macsec1 type macsec port 11 send_sci off +end_station off +ip macsec add macsec1 tx sa 0 pn 2 on key 01 $ETH0_KEY +ip macsec add macsec1 rx port 11 address $ETH0_MAC +ip macsec add macsec1 rx port 11 address $ETH0_MAC sa 0 pn 2 on key 02 +ip link set dev macsec1 up + +Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") +Co-developed-by: Andreu Montiel +Signed-off-by: Andreu Montiel +Signed-off-by: Carlos Fernandez +Reviewed-by: Subbaraya Sundeep +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/macsec.c | 40 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 34 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index 5e30fd017b3ac..e6a013da6680c 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -260,15 +260,39 @@ static sci_t make_sci(u8 *addr, __be16 port) + return sci; + } + +-static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present) ++static sci_t macsec_active_sci(struct macsec_secy *secy) + { +- sci_t sci; ++ struct macsec_rx_sc *rx_sc = rcu_dereference_bh(secy->rx_sc); ++ ++ /* Case single RX SC */ ++ if (rx_sc && !rcu_dereference_bh(rx_sc->next)) ++ return (rx_sc->active) ? rx_sc->sci : 0; ++ /* Case no RX SC or multiple */ ++ else ++ return 0; ++} ++ ++static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present, ++ struct macsec_rxh_data *rxd) ++{ ++ struct macsec_dev *macsec; ++ sci_t sci = 0; + +- if (sci_present) ++ /* SC = 1 */ ++ if (sci_present) { + memcpy(&sci, hdr->secure_channel_id, + sizeof(hdr->secure_channel_id)); +- else ++ /* SC = 0; ES = 0 */ ++ } else if ((!(hdr->tci_an & (MACSEC_TCI_ES | MACSEC_TCI_SC))) && ++ (list_is_singular(&rxd->secys))) { ++ /* Only one SECY should exist on this scenario */ ++ macsec = list_first_or_null_rcu(&rxd->secys, struct macsec_dev, ++ secys); ++ if (macsec) ++ return macsec_active_sci(&macsec->secy); ++ } else { + sci = make_sci(hdr->eth.h_source, MACSEC_PORT_ES); ++ } + + return sci; + } +@@ -1096,7 +1120,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + struct macsec_rxh_data *rxd; + struct macsec_dev *macsec; + unsigned int len; +- sci_t sci; ++ sci_t sci = 0; + u32 hdr_pn; + bool cbit; + struct pcpu_rx_sc_stats *rxsc_stats; +@@ -1143,11 +1167,14 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + + macsec_skb_cb(skb)->has_sci = !!(hdr->tci_an & MACSEC_TCI_SC); + macsec_skb_cb(skb)->assoc_num = hdr->tci_an & MACSEC_AN_MASK; +- sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci); + + rcu_read_lock(); + rxd = macsec_data_rcu(skb->dev); + ++ sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci, rxd); ++ if (!sci) ++ goto drop_nosc; ++ + list_for_each_entry_rcu(macsec, &rxd->secys, secys) { + struct macsec_rx_sc *sc = find_rx_sc(&macsec->secy, sci); + +@@ -1270,6 +1297,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + macsec_rxsa_put(rx_sa); + drop_nosa: + macsec_rxsc_put(rx_sc); ++drop_nosc: + rcu_read_unlock(); + drop_direct: + kfree_skb(skb); +-- +2.39.5 + diff --git a/queue-5.10/net-fix-toctou-issue-in-sk_is_readable.patch b/queue-5.10/net-fix-toctou-issue-in-sk_is_readable.patch new file mode 100644 index 0000000000..d69ae9c403 --- /dev/null +++ b/queue-5.10/net-fix-toctou-issue-in-sk_is_readable.patch @@ -0,0 +1,52 @@ +From 96e1d4fa3e4b397e9f2cfcee71d9686e44975686 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 19:08:03 +0200 +Subject: net: Fix TOCTOU issue in sk_is_readable() + +From: Michal Luczaj + +[ Upstream commit 2660a544fdc0940bba15f70508a46cf9a6491230 ] + +sk->sk_prot->sock_is_readable is a valid function pointer when sk resides +in a sockmap. After the last sk_psock_put() (which usually happens when +socket is removed from sockmap), sk->sk_prot gets restored and +sk->sk_prot->sock_is_readable becomes NULL. + +This makes sk_is_readable() racy, if the value of sk->sk_prot is reloaded +after the initial check. Which in turn may lead to a null pointer +dereference. + +Ensure the function pointer does not turn NULL after the check. + +Fixes: 8934ce2fd081 ("bpf: sockmap redirect ingress support") +Suggested-by: Jakub Sitnicki +Signed-off-by: Michal Luczaj +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250609-skisreadable-toctou-v1-1-d0dfb2d62c37@rbox.co +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/sock.h | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/include/net/sock.h b/include/net/sock.h +index b9e34b955c561..bc9a1e535d580 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -2827,8 +2827,11 @@ int sock_bind_add(struct sock *sk, struct sockaddr *addr, int addr_len); + + static inline bool sk_is_readable(struct sock *sk) + { +- if (sk->sk_prot->sock_is_readable) +- return sk->sk_prot->sock_is_readable(sk); ++ const struct proto *prot = READ_ONCE(sk->sk_prot); ++ ++ if (prot->sock_is_readable) ++ return prot->sock_is_readable(sk); ++ + return false; + } + #endif /* _SOCK_H */ +-- +2.39.5 + diff --git a/queue-5.10/net-mdio-c22-is-now-optional-eopnotsupp-if-not-provi.patch b/queue-5.10/net-mdio-c22-is-now-optional-eopnotsupp-if-not-provi.patch new file mode 100644 index 0000000000..d5aaff0af4 --- /dev/null +++ b/queue-5.10/net-mdio-c22-is-now-optional-eopnotsupp-if-not-provi.patch @@ -0,0 +1,53 @@ +From e57472783e35dfd192f7a2ed322befc3b1c7eaa8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jan 2023 16:30:44 +0100 +Subject: net: mdio: C22 is now optional, EOPNOTSUPP if not provided + +From: Andrew Lunn + +[ Upstream commit b063b1924fd9bf0bc157cf644764dc2151d04ccc ] + +When performing a C22 operation, check that the bus driver actually +provides the methods, and return -EOPNOTSUPP if not. C45 only busses +do exist, and in future their C22 methods will be NULL. + +Signed-off-by: Andrew Lunn +Signed-off-by: Michael Walle +Signed-off-by: Jakub Kicinski +Stable-dep-of: 0e629694126c ("net/mdiobus: Fix potential out-of-bounds read/write access") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index e9303be486556..743a63eca7840 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -754,7 +754,10 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + +- retval = bus->read(bus, addr, regnum); ++ if (bus->read) ++ retval = bus->read(bus, addr, regnum); ++ else ++ retval = -EOPNOTSUPP; + + trace_mdio_access(bus, 1, addr, regnum, retval, retval); + mdiobus_stats_acct(&bus->stats[addr], true, retval); +@@ -780,7 +783,10 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + +- err = bus->write(bus, addr, regnum, val); ++ if (bus->write) ++ err = bus->write(bus, addr, regnum, val); ++ else ++ err = -EOPNOTSUPP; + + trace_mdio_access(bus, 0, addr, regnum, val, err); + mdiobus_stats_acct(&bus->stats[addr], false, err); +-- +2.39.5 + diff --git a/queue-5.10/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch b/queue-5.10/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch new file mode 100644 index 0000000000..2e8cf639f4 --- /dev/null +++ b/queue-5.10/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch @@ -0,0 +1,58 @@ +From 4e0130634e008bf9879122c1345e9df17f3baa35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 17:31:46 +0200 +Subject: net/mdiobus: Fix potential out-of-bounds read/write access + +From: Jakub Raczynski + +[ Upstream commit 0e629694126ca388916f059453a1c36adde219c4 ] + +When using publicly available tools like 'mdio-tools' to read/write data +from/to network interface and its PHY via mdiobus, there is no verification of +parameters passed to the ioctl and it accepts any mdio address. +Currently there is support for 32 addresses in kernel via PHY_MAX_ADDR define, +but it is possible to pass higher value than that via ioctl. +While read/write operation should generally fail in this case, +mdiobus provides stats array, where wrong address may allow out-of-bounds +read/write. + +Fix that by adding address verification before read/write operation. +While this excludes this access from any statistics, it improves security of +read/write operation. + +Fixes: 080bb352fad00 ("net: phy: Maintain MDIO device and bus statistics") +Signed-off-by: Jakub Raczynski +Reported-by: Wenjing Shan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 743a63eca7840..d15deb3281edb 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -754,6 +754,9 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + ++ if (addr >= PHY_MAX_ADDR) ++ return -ENXIO; ++ + if (bus->read) + retval = bus->read(bus, addr, regnum); + else +@@ -783,6 +786,9 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) + + WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock)); + ++ if (addr >= PHY_MAX_ADDR) ++ return -ENXIO; ++ + if (bus->write) + err = bus->write(bus, addr, regnum, val); + else +-- +2.39.5 + diff --git a/queue-5.10/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch b/queue-5.10/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch new file mode 100644 index 0000000000..8876afd010 --- /dev/null +++ b/queue-5.10/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch @@ -0,0 +1,43 @@ +From 80c533e7e3177c16f51cf8649e3e5a63f40eb491 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:06 +0300 +Subject: net/mlx5: Ensure fw pages are always allocated on same NUMA + +From: Moshe Shemesh + +[ Upstream commit f37258133c1e95e61db532e14067e28b4881bf24 ] + +When firmware asks the driver to allocate more pages, using event of +give_pages, the driver should always allocate it from same NUMA, the +original device NUMA. Current code uses dev_to_node() which can result +in different NUMA as it is changed by other driver flows, such as +mlx5_dma_zalloc_coherent_node(). Instead, use saved numa node for +allocating firmware pages. + +Fixes: 311c7c71c9bb ("net/mlx5e: Allocate DMA coherent memory on reader NUMA node") +Signed-off-by: Moshe Shemesh +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-2-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +index 1ea71f06fdb1c..b7ccdef697fd0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +@@ -272,7 +272,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr, u32 function) + static int alloc_system_page(struct mlx5_core_dev *dev, u32 function) + { + struct device *device = mlx5_core_dma_dev(dev); +- int nid = dev_to_node(device); ++ int nid = dev->priv.numa_node; + struct page *page; + u64 zero_addr = 1; + u64 addr; +-- +2.39.5 + diff --git a/queue-5.10/net-mlx5-fix-return-value-when-searching-for-existin.patch b/queue-5.10/net-mlx5-fix-return-value-when-searching-for-existin.patch new file mode 100644 index 0000000000..82310024c6 --- /dev/null +++ b/queue-5.10/net-mlx5-fix-return-value-when-searching-for-existin.patch @@ -0,0 +1,61 @@ +From 6a11cd5752d06c01e20b7c3ef3f43ff7e1c99de0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:08 +0300 +Subject: net/mlx5: Fix return value when searching for existing flow group + +From: Patrisious Haddad + +[ Upstream commit 8ec40e3f1f72bf8f8accf18020d487caa99f46a4 ] + +When attempting to add a rule to an existing flow group, if a matching +flow group exists but is not active, the error code returned should be +EAGAIN, so that the rule can be added to the matching flow group once +it is active, rather than ENOENT, which indicates that no matching +flow group was found. + +Fixes: bd71b08ec2ee ("net/mlx5: Support multiple updates of steering rules in parallel") +Signed-off-by: Gavi Teitz +Signed-off-by: Roi Dayan +Signed-off-by: Patrisious Haddad +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-4-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +index c1a33f05702ec..4b237a0fee34b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -1869,6 +1869,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, + struct mlx5_flow_handle *rule; + struct match_list *iter; + bool take_write = false; ++ bool try_again = false; + struct fs_fte *fte; + u64 version = 0; + int err; +@@ -1928,6 +1929,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, + nested_down_write_ref_node(&g->node, FS_LOCK_PARENT); + + if (!g->node.active) { ++ try_again = true; + up_write_ref_node(&g->node, false); + continue; + } +@@ -1949,7 +1951,8 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, + tree_put_node(&fte->node, false); + return rule; + } +- rule = ERR_PTR(-ENOENT); ++ err = try_again ? -EAGAIN : -ENOENT; ++ rule = ERR_PTR(err); + out: + kmem_cache_free(steering->ftes_cache, fte); + return rule; +-- +2.39.5 + diff --git a/queue-5.10/net-rename-stream_memory_read-to-sock_is_readable.patch b/queue-5.10/net-rename-stream_memory_read-to-sock_is_readable.patch new file mode 100644 index 0000000000..ee38b81550 --- /dev/null +++ b/queue-5.10/net-rename-stream_memory_read-to-sock_is_readable.patch @@ -0,0 +1,138 @@ +From 917aa4e7f43020db651a3d61a749f5394ed3195d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Oct 2021 13:33:03 -0700 +Subject: net: Rename ->stream_memory_read to ->sock_is_readable + +From: Cong Wang + +[ Upstream commit 7b50ecfcc6cdfe87488576bc3ed443dc8d083b90 ] + +The proto ops ->stream_memory_read() is currently only used +by TCP to check whether psock queue is empty or not. We need +to rename it before reusing it for non-TCP protocols, and +adjust the exsiting users accordingly. + +Signed-off-by: Cong Wang +Signed-off-by: Alexei Starovoitov +Link: https://lore.kernel.org/bpf/20211008203306.37525-2-xiyou.wangcong@gmail.com +Stable-dep-of: 2660a544fdc0 ("net: Fix TOCTOU issue in sk_is_readable()") +Signed-off-by: Sasha Levin +--- + include/net/sock.h | 8 +++++++- + include/net/tls.h | 2 +- + net/ipv4/tcp.c | 5 +---- + net/ipv4/tcp_bpf.c | 4 ++-- + net/tls/tls_main.c | 4 ++-- + net/tls/tls_sw.c | 2 +- + 6 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/include/net/sock.h b/include/net/sock.h +index 548f9aab9aa10..b9e34b955c561 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1226,7 +1226,7 @@ struct proto { + #endif + + bool (*stream_memory_free)(const struct sock *sk, int wake); +- bool (*stream_memory_read)(const struct sock *sk); ++ bool (*sock_is_readable)(struct sock *sk); + /* Memory pressure */ + void (*enter_memory_pressure)(struct sock *sk); + void (*leave_memory_pressure)(struct sock *sk); +@@ -2825,4 +2825,10 @@ void sock_set_sndtimeo(struct sock *sk, s64 secs); + + int sock_bind_add(struct sock *sk, struct sockaddr *addr, int addr_len); + ++static inline bool sk_is_readable(struct sock *sk) ++{ ++ if (sk->sk_prot->sock_is_readable) ++ return sk->sk_prot->sock_is_readable(sk); ++ return false; ++} + #endif /* _SOCK_H */ +diff --git a/include/net/tls.h b/include/net/tls.h +index d9cb597cab46a..c76a827a678ae 100644 +--- a/include/net/tls.h ++++ b/include/net/tls.h +@@ -377,7 +377,7 @@ void tls_sw_release_resources_rx(struct sock *sk); + void tls_sw_free_ctx_rx(struct tls_context *tls_ctx); + int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + int nonblock, int flags, int *addr_len); +-bool tls_sw_stream_read(const struct sock *sk); ++bool tls_sw_sock_is_readable(struct sock *sk); + ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, + struct pipe_inode_info *pipe, + size_t len, unsigned int flags); +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 0332fdab942db..2d870d5e31cfb 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -480,10 +480,7 @@ static bool tcp_stream_is_readable(struct sock *sk, int target) + { + if (tcp_epollin_ready(sk, target)) + return true; +- +- if (sk->sk_prot->stream_memory_read) +- return sk->sk_prot->stream_memory_read(sk); +- return false; ++ return sk_is_readable(sk); + } + + /* +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 9765fda6cc378..f97e357e2644d 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -233,7 +233,7 @@ int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, + EXPORT_SYMBOL_GPL(tcp_bpf_sendmsg_redir); + + #ifdef CONFIG_BPF_SYSCALL +-static bool tcp_bpf_stream_read(const struct sock *sk) ++static bool tcp_bpf_sock_is_readable(struct sock *sk) + { + struct sk_psock *psock; + bool empty = true; +@@ -582,7 +582,7 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], + prot[TCP_BPF_BASE].destroy = sock_map_destroy; + prot[TCP_BPF_BASE].close = sock_map_close; + prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg; +- prot[TCP_BPF_BASE].stream_memory_read = tcp_bpf_stream_read; ++ prot[TCP_BPF_BASE].sock_is_readable = tcp_bpf_sock_is_readable; + + prot[TCP_BPF_TX] = prot[TCP_BPF_BASE]; + prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg; +diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c +index 9d7b52370155b..63517995c692a 100644 +--- a/net/tls/tls_main.c ++++ b/net/tls/tls_main.c +@@ -731,12 +731,12 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], + + prot[TLS_BASE][TLS_SW] = prot[TLS_BASE][TLS_BASE]; + prot[TLS_BASE][TLS_SW].recvmsg = tls_sw_recvmsg; +- prot[TLS_BASE][TLS_SW].stream_memory_read = tls_sw_stream_read; ++ prot[TLS_BASE][TLS_SW].sock_is_readable = tls_sw_sock_is_readable; + prot[TLS_BASE][TLS_SW].close = tls_sk_proto_close; + + prot[TLS_SW][TLS_SW] = prot[TLS_SW][TLS_BASE]; + prot[TLS_SW][TLS_SW].recvmsg = tls_sw_recvmsg; +- prot[TLS_SW][TLS_SW].stream_memory_read = tls_sw_stream_read; ++ prot[TLS_SW][TLS_SW].sock_is_readable = tls_sw_sock_is_readable; + prot[TLS_SW][TLS_SW].close = tls_sk_proto_close; + + #ifdef CONFIG_TLS_DEVICE +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 0723b3a4f6d91..7a448fd96f81c 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -2047,7 +2047,7 @@ ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos, + return copied ? : err; + } + +-bool tls_sw_stream_read(const struct sock *sk) ++bool tls_sw_sock_is_readable(struct sock *sk) + { + struct tls_context *tls_ctx = tls_get_ctx(sk); + struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); +-- +2.39.5 + diff --git a/queue-5.10/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch b/queue-5.10/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch new file mode 100644 index 0000000000..5051c8e942 --- /dev/null +++ b/queue-5.10/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch @@ -0,0 +1,58 @@ +From bdbd8553e4f94382e8e1b26032b40c67f0a4dad2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:14 +0000 +Subject: net_sched: ets: fix a race in ets_qdisc_change() + +From: Eric Dumazet + +[ Upstream commit d92adacdd8c2960be856e0b82acc5b7c5395fddb ] + +Gerrard Tai reported a race condition in ETS, whenever SFQ perturb timer +fires at the wrong time. + +The race is as follows: + +CPU 0 CPU 1 +[1]: lock root +[2]: qdisc_tree_flush_backlog() +[3]: unlock root + | + | [5]: lock root + | [6]: rehash + | [7]: qdisc_tree_reduce_backlog() + | +[4]: qdisc_put() + +This can be abused to underflow a parent's qlen. + +Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog() +should fix the race, because all packets will be purged from the qdisc +before releasing the lock. + +Fixes: b05972f01e7d ("net: sched: tbf: don't call qdisc_put() while holding tree lock") +Reported-by: Gerrard Tai +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250611111515.1983366-5-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 55b3362d27106..4f4da11a2c779 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -675,7 +675,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + for (i = q->nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); +- qdisc_tree_flush_backlog(q->classes[i].qdisc); ++ qdisc_purge_queue(q->classes[i].qdisc); + } + q->nstrict = nstrict; + memcpy(q->prio2band, priomap, sizeof(priomap)); +-- +2.39.5 + diff --git a/queue-5.10/net_sched-prio-fix-a-race-in-prio_tune.patch b/queue-5.10/net_sched-prio-fix-a-race-in-prio_tune.patch new file mode 100644 index 0000000000..f7cc85ff72 --- /dev/null +++ b/queue-5.10/net_sched-prio-fix-a-race-in-prio_tune.patch @@ -0,0 +1,58 @@ +From e75b3f7da15f63231dc5b0555b29a7f00faa6718 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:11 +0000 +Subject: net_sched: prio: fix a race in prio_tune() + +From: Eric Dumazet + +[ Upstream commit d35acc1be3480505b5931f17e4ea9b7617fea4d3 ] + +Gerrard Tai reported a race condition in PRIO, whenever SFQ perturb timer +fires at the wrong time. + +The race is as follows: + +CPU 0 CPU 1 +[1]: lock root +[2]: qdisc_tree_flush_backlog() +[3]: unlock root + | + | [5]: lock root + | [6]: rehash + | [7]: qdisc_tree_reduce_backlog() + | +[4]: qdisc_put() + +This can be abused to underflow a parent's qlen. + +Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog() +should fix the race, because all packets will be purged from the qdisc +before releasing the lock. + +Fixes: 7b8e0b6e6599 ("net: sched: prio: delay destroying child qdiscs on change") +Reported-by: Gerrard Tai +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250611111515.1983366-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_prio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c +index 1c805fe05b82a..3d92497af01fe 100644 +--- a/net/sched/sch_prio.c ++++ b/net/sched/sch_prio.c +@@ -211,7 +211,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt, + memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); + + for (i = q->bands; i < oldbands; i++) +- qdisc_tree_flush_backlog(q->queues[i]); ++ qdisc_purge_queue(q->queues[i]); + + for (i = oldbands; i < q->bands; i++) { + q->queues[i] = queues[i]; +-- +2.39.5 + diff --git a/queue-5.10/net_sched-red-fix-a-race-in-__red_change.patch b/queue-5.10/net_sched-red-fix-a-race-in-__red_change.patch new file mode 100644 index 0000000000..e38b0c9422 --- /dev/null +++ b/queue-5.10/net_sched-red-fix-a-race-in-__red_change.patch @@ -0,0 +1,58 @@ +From c875e5abad8f22ca63e6b1cb78b05fa68ca3c729 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:12 +0000 +Subject: net_sched: red: fix a race in __red_change() + +From: Eric Dumazet + +[ Upstream commit 85a3e0ede38450ea3053b8c45d28cf55208409b8 ] + +Gerrard Tai reported a race condition in RED, whenever SFQ perturb timer +fires at the wrong time. + +The race is as follows: + +CPU 0 CPU 1 +[1]: lock root +[2]: qdisc_tree_flush_backlog() +[3]: unlock root + | + | [5]: lock root + | [6]: rehash + | [7]: qdisc_tree_reduce_backlog() + | +[4]: qdisc_put() + +This can be abused to underflow a parent's qlen. + +Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog() +should fix the race, because all packets will be purged from the qdisc +before releasing the lock. + +Fixes: 0c8d13ac9607 ("net: sched: red: delay destroying child qdisc on replace") +Reported-by: Gerrard Tai +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250611111515.1983366-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_red.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c +index 935d90874b1b7..1b69b7b90d858 100644 +--- a/net/sched/sch_red.c ++++ b/net/sched/sch_red.c +@@ -283,7 +283,7 @@ static int __red_change(struct Qdisc *sch, struct nlattr **tb, + q->userbits = userbits; + q->limit = ctl->limit; + if (child) { +- qdisc_tree_flush_backlog(q->qdisc); ++ qdisc_purge_queue(q->qdisc); + old_child = q->qdisc; + q->qdisc = child; + } +-- +2.39.5 + diff --git a/queue-5.10/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch b/queue-5.10/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch new file mode 100644 index 0000000000..a8d90da2e7 --- /dev/null +++ b/queue-5.10/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch @@ -0,0 +1,70 @@ +From 06dda4a78d823b5bb0ccfb2cf3a20dbb401133c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Jun 2025 16:51:27 +0000 +Subject: net_sched: sch_sfq: fix a potential crash on gso_skb handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 82ffbe7776d0ac084031f114167712269bf3d832 ] + +SFQ has an assumption of always being able to queue at least one packet. + +However, after the blamed commit, sch->q.len can be inflated by packets +in sch->gso_skb, and an enqueue() on an empty SFQ qdisc can be followed +by an immediate drop. + +Fix sfq_drop() to properly clear q->tail in this situation. + +Tested: + +ip netns add lb +ip link add dev to-lb type veth peer name in-lb netns lb +ethtool -K to-lb tso off # force qdisc to requeue gso_skb +ip netns exec lb ethtool -K in-lb gro on # enable NAPI +ip link set dev to-lb up +ip -netns lb link set dev in-lb up +ip addr add dev to-lb 192.168.20.1/24 +ip -netns lb addr add dev in-lb 192.168.20.2/24 +tc qdisc replace dev to-lb root sfq limit 100 + +ip netns exec lb netserver + +netperf -H 192.168.20.2 -l 100 & +netperf -H 192.168.20.2 -l 100 & +netperf -H 192.168.20.2 -l 100 & +netperf -H 192.168.20.2 -l 100 & + +Fixes: a53851e2c321 ("net: sched: explicit locking in gso_cpu fallback") +Reported-by: Marcus Wichelmann +Closes: https://lore.kernel.org/netdev/9da42688-bfaa-4364-8797-e9271f3bdaef@hetzner-cloud.de/ +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250606165127.3629486-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_sfq.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c +index 066754a18569b..6b65c5efb378e 100644 +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -317,7 +317,10 @@ static unsigned int sfq_drop(struct Qdisc *sch, struct sk_buff **to_free) + /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */ + x = q->tail->next; + slot = &q->slots[x]; +- q->tail->next = slot->next; ++ if (slot->next == x) ++ q->tail = NULL; /* no more active slots */ ++ else ++ q->tail->next = slot->next; + q->ht[slot->hash] = SFQ_EMPTY_SLOT; + goto drop; + } +-- +2.39.5 + diff --git a/queue-5.10/net_sched-tbf-fix-a-race-in-tbf_change.patch b/queue-5.10/net_sched-tbf-fix-a-race-in-tbf_change.patch new file mode 100644 index 0000000000..c0fde184ba --- /dev/null +++ b/queue-5.10/net_sched-tbf-fix-a-race-in-tbf_change.patch @@ -0,0 +1,59 @@ +From ce4cb70b21348c74fb791c1eb5b19b6325d22488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:13 +0000 +Subject: net_sched: tbf: fix a race in tbf_change() + +From: Eric Dumazet + +[ Upstream commit 43eb466041216d25dedaef1c383ad7bd89929cbc ] + +Gerrard Tai reported a race condition in TBF, whenever SFQ perturb timer +fires at the wrong time. + +The race is as follows: + +CPU 0 CPU 1 +[1]: lock root +[2]: qdisc_tree_flush_backlog() +[3]: unlock root + | + | [5]: lock root + | [6]: rehash + | [7]: qdisc_tree_reduce_backlog() + | +[4]: qdisc_put() + +This can be abused to underflow a parent's qlen. + +Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog() +should fix the race, because all packets will be purged from the qdisc +before releasing the lock. + +Fixes: b05972f01e7d ("net: sched: tbf: don't call qdisc_put() while holding tree lock") +Reported-by: Gerrard Tai +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Cc: Zhengchao Shao +Link: https://patch.msgid.link/20250611111515.1983366-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_tbf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c +index 5f50fdeaafa8d..411970dc07f74 100644 +--- a/net/sched/sch_tbf.c ++++ b/net/sched/sch_tbf.c +@@ -437,7 +437,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt, + + sch_tree_lock(sch); + if (child) { +- qdisc_tree_flush_backlog(q->qdisc); ++ qdisc_purge_queue(q->qdisc); + old = q->qdisc; + q->qdisc = child; + } +-- +2.39.5 + diff --git a/queue-5.10/powerpc-vas-move-vas-api-to-book3s-common-platform.patch b/queue-5.10/powerpc-vas-move-vas-api-to-book3s-common-platform.patch new file mode 100644 index 0000000000..00b51d4aa4 --- /dev/null +++ b/queue-5.10/powerpc-vas-move-vas-api-to-book3s-common-platform.patch @@ -0,0 +1,171 @@ +From 1e56e13d819b3e31b51274183f924972dc9cd6ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Jun 2021 13:29:48 -0700 +Subject: powerpc/vas: Move VAS API to book3s common platform + +From: Haren Myneni + +[ Upstream commit 413d6ed3eac387a2876893c337174f0c5b99d01d ] + +The pseries platform will share vas and nx code and interfaces +with the PowerNV platform, so create the +arch/powerpc/platforms/book3s/ directory and move VAS API code +there. Functionality is not changed. + +Signed-off-by: Haren Myneni +Reviewed-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/e05c8db17b9eabe3545b902d034238e4c6c08180.camel@linux.ibm.com +Stable-dep-of: 0d67f0dee6c9 ("powerpc/vas: Return -EINVAL if the offset is non-zero in mmap()") +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/vas.h | 3 +++ + arch/powerpc/platforms/Kconfig | 1 + + arch/powerpc/platforms/Makefile | 1 + + arch/powerpc/platforms/book3s/Kconfig | 15 +++++++++++++++ + arch/powerpc/platforms/book3s/Makefile | 2 ++ + .../platforms/{powernv => book3s}/vas-api.c | 2 +- + arch/powerpc/platforms/powernv/Kconfig | 14 -------------- + arch/powerpc/platforms/powernv/Makefile | 2 +- + arch/powerpc/platforms/powernv/vas.h | 2 -- + 9 files changed, 24 insertions(+), 18 deletions(-) + create mode 100644 arch/powerpc/platforms/book3s/Kconfig + create mode 100644 arch/powerpc/platforms/book3s/Makefile + rename arch/powerpc/platforms/{powernv => book3s}/vas-api.c (99%) + +diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h +index 47062b4570490..c6df6fefbe8c2 100644 +--- a/arch/powerpc/include/asm/vas.h ++++ b/arch/powerpc/include/asm/vas.h +@@ -162,6 +162,9 @@ int vas_copy_crb(void *crb, int offset); + */ + int vas_paste_crb(struct vas_window *win, int offset, bool re); + ++void vas_win_paste_addr(struct vas_window *window, u64 *addr, ++ int *len); ++ + /* + * Register / unregister coprocessor type to VAS API which will be exported + * to user space. Applications can use this API to open / close window +diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig +index 7a5e8f4541e3f..594544a65b024 100644 +--- a/arch/powerpc/platforms/Kconfig ++++ b/arch/powerpc/platforms/Kconfig +@@ -20,6 +20,7 @@ source "arch/powerpc/platforms/embedded6xx/Kconfig" + source "arch/powerpc/platforms/44x/Kconfig" + source "arch/powerpc/platforms/40x/Kconfig" + source "arch/powerpc/platforms/amigaone/Kconfig" ++source "arch/powerpc/platforms/book3s/Kconfig" + + config KVM_GUEST + bool "KVM Guest support" +diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile +index 143d4417f6ccc..0e75d7df387bb 100644 +--- a/arch/powerpc/platforms/Makefile ++++ b/arch/powerpc/platforms/Makefile +@@ -22,3 +22,4 @@ obj-$(CONFIG_PPC_CELL) += cell/ + obj-$(CONFIG_PPC_PS3) += ps3/ + obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/ + obj-$(CONFIG_AMIGAONE) += amigaone/ ++obj-$(CONFIG_PPC_BOOK3S) += book3s/ +diff --git a/arch/powerpc/platforms/book3s/Kconfig b/arch/powerpc/platforms/book3s/Kconfig +new file mode 100644 +index 0000000000000..34c931592ef01 +--- /dev/null ++++ b/arch/powerpc/platforms/book3s/Kconfig +@@ -0,0 +1,15 @@ ++# SPDX-License-Identifier: GPL-2.0 ++config PPC_VAS ++ bool "IBM Virtual Accelerator Switchboard (VAS)" ++ depends on (PPC_POWERNV || PPC_PSERIES) && PPC_64K_PAGES ++ default y ++ help ++ This enables support for IBM Virtual Accelerator Switchboard (VAS). ++ ++ VAS devices are found in POWER9-based and later systems, they ++ provide access to accelerator coprocessors such as NX-GZIP and ++ NX-842. This config allows the kernel to use NX-842 accelerators, ++ and user-mode APIs for the NX-GZIP accelerator on POWER9 PowerNV ++ and POWER10 PowerVM platforms. ++ ++ If unsure, say "N". +diff --git a/arch/powerpc/platforms/book3s/Makefile b/arch/powerpc/platforms/book3s/Makefile +new file mode 100644 +index 0000000000000..e790f1910f617 +--- /dev/null ++++ b/arch/powerpc/platforms/book3s/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++obj-$(CONFIG_PPC_VAS) += vas-api.o +diff --git a/arch/powerpc/platforms/powernv/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c +similarity index 99% +rename from arch/powerpc/platforms/powernv/vas-api.c +rename to arch/powerpc/platforms/book3s/vas-api.c +index 98ed5d8c5441a..cfc9d7dd65abc 100644 +--- a/arch/powerpc/platforms/powernv/vas-api.c ++++ b/arch/powerpc/platforms/book3s/vas-api.c +@@ -10,9 +10,9 @@ + #include + #include + #include ++#include + #include + #include +-#include "vas.h" + + /* + * The driver creates the device node that can be used as follows: +diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig +index 938803eab0ad4..b3cb3d0c51c76 100644 +--- a/arch/powerpc/platforms/powernv/Kconfig ++++ b/arch/powerpc/platforms/powernv/Kconfig +@@ -33,20 +33,6 @@ config PPC_MEMTRACE + Enabling this option allows for the removal of memory (RAM) + from the kernel mappings to be used for hardware tracing. + +-config PPC_VAS +- bool "IBM Virtual Accelerator Switchboard (VAS)" +- depends on PPC_POWERNV && PPC_64K_PAGES +- default y +- help +- This enables support for IBM Virtual Accelerator Switchboard (VAS). +- +- VAS allows accelerators in co-processors like NX-GZIP and NX-842 +- to be accessible to kernel subsystems and user processes. +- +- VAS adapters are found in POWER9 based systems. +- +- If unsure, say N. +- + config SCOM_DEBUGFS + bool "Expose SCOM controllers via debugfs" + depends on DEBUG_FS +diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile +index 2eb6ae150d1fd..c747a1f1d25b7 100644 +--- a/arch/powerpc/platforms/powernv/Makefile ++++ b/arch/powerpc/platforms/powernv/Makefile +@@ -18,7 +18,7 @@ obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o + obj-$(CONFIG_OPAL_PRD) += opal-prd.o + obj-$(CONFIG_PERF_EVENTS) += opal-imc.o + obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o +-obj-$(CONFIG_PPC_VAS) += vas.o vas-window.o vas-debug.o vas-fault.o vas-api.o ++obj-$(CONFIG_PPC_VAS) += vas.o vas-window.o vas-debug.o vas-fault.o + obj-$(CONFIG_OCXL_BASE) += ocxl.o + obj-$(CONFIG_SCOM_DEBUGFS) += opal-xscom.o + obj-$(CONFIG_PPC_SECURE_BOOT) += opal-secvar.o +diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h +index 1f6e73809205e..032b04d4d3d45 100644 +--- a/arch/powerpc/platforms/powernv/vas.h ++++ b/arch/powerpc/platforms/powernv/vas.h +@@ -437,8 +437,6 @@ extern irqreturn_t vas_fault_handler(int irq, void *dev_id); + extern void vas_return_credit(struct vas_window *window, bool tx); + extern struct vas_window *vas_pswid_to_window(struct vas_instance *vinst, + uint32_t pswid); +-extern void vas_win_paste_addr(struct vas_window *window, u64 *addr, +- int *len); + + static inline int vas_window_pid(struct vas_window *window) + { +-- +2.39.5 + diff --git a/queue-5.10/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch b/queue-5.10/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch new file mode 100644 index 0000000000..ce9cf7b8ef --- /dev/null +++ b/queue-5.10/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch @@ -0,0 +1,52 @@ +From 65d4ac4ebbfedb2443cefce53dd8620a99c7167d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 07:42:27 +0530 +Subject: powerpc/vas: Return -EINVAL if the offset is non-zero in mmap() + +From: Haren Myneni + +[ Upstream commit 0d67f0dee6c9176bc09a5482dd7346e3a0f14d0b ] + +The user space calls mmap() to map VAS window paste address +and the kernel returns the complete mapped page for each +window. So return -EINVAL if non-zero is passed for offset +parameter to mmap(). + +See Documentation/arch/powerpc/vas-api.rst for mmap() +restrictions. + +Co-developed-by: Jonathan Greental +Signed-off-by: Jonathan Greental +Reported-by: Jonathan Greental +Fixes: dda44eb29c23 ("powerpc/vas: Add VAS user space API") +Signed-off-by: Haren Myneni +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250610021227.361980-2-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/book3s/vas-api.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c +index cfc9d7dd65abc..9bf6bc700ae98 100644 +--- a/arch/powerpc/platforms/book3s/vas-api.c ++++ b/arch/powerpc/platforms/book3s/vas-api.c +@@ -162,6 +162,15 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) + return -EINVAL; + } + ++ /* ++ * Map complete page to the paste address. So the user ++ * space should pass 0ULL to the offset parameter. ++ */ ++ if (vma->vm_pgoff) { ++ pr_debug("Page offset unsupported to map paste address\n"); ++ return -EINVAL; ++ } ++ + /* Ensure instance has an open send window */ + if (!txwin) { + pr_err("%s(): No send window open?\n", __func__); +-- +2.39.5 + diff --git a/queue-5.10/sch_ets-make-est_qlen_notify-idempotent.patch b/queue-5.10/sch_ets-make-est_qlen_notify-idempotent.patch new file mode 100644 index 0000000000..e1620e4eab --- /dev/null +++ b/queue-5.10/sch_ets-make-est_qlen_notify-idempotent.patch @@ -0,0 +1,71 @@ +From 4584e87283a76cc7479c675a944d614d98a11b69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Apr 2025 14:10:27 -0700 +Subject: sch_ets: make est_qlen_notify() idempotent + +From: Cong Wang + +[ Upstream commit a7a15f39c682ac4268624da2abdb9114bdde96d5 ] + +est_qlen_notify() deletes its class from its active list with +list_del() when qlen is 0, therefore, it is not idempotent and +not friendly to its callers, like fq_codel_dequeue(). + +Let's make it idempotent to ease qdisc_tree_reduce_backlog() callers' +life. Also change other list_del()'s to list_del_init() just to be +extra safe. + +Reported-by: Gerrard Tai +Signed-off-by: Cong Wang +Link: https://patch.msgid.link/20250403211033.166059-6-xiyou.wangcong@gmail.com +Acked-by: Jamal Hadi Salim +Signed-off-by: Paolo Abeni +Stable-dep-of: d92adacdd8c2 ("net_sched: ets: fix a race in ets_qdisc_change()") +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 35b8577aef7dc..55b3362d27106 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -298,7 +298,7 @@ static void ets_class_qlen_notify(struct Qdisc *sch, unsigned long arg) + * to remove them. + */ + if (!ets_class_is_strict(q, cl) && sch->q.qlen) +- list_del(&cl->alist); ++ list_del_init(&cl->alist); + } + + static int ets_class_dump(struct Qdisc *sch, unsigned long arg, +@@ -499,7 +499,7 @@ static struct sk_buff *ets_qdisc_dequeue(struct Qdisc *sch) + if (unlikely(!skb)) + goto out; + if (cl->qdisc->q.qlen == 0) +- list_del(&cl->alist); ++ list_del_init(&cl->alist); + return ets_qdisc_dequeue_skb(sch, skb); + } + +@@ -674,7 +674,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + } + for (i = q->nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) +- list_del(&q->classes[i].alist); ++ list_del_init(&q->classes[i].alist); + qdisc_tree_flush_backlog(q->classes[i].qdisc); + } + q->nstrict = nstrict; +@@ -723,7 +723,7 @@ static void ets_qdisc_reset(struct Qdisc *sch) + + for (band = q->nstrict; band < q->nbands; band++) { + if (q->classes[band].qdisc->q.qlen) +- list_del(&q->classes[band].alist); ++ list_del_init(&q->classes[band].alist); + } + for (band = 0; band < q->nbands; band++) + qdisc_reset(q->classes[band].qdisc); +-- +2.39.5 + diff --git a/queue-5.10/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch b/queue-5.10/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch new file mode 100644 index 0000000000..9fdcaeae28 --- /dev/null +++ b/queue-5.10/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch @@ -0,0 +1,99 @@ +From aa60ccdb339bd570c6642a0e35e5309f8361c0fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 May 2025 12:29:35 -0700 +Subject: scsi: iscsi: Fix incorrect error path labels for flashnode operations + +From: Alok Tiwari + +[ Upstream commit 9b17621366d210ffee83262a8754086ebbde5e55 ] + +Correct the error handling goto labels used when host lookup fails in +various flashnode-related event handlers: + + - iscsi_new_flashnode() + - iscsi_del_flashnode() + - iscsi_login_flashnode() + - iscsi_logout_flashnode() + - iscsi_logout_flashnode_sid() + +scsi_host_put() is not required when shost is NULL, so jumping to the +correct label avoids unnecessary operations. These functions previously +jumped to the wrong goto label (put_host), which did not match the +intended cleanup logic. + +Use the correct exit labels (exit_new_fnode, exit_del_fnode, etc.) to +ensure proper error handling. Also remove the unused put_host label +under iscsi_new_flashnode() as it is no longer needed. + +No functional changes beyond accurate error path correction. + +Fixes: c6a4bb2ef596 ("[SCSI] scsi_transport_iscsi: Add flash node mgmt support") +Signed-off-by: Alok Tiwari +Link: https://lore.kernel.org/r/20250530193012.3312911-1-alok.a.tiwari@oracle.com +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_transport_iscsi.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index 548adbe544444..9fdfe1be95166 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -3502,7 +3502,7 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport, + pr_err("%s could not find host no %u\n", + __func__, ev->u.new_flashnode.host_no); + err = -ENODEV; +- goto put_host; ++ goto exit_new_fnode; + } + + index = transport->new_flashnode(shost, data, len); +@@ -3512,7 +3512,6 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport, + else + err = -EIO; + +-put_host: + scsi_host_put(shost); + + exit_new_fnode: +@@ -3537,7 +3536,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport, + pr_err("%s could not find host no %u\n", + __func__, ev->u.del_flashnode.host_no); + err = -ENODEV; +- goto put_host; ++ goto exit_del_fnode; + } + + idx = ev->u.del_flashnode.flashnode_idx; +@@ -3579,7 +3578,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport, + pr_err("%s could not find host no %u\n", + __func__, ev->u.login_flashnode.host_no); + err = -ENODEV; +- goto put_host; ++ goto exit_login_fnode; + } + + idx = ev->u.login_flashnode.flashnode_idx; +@@ -3631,7 +3630,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport, + pr_err("%s could not find host no %u\n", + __func__, ev->u.logout_flashnode.host_no); + err = -ENODEV; +- goto put_host; ++ goto exit_logout_fnode; + } + + idx = ev->u.logout_flashnode.flashnode_idx; +@@ -3681,7 +3680,7 @@ static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport, + pr_err("%s could not find host no %u\n", + __func__, ev->u.logout_flashnode.host_no); + err = -ENODEV; +- goto put_host; ++ goto exit_logout_sid; + } + + session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid); +-- +2.39.5 + diff --git a/queue-5.10/series b/queue-5.10/series index 2788493436..3b4fbcb948 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -114,3 +114,26 @@ serial-sh-sci-check-if-tx-data-was-written-to-device.patch serial-sh-sci-move-runtime-pm-enable-to-sci_probe_si.patch serial-sh-sci-clean-sci_ports-0-after-at-earlycon-ex.patch serial-sh-sci-increment-the-runtime-usage-counter-fo.patch +ath10k-add-atomic-protection-for-device-recovery.patch +ath10k-prevent-deinitializing-napi-twice.patch +ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch +scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch +net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch +powerpc-vas-move-vas-api-to-book3s-common-platform.patch +powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch +i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch +i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch +tcp-factorize-logic-into-tcp_epollin_ready.patch +bpf-clean-up-sockmap-related-kconfigs.patch +net-rename-stream_memory_read-to-sock_is_readable.patch +net-fix-toctou-issue-in-sk_is_readable.patch +macsec-macsec-sci-assignment-for-es-0.patch +net-mdio-c22-is-now-optional-eopnotsupp-if-not-provi.patch +net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch +net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch +net-mlx5-fix-return-value-when-searching-for-existin.patch +net_sched-prio-fix-a-race-in-prio_tune.patch +net_sched-red-fix-a-race-in-__red_change.patch +net_sched-tbf-fix-a-race-in-tbf_change.patch +sch_ets-make-est_qlen_notify-idempotent.patch +net_sched-ets-fix-a-race-in-ets_qdisc_change.patch diff --git a/queue-5.10/tcp-factorize-logic-into-tcp_epollin_ready.patch b/queue-5.10/tcp-factorize-logic-into-tcp_epollin_ready.patch new file mode 100644 index 0000000000..80b66e3a5d --- /dev/null +++ b/queue-5.10/tcp-factorize-logic-into-tcp_epollin_ready.patch @@ -0,0 +1,110 @@ +From 018e9bd7ac907f012c1d84628b6b777b9d1f324d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Feb 2021 15:22:14 -0800 +Subject: tcp: factorize logic into tcp_epollin_ready() + +From: Eric Dumazet + +[ Upstream commit 05dc72aba364d374a27de567fac58c199ff5ee97 ] + +Both tcp_data_ready() and tcp_stream_is_readable() share the same logic. + +Add tcp_epollin_ready() helper to avoid duplication. + +Signed-off-by: Eric Dumazet +Cc: Arjun Roy +Cc: Wei Wang +Signed-off-by: David S. Miller +Stable-dep-of: 2660a544fdc0 ("net: Fix TOCTOU issue in sk_is_readable()") +Signed-off-by: Sasha Levin +--- + include/net/tcp.h | 12 ++++++++++++ + net/ipv4/tcp.c | 18 +++++------------- + net/ipv4/tcp_input.c | 11 ++--------- + 3 files changed, 19 insertions(+), 22 deletions(-) + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 2aad2e79ac6ad..41f535dcaa3f9 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1445,6 +1445,18 @@ static inline bool tcp_rmem_pressure(const struct sock *sk) + return atomic_read(&sk->sk_rmem_alloc) > threshold; + } + ++static inline bool tcp_epollin_ready(const struct sock *sk, int target) ++{ ++ const struct tcp_sock *tp = tcp_sk(sk); ++ int avail = READ_ONCE(tp->rcv_nxt) - READ_ONCE(tp->copied_seq); ++ ++ if (avail <= 0) ++ return false; ++ ++ return (avail >= target) || tcp_rmem_pressure(sk) || ++ (tcp_receive_window(tp) <= inet_csk(sk)->icsk_ack.rcv_mss); ++} ++ + extern void tcp_openreq_init_rwin(struct request_sock *req, + const struct sock *sk_listener, + const struct dst_entry *dst); +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 24ebd51c5e0b8..0332fdab942db 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -476,19 +476,11 @@ static void tcp_tx_timestamp(struct sock *sk, u16 tsflags) + } + } + +-static inline bool tcp_stream_is_readable(const struct tcp_sock *tp, +- int target, struct sock *sk) ++static bool tcp_stream_is_readable(struct sock *sk, int target) + { +- int avail = READ_ONCE(tp->rcv_nxt) - READ_ONCE(tp->copied_seq); +- +- if (avail > 0) { +- if (avail >= target) +- return true; +- if (tcp_rmem_pressure(sk)) +- return true; +- if (tcp_receive_window(tp) <= inet_csk(sk)->icsk_ack.rcv_mss) +- return true; +- } ++ if (tcp_epollin_ready(sk, target)) ++ return true; ++ + if (sk->sk_prot->stream_memory_read) + return sk->sk_prot->stream_memory_read(sk); + return false; +@@ -565,7 +557,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait) + tp->urg_data) + target++; + +- if (tcp_stream_is_readable(tp, target, sk)) ++ if (tcp_stream_is_readable(sk, target)) + mask |= EPOLLIN | EPOLLRDNORM; + + if (!(shutdown & SEND_SHUTDOWN)) { +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 7c2e714527f68..318fdeb1deef3 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -5028,15 +5028,8 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) + + void tcp_data_ready(struct sock *sk) + { +- const struct tcp_sock *tp = tcp_sk(sk); +- int avail = tp->rcv_nxt - tp->copied_seq; +- +- if (avail < sk->sk_rcvlowat && !tcp_rmem_pressure(sk) && +- !sock_flag(sk, SOCK_DONE) && +- tcp_receive_window(tp) > inet_csk(sk)->icsk_ack.rcv_mss) +- return; +- +- sk->sk_data_ready(sk); ++ if (tcp_epollin_ready(sk, sk->sk_rcvlowat)) ++ sk->sk_data_ready(sk); + } + + static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) +-- +2.39.5 +