From: Sasha Levin Date: Mon, 1 Dec 2025 11:28:41 +0000 (-0500) Subject: Fixes for all trees X-Git-Tag: v5.4.302~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d02808c34ec1644998f05a97c1fa25dc5cce24cb;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch b/queue-5.10/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch new file mode 100644 index 0000000000..e495bbd1b1 --- /dev/null +++ b/queue-5.10/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch @@ -0,0 +1,87 @@ +From 640db2238d6ef51f4fa56c77430fef02b116dad3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 13:45:13 -0500 +Subject: Bluetooth: SMP: Fix not generating mackey and ltk when repairing + +From: Luiz Augusto von Dentz + +[ Upstream commit 545d7827b2cd5de5eb85580cebeda6b35b3ff443 ] + +The change eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +introduced a goto that bypasses the creation of temporary mackey and ltk +which are later used by the likes of DHKey Check step. + +Later ffee202a78c2 ("Bluetooth: Always request for user confirmation for +Just Works (LE SC)") which means confirm_hint is always set in case +JUST_WORKS so the branch checking for an existing LTK becomes pointless +as confirm_hint will always be set, so this just merge both cases of +malicious or legitimate devices to be confirmed before continuing with the +pairing procedure. + +Link: https://github.com/bluez/bluez/issues/1622 +Fixes: eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index fc896d39a6d95..79550d115364e 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2131,7 +2131,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_chan *smp = chan->data; + struct hci_conn *hcon = conn->hcon; + u8 *pkax, *pkbx, *na, *nb, confirm_hint; +- u32 passkey; ++ u32 passkey = 0; + int err; + + bt_dev_dbg(hcon->hdev, "conn %p", conn); +@@ -2183,24 +2183,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +- +- /* Only Just-Works pairing requires extra checks */ +- if (smp->method != JUST_WORKS) +- goto mackey_and_ltk; +- +- /* If there already exists long term key in local host, leave +- * the decision to user space since the remote device could +- * be legitimate or malicious. +- */ +- if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, +- hcon->role)) { +- /* Set passkey to 0. The value can be any number since +- * it'll be ignored anyway. +- */ +- passkey = 0; +- confirm_hint = 1; +- goto confirm; +- } + } + + mackey_and_ltk: +@@ -2221,11 +2203,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (err) + return SMP_UNSPECIFIED; + +- confirm_hint = 0; +- +-confirm: +- if (smp->method == JUST_WORKS) +- confirm_hint = 1; ++ /* Always require user confirmation for Just-Works pairing to prevent ++ * impersonation attacks, or in case of a legitimate device that is ++ * repairing use the confirmation as acknowledgment to proceed with the ++ * creation of new keys. ++ */ ++ confirm_hint = smp->method == JUST_WORKS ? 1 : 0; + + err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, + hcon->dst_type, passkey, confirm_hint); +-- +2.51.0 + diff --git a/queue-5.10/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch b/queue-5.10/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch new file mode 100644 index 0000000000..8b224ec20d --- /dev/null +++ b/queue-5.10/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch @@ -0,0 +1,62 @@ +From ac75463fa7dccb4dbb575156e1dc1dd0f512c25e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 12:27:09 -0400 +Subject: can: kvaser_usb: leaf: Fix potential infinite loop in command parsers + +From: Seungjin Bae + +[ Upstream commit 0c73772cd2b8cc108d5f5334de89ad648d89b9ec ] + +The `kvaser_usb_leaf_wait_cmd()` and `kvaser_usb_leaf_read_bulk_callback` +functions contain logic to zero-length commands. These commands are used +to align data to the USB endpoint's wMaxPacketSize boundary. + +The driver attempts to skip these placeholders by aligning the buffer +position `pos` to the next packet boundary using `round_up()` function. + +However, if zero-length command is found exactly on a packet boundary +(i.e., `pos` is a multiple of wMaxPacketSize, including 0), `round_up` +function will return the unchanged value of `pos`. This prevents `pos` +to be increased, causing an infinite loop in the parsing logic. + +This patch fixes this in the function by using `pos + 1` instead. +This ensures that even if `pos` is on a boundary, the calculation is +based on `pos + 1`, forcing `round_up()` to always return the next +aligned boundary. + +Fixes: 7259124eac7d ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") +Signed-off-by: Seungjin Bae +Reviewed-by: Jimmy Assarsson +Tested-by: Jimmy Assarsson +Link: https://patch.msgid.link/20251023162709.348240-1-eeodqql09@gmail.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index f06d63db9077b..df0460e3633c5 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -609,7 +609,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, + * for further details. + */ + if (tmp->len == 0) { +- pos = round_up(pos, ++ pos = round_up(pos + 1, + le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; +@@ -1571,7 +1571,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, + * number of events in case of a heavy rx load on the bus. + */ + if (cmd->len == 0) { +- pos = round_up(pos, le16_to_cpu ++ pos = round_up(pos + 1, le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; + } +-- +2.51.0 + diff --git a/queue-5.10/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch b/queue-5.10/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch new file mode 100644 index 0000000000..6bffb4c350 --- /dev/null +++ b/queue-5.10/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch @@ -0,0 +1,38 @@ +From 80951cd3e40c00d65475fb735cdcfa1095d92a90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 10:40:39 +0800 +Subject: mailbox: mailbox-test: Fix debugfs_create_dir error checking + +From: Haotian Zhang + +[ Upstream commit 3acf1028f5003731977f750a7070f3321a9cb740 ] + +The debugfs_create_dir() function returns ERR_PTR() on error, not NULL. +The current null-check fails to catch errors. + +Use IS_ERR() to correctly check for errors. + +Fixes: 8ea4484d0c2b ("mailbox: Add generic mechanism for testing Mailbox Controllers") +Signed-off-by: Haotian Zhang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c +index abcee58e851c2..29c04157b5e88 100644 +--- a/drivers/mailbox/mailbox-test.c ++++ b/drivers/mailbox/mailbox-test.c +@@ -267,7 +267,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, + return 0; + + tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); +- if (!tdev->root_debugfs_dir) { ++ if (IS_ERR(tdev->root_debugfs_dir)) { + dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-5.10/net-aquantia-add-missing-descriptor-cache-invalidati.patch b/queue-5.10/net-aquantia-add-missing-descriptor-cache-invalidati.patch new file mode 100644 index 0000000000..9c6480bfe7 --- /dev/null +++ b/queue-5.10/net-aquantia-add-missing-descriptor-cache-invalidati.patch @@ -0,0 +1,144 @@ +From e531ecd8d1df22162e87c2a783bee8e613cc400e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 12:15:33 +0800 +Subject: net: aquantia: Add missing descriptor cache invalidation on ATL2 + +From: Kai-Heng Feng + +[ Upstream commit 7526183cfdbe352c51c285762f0e15b7c428ea06 ] + +ATL2 hardware was missing descriptor cache invalidation in hw_stop(), +causing SMMU translation faults during device shutdown and module removal: +[ 70.355743] arm-smmu-v3 arm-smmu-v3.5.auto: event 0x10 received: +[ 70.361893] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0002060000000010 +[ 70.367948] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000020000000000 +[ 70.374002] arm-smmu-v3 arm-smmu-v3.5.auto: 0x00000000ff9bc000 +[ 70.380055] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000000000000000 +[ 70.386109] arm-smmu-v3 arm-smmu-v3.5.auto: event: F_TRANSLATION client: 0001:06:00.0 sid: 0x20600 ssid: 0x0 iova: 0xff9bc000 ipa: 0x0 +[ 70.398531] arm-smmu-v3 arm-smmu-v3.5.auto: unpriv data write s1 "Input address caused fault" stag: 0x0 + +Commit 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after +driver unbind") and commit ed4d81c4b3f2 ("net: aquantia: when cleaning +hw cache it should be toggled") fixed cache invalidation for ATL B0, but +ATL2 was left with only interrupt disabling. This allowed hardware to +write to cached descriptors after DMA memory was unmapped, triggering +SMMU faults. Once cache invalidation is applied to ATL2, the translation +fault can't be observed anymore. + +Add shared aq_hw_invalidate_descriptor_cache() helper and use it in both +ATL B0 and ATL2 hw_stop() implementations for consistent behavior. + +Fixes: e54dcf4bba3e ("net: atlantic: basic A2 init/deinit hw_ops") +Tested-by: Carol Soto +Signed-off-by: Kai-Heng Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251120041537.62184-1-kaihengf@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/aquantia/atlantic/aq_hw_utils.c | 22 +++++++++++++++++++ + .../ethernet/aquantia/atlantic/aq_hw_utils.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 +--------------- + .../aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 4 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 1921741f7311d..18b08277d2e1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -15,6 +15,7 @@ + + #include "aq_hw.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_llh.h" + + void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, + u32 shift, u32 val) +@@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) + lo_hi_writeq(value, hw->mmio + reg); + } + ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) ++{ ++ int err; ++ u32 val; ++ ++ /* Invalidate Descriptor Cache to prevent writing to the cached ++ * descriptors and to the data pointer of those descriptors ++ */ ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); ++ ++ err = aq_hw_err_from_flags(hw); ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ hw, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index ffa6e4067c211..d89c63d88e4a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 45c17c585d743..2236bc9ba54d2 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { +- int err; +- u32 val; +- + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +- /* Invalidate Descriptor Cache to prevent writing to the cached +- * descriptors and to the data pointer of those descriptors +- */ +- hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); +- +- err = aq_hw_err_from_flags(self); +- +- if (err) +- goto err_exit; +- +- readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, +- self, val, val == 1, 1000U, 10000U); +- +-err_exit: +- return err; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index c76ccdc77ba60..98d4ba879dd08 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + { + hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); + +- return 0; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) +-- +2.51.0 + diff --git a/queue-5.10/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch b/queue-5.10/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch new file mode 100644 index 0000000000..e70e487984 --- /dev/null +++ b/queue-5.10/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch @@ -0,0 +1,93 @@ +From 0ae576feb2cca8e7e9fc7ffaa349e20490d52893 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:22:49 +0800 +Subject: net: atlantic: fix fragment overflow handling in RX path + +From: Jiefeng Zhang + +[ Upstream commit 5ffcb7b890f61541201461580bb6622ace405aec ] + +The atlantic driver can receive packets with more than MAX_SKB_FRAGS (17) +fragments when handling large multi-descriptor packets. This causes an +out-of-bounds write in skb_add_rx_frag_netmem() leading to kernel panic. + +The issue occurs because the driver doesn't check the total number of +fragments before calling skb_add_rx_frag(). When a packet requires more +than MAX_SKB_FRAGS fragments, the fragment index exceeds the array bounds. + +Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, +then all fragments are accounted for. And reusing the existing check to +prevent the overflow earlier in the code path. + +This crash occurred in production with an Aquantia AQC113 10G NIC. + +Stack trace from production environment: +``` +RIP: 0010:skb_add_rx_frag_netmem+0x29/0xd0 +Code: 90 f3 0f 1e fa 0f 1f 44 00 00 48 89 f8 41 89 +ca 48 89 d7 48 63 ce 8b 90 c0 00 00 00 48 c1 e1 04 48 01 ca 48 03 90 +c8 00 00 00 <48> 89 7a 30 44 89 52 3c 44 89 42 38 40 f6 c7 01 75 74 48 +89 fa 83 +RSP: 0018:ffffa9bec02a8d50 EFLAGS: 00010287 +RAX: ffff925b22e80a00 RBX: ffff925ad38d2700 RCX: +fffffffe0a0c8000 +RDX: ffff9258ea95bac0 RSI: ffff925ae0a0c800 RDI: +0000000000037a40 +RBP: 0000000000000024 R08: 0000000000000000 R09: +0000000000000021 +R10: 0000000000000848 R11: 0000000000000000 R12: +ffffa9bec02a8e24 +R13: ffff925ad8615570 R14: 0000000000000000 R15: +ffff925b22e80a00 +FS: 0000000000000000(0000) +GS:ffff925e47880000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffff9258ea95baf0 CR3: 0000000166022004 CR4: +0000000000f72ef0 +PKRU: 55555554 +Call Trace: + +aq_ring_rx_clean+0x175/0xe60 [atlantic] +? aq_ring_rx_clean+0x14d/0xe60 [atlantic] +? aq_ring_tx_clean+0xdf/0x190 [atlantic] +? kmem_cache_free+0x348/0x450 +? aq_vec_poll+0x81/0x1d0 [atlantic] +? __napi_poll+0x28/0x1c0 +? net_rx_action+0x337/0x420 +``` + +Fixes: 6aecbba12b5c ("net: atlantic: add check for MAX_SKB_FRAGS") +Changes in v4: +- Add Fixes: tag to satisfy patch validation requirements. + +Changes in v3: +- Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, + then all fragments are accounted for. + +Signed-off-by: Jiefeng Zhang +Link: https://patch.msgid.link/20251126032249.69358-1-jiefeng.z.zhang@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 98e8997f80366..5a85999987b51 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -363,6 +363,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + + if (!buff->is_eop) { + unsigned int frag_cnt = 0U; ++ ++ /* There will be an extra fragment */ ++ if (buff->len > AQ_CFG_RX_HDR_SIZE) ++ frag_cnt++; ++ + buff_ = buff; + do { + bool is_rsc_completed = true; +-- +2.51.0 + diff --git a/queue-5.10/net-mlx5e-fix-validation-logic-in-rate-limiting.patch b/queue-5.10/net-mlx5e-fix-validation-logic-in-rate-limiting.patch new file mode 100644 index 0000000000..c28f4b2f12 --- /dev/null +++ b/queue-5.10/net-mlx5e-fix-validation-logic-in-rate-limiting.patch @@ -0,0 +1,63 @@ +From ec944ba8223659be12f78a3d2861954451f454a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:00:43 -0800 +Subject: net/mlx5e: Fix validation logic in rate limiting + +From: Danielle Costantino + +[ Upstream commit d2099d9f16dbfa1c5266d4230ff7860047bb0b68 ] + +The rate limiting validation condition currently checks the output +variable max_bw_value[i] instead of the input value +maxrate->tc_maxrate[i]. This causes the validation to compare an +uninitialized or stale value rather than the actual requested rate. + +The condition should check the input rate to properly validate against +the upper limit: + + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + +This aligns with the pattern used in the first branch, which correctly +checks maxrate->tc_maxrate[i] against upper_limit_mbps. + +The current implementation can lead to unreliable validation behavior: + +- For rates between 25.5 Gbps and 255 Gbps, if max_bw_value[i] is 0 + from initialization, the GBPS path may be taken regardless of whether + the actual rate is within bounds + +- When processing multiple TCs (i > 0), max_bw_value[i] contains the + value computed for the previous TC, affecting the validation logic + +- The overflow check for rates exceeding 255 Gbps may not trigger + consistently depending on previous array values + +This patch ensures the validation correctly examines the requested rate +value for proper bounds checking. + +Fixes: 43b27d1bd88a ("net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps") +Signed-off-by: Danielle Costantino +Reviewed-by: Gal Pressman +Link: https://patch.msgid.link/20251124180043.2314428-1-dcostantino@meta.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 5c48a4872f35d..5d0be9703a48e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -606,7 +606,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else if (max_bw_value[i] <= upper_limit_gbps) { ++ } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; +-- +2.51.0 + diff --git a/queue-5.10/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch b/queue-5.10/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch new file mode 100644 index 0000000000..2e663dc44b --- /dev/null +++ b/queue-5.10/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch @@ -0,0 +1,47 @@ +From 12dcd3112fd40c76a265e5307b26a7a1babe1675 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 12:38:34 +0000 +Subject: net: sxgbe: fix potential NULL dereference in sxgbe_rx() + +From: Alexey Kodanev + +[ Upstream commit f5bce28f6b9125502abec4a67d68eabcd24b3b17 ] + +Currently, when skb is null, the driver prints an error and then +dereferences skb on the next line. + +To fix this, let's add a 'break' after the error message to switch +to sxgbe_rx_refill(), which is similar to the approach taken by the +other drivers in this particular case, e.g. calxeda with xgmac_rx(). + +Found during a code review. + +Fixes: 1edb9ca69e8a ("net: sxgbe: add basic framework for Samsung 10Gb ethernet driver") +Signed-off-by: Alexey Kodanev +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121123834.97748-1-aleksei.kodanev@bell-sw.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index b1dd6189638b3..9c745d48f54b0 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -1518,8 +1518,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) + + skb = priv->rxq[qnum]->rx_skbuff[entry]; + +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + netdev_err(priv->dev, "rx descriptor is not consistent\n"); ++ break; ++ } + + prefetch(skb->data - NET_IP_ALIGN); + priv->rxq[qnum]->rx_skbuff[entry] = NULL; +-- +2.51.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 4a4b5a7211..b408256b18 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -255,3 +255,11 @@ mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch usb-deprecate-the-third-argument-of-usb_maxpacket.patch input-remove-third-argument-of-usb_maxpacket.patch input-pegasus-notetaker-fix-potential-out-of-bounds-access.patch +can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch +bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch +net-aquantia-add-missing-descriptor-cache-invalidati.patch +net-mlx5e-fix-validation-logic-in-rate-limiting.patch +net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch +net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch +mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch +spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch diff --git a/queue-5.10/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch b/queue-5.10/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch new file mode 100644 index 0000000000..57c40f61df --- /dev/null +++ b/queue-5.10/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch @@ -0,0 +1,68 @@ +From 470b7cb63012aa36a0e070ff4db165f6e2b9de26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 01:08:35 +1100 +Subject: spi: bcm63xx: fix premature CS deassertion on RX-only transactions + +From: Hang Zhou <929513338@qq.com> + +[ Upstream commit fd9862f726aedbc2f29a29916cabed7bcf5cadb6 ] + +On BCM6358 (and also observed on BCM6368) the controller appears to +only generate as many SPI clocks as bytes that have been written into +the TX FIFO. For RX-only transfers the driver programs the transfer +length in SPI_MSG_CTL but does not write anything into the FIFO, so +chip select is deasserted early and the RX transfer segment is never +fully clocked in. + +A concrete failing case is a three-transfer MAC address read from +SPI-NOR: + - TX 0x03 (read command) + - TX 3-byte address + - RX 6 bytes (MAC) + +In contrast, a two-transfer JEDEC-ID read (0x9f + 6-byte RX) works +because the driver uses prepend_len and writes dummy bytes into the +TX FIFO for the RX part. + +Fix this by writing 0xff dummy bytes into the TX FIFO for RX-only +segments so that the number of bytes written to the FIFO matches the +total message length seen by the controller. + +Fixes: b17de076062a ("spi/bcm63xx: work around inability to keep CS up") + +Signed-off-by: Hang Zhou <929513338@qq.com> +Link: https://patch.msgid.link/tencent_7AC88FCB3076489A4A7E6C2163DF1ACF8D06@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm63xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c +index da559b86f6b17..e05f8913ccda9 100644 +--- a/drivers/spi/spi-bcm63xx.c ++++ b/drivers/spi/spi-bcm63xx.c +@@ -257,6 +257,20 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + + if (t->rx_buf) { + do_rx = true; ++ ++ /* ++ * In certain hardware implementations, there appears to be a ++ * hidden accumulator that tracks the number of bytes written into ++ * the hardware FIFO, and this accumulator overrides the length in ++ * the SPI_MSG_CTL register. ++ * ++ * Therefore, for read-only transfers, we need to write some dummy ++ * value into the FIFO to keep the accumulator tracking the correct ++ * length. ++ */ ++ if (!t->tx_buf) ++ memset_io(bs->tx_io + len, 0xFF, t->len); ++ + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch b/queue-5.15/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch new file mode 100644 index 0000000000..ab4716e374 --- /dev/null +++ b/queue-5.15/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch @@ -0,0 +1,87 @@ +From 63f0138108df7382a3ebadf08c81700b8a868d98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 13:45:13 -0500 +Subject: Bluetooth: SMP: Fix not generating mackey and ltk when repairing + +From: Luiz Augusto von Dentz + +[ Upstream commit 545d7827b2cd5de5eb85580cebeda6b35b3ff443 ] + +The change eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +introduced a goto that bypasses the creation of temporary mackey and ltk +which are later used by the likes of DHKey Check step. + +Later ffee202a78c2 ("Bluetooth: Always request for user confirmation for +Just Works (LE SC)") which means confirm_hint is always set in case +JUST_WORKS so the branch checking for an existing LTK becomes pointless +as confirm_hint will always be set, so this just merge both cases of +malicious or legitimate devices to be confirmed before continuing with the +pairing procedure. + +Link: https://github.com/bluez/bluez/issues/1622 +Fixes: eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index 697ec98b07982..d1ba41153b66a 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2130,7 +2130,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_chan *smp = chan->data; + struct hci_conn *hcon = conn->hcon; + u8 *pkax, *pkbx, *na, *nb, confirm_hint; +- u32 passkey; ++ u32 passkey = 0; + int err; + + bt_dev_dbg(hcon->hdev, "conn %p", conn); +@@ -2182,24 +2182,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +- +- /* Only Just-Works pairing requires extra checks */ +- if (smp->method != JUST_WORKS) +- goto mackey_and_ltk; +- +- /* If there already exists long term key in local host, leave +- * the decision to user space since the remote device could +- * be legitimate or malicious. +- */ +- if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, +- hcon->role)) { +- /* Set passkey to 0. The value can be any number since +- * it'll be ignored anyway. +- */ +- passkey = 0; +- confirm_hint = 1; +- goto confirm; +- } + } + + mackey_and_ltk: +@@ -2220,11 +2202,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (err) + return SMP_UNSPECIFIED; + +- confirm_hint = 0; +- +-confirm: +- if (smp->method == JUST_WORKS) +- confirm_hint = 1; ++ /* Always require user confirmation for Just-Works pairing to prevent ++ * impersonation attacks, or in case of a legitimate device that is ++ * repairing use the confirmation as acknowledgment to proceed with the ++ * creation of new keys. ++ */ ++ confirm_hint = smp->method == JUST_WORKS ? 1 : 0; + + err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, + hcon->dst_type, passkey, confirm_hint); +-- +2.51.0 + diff --git a/queue-5.15/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch b/queue-5.15/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch new file mode 100644 index 0000000000..ea2d4dc700 --- /dev/null +++ b/queue-5.15/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch @@ -0,0 +1,62 @@ +From 371a6daac73aa67adcd2cdce99eed93faec04488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 12:27:09 -0400 +Subject: can: kvaser_usb: leaf: Fix potential infinite loop in command parsers + +From: Seungjin Bae + +[ Upstream commit 0c73772cd2b8cc108d5f5334de89ad648d89b9ec ] + +The `kvaser_usb_leaf_wait_cmd()` and `kvaser_usb_leaf_read_bulk_callback` +functions contain logic to zero-length commands. These commands are used +to align data to the USB endpoint's wMaxPacketSize boundary. + +The driver attempts to skip these placeholders by aligning the buffer +position `pos` to the next packet boundary using `round_up()` function. + +However, if zero-length command is found exactly on a packet boundary +(i.e., `pos` is a multiple of wMaxPacketSize, including 0), `round_up` +function will return the unchanged value of `pos`. This prevents `pos` +to be increased, causing an infinite loop in the parsing logic. + +This patch fixes this in the function by using `pos + 1` instead. +This ensures that even if `pos` is on a boundary, the calculation is +based on `pos + 1`, forcing `round_up()` to always return the next +aligned boundary. + +Fixes: 7259124eac7d ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") +Signed-off-by: Seungjin Bae +Reviewed-by: Jimmy Assarsson +Tested-by: Jimmy Assarsson +Link: https://patch.msgid.link/20251023162709.348240-1-eeodqql09@gmail.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 43ec056646661..b6cef22a53e77 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -610,7 +610,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, + * for further details. + */ + if (tmp->len == 0) { +- pos = round_up(pos, ++ pos = round_up(pos + 1, + le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; +@@ -1568,7 +1568,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, + * number of events in case of a heavy rx load on the bus. + */ + if (cmd->len == 0) { +- pos = round_up(pos, le16_to_cpu ++ pos = round_up(pos + 1, le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; + } +-- +2.51.0 + diff --git a/queue-5.15/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch b/queue-5.15/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch new file mode 100644 index 0000000000..5a44e3d7e2 --- /dev/null +++ b/queue-5.15/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch @@ -0,0 +1,38 @@ +From b64719d251d172e1e13abebb78a0ede52319225b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 10:40:39 +0800 +Subject: mailbox: mailbox-test: Fix debugfs_create_dir error checking + +From: Haotian Zhang + +[ Upstream commit 3acf1028f5003731977f750a7070f3321a9cb740 ] + +The debugfs_create_dir() function returns ERR_PTR() on error, not NULL. +The current null-check fails to catch errors. + +Use IS_ERR() to correctly check for errors. + +Fixes: 8ea4484d0c2b ("mailbox: Add generic mechanism for testing Mailbox Controllers") +Signed-off-by: Haotian Zhang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c +index abcee58e851c2..29c04157b5e88 100644 +--- a/drivers/mailbox/mailbox-test.c ++++ b/drivers/mailbox/mailbox-test.c +@@ -267,7 +267,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, + return 0; + + tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); +- if (!tdev->root_debugfs_dir) { ++ if (IS_ERR(tdev->root_debugfs_dir)) { + dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-5.15/net-aquantia-add-missing-descriptor-cache-invalidati.patch b/queue-5.15/net-aquantia-add-missing-descriptor-cache-invalidati.patch new file mode 100644 index 0000000000..a809487e71 --- /dev/null +++ b/queue-5.15/net-aquantia-add-missing-descriptor-cache-invalidati.patch @@ -0,0 +1,144 @@ +From cf1a2253aee7b16583890e24cd7cc914af719ba4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 12:15:33 +0800 +Subject: net: aquantia: Add missing descriptor cache invalidation on ATL2 + +From: Kai-Heng Feng + +[ Upstream commit 7526183cfdbe352c51c285762f0e15b7c428ea06 ] + +ATL2 hardware was missing descriptor cache invalidation in hw_stop(), +causing SMMU translation faults during device shutdown and module removal: +[ 70.355743] arm-smmu-v3 arm-smmu-v3.5.auto: event 0x10 received: +[ 70.361893] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0002060000000010 +[ 70.367948] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000020000000000 +[ 70.374002] arm-smmu-v3 arm-smmu-v3.5.auto: 0x00000000ff9bc000 +[ 70.380055] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000000000000000 +[ 70.386109] arm-smmu-v3 arm-smmu-v3.5.auto: event: F_TRANSLATION client: 0001:06:00.0 sid: 0x20600 ssid: 0x0 iova: 0xff9bc000 ipa: 0x0 +[ 70.398531] arm-smmu-v3 arm-smmu-v3.5.auto: unpriv data write s1 "Input address caused fault" stag: 0x0 + +Commit 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after +driver unbind") and commit ed4d81c4b3f2 ("net: aquantia: when cleaning +hw cache it should be toggled") fixed cache invalidation for ATL B0, but +ATL2 was left with only interrupt disabling. This allowed hardware to +write to cached descriptors after DMA memory was unmapped, triggering +SMMU faults. Once cache invalidation is applied to ATL2, the translation +fault can't be observed anymore. + +Add shared aq_hw_invalidate_descriptor_cache() helper and use it in both +ATL B0 and ATL2 hw_stop() implementations for consistent behavior. + +Fixes: e54dcf4bba3e ("net: atlantic: basic A2 init/deinit hw_ops") +Tested-by: Carol Soto +Signed-off-by: Kai-Heng Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251120041537.62184-1-kaihengf@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/aquantia/atlantic/aq_hw_utils.c | 22 +++++++++++++++++++ + .../ethernet/aquantia/atlantic/aq_hw_utils.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 +--------------- + .../aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 4 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 1921741f7311d..18b08277d2e1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -15,6 +15,7 @@ + + #include "aq_hw.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_llh.h" + + void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, + u32 shift, u32 val) +@@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) + lo_hi_writeq(value, hw->mmio + reg); + } + ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) ++{ ++ int err; ++ u32 val; ++ ++ /* Invalidate Descriptor Cache to prevent writing to the cached ++ * descriptors and to the data pointer of those descriptors ++ */ ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); ++ ++ err = aq_hw_err_from_flags(hw); ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ hw, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index ffa6e4067c211..d89c63d88e4a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 15ede7285fb5d..b50c9b6dfb5bf 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { +- int err; +- u32 val; +- + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +- /* Invalidate Descriptor Cache to prevent writing to the cached +- * descriptors and to the data pointer of those descriptors +- */ +- hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); +- +- err = aq_hw_err_from_flags(self); +- +- if (err) +- goto err_exit; +- +- readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, +- self, val, val == 1, 1000U, 10000U); +- +-err_exit: +- return err; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 5dfc751572edc..bc4e1b6035e08 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + { + hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); + +- return 0; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) +-- +2.51.0 + diff --git a/queue-5.15/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch b/queue-5.15/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch new file mode 100644 index 0000000000..9e537f79f6 --- /dev/null +++ b/queue-5.15/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch @@ -0,0 +1,93 @@ +From 57ab00a7fad6120b0fea857846123f0e2e0fb55f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:22:49 +0800 +Subject: net: atlantic: fix fragment overflow handling in RX path + +From: Jiefeng Zhang + +[ Upstream commit 5ffcb7b890f61541201461580bb6622ace405aec ] + +The atlantic driver can receive packets with more than MAX_SKB_FRAGS (17) +fragments when handling large multi-descriptor packets. This causes an +out-of-bounds write in skb_add_rx_frag_netmem() leading to kernel panic. + +The issue occurs because the driver doesn't check the total number of +fragments before calling skb_add_rx_frag(). When a packet requires more +than MAX_SKB_FRAGS fragments, the fragment index exceeds the array bounds. + +Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, +then all fragments are accounted for. And reusing the existing check to +prevent the overflow earlier in the code path. + +This crash occurred in production with an Aquantia AQC113 10G NIC. + +Stack trace from production environment: +``` +RIP: 0010:skb_add_rx_frag_netmem+0x29/0xd0 +Code: 90 f3 0f 1e fa 0f 1f 44 00 00 48 89 f8 41 89 +ca 48 89 d7 48 63 ce 8b 90 c0 00 00 00 48 c1 e1 04 48 01 ca 48 03 90 +c8 00 00 00 <48> 89 7a 30 44 89 52 3c 44 89 42 38 40 f6 c7 01 75 74 48 +89 fa 83 +RSP: 0018:ffffa9bec02a8d50 EFLAGS: 00010287 +RAX: ffff925b22e80a00 RBX: ffff925ad38d2700 RCX: +fffffffe0a0c8000 +RDX: ffff9258ea95bac0 RSI: ffff925ae0a0c800 RDI: +0000000000037a40 +RBP: 0000000000000024 R08: 0000000000000000 R09: +0000000000000021 +R10: 0000000000000848 R11: 0000000000000000 R12: +ffffa9bec02a8e24 +R13: ffff925ad8615570 R14: 0000000000000000 R15: +ffff925b22e80a00 +FS: 0000000000000000(0000) +GS:ffff925e47880000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffff9258ea95baf0 CR3: 0000000166022004 CR4: +0000000000f72ef0 +PKRU: 55555554 +Call Trace: + +aq_ring_rx_clean+0x175/0xe60 [atlantic] +? aq_ring_rx_clean+0x14d/0xe60 [atlantic] +? aq_ring_tx_clean+0xdf/0x190 [atlantic] +? kmem_cache_free+0x348/0x450 +? aq_vec_poll+0x81/0x1d0 [atlantic] +? __napi_poll+0x28/0x1c0 +? net_rx_action+0x337/0x420 +``` + +Fixes: 6aecbba12b5c ("net: atlantic: add check for MAX_SKB_FRAGS") +Changes in v4: +- Add Fixes: tag to satisfy patch validation requirements. + +Changes in v3: +- Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, + then all fragments are accounted for. + +Signed-off-by: Jiefeng Zhang +Link: https://patch.msgid.link/20251126032249.69358-1-jiefeng.z.zhang@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 98e8997f80366..5a85999987b51 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -363,6 +363,11 @@ int aq_ring_rx_clean(struct aq_ring_s *self, + + if (!buff->is_eop) { + unsigned int frag_cnt = 0U; ++ ++ /* There will be an extra fragment */ ++ if (buff->len > AQ_CFG_RX_HDR_SIZE) ++ frag_cnt++; ++ + buff_ = buff; + do { + bool is_rsc_completed = true; +-- +2.51.0 + diff --git a/queue-5.15/net-dsa-sja1105-convert-to-mdiobus_c45_read.patch b/queue-5.15/net-dsa-sja1105-convert-to-mdiobus_c45_read.patch new file mode 100644 index 0000000000..e42d5cbe86 --- /dev/null +++ b/queue-5.15/net-dsa-sja1105-convert-to-mdiobus_c45_read.patch @@ -0,0 +1,47 @@ +From 51f827d77bb1d58680b1616cad4c38c138736e7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 Apr 2022 19:30:36 +0200 +Subject: net: dsa: sja1105: Convert to mdiobus_c45_read + +From: Andrew Lunn + +[ Upstream commit 639e4b93ab68f5f5fc4734c766124ca96c167f14 ] + +Stop using the helpers to construct a special phy address which +indicates C45. Instead use the C45 accessors, which will call the +busses C45 specific read/write API. + +Reviewed-by: Vladimir Oltean +Tested-by: Vladimir Oltean +Signed-off-by: Andrew Lunn +Signed-off-by: Paolo Abeni +Stable-dep-of: da62abaaa268 ("net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing traffic") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index ec1c0ad591184..5c37478a7e822 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -2180,14 +2180,13 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + * change it through the dynamic interface later. + */ + for (i = 0; i < ds->num_ports; i++) { +- u32 reg_addr = mdiobus_c45_addr(MDIO_MMD_VEND2, MDIO_CTRL1); +- + speed_mbps[i] = sja1105_port_speed_to_ethtool(priv, + mac[i].speed); + mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO]; + + if (priv->xpcs[i]) +- bmcr[i] = mdiobus_read(priv->mdio_pcs, i, reg_addr); ++ bmcr[i] = mdiobus_c45_read(priv->mdio_pcs, i, ++ MDIO_MMD_VEND2, MDIO_CTRL1); + } + + /* No PTP operations can run right now */ +-- +2.51.0 + diff --git a/queue-5.15/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch b/queue-5.15/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch new file mode 100644 index 0000000000..f8af9603c6 --- /dev/null +++ b/queue-5.15/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch @@ -0,0 +1,73 @@ +From 2d0825ffb6c49ecde155caa9259ec64eda3eeb3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 13:13:24 +0200 +Subject: net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing + traffic + +From: Vladimir Oltean + +[ Upstream commit da62abaaa268357b1aa66b372ace562189a05df1 ] + +When using the SGMII PCS as a fixed-link chip-to-chip connection, it is +easy to miss the fact that traffic passes only at 1G, since that's what +any normal such connection would use. + +When using the SGMII PCS connected towards an on-board PHY or an SFP +module, it is immediately noticeable that when the link resolves to a +speed other than 1G, traffic from the MAC fails to pass: TX counters +increase, but nothing gets decoded by the other end, and no local RX +counters increase either. + +Artificially lowering a fixed-link rate to speed = <100> makes us able +to see the same issue as in the case of having an SGMII PHY. + +Some debugging shows that the XPCS configuration is A-OK, but that the +MAC Configuration Table entry for the port has the SPEED bits still set +to 1000Mbps, due to a special condition in the driver. Deleting that +condition, and letting the resolved link speed be programmed directly +into the MAC speed field, results in a functional link at all 3 speeds. + +This piece of evidence, based on testing on both generations with SGMII +support (SJA1105S and SJA1110A) directly contradicts the statement from +the blamed commit that "the MAC is fixed at 1 Gbps and we need to +configure the PCS only (if even that)". Worse, that statement is not +backed by any documentation, and no one from NXP knows what it might +refer to. + +I am unable to recall sufficient context regarding my testing from March +2020 to understand what led me to draw such a braindead and factually +incorrect conclusion. Yet, there is nothing of value regarding forcing +the MAC speed, either for SGMII or 2500Base-X (introduced at a later +stage), so remove all such logic. + +Fixes: ffe10e679cec ("net: dsa: sja1105: Add support for the SGMII port") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251122111324.136761-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index 5773d5e72b06f..3a5674e90d77d 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1238,14 +1238,7 @@ static int sja1105_set_port_speed(struct sja1105_private *priv, int port, + * table, since this will be used for the clocking setup, and we no + * longer need to store it in the static config (already told hardware + * we want auto during upload phase). +- * Actually for the SGMII port, the MAC is fixed at 1 Gbps and +- * we need to configure the PCS only (if even that). + */ +- if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; +- else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- + mac[port].speed = speed; + + return 0; +-- +2.51.0 + diff --git a/queue-5.15/net-dsa-sja1105-simplify-static-configuration-reload.patch b/queue-5.15/net-dsa-sja1105-simplify-static-configuration-reload.patch new file mode 100644 index 0000000000..5d4bbd7a0d --- /dev/null +++ b/queue-5.15/net-dsa-sja1105-simplify-static-configuration-reload.patch @@ -0,0 +1,159 @@ +From 4a3d64177f9face7d14909b614ca74e5bb2e86b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 17:04:36 +0100 +Subject: net: dsa: sja1105: simplify static configuration reload + +From: Russell King (Oracle) + +[ Upstream commit a18891b55703a45b700618ef40edd5e9aaecc345 ] + +The static configuration reload saves the port speed in the static +configuration tables by first converting it from the internal +respresentation to the SPEED_xxx ethtool representation, and then +converts it back to restore the setting. This is because +sja1105_adjust_port_config() takes the speed as SPEED_xxx. + +However, this is unnecessarily complex. If we split +sja1105_adjust_port_config() up, we can simply save and restore the +mac[port].speed member in the static configuration tables. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1svfMa-005ZIX-If@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: da62abaaa268 ("net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing traffic") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 65 ++++++++++++++------------ + 1 file changed, 34 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index 5c37478a7e822..5773d5e72b06f 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1192,29 +1192,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv) + return rc; + } + +-/* Convert link speed from SJA1105 to ethtool encoding */ +-static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, +- u64 speed) +-{ +- if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) +- return SPEED_10; +- if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) +- return SPEED_100; +- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) +- return SPEED_1000; +- if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS]) +- return SPEED_2500; +- return SPEED_UNKNOWN; +-} +- +-/* Set link speed in the MAC configuration for a specific port. */ +-static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, +- int speed_mbps) ++static int sja1105_set_port_speed(struct sja1105_private *priv, int port, ++ int speed_mbps) + { + struct sja1105_mac_config_entry *mac; +- struct device *dev = priv->ds->dev; + u64 speed; +- int rc; + + /* On P/Q/R/S, one can read from the device via the MAC reconfiguration + * tables. On E/T, MAC reconfig tables are not readable, only writable. +@@ -1248,7 +1230,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; + break; + default: +- dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); ++ dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps); + return -EINVAL; + } + +@@ -1260,11 +1242,31 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + * we need to configure the PCS only (if even that). + */ + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; ++ speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; + else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- else +- mac[port].speed = speed; ++ speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; ++ ++ mac[port].speed = speed; ++ ++ return 0; ++} ++ ++/* Write the MAC Configuration Table entry and, if necessary, the CGU settings, ++ * after a link speedchange for this port. ++ */ ++static int sja1105_set_port_config(struct sja1105_private *priv, int port) ++{ ++ struct sja1105_mac_config_entry *mac; ++ struct device *dev = priv->ds->dev; ++ int rc; ++ ++ /* On P/Q/R/S, one can read from the device via the MAC reconfiguration ++ * tables. On E/T, MAC reconfig tables are not readable, only writable. ++ * We have to *know* what the MAC looks like. For the sake of keeping ++ * the code common, we'll use the static configuration tables as a ++ * reasonable approximation for both E/T and P/Q/R/S. ++ */ ++ mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + + /* Write to the dynamic reconfiguration tables */ + rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, +@@ -1335,7 +1337,8 @@ static void sja1105_mac_link_up(struct dsa_switch *ds, int port, + { + struct sja1105_private *priv = ds->priv; + +- sja1105_adjust_port_config(priv, port, speed); ++ if (!sja1105_set_port_speed(priv, port, speed)) ++ sja1105_set_port_config(priv, port); + + sja1105_inhibit_tx(priv, BIT(port), false); + } +@@ -2161,8 +2164,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + { + struct ptp_system_timestamp ptp_sts_before; + struct ptp_system_timestamp ptp_sts_after; +- int speed_mbps[SJA1105_MAX_NUM_PORTS]; + u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0}; ++ u64 mac_speed[SJA1105_MAX_NUM_PORTS]; + struct sja1105_mac_config_entry *mac; + struct dsa_switch *ds = priv->ds; + s64 t1, t2, t3, t4; +@@ -2174,14 +2177,13 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + +- /* Back up the dynamic link speed changed by sja1105_adjust_port_config ++ /* Back up the dynamic link speed changed by sja1105_set_port_speed() + * in order to temporarily restore it to SJA1105_SPEED_AUTO - which the + * switch wants to see in the static config in order to allow us to + * change it through the dynamic interface later. + */ + for (i = 0; i < ds->num_ports; i++) { +- speed_mbps[i] = sja1105_port_speed_to_ethtool(priv, +- mac[i].speed); ++ mac_speed[i] = mac[i].speed; + mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO]; + + if (priv->xpcs[i]) +@@ -2244,7 +2246,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + struct dw_xpcs *xpcs = priv->xpcs[i]; + unsigned int mode; + +- rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); ++ mac[i].speed = mac_speed[i]; ++ rc = sja1105_set_port_config(priv, i); + if (rc < 0) + goto out; + +-- +2.51.0 + diff --git a/queue-5.15/net-mlx5e-fix-validation-logic-in-rate-limiting.patch b/queue-5.15/net-mlx5e-fix-validation-logic-in-rate-limiting.patch new file mode 100644 index 0000000000..d38dbc91b4 --- /dev/null +++ b/queue-5.15/net-mlx5e-fix-validation-logic-in-rate-limiting.patch @@ -0,0 +1,63 @@ +From 924fce4678eaebf7bcbfeabf4f97636fc469c97c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:00:43 -0800 +Subject: net/mlx5e: Fix validation logic in rate limiting + +From: Danielle Costantino + +[ Upstream commit d2099d9f16dbfa1c5266d4230ff7860047bb0b68 ] + +The rate limiting validation condition currently checks the output +variable max_bw_value[i] instead of the input value +maxrate->tc_maxrate[i]. This causes the validation to compare an +uninitialized or stale value rather than the actual requested rate. + +The condition should check the input rate to properly validate against +the upper limit: + + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + +This aligns with the pattern used in the first branch, which correctly +checks maxrate->tc_maxrate[i] against upper_limit_mbps. + +The current implementation can lead to unreliable validation behavior: + +- For rates between 25.5 Gbps and 255 Gbps, if max_bw_value[i] is 0 + from initialization, the GBPS path may be taken regardless of whether + the actual rate is within bounds + +- When processing multiple TCs (i > 0), max_bw_value[i] contains the + value computed for the previous TC, affecting the validation logic + +- The overflow check for rates exceeding 255 Gbps may not trigger + consistently depending on previous array values + +This patch ensures the validation correctly examines the requested rate +value for proper bounds checking. + +Fixes: 43b27d1bd88a ("net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps") +Signed-off-by: Danielle Costantino +Reviewed-by: Gal Pressman +Link: https://patch.msgid.link/20251124180043.2314428-1-dcostantino@meta.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 86545554abb4e..dae944d28ee26 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -606,7 +606,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else if (max_bw_value[i] <= upper_limit_gbps) { ++ } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; +-- +2.51.0 + diff --git a/queue-5.15/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch b/queue-5.15/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch new file mode 100644 index 0000000000..4633759ce6 --- /dev/null +++ b/queue-5.15/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch @@ -0,0 +1,47 @@ +From 8f6b17346c6077f9522020218876ea62efde5fc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 12:38:34 +0000 +Subject: net: sxgbe: fix potential NULL dereference in sxgbe_rx() + +From: Alexey Kodanev + +[ Upstream commit f5bce28f6b9125502abec4a67d68eabcd24b3b17 ] + +Currently, when skb is null, the driver prints an error and then +dereferences skb on the next line. + +To fix this, let's add a 'break' after the error message to switch +to sxgbe_rx_refill(), which is similar to the approach taken by the +other drivers in this particular case, e.g. calxeda with xgmac_rx(). + +Found during a code review. + +Fixes: 1edb9ca69e8a ("net: sxgbe: add basic framework for Samsung 10Gb ethernet driver") +Signed-off-by: Alexey Kodanev +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121123834.97748-1-aleksei.kodanev@bell-sw.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index 1b415fe6f9b9f..1fe687b594f9d 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -1518,8 +1518,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) + + skb = priv->rxq[qnum]->rx_skbuff[entry]; + +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + netdev_err(priv->dev, "rx descriptor is not consistent\n"); ++ break; ++ } + + prefetch(skb->data - NET_IP_ALIGN); + priv->rxq[qnum]->rx_skbuff[entry] = NULL; +-- +2.51.0 + diff --git a/queue-5.15/platform-x86-intel-punit_ipc-fix-memory-corruption.patch b/queue-5.15/platform-x86-intel-punit_ipc-fix-memory-corruption.patch new file mode 100644 index 0000000000..6808bd6fdb --- /dev/null +++ b/queue-5.15/platform-x86-intel-punit_ipc-fix-memory-corruption.patch @@ -0,0 +1,46 @@ +From e6827d0db89e9fa282c89ea13ca42dac005f72c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 20:51:28 +0300 +Subject: platform/x86: intel: punit_ipc: fix memory corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit 9b9c0adbc3f8a524d291baccc9d0c04097fb4869 ] + +This passes the address of the pointer "&punit_ipcdev" when the intent +was to pass the pointer itself "punit_ipcdev" (without the ampersand). +This means that the: + + complete(&ipcdev->cmd_complete); + +in intel_punit_ioc() will write to a wrong memory address corrupting it. + +Fixes: fdca4f16f57d ("platform:x86: add Intel P-Unit mailbox IPC driver") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aSCmoBipSQ_tlD-D@stanley.mountain +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/punit_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/punit_ipc.c b/drivers/platform/x86/intel/punit_ipc.c +index 66bb39fd0ef90..8602f4175f123 100644 +--- a/drivers/platform/x86/intel/punit_ipc.c ++++ b/drivers/platform/x86/intel/punit_ipc.c +@@ -283,7 +283,7 @@ static int intel_punit_ipc_probe(struct platform_device *pdev) + } else { + ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc, + IRQF_NO_SUSPEND, "intel_punit_ipc", +- &punit_ipcdev); ++ punit_ipcdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", irq); + return ret; +-- +2.51.0 + diff --git a/queue-5.15/revert-block-don-t-add-or-resize-partition-on-the-di.patch b/queue-5.15/revert-block-don-t-add-or-resize-partition-on-the-di.patch new file mode 100644 index 0000000000..542d8a977f --- /dev/null +++ b/queue-5.15/revert-block-don-t-add-or-resize-partition-on-the-di.patch @@ -0,0 +1,73 @@ +From cf477fe84e1ca4677cb1b3c358f48e95facc12da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 17:54:15 +0000 +Subject: Revert "block: don't add or resize partition on the disk with + GENHD_FL_NO_PART" + +From: Gulam Mohamed + +This reverts commit 1a721de8489fa559ff4471f73c58bb74ac5580d3. + +The commit 1a721de8489f ("block: don't add or resize partition on the disk +with GENHD_FL_NO_PART") and the commit 7777f47f2ea6 ("block: Move checking +GENHD_FL_NO_PART to bdev_add_partition()") used the flag GENHD_FL_NO_PART +to prevent the add or resize of partitions in 5.15 stable kernels.But in +these 5.15 kernels, this is giving an issue with the following error +where the loop driver wants to create a partition when the partscan is +disabled on the loop device: + +dd if=/dev/zero of=loopDisk.dsk bs=1M count=1 seek=10240; +losetup -f loopDisk.dsk;parted -s /dev/loop0 -- mklabel gpt mkpart primary + 2048s 4096s +1+0 records in +1+0 records out +1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0016293 s, 644 MB/s +"" +Error: Partition(s) 1 on /dev/loop0 have been written, but we have been +unable to inform the kernel of the change, probably because it/they are +in use. As a result, the old partition(s) will remain in use. You should +reboot now before making further changes. +"" +If the partition scan is not enabled on the loop device, this flag +GENHD_FL_NO_PART is getting set and when partition creation is tried, +it returns an error EINVAL thereby preventing the creation of partitions. +So, there is no such distinction between disabling of partition scan and +partition creation. + +Later in 6.xxx kernels, the commit b9684a71fca7 ("block, loop: support +partitions without scanning") a new flag GD_SUPPRESS_PART_SCAN was +introduced that just disables the partition scan and uses GENHD_FL_NO_PART +only to prevent creating partition scan. So, the partition creationg can +proceed with even if partition scan is disabled. + +As the commit b9684a71fca7 ("block, loop: support partitions without +scanning") is not available in 5.15 stable kernel, and since there is no +distinction between disabling of "partition scan" and "partition +creation", we need to revert the commits 1a721de8489f and 7777f47f2ea6 +from 5.15 stable kernel to allow partition creation when partscan is +disabled. + +Cc: stable@vger.kernel.org +Signed-off-by: Gulam Mohamed +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + block/ioctl.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/block/ioctl.c b/block/ioctl.c +index d25b844412378..a260e39e56a48 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -20,8 +20,6 @@ static int blkpg_do_ioctl(struct block_device *bdev, + struct blkpg_partition p; + sector_t start, length; + +- if (disk->flags & GENHD_FL_NO_PART) +- return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (copy_from_user(&p, upart, sizeof(struct blkpg_partition))) +-- +2.51.0 + diff --git a/queue-5.15/revert-block-move-checking-genhd_fl_no_part-to-bdev_.patch b/queue-5.15/revert-block-move-checking-genhd_fl_no_part-to-bdev_.patch new file mode 100644 index 0000000000..32079cb15d --- /dev/null +++ b/queue-5.15/revert-block-move-checking-genhd_fl_no_part-to-bdev_.patch @@ -0,0 +1,73 @@ +From f8e2b74a8c26db44964e8cb800305f135fc53f2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 17:54:14 +0000 +Subject: Revert "block: Move checking GENHD_FL_NO_PART to + bdev_add_partition()" + +From: Gulam Mohamed + +This reverts commit 7777f47f2ea64efd1016262e7b59fab34adfb869. + +The commit 1a721de8489f ("block: don't add or resize partition on the disk +with GENHD_FL_NO_PART") and the commit 7777f47f2ea6 ("block: Move checking +GENHD_FL_NO_PART to bdev_add_partition()") used the flag GENHD_FL_NO_PART +to prevent the add or resize of partitions in 5.15 stable kernels.But in +these 5.15 kernels, this is giving an issue with the following error +where the loop driver wants to create a partition when the partscan is +disabled on the loop device: + +dd if=/dev/zero of=loopDisk.dsk bs=1M count=1 seek=10240; +losetup -f loopDisk.dsk;parted -s /dev/loop0 -- mklabel gpt mkpart primary + 2048s 4096s +1+0 records in +1+0 records out +1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0016293 s, 644 MB/s +"" +Error: Partition(s) 1 on /dev/loop0 have been written, but we have been +unable to inform the kernel of the change, probably because it/they are +in use. As a result, the old partition(s) will remain in use. You should +reboot now before making further changes. +"" +If the partition scan is not enabled on the loop device, this flag +GENHD_FL_NO_PART is getting set and when partition creation is tried, +it returns an error EINVAL thereby preventing the creation of partitions. +So, there is no such distinction between disabling of partition scan and +partition creation. + +Later in 6.xxx kernels, the commit b9684a71fca7 ("block, loop: support +partitions without scanning") a new flag GD_SUPPRESS_PART_SCAN was +introduced that just disables the partition scan and uses GENHD_FL_NO_PART +only to prevent creating partition scan. So, the partition creationg can +proceed with even if partition scan is disabled. + +As the commit b9684a71fca7 ("block, loop: support partitions without +scanning") is not available in 5.15 stable kernel, and since there is no +distinction between disabling of "partition scan" and "partition +creation", we need to revert the commits 1a721de8489f and 7777f47f2ea6 +from 5.15 stable kernel to allow partition creation when partscan is +disabled. + +Cc: stable@vger.kernel.org +Signed-off-by: Gulam Mohamed +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + block/ioctl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/block/ioctl.c b/block/ioctl.c +index a260e39e56a48..d25b844412378 100644 +--- a/block/ioctl.c ++++ b/block/ioctl.c +@@ -20,6 +20,8 @@ static int blkpg_do_ioctl(struct block_device *bdev, + struct blkpg_partition p; + sector_t start, length; + ++ if (disk->flags & GENHD_FL_NO_PART) ++ return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + if (copy_from_user(&p, upart, sizeof(struct blkpg_partition))) +-- +2.51.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 6a6cd0cad8..5020d3b537 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -335,3 +335,17 @@ mptcp-fix-a-race-in-mptcp_pm_del_add_timer.patch mptcp-do-not-fallback-when-ooo-is-present.patch revert-block-move-checking-genhd_fl_no_part-to-bdev_add_partition.patch revert-block-don-t-add-or-resize-partition-on-the-disk-with-genhd_fl_no_part.patch +revert-block-move-checking-genhd_fl_no_part-to-bdev_.patch +revert-block-don-t-add-or-resize-partition-on-the-di.patch +can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch +bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch +platform-x86-intel-punit_ipc-fix-memory-corruption.patch +net-aquantia-add-missing-descriptor-cache-invalidati.patch +net-mlx5e-fix-validation-logic-in-rate-limiting.patch +net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch +net-dsa-sja1105-convert-to-mdiobus_c45_read.patch +net-dsa-sja1105-simplify-static-configuration-reload.patch +net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch +net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch +mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch +spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch diff --git a/queue-5.15/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch b/queue-5.15/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch new file mode 100644 index 0000000000..d785106826 --- /dev/null +++ b/queue-5.15/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch @@ -0,0 +1,68 @@ +From 25cca6d7953458218129d11947a40d5f1ddf3e41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 01:08:35 +1100 +Subject: spi: bcm63xx: fix premature CS deassertion on RX-only transactions + +From: Hang Zhou <929513338@qq.com> + +[ Upstream commit fd9862f726aedbc2f29a29916cabed7bcf5cadb6 ] + +On BCM6358 (and also observed on BCM6368) the controller appears to +only generate as many SPI clocks as bytes that have been written into +the TX FIFO. For RX-only transfers the driver programs the transfer +length in SPI_MSG_CTL but does not write anything into the FIFO, so +chip select is deasserted early and the RX transfer segment is never +fully clocked in. + +A concrete failing case is a three-transfer MAC address read from +SPI-NOR: + - TX 0x03 (read command) + - TX 3-byte address + - RX 6 bytes (MAC) + +In contrast, a two-transfer JEDEC-ID read (0x9f + 6-byte RX) works +because the driver uses prepend_len and writes dummy bytes into the +TX FIFO for the RX part. + +Fix this by writing 0xff dummy bytes into the TX FIFO for RX-only +segments so that the number of bytes written to the FIFO matches the +total message length seen by the controller. + +Fixes: b17de076062a ("spi/bcm63xx: work around inability to keep CS up") + +Signed-off-by: Hang Zhou <929513338@qq.com> +Link: https://patch.msgid.link/tencent_7AC88FCB3076489A4A7E6C2163DF1ACF8D06@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm63xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c +index 2f2a130464651..e57e1f75cd9f9 100644 +--- a/drivers/spi/spi-bcm63xx.c ++++ b/drivers/spi/spi-bcm63xx.c +@@ -257,6 +257,20 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + + if (t->rx_buf) { + do_rx = true; ++ ++ /* ++ * In certain hardware implementations, there appears to be a ++ * hidden accumulator that tracks the number of bytes written into ++ * the hardware FIFO, and this accumulator overrides the length in ++ * the SPI_MSG_CTL register. ++ * ++ * Therefore, for read-only transfers, we need to write some dummy ++ * value into the FIFO to keep the accumulator tracking the correct ++ * length. ++ */ ++ if (!t->tx_buf) ++ memset_io(bs->tx_io + len, 0xFF, t->len); ++ + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; +-- +2.51.0 + diff --git a/queue-6.1/acpi-pcc-add-pcc-shared-memory-region-command-and-st.patch b/queue-6.1/acpi-pcc-add-pcc-shared-memory-region-command-and-st.patch new file mode 100644 index 0000000000..4b83edde27 --- /dev/null +++ b/queue-6.1/acpi-pcc-add-pcc-shared-memory-region-command-and-st.patch @@ -0,0 +1,53 @@ +From c10092f3509fec38d5df8844584d544eea4a4c0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 17:26:10 +0100 +Subject: ACPI: PCC: Add PCC shared memory region command and status bitfields + +From: Sudeep Holla + +[ Upstream commit 55d235ebb684b993b3247740c1c8e273f8af4a54 ] + +Define the common macros to use when referring to various bitfields in +the PCC generic communications channel command and status fields. + +Currently different drivers that need to use these bitfields have defined +these locally. This common macro is intended to consolidate and replace +those. + +Cc: "Rafael J. Wysocki" +Link: https://lore.kernel.org/r/20230927-pcc_defines-v2-1-0b8ffeaef2e5@arm.com +Signed-off-by: Sudeep Holla +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + include/acpi/pcc.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h +index 73e806fe7ce70..9b373d172a776 100644 +--- a/include/acpi/pcc.h ++++ b/include/acpi/pcc.h +@@ -18,7 +18,20 @@ struct pcc_mbox_chan { + u16 min_turnaround_time; + }; + ++/* Generic Communications Channel Shared Memory Region */ ++#define PCC_SIGNATURE 0x50434300 ++/* Generic Communications Channel Command Field */ ++#define PCC_CMD_GENERATE_DB_INTR BIT(15) ++/* Generic Communications Channel Status Field */ ++#define PCC_STATUS_CMD_COMPLETE BIT(0) ++#define PCC_STATUS_SCI_DOORBELL BIT(1) ++#define PCC_STATUS_ERROR BIT(2) ++#define PCC_STATUS_PLATFORM_NOTIFY BIT(3) ++/* Initiator Responder Communications Channel Flags */ ++#define PCC_CMD_COMPLETION_NOTIFY BIT(0) ++ + #define MAX_PCC_SUBSPACES 256 ++ + #ifdef CONFIG_PCC + extern struct pcc_mbox_chan * + pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch b/queue-6.1/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch new file mode 100644 index 0000000000..7728e66095 --- /dev/null +++ b/queue-6.1/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch @@ -0,0 +1,87 @@ +From 8661da0cb140918eedf8e7eda8f64812c98f2f76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 13:45:13 -0500 +Subject: Bluetooth: SMP: Fix not generating mackey and ltk when repairing + +From: Luiz Augusto von Dentz + +[ Upstream commit 545d7827b2cd5de5eb85580cebeda6b35b3ff443 ] + +The change eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +introduced a goto that bypasses the creation of temporary mackey and ltk +which are later used by the likes of DHKey Check step. + +Later ffee202a78c2 ("Bluetooth: Always request for user confirmation for +Just Works (LE SC)") which means confirm_hint is always set in case +JUST_WORKS so the branch checking for an existing LTK becomes pointless +as confirm_hint will always be set, so this just merge both cases of +malicious or legitimate devices to be confirmed before continuing with the +pairing procedure. + +Link: https://github.com/bluez/bluez/issues/1622 +Fixes: eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index a03920fe44d94..d8a77bfe65a62 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2130,7 +2130,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_chan *smp = chan->data; + struct hci_conn *hcon = conn->hcon; + u8 *pkax, *pkbx, *na, *nb, confirm_hint; +- u32 passkey; ++ u32 passkey = 0; + int err; + + bt_dev_dbg(hcon->hdev, "conn %p", conn); +@@ -2182,24 +2182,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +- +- /* Only Just-Works pairing requires extra checks */ +- if (smp->method != JUST_WORKS) +- goto mackey_and_ltk; +- +- /* If there already exists long term key in local host, leave +- * the decision to user space since the remote device could +- * be legitimate or malicious. +- */ +- if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, +- hcon->role)) { +- /* Set passkey to 0. The value can be any number since +- * it'll be ignored anyway. +- */ +- passkey = 0; +- confirm_hint = 1; +- goto confirm; +- } + } + + mackey_and_ltk: +@@ -2220,11 +2202,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (err) + return SMP_UNSPECIFIED; + +- confirm_hint = 0; +- +-confirm: +- if (smp->method == JUST_WORKS) +- confirm_hint = 1; ++ /* Always require user confirmation for Just-Works pairing to prevent ++ * impersonation attacks, or in case of a legitimate device that is ++ * repairing use the confirmation as acknowledgment to proceed with the ++ * creation of new keys. ++ */ ++ confirm_hint = smp->method == JUST_WORKS ? 1 : 0; + + err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, + hcon->dst_type, passkey, confirm_hint); +-- +2.51.0 + diff --git a/queue-6.1/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch b/queue-6.1/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch new file mode 100644 index 0000000000..ef08ed7ae0 --- /dev/null +++ b/queue-6.1/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch @@ -0,0 +1,92 @@ +From 53c30c3182bee84ab1ececd153dbed7aaf1647e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:02 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing header + +From: Marc Kleine-Budde + +[ Upstream commit 6fe9f3279f7d2518439a7962c5870c6e9ecbadcf ] + +The driver expects to receive a struct gs_host_frame in +gs_usb_receive_bulk_callback(). + +Use struct_group to describe the header of the struct gs_host_frame and +check that we have at least received the header before accessing any +members of it. + +To resubmit the URB, do not dereference the pointer chain +"dev->parent->hf_size_rx" but use "parent->hf_size_rx" instead. Since +"urb->context" contains "parent", it is always defined, while "dev" is not +defined if the URB it too short. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-2-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 7fe9d497491d1..5d0cee57ab970 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -252,13 +252,15 @@ struct canfd_quirk { + } __packed; + + struct gs_host_frame { +- u32 echo_id; +- __le32 can_id; ++ struct_group(header, ++ u32 echo_id; ++ __le32 can_id; + +- u8 can_dlc; +- u8 channel; +- u8 flags; +- u8 reserved; ++ u8 can_dlc; ++ u8 channel; ++ u8 flags; ++ u8 reserved; ++ ); + + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); +@@ -528,6 +530,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; ++ unsigned int minimum_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -546,6 +549,15 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + return; + } + ++ minimum_length = sizeof(hf->header); ++ if (urb->actual_length < minimum_length) { ++ dev_err_ratelimited(&parent->udev->dev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ + /* device reports out of range channel id */ + if (hf->channel >= parent->channel_cnt) + goto device_detach; +@@ -642,7 +654,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + resubmit_urb: + usb_fill_bulk_urb(urb, parent->udev, + parent->pipe_in, +- hf, dev->parent->hf_size_rx, ++ hf, parent->hf_size_rx, + gs_usb_receive_bulk_callback, parent); + + rc = usb_submit_urb(urb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.1/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch b/queue-6.1/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch new file mode 100644 index 0000000000..44a60d2625 --- /dev/null +++ b/queue-6.1/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch @@ -0,0 +1,60 @@ +From 0b84d409e3c3bb7e862287010890a4878cfbfd0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:01 +0100 +Subject: can: gs_usb: gs_usb_xmit_callback(): fix handling of failed + transmitted URBs + +From: Marc Kleine-Budde + +[ Upstream commit 516a0cd1c03fa266bb67dd87940a209fd4e53ce7 ] + +The driver lacks the cleanup of failed transfers of URBs. This reduces the +number of available URBs per error by 1. This leads to reduced performance +and ultimately to a complete stop of the transmission. + +If the sending of a bulk URB fails do proper cleanup: +- increase netdev stats +- mark the echo_sbk as free +- free the driver's context and do accounting +- wake the send queue + +Closes: https://github.com/candle-usb/candleLight_fw/issues/187 +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-1-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 2cacea6b00f80..7fe9d497491d1 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -707,8 +707,21 @@ static void gs_usb_xmit_callback(struct urb *urb) + struct gs_can *dev = txc->dev; + struct net_device *netdev = dev->netdev; + +- if (urb->status) +- netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); ++ if (!urb->status) ++ return; ++ ++ if (urb->status != -ESHUTDOWN && net_ratelimit()) ++ netdev_info(netdev, "failed to xmit URB %u: %pe\n", ++ txc->echo_id, ERR_PTR(urb->status)); ++ ++ netdev->stats.tx_dropped++; ++ netdev->stats.tx_errors++; ++ ++ can_free_echo_skb(netdev, txc->echo_id, NULL); ++ gs_free_tx_context(txc); ++ atomic_dec(&dev->active_tx_urbs); ++ ++ netif_wake_queue(netdev); + } + + static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, +-- +2.51.0 + diff --git a/queue-6.1/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch b/queue-6.1/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch new file mode 100644 index 0000000000..7e2bab6d9f --- /dev/null +++ b/queue-6.1/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch @@ -0,0 +1,62 @@ +From 8f6a5d0f33bdabbd2436a714c22aaa38c14e6b09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 12:27:09 -0400 +Subject: can: kvaser_usb: leaf: Fix potential infinite loop in command parsers + +From: Seungjin Bae + +[ Upstream commit 0c73772cd2b8cc108d5f5334de89ad648d89b9ec ] + +The `kvaser_usb_leaf_wait_cmd()` and `kvaser_usb_leaf_read_bulk_callback` +functions contain logic to zero-length commands. These commands are used +to align data to the USB endpoint's wMaxPacketSize boundary. + +The driver attempts to skip these placeholders by aligning the buffer +position `pos` to the next packet boundary using `round_up()` function. + +However, if zero-length command is found exactly on a packet boundary +(i.e., `pos` is a multiple of wMaxPacketSize, including 0), `round_up` +function will return the unchanged value of `pos`. This prevents `pos` +to be increased, causing an infinite loop in the parsing logic. + +This patch fixes this in the function by using `pos + 1` instead. +This ensures that even if `pos` is on a boundary, the calculation is +based on `pos + 1`, forcing `round_up()` to always return the next +aligned boundary. + +Fixes: 7259124eac7d ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") +Signed-off-by: Seungjin Bae +Reviewed-by: Jimmy Assarsson +Tested-by: Jimmy Assarsson +Link: https://patch.msgid.link/20251023162709.348240-1-eeodqql09@gmail.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index b423fd4c79890..57c68bc926d8d 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -608,7 +608,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, + * for further details. + */ + if (tmp->len == 0) { +- pos = round_up(pos, ++ pos = round_up(pos + 1, + le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; +@@ -1567,7 +1567,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, + * number of events in case of a heavy rx load on the bus. + */ + if (cmd->len == 0) { +- pos = round_up(pos, le16_to_cpu ++ pos = round_up(pos + 1, le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; + } +-- +2.51.0 + diff --git a/queue-6.1/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch b/queue-6.1/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch new file mode 100644 index 0000000000..6e993697ce --- /dev/null +++ b/queue-6.1/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch @@ -0,0 +1,39 @@ +From cd8ba40e3698b9edbd6fe5d11f9d231b8ee58ff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 09:40:31 -0500 +Subject: drm/amdgpu: fix cyan_skillfish2 gpu info fw handling + +From: Alex Deucher + +[ Upstream commit 7fa666ab07ba9e08f52f357cb8e1aad753e83ac6 ] + +If the board supports IP discovery, we don't need to +parse the gpu info firmware. + +Backport to 6.18. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4721 +Fixes: fa819e3a7c1e ("drm/amdgpu: add support for cyan skillfish gpu_info") +Signed-off-by: Alex Deucher +(cherry picked from commit 5427e32fa3a0ba9a016db83877851ed277b065fb) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index f18f165876043..38b81ae236cb3 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -2021,6 +2021,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) + chip_name = "navi12"; + break; + case CHIP_CYAN_SKILLFISH: ++ if (adev->mman.discovery_bin) ++ return 0; + chip_name = "cyan_skillfish"; + break; + } +-- +2.51.0 + diff --git a/queue-6.1/mailbox-allow-direct-registration-to-a-channel.patch b/queue-6.1/mailbox-allow-direct-registration-to-a-channel.patch new file mode 100644 index 0000000000..4f87b52f61 --- /dev/null +++ b/queue-6.1/mailbox-allow-direct-registration-to-a-channel.patch @@ -0,0 +1,159 @@ +From ae7efac83b4d5e53609f06c67dfd9d02d61d77e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Apr 2023 09:16:52 -0700 +Subject: mailbox: Allow direct registration to a channel + +From: Elliot Berman + +[ Upstream commit 85a953806557dbf25d16e8c132b5b9b100d16496 ] + +Support virtual mailbox controllers and clients which are not platform +devices or come from the devicetree by allowing them to match client to +channel via some other mechanism. + +Tested-by: Sudeep Holla (pcc) +Signed-off-by: Elliot Berman +Signed-off-by: Jassi Brar +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox.c | 96 ++++++++++++++++++++++++---------- + include/linux/mailbox_client.h | 1 + + 2 files changed, 69 insertions(+), 28 deletions(-) + +diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c +index cb31ad917b352..f4cfbdfe4111c 100644 +--- a/drivers/mailbox/mailbox.c ++++ b/drivers/mailbox/mailbox.c +@@ -317,6 +317,71 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout) + } + EXPORT_SYMBOL_GPL(mbox_flush); + ++static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl) ++{ ++ struct device *dev = cl->dev; ++ unsigned long flags; ++ int ret; ++ ++ if (chan->cl || !try_module_get(chan->mbox->dev->driver->owner)) { ++ dev_dbg(dev, "%s: mailbox not free\n", __func__); ++ return -EBUSY; ++ } ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->msg_free = 0; ++ chan->msg_count = 0; ++ chan->active_req = NULL; ++ chan->cl = cl; ++ init_completion(&chan->tx_complete); ++ ++ if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) ++ chan->txdone_method = TXDONE_BY_ACK; ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ if (chan->mbox->ops->startup) { ++ ret = chan->mbox->ops->startup(chan); ++ ++ if (ret) { ++ dev_err(dev, "Unable to startup the chan (%d)\n", ret); ++ mbox_free_channel(chan); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * mbox_bind_client - Request a mailbox channel. ++ * @chan: The mailbox channel to bind the client to. ++ * @cl: Identity of the client requesting the channel. ++ * ++ * The Client specifies its requirements and capabilities while asking for ++ * a mailbox channel. It can't be called from atomic context. ++ * The channel is exclusively allocated and can't be used by another ++ * client before the owner calls mbox_free_channel. ++ * After assignment, any packet received on this channel will be ++ * handed over to the client via the 'rx_callback'. ++ * The framework holds reference to the client, so the mbox_client ++ * structure shouldn't be modified until the mbox_free_channel returns. ++ * ++ * Return: 0 if the channel was assigned to the client successfully. ++ * <0 for request failure. ++ */ ++int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl) ++{ ++ int ret; ++ ++ mutex_lock(&con_mutex); ++ ret = __mbox_bind_client(chan, cl); ++ mutex_unlock(&con_mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(mbox_bind_client); ++ + /** + * mbox_request_channel - Request a mailbox channel. + * @cl: Identity of the client requesting the channel. +@@ -340,7 +405,6 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) + struct mbox_controller *mbox; + struct of_phandle_args spec; + struct mbox_chan *chan; +- unsigned long flags; + int ret; + + if (!dev || !dev->of_node) { +@@ -373,33 +437,9 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) + return chan; + } + +- if (chan->cl || !try_module_get(mbox->dev->driver->owner)) { +- dev_dbg(dev, "%s: mailbox not free\n", __func__); +- mutex_unlock(&con_mutex); +- return ERR_PTR(-EBUSY); +- } +- +- spin_lock_irqsave(&chan->lock, flags); +- chan->msg_free = 0; +- chan->msg_count = 0; +- chan->active_req = NULL; +- chan->cl = cl; +- init_completion(&chan->tx_complete); +- +- if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) +- chan->txdone_method = TXDONE_BY_ACK; +- +- spin_unlock_irqrestore(&chan->lock, flags); +- +- if (chan->mbox->ops->startup) { +- ret = chan->mbox->ops->startup(chan); +- +- if (ret) { +- dev_err(dev, "Unable to startup the chan (%d)\n", ret); +- mbox_free_channel(chan); +- chan = ERR_PTR(ret); +- } +- } ++ ret = __mbox_bind_client(chan, cl); ++ if (ret) ++ chan = ERR_PTR(ret); + + mutex_unlock(&con_mutex); + return chan; +diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h +index 65229a45590f1..734694912ef74 100644 +--- a/include/linux/mailbox_client.h ++++ b/include/linux/mailbox_client.h +@@ -37,6 +37,7 @@ struct mbox_client { + void (*tx_done)(struct mbox_client *cl, void *mssg, int r); + }; + ++int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl); + struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl, + const char *name); + struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index); +-- +2.51.0 + diff --git a/queue-6.1/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch b/queue-6.1/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch new file mode 100644 index 0000000000..212f184d57 --- /dev/null +++ b/queue-6.1/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch @@ -0,0 +1,38 @@ +From 5b2af21ee3f824906068e45ada8445ce48cc60ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 10:40:39 +0800 +Subject: mailbox: mailbox-test: Fix debugfs_create_dir error checking + +From: Haotian Zhang + +[ Upstream commit 3acf1028f5003731977f750a7070f3321a9cb740 ] + +The debugfs_create_dir() function returns ERR_PTR() on error, not NULL. +The current null-check fails to catch errors. + +Use IS_ERR() to correctly check for errors. + +Fixes: 8ea4484d0c2b ("mailbox: Add generic mechanism for testing Mailbox Controllers") +Signed-off-by: Haotian Zhang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c +index abcee58e851c2..29c04157b5e88 100644 +--- a/drivers/mailbox/mailbox-test.c ++++ b/drivers/mailbox/mailbox-test.c +@@ -267,7 +267,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, + return 0; + + tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); +- if (!tdev->root_debugfs_dir) { ++ if (IS_ERR(tdev->root_debugfs_dir)) { + dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-6.1/mailbox-pcc-add-support-for-platform-notification-ha.patch b/queue-6.1/mailbox-pcc-add-support-for-platform-notification-ha.patch new file mode 100644 index 0000000000..daea01d9e7 --- /dev/null +++ b/queue-6.1/mailbox-pcc-add-support-for-platform-notification-ha.patch @@ -0,0 +1,141 @@ +From f65f37153f3255f5e21581d4e8177e384653d841 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Aug 2023 14:38:26 +0800 +Subject: mailbox: pcc: Add support for platform notification handling + +From: Huisong Li + +[ Upstream commit 60c40b06fa68694dd08a1a0038ea8b9de3f3b1ca ] + +Currently, PCC driver doesn't support the processing of platform +notification for type 4 PCC subspaces. + +According to ACPI specification, if platform sends a notification +to OSPM, it must clear the command complete bit and trigger platform +interrupt. OSPM needs to check whether the command complete bit is +cleared, clear platform interrupt, process command, and then set the +command complete and ring doorbell to the Platform. + +Let us stash the value of the pcc type and use the same while processing +the interrupt of the channel. We also need to set the command complete +bit and ring doorbell in the interrupt handler for the type 4 channel to +complete the communication flow after processing the notification from +the Platform. + +Signed-off-by: Huisong Li +Reviewed-by: Hanjun Guo +Link: https://lore.kernel.org/r/20230801063827.25336-2-lihuisong@huawei.com +Signed-off-by: Sudeep Holla +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 50 +++++++++++++++++++++++++++++++++++-------- + 1 file changed, 41 insertions(+), 9 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index a44d4b3e5beb2..80310b48bfb6a 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -91,6 +91,7 @@ struct pcc_chan_reg { + * @cmd_update: PCC register bundle for the command complete update register + * @error: PCC register bundle for the error status register + * @plat_irq: platform interrupt ++ * @type: PCC subspace type + */ + struct pcc_chan_info { + struct pcc_mbox_chan chan; +@@ -100,12 +101,15 @@ struct pcc_chan_info { + struct pcc_chan_reg cmd_update; + struct pcc_chan_reg error; + int plat_irq; ++ u8 type; + }; + + #define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan) + static struct pcc_chan_info *chan_info; + static int pcc_chan_count; + ++static int pcc_send_data(struct mbox_chan *chan, void *data); ++ + /* + * PCC can be used with perf critical drivers such as CPPC + * So it makes sense to locally cache the virtual address and +@@ -221,6 +225,34 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags) + return acpi_register_gsi(NULL, interrupt, trigger, polarity); + } + ++static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) ++{ ++ u64 val; ++ int ret; ++ ++ ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); ++ if (ret) ++ return false; ++ ++ if (!pchan->cmd_complete.gas) ++ return true; ++ ++ /* ++ * Judge if the channel respond the interrupt based on the value of ++ * command complete. ++ */ ++ val &= pchan->cmd_complete.status_mask; ++ /* ++ * If this is PCC slave subspace channel, and the command complete ++ * bit 0 indicates that Platform is sending a notification and OSPM ++ * needs to respond this interrupt to process this command. ++ */ ++ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) ++ return !val; ++ ++ return !!val; ++} ++ + /** + * pcc_mbox_irq - PCC mailbox interrupt handler + * @irq: interrupt number +@@ -236,17 +268,9 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + int ret; + + pchan = chan->con_priv; +- +- ret = pcc_chan_reg_read(&pchan->cmd_complete, &val); +- if (ret) ++ if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; + +- if (val) { /* Ensure GAS exists and value is non-zero */ +- val &= pchan->cmd_complete.status_mask; +- if (!val) +- return IRQ_NONE; +- } +- + ret = pcc_chan_reg_read(&pchan->error, &val); + if (ret) + return IRQ_NONE; +@@ -262,6 +286,13 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + + mbox_chan_received_data(chan, NULL); + ++ /* ++ * The PCC slave subspace channel needs to set the command complete bit ++ * and ring doorbell after processing message. ++ */ ++ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) ++ pcc_send_data(chan, NULL); ++ + return IRQ_HANDLED; + } + +@@ -698,6 +729,7 @@ static int pcc_mbox_probe(struct platform_device *pdev) + + pcc_parse_subspace_shmem(pchan, pcct_entry); + ++ pchan->type = pcct_entry->type; + pcct_entry = (struct acpi_subtable_header *) + ((unsigned long) pcct_entry + pcct_entry->length); + } +-- +2.51.0 + diff --git a/queue-6.1/mailbox-pcc-check-before-sending-mctp-pcc-response-a.patch b/queue-6.1/mailbox-pcc-check-before-sending-mctp-pcc-response-a.patch new file mode 100644 index 0000000000..204006c3a8 --- /dev/null +++ b/queue-6.1/mailbox-pcc-check-before-sending-mctp-pcc-response-a.patch @@ -0,0 +1,167 @@ +From 31ee578b37bca7aeaa4876bfe83356e48bd638d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Nov 2024 14:02:14 -0500 +Subject: mailbox: pcc: Check before sending MCTP PCC response ACK + +From: Adam Young + +[ Upstream commit 7f9e19f207be0c534d517d65e01417ba968cdd34 ] + +Type 4 PCC channels have an option to send back a response +to the platform when they are done processing the request. +The flag to indicate whether or not to respond is inside +the message body, and thus is not available to the pcc +mailbox. + +If the flag is not set, still set command completion +bit after processing message. + +In order to read the flag, this patch maps the shared +buffer to virtual memory. To avoid duplication of mapping +the shared buffer is then made available to be used by +the driver that uses the mailbox. + +Signed-off-by: Adam Young +Cc: Sudeep Holla +Signed-off-by: Jassi Brar +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 61 +++++++++++++++++++++++++++++++++++++------ + include/acpi/pcc.h | 7 +++++ + 2 files changed, 60 insertions(+), 8 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 94885e411085a..82102a4c5d688 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -269,6 +269,35 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) + return !!val; + } + ++static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) ++{ ++ struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; ++ ++ if (pchan->type != ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) ++ return; ++ /* If the memory region has not been mapped, we cannot ++ * determine if we need to send the message, but we still ++ * need to set the cmd_update flag before returning. ++ */ ++ if (pchan->chan.shmem == NULL) { ++ pcc_chan_reg_read_modify_write(&pchan->cmd_update); ++ return; ++ } ++ memcpy_fromio(&pcc_hdr, pchan->chan.shmem, ++ sizeof(struct acpi_pcct_ext_pcc_shared_memory)); ++ /* ++ * The PCC slave subspace channel needs to set the command complete bit ++ * after processing message. If the PCC_ACK_FLAG is set, it should also ++ * ring the doorbell. ++ * ++ * The PCC master subspace channel clears chan_in_use to free channel. ++ */ ++ if (le32_to_cpup(&pcc_hdr.flags) & PCC_ACK_FLAG_MASK) ++ pcc_send_data(chan, NULL); ++ else ++ pcc_chan_reg_read_modify_write(&pchan->cmd_update); ++} ++ + /** + * pcc_mbox_irq - PCC mailbox interrupt handler + * @irq: interrupt number +@@ -306,14 +335,7 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + + mbox_chan_received_data(chan, NULL); + +- /* +- * The PCC slave subspace channel needs to set the command complete bit +- * and ring doorbell after processing message. +- * +- * The PCC master subspace channel clears chan_in_use to free channel. +- */ +- if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) +- pcc_send_data(chan, NULL); ++ check_and_ack(pchan, chan); + pchan->chan_in_use = false; + + return IRQ_HANDLED; +@@ -365,14 +387,37 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel); + void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan) + { + struct mbox_chan *chan = pchan->mchan; ++ struct pcc_chan_info *pchan_info; ++ struct pcc_mbox_chan *pcc_mbox_chan; + + if (!chan || !chan->cl) + return; ++ pchan_info = chan->con_priv; ++ pcc_mbox_chan = &pchan_info->chan; ++ if (pcc_mbox_chan->shmem) { ++ iounmap(pcc_mbox_chan->shmem); ++ pcc_mbox_chan->shmem = NULL; ++ } + + mbox_free_channel(chan); + } + EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); + ++int pcc_mbox_ioremap(struct mbox_chan *chan) ++{ ++ struct pcc_chan_info *pchan_info; ++ struct pcc_mbox_chan *pcc_mbox_chan; ++ ++ if (!chan || !chan->cl) ++ return -1; ++ pchan_info = chan->con_priv; ++ pcc_mbox_chan = &pchan_info->chan; ++ pcc_mbox_chan->shmem = ioremap(pcc_mbox_chan->shmem_base_addr, ++ pcc_mbox_chan->shmem_size); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(pcc_mbox_ioremap); ++ + /** + * pcc_send_data - Called from Mailbox Controller code. Used + * here only to ring the channel doorbell. The PCC client +diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h +index 9b373d172a776..699c1a37b8e78 100644 +--- a/include/acpi/pcc.h ++++ b/include/acpi/pcc.h +@@ -12,6 +12,7 @@ + struct pcc_mbox_chan { + struct mbox_chan *mchan; + u64 shmem_base_addr; ++ void __iomem *shmem; + u64 shmem_size; + u32 latency; + u32 max_access_rate; +@@ -31,11 +32,13 @@ struct pcc_mbox_chan { + #define PCC_CMD_COMPLETION_NOTIFY BIT(0) + + #define MAX_PCC_SUBSPACES 256 ++#define PCC_ACK_FLAG_MASK 0x1 + + #ifdef CONFIG_PCC + extern struct pcc_mbox_chan * + pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); + extern void pcc_mbox_free_channel(struct pcc_mbox_chan *chan); ++extern int pcc_mbox_ioremap(struct mbox_chan *chan); + #else + static inline struct pcc_mbox_chan * + pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) +@@ -43,6 +46,10 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) + return ERR_PTR(-ENODEV); + } + static inline void pcc_mbox_free_channel(struct pcc_mbox_chan *chan) { } ++static inline int pcc_mbox_ioremap(struct mbox_chan *chan) ++{ ++ return 0; ++}; + #endif + + #endif /* _PCC_H */ +-- +2.51.0 + diff --git a/queue-6.1/mailbox-pcc-don-t-zero-error-register.patch b/queue-6.1/mailbox-pcc-don-t-zero-error-register.patch new file mode 100644 index 0000000000..4cce407a1c --- /dev/null +++ b/queue-6.1/mailbox-pcc-don-t-zero-error-register.patch @@ -0,0 +1,57 @@ +From 15c1568ebe1ead5b1508c755245dc54c3af8a49f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:42:29 +0000 +Subject: mailbox: pcc: don't zero error register + +From: Jamie Iles + +[ Upstream commit ff0e4d4c97c94af34cc9cad37b5a5cdbe597a3b0 ] + +The error status mask for a type 3/4 subspace is used for reading the +error status, and the bitwise inverse is used for clearing the error +with the intent being to preserve any of the non-error bits. However, +we were previously applying the mask to extract the status and then +applying the inverse to the result which ended up clearing all bits. + +Instead, store the inverse mask in the preserve mask and then use that +on the original value read from the error status so that only the error +is cleared. + +Fixes: c45ded7e1135 ("mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)") +Signed-off-by: Jamie Iles +Signed-off-by: Punit Agrawal +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 94e99b87496d2..0729988467554 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -278,9 +278,8 @@ static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) + if (ret) + return ret; + +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; ++ if (val & pchan->error.status_mask) { ++ val &= pchan->error.preserve_mask; + pcc_chan_reg_write(&pchan->error, val); + return -EIO; + } +@@ -662,7 +661,8 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan, + + ret = pcc_chan_reg_init(&pchan->error, + &pcct_ext->error_status_register, +- 0, 0, pcct_ext->error_status_mask, ++ ~pcct_ext->error_status_mask, 0, ++ pcct_ext->error_status_mask, + "Error Status"); + } + return ret; +-- +2.51.0 + diff --git a/queue-6.1/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch b/queue-6.1/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch new file mode 100644 index 0000000000..94b5a6186a --- /dev/null +++ b/queue-6.1/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch @@ -0,0 +1,92 @@ +From 54e5515087563c57fcbb80116ced6ee72a119ed9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 15:28:52 +0000 +Subject: mailbox: pcc: Refactor error handling in irq handler into separate + function + +From: Sudeep Holla + +[ Upstream commit 3a675f50415b95f2ae10bfd932e2154ba1a08ee7 ] + +The existing error handling logic in pcc_mbox_irq() is intermixed with the +main flow of the function. The command complete check and the complete +complete update/acknowledgment are nicely factored into separate functions. + +Moves error detection and clearing logic into a separate function called: +pcc_mbox_error_check_and_clear() by extracting error-handling logic from +pcc_mbox_irq(). + +This ensures error checking and clearing are handled separately and it +improves maintainability by keeping the IRQ handler focused on processing +events. + +Acked-by: Huisong Li +Tested-by: Huisong Li +Tested-by: Adam Young +Signed-off-by: Sudeep Holla +Signed-off-by: Jassi Brar +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 82102a4c5d688..94e99b87496d2 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -269,6 +269,25 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) + return !!val; + } + ++static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) ++{ ++ u64 val; ++ int ret; ++ ++ ret = pcc_chan_reg_read(&pchan->error, &val); ++ if (ret) ++ return ret; ++ ++ val &= pchan->error.status_mask; ++ if (val) { ++ val &= ~pchan->error.status_mask; ++ pcc_chan_reg_write(&pchan->error, val); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ + static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) + { + struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; +@@ -309,8 +328,6 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + { + struct pcc_chan_info *pchan; + struct mbox_chan *chan = p; +- u64 val; +- int ret; + + pchan = chan->con_priv; + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE && +@@ -320,15 +337,8 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; + +- ret = pcc_chan_reg_read(&pchan->error, &val); +- if (ret) ++ if (pcc_mbox_error_check_and_clear(pchan)) + return IRQ_NONE; +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; +- pcc_chan_reg_write(&pchan->error, val); +- return IRQ_NONE; +- } + + if (pcc_chan_reg_read_modify_write(&pchan->plat_irq_ack)) + return IRQ_NONE; +-- +2.51.0 + diff --git a/queue-6.1/mailbox-pcc-support-shared-interrupt-for-multiple-su.patch b/queue-6.1/mailbox-pcc-support-shared-interrupt-for-multiple-su.patch new file mode 100644 index 0000000000..831a848115 --- /dev/null +++ b/queue-6.1/mailbox-pcc-support-shared-interrupt-for-multiple-su.patch @@ -0,0 +1,178 @@ +From bb36470504b0749cda9e02dfe00d2eed7385d06e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Aug 2023 14:38:27 +0800 +Subject: mailbox: pcc: Support shared interrupt for multiple subspaces + +From: Huisong Li + +[ Upstream commit 3db174e478cb0bb34888c20a531608b70aec9c1f ] + +If the platform acknowledge interrupt is level triggered, then it can +be shared by multiple subspaces provided each one has a unique platform +interrupt ack preserve and ack set masks. + +If it can be shared, then we can request the irq with IRQF_SHARED and +IRQF_ONESHOT flags. The first one indicating it can be shared and the +latter one to keep the interrupt disabled until the hardirq handler +finished. + +Further, since there is no way to detect if the interrupt is for a given +channel as the interrupt ack preserve and ack set masks are for clearing +the interrupt and not for reading the status(in case Irq Ack register +may be write-only on some platforms), we need a way to identify if the +given channel is in use and expecting the interrupt. + +PCC type0, type1 and type5 do not support shared level triggered interrupt. +The methods of determining whether a given channel for remaining types +should respond to an interrupt are as follows: + - type2: Whether the interrupt belongs to a given channel is only + determined by the status field in Generic Communications Channel + Shared Memory Region, which is done in rx_callback of PCC client. + - type3: This channel checks chan_in_use flag first and then checks the + command complete bit(value '1' indicates that the command has + been completed). + - type4: Platform ensure that the default value of the command complete + bit corresponding to the type4 channel is '1'. This command + complete bit is '0' when receive a platform notification. + +The new field, 'chan_in_use' is used by the type only support the +communication from OSPM to Platform (like type3) and should be completely +ignored by other types so as to avoid too many type unnecessary checks in +IRQ handler. + +Signed-off-by: Huisong Li +Reviewed-by: Hanjun Guo +Link: https://lore.kernel.org/r/20230801063827.25336-3-lihuisong@huawei.com +Signed-off-by: Sudeep Holla +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 43 ++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 40 insertions(+), 3 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 80310b48bfb6a..94885e411085a 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -92,6 +92,13 @@ struct pcc_chan_reg { + * @error: PCC register bundle for the error status register + * @plat_irq: platform interrupt + * @type: PCC subspace type ++ * @plat_irq_flags: platform interrupt flags ++ * @chan_in_use: this flag is used just to check if the interrupt needs ++ * handling when it is shared. Since only one transfer can occur ++ * at a time and mailbox takes care of locking, this flag can be ++ * accessed without a lock. Note: the type only support the ++ * communication from OSPM to Platform, like type3, use it, and ++ * other types completely ignore it. + */ + struct pcc_chan_info { + struct pcc_mbox_chan chan; +@@ -102,6 +109,8 @@ struct pcc_chan_info { + struct pcc_chan_reg error; + int plat_irq; + u8 type; ++ unsigned int plat_irq_flags; ++ bool chan_in_use; + }; + + #define to_pcc_chan_info(c) container_of(c, struct pcc_chan_info, chan) +@@ -225,6 +234,12 @@ static int pcc_map_interrupt(u32 interrupt, u32 flags) + return acpi_register_gsi(NULL, interrupt, trigger, polarity); + } + ++static bool pcc_chan_plat_irq_can_be_shared(struct pcc_chan_info *pchan) ++{ ++ return (pchan->plat_irq_flags & ACPI_PCCT_INTERRUPT_MODE) == ++ ACPI_LEVEL_SENSITIVE; ++} ++ + static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) + { + u64 val; +@@ -242,6 +257,7 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) + * command complete. + */ + val &= pchan->cmd_complete.status_mask; ++ + /* + * If this is PCC slave subspace channel, and the command complete + * bit 0 indicates that Platform is sending a notification and OSPM +@@ -268,6 +284,10 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + int ret; + + pchan = chan->con_priv; ++ if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE && ++ !pchan->chan_in_use) ++ return IRQ_NONE; ++ + if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; + +@@ -289,9 +309,12 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + /* + * The PCC slave subspace channel needs to set the command complete bit + * and ring doorbell after processing message. ++ * ++ * The PCC master subspace channel clears chan_in_use to free channel. + */ + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE) + pcc_send_data(chan, NULL); ++ pchan->chan_in_use = false; + + return IRQ_HANDLED; + } +@@ -371,7 +394,11 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) + if (ret) + return ret; + +- return pcc_chan_reg_read_modify_write(&pchan->db); ++ ret = pcc_chan_reg_read_modify_write(&pchan->db); ++ if (!ret && pchan->plat_irq > 0) ++ pchan->chan_in_use = true; ++ ++ return ret; + } + + /** +@@ -384,11 +411,14 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) + static int pcc_startup(struct mbox_chan *chan) + { + struct pcc_chan_info *pchan = chan->con_priv; ++ unsigned long irqflags; + int rc; + + if (pchan->plat_irq > 0) { +- rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0, +- MBOX_IRQ_NAME, chan); ++ irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ? ++ IRQF_SHARED | IRQF_ONESHOT : 0; ++ rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, ++ irqflags, MBOX_IRQ_NAME, chan); + if (unlikely(rc)) { + dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n", + pchan->plat_irq); +@@ -494,6 +524,7 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, + pcct_ss->platform_interrupt); + return -EINVAL; + } ++ pchan->plat_irq_flags = pcct_ss->flags; + + if (pcct_ss->header.type == ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2) { + struct acpi_pcct_hw_reduced_type2 *pcct2_ss = (void *)pcct_ss; +@@ -515,6 +546,12 @@ static int pcc_parse_subspace_irq(struct pcc_chan_info *pchan, + "PLAT IRQ ACK"); + } + ++ if (pcc_chan_plat_irq_can_be_shared(pchan) && ++ !pchan->plat_irq_ack.gas) { ++ pr_err("PCC subspace has level IRQ with no ACK register\n"); ++ return -EINVAL; ++ } ++ + return ret; + } + +-- +2.51.0 + diff --git a/queue-6.1/mailbox-pcc-use-mbox_bind_client.patch b/queue-6.1/mailbox-pcc-use-mbox_bind_client.patch new file mode 100644 index 0000000000..9c64cbbaf7 --- /dev/null +++ b/queue-6.1/mailbox-pcc-use-mbox_bind_client.patch @@ -0,0 +1,157 @@ +From c185b001ab28b0fd7d83b038d62719c60bfe0b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Apr 2023 09:16:54 -0700 +Subject: mailbox: pcc: Use mbox_bind_client + +From: Elliot Berman + +[ Upstream commit 76d4adacd52e78bea2e393081f2a5766261d1e3a ] + +Use generic mbox_bind_client() to bind omap mailbox channel to a client. + +mbox_bind_client is identical to the replaced lines, except that it: + - Does the operation under con_mutex which prevents possible races in + removal path + - Sets TXDONE_BY_ACK if pcc uses TXDONE_BY_POLL and the client knows + when tx is done. TXDONE_BY_ACK is already set if there's no interrupt, + so this is not applicable. + - Calls chan->mbox->ops->startup. This is usecase for requesting irq: + move the devm_request_irq into the startup callback and unregister it + in the shutdown path. + +Tested-by: Sudeep Holla +Signed-off-by: Elliot Berman +Signed-off-by: Jassi Brar +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 84 +++++++++++++++++++++++-------------------- + 1 file changed, 45 insertions(+), 39 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 105d46c9801ba..a44d4b3e5beb2 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -282,8 +282,7 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) + { + struct pcc_chan_info *pchan; + struct mbox_chan *chan; +- struct device *dev; +- unsigned long flags; ++ int rc; + + if (subspace_id < 0 || subspace_id >= pcc_chan_count) + return ERR_PTR(-ENOENT); +@@ -294,32 +293,10 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id) + pr_err("Channel not found for idx: %d\n", subspace_id); + return ERR_PTR(-EBUSY); + } +- dev = chan->mbox->dev; + +- spin_lock_irqsave(&chan->lock, flags); +- chan->msg_free = 0; +- chan->msg_count = 0; +- chan->active_req = NULL; +- chan->cl = cl; +- init_completion(&chan->tx_complete); +- +- if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) +- chan->txdone_method = TXDONE_BY_ACK; +- +- spin_unlock_irqrestore(&chan->lock, flags); +- +- if (pchan->plat_irq > 0) { +- int rc; +- +- rc = devm_request_irq(dev, pchan->plat_irq, pcc_mbox_irq, 0, +- MBOX_IRQ_NAME, chan); +- if (unlikely(rc)) { +- dev_err(dev, "failed to register PCC interrupt %d\n", +- pchan->plat_irq); +- pcc_mbox_free_channel(&pchan->chan); +- return ERR_PTR(rc); +- } +- } ++ rc = mbox_bind_client(chan, cl); ++ if (rc) ++ return ERR_PTR(rc); + + return &pchan->chan; + } +@@ -333,23 +310,12 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel); + */ + void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan) + { +- struct pcc_chan_info *pchan_info = to_pcc_chan_info(pchan); + struct mbox_chan *chan = pchan->mchan; +- unsigned long flags; + + if (!chan || !chan->cl) + return; + +- if (pchan_info->plat_irq > 0) +- devm_free_irq(chan->mbox->dev, pchan_info->plat_irq, chan); +- +- spin_lock_irqsave(&chan->lock, flags); +- chan->cl = NULL; +- chan->active_req = NULL; +- if (chan->txdone_method == TXDONE_BY_ACK) +- chan->txdone_method = TXDONE_BY_POLL; +- +- spin_unlock_irqrestore(&chan->lock, flags); ++ mbox_free_channel(chan); + } + EXPORT_SYMBOL_GPL(pcc_mbox_free_channel); + +@@ -377,8 +343,48 @@ static int pcc_send_data(struct mbox_chan *chan, void *data) + return pcc_chan_reg_read_modify_write(&pchan->db); + } + ++/** ++ * pcc_startup - Called from Mailbox Controller code. Used here ++ * to request the interrupt. ++ * @chan: Pointer to Mailbox channel to startup. ++ * ++ * Return: Err if something failed else 0 for success. ++ */ ++static int pcc_startup(struct mbox_chan *chan) ++{ ++ struct pcc_chan_info *pchan = chan->con_priv; ++ int rc; ++ ++ if (pchan->plat_irq > 0) { ++ rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0, ++ MBOX_IRQ_NAME, chan); ++ if (unlikely(rc)) { ++ dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n", ++ pchan->plat_irq); ++ return rc; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * pcc_shutdown - Called from Mailbox Controller code. Used here ++ * to free the interrupt. ++ * @chan: Pointer to Mailbox channel to shutdown. ++ */ ++static void pcc_shutdown(struct mbox_chan *chan) ++{ ++ struct pcc_chan_info *pchan = chan->con_priv; ++ ++ if (pchan->plat_irq > 0) ++ devm_free_irq(chan->mbox->dev, pchan->plat_irq, chan); ++} ++ + static const struct mbox_chan_ops pcc_chan_ops = { + .send_data = pcc_send_data, ++ .startup = pcc_startup, ++ .shutdown = pcc_shutdown, + }; + + /** +-- +2.51.0 + diff --git a/queue-6.1/net-aquantia-add-missing-descriptor-cache-invalidati.patch b/queue-6.1/net-aquantia-add-missing-descriptor-cache-invalidati.patch new file mode 100644 index 0000000000..eb3d35b14d --- /dev/null +++ b/queue-6.1/net-aquantia-add-missing-descriptor-cache-invalidati.patch @@ -0,0 +1,144 @@ +From 622ce66063a00d295e9e251828ee7723775f5643 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 12:15:33 +0800 +Subject: net: aquantia: Add missing descriptor cache invalidation on ATL2 + +From: Kai-Heng Feng + +[ Upstream commit 7526183cfdbe352c51c285762f0e15b7c428ea06 ] + +ATL2 hardware was missing descriptor cache invalidation in hw_stop(), +causing SMMU translation faults during device shutdown and module removal: +[ 70.355743] arm-smmu-v3 arm-smmu-v3.5.auto: event 0x10 received: +[ 70.361893] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0002060000000010 +[ 70.367948] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000020000000000 +[ 70.374002] arm-smmu-v3 arm-smmu-v3.5.auto: 0x00000000ff9bc000 +[ 70.380055] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000000000000000 +[ 70.386109] arm-smmu-v3 arm-smmu-v3.5.auto: event: F_TRANSLATION client: 0001:06:00.0 sid: 0x20600 ssid: 0x0 iova: 0xff9bc000 ipa: 0x0 +[ 70.398531] arm-smmu-v3 arm-smmu-v3.5.auto: unpriv data write s1 "Input address caused fault" stag: 0x0 + +Commit 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after +driver unbind") and commit ed4d81c4b3f2 ("net: aquantia: when cleaning +hw cache it should be toggled") fixed cache invalidation for ATL B0, but +ATL2 was left with only interrupt disabling. This allowed hardware to +write to cached descriptors after DMA memory was unmapped, triggering +SMMU faults. Once cache invalidation is applied to ATL2, the translation +fault can't be observed anymore. + +Add shared aq_hw_invalidate_descriptor_cache() helper and use it in both +ATL B0 and ATL2 hw_stop() implementations for consistent behavior. + +Fixes: e54dcf4bba3e ("net: atlantic: basic A2 init/deinit hw_ops") +Tested-by: Carol Soto +Signed-off-by: Kai-Heng Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251120041537.62184-1-kaihengf@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/aquantia/atlantic/aq_hw_utils.c | 22 +++++++++++++++++++ + .../ethernet/aquantia/atlantic/aq_hw_utils.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 +--------------- + .../aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 4 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 1921741f7311d..18b08277d2e1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -15,6 +15,7 @@ + + #include "aq_hw.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_llh.h" + + void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, + u32 shift, u32 val) +@@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) + lo_hi_writeq(value, hw->mmio + reg); + } + ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) ++{ ++ int err; ++ u32 val; ++ ++ /* Invalidate Descriptor Cache to prevent writing to the cached ++ * descriptors and to the data pointer of those descriptors ++ */ ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); ++ ++ err = aq_hw_err_from_flags(hw); ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ hw, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index ffa6e4067c211..d89c63d88e4a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 54e70f07b5734..7b4814b3ba442 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { +- int err; +- u32 val; +- + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +- /* Invalidate Descriptor Cache to prevent writing to the cached +- * descriptors and to the data pointer of those descriptors +- */ +- hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); +- +- err = aq_hw_err_from_flags(self); +- +- if (err) +- goto err_exit; +- +- readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, +- self, val, val == 1, 1000U, 10000U); +- +-err_exit: +- return err; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 5dfc751572edc..bc4e1b6035e08 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + { + hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); + +- return 0; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) +-- +2.51.0 + diff --git a/queue-6.1/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch b/queue-6.1/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch new file mode 100644 index 0000000000..b89b9a685e --- /dev/null +++ b/queue-6.1/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch @@ -0,0 +1,93 @@ +From 1dee0dcf941d6e0091a374eac158b31c207b86ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:22:49 +0800 +Subject: net: atlantic: fix fragment overflow handling in RX path + +From: Jiefeng Zhang + +[ Upstream commit 5ffcb7b890f61541201461580bb6622ace405aec ] + +The atlantic driver can receive packets with more than MAX_SKB_FRAGS (17) +fragments when handling large multi-descriptor packets. This causes an +out-of-bounds write in skb_add_rx_frag_netmem() leading to kernel panic. + +The issue occurs because the driver doesn't check the total number of +fragments before calling skb_add_rx_frag(). When a packet requires more +than MAX_SKB_FRAGS fragments, the fragment index exceeds the array bounds. + +Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, +then all fragments are accounted for. And reusing the existing check to +prevent the overflow earlier in the code path. + +This crash occurred in production with an Aquantia AQC113 10G NIC. + +Stack trace from production environment: +``` +RIP: 0010:skb_add_rx_frag_netmem+0x29/0xd0 +Code: 90 f3 0f 1e fa 0f 1f 44 00 00 48 89 f8 41 89 +ca 48 89 d7 48 63 ce 8b 90 c0 00 00 00 48 c1 e1 04 48 01 ca 48 03 90 +c8 00 00 00 <48> 89 7a 30 44 89 52 3c 44 89 42 38 40 f6 c7 01 75 74 48 +89 fa 83 +RSP: 0018:ffffa9bec02a8d50 EFLAGS: 00010287 +RAX: ffff925b22e80a00 RBX: ffff925ad38d2700 RCX: +fffffffe0a0c8000 +RDX: ffff9258ea95bac0 RSI: ffff925ae0a0c800 RDI: +0000000000037a40 +RBP: 0000000000000024 R08: 0000000000000000 R09: +0000000000000021 +R10: 0000000000000848 R11: 0000000000000000 R12: +ffffa9bec02a8e24 +R13: ffff925ad8615570 R14: 0000000000000000 R15: +ffff925b22e80a00 +FS: 0000000000000000(0000) +GS:ffff925e47880000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffff9258ea95baf0 CR3: 0000000166022004 CR4: +0000000000f72ef0 +PKRU: 55555554 +Call Trace: + +aq_ring_rx_clean+0x175/0xe60 [atlantic] +? aq_ring_rx_clean+0x14d/0xe60 [atlantic] +? aq_ring_tx_clean+0xdf/0x190 [atlantic] +? kmem_cache_free+0x348/0x450 +? aq_vec_poll+0x81/0x1d0 [atlantic] +? __napi_poll+0x28/0x1c0 +? net_rx_action+0x337/0x420 +``` + +Fixes: 6aecbba12b5c ("net: atlantic: add check for MAX_SKB_FRAGS") +Changes in v4: +- Add Fixes: tag to satisfy patch validation requirements. + +Changes in v3: +- Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, + then all fragments are accounted for. + +Signed-off-by: Jiefeng Zhang +Link: https://patch.msgid.link/20251126032249.69358-1-jiefeng.z.zhang@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index 0eaaba3a18ee0..c8466ebd4a031 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -547,6 +547,11 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi, + + if (!buff->is_eop) { + unsigned int frag_cnt = 0U; ++ ++ /* There will be an extra fragment */ ++ if (buff->len > AQ_CFG_RX_HDR_SIZE) ++ frag_cnt++; ++ + buff_ = buff; + do { + bool is_rsc_completed = true; +-- +2.51.0 + diff --git a/queue-6.1/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch b/queue-6.1/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch new file mode 100644 index 0000000000..5f15b69bac --- /dev/null +++ b/queue-6.1/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch @@ -0,0 +1,73 @@ +From a46862e235b951513cca251e5e79ede0b9aa43ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 13:13:24 +0200 +Subject: net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing + traffic + +From: Vladimir Oltean + +[ Upstream commit da62abaaa268357b1aa66b372ace562189a05df1 ] + +When using the SGMII PCS as a fixed-link chip-to-chip connection, it is +easy to miss the fact that traffic passes only at 1G, since that's what +any normal such connection would use. + +When using the SGMII PCS connected towards an on-board PHY or an SFP +module, it is immediately noticeable that when the link resolves to a +speed other than 1G, traffic from the MAC fails to pass: TX counters +increase, but nothing gets decoded by the other end, and no local RX +counters increase either. + +Artificially lowering a fixed-link rate to speed = <100> makes us able +to see the same issue as in the case of having an SGMII PHY. + +Some debugging shows that the XPCS configuration is A-OK, but that the +MAC Configuration Table entry for the port has the SPEED bits still set +to 1000Mbps, due to a special condition in the driver. Deleting that +condition, and letting the resolved link speed be programmed directly +into the MAC speed field, results in a functional link at all 3 speeds. + +This piece of evidence, based on testing on both generations with SGMII +support (SJA1105S and SJA1110A) directly contradicts the statement from +the blamed commit that "the MAC is fixed at 1 Gbps and we need to +configure the PCS only (if even that)". Worse, that statement is not +backed by any documentation, and no one from NXP knows what it might +refer to. + +I am unable to recall sufficient context regarding my testing from March +2020 to understand what led me to draw such a braindead and factually +incorrect conclusion. Yet, there is nothing of value regarding forcing +the MAC speed, either for SGMII or 2500Base-X (introduced at a later +stage), so remove all such logic. + +Fixes: ffe10e679cec ("net: dsa: sja1105: Add support for the SGMII port") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251122111324.136761-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index 8350696bdda5b..cb6f924b92ac0 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1308,14 +1308,7 @@ static int sja1105_set_port_speed(struct sja1105_private *priv, int port, + * table, since this will be used for the clocking setup, and we no + * longer need to store it in the static config (already told hardware + * we want auto during upload phase). +- * Actually for the SGMII port, the MAC is fixed at 1 Gbps and +- * we need to configure the PCS only (if even that). + */ +- if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; +- else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- + mac[port].speed = speed; + + return 0; +-- +2.51.0 + diff --git a/queue-6.1/net-dsa-sja1105-simplify-static-configuration-reload.patch b/queue-6.1/net-dsa-sja1105-simplify-static-configuration-reload.patch new file mode 100644 index 0000000000..3d8837fe86 --- /dev/null +++ b/queue-6.1/net-dsa-sja1105-simplify-static-configuration-reload.patch @@ -0,0 +1,159 @@ +From 5be00a02f66dd2f15b8bad770709d11fd6ab2972 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 17:04:36 +0100 +Subject: net: dsa: sja1105: simplify static configuration reload + +From: Russell King (Oracle) + +[ Upstream commit a18891b55703a45b700618ef40edd5e9aaecc345 ] + +The static configuration reload saves the port speed in the static +configuration tables by first converting it from the internal +respresentation to the SPEED_xxx ethtool representation, and then +converts it back to restore the setting. This is because +sja1105_adjust_port_config() takes the speed as SPEED_xxx. + +However, this is unnecessarily complex. If we split +sja1105_adjust_port_config() up, we can simply save and restore the +mac[port].speed member in the static configuration tables. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1svfMa-005ZIX-If@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: da62abaaa268 ("net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing traffic") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 65 ++++++++++++++------------ + 1 file changed, 34 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index d51d982c4bc01..8350696bdda5b 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1262,29 +1262,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv) + return rc; + } + +-/* Convert link speed from SJA1105 to ethtool encoding */ +-static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, +- u64 speed) +-{ +- if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) +- return SPEED_10; +- if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) +- return SPEED_100; +- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) +- return SPEED_1000; +- if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS]) +- return SPEED_2500; +- return SPEED_UNKNOWN; +-} +- +-/* Set link speed in the MAC configuration for a specific port. */ +-static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, +- int speed_mbps) ++static int sja1105_set_port_speed(struct sja1105_private *priv, int port, ++ int speed_mbps) + { + struct sja1105_mac_config_entry *mac; +- struct device *dev = priv->ds->dev; + u64 speed; +- int rc; + + /* On P/Q/R/S, one can read from the device via the MAC reconfiguration + * tables. On E/T, MAC reconfig tables are not readable, only writable. +@@ -1318,7 +1300,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; + break; + default: +- dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); ++ dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps); + return -EINVAL; + } + +@@ -1330,11 +1312,31 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + * we need to configure the PCS only (if even that). + */ + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; ++ speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; + else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- else +- mac[port].speed = speed; ++ speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; ++ ++ mac[port].speed = speed; ++ ++ return 0; ++} ++ ++/* Write the MAC Configuration Table entry and, if necessary, the CGU settings, ++ * after a link speedchange for this port. ++ */ ++static int sja1105_set_port_config(struct sja1105_private *priv, int port) ++{ ++ struct sja1105_mac_config_entry *mac; ++ struct device *dev = priv->ds->dev; ++ int rc; ++ ++ /* On P/Q/R/S, one can read from the device via the MAC reconfiguration ++ * tables. On E/T, MAC reconfig tables are not readable, only writable. ++ * We have to *know* what the MAC looks like. For the sake of keeping ++ * the code common, we'll use the static configuration tables as a ++ * reasonable approximation for both E/T and P/Q/R/S. ++ */ ++ mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + + /* Write to the dynamic reconfiguration tables */ + rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, +@@ -1384,7 +1386,8 @@ static void sja1105_mac_link_up(struct dsa_switch *ds, int port, + { + struct sja1105_private *priv = ds->priv; + +- sja1105_adjust_port_config(priv, port, speed); ++ if (!sja1105_set_port_speed(priv, port, speed)) ++ sja1105_set_port_config(priv, port); + + sja1105_inhibit_tx(priv, BIT(port), false); + } +@@ -2291,8 +2294,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + { + struct ptp_system_timestamp ptp_sts_before; + struct ptp_system_timestamp ptp_sts_after; +- int speed_mbps[SJA1105_MAX_NUM_PORTS]; + u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0}; ++ u64 mac_speed[SJA1105_MAX_NUM_PORTS]; + struct sja1105_mac_config_entry *mac; + struct dsa_switch *ds = priv->ds; + s64 t1, t2, t3, t4; +@@ -2305,14 +2308,13 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + +- /* Back up the dynamic link speed changed by sja1105_adjust_port_config ++ /* Back up the dynamic link speed changed by sja1105_set_port_speed() + * in order to temporarily restore it to SJA1105_SPEED_AUTO - which the + * switch wants to see in the static config in order to allow us to + * change it through the dynamic interface later. + */ + for (i = 0; i < ds->num_ports; i++) { +- speed_mbps[i] = sja1105_port_speed_to_ethtool(priv, +- mac[i].speed); ++ mac_speed[i] = mac[i].speed; + mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO]; + + if (priv->xpcs[i]) +@@ -2375,7 +2377,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + struct dw_xpcs *xpcs = priv->xpcs[i]; + unsigned int mode; + +- rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); ++ mac[i].speed = mac_speed[i]; ++ rc = sja1105_set_port_config(priv, i); + if (rc < 0) + goto out; + +-- +2.51.0 + diff --git a/queue-6.1/net-lan966x-fix-the-initialization-of-taprio.patch b/queue-6.1/net-lan966x-fix-the-initialization-of-taprio.patch new file mode 100644 index 0000000000..88586ca50b --- /dev/null +++ b/queue-6.1/net-lan966x-fix-the-initialization-of-taprio.patch @@ -0,0 +1,54 @@ +From 8f13327be824045192b392cd804c9f4aff7c22b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 07:14:11 +0100 +Subject: net: lan966x: Fix the initialization of taprio + +From: Horatiu Vultur + +[ Upstream commit 9780f535f8e0f20b4632b5a173ead71aa8f095d2 ] + +To initialize the taprio block in lan966x, it is required to configure +the register REVISIT_DLY. The purpose of this register is to set the +delay before revisit the next gate and the value of this register depends +on the system clock. The problem is that the we calculated wrong the value +of the system clock period in picoseconds. The actual system clock is +~165.617754MHZ and this correspond to a period of 6038 pico seconds and +not 15125 as currently set. + +Fixes: e462b2717380b4 ("net: lan966x: Add offload support for taprio") +Signed-off-by: Horatiu Vultur +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121061411.810571-1-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +index 0a0e233f36ab0..667f2651ee309 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +@@ -1,9 +1,12 @@ + // SPDX-License-Identifier: GPL-2.0+ + + #include ++#include + + #include "lan966x_main.h" + ++#define LAN9X66_CLOCK_RATE 165617754 ++ + #define LAN966X_MAX_PTP_ID 512 + + /* Represents 1ppm adjustment in 2^59 format with 6.037735849ns as reference +@@ -896,5 +899,5 @@ void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, + u32 lan966x_ptp_get_period_ps(void) + { + /* This represents the system clock period in picoseconds */ +- return 15125; ++ return PICO / LAN9X66_CLOCK_RATE; + } +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-fix-validation-logic-in-rate-limiting.patch b/queue-6.1/net-mlx5e-fix-validation-logic-in-rate-limiting.patch new file mode 100644 index 0000000000..2e7e38a203 --- /dev/null +++ b/queue-6.1/net-mlx5e-fix-validation-logic-in-rate-limiting.patch @@ -0,0 +1,63 @@ +From a1e787f3d117d25fa45ecce95fb1324f8caa048e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:00:43 -0800 +Subject: net/mlx5e: Fix validation logic in rate limiting + +From: Danielle Costantino + +[ Upstream commit d2099d9f16dbfa1c5266d4230ff7860047bb0b68 ] + +The rate limiting validation condition currently checks the output +variable max_bw_value[i] instead of the input value +maxrate->tc_maxrate[i]. This causes the validation to compare an +uninitialized or stale value rather than the actual requested rate. + +The condition should check the input rate to properly validate against +the upper limit: + + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + +This aligns with the pattern used in the first branch, which correctly +checks maxrate->tc_maxrate[i] against upper_limit_mbps. + +The current implementation can lead to unreliable validation behavior: + +- For rates between 25.5 Gbps and 255 Gbps, if max_bw_value[i] is 0 + from initialization, the GBPS path may be taken regardless of whether + the actual rate is within bounds + +- When processing multiple TCs (i > 0), max_bw_value[i] contains the + value computed for the previous TC, affecting the validation logic + +- The overflow check for rates exceeding 255 Gbps may not trigger + consistently depending on previous array values + +This patch ensures the validation correctly examines the requested rate +value for proper bounds checking. + +Fixes: 43b27d1bd88a ("net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps") +Signed-off-by: Danielle Costantino +Reviewed-by: Gal Pressman +Link: https://patch.msgid.link/20251124180043.2314428-1-dcostantino@meta.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 29e633e6dd3f0..e29a8ed7e7ac1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -619,7 +619,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else if (max_bw_value[i] <= upper_limit_gbps) { ++ } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; +-- +2.51.0 + diff --git a/queue-6.1/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch b/queue-6.1/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch new file mode 100644 index 0000000000..13007a64f0 --- /dev/null +++ b/queue-6.1/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch @@ -0,0 +1,47 @@ +From 9dfb7317bc032f61baa757228f2d9adc937f8839 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 12:38:34 +0000 +Subject: net: sxgbe: fix potential NULL dereference in sxgbe_rx() + +From: Alexey Kodanev + +[ Upstream commit f5bce28f6b9125502abec4a67d68eabcd24b3b17 ] + +Currently, when skb is null, the driver prints an error and then +dereferences skb on the next line. + +To fix this, let's add a 'break' after the error message to switch +to sxgbe_rx_refill(), which is similar to the approach taken by the +other drivers in this particular case, e.g. calxeda with xgmac_rx(). + +Found during a code review. + +Fixes: 1edb9ca69e8a ("net: sxgbe: add basic framework for Samsung 10Gb ethernet driver") +Signed-off-by: Alexey Kodanev +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121123834.97748-1-aleksei.kodanev@bell-sw.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index 9664f029fa161..f6f99712d562e 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -1521,8 +1521,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) + + skb = priv->rxq[qnum]->rx_skbuff[entry]; + +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + netdev_err(priv->dev, "rx descriptor is not consistent\n"); ++ break; ++ } + + prefetch(skb->data - NET_IP_ALIGN); + priv->rxq[qnum]->rx_skbuff[entry] = NULL; +-- +2.51.0 + diff --git a/queue-6.1/platform-x86-intel-punit_ipc-fix-memory-corruption.patch b/queue-6.1/platform-x86-intel-punit_ipc-fix-memory-corruption.patch new file mode 100644 index 0000000000..307bccdc67 --- /dev/null +++ b/queue-6.1/platform-x86-intel-punit_ipc-fix-memory-corruption.patch @@ -0,0 +1,46 @@ +From 53121c5124e56870b3ab7c0ff34a614bc2f14372 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 20:51:28 +0300 +Subject: platform/x86: intel: punit_ipc: fix memory corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit 9b9c0adbc3f8a524d291baccc9d0c04097fb4869 ] + +This passes the address of the pointer "&punit_ipcdev" when the intent +was to pass the pointer itself "punit_ipcdev" (without the ampersand). +This means that the: + + complete(&ipcdev->cmd_complete); + +in intel_punit_ioc() will write to a wrong memory address corrupting it. + +Fixes: fdca4f16f57d ("platform:x86: add Intel P-Unit mailbox IPC driver") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aSCmoBipSQ_tlD-D@stanley.mountain +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/punit_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/punit_ipc.c b/drivers/platform/x86/intel/punit_ipc.c +index 66bb39fd0ef90..8602f4175f123 100644 +--- a/drivers/platform/x86/intel/punit_ipc.c ++++ b/drivers/platform/x86/intel/punit_ipc.c +@@ -283,7 +283,7 @@ static int intel_punit_ipc_probe(struct platform_device *pdev) + } else { + ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc, + IRQF_NO_SUSPEND, "intel_punit_ipc", +- &punit_ipcdev); ++ punit_ipcdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", irq); + return ret; +-- +2.51.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 73f37f2d27..23363f20d4 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -492,3 +492,26 @@ pmdomain-arm-scmi-fix-genpd-leak-on-provider-registration-failure.patch pmdomain-imx-fix-reference-count-leak-in-imx_gpc_remove.patch filemap-cap-pte-range-to-be-created-to-allowed-zero-.patch mm-memory-do-not-populate-page-table-entries-beyond-.patch +can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch +can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch +bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch +platform-x86-intel-punit_ipc-fix-memory-corruption.patch +net-aquantia-add-missing-descriptor-cache-invalidati.patch +net-lan966x-fix-the-initialization-of-taprio.patch +net-mlx5e-fix-validation-logic-in-rate-limiting.patch +net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch +drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch +net-dsa-sja1105-simplify-static-configuration-reload.patch +net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch +net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch +mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch +mailbox-allow-direct-registration-to-a-channel.patch +mailbox-pcc-use-mbox_bind_client.patch +mailbox-pcc-add-support-for-platform-notification-ha.patch +mailbox-pcc-support-shared-interrupt-for-multiple-su.patch +acpi-pcc-add-pcc-shared-memory-region-command-and-st.patch +mailbox-pcc-check-before-sending-mctp-pcc-response-a.patch +mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch +mailbox-pcc-don-t-zero-error-register.patch +spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch diff --git a/queue-6.1/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch b/queue-6.1/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch new file mode 100644 index 0000000000..bbe920a2ad --- /dev/null +++ b/queue-6.1/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch @@ -0,0 +1,68 @@ +From 1e119775f5a82b39349c92d7d8e5bc6cbc3439fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 01:08:35 +1100 +Subject: spi: bcm63xx: fix premature CS deassertion on RX-only transactions + +From: Hang Zhou <929513338@qq.com> + +[ Upstream commit fd9862f726aedbc2f29a29916cabed7bcf5cadb6 ] + +On BCM6358 (and also observed on BCM6368) the controller appears to +only generate as many SPI clocks as bytes that have been written into +the TX FIFO. For RX-only transfers the driver programs the transfer +length in SPI_MSG_CTL but does not write anything into the FIFO, so +chip select is deasserted early and the RX transfer segment is never +fully clocked in. + +A concrete failing case is a three-transfer MAC address read from +SPI-NOR: + - TX 0x03 (read command) + - TX 3-byte address + - RX 6 bytes (MAC) + +In contrast, a two-transfer JEDEC-ID read (0x9f + 6-byte RX) works +because the driver uses prepend_len and writes dummy bytes into the +TX FIFO for the RX part. + +Fix this by writing 0xff dummy bytes into the TX FIFO for RX-only +segments so that the number of bytes written to the FIFO matches the +total message length seen by the controller. + +Fixes: b17de076062a ("spi/bcm63xx: work around inability to keep CS up") + +Signed-off-by: Hang Zhou <929513338@qq.com> +Link: https://patch.msgid.link/tencent_7AC88FCB3076489A4A7E6C2163DF1ACF8D06@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm63xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c +index 2f2a130464651..e57e1f75cd9f9 100644 +--- a/drivers/spi/spi-bcm63xx.c ++++ b/drivers/spi/spi-bcm63xx.c +@@ -257,6 +257,20 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + + if (t->rx_buf) { + do_rx = true; ++ ++ /* ++ * In certain hardware implementations, there appears to be a ++ * hidden accumulator that tracks the number of bytes written into ++ * the hardware FIFO, and this accumulator overrides the length in ++ * the SPI_MSG_CTL register. ++ * ++ * Therefore, for read-only transfers, we need to write some dummy ++ * value into the FIFO to keep the accumulator tracking the correct ++ * length. ++ */ ++ if (!t->tx_buf) ++ memset_io(bs->tx_io + len, 0xFF, t->len); ++ + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch b/queue-6.12/bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch new file mode 100644 index 0000000000..6ab50ad530 --- /dev/null +++ b/queue-6.12/bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch @@ -0,0 +1,132 @@ +From 61b99f35b56f17619f1a7e86df35c48a90a862ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Nov 2025 15:53:34 +0800 +Subject: Bluetooth: btusb: mediatek: Fix kernel crash when releasing mtk iso + interface + +From: Chris Lu + +[ Upstream commit 4015b979767125cf8a2233a145a3b3af78bfd8fb ] + +When performing reset tests and encountering abnormal card drop issues +that lead to a kernel crash, it is necessary to perform a null check +before releasing resources to avoid attempting to release a null pointer. + +<4>[ 29.158070] Hardware name: Google Quigon sku196612/196613 board (DT) +<4>[ 29.158076] Workqueue: hci0 hci_cmd_sync_work [bluetooth] +<4>[ 29.158154] pstate: 20400009 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +<4>[ 29.158162] pc : klist_remove+0x90/0x158 +<4>[ 29.158174] lr : klist_remove+0x88/0x158 +<4>[ 29.158180] sp : ffffffc0846b3c00 +<4>[ 29.158185] pmr_save: 000000e0 +<4>[ 29.158188] x29: ffffffc0846b3c30 x28: ffffff80cd31f880 x27: ffffff80c1bdc058 +<4>[ 29.158199] x26: dead000000000100 x25: ffffffdbdc624ea3 x24: ffffff80c1bdc4c0 +<4>[ 29.158209] x23: ffffffdbdc62a3e6 x22: ffffff80c6c07000 x21: ffffffdbdc829290 +<4>[ 29.158219] x20: 0000000000000000 x19: ffffff80cd3e0648 x18: 000000031ec97781 +<4>[ 29.158229] x17: ffffff80c1bdc4a8 x16: ffffffdc10576548 x15: ffffff80c1180428 +<4>[ 29.158238] x14: 0000000000000000 x13: 000000000000e380 x12: 0000000000000018 +<4>[ 29.158248] x11: ffffff80c2a7fd10 x10: 0000000000000000 x9 : 0000000100000000 +<4>[ 29.158257] x8 : 0000000000000000 x7 : 7f7f7f7f7f7f7f7f x6 : 2d7223ff6364626d +<4>[ 29.158266] x5 : 0000008000000000 x4 : 0000000000000020 x3 : 2e7325006465636e +<4>[ 29.158275] x2 : ffffffdc11afeff8 x1 : 0000000000000000 x0 : ffffffdc11be4d0c +<4>[ 29.158285] Call trace: +<4>[ 29.158290] klist_remove+0x90/0x158 +<4>[ 29.158298] device_release_driver_internal+0x20c/0x268 +<4>[ 29.158308] device_release_driver+0x1c/0x30 +<4>[ 29.158316] usb_driver_release_interface+0x70/0x88 +<4>[ 29.158325] btusb_mtk_release_iso_intf+0x68/0xd8 [btusb (HASH:e8b6 5)] +<4>[ 29.158347] btusb_mtk_reset+0x5c/0x480 [btusb (HASH:e8b6 5)] +<4>[ 29.158361] hci_cmd_sync_work+0x10c/0x188 [bluetooth (HASH:a4fa 6)] +<4>[ 29.158430] process_scheduled_works+0x258/0x4e8 +<4>[ 29.158441] worker_thread+0x300/0x428 +<4>[ 29.158448] kthread+0x108/0x1d0 +<4>[ 29.158455] ret_from_fork+0x10/0x20 +<0>[ 29.158467] Code: 91343000 940139d1 f9400268 927ff914 (f9401297) +<4>[ 29.158474] ---[ end trace 0000000000000000 ]--- +<0>[ 29.167129] Kernel panic - not syncing: Oops: Fatal exception +<2>[ 29.167144] SMP: stopping secondary CPUs +<4>[ 29.167158] ------------[ cut here ]------------ + +Fixes: ceac1cb0259d ("Bluetooth: btusb: mediatek: add ISO data transmission functions") +Signed-off-by: Chris Lu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 34 +++++++++++++++++++++++++------- + include/net/bluetooth/hci_core.h | 1 - + 2 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index aedb478614000..b6c37e87c6a08 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2704,9 +2704,16 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + + static void btusb_mtk_claim_iso_intf(struct btusb_data *data) + { +- struct btmtk_data *btmtk_data = hci_get_priv(data->hdev); ++ struct btmtk_data *btmtk_data; + int err; + ++ if (!data->hdev) ++ return; ++ ++ btmtk_data = hci_get_priv(data->hdev); ++ if (!btmtk_data) ++ return; ++ + /* + * The function usb_driver_claim_interface() is documented to need + * locks held if it's not called from a probe routine. The code here +@@ -2728,17 +2735,30 @@ static void btusb_mtk_claim_iso_intf(struct btusb_data *data) + + static void btusb_mtk_release_iso_intf(struct hci_dev *hdev) + { +- struct btmtk_data *btmtk_data = hci_get_priv(hdev); ++ struct btmtk_data *btmtk_data; ++ ++ if (!hdev) ++ return; ++ ++ btmtk_data = hci_get_priv(hdev); ++ if (!btmtk_data) ++ return; + + if (test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) { + usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor); + clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags); + +- dev_kfree_skb_irq(btmtk_data->isopkt_skb); +- btmtk_data->isopkt_skb = NULL; +- usb_set_intfdata(btmtk_data->isopkt_intf, NULL); +- usb_driver_release_interface(&btusb_driver, +- btmtk_data->isopkt_intf); ++ if (btmtk_data->isopkt_skb) { ++ dev_kfree_skb_irq(btmtk_data->isopkt_skb); ++ btmtk_data->isopkt_skb = NULL; ++ } ++ ++ if (btmtk_data->isopkt_intf) { ++ usb_set_intfdata(btmtk_data->isopkt_intf, NULL); ++ usb_driver_release_interface(&btusb_driver, ++ btmtk_data->isopkt_intf); ++ btmtk_data->isopkt_intf = NULL; ++ } + } + + clear_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags); +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 35b5f58b562cb..ba5d176069a69 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -732,7 +732,6 @@ struct hci_conn { + + __u8 remote_cap; + __u8 remote_auth; +- __u8 remote_id; + + unsigned int sent; + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch b/queue-6.12/bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch new file mode 100644 index 0000000000..c591c80f9c --- /dev/null +++ b/queue-6.12/bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch @@ -0,0 +1,85 @@ +From a2b27d70304d4d67afa414884a4deb711fccdc8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Nov 2025 09:49:27 -0500 +Subject: Bluetooth: hci_core: Fix triggering cmd_timer for HCI_OP_NOP + +From: Luiz Augusto von Dentz + +[ Upstream commit 275ddfeb3fdc274050c2173ffd985b1e80a9aa37 ] + +HCI_OP_NOP means no command was actually sent so there is no point in +triggering cmd_timer which may cause a hdev->reset in the process since +it is assumed that the controller is stuck processing a command. + +Fixes: e2d471b7806b ("Bluetooth: ISO: Fix not using SID from adv report") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_core.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index b74ada8092378..ba01d0fa07193 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -4076,7 +4076,7 @@ static void hci_rx_work(struct work_struct *work) + } + } + +-static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) ++static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) + { + int err; + +@@ -4088,16 +4088,19 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) + if (!hdev->sent_cmd) { + skb_queue_head(&hdev->cmd_q, skb); + queue_work(hdev->workqueue, &hdev->cmd_work); +- return; ++ return -EINVAL; + } + + if (hci_skb_opcode(skb) != HCI_OP_NOP) { + err = hci_send_frame(hdev, skb); + if (err < 0) { + hci_cmd_sync_cancel_sync(hdev, -err); +- return; ++ return err; + } + atomic_dec(&hdev->cmd_cnt); ++ } else { ++ err = -ENODATA; ++ kfree_skb(skb); + } + + if (hdev->req_status == HCI_REQ_PEND && +@@ -4105,12 +4108,15 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) + kfree_skb(hdev->req_skb); + hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL); + } ++ ++ return err; + } + + static void hci_cmd_work(struct work_struct *work) + { + struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work); + struct sk_buff *skb; ++ int err; + + BT_DBG("%s cmd_cnt %d cmd queued %d", hdev->name, + atomic_read(&hdev->cmd_cnt), skb_queue_len(&hdev->cmd_q)); +@@ -4121,7 +4127,9 @@ static void hci_cmd_work(struct work_struct *work) + if (!skb) + return; + +- hci_send_cmd_sync(hdev, skb); ++ err = hci_send_cmd_sync(hdev, skb); ++ if (err) ++ return; + + rcu_read_lock(); + if (test_bit(HCI_RESET, &hdev->flags) || +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch b/queue-6.12/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch new file mode 100644 index 0000000000..78bf24f4a2 --- /dev/null +++ b/queue-6.12/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch @@ -0,0 +1,72 @@ +From cc46f235e97e47f8d296605d8e5f3b906c410ac0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Nov 2025 17:04:43 +0800 +Subject: Bluetooth: hci_sock: Prevent race in socket write iter and sock bind + +From: Edward Adam Davis + +[ Upstream commit 89bb613511cc21ed5ba6bddc1c9b9ae9c0dad392 ] + +There is a potential race condition between sock bind and socket write +iter. bind may free the same cmd via mgmt_pending before write iter sends +the cmd, just as syzbot reported in UAF[1]. + +Here we use hci_dev_lock to synchronize the two, thereby avoiding the +UAF mentioned in [1]. + +[1] +syzbot reported: +BUG: KASAN: slab-use-after-free in mgmt_pending_remove+0x3b/0x210 net/bluetooth/mgmt_util.c:316 +Read of size 8 at addr ffff888077164818 by task syz.0.17/5989 +Call Trace: + mgmt_pending_remove+0x3b/0x210 net/bluetooth/mgmt_util.c:316 + set_link_security+0x5c2/0x710 net/bluetooth/mgmt.c:1918 + hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 + hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + sock_write_iter+0x279/0x360 net/socket.c:1195 + +Allocated by task 5989: + mgmt_pending_add+0x35/0x140 net/bluetooth/mgmt_util.c:296 + set_link_security+0x557/0x710 net/bluetooth/mgmt.c:1910 + hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 + hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + sock_write_iter+0x279/0x360 net/socket.c:1195 + +Freed by task 5991: + mgmt_pending_free net/bluetooth/mgmt_util.c:311 [inline] + mgmt_pending_foreach+0x30d/0x380 net/bluetooth/mgmt_util.c:257 + mgmt_index_removed+0x112/0x2f0 net/bluetooth/mgmt.c:9477 + hci_sock_bind+0xbe9/0x1000 net/bluetooth/hci_sock.c:1314 + +Fixes: 6fe26f694c82 ("Bluetooth: MGMT: Protect mgmt_pending list with its own lock") +Reported-by: syzbot+9aa47cd4633a3cf92a80@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9aa47cd4633a3cf92a80 +Tested-by: syzbot+9aa47cd4633a3cf92a80@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sock.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index 4ad5296d79345..fbfc962374a88 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -1304,7 +1304,9 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, + goto done; + } + ++ hci_dev_lock(hdev); + mgmt_index_removed(hdev); ++ hci_dev_unlock(hdev); + + err = hci_dev_open(hdev->id); + if (err) { +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch b/queue-6.12/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch new file mode 100644 index 0000000000..34730a8875 --- /dev/null +++ b/queue-6.12/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch @@ -0,0 +1,87 @@ +From fc62ce142acc8e734b80255ea0f1a13d7b05b4a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 13:45:13 -0500 +Subject: Bluetooth: SMP: Fix not generating mackey and ltk when repairing + +From: Luiz Augusto von Dentz + +[ Upstream commit 545d7827b2cd5de5eb85580cebeda6b35b3ff443 ] + +The change eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +introduced a goto that bypasses the creation of temporary mackey and ltk +which are later used by the likes of DHKey Check step. + +Later ffee202a78c2 ("Bluetooth: Always request for user confirmation for +Just Works (LE SC)") which means confirm_hint is always set in case +JUST_WORKS so the branch checking for an existing LTK becomes pointless +as confirm_hint will always be set, so this just merge both cases of +malicious or legitimate devices to be confirmed before continuing with the +pairing procedure. + +Link: https://github.com/bluez/bluez/issues/1622 +Fixes: eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index a31971fe2fd7e..3a33fd06e6a4c 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2136,7 +2136,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_chan *smp = chan->data; + struct hci_conn *hcon = conn->hcon; + u8 *pkax, *pkbx, *na, *nb, confirm_hint; +- u32 passkey; ++ u32 passkey = 0; + int err; + + bt_dev_dbg(hcon->hdev, "conn %p", conn); +@@ -2188,24 +2188,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +- +- /* Only Just-Works pairing requires extra checks */ +- if (smp->method != JUST_WORKS) +- goto mackey_and_ltk; +- +- /* If there already exists long term key in local host, leave +- * the decision to user space since the remote device could +- * be legitimate or malicious. +- */ +- if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, +- hcon->role)) { +- /* Set passkey to 0. The value can be any number since +- * it'll be ignored anyway. +- */ +- passkey = 0; +- confirm_hint = 1; +- goto confirm; +- } + } + + mackey_and_ltk: +@@ -2226,11 +2208,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (err) + return SMP_UNSPECIFIED; + +- confirm_hint = 0; +- +-confirm: +- if (smp->method == JUST_WORKS) +- confirm_hint = 1; ++ /* Always require user confirmation for Just-Works pairing to prevent ++ * impersonation attacks, or in case of a legitimate device that is ++ * repairing use the confirmation as acknowledgment to proceed with the ++ * creation of new keys. ++ */ ++ confirm_hint = smp->method == JUST_WORKS ? 1 : 0; + + err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, + hcon->dst_type, passkey, confirm_hint); +-- +2.51.0 + diff --git a/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch b/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch new file mode 100644 index 0000000000..9faaafbeb3 --- /dev/null +++ b/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch @@ -0,0 +1,92 @@ +From 0e0553f9067c4ef44a37ec3613ea6381c4ee4a51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:02 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing header + +From: Marc Kleine-Budde + +[ Upstream commit 6fe9f3279f7d2518439a7962c5870c6e9ecbadcf ] + +The driver expects to receive a struct gs_host_frame in +gs_usb_receive_bulk_callback(). + +Use struct_group to describe the header of the struct gs_host_frame and +check that we have at least received the header before accessing any +members of it. + +To resubmit the URB, do not dereference the pointer chain +"dev->parent->hf_size_rx" but use "parent->hf_size_rx" instead. Since +"urb->context" contains "parent", it is always defined, while "dev" is not +defined if the URB it too short. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-2-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index fd34945d831e9..b2cfdc3558a5a 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -259,13 +259,15 @@ struct canfd_quirk { + } __packed; + + struct gs_host_frame { +- u32 echo_id; +- __le32 can_id; ++ struct_group(header, ++ u32 echo_id; ++ __le32 can_id; + +- u8 can_dlc; +- u8 channel; +- u8 flags; +- u8 reserved; ++ u8 can_dlc; ++ u8 channel; ++ u8 flags; ++ u8 reserved; ++ ); + + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); +@@ -573,6 +575,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; ++ unsigned int minimum_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -591,6 +594,15 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + return; + } + ++ minimum_length = sizeof(hf->header); ++ if (urb->actual_length < minimum_length) { ++ dev_err_ratelimited(&parent->udev->dev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ + /* device reports out of range channel id */ + if (hf->channel >= parent->channel_cnt) + goto device_detach; +@@ -684,7 +696,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + resubmit_urb: + usb_fill_bulk_urb(urb, parent->udev, + parent->pipe_in, +- hf, dev->parent->hf_size_rx, ++ hf, parent->hf_size_rx, + gs_usb_receive_bulk_callback, parent); + + rc = usb_submit_urb(urb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-29525 b/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-29525 new file mode 100644 index 0000000000..791d9a959b --- /dev/null +++ b/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-29525 @@ -0,0 +1,140 @@ +From 91ae7e804275c479b48875f1862b4c4c569c9d82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:03 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing data + +From: Marc Kleine-Budde + +[ Upstream commit 395d988f93861101ec89d0dd9e3b876ae9392a5b ] + +The URB received in gs_usb_receive_bulk_callback() contains a struct +gs_host_frame. The length of the data after the header depends on the +gs_host_frame hf::flags and the active device features (e.g. time +stamping). + +Introduce a new function gs_usb_get_minimum_length() and check that we have +at least received the required amount of data before accessing it. Only +copy the data to that skb that has actually been received. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-3-a29b42eacada@pengutronix.de +[mkl: rename gs_usb_get_minimum_length() -> +gs_usb_get_minimum_rx_length()] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 59 +++++++++++++++++++++++++++++++++--- + 1 file changed, 54 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index b2cfdc3558a5a..36540a2544586 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -258,6 +258,11 @@ struct canfd_quirk { + u8 quirk; + } __packed; + ++/* struct gs_host_frame::echo_id == GS_HOST_FRAME_ECHO_ID_RX indicates ++ * a regular RX'ed CAN frame ++ */ ++#define GS_HOST_FRAME_ECHO_ID_RX 0xffffffff ++ + struct gs_host_frame { + struct_group(header, + u32 echo_id; +@@ -567,6 +572,37 @@ gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, + return len; + } + ++static unsigned int ++gs_usb_get_minimum_rx_length(const struct gs_can *dev, const struct gs_host_frame *hf, ++ unsigned int *data_length_p) ++{ ++ unsigned int minimum_length, data_length = 0; ++ ++ if (hf->flags & GS_CAN_FLAG_FD) { ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) ++ data_length = can_fd_dlc2len(hf->can_dlc); ++ ++ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) ++ /* timestamp follows data field of max size */ ++ minimum_length = struct_size(hf, canfd_ts, 1); ++ else ++ minimum_length = sizeof(hf->header) + data_length; ++ } else { ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX && ++ !(hf->can_id & cpu_to_le32(CAN_RTR_FLAG))) ++ data_length = can_cc_dlc2len(hf->can_dlc); ++ ++ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) ++ /* timestamp follows data field of max size */ ++ minimum_length = struct_size(hf, classic_can_ts, 1); ++ else ++ minimum_length = sizeof(hf->header) + data_length; ++ } ++ ++ *data_length_p = data_length; ++ return minimum_length; ++} ++ + static void gs_usb_receive_bulk_callback(struct urb *urb) + { + struct gs_usb *parent = urb->context; +@@ -575,7 +611,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; +- unsigned int minimum_length; ++ unsigned int minimum_length, data_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -618,20 +654,33 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + if (!netif_running(netdev)) + goto resubmit_urb; + +- if (hf->echo_id == -1) { /* normal rx */ ++ minimum_length = gs_usb_get_minimum_rx_length(dev, hf, &data_length); ++ if (urb->actual_length < minimum_length) { ++ stats->rx_errors++; ++ stats->rx_length_errors++; ++ ++ if (net_ratelimit()) ++ netdev_err(netdev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) { /* normal rx */ + if (hf->flags & GS_CAN_FLAG_FD) { + skb = alloc_canfd_skb(netdev, &cfd); + if (!skb) + return; + + cfd->can_id = le32_to_cpu(hf->can_id); +- cfd->len = can_fd_dlc2len(hf->can_dlc); ++ cfd->len = data_length; + if (hf->flags & GS_CAN_FLAG_BRS) + cfd->flags |= CANFD_BRS; + if (hf->flags & GS_CAN_FLAG_ESI) + cfd->flags |= CANFD_ESI; + +- memcpy(cfd->data, hf->canfd->data, cfd->len); ++ memcpy(cfd->data, hf->canfd->data, data_length); + } else { + skb = alloc_can_skb(netdev, &cf); + if (!skb) +@@ -640,7 +689,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + cf->can_id = le32_to_cpu(hf->can_id); + can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); + +- memcpy(cf->data, hf->classic_can->data, 8); ++ memcpy(cf->data, hf->classic_can->data, data_length); + + /* ERROR frames tell us information about the controller */ + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) +-- +2.51.0 + diff --git a/queue-6.12/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch b/queue-6.12/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch new file mode 100644 index 0000000000..035cf628ef --- /dev/null +++ b/queue-6.12/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch @@ -0,0 +1,60 @@ +From 9972b3d20d06ff86c3547243fb5494043e3367ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:01 +0100 +Subject: can: gs_usb: gs_usb_xmit_callback(): fix handling of failed + transmitted URBs + +From: Marc Kleine-Budde + +[ Upstream commit 516a0cd1c03fa266bb67dd87940a209fd4e53ce7 ] + +The driver lacks the cleanup of failed transfers of URBs. This reduces the +number of available URBs per error by 1. This leads to reduced performance +and ultimately to a complete stop of the transmission. + +If the sending of a bulk URB fails do proper cleanup: +- increase netdev stats +- mark the echo_sbk as free +- free the driver's context and do accounting +- wake the send queue + +Closes: https://github.com/candle-usb/candleLight_fw/issues/187 +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-1-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index fb904dc28b8ee..fd34945d831e9 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -747,8 +747,21 @@ static void gs_usb_xmit_callback(struct urb *urb) + struct gs_can *dev = txc->dev; + struct net_device *netdev = dev->netdev; + +- if (urb->status) +- netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); ++ if (!urb->status) ++ return; ++ ++ if (urb->status != -ESHUTDOWN && net_ratelimit()) ++ netdev_info(netdev, "failed to xmit URB %u: %pe\n", ++ txc->echo_id, ERR_PTR(urb->status)); ++ ++ netdev->stats.tx_dropped++; ++ netdev->stats.tx_errors++; ++ ++ can_free_echo_skb(netdev, txc->echo_id, NULL); ++ gs_free_tx_context(txc); ++ atomic_dec(&dev->active_tx_urbs); ++ ++ netif_wake_queue(netdev); + } + + static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, +-- +2.51.0 + diff --git a/queue-6.12/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch b/queue-6.12/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch new file mode 100644 index 0000000000..2bd9b528ac --- /dev/null +++ b/queue-6.12/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch @@ -0,0 +1,62 @@ +From 39dfb19f39b5ad569b73c6b593fa62207cdacf93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 12:27:09 -0400 +Subject: can: kvaser_usb: leaf: Fix potential infinite loop in command parsers + +From: Seungjin Bae + +[ Upstream commit 0c73772cd2b8cc108d5f5334de89ad648d89b9ec ] + +The `kvaser_usb_leaf_wait_cmd()` and `kvaser_usb_leaf_read_bulk_callback` +functions contain logic to zero-length commands. These commands are used +to align data to the USB endpoint's wMaxPacketSize boundary. + +The driver attempts to skip these placeholders by aligning the buffer +position `pos` to the next packet boundary using `round_up()` function. + +However, if zero-length command is found exactly on a packet boundary +(i.e., `pos` is a multiple of wMaxPacketSize, including 0), `round_up` +function will return the unchanged value of `pos`. This prevents `pos` +to be increased, causing an infinite loop in the parsing logic. + +This patch fixes this in the function by using `pos + 1` instead. +This ensures that even if `pos` is on a boundary, the calculation is +based on `pos + 1`, forcing `round_up()` to always return the next +aligned boundary. + +Fixes: 7259124eac7d ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") +Signed-off-by: Seungjin Bae +Reviewed-by: Jimmy Assarsson +Tested-by: Jimmy Assarsson +Link: https://patch.msgid.link/20251023162709.348240-1-eeodqql09@gmail.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 6b9122ab1464f..b7f6935686c96 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -662,7 +662,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, + * for further details. + */ + if (tmp->len == 0) { +- pos = round_up(pos, ++ pos = round_up(pos + 1, + le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; +@@ -1672,7 +1672,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, + * number of events in case of a heavy rx load on the bus. + */ + if (cmd->len == 0) { +- pos = round_up(pos, le16_to_cpu ++ pos = round_up(pos + 1, le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; + } +-- +2.51.0 + diff --git a/queue-6.12/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch b/queue-6.12/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch new file mode 100644 index 0000000000..98fa92bf18 --- /dev/null +++ b/queue-6.12/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch @@ -0,0 +1,39 @@ +From 3a9fa1cfaecdeb25e179d0442f5efed26fc3ba9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 09:40:31 -0500 +Subject: drm/amdgpu: fix cyan_skillfish2 gpu info fw handling + +From: Alex Deucher + +[ Upstream commit 7fa666ab07ba9e08f52f357cb8e1aad753e83ac6 ] + +If the board supports IP discovery, we don't need to +parse the gpu info firmware. + +Backport to 6.18. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4721 +Fixes: fa819e3a7c1e ("drm/amdgpu: add support for cyan skillfish gpu_info") +Signed-off-by: Alex Deucher +(cherry picked from commit 5427e32fa3a0ba9a016db83877851ed277b065fb) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index b93afd52a0094..9e1716a3f70ba 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -2414,6 +2414,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) + chip_name = "navi12"; + break; + case CHIP_CYAN_SKILLFISH: ++ if (adev->mman.discovery_bin) ++ return 0; + chip_name = "cyan_skillfish"; + break; + } +-- +2.51.0 + diff --git a/queue-6.12/drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch b/queue-6.12/drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch new file mode 100644 index 0000000000..349798876d --- /dev/null +++ b/queue-6.12/drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch @@ -0,0 +1,54 @@ +From 61ed2e84e90037089f287ab249c66a1455611e5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 11:48:43 -0800 +Subject: drm/xe: Fix conversion from clock ticks to milliseconds + +From: Harish Chegondi + +[ Upstream commit 7276878b069c57d9a9cca5db01d2f7a427b73456 ] + +When tick counts are large and multiplication by MSEC_PER_SEC is larger +than 64 bits, the conversion from clock ticks to milliseconds can go bad. + +Use mul_u64_u32_div() instead. + +Cc: Ashutosh Dixit +Signed-off-by: Harish Chegondi +Suggested-by: Umesh Nerlige Ramappa +Fixes: 49cc215aad7f ("drm/xe: Add xe_gt_clock_interval_to_ms helper") +Reviewed-by: Ashutosh Dixit +Signed-off-by: Ashutosh Dixit +Link: https://patch.msgid.link/1562f1b62d5be3fbaee100f09107f3cc49e40dd1.1763408584.git.harish.chegondi@intel.com +(cherry picked from commit 96b93ac214f9dd66294d975d86c5dee256faef91) +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_clock.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_clock.c b/drivers/gpu/drm/xe/xe_gt_clock.c +index 86c2d62b4bdc3..fa66295695c01 100644 +--- a/drivers/gpu/drm/xe/xe_gt_clock.c ++++ b/drivers/gpu/drm/xe/xe_gt_clock.c +@@ -82,11 +82,6 @@ int xe_gt_clock_init(struct xe_gt *gt) + return 0; + } + +-static u64 div_u64_roundup(u64 n, u32 d) +-{ +- return div_u64(n + d - 1, d); +-} +- + /** + * xe_gt_clock_interval_to_ms - Convert sampled GT clock ticks to msec + * +@@ -97,5 +92,5 @@ static u64 div_u64_roundup(u64 n, u32 d) + */ + u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count) + { +- return div_u64_roundup(count * MSEC_PER_SEC, gt->info.reference_clock); ++ return mul_u64_u32_div(count, MSEC_PER_SEC, gt->info.reference_clock); + } +-- +2.51.0 + diff --git a/queue-6.12/eth-fbnic-fix-counter-roll-over-issue.patch b/queue-6.12/eth-fbnic-fix-counter-roll-over-issue.patch new file mode 100644 index 0000000000..e3651cc1f2 --- /dev/null +++ b/queue-6.12/eth-fbnic-fix-counter-roll-over-issue.patch @@ -0,0 +1,43 @@ +From 2115dde7cccd1ac0075de73f12c73c8a77147956 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 13:17:04 -0800 +Subject: eth: fbnic: Fix counter roll-over issue + +From: Mohsin Bashir + +[ Upstream commit 6d66e093e0740d39a36ef742c60eec247df26f41 ] + +Fix a potential counter roll-over issue in fbnic_mbx_alloc_rx_msgs() +when calculating descriptor slots. The issue occurs when head - tail +results in a large positive value (unsigned) and the compiler interprets +head - tail - 1 as a signed value. + +Since FBNIC_IPC_MBX_DESC_LEN is a power of two, use a masking operation, +which is a common way of avoiding this problem when dealing with these +sort of ring space calculations. + +Fixes: da3cde08209e ("eth: fbnic: Add FW communication mechanism") +Signed-off-by: Mohsin Bashir +Link: https://patch.msgid.link/20251125211704.3222413-1-mohsin.bashr@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +index d6cf97ecf3276..6f606bdfd2296 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +@@ -198,7 +198,7 @@ static int fbnic_mbx_alloc_rx_msgs(struct fbnic_dev *fbd) + return -ENODEV; + + /* Fill all but 1 unused descriptors in the Rx queue. */ +- count = (head - tail - 1) % FBNIC_IPC_MBX_DESC_LEN; ++ count = (head - tail - 1) & (FBNIC_IPC_MBX_DESC_LEN - 1); + while (!err && count--) { + struct fbnic_tlv_msg *msg; + +-- +2.51.0 + diff --git a/queue-6.12/fs-namespace-fix-reference-leak-in-grab_requested_mn.patch b/queue-6.12/fs-namespace-fix-reference-leak-in-grab_requested_mn.patch new file mode 100644 index 0000000000..6dc7af87f1 --- /dev/null +++ b/queue-6.12/fs-namespace-fix-reference-leak-in-grab_requested_mn.patch @@ -0,0 +1,53 @@ +From bc381b5617c95412054f09590692275839f1060c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 07:19:53 +0000 +Subject: fs/namespace: fix reference leak in grab_requested_mnt_ns + +From: Andrei Vagin + +[ Upstream commit 7b6dcd9bfd869eee7693e45b1817dac8c56e5f86 ] + +lookup_mnt_ns() already takes a reference on mnt_ns. +grab_requested_mnt_ns() doesn't need to take an extra reference. + +Fixes: 78f0e33cd6c93 ("fs/namespace: correctly handle errors returned by grab_requested_mnt_ns") +Signed-off-by: Andrei Vagin +Link: https://patch.msgid.link/20251122071953.3053755-1-avagin@google.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/namespace.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 035d6f1f0b6ef..c3702f3303a89 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -5345,6 +5345,8 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq + + if (kreq->mnt_ns_id) { + mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id); ++ if (!mnt_ns) ++ return ERR_PTR(-ENOENT); + } else if (kreq->mnt_ns_fd) { + struct ns_common *ns; + +@@ -5360,13 +5362,12 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq + return ERR_PTR(-EINVAL); + + mnt_ns = to_mnt_ns(ns); ++ refcount_inc(&mnt_ns->passive); + } else { + mnt_ns = current->nsproxy->mnt_ns; ++ refcount_inc(&mnt_ns->passive); + } +- if (!mnt_ns) +- return ERR_PTR(-ENOENT); + +- refcount_inc(&mnt_ns->passive); + return mnt_ns; + } + +-- +2.51.0 + diff --git a/queue-6.12/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch b/queue-6.12/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch new file mode 100644 index 0000000000..2c3f14903a --- /dev/null +++ b/queue-6.12/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch @@ -0,0 +1,132 @@ +From 078c2076d76c6541087be5c36b92c07006962abc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Oct 2025 18:16:19 +0200 +Subject: iio: st_lsm6dsx: Fixed calibrated timestamp calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mario Tesi + +[ Upstream commit 8abbf45fcda028c2c05ba38eb14ede9fa9e7341b ] + +The calibrated timestamp is calculated from the nominal value using the +formula: + ts_gain[ns] ≈ ts_sensitivity - (ts_trim_coeff * val) / 1000. + +The values of ts_sensitivity and ts_trim_coeff are not the same for all +devices, so it is necessary to differentiate them based on the part name. +For the correct values please consult the relevant AN. + +Fixes: cb3b6b8e1bc0 ("iio: imu: st_lsm6dsx: add odr calibration feature") +Signed-off-by: Mario Tesi +Acked-by: Lorenzo Bianconi +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 18 ++++++++++++++++++ + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 19 ++++++++----------- + 2 files changed, 26 insertions(+), 11 deletions(-) + +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +index a3b93566533bc..6689621b33e05 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +@@ -192,6 +192,22 @@ struct st_lsm6dsx_fifo_ops { + * @fifo_en: Hw timer FIFO enable register info (addr + mask). + * @decimator: Hw timer FIFO decimator register info (addr + mask). + * @freq_fine: Difference in % of ODR with respect to the typical. ++ * @ts_sensitivity: Nominal timestamp sensitivity. ++ * @ts_trim_coeff: Coefficient for calculating the calibrated timestamp gain. ++ * This coefficient comes into play when linearizing the formula ++ * used to calculate the calibrated timestamp (please see the ++ * relevant formula in the AN for the specific IMU). ++ * For example, in the case of LSM6DSO we have: ++ * ++ * 1 / (1 + x) ~= 1 - x (Taylor’s Series) ++ * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) (from AN5192) ++ * ttrim[ns] ~= 25000 - 37.5 * val ++ * ttrim[ns] ~= 25000 - (37500 * val) / 1000 ++ * ++ * so, replacing ts_sensitivity = 25000 and ++ * ts_trim_coeff = 37500 ++ * ++ * ttrim[ns] ~= ts_sensitivity - (ts_trim_coeff * val) / 1000 + */ + struct st_lsm6dsx_hw_ts_settings { + struct st_lsm6dsx_reg timer_en; +@@ -199,6 +215,8 @@ struct st_lsm6dsx_hw_ts_settings { + struct st_lsm6dsx_reg fifo_en; + struct st_lsm6dsx_reg decimator; + u8 freq_fine; ++ u16 ts_sensitivity; ++ u16 ts_trim_coeff; + }; + + /** +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +index ed02679297252..11e144be85303 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +@@ -94,8 +94,6 @@ + + #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f + +-#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */ +- + static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { + ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), +@@ -983,6 +981,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x63, ++ .ts_sensitivity = 25000, ++ .ts_trim_coeff = 37500, + }, + .shub_settings = { + .page_mux = { +@@ -1196,6 +1196,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x63, ++ .ts_sensitivity = 25000, ++ .ts_trim_coeff = 37500, + }, + .event_settings = { + .enable_reg = { +@@ -1371,6 +1373,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x4f, ++ .ts_sensitivity = 21701, ++ .ts_trim_coeff = 28212, + }, + .shub_settings = { + .page_mux = { +@@ -2254,20 +2258,13 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) + } + + /* calibrate timestamp sensitivity */ +- hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY; ++ hw->ts_gain = ts_settings->ts_sensitivity; + if (ts_settings->freq_fine) { + err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); + if (err < 0) + return err; + +- /* +- * linearize the AN5192 formula: +- * 1 / (1 + x) ~= 1 - x (Taylor’s Series) +- * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) +- * ttrim[ns] ~= 25000 - 37.5 * val +- * ttrim[ns] ~= 25000 - (37500 * val) / 1000 +- */ +- hw->ts_gain -= ((s8)val * 37500) / 1000; ++ hw->ts_gain -= ((s8)val * ts_settings->ts_trim_coeff) / 1000; + } + + return 0; +-- +2.51.0 + diff --git a/queue-6.12/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch b/queue-6.12/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch new file mode 100644 index 0000000000..676a383c21 --- /dev/null +++ b/queue-6.12/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch @@ -0,0 +1,38 @@ +From acd1022d791c2ca3764fc065907ced9ae47df70b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 10:40:39 +0800 +Subject: mailbox: mailbox-test: Fix debugfs_create_dir error checking + +From: Haotian Zhang + +[ Upstream commit 3acf1028f5003731977f750a7070f3321a9cb740 ] + +The debugfs_create_dir() function returns ERR_PTR() on error, not NULL. +The current null-check fails to catch errors. + +Use IS_ERR() to correctly check for errors. + +Fixes: 8ea4484d0c2b ("mailbox: Add generic mechanism for testing Mailbox Controllers") +Signed-off-by: Haotian Zhang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c +index 3386b4e72551c..e416ce9e2d674 100644 +--- a/drivers/mailbox/mailbox-test.c ++++ b/drivers/mailbox/mailbox-test.c +@@ -268,7 +268,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, + return 0; + + tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); +- if (!tdev->root_debugfs_dir) { ++ if (IS_ERR(tdev->root_debugfs_dir)) { + dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-6.12/mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch b/queue-6.12/mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch new file mode 100644 index 0000000000..140a9e3358 --- /dev/null +++ b/queue-6.12/mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch @@ -0,0 +1,169 @@ +From 5910dafc0cfebfed985bc202989112557eb28678 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 01:16:30 +0800 +Subject: mailbox: mtk-cmdq: Refine DMA address handling for the command buffer + +From: Jason-JH Lin + +[ Upstream commit a195c7ccfb7a21b8118139835e25936ec8722596 ] + +GCE can only fetch the command buffer address from a 32-bit register. +Some SoCs support a 35-bit command buffer address for GCE, which +requires a right shift of 3 bits before setting the address into +the 32-bit register. A comment has been added to the header of +cmdq_get_shift_pa() to explain this requirement. + +To prevent the GCE command buffer address from being DMA mapped beyond +its supported bit range, the DMA bit mask for the device is set during +initialization. + +Additionally, to ensure the correct shift is applied when setting or +reading the register that stores the GCE command buffer address, +new APIs, cmdq_convert_gce_addr() and cmdq_revert_gce_addr(), have +been introduced for consistent operations on this register. + +The variable type for the command buffer address has been standardized +to dma_addr_t to prevent handling issues caused by type mismatches. + +Fixes: 0858fde496f8 ("mailbox: cmdq: variablize address shift in platform") +Signed-off-by: Jason-JH Lin +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mtk-cmdq-mailbox.c | 45 ++++++++++++++++-------- + include/linux/mailbox/mtk-cmdq-mailbox.h | 10 ++++++ + 2 files changed, 41 insertions(+), 14 deletions(-) + +diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c +index 38ab35157c85f..80a10361492b0 100644 +--- a/drivers/mailbox/mtk-cmdq-mailbox.c ++++ b/drivers/mailbox/mtk-cmdq-mailbox.c +@@ -92,6 +92,18 @@ struct gce_plat { + u32 gce_num; + }; + ++static inline u32 cmdq_convert_gce_addr(dma_addr_t addr, const struct gce_plat *pdata) ++{ ++ /* Convert DMA addr (PA or IOVA) to GCE readable addr */ ++ return addr >> pdata->shift; ++} ++ ++static inline dma_addr_t cmdq_revert_gce_addr(u32 addr, const struct gce_plat *pdata) ++{ ++ /* Revert GCE readable addr to DMA addr (PA or IOVA) */ ++ return (dma_addr_t)addr << pdata->shift; ++} ++ + u8 cmdq_get_shift_pa(struct mbox_chan *chan) + { + struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); +@@ -188,13 +200,12 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task) + struct cmdq_task *prev_task = list_last_entry( + &thread->task_busy_list, typeof(*task), list_entry); + u64 *prev_task_base = prev_task->pkt->va_base; ++ u32 gce_addr = cmdq_convert_gce_addr(task->pa_base, task->cmdq->pdata); + + /* let previous task jump to this task */ + dma_sync_single_for_cpu(dev, prev_task->pa_base, + prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); +- prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = +- (u64)CMDQ_JUMP_BY_PA << 32 | +- (task->pa_base >> task->cmdq->pdata->shift); ++ prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | gce_addr; + dma_sync_single_for_device(dev, prev_task->pa_base, + prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); + +@@ -237,7 +248,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, + struct cmdq_thread *thread) + { + struct cmdq_task *task, *tmp, *curr_task = NULL; +- u32 curr_pa, irq_flag, task_end_pa; ++ u32 irq_flag, gce_addr; ++ dma_addr_t curr_pa, task_end_pa; + bool err; + + irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS); +@@ -259,7 +271,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, + else + return; + +- curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift; ++ gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); ++ curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); + + list_for_each_entry_safe(task, tmp, &thread->task_busy_list, + list_entry) { +@@ -378,7 +391,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) + struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; + struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); + struct cmdq_task *task; +- unsigned long curr_pa, end_pa; ++ u32 gce_addr; ++ dma_addr_t curr_pa, end_pa; + + /* Client should not flush new tasks if suspended. */ + WARN_ON(cmdq->suspended); +@@ -402,20 +416,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) + */ + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); + +- writel(task->pa_base >> cmdq->pdata->shift, +- thread->base + CMDQ_THR_CURR_ADDR); +- writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift, +- thread->base + CMDQ_THR_END_ADDR); ++ gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata); ++ writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR); ++ gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata); ++ writel(gce_addr, thread->base + CMDQ_THR_END_ADDR); + + writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); + writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); + writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); + } else { + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); +- curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << +- cmdq->pdata->shift; +- end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << +- cmdq->pdata->shift; ++ gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); ++ curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); ++ gce_addr = readl(thread->base + CMDQ_THR_END_ADDR); ++ end_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); + /* check boundary */ + if (curr_pa == end_pa - CMDQ_INST_SIZE || + curr_pa == end_pa) { +@@ -646,6 +660,9 @@ static int cmdq_probe(struct platform_device *pdev) + if (err) + return err; + ++ dma_set_coherent_mask(dev, ++ DMA_BIT_MASK(sizeof(u32) * BITS_PER_BYTE + cmdq->pdata->shift)); ++ + cmdq->mbox.dev = dev; + cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, + sizeof(*cmdq->mbox.chans), GFP_KERNEL); +diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h +index a8f0070c7aa98..9914dcd33e2d9 100644 +--- a/include/linux/mailbox/mtk-cmdq-mailbox.h ++++ b/include/linux/mailbox/mtk-cmdq-mailbox.h +@@ -78,6 +78,16 @@ struct cmdq_pkt { + void *cl; + }; + ++/** ++ * cmdq_get_shift_pa() - get the shift bits of physical address ++ * @chan: mailbox channel ++ * ++ * GCE can only fetch the command buffer address from a 32-bit register. ++ * Some SOCs support more than 32-bit command buffer address for GCE, which ++ * requires some shift bits to make the address fit into the 32-bit register. ++ * ++ * Return: the shift bits of physical address ++ */ + u8 cmdq_get_shift_pa(struct mbox_chan *chan); + + #endif /* __MTK_CMDQ_MAILBOX_H__ */ +-- +2.51.0 + diff --git a/queue-6.12/mailbox-pcc-don-t-zero-error-register.patch b/queue-6.12/mailbox-pcc-don-t-zero-error-register.patch new file mode 100644 index 0000000000..984ec90391 --- /dev/null +++ b/queue-6.12/mailbox-pcc-don-t-zero-error-register.patch @@ -0,0 +1,57 @@ +From a9e2d7a5c04ab0f50d71d0f1deba045f9348b61a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:42:29 +0000 +Subject: mailbox: pcc: don't zero error register + +From: Jamie Iles + +[ Upstream commit ff0e4d4c97c94af34cc9cad37b5a5cdbe597a3b0 ] + +The error status mask for a type 3/4 subspace is used for reading the +error status, and the bitwise inverse is used for clearing the error +with the intent being to preserve any of the non-error bits. However, +we were previously applying the mask to extract the status and then +applying the inverse to the result which ended up clearing all bits. + +Instead, store the inverse mask in the preserve mask and then use that +on the original value read from the error status so that only the error +is cleared. + +Fixes: c45ded7e1135 ("mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)") +Signed-off-by: Jamie Iles +Signed-off-by: Punit Agrawal +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index bb977cf8ad423..2b7d0bc920726 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -278,9 +278,8 @@ static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) + if (ret) + return ret; + +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; ++ if (val & pchan->error.status_mask) { ++ val &= pchan->error.preserve_mask; + pcc_chan_reg_write(&pchan->error, val); + return -EIO; + } +@@ -673,7 +672,8 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan, + + ret = pcc_chan_reg_init(&pchan->error, + &pcct_ext->error_status_register, +- 0, 0, pcct_ext->error_status_mask, ++ ~pcct_ext->error_status_mask, 0, ++ pcct_ext->error_status_mask, + "Error Status"); + } + return ret; +-- +2.51.0 + diff --git a/queue-6.12/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch b/queue-6.12/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch new file mode 100644 index 0000000000..fbe339cde2 --- /dev/null +++ b/queue-6.12/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch @@ -0,0 +1,92 @@ +From 3a9cae1572b1b430772cbf437f495e081abad781 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 15:28:52 +0000 +Subject: mailbox: pcc: Refactor error handling in irq handler into separate + function + +From: Sudeep Holla + +[ Upstream commit 3a675f50415b95f2ae10bfd932e2154ba1a08ee7 ] + +The existing error handling logic in pcc_mbox_irq() is intermixed with the +main flow of the function. The command complete check and the complete +complete update/acknowledgment are nicely factored into separate functions. + +Moves error detection and clearing logic into a separate function called: +pcc_mbox_error_check_and_clear() by extracting error-handling logic from +pcc_mbox_irq(). + +This ensures error checking and clearing are handled separately and it +improves maintainability by keeping the IRQ handler focused on processing +events. + +Acked-by: Huisong Li +Tested-by: Huisong Li +Tested-by: Adam Young +Signed-off-by: Sudeep Holla +Signed-off-by: Jassi Brar +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 49254d99a8ad6..bb977cf8ad423 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -269,6 +269,25 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) + return !!val; + } + ++static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) ++{ ++ u64 val; ++ int ret; ++ ++ ret = pcc_chan_reg_read(&pchan->error, &val); ++ if (ret) ++ return ret; ++ ++ val &= pchan->error.status_mask; ++ if (val) { ++ val &= ~pchan->error.status_mask; ++ pcc_chan_reg_write(&pchan->error, val); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ + static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) + { + struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; +@@ -309,8 +328,6 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + { + struct pcc_chan_info *pchan; + struct mbox_chan *chan = p; +- u64 val; +- int ret; + + pchan = chan->con_priv; + +@@ -324,15 +341,8 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; + +- ret = pcc_chan_reg_read(&pchan->error, &val); +- if (ret) ++ if (pcc_mbox_error_check_and_clear(pchan)) + return IRQ_NONE; +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; +- pcc_chan_reg_write(&pchan->error, val); +- return IRQ_NONE; +- } + + /* + * Clear this flag after updating interrupt ack register and just +-- +2.51.0 + diff --git a/queue-6.12/net-aquantia-add-missing-descriptor-cache-invalidati.patch b/queue-6.12/net-aquantia-add-missing-descriptor-cache-invalidati.patch new file mode 100644 index 0000000000..7cd6b6e68c --- /dev/null +++ b/queue-6.12/net-aquantia-add-missing-descriptor-cache-invalidati.patch @@ -0,0 +1,144 @@ +From f6f30312746dc9fbda75909231ecad06c43609db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 12:15:33 +0800 +Subject: net: aquantia: Add missing descriptor cache invalidation on ATL2 + +From: Kai-Heng Feng + +[ Upstream commit 7526183cfdbe352c51c285762f0e15b7c428ea06 ] + +ATL2 hardware was missing descriptor cache invalidation in hw_stop(), +causing SMMU translation faults during device shutdown and module removal: +[ 70.355743] arm-smmu-v3 arm-smmu-v3.5.auto: event 0x10 received: +[ 70.361893] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0002060000000010 +[ 70.367948] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000020000000000 +[ 70.374002] arm-smmu-v3 arm-smmu-v3.5.auto: 0x00000000ff9bc000 +[ 70.380055] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000000000000000 +[ 70.386109] arm-smmu-v3 arm-smmu-v3.5.auto: event: F_TRANSLATION client: 0001:06:00.0 sid: 0x20600 ssid: 0x0 iova: 0xff9bc000 ipa: 0x0 +[ 70.398531] arm-smmu-v3 arm-smmu-v3.5.auto: unpriv data write s1 "Input address caused fault" stag: 0x0 + +Commit 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after +driver unbind") and commit ed4d81c4b3f2 ("net: aquantia: when cleaning +hw cache it should be toggled") fixed cache invalidation for ATL B0, but +ATL2 was left with only interrupt disabling. This allowed hardware to +write to cached descriptors after DMA memory was unmapped, triggering +SMMU faults. Once cache invalidation is applied to ATL2, the translation +fault can't be observed anymore. + +Add shared aq_hw_invalidate_descriptor_cache() helper and use it in both +ATL B0 and ATL2 hw_stop() implementations for consistent behavior. + +Fixes: e54dcf4bba3e ("net: atlantic: basic A2 init/deinit hw_ops") +Tested-by: Carol Soto +Signed-off-by: Kai-Heng Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251120041537.62184-1-kaihengf@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/aquantia/atlantic/aq_hw_utils.c | 22 +++++++++++++++++++ + .../ethernet/aquantia/atlantic/aq_hw_utils.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 +--------------- + .../aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 4 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 1921741f7311d..18b08277d2e1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -15,6 +15,7 @@ + + #include "aq_hw.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_llh.h" + + void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, + u32 shift, u32 val) +@@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) + lo_hi_writeq(value, hw->mmio + reg); + } + ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) ++{ ++ int err; ++ u32 val; ++ ++ /* Invalidate Descriptor Cache to prevent writing to the cached ++ * descriptors and to the data pointer of those descriptors ++ */ ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); ++ ++ err = aq_hw_err_from_flags(hw); ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ hw, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index ffa6e4067c211..d89c63d88e4a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 56c46266bb0ae..3a0b6d65d5fca 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { +- int err; +- u32 val; +- + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +- /* Invalidate Descriptor Cache to prevent writing to the cached +- * descriptors and to the data pointer of those descriptors +- */ +- hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); +- +- err = aq_hw_err_from_flags(self); +- +- if (err) +- goto err_exit; +- +- readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, +- self, val, val == 1, 1000U, 10000U); +- +-err_exit: +- return err; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index b0ed572e88c67..0ce9caae8799c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + { + hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); + +- return 0; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) +-- +2.51.0 + diff --git a/queue-6.12/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch b/queue-6.12/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch new file mode 100644 index 0000000000..4b4b41cbe8 --- /dev/null +++ b/queue-6.12/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch @@ -0,0 +1,93 @@ +From 9d204ddeac9473a0cef886508d2fa3d65dfc6267 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:22:49 +0800 +Subject: net: atlantic: fix fragment overflow handling in RX path + +From: Jiefeng Zhang + +[ Upstream commit 5ffcb7b890f61541201461580bb6622ace405aec ] + +The atlantic driver can receive packets with more than MAX_SKB_FRAGS (17) +fragments when handling large multi-descriptor packets. This causes an +out-of-bounds write in skb_add_rx_frag_netmem() leading to kernel panic. + +The issue occurs because the driver doesn't check the total number of +fragments before calling skb_add_rx_frag(). When a packet requires more +than MAX_SKB_FRAGS fragments, the fragment index exceeds the array bounds. + +Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, +then all fragments are accounted for. And reusing the existing check to +prevent the overflow earlier in the code path. + +This crash occurred in production with an Aquantia AQC113 10G NIC. + +Stack trace from production environment: +``` +RIP: 0010:skb_add_rx_frag_netmem+0x29/0xd0 +Code: 90 f3 0f 1e fa 0f 1f 44 00 00 48 89 f8 41 89 +ca 48 89 d7 48 63 ce 8b 90 c0 00 00 00 48 c1 e1 04 48 01 ca 48 03 90 +c8 00 00 00 <48> 89 7a 30 44 89 52 3c 44 89 42 38 40 f6 c7 01 75 74 48 +89 fa 83 +RSP: 0018:ffffa9bec02a8d50 EFLAGS: 00010287 +RAX: ffff925b22e80a00 RBX: ffff925ad38d2700 RCX: +fffffffe0a0c8000 +RDX: ffff9258ea95bac0 RSI: ffff925ae0a0c800 RDI: +0000000000037a40 +RBP: 0000000000000024 R08: 0000000000000000 R09: +0000000000000021 +R10: 0000000000000848 R11: 0000000000000000 R12: +ffffa9bec02a8e24 +R13: ffff925ad8615570 R14: 0000000000000000 R15: +ffff925b22e80a00 +FS: 0000000000000000(0000) +GS:ffff925e47880000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffff9258ea95baf0 CR3: 0000000166022004 CR4: +0000000000f72ef0 +PKRU: 55555554 +Call Trace: + +aq_ring_rx_clean+0x175/0xe60 [atlantic] +? aq_ring_rx_clean+0x14d/0xe60 [atlantic] +? aq_ring_tx_clean+0xdf/0x190 [atlantic] +? kmem_cache_free+0x348/0x450 +? aq_vec_poll+0x81/0x1d0 [atlantic] +? __napi_poll+0x28/0x1c0 +? net_rx_action+0x337/0x420 +``` + +Fixes: 6aecbba12b5c ("net: atlantic: add check for MAX_SKB_FRAGS") +Changes in v4: +- Add Fixes: tag to satisfy patch validation requirements. + +Changes in v3: +- Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, + then all fragments are accounted for. + +Signed-off-by: Jiefeng Zhang +Link: https://patch.msgid.link/20251126032249.69358-1-jiefeng.z.zhang@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index f21de0c21e524..d23d23bed39fe 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -547,6 +547,11 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi, + + if (!buff->is_eop) { + unsigned int frag_cnt = 0U; ++ ++ /* There will be an extra fragment */ ++ if (buff->len > AQ_CFG_RX_HDR_SIZE) ++ frag_cnt++; ++ + buff_ = buff; + do { + bool is_rsc_completed = true; +-- +2.51.0 + diff --git a/queue-6.12/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch b/queue-6.12/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch new file mode 100644 index 0000000000..64562fce83 --- /dev/null +++ b/queue-6.12/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch @@ -0,0 +1,73 @@ +From 8a5d9d136f5c005aaf122ee93d28ba166d52e79b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 13:13:24 +0200 +Subject: net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing + traffic + +From: Vladimir Oltean + +[ Upstream commit da62abaaa268357b1aa66b372ace562189a05df1 ] + +When using the SGMII PCS as a fixed-link chip-to-chip connection, it is +easy to miss the fact that traffic passes only at 1G, since that's what +any normal such connection would use. + +When using the SGMII PCS connected towards an on-board PHY or an SFP +module, it is immediately noticeable that when the link resolves to a +speed other than 1G, traffic from the MAC fails to pass: TX counters +increase, but nothing gets decoded by the other end, and no local RX +counters increase either. + +Artificially lowering a fixed-link rate to speed = <100> makes us able +to see the same issue as in the case of having an SGMII PHY. + +Some debugging shows that the XPCS configuration is A-OK, but that the +MAC Configuration Table entry for the port has the SPEED bits still set +to 1000Mbps, due to a special condition in the driver. Deleting that +condition, and letting the resolved link speed be programmed directly +into the MAC speed field, results in a functional link at all 3 speeds. + +This piece of evidence, based on testing on both generations with SGMII +support (SJA1105S and SJA1110A) directly contradicts the statement from +the blamed commit that "the MAC is fixed at 1 Gbps and we need to +configure the PCS only (if even that)". Worse, that statement is not +backed by any documentation, and no one from NXP knows what it might +refer to. + +I am unable to recall sufficient context regarding my testing from March +2020 to understand what led me to draw such a braindead and factually +incorrect conclusion. Yet, there is nothing of value regarding forcing +the MAC speed, either for SGMII or 2500Base-X (introduced at a later +stage), so remove all such logic. + +Fixes: ffe10e679cec ("net: dsa: sja1105: Add support for the SGMII port") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251122111324.136761-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index f3bb49a9e63c0..a078653531b51 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1303,14 +1303,7 @@ static int sja1105_set_port_speed(struct sja1105_private *priv, int port, + * table, since this will be used for the clocking setup, and we no + * longer need to store it in the static config (already told hardware + * we want auto during upload phase). +- * Actually for the SGMII port, the MAC is fixed at 1 Gbps and +- * we need to configure the PCS only (if even that). + */ +- if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; +- else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- + mac[port].speed = speed; + + return 0; +-- +2.51.0 + diff --git a/queue-6.12/net-dsa-sja1105-simplify-static-configuration-reload.patch b/queue-6.12/net-dsa-sja1105-simplify-static-configuration-reload.patch new file mode 100644 index 0000000000..ca8416377f --- /dev/null +++ b/queue-6.12/net-dsa-sja1105-simplify-static-configuration-reload.patch @@ -0,0 +1,159 @@ +From daabb4df84ed9210d4630eb7f07baedc6e909a97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 17:04:36 +0100 +Subject: net: dsa: sja1105: simplify static configuration reload + +From: Russell King (Oracle) + +[ Upstream commit a18891b55703a45b700618ef40edd5e9aaecc345 ] + +The static configuration reload saves the port speed in the static +configuration tables by first converting it from the internal +respresentation to the SPEED_xxx ethtool representation, and then +converts it back to restore the setting. This is because +sja1105_adjust_port_config() takes the speed as SPEED_xxx. + +However, this is unnecessarily complex. If we split +sja1105_adjust_port_config() up, we can simply save and restore the +mac[port].speed member in the static configuration tables. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1svfMa-005ZIX-If@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: da62abaaa268 ("net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing traffic") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 65 ++++++++++++++------------ + 1 file changed, 34 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index fbac2a647b20b..f3bb49a9e63c0 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1257,29 +1257,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv) + return rc; + } + +-/* Convert link speed from SJA1105 to ethtool encoding */ +-static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, +- u64 speed) +-{ +- if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) +- return SPEED_10; +- if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) +- return SPEED_100; +- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) +- return SPEED_1000; +- if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS]) +- return SPEED_2500; +- return SPEED_UNKNOWN; +-} +- +-/* Set link speed in the MAC configuration for a specific port. */ +-static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, +- int speed_mbps) ++static int sja1105_set_port_speed(struct sja1105_private *priv, int port, ++ int speed_mbps) + { + struct sja1105_mac_config_entry *mac; +- struct device *dev = priv->ds->dev; + u64 speed; +- int rc; + + /* On P/Q/R/S, one can read from the device via the MAC reconfiguration + * tables. On E/T, MAC reconfig tables are not readable, only writable. +@@ -1313,7 +1295,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; + break; + default: +- dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); ++ dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps); + return -EINVAL; + } + +@@ -1325,11 +1307,31 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + * we need to configure the PCS only (if even that). + */ + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; ++ speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; + else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- else +- mac[port].speed = speed; ++ speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; ++ ++ mac[port].speed = speed; ++ ++ return 0; ++} ++ ++/* Write the MAC Configuration Table entry and, if necessary, the CGU settings, ++ * after a link speedchange for this port. ++ */ ++static int sja1105_set_port_config(struct sja1105_private *priv, int port) ++{ ++ struct sja1105_mac_config_entry *mac; ++ struct device *dev = priv->ds->dev; ++ int rc; ++ ++ /* On P/Q/R/S, one can read from the device via the MAC reconfiguration ++ * tables. On E/T, MAC reconfig tables are not readable, only writable. ++ * We have to *know* what the MAC looks like. For the sake of keeping ++ * the code common, we'll use the static configuration tables as a ++ * reasonable approximation for both E/T and P/Q/R/S. ++ */ ++ mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + + /* Write to the dynamic reconfiguration tables */ + rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, +@@ -1390,7 +1392,8 @@ static void sja1105_mac_link_up(struct phylink_config *config, + struct sja1105_private *priv = dp->ds->priv; + int port = dp->index; + +- sja1105_adjust_port_config(priv, port, speed); ++ if (!sja1105_set_port_speed(priv, port, speed)) ++ sja1105_set_port_config(priv, port); + + sja1105_inhibit_tx(priv, BIT(port), false); + } +@@ -2289,8 +2292,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + { + struct ptp_system_timestamp ptp_sts_before; + struct ptp_system_timestamp ptp_sts_after; +- int speed_mbps[SJA1105_MAX_NUM_PORTS]; + u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0}; ++ u64 mac_speed[SJA1105_MAX_NUM_PORTS]; + struct sja1105_mac_config_entry *mac; + struct dsa_switch *ds = priv->ds; + s64 t1, t2, t3, t4; +@@ -2303,14 +2306,13 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + +- /* Back up the dynamic link speed changed by sja1105_adjust_port_config ++ /* Back up the dynamic link speed changed by sja1105_set_port_speed() + * in order to temporarily restore it to SJA1105_SPEED_AUTO - which the + * switch wants to see in the static config in order to allow us to + * change it through the dynamic interface later. + */ + for (i = 0; i < ds->num_ports; i++) { +- speed_mbps[i] = sja1105_port_speed_to_ethtool(priv, +- mac[i].speed); ++ mac_speed[i] = mac[i].speed; + mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO]; + + if (priv->xpcs[i]) +@@ -2373,7 +2375,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + struct dw_xpcs *xpcs = priv->xpcs[i]; + unsigned int neg_mode; + +- rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); ++ mac[i].speed = mac_speed[i]; ++ rc = sja1105_set_port_config(priv, i); + if (rc < 0) + goto out; + +-- +2.51.0 + diff --git a/queue-6.12/net-fec-cancel-perout_timer-when-perout-is-disabled.patch b/queue-6.12/net-fec-cancel-perout_timer-when-perout-is-disabled.patch new file mode 100644 index 0000000000..b8ba6d5063 --- /dev/null +++ b/queue-6.12/net-fec-cancel-perout_timer-when-perout-is-disabled.patch @@ -0,0 +1,42 @@ +From 9e17d38c2f980c5a26030649086f6a67013de11f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:07 +0800 +Subject: net: fec: cancel perout_timer when PEROUT is disabled + +From: Wei Fang + +[ Upstream commit 50caa744689e505414673c20359b04aa918439e3 ] + +The PEROUT allows the user to set a specified future time to output the +periodic signal. If the future time is far from the current time, the FEC +driver will use hrtimer to configure PEROUT one second before the future +time. However, the hrtimer will not be canceled if the PEROUT is disabled +before the hrtimer expires. So the PEROUT will be configured when the +hrtimer expires, which is not as expected. Therefore, cancel the hrtimer +in fec_ptp_pps_disable() to fix this issue. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-2-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index 7f6b574320716..cb3f05da3eee6 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -498,6 +498,8 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) + { + unsigned long flags; + ++ hrtimer_cancel(&fep->perout_timer); ++ + spin_lock_irqsave(&fep->tmreg_lock, flags); + writel(0, fep->hwp + FEC_TCSR(channel)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); +-- +2.51.0 + diff --git a/queue-6.12/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch b/queue-6.12/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch new file mode 100644 index 0000000000..97eb43779c --- /dev/null +++ b/queue-6.12/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch @@ -0,0 +1,58 @@ +From dedd616c8f583437908bb4dd7ab7dfc3bd27e95b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:09 +0800 +Subject: net: fec: do not allow enabling PPS and PEROUT simultaneously + +From: Wei Fang + +[ Upstream commit c0a1f3d7e128e8d1b6c0fe09c68eac5ebcf677c8 ] + +In the current driver, PPS and PEROUT use the same channel to generate +the events, so they cannot be enabled at the same time. Otherwise, the +later configuration will overwrite the earlier configuration. Therefore, +when configuring PPS, the driver will check whether PEROUT is enabled. +Similarly, when configuring PEROUT, the driver will check whether PPS +is enabled. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-4-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index a3853fccdc7b6..beb1d98fa741a 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -129,6 +129,12 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->perout_enable) { ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ dev_err(&fep->pdev->dev, "PEROUT is running"); ++ return -EBUSY; ++ } ++ + if (fep->pps_enable == enable) { + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return 0; +@@ -572,6 +578,12 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + } + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->pps_enable) { ++ dev_err(&fep->pdev->dev, "PPS is running"); ++ ret = -EBUSY; ++ goto unlock; ++ } ++ + if (fep->perout_enable) { + dev_err(&fep->pdev->dev, + "PEROUT has been enabled\n"); +-- +2.51.0 + diff --git a/queue-6.12/net-fec-do-not-register-pps-event-for-perout.patch b/queue-6.12/net-fec-do-not-register-pps-event-for-perout.patch new file mode 100644 index 0000000000..daf6a1f593 --- /dev/null +++ b/queue-6.12/net-fec-do-not-register-pps-event-for-perout.patch @@ -0,0 +1,48 @@ +From 858da6f8f5f0cb23b937dc1620577a1861726ec2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:10 +0800 +Subject: net: fec: do not register PPS event for PEROUT + +From: Wei Fang + +[ Upstream commit 9a060d0fac9e75524f72864adec6d8cdb70a5bca ] + +There are currently two situations that can trigger the PTP interrupt, +one is the PPS event, the other is the PEROUT event. However, the irq +handler fec_pps_interrupt() does not check the irq event type and +directly registers a PPS event into the system, but the event may be +a PEROUT event. This is incorrect because PEROUT is an output signal, +while PPS is the input of the kernel PPS system. Therefore, add a check +for the event type, if pps_enable is true, it means that the current +event is a PPS event, and then the PPS event is registered. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-5-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index beb1d98fa741a..4bb894b5afcb9 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -719,8 +719,11 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) + fep->next_counter = (fep->next_counter + fep->reload_period) & + fep->cc.mask; + +- event.type = PTP_CLOCK_PPS; +- ptp_clock_event(fep->ptp_clock, &event); ++ if (fep->pps_enable) { ++ event.type = PTP_CLOCK_PPS; ++ ptp_clock_event(fep->ptp_clock, &event); ++ } ++ + return IRQ_HANDLED; + } + +-- +2.51.0 + diff --git a/queue-6.12/net-fec-do-not-update-perout-if-it-is-enabled.patch b/queue-6.12/net-fec-do-not-update-perout-if-it-is-enabled.patch new file mode 100644 index 0000000000..d1f1d5fb18 --- /dev/null +++ b/queue-6.12/net-fec-do-not-update-perout-if-it-is-enabled.patch @@ -0,0 +1,137 @@ +From e2342f4b379e8b069528f3b9d1f1d6264886ff5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:08 +0800 +Subject: net: fec: do not update PEROUT if it is enabled + +From: Wei Fang + +[ Upstream commit e97faa0c20ea8840f45569ba434e30538fff8fc9 ] + +If the previously set PEROUT is already active, updating it will cause +the new PEROUT to start immediately instead of at the specified time. +This is because fep->reload_period is updated whithout check whether +the PEROUT is enabled, and the old PEROUT is not disabled. Therefore, +the pulse period will be updated immediately in the pulse interrupt +handler fec_pps_interrupt(). + +Currently, the driver does not support directly updating PEROUT and it +will make the logic be more complicated. To fix the current issue, add +a check before enabling the PEROUT, the driver will return an error if +PEROUT is enabled. If users wants to update a new PEROUT, they should +disable the old PEROUT first. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-3-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec.h | 1 + + drivers/net/ethernet/freescale/fec_ptp.c | 43 ++++++++++++++++++------ + 2 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index 1cca0425d4939..03fa6d6e6f0a8 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -683,6 +683,7 @@ struct fec_enet_private { + unsigned int reload_period; + int pps_enable; + unsigned int next_counter; ++ bool perout_enable; + struct hrtimer perout_timer; + u64 perout_stime; + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index cb3f05da3eee6..a3853fccdc7b6 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -244,6 +244,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) + * the FEC_TCCR register in time and missed the start time. + */ + if (fep->perout_stime < curr_time + 100 * NSEC_PER_MSEC) { ++ fep->perout_enable = false; + dev_err(&fep->pdev->dev, "Current time is too close to the start time!\n"); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return -1; +@@ -501,6 +502,7 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) + hrtimer_cancel(&fep->perout_timer); + + spin_lock_irqsave(&fep->tmreg_lock, flags); ++ fep->perout_enable = false; + writel(0, fep->hwp + FEC_TCSR(channel)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + +@@ -532,6 +534,8 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + + return ret; + } else if (rq->type == PTP_CLK_REQ_PEROUT) { ++ u32 reload_period; ++ + /* Reject requests with unsupported flags */ + if (rq->perout.flags) + return -EOPNOTSUPP; +@@ -551,12 +555,14 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + return -EOPNOTSUPP; + } + +- fep->reload_period = div_u64(period_ns, 2); +- if (on && fep->reload_period) { ++ reload_period = div_u64(period_ns, 2); ++ if (on && reload_period) { ++ u64 perout_stime; ++ + /* Convert 1588 timestamp to ns*/ + start_time.tv_sec = rq->perout.start.sec; + start_time.tv_nsec = rq->perout.start.nsec; +- fep->perout_stime = timespec64_to_ns(&start_time); ++ perout_stime = timespec64_to_ns(&start_time); + + mutex_lock(&fep->ptp_clk_mutex); + if (!fep->ptp_clk_on) { +@@ -565,18 +571,35 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + return -EOPNOTSUPP; + } + spin_lock_irqsave(&fep->tmreg_lock, flags); ++ ++ if (fep->perout_enable) { ++ dev_err(&fep->pdev->dev, ++ "PEROUT has been enabled\n"); ++ ret = -EBUSY; ++ goto unlock; ++ } ++ + /* Read current timestamp */ + curr_time = timecounter_read(&fep->tc); +- spin_unlock_irqrestore(&fep->tmreg_lock, flags); +- mutex_unlock(&fep->ptp_clk_mutex); ++ if (perout_stime <= curr_time) { ++ dev_err(&fep->pdev->dev, ++ "Start time must be greater than current time\n"); ++ ret = -EINVAL; ++ goto unlock; ++ } + + /* Calculate time difference */ +- delta = fep->perout_stime - curr_time; ++ delta = perout_stime - curr_time; ++ fep->reload_period = reload_period; ++ fep->perout_stime = perout_stime; ++ fep->perout_enable = true; + +- if (fep->perout_stime <= curr_time) { +- dev_err(&fep->pdev->dev, "Start time must larger than current time!\n"); +- return -EINVAL; +- } ++unlock: ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ mutex_unlock(&fep->ptp_clk_mutex); ++ ++ if (ret) ++ return ret; + + /* Because the timer counter of FEC only has 31-bits, correspondingly, + * the time comparison register FEC_TCCR also only low 31 bits can be +-- +2.51.0 + diff --git a/queue-6.12/net-lan966x-fix-the-initialization-of-taprio.patch b/queue-6.12/net-lan966x-fix-the-initialization-of-taprio.patch new file mode 100644 index 0000000000..dfdf193978 --- /dev/null +++ b/queue-6.12/net-lan966x-fix-the-initialization-of-taprio.patch @@ -0,0 +1,56 @@ +From d8167e280e823bec74617a9b0ec81f80f8115fdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 07:14:11 +0100 +Subject: net: lan966x: Fix the initialization of taprio + +From: Horatiu Vultur + +[ Upstream commit 9780f535f8e0f20b4632b5a173ead71aa8f095d2 ] + +To initialize the taprio block in lan966x, it is required to configure +the register REVISIT_DLY. The purpose of this register is to set the +delay before revisit the next gate and the value of this register depends +on the system clock. The problem is that the we calculated wrong the value +of the system clock period in picoseconds. The actual system clock is +~165.617754MHZ and this correspond to a period of 6038 pico seconds and +not 15125 as currently set. + +Fixes: e462b2717380b4 ("net: lan966x: Add offload support for taprio") +Signed-off-by: Horatiu Vultur +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121061411.810571-1-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +index 87e5e81d40dc6..84f5b4410e48e 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +@@ -1,11 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0+ + + #include ++#include + + #include "lan966x_main.h" + #include "vcap_api.h" + #include "vcap_api_client.h" + ++#define LAN9X66_CLOCK_RATE 165617754 ++ + #define LAN966X_MAX_PTP_ID 512 + + /* Represents 1ppm adjustment in 2^59 format with 6.037735849ns as reference +@@ -1132,5 +1135,5 @@ void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, + u32 lan966x_ptp_get_period_ps(void) + { + /* This represents the system clock period in picoseconds */ +- return 15125; ++ return PICO / LAN9X66_CLOCK_RATE; + } +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5e-fix-validation-logic-in-rate-limiting.patch b/queue-6.12/net-mlx5e-fix-validation-logic-in-rate-limiting.patch new file mode 100644 index 0000000000..49027be9e3 --- /dev/null +++ b/queue-6.12/net-mlx5e-fix-validation-logic-in-rate-limiting.patch @@ -0,0 +1,63 @@ +From 2e87d68851a5163272c3db1a7dd38470debeca97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:00:43 -0800 +Subject: net/mlx5e: Fix validation logic in rate limiting + +From: Danielle Costantino + +[ Upstream commit d2099d9f16dbfa1c5266d4230ff7860047bb0b68 ] + +The rate limiting validation condition currently checks the output +variable max_bw_value[i] instead of the input value +maxrate->tc_maxrate[i]. This causes the validation to compare an +uninitialized or stale value rather than the actual requested rate. + +The condition should check the input rate to properly validate against +the upper limit: + + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + +This aligns with the pattern used in the first branch, which correctly +checks maxrate->tc_maxrate[i] against upper_limit_mbps. + +The current implementation can lead to unreliable validation behavior: + +- For rates between 25.5 Gbps and 255 Gbps, if max_bw_value[i] is 0 + from initialization, the GBPS path may be taken regardless of whether + the actual rate is within bounds + +- When processing multiple TCs (i > 0), max_bw_value[i] contains the + value computed for the previous TC, affecting the validation logic + +- The overflow check for rates exceeding 255 Gbps may not trigger + consistently depending on previous array values + +This patch ensures the validation correctly examines the requested rate +value for proper bounds checking. + +Fixes: 43b27d1bd88a ("net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps") +Signed-off-by: Danielle Costantino +Reviewed-by: Gal Pressman +Link: https://patch.msgid.link/20251124180043.2314428-1-dcostantino@meta.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 2ca32fb1961e1..84e700777941e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -627,7 +627,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else if (max_bw_value[i] <= upper_limit_gbps) { ++ } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; +-- +2.51.0 + diff --git a/queue-6.12/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch b/queue-6.12/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch new file mode 100644 index 0000000000..efa86611d8 --- /dev/null +++ b/queue-6.12/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch @@ -0,0 +1,42 @@ +From 87e97999cb5188ca95aeced3e7bfa12815a1ceb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 14:17:13 +0000 +Subject: net: phy: mxl-gpy: fix bogus error on USXGMII and integrated PHY + +From: Daniel Golle + +[ Upstream commit ec3803b5917b6ff2f86ea965d0985c95d8a85119 ] + +As the interface mode doesn't need to be updated on PHYs connected with +USXGMII and integrated PHYs, gpy_update_interface() should just return 0 +in these cases rather than -EINVAL which has wrongly been introduced by +commit 7a495dde27ebc ("net: phy: mxl-gpy: Change gpy_update_interface() +function return type"), as this breaks support for those PHYs. + +Fixes: 7a495dde27ebc ("net: phy: mxl-gpy: Change gpy_update_interface() function return type") +Signed-off-by: Daniel Golle +Reviewed-by: Maxime Chevallier +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/f744f721a1fcc5e2e936428c62ff2c7d94d2a293.1763648168.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mxl-gpy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c +index e5f8ac4b4604b..17b0654644de5 100644 +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -523,7 +523,7 @@ static int gpy_update_interface(struct phy_device *phydev) + /* Interface mode is fixed for USXGMII and integrated PHY */ + if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || + phydev->interface == PHY_INTERFACE_MODE_INTERNAL) +- return -EINVAL; ++ return 0; + + /* Automatically switch SERDES interface between SGMII and 2500-BaseX + * according to speed. Disable ANEG in 2500-BaseX mode. +-- +2.51.0 + diff --git a/queue-6.12/net-sched-generalize-check-for-no-queue-qdisc-on-tx-.patch b/queue-6.12/net-sched-generalize-check-for-no-queue-qdisc-on-tx-.patch new file mode 100644 index 0000000000..be14e13b88 --- /dev/null +++ b/queue-6.12/net-sched-generalize-check-for-no-queue-qdisc-on-tx-.patch @@ -0,0 +1,93 @@ +From 9b66850e20d804ced348db390eff4e42dcfa2db7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 16:55:31 +0200 +Subject: net: sched: generalize check for no-queue qdisc on TX queue +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jesper Dangaard Brouer + +[ Upstream commit 34dd0fecaa02d654c447d43a7e4c72f9b18b7033 ] + +The "noqueue" qdisc can either be directly attached, or get default +attached if net_device priv_flags has IFF_NO_QUEUE. In both cases, the +allocated Qdisc structure gets it's enqueue function pointer reset to +NULL by noqueue_init() via noqueue_qdisc_ops. + +This is a common case for software virtual net_devices. For these devices +with no-queue, the transmission path in __dev_queue_xmit() will bypass +the qdisc layer. Directly invoking device drivers ndo_start_xmit (via +dev_hard_start_xmit). In this mode the device driver is not allowed to +ask for packets to be queued (either via returning NETDEV_TX_BUSY or +stopping the TXQ). + +The simplest and most reliable way to identify this no-queue case is by +checking if enqueue == NULL. + +The vrf driver currently open-codes this check (!qdisc->enqueue). While +functionally correct, this low-level detail is better encapsulated in a +dedicated helper for clarity and long-term maintainability. + +To make this behavior more explicit and reusable, this patch introduce a +new helper: qdisc_txq_has_no_queue(). Helper will also be used by the +veth driver in the next patch, which introduces optional qdisc-based +backpressure. + +This is a non-functional change. + +Reviewed-by: David Ahern +Reviewed-by: Toke Høiland-Jørgensen +Signed-off-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/174559293172.827981.7583862632045264175.stgit@firesoul +Signed-off-by: Jakub Kicinski +Stable-dep-of: a14602fcae17 ("veth: reduce XDP no_direct return section to fix race") +Signed-off-by: Sasha Levin +--- + drivers/net/vrf.c | 4 +--- + include/net/sch_generic.h | 8 ++++++++ + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c +index 89dde220058a2..b62462d8eff26 100644 +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -352,15 +352,13 @@ static int vrf_ifindex_lookup_by_table_id(struct net *net, u32 table_id) + static bool qdisc_tx_is_default(const struct net_device *dev) + { + struct netdev_queue *txq; +- struct Qdisc *qdisc; + + if (dev->num_tx_queues > 1) + return false; + + txq = netdev_get_tx_queue(dev, 0); +- qdisc = rcu_access_pointer(txq->qdisc); + +- return !qdisc->enqueue; ++ return qdisc_txq_has_no_queue(txq); + } + + /* Local traffic destined to local address. Reinsert the packet to rx +diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h +index a9d7e9ecee6b5..1e002b1dea629 100644 +--- a/include/net/sch_generic.h ++++ b/include/net/sch_generic.h +@@ -803,6 +803,14 @@ static inline bool qdisc_tx_changing(const struct net_device *dev) + return false; + } + ++/* "noqueue" qdisc identified by not having any enqueue, see noqueue_init() */ ++static inline bool qdisc_txq_has_no_queue(const struct netdev_queue *txq) ++{ ++ struct Qdisc *qdisc = rcu_access_pointer(txq->qdisc); ++ ++ return qdisc->enqueue == NULL; ++} ++ + /* Is the device using the noop qdisc on all queues? */ + static inline bool qdisc_tx_is_noop(const struct net_device *dev) + { +-- +2.51.0 + diff --git a/queue-6.12/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch b/queue-6.12/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch new file mode 100644 index 0000000000..a7a367045e --- /dev/null +++ b/queue-6.12/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch @@ -0,0 +1,47 @@ +From 8171f61800bbaca80129765f10f323b2665e05ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 12:38:34 +0000 +Subject: net: sxgbe: fix potential NULL dereference in sxgbe_rx() + +From: Alexey Kodanev + +[ Upstream commit f5bce28f6b9125502abec4a67d68eabcd24b3b17 ] + +Currently, when skb is null, the driver prints an error and then +dereferences skb on the next line. + +To fix this, let's add a 'break' after the error message to switch +to sxgbe_rx_refill(), which is similar to the approach taken by the +other drivers in this particular case, e.g. calxeda with xgmac_rx(). + +Found during a code review. + +Fixes: 1edb9ca69e8a ("net: sxgbe: add basic framework for Samsung 10Gb ethernet driver") +Signed-off-by: Alexey Kodanev +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121123834.97748-1-aleksei.kodanev@bell-sw.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index 12c8396b6942d..d2ba283f6123f 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -1520,8 +1520,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) + + skb = priv->rxq[qnum]->rx_skbuff[entry]; + +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + netdev_err(priv->dev, "rx descriptor is not consistent\n"); ++ break; ++ } + + prefetch(skb->data - NET_IP_ALIGN); + priv->rxq[qnum]->rx_skbuff[entry] = NULL; +-- +2.51.0 + diff --git a/queue-6.12/net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch b/queue-6.12/net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch new file mode 100644 index 0000000000..20ba137cd5 --- /dev/null +++ b/queue-6.12/net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch @@ -0,0 +1,39 @@ +From 64f442434126357abc7bc388b5c84d354375f63c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 15:09:00 +0800 +Subject: net: wwan: mhi: Keep modem name match with Foxconn T99W640 + +From: Slark Xiao + +[ Upstream commit 4fcb8ab4a09b1855dbfd7062605dd13abd64c086 ] + +Correct it since M.2 device T99W640 has updated from T99W515. +We need to align it with MHI side otherwise this modem can't +get the network. + +Fixes: ae5a34264354 ("bus: mhi: host: pci_generic: Fix the modem name of Foxconn T99W640") +Signed-off-by: Slark Xiao +Reviewed-by: Loic Poulain +Link: https://patch.msgid.link/20251125070900.33324-1-slark_xiao@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/wwan/mhi_wwan_mbim.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c +index c814fbd756a1e..f8bc9a39bfa30 100644 +--- a/drivers/net/wwan/mhi_wwan_mbim.c ++++ b/drivers/net/wwan/mhi_wwan_mbim.c +@@ -98,7 +98,7 @@ static struct mhi_mbim_link *mhi_mbim_get_link_rcu(struct mhi_mbim_context *mbim + static int mhi_mbim_get_link_mux_id(struct mhi_controller *cntrl) + { + if (strcmp(cntrl->name, "foxconn-dw5934e") == 0 || +- strcmp(cntrl->name, "foxconn-t99w515") == 0) ++ strcmp(cntrl->name, "foxconn-t99w640") == 0) + return WDS_BIND_MUX_DATA_PORT_MUX_ID; + + return 0; +-- +2.51.0 + diff --git a/queue-6.12/platform-x86-intel-punit_ipc-fix-memory-corruption.patch b/queue-6.12/platform-x86-intel-punit_ipc-fix-memory-corruption.patch new file mode 100644 index 0000000000..decd78f930 --- /dev/null +++ b/queue-6.12/platform-x86-intel-punit_ipc-fix-memory-corruption.patch @@ -0,0 +1,46 @@ +From 1ca2959c0ce20254654f5be5245e6d2b794f750f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 20:51:28 +0300 +Subject: platform/x86: intel: punit_ipc: fix memory corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit 9b9c0adbc3f8a524d291baccc9d0c04097fb4869 ] + +This passes the address of the pointer "&punit_ipcdev" when the intent +was to pass the pointer itself "punit_ipcdev" (without the ampersand). +This means that the: + + complete(&ipcdev->cmd_complete); + +in intel_punit_ioc() will write to a wrong memory address corrupting it. + +Fixes: fdca4f16f57d ("platform:x86: add Intel P-Unit mailbox IPC driver") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aSCmoBipSQ_tlD-D@stanley.mountain +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/punit_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/punit_ipc.c b/drivers/platform/x86/intel/punit_ipc.c +index cd0ba84cc8e4a..9e48229538a5e 100644 +--- a/drivers/platform/x86/intel/punit_ipc.c ++++ b/drivers/platform/x86/intel/punit_ipc.c +@@ -283,7 +283,7 @@ static int intel_punit_ipc_probe(struct platform_device *pdev) + } else { + ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc, + IRQF_NO_SUSPEND, "intel_punit_ipc", +- &punit_ipcdev); ++ punit_ipcdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", irq); + return ret; +-- +2.51.0 + diff --git a/queue-6.12/series b/queue-6.12/series new file mode 100644 index 0000000000..d7c4f1f006 --- /dev/null +++ b/queue-6.12/series @@ -0,0 +1,48 @@ +can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch +can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-29525 +bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch +bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch +bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch +bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch +net-sched-generalize-check-for-no-queue-qdisc-on-tx-.patch +veth-apply-qdisc-backpressure-on-full-ptr_ring-to-re.patch +veth-prevent-null-pointer-dereference-in-veth_xdp_rc.patch +veth-more-robust-handing-of-race-to-avoid-txq-gettin.patch +veth-reduce-xdp-no_direct-return-section-to-fix-race.patch +net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch +platform-x86-intel-punit_ipc-fix-memory-corruption.patch +net-aquantia-add-missing-descriptor-cache-invalidati.patch +net-lan966x-fix-the-initialization-of-taprio.patch +drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch +net-mlx5e-fix-validation-logic-in-rate-limiting.patch +team-move-team-device-type-change-at-the-end-of-team.patch +net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch +drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch +net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch +net-dsa-sja1105-simplify-static-configuration-reload.patch +net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch +eth-fbnic-fix-counter-roll-over-issue.patch +net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch +net-fec-cancel-perout_timer-when-perout-is-disabled.patch +net-fec-do-not-update-perout-if-it-is-enabled.patch +net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch +net-fec-do-not-register-pps-event-for-perout.patch +iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch +usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch +mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch +mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch +mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch +mailbox-pcc-don-t-zero-error-register.patch +fs-namespace-fix-reference-leak-in-grab_requested_mn.patch +spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch +spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch +spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch +spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch +spi-spi-mem-add-a-new-controller-capability.patch +spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch +spi-spi-nxp-fspi-remove-the-goto-in-probe.patch +spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch +spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch +spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch diff --git a/queue-6.12/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch b/queue-6.12/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch new file mode 100644 index 0000000000..291fbc0787 --- /dev/null +++ b/queue-6.12/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch @@ -0,0 +1,42 @@ +From d02ea71712ac6d7278d2c9952421151a109e3ea8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 09:58:52 +0800 +Subject: spi: amlogic-spifc-a1: Handle devm_pm_runtime_enable() errors + +From: Haotian Zhang + +[ Upstream commit a90903c2a3c38bce475f46ea3f93dbf6a9971553 ] + +devm_pm_runtime_enable() can fail due to memory allocation. The current +code ignores its return value, potentially causing runtime PM operations +to fail silently after autosuspend configuration. + +Check the return value of devm_pm_runtime_enable() and return on failure. + +Fixes: 909fac05b926 ("spi: add support for Amlogic A1 SPI Flash Controller") +Signed-off-by: Haotian Zhang +Link: https://patch.msgid.link/20251124015852.937-1-vulab@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-amlogic-spifc-a1.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-amlogic-spifc-a1.c b/drivers/spi/spi-amlogic-spifc-a1.c +index fadf6667cd51c..b430bca4f8bce 100644 +--- a/drivers/spi/spi-amlogic-spifc-a1.c ++++ b/drivers/spi/spi-amlogic-spifc-a1.c +@@ -349,7 +349,9 @@ static int amlogic_spifc_a1_probe(struct platform_device *pdev) + + pm_runtime_set_autosuspend_delay(spifc->dev, 500); + pm_runtime_use_autosuspend(spifc->dev); +- devm_pm_runtime_enable(spifc->dev); ++ ret = devm_pm_runtime_enable(spifc->dev); ++ if (ret) ++ return ret; + + ctrl->num_chipselect = 1; + ctrl->dev.of_node = pdev->dev.of_node; +-- +2.51.0 + diff --git a/queue-6.12/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch b/queue-6.12/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch new file mode 100644 index 0000000000..eb3f13d141 --- /dev/null +++ b/queue-6.12/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch @@ -0,0 +1,68 @@ +From fdb8049d0611c0c32852f7d681ea8b09dc3e1b7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 01:08:35 +1100 +Subject: spi: bcm63xx: fix premature CS deassertion on RX-only transactions + +From: Hang Zhou <929513338@qq.com> + +[ Upstream commit fd9862f726aedbc2f29a29916cabed7bcf5cadb6 ] + +On BCM6358 (and also observed on BCM6368) the controller appears to +only generate as many SPI clocks as bytes that have been written into +the TX FIFO. For RX-only transfers the driver programs the transfer +length in SPI_MSG_CTL but does not write anything into the FIFO, so +chip select is deasserted early and the RX transfer segment is never +fully clocked in. + +A concrete failing case is a three-transfer MAC address read from +SPI-NOR: + - TX 0x03 (read command) + - TX 3-byte address + - RX 6 bytes (MAC) + +In contrast, a two-transfer JEDEC-ID read (0x9f + 6-byte RX) works +because the driver uses prepend_len and writes dummy bytes into the +TX FIFO for the RX part. + +Fix this by writing 0xff dummy bytes into the TX FIFO for RX-only +segments so that the number of bytes written to the FIFO matches the +total message length seen by the controller. + +Fixes: b17de076062a ("spi/bcm63xx: work around inability to keep CS up") + +Signed-off-by: Hang Zhou <929513338@qq.com> +Link: https://patch.msgid.link/tencent_7AC88FCB3076489A4A7E6C2163DF1ACF8D06@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm63xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c +index a95badb7b7114..ba66fe9f1f543 100644 +--- a/drivers/spi/spi-bcm63xx.c ++++ b/drivers/spi/spi-bcm63xx.c +@@ -247,6 +247,20 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + + if (t->rx_buf) { + do_rx = true; ++ ++ /* ++ * In certain hardware implementations, there appears to be a ++ * hidden accumulator that tracks the number of bytes written into ++ * the hardware FIFO, and this accumulator overrides the length in ++ * the SPI_MSG_CTL register. ++ * ++ * Therefore, for read-only transfers, we need to write some dummy ++ * value into the FIFO to keep the accumulator tracking the correct ++ * length. ++ */ ++ if (!t->tx_buf) ++ memset_io(bs->tx_io + len, 0xFF, t->len); ++ + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; +-- +2.51.0 + diff --git a/queue-6.12/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch b/queue-6.12/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch new file mode 100644 index 0000000000..c390a5f265 --- /dev/null +++ b/queue-6.12/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch @@ -0,0 +1,78 @@ +From 8c154dd6ae76e73b331b36ebf0efe10212a83add Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 21:25:01 +0100 +Subject: spi: nxp-fspi: Propagate fwnode in ACPI case as well + +From: Andy Shevchenko + +[ Upstream commit 40ad64ac25bb736740f895d99a4aebbda9b80991 ] + +Propagate fwnode of the ACPI device to the SPI controller Linux device. +Currently only OF case propagates fwnode to the controller. + +While at it, replace several calls to dev_fwnode() with a single one +cached in a local variable, and unify checks for fwnode type by using +is_*_node() APIs. + +Fixes: 55ab8487e01d ("spi: spi-nxp-fspi: Add ACPI support") +Signed-off-by: Andy Shevchenko +Reviewed-by: Haibo Chen +Link: https://patch.msgid.link/20251126202501.2319679-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index 6cdeee9c581bd..5100b189c9050 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -1173,7 +1173,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + { + struct spi_controller *ctlr; + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; ++ struct fwnode_handle *fwnode = dev_fwnode(dev); + struct resource *res; + struct nxp_fspi *f; + int ret, irq; +@@ -1195,7 +1195,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, f); + + /* find the resources - configuration register address space */ +- if (is_acpi_node(dev_fwnode(f->dev))) ++ if (is_acpi_node(fwnode)) + f->iobase = devm_platform_ioremap_resource(pdev, 0); + else + f->iobase = devm_platform_ioremap_resource_byname(pdev, "fspi_base"); +@@ -1203,7 +1203,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + return PTR_ERR(f->iobase); + + /* find the resources - controller memory mapped space */ +- if (is_acpi_node(dev_fwnode(f->dev))) ++ if (is_acpi_node(fwnode)) + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + else + res = platform_get_resource_byname(pdev, +@@ -1216,7 +1216,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + f->memmap_phy_size = resource_size(res); + + /* find the clocks */ +- if (dev_of_node(&pdev->dev)) { ++ if (is_of_node(fwnode)) { + f->clk_en = devm_clk_get(dev, "fspi_en"); + if (IS_ERR(f->clk_en)) + return PTR_ERR(f->clk_en); +@@ -1260,7 +1260,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + else + ctlr->mem_caps = &nxp_fspi_mem_caps; + +- ctlr->dev.of_node = np; ++ device_set_node(&ctlr->dev, fwnode); + + return devm_spi_register_controller(&pdev->dev, ctlr); + } +-- +2.51.0 + diff --git a/queue-6.12/spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch b/queue-6.12/spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch new file mode 100644 index 0000000000..1246708ee5 --- /dev/null +++ b/queue-6.12/spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch @@ -0,0 +1,77 @@ +From 5fecf9bf71a022b479d18c4410bca6041c984cd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 18:05:57 +0100 +Subject: spi: nxp-fspi: Support per spi-mem operation frequency switches + +From: Miquel Raynal + +[ Upstream commit 26851cf65ffca2d3a8d529a125e54cf0084d69e7 ] + +Every ->exec_op() call correctly configures the spi bus speed to the +maximum allowed frequency for the memory using the constant spi default +parameter. Since we can now have per-operation constraints, let's use +the value that comes from the spi-mem operation structure instead. In +case there is no specific limitation for this operation, the default spi +device value will be given anyway. + +The per-operation frequency capability is thus advertised to the spi-mem +core. + +Cc: AngeloGioacchino Del Regno +Signed-off-by: Miquel Raynal +Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-12-ad218dbc406f@bootlin.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index b569302f22e61..78afef8851fc9 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -711,9 +711,10 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f) + * Value for rest of the CS FLSHxxCR0 register would be zero. + * + */ +-static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi) ++static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi, ++ const struct spi_mem_op *op) + { +- unsigned long rate = spi->max_speed_hz; ++ unsigned long rate = op->max_freq; + int ret; + uint64_t size_kb; + +@@ -937,7 +938,7 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true); + WARN_ON(err); + +- nxp_fspi_select_mem(f, mem->spi); ++ nxp_fspi_select_mem(f, mem->spi, op); + + nxp_fspi_prepare_lut(f, op); + /* +@@ -1155,6 +1156,10 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = { + .get_name = nxp_fspi_get_name, + }; + ++static const struct spi_controller_mem_caps nxp_fspi_mem_caps = { ++ .per_op_freq = true, ++}; ++ + static int nxp_fspi_probe(struct platform_device *pdev) + { + struct spi_controller *ctlr; +@@ -1252,6 +1257,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + ctlr->bus_num = -1; + ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; + ctlr->mem_ops = &nxp_fspi_mem_ops; ++ ctlr->mem_caps = &nxp_fspi_mem_caps; + + nxp_fspi_default_setup(f); + +-- +2.51.0 + diff --git a/queue-6.12/spi-spi-mem-add-a-new-controller-capability.patch b/queue-6.12/spi-spi-mem-add-a-new-controller-capability.patch new file mode 100644 index 0000000000..6a6e75c102 --- /dev/null +++ b/queue-6.12/spi-spi-mem-add-a-new-controller-capability.patch @@ -0,0 +1,73 @@ +From 2a6a79330cff2c4bddcc807db162d1b3e13baf02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 18:05:47 +0100 +Subject: spi: spi-mem: Add a new controller capability + +From: Miquel Raynal + +[ Upstream commit 1248c9b8d54120950fda10fbeb98fb8932b4d45c ] + +There are spi devices with multiple frequency limitations depending on +the invoked command. We probably do not want to afford running at the +lowest supported frequency all the time, so if we want to get the most +of our hardware, we need to allow per-operation frequency limitations. + +Among all the SPI memory controllers, I believe all are capable of +changing the spi frequency on the fly. Some of the drivers do not make +any frequency setup though. And some others will derive a per chip +prescaler value which will be used forever. + +Actually changing the frequency on the fly is something new in Linux, so +we need to carefully flag the drivers which do and do not support it. A +controller capability is created for that, and the presence for this +capability will always be checked before accepting such pattern. + +Signed-off-by: Miquel Raynal +Reviewed-by: Tudor Ambarus +Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-2-ad218dbc406f@bootlin.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mem.c | 6 ++++++ + include/linux/spi/spi-mem.h | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index 12299ce89a1cc..96374afd0193c 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -191,6 +191,12 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + op->max_freq < mem->spi->controller->min_speed_hz) + return false; + ++ if (op->max_freq && ++ op->max_freq < mem->spi->max_speed_hz) { ++ if (!spi_mem_controller_is_capable(ctlr, per_op_freq)) ++ return false; ++ } ++ + return spi_mem_check_buswidth(mem, op); + } + EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); +diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h +index 84ec524987921..c7a7719c26484 100644 +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -311,11 +311,13 @@ struct spi_controller_mem_ops { + * @ecc: Supports operations with error correction + * @swap16: Supports swapping bytes on a 16 bit boundary when configured in + * Octal DTR ++ * @per_op_freq: Supports per operation frequency switching + */ + struct spi_controller_mem_caps { + bool dtr; + bool ecc; + bool swap16; ++ bool per_op_freq; + }; + + #define spi_mem_controller_is_capable(ctlr, cap) \ +-- +2.51.0 + diff --git a/queue-6.12/spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch b/queue-6.12/spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch new file mode 100644 index 0000000000..5d2411cfde --- /dev/null +++ b/queue-6.12/spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch @@ -0,0 +1,93 @@ +From f87fd2c63f7b55b4ffc9862c94ef267f69038355 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Sep 2024 22:19:52 +0800 +Subject: spi: spi-mem: Allow specifying the byte order in Octal DTR mode + +From: Tudor Ambarus + +[ Upstream commit 030ace430afcf847f537227afceb22dfe8fb8fc8 ] + +There are NOR flashes (Macronix) that swap the bytes on a 16-bit +boundary when configured in Octal DTR mode. The byte order of +16-bit words is swapped when read or written in Octal Double +Transfer Rate (DTR) mode compared to Single Transfer Rate (STR) +modes. If one writes D0 D1 D2 D3 bytes using 1-1-1 mode, and uses +8D-8D-8D SPI mode for reading, it will read back D1 D0 D3 D2. +Swapping the bytes may introduce some endianness problems. It can +affect the boot sequence if the entire boot sequence is not handled +in either 8D-8D-8D mode or 1-1-1 mode. Therefore, it is necessary +to swap the bytes back to ensure the same byte order as in STR modes. +Fortunately there are controllers that could swap the bytes back at +runtime, addressing the flash's endianness requirements. Provide a +way for the upper layers to specify the byte order in Octal DTR mode. + +Merge Tudor's patch and add modifications for suiting newer version +of Linux kernel. + +Suggested-by: Michael Walle +Signed-off-by: JaimeLiao +Signed-off-by: AlvinZhou +Acked-by: Mark Brown +Link: https://lore.kernel.org/r/20240926141956.2386374-3-alvinzhou.tw@gmail.com +Signed-off-by: Tudor Ambarus +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mem.c | 3 +++ + include/linux/spi/spi-mem.h | 8 +++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index 17b8baf749e6a..abc6792e738c7 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -172,6 +172,9 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + if (!spi_mem_controller_is_capable(ctlr, dtr)) + return false; + ++ if (op->data.swap16 && !spi_mem_controller_is_capable(ctlr, swap16)) ++ return false; ++ + if (op->cmd.nbytes != 2) + return false; + } else { +diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h +index f866d5c8ed32a..c46d2b8029be5 100644 +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -90,6 +90,8 @@ enum spi_mem_data_dir { + * @data.buswidth: number of IO lanes used to send/receive the data + * @data.dtr: whether the data should be sent in DTR mode or not + * @data.ecc: whether error correction is required or not ++ * @data.swap16: whether the byte order of 16-bit words is swapped when read ++ * or written in Octal DTR mode compared to STR mode. + * @data.dir: direction of the transfer + * @data.nbytes: number of data bytes to send/receive. Can be zero if the + * operation does not involve transferring data +@@ -124,7 +126,8 @@ struct spi_mem_op { + u8 buswidth; + u8 dtr : 1; + u8 ecc : 1; +- u8 __pad : 6; ++ u8 swap16 : 1; ++ u8 __pad : 5; + enum spi_mem_data_dir dir; + unsigned int nbytes; + union { +@@ -297,10 +300,13 @@ struct spi_controller_mem_ops { + * struct spi_controller_mem_caps - SPI memory controller capabilities + * @dtr: Supports DTR operations + * @ecc: Supports operations with error correction ++ * @swap16: Supports swapping bytes on a 16 bit boundary when configured in ++ * Octal DTR + */ + struct spi_controller_mem_caps { + bool dtr; + bool ecc; ++ bool swap16; + }; + + #define spi_mem_controller_is_capable(ctlr, cap) \ +-- +2.51.0 + diff --git a/queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch b/queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch new file mode 100644 index 0000000000..146a8f0a05 --- /dev/null +++ b/queue-6.12/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch @@ -0,0 +1,221 @@ +From ef874c7a2c988d3e4e86dd78238594e189e029e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 18:05:46 +0100 +Subject: spi: spi-mem: Extend spi-mem operations with a per-operation maximum + frequency + +From: Miquel Raynal + +[ Upstream commit 0fefeade90e74bc8f40ab0e460f483565c492e28 ] + +In the spi subsystem, the bus frequency is derived as follows: +- the controller may expose a minimum and maximum operating frequency +- the hardware description, through the spi peripheral properties, + advise what is the maximum acceptable frequency from a device/wiring + point of view. +Transfers must be observed at a frequency which fits both (so in +practice, the lowest maximum). + +Actually, this second point mixes two information and already takes the +lowest frequency among: +- what the spi device is capable of (what is written in the component + datasheet) +- what the wiring allows (electromagnetic sensibility, crossovers, + terminations, antenna effect, etc). + +This logic works until spi devices are no longer capable of sustaining +their highest frequency regardless of the operation. Spi memories are +typically subject to such variation. Some devices are capable of +spitting their internally stored data (essentially in read mode) at a +very fast rate, typically up to 166MHz on Winbond SPI-NAND chips, using +"fast" commands. However, some of the low-end operations, such as +regular page read-from-cache commands, are more limited and can only be +executed at 54MHz at most. This is currently a problem in the SPI-NAND +subsystem. Another situation, even if not yet supported, will be with +DTR commands, when the data is latched on both edges of the clock. The +same chips as mentioned previously are in this case limited to +80MHz. Yet another example might be continuous reads, which, under +certain circumstances, can also run at most at 104 or 120MHz. + +As a matter of fact, the "one frequency per chip" policy is outdated and +more fine grain configuration is needed: we need to allow per-operation +frequency limitations. So far, all datasheets I encountered advertise a +maximum default frequency, which need to be lowered for certain specific +operations. So based on the current infrastructure, we can still expect +firmware (device trees in general) to continued advertising the same +maximum speed which is a mix between the PCB limitations and the chip +maximum capability, and expect per-operation lower frequencies when this +is relevant. + +Add a `struct spi_mem_op` member to carry this information. Not +providing this field explicitly from upper layers means that there is no +further constraint and the default spi device maximum speed will be +carried instead. The SPI_MEM_OP() macro is also expanded with an +optional frequency argument, because virtually all operations can be +subject to such a limitation, and this will allow for a smooth and +discrete transition. + +For controller drivers which do not implement the spi-mem interface, the +per-transfer speed is also set acordingly to a lower (than the maximum +default) speed when relevant. + +Acked-by: Pratyush Yadav +Signed-off-by: Miquel Raynal +Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-1-ad218dbc406f@bootlin.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/spi/core.c | 2 ++ + drivers/spi/spi-mem.c | 28 ++++++++++++++++++++++++++++ + include/linux/spi/spi-mem.h | 12 +++++++++++- + 3 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c +index c523a1a22c2b0..57b8807b19482 100644 +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1217,6 +1217,8 @@ spinand_select_op_variant(struct spinand_device *spinand, + if (ret) + break; + ++ spi_mem_adjust_op_freq(spinand->spimem, &op); ++ + if (!spi_mem_supports_op(spinand->spimem, &op)) + break; + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index abc6792e738c7..12299ce89a1cc 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -187,6 +187,10 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + return false; + } + ++ if (op->max_freq && mem->spi->controller->min_speed_hz && ++ op->max_freq < mem->spi->controller->min_speed_hz) ++ return false; ++ + return spi_mem_check_buswidth(mem, op); + } + EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); +@@ -364,6 +368,9 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + u8 *tmpbuf; + int ret; + ++ /* Make sure the operation frequency is correct before going futher */ ++ spi_mem_adjust_op_freq(mem, (struct spi_mem_op *)op); ++ + ret = spi_mem_check_op(op); + if (ret) + return ret; +@@ -410,6 +417,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + xfers[xferpos].tx_buf = tmpbuf; + xfers[xferpos].len = op->cmd.nbytes; + xfers[xferpos].tx_nbits = op->cmd.buswidth; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen++; +@@ -424,6 +432,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + xfers[xferpos].tx_buf = tmpbuf + 1; + xfers[xferpos].len = op->addr.nbytes; + xfers[xferpos].tx_nbits = op->addr.buswidth; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen += op->addr.nbytes; +@@ -435,6 +444,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + xfers[xferpos].len = op->dummy.nbytes; + xfers[xferpos].tx_nbits = op->dummy.buswidth; + xfers[xferpos].dummy_data = 1; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen += op->dummy.nbytes; +@@ -450,6 +460,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + } + + xfers[xferpos].len = op->data.nbytes; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen += op->data.nbytes; +@@ -528,6 +539,23 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) + } + EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size); + ++/** ++ * spi_mem_adjust_op_freq() - Adjust the frequency of a SPI mem operation to ++ * match controller, PCB and chip limitations ++ * @mem: the SPI memory ++ * @op: the operation to adjust ++ * ++ * Some chips have per-op frequency limitations and must adapt the maximum ++ * speed. This function allows SPI mem drivers to set @op->max_freq to the ++ * maximum supported value. ++ */ ++void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op) ++{ ++ if (!op->max_freq || op->max_freq > mem->spi->max_speed_hz) ++ op->max_freq = mem->spi->max_speed_hz; ++} ++EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq); ++ + static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) + { +diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h +index c46d2b8029be5..84ec524987921 100644 +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -68,6 +68,9 @@ enum spi_mem_data_dir { + SPI_MEM_DATA_OUT, + }; + ++#define SPI_MEM_OP_MAX_FREQ(__freq) \ ++ .max_freq = __freq ++ + /** + * struct spi_mem_op - describes a SPI memory operation + * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is +@@ -97,6 +100,9 @@ enum spi_mem_data_dir { + * operation does not involve transferring data + * @data.buf.in: input buffer (must be DMA-able) + * @data.buf.out: output buffer (must be DMA-able) ++ * @max_freq: frequency limitation wrt this operation. 0 means there is no ++ * specific constraint and the highest achievable frequency can be ++ * attempted. + */ + struct spi_mem_op { + struct { +@@ -135,14 +141,17 @@ struct spi_mem_op { + const void *out; + } buf; + } data; ++ ++ unsigned int max_freq; + }; + +-#define SPI_MEM_OP(__cmd, __addr, __dummy, __data) \ ++#define SPI_MEM_OP(__cmd, __addr, __dummy, __data, ...) \ + { \ + .cmd = __cmd, \ + .addr = __addr, \ + .dummy = __dummy, \ + .data = __data, \ ++ __VA_ARGS__ \ + } + + /** +@@ -371,6 +380,7 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + #endif /* CONFIG_SPI_MEM */ + + int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op); ++void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op); + + bool spi_mem_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op); +-- +2.51.0 + diff --git a/queue-6.12/spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch b/queue-6.12/spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch new file mode 100644 index 0000000000..b43cb0fbee --- /dev/null +++ b/queue-6.12/spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch @@ -0,0 +1,79 @@ +From f8c93ff4d0ad8a8d5c8c2a216504d72b41e0da2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Sep 2025 15:27:10 +0800 +Subject: spi: spi-nxp-fspi: Add OCT-DTR mode support + +From: Haibo Chen + +[ Upstream commit 0f67557763accbdd56681f17ed5350735198c57b ] + +Add OCT-DTR mode support in default, since flexspi do not supports +swapping bytes on a 16 bit boundary in OCT-DTR mode, so mark swap16 +as false. + +lx2160a do not support DQS, so add a quirk to disable DTR mode for this +platform. + +Signed-off-by: Haibo Chen +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20250917-flexspi-ddr-v2-5-bb9fe2a01889@nxp.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index 825b2a36377c2..6cdeee9c581bd 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -325,6 +325,8 @@ + + /* Access flash memory using IP bus only */ + #define FSPI_QUIRK_USE_IP_ONLY BIT(0) ++/* Disable DTR */ ++#define FSPI_QUIRK_DISABLE_DTR BIT(1) + + struct nxp_fspi_devtype_data { + unsigned int rxfifo; +@@ -339,7 +341,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = { + .rxfifo = SZ_512, /* (64 * 64 bits) */ + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ +- .quirks = 0, ++ .quirks = FSPI_QUIRK_DISABLE_DTR, + .lut_num = 32, + .little_endian = true, /* little-endian */ + }; +@@ -1157,6 +1159,13 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = { + }; + + static const struct spi_controller_mem_caps nxp_fspi_mem_caps = { ++ .dtr = true, ++ .swap16 = false, ++ .per_op_freq = true, ++}; ++ ++static const struct spi_controller_mem_caps nxp_fspi_mem_caps_disable_dtr = { ++ .dtr = false, + .per_op_freq = true, + }; + +@@ -1245,7 +1254,12 @@ static int nxp_fspi_probe(struct platform_device *pdev) + ctlr->bus_num = -1; + ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; + ctlr->mem_ops = &nxp_fspi_mem_ops; +- ctlr->mem_caps = &nxp_fspi_mem_caps; ++ ++ if (f->devtype_data->quirks & FSPI_QUIRK_DISABLE_DTR) ++ ctlr->mem_caps = &nxp_fspi_mem_caps_disable_dtr; ++ else ++ ctlr->mem_caps = &nxp_fspi_mem_caps; ++ + ctlr->dev.of_node = np; + + return devm_spi_register_controller(&pdev->dev, ctlr); +-- +2.51.0 + diff --git a/queue-6.12/spi-spi-nxp-fspi-remove-the-goto-in-probe.patch b/queue-6.12/spi-spi-nxp-fspi-remove-the-goto-in-probe.patch new file mode 100644 index 0000000000..a7a4eaf2b8 --- /dev/null +++ b/queue-6.12/spi-spi-nxp-fspi-remove-the-goto-in-probe.patch @@ -0,0 +1,179 @@ +From ffd2b6a6c136c1b564b92e73b16fe33191e7ab72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Apr 2025 18:06:43 +0800 +Subject: spi: spi-nxp-fspi: remove the goto in probe + +From: Haibo Chen + +[ Upstream commit 48900813abd2730a35c6e3afd1609bafac5271cc ] + +Remove all the goto in probe to simplify the driver. + +Signed-off-by: Haibo Chen +Link: https://patch.msgid.link/20250428-flexspipatch-v3-1-61d5e8f591bc@nxp.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 87 ++++++++++++-------------------------- + 1 file changed, 27 insertions(+), 60 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index 78afef8851fc9..825b2a36377c2 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -1167,10 +1167,10 @@ static int nxp_fspi_probe(struct platform_device *pdev) + struct device_node *np = dev->of_node; + struct resource *res; + struct nxp_fspi *f; +- int ret; ++ int ret, irq; + u32 reg; + +- ctlr = spi_alloc_host(&pdev->dev, sizeof(*f)); ++ ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*f)); + if (!ctlr) + return -ENOMEM; + +@@ -1180,10 +1180,8 @@ static int nxp_fspi_probe(struct platform_device *pdev) + f = spi_controller_get_devdata(ctlr); + f->dev = dev; + f->devtype_data = (struct nxp_fspi_devtype_data *)device_get_match_data(dev); +- if (!f->devtype_data) { +- ret = -ENODEV; +- goto err_put_ctrl; +- } ++ if (!f->devtype_data) ++ return -ENODEV; + + platform_set_drvdata(pdev, f); + +@@ -1192,11 +1190,8 @@ static int nxp_fspi_probe(struct platform_device *pdev) + f->iobase = devm_platform_ioremap_resource(pdev, 0); + else + f->iobase = devm_platform_ioremap_resource_byname(pdev, "fspi_base"); +- +- if (IS_ERR(f->iobase)) { +- ret = PTR_ERR(f->iobase); +- goto err_put_ctrl; +- } ++ if (IS_ERR(f->iobase)) ++ return PTR_ERR(f->iobase); + + /* find the resources - controller memory mapped space */ + if (is_acpi_node(dev_fwnode(f->dev))) +@@ -1204,11 +1199,8 @@ static int nxp_fspi_probe(struct platform_device *pdev) + else + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "fspi_mmap"); +- +- if (!res) { +- ret = -ENODEV; +- goto err_put_ctrl; +- } ++ if (!res) ++ return -ENODEV; + + /* assign memory mapped starting address and mapped size. */ + f->memmap_phy = res->start; +@@ -1217,69 +1209,46 @@ static int nxp_fspi_probe(struct platform_device *pdev) + /* find the clocks */ + if (dev_of_node(&pdev->dev)) { + f->clk_en = devm_clk_get(dev, "fspi_en"); +- if (IS_ERR(f->clk_en)) { +- ret = PTR_ERR(f->clk_en); +- goto err_put_ctrl; +- } ++ if (IS_ERR(f->clk_en)) ++ return PTR_ERR(f->clk_en); + + f->clk = devm_clk_get(dev, "fspi"); +- if (IS_ERR(f->clk)) { +- ret = PTR_ERR(f->clk); +- goto err_put_ctrl; +- } +- +- ret = nxp_fspi_clk_prep_enable(f); +- if (ret) { +- dev_err(dev, "can not enable the clock\n"); +- goto err_put_ctrl; +- } ++ if (IS_ERR(f->clk)) ++ return PTR_ERR(f->clk); + } + ++ /* find the irq */ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return dev_err_probe(dev, irq, "Failed to get irq source"); ++ ++ ret = nxp_fspi_clk_prep_enable(f); ++ if (ret) ++ return dev_err_probe(dev, ret, "Can't enable the clock\n"); ++ + /* Clear potential interrupts */ + reg = fspi_readl(f, f->iobase + FSPI_INTR); + if (reg) + fspi_writel(f, reg, f->iobase + FSPI_INTR); + +- /* find the irq */ +- ret = platform_get_irq(pdev, 0); +- if (ret < 0) +- goto err_disable_clk; ++ nxp_fspi_default_setup(f); + +- ret = devm_request_irq(dev, ret, ++ ret = devm_request_irq(dev, irq, + nxp_fspi_irq_handler, 0, pdev->name, f); + if (ret) { +- dev_err(dev, "failed to request irq: %d\n", ret); +- goto err_disable_clk; ++ nxp_fspi_clk_disable_unprep(f); ++ return dev_err_probe(dev, ret, "Failed to request irq\n"); + } + +- mutex_init(&f->lock); ++ devm_mutex_init(dev, &f->lock); + + ctlr->bus_num = -1; + ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; + ctlr->mem_ops = &nxp_fspi_mem_ops; + ctlr->mem_caps = &nxp_fspi_mem_caps; +- +- nxp_fspi_default_setup(f); +- + ctlr->dev.of_node = np; + +- ret = devm_spi_register_controller(&pdev->dev, ctlr); +- if (ret) +- goto err_destroy_mutex; +- +- return 0; +- +-err_destroy_mutex: +- mutex_destroy(&f->lock); +- +-err_disable_clk: +- nxp_fspi_clk_disable_unprep(f); +- +-err_put_ctrl: +- spi_controller_put(ctlr); +- +- dev_err(dev, "NXP FSPI probe failed\n"); +- return ret; ++ return devm_spi_register_controller(&pdev->dev, ctlr); + } + + static void nxp_fspi_remove(struct platform_device *pdev) +@@ -1291,8 +1260,6 @@ static void nxp_fspi_remove(struct platform_device *pdev) + + nxp_fspi_clk_disable_unprep(f); + +- mutex_destroy(&f->lock); +- + if (f->ahb_addr) + iounmap(f->ahb_addr); + } +-- +2.51.0 + diff --git a/queue-6.12/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch b/queue-6.12/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch new file mode 100644 index 0000000000..1fc002960b --- /dev/null +++ b/queue-6.12/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch @@ -0,0 +1,44 @@ +From ffb7737a66dce2f342fe6ad03cd56533927a7148 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 10:50:27 +0100 +Subject: spi: tegra114: remove Kconfig dependency on TEGRA20_APB_DMA + +From: Francesco Lavra + +[ Upstream commit 3dcf44ab56e1d3ca3532083c0d5390b758e45b45 ] + +This driver runs also on Tegra SoCs without a Tegra20 APB DMA controller +(e.g. Tegra234). +Remove the Kconfig dependency on TEGRA20_APB_DMA; in addition, amend the +help text to reflect the fact that this driver works on SoCs different from +Tegra114. + +Fixes: bb9667d8187b ("arm64: tegra: Add SPI device tree nodes for Tegra234") +Signed-off-by: Francesco Lavra +Link: https://patch.msgid.link/20251126095027.4102004-1-flavra@baylibre.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 8237972174048..06c740442fa73 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -1087,10 +1087,10 @@ config SPI_TEGRA210_QUAD + + config SPI_TEGRA114 + tristate "NVIDIA Tegra114 SPI Controller" +- depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST ++ depends on ARCH_TEGRA || COMPILE_TEST + depends on RESET_CONTROLLER + help +- SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller ++ SPI controller driver for NVIDIA Tegra114 and later SoCs. This controller + is different than the older SoCs SPI controller and also register interface + get changed with this controller. + +-- +2.51.0 + diff --git a/queue-6.12/team-move-team-device-type-change-at-the-end-of-team.patch b/queue-6.12/team-move-team-device-type-change-at-the-end-of-team.patch new file mode 100644 index 0000000000..30d91ab077 --- /dev/null +++ b/queue-6.12/team-move-team-device-type-change-at-the-end-of-team.patch @@ -0,0 +1,118 @@ +From fa35338f2e45e461afacbedf698b6a190886d63c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 02:20:27 +0200 +Subject: team: Move team device type change at the end of team_port_add + +From: Nikola Z. Ivanov + +[ Upstream commit 0ae9cfc454ea5ead5f3ddbdfe2e70270d8e2c8ef ] + +Attempting to add a port device that is already up will expectedly fail, +but not before modifying the team device header_ops. + +In the case of the syzbot reproducer the gre0 device is +already in state UP when it attempts to add it as a +port device of team0, this fails but before that +header_ops->create of team0 is changed from eth_header to ipgre_header +in the call to team_dev_type_check_change. + +Later when we end up in ipgre_header() struct ip_tunnel* points to nonsense +as the private data of the device still holds a struct team. + +Example sequence of iproute2 commands to reproduce the hang/BUG(): +ip link add dev team0 type team +ip link add dev gre0 type gre +ip link set dev gre0 up +ip link set dev gre0 master team0 +ip link set dev team0 up +ping -I team0 1.1.1.1 + +Move team_dev_type_check_change down where all other checks have passed +as it changes the dev type with no way to restore it in case +one of the checks that follow it fail. + +Also make sure to preserve the origial mtu assignment: + - If port_dev is not the same type as dev, dev takes mtu from port_dev + - If port_dev is the same type as dev, port_dev takes mtu from dev + +This is done by adding a conditional before the call to dev_set_mtu +to prevent it from assigning port_dev->mtu = dev->mtu and instead +letting team_dev_type_check_change assign dev->mtu = port_dev->mtu. +The conditional is needed because the patch moves the call to +team_dev_type_check_change past dev_set_mtu. + +Testing: + - team device driver in-tree selftests + - Add/remove various devices as slaves of team device + - syzbot + +Reported-by: syzbot+a2a3b519de727b0f7903@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=a2a3b519de727b0f7903 +Fixes: 1d76efe1577b ("team: add support for non-ethernet devices") +Signed-off-by: Nikola Z. Ivanov +Reviewed-by: Jiri Pirko +Link: https://patch.msgid.link/20251122002027.695151-1-zlatistiv@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/team/team_core.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c +index 6cfafaac1b4fb..94c40c5cebdd6 100644 +--- a/drivers/net/team/team_core.c ++++ b/drivers/net/team/team_core.c +@@ -1190,10 +1190,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + return -EPERM; + } + +- err = team_dev_type_check_change(dev, port_dev); +- if (err) +- return err; +- + if (port_dev->flags & IFF_UP) { + NL_SET_ERR_MSG(extack, "Device is up. Set it down before adding it as a team port"); + netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", +@@ -1211,10 +1207,16 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + INIT_LIST_HEAD(&port->qom_list); + + port->orig.mtu = port_dev->mtu; +- err = dev_set_mtu(port_dev, dev->mtu); +- if (err) { +- netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); +- goto err_set_mtu; ++ /* ++ * MTU assignment will be handled in team_dev_type_check_change ++ * if dev and port_dev are of different types ++ */ ++ if (dev->type == port_dev->type) { ++ err = dev_set_mtu(port_dev, dev->mtu); ++ if (err) { ++ netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); ++ goto err_set_mtu; ++ } + } + + memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); +@@ -1289,6 +1291,10 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + } + } + ++ err = team_dev_type_check_change(dev, port_dev); ++ if (err) ++ goto err_set_dev_type; ++ + if (dev->flags & IFF_UP) { + netif_addr_lock_bh(dev); + dev_uc_sync_multiple(port_dev, dev); +@@ -1307,6 +1313,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + + return 0; + ++err_set_dev_type: + err_set_slave_promisc: + __team_option_inst_del_port(team, port); + +-- +2.51.0 + diff --git a/queue-6.12/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch b/queue-6.12/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch new file mode 100644 index 0000000000..a22b7a9c2d --- /dev/null +++ b/queue-6.12/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch @@ -0,0 +1,45 @@ +From b74ff16217d90201f5d841083c794592d293b8e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:22:15 +0800 +Subject: usb: gadget: renesas_usbf: Handle devm_pm_runtime_enable() errors + +From: Haotian Zhang + +[ Upstream commit 74851fbb6d647304f8a7dc491434d3a335ef4b8d ] + +devm_pm_runtime_enable() can fail due to memory allocation. +The current code ignores its return value, potentially causing +pm_runtime_resume_and_get() to operate on uninitialized runtime +PM state. + +Check the return value of devm_pm_runtime_enable() and return on failure. + +Fixes: 3e6e14ffdea4 ("usb: gadget: udc: add Renesas RZ/N1 USBF controller support") +Signed-off-by: Haotian Zhang +Acked-by: Herve Codina +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20251124022215.1619-1-vulab@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/renesas_usbf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c +index 657f265ac7cc5..8463f681ae673 100644 +--- a/drivers/usb/gadget/udc/renesas_usbf.c ++++ b/drivers/usb/gadget/udc/renesas_usbf.c +@@ -3262,7 +3262,9 @@ static int usbf_probe(struct platform_device *pdev) + if (IS_ERR(udc->regs)) + return PTR_ERR(udc->regs); + +- devm_pm_runtime_enable(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); ++ if (ret) ++ return ret; + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; +-- +2.51.0 + diff --git a/queue-6.12/veth-apply-qdisc-backpressure-on-full-ptr_ring-to-re.patch b/queue-6.12/veth-apply-qdisc-backpressure-on-full-ptr_ring-to-re.patch new file mode 100644 index 0000000000..28789f07bb --- /dev/null +++ b/queue-6.12/veth-apply-qdisc-backpressure-on-full-ptr_ring-to-re.patch @@ -0,0 +1,175 @@ +From 679f02e5c3b8813daceb030ef0824c6de9163cb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 16:55:40 +0200 +Subject: veth: apply qdisc backpressure on full ptr_ring to reduce TX drops + +From: Jesper Dangaard Brouer + +[ Upstream commit dc82a33297fc2c58cb0b2b008d728668d45c0f6a ] + +In production, we're seeing TX drops on veth devices when the ptr_ring +fills up. This can occur when NAPI mode is enabled, though it's +relatively rare. However, with threaded NAPI - which we use in +production - the drops become significantly more frequent. + +The underlying issue is that with threaded NAPI, the consumer often runs +on a different CPU than the producer. This increases the likelihood of +the ring filling up before the consumer gets scheduled, especially under +load, leading to drops in veth_xmit() (ndo_start_xmit()). + +This patch introduces backpressure by returning NETDEV_TX_BUSY when the +ring is full, signaling the qdisc layer to requeue the packet. The txq +(netdev queue) is stopped in this condition and restarted once +veth_poll() drains entries from the ring, ensuring coordination between +NAPI and qdisc. + +Backpressure is only enabled when a qdisc is attached. Without a qdisc, +the driver retains its original behavior - dropping packets immediately +when the ring is full. This avoids unexpected behavior changes in setups +without a configured qdisc. + +With a qdisc in place (e.g. fq, sfq) this allows Active Queue Management +(AQM) to fairly schedule packets across flows and reduce collateral +damage from elephant flows. + +A known limitation of this approach is that the full ring sits in front +of the qdisc layer, effectively forming a FIFO buffer that introduces +base latency. While AQM still improves fairness and mitigates flow +dominance, the latency impact is measurable. + +In hardware drivers, this issue is typically addressed using BQL (Byte +Queue Limits), which tracks in-flight bytes needed based on physical link +rate. However, for virtual drivers like veth, there is no fixed bandwidth +constraint - the bottleneck is CPU availability and the scheduler's ability +to run the NAPI thread. It is unclear how effective BQL would be in this +context. + +This patch serves as a first step toward addressing TX drops. Future work +may explore adapting a BQL-like mechanism to better suit virtual devices +like veth. + +Reported-by: Yan Zhai +Signed-off-by: Jesper Dangaard Brouer +Reviewed-by: Toshiaki Makita +Link: https://patch.msgid.link/174559294022.827981.1282809941662942189.stgit@firesoul +Signed-off-by: Jakub Kicinski +Stable-dep-of: a14602fcae17 ("veth: reduce XDP no_direct return section to fix race") +Signed-off-by: Sasha Levin +--- + drivers/net/veth.c | 57 ++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 47 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 18148e068aa00..44903e2b0925e 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -306,12 +306,10 @@ static void __veth_xdp_flush(struct veth_rq *rq) + + static int veth_xdp_rx(struct veth_rq *rq, struct sk_buff *skb) + { +- if (unlikely(ptr_ring_produce(&rq->xdp_ring, skb))) { +- dev_kfree_skb_any(skb); +- return NET_RX_DROP; +- } ++ if (unlikely(ptr_ring_produce(&rq->xdp_ring, skb))) ++ return NETDEV_TX_BUSY; /* signal qdisc layer */ + +- return NET_RX_SUCCESS; ++ return NET_RX_SUCCESS; /* same as NETDEV_TX_OK */ + } + + static int veth_forward_skb(struct net_device *dev, struct sk_buff *skb, +@@ -345,11 +343,11 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct veth_priv *rcv_priv, *priv = netdev_priv(dev); + struct veth_rq *rq = NULL; +- int ret = NETDEV_TX_OK; ++ struct netdev_queue *txq; + struct net_device *rcv; + int length = skb->len; + bool use_napi = false; +- int rxq; ++ int ret, rxq; + + rcu_read_lock(); + rcv = rcu_dereference(priv->peer); +@@ -372,17 +370,45 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) + } + + skb_tx_timestamp(skb); +- if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) { ++ ++ ret = veth_forward_skb(rcv, skb, rq, use_napi); ++ switch (ret) { ++ case NET_RX_SUCCESS: /* same as NETDEV_TX_OK */ + if (!use_napi) + dev_sw_netstats_tx_add(dev, 1, length); + else + __veth_xdp_flush(rq); +- } else { ++ break; ++ case NETDEV_TX_BUSY: ++ /* If a qdisc is attached to our virtual device, returning ++ * NETDEV_TX_BUSY is allowed. ++ */ ++ txq = netdev_get_tx_queue(dev, rxq); ++ ++ if (qdisc_txq_has_no_queue(txq)) { ++ dev_kfree_skb_any(skb); ++ goto drop; ++ } ++ /* Restore Eth hdr pulled by dev_forward_skb/eth_type_trans */ ++ __skb_push(skb, ETH_HLEN); ++ /* Depend on prior success packets started NAPI consumer via ++ * __veth_xdp_flush(). Cancel TXQ stop if consumer stopped, ++ * paired with empty check in veth_poll(). ++ */ ++ netif_tx_stop_queue(txq); ++ smp_mb__after_atomic(); ++ if (unlikely(__ptr_ring_empty(&rq->xdp_ring))) ++ netif_tx_wake_queue(txq); ++ break; ++ case NET_RX_DROP: /* same as NET_XMIT_DROP */ + drop: + atomic64_inc(&priv->dropped); + ret = NET_XMIT_DROP; ++ break; ++ default: ++ net_crit_ratelimited("%s(%s): Invalid return code(%d)", ++ __func__, dev->name, ret); + } +- + rcu_read_unlock(); + + return ret; +@@ -874,9 +900,17 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + struct veth_xdp_tx_bq *bq, + struct veth_stats *stats) + { ++ struct veth_priv *priv = netdev_priv(rq->dev); ++ int queue_idx = rq->xdp_rxq.queue_index; ++ struct netdev_queue *peer_txq; ++ struct net_device *peer_dev; + int i, done = 0, n_xdpf = 0; + void *xdpf[VETH_XDP_BATCH]; + ++ /* NAPI functions as RCU section */ ++ peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); ++ peer_txq = netdev_get_tx_queue(peer_dev, queue_idx); ++ + for (i = 0; i < budget; i++) { + void *ptr = __ptr_ring_consume(&rq->xdp_ring); + +@@ -925,6 +959,9 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + rq->stats.vs.xdp_packets += done; + u64_stats_update_end(&rq->stats.syncp); + ++ if (unlikely(netif_tx_queue_stopped(peer_txq))) ++ netif_tx_wake_queue(peer_txq); ++ + return done; + } + +-- +2.51.0 + diff --git a/queue-6.12/veth-more-robust-handing-of-race-to-avoid-txq-gettin.patch b/queue-6.12/veth-more-robust-handing-of-race-to-avoid-txq-gettin.patch new file mode 100644 index 0000000000..2b7ec07c5b --- /dev/null +++ b/queue-6.12/veth-more-robust-handing-of-race-to-avoid-txq-gettin.patch @@ -0,0 +1,152 @@ +From 0e606f973813464604e164463f8566abf583c982 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Nov 2025 14:13:52 +0100 +Subject: veth: more robust handing of race to avoid txq getting stuck + +From: Jesper Dangaard Brouer + +[ Upstream commit 5442a9da69789741bfda39f34ee7f69552bf0c56 ] + +Commit dc82a33297fc ("veth: apply qdisc backpressure on full ptr_ring to +reduce TX drops") introduced a race condition that can lead to a permanently +stalled TXQ. This was observed in production on ARM64 systems (Ampere Altra +Max). + +The race occurs in veth_xmit(). The producer observes a full ptr_ring and +stops the queue (netif_tx_stop_queue()). The subsequent conditional logic, +intended to re-wake the queue if the consumer had just emptied it (if +(__ptr_ring_empty(...)) netif_tx_wake_queue()), can fail. This leads to a +"lost wakeup" where the TXQ remains stopped (QUEUE_STATE_DRV_XOFF) and +traffic halts. + +This failure is caused by an incorrect use of the __ptr_ring_empty() API +from the producer side. As noted in kernel comments, this check is not +guaranteed to be correct if a consumer is operating on another CPU. The +empty test is based on ptr_ring->consumer_head, making it reliable only for +the consumer. Using this check from the producer side is fundamentally racy. + +This patch fixes the race by adopting the more robust logic from an earlier +version V4 of the patchset, which always flushed the peer: + +(1) In veth_xmit(), the racy conditional wake-up logic and its memory barrier +are removed. Instead, after stopping the queue, we unconditionally call +__veth_xdp_flush(rq). This guarantees that the NAPI consumer is scheduled, +making it solely responsible for re-waking the TXQ. + This handles the race where veth_poll() consumes all packets and completes +NAPI *before* veth_xmit() on the producer side has called netif_tx_stop_queue. +The __veth_xdp_flush(rq) will observe rx_notify_masked is false and schedule +NAPI. + +(2) On the consumer side, the logic for waking the peer TXQ is moved out of +veth_xdp_rcv() and placed at the end of the veth_poll() function. This +placement is part of fixing the race, as the netif_tx_queue_stopped() check +must occur after rx_notify_masked is potentially set to false during NAPI +completion. + This handles the race where veth_poll() consumes all packets, but haven't +finished (rx_notify_masked is still true). The producer veth_xmit() stops the +TXQ and __veth_xdp_flush(rq) will observe rx_notify_masked is true, meaning +not starting NAPI. Then veth_poll() change rx_notify_masked to false and +stops NAPI. Before exiting veth_poll() will observe TXQ is stopped and wake +it up. + +Fixes: dc82a33297fc ("veth: apply qdisc backpressure on full ptr_ring to reduce TX drops") +Reviewed-by: Toshiaki Makita +Signed-off-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/176295323282.307447.14790015927673763094.stgit@firesoul +Signed-off-by: Jakub Kicinski +Stable-dep-of: a14602fcae17 ("veth: reduce XDP no_direct return section to fix race") +Signed-off-by: Sasha Levin +--- + drivers/net/veth.c | 38 ++++++++++++++++++++------------------ + 1 file changed, 20 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 25b43036cc08b..0f37e056b3dd7 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -391,14 +391,12 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) + } + /* Restore Eth hdr pulled by dev_forward_skb/eth_type_trans */ + __skb_push(skb, ETH_HLEN); +- /* Depend on prior success packets started NAPI consumer via +- * __veth_xdp_flush(). Cancel TXQ stop if consumer stopped, +- * paired with empty check in veth_poll(). +- */ + netif_tx_stop_queue(txq); +- smp_mb__after_atomic(); +- if (unlikely(__ptr_ring_empty(&rq->xdp_ring))) +- netif_tx_wake_queue(txq); ++ /* Makes sure NAPI peer consumer runs. Consumer is responsible ++ * for starting txq again, until then ndo_start_xmit (this ++ * function) will not be invoked by the netstack again. ++ */ ++ __veth_xdp_flush(rq); + break; + case NET_RX_DROP: /* same as NET_XMIT_DROP */ + drop: +@@ -900,17 +898,9 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + struct veth_xdp_tx_bq *bq, + struct veth_stats *stats) + { +- struct veth_priv *priv = netdev_priv(rq->dev); +- int queue_idx = rq->xdp_rxq.queue_index; +- struct netdev_queue *peer_txq; +- struct net_device *peer_dev; + int i, done = 0, n_xdpf = 0; + void *xdpf[VETH_XDP_BATCH]; + +- /* NAPI functions as RCU section */ +- peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); +- peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL; +- + for (i = 0; i < budget; i++) { + void *ptr = __ptr_ring_consume(&rq->xdp_ring); + +@@ -959,9 +949,6 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + rq->stats.vs.xdp_packets += done; + u64_stats_update_end(&rq->stats.syncp); + +- if (peer_txq && unlikely(netif_tx_queue_stopped(peer_txq))) +- netif_tx_wake_queue(peer_txq); +- + return done; + } + +@@ -969,12 +956,20 @@ static int veth_poll(struct napi_struct *napi, int budget) + { + struct veth_rq *rq = + container_of(napi, struct veth_rq, xdp_napi); ++ struct veth_priv *priv = netdev_priv(rq->dev); ++ int queue_idx = rq->xdp_rxq.queue_index; ++ struct netdev_queue *peer_txq; + struct veth_stats stats = {}; ++ struct net_device *peer_dev; + struct veth_xdp_tx_bq bq; + int done; + + bq.count = 0; + ++ /* NAPI functions as RCU section */ ++ peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); ++ peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL; ++ + xdp_set_return_frame_no_direct(); + done = veth_xdp_rcv(rq, budget, &bq, &stats); + +@@ -996,6 +991,13 @@ static int veth_poll(struct napi_struct *napi, int budget) + veth_xdp_flush(rq, &bq); + xdp_clear_return_frame_no_direct(); + ++ /* Release backpressure per NAPI poll */ ++ smp_rmb(); /* Paired with netif_tx_stop_queue set_bit */ ++ if (peer_txq && netif_tx_queue_stopped(peer_txq)) { ++ txq_trans_cond_update(peer_txq); ++ netif_tx_wake_queue(peer_txq); ++ } ++ + return done; + } + +-- +2.51.0 + diff --git a/queue-6.12/veth-prevent-null-pointer-dereference-in-veth_xdp_rc.patch b/queue-6.12/veth-prevent-null-pointer-dereference-in-veth_xdp_rc.patch new file mode 100644 index 0000000000..033abc0c17 --- /dev/null +++ b/queue-6.12/veth-prevent-null-pointer-dereference-in-veth_xdp_rc.patch @@ -0,0 +1,61 @@ +From 0dbd072a3e139b6a818d01c693a0062eff92d65b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 14:40:04 +0200 +Subject: veth: prevent NULL pointer dereference in veth_xdp_rcv + +From: Jesper Dangaard Brouer + +[ Upstream commit 9337c54401a5bb6ac3c9f6c71dd2a9130cfba82e ] + +The veth peer device is RCU protected, but when the peer device gets +deleted (veth_dellink) then the pointer is assigned NULL (via +RCU_INIT_POINTER). + +This patch adds a necessary NULL check in veth_xdp_rcv when accessing +the veth peer net_device. + +This fixes a bug introduced in commit dc82a33297fc ("veth: apply qdisc +backpressure on full ptr_ring to reduce TX drops"). The bug is a race +and only triggers when having inflight packets on a veth that is being +deleted. + +Reported-by: Ihor Solodrai +Closes: https://lore.kernel.org/all/fecfcad0-7a16-42b8-bff2-66ee83a6e5c4@linux.dev/ +Reported-by: syzbot+c4c7bf27f6b0c4bd97fe@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/683da55e.a00a0220.d8eae.0052.GAE@google.com/ +Fixes: dc82a33297fc ("veth: apply qdisc backpressure on full ptr_ring to reduce TX drops") +Signed-off-by: Jesper Dangaard Brouer +Acked-by: Ihor Solodrai +Link: https://patch.msgid.link/174964557873.519608.10855046105237280978.stgit@firesoul +Signed-off-by: Jakub Kicinski +Stable-dep-of: a14602fcae17 ("veth: reduce XDP no_direct return section to fix race") +Signed-off-by: Sasha Levin +--- + drivers/net/veth.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 44903e2b0925e..25b43036cc08b 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -909,7 +909,7 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + + /* NAPI functions as RCU section */ + peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); +- peer_txq = netdev_get_tx_queue(peer_dev, queue_idx); ++ peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL; + + for (i = 0; i < budget; i++) { + void *ptr = __ptr_ring_consume(&rq->xdp_ring); +@@ -959,7 +959,7 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, + rq->stats.vs.xdp_packets += done; + u64_stats_update_end(&rq->stats.syncp); + +- if (unlikely(netif_tx_queue_stopped(peer_txq))) ++ if (peer_txq && unlikely(netif_tx_queue_stopped(peer_txq))) + netif_tx_wake_queue(peer_txq); + + return done; +-- +2.51.0 + diff --git a/queue-6.12/veth-reduce-xdp-no_direct-return-section-to-fix-race.patch b/queue-6.12/veth-reduce-xdp-no_direct-return-section-to-fix-race.patch new file mode 100644 index 0000000000..a1de255904 --- /dev/null +++ b/queue-6.12/veth-reduce-xdp-no_direct-return-section-to-fix-race.patch @@ -0,0 +1,70 @@ +From 3d2864111cf8d7f7f0127896ce2ca4bebe23408b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Nov 2025 17:28:36 +0100 +Subject: veth: reduce XDP no_direct return section to fix race + +From: Jesper Dangaard Brouer + +[ Upstream commit a14602fcae17a3f1cb8a8521bedf31728f9e7e39 ] + +As explain in commit fa349e396e48 ("veth: Fix race with AF_XDP exposing +old or uninitialized descriptors") for veth there is a chance after +napi_complete_done() that another CPU can manage start another NAPI +instance running veth_pool(). For NAPI this is correctly handled as the +napi_schedule_prep() check will prevent multiple instances from getting +scheduled, but for the remaining code in veth_pool() this can run +concurrent with the newly started NAPI instance. + +The problem/race is that xdp_clear_return_frame_no_direct() isn't +designed to be nested. + +Prior to commit 401cb7dae813 ("net: Reference bpf_redirect_info via +task_struct on PREEMPT_RT.") the temporary BPF net context +bpf_redirect_info was stored per CPU, where this wasn't an issue. Since +this commit the BPF context is stored in 'current' task_struct. When +running veth in threaded-NAPI mode, then the kthread becomes the storage +area. Now a race exists between two concurrent veth_pool() function calls +one exiting NAPI and one running new NAPI, both using the same BPF net +context. + +Race is when another CPU gets within the xdp_set_return_frame_no_direct() +section before exiting veth_pool() calls the clear-function +xdp_clear_return_frame_no_direct(). + +Fixes: 401cb7dae8130 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.") +Signed-off-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/176356963888.337072.4805242001928705046.stgit@firesoul +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/veth.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 0f37e056b3dd7..4ff0d4232914f 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -975,6 +975,9 @@ static int veth_poll(struct napi_struct *napi, int budget) + + if (stats.xdp_redirect > 0) + xdp_do_flush(); ++ if (stats.xdp_tx > 0) ++ veth_xdp_flush(rq, &bq); ++ xdp_clear_return_frame_no_direct(); + + if (done < budget && napi_complete_done(napi, done)) { + /* Write rx_notify_masked before reading ptr_ring */ +@@ -987,10 +990,6 @@ static int veth_poll(struct napi_struct *napi, int budget) + } + } + +- if (stats.xdp_tx > 0) +- veth_xdp_flush(rq, &bq); +- xdp_clear_return_frame_no_direct(); +- + /* Release backpressure per NAPI poll */ + smp_rmb(); /* Paired with netif_tx_stop_queue set_bit */ + if (peer_txq && netif_tx_queue_stopped(peer_txq)) { +-- +2.51.0 + diff --git a/queue-6.17/afs-fix-delayed-allocation-of-a-cell-s-anonymous-key.patch b/queue-6.17/afs-fix-delayed-allocation-of-a-cell-s-anonymous-key.patch new file mode 100644 index 0000000000..2cd87cefe2 --- /dev/null +++ b/queue-6.17/afs-fix-delayed-allocation-of-a-cell-s-anonymous-key.patch @@ -0,0 +1,242 @@ +From cd9b0077a8fd60294951b9a8c1f846aa1e892b67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 10:19:05 +0000 +Subject: afs: Fix delayed allocation of a cell's anonymous key + +From: David Howells + +[ Upstream commit d27c71257825dced46104eefe42e4d9964bd032e ] + +The allocation of a cell's anonymous key is done in a background thread +along with other cell setup such as doing a DNS upcall. In the reported +bug, this is triggered by afs_parse_source() parsing the device name given +to mount() and calling afs_lookup_cell() with the name of the cell. + +The normal key lookup then tries to use the key description on the +anonymous authentication key as the reference for request_key() - but it +may not yet be set and so an oops can happen. + +This has been made more likely to happen by the fix for dynamic lookup +failure. + +Fix this by firstly allocating a reference name and attaching it to the +afs_cell record when the record is created. It can share the memory +allocation with the cell name (unfortunately it can't just overlap the cell +name by prepending it with "afs@" as the cell name already has a '.' +prepended for other purposes). This reference name is then passed to +request_key(). + +Secondly, the anon key is now allocated on demand at the point a key is +requested in afs_request_key() if it is not already allocated. A mutex is +used to prevent multiple allocation for a cell. + +Thirdly, make afs_request_key_rcu() return NULL if the anonymous key isn't +yet allocated (if we need it) and then the caller can return -ECHILD to +drop out of RCU-mode and afs_request_key() can be called. + +Note that the anonymous key is kind of necessary to make the key lookup +cache work as that doesn't currently cache a negative lookup, but it's +probably worth some investigation to see if NULL can be used instead. + +Fixes: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure") +Reported-by: syzbot+41c68824eefb67cdf00c@syzkaller.appspotmail.com +Signed-off-by: David Howells +Link: https://patch.msgid.link/800328.1764325145@warthog.procyon.org.uk +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +cc: linux-fsdevel@vger.kernel.org +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/afs/cell.c | 43 ++++++++---------------------------------- + fs/afs/internal.h | 1 + + fs/afs/security.c | 48 +++++++++++++++++++++++++++++++++++++++-------- + 3 files changed, 49 insertions(+), 43 deletions(-) + +diff --git a/fs/afs/cell.c b/fs/afs/cell.c +index d9b6fa1088b7b..71c10a05cebe5 100644 +--- a/fs/afs/cell.c ++++ b/fs/afs/cell.c +@@ -140,7 +140,9 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, + return ERR_PTR(-ENOMEM); + } + +- cell->name = kmalloc(1 + namelen + 1, GFP_KERNEL); ++ /* Allocate the cell name and the key name in one go. */ ++ cell->name = kmalloc(1 + namelen + 1 + ++ 4 + namelen + 1, GFP_KERNEL); + if (!cell->name) { + kfree(cell); + return ERR_PTR(-ENOMEM); +@@ -151,7 +153,11 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, + cell->name_len = namelen; + for (i = 0; i < namelen; i++) + cell->name[i] = tolower(name[i]); +- cell->name[i] = 0; ++ cell->name[i++] = 0; ++ ++ cell->key_desc = cell->name + i; ++ memcpy(cell->key_desc, "afs@", 4); ++ memcpy(cell->key_desc + 4, cell->name, cell->name_len + 1); + + cell->net = net; + refcount_set(&cell->ref, 1); +@@ -710,33 +716,6 @@ void afs_set_cell_timer(struct afs_cell *cell, unsigned int delay_secs) + timer_reduce(&cell->management_timer, jiffies + delay_secs * HZ); + } + +-/* +- * Allocate a key to use as a placeholder for anonymous user security. +- */ +-static int afs_alloc_anon_key(struct afs_cell *cell) +-{ +- struct key *key; +- char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp; +- +- /* Create a key to represent an anonymous user. */ +- memcpy(keyname, "afs@", 4); +- dp = keyname + 4; +- cp = cell->name; +- do { +- *dp++ = tolower(*cp); +- } while (*cp++); +- +- key = rxrpc_get_null_key(keyname); +- if (IS_ERR(key)) +- return PTR_ERR(key); +- +- cell->anonymous_key = key; +- +- _debug("anon key %p{%x}", +- cell->anonymous_key, key_serial(cell->anonymous_key)); +- return 0; +-} +- + /* + * Activate a cell. + */ +@@ -746,12 +725,6 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) + struct afs_cell *pcell; + int ret; + +- if (!cell->anonymous_key) { +- ret = afs_alloc_anon_key(cell); +- if (ret < 0) +- return ret; +- } +- + ret = afs_proc_cell_setup(cell); + if (ret < 0) + return ret; +diff --git a/fs/afs/internal.h b/fs/afs/internal.h +index 87828d685293f..470e6eef8bd49 100644 +--- a/fs/afs/internal.h ++++ b/fs/afs/internal.h +@@ -413,6 +413,7 @@ struct afs_cell { + + u8 name_len; /* Length of name */ + char *name; /* Cell name, case-flattened and NUL-padded */ ++ char *key_desc; /* Authentication key description */ + }; + + /* +diff --git a/fs/afs/security.c b/fs/afs/security.c +index 6a7744c9e2a2d..ff8830e6982fb 100644 +--- a/fs/afs/security.c ++++ b/fs/afs/security.c +@@ -16,6 +16,30 @@ + + static DEFINE_HASHTABLE(afs_permits_cache, 10); + static DEFINE_SPINLOCK(afs_permits_lock); ++static DEFINE_MUTEX(afs_key_lock); ++ ++/* ++ * Allocate a key to use as a placeholder for anonymous user security. ++ */ ++static int afs_alloc_anon_key(struct afs_cell *cell) ++{ ++ struct key *key; ++ ++ mutex_lock(&afs_key_lock); ++ if (!cell->anonymous_key) { ++ key = rxrpc_get_null_key(cell->key_desc); ++ if (!IS_ERR(key)) ++ cell->anonymous_key = key; ++ } ++ mutex_unlock(&afs_key_lock); ++ ++ if (IS_ERR(key)) ++ return PTR_ERR(key); ++ ++ _debug("anon key %p{%x}", ++ cell->anonymous_key, key_serial(cell->anonymous_key)); ++ return 0; ++} + + /* + * get a key +@@ -23,11 +47,12 @@ static DEFINE_SPINLOCK(afs_permits_lock); + struct key *afs_request_key(struct afs_cell *cell) + { + struct key *key; ++ int ret; + +- _enter("{%x}", key_serial(cell->anonymous_key)); ++ _enter("{%s}", cell->key_desc); + +- _debug("key %s", cell->anonymous_key->description); +- key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description, ++ _debug("key %s", cell->key_desc); ++ key = request_key_net(&key_type_rxrpc, cell->key_desc, + cell->net->net, NULL); + if (IS_ERR(key)) { + if (PTR_ERR(key) != -ENOKEY) { +@@ -35,6 +60,12 @@ struct key *afs_request_key(struct afs_cell *cell) + return key; + } + ++ if (!cell->anonymous_key) { ++ ret = afs_alloc_anon_key(cell); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ } ++ + /* act as anonymous user */ + _leave(" = {%x} [anon]", key_serial(cell->anonymous_key)); + return key_get(cell->anonymous_key); +@@ -52,11 +83,10 @@ struct key *afs_request_key_rcu(struct afs_cell *cell) + { + struct key *key; + +- _enter("{%x}", key_serial(cell->anonymous_key)); ++ _enter("{%s}", cell->key_desc); + +- _debug("key %s", cell->anonymous_key->description); +- key = request_key_net_rcu(&key_type_rxrpc, +- cell->anonymous_key->description, ++ _debug("key %s", cell->key_desc); ++ key = request_key_net_rcu(&key_type_rxrpc, cell->key_desc, + cell->net->net); + if (IS_ERR(key)) { + if (PTR_ERR(key) != -ENOKEY) { +@@ -65,6 +95,8 @@ struct key *afs_request_key_rcu(struct afs_cell *cell) + } + + /* act as anonymous user */ ++ if (!cell->anonymous_key) ++ return NULL; /* Need to allocate */ + _leave(" = {%x} [anon]", key_serial(cell->anonymous_key)); + return key_get(cell->anonymous_key); + } else { +@@ -408,7 +440,7 @@ int afs_permission(struct mnt_idmap *idmap, struct inode *inode, + + if (mask & MAY_NOT_BLOCK) { + key = afs_request_key_rcu(vnode->volume->cell); +- if (IS_ERR(key)) ++ if (IS_ERR_OR_NULL(key)) + return -ECHILD; + + ret = -ECHILD; +-- +2.51.0 + diff --git a/queue-6.17/afs-fix-uninit-var-in-afs_alloc_anon_key.patch b/queue-6.17/afs-fix-uninit-var-in-afs_alloc_anon_key.patch new file mode 100644 index 0000000000..783c1c3a3d --- /dev/null +++ b/queue-6.17/afs-fix-uninit-var-in-afs_alloc_anon_key.patch @@ -0,0 +1,50 @@ +From 8b819d95114ef5f39787f9dd8822141c0d2a426d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Nov 2025 00:40:11 +0000 +Subject: afs: Fix uninit var in afs_alloc_anon_key() + +From: David Howells + +[ Upstream commit 19eef1d98eeda3745df35839190b7d4a4adea656 ] + +Fix an uninitialised variable (key) in afs_alloc_anon_key() by setting it +to cell->anonymous_key. Without this change, the error check may return a +false failure with a bad error number. + +Most of the time this is unlikely to happen because the first encounter +with afs_alloc_anon_key() will usually be from (auto)mount, for which all +subsequent operations must wait - apart from other (auto)mounts. Once the +call->anonymous_key is allocated, all further calls to afs_request_key() +will skip the call to afs_alloc_anon_key() for that cell. + +Fixes: d27c71257825 ("afs: Fix delayed allocation of a cell's anonymous key") +Reported-by: Paulo Alcantra +Signed-off-by: David Howells +Reviewed-by: Paulo Alcantara +cc: Marc Dionne +cc: syzbot+41c68824eefb67cdf00c@syzkaller.appspotmail.com +cc: linux-afs@lists.infradead.org +cc: linux-fsdevel@vger.kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/afs/security.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/afs/security.c b/fs/afs/security.c +index ff8830e6982fb..55ddce94af031 100644 +--- a/fs/afs/security.c ++++ b/fs/afs/security.c +@@ -26,7 +26,8 @@ static int afs_alloc_anon_key(struct afs_cell *cell) + struct key *key; + + mutex_lock(&afs_key_lock); +- if (!cell->anonymous_key) { ++ key = cell->anonymous_key; ++ if (!key) { + key = rxrpc_get_null_key(cell->key_desc); + if (!IS_ERR(key)) + cell->anonymous_key = key; +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch b/queue-6.17/bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch new file mode 100644 index 0000000000..d136f2744c --- /dev/null +++ b/queue-6.17/bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch @@ -0,0 +1,132 @@ +From 720403fe3ad2eefe049efbbc546795cc0edde709 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Nov 2025 15:53:34 +0800 +Subject: Bluetooth: btusb: mediatek: Fix kernel crash when releasing mtk iso + interface + +From: Chris Lu + +[ Upstream commit 4015b979767125cf8a2233a145a3b3af78bfd8fb ] + +When performing reset tests and encountering abnormal card drop issues +that lead to a kernel crash, it is necessary to perform a null check +before releasing resources to avoid attempting to release a null pointer. + +<4>[ 29.158070] Hardware name: Google Quigon sku196612/196613 board (DT) +<4>[ 29.158076] Workqueue: hci0 hci_cmd_sync_work [bluetooth] +<4>[ 29.158154] pstate: 20400009 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +<4>[ 29.158162] pc : klist_remove+0x90/0x158 +<4>[ 29.158174] lr : klist_remove+0x88/0x158 +<4>[ 29.158180] sp : ffffffc0846b3c00 +<4>[ 29.158185] pmr_save: 000000e0 +<4>[ 29.158188] x29: ffffffc0846b3c30 x28: ffffff80cd31f880 x27: ffffff80c1bdc058 +<4>[ 29.158199] x26: dead000000000100 x25: ffffffdbdc624ea3 x24: ffffff80c1bdc4c0 +<4>[ 29.158209] x23: ffffffdbdc62a3e6 x22: ffffff80c6c07000 x21: ffffffdbdc829290 +<4>[ 29.158219] x20: 0000000000000000 x19: ffffff80cd3e0648 x18: 000000031ec97781 +<4>[ 29.158229] x17: ffffff80c1bdc4a8 x16: ffffffdc10576548 x15: ffffff80c1180428 +<4>[ 29.158238] x14: 0000000000000000 x13: 000000000000e380 x12: 0000000000000018 +<4>[ 29.158248] x11: ffffff80c2a7fd10 x10: 0000000000000000 x9 : 0000000100000000 +<4>[ 29.158257] x8 : 0000000000000000 x7 : 7f7f7f7f7f7f7f7f x6 : 2d7223ff6364626d +<4>[ 29.158266] x5 : 0000008000000000 x4 : 0000000000000020 x3 : 2e7325006465636e +<4>[ 29.158275] x2 : ffffffdc11afeff8 x1 : 0000000000000000 x0 : ffffffdc11be4d0c +<4>[ 29.158285] Call trace: +<4>[ 29.158290] klist_remove+0x90/0x158 +<4>[ 29.158298] device_release_driver_internal+0x20c/0x268 +<4>[ 29.158308] device_release_driver+0x1c/0x30 +<4>[ 29.158316] usb_driver_release_interface+0x70/0x88 +<4>[ 29.158325] btusb_mtk_release_iso_intf+0x68/0xd8 [btusb (HASH:e8b6 5)] +<4>[ 29.158347] btusb_mtk_reset+0x5c/0x480 [btusb (HASH:e8b6 5)] +<4>[ 29.158361] hci_cmd_sync_work+0x10c/0x188 [bluetooth (HASH:a4fa 6)] +<4>[ 29.158430] process_scheduled_works+0x258/0x4e8 +<4>[ 29.158441] worker_thread+0x300/0x428 +<4>[ 29.158448] kthread+0x108/0x1d0 +<4>[ 29.158455] ret_from_fork+0x10/0x20 +<0>[ 29.158467] Code: 91343000 940139d1 f9400268 927ff914 (f9401297) +<4>[ 29.158474] ---[ end trace 0000000000000000 ]--- +<0>[ 29.167129] Kernel panic - not syncing: Oops: Fatal exception +<2>[ 29.167144] SMP: stopping secondary CPUs +<4>[ 29.167158] ------------[ cut here ]------------ + +Fixes: ceac1cb0259d ("Bluetooth: btusb: mediatek: add ISO data transmission functions") +Signed-off-by: Chris Lu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 34 +++++++++++++++++++++++++------- + include/net/bluetooth/hci_core.h | 1 - + 2 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a722446ec73dd..202a845e0236f 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2711,9 +2711,16 @@ static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + + static void btusb_mtk_claim_iso_intf(struct btusb_data *data) + { +- struct btmtk_data *btmtk_data = hci_get_priv(data->hdev); ++ struct btmtk_data *btmtk_data; + int err; + ++ if (!data->hdev) ++ return; ++ ++ btmtk_data = hci_get_priv(data->hdev); ++ if (!btmtk_data) ++ return; ++ + /* + * The function usb_driver_claim_interface() is documented to need + * locks held if it's not called from a probe routine. The code here +@@ -2735,17 +2742,30 @@ static void btusb_mtk_claim_iso_intf(struct btusb_data *data) + + static void btusb_mtk_release_iso_intf(struct hci_dev *hdev) + { +- struct btmtk_data *btmtk_data = hci_get_priv(hdev); ++ struct btmtk_data *btmtk_data; ++ ++ if (!hdev) ++ return; ++ ++ btmtk_data = hci_get_priv(hdev); ++ if (!btmtk_data) ++ return; + + if (test_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags)) { + usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor); + clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags); + +- dev_kfree_skb_irq(btmtk_data->isopkt_skb); +- btmtk_data->isopkt_skb = NULL; +- usb_set_intfdata(btmtk_data->isopkt_intf, NULL); +- usb_driver_release_interface(&btusb_driver, +- btmtk_data->isopkt_intf); ++ if (btmtk_data->isopkt_skb) { ++ dev_kfree_skb_irq(btmtk_data->isopkt_skb); ++ btmtk_data->isopkt_skb = NULL; ++ } ++ ++ if (btmtk_data->isopkt_intf) { ++ usb_set_intfdata(btmtk_data->isopkt_intf, NULL); ++ usb_driver_release_interface(&btusb_driver, ++ btmtk_data->isopkt_intf); ++ btmtk_data->isopkt_intf = NULL; ++ } + } + + clear_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags); +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 8d78cb2b9f1ab..4ccb462a0a4b8 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -748,7 +748,6 @@ struct hci_conn { + + __u8 remote_cap; + __u8 remote_auth; +- __u8 remote_id; + + unsigned int sent; + +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch b/queue-6.17/bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch new file mode 100644 index 0000000000..2ddef62b64 --- /dev/null +++ b/queue-6.17/bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch @@ -0,0 +1,85 @@ +From 183129f38bfb3671a983e5d649a1790a940407cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Nov 2025 09:49:27 -0500 +Subject: Bluetooth: hci_core: Fix triggering cmd_timer for HCI_OP_NOP + +From: Luiz Augusto von Dentz + +[ Upstream commit 275ddfeb3fdc274050c2173ffd985b1e80a9aa37 ] + +HCI_OP_NOP means no command was actually sent so there is no point in +triggering cmd_timer which may cause a hdev->reset in the process since +it is assumed that the controller is stuck processing a command. + +Fixes: e2d471b7806b ("Bluetooth: ISO: Fix not using SID from adv report") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_core.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 55e0722fd0662..72c7607aac209 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -4093,7 +4093,7 @@ static void hci_rx_work(struct work_struct *work) + } + } + +-static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) ++static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) + { + int err; + +@@ -4105,16 +4105,19 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) + if (!hdev->sent_cmd) { + skb_queue_head(&hdev->cmd_q, skb); + queue_work(hdev->workqueue, &hdev->cmd_work); +- return; ++ return -EINVAL; + } + + if (hci_skb_opcode(skb) != HCI_OP_NOP) { + err = hci_send_frame(hdev, skb); + if (err < 0) { + hci_cmd_sync_cancel_sync(hdev, -err); +- return; ++ return err; + } + atomic_dec(&hdev->cmd_cnt); ++ } else { ++ err = -ENODATA; ++ kfree_skb(skb); + } + + if (hdev->req_status == HCI_REQ_PEND && +@@ -4122,12 +4125,15 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) + kfree_skb(hdev->req_skb); + hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL); + } ++ ++ return err; + } + + static void hci_cmd_work(struct work_struct *work) + { + struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work); + struct sk_buff *skb; ++ int err; + + BT_DBG("%s cmd_cnt %d cmd queued %d", hdev->name, + atomic_read(&hdev->cmd_cnt), skb_queue_len(&hdev->cmd_q)); +@@ -4138,7 +4144,9 @@ static void hci_cmd_work(struct work_struct *work) + if (!skb) + return; + +- hci_send_cmd_sync(hdev, skb); ++ err = hci_send_cmd_sync(hdev, skb); ++ if (err) ++ return; + + rcu_read_lock(); + if (test_bit(HCI_RESET, &hdev->flags) || +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-hci_core-lookup-hci_conn-on-rx-path-on-pro.patch b/queue-6.17/bluetooth-hci_core-lookup-hci_conn-on-rx-path-on-pro.patch new file mode 100644 index 0000000000..6b39f962f0 --- /dev/null +++ b/queue-6.17/bluetooth-hci_core-lookup-hci_conn-on-rx-path-on-pro.patch @@ -0,0 +1,417 @@ +From 16486fe11c98ab223348a2dc1429a5a6b87bb51e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Nov 2025 18:43:55 +0200 +Subject: Bluetooth: hci_core: lookup hci_conn on RX path on protocol side + +From: Pauli Virtanen + +[ Upstream commit 79a2d4678ba90bdba577dc3af88cc900d6dcd5ee ] + +The hdev lock/lookup/unlock/use pattern in the packet RX path doesn't +ensure hci_conn* is not concurrently modified/deleted. This locking +appears to be leftover from before conn_hash started using RCU +commit bf4c63252490b ("Bluetooth: convert conn hash to RCU") +and not clear if it had purpose since then. + +Currently, there are code paths that delete hci_conn* from elsewhere +than the ordered hdev->workqueue where the RX work runs in. E.g. +commit 5af1f84ed13a ("Bluetooth: hci_sync: Fix UAF on hci_abort_conn_sync") +introduced some of these, and there probably were a few others before +it. It's better to do the locking so that even if these run +concurrently no UAF is possible. + +Move the lookup of hci_conn and associated socket-specific conn to +protocol recv handlers, and do them within a single critical section +to cover hci_conn* usage and lookup. + +syzkaller has reported a crash that appears to be this issue: + + [Task hdev->workqueue] [Task 2] + hci_disconnect_all_sync + l2cap_recv_acldata(hcon) + hci_conn_get(hcon) + hci_abort_conn_sync(hcon) + hci_dev_lock + hci_dev_lock + hci_conn_del(hcon) + v-------------------------------- hci_dev_unlock + hci_conn_put(hcon) + conn = hcon->l2cap_data (UAF) + +Fixes: 5af1f84ed13a ("Bluetooth: hci_sync: Fix UAF on hci_abort_conn_sync") +Reported-by: syzbot+d32d77220b92eddd89ad@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=d32d77220b92eddd89ad +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_core.h | 20 ++++++--- + net/bluetooth/hci_core.c | 73 +++++++++++--------------------- + net/bluetooth/iso.c | 30 ++++++++++--- + net/bluetooth/l2cap_core.c | 23 +++++++--- + net/bluetooth/sco.c | 35 +++++++++++---- + 5 files changed, 108 insertions(+), 73 deletions(-) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 4ccb462a0a4b8..b020ce30929e6 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -855,11 +855,12 @@ extern struct mutex hci_cb_list_lock; + /* ----- HCI interface to upper protocols ----- */ + int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); + int l2cap_disconn_ind(struct hci_conn *hcon); +-void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); ++int l2cap_recv_acldata(struct hci_dev *hdev, u16 handle, struct sk_buff *skb, ++ u16 flags); + + #if IS_ENABLED(CONFIG_BT_BREDR) + int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); +-void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); ++int sco_recv_scodata(struct hci_dev *hdev, u16 handle, struct sk_buff *skb); + #else + static inline int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, + __u8 *flags) +@@ -867,23 +868,30 @@ static inline int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, + return 0; + } + +-static inline void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) ++static inline int sco_recv_scodata(struct hci_dev *hdev, u16 handle, ++ struct sk_buff *skb) + { ++ kfree_skb(skb); ++ return -ENOENT; + } + #endif + + #if IS_ENABLED(CONFIG_BT_LE) + int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); +-void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); ++int iso_recv(struct hci_dev *hdev, u16 handle, struct sk_buff *skb, ++ u16 flags); + #else + static inline int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, + __u8 *flags) + { + return 0; + } +-static inline void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, +- u16 flags) ++ ++static inline int iso_recv(struct hci_dev *hdev, u16 handle, ++ struct sk_buff *skb, u16 flags) + { ++ kfree_skb(skb); ++ return -ENOENT; + } + #endif + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 72c7607aac209..057ec1a5230d9 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -3804,13 +3804,14 @@ static void hci_tx_work(struct work_struct *work) + static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) + { + struct hci_acl_hdr *hdr; +- struct hci_conn *conn; + __u16 handle, flags; ++ int err; + + hdr = skb_pull_data(skb, sizeof(*hdr)); + if (!hdr) { + bt_dev_err(hdev, "ACL packet too small"); +- goto drop; ++ kfree_skb(skb); ++ return; + } + + handle = __le16_to_cpu(hdr->handle); +@@ -3822,36 +3823,27 @@ static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) + + hdev->stat.acl_rx++; + +- hci_dev_lock(hdev); +- conn = hci_conn_hash_lookup_handle(hdev, handle); +- hci_dev_unlock(hdev); +- +- if (conn) { +- hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); +- +- /* Send to upper protocol */ +- l2cap_recv_acldata(conn, skb, flags); +- return; +- } else { ++ err = l2cap_recv_acldata(hdev, handle, skb, flags); ++ if (err == -ENOENT) + bt_dev_err(hdev, "ACL packet for unknown connection handle %d", + handle); +- } +- +-drop: +- kfree_skb(skb); ++ else if (err) ++ bt_dev_dbg(hdev, "ACL packet recv for handle %d failed: %d", ++ handle, err); + } + + /* SCO data packet */ + static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) + { + struct hci_sco_hdr *hdr; +- struct hci_conn *conn; + __u16 handle, flags; ++ int err; + + hdr = skb_pull_data(skb, sizeof(*hdr)); + if (!hdr) { + bt_dev_err(hdev, "SCO packet too small"); +- goto drop; ++ kfree_skb(skb); ++ return; + } + + handle = __le16_to_cpu(hdr->handle); +@@ -3863,34 +3855,28 @@ static void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) + + hdev->stat.sco_rx++; + +- hci_dev_lock(hdev); +- conn = hci_conn_hash_lookup_handle(hdev, handle); +- hci_dev_unlock(hdev); ++ hci_skb_pkt_status(skb) = flags & 0x03; + +- if (conn) { +- /* Send to upper protocol */ +- hci_skb_pkt_status(skb) = flags & 0x03; +- sco_recv_scodata(conn, skb); +- return; +- } else { ++ err = sco_recv_scodata(hdev, handle, skb); ++ if (err == -ENOENT) + bt_dev_err_ratelimited(hdev, "SCO packet for unknown connection handle %d", + handle); +- } +- +-drop: +- kfree_skb(skb); ++ else if (err) ++ bt_dev_dbg(hdev, "SCO packet recv for handle %d failed: %d", ++ handle, err); + } + + static void hci_isodata_packet(struct hci_dev *hdev, struct sk_buff *skb) + { + struct hci_iso_hdr *hdr; +- struct hci_conn *conn; + __u16 handle, flags; ++ int err; + + hdr = skb_pull_data(skb, sizeof(*hdr)); + if (!hdr) { + bt_dev_err(hdev, "ISO packet too small"); +- goto drop; ++ kfree_skb(skb); ++ return; + } + + handle = __le16_to_cpu(hdr->handle); +@@ -3900,22 +3886,13 @@ static void hci_isodata_packet(struct hci_dev *hdev, struct sk_buff *skb) + bt_dev_dbg(hdev, "len %d handle 0x%4.4x flags 0x%4.4x", skb->len, + handle, flags); + +- hci_dev_lock(hdev); +- conn = hci_conn_hash_lookup_handle(hdev, handle); +- hci_dev_unlock(hdev); +- +- if (!conn) { ++ err = iso_recv(hdev, handle, skb, flags); ++ if (err == -ENOENT) + bt_dev_err(hdev, "ISO packet for unknown connection handle %d", + handle); +- goto drop; +- } +- +- /* Send to upper protocol */ +- iso_recv(conn, skb, flags); +- return; +- +-drop: +- kfree_skb(skb); ++ else if (err) ++ bt_dev_dbg(hdev, "ISO packet recv for handle %d failed: %d", ++ handle, err); + } + + static bool hci_req_is_complete(struct hci_dev *hdev) +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 3d98cb6291da6..616c2fef91d24 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -2314,14 +2314,31 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason) + iso_conn_del(hcon, bt_to_errno(reason)); + } + +-void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) ++int iso_recv(struct hci_dev *hdev, u16 handle, struct sk_buff *skb, u16 flags) + { +- struct iso_conn *conn = hcon->iso_data; ++ struct hci_conn *hcon; ++ struct iso_conn *conn; + struct skb_shared_hwtstamps *hwts; + __u16 pb, ts, len, sn; + +- if (!conn) +- goto drop; ++ hci_dev_lock(hdev); ++ ++ hcon = hci_conn_hash_lookup_handle(hdev, handle); ++ if (!hcon) { ++ hci_dev_unlock(hdev); ++ kfree_skb(skb); ++ return -ENOENT; ++ } ++ ++ conn = iso_conn_hold_unless_zero(hcon->iso_data); ++ hcon = NULL; ++ ++ hci_dev_unlock(hdev); ++ ++ if (!conn) { ++ kfree_skb(skb); ++ return -EINVAL; ++ } + + pb = hci_iso_flags_pb(flags); + ts = hci_iso_flags_ts(flags); +@@ -2377,7 +2394,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + hci_skb_pkt_status(skb) = flags & 0x03; + hci_skb_pkt_seqnum(skb) = sn; + iso_recv_frame(conn, skb); +- return; ++ goto done; + } + + if (pb == ISO_SINGLE) { +@@ -2455,6 +2472,9 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + + drop: + kfree_skb(skb); ++done: ++ iso_conn_put(conn); ++ return 0; + } + + static struct hci_cb iso_cb = { +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 35c57657bcf4e..07b493331fd78 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7510,13 +7510,24 @@ struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c) + return c; + } + +-void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) ++int l2cap_recv_acldata(struct hci_dev *hdev, u16 handle, ++ struct sk_buff *skb, u16 flags) + { ++ struct hci_conn *hcon; + struct l2cap_conn *conn; + int len; + +- /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */ +- hci_dev_lock(hcon->hdev); ++ /* Lock hdev for hci_conn, and race on l2cap_data vs. l2cap_conn_del */ ++ hci_dev_lock(hdev); ++ ++ hcon = hci_conn_hash_lookup_handle(hdev, handle); ++ if (!hcon) { ++ hci_dev_unlock(hdev); ++ kfree_skb(skb); ++ return -ENOENT; ++ } ++ ++ hci_conn_enter_active_mode(hcon, BT_POWER_FORCE_ACTIVE_OFF); + + conn = hcon->l2cap_data; + +@@ -7524,12 +7535,13 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + conn = l2cap_conn_add(hcon); + + conn = l2cap_conn_hold_unless_zero(conn); ++ hcon = NULL; + +- hci_dev_unlock(hcon->hdev); ++ hci_dev_unlock(hdev); + + if (!conn) { + kfree_skb(skb); +- return; ++ return -EINVAL; + } + + BT_DBG("conn %p len %u flags 0x%x", conn, skb->len, flags); +@@ -7643,6 +7655,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) + unlock: + mutex_unlock(&conn->lock); + l2cap_conn_put(conn); ++ return 0; + } + + static struct hci_cb l2cap_cb = { +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index ab0cf442d57b9..298c2a9ab4df8 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -1458,22 +1458,39 @@ static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) + sco_conn_del(hcon, bt_to_errno(reason)); + } + +-void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) ++int sco_recv_scodata(struct hci_dev *hdev, u16 handle, struct sk_buff *skb) + { +- struct sco_conn *conn = hcon->sco_data; ++ struct hci_conn *hcon; ++ struct sco_conn *conn; + +- if (!conn) +- goto drop; ++ hci_dev_lock(hdev); ++ ++ hcon = hci_conn_hash_lookup_handle(hdev, handle); ++ if (!hcon) { ++ hci_dev_unlock(hdev); ++ kfree_skb(skb); ++ return -ENOENT; ++ } ++ ++ conn = sco_conn_hold_unless_zero(hcon->sco_data); ++ hcon = NULL; ++ ++ hci_dev_unlock(hdev); ++ ++ if (!conn) { ++ kfree_skb(skb); ++ return -EINVAL; ++ } + + BT_DBG("conn %p len %u", conn, skb->len); + +- if (skb->len) { ++ if (skb->len) + sco_recv_frame(conn, skb); +- return; +- } ++ else ++ kfree_skb(skb); + +-drop: +- kfree_skb(skb); ++ sco_conn_put(conn); ++ return 0; + } + + static struct hci_cb sco_cb = { +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch b/queue-6.17/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch new file mode 100644 index 0000000000..283300e38e --- /dev/null +++ b/queue-6.17/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch @@ -0,0 +1,72 @@ +From 0970cdaa84350f65d1366fbbc3886989ce95a20a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Nov 2025 17:04:43 +0800 +Subject: Bluetooth: hci_sock: Prevent race in socket write iter and sock bind + +From: Edward Adam Davis + +[ Upstream commit 89bb613511cc21ed5ba6bddc1c9b9ae9c0dad392 ] + +There is a potential race condition between sock bind and socket write +iter. bind may free the same cmd via mgmt_pending before write iter sends +the cmd, just as syzbot reported in UAF[1]. + +Here we use hci_dev_lock to synchronize the two, thereby avoiding the +UAF mentioned in [1]. + +[1] +syzbot reported: +BUG: KASAN: slab-use-after-free in mgmt_pending_remove+0x3b/0x210 net/bluetooth/mgmt_util.c:316 +Read of size 8 at addr ffff888077164818 by task syz.0.17/5989 +Call Trace: + mgmt_pending_remove+0x3b/0x210 net/bluetooth/mgmt_util.c:316 + set_link_security+0x5c2/0x710 net/bluetooth/mgmt.c:1918 + hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 + hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + sock_write_iter+0x279/0x360 net/socket.c:1195 + +Allocated by task 5989: + mgmt_pending_add+0x35/0x140 net/bluetooth/mgmt_util.c:296 + set_link_security+0x557/0x710 net/bluetooth/mgmt.c:1910 + hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 + hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + sock_write_iter+0x279/0x360 net/socket.c:1195 + +Freed by task 5991: + mgmt_pending_free net/bluetooth/mgmt_util.c:311 [inline] + mgmt_pending_foreach+0x30d/0x380 net/bluetooth/mgmt_util.c:257 + mgmt_index_removed+0x112/0x2f0 net/bluetooth/mgmt.c:9477 + hci_sock_bind+0xbe9/0x1000 net/bluetooth/hci_sock.c:1314 + +Fixes: 6fe26f694c82 ("Bluetooth: MGMT: Protect mgmt_pending list with its own lock") +Reported-by: syzbot+9aa47cd4633a3cf92a80@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9aa47cd4633a3cf92a80 +Tested-by: syzbot+9aa47cd4633a3cf92a80@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sock.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index fc866759910d9..ad19022ae127a 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -1311,7 +1311,9 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, + goto done; + } + ++ hci_dev_lock(hdev); + mgmt_index_removed(hdev); ++ hci_dev_unlock(hdev); + + err = hci_dev_open(hdev->id); + if (err) { +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch b/queue-6.17/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch new file mode 100644 index 0000000000..9445e70282 --- /dev/null +++ b/queue-6.17/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch @@ -0,0 +1,87 @@ +From f3b3b3d18fab81e61e22c6d0ea6ccb95f376710e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 13:45:13 -0500 +Subject: Bluetooth: SMP: Fix not generating mackey and ltk when repairing + +From: Luiz Augusto von Dentz + +[ Upstream commit 545d7827b2cd5de5eb85580cebeda6b35b3ff443 ] + +The change eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +introduced a goto that bypasses the creation of temporary mackey and ltk +which are later used by the likes of DHKey Check step. + +Later ffee202a78c2 ("Bluetooth: Always request for user confirmation for +Just Works (LE SC)") which means confirm_hint is always set in case +JUST_WORKS so the branch checking for an existing LTK becomes pointless +as confirm_hint will always be set, so this just merge both cases of +malicious or legitimate devices to be confirmed before continuing with the +pairing procedure. + +Link: https://github.com/bluez/bluez/issues/1622 +Fixes: eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index 45512b2ba951c..3a1ce04a7a536 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2136,7 +2136,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_chan *smp = chan->data; + struct hci_conn *hcon = conn->hcon; + u8 *pkax, *pkbx, *na, *nb, confirm_hint; +- u32 passkey; ++ u32 passkey = 0; + int err; + + bt_dev_dbg(hcon->hdev, "conn %p", conn); +@@ -2188,24 +2188,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +- +- /* Only Just-Works pairing requires extra checks */ +- if (smp->method != JUST_WORKS) +- goto mackey_and_ltk; +- +- /* If there already exists long term key in local host, leave +- * the decision to user space since the remote device could +- * be legitimate or malicious. +- */ +- if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, +- hcon->role)) { +- /* Set passkey to 0. The value can be any number since +- * it'll be ignored anyway. +- */ +- passkey = 0; +- confirm_hint = 1; +- goto confirm; +- } + } + + mackey_and_ltk: +@@ -2226,11 +2208,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (err) + return SMP_UNSPECIFIED; + +- confirm_hint = 0; +- +-confirm: +- if (smp->method == JUST_WORKS) +- confirm_hint = 1; ++ /* Always require user confirmation for Just-Works pairing to prevent ++ * impersonation attacks, or in case of a legitimate device that is ++ * repairing use the confirmation as acknowledgment to proceed with the ++ * creation of new keys. ++ */ ++ confirm_hint = smp->method == JUST_WORKS ? 1 : 0; + + err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, + hcon->dst_type, passkey, confirm_hint); +-- +2.51.0 + diff --git a/queue-6.17/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch b/queue-6.17/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch new file mode 100644 index 0000000000..de07a27ea8 --- /dev/null +++ b/queue-6.17/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch @@ -0,0 +1,92 @@ +From 983a287813f8200f17100df3337f21f2acdd1de1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:02 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing header + +From: Marc Kleine-Budde + +[ Upstream commit 6fe9f3279f7d2518439a7962c5870c6e9ecbadcf ] + +The driver expects to receive a struct gs_host_frame in +gs_usb_receive_bulk_callback(). + +Use struct_group to describe the header of the struct gs_host_frame and +check that we have at least received the header before accessing any +members of it. + +To resubmit the URB, do not dereference the pointer chain +"dev->parent->hf_size_rx" but use "parent->hf_size_rx" instead. Since +"urb->context" contains "parent", it is always defined, while "dev" is not +defined if the URB it too short. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-2-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index fa9bab8c89aea..51f8d694104d9 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -262,13 +262,15 @@ struct canfd_quirk { + } __packed; + + struct gs_host_frame { +- u32 echo_id; +- __le32 can_id; ++ struct_group(header, ++ u32 echo_id; ++ __le32 can_id; + +- u8 can_dlc; +- u8 channel; +- u8 flags; +- u8 reserved; ++ u8 can_dlc; ++ u8 channel; ++ u8 flags; ++ u8 reserved; ++ ); + + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); +@@ -576,6 +578,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; ++ unsigned int minimum_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -594,6 +597,15 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + return; + } + ++ minimum_length = sizeof(hf->header); ++ if (urb->actual_length < minimum_length) { ++ dev_err_ratelimited(&parent->udev->dev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ + /* device reports out of range channel id */ + if (hf->channel >= parent->channel_cnt) + goto device_detach; +@@ -687,7 +699,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + resubmit_urb: + usb_fill_bulk_urb(urb, parent->udev, + parent->pipe_in, +- hf, dev->parent->hf_size_rx, ++ hf, parent->hf_size_rx, + gs_usb_receive_bulk_callback, parent); + + rc = usb_submit_urb(urb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.17/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-24056 b/queue-6.17/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-24056 new file mode 100644 index 0000000000..ccc72b749e --- /dev/null +++ b/queue-6.17/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-24056 @@ -0,0 +1,140 @@ +From 55152876a57052fae02003905df6bc971af434d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:03 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing data + +From: Marc Kleine-Budde + +[ Upstream commit 395d988f93861101ec89d0dd9e3b876ae9392a5b ] + +The URB received in gs_usb_receive_bulk_callback() contains a struct +gs_host_frame. The length of the data after the header depends on the +gs_host_frame hf::flags and the active device features (e.g. time +stamping). + +Introduce a new function gs_usb_get_minimum_length() and check that we have +at least received the required amount of data before accessing it. Only +copy the data to that skb that has actually been received. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-3-a29b42eacada@pengutronix.de +[mkl: rename gs_usb_get_minimum_length() -> +gs_usb_get_minimum_rx_length()] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 59 +++++++++++++++++++++++++++++++++--- + 1 file changed, 54 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 51f8d694104d9..8d8a610f91441 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -261,6 +261,11 @@ struct canfd_quirk { + u8 quirk; + } __packed; + ++/* struct gs_host_frame::echo_id == GS_HOST_FRAME_ECHO_ID_RX indicates ++ * a regular RX'ed CAN frame ++ */ ++#define GS_HOST_FRAME_ECHO_ID_RX 0xffffffff ++ + struct gs_host_frame { + struct_group(header, + u32 echo_id; +@@ -570,6 +575,37 @@ gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, + return len; + } + ++static unsigned int ++gs_usb_get_minimum_rx_length(const struct gs_can *dev, const struct gs_host_frame *hf, ++ unsigned int *data_length_p) ++{ ++ unsigned int minimum_length, data_length = 0; ++ ++ if (hf->flags & GS_CAN_FLAG_FD) { ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) ++ data_length = can_fd_dlc2len(hf->can_dlc); ++ ++ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) ++ /* timestamp follows data field of max size */ ++ minimum_length = struct_size(hf, canfd_ts, 1); ++ else ++ minimum_length = sizeof(hf->header) + data_length; ++ } else { ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX && ++ !(hf->can_id & cpu_to_le32(CAN_RTR_FLAG))) ++ data_length = can_cc_dlc2len(hf->can_dlc); ++ ++ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) ++ /* timestamp follows data field of max size */ ++ minimum_length = struct_size(hf, classic_can_ts, 1); ++ else ++ minimum_length = sizeof(hf->header) + data_length; ++ } ++ ++ *data_length_p = data_length; ++ return minimum_length; ++} ++ + static void gs_usb_receive_bulk_callback(struct urb *urb) + { + struct gs_usb *parent = urb->context; +@@ -578,7 +614,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; +- unsigned int minimum_length; ++ unsigned int minimum_length, data_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -621,20 +657,33 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + if (!netif_running(netdev)) + goto resubmit_urb; + +- if (hf->echo_id == -1) { /* normal rx */ ++ minimum_length = gs_usb_get_minimum_rx_length(dev, hf, &data_length); ++ if (urb->actual_length < minimum_length) { ++ stats->rx_errors++; ++ stats->rx_length_errors++; ++ ++ if (net_ratelimit()) ++ netdev_err(netdev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) { /* normal rx */ + if (hf->flags & GS_CAN_FLAG_FD) { + skb = alloc_canfd_skb(netdev, &cfd); + if (!skb) + return; + + cfd->can_id = le32_to_cpu(hf->can_id); +- cfd->len = can_fd_dlc2len(hf->can_dlc); ++ cfd->len = data_length; + if (hf->flags & GS_CAN_FLAG_BRS) + cfd->flags |= CANFD_BRS; + if (hf->flags & GS_CAN_FLAG_ESI) + cfd->flags |= CANFD_ESI; + +- memcpy(cfd->data, hf->canfd->data, cfd->len); ++ memcpy(cfd->data, hf->canfd->data, data_length); + } else { + skb = alloc_can_skb(netdev, &cf); + if (!skb) +@@ -643,7 +692,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + cf->can_id = le32_to_cpu(hf->can_id); + can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); + +- memcpy(cf->data, hf->classic_can->data, 8); ++ memcpy(cf->data, hf->classic_can->data, data_length); + + /* ERROR frames tell us information about the controller */ + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) +-- +2.51.0 + diff --git a/queue-6.17/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch b/queue-6.17/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch new file mode 100644 index 0000000000..949e05ff0b --- /dev/null +++ b/queue-6.17/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch @@ -0,0 +1,60 @@ +From 73a7c20c979b8ed358ac3d15a4a0a122b5cdeeb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:01 +0100 +Subject: can: gs_usb: gs_usb_xmit_callback(): fix handling of failed + transmitted URBs + +From: Marc Kleine-Budde + +[ Upstream commit 516a0cd1c03fa266bb67dd87940a209fd4e53ce7 ] + +The driver lacks the cleanup of failed transfers of URBs. This reduces the +number of available URBs per error by 1. This leads to reduced performance +and ultimately to a complete stop of the transmission. + +If the sending of a bulk URB fails do proper cleanup: +- increase netdev stats +- mark the echo_sbk as free +- free the driver's context and do accounting +- wake the send queue + +Closes: https://github.com/candle-usb/candleLight_fw/issues/187 +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-1-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 69b8d6da651bf..fa9bab8c89aea 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -750,8 +750,21 @@ static void gs_usb_xmit_callback(struct urb *urb) + struct gs_can *dev = txc->dev; + struct net_device *netdev = dev->netdev; + +- if (urb->status) +- netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); ++ if (!urb->status) ++ return; ++ ++ if (urb->status != -ESHUTDOWN && net_ratelimit()) ++ netdev_info(netdev, "failed to xmit URB %u: %pe\n", ++ txc->echo_id, ERR_PTR(urb->status)); ++ ++ netdev->stats.tx_dropped++; ++ netdev->stats.tx_errors++; ++ ++ can_free_echo_skb(netdev, txc->echo_id, NULL); ++ gs_free_tx_context(txc); ++ atomic_dec(&dev->active_tx_urbs); ++ ++ netif_wake_queue(netdev); + } + + static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, +-- +2.51.0 + diff --git a/queue-6.17/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch b/queue-6.17/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch new file mode 100644 index 0000000000..29079fe551 --- /dev/null +++ b/queue-6.17/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch @@ -0,0 +1,62 @@ +From 33c13d92da6b54dbf988b0ac828db00dadf08e88 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 12:27:09 -0400 +Subject: can: kvaser_usb: leaf: Fix potential infinite loop in command parsers + +From: Seungjin Bae + +[ Upstream commit 0c73772cd2b8cc108d5f5334de89ad648d89b9ec ] + +The `kvaser_usb_leaf_wait_cmd()` and `kvaser_usb_leaf_read_bulk_callback` +functions contain logic to zero-length commands. These commands are used +to align data to the USB endpoint's wMaxPacketSize boundary. + +The driver attempts to skip these placeholders by aligning the buffer +position `pos` to the next packet boundary using `round_up()` function. + +However, if zero-length command is found exactly on a packet boundary +(i.e., `pos` is a multiple of wMaxPacketSize, including 0), `round_up` +function will return the unchanged value of `pos`. This prevents `pos` +to be increased, causing an infinite loop in the parsing logic. + +This patch fixes this in the function by using `pos + 1` instead. +This ensures that even if `pos` is on a boundary, the calculation is +based on `pos + 1`, forcing `round_up()` to always return the next +aligned boundary. + +Fixes: 7259124eac7d ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") +Signed-off-by: Seungjin Bae +Reviewed-by: Jimmy Assarsson +Tested-by: Jimmy Assarsson +Link: https://patch.msgid.link/20251023162709.348240-1-eeodqql09@gmail.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index c29828a94ad0e..1167d38344f1d 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -685,7 +685,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, + * for further details. + */ + if (tmp->len == 0) { +- pos = round_up(pos, ++ pos = round_up(pos + 1, + le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; +@@ -1732,7 +1732,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, + * number of events in case of a heavy rx load on the bus. + */ + if (cmd->len == 0) { +- pos = round_up(pos, le16_to_cpu ++ pos = round_up(pos + 1, le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; + } +-- +2.51.0 + diff --git a/queue-6.17/dma-direct-fix-missing-sg_dma_len-assignment-in-p2pd.patch b/queue-6.17/dma-direct-fix-missing-sg_dma_len-assignment-in-p2pd.patch new file mode 100644 index 0000000000..70e5828e99 --- /dev/null +++ b/queue-6.17/dma-direct-fix-missing-sg_dma_len-assignment-in-p2pd.patch @@ -0,0 +1,65 @@ +From 93e0fa80961761bb76e8134f8f72a3b0b4085d8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:41:12 +0000 +Subject: dma-direct: Fix missing sg_dma_len assignment in P2PDMA bus mappings + +From: Pranjal Shrivastava + +[ Upstream commit d0d08f4bd7f667dc7a65cd7133c0a94a6f02aca3 ] + +Prior to commit a25e7962db0d7 ("PCI/P2PDMA: Refactor the p2pdma mapping +helpers"), P2P segments were mapped using the pci_p2pdma_map_segment() +helper. This helper was responsible for populating sg->dma_address, +marking the bus address, and also setting sg_dma_len(sg). + +The refactor[1] removed this helper and moved the mapping logic directly +into the callers. While iommu_dma_map_sg() was correctly updated to set +the length in the new flow, it was missed in dma_direct_map_sg(). + +Thus, in dma_direct_map_sg(), the PCI_P2PDMA_MAP_BUS_ADDR case sets the +dma_address and marks the segment, but immediately executes 'continue', +which causes the loop to skip the standard assignment logic at the end: + + sg_dma_len(sg) = sg->length; + +As a result, when CONFIG_NEED_SG_DMA_LENGTH is enabled, the dma_length +field remains uninitialized (zero) for P2P bus address mappings. This +breaks upper-layer drivers (for e.g. RDMA/IB) that rely on sg_dma_len() +to determine the transfer size. + +Fix this by explicitly setting the DMA length in the +PCI_P2PDMA_MAP_BUS_ADDR case before continuing to the next scatterlist +entry. + +Fixes: a25e7962db0d7 ("PCI/P2PDMA: Refactor the p2pdma mapping helpers") +Reported-by: Jacob Moroni +Signed-off-by: Pranjal Shrivastava + +[1] +https://lore.kernel.org/all/ac14a0e94355bf898de65d023ccf8a2ad22a3ece.1746424934.git.leon@kernel.org/ + +Reviewed-by: Logan Gunthorpe +Reviewed-by: Leon Romanovsky +Reviewed-by: Shivaji Kant +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20251126114112.3694469-1-praan@google.com +Signed-off-by: Sasha Levin +--- + kernel/dma/direct.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c +index 24c359d9c8799..95f37028032df 100644 +--- a/kernel/dma/direct.c ++++ b/kernel/dma/direct.c +@@ -486,6 +486,7 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, + case PCI_P2PDMA_MAP_BUS_ADDR: + sg->dma_address = pci_p2pdma_bus_addr_map(&p2pdma_state, + sg_phys(sg)); ++ sg_dma_len(sg) = sg->length; + sg_dma_mark_bus_address(sg); + continue; + default: +-- +2.51.0 + diff --git a/queue-6.17/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch b/queue-6.17/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch new file mode 100644 index 0000000000..c0ffa55c90 --- /dev/null +++ b/queue-6.17/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch @@ -0,0 +1,39 @@ +From 7ee18e074e4edf6272b7fba54bcb291d4942e65c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 09:40:31 -0500 +Subject: drm/amdgpu: fix cyan_skillfish2 gpu info fw handling + +From: Alex Deucher + +[ Upstream commit 7fa666ab07ba9e08f52f357cb8e1aad753e83ac6 ] + +If the board supports IP discovery, we don't need to +parse the gpu info firmware. + +Backport to 6.18. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4721 +Fixes: fa819e3a7c1e ("drm/amdgpu: add support for cyan skillfish gpu_info") +Signed-off-by: Alex Deucher +(cherry picked from commit 5427e32fa3a0ba9a016db83877851ed277b065fb) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index aaee97cd9a109..a713d5e6e4012 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -2604,6 +2604,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) + chip_name = "navi12"; + break; + case CHIP_CYAN_SKILLFISH: ++ if (adev->mman.discovery_bin) ++ return 0; + chip_name = "cyan_skillfish"; + break; + } +-- +2.51.0 + diff --git a/queue-6.17/drm-bridge-sii902x-fix-hdmi-detection-with-drm_bridg.patch b/queue-6.17/drm-bridge-sii902x-fix-hdmi-detection-with-drm_bridg.patch new file mode 100644 index 0000000000..c740eaa1e9 --- /dev/null +++ b/queue-6.17/drm-bridge-sii902x-fix-hdmi-detection-with-drm_bridg.patch @@ -0,0 +1,118 @@ +From 2e16f286f9c5109051146eccf91b6a51b4ca3c24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Oct 2025 20:46:35 +0530 +Subject: drm/bridge: sii902x: Fix HDMI detection with + DRM_BRIDGE_ATTACH_NO_CONNECTOR + +From: Devarsh Thakkar + +[ Upstream commit d6732ef4ab252e5753be7acad87b0a91cfd06953 ] + +The sii902x driver was caching HDMI detection state in a sink_is_hdmi field +and checking it in mode_set() to determine whether to set HDMI or DVI +output mode. This approach had two problems: + +1. With DRM_BRIDGE_ATTACH_NO_CONNECTOR (used by modern display drivers like +TIDSS), the bridge's get_modes() is never called. Instead, the +drm_bridge_connector helper calls the bridge's edid_read() and updates the +connector itself. This meant sink_is_hdmi was never populated, causing the +driver to default to DVI mode and breaking HDMI audio. + +2. The mode_set() callback doesn't receive atomic state or connector +pointer, making it impossible to check connector->display_info.is_hdmi +directly at that point. + +Fix this by moving the HDMI vs DVI decision from mode_set() to +atomic_enable(), where we can access the connector via +drm_atomic_get_new_connector_for_encoder(). This works for both connector +models: + +- With DRM_BRIDGE_ATTACH_NO_CONNECTOR: Returns the drm_bridge_connector + created by the display driver, which has already been updated by the +helper's call to drm_edid_connector_update() + +- Without DRM_BRIDGE_ATTACH_NO_CONNECTOR (legacy): Returns the connector + embedded in sii902x struct, which gets updated by the bridge's own +get_modes() + +Fixes: 3de47e1309c2 ("drm/bridge: sii902x: use display info is_hdmi") +Signed-off-by: Devarsh Thakkar +Reviewed-by: Tomi Valkeinen +Signed-off-by: Neil Armstrong +Link: https://patch.msgid.link/20251030151635.3019864-1-devarsht@ti.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/sii902x.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c +index d537b1d036fb0..1f0aba28ad1e1 100644 +--- a/drivers/gpu/drm/bridge/sii902x.c ++++ b/drivers/gpu/drm/bridge/sii902x.c +@@ -179,7 +179,6 @@ struct sii902x { + struct drm_connector connector; + struct gpio_desc *reset_gpio; + struct i2c_mux_core *i2cmux; +- bool sink_is_hdmi; + u32 bus_width; + + /* +@@ -315,8 +314,6 @@ static int sii902x_get_modes(struct drm_connector *connector) + drm_edid_free(drm_edid); + } + +- sii902x->sink_is_hdmi = connector->display_info.is_hdmi; +- + return num; + } + +@@ -342,9 +339,17 @@ static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) + { + struct sii902x *sii902x = bridge_to_sii902x(bridge); ++ struct drm_connector *connector; ++ u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); ++ if (connector && connector->display_info.is_hdmi) ++ output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI; + + mutex_lock(&sii902x->mutex); + ++ regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, ++ SII902X_SYS_CTRL_OUTPUT_MODE, output_mode); + regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL, + SII902X_AVI_POWER_STATE_MSK, + SII902X_AVI_POWER_STATE_D(0)); +@@ -359,16 +364,12 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *adj) + { + struct sii902x *sii902x = bridge_to_sii902x(bridge); +- u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI; + struct regmap *regmap = sii902x->regmap; + u8 buf[HDMI_INFOFRAME_SIZE(AVI)]; + struct hdmi_avi_infoframe frame; + u16 pixel_clock_10kHz = adj->clock / 10; + int ret; + +- if (sii902x->sink_is_hdmi) +- output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI; +- + buf[0] = pixel_clock_10kHz & 0xff; + buf[1] = pixel_clock_10kHz >> 8; + buf[2] = drm_mode_vrefresh(adj); +@@ -384,11 +385,6 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge, + + mutex_lock(&sii902x->mutex); + +- ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, +- SII902X_SYS_CTRL_OUTPUT_MODE, output_mode); +- if (ret) +- goto out; +- + ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10); + if (ret) + goto out; +-- +2.51.0 + diff --git a/queue-6.17/drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch b/queue-6.17/drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch new file mode 100644 index 0000000000..6880080a3b --- /dev/null +++ b/queue-6.17/drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch @@ -0,0 +1,54 @@ +From 159a51be38e048c106ba0e8d5d6b3378bab57f11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 11:48:43 -0800 +Subject: drm/xe: Fix conversion from clock ticks to milliseconds + +From: Harish Chegondi + +[ Upstream commit 7276878b069c57d9a9cca5db01d2f7a427b73456 ] + +When tick counts are large and multiplication by MSEC_PER_SEC is larger +than 64 bits, the conversion from clock ticks to milliseconds can go bad. + +Use mul_u64_u32_div() instead. + +Cc: Ashutosh Dixit +Signed-off-by: Harish Chegondi +Suggested-by: Umesh Nerlige Ramappa +Fixes: 49cc215aad7f ("drm/xe: Add xe_gt_clock_interval_to_ms helper") +Reviewed-by: Ashutosh Dixit +Signed-off-by: Ashutosh Dixit +Link: https://patch.msgid.link/1562f1b62d5be3fbaee100f09107f3cc49e40dd1.1763408584.git.harish.chegondi@intel.com +(cherry picked from commit 96b93ac214f9dd66294d975d86c5dee256faef91) +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_clock.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_clock.c b/drivers/gpu/drm/xe/xe_gt_clock.c +index 4f011d1573c65..f65d1edd05671 100644 +--- a/drivers/gpu/drm/xe/xe_gt_clock.c ++++ b/drivers/gpu/drm/xe/xe_gt_clock.c +@@ -93,11 +93,6 @@ int xe_gt_clock_init(struct xe_gt *gt) + return 0; + } + +-static u64 div_u64_roundup(u64 n, u32 d) +-{ +- return div_u64(n + d - 1, d); +-} +- + /** + * xe_gt_clock_interval_to_ms - Convert sampled GT clock ticks to msec + * +@@ -108,5 +103,5 @@ static u64 div_u64_roundup(u64 n, u32 d) + */ + u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count) + { +- return div_u64_roundup(count * MSEC_PER_SEC, gt->info.reference_clock); ++ return mul_u64_u32_div(count, MSEC_PER_SEC, gt->info.reference_clock); + } +-- +2.51.0 + diff --git a/queue-6.17/eth-fbnic-fix-counter-roll-over-issue.patch b/queue-6.17/eth-fbnic-fix-counter-roll-over-issue.patch new file mode 100644 index 0000000000..40c63d1cc9 --- /dev/null +++ b/queue-6.17/eth-fbnic-fix-counter-roll-over-issue.patch @@ -0,0 +1,43 @@ +From 990942516145fa85c3f5427a60ec5943b26be0ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 13:17:04 -0800 +Subject: eth: fbnic: Fix counter roll-over issue + +From: Mohsin Bashir + +[ Upstream commit 6d66e093e0740d39a36ef742c60eec247df26f41 ] + +Fix a potential counter roll-over issue in fbnic_mbx_alloc_rx_msgs() +when calculating descriptor slots. The issue occurs when head - tail +results in a large positive value (unsigned) and the compiler interprets +head - tail - 1 as a signed value. + +Since FBNIC_IPC_MBX_DESC_LEN is a power of two, use a masking operation, +which is a common way of avoiding this problem when dealing with these +sort of ring space calculations. + +Fixes: da3cde08209e ("eth: fbnic: Add FW communication mechanism") +Signed-off-by: Mohsin Bashir +Link: https://patch.msgid.link/20251125211704.3222413-1-mohsin.bashr@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +index 0c55be7d25476..acc1ad91b0c3a 100644 +--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c ++++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +@@ -201,7 +201,7 @@ static int fbnic_mbx_alloc_rx_msgs(struct fbnic_dev *fbd) + return -ENODEV; + + /* Fill all but 1 unused descriptors in the Rx queue. */ +- count = (head - tail - 1) % FBNIC_IPC_MBX_DESC_LEN; ++ count = (head - tail - 1) & (FBNIC_IPC_MBX_DESC_LEN - 1); + while (!err && count--) { + struct fbnic_tlv_msg *msg; + +-- +2.51.0 + diff --git a/queue-6.17/fs-namespace-fix-reference-leak-in-grab_requested_mn.patch b/queue-6.17/fs-namespace-fix-reference-leak-in-grab_requested_mn.patch new file mode 100644 index 0000000000..8a4ae08319 --- /dev/null +++ b/queue-6.17/fs-namespace-fix-reference-leak-in-grab_requested_mn.patch @@ -0,0 +1,53 @@ +From b1b8dd2b1c34a47d18db09438cf385205d8f93d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 07:19:53 +0000 +Subject: fs/namespace: fix reference leak in grab_requested_mnt_ns + +From: Andrei Vagin + +[ Upstream commit 7b6dcd9bfd869eee7693e45b1817dac8c56e5f86 ] + +lookup_mnt_ns() already takes a reference on mnt_ns. +grab_requested_mnt_ns() doesn't need to take an extra reference. + +Fixes: 78f0e33cd6c93 ("fs/namespace: correctly handle errors returned by grab_requested_mnt_ns") +Signed-off-by: Andrei Vagin +Link: https://patch.msgid.link/20251122071953.3053755-1-avagin@google.com +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/namespace.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index fd988bc759bd3..e059c2c9867f0 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -5901,6 +5901,8 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq + + if (kreq->mnt_ns_id) { + mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id); ++ if (!mnt_ns) ++ return ERR_PTR(-ENOENT); + } else if (kreq->mnt_ns_fd) { + struct ns_common *ns; + +@@ -5916,13 +5918,12 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq + return ERR_PTR(-EINVAL); + + mnt_ns = to_mnt_ns(ns); ++ refcount_inc(&mnt_ns->passive); + } else { + mnt_ns = current->nsproxy->mnt_ns; ++ refcount_inc(&mnt_ns->passive); + } +- if (!mnt_ns) +- return ERR_PTR(-ENOENT); + +- refcount_inc(&mnt_ns->passive); + return mnt_ns; + } + +-- +2.51.0 + diff --git a/queue-6.17/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch b/queue-6.17/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch new file mode 100644 index 0000000000..159068021d --- /dev/null +++ b/queue-6.17/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch @@ -0,0 +1,132 @@ +From 6ec900978604cc3ba958356ba123f4bf2b4cb613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Oct 2025 18:16:19 +0200 +Subject: iio: st_lsm6dsx: Fixed calibrated timestamp calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mario Tesi + +[ Upstream commit 8abbf45fcda028c2c05ba38eb14ede9fa9e7341b ] + +The calibrated timestamp is calculated from the nominal value using the +formula: + ts_gain[ns] ≈ ts_sensitivity - (ts_trim_coeff * val) / 1000. + +The values of ts_sensitivity and ts_trim_coeff are not the same for all +devices, so it is necessary to differentiate them based on the part name. +For the correct values please consult the relevant AN. + +Fixes: cb3b6b8e1bc0 ("iio: imu: st_lsm6dsx: add odr calibration feature") +Signed-off-by: Mario Tesi +Acked-by: Lorenzo Bianconi +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 18 ++++++++++++++++++ + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 19 ++++++++----------- + 2 files changed, 26 insertions(+), 11 deletions(-) + +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +index c225b246c8a55..f8486a1b02d07 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +@@ -192,6 +192,22 @@ struct st_lsm6dsx_fifo_ops { + * @fifo_en: Hw timer FIFO enable register info (addr + mask). + * @decimator: Hw timer FIFO decimator register info (addr + mask). + * @freq_fine: Difference in % of ODR with respect to the typical. ++ * @ts_sensitivity: Nominal timestamp sensitivity. ++ * @ts_trim_coeff: Coefficient for calculating the calibrated timestamp gain. ++ * This coefficient comes into play when linearizing the formula ++ * used to calculate the calibrated timestamp (please see the ++ * relevant formula in the AN for the specific IMU). ++ * For example, in the case of LSM6DSO we have: ++ * ++ * 1 / (1 + x) ~= 1 - x (Taylor’s Series) ++ * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) (from AN5192) ++ * ttrim[ns] ~= 25000 - 37.5 * val ++ * ttrim[ns] ~= 25000 - (37500 * val) / 1000 ++ * ++ * so, replacing ts_sensitivity = 25000 and ++ * ts_trim_coeff = 37500 ++ * ++ * ttrim[ns] ~= ts_sensitivity - (ts_trim_coeff * val) / 1000 + */ + struct st_lsm6dsx_hw_ts_settings { + struct st_lsm6dsx_reg timer_en; +@@ -199,6 +215,8 @@ struct st_lsm6dsx_hw_ts_settings { + struct st_lsm6dsx_reg fifo_en; + struct st_lsm6dsx_reg decimator; + u8 freq_fine; ++ u16 ts_sensitivity; ++ u16 ts_trim_coeff; + }; + + /** +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +index c65ad49829e7d..72d8af39a9535 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +@@ -94,8 +94,6 @@ + + #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f + +-#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */ +- + static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { + ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), +@@ -983,6 +981,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x63, ++ .ts_sensitivity = 25000, ++ .ts_trim_coeff = 37500, + }, + .shub_settings = { + .page_mux = { +@@ -1196,6 +1196,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x63, ++ .ts_sensitivity = 25000, ++ .ts_trim_coeff = 37500, + }, + .event_settings = { + .enable_reg = { +@@ -1371,6 +1373,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x4f, ++ .ts_sensitivity = 21701, ++ .ts_trim_coeff = 28212, + }, + .shub_settings = { + .page_mux = { +@@ -2248,20 +2252,13 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) + } + + /* calibrate timestamp sensitivity */ +- hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY; ++ hw->ts_gain = ts_settings->ts_sensitivity; + if (ts_settings->freq_fine) { + err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); + if (err < 0) + return err; + +- /* +- * linearize the AN5192 formula: +- * 1 / (1 + x) ~= 1 - x (Taylor’s Series) +- * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) +- * ttrim[ns] ~= 25000 - 37.5 * val +- * ttrim[ns] ~= 25000 - (37500 * val) / 1000 +- */ +- hw->ts_gain -= ((s8)val * 37500) / 1000; ++ hw->ts_gain -= ((s8)val * ts_settings->ts_trim_coeff) / 1000; + } + + return 0; +-- +2.51.0 + diff --git a/queue-6.17/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch b/queue-6.17/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch new file mode 100644 index 0000000000..be219f5839 --- /dev/null +++ b/queue-6.17/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch @@ -0,0 +1,38 @@ +From 7eb2c9d3a1fdde48cd0ec0912d7e2bbe5f1272a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 10:40:39 +0800 +Subject: mailbox: mailbox-test: Fix debugfs_create_dir error checking + +From: Haotian Zhang + +[ Upstream commit 3acf1028f5003731977f750a7070f3321a9cb740 ] + +The debugfs_create_dir() function returns ERR_PTR() on error, not NULL. +The current null-check fails to catch errors. + +Use IS_ERR() to correctly check for errors. + +Fixes: 8ea4484d0c2b ("mailbox: Add generic mechanism for testing Mailbox Controllers") +Signed-off-by: Haotian Zhang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c +index c9dd8c42c0cdf..3a28ab5c42e57 100644 +--- a/drivers/mailbox/mailbox-test.c ++++ b/drivers/mailbox/mailbox-test.c +@@ -268,7 +268,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, + return 0; + + tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); +- if (!tdev->root_debugfs_dir) { ++ if (IS_ERR(tdev->root_debugfs_dir)) { + dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-6.17/mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch b/queue-6.17/mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch new file mode 100644 index 0000000000..18ee48f6dd --- /dev/null +++ b/queue-6.17/mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch @@ -0,0 +1,169 @@ +From a2f5d24e27777a586ebf0e0155257d947c3240bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 01:16:30 +0800 +Subject: mailbox: mtk-cmdq: Refine DMA address handling for the command buffer + +From: Jason-JH Lin + +[ Upstream commit a195c7ccfb7a21b8118139835e25936ec8722596 ] + +GCE can only fetch the command buffer address from a 32-bit register. +Some SoCs support a 35-bit command buffer address for GCE, which +requires a right shift of 3 bits before setting the address into +the 32-bit register. A comment has been added to the header of +cmdq_get_shift_pa() to explain this requirement. + +To prevent the GCE command buffer address from being DMA mapped beyond +its supported bit range, the DMA bit mask for the device is set during +initialization. + +Additionally, to ensure the correct shift is applied when setting or +reading the register that stores the GCE command buffer address, +new APIs, cmdq_convert_gce_addr() and cmdq_revert_gce_addr(), have +been introduced for consistent operations on this register. + +The variable type for the command buffer address has been standardized +to dma_addr_t to prevent handling issues caused by type mismatches. + +Fixes: 0858fde496f8 ("mailbox: cmdq: variablize address shift in platform") +Signed-off-by: Jason-JH Lin +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mtk-cmdq-mailbox.c | 45 ++++++++++++++++-------- + include/linux/mailbox/mtk-cmdq-mailbox.h | 10 ++++++ + 2 files changed, 41 insertions(+), 14 deletions(-) + +diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c +index 654a60f63756a..5791f80f995ab 100644 +--- a/drivers/mailbox/mtk-cmdq-mailbox.c ++++ b/drivers/mailbox/mtk-cmdq-mailbox.c +@@ -92,6 +92,18 @@ struct gce_plat { + u32 gce_num; + }; + ++static inline u32 cmdq_convert_gce_addr(dma_addr_t addr, const struct gce_plat *pdata) ++{ ++ /* Convert DMA addr (PA or IOVA) to GCE readable addr */ ++ return addr >> pdata->shift; ++} ++ ++static inline dma_addr_t cmdq_revert_gce_addr(u32 addr, const struct gce_plat *pdata) ++{ ++ /* Revert GCE readable addr to DMA addr (PA or IOVA) */ ++ return (dma_addr_t)addr << pdata->shift; ++} ++ + u8 cmdq_get_shift_pa(struct mbox_chan *chan) + { + struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); +@@ -188,13 +200,12 @@ static void cmdq_task_insert_into_thread(struct cmdq_task *task) + struct cmdq_task *prev_task = list_last_entry( + &thread->task_busy_list, typeof(*task), list_entry); + u64 *prev_task_base = prev_task->pkt->va_base; ++ u32 gce_addr = cmdq_convert_gce_addr(task->pa_base, task->cmdq->pdata); + + /* let previous task jump to this task */ + dma_sync_single_for_cpu(dev, prev_task->pa_base, + prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); +- prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = +- (u64)CMDQ_JUMP_BY_PA << 32 | +- (task->pa_base >> task->cmdq->pdata->shift); ++ prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] = (u64)CMDQ_JUMP_BY_PA << 32 | gce_addr; + dma_sync_single_for_device(dev, prev_task->pa_base, + prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE); + +@@ -237,7 +248,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, + struct cmdq_thread *thread) + { + struct cmdq_task *task, *tmp, *curr_task = NULL; +- u32 curr_pa, irq_flag, task_end_pa; ++ u32 irq_flag, gce_addr; ++ dma_addr_t curr_pa, task_end_pa; + bool err; + + irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS); +@@ -259,7 +271,8 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, + else + return; + +- curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->pdata->shift; ++ gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); ++ curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); + + list_for_each_entry_safe(task, tmp, &thread->task_busy_list, + list_entry) { +@@ -378,7 +391,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) + struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; + struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); + struct cmdq_task *task; +- unsigned long curr_pa, end_pa; ++ u32 gce_addr; ++ dma_addr_t curr_pa, end_pa; + + /* Client should not flush new tasks if suspended. */ + WARN_ON(cmdq->suspended); +@@ -402,20 +416,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) + */ + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); + +- writel(task->pa_base >> cmdq->pdata->shift, +- thread->base + CMDQ_THR_CURR_ADDR); +- writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->pdata->shift, +- thread->base + CMDQ_THR_END_ADDR); ++ gce_addr = cmdq_convert_gce_addr(task->pa_base, cmdq->pdata); ++ writel(gce_addr, thread->base + CMDQ_THR_CURR_ADDR); ++ gce_addr = cmdq_convert_gce_addr(task->pa_base + pkt->cmd_buf_size, cmdq->pdata); ++ writel(gce_addr, thread->base + CMDQ_THR_END_ADDR); + + writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); + writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); + writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); + } else { + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); +- curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << +- cmdq->pdata->shift; +- end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << +- cmdq->pdata->shift; ++ gce_addr = readl(thread->base + CMDQ_THR_CURR_ADDR); ++ curr_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); ++ gce_addr = readl(thread->base + CMDQ_THR_END_ADDR); ++ end_pa = cmdq_revert_gce_addr(gce_addr, cmdq->pdata); + /* check boundary */ + if (curr_pa == end_pa - CMDQ_INST_SIZE || + curr_pa == end_pa) { +@@ -646,6 +660,9 @@ static int cmdq_probe(struct platform_device *pdev) + if (err) + return err; + ++ dma_set_coherent_mask(dev, ++ DMA_BIT_MASK(sizeof(u32) * BITS_PER_BYTE + cmdq->pdata->shift)); ++ + cmdq->mbox.dev = dev; + cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, + sizeof(*cmdq->mbox.chans), GFP_KERNEL); +diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h +index 4c1a91b07de39..e1555e06e7e55 100644 +--- a/include/linux/mailbox/mtk-cmdq-mailbox.h ++++ b/include/linux/mailbox/mtk-cmdq-mailbox.h +@@ -77,6 +77,16 @@ struct cmdq_pkt { + size_t buf_size; /* real buffer size */ + }; + ++/** ++ * cmdq_get_shift_pa() - get the shift bits of physical address ++ * @chan: mailbox channel ++ * ++ * GCE can only fetch the command buffer address from a 32-bit register. ++ * Some SOCs support more than 32-bit command buffer address for GCE, which ++ * requires some shift bits to make the address fit into the 32-bit register. ++ * ++ * Return: the shift bits of physical address ++ */ + u8 cmdq_get_shift_pa(struct mbox_chan *chan); + + #endif /* __MTK_CMDQ_MAILBOX_H__ */ +-- +2.51.0 + diff --git a/queue-6.17/mailbox-pcc-don-t-zero-error-register.patch b/queue-6.17/mailbox-pcc-don-t-zero-error-register.patch new file mode 100644 index 0000000000..74a2790147 --- /dev/null +++ b/queue-6.17/mailbox-pcc-don-t-zero-error-register.patch @@ -0,0 +1,57 @@ +From 6e0b5c86b230decae3b67f282797e659f4931068 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:42:29 +0000 +Subject: mailbox: pcc: don't zero error register + +From: Jamie Iles + +[ Upstream commit ff0e4d4c97c94af34cc9cad37b5a5cdbe597a3b0 ] + +The error status mask for a type 3/4 subspace is used for reading the +error status, and the bitwise inverse is used for clearing the error +with the intent being to preserve any of the non-error bits. However, +we were previously applying the mask to extract the status and then +applying the inverse to the result which ended up clearing all bits. + +Instead, store the inverse mask in the preserve mask and then use that +on the original value read from the error status so that only the error +is cleared. + +Fixes: c45ded7e1135 ("mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)") +Signed-off-by: Jamie Iles +Signed-off-by: Punit Agrawal +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 0a00719b24827..ff292b9e0be9e 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -276,9 +276,8 @@ static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) + if (ret) + return ret; + +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; ++ if (val & pchan->error.status_mask) { ++ val &= pchan->error.preserve_mask; + pcc_chan_reg_write(&pchan->error, val); + return -EIO; + } +@@ -745,7 +744,8 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan, + + ret = pcc_chan_reg_init(&pchan->error, + &pcct_ext->error_status_register, +- 0, 0, pcct_ext->error_status_mask, ++ ~pcct_ext->error_status_mask, 0, ++ pcct_ext->error_status_mask, + "Error Status"); + } + return ret; +-- +2.51.0 + diff --git a/queue-6.17/net-aquantia-add-missing-descriptor-cache-invalidati.patch b/queue-6.17/net-aquantia-add-missing-descriptor-cache-invalidati.patch new file mode 100644 index 0000000000..6b3be435c8 --- /dev/null +++ b/queue-6.17/net-aquantia-add-missing-descriptor-cache-invalidati.patch @@ -0,0 +1,144 @@ +From f9d66bf8f2bc1fc45070941b05fb5814dc50da0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 12:15:33 +0800 +Subject: net: aquantia: Add missing descriptor cache invalidation on ATL2 + +From: Kai-Heng Feng + +[ Upstream commit 7526183cfdbe352c51c285762f0e15b7c428ea06 ] + +ATL2 hardware was missing descriptor cache invalidation in hw_stop(), +causing SMMU translation faults during device shutdown and module removal: +[ 70.355743] arm-smmu-v3 arm-smmu-v3.5.auto: event 0x10 received: +[ 70.361893] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0002060000000010 +[ 70.367948] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000020000000000 +[ 70.374002] arm-smmu-v3 arm-smmu-v3.5.auto: 0x00000000ff9bc000 +[ 70.380055] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000000000000000 +[ 70.386109] arm-smmu-v3 arm-smmu-v3.5.auto: event: F_TRANSLATION client: 0001:06:00.0 sid: 0x20600 ssid: 0x0 iova: 0xff9bc000 ipa: 0x0 +[ 70.398531] arm-smmu-v3 arm-smmu-v3.5.auto: unpriv data write s1 "Input address caused fault" stag: 0x0 + +Commit 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after +driver unbind") and commit ed4d81c4b3f2 ("net: aquantia: when cleaning +hw cache it should be toggled") fixed cache invalidation for ATL B0, but +ATL2 was left with only interrupt disabling. This allowed hardware to +write to cached descriptors after DMA memory was unmapped, triggering +SMMU faults. Once cache invalidation is applied to ATL2, the translation +fault can't be observed anymore. + +Add shared aq_hw_invalidate_descriptor_cache() helper and use it in both +ATL B0 and ATL2 hw_stop() implementations for consistent behavior. + +Fixes: e54dcf4bba3e ("net: atlantic: basic A2 init/deinit hw_ops") +Tested-by: Carol Soto +Signed-off-by: Kai-Heng Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251120041537.62184-1-kaihengf@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/aquantia/atlantic/aq_hw_utils.c | 22 +++++++++++++++++++ + .../ethernet/aquantia/atlantic/aq_hw_utils.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 +--------------- + .../aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 4 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 1921741f7311d..18b08277d2e1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -15,6 +15,7 @@ + + #include "aq_hw.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_llh.h" + + void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, + u32 shift, u32 val) +@@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) + lo_hi_writeq(value, hw->mmio + reg); + } + ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) ++{ ++ int err; ++ u32 val; ++ ++ /* Invalidate Descriptor Cache to prevent writing to the cached ++ * descriptors and to the data pointer of those descriptors ++ */ ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); ++ ++ err = aq_hw_err_from_flags(hw); ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ hw, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index ffa6e4067c211..d89c63d88e4a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 493432d036b9a..c7895bfb2ecf8 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { +- int err; +- u32 val; +- + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +- /* Invalidate Descriptor Cache to prevent writing to the cached +- * descriptors and to the data pointer of those descriptors +- */ +- hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); +- +- err = aq_hw_err_from_flags(self); +- +- if (err) +- goto err_exit; +- +- readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, +- self, val, val == 1, 1000U, 10000U); +- +-err_exit: +- return err; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index b0ed572e88c67..0ce9caae8799c 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + { + hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); + +- return 0; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) +-- +2.51.0 + diff --git a/queue-6.17/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch b/queue-6.17/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch new file mode 100644 index 0000000000..e8937fa11e --- /dev/null +++ b/queue-6.17/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch @@ -0,0 +1,93 @@ +From 676b0c8ffde531e31764c12559a89a3f60925777 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:22:49 +0800 +Subject: net: atlantic: fix fragment overflow handling in RX path + +From: Jiefeng Zhang + +[ Upstream commit 5ffcb7b890f61541201461580bb6622ace405aec ] + +The atlantic driver can receive packets with more than MAX_SKB_FRAGS (17) +fragments when handling large multi-descriptor packets. This causes an +out-of-bounds write in skb_add_rx_frag_netmem() leading to kernel panic. + +The issue occurs because the driver doesn't check the total number of +fragments before calling skb_add_rx_frag(). When a packet requires more +than MAX_SKB_FRAGS fragments, the fragment index exceeds the array bounds. + +Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, +then all fragments are accounted for. And reusing the existing check to +prevent the overflow earlier in the code path. + +This crash occurred in production with an Aquantia AQC113 10G NIC. + +Stack trace from production environment: +``` +RIP: 0010:skb_add_rx_frag_netmem+0x29/0xd0 +Code: 90 f3 0f 1e fa 0f 1f 44 00 00 48 89 f8 41 89 +ca 48 89 d7 48 63 ce 8b 90 c0 00 00 00 48 c1 e1 04 48 01 ca 48 03 90 +c8 00 00 00 <48> 89 7a 30 44 89 52 3c 44 89 42 38 40 f6 c7 01 75 74 48 +89 fa 83 +RSP: 0018:ffffa9bec02a8d50 EFLAGS: 00010287 +RAX: ffff925b22e80a00 RBX: ffff925ad38d2700 RCX: +fffffffe0a0c8000 +RDX: ffff9258ea95bac0 RSI: ffff925ae0a0c800 RDI: +0000000000037a40 +RBP: 0000000000000024 R08: 0000000000000000 R09: +0000000000000021 +R10: 0000000000000848 R11: 0000000000000000 R12: +ffffa9bec02a8e24 +R13: ffff925ad8615570 R14: 0000000000000000 R15: +ffff925b22e80a00 +FS: 0000000000000000(0000) +GS:ffff925e47880000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffff9258ea95baf0 CR3: 0000000166022004 CR4: +0000000000f72ef0 +PKRU: 55555554 +Call Trace: + +aq_ring_rx_clean+0x175/0xe60 [atlantic] +? aq_ring_rx_clean+0x14d/0xe60 [atlantic] +? aq_ring_tx_clean+0xdf/0x190 [atlantic] +? kmem_cache_free+0x348/0x450 +? aq_vec_poll+0x81/0x1d0 [atlantic] +? __napi_poll+0x28/0x1c0 +? net_rx_action+0x337/0x420 +``` + +Fixes: 6aecbba12b5c ("net: atlantic: add check for MAX_SKB_FRAGS") +Changes in v4: +- Add Fixes: tag to satisfy patch validation requirements. + +Changes in v3: +- Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, + then all fragments are accounted for. + +Signed-off-by: Jiefeng Zhang +Link: https://patch.msgid.link/20251126032249.69358-1-jiefeng.z.zhang@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index f21de0c21e524..d23d23bed39fe 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -547,6 +547,11 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi, + + if (!buff->is_eop) { + unsigned int frag_cnt = 0U; ++ ++ /* There will be an extra fragment */ ++ if (buff->len > AQ_CFG_RX_HDR_SIZE) ++ frag_cnt++; ++ + buff_ = buff; + do { + bool is_rsc_completed = true; +-- +2.51.0 + diff --git a/queue-6.17/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch b/queue-6.17/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch new file mode 100644 index 0000000000..f28736ae1d --- /dev/null +++ b/queue-6.17/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch @@ -0,0 +1,73 @@ +From 9cfbd94ace102d9cbb15152dd5b8461442ff0fa6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 13:13:24 +0200 +Subject: net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing + traffic + +From: Vladimir Oltean + +[ Upstream commit da62abaaa268357b1aa66b372ace562189a05df1 ] + +When using the SGMII PCS as a fixed-link chip-to-chip connection, it is +easy to miss the fact that traffic passes only at 1G, since that's what +any normal such connection would use. + +When using the SGMII PCS connected towards an on-board PHY or an SFP +module, it is immediately noticeable that when the link resolves to a +speed other than 1G, traffic from the MAC fails to pass: TX counters +increase, but nothing gets decoded by the other end, and no local RX +counters increase either. + +Artificially lowering a fixed-link rate to speed = <100> makes us able +to see the same issue as in the case of having an SGMII PHY. + +Some debugging shows that the XPCS configuration is A-OK, but that the +MAC Configuration Table entry for the port has the SPEED bits still set +to 1000Mbps, due to a special condition in the driver. Deleting that +condition, and letting the resolved link speed be programmed directly +into the MAC speed field, results in a functional link at all 3 speeds. + +This piece of evidence, based on testing on both generations with SGMII +support (SJA1105S and SJA1110A) directly contradicts the statement from +the blamed commit that "the MAC is fixed at 1 Gbps and we need to +configure the PCS only (if even that)". Worse, that statement is not +backed by any documentation, and no one from NXP knows what it might +refer to. + +I am unable to recall sufficient context regarding my testing from March +2020 to understand what led me to draw such a braindead and factually +incorrect conclusion. Yet, there is nothing of value regarding forcing +the MAC speed, either for SGMII or 2500Base-X (introduced at a later +stage), so remove all such logic. + +Fixes: ffe10e679cec ("net: dsa: sja1105: Add support for the SGMII port") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251122111324.136761-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index f674c400f05b2..aa2145cf29a67 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1302,14 +1302,7 @@ static int sja1105_set_port_speed(struct sja1105_private *priv, int port, + * table, since this will be used for the clocking setup, and we no + * longer need to store it in the static config (already told hardware + * we want auto during upload phase). +- * Actually for the SGMII port, the MAC is fixed at 1 Gbps and +- * we need to configure the PCS only (if even that). + */ +- if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; +- else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- + mac[port].speed = speed; + + return 0; +-- +2.51.0 + diff --git a/queue-6.17/net-fec-cancel-perout_timer-when-perout-is-disabled.patch b/queue-6.17/net-fec-cancel-perout_timer-when-perout-is-disabled.patch new file mode 100644 index 0000000000..22b2db7c6d --- /dev/null +++ b/queue-6.17/net-fec-cancel-perout_timer-when-perout-is-disabled.patch @@ -0,0 +1,42 @@ +From 1167763a1a9b2779391ed74c75eca6abdb4ed95d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:07 +0800 +Subject: net: fec: cancel perout_timer when PEROUT is disabled + +From: Wei Fang + +[ Upstream commit 50caa744689e505414673c20359b04aa918439e3 ] + +The PEROUT allows the user to set a specified future time to output the +periodic signal. If the future time is far from the current time, the FEC +driver will use hrtimer to configure PEROUT one second before the future +time. However, the hrtimer will not be canceled if the PEROUT is disabled +before the hrtimer expires. So the PEROUT will be configured when the +hrtimer expires, which is not as expected. Therefore, cancel the hrtimer +in fec_ptp_pps_disable() to fix this issue. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-2-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index fa88b47d526c0..7a5367ea94101 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -497,6 +497,8 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) + { + unsigned long flags; + ++ hrtimer_cancel(&fep->perout_timer); ++ + spin_lock_irqsave(&fep->tmreg_lock, flags); + writel(0, fep->hwp + FEC_TCSR(channel)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); +-- +2.51.0 + diff --git a/queue-6.17/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch b/queue-6.17/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch new file mode 100644 index 0000000000..9e3c90ea15 --- /dev/null +++ b/queue-6.17/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch @@ -0,0 +1,58 @@ +From ec2aaace8584afe9eafcba76c95caff7d8f56fbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:09 +0800 +Subject: net: fec: do not allow enabling PPS and PEROUT simultaneously + +From: Wei Fang + +[ Upstream commit c0a1f3d7e128e8d1b6c0fe09c68eac5ebcf677c8 ] + +In the current driver, PPS and PEROUT use the same channel to generate +the events, so they cannot be enabled at the same time. Otherwise, the +later configuration will overwrite the earlier configuration. Therefore, +when configuring PPS, the driver will check whether PEROUT is enabled. +Similarly, when configuring PEROUT, the driver will check whether PPS +is enabled. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-4-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index f31b1626c12f7..ed5d59abeb537 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -128,6 +128,12 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->perout_enable) { ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ dev_err(&fep->pdev->dev, "PEROUT is running"); ++ return -EBUSY; ++ } ++ + if (fep->pps_enable == enable) { + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return 0; +@@ -571,6 +577,12 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + } + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->pps_enable) { ++ dev_err(&fep->pdev->dev, "PPS is running"); ++ ret = -EBUSY; ++ goto unlock; ++ } ++ + if (fep->perout_enable) { + dev_err(&fep->pdev->dev, + "PEROUT has been enabled\n"); +-- +2.51.0 + diff --git a/queue-6.17/net-fec-do-not-register-pps-event-for-perout.patch b/queue-6.17/net-fec-do-not-register-pps-event-for-perout.patch new file mode 100644 index 0000000000..f843f95b07 --- /dev/null +++ b/queue-6.17/net-fec-do-not-register-pps-event-for-perout.patch @@ -0,0 +1,48 @@ +From e88d4903d313fca971622f6beb5e280f76aab188 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:10 +0800 +Subject: net: fec: do not register PPS event for PEROUT + +From: Wei Fang + +[ Upstream commit 9a060d0fac9e75524f72864adec6d8cdb70a5bca ] + +There are currently two situations that can trigger the PTP interrupt, +one is the PPS event, the other is the PEROUT event. However, the irq +handler fec_pps_interrupt() does not check the irq event type and +directly registers a PPS event into the system, but the event may be +a PEROUT event. This is incorrect because PEROUT is an output signal, +while PPS is the input of the kernel PPS system. Therefore, add a check +for the event type, if pps_enable is true, it means that the current +event is a PPS event, and then the PPS event is registered. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-5-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index ed5d59abeb537..4b7bad9a485df 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -718,8 +718,11 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) + fep->next_counter = (fep->next_counter + fep->reload_period) & + fep->cc.mask; + +- event.type = PTP_CLOCK_PPS; +- ptp_clock_event(fep->ptp_clock, &event); ++ if (fep->pps_enable) { ++ event.type = PTP_CLOCK_PPS; ++ ptp_clock_event(fep->ptp_clock, &event); ++ } ++ + return IRQ_HANDLED; + } + +-- +2.51.0 + diff --git a/queue-6.17/net-fec-do-not-update-perout-if-it-is-enabled.patch b/queue-6.17/net-fec-do-not-update-perout-if-it-is-enabled.patch new file mode 100644 index 0000000000..ce6cd1a391 --- /dev/null +++ b/queue-6.17/net-fec-do-not-update-perout-if-it-is-enabled.patch @@ -0,0 +1,137 @@ +From 53cd1a9a31fff9c37d5df6945309100d130617fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:08 +0800 +Subject: net: fec: do not update PEROUT if it is enabled + +From: Wei Fang + +[ Upstream commit e97faa0c20ea8840f45569ba434e30538fff8fc9 ] + +If the previously set PEROUT is already active, updating it will cause +the new PEROUT to start immediately instead of at the specified time. +This is because fep->reload_period is updated whithout check whether +the PEROUT is enabled, and the old PEROUT is not disabled. Therefore, +the pulse period will be updated immediately in the pulse interrupt +handler fec_pps_interrupt(). + +Currently, the driver does not support directly updating PEROUT and it +will make the logic be more complicated. To fix the current issue, add +a check before enabling the PEROUT, the driver will return an error if +PEROUT is enabled. If users wants to update a new PEROUT, they should +disable the old PEROUT first. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-3-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec.h | 1 + + drivers/net/ethernet/freescale/fec_ptp.c | 43 ++++++++++++++++++------ + 2 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index 5c8fdcef759ba..2601e0b074dd6 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -680,6 +680,7 @@ struct fec_enet_private { + unsigned int reload_period; + int pps_enable; + unsigned int next_counter; ++ bool perout_enable; + struct hrtimer perout_timer; + u64 perout_stime; + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index 7a5367ea94101..f31b1626c12f7 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -243,6 +243,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) + * the FEC_TCCR register in time and missed the start time. + */ + if (fep->perout_stime < curr_time + 100 * NSEC_PER_MSEC) { ++ fep->perout_enable = false; + dev_err(&fep->pdev->dev, "Current time is too close to the start time!\n"); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return -1; +@@ -500,6 +501,7 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) + hrtimer_cancel(&fep->perout_timer); + + spin_lock_irqsave(&fep->tmreg_lock, flags); ++ fep->perout_enable = false; + writel(0, fep->hwp + FEC_TCSR(channel)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + +@@ -531,6 +533,8 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + + return ret; + } else if (rq->type == PTP_CLK_REQ_PEROUT) { ++ u32 reload_period; ++ + /* Reject requests with unsupported flags */ + if (rq->perout.flags) + return -EOPNOTSUPP; +@@ -550,12 +554,14 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + return -EOPNOTSUPP; + } + +- fep->reload_period = div_u64(period_ns, 2); +- if (on && fep->reload_period) { ++ reload_period = div_u64(period_ns, 2); ++ if (on && reload_period) { ++ u64 perout_stime; ++ + /* Convert 1588 timestamp to ns*/ + start_time.tv_sec = rq->perout.start.sec; + start_time.tv_nsec = rq->perout.start.nsec; +- fep->perout_stime = timespec64_to_ns(&start_time); ++ perout_stime = timespec64_to_ns(&start_time); + + mutex_lock(&fep->ptp_clk_mutex); + if (!fep->ptp_clk_on) { +@@ -564,18 +570,35 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + return -EOPNOTSUPP; + } + spin_lock_irqsave(&fep->tmreg_lock, flags); ++ ++ if (fep->perout_enable) { ++ dev_err(&fep->pdev->dev, ++ "PEROUT has been enabled\n"); ++ ret = -EBUSY; ++ goto unlock; ++ } ++ + /* Read current timestamp */ + curr_time = timecounter_read(&fep->tc); +- spin_unlock_irqrestore(&fep->tmreg_lock, flags); +- mutex_unlock(&fep->ptp_clk_mutex); ++ if (perout_stime <= curr_time) { ++ dev_err(&fep->pdev->dev, ++ "Start time must be greater than current time\n"); ++ ret = -EINVAL; ++ goto unlock; ++ } + + /* Calculate time difference */ +- delta = fep->perout_stime - curr_time; ++ delta = perout_stime - curr_time; ++ fep->reload_period = reload_period; ++ fep->perout_stime = perout_stime; ++ fep->perout_enable = true; + +- if (fep->perout_stime <= curr_time) { +- dev_err(&fep->pdev->dev, "Start time must larger than current time!\n"); +- return -EINVAL; +- } ++unlock: ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ mutex_unlock(&fep->ptp_clk_mutex); ++ ++ if (ret) ++ return ret; + + /* Because the timer counter of FEC only has 31-bits, correspondingly, + * the time comparison register FEC_TCCR also only low 31 bits can be +-- +2.51.0 + diff --git a/queue-6.17/net-lan966x-fix-the-initialization-of-taprio.patch b/queue-6.17/net-lan966x-fix-the-initialization-of-taprio.patch new file mode 100644 index 0000000000..15c70565fa --- /dev/null +++ b/queue-6.17/net-lan966x-fix-the-initialization-of-taprio.patch @@ -0,0 +1,56 @@ +From 14208465038283a11780d2c216b53aa11c9893f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 07:14:11 +0100 +Subject: net: lan966x: Fix the initialization of taprio + +From: Horatiu Vultur + +[ Upstream commit 9780f535f8e0f20b4632b5a173ead71aa8f095d2 ] + +To initialize the taprio block in lan966x, it is required to configure +the register REVISIT_DLY. The purpose of this register is to set the +delay before revisit the next gate and the value of this register depends +on the system clock. The problem is that the we calculated wrong the value +of the system clock period in picoseconds. The actual system clock is +~165.617754MHZ and this correspond to a period of 6038 pico seconds and +not 15125 as currently set. + +Fixes: e462b2717380b4 ("net: lan966x: Add offload support for taprio") +Signed-off-by: Horatiu Vultur +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121061411.810571-1-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +index b4377b8613c3a..8c40db90ee8f6 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +@@ -1,11 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0+ + + #include ++#include + + #include "lan966x_main.h" + #include "vcap_api.h" + #include "vcap_api_client.h" + ++#define LAN9X66_CLOCK_RATE 165617754 ++ + #define LAN966X_MAX_PTP_ID 512 + + /* Represents 1ppm adjustment in 2^59 format with 6.037735849ns as reference +@@ -1126,5 +1129,5 @@ void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, + u32 lan966x_ptp_get_period_ps(void) + { + /* This represents the system clock period in picoseconds */ +- return 15125; ++ return PICO / LAN9X66_CLOCK_RATE; + } +-- +2.51.0 + diff --git a/queue-6.17/net-mctp-unconditionally-set-skb-dev-on-dst-output.patch b/queue-6.17/net-mctp-unconditionally-set-skb-dev-on-dst-output.patch new file mode 100644 index 0000000000..a34eae8faa --- /dev/null +++ b/queue-6.17/net-mctp-unconditionally-set-skb-dev-on-dst-output.patch @@ -0,0 +1,46 @@ +From 325afd0b13d76d93dc4c38c5e7f138a334334270 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 14:48:54 +0800 +Subject: net: mctp: unconditionally set skb->dev on dst output + +From: Jeremy Kerr + +[ Upstream commit b3e528a5811bbc8246dbdb962f0812dc9b721681 ] + +On transmit, we are currently relying on skb->dev being set by +mctp_local_output() when we first set up the skb destination fields. +However, forwarded skbs do not use the local_output path, so will retain +their incoming netdev as their ->dev on tx. This does not work when +we're forwarding between interfaces. + +Set skb->dev unconditionally in the transmit path, to allow for proper +forwarding. + +We keep the skb->dev initialisation in mctp_local_output(), as we use it +for fragmentation. + +Fixes: 269936db5eb3 ("net: mctp: separate routing database from routing operations") +Suggested-by: Vince Chang +Signed-off-by: Jeremy Kerr +Link: https://patch.msgid.link/20251125-dev-forward-v1-1-54ecffcd0616@codeconstruct.com.au +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mctp/route.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/mctp/route.c b/net/mctp/route.c +index 4d314e062ba9c..2ac4011a953ff 100644 +--- a/net/mctp/route.c ++++ b/net/mctp/route.c +@@ -623,6 +623,7 @@ static int mctp_dst_output(struct mctp_dst *dst, struct sk_buff *skb) + + skb->protocol = htons(ETH_P_MCTP); + skb->pkt_type = PACKET_OUTGOING; ++ skb->dev = dst->dev->dev; + + if (skb->len > dst->mtu) { + kfree_skb(skb); +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5e-fix-validation-logic-in-rate-limiting.patch b/queue-6.17/net-mlx5e-fix-validation-logic-in-rate-limiting.patch new file mode 100644 index 0000000000..6070c5e278 --- /dev/null +++ b/queue-6.17/net-mlx5e-fix-validation-logic-in-rate-limiting.patch @@ -0,0 +1,63 @@ +From 72c301752b56dedd9521231a80fb677a7a065f92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:00:43 -0800 +Subject: net/mlx5e: Fix validation logic in rate limiting + +From: Danielle Costantino + +[ Upstream commit d2099d9f16dbfa1c5266d4230ff7860047bb0b68 ] + +The rate limiting validation condition currently checks the output +variable max_bw_value[i] instead of the input value +maxrate->tc_maxrate[i]. This causes the validation to compare an +uninitialized or stale value rather than the actual requested rate. + +The condition should check the input rate to properly validate against +the upper limit: + + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + +This aligns with the pattern used in the first branch, which correctly +checks maxrate->tc_maxrate[i] against upper_limit_mbps. + +The current implementation can lead to unreliable validation behavior: + +- For rates between 25.5 Gbps and 255 Gbps, if max_bw_value[i] is 0 + from initialization, the GBPS path may be taken regardless of whether + the actual rate is within bounds + +- When processing multiple TCs (i > 0), max_bw_value[i] contains the + value computed for the previous TC, affecting the validation logic + +- The overflow check for rates exceeding 255 Gbps may not trigger + consistently depending on previous array values + +This patch ensures the validation correctly examines the requested rate +value for proper bounds checking. + +Fixes: 43b27d1bd88a ("net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps") +Signed-off-by: Danielle Costantino +Reviewed-by: Gal Pressman +Link: https://patch.msgid.link/20251124180043.2314428-1-dcostantino@meta.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 9b93da4d52f64..cf8f14ce4cd50 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -627,7 +627,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else if (max_bw_value[i] <= upper_limit_gbps) { ++ } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; +-- +2.51.0 + diff --git a/queue-6.17/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch b/queue-6.17/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch new file mode 100644 index 0000000000..e36d353e76 --- /dev/null +++ b/queue-6.17/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch @@ -0,0 +1,42 @@ +From 8e41d31997f805165ac96ff12fedf8069a5a9271 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 14:17:13 +0000 +Subject: net: phy: mxl-gpy: fix bogus error on USXGMII and integrated PHY + +From: Daniel Golle + +[ Upstream commit ec3803b5917b6ff2f86ea965d0985c95d8a85119 ] + +As the interface mode doesn't need to be updated on PHYs connected with +USXGMII and integrated PHYs, gpy_update_interface() should just return 0 +in these cases rather than -EINVAL which has wrongly been introduced by +commit 7a495dde27ebc ("net: phy: mxl-gpy: Change gpy_update_interface() +function return type"), as this breaks support for those PHYs. + +Fixes: 7a495dde27ebc ("net: phy: mxl-gpy: Change gpy_update_interface() function return type") +Signed-off-by: Daniel Golle +Reviewed-by: Maxime Chevallier +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/f744f721a1fcc5e2e936428c62ff2c7d94d2a293.1763648168.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mxl-gpy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c +index 0c8dc16ee7bde..221b315203d06 100644 +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -540,7 +540,7 @@ static int gpy_update_interface(struct phy_device *phydev) + /* Interface mode is fixed for USXGMII and integrated PHY */ + if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || + phydev->interface == PHY_INTERFACE_MODE_INTERNAL) +- return -EINVAL; ++ return 0; + + /* Automatically switch SERDES interface between SGMII and 2500-BaseX + * according to speed. Disable ANEG in 2500-BaseX mode. +-- +2.51.0 + diff --git a/queue-6.17/net-phy-mxl-gpy-fix-link-properties-on-usxgmii-and-i.patch b/queue-6.17/net-phy-mxl-gpy-fix-link-properties-on-usxgmii-and-i.patch new file mode 100644 index 0000000000..a2283604b5 --- /dev/null +++ b/queue-6.17/net-phy-mxl-gpy-fix-link-properties-on-usxgmii-and-i.patch @@ -0,0 +1,65 @@ +From 528a61ad10c14ffaf78deddaa4f96704f42351dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 15:02:19 +0000 +Subject: net: phy: mxl-gpy: fix link properties on USXGMII and internal PHYs + +From: Daniel Golle + +[ Upstream commit 081156ce13f8fa4e97b5148dc54d8c0ddf02117b ] + +gpy_update_interface() returns early in case the PHY is internal or +connected via USXGMII. In this case the gigabit master/slave property +as well as MDI/MDI-X status also won't be read which seems wrong. +Always read those properties by moving the logic to retrieve them to +gpy_read_status(). + +Fixes: fd8825cd8c6fc ("net: phy: mxl-gpy: Add PHY Auto/MDI/MDI-X set driver for GPY211 chips") +Fixes: 311abcdddc00a ("net: phy: add support to get Master-Slave configuration") +Suggested-by: "Russell King (Oracle)" +Signed-off-by: Daniel Golle +Link: https://patch.msgid.link/71fccf3f56742116eb18cc070d2a9810479ea7f9.1763650701.git.daniel@makrotopia.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mxl-gpy.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c +index 221b315203d06..2a873f791733a 100644 +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -578,13 +578,7 @@ static int gpy_update_interface(struct phy_device *phydev) + break; + } + +- if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) { +- ret = genphy_read_master_slave(phydev); +- if (ret < 0) +- return ret; +- } +- +- return gpy_update_mdix(phydev); ++ return 0; + } + + static int gpy_read_status(struct phy_device *phydev) +@@ -639,6 +633,16 @@ static int gpy_read_status(struct phy_device *phydev) + ret = gpy_update_interface(phydev); + if (ret < 0) + return ret; ++ ++ if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) { ++ ret = genphy_read_master_slave(phydev); ++ if (ret < 0) ++ return ret; ++ } ++ ++ ret = gpy_update_mdix(phydev); ++ if (ret < 0) ++ return ret; + } + + return 0; +-- +2.51.0 + diff --git a/queue-6.17/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch b/queue-6.17/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch new file mode 100644 index 0000000000..a2b1602de3 --- /dev/null +++ b/queue-6.17/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch @@ -0,0 +1,47 @@ +From 816f7a6e37ce885f81ee19a84418eb3f190e341c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 12:38:34 +0000 +Subject: net: sxgbe: fix potential NULL dereference in sxgbe_rx() + +From: Alexey Kodanev + +[ Upstream commit f5bce28f6b9125502abec4a67d68eabcd24b3b17 ] + +Currently, when skb is null, the driver prints an error and then +dereferences skb on the next line. + +To fix this, let's add a 'break' after the error message to switch +to sxgbe_rx_refill(), which is similar to the approach taken by the +other drivers in this particular case, e.g. calxeda with xgmac_rx(). + +Found during a code review. + +Fixes: 1edb9ca69e8a ("net: sxgbe: add basic framework for Samsung 10Gb ethernet driver") +Signed-off-by: Alexey Kodanev +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121123834.97748-1-aleksei.kodanev@bell-sw.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index 75bad561b3525..849c5a6c2af1e 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -1521,8 +1521,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) + + skb = priv->rxq[qnum]->rx_skbuff[entry]; + +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + netdev_err(priv->dev, "rx descriptor is not consistent\n"); ++ break; ++ } + + prefetch(skb->data - NET_IP_ALIGN); + priv->rxq[qnum]->rx_skbuff[entry] = NULL; +-- +2.51.0 + diff --git a/queue-6.17/net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch b/queue-6.17/net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch new file mode 100644 index 0000000000..dc214f9b99 --- /dev/null +++ b/queue-6.17/net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch @@ -0,0 +1,39 @@ +From 51ad1881a6b15a28ef54c2ff651b4d4ab72880f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 15:09:00 +0800 +Subject: net: wwan: mhi: Keep modem name match with Foxconn T99W640 + +From: Slark Xiao + +[ Upstream commit 4fcb8ab4a09b1855dbfd7062605dd13abd64c086 ] + +Correct it since M.2 device T99W640 has updated from T99W515. +We need to align it with MHI side otherwise this modem can't +get the network. + +Fixes: ae5a34264354 ("bus: mhi: host: pci_generic: Fix the modem name of Foxconn T99W640") +Signed-off-by: Slark Xiao +Reviewed-by: Loic Poulain +Link: https://patch.msgid.link/20251125070900.33324-1-slark_xiao@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/wwan/mhi_wwan_mbim.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c +index c814fbd756a1e..f8bc9a39bfa30 100644 +--- a/drivers/net/wwan/mhi_wwan_mbim.c ++++ b/drivers/net/wwan/mhi_wwan_mbim.c +@@ -98,7 +98,7 @@ static struct mhi_mbim_link *mhi_mbim_get_link_rcu(struct mhi_mbim_context *mbim + static int mhi_mbim_get_link_mux_id(struct mhi_controller *cntrl) + { + if (strcmp(cntrl->name, "foxconn-dw5934e") == 0 || +- strcmp(cntrl->name, "foxconn-t99w515") == 0) ++ strcmp(cntrl->name, "foxconn-t99w640") == 0) + return WDS_BIND_MUX_DATA_PORT_MUX_ID; + + return 0; +-- +2.51.0 + diff --git a/queue-6.17/ovl-fail-ovl_lock_rename_workdir-if-either-target-is.patch b/queue-6.17/ovl-fail-ovl_lock_rename_workdir-if-either-target-is.patch new file mode 100644 index 0000000000..7b4386c575 --- /dev/null +++ b/queue-6.17/ovl-fail-ovl_lock_rename_workdir-if-either-target-is.patch @@ -0,0 +1,44 @@ +From 886f8e95661e175c01b8abb1971a06ce258936aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Nov 2025 12:22:35 +1100 +Subject: ovl: fail ovl_lock_rename_workdir() if either target is unhashed + +From: NeilBrown + +[ Upstream commit e9c70084a64e51b65bb68f810692a03dc8bedffa ] + +As well as checking that the parent hasn't changed after getting the +lock we need to check that the dentry hasn't been unhashed. +Otherwise we might try to rename something that has been removed. + +Reported-by: syzbot+bfc9a0ccf0de47d04e8c@syzkaller.appspotmail.com +Fixes: d2c995581c7c ("ovl: Call ovl_create_temp() without lock held.") +Signed-off-by: NeilBrown +Link: https://patch.msgid.link/176429295510.634289.1552337113663461690@noble.neil.brown.name +Tested-by: syzbot+bfc9a0ccf0de47d04e8c@syzkaller.appspotmail.com +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/overlayfs/util.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index 41033bac96cbb..ab652164ffc90 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -1234,9 +1234,9 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *work, + goto err; + if (trap) + goto err_unlock; +- if (work && work->d_parent != workdir) ++ if (work && (work->d_parent != workdir || d_unhashed(work))) + goto err_unlock; +- if (upper && upper->d_parent != upperdir) ++ if (upper && (upper->d_parent != upperdir || d_unhashed(upper))) + goto err_unlock; + + return 0; +-- +2.51.0 + diff --git a/queue-6.17/platform-x86-intel-punit_ipc-fix-memory-corruption.patch b/queue-6.17/platform-x86-intel-punit_ipc-fix-memory-corruption.patch new file mode 100644 index 0000000000..efe7c90166 --- /dev/null +++ b/queue-6.17/platform-x86-intel-punit_ipc-fix-memory-corruption.patch @@ -0,0 +1,46 @@ +From 6716124e0974ae8d44a6c7e323067e4e731f5e4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 20:51:28 +0300 +Subject: platform/x86: intel: punit_ipc: fix memory corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit 9b9c0adbc3f8a524d291baccc9d0c04097fb4869 ] + +This passes the address of the pointer "&punit_ipcdev" when the intent +was to pass the pointer itself "punit_ipcdev" (without the ampersand). +This means that the: + + complete(&ipcdev->cmd_complete); + +in intel_punit_ioc() will write to a wrong memory address corrupting it. + +Fixes: fdca4f16f57d ("platform:x86: add Intel P-Unit mailbox IPC driver") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aSCmoBipSQ_tlD-D@stanley.mountain +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/punit_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/punit_ipc.c b/drivers/platform/x86/intel/punit_ipc.c +index bafac8aa2baf6..14513010daadf 100644 +--- a/drivers/platform/x86/intel/punit_ipc.c ++++ b/drivers/platform/x86/intel/punit_ipc.c +@@ -250,7 +250,7 @@ static int intel_punit_ipc_probe(struct platform_device *pdev) + } else { + ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc, + IRQF_NO_SUSPEND, "intel_punit_ipc", +- &punit_ipcdev); ++ punit_ipcdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", irq); + return ret; +-- +2.51.0 + diff --git a/queue-6.17/riscv-dts-allwinner-d1-fix-vlenb-property.patch b/queue-6.17/riscv-dts-allwinner-d1-fix-vlenb-property.patch new file mode 100644 index 0000000000..f3add535ce --- /dev/null +++ b/queue-6.17/riscv-dts-allwinner-d1-fix-vlenb-property.patch @@ -0,0 +1,40 @@ +From 44cb1109a21c44c2534eaf80e69157b8a0eabdd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Nov 2025 23:35:06 +0300 +Subject: riscv: dts: allwinner: d1: fix vlenb property + +From: Sergey Matyukevich + +[ Upstream commit 9f393d8e757f79060baf4b2e703bd6b2d0d8d323 ] + +According to [1], the C906 vector registers are 128 bits wide. +The 'thead,vlenb' property specifies the vector register length +in bytes, so its value must be set to 16. + +[1] https://dl.linux-sunxi.org/D1/Xuantie_C906_R1S0_User_Manual.pdf + +Fixes: ce1daeeba600 ("riscv: dts: allwinner: Add xtheadvector to the D1/D1s devicetree") +Signed-off-by: Sergey Matyukevich +Link: https://patch.msgid.link/20251119203508.1032716-1-geomatsi@gmail.com +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi +index 6367112e614a1..a7442a508433d 100644 +--- a/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi ++++ b/arch/riscv/boot/dts/allwinner/sun20i-d1s.dtsi +@@ -28,7 +28,7 @@ + riscv,isa-base = "rv64i"; + riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr", + "zifencei", "zihpm", "xtheadvector"; +- thead,vlenb = <128>; ++ thead,vlenb = <16>; + #cooling-cells = <2>; + + cpu0_intc: interrupt-controller { +-- +2.51.0 + diff --git a/queue-6.17/series b/queue-6.17/series new file mode 100644 index 0000000000..3edb53dfe0 --- /dev/null +++ b/queue-6.17/series @@ -0,0 +1,52 @@ +can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch +can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-24056 +bluetooth-btusb-mediatek-fix-kernel-crash-when-relea.patch +bluetooth-hci_core-fix-triggering-cmd_timer-for-hci_.patch +bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch +bluetooth-hci_core-lookup-hci_conn-on-rx-path-on-pro.patch +bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch +veth-reduce-xdp-no_direct-return-section-to-fix-race.patch +drm-bridge-sii902x-fix-hdmi-detection-with-drm_bridg.patch +net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch +platform-x86-intel-punit_ipc-fix-memory-corruption.patch +net-aquantia-add-missing-descriptor-cache-invalidati.patch +net-phy-mxl-gpy-fix-link-properties-on-usxgmii-and-i.patch +net-lan966x-fix-the-initialization-of-taprio.patch +drm-xe-fix-conversion-from-clock-ticks-to-millisecon.patch +net-mlx5e-fix-validation-logic-in-rate-limiting.patch +team-move-team-device-type-change-at-the-end-of-team.patch +net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch +xsk-avoid-overwriting-skb-fields-for-multi-buffer-tr.patch +xsk-avoid-data-corruption-on-cq-descriptor-number.patch +drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch +dma-direct-fix-missing-sg_dma_len-assignment-in-p2pd.patch +net-wwan-mhi-keep-modem-name-match-with-foxconn-t99w.patch +net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch +eth-fbnic-fix-counter-roll-over-issue.patch +net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch +net-mctp-unconditionally-set-skb-dev-on-dst-output.patch +net-fec-cancel-perout_timer-when-perout-is-disabled.patch +net-fec-do-not-update-perout-if-it-is-enabled.patch +net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch +net-fec-do-not-register-pps-event-for-perout.patch +iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch +xhci-sideband-add-api-to-trace-sideband-usage.patch +xhci-sideband-fix-race-condition-in-sideband-unregis.patch +usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch +mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch +mailbox-mtk-cmdq-refine-dma-address-handling-for-the.patch +mailbox-pcc-don-t-zero-error-register.patch +spi-spi-cadence-quadspi-remove-duplicate-pm_runtime_.patch +spi-spi-cadence-quadspi-enable-pm-runtime-earlier-to.patch +fs-namespace-fix-reference-leak-in-grab_requested_mn.patch +afs-fix-delayed-allocation-of-a-cell-s-anonymous-key.patch +ovl-fail-ovl_lock_rename_workdir-if-either-target-is.patch +riscv-dts-allwinner-d1-fix-vlenb-property.patch +spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch +spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch +spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch +spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch +spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch +afs-fix-uninit-var-in-afs_alloc_anon_key.patch diff --git a/queue-6.17/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch b/queue-6.17/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch new file mode 100644 index 0000000000..85cf7733fa --- /dev/null +++ b/queue-6.17/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch @@ -0,0 +1,42 @@ +From 24bf9126ca51b4d12eaf5d5ad3c77409d23db7de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 09:58:52 +0800 +Subject: spi: amlogic-spifc-a1: Handle devm_pm_runtime_enable() errors + +From: Haotian Zhang + +[ Upstream commit a90903c2a3c38bce475f46ea3f93dbf6a9971553 ] + +devm_pm_runtime_enable() can fail due to memory allocation. The current +code ignores its return value, potentially causing runtime PM operations +to fail silently after autosuspend configuration. + +Check the return value of devm_pm_runtime_enable() and return on failure. + +Fixes: 909fac05b926 ("spi: add support for Amlogic A1 SPI Flash Controller") +Signed-off-by: Haotian Zhang +Link: https://patch.msgid.link/20251124015852.937-1-vulab@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-amlogic-spifc-a1.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-amlogic-spifc-a1.c b/drivers/spi/spi-amlogic-spifc-a1.c +index 18c9aa2cbc290..eb503790017b2 100644 +--- a/drivers/spi/spi-amlogic-spifc-a1.c ++++ b/drivers/spi/spi-amlogic-spifc-a1.c +@@ -353,7 +353,9 @@ static int amlogic_spifc_a1_probe(struct platform_device *pdev) + + pm_runtime_set_autosuspend_delay(spifc->dev, 500); + pm_runtime_use_autosuspend(spifc->dev); +- devm_pm_runtime_enable(spifc->dev); ++ ret = devm_pm_runtime_enable(spifc->dev); ++ if (ret) ++ return ret; + + ctrl->num_chipselect = 1; + ctrl->dev.of_node = pdev->dev.of_node; +-- +2.51.0 + diff --git a/queue-6.17/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch b/queue-6.17/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch new file mode 100644 index 0000000000..a156afa79f --- /dev/null +++ b/queue-6.17/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch @@ -0,0 +1,68 @@ +From ffe3e2eceaff6a3425916658b4d249e302ed2745 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 01:08:35 +1100 +Subject: spi: bcm63xx: fix premature CS deassertion on RX-only transactions + +From: Hang Zhou <929513338@qq.com> + +[ Upstream commit fd9862f726aedbc2f29a29916cabed7bcf5cadb6 ] + +On BCM6358 (and also observed on BCM6368) the controller appears to +only generate as many SPI clocks as bytes that have been written into +the TX FIFO. For RX-only transfers the driver programs the transfer +length in SPI_MSG_CTL but does not write anything into the FIFO, so +chip select is deasserted early and the RX transfer segment is never +fully clocked in. + +A concrete failing case is a three-transfer MAC address read from +SPI-NOR: + - TX 0x03 (read command) + - TX 3-byte address + - RX 6 bytes (MAC) + +In contrast, a two-transfer JEDEC-ID read (0x9f + 6-byte RX) works +because the driver uses prepend_len and writes dummy bytes into the +TX FIFO for the RX part. + +Fix this by writing 0xff dummy bytes into the TX FIFO for RX-only +segments so that the number of bytes written to the FIFO matches the +total message length seen by the controller. + +Fixes: b17de076062a ("spi/bcm63xx: work around inability to keep CS up") + +Signed-off-by: Hang Zhou <929513338@qq.com> +Link: https://patch.msgid.link/tencent_7AC88FCB3076489A4A7E6C2163DF1ACF8D06@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm63xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c +index b56210734caaf..2e3c62f12bef9 100644 +--- a/drivers/spi/spi-bcm63xx.c ++++ b/drivers/spi/spi-bcm63xx.c +@@ -247,6 +247,20 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + + if (t->rx_buf) { + do_rx = true; ++ ++ /* ++ * In certain hardware implementations, there appears to be a ++ * hidden accumulator that tracks the number of bytes written into ++ * the hardware FIFO, and this accumulator overrides the length in ++ * the SPI_MSG_CTL register. ++ * ++ * Therefore, for read-only transfers, we need to write some dummy ++ * value into the FIFO to keep the accumulator tracking the correct ++ * length. ++ */ ++ if (!t->tx_buf) ++ memset_io(bs->tx_io + len, 0xFF, t->len); ++ + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; +-- +2.51.0 + diff --git a/queue-6.17/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch b/queue-6.17/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch new file mode 100644 index 0000000000..63caee96d7 --- /dev/null +++ b/queue-6.17/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch @@ -0,0 +1,78 @@ +From 0cbdad79d645ad14c27615674a1a49a28bac77be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 21:25:01 +0100 +Subject: spi: nxp-fspi: Propagate fwnode in ACPI case as well + +From: Andy Shevchenko + +[ Upstream commit 40ad64ac25bb736740f895d99a4aebbda9b80991 ] + +Propagate fwnode of the ACPI device to the SPI controller Linux device. +Currently only OF case propagates fwnode to the controller. + +While at it, replace several calls to dev_fwnode() with a single one +cached in a local variable, and unify checks for fwnode type by using +is_*_node() APIs. + +Fixes: 55ab8487e01d ("spi: spi-nxp-fspi: Add ACPI support") +Signed-off-by: Andy Shevchenko +Reviewed-by: Haibo Chen +Link: https://patch.msgid.link/20251126202501.2319679-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index fcf10be66d391..f96638cae1d94 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -1270,7 +1270,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + { + struct spi_controller *ctlr; + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; ++ struct fwnode_handle *fwnode = dev_fwnode(dev); + struct resource *res; + struct nxp_fspi *f; + int ret, irq; +@@ -1292,7 +1292,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, f); + + /* find the resources - configuration register address space */ +- if (is_acpi_node(dev_fwnode(f->dev))) ++ if (is_acpi_node(fwnode)) + f->iobase = devm_platform_ioremap_resource(pdev, 0); + else + f->iobase = devm_platform_ioremap_resource_byname(pdev, "fspi_base"); +@@ -1300,7 +1300,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + return PTR_ERR(f->iobase); + + /* find the resources - controller memory mapped space */ +- if (is_acpi_node(dev_fwnode(f->dev))) ++ if (is_acpi_node(fwnode)) + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + else + res = platform_get_resource_byname(pdev, +@@ -1313,7 +1313,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + f->memmap_phy_size = resource_size(res); + + /* find the clocks */ +- if (dev_of_node(&pdev->dev)) { ++ if (is_of_node(fwnode)) { + f->clk_en = devm_clk_get(dev, "fspi_en"); + if (IS_ERR(f->clk_en)) + return PTR_ERR(f->clk_en); +@@ -1366,7 +1366,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + else + ctlr->mem_caps = &nxp_fspi_mem_caps; + +- ctlr->dev.of_node = np; ++ device_set_node(&ctlr->dev, fwnode); + + ret = devm_add_action_or_reset(dev, nxp_fspi_cleanup, f); + if (ret) +-- +2.51.0 + diff --git a/queue-6.17/spi-spi-cadence-quadspi-enable-pm-runtime-earlier-to.patch b/queue-6.17/spi-spi-cadence-quadspi-enable-pm-runtime-earlier-to.patch new file mode 100644 index 0000000000..f608a38a1e --- /dev/null +++ b/queue-6.17/spi-spi-cadence-quadspi-enable-pm-runtime-earlier-to.patch @@ -0,0 +1,64 @@ +From fef97a3086e4ed7ab8550257a9236d845d6f4db4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 21:41:45 +0530 +Subject: spi: spi-cadence-quadspi: Enable pm runtime earlier to avoid + imbalance + +From: Anurag Dutta + +[ Upstream commit f1eb4e792bb1ee3dcdffa66f8a83a4867cda2dd3 ] + +The "probe_setup_failed" label calls pm_runtime_disable(), but +pm_runtime_enable() was placed after a possible jump to this label. +When cqspi_setup_flash() fails, control jumps to the label without +pm_runtime_enable() being called, leading to unbalanced PM runtime +reference counting. + +Move pm_runtime_enable() and associated calls above the first +possible branch to "probe_setup_failed" to ensure balanced +enable/disable calls across all error paths. + +Fixes: 30dbc1c8d50f ("spi: cadence-qspi: defer runtime support on socfpga if reset bit is enabled") +Signed-off-by: Anurag Dutta +Link: https://patch.msgid.link/20251105161146.2019090-2-a-dutta@ti.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-cadence-quadspi.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +index d7720931403c2..4a5a83dc8fe37 100644 +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -1981,6 +1981,13 @@ static int cqspi_probe(struct platform_device *pdev) + cqspi->current_cs = -1; + cqspi->sclk = 0; + ++ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { ++ pm_runtime_enable(dev); ++ pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT); ++ pm_runtime_use_autosuspend(dev); ++ pm_runtime_get_noresume(dev); ++ } ++ + ret = cqspi_setup_flash(cqspi); + if (ret) { + dev_err(dev, "failed to setup flash parameters %d\n", ret); +@@ -1998,13 +2005,6 @@ static int cqspi_probe(struct platform_device *pdev) + goto probe_dma_failed; + } + +- if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { +- pm_runtime_enable(dev); +- pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT); +- pm_runtime_use_autosuspend(dev); +- pm_runtime_get_noresume(dev); +- } +- + ret = spi_register_controller(host); + if (ret) { + dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret); +-- +2.51.0 + diff --git a/queue-6.17/spi-spi-cadence-quadspi-remove-duplicate-pm_runtime_.patch b/queue-6.17/spi-spi-cadence-quadspi-remove-duplicate-pm_runtime_.patch new file mode 100644 index 0000000000..e55866aeef --- /dev/null +++ b/queue-6.17/spi-spi-cadence-quadspi-remove-duplicate-pm_runtime_.patch @@ -0,0 +1,42 @@ +From fd7c7f7167b22dd1eaaabcea3643ba2802943067 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 21:41:46 +0530 +Subject: spi: spi-cadence-quadspi: Remove duplicate + pm_runtime_put_autosuspend() call + +From: Anurag Dutta + +[ Upstream commit 10eaa4c4a257944e9b30d13fda7d09164a70866d ] + +Fix runtime PM usage count underflow caused by calling +pm_runtime_put_autosuspend() twice with only one corresponding +pm_runtime_get_noresume() call. This triggers the warning: +"Runtime PM usage count underflow!" + +Remove the duplicate put call to balance the runtime PM reference +counting. + +Fixes: 30dbc1c8d50f ("spi: cadence-qspi: defer runtime support on socfpga if reset bit is enabled") +Signed-off-by: Anurag Dutta +Link: https://patch.msgid.link/20251105161146.2019090-3-a-dutta@ti.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-cadence-quadspi.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +index ce0f605ab688b..d7720931403c2 100644 +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -2012,7 +2012,6 @@ static int cqspi_probe(struct platform_device *pdev) + } + + if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { +- pm_runtime_put_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + } +-- +2.51.0 + diff --git a/queue-6.17/spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch b/queue-6.17/spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch new file mode 100644 index 0000000000..e7cacda76d --- /dev/null +++ b/queue-6.17/spi-spi-nxp-fspi-add-oct-dtr-mode-support.patch @@ -0,0 +1,79 @@ +From edeac5ea6317a394d6d398c545105ead4a259d7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Sep 2025 15:27:10 +0800 +Subject: spi: spi-nxp-fspi: Add OCT-DTR mode support + +From: Haibo Chen + +[ Upstream commit 0f67557763accbdd56681f17ed5350735198c57b ] + +Add OCT-DTR mode support in default, since flexspi do not supports +swapping bytes on a 16 bit boundary in OCT-DTR mode, so mark swap16 +as false. + +lx2160a do not support DQS, so add a quirk to disable DTR mode for this +platform. + +Signed-off-by: Haibo Chen +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20250917-flexspi-ddr-v2-5-bb9fe2a01889@nxp.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index ab13f11242c3c..fcf10be66d391 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -330,6 +330,8 @@ + + /* Access flash memory using IP bus only */ + #define FSPI_QUIRK_USE_IP_ONLY BIT(0) ++/* Disable DTR */ ++#define FSPI_QUIRK_DISABLE_DTR BIT(1) + + struct nxp_fspi_devtype_data { + unsigned int rxfifo; +@@ -344,7 +346,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = { + .rxfifo = SZ_512, /* (64 * 64 bits) */ + .txfifo = SZ_1K, /* (128 * 64 bits) */ + .ahb_buf_size = SZ_2K, /* (256 * 64 bits) */ +- .quirks = 0, ++ .quirks = FSPI_QUIRK_DISABLE_DTR, + .lut_num = 32, + .little_endian = true, /* little-endian */ + }; +@@ -1236,6 +1238,13 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = { + }; + + static const struct spi_controller_mem_caps nxp_fspi_mem_caps = { ++ .dtr = true, ++ .swap16 = false, ++ .per_op_freq = true, ++}; ++ ++static const struct spi_controller_mem_caps nxp_fspi_mem_caps_disable_dtr = { ++ .dtr = false, + .per_op_freq = true, + }; + +@@ -1351,7 +1360,12 @@ static int nxp_fspi_probe(struct platform_device *pdev) + ctlr->bus_num = -1; + ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; + ctlr->mem_ops = &nxp_fspi_mem_ops; +- ctlr->mem_caps = &nxp_fspi_mem_caps; ++ ++ if (f->devtype_data->quirks & FSPI_QUIRK_DISABLE_DTR) ++ ctlr->mem_caps = &nxp_fspi_mem_caps_disable_dtr; ++ else ++ ctlr->mem_caps = &nxp_fspi_mem_caps; ++ + ctlr->dev.of_node = np; + + ret = devm_add_action_or_reset(dev, nxp_fspi_cleanup, f); +-- +2.51.0 + diff --git a/queue-6.17/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch b/queue-6.17/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch new file mode 100644 index 0000000000..7a9b8452d7 --- /dev/null +++ b/queue-6.17/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch @@ -0,0 +1,44 @@ +From 4b44046410101ea85b613578a0f31da808ba0c56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 10:50:27 +0100 +Subject: spi: tegra114: remove Kconfig dependency on TEGRA20_APB_DMA + +From: Francesco Lavra + +[ Upstream commit 3dcf44ab56e1d3ca3532083c0d5390b758e45b45 ] + +This driver runs also on Tegra SoCs without a Tegra20 APB DMA controller +(e.g. Tegra234). +Remove the Kconfig dependency on TEGRA20_APB_DMA; in addition, amend the +help text to reflect the fact that this driver works on SoCs different from +Tegra114. + +Fixes: bb9667d8187b ("arm64: tegra: Add SPI device tree nodes for Tegra234") +Signed-off-by: Francesco Lavra +Link: https://patch.msgid.link/20251126095027.4102004-1-flavra@baylibre.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 891729c9c5642..9f20cb75bb856 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -1170,10 +1170,10 @@ config SPI_TEGRA210_QUAD + + config SPI_TEGRA114 + tristate "NVIDIA Tegra114 SPI Controller" +- depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST ++ depends on ARCH_TEGRA || COMPILE_TEST + depends on RESET_CONTROLLER + help +- SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller ++ SPI controller driver for NVIDIA Tegra114 and later SoCs. This controller + is different than the older SoCs SPI controller and also register interface + get changed with this controller. + +-- +2.51.0 + diff --git a/queue-6.17/team-move-team-device-type-change-at-the-end-of-team.patch b/queue-6.17/team-move-team-device-type-change-at-the-end-of-team.patch new file mode 100644 index 0000000000..96cd899eb3 --- /dev/null +++ b/queue-6.17/team-move-team-device-type-change-at-the-end-of-team.patch @@ -0,0 +1,118 @@ +From b93ffa9bed3f9a03fe675480dbbf1c6040180d3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 02:20:27 +0200 +Subject: team: Move team device type change at the end of team_port_add + +From: Nikola Z. Ivanov + +[ Upstream commit 0ae9cfc454ea5ead5f3ddbdfe2e70270d8e2c8ef ] + +Attempting to add a port device that is already up will expectedly fail, +but not before modifying the team device header_ops. + +In the case of the syzbot reproducer the gre0 device is +already in state UP when it attempts to add it as a +port device of team0, this fails but before that +header_ops->create of team0 is changed from eth_header to ipgre_header +in the call to team_dev_type_check_change. + +Later when we end up in ipgre_header() struct ip_tunnel* points to nonsense +as the private data of the device still holds a struct team. + +Example sequence of iproute2 commands to reproduce the hang/BUG(): +ip link add dev team0 type team +ip link add dev gre0 type gre +ip link set dev gre0 up +ip link set dev gre0 master team0 +ip link set dev team0 up +ping -I team0 1.1.1.1 + +Move team_dev_type_check_change down where all other checks have passed +as it changes the dev type with no way to restore it in case +one of the checks that follow it fail. + +Also make sure to preserve the origial mtu assignment: + - If port_dev is not the same type as dev, dev takes mtu from port_dev + - If port_dev is the same type as dev, port_dev takes mtu from dev + +This is done by adding a conditional before the call to dev_set_mtu +to prevent it from assigning port_dev->mtu = dev->mtu and instead +letting team_dev_type_check_change assign dev->mtu = port_dev->mtu. +The conditional is needed because the patch moves the call to +team_dev_type_check_change past dev_set_mtu. + +Testing: + - team device driver in-tree selftests + - Add/remove various devices as slaves of team device + - syzbot + +Reported-by: syzbot+a2a3b519de727b0f7903@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=a2a3b519de727b0f7903 +Fixes: 1d76efe1577b ("team: add support for non-ethernet devices") +Signed-off-by: Nikola Z. Ivanov +Reviewed-by: Jiri Pirko +Link: https://patch.msgid.link/20251122002027.695151-1-zlatistiv@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/team/team_core.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c +index 17f07eb0ee52a..25562b17debe1 100644 +--- a/drivers/net/team/team_core.c ++++ b/drivers/net/team/team_core.c +@@ -1191,10 +1191,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + return -EPERM; + } + +- err = team_dev_type_check_change(dev, port_dev); +- if (err) +- return err; +- + if (port_dev->flags & IFF_UP) { + NL_SET_ERR_MSG(extack, "Device is up. Set it down before adding it as a team port"); + netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n", +@@ -1212,10 +1208,16 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + INIT_LIST_HEAD(&port->qom_list); + + port->orig.mtu = port_dev->mtu; +- err = dev_set_mtu(port_dev, dev->mtu); +- if (err) { +- netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); +- goto err_set_mtu; ++ /* ++ * MTU assignment will be handled in team_dev_type_check_change ++ * if dev and port_dev are of different types ++ */ ++ if (dev->type == port_dev->type) { ++ err = dev_set_mtu(port_dev, dev->mtu); ++ if (err) { ++ netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err); ++ goto err_set_mtu; ++ } + } + + memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len); +@@ -1290,6 +1292,10 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + } + } + ++ err = team_dev_type_check_change(dev, port_dev); ++ if (err) ++ goto err_set_dev_type; ++ + if (dev->flags & IFF_UP) { + netif_addr_lock_bh(dev); + dev_uc_sync_multiple(port_dev, dev); +@@ -1308,6 +1314,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev, + + return 0; + ++err_set_dev_type: + err_set_slave_promisc: + __team_option_inst_del_port(team, port); + +-- +2.51.0 + diff --git a/queue-6.17/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch b/queue-6.17/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch new file mode 100644 index 0000000000..26efa95d8c --- /dev/null +++ b/queue-6.17/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch @@ -0,0 +1,45 @@ +From 4050504e9b34c44f3411c0057459d9695836084a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:22:15 +0800 +Subject: usb: gadget: renesas_usbf: Handle devm_pm_runtime_enable() errors + +From: Haotian Zhang + +[ Upstream commit 74851fbb6d647304f8a7dc491434d3a335ef4b8d ] + +devm_pm_runtime_enable() can fail due to memory allocation. +The current code ignores its return value, potentially causing +pm_runtime_resume_and_get() to operate on uninitialized runtime +PM state. + +Check the return value of devm_pm_runtime_enable() and return on failure. + +Fixes: 3e6e14ffdea4 ("usb: gadget: udc: add Renesas RZ/N1 USBF controller support") +Signed-off-by: Haotian Zhang +Acked-by: Herve Codina +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20251124022215.1619-1-vulab@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/renesas_usbf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c +index 14f4b2cf05a48..4c201574a0af8 100644 +--- a/drivers/usb/gadget/udc/renesas_usbf.c ++++ b/drivers/usb/gadget/udc/renesas_usbf.c +@@ -3262,7 +3262,9 @@ static int usbf_probe(struct platform_device *pdev) + if (IS_ERR(udc->regs)) + return PTR_ERR(udc->regs); + +- devm_pm_runtime_enable(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); ++ if (ret) ++ return ret; + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; +-- +2.51.0 + diff --git a/queue-6.17/veth-reduce-xdp-no_direct-return-section-to-fix-race.patch b/queue-6.17/veth-reduce-xdp-no_direct-return-section-to-fix-race.patch new file mode 100644 index 0000000000..223bb646f0 --- /dev/null +++ b/queue-6.17/veth-reduce-xdp-no_direct-return-section-to-fix-race.patch @@ -0,0 +1,70 @@ +From e10f87a144bcf4ce35d186f37263fbcc60f6703d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Nov 2025 17:28:36 +0100 +Subject: veth: reduce XDP no_direct return section to fix race + +From: Jesper Dangaard Brouer + +[ Upstream commit a14602fcae17a3f1cb8a8521bedf31728f9e7e39 ] + +As explain in commit fa349e396e48 ("veth: Fix race with AF_XDP exposing +old or uninitialized descriptors") for veth there is a chance after +napi_complete_done() that another CPU can manage start another NAPI +instance running veth_pool(). For NAPI this is correctly handled as the +napi_schedule_prep() check will prevent multiple instances from getting +scheduled, but for the remaining code in veth_pool() this can run +concurrent with the newly started NAPI instance. + +The problem/race is that xdp_clear_return_frame_no_direct() isn't +designed to be nested. + +Prior to commit 401cb7dae813 ("net: Reference bpf_redirect_info via +task_struct on PREEMPT_RT.") the temporary BPF net context +bpf_redirect_info was stored per CPU, where this wasn't an issue. Since +this commit the BPF context is stored in 'current' task_struct. When +running veth in threaded-NAPI mode, then the kthread becomes the storage +area. Now a race exists between two concurrent veth_pool() function calls +one exiting NAPI and one running new NAPI, both using the same BPF net +context. + +Race is when another CPU gets within the xdp_set_return_frame_no_direct() +section before exiting veth_pool() calls the clear-function +xdp_clear_return_frame_no_direct(). + +Fixes: 401cb7dae8130 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.") +Signed-off-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/176356963888.337072.4805242001928705046.stgit@firesoul +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/veth.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 35dd89aff4a94..cc502bf022d55 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -975,6 +975,9 @@ static int veth_poll(struct napi_struct *napi, int budget) + + if (stats.xdp_redirect > 0) + xdp_do_flush(); ++ if (stats.xdp_tx > 0) ++ veth_xdp_flush(rq, &bq); ++ xdp_clear_return_frame_no_direct(); + + if (done < budget && napi_complete_done(napi, done)) { + /* Write rx_notify_masked before reading ptr_ring */ +@@ -987,10 +990,6 @@ static int veth_poll(struct napi_struct *napi, int budget) + } + } + +- if (stats.xdp_tx > 0) +- veth_xdp_flush(rq, &bq); +- xdp_clear_return_frame_no_direct(); +- + /* Release backpressure per NAPI poll */ + smp_rmb(); /* Paired with netif_tx_stop_queue set_bit */ + if (peer_txq && netif_tx_queue_stopped(peer_txq)) { +-- +2.51.0 + diff --git a/queue-6.17/xhci-sideband-add-api-to-trace-sideband-usage.patch b/queue-6.17/xhci-sideband-add-api-to-trace-sideband-usage.patch new file mode 100644 index 0000000000..dd8ffe81fc --- /dev/null +++ b/queue-6.17/xhci-sideband-add-api-to-trace-sideband-usage.patch @@ -0,0 +1,131 @@ +From a9e52c49125fe55a68d3b5dedec3fe61e2d19464 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Sep 2025 14:20:15 +0000 +Subject: xhci: sideband: add api to trace sideband usage + +From: Guan-Yu Lin + +[ Upstream commit ef82a4803aabaf623bfcae07981406f1386eabf9 ] + +The existing sideband driver only registers sidebands without tracking +their active usage. To address this, sideband will now record its active +usage when it creates/removes interrupters. In addition, a new api is +introduced to provide a means for other dirvers to fetch sideband +activity information on a USB host controller. + +Signed-off-by: Guan-Yu Lin +Link: https://lore.kernel.org/r/20250911142051.90822-4-guanyulin@google.com +Signed-off-by: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20250911142051.90822-4-guanyulin@google.com +Stable-dep-of: 8c13a7323b84 ("xhci: sideband: Fix race condition in sideband unregister") +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-sideband.c | 36 +++++++++++++++++++++++++++++++ + include/linux/usb/xhci-sideband.h | 9 ++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c +index d49f9886dd848..e771a476fef2e 100644 +--- a/drivers/usb/host/xhci-sideband.c ++++ b/drivers/usb/host/xhci-sideband.c +@@ -266,6 +266,31 @@ xhci_sideband_get_event_buffer(struct xhci_sideband *sb) + } + EXPORT_SYMBOL_GPL(xhci_sideband_get_event_buffer); + ++/** ++ * xhci_sideband_check - check the existence of active sidebands ++ * @hcd: the host controller driver associated with the target host controller ++ * ++ * Allow other drivers, such as usb controller driver, to check if there are ++ * any sideband activity on the host controller. This information could be used ++ * for power management or other forms of resource management. The caller should ++ * ensure downstream usb devices are all either suspended or marked as ++ * "offload_at_suspend" to ensure the correctness of the return value. ++ * ++ * Returns true on any active sideband existence, false otherwise. ++ */ ++bool xhci_sideband_check(struct usb_hcd *hcd) ++{ ++ struct usb_device *udev = hcd->self.root_hub; ++ bool active; ++ ++ usb_lock_device(udev); ++ active = usb_offload_check(udev); ++ usb_unlock_device(udev); ++ ++ return active; ++} ++EXPORT_SYMBOL_GPL(xhci_sideband_check); ++ + /** + * xhci_sideband_create_interrupter - creates a new interrupter for this sideband + * @sb: sideband instance for this usb device +@@ -286,6 +311,7 @@ xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear, u32 imod_interval, int intr_num) + { + int ret = 0; ++ struct usb_device *udev; + + if (!sb || !sb->xhci) + return -ENODEV; +@@ -304,6 +330,9 @@ xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + goto out; + } + ++ udev = sb->vdev->udev; ++ ret = usb_offload_get(udev); ++ + sb->ir->ip_autoclear = ip_autoclear; + + out: +@@ -323,6 +352,8 @@ EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter); + void + xhci_sideband_remove_interrupter(struct xhci_sideband *sb) + { ++ struct usb_device *udev; ++ + if (!sb || !sb->ir) + return; + +@@ -330,6 +361,11 @@ xhci_sideband_remove_interrupter(struct xhci_sideband *sb) + xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir); + + sb->ir = NULL; ++ udev = sb->vdev->udev; ++ ++ if (udev->state != USB_STATE_NOTATTACHED) ++ usb_offload_put(udev); ++ + mutex_unlock(&sb->mutex); + } + EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter); +diff --git a/include/linux/usb/xhci-sideband.h b/include/linux/usb/xhci-sideband.h +index 45288c392f6e0..005257085dcbd 100644 +--- a/include/linux/usb/xhci-sideband.h ++++ b/include/linux/usb/xhci-sideband.h +@@ -11,6 +11,7 @@ + + #include + #include ++#include + + #define EP_CTX_PER_DEV 31 /* FIXME defined twice, from xhci.h */ + +@@ -83,6 +84,14 @@ xhci_sideband_get_endpoint_buffer(struct xhci_sideband *sb, + struct usb_host_endpoint *host_ep); + struct sg_table * + xhci_sideband_get_event_buffer(struct xhci_sideband *sb); ++ ++#if IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) ++bool xhci_sideband_check(struct usb_hcd *hcd); ++#else ++static inline bool xhci_sideband_check(struct usb_hcd *hcd) ++{ return false; } ++#endif /* IS_ENABLED(CONFIG_USB_XHCI_SIDEBAND) */ ++ + int + xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + bool ip_autoclear, u32 imod_interval, int intr_num); +-- +2.51.0 + diff --git a/queue-6.17/xhci-sideband-fix-race-condition-in-sideband-unregis.patch b/queue-6.17/xhci-sideband-fix-race-condition-in-sideband-unregis.patch new file mode 100644 index 0000000000..a26ddf78f8 --- /dev/null +++ b/queue-6.17/xhci-sideband-fix-race-condition-in-sideband-unregis.patch @@ -0,0 +1,247 @@ +From 4281c3b2ba2dd298a105d49d2698ac542aecc278 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 18:28:18 +0200 +Subject: xhci: sideband: Fix race condition in sideband unregister + +From: Mathias Nyman + +[ Upstream commit 8c13a7323b847c0370aec66f655e2596a2174a17 ] + +Uttkarsh Aggarwal observed a kernel panic during sideband un-register +and found it was caused by a race condition between sideband unregister, +and creating sideband interrupters. +The issue occurrs when thread T1 runs uaudio_disconnect() and released +sb->xhci via sideband_unregister, while thread T2 simultaneously accessed +the now-NULL sb->xhci in xhci_sideband_create_interrupter() resulting in +a crash. + +Ensure new endpoints or interrupter can't be added to a sidenband after +xhci_sideband_unregister() cleared the existing ones, and unlocked the +sideband mutex. +Reorganize code so that mutex is only taken and released once in +xhci_sideband_unregister(), and clear sb->vdev while mutex is taken. + +Use mutex guards to reduce human unlock errors in code + +Refuse to add endpoints or interrupter if sb->vdev is not set. +sb->vdev is set when sideband is created and registered. + +Reported-by: Uttkarsh Aggarwal +Closes: https://lore.kernel.org/linux-usb/20251028080043.27760-1-uttkarsh.aggarwal@oss.qualcomm.com +Fixes: de66754e9f80 ("xhci: sideband: add initial api to register a secondary interrupter entity") +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Mathias Nyman +Link: https://patch.msgid.link/20251107162819.1362579-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-sideband.c | 102 ++++++++++++++++++------------- + 1 file changed, 58 insertions(+), 44 deletions(-) + +diff --git a/drivers/usb/host/xhci-sideband.c b/drivers/usb/host/xhci-sideband.c +index e771a476fef2e..a85f62a73313a 100644 +--- a/drivers/usb/host/xhci-sideband.c ++++ b/drivers/usb/host/xhci-sideband.c +@@ -73,9 +73,12 @@ xhci_ring_to_sgtable(struct xhci_sideband *sb, struct xhci_ring *ring) + return NULL; + } + ++/* Caller must hold sb->mutex */ + static void + __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *ep) + { ++ lockdep_assert_held(&sb->mutex); ++ + /* + * Issue a stop endpoint command when an endpoint is removed. + * The stop ep cmd handler will handle the ring cleanup. +@@ -86,6 +89,25 @@ __xhci_sideband_remove_endpoint(struct xhci_sideband *sb, struct xhci_virt_ep *e + sb->eps[ep->ep_index] = NULL; + } + ++/* Caller must hold sb->mutex */ ++static void ++__xhci_sideband_remove_interrupter(struct xhci_sideband *sb) ++{ ++ struct usb_device *udev; ++ ++ lockdep_assert_held(&sb->mutex); ++ ++ if (!sb->ir) ++ return; ++ ++ xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir); ++ sb->ir = NULL; ++ udev = sb->vdev->udev; ++ ++ if (udev->state != USB_STATE_NOTATTACHED) ++ usb_offload_put(udev); ++} ++ + /* sideband api functions */ + + /** +@@ -131,14 +153,16 @@ xhci_sideband_add_endpoint(struct xhci_sideband *sb, + struct xhci_virt_ep *ep; + unsigned int ep_index; + +- mutex_lock(&sb->mutex); ++ guard(mutex)(&sb->mutex); ++ ++ if (!sb->vdev) ++ return -ENODEV; ++ + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = &sb->vdev->eps[ep_index]; + +- if (ep->ep_state & EP_HAS_STREAMS) { +- mutex_unlock(&sb->mutex); ++ if (ep->ep_state & EP_HAS_STREAMS) + return -EINVAL; +- } + + /* + * Note, we don't know the DMA mask of the audio DSP device, if its +@@ -148,14 +172,11 @@ xhci_sideband_add_endpoint(struct xhci_sideband *sb, + * and let this function add the endpoint and allocate the ring buffer + * with the smallest common DMA mask + */ +- if (sb->eps[ep_index] || ep->sideband) { +- mutex_unlock(&sb->mutex); ++ if (sb->eps[ep_index] || ep->sideband) + return -EBUSY; +- } + + ep->sideband = sb; + sb->eps[ep_index] = ep; +- mutex_unlock(&sb->mutex); + + return 0; + } +@@ -180,18 +201,16 @@ xhci_sideband_remove_endpoint(struct xhci_sideband *sb, + struct xhci_virt_ep *ep; + unsigned int ep_index; + +- mutex_lock(&sb->mutex); ++ guard(mutex)(&sb->mutex); ++ + ep_index = xhci_get_endpoint_index(&host_ep->desc); + ep = sb->eps[ep_index]; + +- if (!ep || !ep->sideband || ep->sideband != sb) { +- mutex_unlock(&sb->mutex); ++ if (!ep || !ep->sideband || ep->sideband != sb) + return -ENODEV; +- } + + __xhci_sideband_remove_endpoint(sb, ep); + xhci_initialize_ring_info(ep->ring); +- mutex_unlock(&sb->mutex); + + return 0; + } +@@ -316,28 +335,25 @@ xhci_sideband_create_interrupter(struct xhci_sideband *sb, int num_seg, + if (!sb || !sb->xhci) + return -ENODEV; + +- mutex_lock(&sb->mutex); +- if (sb->ir) { +- ret = -EBUSY; +- goto out; +- } ++ guard(mutex)(&sb->mutex); ++ ++ if (!sb->vdev) ++ return -ENODEV; ++ ++ if (sb->ir) ++ return -EBUSY; + + sb->ir = xhci_create_secondary_interrupter(xhci_to_hcd(sb->xhci), + num_seg, imod_interval, + intr_num); +- if (!sb->ir) { +- ret = -ENOMEM; +- goto out; +- } ++ if (!sb->ir) ++ return -ENOMEM; + + udev = sb->vdev->udev; + ret = usb_offload_get(udev); + + sb->ir->ip_autoclear = ip_autoclear; + +-out: +- mutex_unlock(&sb->mutex); +- + return ret; + } + EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter); +@@ -352,21 +368,12 @@ EXPORT_SYMBOL_GPL(xhci_sideband_create_interrupter); + void + xhci_sideband_remove_interrupter(struct xhci_sideband *sb) + { +- struct usb_device *udev; +- +- if (!sb || !sb->ir) ++ if (!sb) + return; + +- mutex_lock(&sb->mutex); +- xhci_remove_secondary_interrupter(xhci_to_hcd(sb->xhci), sb->ir); +- +- sb->ir = NULL; +- udev = sb->vdev->udev; ++ guard(mutex)(&sb->mutex); + +- if (udev->state != USB_STATE_NOTATTACHED) +- usb_offload_put(udev); +- +- mutex_unlock(&sb->mutex); ++ __xhci_sideband_remove_interrupter(sb); + } + EXPORT_SYMBOL_GPL(xhci_sideband_remove_interrupter); + +@@ -465,6 +472,7 @@ EXPORT_SYMBOL_GPL(xhci_sideband_register); + void + xhci_sideband_unregister(struct xhci_sideband *sb) + { ++ struct xhci_virt_device *vdev; + struct xhci_hcd *xhci; + int i; + +@@ -473,17 +481,23 @@ xhci_sideband_unregister(struct xhci_sideband *sb) + + xhci = sb->xhci; + +- mutex_lock(&sb->mutex); +- for (i = 0; i < EP_CTX_PER_DEV; i++) +- if (sb->eps[i]) +- __xhci_sideband_remove_endpoint(sb, sb->eps[i]); +- mutex_unlock(&sb->mutex); ++ scoped_guard(mutex, &sb->mutex) { ++ vdev = sb->vdev; ++ if (!vdev) ++ return; ++ ++ for (i = 0; i < EP_CTX_PER_DEV; i++) ++ if (sb->eps[i]) ++ __xhci_sideband_remove_endpoint(sb, sb->eps[i]); + +- xhci_sideband_remove_interrupter(sb); ++ __xhci_sideband_remove_interrupter(sb); ++ ++ sb->vdev = NULL; ++ } + + spin_lock_irq(&xhci->lock); + sb->xhci = NULL; +- sb->vdev->sideband = NULL; ++ vdev->sideband = NULL; + spin_unlock_irq(&xhci->lock); + + kfree(sb); +-- +2.51.0 + diff --git a/queue-6.17/xsk-avoid-data-corruption-on-cq-descriptor-number.patch b/queue-6.17/xsk-avoid-data-corruption-on-cq-descriptor-number.patch new file mode 100644 index 0000000000..884de80123 --- /dev/null +++ b/queue-6.17/xsk-avoid-data-corruption-on-cq-descriptor-number.patch @@ -0,0 +1,340 @@ +From 0617068bae90aeaaa11d1fdb3cc3b277c3a567a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 18:14:09 +0100 +Subject: xsk: avoid data corruption on cq descriptor number + +From: Fernando Fernandez Mancera + +[ Upstream commit 0ebc27a4c67d44e5ce88d21cdad8201862b78837 ] + +Since commit 30f241fcf52a ("xsk: Fix immature cq descriptor +production"), the descriptor number is stored in skb control block and +xsk_cq_submit_addr_locked() relies on it to put the umem addrs onto +pool's completion queue. + +skb control block shouldn't be used for this purpose as after transmit +xsk doesn't have control over it and other subsystems could use it. This +leads to the following kernel panic due to a NULL pointer dereference. + + BUG: kernel NULL pointer dereference, address: 0000000000000000 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 0 P4D 0 + Oops: Oops: 0000 [#1] SMP NOPTI + CPU: 2 UID: 1 PID: 927 Comm: p4xsk.bin Not tainted 6.16.12+deb14-cloud-amd64 #1 PREEMPT(lazy) Debian 6.16.12-1 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014 + RIP: 0010:xsk_destruct_skb+0xd0/0x180 + [...] + Call Trace: + + ? napi_complete_done+0x7a/0x1a0 + ip_rcv_core+0x1bb/0x340 + ip_rcv+0x30/0x1f0 + __netif_receive_skb_one_core+0x85/0xa0 + process_backlog+0x87/0x130 + __napi_poll+0x28/0x180 + net_rx_action+0x339/0x420 + handle_softirqs+0xdc/0x320 + ? handle_edge_irq+0x90/0x1e0 + do_softirq.part.0+0x3b/0x60 + + + __local_bh_enable_ip+0x60/0x70 + __dev_direct_xmit+0x14e/0x1f0 + __xsk_generic_xmit+0x482/0xb70 + ? __remove_hrtimer+0x41/0xa0 + ? __xsk_generic_xmit+0x51/0xb70 + ? _raw_spin_unlock_irqrestore+0xe/0x40 + xsk_sendmsg+0xda/0x1c0 + __sys_sendto+0x1ee/0x200 + __x64_sys_sendto+0x24/0x30 + do_syscall_64+0x84/0x2f0 + ? __pfx_pollwake+0x10/0x10 + ? __rseq_handle_notify_resume+0xad/0x4c0 + ? restore_fpregs_from_fpstate+0x3c/0x90 + ? switch_fpu_return+0x5b/0xe0 + ? do_syscall_64+0x204/0x2f0 + ? do_syscall_64+0x204/0x2f0 + ? do_syscall_64+0x204/0x2f0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + [...] + Kernel panic - not syncing: Fatal exception in interrupt + Kernel Offset: 0x1c000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) + +Instead use the skb destructor_arg pointer along with pointer tagging. +As pointers are always aligned to 8B, use the bottom bit to indicate +whether this a single address or an allocated struct containing several +addresses. + +Fixes: 30f241fcf52a ("xsk: Fix immature cq descriptor production") +Closes: https://lore.kernel.org/netdev/0435b904-f44f-48f8-afb0-68868474bf1c@nop.hu/ +Suggested-by: Jakub Kicinski +Signed-off-by: Fernando Fernandez Mancera +Reviewed-by: Maciej Fijalkowski +Reviewed-by: Jason Xing +Link: https://patch.msgid.link/20251124171409.3845-1-fmancera@suse.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/xdp/xsk.c | 143 +++++++++++++++++++++++++++++++------------------- + 1 file changed, 88 insertions(+), 55 deletions(-) + +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 01f258894faeb..78fc25e88d7c3 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -36,20 +36,13 @@ + #define TX_BATCH_SIZE 32 + #define MAX_PER_SOCKET_BUDGET 32 + +-struct xsk_addr_node { +- u64 addr; +- struct list_head addr_node; +-}; +- +-struct xsk_addr_head { ++struct xsk_addrs { + u32 num_descs; +- struct list_head addrs_list; ++ u64 addrs[MAX_SKB_FRAGS + 1]; + }; + + static struct kmem_cache *xsk_tx_generic_cache; + +-#define XSKCB(skb) ((struct xsk_addr_head *)((skb)->cb)) +- + void xsk_set_rx_need_wakeup(struct xsk_buff_pool *pool) + { + if (pool->cached_need_wakeup & XDP_WAKEUP_RX) +@@ -558,29 +551,68 @@ static int xsk_cq_reserve_locked(struct xsk_buff_pool *pool) + return ret; + } + ++static bool xsk_skb_destructor_is_addr(struct sk_buff *skb) ++{ ++ return (uintptr_t)skb_shinfo(skb)->destructor_arg & 0x1UL; ++} ++ ++static u64 xsk_skb_destructor_get_addr(struct sk_buff *skb) ++{ ++ return (u64)((uintptr_t)skb_shinfo(skb)->destructor_arg & ~0x1UL); ++} ++ ++static void xsk_skb_destructor_set_addr(struct sk_buff *skb, u64 addr) ++{ ++ skb_shinfo(skb)->destructor_arg = (void *)((uintptr_t)addr | 0x1UL); ++} ++ ++static void xsk_inc_num_desc(struct sk_buff *skb) ++{ ++ struct xsk_addrs *xsk_addr; ++ ++ if (!xsk_skb_destructor_is_addr(skb)) { ++ xsk_addr = (struct xsk_addrs *)skb_shinfo(skb)->destructor_arg; ++ xsk_addr->num_descs++; ++ } ++} ++ ++static u32 xsk_get_num_desc(struct sk_buff *skb) ++{ ++ struct xsk_addrs *xsk_addr; ++ ++ if (xsk_skb_destructor_is_addr(skb)) ++ return 1; ++ ++ xsk_addr = (struct xsk_addrs *)skb_shinfo(skb)->destructor_arg; ++ ++ return xsk_addr->num_descs; ++} ++ + static void xsk_cq_submit_addr_locked(struct xsk_buff_pool *pool, + struct sk_buff *skb) + { +- struct xsk_addr_node *pos, *tmp; ++ u32 num_descs = xsk_get_num_desc(skb); ++ struct xsk_addrs *xsk_addr; + u32 descs_processed = 0; + unsigned long flags; +- u32 idx; ++ u32 idx, i; + + spin_lock_irqsave(&pool->cq_lock, flags); + idx = xskq_get_prod(pool->cq); + +- xskq_prod_write_addr(pool->cq, idx, +- (u64)(uintptr_t)skb_shinfo(skb)->destructor_arg); +- descs_processed++; ++ if (unlikely(num_descs > 1)) { ++ xsk_addr = (struct xsk_addrs *)skb_shinfo(skb)->destructor_arg; + +- if (unlikely(XSKCB(skb)->num_descs > 1)) { +- list_for_each_entry_safe(pos, tmp, &XSKCB(skb)->addrs_list, addr_node) { ++ for (i = 0; i < num_descs; i++) { + xskq_prod_write_addr(pool->cq, idx + descs_processed, +- pos->addr); ++ xsk_addr->addrs[i]); + descs_processed++; +- list_del(&pos->addr_node); +- kmem_cache_free(xsk_tx_generic_cache, pos); + } ++ kmem_cache_free(xsk_tx_generic_cache, xsk_addr); ++ } else { ++ xskq_prod_write_addr(pool->cq, idx, ++ xsk_skb_destructor_get_addr(skb)); ++ descs_processed++; + } + xskq_prod_submit_n(pool->cq, descs_processed); + spin_unlock_irqrestore(&pool->cq_lock, flags); +@@ -595,16 +627,6 @@ static void xsk_cq_cancel_locked(struct xsk_buff_pool *pool, u32 n) + spin_unlock_irqrestore(&pool->cq_lock, flags); + } + +-static void xsk_inc_num_desc(struct sk_buff *skb) +-{ +- XSKCB(skb)->num_descs++; +-} +- +-static u32 xsk_get_num_desc(struct sk_buff *skb) +-{ +- return XSKCB(skb)->num_descs; +-} +- + static void xsk_destruct_skb(struct sk_buff *skb) + { + struct xsk_tx_metadata_compl *compl = &skb_shinfo(skb)->xsk_meta; +@@ -621,27 +643,22 @@ static void xsk_destruct_skb(struct sk_buff *skb) + static void xsk_skb_init_misc(struct sk_buff *skb, struct xdp_sock *xs, + u64 addr) + { +- BUILD_BUG_ON(sizeof(struct xsk_addr_head) > sizeof(skb->cb)); +- INIT_LIST_HEAD(&XSKCB(skb)->addrs_list); + skb->dev = xs->dev; + skb->priority = READ_ONCE(xs->sk.sk_priority); + skb->mark = READ_ONCE(xs->sk.sk_mark); +- XSKCB(skb)->num_descs = 0; + skb->destructor = xsk_destruct_skb; +- skb_shinfo(skb)->destructor_arg = (void *)(uintptr_t)addr; ++ xsk_skb_destructor_set_addr(skb, addr); + } + + static void xsk_consume_skb(struct sk_buff *skb) + { + struct xdp_sock *xs = xdp_sk(skb->sk); + u32 num_descs = xsk_get_num_desc(skb); +- struct xsk_addr_node *pos, *tmp; ++ struct xsk_addrs *xsk_addr; + + if (unlikely(num_descs > 1)) { +- list_for_each_entry_safe(pos, tmp, &XSKCB(skb)->addrs_list, addr_node) { +- list_del(&pos->addr_node); +- kmem_cache_free(xsk_tx_generic_cache, pos); +- } ++ xsk_addr = (struct xsk_addrs *)skb_shinfo(skb)->destructor_arg; ++ kmem_cache_free(xsk_tx_generic_cache, xsk_addr); + } + + skb->destructor = sock_wfree; +@@ -662,7 +679,6 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, + { + struct xsk_buff_pool *pool = xs->pool; + u32 hr, len, ts, offset, copy, copied; +- struct xsk_addr_node *xsk_addr; + struct sk_buff *skb = xs->skb; + struct page *page; + void *buffer; +@@ -680,16 +696,26 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, + + xsk_skb_init_misc(skb, xs, desc->addr); + } else { +- xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, GFP_KERNEL); +- if (!xsk_addr) +- return ERR_PTR(-ENOMEM); ++ struct xsk_addrs *xsk_addr; ++ ++ if (xsk_skb_destructor_is_addr(skb)) { ++ xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, ++ GFP_KERNEL); ++ if (!xsk_addr) ++ return ERR_PTR(-ENOMEM); ++ ++ xsk_addr->num_descs = 1; ++ xsk_addr->addrs[0] = xsk_skb_destructor_get_addr(skb); ++ skb_shinfo(skb)->destructor_arg = (void *)xsk_addr; ++ } else { ++ xsk_addr = (struct xsk_addrs *)skb_shinfo(skb)->destructor_arg; ++ } + + /* in case of -EOVERFLOW that could happen below, + * xsk_consume_skb() will release this node as whole skb + * would be dropped, which implies freeing all list elements + */ +- xsk_addr->addr = desc->addr; +- list_add_tail(&xsk_addr->addr_node, &XSKCB(skb)->addrs_list); ++ xsk_addr->addrs[xsk_addr->num_descs] = desc->addr; + } + + addr = desc->addr; +@@ -765,10 +791,25 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + xsk_skb_init_misc(skb, xs, desc->addr); + } else { + int nr_frags = skb_shinfo(skb)->nr_frags; +- struct xsk_addr_node *xsk_addr; ++ struct xsk_addrs *xsk_addr; + struct page *page; + u8 *vaddr; + ++ if (xsk_skb_destructor_is_addr(skb)) { ++ xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, ++ GFP_KERNEL); ++ if (!xsk_addr) { ++ err = -ENOMEM; ++ goto free_err; ++ } ++ ++ xsk_addr->num_descs = 1; ++ xsk_addr->addrs[0] = xsk_skb_destructor_get_addr(skb); ++ skb_shinfo(skb)->destructor_arg = (void *)xsk_addr; ++ } else { ++ xsk_addr = (struct xsk_addrs *)skb_shinfo(skb)->destructor_arg; ++ } ++ + if (unlikely(nr_frags == (MAX_SKB_FRAGS - 1) && xp_mb_desc(desc))) { + err = -EOVERFLOW; + goto free_err; +@@ -780,13 +821,6 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + goto free_err; + } + +- xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, GFP_KERNEL); +- if (!xsk_addr) { +- __free_page(page); +- err = -ENOMEM; +- goto free_err; +- } +- + vaddr = kmap_local_page(page); + memcpy(vaddr, buffer, len); + kunmap_local(vaddr); +@@ -794,8 +828,7 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + skb_add_rx_frag(skb, nr_frags, page, 0, len, PAGE_SIZE); + refcount_add(PAGE_SIZE, &xs->sk.sk_wmem_alloc); + +- xsk_addr->addr = desc->addr; +- list_add_tail(&xsk_addr->addr_node, &XSKCB(skb)->addrs_list); ++ xsk_addr->addrs[xsk_addr->num_descs] = desc->addr; + } + + if (first_frag && desc->options & XDP_TX_METADATA) { +@@ -1892,7 +1925,7 @@ static int __init xsk_init(void) + goto out_pernet; + + xsk_tx_generic_cache = kmem_cache_create("xsk_generic_xmit_cache", +- sizeof(struct xsk_addr_node), ++ sizeof(struct xsk_addrs), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!xsk_tx_generic_cache) { + err = -ENOMEM; +-- +2.51.0 + diff --git a/queue-6.17/xsk-avoid-overwriting-skb-fields-for-multi-buffer-tr.patch b/queue-6.17/xsk-avoid-overwriting-skb-fields-for-multi-buffer-tr.patch new file mode 100644 index 0000000000..9c132a05d1 --- /dev/null +++ b/queue-6.17/xsk-avoid-overwriting-skb-fields-for-multi-buffer-tr.patch @@ -0,0 +1,87 @@ +From b18fcd7cceaef3858d237bec0395cde9fd13362f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Sep 2025 18:00:07 +0200 +Subject: xsk: avoid overwriting skb fields for multi-buffer traffic + +From: Maciej Fijalkowski + +[ Upstream commit c30d084960cf316c95fbf145d39974ce1ff7889c ] + +We are unnecessarily setting a bunch of skb fields per each processed +descriptor, which is redundant for fragmented frames. + +Let us set these respective members for first fragment only. To address +both paths that we have within xsk_build_skb(), move assignments onto +xsk_set_destructor_arg() and rename it to xsk_skb_init_misc(). + +Signed-off-by: Maciej Fijalkowski +Acked-by: Stanislav Fomichev +Reviewed-by: Jason Xing +Acked-by: Martin KaFai Lau +Link: https://patch.msgid.link/20250925160009.2474816-2-maciej.fijalkowski@intel.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 0ebc27a4c67d ("xsk: avoid data corruption on cq descriptor number") +Signed-off-by: Sasha Levin +--- + net/xdp/xsk.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 72e34bd2d925c..01f258894faeb 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -618,11 +618,16 @@ static void xsk_destruct_skb(struct sk_buff *skb) + sock_wfree(skb); + } + +-static void xsk_set_destructor_arg(struct sk_buff *skb, u64 addr) ++static void xsk_skb_init_misc(struct sk_buff *skb, struct xdp_sock *xs, ++ u64 addr) + { + BUILD_BUG_ON(sizeof(struct xsk_addr_head) > sizeof(skb->cb)); + INIT_LIST_HEAD(&XSKCB(skb)->addrs_list); ++ skb->dev = xs->dev; ++ skb->priority = READ_ONCE(xs->sk.sk_priority); ++ skb->mark = READ_ONCE(xs->sk.sk_mark); + XSKCB(skb)->num_descs = 0; ++ skb->destructor = xsk_destruct_skb; + skb_shinfo(skb)->destructor_arg = (void *)(uintptr_t)addr; + } + +@@ -673,7 +678,7 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, + + skb_reserve(skb, hr); + +- xsk_set_destructor_arg(skb, desc->addr); ++ xsk_skb_init_misc(skb, xs, desc->addr); + } else { + xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, GFP_KERNEL); + if (!xsk_addr) +@@ -757,7 +762,7 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + if (unlikely(err)) + goto free_err; + +- xsk_set_destructor_arg(skb, desc->addr); ++ xsk_skb_init_misc(skb, xs, desc->addr); + } else { + int nr_frags = skb_shinfo(skb)->nr_frags; + struct xsk_addr_node *xsk_addr; +@@ -826,14 +831,10 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + + if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME) + skb->skb_mstamp_ns = meta->request.launch_time; ++ xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta); + } + } + +- skb->dev = dev; +- skb->priority = READ_ONCE(xs->sk.sk_priority); +- skb->mark = READ_ONCE(xs->sk.sk_mark); +- skb->destructor = xsk_destruct_skb; +- xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta); + xsk_inc_num_desc(skb); + + return skb; +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch b/queue-6.6/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch new file mode 100644 index 0000000000..2b7383c43e --- /dev/null +++ b/queue-6.6/bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch @@ -0,0 +1,72 @@ +From 6868aa21003bfbddc1d87c8dcb220c6f6eb1d64e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Nov 2025 17:04:43 +0800 +Subject: Bluetooth: hci_sock: Prevent race in socket write iter and sock bind + +From: Edward Adam Davis + +[ Upstream commit 89bb613511cc21ed5ba6bddc1c9b9ae9c0dad392 ] + +There is a potential race condition between sock bind and socket write +iter. bind may free the same cmd via mgmt_pending before write iter sends +the cmd, just as syzbot reported in UAF[1]. + +Here we use hci_dev_lock to synchronize the two, thereby avoiding the +UAF mentioned in [1]. + +[1] +syzbot reported: +BUG: KASAN: slab-use-after-free in mgmt_pending_remove+0x3b/0x210 net/bluetooth/mgmt_util.c:316 +Read of size 8 at addr ffff888077164818 by task syz.0.17/5989 +Call Trace: + mgmt_pending_remove+0x3b/0x210 net/bluetooth/mgmt_util.c:316 + set_link_security+0x5c2/0x710 net/bluetooth/mgmt.c:1918 + hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 + hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + sock_write_iter+0x279/0x360 net/socket.c:1195 + +Allocated by task 5989: + mgmt_pending_add+0x35/0x140 net/bluetooth/mgmt_util.c:296 + set_link_security+0x557/0x710 net/bluetooth/mgmt.c:1910 + hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719 + hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:742 + sock_write_iter+0x279/0x360 net/socket.c:1195 + +Freed by task 5991: + mgmt_pending_free net/bluetooth/mgmt_util.c:311 [inline] + mgmt_pending_foreach+0x30d/0x380 net/bluetooth/mgmt_util.c:257 + mgmt_index_removed+0x112/0x2f0 net/bluetooth/mgmt.c:9477 + hci_sock_bind+0xbe9/0x1000 net/bluetooth/hci_sock.c:1314 + +Fixes: 6fe26f694c82 ("Bluetooth: MGMT: Protect mgmt_pending list with its own lock") +Reported-by: syzbot+9aa47cd4633a3cf92a80@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9aa47cd4633a3cf92a80 +Tested-by: syzbot+9aa47cd4633a3cf92a80@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sock.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index d2613bd3e6db0..8b3ef088ed14e 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -1304,7 +1304,9 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, + goto done; + } + ++ hci_dev_lock(hdev); + mgmt_index_removed(hdev); ++ hci_dev_unlock(hdev); + + err = hci_dev_open(hdev->id); + if (err) { +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch b/queue-6.6/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch new file mode 100644 index 0000000000..f45bdcfdc0 --- /dev/null +++ b/queue-6.6/bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch @@ -0,0 +1,87 @@ +From de8be4a98c74fac3d59e4d3904249f64984c3a3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 13:45:13 -0500 +Subject: Bluetooth: SMP: Fix not generating mackey and ltk when repairing + +From: Luiz Augusto von Dentz + +[ Upstream commit 545d7827b2cd5de5eb85580cebeda6b35b3ff443 ] + +The change eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +introduced a goto that bypasses the creation of temporary mackey and ltk +which are later used by the likes of DHKey Check step. + +Later ffee202a78c2 ("Bluetooth: Always request for user confirmation for +Just Works (LE SC)") which means confirm_hint is always set in case +JUST_WORKS so the branch checking for an existing LTK becomes pointless +as confirm_hint will always be set, so this just merge both cases of +malicious or legitimate devices to be confirmed before continuing with the +pairing procedure. + +Link: https://github.com/bluez/bluez/issues/1622 +Fixes: eed467b517e8 ("Bluetooth: fix passkey uninitialized when used") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/smp.c | 31 +++++++------------------------ + 1 file changed, 7 insertions(+), 24 deletions(-) + +diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c +index 4c00bc50de811..e7ee13fe83a74 100644 +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2137,7 +2137,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + struct smp_chan *smp = chan->data; + struct hci_conn *hcon = conn->hcon; + u8 *pkax, *pkbx, *na, *nb, confirm_hint; +- u32 passkey; ++ u32 passkey = 0; + int err; + + bt_dev_dbg(hcon->hdev, "conn %p", conn); +@@ -2189,24 +2189,6 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), + smp->prnd); + SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK); +- +- /* Only Just-Works pairing requires extra checks */ +- if (smp->method != JUST_WORKS) +- goto mackey_and_ltk; +- +- /* If there already exists long term key in local host, leave +- * the decision to user space since the remote device could +- * be legitimate or malicious. +- */ +- if (hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, +- hcon->role)) { +- /* Set passkey to 0. The value can be any number since +- * it'll be ignored anyway. +- */ +- passkey = 0; +- confirm_hint = 1; +- goto confirm; +- } + } + + mackey_and_ltk: +@@ -2227,11 +2209,12 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) + if (err) + return SMP_UNSPECIFIED; + +- confirm_hint = 0; +- +-confirm: +- if (smp->method == JUST_WORKS) +- confirm_hint = 1; ++ /* Always require user confirmation for Just-Works pairing to prevent ++ * impersonation attacks, or in case of a legitimate device that is ++ * repairing use the confirmation as acknowledgment to proceed with the ++ * creation of new keys. ++ */ ++ confirm_hint = smp->method == JUST_WORKS ? 1 : 0; + + err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, + hcon->dst_type, passkey, confirm_hint); +-- +2.51.0 + diff --git a/queue-6.6/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch b/queue-6.6/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch new file mode 100644 index 0000000000..16c117f97b --- /dev/null +++ b/queue-6.6/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch @@ -0,0 +1,92 @@ +From b0e7b67bfb17560ce3e97df77fbaae7a7800029a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:02 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing header + +From: Marc Kleine-Budde + +[ Upstream commit 6fe9f3279f7d2518439a7962c5870c6e9ecbadcf ] + +The driver expects to receive a struct gs_host_frame in +gs_usb_receive_bulk_callback(). + +Use struct_group to describe the header of the struct gs_host_frame and +check that we have at least received the header before accessing any +members of it. + +To resubmit the URB, do not dereference the pointer chain +"dev->parent->hf_size_rx" but use "parent->hf_size_rx" instead. Since +"urb->context" contains "parent", it is always defined, while "dev" is not +defined if the URB it too short. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-2-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 1ba6395a5a667..e786616d167b8 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -259,13 +259,15 @@ struct canfd_quirk { + } __packed; + + struct gs_host_frame { +- u32 echo_id; +- __le32 can_id; ++ struct_group(header, ++ u32 echo_id; ++ __le32 can_id; + +- u8 can_dlc; +- u8 channel; +- u8 flags; +- u8 reserved; ++ u8 can_dlc; ++ u8 channel; ++ u8 flags; ++ u8 reserved; ++ ); + + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); +@@ -573,6 +575,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; ++ unsigned int minimum_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -591,6 +594,15 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + return; + } + ++ minimum_length = sizeof(hf->header); ++ if (urb->actual_length < minimum_length) { ++ dev_err_ratelimited(&parent->udev->dev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ + /* device reports out of range channel id */ + if (hf->channel >= parent->channel_cnt) + goto device_detach; +@@ -684,7 +696,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + resubmit_urb: + usb_fill_bulk_urb(urb, parent->udev, + parent->pipe_in, +- hf, dev->parent->hf_size_rx, ++ hf, parent->hf_size_rx, + gs_usb_receive_bulk_callback, parent); + + rc = usb_submit_urb(urb, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.6/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-2290 b/queue-6.6/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-2290 new file mode 100644 index 0000000000..1defd8effe --- /dev/null +++ b/queue-6.6/can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-2290 @@ -0,0 +1,140 @@ +From da34234948b26d1abb80e061227382ad2e1d8928 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:03 +0100 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length + before accessing data + +From: Marc Kleine-Budde + +[ Upstream commit 395d988f93861101ec89d0dd9e3b876ae9392a5b ] + +The URB received in gs_usb_receive_bulk_callback() contains a struct +gs_host_frame. The length of the data after the header depends on the +gs_host_frame hf::flags and the active device features (e.g. time +stamping). + +Introduce a new function gs_usb_get_minimum_length() and check that we have +at least received the required amount of data before accessing it. Only +copy the data to that skb that has actually been received. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-3-a29b42eacada@pengutronix.de +[mkl: rename gs_usb_get_minimum_length() -> +gs_usb_get_minimum_rx_length()] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 59 +++++++++++++++++++++++++++++++++--- + 1 file changed, 54 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index e786616d167b8..72997312c9567 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -258,6 +258,11 @@ struct canfd_quirk { + u8 quirk; + } __packed; + ++/* struct gs_host_frame::echo_id == GS_HOST_FRAME_ECHO_ID_RX indicates ++ * a regular RX'ed CAN frame ++ */ ++#define GS_HOST_FRAME_ECHO_ID_RX 0xffffffff ++ + struct gs_host_frame { + struct_group(header, + u32 echo_id; +@@ -567,6 +572,37 @@ gs_usb_get_echo_skb(struct gs_can *dev, struct sk_buff *skb, + return len; + } + ++static unsigned int ++gs_usb_get_minimum_rx_length(const struct gs_can *dev, const struct gs_host_frame *hf, ++ unsigned int *data_length_p) ++{ ++ unsigned int minimum_length, data_length = 0; ++ ++ if (hf->flags & GS_CAN_FLAG_FD) { ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) ++ data_length = can_fd_dlc2len(hf->can_dlc); ++ ++ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) ++ /* timestamp follows data field of max size */ ++ minimum_length = struct_size(hf, canfd_ts, 1); ++ else ++ minimum_length = sizeof(hf->header) + data_length; ++ } else { ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX && ++ !(hf->can_id & cpu_to_le32(CAN_RTR_FLAG))) ++ data_length = can_cc_dlc2len(hf->can_dlc); ++ ++ if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) ++ /* timestamp follows data field of max size */ ++ minimum_length = struct_size(hf, classic_can_ts, 1); ++ else ++ minimum_length = sizeof(hf->header) + data_length; ++ } ++ ++ *data_length_p = data_length; ++ return minimum_length; ++} ++ + static void gs_usb_receive_bulk_callback(struct urb *urb) + { + struct gs_usb *parent = urb->context; +@@ -575,7 +611,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + int rc; + struct net_device_stats *stats; + struct gs_host_frame *hf = urb->transfer_buffer; +- unsigned int minimum_length; ++ unsigned int minimum_length, data_length; + struct gs_tx_context *txc; + struct can_frame *cf; + struct canfd_frame *cfd; +@@ -618,20 +654,33 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + if (!netif_running(netdev)) + goto resubmit_urb; + +- if (hf->echo_id == -1) { /* normal rx */ ++ minimum_length = gs_usb_get_minimum_rx_length(dev, hf, &data_length); ++ if (urb->actual_length < minimum_length) { ++ stats->rx_errors++; ++ stats->rx_length_errors++; ++ ++ if (net_ratelimit()) ++ netdev_err(netdev, ++ "short read (actual_length=%u, minimum_length=%u)\n", ++ urb->actual_length, minimum_length); ++ ++ goto resubmit_urb; ++ } ++ ++ if (hf->echo_id == GS_HOST_FRAME_ECHO_ID_RX) { /* normal rx */ + if (hf->flags & GS_CAN_FLAG_FD) { + skb = alloc_canfd_skb(netdev, &cfd); + if (!skb) + return; + + cfd->can_id = le32_to_cpu(hf->can_id); +- cfd->len = can_fd_dlc2len(hf->can_dlc); ++ cfd->len = data_length; + if (hf->flags & GS_CAN_FLAG_BRS) + cfd->flags |= CANFD_BRS; + if (hf->flags & GS_CAN_FLAG_ESI) + cfd->flags |= CANFD_ESI; + +- memcpy(cfd->data, hf->canfd->data, cfd->len); ++ memcpy(cfd->data, hf->canfd->data, data_length); + } else { + skb = alloc_can_skb(netdev, &cf); + if (!skb) +@@ -640,7 +689,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) + cf->can_id = le32_to_cpu(hf->can_id); + can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); + +- memcpy(cf->data, hf->classic_can->data, 8); ++ memcpy(cf->data, hf->classic_can->data, data_length); + + /* ERROR frames tell us information about the controller */ + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) +-- +2.51.0 + diff --git a/queue-6.6/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch b/queue-6.6/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch new file mode 100644 index 0000000000..36a2fafd56 --- /dev/null +++ b/queue-6.6/can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch @@ -0,0 +1,60 @@ +From 75ce03b6fdb4d1c5a87de7875f1c083094fefd7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 10:01:01 +0100 +Subject: can: gs_usb: gs_usb_xmit_callback(): fix handling of failed + transmitted URBs + +From: Marc Kleine-Budde + +[ Upstream commit 516a0cd1c03fa266bb67dd87940a209fd4e53ce7 ] + +The driver lacks the cleanup of failed transfers of URBs. This reduces the +number of available URBs per error by 1. This leads to reduced performance +and ultimately to a complete stop of the transmission. + +If the sending of a bulk URB fails do proper cleanup: +- increase netdev stats +- mark the echo_sbk as free +- free the driver's context and do accounting +- wake the send queue + +Closes: https://github.com/candle-usb/candleLight_fw/issues/187 +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-1-a29b42eacada@pengutronix.de +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/gs_usb.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 9bd61fd8e5013..1ba6395a5a667 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -747,8 +747,21 @@ static void gs_usb_xmit_callback(struct urb *urb) + struct gs_can *dev = txc->dev; + struct net_device *netdev = dev->netdev; + +- if (urb->status) +- netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); ++ if (!urb->status) ++ return; ++ ++ if (urb->status != -ESHUTDOWN && net_ratelimit()) ++ netdev_info(netdev, "failed to xmit URB %u: %pe\n", ++ txc->echo_id, ERR_PTR(urb->status)); ++ ++ netdev->stats.tx_dropped++; ++ netdev->stats.tx_errors++; ++ ++ can_free_echo_skb(netdev, txc->echo_id, NULL); ++ gs_free_tx_context(txc); ++ atomic_dec(&dev->active_tx_urbs); ++ ++ netif_wake_queue(netdev); + } + + static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, +-- +2.51.0 + diff --git a/queue-6.6/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch b/queue-6.6/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch new file mode 100644 index 0000000000..e33e132054 --- /dev/null +++ b/queue-6.6/can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch @@ -0,0 +1,62 @@ +From 007a8ceaabb8f5466ef14be9ed4e6cfb3d2acecf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Oct 2025 12:27:09 -0400 +Subject: can: kvaser_usb: leaf: Fix potential infinite loop in command parsers + +From: Seungjin Bae + +[ Upstream commit 0c73772cd2b8cc108d5f5334de89ad648d89b9ec ] + +The `kvaser_usb_leaf_wait_cmd()` and `kvaser_usb_leaf_read_bulk_callback` +functions contain logic to zero-length commands. These commands are used +to align data to the USB endpoint's wMaxPacketSize boundary. + +The driver attempts to skip these placeholders by aligning the buffer +position `pos` to the next packet boundary using `round_up()` function. + +However, if zero-length command is found exactly on a packet boundary +(i.e., `pos` is a multiple of wMaxPacketSize, including 0), `round_up` +function will return the unchanged value of `pos`. This prevents `pos` +to be increased, causing an infinite loop in the parsing logic. + +This patch fixes this in the function by using `pos + 1` instead. +This ensures that even if `pos` is on a boundary, the calculation is +based on `pos + 1`, forcing `round_up()` to always return the next +aligned boundary. + +Fixes: 7259124eac7d ("can: kvaser_usb: Split driver into kvaser_usb_core.c and kvaser_usb_leaf.c") +Signed-off-by: Seungjin Bae +Reviewed-by: Jimmy Assarsson +Tested-by: Jimmy Assarsson +Link: https://patch.msgid.link/20251023162709.348240-1-eeodqql09@gmail.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 23bd7574b1c7e..7b931953dadc4 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -611,7 +611,7 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, + * for further details. + */ + if (tmp->len == 0) { +- pos = round_up(pos, ++ pos = round_up(pos + 1, + le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; +@@ -1590,7 +1590,7 @@ static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, + * number of events in case of a heavy rx load on the bus. + */ + if (cmd->len == 0) { +- pos = round_up(pos, le16_to_cpu ++ pos = round_up(pos + 1, le16_to_cpu + (dev->bulk_in->wMaxPacketSize)); + continue; + } +-- +2.51.0 + diff --git a/queue-6.6/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch b/queue-6.6/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch new file mode 100644 index 0000000000..64f5f441f3 --- /dev/null +++ b/queue-6.6/drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch @@ -0,0 +1,39 @@ +From 6bf3d331c975ee81ff800b9dd0287957255b33ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 09:40:31 -0500 +Subject: drm/amdgpu: fix cyan_skillfish2 gpu info fw handling + +From: Alex Deucher + +[ Upstream commit 7fa666ab07ba9e08f52f357cb8e1aad753e83ac6 ] + +If the board supports IP discovery, we don't need to +parse the gpu info firmware. + +Backport to 6.18. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4721 +Fixes: fa819e3a7c1e ("drm/amdgpu: add support for cyan skillfish gpu_info") +Signed-off-by: Alex Deucher +(cherry picked from commit 5427e32fa3a0ba9a016db83877851ed277b065fb) +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index b2a1dc193cb8f..c1b9333d7b78a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -1941,6 +1941,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) + chip_name = "navi12"; + break; + case CHIP_CYAN_SKILLFISH: ++ if (adev->mman.discovery_bin) ++ return 0; + chip_name = "cyan_skillfish"; + break; + } +-- +2.51.0 + diff --git a/queue-6.6/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch b/queue-6.6/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch new file mode 100644 index 0000000000..5530a7debd --- /dev/null +++ b/queue-6.6/iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch @@ -0,0 +1,132 @@ +From a423c1846b5aa8684b95834f2f65cbcdedb67f86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Oct 2025 18:16:19 +0200 +Subject: iio: st_lsm6dsx: Fixed calibrated timestamp calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mario Tesi + +[ Upstream commit 8abbf45fcda028c2c05ba38eb14ede9fa9e7341b ] + +The calibrated timestamp is calculated from the nominal value using the +formula: + ts_gain[ns] ≈ ts_sensitivity - (ts_trim_coeff * val) / 1000. + +The values of ts_sensitivity and ts_trim_coeff are not the same for all +devices, so it is necessary to differentiate them based on the part name. +For the correct values please consult the relevant AN. + +Fixes: cb3b6b8e1bc0 ("iio: imu: st_lsm6dsx: add odr calibration feature") +Signed-off-by: Mario Tesi +Acked-by: Lorenzo Bianconi +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 18 ++++++++++++++++++ + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 19 ++++++++----------- + 2 files changed, 26 insertions(+), 11 deletions(-) + +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +index c19237717e812..0f347684f6fc9 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +@@ -190,6 +190,22 @@ struct st_lsm6dsx_fifo_ops { + * @fifo_en: Hw timer FIFO enable register info (addr + mask). + * @decimator: Hw timer FIFO decimator register info (addr + mask). + * @freq_fine: Difference in % of ODR with respect to the typical. ++ * @ts_sensitivity: Nominal timestamp sensitivity. ++ * @ts_trim_coeff: Coefficient for calculating the calibrated timestamp gain. ++ * This coefficient comes into play when linearizing the formula ++ * used to calculate the calibrated timestamp (please see the ++ * relevant formula in the AN for the specific IMU). ++ * For example, in the case of LSM6DSO we have: ++ * ++ * 1 / (1 + x) ~= 1 - x (Taylor’s Series) ++ * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) (from AN5192) ++ * ttrim[ns] ~= 25000 - 37.5 * val ++ * ttrim[ns] ~= 25000 - (37500 * val) / 1000 ++ * ++ * so, replacing ts_sensitivity = 25000 and ++ * ts_trim_coeff = 37500 ++ * ++ * ttrim[ns] ~= ts_sensitivity - (ts_trim_coeff * val) / 1000 + */ + struct st_lsm6dsx_hw_ts_settings { + struct st_lsm6dsx_reg timer_en; +@@ -197,6 +213,8 @@ struct st_lsm6dsx_hw_ts_settings { + struct st_lsm6dsx_reg fifo_en; + struct st_lsm6dsx_reg decimator; + u8 freq_fine; ++ u16 ts_sensitivity; ++ u16 ts_trim_coeff; + }; + + /** +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +index b6e6b1df8a618..6e42e0c659e0c 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +@@ -77,8 +77,6 @@ + + #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f + +-#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */ +- + static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { + ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), +@@ -962,6 +960,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x63, ++ .ts_sensitivity = 25000, ++ .ts_trim_coeff = 37500, + }, + .shub_settings = { + .page_mux = { +@@ -1175,6 +1175,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x63, ++ .ts_sensitivity = 25000, ++ .ts_trim_coeff = 37500, + }, + .event_settings = { + .enable_reg = { +@@ -1350,6 +1352,8 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + .mask = GENMASK(7, 6), + }, + .freq_fine = 0x4f, ++ .ts_sensitivity = 21701, ++ .ts_trim_coeff = 28212, + }, + .shub_settings = { + .page_mux = { +@@ -2243,20 +2247,13 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) + } + + /* calibrate timestamp sensitivity */ +- hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY; ++ hw->ts_gain = ts_settings->ts_sensitivity; + if (ts_settings->freq_fine) { + err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); + if (err < 0) + return err; + +- /* +- * linearize the AN5192 formula: +- * 1 / (1 + x) ~= 1 - x (Taylor’s Series) +- * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) +- * ttrim[ns] ~= 25000 - 37.5 * val +- * ttrim[ns] ~= 25000 - (37500 * val) / 1000 +- */ +- hw->ts_gain -= ((s8)val * 37500) / 1000; ++ hw->ts_gain -= ((s8)val * ts_settings->ts_trim_coeff) / 1000; + } + + return 0; +-- +2.51.0 + diff --git a/queue-6.6/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch b/queue-6.6/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch new file mode 100644 index 0000000000..dfd6beb24b --- /dev/null +++ b/queue-6.6/mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch @@ -0,0 +1,38 @@ +From 1ce4753ea297b48e491adfb643bcb75fb3118d80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 10:40:39 +0800 +Subject: mailbox: mailbox-test: Fix debugfs_create_dir error checking + +From: Haotian Zhang + +[ Upstream commit 3acf1028f5003731977f750a7070f3321a9cb740 ] + +The debugfs_create_dir() function returns ERR_PTR() on error, not NULL. +The current null-check fails to catch errors. + +Use IS_ERR() to correctly check for errors. + +Fixes: 8ea4484d0c2b ("mailbox: Add generic mechanism for testing Mailbox Controllers") +Signed-off-by: Haotian Zhang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c +index 22d6018ceec3c..6bdee87f30836 100644 +--- a/drivers/mailbox/mailbox-test.c ++++ b/drivers/mailbox/mailbox-test.c +@@ -268,7 +268,7 @@ static int mbox_test_add_debugfs(struct platform_device *pdev, + return 0; + + tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL); +- if (!tdev->root_debugfs_dir) { ++ if (IS_ERR(tdev->root_debugfs_dir)) { + dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n"); + return -EINVAL; + } +-- +2.51.0 + diff --git a/queue-6.6/mailbox-pcc-don-t-zero-error-register.patch b/queue-6.6/mailbox-pcc-don-t-zero-error-register.patch new file mode 100644 index 0000000000..b90390db87 --- /dev/null +++ b/queue-6.6/mailbox-pcc-don-t-zero-error-register.patch @@ -0,0 +1,57 @@ +From ac5da2a5fc97a9cd4b51dce0ba21032d6bff45e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:42:29 +0000 +Subject: mailbox: pcc: don't zero error register + +From: Jamie Iles + +[ Upstream commit ff0e4d4c97c94af34cc9cad37b5a5cdbe597a3b0 ] + +The error status mask for a type 3/4 subspace is used for reading the +error status, and the bitwise inverse is used for clearing the error +with the intent being to preserve any of the non-error bits. However, +we were previously applying the mask to extract the status and then +applying the inverse to the result which ended up clearing all bits. + +Instead, store the inverse mask in the preserve mask and then use that +on the original value read from the error status so that only the error +is cleared. + +Fixes: c45ded7e1135 ("mailbox: pcc: Add support for PCCT extended PCC subspaces(type 3/4)") +Signed-off-by: Jamie Iles +Signed-off-by: Punit Agrawal +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index bb977cf8ad423..2b7d0bc920726 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -278,9 +278,8 @@ static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) + if (ret) + return ret; + +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; ++ if (val & pchan->error.status_mask) { ++ val &= pchan->error.preserve_mask; + pcc_chan_reg_write(&pchan->error, val); + return -EIO; + } +@@ -673,7 +672,8 @@ static int pcc_parse_subspace_db_reg(struct pcc_chan_info *pchan, + + ret = pcc_chan_reg_init(&pchan->error, + &pcct_ext->error_status_register, +- 0, 0, pcct_ext->error_status_mask, ++ ~pcct_ext->error_status_mask, 0, ++ pcct_ext->error_status_mask, + "Error Status"); + } + return ret; +-- +2.51.0 + diff --git a/queue-6.6/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch b/queue-6.6/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch new file mode 100644 index 0000000000..2c10326595 --- /dev/null +++ b/queue-6.6/mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch @@ -0,0 +1,92 @@ +From 2ed84f02a5c3a92b88c0fc9c7b27a46bfa6a4739 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Mar 2025 15:28:52 +0000 +Subject: mailbox: pcc: Refactor error handling in irq handler into separate + function + +From: Sudeep Holla + +[ Upstream commit 3a675f50415b95f2ae10bfd932e2154ba1a08ee7 ] + +The existing error handling logic in pcc_mbox_irq() is intermixed with the +main flow of the function. The command complete check and the complete +complete update/acknowledgment are nicely factored into separate functions. + +Moves error detection and clearing logic into a separate function called: +pcc_mbox_error_check_and_clear() by extracting error-handling logic from +pcc_mbox_irq(). + +This ensures error checking and clearing are handled separately and it +improves maintainability by keeping the IRQ handler focused on processing +events. + +Acked-by: Huisong Li +Tested-by: Huisong Li +Tested-by: Adam Young +Signed-off-by: Sudeep Holla +Signed-off-by: Jassi Brar +Stable-dep-of: ff0e4d4c97c9 ("mailbox: pcc: don't zero error register") +Signed-off-by: Sasha Levin +--- + drivers/mailbox/pcc.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c +index 49254d99a8ad6..bb977cf8ad423 100644 +--- a/drivers/mailbox/pcc.c ++++ b/drivers/mailbox/pcc.c +@@ -269,6 +269,25 @@ static bool pcc_mbox_cmd_complete_check(struct pcc_chan_info *pchan) + return !!val; + } + ++static int pcc_mbox_error_check_and_clear(struct pcc_chan_info *pchan) ++{ ++ u64 val; ++ int ret; ++ ++ ret = pcc_chan_reg_read(&pchan->error, &val); ++ if (ret) ++ return ret; ++ ++ val &= pchan->error.status_mask; ++ if (val) { ++ val &= ~pchan->error.status_mask; ++ pcc_chan_reg_write(&pchan->error, val); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ + static void check_and_ack(struct pcc_chan_info *pchan, struct mbox_chan *chan) + { + struct acpi_pcct_ext_pcc_shared_memory pcc_hdr; +@@ -309,8 +328,6 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + { + struct pcc_chan_info *pchan; + struct mbox_chan *chan = p; +- u64 val; +- int ret; + + pchan = chan->con_priv; + +@@ -324,15 +341,8 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) + if (!pcc_mbox_cmd_complete_check(pchan)) + return IRQ_NONE; + +- ret = pcc_chan_reg_read(&pchan->error, &val); +- if (ret) ++ if (pcc_mbox_error_check_and_clear(pchan)) + return IRQ_NONE; +- val &= pchan->error.status_mask; +- if (val) { +- val &= ~pchan->error.status_mask; +- pcc_chan_reg_write(&pchan->error, val); +- return IRQ_NONE; +- } + + /* + * Clear this flag after updating interrupt ack register and just +-- +2.51.0 + diff --git a/queue-6.6/net-aquantia-add-missing-descriptor-cache-invalidati.patch b/queue-6.6/net-aquantia-add-missing-descriptor-cache-invalidati.patch new file mode 100644 index 0000000000..f42b893b1a --- /dev/null +++ b/queue-6.6/net-aquantia-add-missing-descriptor-cache-invalidati.patch @@ -0,0 +1,144 @@ +From f7e6996e4bd04d599e40464c28ce806d29e7d713 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 12:15:33 +0800 +Subject: net: aquantia: Add missing descriptor cache invalidation on ATL2 + +From: Kai-Heng Feng + +[ Upstream commit 7526183cfdbe352c51c285762f0e15b7c428ea06 ] + +ATL2 hardware was missing descriptor cache invalidation in hw_stop(), +causing SMMU translation faults during device shutdown and module removal: +[ 70.355743] arm-smmu-v3 arm-smmu-v3.5.auto: event 0x10 received: +[ 70.361893] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0002060000000010 +[ 70.367948] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000020000000000 +[ 70.374002] arm-smmu-v3 arm-smmu-v3.5.auto: 0x00000000ff9bc000 +[ 70.380055] arm-smmu-v3 arm-smmu-v3.5.auto: 0x0000000000000000 +[ 70.386109] arm-smmu-v3 arm-smmu-v3.5.auto: event: F_TRANSLATION client: 0001:06:00.0 sid: 0x20600 ssid: 0x0 iova: 0xff9bc000 ipa: 0x0 +[ 70.398531] arm-smmu-v3 arm-smmu-v3.5.auto: unpriv data write s1 "Input address caused fault" stag: 0x0 + +Commit 7a1bb49461b1 ("net: aquantia: fix potential IOMMU fault after +driver unbind") and commit ed4d81c4b3f2 ("net: aquantia: when cleaning +hw cache it should be toggled") fixed cache invalidation for ATL B0, but +ATL2 was left with only interrupt disabling. This allowed hardware to +write to cached descriptors after DMA memory was unmapped, triggering +SMMU faults. Once cache invalidation is applied to ATL2, the translation +fault can't be observed anymore. + +Add shared aq_hw_invalidate_descriptor_cache() helper and use it in both +ATL B0 and ATL2 hw_stop() implementations for consistent behavior. + +Fixes: e54dcf4bba3e ("net: atlantic: basic A2 init/deinit hw_ops") +Tested-by: Carol Soto +Signed-off-by: Kai-Heng Feng +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251120041537.62184-1-kaihengf@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/aquantia/atlantic/aq_hw_utils.c | 22 +++++++++++++++++++ + .../ethernet/aquantia/atlantic/aq_hw_utils.h | 1 + + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 19 +--------------- + .../aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- + 4 files changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +index 1921741f7311d..18b08277d2e1a 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +@@ -15,6 +15,7 @@ + + #include "aq_hw.h" + #include "aq_nic.h" ++#include "hw_atl/hw_atl_llh.h" + + void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, + u32 shift, u32 val) +@@ -81,6 +82,27 @@ void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value) + lo_hi_writeq(value, hw->mmio + reg); + } + ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw) ++{ ++ int err; ++ u32 val; ++ ++ /* Invalidate Descriptor Cache to prevent writing to the cached ++ * descriptors and to the data pointer of those descriptors ++ */ ++ hw_atl_rdm_rx_dma_desc_cache_init_tgl(hw); ++ ++ err = aq_hw_err_from_flags(hw); ++ if (err) ++ goto err_exit; ++ ++ readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, ++ hw, val, val == 1, 1000U, 10000U); ++ ++err_exit: ++ return err; ++} ++ + int aq_hw_err_from_flags(struct aq_hw_s *hw) + { + int err = 0; +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +index ffa6e4067c211..d89c63d88e4a4 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +@@ -35,6 +35,7 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg(struct aq_hw_s *hw, u32 reg, u32 value); + u64 aq_hw_read_reg64(struct aq_hw_s *hw, u32 reg); + void aq_hw_write_reg64(struct aq_hw_s *hw, u32 reg, u64 value); ++int aq_hw_invalidate_descriptor_cache(struct aq_hw_s *hw); + int aq_hw_err_from_flags(struct aq_hw_s *hw); + int aq_hw_num_tcs(struct aq_hw_s *hw); + int aq_hw_q_per_tc(struct aq_hw_s *hw); +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +index 54e70f07b5734..7b4814b3ba442 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +@@ -1198,26 +1198,9 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) + + static int hw_atl_b0_hw_stop(struct aq_hw_s *self) + { +- int err; +- u32 val; +- + hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +- /* Invalidate Descriptor Cache to prevent writing to the cached +- * descriptors and to the data pointer of those descriptors +- */ +- hw_atl_rdm_rx_dma_desc_cache_init_tgl(self); +- +- err = aq_hw_err_from_flags(self); +- +- if (err) +- goto err_exit; +- +- readx_poll_timeout_atomic(hw_atl_rdm_rx_dma_desc_cache_init_done_get, +- self, val, val == 1, 1000U, 10000U); +- +-err_exit: +- return err; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + int hw_atl_b0_hw_ring_tx_stop(struct aq_hw_s *self, struct aq_ring_s *ring) +diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +index 220400a633f5e..a7bef9da823da 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c ++++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +@@ -759,7 +759,7 @@ static int hw_atl2_hw_stop(struct aq_hw_s *self) + { + hw_atl_b0_hw_irq_disable(self, HW_ATL2_INT_MASK); + +- return 0; ++ return aq_hw_invalidate_descriptor_cache(self); + } + + static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self) +-- +2.51.0 + diff --git a/queue-6.6/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch b/queue-6.6/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch new file mode 100644 index 0000000000..3258e18c17 --- /dev/null +++ b/queue-6.6/net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch @@ -0,0 +1,93 @@ +From fe8b7626622ee197fd4721fc67f21e62a31d10a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 11:22:49 +0800 +Subject: net: atlantic: fix fragment overflow handling in RX path + +From: Jiefeng Zhang + +[ Upstream commit 5ffcb7b890f61541201461580bb6622ace405aec ] + +The atlantic driver can receive packets with more than MAX_SKB_FRAGS (17) +fragments when handling large multi-descriptor packets. This causes an +out-of-bounds write in skb_add_rx_frag_netmem() leading to kernel panic. + +The issue occurs because the driver doesn't check the total number of +fragments before calling skb_add_rx_frag(). When a packet requires more +than MAX_SKB_FRAGS fragments, the fragment index exceeds the array bounds. + +Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, +then all fragments are accounted for. And reusing the existing check to +prevent the overflow earlier in the code path. + +This crash occurred in production with an Aquantia AQC113 10G NIC. + +Stack trace from production environment: +``` +RIP: 0010:skb_add_rx_frag_netmem+0x29/0xd0 +Code: 90 f3 0f 1e fa 0f 1f 44 00 00 48 89 f8 41 89 +ca 48 89 d7 48 63 ce 8b 90 c0 00 00 00 48 c1 e1 04 48 01 ca 48 03 90 +c8 00 00 00 <48> 89 7a 30 44 89 52 3c 44 89 42 38 40 f6 c7 01 75 74 48 +89 fa 83 +RSP: 0018:ffffa9bec02a8d50 EFLAGS: 00010287 +RAX: ffff925b22e80a00 RBX: ffff925ad38d2700 RCX: +fffffffe0a0c8000 +RDX: ffff9258ea95bac0 RSI: ffff925ae0a0c800 RDI: +0000000000037a40 +RBP: 0000000000000024 R08: 0000000000000000 R09: +0000000000000021 +R10: 0000000000000848 R11: 0000000000000000 R12: +ffffa9bec02a8e24 +R13: ffff925ad8615570 R14: 0000000000000000 R15: +ffff925b22e80a00 +FS: 0000000000000000(0000) +GS:ffff925e47880000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffff9258ea95baf0 CR3: 0000000166022004 CR4: +0000000000f72ef0 +PKRU: 55555554 +Call Trace: + +aq_ring_rx_clean+0x175/0xe60 [atlantic] +? aq_ring_rx_clean+0x14d/0xe60 [atlantic] +? aq_ring_tx_clean+0xdf/0x190 [atlantic] +? kmem_cache_free+0x348/0x450 +? aq_vec_poll+0x81/0x1d0 [atlantic] +? __napi_poll+0x28/0x1c0 +? net_rx_action+0x337/0x420 +``` + +Fixes: 6aecbba12b5c ("net: atlantic: add check for MAX_SKB_FRAGS") +Changes in v4: +- Add Fixes: tag to satisfy patch validation requirements. + +Changes in v3: +- Fix by assuming there will be an extra frag if buff->len > AQ_CFG_RX_HDR_SIZE, + then all fragments are accounted for. + +Signed-off-by: Jiefeng Zhang +Link: https://patch.msgid.link/20251126032249.69358-1-jiefeng.z.zhang@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +index f7433abd65915..3f004d08307fb 100644 +--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c ++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +@@ -547,6 +547,11 @@ static int __aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi, + + if (!buff->is_eop) { + unsigned int frag_cnt = 0U; ++ ++ /* There will be an extra fragment */ ++ if (buff->len > AQ_CFG_RX_HDR_SIZE) ++ frag_cnt++; ++ + buff_ = buff; + do { + bool is_rsc_completed = true; +-- +2.51.0 + diff --git a/queue-6.6/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch b/queue-6.6/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch new file mode 100644 index 0000000000..30ef7c237e --- /dev/null +++ b/queue-6.6/net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch @@ -0,0 +1,73 @@ +From 0531a52c763c06ccc21ace6f636a48ff5d12a0c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Nov 2025 13:13:24 +0200 +Subject: net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing + traffic + +From: Vladimir Oltean + +[ Upstream commit da62abaaa268357b1aa66b372ace562189a05df1 ] + +When using the SGMII PCS as a fixed-link chip-to-chip connection, it is +easy to miss the fact that traffic passes only at 1G, since that's what +any normal such connection would use. + +When using the SGMII PCS connected towards an on-board PHY or an SFP +module, it is immediately noticeable that when the link resolves to a +speed other than 1G, traffic from the MAC fails to pass: TX counters +increase, but nothing gets decoded by the other end, and no local RX +counters increase either. + +Artificially lowering a fixed-link rate to speed = <100> makes us able +to see the same issue as in the case of having an SGMII PHY. + +Some debugging shows that the XPCS configuration is A-OK, but that the +MAC Configuration Table entry for the port has the SPEED bits still set +to 1000Mbps, due to a special condition in the driver. Deleting that +condition, and letting the resolved link speed be programmed directly +into the MAC speed field, results in a functional link at all 3 speeds. + +This piece of evidence, based on testing on both generations with SGMII +support (SJA1105S and SJA1110A) directly contradicts the statement from +the blamed commit that "the MAC is fixed at 1 Gbps and we need to +configure the PCS only (if even that)". Worse, that statement is not +backed by any documentation, and no one from NXP knows what it might +refer to. + +I am unable to recall sufficient context regarding my testing from March +2020 to understand what led me to draw such a braindead and factually +incorrect conclusion. Yet, there is nothing of value regarding forcing +the MAC speed, either for SGMII or 2500Base-X (introduced at a later +stage), so remove all such logic. + +Fixes: ffe10e679cec ("net: dsa: sja1105: Add support for the SGMII port") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20251122111324.136761-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index 0de73a6257f9a..1acc5d912d161 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1307,14 +1307,7 @@ static int sja1105_set_port_speed(struct sja1105_private *priv, int port, + * table, since this will be used for the clocking setup, and we no + * longer need to store it in the static config (already told hardware + * we want auto during upload phase). +- * Actually for the SGMII port, the MAC is fixed at 1 Gbps and +- * we need to configure the PCS only (if even that). + */ +- if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; +- else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- + mac[port].speed = speed; + + return 0; +-- +2.51.0 + diff --git a/queue-6.6/net-dsa-sja1105-simplify-static-configuration-reload.patch b/queue-6.6/net-dsa-sja1105-simplify-static-configuration-reload.patch new file mode 100644 index 0000000000..5f794a2076 --- /dev/null +++ b/queue-6.6/net-dsa-sja1105-simplify-static-configuration-reload.patch @@ -0,0 +1,159 @@ +From b868b4fbe230d28bb168a69bf9003fc1af18abd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2024 17:04:36 +0100 +Subject: net: dsa: sja1105: simplify static configuration reload + +From: Russell King (Oracle) + +[ Upstream commit a18891b55703a45b700618ef40edd5e9aaecc345 ] + +The static configuration reload saves the port speed in the static +configuration tables by first converting it from the internal +respresentation to the SPEED_xxx ethtool representation, and then +converts it back to restore the setting. This is because +sja1105_adjust_port_config() takes the speed as SPEED_xxx. + +However, this is unnecessarily complex. If we split +sja1105_adjust_port_config() up, we can simply save and restore the +mac[port].speed member in the static configuration tables. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1svfMa-005ZIX-If@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: da62abaaa268 ("net: dsa: sja1105: fix SGMII linking at 10M or 100M but not passing traffic") +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_main.c | 65 ++++++++++++++------------ + 1 file changed, 34 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index 843e50b5a0ec5..0de73a6257f9a 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1261,29 +1261,11 @@ static int sja1105_parse_dt(struct sja1105_private *priv) + return rc; + } + +-/* Convert link speed from SJA1105 to ethtool encoding */ +-static int sja1105_port_speed_to_ethtool(struct sja1105_private *priv, +- u64 speed) +-{ +- if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) +- return SPEED_10; +- if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) +- return SPEED_100; +- if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) +- return SPEED_1000; +- if (speed == priv->info->port_speed[SJA1105_SPEED_2500MBPS]) +- return SPEED_2500; +- return SPEED_UNKNOWN; +-} +- +-/* Set link speed in the MAC configuration for a specific port. */ +-static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, +- int speed_mbps) ++static int sja1105_set_port_speed(struct sja1105_private *priv, int port, ++ int speed_mbps) + { + struct sja1105_mac_config_entry *mac; +- struct device *dev = priv->ds->dev; + u64 speed; +- int rc; + + /* On P/Q/R/S, one can read from the device via the MAC reconfiguration + * tables. On E/T, MAC reconfig tables are not readable, only writable. +@@ -1317,7 +1299,7 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; + break; + default: +- dev_err(dev, "Invalid speed %iMbps\n", speed_mbps); ++ dev_err(priv->ds->dev, "Invalid speed %iMbps\n", speed_mbps); + return -EINVAL; + } + +@@ -1329,11 +1311,31 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, + * we need to configure the PCS only (if even that). + */ + if (priv->phy_mode[port] == PHY_INTERFACE_MODE_SGMII) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; ++ speed = priv->info->port_speed[SJA1105_SPEED_1000MBPS]; + else if (priv->phy_mode[port] == PHY_INTERFACE_MODE_2500BASEX) +- mac[port].speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; +- else +- mac[port].speed = speed; ++ speed = priv->info->port_speed[SJA1105_SPEED_2500MBPS]; ++ ++ mac[port].speed = speed; ++ ++ return 0; ++} ++ ++/* Write the MAC Configuration Table entry and, if necessary, the CGU settings, ++ * after a link speedchange for this port. ++ */ ++static int sja1105_set_port_config(struct sja1105_private *priv, int port) ++{ ++ struct sja1105_mac_config_entry *mac; ++ struct device *dev = priv->ds->dev; ++ int rc; ++ ++ /* On P/Q/R/S, one can read from the device via the MAC reconfiguration ++ * tables. On E/T, MAC reconfig tables are not readable, only writable. ++ * We have to *know* what the MAC looks like. For the sake of keeping ++ * the code common, we'll use the static configuration tables as a ++ * reasonable approximation for both E/T and P/Q/R/S. ++ */ ++ mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + + /* Write to the dynamic reconfiguration tables */ + rc = sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, +@@ -1383,7 +1385,8 @@ static void sja1105_mac_link_up(struct dsa_switch *ds, int port, + { + struct sja1105_private *priv = ds->priv; + +- sja1105_adjust_port_config(priv, port, speed); ++ if (!sja1105_set_port_speed(priv, port, speed)) ++ sja1105_set_port_config(priv, port); + + sja1105_inhibit_tx(priv, BIT(port), false); + } +@@ -2284,8 +2287,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + { + struct ptp_system_timestamp ptp_sts_before; + struct ptp_system_timestamp ptp_sts_after; +- int speed_mbps[SJA1105_MAX_NUM_PORTS]; + u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0}; ++ u64 mac_speed[SJA1105_MAX_NUM_PORTS]; + struct sja1105_mac_config_entry *mac; + struct dsa_switch *ds = priv->ds; + s64 t1, t2, t3, t4; +@@ -2298,14 +2301,13 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + +- /* Back up the dynamic link speed changed by sja1105_adjust_port_config ++ /* Back up the dynamic link speed changed by sja1105_set_port_speed() + * in order to temporarily restore it to SJA1105_SPEED_AUTO - which the + * switch wants to see in the static config in order to allow us to + * change it through the dynamic interface later. + */ + for (i = 0; i < ds->num_ports; i++) { +- speed_mbps[i] = sja1105_port_speed_to_ethtool(priv, +- mac[i].speed); ++ mac_speed[i] = mac[i].speed; + mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO]; + + if (priv->xpcs[i]) +@@ -2368,7 +2370,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, + struct dw_xpcs *xpcs = priv->xpcs[i]; + unsigned int neg_mode; + +- rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); ++ mac[i].speed = mac_speed[i]; ++ rc = sja1105_set_port_config(priv, i); + if (rc < 0) + goto out; + +-- +2.51.0 + diff --git a/queue-6.6/net-fec-cancel-perout_timer-when-perout-is-disabled.patch b/queue-6.6/net-fec-cancel-perout_timer-when-perout-is-disabled.patch new file mode 100644 index 0000000000..eea1d8552f --- /dev/null +++ b/queue-6.6/net-fec-cancel-perout_timer-when-perout-is-disabled.patch @@ -0,0 +1,42 @@ +From 154dff42240b04b4495c96630f197d71e3fc2cb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:07 +0800 +Subject: net: fec: cancel perout_timer when PEROUT is disabled + +From: Wei Fang + +[ Upstream commit 50caa744689e505414673c20359b04aa918439e3 ] + +The PEROUT allows the user to set a specified future time to output the +periodic signal. If the future time is far from the current time, the FEC +driver will use hrtimer to configure PEROUT one second before the future +time. However, the hrtimer will not be canceled if the PEROUT is disabled +before the hrtimer expires. So the PEROUT will be configured when the +hrtimer expires, which is not as expected. Therefore, cancel the hrtimer +in fec_ptp_pps_disable() to fix this issue. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-2-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index 7f6b574320716..cb3f05da3eee6 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -498,6 +498,8 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) + { + unsigned long flags; + ++ hrtimer_cancel(&fep->perout_timer); ++ + spin_lock_irqsave(&fep->tmreg_lock, flags); + writel(0, fep->hwp + FEC_TCSR(channel)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); +-- +2.51.0 + diff --git a/queue-6.6/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch b/queue-6.6/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch new file mode 100644 index 0000000000..85329a0652 --- /dev/null +++ b/queue-6.6/net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch @@ -0,0 +1,58 @@ +From 0fce626b2b228fb1699019cbc3e3de4010092f04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:09 +0800 +Subject: net: fec: do not allow enabling PPS and PEROUT simultaneously + +From: Wei Fang + +[ Upstream commit c0a1f3d7e128e8d1b6c0fe09c68eac5ebcf677c8 ] + +In the current driver, PPS and PEROUT use the same channel to generate +the events, so they cannot be enabled at the same time. Otherwise, the +later configuration will overwrite the earlier configuration. Therefore, +when configuring PPS, the driver will check whether PEROUT is enabled. +Similarly, when configuring PEROUT, the driver will check whether PPS +is enabled. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-4-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index a3853fccdc7b6..beb1d98fa741a 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -129,6 +129,12 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->perout_enable) { ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ dev_err(&fep->pdev->dev, "PEROUT is running"); ++ return -EBUSY; ++ } ++ + if (fep->pps_enable == enable) { + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return 0; +@@ -572,6 +578,12 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + } + spin_lock_irqsave(&fep->tmreg_lock, flags); + ++ if (fep->pps_enable) { ++ dev_err(&fep->pdev->dev, "PPS is running"); ++ ret = -EBUSY; ++ goto unlock; ++ } ++ + if (fep->perout_enable) { + dev_err(&fep->pdev->dev, + "PEROUT has been enabled\n"); +-- +2.51.0 + diff --git a/queue-6.6/net-fec-do-not-register-pps-event-for-perout.patch b/queue-6.6/net-fec-do-not-register-pps-event-for-perout.patch new file mode 100644 index 0000000000..1d3170eed3 --- /dev/null +++ b/queue-6.6/net-fec-do-not-register-pps-event-for-perout.patch @@ -0,0 +1,48 @@ +From 315ef572f3f8dfb7fefc6c95f8c69aabb557f3c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:10 +0800 +Subject: net: fec: do not register PPS event for PEROUT + +From: Wei Fang + +[ Upstream commit 9a060d0fac9e75524f72864adec6d8cdb70a5bca ] + +There are currently two situations that can trigger the PTP interrupt, +one is the PPS event, the other is the PEROUT event. However, the irq +handler fec_pps_interrupt() does not check the irq event type and +directly registers a PPS event into the system, but the event may be +a PEROUT event. This is incorrect because PEROUT is an output signal, +while PPS is the input of the kernel PPS system. Therefore, add a check +for the event type, if pps_enable is true, it means that the current +event is a PPS event, and then the PPS event is registered. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-5-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_ptp.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index beb1d98fa741a..4bb894b5afcb9 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -719,8 +719,11 @@ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) + fep->next_counter = (fep->next_counter + fep->reload_period) & + fep->cc.mask; + +- event.type = PTP_CLOCK_PPS; +- ptp_clock_event(fep->ptp_clock, &event); ++ if (fep->pps_enable) { ++ event.type = PTP_CLOCK_PPS; ++ ptp_clock_event(fep->ptp_clock, &event); ++ } ++ + return IRQ_HANDLED; + } + +-- +2.51.0 + diff --git a/queue-6.6/net-fec-do-not-update-perout-if-it-is-enabled.patch b/queue-6.6/net-fec-do-not-update-perout-if-it-is-enabled.patch new file mode 100644 index 0000000000..2ffdb3564a --- /dev/null +++ b/queue-6.6/net-fec-do-not-update-perout-if-it-is-enabled.patch @@ -0,0 +1,137 @@ +From bcc78467e4709dccd613569f78ca5871b4343149 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Nov 2025 16:52:08 +0800 +Subject: net: fec: do not update PEROUT if it is enabled + +From: Wei Fang + +[ Upstream commit e97faa0c20ea8840f45569ba434e30538fff8fc9 ] + +If the previously set PEROUT is already active, updating it will cause +the new PEROUT to start immediately instead of at the specified time. +This is because fep->reload_period is updated whithout check whether +the PEROUT is enabled, and the old PEROUT is not disabled. Therefore, +the pulse period will be updated immediately in the pulse interrupt +handler fec_pps_interrupt(). + +Currently, the driver does not support directly updating PEROUT and it +will make the logic be more complicated. To fix the current issue, add +a check before enabling the PEROUT, the driver will return an error if +PEROUT is enabled. If users wants to update a new PEROUT, they should +disable the old PEROUT first. + +Fixes: 350749b909bf ("net: fec: Add support for periodic output signal of PPS") +Signed-off-by: Wei Fang +Link: https://patch.msgid.link/20251125085210.1094306-3-wei.fang@nxp.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec.h | 1 + + drivers/net/ethernet/freescale/fec_ptp.c | 43 ++++++++++++++++++------ + 2 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index 733af928caffc..d80a8c07c0200 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -683,6 +683,7 @@ struct fec_enet_private { + unsigned int reload_period; + int pps_enable; + unsigned int next_counter; ++ bool perout_enable; + struct hrtimer perout_timer; + u64 perout_stime; + +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index cb3f05da3eee6..a3853fccdc7b6 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -244,6 +244,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep) + * the FEC_TCCR register in time and missed the start time. + */ + if (fep->perout_stime < curr_time + 100 * NSEC_PER_MSEC) { ++ fep->perout_enable = false; + dev_err(&fep->pdev->dev, "Current time is too close to the start time!\n"); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + return -1; +@@ -501,6 +502,7 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel) + hrtimer_cancel(&fep->perout_timer); + + spin_lock_irqsave(&fep->tmreg_lock, flags); ++ fep->perout_enable = false; + writel(0, fep->hwp + FEC_TCSR(channel)); + spin_unlock_irqrestore(&fep->tmreg_lock, flags); + +@@ -532,6 +534,8 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + + return ret; + } else if (rq->type == PTP_CLK_REQ_PEROUT) { ++ u32 reload_period; ++ + /* Reject requests with unsupported flags */ + if (rq->perout.flags) + return -EOPNOTSUPP; +@@ -551,12 +555,14 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + return -EOPNOTSUPP; + } + +- fep->reload_period = div_u64(period_ns, 2); +- if (on && fep->reload_period) { ++ reload_period = div_u64(period_ns, 2); ++ if (on && reload_period) { ++ u64 perout_stime; ++ + /* Convert 1588 timestamp to ns*/ + start_time.tv_sec = rq->perout.start.sec; + start_time.tv_nsec = rq->perout.start.nsec; +- fep->perout_stime = timespec64_to_ns(&start_time); ++ perout_stime = timespec64_to_ns(&start_time); + + mutex_lock(&fep->ptp_clk_mutex); + if (!fep->ptp_clk_on) { +@@ -565,18 +571,35 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, + return -EOPNOTSUPP; + } + spin_lock_irqsave(&fep->tmreg_lock, flags); ++ ++ if (fep->perout_enable) { ++ dev_err(&fep->pdev->dev, ++ "PEROUT has been enabled\n"); ++ ret = -EBUSY; ++ goto unlock; ++ } ++ + /* Read current timestamp */ + curr_time = timecounter_read(&fep->tc); +- spin_unlock_irqrestore(&fep->tmreg_lock, flags); +- mutex_unlock(&fep->ptp_clk_mutex); ++ if (perout_stime <= curr_time) { ++ dev_err(&fep->pdev->dev, ++ "Start time must be greater than current time\n"); ++ ret = -EINVAL; ++ goto unlock; ++ } + + /* Calculate time difference */ +- delta = fep->perout_stime - curr_time; ++ delta = perout_stime - curr_time; ++ fep->reload_period = reload_period; ++ fep->perout_stime = perout_stime; ++ fep->perout_enable = true; + +- if (fep->perout_stime <= curr_time) { +- dev_err(&fep->pdev->dev, "Start time must larger than current time!\n"); +- return -EINVAL; +- } ++unlock: ++ spin_unlock_irqrestore(&fep->tmreg_lock, flags); ++ mutex_unlock(&fep->ptp_clk_mutex); ++ ++ if (ret) ++ return ret; + + /* Because the timer counter of FEC only has 31-bits, correspondingly, + * the time comparison register FEC_TCCR also only low 31 bits can be +-- +2.51.0 + diff --git a/queue-6.6/net-lan966x-fix-the-initialization-of-taprio.patch b/queue-6.6/net-lan966x-fix-the-initialization-of-taprio.patch new file mode 100644 index 0000000000..75dba22c34 --- /dev/null +++ b/queue-6.6/net-lan966x-fix-the-initialization-of-taprio.patch @@ -0,0 +1,56 @@ +From 966b8ac6e88ccb0e7da6f8de124b58de479e6581 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 07:14:11 +0100 +Subject: net: lan966x: Fix the initialization of taprio + +From: Horatiu Vultur + +[ Upstream commit 9780f535f8e0f20b4632b5a173ead71aa8f095d2 ] + +To initialize the taprio block in lan966x, it is required to configure +the register REVISIT_DLY. The purpose of this register is to set the +delay before revisit the next gate and the value of this register depends +on the system clock. The problem is that the we calculated wrong the value +of the system clock period in picoseconds. The actual system clock is +~165.617754MHZ and this correspond to a period of 6038 pico seconds and +not 15125 as currently set. + +Fixes: e462b2717380b4 ("net: lan966x: Add offload support for taprio") +Signed-off-by: Horatiu Vultur +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121061411.810571-1-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +index 87e5e81d40dc6..84f5b4410e48e 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c +@@ -1,11 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0+ + + #include ++#include + + #include "lan966x_main.h" + #include "vcap_api.h" + #include "vcap_api_client.h" + ++#define LAN9X66_CLOCK_RATE 165617754 ++ + #define LAN966X_MAX_PTP_ID 512 + + /* Represents 1ppm adjustment in 2^59 format with 6.037735849ns as reference +@@ -1132,5 +1135,5 @@ void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, + u32 lan966x_ptp_get_period_ps(void) + { + /* This represents the system clock period in picoseconds */ +- return 15125; ++ return PICO / LAN9X66_CLOCK_RATE; + } +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5e-fix-validation-logic-in-rate-limiting.patch b/queue-6.6/net-mlx5e-fix-validation-logic-in-rate-limiting.patch new file mode 100644 index 0000000000..0b8dceb72d --- /dev/null +++ b/queue-6.6/net-mlx5e-fix-validation-logic-in-rate-limiting.patch @@ -0,0 +1,63 @@ +From 19d7956379623190125df62a066356f6dcf60a7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:00:43 -0800 +Subject: net/mlx5e: Fix validation logic in rate limiting + +From: Danielle Costantino + +[ Upstream commit d2099d9f16dbfa1c5266d4230ff7860047bb0b68 ] + +The rate limiting validation condition currently checks the output +variable max_bw_value[i] instead of the input value +maxrate->tc_maxrate[i]. This causes the validation to compare an +uninitialized or stale value rather than the actual requested rate. + +The condition should check the input rate to properly validate against +the upper limit: + + } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + +This aligns with the pattern used in the first branch, which correctly +checks maxrate->tc_maxrate[i] against upper_limit_mbps. + +The current implementation can lead to unreliable validation behavior: + +- For rates between 25.5 Gbps and 255 Gbps, if max_bw_value[i] is 0 + from initialization, the GBPS path may be taken regardless of whether + the actual rate is within bounds + +- When processing multiple TCs (i > 0), max_bw_value[i] contains the + value computed for the previous TC, affecting the validation logic + +- The overflow check for rates exceeding 255 Gbps may not trigger + consistently depending on previous array values + +This patch ensures the validation correctly examines the requested rate +value for proper bounds checking. + +Fixes: 43b27d1bd88a ("net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps") +Signed-off-by: Danielle Costantino +Reviewed-by: Gal Pressman +Link: https://patch.msgid.link/20251124180043.2314428-1-dcostantino@meta.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 29e633e6dd3f0..e29a8ed7e7ac1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -619,7 +619,7 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else if (max_bw_value[i] <= upper_limit_gbps) { ++ } else if (maxrate->tc_maxrate[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; +-- +2.51.0 + diff --git a/queue-6.6/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch b/queue-6.6/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch new file mode 100644 index 0000000000..c9c8e2ee29 --- /dev/null +++ b/queue-6.6/net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch @@ -0,0 +1,42 @@ +From 9966de5088b4b34f1db3d0efa433368dc7f953d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Nov 2025 14:17:13 +0000 +Subject: net: phy: mxl-gpy: fix bogus error on USXGMII and integrated PHY + +From: Daniel Golle + +[ Upstream commit ec3803b5917b6ff2f86ea965d0985c95d8a85119 ] + +As the interface mode doesn't need to be updated on PHYs connected with +USXGMII and integrated PHYs, gpy_update_interface() should just return 0 +in these cases rather than -EINVAL which has wrongly been introduced by +commit 7a495dde27ebc ("net: phy: mxl-gpy: Change gpy_update_interface() +function return type"), as this breaks support for those PHYs. + +Fixes: 7a495dde27ebc ("net: phy: mxl-gpy: Change gpy_update_interface() function return type") +Signed-off-by: Daniel Golle +Reviewed-by: Maxime Chevallier +Reviewed-by: Russell King (Oracle) +Link: https://patch.msgid.link/f744f721a1fcc5e2e936428c62ff2c7d94d2a293.1763648168.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mxl-gpy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c +index 034f5c4d03377..5868a0747097f 100644 +--- a/drivers/net/phy/mxl-gpy.c ++++ b/drivers/net/phy/mxl-gpy.c +@@ -515,7 +515,7 @@ static int gpy_update_interface(struct phy_device *phydev) + /* Interface mode is fixed for USXGMII and integrated PHY */ + if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || + phydev->interface == PHY_INTERFACE_MODE_INTERNAL) +- return -EINVAL; ++ return 0; + + /* Automatically switch SERDES interface between SGMII and 2500-BaseX + * according to speed. Disable ANEG in 2500-BaseX mode. +-- +2.51.0 + diff --git a/queue-6.6/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch b/queue-6.6/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch new file mode 100644 index 0000000000..5d4297e333 --- /dev/null +++ b/queue-6.6/net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch @@ -0,0 +1,47 @@ +From 2d112a7540c0bdbd79c80d508df148132877ed72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 12:38:34 +0000 +Subject: net: sxgbe: fix potential NULL dereference in sxgbe_rx() + +From: Alexey Kodanev + +[ Upstream commit f5bce28f6b9125502abec4a67d68eabcd24b3b17 ] + +Currently, when skb is null, the driver prints an error and then +dereferences skb on the next line. + +To fix this, let's add a 'break' after the error message to switch +to sxgbe_rx_refill(), which is similar to the approach taken by the +other drivers in this particular case, e.g. calxeda with xgmac_rx(). + +Found during a code review. + +Fixes: 1edb9ca69e8a ("net: sxgbe: add basic framework for Samsung 10Gb ethernet driver") +Signed-off-by: Alexey Kodanev +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251121123834.97748-1-aleksei.kodanev@bell-sw.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +index 71439825ea4e0..d662679c29832 100644 +--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c ++++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +@@ -1521,8 +1521,10 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) + + skb = priv->rxq[qnum]->rx_skbuff[entry]; + +- if (unlikely(!skb)) ++ if (unlikely(!skb)) { + netdev_err(priv->dev, "rx descriptor is not consistent\n"); ++ break; ++ } + + prefetch(skb->data - NET_IP_ALIGN); + priv->rxq[qnum]->rx_skbuff[entry] = NULL; +-- +2.51.0 + diff --git a/queue-6.6/platform-x86-intel-punit_ipc-fix-memory-corruption.patch b/queue-6.6/platform-x86-intel-punit_ipc-fix-memory-corruption.patch new file mode 100644 index 0000000000..f1116bd681 --- /dev/null +++ b/queue-6.6/platform-x86-intel-punit_ipc-fix-memory-corruption.patch @@ -0,0 +1,46 @@ +From b011302d23bdf3a7d1b01c61606bbc1d8339e2b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Nov 2025 20:51:28 +0300 +Subject: platform/x86: intel: punit_ipc: fix memory corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit 9b9c0adbc3f8a524d291baccc9d0c04097fb4869 ] + +This passes the address of the pointer "&punit_ipcdev" when the intent +was to pass the pointer itself "punit_ipcdev" (without the ampersand). +This means that the: + + complete(&ipcdev->cmd_complete); + +in intel_punit_ioc() will write to a wrong memory address corrupting it. + +Fixes: fdca4f16f57d ("platform:x86: add Intel P-Unit mailbox IPC driver") +Signed-off-by: Dan Carpenter +Link: https://patch.msgid.link/aSCmoBipSQ_tlD-D@stanley.mountain +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/punit_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/punit_ipc.c b/drivers/platform/x86/intel/punit_ipc.c +index cd0ba84cc8e4a..9e48229538a5e 100644 +--- a/drivers/platform/x86/intel/punit_ipc.c ++++ b/drivers/platform/x86/intel/punit_ipc.c +@@ -283,7 +283,7 @@ static int intel_punit_ipc_probe(struct platform_device *pdev) + } else { + ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc, + IRQF_NO_SUSPEND, "intel_punit_ipc", +- &punit_ipcdev); ++ punit_ipcdev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", irq); + return ret; +-- +2.51.0 + diff --git a/queue-6.6/series b/queue-6.6/series new file mode 100644 index 0000000000..c17fb07ce7 --- /dev/null +++ b/queue-6.6/series @@ -0,0 +1,33 @@ +can-kvaser_usb-leaf-fix-potential-infinite-loop-in-c.patch +can-gs_usb-gs_usb_xmit_callback-fix-handling-of-fail.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch +can-gs_usb-gs_usb_receive_bulk_callback-check-actual.patch-2290 +bluetooth-hci_sock-prevent-race-in-socket-write-iter.patch +bluetooth-smp-fix-not-generating-mackey-and-ltk-when.patch +net-phy-mxl-gpy-fix-bogus-error-on-usxgmii-and-integ.patch +platform-x86-intel-punit_ipc-fix-memory-corruption.patch +net-aquantia-add-missing-descriptor-cache-invalidati.patch +net-lan966x-fix-the-initialization-of-taprio.patch +net-mlx5e-fix-validation-logic-in-rate-limiting.patch +net-sxgbe-fix-potential-null-dereference-in-sxgbe_rx.patch +drm-amdgpu-fix-cyan_skillfish2-gpu-info-fw-handling.patch +net-dsa-sja1105-simplify-static-configuration-reload.patch +net-dsa-sja1105-fix-sgmii-linking-at-10m-or-100m-but.patch +net-atlantic-fix-fragment-overflow-handling-in-rx-pa.patch +net-fec-cancel-perout_timer-when-perout-is-disabled.patch +net-fec-do-not-update-perout-if-it-is-enabled.patch +net-fec-do-not-allow-enabling-pps-and-perout-simulta.patch +net-fec-do-not-register-pps-event-for-perout.patch +iio-st_lsm6dsx-fixed-calibrated-timestamp-calculatio.patch +usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch +mailbox-mailbox-test-fix-debugfs_create_dir-error-ch.patch +mailbox-pcc-refactor-error-handling-in-irq-handler-i.patch +mailbox-pcc-don-t-zero-error-register.patch +spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch +spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch +spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch +spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch +spi-spi-mem-add-a-new-controller-capability.patch +spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch +spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch +spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch diff --git a/queue-6.6/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch b/queue-6.6/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch new file mode 100644 index 0000000000..8909b8ceaf --- /dev/null +++ b/queue-6.6/spi-amlogic-spifc-a1-handle-devm_pm_runtime_enable-e.patch @@ -0,0 +1,42 @@ +From c93aa495cf3e15d9ebaf1e11e5a4fb4cbd1afb4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 09:58:52 +0800 +Subject: spi: amlogic-spifc-a1: Handle devm_pm_runtime_enable() errors + +From: Haotian Zhang + +[ Upstream commit a90903c2a3c38bce475f46ea3f93dbf6a9971553 ] + +devm_pm_runtime_enable() can fail due to memory allocation. The current +code ignores its return value, potentially causing runtime PM operations +to fail silently after autosuspend configuration. + +Check the return value of devm_pm_runtime_enable() and return on failure. + +Fixes: 909fac05b926 ("spi: add support for Amlogic A1 SPI Flash Controller") +Signed-off-by: Haotian Zhang +Link: https://patch.msgid.link/20251124015852.937-1-vulab@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-amlogic-spifc-a1.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-amlogic-spifc-a1.c b/drivers/spi/spi-amlogic-spifc-a1.c +index fadf6667cd51c..b430bca4f8bce 100644 +--- a/drivers/spi/spi-amlogic-spifc-a1.c ++++ b/drivers/spi/spi-amlogic-spifc-a1.c +@@ -349,7 +349,9 @@ static int amlogic_spifc_a1_probe(struct platform_device *pdev) + + pm_runtime_set_autosuspend_delay(spifc->dev, 500); + pm_runtime_use_autosuspend(spifc->dev); +- devm_pm_runtime_enable(spifc->dev); ++ ret = devm_pm_runtime_enable(spifc->dev); ++ if (ret) ++ return ret; + + ctrl->num_chipselect = 1; + ctrl->dev.of_node = pdev->dev.of_node; +-- +2.51.0 + diff --git a/queue-6.6/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch b/queue-6.6/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch new file mode 100644 index 0000000000..42be2d3b64 --- /dev/null +++ b/queue-6.6/spi-bcm63xx-fix-premature-cs-deassertion-on-rx-only-.patch @@ -0,0 +1,68 @@ +From 5fba3709d48bb6f2b350578042c9d78db1fdfeb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 01:08:35 +1100 +Subject: spi: bcm63xx: fix premature CS deassertion on RX-only transactions + +From: Hang Zhou <929513338@qq.com> + +[ Upstream commit fd9862f726aedbc2f29a29916cabed7bcf5cadb6 ] + +On BCM6358 (and also observed on BCM6368) the controller appears to +only generate as many SPI clocks as bytes that have been written into +the TX FIFO. For RX-only transfers the driver programs the transfer +length in SPI_MSG_CTL but does not write anything into the FIFO, so +chip select is deasserted early and the RX transfer segment is never +fully clocked in. + +A concrete failing case is a three-transfer MAC address read from +SPI-NOR: + - TX 0x03 (read command) + - TX 3-byte address + - RX 6 bytes (MAC) + +In contrast, a two-transfer JEDEC-ID read (0x9f + 6-byte RX) works +because the driver uses prepend_len and writes dummy bytes into the +TX FIFO for the RX part. + +Fix this by writing 0xff dummy bytes into the TX FIFO for RX-only +segments so that the number of bytes written to the FIFO matches the +total message length seen by the controller. + +Fixes: b17de076062a ("spi/bcm63xx: work around inability to keep CS up") + +Signed-off-by: Hang Zhou <929513338@qq.com> +Link: https://patch.msgid.link/tencent_7AC88FCB3076489A4A7E6C2163DF1ACF8D06@qq.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-bcm63xx.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c +index a95badb7b7114..ba66fe9f1f543 100644 +--- a/drivers/spi/spi-bcm63xx.c ++++ b/drivers/spi/spi-bcm63xx.c +@@ -247,6 +247,20 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, + + if (t->rx_buf) { + do_rx = true; ++ ++ /* ++ * In certain hardware implementations, there appears to be a ++ * hidden accumulator that tracks the number of bytes written into ++ * the hardware FIFO, and this accumulator overrides the length in ++ * the SPI_MSG_CTL register. ++ * ++ * Therefore, for read-only transfers, we need to write some dummy ++ * value into the FIFO to keep the accumulator tracking the correct ++ * length. ++ */ ++ if (!t->tx_buf) ++ memset_io(bs->tx_io + len, 0xFF, t->len); ++ + /* prepend is half-duplex write only */ + if (t == first) + prepend_len = 0; +-- +2.51.0 + diff --git a/queue-6.6/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch b/queue-6.6/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch new file mode 100644 index 0000000000..f1193a9109 --- /dev/null +++ b/queue-6.6/spi-nxp-fspi-propagate-fwnode-in-acpi-case-as-well.patch @@ -0,0 +1,78 @@ +From c8cac72655f936f3e80bbfe12c6a829e8e3ab8cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 21:25:01 +0100 +Subject: spi: nxp-fspi: Propagate fwnode in ACPI case as well + +From: Andy Shevchenko + +[ Upstream commit 40ad64ac25bb736740f895d99a4aebbda9b80991 ] + +Propagate fwnode of the ACPI device to the SPI controller Linux device. +Currently only OF case propagates fwnode to the controller. + +While at it, replace several calls to dev_fwnode() with a single one +cached in a local variable, and unify checks for fwnode type by using +is_*_node() APIs. + +Fixes: 55ab8487e01d ("spi: spi-nxp-fspi: Add ACPI support") +Signed-off-by: Andy Shevchenko +Reviewed-by: Haibo Chen +Link: https://patch.msgid.link/20251126202501.2319679-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index 5d631f8c593e3..ce110035a3597 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -1165,7 +1165,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + { + struct spi_controller *ctlr; + struct device *dev = &pdev->dev; +- struct device_node *np = dev->of_node; ++ struct fwnode_handle *fwnode = dev_fwnode(dev); + struct resource *res; + struct nxp_fspi *f; + int ret; +@@ -1189,7 +1189,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, f); + + /* find the resources - configuration register address space */ +- if (is_acpi_node(dev_fwnode(f->dev))) ++ if (is_acpi_node(fwnode)) + f->iobase = devm_platform_ioremap_resource(pdev, 0); + else + f->iobase = devm_platform_ioremap_resource_byname(pdev, "fspi_base"); +@@ -1200,7 +1200,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + } + + /* find the resources - controller memory mapped space */ +- if (is_acpi_node(dev_fwnode(f->dev))) ++ if (is_acpi_node(fwnode)) + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + else + res = platform_get_resource_byname(pdev, +@@ -1216,7 +1216,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + f->memmap_phy_size = resource_size(res); + + /* find the clocks */ +- if (dev_of_node(&pdev->dev)) { ++ if (is_of_node(fwnode)) { + f->clk_en = devm_clk_get(dev, "fspi_en"); + if (IS_ERR(f->clk_en)) { + ret = PTR_ERR(f->clk_en); +@@ -1262,7 +1262,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + + nxp_fspi_default_setup(f); + +- ctlr->dev.of_node = np; ++ device_set_node(&ctlr->dev, fwnode); + + ret = devm_spi_register_controller(&pdev->dev, ctlr); + if (ret) +-- +2.51.0 + diff --git a/queue-6.6/spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch b/queue-6.6/spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch new file mode 100644 index 0000000000..225deb86f7 --- /dev/null +++ b/queue-6.6/spi-nxp-fspi-support-per-spi-mem-operation-frequency.patch @@ -0,0 +1,77 @@ +From e124bfb79ff92599a5f34d3d0e45e73893c9a2c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 18:05:57 +0100 +Subject: spi: nxp-fspi: Support per spi-mem operation frequency switches + +From: Miquel Raynal + +[ Upstream commit 26851cf65ffca2d3a8d529a125e54cf0084d69e7 ] + +Every ->exec_op() call correctly configures the spi bus speed to the +maximum allowed frequency for the memory using the constant spi default +parameter. Since we can now have per-operation constraints, let's use +the value that comes from the spi-mem operation structure instead. In +case there is no specific limitation for this operation, the default spi +device value will be given anyway. + +The per-operation frequency capability is thus advertised to the spi-mem +core. + +Cc: AngeloGioacchino Del Regno +Signed-off-by: Miquel Raynal +Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-12-ad218dbc406f@bootlin.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-nxp-fspi.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c +index 731504ec7ef8b..5d631f8c593e3 100644 +--- a/drivers/spi/spi-nxp-fspi.c ++++ b/drivers/spi/spi-nxp-fspi.c +@@ -711,9 +711,10 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f) + * Value for rest of the CS FLSHxxCR0 register would be zero. + * + */ +-static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi) ++static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi, ++ const struct spi_mem_op *op) + { +- unsigned long rate = spi->max_speed_hz; ++ unsigned long rate = op->max_freq; + int ret; + uint64_t size_kb; + +@@ -938,7 +939,7 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true); + WARN_ON(err); + +- nxp_fspi_select_mem(f, mem->spi); ++ nxp_fspi_select_mem(f, mem->spi, op); + + nxp_fspi_prepare_lut(f, op); + /* +@@ -1156,6 +1157,10 @@ static const struct spi_controller_mem_ops nxp_fspi_mem_ops = { + .get_name = nxp_fspi_get_name, + }; + ++static const struct spi_controller_mem_caps nxp_fspi_mem_caps = { ++ .per_op_freq = true, ++}; ++ + static int nxp_fspi_probe(struct platform_device *pdev) + { + struct spi_controller *ctlr; +@@ -1253,6 +1258,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) + ctlr->bus_num = -1; + ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; + ctlr->mem_ops = &nxp_fspi_mem_ops; ++ ctlr->mem_caps = &nxp_fspi_mem_caps; + + nxp_fspi_default_setup(f); + +-- +2.51.0 + diff --git a/queue-6.6/spi-spi-mem-add-a-new-controller-capability.patch b/queue-6.6/spi-spi-mem-add-a-new-controller-capability.patch new file mode 100644 index 0000000000..a51356a0d0 --- /dev/null +++ b/queue-6.6/spi-spi-mem-add-a-new-controller-capability.patch @@ -0,0 +1,73 @@ +From 9af862094c74f1d895a710035a18e6b6d8039bc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 18:05:47 +0100 +Subject: spi: spi-mem: Add a new controller capability + +From: Miquel Raynal + +[ Upstream commit 1248c9b8d54120950fda10fbeb98fb8932b4d45c ] + +There are spi devices with multiple frequency limitations depending on +the invoked command. We probably do not want to afford running at the +lowest supported frequency all the time, so if we want to get the most +of our hardware, we need to allow per-operation frequency limitations. + +Among all the SPI memory controllers, I believe all are capable of +changing the spi frequency on the fly. Some of the drivers do not make +any frequency setup though. And some others will derive a per chip +prescaler value which will be used forever. + +Actually changing the frequency on the fly is something new in Linux, so +we need to carefully flag the drivers which do and do not support it. A +controller capability is created for that, and the presence for this +capability will always be checked before accepting such pattern. + +Signed-off-by: Miquel Raynal +Reviewed-by: Tudor Ambarus +Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-2-ad218dbc406f@bootlin.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mem.c | 6 ++++++ + include/linux/spi/spi-mem.h | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index b73a659e268d6..c581aa5fbf7cf 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -191,6 +191,12 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + op->max_freq < mem->spi->controller->min_speed_hz) + return false; + ++ if (op->max_freq && ++ op->max_freq < mem->spi->max_speed_hz) { ++ if (!spi_mem_controller_is_capable(ctlr, per_op_freq)) ++ return false; ++ } ++ + return spi_mem_check_buswidth(mem, op); + } + EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); +diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h +index cceebf8c78ba9..6bd0b548bd1e9 100644 +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -309,11 +309,13 @@ struct spi_controller_mem_ops { + * @ecc: Supports operations with error correction + * @swap16: Supports swapping bytes on a 16 bit boundary when configured in + * Octal DTR ++ * @per_op_freq: Supports per operation frequency switching + */ + struct spi_controller_mem_caps { + bool dtr; + bool ecc; + bool swap16; ++ bool per_op_freq; + }; + + #define spi_mem_controller_is_capable(ctlr, cap) \ +-- +2.51.0 + diff --git a/queue-6.6/spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch b/queue-6.6/spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch new file mode 100644 index 0000000000..75dd809fd3 --- /dev/null +++ b/queue-6.6/spi-spi-mem-allow-specifying-the-byte-order-in-octal.patch @@ -0,0 +1,93 @@ +From 3b80fa87abc28da890346bfa1eb0f5d090ae4f83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Sep 2024 22:19:52 +0800 +Subject: spi: spi-mem: Allow specifying the byte order in Octal DTR mode + +From: Tudor Ambarus + +[ Upstream commit 030ace430afcf847f537227afceb22dfe8fb8fc8 ] + +There are NOR flashes (Macronix) that swap the bytes on a 16-bit +boundary when configured in Octal DTR mode. The byte order of +16-bit words is swapped when read or written in Octal Double +Transfer Rate (DTR) mode compared to Single Transfer Rate (STR) +modes. If one writes D0 D1 D2 D3 bytes using 1-1-1 mode, and uses +8D-8D-8D SPI mode for reading, it will read back D1 D0 D3 D2. +Swapping the bytes may introduce some endianness problems. It can +affect the boot sequence if the entire boot sequence is not handled +in either 8D-8D-8D mode or 1-1-1 mode. Therefore, it is necessary +to swap the bytes back to ensure the same byte order as in STR modes. +Fortunately there are controllers that could swap the bytes back at +runtime, addressing the flash's endianness requirements. Provide a +way for the upper layers to specify the byte order in Octal DTR mode. + +Merge Tudor's patch and add modifications for suiting newer version +of Linux kernel. + +Suggested-by: Michael Walle +Signed-off-by: JaimeLiao +Signed-off-by: AlvinZhou +Acked-by: Mark Brown +Link: https://lore.kernel.org/r/20240926141956.2386374-3-alvinzhou.tw@gmail.com +Signed-off-by: Tudor Ambarus +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mem.c | 3 +++ + include/linux/spi/spi-mem.h | 8 +++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index edd7430d4c052..84b250703e138 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -172,6 +172,9 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + if (!spi_mem_controller_is_capable(ctlr, dtr)) + return false; + ++ if (op->data.swap16 && !spi_mem_controller_is_capable(ctlr, swap16)) ++ return false; ++ + if (op->cmd.nbytes != 2) + return false; + } else { +diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h +index 6b0a7dc48a4b7..eed6e016d69cc 100644 +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -90,6 +90,8 @@ enum spi_mem_data_dir { + * @data.buswidth: number of IO lanes used to send/receive the data + * @data.dtr: whether the data should be sent in DTR mode or not + * @data.ecc: whether error correction is required or not ++ * @data.swap16: whether the byte order of 16-bit words is swapped when read ++ * or written in Octal DTR mode compared to STR mode. + * @data.dir: direction of the transfer + * @data.nbytes: number of data bytes to send/receive. Can be zero if the + * operation does not involve transferring data +@@ -124,7 +126,8 @@ struct spi_mem_op { + u8 buswidth; + u8 dtr : 1; + u8 ecc : 1; +- u8 __pad : 6; ++ u8 swap16 : 1; ++ u8 __pad : 5; + enum spi_mem_data_dir dir; + unsigned int nbytes; + union { +@@ -295,10 +298,13 @@ struct spi_controller_mem_ops { + * struct spi_controller_mem_caps - SPI memory controller capabilities + * @dtr: Supports DTR operations + * @ecc: Supports operations with error correction ++ * @swap16: Supports swapping bytes on a 16 bit boundary when configured in ++ * Octal DTR + */ + struct spi_controller_mem_caps { + bool dtr; + bool ecc; ++ bool swap16; + }; + + #define spi_mem_controller_is_capable(ctlr, cap) \ +-- +2.51.0 + diff --git a/queue-6.6/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch b/queue-6.6/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch new file mode 100644 index 0000000000..72b16faecd --- /dev/null +++ b/queue-6.6/spi-spi-mem-extend-spi-mem-operations-with-a-per-ope.patch @@ -0,0 +1,221 @@ +From b509ac741343a10723ed1ab07a942bc9a2783713 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Dec 2024 18:05:46 +0100 +Subject: spi: spi-mem: Extend spi-mem operations with a per-operation maximum + frequency + +From: Miquel Raynal + +[ Upstream commit 0fefeade90e74bc8f40ab0e460f483565c492e28 ] + +In the spi subsystem, the bus frequency is derived as follows: +- the controller may expose a minimum and maximum operating frequency +- the hardware description, through the spi peripheral properties, + advise what is the maximum acceptable frequency from a device/wiring + point of view. +Transfers must be observed at a frequency which fits both (so in +practice, the lowest maximum). + +Actually, this second point mixes two information and already takes the +lowest frequency among: +- what the spi device is capable of (what is written in the component + datasheet) +- what the wiring allows (electromagnetic sensibility, crossovers, + terminations, antenna effect, etc). + +This logic works until spi devices are no longer capable of sustaining +their highest frequency regardless of the operation. Spi memories are +typically subject to such variation. Some devices are capable of +spitting their internally stored data (essentially in read mode) at a +very fast rate, typically up to 166MHz on Winbond SPI-NAND chips, using +"fast" commands. However, some of the low-end operations, such as +regular page read-from-cache commands, are more limited and can only be +executed at 54MHz at most. This is currently a problem in the SPI-NAND +subsystem. Another situation, even if not yet supported, will be with +DTR commands, when the data is latched on both edges of the clock. The +same chips as mentioned previously are in this case limited to +80MHz. Yet another example might be continuous reads, which, under +certain circumstances, can also run at most at 104 or 120MHz. + +As a matter of fact, the "one frequency per chip" policy is outdated and +more fine grain configuration is needed: we need to allow per-operation +frequency limitations. So far, all datasheets I encountered advertise a +maximum default frequency, which need to be lowered for certain specific +operations. So based on the current infrastructure, we can still expect +firmware (device trees in general) to continued advertising the same +maximum speed which is a mix between the PCB limitations and the chip +maximum capability, and expect per-operation lower frequencies when this +is relevant. + +Add a `struct spi_mem_op` member to carry this information. Not +providing this field explicitly from upper layers means that there is no +further constraint and the default spi device maximum speed will be +carried instead. The SPI_MEM_OP() macro is also expanded with an +optional frequency argument, because virtually all operations can be +subject to such a limitation, and this will allow for a smooth and +discrete transition. + +For controller drivers which do not implement the spi-mem interface, the +per-transfer speed is also set acordingly to a lower (than the maximum +default) speed when relevant. + +Acked-by: Pratyush Yadav +Signed-off-by: Miquel Raynal +Link: https://patch.msgid.link/20241224-winbond-6-11-rc1-quad-support-v2-1-ad218dbc406f@bootlin.com +Signed-off-by: Mark Brown +Stable-dep-of: 40ad64ac25bb ("spi: nxp-fspi: Propagate fwnode in ACPI case as well") +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/spi/core.c | 2 ++ + drivers/spi/spi-mem.c | 28 ++++++++++++++++++++++++++++ + include/linux/spi/spi-mem.h | 12 +++++++++++- + 3 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c +index ee61b2d882320..4c2776f52fee5 100644 +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1044,6 +1044,8 @@ spinand_select_op_variant(struct spinand_device *spinand, + if (ret) + break; + ++ spi_mem_adjust_op_freq(spinand->spimem, &op); ++ + if (!spi_mem_supports_op(spinand->spimem, &op)) + break; + +diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c +index 84b250703e138..b73a659e268d6 100644 +--- a/drivers/spi/spi-mem.c ++++ b/drivers/spi/spi-mem.c +@@ -187,6 +187,10 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + return false; + } + ++ if (op->max_freq && mem->spi->controller->min_speed_hz && ++ op->max_freq < mem->spi->controller->min_speed_hz) ++ return false; ++ + return spi_mem_check_buswidth(mem, op); + } + EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); +@@ -321,6 +325,9 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + u8 *tmpbuf; + int ret; + ++ /* Make sure the operation frequency is correct before going futher */ ++ spi_mem_adjust_op_freq(mem, (struct spi_mem_op *)op); ++ + ret = spi_mem_check_op(op); + if (ret) + return ret; +@@ -363,6 +370,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + xfers[xferpos].tx_buf = tmpbuf; + xfers[xferpos].len = op->cmd.nbytes; + xfers[xferpos].tx_nbits = op->cmd.buswidth; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen++; +@@ -377,6 +385,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + xfers[xferpos].tx_buf = tmpbuf + 1; + xfers[xferpos].len = op->addr.nbytes; + xfers[xferpos].tx_nbits = op->addr.buswidth; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen += op->addr.nbytes; +@@ -388,6 +397,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + xfers[xferpos].len = op->dummy.nbytes; + xfers[xferpos].tx_nbits = op->dummy.buswidth; + xfers[xferpos].dummy_data = 1; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen += op->dummy.nbytes; +@@ -403,6 +413,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) + } + + xfers[xferpos].len = op->data.nbytes; ++ xfers[xferpos].speed_hz = op->max_freq; + spi_message_add_tail(&xfers[xferpos], &msg); + xferpos++; + totalxferlen += op->data.nbytes; +@@ -481,6 +492,23 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) + } + EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size); + ++/** ++ * spi_mem_adjust_op_freq() - Adjust the frequency of a SPI mem operation to ++ * match controller, PCB and chip limitations ++ * @mem: the SPI memory ++ * @op: the operation to adjust ++ * ++ * Some chips have per-op frequency limitations and must adapt the maximum ++ * speed. This function allows SPI mem drivers to set @op->max_freq to the ++ * maximum supported value. ++ */ ++void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op) ++{ ++ if (!op->max_freq || op->max_freq > mem->spi->max_speed_hz) ++ op->max_freq = mem->spi->max_speed_hz; ++} ++EXPORT_SYMBOL_GPL(spi_mem_adjust_op_freq); ++ + static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) + { +diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h +index eed6e016d69cc..cceebf8c78ba9 100644 +--- a/include/linux/spi/spi-mem.h ++++ b/include/linux/spi/spi-mem.h +@@ -68,6 +68,9 @@ enum spi_mem_data_dir { + SPI_MEM_DATA_OUT, + }; + ++#define SPI_MEM_OP_MAX_FREQ(__freq) \ ++ .max_freq = __freq ++ + /** + * struct spi_mem_op - describes a SPI memory operation + * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is +@@ -97,6 +100,9 @@ enum spi_mem_data_dir { + * operation does not involve transferring data + * @data.buf.in: input buffer (must be DMA-able) + * @data.buf.out: output buffer (must be DMA-able) ++ * @max_freq: frequency limitation wrt this operation. 0 means there is no ++ * specific constraint and the highest achievable frequency can be ++ * attempted. + */ + struct spi_mem_op { + struct { +@@ -135,14 +141,17 @@ struct spi_mem_op { + const void *out; + } buf; + } data; ++ ++ unsigned int max_freq; + }; + +-#define SPI_MEM_OP(__cmd, __addr, __dummy, __data) \ ++#define SPI_MEM_OP(__cmd, __addr, __dummy, __data, ...) \ + { \ + .cmd = __cmd, \ + .addr = __addr, \ + .dummy = __dummy, \ + .data = __data, \ ++ __VA_ARGS__ \ + } + + /** +@@ -369,6 +378,7 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, + #endif /* CONFIG_SPI_MEM */ + + int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op); ++void spi_mem_adjust_op_freq(struct spi_mem *mem, struct spi_mem_op *op); + + bool spi_mem_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op); +-- +2.51.0 + diff --git a/queue-6.6/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch b/queue-6.6/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch new file mode 100644 index 0000000000..f1e7cac317 --- /dev/null +++ b/queue-6.6/spi-tegra114-remove-kconfig-dependency-on-tegra20_ap.patch @@ -0,0 +1,44 @@ +From 20eba44098ce715314df88a6bfab48c7819972d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Nov 2025 10:50:27 +0100 +Subject: spi: tegra114: remove Kconfig dependency on TEGRA20_APB_DMA + +From: Francesco Lavra + +[ Upstream commit 3dcf44ab56e1d3ca3532083c0d5390b758e45b45 ] + +This driver runs also on Tegra SoCs without a Tegra20 APB DMA controller +(e.g. Tegra234). +Remove the Kconfig dependency on TEGRA20_APB_DMA; in addition, amend the +help text to reflect the fact that this driver works on SoCs different from +Tegra114. + +Fixes: bb9667d8187b ("arm64: tegra: Add SPI device tree nodes for Tegra234") +Signed-off-by: Francesco Lavra +Link: https://patch.msgid.link/20251126095027.4102004-1-flavra@baylibre.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 3ce0fd5df8e9c..cda333f226b66 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -1059,10 +1059,10 @@ config SPI_TEGRA210_QUAD + + config SPI_TEGRA114 + tristate "NVIDIA Tegra114 SPI Controller" +- depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST ++ depends on ARCH_TEGRA || COMPILE_TEST + depends on RESET_CONTROLLER + help +- SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller ++ SPI controller driver for NVIDIA Tegra114 and later SoCs. This controller + is different than the older SoCs SPI controller and also register interface + get changed with this controller. + +-- +2.51.0 + diff --git a/queue-6.6/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch b/queue-6.6/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch new file mode 100644 index 0000000000..99443bbc7a --- /dev/null +++ b/queue-6.6/usb-gadget-renesas_usbf-handle-devm_pm_runtime_enabl.patch @@ -0,0 +1,45 @@ +From 205f18c43f82f5c174c77c4ef6f0c8d6de616fec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Nov 2025 10:22:15 +0800 +Subject: usb: gadget: renesas_usbf: Handle devm_pm_runtime_enable() errors + +From: Haotian Zhang + +[ Upstream commit 74851fbb6d647304f8a7dc491434d3a335ef4b8d ] + +devm_pm_runtime_enable() can fail due to memory allocation. +The current code ignores its return value, potentially causing +pm_runtime_resume_and_get() to operate on uninitialized runtime +PM state. + +Check the return value of devm_pm_runtime_enable() and return on failure. + +Fixes: 3e6e14ffdea4 ("usb: gadget: udc: add Renesas RZ/N1 USBF controller support") +Signed-off-by: Haotian Zhang +Acked-by: Herve Codina +Reviewed-by: Geert Uytterhoeven +Link: https://patch.msgid.link/20251124022215.1619-1-vulab@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/renesas_usbf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c +index 657f265ac7cc5..8463f681ae673 100644 +--- a/drivers/usb/gadget/udc/renesas_usbf.c ++++ b/drivers/usb/gadget/udc/renesas_usbf.c +@@ -3262,7 +3262,9 @@ static int usbf_probe(struct platform_device *pdev) + if (IS_ERR(udc->regs)) + return PTR_ERR(udc->regs); + +- devm_pm_runtime_enable(&pdev->dev); ++ ret = devm_pm_runtime_enable(&pdev->dev); ++ if (ret) ++ return ret; + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) + return ret; +-- +2.51.0 +