From: Sasha Levin Date: Tue, 6 May 2025 11:50:06 +0000 (-0400) Subject: Fixes for 6.6 X-Git-Tag: v5.15.182~55 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2e2bbb5b2c6faad7fe1378775815f1f700a1edef;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.6 Signed-off-by: Sasha Levin --- diff --git a/queue-6.6/alsa-ump-fix-buffer-overflow-at-ump-sysex-message-co.patch b/queue-6.6/alsa-ump-fix-buffer-overflow-at-ump-sysex-message-co.patch new file mode 100644 index 0000000000..14fa92efa7 --- /dev/null +++ b/queue-6.6/alsa-ump-fix-buffer-overflow-at-ump-sysex-message-co.patch @@ -0,0 +1,45 @@ +From a4ce9d143baab6cf9620e242d78a27f4e70c8451 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 14:48:41 +0200 +Subject: ALSA: ump: Fix buffer overflow at UMP SysEx message conversion + +From: Takashi Iwai + +[ Upstream commit 56f1f30e6795b890463d9b20b11e576adf5a2f77 ] + +The conversion function from MIDI 1.0 to UMP packet contains an +internal buffer to keep the incoming MIDI bytes, and its size is 4, as +it was supposed to be the max size for a MIDI1 UMP packet data. +However, the implementation overlooked that SysEx is handled in a +different format, and it can be up to 6 bytes, as found in +do_convert_to_ump(). It leads eventually to a buffer overflow, and +may corrupt the memory when a longer SysEx message is received. + +The fix is simply to extend the buffer size to 6 to fit with the SysEx +UMP message. + +Fixes: 0b5288f5fe63 ("ALSA: ump: Add legacy raw MIDI support") +Reported-by: Argusee +Link: https://patch.msgid.link/20250429124845.25128-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + include/sound/ump_convert.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/sound/ump_convert.h b/include/sound/ump_convert.h +index d099ae27f8491..682499b871eac 100644 +--- a/include/sound/ump_convert.h ++++ b/include/sound/ump_convert.h +@@ -19,7 +19,7 @@ struct ump_cvt_to_ump_bank { + /* context for converting from MIDI1 byte stream to UMP packet */ + struct ump_cvt_to_ump { + /* MIDI1 intermediate buffer */ +- unsigned char buf[4]; ++ unsigned char buf[6]; /* up to 6 bytes for SysEx */ + int len; + int cmd_bytes; + +-- +2.39.5 + diff --git a/queue-6.6/asoc-soc-pcm-fix-hw_params-and-dapm-widget-sequence.patch b/queue-6.6/asoc-soc-pcm-fix-hw_params-and-dapm-widget-sequence.patch new file mode 100644 index 0000000000..eed9d49a84 --- /dev/null +++ b/queue-6.6/asoc-soc-pcm-fix-hw_params-and-dapm-widget-sequence.patch @@ -0,0 +1,69 @@ +From 6c127747c88ba1fcf2c19155f2bfecac340d2271 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Apr 2025 10:59:53 +0000 +Subject: ASoC: soc-pcm: Fix hw_params() and DAPM widget sequence + +From: Sheetal + +[ Upstream commit 9aff2e8df240e84a36f2607f98a0a9924a24e65d ] + +Issue: + When multiple audio streams share a common BE DAI, the BE DAI + widget can be powered up before its hardware parameters are configured. + This incorrect sequence leads to intermittent pcm_write errors. + + For example, the below Tegra use-case throws an error: + aplay(2 streams) -> AMX(mux) -> ADX(demux) -> arecord(2 streams), + here, 'AMX TX' and 'ADX RX' are common BE DAIs. + +For above usecase when failure happens below sequence is observed: + aplay(1) FE open() + - BE DAI callbacks added to the list + - BE DAI state = SND_SOC_DPCM_STATE_OPEN + aplay(2) FE open() + - BE DAI callbacks are not added to the list as the state is + already SND_SOC_DPCM_STATE_OPEN during aplay(1) FE open(). + aplay(2) FE hw_params() + - BE DAI hw_params() callback ignored + aplay(2) FE prepare() + - Widget is powered ON without BE DAI hw_params() call + aplay(1) FE hw_params() + - BE DAI hw_params() is now called + +Fix: + Add BE DAIs in the list if its state is either SND_SOC_DPCM_STATE_OPEN + or SND_SOC_DPCM_STATE_HW_PARAMS as well. + +It ensures the widget is powered ON after BE DAI hw_params() callback. + +Fixes: 0c25db3f7621 ("ASoC: soc-pcm: Don't reconnect an already active BE") +Signed-off-by: Sheetal +Link: https://patch.msgid.link/20250404105953.2784819-1-sheetal@nvidia.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-pcm.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 60248a6820aac..30e93f9aad762 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1534,10 +1534,13 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, + /* + * Filter for systems with 'component_chaining' enabled. + * This helps to avoid unnecessary re-configuration of an +- * already active BE on such systems. ++ * already active BE on such systems and ensures the BE DAI ++ * widget is powered ON after hw_params() BE DAI callback. + */ + if (fe->card->component_chaining && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) && ++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && ++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE)) + continue; + +-- +2.39.5 + diff --git a/queue-6.6/bluetooth-btusb-avoid-null-pointer-dereference-in-sk.patch b/queue-6.6/bluetooth-btusb-avoid-null-pointer-dereference-in-sk.patch new file mode 100644 index 0000000000..77ae09efa6 --- /dev/null +++ b/queue-6.6/bluetooth-btusb-avoid-null-pointer-dereference-in-sk.patch @@ -0,0 +1,197 @@ +From d740bb2365a57f1407957c0ba867de1890f1a08f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Apr 2025 21:00:37 +0800 +Subject: Bluetooth: btusb: avoid NULL pointer dereference in skb_dequeue() + +From: En-Wei Wu + +[ Upstream commit 0317b033abcd1d8dd2798f0e2de5e84543d0bd22 ] + +A NULL pointer dereference can occur in skb_dequeue() when processing a +QCA firmware crash dump on WCN7851 (0489:e0f3). + +[ 93.672166] Bluetooth: hci0: ACL memdump size(589824) + +[ 93.672475] BUG: kernel NULL pointer dereference, address: 0000000000000008 +[ 93.672517] Workqueue: hci0 hci_devcd_rx [bluetooth] +[ 93.672598] RIP: 0010:skb_dequeue+0x50/0x80 + +The issue stems from handle_dump_pkt_qca() returning 0 even when a dump +packet is successfully processed. This is because it incorrectly +forwards the return value of hci_devcd_init() (which returns 0 on +success). As a result, the caller (btusb_recv_acl_qca() or +btusb_recv_evt_qca()) assumes the packet was not handled and passes it +to hci_recv_frame(), leading to premature kfree() of the skb. + +Later, hci_devcd_rx() attempts to dequeue the same skb from the dump +queue, resulting in a NULL pointer dereference. + +Fix this by: +1. Making handle_dump_pkt_qca() return 0 on success and negative errno + on failure, consistent with kernel conventions. +2. Splitting dump packet detection into separate functions for ACL + and event packets for better structure and readability. + +This ensures dump packets are properly identified and consumed, avoiding +double handling and preventing NULL pointer access. + +Fixes: 20981ce2d5a5 ("Bluetooth: btusb: Add WCN6855 devcoredump support") +Signed-off-by: En-Wei Wu +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 101 +++++++++++++++++++++++++++----------- + 1 file changed, 73 insertions(+), 28 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index bc3f63f1ccd86..d6195565ef7ae 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -3521,22 +3521,16 @@ static void btusb_coredump_qca(struct hci_dev *hdev) + bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err); + } + +-/* +- * ==0: not a dump pkt. +- * < 0: fails to handle a dump pkt +- * > 0: otherwise. +- */ ++/* Return: 0 on success, negative errno on failure. */ + static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) + { +- int ret = 1; ++ int ret = 0; + u8 pkt_type; + u8 *sk_ptr; + unsigned int sk_len; + u16 seqno; + u32 dump_size; + +- struct hci_event_hdr *event_hdr; +- struct hci_acl_hdr *acl_hdr; + struct qca_dump_hdr *dump_hdr; + struct btusb_data *btdata = hci_get_drvdata(hdev); + struct usb_device *udev = btdata->udev; +@@ -3546,30 +3540,14 @@ static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) + sk_len = skb->len; + + if (pkt_type == HCI_ACLDATA_PKT) { +- acl_hdr = hci_acl_hdr(skb); +- if (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE) +- return 0; + sk_ptr += HCI_ACL_HDR_SIZE; + sk_len -= HCI_ACL_HDR_SIZE; +- event_hdr = (struct hci_event_hdr *)sk_ptr; +- } else { +- event_hdr = hci_event_hdr(skb); + } + +- if ((event_hdr->evt != HCI_VENDOR_PKT) +- || (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE))) +- return 0; +- + sk_ptr += HCI_EVENT_HDR_SIZE; + sk_len -= HCI_EVENT_HDR_SIZE; + + dump_hdr = (struct qca_dump_hdr *)sk_ptr; +- if ((sk_len < offsetof(struct qca_dump_hdr, data)) +- || (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) +- || (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) +- return 0; +- +- /*it is dump pkt now*/ + seqno = le16_to_cpu(dump_hdr->seqno); + if (seqno == 0) { + set_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags); +@@ -3643,17 +3621,84 @@ static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb) + return ret; + } + ++/* Return: true if the ACL packet is a dump packet, false otherwise. */ ++static bool acl_pkt_is_dump_qca(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ u8 *sk_ptr; ++ unsigned int sk_len; ++ ++ struct hci_event_hdr *event_hdr; ++ struct hci_acl_hdr *acl_hdr; ++ struct qca_dump_hdr *dump_hdr; ++ ++ sk_ptr = skb->data; ++ sk_len = skb->len; ++ ++ acl_hdr = hci_acl_hdr(skb); ++ if (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE) ++ return false; ++ ++ sk_ptr += HCI_ACL_HDR_SIZE; ++ sk_len -= HCI_ACL_HDR_SIZE; ++ event_hdr = (struct hci_event_hdr *)sk_ptr; ++ ++ if ((event_hdr->evt != HCI_VENDOR_PKT) || ++ (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE))) ++ return false; ++ ++ sk_ptr += HCI_EVENT_HDR_SIZE; ++ sk_len -= HCI_EVENT_HDR_SIZE; ++ ++ dump_hdr = (struct qca_dump_hdr *)sk_ptr; ++ if ((sk_len < offsetof(struct qca_dump_hdr, data)) || ++ (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || ++ (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) ++ return false; ++ ++ return true; ++} ++ ++/* Return: true if the event packet is a dump packet, false otherwise. */ ++static bool evt_pkt_is_dump_qca(struct hci_dev *hdev, struct sk_buff *skb) ++{ ++ u8 *sk_ptr; ++ unsigned int sk_len; ++ ++ struct hci_event_hdr *event_hdr; ++ struct qca_dump_hdr *dump_hdr; ++ ++ sk_ptr = skb->data; ++ sk_len = skb->len; ++ ++ event_hdr = hci_event_hdr(skb); ++ ++ if ((event_hdr->evt != HCI_VENDOR_PKT) ++ || (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE))) ++ return false; ++ ++ sk_ptr += HCI_EVENT_HDR_SIZE; ++ sk_len -= HCI_EVENT_HDR_SIZE; ++ ++ dump_hdr = (struct qca_dump_hdr *)sk_ptr; ++ if ((sk_len < offsetof(struct qca_dump_hdr, data)) || ++ (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS) || ++ (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE)) ++ return false; ++ ++ return true; ++} ++ + static int btusb_recv_acl_qca(struct hci_dev *hdev, struct sk_buff *skb) + { +- if (handle_dump_pkt_qca(hdev, skb)) +- return 0; ++ if (acl_pkt_is_dump_qca(hdev, skb)) ++ return handle_dump_pkt_qca(hdev, skb); + return hci_recv_frame(hdev, skb); + } + + static int btusb_recv_evt_qca(struct hci_dev *hdev, struct sk_buff *skb) + { +- if (handle_dump_pkt_qca(hdev, skb)) +- return 0; ++ if (evt_pkt_is_dump_qca(hdev, skb)) ++ return handle_dump_pkt_qca(hdev, skb); + return hci_recv_frame(hdev, skb); + } + +-- +2.39.5 + diff --git a/queue-6.6/bluetooth-l2cap-copy-rx-timestamp-to-new-fragments.patch b/queue-6.6/bluetooth-l2cap-copy-rx-timestamp-to-new-fragments.patch new file mode 100644 index 0000000000..e59cf87fcf --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-copy-rx-timestamp-to-new-fragments.patch @@ -0,0 +1,37 @@ +From 10d09db3e272a4a0b019314937cefb7ad2d9ed09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 22:51:03 +0300 +Subject: Bluetooth: L2CAP: copy RX timestamp to new fragments + +From: Pauli Virtanen + +[ Upstream commit 3908feb1bd7f319a10e18d84369a48163264cc7d ] + +Copy timestamp too when allocating new skb for received fragment. +Fixes missing RX timestamps with fragmentation. + +Fixes: 4d7ea8ee90e4 ("Bluetooth: L2CAP: Fix handling fragmented length") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index d4dcdb2370cc9..72ee41b894a52 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -7386,6 +7386,9 @@ static int l2cap_recv_frag(struct l2cap_conn *conn, struct sk_buff *skb, + return -ENOMEM; + /* Init rx_len */ + conn->rx_len = len; ++ ++ skb_set_delivery_time(conn->rx_skb, skb->tstamp, ++ skb->tstamp_type); + } + + /* Copy as much as the rx_skb can hold */ +-- +2.39.5 + diff --git a/queue-6.6/bnxt_en-fix-coredump-logic-to-free-allocated-buffer.patch b/queue-6.6/bnxt_en-fix-coredump-logic-to-free-allocated-buffer.patch new file mode 100644 index 0000000000..1ba2c0c171 --- /dev/null +++ b/queue-6.6/bnxt_en-fix-coredump-logic-to-free-allocated-buffer.patch @@ -0,0 +1,48 @@ +From 3dddebae4118bd5a4862a3ea1e72528f8148077e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Apr 2025 15:59:01 -0700 +Subject: bnxt_en: Fix coredump logic to free allocated buffer + +From: Shruti Parab + +[ Upstream commit ea9376cf68230e05492f22ca45d329f16e262c7b ] + +When handling HWRM_DBG_COREDUMP_LIST FW command in +bnxt_hwrm_dbg_dma_data(), the allocated buffer info->dest_buf is +not freed in the error path. In the normal path, info->dest_buf +is assigned to coredump->data and it will eventually be freed after +the coredump is collected. + +Free info->dest_buf immediately inside bnxt_hwrm_dbg_dma_data() in +the error path. + +Fixes: c74751f4c392 ("bnxt_en: Return error if FW returns more data than dump length") +Reported-by: Michael Chan +Reviewed-by: Kalesh AP +Signed-off-by: Shruti Parab +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +index c067898820360..b57d2a25ae276 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +@@ -72,6 +72,11 @@ static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, + memcpy(info->dest_buf + off, dma_buf, len); + } else { + rc = -ENOBUFS; ++ if (cmn_req->req_type == ++ cpu_to_le16(HWRM_DBG_COREDUMP_LIST)) { ++ kfree(info->dest_buf); ++ info->dest_buf = NULL; ++ } + break; + } + } +-- +2.39.5 + diff --git a/queue-6.6/bnxt_en-fix-ethtool-d-byte-order-for-32-bit-values.patch b/queue-6.6/bnxt_en-fix-ethtool-d-byte-order-for-32-bit-values.patch new file mode 100644 index 0000000000..44478cc99d --- /dev/null +++ b/queue-6.6/bnxt_en-fix-ethtool-d-byte-order-for-32-bit-values.patch @@ -0,0 +1,85 @@ +From bcca305ca1df074be5be33dc8781e508398734c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Apr 2025 15:59:03 -0700 +Subject: bnxt_en: Fix ethtool -d byte order for 32-bit values + +From: Michael Chan + +[ Upstream commit 02e8be5a032cae0f4ca33c6053c44d83cf4acc93 ] + +For version 1 register dump that includes the PCIe stats, the existing +code incorrectly assumes that all PCIe stats are 64-bit values. Fix it +by using an array containing the starting and ending index of the 32-bit +values. The loop in bnxt_get_regs() will use the array to do proper +endian swap for the 32-bit values. + +Fixes: b5d600b027eb ("bnxt_en: Add support for 'ethtool -d'") +Reviewed-by: Shruti Parab +Reviewed-by: Kalesh AP +Reviewed-by: Andy Gospodarek +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 38 ++++++++++++++++--- + 1 file changed, 32 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +index 2e7ddbca9d53b..dcedafa4d2e14 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +@@ -1393,6 +1393,17 @@ static int bnxt_get_regs_len(struct net_device *dev) + return reg_len; + } + ++#define BNXT_PCIE_32B_ENTRY(start, end) \ ++ { offsetof(struct pcie_ctx_hw_stats, start), \ ++ offsetof(struct pcie_ctx_hw_stats, end) } ++ ++static const struct { ++ u16 start; ++ u16 end; ++} bnxt_pcie_32b_entries[] = { ++ BNXT_PCIE_32B_ENTRY(pcie_ltssm_histogram[0], pcie_ltssm_histogram[3]), ++}; ++ + static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *_p) + { +@@ -1424,12 +1435,27 @@ static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs, + req->pcie_stat_host_addr = cpu_to_le64(hw_pcie_stats_addr); + rc = hwrm_req_send(bp, req); + if (!rc) { +- __le64 *src = (__le64 *)hw_pcie_stats; +- u64 *dst = (u64 *)(_p + BNXT_PXP_REG_LEN); +- int i; +- +- for (i = 0; i < sizeof(*hw_pcie_stats) / sizeof(__le64); i++) +- dst[i] = le64_to_cpu(src[i]); ++ u8 *dst = (u8 *)(_p + BNXT_PXP_REG_LEN); ++ u8 *src = (u8 *)hw_pcie_stats; ++ int i, j; ++ ++ for (i = 0, j = 0; i < sizeof(*hw_pcie_stats); ) { ++ if (i >= bnxt_pcie_32b_entries[j].start && ++ i <= bnxt_pcie_32b_entries[j].end) { ++ u32 *dst32 = (u32 *)(dst + i); ++ ++ *dst32 = le32_to_cpu(*(__le32 *)(src + i)); ++ i += 4; ++ if (i > bnxt_pcie_32b_entries[j].end && ++ j < ARRAY_SIZE(bnxt_pcie_32b_entries) - 1) ++ j++; ++ } else { ++ u64 *dst64 = (u64 *)(dst + i); ++ ++ *dst64 = le64_to_cpu(*(__le64 *)(src + i)); ++ i += 8; ++ } ++ } + } + hwrm_req_drop(bp, req); + } +-- +2.39.5 + diff --git a/queue-6.6/bnxt_en-fix-out-of-bound-memcpy-during-ethtool-w.patch b/queue-6.6/bnxt_en-fix-out-of-bound-memcpy-during-ethtool-w.patch new file mode 100644 index 0000000000..cfed034be7 --- /dev/null +++ b/queue-6.6/bnxt_en-fix-out-of-bound-memcpy-during-ethtool-w.patch @@ -0,0 +1,95 @@ +From a1eda14e00448a63000dc73d277e74fac72cffbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Apr 2025 15:59:02 -0700 +Subject: bnxt_en: Fix out-of-bound memcpy() during ethtool -w + +From: Shruti Parab + +[ Upstream commit 6b87bd94f34370bbf1dfa59352bed8efab5bf419 ] + +When retrieving the FW coredump using ethtool, it can sometimes cause +memory corruption: + +BUG: KFENCE: memory corruption in __bnxt_get_coredump+0x3ef/0x670 [bnxt_en] +Corrupted memory at 0x000000008f0f30e8 [ ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ] (in kfence-#45): +__bnxt_get_coredump+0x3ef/0x670 [bnxt_en] +ethtool_get_dump_data+0xdc/0x1a0 +__dev_ethtool+0xa1e/0x1af0 +dev_ethtool+0xa8/0x170 +dev_ioctl+0x1b5/0x580 +sock_do_ioctl+0xab/0xf0 +sock_ioctl+0x1ce/0x2e0 +__x64_sys_ioctl+0x87/0xc0 +do_syscall_64+0x5c/0xf0 +entry_SYSCALL_64_after_hwframe+0x78/0x80 + +... + +This happens when copying the coredump segment list in +bnxt_hwrm_dbg_dma_data() with the HWRM_DBG_COREDUMP_LIST FW command. +The info->dest_buf buffer is allocated based on the number of coredump +segments returned by the FW. The segment list is then DMA'ed by +the FW and the length of the DMA is returned by FW. The driver then +copies this DMA'ed segment list to info->dest_buf. + +In some cases, this DMA length may exceed the info->dest_buf length +and cause the above BUG condition. Fix it by capping the copy +length to not exceed the length of info->dest_buf. The extra +DMA data contains no useful information. + +This code path is shared for the HWRM_DBG_COREDUMP_LIST and the +HWRM_DBG_COREDUMP_RETRIEVE FW commands. The buffering is different +for these 2 FW commands. To simplify the logic, we need to move +the line to adjust the buffer length for HWRM_DBG_COREDUMP_RETRIEVE +up, so that the new check to cap the copy length will work for both +commands. + +Fixes: c74751f4c392 ("bnxt_en: Return error if FW returns more data than dump length") +Reviewed-by: Kalesh AP +Signed-off-by: Shruti Parab +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../net/ethernet/broadcom/bnxt/bnxt_coredump.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +index b57d2a25ae276..32813cdd5aa5c 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c +@@ -66,10 +66,19 @@ static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, + } + } + ++ if (cmn_req->req_type == ++ cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE)) ++ info->dest_buf_size += len; ++ + if (info->dest_buf) { + if ((info->seg_start + off + len) <= + BNXT_COREDUMP_BUF_LEN(info->buf_len)) { +- memcpy(info->dest_buf + off, dma_buf, len); ++ u16 copylen = min_t(u16, len, ++ info->dest_buf_size - off); ++ ++ memcpy(info->dest_buf + off, dma_buf, copylen); ++ if (copylen < len) ++ break; + } else { + rc = -ENOBUFS; + if (cmn_req->req_type == +@@ -81,10 +90,6 @@ static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, + } + } + +- if (cmn_req->req_type == +- cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE)) +- info->dest_buf_size += len; +- + if (!(cmn_resp->flags & HWRM_DBG_CMN_FLAGS_MORE)) + break; + +-- +2.39.5 + diff --git a/queue-6.6/book3s64-radix-align-section-vmemmap-start-address-t.patch b/queue-6.6/book3s64-radix-align-section-vmemmap-start-address-t.patch new file mode 100644 index 0000000000..0eb48b7307 --- /dev/null +++ b/queue-6.6/book3s64-radix-align-section-vmemmap-start-address-t.patch @@ -0,0 +1,160 @@ +From b59ecf3dceac1d0732746cf413598fc53c594dd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 07:44:10 -0500 +Subject: book3s64/radix : Align section vmemmap start address to PAGE_SIZE + +From: Donet Tom + +[ Upstream commit 9cf7e13fecbab0894f6986fc6986ab2eba8de52e ] + +A vmemmap altmap is a device-provided region used to provide +backing storage for struct pages. For each namespace, the altmap +should belong to that same namespace. If the namespaces are +created unaligned, there is a chance that the section vmemmap +start address could also be unaligned. If the section vmemmap +start address is unaligned, the altmap page allocated from the +current namespace might be used by the previous namespace also. +During the free operation, since the altmap is shared between two +namespaces, the previous namespace may detect that the page does +not belong to its altmap and incorrectly assume that the page is a +normal page. It then attempts to free the normal page, which leads +to a kernel crash. + +Kernel attempted to read user page (18) - exploit attempt? (uid: 0) +BUG: Kernel NULL pointer dereference on read at 0x00000018 +Faulting instruction address: 0xc000000000530c7c +Oops: Kernel access of bad area, sig: 11 [#1] +LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries +CPU: 32 PID: 2104 Comm: ndctl Kdump: loaded Tainted: G W +NIP: c000000000530c7c LR: c000000000530e00 CTR: 0000000000007ffe +REGS: c000000015e57040 TRAP: 0300 Tainted: G W +MSR: 800000000280b033 CR: 84482404 +CFAR: c000000000530dfc DAR: 0000000000000018 DSISR: 40000000 IRQMASK: 0 +GPR00: c000000000530e00 c000000015e572e0 c000000002c5cb00 c00c000101008040 +GPR04: 0000000000000000 0000000000000007 0000000000000001 000000000000001f +GPR08: 0000000000000005 0000000000000000 0000000000000018 0000000000002000 +GPR12: c0000000001d2fb0 c0000060de6b0080 0000000000000000 c0000060dbf90020 +GPR16: c00c000101008000 0000000000000001 0000000000000000 c000000125b20f00 +GPR20: 0000000000000001 0000000000000000 ffffffffffffffff c00c000101007fff +GPR24: 0000000000000001 0000000000000000 0000000000000000 0000000000000000 +GPR28: 0000000004040201 0000000000000001 0000000000000000 c00c000101008040 +NIP [c000000000530c7c] get_pfnblock_flags_mask+0x7c/0xd0 +LR [c000000000530e00] free_unref_page_prepare+0x130/0x4f0 +Call Trace: +free_unref_page+0x50/0x1e0 +free_reserved_page+0x40/0x68 +free_vmemmap_pages+0x98/0xe0 +remove_pte_table+0x164/0x1e8 +remove_pmd_table+0x204/0x2c8 +remove_pud_table+0x1c4/0x288 +remove_pagetable+0x1c8/0x310 +vmemmap_free+0x24/0x50 +section_deactivate+0x28c/0x2a0 +__remove_pages+0x84/0x110 +arch_remove_memory+0x38/0x60 +memunmap_pages+0x18c/0x3d0 +devm_action_release+0x30/0x50 +release_nodes+0x68/0x140 +devres_release_group+0x100/0x190 +dax_pmem_compat_release+0x44/0x80 [dax_pmem_compat] +device_for_each_child+0x8c/0x100 +[dax_pmem_compat_remove+0x2c/0x50 [dax_pmem_compat] +nvdimm_bus_remove+0x78/0x140 [libnvdimm] +device_remove+0x70/0xd0 + +Another issue is that if there is no altmap, a PMD-sized vmemmap +page will be allocated from RAM, regardless of the alignment of +the section start address. If the section start address is not +aligned to the PMD size, a VM_BUG_ON will be triggered when +setting the PMD-sized page to page table. + +In this patch, we are aligning the section vmemmap start address +to PAGE_SIZE. After alignment, the start address will not be +part of the current namespace, and a normal page will be allocated +for the vmemmap mapping of the current section. For the remaining +sections, altmaps will be allocated. During the free operation, +the normal page will be correctly freed. + +In the same way, a PMD_SIZE vmemmap page will be allocated only if +the section start address is PMD_SIZE-aligned; otherwise, it will +fall back to a PAGE-sized vmemmap allocation. + +Without this patch +================== +NS1 start NS2 start + _________________________________________________________ +| NS1 | NS2 | + --------------------------------------------------------- +| Altmap| Altmap | .....|Altmap| Altmap | ........... +| NS1 | NS1 | | NS2 | NS2 | + +In the above scenario, NS1 and NS2 are two namespaces. The vmemmap +for NS1 comes from Altmap NS1, which belongs to NS1, and the +vmemmap for NS2 comes from Altmap NS2, which belongs to NS2. + +The vmemmap start for NS2 is not aligned, so Altmap NS2 is shared +by both NS1 and NS2. During the free operation in NS1, Altmap NS2 +is not part of NS1's altmap, causing it to attempt to free an +invalid page. + +With this patch +=============== +NS1 start NS2 start + _________________________________________________________ +| NS1 | NS2 | + --------------------------------------------------------- +| Altmap| Altmap | .....| Normal | Altmap | Altmap |....... +| NS1 | NS1 | | Page | NS2 | NS2 | + +If the vmemmap start for NS2 is not aligned then we are allocating +a normal page. NS1 and NS2 vmemmap will be freed correctly. + +Fixes: 368a0590d954 ("powerpc/book3s64/vmemmap: switch radix to use a different vmemmap handling function") +Co-developed-by: Ritesh Harjani (IBM) +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Donet Tom +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/8f98ec2b442977c618f7256cec88eb17dde3f2b9.1741609795.git.donettom@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/mm/book3s64/radix_pgtable.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c +index c6a4ac766b2bf..28460e3340808 100644 +--- a/arch/powerpc/mm/book3s64/radix_pgtable.c ++++ b/arch/powerpc/mm/book3s64/radix_pgtable.c +@@ -1056,6 +1056,19 @@ int __meminit radix__vmemmap_populate(unsigned long start, unsigned long end, in + pmd_t *pmd; + pte_t *pte; + ++ /* ++ * Make sure we align the start vmemmap addr so that we calculate ++ * the correct start_pfn in altmap boundary check to decided whether ++ * we should use altmap or RAM based backing memory allocation. Also ++ * the address need to be aligned for set_pte operation. ++ ++ * If the start addr is already PMD_SIZE aligned we will try to use ++ * a pmd mapping. We don't want to be too aggressive here beacause ++ * that will cause more allocations in RAM. So only if the namespace ++ * vmemmap start addr is PMD_SIZE aligned we will use PMD mapping. ++ */ ++ ++ start = ALIGN_DOWN(start, PAGE_SIZE); + for (addr = start; addr < end; addr = next) { + next = pmd_addr_end(addr, end); + +@@ -1081,8 +1094,8 @@ int __meminit radix__vmemmap_populate(unsigned long start, unsigned long end, in + * in altmap block allocation failures, in which case + * we fallback to RAM for vmemmap allocation. + */ +- if (altmap && (!IS_ALIGNED(addr, PMD_SIZE) || +- altmap_cross_boundary(altmap, addr, PMD_SIZE))) { ++ if (!IS_ALIGNED(addr, PMD_SIZE) || (altmap && ++ altmap_cross_boundary(altmap, addr, PMD_SIZE))) { + /* + * make sure we don't create altmap mappings + * covering things outside the device. +-- +2.39.5 + diff --git a/queue-6.6/drm-i915-pxp-fix-undefined-reference-to-intel_pxp_gs.patch b/queue-6.6/drm-i915-pxp-fix-undefined-reference-to-intel_pxp_gs.patch new file mode 100644 index 0000000000..c9741887f9 --- /dev/null +++ b/queue-6.6/drm-i915-pxp-fix-undefined-reference-to-intel_pxp_gs.patch @@ -0,0 +1,67 @@ +From 4ee4ad7d62a10a717fbb95ff7ebbbcd38de628e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Apr 2025 12:06:16 +0300 +Subject: drm/i915/pxp: fix undefined reference to + `intel_pxp_gsccs_is_ready_for_sessions' + +From: Chen Linxuan + +[ Upstream commit 7e21ea8149a0e41c3666ee52cc063a6f797a7a2a ] + +On x86_64 with gcc version 13.3.0, I compile kernel with: + + make defconfig + ./scripts/kconfig/merge_config.sh .config <( + echo CONFIG_COMPILE_TEST=y + ) + make KCFLAGS="-fno-inline-functions -fno-inline-small-functions -fno-inline-functions-called-once" + +Then I get a linker error: + + ld: vmlinux.o: in function `pxp_fw_dependencies_completed': + kintel_pxp.c:(.text+0x95728f): undefined reference to `intel_pxp_gsccs_is_ready_for_sessions' + +This is caused by not having a intel_pxp_gsccs_is_ready_for_sessions() +header stub for CONFIG_DRM_I915_PXP=n. Add it. + +Signed-off-by: Chen Linxuan +Fixes: 99afb7cc8c44 ("drm/i915/pxp: Add ARB session creation and cleanup") +Reviewed-by: Jani Nikula +Link: https://lore.kernel.org/r/20250415090616.2649889-1-jani.nikula@intel.com +Signed-off-by: Jani Nikula +(cherry picked from commit b484c1e225a6a582fc78c4d7af7b286408bb7d41) +Signed-off-by: Jani Nikula +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h +index 298ad38e6c7df..c36d956b9b824 100644 +--- a/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h ++++ b/drivers/gpu/drm/i915/pxp/intel_pxp_gsccs.h +@@ -25,6 +25,7 @@ int intel_pxp_gsccs_init(struct intel_pxp *pxp); + + int intel_pxp_gsccs_create_session(struct intel_pxp *pxp, int arb_session_id); + void intel_pxp_gsccs_end_arb_fw_session(struct intel_pxp *pxp, u32 arb_session_id); ++bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp); + + #else + static inline void intel_pxp_gsccs_fini(struct intel_pxp *pxp) +@@ -36,8 +37,11 @@ static inline int intel_pxp_gsccs_init(struct intel_pxp *pxp) + return 0; + } + +-#endif ++static inline bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp) ++{ ++ return false; ++} + +-bool intel_pxp_gsccs_is_ready_for_sessions(struct intel_pxp *pxp); ++#endif + + #endif /*__INTEL_PXP_GSCCS_H__ */ +-- +2.39.5 + diff --git a/queue-6.6/ice-check-vf-vsi-pointer-value-in-ice_vc_add_fdir_fl.patch b/queue-6.6/ice-check-vf-vsi-pointer-value-in-ice_vc_add_fdir_fl.patch new file mode 100644 index 0000000000..8bf2f56f3a --- /dev/null +++ b/queue-6.6/ice-check-vf-vsi-pointer-value-in-ice_vc_add_fdir_fl.patch @@ -0,0 +1,44 @@ +From ca89e8e30c573dc96d94716a636b9a57be311d22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 15:26:32 -0700 +Subject: ice: Check VF VSI Pointer Value in ice_vc_add_fdir_fltr() + +From: Xuanqiang Luo + +[ Upstream commit 425c5f266b2edeee0ce16fedd8466410cdcfcfe3 ] + +As mentioned in the commit baeb705fd6a7 ("ice: always check VF VSI +pointer values"), we need to perform a null pointer check on the return +value of ice_get_vf_vsi() before using it. + +Fixes: 6ebbe97a4881 ("ice: Add a per-VF limit on number of FDIR filters") +Signed-off-by: Xuanqiang Luo +Reviewed-by: Przemek Kitszel +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20250425222636.3188441-3-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +index 3ca5f44dea26e..88c1acd5e8f05 100644 +--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c ++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c +@@ -1824,6 +1824,11 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg) + pf = vf->pf; + dev = ice_pf_to_dev(pf); + vf_vsi = ice_get_vf_vsi(vf); ++ if (!vf_vsi) { ++ dev_err(dev, "Can not get FDIR vf_vsi for VF %u\n", vf->vf_id); ++ v_ret = VIRTCHNL_STATUS_ERR_PARAM; ++ goto err_exit; ++ } + + #define ICE_VF_MAX_FDIR_FILTERS 128 + if (!ice_fdir_num_avail_fltr(&pf->hw, vf_vsi) || +-- +2.39.5 + diff --git a/queue-6.6/igc-fix-lock-order-in-igc_ptp_reset.patch b/queue-6.6/igc-fix-lock-order-in-igc_ptp_reset.patch new file mode 100644 index 0000000000..3c56aca66e --- /dev/null +++ b/queue-6.6/igc-fix-lock-order-in-igc_ptp_reset.patch @@ -0,0 +1,82 @@ +From 2cf879932a2cc164be7decc446c9e5e8651e3d7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Apr 2025 14:03:09 -0700 +Subject: igc: fix lock order in igc_ptp_reset + +From: Jacob Keller + +[ Upstream commit c7d6cb96d5c33b5148f3dc76fcd30a9b8cd9e973 ] + +Commit 1a931c4f5e68 ("igc: add lock preventing multiple simultaneous PTM +transactions") added a new mutex to protect concurrent PTM transactions. +This lock is acquired in igc_ptp_reset() in order to ensure the PTM +registers are properly disabled after a device reset. + +The flow where the lock is acquired already holds a spinlock, so acquiring +a mutex leads to a sleep-while-locking bug, reported both by smatch, +and the kernel test robot. + +The critical section in igc_ptp_reset() does correctly use the +readx_poll_timeout_atomic variants, but the standard PTM flow uses regular +sleeping variants. This makes converting the mutex to a spinlock a bit +tricky. + +Instead, re-order the locking in igc_ptp_reset. Acquire the mutex first, +and then the tmreg_lock spinlock. This is safe because there is no other +ordering dependency on these locks, as this is the only place where both +locks were acquired simultaneously. Indeed, any other flow acquiring locks +in that order would be wrong regardless. + +Signed-off-by: Jacob Keller +Fixes: 1a931c4f5e68 ("igc: add lock preventing multiple simultaneous PTM transactions") +Link: https://lore.kernel.org/intel-wired-lan/Z_-P-Hc1yxcw0lTB@stanley.mountain/ +Link: https://lore.kernel.org/intel-wired-lan/202504211511.f7738f5d-lkp@intel.com/T/#u +Reviewed-by: Przemek Kitszel +Reviewed-by: Vitaly Lifshits +Tested-by: Mor Bar-Gabay +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_ptp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c +index b6bb01a486d9d..a82af96e6bd12 100644 +--- a/drivers/net/ethernet/intel/igc/igc_ptp.c ++++ b/drivers/net/ethernet/intel/igc/igc_ptp.c +@@ -1237,6 +1237,8 @@ void igc_ptp_reset(struct igc_adapter *adapter) + /* reset the tstamp_config */ + igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); + ++ mutex_lock(&adapter->ptm_lock); ++ + spin_lock_irqsave(&adapter->tmreg_lock, flags); + + switch (adapter->hw.mac.type) { +@@ -1255,7 +1257,6 @@ void igc_ptp_reset(struct igc_adapter *adapter) + if (!igc_is_crosststamp_supported(adapter)) + break; + +- mutex_lock(&adapter->ptm_lock); + wr32(IGC_PCIE_DIG_DELAY, IGC_PCIE_DIG_DELAY_DEFAULT); + wr32(IGC_PCIE_PHY_DELAY, IGC_PCIE_PHY_DELAY_DEFAULT); + +@@ -1279,7 +1280,6 @@ void igc_ptp_reset(struct igc_adapter *adapter) + netdev_err(adapter->netdev, "Timeout reading IGC_PTM_STAT register\n"); + + igc_ptm_reset(hw); +- mutex_unlock(&adapter->ptm_lock); + break; + default: + /* No work to do. */ +@@ -1296,5 +1296,7 @@ void igc_ptp_reset(struct igc_adapter *adapter) + out: + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + ++ mutex_unlock(&adapter->ptm_lock); ++ + wrfl(); + } +-- +2.39.5 + diff --git a/queue-6.6/net-dlink-correct-endianness-handling-of-led_mode.patch b/queue-6.6/net-dlink-correct-endianness-handling-of-led_mode.patch new file mode 100644 index 0000000000..e57d488331 --- /dev/null +++ b/queue-6.6/net-dlink-correct-endianness-handling-of-led_mode.patch @@ -0,0 +1,80 @@ +From f49adc4b8100c4cd63e0f052fb9ee730cabdbc92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 16:50:47 +0100 +Subject: net: dlink: Correct endianness handling of led_mode + +From: Simon Horman + +[ Upstream commit e7e5ae71831c44d58627a991e603845a2fed2cab ] + +As it's name suggests, parse_eeprom() parses EEPROM data. + +This is done by reading data, 16 bits at a time as follows: + + for (i = 0; i < 128; i++) + ((__le16 *) sromdata)[i] = cpu_to_le16(read_eeprom(np, i)); + +sromdata is at the same memory location as psrom. +And the type of psrom is a pointer to struct t_SROM. + +As can be seen in the loop above, data is stored in sromdata, and thus psrom, +as 16-bit little-endian values. + +However, the integer fields of t_SROM are host byte order integers. +And in the case of led_mode this leads to a little endian value +being incorrectly treated as host byte order. + +Looking at rio_set_led_mode, this does appear to be a bug as that code +masks led_mode with 0x1, 0x2 and 0x8. Logic that would be effected by a +reversed byte order. + +This problem would only manifest on big endian hosts. + +Found by inspection while investigating a sparse warning +regarding the crc field of t_SROM. + +I believe that warning is a false positive. And although I plan +to send a follow-up to use little-endian types for other the integer +fields of PSROM_t I do not believe that will involve any bug fixes. + +Compile tested only. + +Fixes: c3f45d322cbd ("dl2k: Add support for IP1000A-based cards") +Signed-off-by: Simon Horman +Link: https://patch.msgid.link/20250425-dlink-led-mode-v1-1-6bae3c36e736@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dlink/dl2k.c | 2 +- + drivers/net/ethernet/dlink/dl2k.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c +index db6615aa921b1..ce46f3ac3b5a1 100644 +--- a/drivers/net/ethernet/dlink/dl2k.c ++++ b/drivers/net/ethernet/dlink/dl2k.c +@@ -352,7 +352,7 @@ parse_eeprom (struct net_device *dev) + eth_hw_addr_set(dev, psrom->mac_addr); + + if (np->chip_id == CHIP_IP1000A) { +- np->led_mode = psrom->led_mode; ++ np->led_mode = le16_to_cpu(psrom->led_mode); + return 0; + } + +diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h +index 195dc6cfd8955..0e33e2eaae960 100644 +--- a/drivers/net/ethernet/dlink/dl2k.h ++++ b/drivers/net/ethernet/dlink/dl2k.h +@@ -335,7 +335,7 @@ typedef struct t_SROM { + u16 sub_system_id; /* 0x06 */ + u16 pci_base_1; /* 0x08 (IP1000A only) */ + u16 pci_base_2; /* 0x0a (IP1000A only) */ +- u16 led_mode; /* 0x0c (IP1000A only) */ ++ __le16 led_mode; /* 0x0c (IP1000A only) */ + u16 reserved1[9]; /* 0x0e-0x1f */ + u8 mac_addr[6]; /* 0x20-0x25 */ + u8 reserved2[10]; /* 0x26-0x2f */ +-- +2.39.5 + diff --git a/queue-6.6/net-dsa-felix-fix-broken-taprio-gate-states-after-cl.patch b/queue-6.6/net-dsa-felix-fix-broken-taprio-gate-states-after-cl.patch new file mode 100644 index 0000000000..52dfe8f3c0 --- /dev/null +++ b/queue-6.6/net-dsa-felix-fix-broken-taprio-gate-states-after-cl.patch @@ -0,0 +1,197 @@ +From 1e8e2d9682d76b9f82448cbd8890501cd928f9af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Apr 2025 17:48:55 +0300 +Subject: net: dsa: felix: fix broken taprio gate states after clock jump + +From: Vladimir Oltean + +[ Upstream commit 426d487bca38b34f39c483edfc6313a036446b33 ] + +Simplest setup to reproduce the issue: connect 2 ports of the +LS1028A-RDB together (eno0 with swp0) and run: + +$ ip link set eno0 up && ip link set swp0 up +$ tc qdisc replace dev swp0 parent root handle 100 taprio num_tc 8 \ + queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 map 0 1 2 3 4 5 6 7 \ + base-time 0 sched-entry S 20 300000 sched-entry S 10 200000 \ + sched-entry S 20 300000 sched-entry S 48 200000 \ + sched-entry S 20 300000 sched-entry S 83 200000 \ + sched-entry S 40 300000 sched-entry S 00 200000 flags 2 +$ ptp4l -i eno0 -f /etc/linuxptp/configs/gPTP.cfg -m & +$ ptp4l -i swp0 -f /etc/linuxptp/configs/gPTP.cfg -m + +One will observe that the PTP state machine on swp0 starts +synchronizing, then it attempts to do a clock step, and after that, it +never fails to recover from the condition below. + +ptp4l[82.427]: selected best master clock 00049f.fffe.05f627 +ptp4l[82.428]: port 1 (swp0): MASTER to UNCALIBRATED on RS_SLAVE +ptp4l[83.252]: port 1 (swp0): UNCALIBRATED to SLAVE on MASTER_CLOCK_SELECTED +ptp4l[83.886]: rms 4537731277 max 9075462553 freq -18518 +/- 11467 delay 818 +/- 0 +ptp4l[84.170]: timed out while polling for tx timestamp +ptp4l[84.171]: increasing tx_timestamp_timeout or increasing kworker priority may correct this issue, but a driver bug likely causes it +ptp4l[84.172]: port 1 (swp0): send peer delay request failed +ptp4l[84.173]: port 1 (swp0): clearing fault immediately +ptp4l[84.269]: port 1 (swp0): SLAVE to LISTENING on INIT_COMPLETE +ptp4l[85.303]: timed out while polling for tx timestamp +ptp4l[84.171]: increasing tx_timestamp_timeout or increasing kworker priority may correct this issue, but a driver bug likely causes it +ptp4l[84.172]: port 1 (swp0): send peer delay request failed +ptp4l[84.173]: port 1 (swp0): clearing fault immediately +ptp4l[84.269]: port 1 (swp0): SLAVE to LISTENING on INIT_COMPLETE +ptp4l[85.303]: timed out while polling for tx timestamp +ptp4l[85.304]: increasing tx_timestamp_timeout or increasing kworker priority may correct this issue, but a driver bug likely causes it +ptp4l[85.305]: port 1 (swp0): send peer delay response failed +ptp4l[85.306]: port 1 (swp0): clearing fault immediately +ptp4l[86.304]: timed out while polling for tx timestamp + +A hint is given by the non-zero statistics for dropped packets which +were expecting hardware TX timestamps: + +$ ethtool --include-statistics -T swp0 +(...) +Statistics: + tx_pkts: 30 + tx_lost: 11 + tx_err: 0 + +We know that when PTP clock stepping takes place (from ocelot_ptp_settime64() +or from ocelot_ptp_adjtime()), vsc9959_tas_clock_adjust() is called. + +Another interesting hint is that placing an early return in +vsc9959_tas_clock_adjust(), so as to neutralize this function, fixes the +issue and TX timestamps are no longer dropped. + +The debugging function written by me and included below is intended to +read the GCL RAM, after the admin schedule became operational, through +the two status registers available for this purpose: +QSYS_GCL_STATUS_REG_1 and QSYS_GCL_STATUS_REG_2. + +static void vsc9959_print_tas_gcl(struct ocelot *ocelot) +{ + u32 val, list_length, interval, gate_state; + int i, err; + + err = read_poll_timeout(ocelot_read, val, + !(val & QSYS_PARAM_STATUS_REG_8_CONFIG_PENDING), + 10, 100000, false, ocelot, QSYS_PARAM_STATUS_REG_8); + if (err) { + dev_err(ocelot->dev, + "Failed to wait for TAS config pending bit to clear: %pe\n", + ERR_PTR(err)); + return; + } + + val = ocelot_read(ocelot, QSYS_PARAM_STATUS_REG_3); + list_length = QSYS_PARAM_STATUS_REG_3_LIST_LENGTH_X(val); + + dev_info(ocelot->dev, "GCL length: %u\n", list_length); + + for (i = 0; i < list_length; i++) { + ocelot_rmw(ocelot, + QSYS_GCL_STATUS_REG_1_GCL_ENTRY_NUM(i), + QSYS_GCL_STATUS_REG_1_GCL_ENTRY_NUM_M, + QSYS_GCL_STATUS_REG_1); + interval = ocelot_read(ocelot, QSYS_GCL_STATUS_REG_2); + val = ocelot_read(ocelot, QSYS_GCL_STATUS_REG_1); + gate_state = QSYS_GCL_STATUS_REG_1_GATE_STATE_X(val); + + dev_info(ocelot->dev, "GCL entry %d: states 0x%x interval %u\n", + i, gate_state, interval); + } +} + +Calling it from two places: after the initial QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE +performed by vsc9959_qos_port_tas_set(), and after the one done by +vsc9959_tas_clock_adjust(), I notice the following difference. + +From the tc-taprio process context, where the schedule was initially +configured, the GCL looks like this: + +mscc_felix 0000:00:00.5: GCL length: 8 +mscc_felix 0000:00:00.5: GCL entry 0: states 0x20 interval 300000 +mscc_felix 0000:00:00.5: GCL entry 1: states 0x10 interval 200000 +mscc_felix 0000:00:00.5: GCL entry 2: states 0x20 interval 300000 +mscc_felix 0000:00:00.5: GCL entry 3: states 0x48 interval 200000 +mscc_felix 0000:00:00.5: GCL entry 4: states 0x20 interval 300000 +mscc_felix 0000:00:00.5: GCL entry 5: states 0x83 interval 200000 +mscc_felix 0000:00:00.5: GCL entry 6: states 0x40 interval 300000 +mscc_felix 0000:00:00.5: GCL entry 7: states 0x0 interval 200000 + +But from the ptp4l clock stepping process context, when the +vsc9959_tas_clock_adjust() hook is called, the GCL RAM of the +operational schedule now looks like this: + +mscc_felix 0000:00:00.5: GCL length: 8 +mscc_felix 0000:00:00.5: GCL entry 0: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 1: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 2: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 3: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 4: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 5: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 6: states 0x0 interval 0 +mscc_felix 0000:00:00.5: GCL entry 7: states 0x0 interval 0 + +I do not have a formal explanation, just experimental conclusions. +It appears that after triggering QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE +for a port's TAS, the GCL entry RAM is updated anyway, despite what the +documentation claims: "Specify the time interval in +QSYS::GCL_CFG_REG_2.TIME_INTERVAL. This triggers the actual RAM +write with the gate state and the time interval for the entry number +specified". We don't touch that register (through vsc9959_tas_gcl_set()) +from vsc9959_tas_clock_adjust(), yet the GCL RAM is updated anyway. + +It seems to be updated with effectively stale memory, which in my +testing can hold a variety of things, including even pieces of the +previously applied schedule, for particular schedule lengths. + +As such, in most circumstances it is very difficult to pinpoint this +issue, because the newly updated schedule would "behave strangely", +but ultimately might still pass traffic to some extent, due to some +gate entries still being present in the stale GCL entry RAM. It is easy +to miss. + +With the particular schedule given at the beginning, the GCL RAM +"happens" to be reproducibly rewritten with all zeroes, and this is +consistent with what we see: when the time-aware shaper has gate entries +with all gates closed, traffic is dropped on TX, no wonder we can't +retrieve TX timestamps. + +Rewriting the GCL entry RAM when reapplying the new base time fixes the +observed issue. + +Fixes: 8670dc33f48b ("net: dsa: felix: update base time of time-aware shaper when adjusting PTP time") +Reported-by: Richie Pearn +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20250426144859.3128352-2-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/ocelot/felix_vsc9959.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c +index 8d27933c3733b..f91f25578f075 100644 +--- a/drivers/net/dsa/ocelot/felix_vsc9959.c ++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c +@@ -1543,7 +1543,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) + struct tc_taprio_qopt_offload *taprio; + struct ocelot_port *ocelot_port; + struct timespec64 base_ts; +- int port; ++ int i, port; + u32 val; + + mutex_lock(&ocelot->fwd_domain_lock); +@@ -1575,6 +1575,9 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) + QSYS_PARAM_CFG_REG_3_BASE_TIME_SEC_MSB_M, + QSYS_PARAM_CFG_REG_3); + ++ for (i = 0; i < taprio->num_entries; i++) ++ vsc9959_tas_gcl_set(ocelot, i, &taprio->entries[i]); ++ + ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE, + QSYS_TAS_PARAM_CFG_CTRL_CONFIG_CHANGE, + QSYS_TAS_PARAM_CFG_CTRL); +-- +2.39.5 + diff --git a/queue-6.6/net-ethernet-mtk-star-emac-fix-spinlock-recursion-is.patch b/queue-6.6/net-ethernet-mtk-star-emac-fix-spinlock-recursion-is.patch new file mode 100644 index 0000000000..caf1f30542 --- /dev/null +++ b/queue-6.6/net-ethernet-mtk-star-emac-fix-spinlock-recursion-is.patch @@ -0,0 +1,124 @@ +From 11f588c2dbd469d926aed789dfcc65bc3c968680 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 10:38:48 +0200 +Subject: net: ethernet: mtk-star-emac: fix spinlock recursion issues on rx/tx + poll + +From: Louis-Alexis Eyraud + +[ Upstream commit 6fe0866014486736cc3ba1c6fd4606d3dbe55c9c ] + +Use spin_lock_irqsave and spin_unlock_irqrestore instead of spin_lock +and spin_unlock in mtk_star_emac driver to avoid spinlock recursion +occurrence that can happen when enabling the DMA interrupts again in +rx/tx poll. + +``` +BUG: spinlock recursion on CPU#0, swapper/0/0 + lock: 0xffff00000db9cf20, .magic: dead4ead, .owner: swapper/0/0, + .owner_cpu: 0 +CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted + 6.15.0-rc2-next-20250417-00001-gf6a27738686c-dirty #28 PREEMPT +Hardware name: MediaTek MT8365 Open Platform EVK (DT) +Call trace: + show_stack+0x18/0x24 (C) + dump_stack_lvl+0x60/0x80 + dump_stack+0x18/0x24 + spin_dump+0x78/0x88 + do_raw_spin_lock+0x11c/0x120 + _raw_spin_lock+0x20/0x2c + mtk_star_handle_irq+0xc0/0x22c [mtk_star_emac] + __handle_irq_event_percpu+0x48/0x140 + handle_irq_event+0x4c/0xb0 + handle_fasteoi_irq+0xa0/0x1bc + handle_irq_desc+0x34/0x58 + generic_handle_domain_irq+0x1c/0x28 + gic_handle_irq+0x4c/0x120 + do_interrupt_handler+0x50/0x84 + el1_interrupt+0x34/0x68 + el1h_64_irq_handler+0x18/0x24 + el1h_64_irq+0x6c/0x70 + regmap_mmio_read32le+0xc/0x20 (P) + _regmap_bus_reg_read+0x6c/0xac + _regmap_read+0x60/0xdc + regmap_read+0x4c/0x80 + mtk_star_rx_poll+0x2f4/0x39c [mtk_star_emac] + __napi_poll+0x38/0x188 + net_rx_action+0x164/0x2c0 + handle_softirqs+0x100/0x244 + __do_softirq+0x14/0x20 + ____do_softirq+0x10/0x20 + call_on_irq_stack+0x24/0x64 + do_softirq_own_stack+0x1c/0x40 + __irq_exit_rcu+0xd4/0x10c + irq_exit_rcu+0x10/0x1c + el1_interrupt+0x38/0x68 + el1h_64_irq_handler+0x18/0x24 + el1h_64_irq+0x6c/0x70 + cpuidle_enter_state+0xac/0x320 (P) + cpuidle_enter+0x38/0x50 + do_idle+0x1e4/0x260 + cpu_startup_entry+0x34/0x3c + rest_init+0xdc/0xe0 + console_on_rootfs+0x0/0x6c + __primary_switched+0x88/0x90 +``` + +Fixes: 0a8bd81fd6aa ("net: ethernet: mtk-star-emac: separate tx/rx handling with two NAPIs") +Signed-off-by: Louis-Alexis Eyraud +Reviewed-by: Maxime Chevallier +Acked-by: Bartosz Golaszewski +Link: https://patch.msgid.link/20250424-mtk_star_emac-fix-spinlock-recursion-issue-v2-1-f3fde2e529d8@collabora.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_star_emac.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c +index 25989c79c92e6..47a00e02365a2 100644 +--- a/drivers/net/ethernet/mediatek/mtk_star_emac.c ++++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c +@@ -1163,6 +1163,7 @@ static int mtk_star_tx_poll(struct napi_struct *napi, int budget) + struct net_device *ndev = priv->ndev; + unsigned int head = ring->head; + unsigned int entry = ring->tail; ++ unsigned long flags; + + while (entry != head && count < (MTK_STAR_RING_NUM_DESCS - 1)) { + ret = mtk_star_tx_complete_one(priv); +@@ -1182,9 +1183,9 @@ static int mtk_star_tx_poll(struct napi_struct *napi, int budget) + netif_wake_queue(ndev); + + if (napi_complete(napi)) { +- spin_lock(&priv->lock); ++ spin_lock_irqsave(&priv->lock, flags); + mtk_star_enable_dma_irq(priv, false, true); +- spin_unlock(&priv->lock); ++ spin_unlock_irqrestore(&priv->lock, flags); + } + + return 0; +@@ -1341,6 +1342,7 @@ static int mtk_star_rx(struct mtk_star_priv *priv, int budget) + static int mtk_star_rx_poll(struct napi_struct *napi, int budget) + { + struct mtk_star_priv *priv; ++ unsigned long flags; + int work_done = 0; + + priv = container_of(napi, struct mtk_star_priv, rx_napi); +@@ -1348,9 +1350,9 @@ static int mtk_star_rx_poll(struct napi_struct *napi, int budget) + work_done = mtk_star_rx(priv, budget); + if (work_done < budget) { + napi_complete_done(napi, work_done); +- spin_lock(&priv->lock); ++ spin_lock_irqsave(&priv->lock, flags); + mtk_star_enable_dma_irq(priv, true, false); +- spin_unlock(&priv->lock); ++ spin_unlock_irqrestore(&priv->lock, flags); + } + + return work_done; +-- +2.39.5 + diff --git a/queue-6.6/net-ethernet-mtk-star-emac-rearm-interrupts-in-rx_po.patch b/queue-6.6/net-ethernet-mtk-star-emac-rearm-interrupts-in-rx_po.patch new file mode 100644 index 0000000000..b11399a33c --- /dev/null +++ b/queue-6.6/net-ethernet-mtk-star-emac-rearm-interrupts-in-rx_po.patch @@ -0,0 +1,43 @@ +From 764077684459b830424a2ae2757fd569bb1857d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 10:38:49 +0200 +Subject: net: ethernet: mtk-star-emac: rearm interrupts in rx_poll only when + advised + +From: Louis-Alexis Eyraud + +[ Upstream commit e54b4db35e201a9173da9cb7abc8377e12abaf87 ] + +In mtk_star_rx_poll function, on event processing completion, the +mtk_star_emac driver calls napi_complete_done but ignores its return +code and enable RX DMA interrupts inconditionally. This return code +gives the info if a device should avoid rearming its interrupts or not, +so fix this behaviour by taking it into account. + +Fixes: 8c7bd5a454ff ("net: ethernet: mtk-star-emac: new driver") +Signed-off-by: Louis-Alexis Eyraud +Acked-by: Bartosz Golaszewski +Link: https://patch.msgid.link/20250424-mtk_star_emac-fix-spinlock-recursion-issue-v2-2-f3fde2e529d8@collabora.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_star_emac.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c +index 47a00e02365a2..c2ab87828d858 100644 +--- a/drivers/net/ethernet/mediatek/mtk_star_emac.c ++++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c +@@ -1348,8 +1348,7 @@ static int mtk_star_rx_poll(struct napi_struct *napi, int budget) + priv = container_of(napi, struct mtk_star_priv, rx_napi); + + work_done = mtk_star_rx(priv, budget); +- if (work_done < budget) { +- napi_complete_done(napi, work_done); ++ if (work_done < budget && napi_complete_done(napi, work_done)) { + spin_lock_irqsave(&priv->lock, flags); + mtk_star_enable_dma_irq(priv, true, false); + spin_unlock_irqrestore(&priv->lock, flags); +-- +2.39.5 + diff --git a/queue-6.6/net-ethernet-mtk_eth_soc-fix-ser-panic-with-4gb-ram.patch b/queue-6.6/net-ethernet-mtk_eth_soc-fix-ser-panic-with-4gb-ram.patch new file mode 100644 index 0000000000..b499685eee --- /dev/null +++ b/queue-6.6/net-ethernet-mtk_eth_soc-fix-ser-panic-with-4gb-ram.patch @@ -0,0 +1,57 @@ +From f9cbf2b286291ee80de429c4b208edcded8b4b23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Apr 2025 02:05:44 +0100 +Subject: net: ethernet: mtk_eth_soc: fix SER panic with 4GB+ RAM + +From: Chad Monroe + +[ Upstream commit 6e0490fc36cdac696f96e57b61d93b9ae32e0f4c ] + +If the mtk_poll_rx() function detects the MTK_RESETTING flag, it will +jump to release_desc and refill the high word of the SDP on the 4GB RFB. +Subsequently, mtk_rx_clean will process an incorrect SDP, leading to a +panic. + +Add patch from MediaTek's SDK to resolve this. + +Fixes: 2d75891ebc09 ("net: ethernet: mtk_eth_soc: support 36-bit DMA addressing on MT7988") +Link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/71f47ea785699c6aa3b922d66c2bdc1a43da25b1 +Signed-off-by: Chad Monroe +Link: https://patch.msgid.link/4adc2aaeb0fb1b9cdc56bf21cf8e7fa328daa345.1745715843.git.daniel@makrotopia.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index dc89dbc13b251..d2ec8f642c2fa 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2180,14 +2180,18 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + ring->data[idx] = new_data; + rxd->rxd1 = (unsigned int)dma_addr; + release_desc: ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { ++ if (unlikely(dma_addr == DMA_MAPPING_ERROR)) ++ addr64 = FIELD_GET(RX_DMA_ADDR64_MASK, ++ rxd->rxd2); ++ else ++ addr64 = RX_DMA_PREP_ADDR64(dma_addr); ++ } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) + rxd->rxd2 = RX_DMA_LSO; + else +- rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size); +- +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA) && +- likely(dma_addr != DMA_MAPPING_ERROR)) +- rxd->rxd2 |= RX_DMA_PREP_ADDR64(dma_addr); ++ rxd->rxd2 = RX_DMA_PREP_PLEN0(ring->buf_size) | addr64; + + ring->calc_idx = idx; + done++; +-- +2.39.5 + diff --git a/queue-6.6/net-fec-err007885-workaround-for-conventional-tx.patch b/queue-6.6/net-fec-err007885-workaround-for-conventional-tx.patch new file mode 100644 index 0000000000..a500607cc1 --- /dev/null +++ b/queue-6.6/net-fec-err007885-workaround-for-conventional-tx.patch @@ -0,0 +1,55 @@ +From 855be65606981544820be681f8b95b780015107f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 11:08:26 +0200 +Subject: net: fec: ERR007885 Workaround for conventional TX + +From: Mattias Barthel + +[ Upstream commit a179aad12badc43201cbf45d1e8ed2c1383c76b9 ] + +Activate TX hang workaround also in +fec_enet_txq_submit_skb() when TSO is not enabled. + +Errata: ERR007885 + +Symptoms: NETDEV WATCHDOG: eth0 (fec): transmit queue 0 timed out + +commit 37d6017b84f7 ("net: fec: Workaround for imx6sx enet tx hang when enable three queues") +There is a TDAR race condition for mutliQ when the software sets TDAR +and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles). +This will cause the udma_tx and udma_tx_arbiter state machines to hang. + +So, the Workaround is checking TDAR status four time, if TDAR cleared by + hardware and then write TDAR, otherwise don't set TDAR. + +Fixes: 53bb20d1faba ("net: fec: add variable reg_desc_active to speed things up") +Signed-off-by: Mattias Barthel +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250429090826.3101258-1-mattiasbarthel@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 2d6b50903c923..7261838a09db6 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -695,7 +695,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + txq->bd.cur = bdp; + + /* Trigger transmission start */ +- writel(0, txq->bd.reg_desc_active); ++ if (!(fep->quirks & FEC_QUIRK_ERR007885) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active) || ++ !readl(txq->bd.reg_desc_active)) ++ writel(0, txq->bd.reg_desc_active); + + return 0; + } +-- +2.39.5 + diff --git a/queue-6.6/net-hns3-defer-calling-ptp_clock_register.patch b/queue-6.6/net-hns3-defer-calling-ptp_clock_register.patch new file mode 100644 index 0000000000..0db6bf8dc2 --- /dev/null +++ b/queue-6.6/net-hns3-defer-calling-ptp_clock_register.patch @@ -0,0 +1,59 @@ +From ec3f4beeeff72cd14c7e0f81b2786e14c64ec519 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 17:30:52 +0800 +Subject: net: hns3: defer calling ptp_clock_register() + +From: Jian Shen + +[ Upstream commit 4971394d9d624f91689d766f31ce668d169d9959 ] + +Currently the ptp_clock_register() is called before relative +ptp resource ready. It may cause unexpected result when upper +layer called the ptp API during the timewindow. Fix it by +moving the ptp_clock_register() to the function end. + +Fixes: 0bf5eb788512 ("net: hns3: add support for PTP") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Vadim Fedorenko +Link: https://patch.msgid.link/20250430093052.2400464-5-shaojijie@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +index ddc691424c816..9a806ac727cf5 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c +@@ -440,6 +440,13 @@ static int hclge_ptp_create_clock(struct hclge_dev *hdev) + ptp->info.settime64 = hclge_ptp_settime; + + ptp->info.n_alarm = 0; ++ ++ spin_lock_init(&ptp->lock); ++ ptp->io_base = hdev->hw.hw.io_base + HCLGE_PTP_REG_OFFSET; ++ ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE; ++ ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF; ++ hdev->ptp = ptp; ++ + ptp->clock = ptp_clock_register(&ptp->info, &hdev->pdev->dev); + if (IS_ERR(ptp->clock)) { + dev_err(&hdev->pdev->dev, +@@ -451,12 +458,6 @@ static int hclge_ptp_create_clock(struct hclge_dev *hdev) + return -ENODEV; + } + +- spin_lock_init(&ptp->lock); +- ptp->io_base = hdev->hw.hw.io_base + HCLGE_PTP_REG_OFFSET; +- ptp->ts_cfg.rx_filter = HWTSTAMP_FILTER_NONE; +- ptp->ts_cfg.tx_type = HWTSTAMP_TX_OFF; +- hdev->ptp = ptp; +- + return 0; + } + +-- +2.39.5 + diff --git a/queue-6.6/net-hns3-fix-an-interrupt-residual-problem.patch b/queue-6.6/net-hns3-fix-an-interrupt-residual-problem.patch new file mode 100644 index 0000000000..1a6e2cf6ac --- /dev/null +++ b/queue-6.6/net-hns3-fix-an-interrupt-residual-problem.patch @@ -0,0 +1,192 @@ +From 5d8719d7acd189367046f27028086fb1ec1bcf45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 17:30:50 +0800 +Subject: net: hns3: fix an interrupt residual problem + +From: Yonglong Liu + +[ Upstream commit 8e6b9c6ea5a55045eed6526d8ee49e93192d1a58 ] + +When a VF is passthrough to a VM, and the VM is killed, the reported +interrupt may not been handled, it will remain, and won't be clear by +the nic engine even with a flr or tqp reset. When the VM restart, the +interrupt of the first vector may be dropped by the second enable_irq +in vfio, see the issue below: +https://gitlab.com/qemu-project/qemu/-/issues/2884#note_2423361621 + +We notice that the vfio has always behaved this way, and the interrupt +is a residue of the nic engine, so we fix the problem by moving the +vector enable process out of the enable_irq loop. + +Fixes: 08a100689d4b ("net: hns3: re-organize vector handle") +Signed-off-by: Yonglong Liu +Signed-off-by: Jijie Shao +Link: https://patch.msgid.link/20250430093052.2400464-3-shaojijie@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/hisilicon/hns3/hns3_enet.c | 82 +++++++++---------- + 1 file changed, 39 insertions(+), 43 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 801801e8803e9..0ed01f4d68061 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -473,20 +473,14 @@ static void hns3_mask_vector_irq(struct hns3_enet_tqp_vector *tqp_vector, + writel(mask_en, tqp_vector->mask_addr); + } + +-static void hns3_vector_enable(struct hns3_enet_tqp_vector *tqp_vector) ++static void hns3_irq_enable(struct hns3_enet_tqp_vector *tqp_vector) + { + napi_enable(&tqp_vector->napi); + enable_irq(tqp_vector->vector_irq); +- +- /* enable vector */ +- hns3_mask_vector_irq(tqp_vector, 1); + } + +-static void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector) ++static void hns3_irq_disable(struct hns3_enet_tqp_vector *tqp_vector) + { +- /* disable vector */ +- hns3_mask_vector_irq(tqp_vector, 0); +- + disable_irq(tqp_vector->vector_irq); + napi_disable(&tqp_vector->napi); + cancel_work_sync(&tqp_vector->rx_group.dim.work); +@@ -707,11 +701,42 @@ static int hns3_set_rx_cpu_rmap(struct net_device *netdev) + return 0; + } + ++static void hns3_enable_irqs_and_tqps(struct net_device *netdev) ++{ ++ struct hns3_nic_priv *priv = netdev_priv(netdev); ++ struct hnae3_handle *h = priv->ae_handle; ++ u16 i; ++ ++ for (i = 0; i < priv->vector_num; i++) ++ hns3_irq_enable(&priv->tqp_vector[i]); ++ ++ for (i = 0; i < priv->vector_num; i++) ++ hns3_mask_vector_irq(&priv->tqp_vector[i], 1); ++ ++ for (i = 0; i < h->kinfo.num_tqps; i++) ++ hns3_tqp_enable(h->kinfo.tqp[i]); ++} ++ ++static void hns3_disable_irqs_and_tqps(struct net_device *netdev) ++{ ++ struct hns3_nic_priv *priv = netdev_priv(netdev); ++ struct hnae3_handle *h = priv->ae_handle; ++ u16 i; ++ ++ for (i = 0; i < h->kinfo.num_tqps; i++) ++ hns3_tqp_disable(h->kinfo.tqp[i]); ++ ++ for (i = 0; i < priv->vector_num; i++) ++ hns3_mask_vector_irq(&priv->tqp_vector[i], 0); ++ ++ for (i = 0; i < priv->vector_num; i++) ++ hns3_irq_disable(&priv->tqp_vector[i]); ++} ++ + static int hns3_nic_net_up(struct net_device *netdev) + { + struct hns3_nic_priv *priv = netdev_priv(netdev); + struct hnae3_handle *h = priv->ae_handle; +- int i, j; + int ret; + + ret = hns3_nic_reset_all_ring(h); +@@ -720,23 +745,13 @@ static int hns3_nic_net_up(struct net_device *netdev) + + clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); + +- /* enable the vectors */ +- for (i = 0; i < priv->vector_num; i++) +- hns3_vector_enable(&priv->tqp_vector[i]); +- +- /* enable rcb */ +- for (j = 0; j < h->kinfo.num_tqps; j++) +- hns3_tqp_enable(h->kinfo.tqp[j]); ++ hns3_enable_irqs_and_tqps(netdev); + + /* start the ae_dev */ + ret = h->ae_algo->ops->start ? h->ae_algo->ops->start(h) : 0; + if (ret) { + set_bit(HNS3_NIC_STATE_DOWN, &priv->state); +- while (j--) +- hns3_tqp_disable(h->kinfo.tqp[j]); +- +- for (j = i - 1; j >= 0; j--) +- hns3_vector_disable(&priv->tqp_vector[j]); ++ hns3_disable_irqs_and_tqps(netdev); + } + + return ret; +@@ -823,17 +838,9 @@ static void hns3_reset_tx_queue(struct hnae3_handle *h) + static void hns3_nic_net_down(struct net_device *netdev) + { + struct hns3_nic_priv *priv = netdev_priv(netdev); +- struct hnae3_handle *h = hns3_get_handle(netdev); + const struct hnae3_ae_ops *ops; +- int i; + +- /* disable vectors */ +- for (i = 0; i < priv->vector_num; i++) +- hns3_vector_disable(&priv->tqp_vector[i]); +- +- /* disable rcb */ +- for (i = 0; i < h->kinfo.num_tqps; i++) +- hns3_tqp_disable(h->kinfo.tqp[i]); ++ hns3_disable_irqs_and_tqps(netdev); + + /* stop ae_dev */ + ops = priv->ae_handle->ae_algo->ops; +@@ -5870,8 +5877,6 @@ int hns3_set_channels(struct net_device *netdev, + void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) + { + struct hns3_nic_priv *priv = netdev_priv(ndev); +- struct hnae3_handle *h = priv->ae_handle; +- int i; + + if (!if_running) + return; +@@ -5882,11 +5887,7 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) + netif_carrier_off(ndev); + netif_tx_disable(ndev); + +- for (i = 0; i < priv->vector_num; i++) +- hns3_vector_disable(&priv->tqp_vector[i]); +- +- for (i = 0; i < h->kinfo.num_tqps; i++) +- hns3_tqp_disable(h->kinfo.tqp[i]); ++ hns3_disable_irqs_and_tqps(ndev); + + /* delay ring buffer clearing to hns3_reset_notify_uninit_enet + * during reset process, because driver may not be able +@@ -5902,7 +5903,6 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running) + { + struct hns3_nic_priv *priv = netdev_priv(ndev); + struct hnae3_handle *h = priv->ae_handle; +- int i; + + if (!if_running) + return; +@@ -5918,11 +5918,7 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running) + + clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); + +- for (i = 0; i < priv->vector_num; i++) +- hns3_vector_enable(&priv->tqp_vector[i]); +- +- for (i = 0; i < h->kinfo.num_tqps; i++) +- hns3_tqp_enable(h->kinfo.tqp[i]); ++ hns3_enable_irqs_and_tqps(ndev); + + netif_tx_wake_all_queues(ndev); + +-- +2.39.5 + diff --git a/queue-6.6/net-hns3-fixed-debugfs-tm_qset-size.patch b/queue-6.6/net-hns3-fixed-debugfs-tm_qset-size.patch new file mode 100644 index 0000000000..d51d468387 --- /dev/null +++ b/queue-6.6/net-hns3-fixed-debugfs-tm_qset-size.patch @@ -0,0 +1,40 @@ +From 5c3556072bcb7ef12387c19cc45ff6d7fed9ebe3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 17:30:51 +0800 +Subject: net: hns3: fixed debugfs tm_qset size + +From: Hao Lan + +[ Upstream commit e317aebeefcb3b0c71f2305af3c22871ca6b3833 ] + +The size of the tm_qset file of debugfs is limited to 64 KB, +which is too small in the scenario with 1280 qsets. +The size needs to be expanded to 1 MB. + +Fixes: 5e69ea7ee2a6 ("net: hns3: refactor the debugfs process") +Signed-off-by: Hao Lan +Signed-off-by: Peiyang Wang +Signed-off-by: Jijie Shao +Link: https://patch.msgid.link/20250430093052.2400464-4-shaojijie@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +index 4f385a18d288e..36206273453f3 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c +@@ -60,7 +60,7 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { + .name = "tm_qset", + .cmd = HNAE3_DBG_CMD_TM_QSET, + .dentry = HNS3_DBG_DENTRY_TM, +- .buf_len = HNS3_DBG_READ_LEN, ++ .buf_len = HNS3_DBG_READ_LEN_1MB, + .init = hns3_dbg_common_file_init, + }, + { +-- +2.39.5 + diff --git a/queue-6.6/net-hns3-store-rx-vlan-tag-offload-state-for-vf.patch b/queue-6.6/net-hns3-store-rx-vlan-tag-offload-state-for-vf.patch new file mode 100644 index 0000000000..1a9770ca99 --- /dev/null +++ b/queue-6.6/net-hns3-store-rx-vlan-tag-offload-state-for-vf.patch @@ -0,0 +1,113 @@ +From 5267e61e50f59b7e38f43be28c45f90f26da5a79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 17:30:49 +0800 +Subject: net: hns3: store rx VLAN tag offload state for VF + +From: Jian Shen + +[ Upstream commit ef2383d078edcbe3055032436b16cdf206f26de2 ] + +The VF driver missed to store the rx VLAN tag strip state when +user change the rx VLAN tag offload state. And it will default +to enable the rx vlan tag strip when re-init VF device after +reset. So if user disable rx VLAN tag offload, and trig reset, +then the HW will still strip the VLAN tag from packet nad fill +into RX BD, but the VF driver will ignore it for rx VLAN tag +offload disabled. It may cause the rx VLAN tag dropped. + +Fixes: b2641e2ad456 ("net: hns3: Add support of hardware rx-vlan-offload to HNS3 VF driver") +Signed-off-by: Jian Shen +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250430093052.2400464-2-shaojijie@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../hisilicon/hns3/hns3vf/hclgevf_main.c | 25 ++++++++++++++----- + .../hisilicon/hns3/hns3vf/hclgevf_main.h | 1 + + 2 files changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 69bfcfb148def..1ba0b57c7a72d 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -1257,9 +1257,8 @@ static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev) + rtnl_unlock(); + } + +-static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) ++static int hclgevf_en_hw_strip_rxvtag_cmd(struct hclgevf_dev *hdev, bool enable) + { +- struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + struct hclge_vf_to_pf_msg send_msg; + + hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN, +@@ -1268,6 +1267,19 @@ static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) + return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0); + } + ++static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) ++{ ++ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); ++ int ret; ++ ++ ret = hclgevf_en_hw_strip_rxvtag_cmd(hdev, enable); ++ if (ret) ++ return ret; ++ ++ hdev->rxvtag_strip_en = enable; ++ return 0; ++} ++ + static int hclgevf_reset_tqp(struct hnae3_handle *handle) + { + #define HCLGEVF_RESET_ALL_QUEUE_DONE 1U +@@ -2143,12 +2155,13 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) + tc_valid, tc_size); + } + +-static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev) ++static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev, ++ bool rxvtag_strip_en) + { + struct hnae3_handle *nic = &hdev->nic; + int ret; + +- ret = hclgevf_en_hw_strip_rxvtag(nic, true); ++ ret = hclgevf_en_hw_strip_rxvtag(nic, rxvtag_strip_en); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed to enable rx vlan offload, ret = %d\n", ret); +@@ -2815,7 +2828,7 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev) + if (ret) + return ret; + +- ret = hclgevf_init_vlan_config(hdev); ++ ret = hclgevf_init_vlan_config(hdev, hdev->rxvtag_strip_en); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed(%d) to initialize VLAN config\n", ret); +@@ -2928,7 +2941,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) + goto err_config; + } + +- ret = hclgevf_init_vlan_config(hdev); ++ ret = hclgevf_init_vlan_config(hdev, true); + if (ret) { + dev_err(&hdev->pdev->dev, + "failed(%d) to initialize VLAN config\n", ret); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +index cccef32284616..0208425ab594f 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +@@ -253,6 +253,7 @@ struct hclgevf_dev { + int *vector_irq; + + bool gro_en; ++ bool rxvtag_strip_en; + + unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)]; + +-- +2.39.5 + diff --git a/queue-6.6/net-ipv6-fix-udpv6-gso-segmentation-with-nat.patch b/queue-6.6/net-ipv6-fix-udpv6-gso-segmentation-with-nat.patch new file mode 100644 index 0000000000..a69210156f --- /dev/null +++ b/queue-6.6/net-ipv6-fix-udpv6-gso-segmentation-with-nat.patch @@ -0,0 +1,104 @@ +From 90b1d241213ed10e179ca0b922880f91f34301de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Apr 2025 17:32:09 +0200 +Subject: net: ipv6: fix UDPv6 GSO segmentation with NAT + +From: Felix Fietkau + +[ Upstream commit b936a9b8d4a585ccb6d454921c36286bfe63e01d ] + +If any address or port is changed, update it in all packets and recalculate +checksum. + +Fixes: 9fd1ff5d2ac7 ("udp: Support UDP fraglist GRO/GSO.") +Signed-off-by: Felix Fietkau +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250426153210.14044-1-nbd@nbd.name +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/udp_offload.c | 61 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 60 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index 2ab16139c197b..132cfc3b2c847 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -247,6 +247,62 @@ static struct sk_buff *__udpv4_gso_segment_list_csum(struct sk_buff *segs) + return segs; + } + ++static void __udpv6_gso_segment_csum(struct sk_buff *seg, ++ struct in6_addr *oldip, ++ const struct in6_addr *newip, ++ __be16 *oldport, __be16 newport) ++{ ++ struct udphdr *uh = udp_hdr(seg); ++ ++ if (ipv6_addr_equal(oldip, newip) && *oldport == newport) ++ return; ++ ++ if (uh->check) { ++ inet_proto_csum_replace16(&uh->check, seg, oldip->s6_addr32, ++ newip->s6_addr32, true); ++ ++ inet_proto_csum_replace2(&uh->check, seg, *oldport, newport, ++ false); ++ if (!uh->check) ++ uh->check = CSUM_MANGLED_0; ++ } ++ ++ *oldip = *newip; ++ *oldport = newport; ++} ++ ++static struct sk_buff *__udpv6_gso_segment_list_csum(struct sk_buff *segs) ++{ ++ const struct ipv6hdr *iph; ++ const struct udphdr *uh; ++ struct ipv6hdr *iph2; ++ struct sk_buff *seg; ++ struct udphdr *uh2; ++ ++ seg = segs; ++ uh = udp_hdr(seg); ++ iph = ipv6_hdr(seg); ++ uh2 = udp_hdr(seg->next); ++ iph2 = ipv6_hdr(seg->next); ++ ++ if (!(*(const u32 *)&uh->source ^ *(const u32 *)&uh2->source) && ++ ipv6_addr_equal(&iph->saddr, &iph2->saddr) && ++ ipv6_addr_equal(&iph->daddr, &iph2->daddr)) ++ return segs; ++ ++ while ((seg = seg->next)) { ++ uh2 = udp_hdr(seg); ++ iph2 = ipv6_hdr(seg); ++ ++ __udpv6_gso_segment_csum(seg, &iph2->saddr, &iph->saddr, ++ &uh2->source, uh->source); ++ __udpv6_gso_segment_csum(seg, &iph2->daddr, &iph->daddr, ++ &uh2->dest, uh->dest); ++ } ++ ++ return segs; ++} ++ + static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb, + netdev_features_t features, + bool is_ipv6) +@@ -259,7 +315,10 @@ static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb, + + udp_hdr(skb)->len = htons(sizeof(struct udphdr) + mss); + +- return is_ipv6 ? skb : __udpv4_gso_segment_list_csum(skb); ++ if (is_ipv6) ++ return __udpv6_gso_segment_list_csum(skb); ++ else ++ return __udpv4_gso_segment_list_csum(skb); + } + + struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, +-- +2.39.5 + diff --git a/queue-6.6/net-lan743x-fix-memleak-issue-when-gso-enabled.patch b/queue-6.6/net-lan743x-fix-memleak-issue-when-gso-enabled.patch new file mode 100644 index 0000000000..92364e4b06 --- /dev/null +++ b/queue-6.6/net-lan743x-fix-memleak-issue-when-gso-enabled.patch @@ -0,0 +1,81 @@ +From 9559b2c5798cbf4da0fd34aa1ca506353111f80d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 10:55:27 +0530 +Subject: net: lan743x: Fix memleak issue when GSO enabled + +From: Thangaraj Samynathan + +[ Upstream commit 2d52e2e38b85c8b7bc00dca55c2499f46f8c8198 ] + +Always map the `skb` to the LS descriptor. Previously skb was +mapped to EXT descriptor when the number of fragments is zero with +GSO enabled. Mapping the skb to EXT descriptor prevents it from +being freed, leading to a memory leak + +Fixes: 23f0703c125b ("lan743x: Add main source files for new lan743x driver") +Signed-off-by: Thangaraj Samynathan +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20250429052527.10031-1-thangaraj.s@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_main.c | 8 ++++++-- + drivers/net/ethernet/microchip/lan743x_main.h | 1 + + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c +index 92010bfe5e413..5d2ceff72784f 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.c ++++ b/drivers/net/ethernet/microchip/lan743x_main.c +@@ -1949,6 +1949,7 @@ static void lan743x_tx_frame_add_lso(struct lan743x_tx *tx, + if (nr_frags <= 0) { + tx->frame_data0 |= TX_DESC_DATA0_LS_; + tx->frame_data0 |= TX_DESC_DATA0_IOC_; ++ tx->frame_last = tx->frame_first; + } + tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail]; + tx_descriptor->data0 = cpu_to_le32(tx->frame_data0); +@@ -2018,6 +2019,7 @@ static int lan743x_tx_frame_add_fragment(struct lan743x_tx *tx, + tx->frame_first = 0; + tx->frame_data0 = 0; + tx->frame_tail = 0; ++ tx->frame_last = 0; + return -ENOMEM; + } + +@@ -2058,16 +2060,18 @@ static void lan743x_tx_frame_end(struct lan743x_tx *tx, + TX_DESC_DATA0_DTYPE_DATA_) { + tx->frame_data0 |= TX_DESC_DATA0_LS_; + tx->frame_data0 |= TX_DESC_DATA0_IOC_; ++ tx->frame_last = tx->frame_tail; + } + +- tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail]; +- buffer_info = &tx->buffer_info[tx->frame_tail]; ++ tx_descriptor = &tx->ring_cpu_ptr[tx->frame_last]; ++ buffer_info = &tx->buffer_info[tx->frame_last]; + buffer_info->skb = skb; + if (time_stamp) + buffer_info->flags |= TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED; + if (ignore_sync) + buffer_info->flags |= TX_BUFFER_INFO_FLAG_IGNORE_SYNC; + ++ tx_descriptor = &tx->ring_cpu_ptr[tx->frame_tail]; + tx_descriptor->data0 = cpu_to_le32(tx->frame_data0); + tx->frame_tail = lan743x_tx_next_index(tx, tx->frame_tail); + tx->last_tail = tx->frame_tail; +diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h +index 3b2c6046eb3ad..b6c83c68241e6 100644 +--- a/drivers/net/ethernet/microchip/lan743x_main.h ++++ b/drivers/net/ethernet/microchip/lan743x_main.h +@@ -974,6 +974,7 @@ struct lan743x_tx { + u32 frame_first; + u32 frame_data0; + u32 frame_tail; ++ u32 frame_last; + + struct lan743x_tx_buffer_info *buffer_info; + +-- +2.39.5 + diff --git a/queue-6.6/net-mdio-mux-meson-gxl-set-reversed-bit-when-using-i.patch b/queue-6.6/net-mdio-mux-meson-gxl-set-reversed-bit-when-using-i.patch new file mode 100644 index 0000000000..d9a1a9e43b --- /dev/null +++ b/queue-6.6/net-mdio-mux-meson-gxl-set-reversed-bit-when-using-i.patch @@ -0,0 +1,51 @@ +From 017db693d4544f1572ec5ff1fc3ac34f790d08b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 15:20:09 -0400 +Subject: net: mdio: mux-meson-gxl: set reversed bit when using internal phy + +From: Da Xue + +[ Upstream commit b23285e93bef729e67519a5209d5b7fde3b4af50 ] + +This bit is necessary to receive packets from the internal PHY. +Without this bit set, no activity occurs on the interface. + +Normally u-boot sets this bit, but if u-boot is compiled without +net support, the interface will be up but without any activity. +If bit is set once, it will work until the IP is powered down or reset. + +The vendor SDK sets this bit along with the PHY_ID bits. + +Signed-off-by: Da Xue +Fixes: 9a24e1ff4326 ("net: mdio: add amlogic gxl mdio mux support") +Link: https://patch.msgid.link/20250425192009.1439508-1-da@libre.computer +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/mdio/mdio-mux-meson-gxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/mdio/mdio-mux-meson-gxl.c b/drivers/net/mdio/mdio-mux-meson-gxl.c +index 76188575ca1fc..19153d44800a9 100644 +--- a/drivers/net/mdio/mdio-mux-meson-gxl.c ++++ b/drivers/net/mdio/mdio-mux-meson-gxl.c +@@ -17,6 +17,7 @@ + #define REG2_LEDACT GENMASK(23, 22) + #define REG2_LEDLINK GENMASK(25, 24) + #define REG2_DIV4SEL BIT(27) ++#define REG2_REVERSED BIT(28) + #define REG2_ADCBYPASS BIT(30) + #define REG2_CLKINSEL BIT(31) + #define ETH_REG3 0x4 +@@ -65,7 +66,7 @@ static void gxl_enable_internal_mdio(struct gxl_mdio_mux *priv) + * The only constraint is that it must match the one in + * drivers/net/phy/meson-gxl.c to properly match the PHY. + */ +- writel(FIELD_PREP(REG2_PHYID, EPHY_GXL_ID), ++ writel(REG2_REVERSED | FIELD_PREP(REG2_PHYID, EPHY_GXL_ID), + priv->regs + ETH_REG2); + + /* Enable the internal phy */ +-- +2.39.5 + diff --git a/queue-6.6/net-mlx5-e-switch-fix-error-handling-for-enabling-ro.patch b/queue-6.6/net-mlx5-e-switch-fix-error-handling-for-enabling-ro.patch new file mode 100644 index 0000000000..d028bbd3aa --- /dev/null +++ b/queue-6.6/net-mlx5-e-switch-fix-error-handling-for-enabling-ro.patch @@ -0,0 +1,110 @@ +From 5dbb82b8cdd384cff548083b4f95752d83ee4850 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 11:36:11 +0300 +Subject: net/mlx5: E-switch, Fix error handling for enabling roce + +From: Chris Mi + +[ Upstream commit 90538d23278a981e344d364e923162fce752afeb ] + +The cited commit assumes enabling roce always succeeds. But it is +not true. Add error handling for it. + +Fixes: 80f09dfc237f ("net/mlx5: Eswitch, enable RoCE loopback traffic") +Signed-off-by: Chris Mi +Reviewed-by: Roi Dayan +Reviewed-by: Maor Gottlieb +Signed-off-by: Mark Bloch +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250423083611.324567-6-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 5 ++++- + drivers/net/ethernet/mellanox/mlx5/core/rdma.c | 9 +++++---- + drivers/net/ethernet/mellanox/mlx5/core/rdma.h | 4 ++-- + 3 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 7eba3a5bb97ca..326c72b3df867 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -3499,7 +3499,9 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) + int err; + + mutex_init(&esw->offloads.termtbl_mutex); +- mlx5_rdma_enable_roce(esw->dev); ++ err = mlx5_rdma_enable_roce(esw->dev); ++ if (err) ++ goto err_roce; + + err = mlx5_esw_host_number_init(esw); + if (err) +@@ -3560,6 +3562,7 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) + esw_offloads_metadata_uninit(esw); + err_metadata: + mlx5_rdma_disable_roce(esw->dev); ++err_roce: + mutex_destroy(&esw->offloads.termtbl_mutex); + return err; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +index f585ef5a34243..5c552b71e371c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +@@ -140,17 +140,17 @@ void mlx5_rdma_disable_roce(struct mlx5_core_dev *dev) + mlx5_nic_vport_disable_roce(dev); + } + +-void mlx5_rdma_enable_roce(struct mlx5_core_dev *dev) ++int mlx5_rdma_enable_roce(struct mlx5_core_dev *dev) + { + int err; + + if (!MLX5_CAP_GEN(dev, roce)) +- return; ++ return 0; + + err = mlx5_nic_vport_enable_roce(dev); + if (err) { + mlx5_core_err(dev, "Failed to enable RoCE: %d\n", err); +- return; ++ return err; + } + + err = mlx5_rdma_add_roce_addr(dev); +@@ -165,10 +165,11 @@ void mlx5_rdma_enable_roce(struct mlx5_core_dev *dev) + goto del_roce_addr; + } + +- return; ++ return err; + + del_roce_addr: + mlx5_rdma_del_roce_addr(dev); + disable_roce: + mlx5_nic_vport_disable_roce(dev); ++ return err; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.h b/drivers/net/ethernet/mellanox/mlx5/core/rdma.h +index 750cff2a71a4b..3d9e76c3d42fb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.h +@@ -8,12 +8,12 @@ + + #ifdef CONFIG_MLX5_ESWITCH + +-void mlx5_rdma_enable_roce(struct mlx5_core_dev *dev); ++int mlx5_rdma_enable_roce(struct mlx5_core_dev *dev); + void mlx5_rdma_disable_roce(struct mlx5_core_dev *dev); + + #else /* CONFIG_MLX5_ESWITCH */ + +-static inline void mlx5_rdma_enable_roce(struct mlx5_core_dev *dev) {} ++static inline int mlx5_rdma_enable_roce(struct mlx5_core_dev *dev) { return 0; } + static inline void mlx5_rdma_disable_roce(struct mlx5_core_dev *dev) {} + + #endif /* CONFIG_MLX5_ESWITCH */ +-- +2.39.5 + diff --git a/queue-6.6/net-mlx5-e-switch-initialize-mac-address-for-default.patch b/queue-6.6/net-mlx5-e-switch-initialize-mac-address-for-default.patch new file mode 100644 index 0000000000..fdd3657b4a --- /dev/null +++ b/queue-6.6/net-mlx5-e-switch-initialize-mac-address-for-default.patch @@ -0,0 +1,48 @@ +From 33f05fe5c3574e7c70f39c32b4dafbf861c73d17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 11:36:08 +0300 +Subject: net/mlx5: E-Switch, Initialize MAC Address for Default GID + +From: Maor Gottlieb + +[ Upstream commit 5d1a04f347e6cbf5ffe74da409a5d71fbe8c5f19 ] + +Initialize the source MAC address when creating the default GID entry. +Since this entry is used only for loopback traffic, it only needs to +be a unicast address. A zeroed-out MAC address is sufficient for this +purpose. +Without this fix, random bits would be assigned as the source address. +If these bits formed a multicast address, the firmware would return an +error, preventing the user from switching to switchdev mode: + +Error: mlx5_core: Failed setting eswitch to offloads. +kernel answers: Invalid argument + +Fixes: 80f09dfc237f ("net/mlx5: Eswitch, enable RoCE loopback traffic") +Signed-off-by: Maor Gottlieb +Signed-off-by: Mark Bloch +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250423083611.324567-3-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/rdma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +index a42f6cd99b744..f585ef5a34243 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +@@ -118,8 +118,8 @@ static void mlx5_rdma_make_default_gid(struct mlx5_core_dev *dev, union ib_gid * + + static int mlx5_rdma_add_roce_addr(struct mlx5_core_dev *dev) + { ++ u8 mac[ETH_ALEN] = {}; + union ib_gid gid; +- u8 mac[ETH_ALEN]; + + mlx5_rdma_make_default_gid(dev, &gid); + return mlx5_core_roce_gid_set(dev, 0, +-- +2.39.5 + diff --git a/queue-6.6/net-mscc-ocelot-delete-pvid-vlan-when-readding-it-as.patch b/queue-6.6/net-mscc-ocelot-delete-pvid-vlan-when-readding-it-as.patch new file mode 100644 index 0000000000..7d2303413b --- /dev/null +++ b/queue-6.6/net-mscc-ocelot-delete-pvid-vlan-when-readding-it-as.patch @@ -0,0 +1,72 @@ +From 776888059231e2724b8441381788acaec193544e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 01:37:33 +0300 +Subject: net: mscc: ocelot: delete PVID VLAN when readding it as non-PVID + +From: Vladimir Oltean + +[ Upstream commit 5ec6d7d737a491256cd37e33910f7ac1978db591 ] + +The following set of commands: + +ip link add br0 type bridge vlan_filtering 1 # vlan_default_pvid 1 is implicit +ip link set swp0 master br0 +bridge vlan add dev swp0 vid 1 + +should result in the dropping of untagged and 802.1p-tagged traffic, but +we see that it continues to be accepted. Whereas, had we deleted VID 1 +instead, the aforementioned dropping would have worked + +This is because the ANA_PORT_DROP_CFG update logic doesn't run, because +ocelot_vlan_add() only calls ocelot_port_set_pvid() if the new VLAN has +the BRIDGE_VLAN_INFO_PVID flag. + +Similar to other drivers like mt7530_port_vlan_add() which handle this +case correctly, we need to test whether the VLAN we're changing used to +have the BRIDGE_VLAN_INFO_PVID flag, but lost it now. That amounts to a +PVID deletion and should be treated as such. + +Regarding blame attribution: this never worked properly since the +introduction of bridge VLAN filtering in commit 7142529f1688 ("net: +mscc: ocelot: add VLAN filtering"). However, there was a significant +paradigm shift which aligned the ANA_PORT_DROP_CFG register with the +PVID concept rather than with the native VLAN concept, and that change +wasn't targeted for 'stable'. Realistically, that is as far as this fix +needs to be propagated to. + +Fixes: be0576fed6d3 ("net: mscc: ocelot: move the logic to drop 802.1p traffic to the pvid deletion") +Signed-off-by: Vladimir Oltean +Link: https://patch.msgid.link/20250424223734.3096202-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mscc/ocelot.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c +index d3e7aff5a794a..252d8e6f18c3c 100644 +--- a/drivers/net/ethernet/mscc/ocelot.c ++++ b/drivers/net/ethernet/mscc/ocelot.c +@@ -830,6 +830,7 @@ EXPORT_SYMBOL(ocelot_vlan_prepare); + int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, + bool untagged) + { ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; + int err; + + /* Ignore VID 0 added to our RX filter by the 8021q module, since +@@ -849,6 +850,11 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, + ocelot_bridge_vlan_find(ocelot, vid)); + if (err) + return err; ++ } else if (ocelot_port->pvid_vlan && ++ ocelot_bridge_vlan_find(ocelot, vid) == ocelot_port->pvid_vlan) { ++ err = ocelot_port_set_pvid(ocelot, port, NULL); ++ if (err) ++ return err; + } + + /* Untagged egress vlan clasification */ +-- +2.39.5 + diff --git a/queue-6.6/net-mscc-ocelot-treat-802.1ad-tagged-traffic-as-802..patch b/queue-6.6/net-mscc-ocelot-treat-802.1ad-tagged-traffic-as-802..patch new file mode 100644 index 0000000000..71b9c58be4 --- /dev/null +++ b/queue-6.6/net-mscc-ocelot-treat-802.1ad-tagged-traffic-as-802..patch @@ -0,0 +1,324 @@ +From 50109b6edcde73686d9f604c110af860fb0e26d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Aug 2024 03:07:07 +0300 +Subject: net: mscc: ocelot: treat 802.1ad tagged traffic as 802.1Q-untagged + +From: Vladimir Oltean + +[ Upstream commit 36dd1141be70b5966906919714dc504a24c65ddf ] + +I was revisiting the topic of 802.1ad treatment in the Ocelot switch [0] +and realized that not only is its basic VLAN classification pipeline +improper for offloading vlan_protocol 802.1ad bridges, but also improper +for offloading regular 802.1Q bridges already. + +Namely, 802.1ad-tagged traffic should be treated as VLAN-untagged by +bridged ports, but this switch treats it as if it was 802.1Q-tagged with +the same VID as in the 802.1ad header. This is markedly different to +what the Linux bridge expects; see the "other_tpid()" function in +tools/testing/selftests/net/forwarding/bridge_vlan_aware.sh. + +An idea came to me that the VCAP IS1 TCAM is more powerful than I'm +giving it credit for, and that it actually overwrites the classified VID +before the VLAN Table lookup takes place. In other words, it can be +used even to save a packet from being dropped on ingress due to VLAN +membership. + +Add a sophisticated TCAM rule hardcoded into the driver to force the +switch to behave like a Linux bridge with vlan_filtering 1 vlan_protocol +802.1Q. + +Regarding the lifetime of the filter: eventually the bridge will +disappear, and vlan_filtering on the port will be restored to 0 for +standalone mode. Then the filter will be deleted. + +[0]: https://lore.kernel.org/netdev/20201009122947.nvhye4hvcha3tljh@skbuf/ + +Fixes: 7142529f1688 ("net: mscc: ocelot: add VLAN filtering") +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +Stable-dep-of: 5ec6d7d737a4 ("net: mscc: ocelot: delete PVID VLAN when readding it as non-PVID") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mscc/ocelot.c | 188 ++++++++++++++++++++++-- + drivers/net/ethernet/mscc/ocelot_vcap.c | 1 + + include/soc/mscc/ocelot_vcap.h | 2 + + 3 files changed, 180 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c +index f6aa5d6b6597e..d3e7aff5a794a 100644 +--- a/drivers/net/ethernet/mscc/ocelot.c ++++ b/drivers/net/ethernet/mscc/ocelot.c +@@ -453,9 +453,158 @@ static u16 ocelot_vlan_unaware_pvid(struct ocelot *ocelot, + return VLAN_N_VID - bridge_num - 1; + } + ++/** ++ * ocelot_update_vlan_reclassify_rule() - Make switch aware only to bridge VLAN TPID ++ * ++ * @ocelot: Switch private data structure ++ * @port: Index of ingress port ++ * ++ * IEEE 802.1Q-2018 clauses "5.5 C-VLAN component conformance" and "5.6 S-VLAN ++ * component conformance" suggest that a C-VLAN component should only recognize ++ * and filter on C-Tags, and an S-VLAN component should only recognize and ++ * process based on C-Tags. ++ * ++ * In Linux, as per commit 1a0b20b25732 ("Merge branch 'bridge-next'"), C-VLAN ++ * components are largely represented by a bridge with vlan_protocol 802.1Q, ++ * and S-VLAN components by a bridge with vlan_protocol 802.1ad. ++ * ++ * Currently the driver only offloads vlan_protocol 802.1Q, but the hardware ++ * design is non-conformant, because the switch assigns each frame to a VLAN ++ * based on an entirely different question, as detailed in figure "Basic VLAN ++ * Classification Flow" from its manual and reproduced below. ++ * ++ * Set TAG_TYPE, PCP, DEI, VID to port-default values in VLAN_CFG register ++ * if VLAN_AWARE_ENA[port] and frame has outer tag then: ++ * if VLAN_INNER_TAG_ENA[port] and frame has inner tag then: ++ * TAG_TYPE = (Frame.InnerTPID <> 0x8100) ++ * Set PCP, DEI, VID to values from inner VLAN header ++ * else: ++ * TAG_TYPE = (Frame.OuterTPID <> 0x8100) ++ * Set PCP, DEI, VID to values from outer VLAN header ++ * if VID == 0 then: ++ * VID = VLAN_CFG.VLAN_VID ++ * ++ * Summarized, the switch will recognize both 802.1Q and 802.1ad TPIDs as VLAN ++ * "with equal rights", and just set the TAG_TYPE bit to 0 (if 802.1Q) or to 1 ++ * (if 802.1ad). It will classify based on whichever of the tags is "outer", no ++ * matter what TPID that may have (or "inner", if VLAN_INNER_TAG_ENA[port]). ++ * ++ * In the VLAN Table, the TAG_TYPE information is not accessible - just the ++ * classified VID is - so it is as if each VLAN Table entry is for 2 VLANs: ++ * C-VLAN X, and S-VLAN X. ++ * ++ * Whereas the Linux bridge behavior is to only filter on frames with a TPID ++ * equal to the vlan_protocol, and treat everything else as VLAN-untagged. ++ * ++ * Consider an ingress packet tagged with 802.1ad VID=3 and 802.1Q VID=5, ++ * received on a bridge vlan_filtering=1 vlan_protocol=802.1Q port. This frame ++ * should be treated as 802.1Q-untagged, and classified to the PVID of that ++ * bridge port. Not to VID=3, and not to VID=5. ++ * ++ * The VCAP IS1 TCAM has everything we need to overwrite the choices made in ++ * the basic VLAN classification pipeline: it can match on TAG_TYPE in the key, ++ * and it can modify the classified VID in the action. Thus, for each port ++ * under a vlan_filtering bridge, we can insert a rule in VCAP IS1 lookup 0 to ++ * match on 802.1ad tagged frames and modify their classified VID to the 802.1Q ++ * PVID of the port. This effectively makes it appear to the outside world as ++ * if those packets were processed as VLAN-untagged. ++ * ++ * The rule needs to be updated each time the bridge PVID changes, and needs ++ * to be deleted if the bridge PVID is deleted, or if the port becomes ++ * VLAN-unaware. ++ */ ++static int ocelot_update_vlan_reclassify_rule(struct ocelot *ocelot, int port) ++{ ++ unsigned long cookie = OCELOT_VCAP_IS1_VLAN_RECLASSIFY(ocelot, port); ++ struct ocelot_vcap_block *block_vcap_is1 = &ocelot->block[VCAP_IS1]; ++ struct ocelot_port *ocelot_port = ocelot->ports[port]; ++ const struct ocelot_bridge_vlan *pvid_vlan; ++ struct ocelot_vcap_filter *filter; ++ int err, val, pcp, dei; ++ bool vid_replace_ena; ++ u16 vid; ++ ++ pvid_vlan = ocelot_port->pvid_vlan; ++ vid_replace_ena = ocelot_port->vlan_aware && pvid_vlan; ++ ++ filter = ocelot_vcap_block_find_filter_by_id(block_vcap_is1, cookie, ++ false); ++ if (!vid_replace_ena) { ++ /* If the reclassification filter doesn't need to exist, delete ++ * it if it was previously installed, and exit doing nothing ++ * otherwise. ++ */ ++ if (filter) ++ return ocelot_vcap_filter_del(ocelot, filter); ++ ++ return 0; ++ } ++ ++ /* The reclassification rule must apply. See if it already exists ++ * or if it must be created. ++ */ ++ ++ /* Treating as VLAN-untagged means using as classified VID equal to ++ * the bridge PVID, and PCP/DEI set to the port default QoS values. ++ */ ++ vid = pvid_vlan->vid; ++ val = ocelot_read_gix(ocelot, ANA_PORT_QOS_CFG, port); ++ pcp = ANA_PORT_QOS_CFG_QOS_DEFAULT_VAL_X(val); ++ dei = !!(val & ANA_PORT_QOS_CFG_DP_DEFAULT_VAL); ++ ++ if (filter) { ++ bool changed = false; ++ ++ /* Filter exists, just update it */ ++ if (filter->action.vid != vid) { ++ filter->action.vid = vid; ++ changed = true; ++ } ++ if (filter->action.pcp != pcp) { ++ filter->action.pcp = pcp; ++ changed = true; ++ } ++ if (filter->action.dei != dei) { ++ filter->action.dei = dei; ++ changed = true; ++ } ++ ++ if (!changed) ++ return 0; ++ ++ return ocelot_vcap_filter_replace(ocelot, filter); ++ } ++ ++ /* Filter doesn't exist, create it */ ++ filter = kzalloc(sizeof(*filter), GFP_KERNEL); ++ if (!filter) ++ return -ENOMEM; ++ ++ filter->key_type = OCELOT_VCAP_KEY_ANY; ++ filter->ingress_port_mask = BIT(port); ++ filter->vlan.tpid = OCELOT_VCAP_BIT_1; ++ filter->prio = 1; ++ filter->id.cookie = cookie; ++ filter->id.tc_offload = false; ++ filter->block_id = VCAP_IS1; ++ filter->type = OCELOT_VCAP_FILTER_OFFLOAD; ++ filter->lookup = 0; ++ filter->action.vid_replace_ena = true; ++ filter->action.pcp_dei_ena = true; ++ filter->action.vid = vid; ++ filter->action.pcp = pcp; ++ filter->action.dei = dei; ++ ++ err = ocelot_vcap_filter_add(ocelot, filter, NULL); ++ if (err) ++ kfree(filter); ++ ++ return err; ++} ++ + /* Default vlan to clasify for untagged frames (may be zero) */ +-static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, +- const struct ocelot_bridge_vlan *pvid_vlan) ++static int ocelot_port_set_pvid(struct ocelot *ocelot, int port, ++ const struct ocelot_bridge_vlan *pvid_vlan) + { + struct ocelot_port *ocelot_port = ocelot->ports[port]; + u16 pvid = ocelot_vlan_unaware_pvid(ocelot, ocelot_port->bridge); +@@ -475,15 +624,23 @@ static void ocelot_port_set_pvid(struct ocelot *ocelot, int port, + * happens automatically), but also 802.1p traffic which gets + * classified to VLAN 0, but that is always in our RX filter, so it + * would get accepted were it not for this setting. ++ * ++ * Also, we only support the bridge 802.1Q VLAN protocol, so ++ * 802.1ad-tagged frames (carrying S-Tags) should be considered ++ * 802.1Q-untagged, and also dropped. + */ + if (!pvid_vlan && ocelot_port->vlan_aware) + val = ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA | +- ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA; ++ ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA | ++ ANA_PORT_DROP_CFG_DROP_S_TAGGED_ENA; + + ocelot_rmw_gix(ocelot, val, + ANA_PORT_DROP_CFG_DROP_PRIO_S_TAGGED_ENA | +- ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA, ++ ANA_PORT_DROP_CFG_DROP_PRIO_C_TAGGED_ENA | ++ ANA_PORT_DROP_CFG_DROP_S_TAGGED_ENA, + ANA_PORT_DROP_CFG, port); ++ ++ return ocelot_update_vlan_reclassify_rule(ocelot, port); + } + + static struct ocelot_bridge_vlan *ocelot_bridge_vlan_find(struct ocelot *ocelot, +@@ -631,7 +788,10 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, + ANA_PORT_VLAN_CFG_VLAN_POP_CNT_M, + ANA_PORT_VLAN_CFG, port); + +- ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan); ++ err = ocelot_port_set_pvid(ocelot, port, ocelot_port->pvid_vlan); ++ if (err) ++ return err; ++ + ocelot_port_manage_port_tag(ocelot, port); + + return 0; +@@ -684,9 +844,12 @@ int ocelot_vlan_add(struct ocelot *ocelot, int port, u16 vid, bool pvid, + return err; + + /* Default ingress vlan classification */ +- if (pvid) +- ocelot_port_set_pvid(ocelot, port, +- ocelot_bridge_vlan_find(ocelot, vid)); ++ if (pvid) { ++ err = ocelot_port_set_pvid(ocelot, port, ++ ocelot_bridge_vlan_find(ocelot, vid)); ++ if (err) ++ return err; ++ } + + /* Untagged egress vlan clasification */ + ocelot_port_manage_port_tag(ocelot, port); +@@ -712,8 +875,11 @@ int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid) + return err; + + /* Ingress */ +- if (del_pvid) +- ocelot_port_set_pvid(ocelot, port, NULL); ++ if (del_pvid) { ++ err = ocelot_port_set_pvid(ocelot, port, NULL); ++ if (err) ++ return err; ++ } + + /* Egress */ + ocelot_port_manage_port_tag(ocelot, port); +@@ -2607,7 +2773,7 @@ int ocelot_port_set_default_prio(struct ocelot *ocelot, int port, u8 prio) + ANA_PORT_QOS_CFG, + port); + +- return 0; ++ return ocelot_update_vlan_reclassify_rule(ocelot, port); + } + EXPORT_SYMBOL_GPL(ocelot_port_set_default_prio); + +diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c +index 73cdec5ca6a34..5734b86aed5b5 100644 +--- a/drivers/net/ethernet/mscc/ocelot_vcap.c ++++ b/drivers/net/ethernet/mscc/ocelot_vcap.c +@@ -695,6 +695,7 @@ static void is1_entry_set(struct ocelot *ocelot, int ix, + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_L2_MC, filter->dmac_mc); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_L2_BC, filter->dmac_bc); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_VLAN_TAGGED, tag->tagged); ++ vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_TPID, tag->tpid); + vcap_key_set(vcap, &data, VCAP_IS1_HK_VID, + tag->vid.value, tag->vid.mask); + vcap_key_set(vcap, &data, VCAP_IS1_HK_PCP, +diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h +index c601a4598b0da..eb19668a06db1 100644 +--- a/include/soc/mscc/ocelot_vcap.h ++++ b/include/soc/mscc/ocelot_vcap.h +@@ -13,6 +13,7 @@ + */ + #define OCELOT_VCAP_ES0_TAG_8021Q_RXVLAN(ocelot, port, upstream) ((upstream) << 16 | (port)) + #define OCELOT_VCAP_IS1_TAG_8021Q_TXVLAN(ocelot, port) (port) ++#define OCELOT_VCAP_IS1_VLAN_RECLASSIFY(ocelot, port) ((ocelot)->num_phys_ports + (port)) + #define OCELOT_VCAP_IS2_TAG_8021Q_TXVLAN(ocelot, port) (port) + #define OCELOT_VCAP_IS2_MRP_REDIRECT(ocelot, port) ((ocelot)->num_phys_ports + (port)) + #define OCELOT_VCAP_IS2_MRP_TRAP(ocelot) ((ocelot)->num_phys_ports * 2) +@@ -499,6 +500,7 @@ struct ocelot_vcap_key_vlan { + struct ocelot_vcap_u8 pcp; /* PCP (3 bit) */ + enum ocelot_vcap_bit dei; /* DEI */ + enum ocelot_vcap_bit tagged; /* Tagged/untagged frame */ ++ enum ocelot_vcap_bit tpid; + }; + + struct ocelot_vcap_key_etype { +-- +2.39.5 + diff --git a/queue-6.6/net-rename-mono_delivery_time-to-tstamp_type-for-sca.patch b/queue-6.6/net-rename-mono_delivery_time-to-tstamp_type-for-sca.patch new file mode 100644 index 0000000000..c0ac78e000 --- /dev/null +++ b/queue-6.6/net-rename-mono_delivery_time-to-tstamp_type-for-sca.patch @@ -0,0 +1,569 @@ +From 58e669afbd2ced4d71a434c562beff27ca46d833 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2024 14:18:32 -0700 +Subject: net: Rename mono_delivery_time to tstamp_type for scalabilty + +From: Abhishek Chauhan + +[ Upstream commit 4d25ca2d6801cfcf26f7f39c561611ba5be99bf8 ] + +mono_delivery_time was added to check if skb->tstamp has delivery +time in mono clock base (i.e. EDT) otherwise skb->tstamp has +timestamp in ingress and delivery_time at egress. + +Renaming the bitfield from mono_delivery_time to tstamp_type is for +extensibilty for other timestamps such as userspace timestamp +(i.e. SO_TXTIME) set via sock opts. + +As we are renaming the mono_delivery_time to tstamp_type, it makes +sense to start assigning tstamp_type based on enum defined +in this commit. + +Earlier we used bool arg flag to check if the tstamp is mono in +function skb_set_delivery_time, Now the signature of the functions +accepts tstamp_type to distinguish between mono and real time. + +Also skb_set_delivery_type_by_clockid is a new function which accepts +clockid to determine the tstamp_type. + +In future tstamp_type:1 can be extended to support userspace timestamp +by increasing the bitfield. + +Signed-off-by: Abhishek Chauhan +Reviewed-by: Willem de Bruijn +Reviewed-by: Martin KaFai Lau +Link: https://lore.kernel.org/r/20240509211834.3235191-2-quic_abchauha@quicinc.com +Signed-off-by: Martin KaFai Lau +Stable-dep-of: 3908feb1bd7f ("Bluetooth: L2CAP: copy RX timestamp to new fragments") +Signed-off-by: Sasha Levin +--- + include/linux/skbuff.h | 52 ++++++++++++++++------ + include/net/inet_frag.h | 4 +- + net/bridge/netfilter/nf_conntrack_bridge.c | 6 +-- + net/core/dev.c | 2 +- + net/core/filter.c | 10 ++--- + net/ieee802154/6lowpan/reassembly.c | 2 +- + net/ipv4/inet_fragment.c | 2 +- + net/ipv4/ip_fragment.c | 2 +- + net/ipv4/ip_output.c | 9 ++-- + net/ipv4/tcp_output.c | 14 +++--- + net/ipv6/ip6_output.c | 6 +-- + net/ipv6/netfilter.c | 6 +-- + net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +- + net/ipv6/reassembly.c | 2 +- + net/ipv6/tcp_ipv6.c | 2 +- + net/sched/act_bpf.c | 4 +- + net/sched/cls_bpf.c | 4 +- + 17 files changed, 78 insertions(+), 51 deletions(-) + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 5f11f98733419..f7d392d849be5 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -685,6 +685,11 @@ typedef unsigned int sk_buff_data_t; + typedef unsigned char *sk_buff_data_t; + #endif + ++enum skb_tstamp_type { ++ SKB_CLOCK_REALTIME, ++ SKB_CLOCK_MONOTONIC, ++}; ++ + /** + * DOC: Basic sk_buff geometry + * +@@ -804,10 +809,8 @@ typedef unsigned char *sk_buff_data_t; + * @dst_pending_confirm: need to confirm neighbour + * @decrypted: Decrypted SKB + * @slow_gro: state present at GRO time, slower prepare step required +- * @mono_delivery_time: When set, skb->tstamp has the +- * delivery_time in mono clock base (i.e. EDT). Otherwise, the +- * skb->tstamp has the (rcv) timestamp at ingress and +- * delivery_time at egress. ++ * @tstamp_type: When set, skb->tstamp has the ++ * delivery_time clock base of skb->tstamp. + * @napi_id: id of the NAPI struct this skb came from + * @sender_cpu: (aka @napi_id) source CPU in XPS + * @alloc_cpu: CPU which did the skb allocation. +@@ -935,7 +938,7 @@ struct sk_buff { + /* private: */ + __u8 __mono_tc_offset[0]; + /* public: */ +- __u8 mono_delivery_time:1; /* See SKB_MONO_DELIVERY_TIME_MASK */ ++ __u8 tstamp_type:1; /* See skb_tstamp_type */ + #ifdef CONFIG_NET_XGRESS + __u8 tc_at_ingress:1; /* See TC_AT_INGRESS_MASK */ + __u8 tc_skip_classify:1; +@@ -4189,7 +4192,7 @@ static inline void skb_get_new_timestampns(const struct sk_buff *skb, + static inline void __net_timestamp(struct sk_buff *skb) + { + skb->tstamp = ktime_get_real(); +- skb->mono_delivery_time = 0; ++ skb->tstamp_type = SKB_CLOCK_REALTIME; + } + + static inline ktime_t net_timedelta(ktime_t t) +@@ -4198,10 +4201,33 @@ static inline ktime_t net_timedelta(ktime_t t) + } + + static inline void skb_set_delivery_time(struct sk_buff *skb, ktime_t kt, +- bool mono) ++ u8 tstamp_type) + { + skb->tstamp = kt; +- skb->mono_delivery_time = kt && mono; ++ ++ if (kt) ++ skb->tstamp_type = tstamp_type; ++ else ++ skb->tstamp_type = SKB_CLOCK_REALTIME; ++} ++ ++static inline void skb_set_delivery_type_by_clockid(struct sk_buff *skb, ++ ktime_t kt, clockid_t clockid) ++{ ++ u8 tstamp_type = SKB_CLOCK_REALTIME; ++ ++ switch (clockid) { ++ case CLOCK_REALTIME: ++ break; ++ case CLOCK_MONOTONIC: ++ tstamp_type = SKB_CLOCK_MONOTONIC; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ kt = 0; ++ } ++ ++ skb_set_delivery_time(skb, kt, tstamp_type); + } + + DECLARE_STATIC_KEY_FALSE(netstamp_needed_key); +@@ -4211,8 +4237,8 @@ DECLARE_STATIC_KEY_FALSE(netstamp_needed_key); + */ + static inline void skb_clear_delivery_time(struct sk_buff *skb) + { +- if (skb->mono_delivery_time) { +- skb->mono_delivery_time = 0; ++ if (skb->tstamp_type) { ++ skb->tstamp_type = SKB_CLOCK_REALTIME; + if (static_branch_unlikely(&netstamp_needed_key)) + skb->tstamp = ktime_get_real(); + else +@@ -4222,7 +4248,7 @@ static inline void skb_clear_delivery_time(struct sk_buff *skb) + + static inline void skb_clear_tstamp(struct sk_buff *skb) + { +- if (skb->mono_delivery_time) ++ if (skb->tstamp_type) + return; + + skb->tstamp = 0; +@@ -4230,7 +4256,7 @@ static inline void skb_clear_tstamp(struct sk_buff *skb) + + static inline ktime_t skb_tstamp(const struct sk_buff *skb) + { +- if (skb->mono_delivery_time) ++ if (skb->tstamp_type) + return 0; + + return skb->tstamp; +@@ -4238,7 +4264,7 @@ static inline ktime_t skb_tstamp(const struct sk_buff *skb) + + static inline ktime_t skb_tstamp_cond(const struct sk_buff *skb, bool cond) + { +- if (!skb->mono_delivery_time && skb->tstamp) ++ if (skb->tstamp_type != SKB_CLOCK_MONOTONIC && skb->tstamp) + return skb->tstamp; + + if (static_branch_unlikely(&netstamp_needed_key) || cond) +diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h +index 153960663ce4c..5af6eb14c5db1 100644 +--- a/include/net/inet_frag.h ++++ b/include/net/inet_frag.h +@@ -76,7 +76,7 @@ struct frag_v6_compare_key { + * @stamp: timestamp of the last received fragment + * @len: total length of the original datagram + * @meat: length of received fragments so far +- * @mono_delivery_time: stamp has a mono delivery time (EDT) ++ * @tstamp_type: stamp has a mono delivery time (EDT) + * @flags: fragment queue flags + * @max_size: maximum received fragment size + * @fqdir: pointer to struct fqdir +@@ -97,7 +97,7 @@ struct inet_frag_queue { + ktime_t stamp; + int len; + int meat; +- u8 mono_delivery_time; ++ u8 tstamp_type; + __u8 flags; + u16 max_size; + struct fqdir *fqdir; +diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c +index 6ef04f9fe481b..4fbfbafdfa027 100644 +--- a/net/bridge/netfilter/nf_conntrack_bridge.c ++++ b/net/bridge/netfilter/nf_conntrack_bridge.c +@@ -32,7 +32,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, + struct sk_buff *)) + { + int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; +- bool mono_delivery_time = skb->mono_delivery_time; ++ u8 tstamp_type = skb->tstamp_type; + unsigned int hlen, ll_rs, mtu; + ktime_t tstamp = skb->tstamp; + struct ip_frag_state state; +@@ -82,7 +82,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, + if (iter.frag) + ip_fraglist_prepare(skb, &iter); + +- skb_set_delivery_time(skb, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb, tstamp, tstamp_type); + err = output(net, sk, data, skb); + if (err || !iter.frag) + break; +@@ -113,7 +113,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, + goto blackhole; + } + +- skb_set_delivery_time(skb2, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb2, tstamp, tstamp_type); + err = output(net, sk, data, skb2); + if (err) + goto blackhole; +diff --git a/net/core/dev.c b/net/core/dev.c +index c31a7f7bedf3d..4006fd164b7bc 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2189,7 +2189,7 @@ EXPORT_SYMBOL(net_disable_timestamp); + static inline void net_timestamp_set(struct sk_buff *skb) + { + skb->tstamp = 0; +- skb->mono_delivery_time = 0; ++ skb->tstamp_type = SKB_CLOCK_REALTIME; + if (static_branch_unlikely(&netstamp_needed_key)) + skb->tstamp = ktime_get_real(); + } +diff --git a/net/core/filter.c b/net/core/filter.c +index c4c27e03279c9..066277b91a1be 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -7734,13 +7734,13 @@ BPF_CALL_3(bpf_skb_set_tstamp, struct sk_buff *, skb, + if (!tstamp) + return -EINVAL; + skb->tstamp = tstamp; +- skb->mono_delivery_time = 1; ++ skb->tstamp_type = SKB_CLOCK_MONOTONIC; + break; + case BPF_SKB_TSTAMP_UNSPEC: + if (tstamp) + return -EINVAL; + skb->tstamp = 0; +- skb->mono_delivery_time = 0; ++ skb->tstamp_type = SKB_CLOCK_REALTIME; + break; + default: + return -EINVAL; +@@ -9438,7 +9438,7 @@ static struct bpf_insn *bpf_convert_tstamp_read(const struct bpf_prog *prog, + TC_AT_INGRESS_MASK | SKB_MONO_DELIVERY_TIME_MASK); + *insn++ = BPF_JMP32_IMM(BPF_JNE, tmp_reg, + TC_AT_INGRESS_MASK | SKB_MONO_DELIVERY_TIME_MASK, 2); +- /* skb->tc_at_ingress && skb->mono_delivery_time, ++ /* skb->tc_at_ingress && skb->tstamp_type, + * read 0 as the (rcv) timestamp. + */ + *insn++ = BPF_MOV64_IMM(value_reg, 0); +@@ -9463,7 +9463,7 @@ static struct bpf_insn *bpf_convert_tstamp_write(const struct bpf_prog *prog, + * the bpf prog is aware the tstamp could have delivery time. + * Thus, write skb->tstamp as is if tstamp_type_access is true. + * Otherwise, writing at ingress will have to clear the +- * mono_delivery_time bit also. ++ * skb->tstamp_type bit also. + */ + if (!prog->tstamp_type_access) { + __u8 tmp_reg = BPF_REG_AX; +@@ -9473,7 +9473,7 @@ static struct bpf_insn *bpf_convert_tstamp_write(const struct bpf_prog *prog, + *insn++ = BPF_JMP32_IMM(BPF_JSET, tmp_reg, TC_AT_INGRESS_MASK, 1); + /* goto */ + *insn++ = BPF_JMP_A(2); +- /* : mono_delivery_time */ ++ /* : skb->tstamp_type */ + *insn++ = BPF_ALU32_IMM(BPF_AND, tmp_reg, ~SKB_MONO_DELIVERY_TIME_MASK); + *insn++ = BPF_STX_MEM(BPF_B, skb_reg, tmp_reg, SKB_BF_MONO_TC_OFFSET); + } +diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c +index 6dd960ec558cf..ba0455ad77019 100644 +--- a/net/ieee802154/6lowpan/reassembly.c ++++ b/net/ieee802154/6lowpan/reassembly.c +@@ -130,7 +130,7 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq, + goto err; + + fq->q.stamp = skb->tstamp; +- fq->q.mono_delivery_time = skb->mono_delivery_time; ++ fq->q.tstamp_type = skb->tstamp_type; + if (frag_type == LOWPAN_DISPATCH_FRAG1) + fq->q.flags |= INET_FRAG_FIRST_IN; + +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index c88c9034d6300..496308c023848 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -619,7 +619,7 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head, + skb_mark_not_on_list(head); + head->prev = NULL; + head->tstamp = q->stamp; +- head->mono_delivery_time = q->mono_delivery_time; ++ head->tstamp_type = q->tstamp_type; + + if (sk) + refcount_add(sum_truesize - head_truesize, &sk->sk_wmem_alloc); +diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c +index 877d1e03150c7..484edc8513e4b 100644 +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -360,7 +360,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) + qp->iif = dev->ifindex; + + qp->q.stamp = skb->tstamp; +- qp->q.mono_delivery_time = skb->mono_delivery_time; ++ qp->q.tstamp_type = skb->tstamp_type; + qp->q.meat += skb->len; + qp->ecn |= ecn; + add_frag_mem_limit(qp->q.fqdir, skb->truesize); +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 765bd3f2a8408..b8cfe6afc84b8 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -764,7 +764,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + { + struct iphdr *iph; + struct sk_buff *skb2; +- bool mono_delivery_time = skb->mono_delivery_time; ++ u8 tstamp_type = skb->tstamp_type; + struct rtable *rt = skb_rtable(skb); + unsigned int mtu, hlen, ll_rs; + struct ip_fraglist_iter iter; +@@ -856,7 +856,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + } + } + +- skb_set_delivery_time(skb, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb, tstamp, tstamp_type); + err = output(net, sk, skb); + + if (!err) +@@ -912,7 +912,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + /* + * Put this fragment into the sending queue. + */ +- skb_set_delivery_time(skb2, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb2, tstamp, tstamp_type); + err = output(net, sk, skb2); + if (err) + goto fail; +@@ -1648,7 +1648,8 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, + arg->csumoffset) = csum_fold(csum_add(nskb->csum, + arg->csum)); + nskb->ip_summed = CHECKSUM_NONE; +- nskb->mono_delivery_time = !!transmit_time; ++ if (transmit_time) ++ nskb->tstamp_type = SKB_CLOCK_MONOTONIC; + if (txhash) + skb_set_hash(nskb, txhash, PKT_HASH_TYPE_L4); + ip_push_pending_frames(sk, &fl4); +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 3771ed22c2f56..560273e7f7736 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1266,7 +1266,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, + tp = tcp_sk(sk); + prior_wstamp = tp->tcp_wstamp_ns; + tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache); +- skb_set_delivery_time(skb, tp->tcp_wstamp_ns, true); ++ skb_set_delivery_time(skb, tp->tcp_wstamp_ns, SKB_CLOCK_MONOTONIC); + if (clone_it) { + oskb = skb; + +@@ -1607,7 +1607,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, + + skb_split(skb, buff, len); + +- skb_set_delivery_time(buff, skb->tstamp, true); ++ skb_set_delivery_time(buff, skb->tstamp, SKB_CLOCK_MONOTONIC); + tcp_fragment_tstamp(skb, buff); + + old_factor = tcp_skb_pcount(skb); +@@ -2703,7 +2703,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) { + /* "skb_mstamp_ns" is used as a start point for the retransmit timer */ + tp->tcp_wstamp_ns = tp->tcp_clock_cache; +- skb_set_delivery_time(skb, tp->tcp_wstamp_ns, true); ++ skb_set_delivery_time(skb, tp->tcp_wstamp_ns, SKB_CLOCK_MONOTONIC); + list_move_tail(&skb->tcp_tsorted_anchor, &tp->tsorted_sent_queue); + tcp_init_tso_segs(skb, mss_now); + goto repair; /* Skip network transmission */ +@@ -3688,11 +3688,11 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, + #ifdef CONFIG_SYN_COOKIES + if (unlikely(synack_type == TCP_SYNACK_COOKIE && ireq->tstamp_ok)) + skb_set_delivery_time(skb, cookie_init_timestamp(req, now), +- true); ++ SKB_CLOCK_MONOTONIC); + else + #endif + { +- skb_set_delivery_time(skb, now, true); ++ skb_set_delivery_time(skb, now, SKB_CLOCK_MONOTONIC); + if (!tcp_rsk(req)->snt_synack) /* Timestamp first SYNACK */ + tcp_rsk(req)->snt_synack = tcp_skb_timestamp_us(skb); + } +@@ -3741,7 +3741,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, + bpf_skops_write_hdr_opt((struct sock *)sk, skb, req, syn_skb, + synack_type, &opts); + +- skb_set_delivery_time(skb, now, true); ++ skb_set_delivery_time(skb, now, SKB_CLOCK_MONOTONIC); + tcp_add_tx_delay(skb, tp); + + return skb; +@@ -3923,7 +3923,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) + + err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation); + +- skb_set_delivery_time(syn, syn_data->skb_mstamp_ns, true); ++ skb_set_delivery_time(syn, syn_data->skb_mstamp_ns, SKB_CLOCK_MONOTONIC); + + /* Now full SYN+DATA was cloned and sent (or not), + * remove the SYN from the original skb (syn_data) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index cd89a2b35dfb5..c86d5dca29df0 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -864,7 +864,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + struct rt6_info *rt = dst_rt6_info(skb_dst(skb)); + struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? + inet6_sk(skb->sk) : NULL; +- bool mono_delivery_time = skb->mono_delivery_time; ++ u8 tstamp_type = skb->tstamp_type; + struct ip6_frag_state state; + unsigned int mtu, hlen, nexthdr_offset; + ktime_t tstamp = skb->tstamp; +@@ -958,7 +958,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + if (iter.frag) + ip6_fraglist_prepare(skb, &iter); + +- skb_set_delivery_time(skb, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb, tstamp, tstamp_type); + err = output(net, sk, skb); + if (!err) + IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), +@@ -1019,7 +1019,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + /* + * Put this fragment into the sending queue. + */ +- skb_set_delivery_time(frag, tstamp, mono_delivery_time); ++ skb_set_delivery_time(frag, tstamp, tstamp_type); + err = output(net, sk, frag); + if (err) + goto fail; +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index 857713d7a38a5..7c4af48d529e1 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -126,7 +126,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + struct sk_buff *)) + { + int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; +- bool mono_delivery_time = skb->mono_delivery_time; ++ u8 tstamp_type = skb->tstamp_type; + ktime_t tstamp = skb->tstamp; + struct ip6_frag_state state; + u8 *prevhdr, nexthdr = 0; +@@ -192,7 +192,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + if (iter.frag) + ip6_fraglist_prepare(skb, &iter); + +- skb_set_delivery_time(skb, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb, tstamp, tstamp_type); + err = output(net, sk, data, skb); + if (err || !iter.frag) + break; +@@ -225,7 +225,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + goto blackhole; + } + +- skb_set_delivery_time(skb2, tstamp, mono_delivery_time); ++ skb_set_delivery_time(skb2, tstamp, tstamp_type); + err = output(net, sk, data, skb2); + if (err) + goto blackhole; +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index c78b13ea5b196..82e51b2ec4f51 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -268,7 +268,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, + fq->iif = dev->ifindex; + + fq->q.stamp = skb->tstamp; +- fq->q.mono_delivery_time = skb->mono_delivery_time; ++ fq->q.tstamp_type = skb->tstamp_type; + fq->q.meat += skb->len; + fq->ecn |= ecn; + if (payload_len > fq->q.max_size) +diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c +index 2af98edef87ee..cb219d4bdf25e 100644 +--- a/net/ipv6/reassembly.c ++++ b/net/ipv6/reassembly.c +@@ -198,7 +198,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, + fq->iif = dev->ifindex; + + fq->q.stamp = skb->tstamp; +- fq->q.mono_delivery_time = skb->mono_delivery_time; ++ fq->q.tstamp_type = skb->tstamp_type; + fq->q.meat += skb->len; + fq->ecn |= ecn; + add_frag_mem_limit(fq->q.fqdir, skb->truesize); +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index f285e52b8b857..624ab1424eba7 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -934,7 +934,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 + mark = inet_twsk(sk)->tw_mark; + else + mark = READ_ONCE(sk->sk_mark); +- skb_set_delivery_time(buff, tcp_transmit_time(sk), true); ++ skb_set_delivery_time(buff, tcp_transmit_time(sk), SKB_CLOCK_MONOTONIC); + } + if (txhash) { + /* autoflowlabel/skb_get_hash_flowi6 rely on buff->hash */ +diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c +index b0455fda7d0ba..ac87fcff4795e 100644 +--- a/net/sched/act_bpf.c ++++ b/net/sched/act_bpf.c +@@ -54,8 +54,8 @@ TC_INDIRECT_SCOPE int tcf_bpf_act(struct sk_buff *skb, + bpf_compute_data_pointers(skb); + filter_res = bpf_prog_run(filter, skb); + } +- if (unlikely(!skb->tstamp && skb->mono_delivery_time)) +- skb->mono_delivery_time = 0; ++ if (unlikely(!skb->tstamp && skb->tstamp_type)) ++ skb->tstamp_type = SKB_CLOCK_REALTIME; + if (skb_sk_is_prefetched(skb) && filter_res != TC_ACT_OK) + skb_orphan(skb); + +diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c +index 382c7a71f81f2..db7151c6b70b7 100644 +--- a/net/sched/cls_bpf.c ++++ b/net/sched/cls_bpf.c +@@ -104,8 +104,8 @@ TC_INDIRECT_SCOPE int cls_bpf_classify(struct sk_buff *skb, + bpf_compute_data_pointers(skb); + filter_res = bpf_prog_run(prog->filter, skb); + } +- if (unlikely(!skb->tstamp && skb->mono_delivery_time)) +- skb->mono_delivery_time = 0; ++ if (unlikely(!skb->tstamp && skb->tstamp_type)) ++ skb->tstamp_type = SKB_CLOCK_REALTIME; + + if (prog->exts_integrated) { + res->class = 0; +-- +2.39.5 + diff --git a/queue-6.6/net-vertexcom-mse102x-add-range-check-for-cmd_rts.patch b/queue-6.6/net-vertexcom-mse102x-add-range-check-for-cmd_rts.patch new file mode 100644 index 0000000000..cba01d0cb5 --- /dev/null +++ b/queue-6.6/net-vertexcom-mse102x-add-range-check-for-cmd_rts.patch @@ -0,0 +1,50 @@ +From ba128defaca58e649a630a35828dd47b08fb5f89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 15:30:42 +0200 +Subject: net: vertexcom: mse102x: Add range check for CMD_RTS + +From: Stefan Wahren + +[ Upstream commit d4dda902dac194e3231a1ed0f76c6c3b6340ba8a ] + +Since there is no protection in the SPI protocol against electrical +interferences, the driver shouldn't blindly trust the length payload +of CMD_RTS. So introduce a bounds check for incoming frames. + +Fixes: 2f207cbf0dd4 ("net: vertexcom: Add MSE102x SPI support") +Signed-off-by: Stefan Wahren +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250430133043.7722-4-wahrenst@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/vertexcom/mse102x.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c +index 55f34d9d111c4..2b1aac72601d0 100644 +--- a/drivers/net/ethernet/vertexcom/mse102x.c ++++ b/drivers/net/ethernet/vertexcom/mse102x.c +@@ -6,6 +6,7 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + ++#include + #include + #include + #include +@@ -337,8 +338,9 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) + } + + rxlen = cmd_resp & LEN_MASK; +- if (!rxlen) { +- net_dbg_ratelimited("%s: No frame length defined\n", __func__); ++ if (rxlen < ETH_ZLEN || rxlen > VLAN_ETH_FRAME_LEN) { ++ net_dbg_ratelimited("%s: Invalid frame length: %d\n", __func__, ++ rxlen); + mse->stats.invalid_len++; + return; + } +-- +2.39.5 + diff --git a/queue-6.6/net-vertexcom-mse102x-fix-len_mask.patch b/queue-6.6/net-vertexcom-mse102x-fix-len_mask.patch new file mode 100644 index 0000000000..f3fd16a910 --- /dev/null +++ b/queue-6.6/net-vertexcom-mse102x-fix-len_mask.patch @@ -0,0 +1,38 @@ +From a0f032294dc7cc7bdd44ddc478678c453cdfc5e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 15:30:41 +0200 +Subject: net: vertexcom: mse102x: Fix LEN_MASK + +From: Stefan Wahren + +[ Upstream commit 74987089ec678b4018dba0a609e9f4bf6ef7f4ad ] + +The LEN_MASK for CMD_RTS doesn't cover the whole parameter mask. +The Bit 11 is reserved, so adjust LEN_MASK accordingly. + +Fixes: 2f207cbf0dd4 ("net: vertexcom: Add MSE102x SPI support") +Signed-off-by: Stefan Wahren +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250430133043.7722-3-wahrenst@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/vertexcom/mse102x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c +index 45f4d2cb5b31a..55f34d9d111c4 100644 +--- a/drivers/net/ethernet/vertexcom/mse102x.c ++++ b/drivers/net/ethernet/vertexcom/mse102x.c +@@ -33,7 +33,7 @@ + #define CMD_CTR (0x2 << CMD_SHIFT) + + #define CMD_MASK GENMASK(15, CMD_SHIFT) +-#define LEN_MASK GENMASK(CMD_SHIFT - 1, 0) ++#define LEN_MASK GENMASK(CMD_SHIFT - 2, 0) + + #define DET_CMD_LEN 4 + #define DET_SOF_LEN 2 +-- +2.39.5 + diff --git a/queue-6.6/net-vertexcom-mse102x-fix-possible-stuck-of-spi-inte.patch b/queue-6.6/net-vertexcom-mse102x-fix-possible-stuck-of-spi-inte.patch new file mode 100644 index 0000000000..67910546b9 --- /dev/null +++ b/queue-6.6/net-vertexcom-mse102x-fix-possible-stuck-of-spi-inte.patch @@ -0,0 +1,53 @@ +From 12d2c41333b1a593488a43a3cd979c96d06cf5e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 15:30:40 +0200 +Subject: net: vertexcom: mse102x: Fix possible stuck of SPI interrupt + +From: Stefan Wahren + +[ Upstream commit 55f362885951b2d00fd7fbb02ef0227deea572c2 ] + +The MSE102x doesn't provide any SPI commands for interrupt handling. +So in case the interrupt fired before the driver requests the IRQ, +the interrupt will never fire again. In order to fix this always poll +for pending packets after opening the interface. + +Fixes: 2f207cbf0dd4 ("net: vertexcom: Add MSE102x SPI support") +Signed-off-by: Stefan Wahren +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250430133043.7722-2-wahrenst@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/vertexcom/mse102x.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c +index 8f67c39f479ee..45f4d2cb5b31a 100644 +--- a/drivers/net/ethernet/vertexcom/mse102x.c ++++ b/drivers/net/ethernet/vertexcom/mse102x.c +@@ -509,6 +509,7 @@ static irqreturn_t mse102x_irq(int irq, void *_mse) + static int mse102x_net_open(struct net_device *ndev) + { + struct mse102x_net *mse = netdev_priv(ndev); ++ struct mse102x_net_spi *mses = to_mse102x_spi(mse); + int ret; + + ret = request_threaded_irq(ndev->irq, NULL, mse102x_irq, IRQF_ONESHOT, +@@ -524,6 +525,13 @@ static int mse102x_net_open(struct net_device *ndev) + + netif_carrier_on(ndev); + ++ /* The SPI interrupt can stuck in case of pending packet(s). ++ * So poll for possible packet(s) to re-arm the interrupt. ++ */ ++ mutex_lock(&mses->lock); ++ mse102x_rx_pkt_spi(mse); ++ mutex_unlock(&mses->lock); ++ + netif_dbg(mse, ifup, ndev, "network device up\n"); + + return 0; +-- +2.39.5 + diff --git a/queue-6.6/net-vertexcom-mse102x-fix-rx-error-handling.patch b/queue-6.6/net-vertexcom-mse102x-fix-rx-error-handling.patch new file mode 100644 index 0000000000..12adb40766 --- /dev/null +++ b/queue-6.6/net-vertexcom-mse102x-fix-rx-error-handling.patch @@ -0,0 +1,95 @@ +From 5dbf5b53ecc96f352af3ab7f5591cabf143f37c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Apr 2025 15:30:43 +0200 +Subject: net: vertexcom: mse102x: Fix RX error handling + +From: Stefan Wahren + +[ Upstream commit ee512922ddd7d64afe2b28830a88f19063217649 ] + +In case the CMD_RTS got corrupted by interferences, the MSE102x +doesn't allow a retransmission of the command. Instead the Ethernet +frame must be shifted out of the SPI FIFO. Since the actual length is +unknown, assume the maximum possible value. + +Fixes: 2f207cbf0dd4 ("net: vertexcom: Add MSE102x SPI support") +Signed-off-by: Stefan Wahren +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250430133043.7722-5-wahrenst@gmx.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/vertexcom/mse102x.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c +index 2b1aac72601d0..060a566bc6aae 100644 +--- a/drivers/net/ethernet/vertexcom/mse102x.c ++++ b/drivers/net/ethernet/vertexcom/mse102x.c +@@ -263,7 +263,7 @@ static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp, + } + + static int mse102x_rx_frame_spi(struct mse102x_net *mse, u8 *buff, +- unsigned int frame_len) ++ unsigned int frame_len, bool drop) + { + struct mse102x_net_spi *mses = to_mse102x_spi(mse); + struct spi_transfer *xfer = &mses->spi_xfer; +@@ -281,6 +281,9 @@ static int mse102x_rx_frame_spi(struct mse102x_net *mse, u8 *buff, + netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n", + __func__, ret); + mse->stats.xfer_err++; ++ } else if (drop) { ++ netdev_dbg(mse->ndev, "%s: Drop frame\n", __func__); ++ ret = -EINVAL; + } else if (*sof != cpu_to_be16(DET_SOF)) { + netdev_dbg(mse->ndev, "%s: SPI start of frame is invalid (0x%04x)\n", + __func__, *sof); +@@ -308,6 +311,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) + struct sk_buff *skb; + unsigned int rxalign; + unsigned int rxlen; ++ bool drop = false; + __be16 rx = 0; + u16 cmd_resp; + u8 *rxpkt; +@@ -330,7 +334,8 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) + net_dbg_ratelimited("%s: Unexpected response (0x%04x)\n", + __func__, cmd_resp); + mse->stats.invalid_rts++; +- return; ++ drop = true; ++ goto drop; + } + + net_dbg_ratelimited("%s: Unexpected response to first CMD\n", +@@ -342,9 +347,16 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) + net_dbg_ratelimited("%s: Invalid frame length: %d\n", __func__, + rxlen); + mse->stats.invalid_len++; +- return; ++ drop = true; + } + ++ /* In case of a invalid CMD_RTS, the frame must be consumed anyway. ++ * So assume the maximum possible frame length. ++ */ ++drop: ++ if (drop) ++ rxlen = VLAN_ETH_FRAME_LEN; ++ + rxalign = ALIGN(rxlen + DET_SOF_LEN + DET_DFT_LEN, 4); + skb = netdev_alloc_skb_ip_align(mse->ndev, rxalign); + if (!skb) +@@ -355,7 +367,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) + * They are copied, but ignored. + */ + rxpkt = skb_put(skb, rxlen) - DET_SOF_LEN; +- if (mse102x_rx_frame_spi(mse, rxpkt, rxlen)) { ++ if (mse102x_rx_frame_spi(mse, rxpkt, rxlen, drop)) { + mse->ndev->stats.rx_errors++; + dev_kfree_skb(skb); + return; +-- +2.39.5 + diff --git a/queue-6.6/net_sched-drr-fix-double-list-add-in-class-with-nete.patch b/queue-6.6/net_sched-drr-fix-double-list-add-in-class-with-nete.patch new file mode 100644 index 0000000000..c5731cbda8 --- /dev/null +++ b/queue-6.6/net_sched-drr-fix-double-list-add-in-class-with-nete.patch @@ -0,0 +1,75 @@ +From 9a925af1d2e04b589a5265d1b173d195232ef667 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 19:07:05 -0300 +Subject: net_sched: drr: Fix double list add in class with netem as child + qdisc + +From: Victor Nogueira + +[ Upstream commit f99a3fbf023e20b626be4b0f042463d598050c9a ] + +As described in Gerrard's report [1], there are use cases where a netem +child qdisc will make the parent qdisc's enqueue callback reentrant. +In the case of drr, there won't be a UAF, but the code will add the same +classifier to the list twice, which will cause memory corruption. + +In addition to checking for qlen being zero, this patch checks whether the +class was already added to the active_list (cl_is_active) before adding +to the list to cover for the reentrant case. + +[1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/ + +Fixes: 37d9cf1a3ce3 ("sched: Fix detection of empty queues in child qdiscs") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Link: https://patch.msgid.link/20250425220710.3964791-2-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_drr.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c +index 19901e77cd3b7..edadb3a7bd142 100644 +--- a/net/sched/sch_drr.c ++++ b/net/sched/sch_drr.c +@@ -35,6 +35,11 @@ struct drr_sched { + struct Qdisc_class_hash clhash; + }; + ++static bool cl_is_active(struct drr_class *cl) ++{ ++ return !list_empty(&cl->alist); ++} ++ + static struct drr_class *drr_find_class(struct Qdisc *sch, u32 classid) + { + struct drr_sched *q = qdisc_priv(sch); +@@ -336,7 +341,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct drr_sched *q = qdisc_priv(sch); + struct drr_class *cl; + int err = 0; +- bool first; + + cl = drr_classify(skb, sch, &err); + if (cl == NULL) { +@@ -346,7 +350,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, + return err; + } + +- first = !cl->qdisc->q.qlen; + err = qdisc_enqueue(skb, cl->qdisc, to_free); + if (unlikely(err != NET_XMIT_SUCCESS)) { + if (net_xmit_drop_count(err)) { +@@ -356,7 +359,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, + return err; + } + +- if (first) { ++ if (!cl_is_active(cl)) { + list_add_tail(&cl->alist, &q->active); + cl->deficit = cl->quantum; + } +-- +2.39.5 + diff --git a/queue-6.6/net_sched-ets-fix-double-list-add-in-class-with-nete.patch b/queue-6.6/net_sched-ets-fix-double-list-add-in-class-with-nete.patch new file mode 100644 index 0000000000..cc8f263d3f --- /dev/null +++ b/queue-6.6/net_sched-ets-fix-double-list-add-in-class-with-nete.patch @@ -0,0 +1,75 @@ +From b2e8d1af710687ca85d6a7148ae04c8ae04b9949 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 19:07:07 -0300 +Subject: net_sched: ets: Fix double list add in class with netem as child + qdisc + +From: Victor Nogueira + +[ Upstream commit 1a6d0c00fa07972384b0c308c72db091d49988b6 ] + +As described in Gerrard's report [1], there are use cases where a netem +child qdisc will make the parent qdisc's enqueue callback reentrant. +In the case of ets, there won't be a UAF, but the code will add the same +classifier to the list twice, which will cause memory corruption. + +In addition to checking for qlen being zero, this patch checks whether +the class was already added to the active_list (cl_is_active) before +doing the addition to cater for the reentrant case. + +[1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/ + +Fixes: 37d9cf1a3ce3 ("sched: Fix detection of empty queues in child qdiscs") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Link: https://patch.msgid.link/20250425220710.3964791-4-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_ets.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index 9fd70462b41d5..18269f86d21ef 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -74,6 +74,11 @@ static const struct nla_policy ets_class_policy[TCA_ETS_MAX + 1] = { + [TCA_ETS_QUANTA_BAND] = { .type = NLA_U32 }, + }; + ++static bool cl_is_active(struct ets_class *cl) ++{ ++ return !list_empty(&cl->alist); ++} ++ + static int ets_quantum_parse(struct Qdisc *sch, const struct nlattr *attr, + unsigned int *quantum, + struct netlink_ext_ack *extack) +@@ -416,7 +421,6 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct ets_sched *q = qdisc_priv(sch); + struct ets_class *cl; + int err = 0; +- bool first; + + cl = ets_classify(skb, sch, &err); + if (!cl) { +@@ -426,7 +430,6 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, + return err; + } + +- first = !cl->qdisc->q.qlen; + err = qdisc_enqueue(skb, cl->qdisc, to_free); + if (unlikely(err != NET_XMIT_SUCCESS)) { + if (net_xmit_drop_count(err)) { +@@ -436,7 +439,7 @@ static int ets_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, + return err; + } + +- if (first && !ets_class_is_strict(q, cl)) { ++ if (!cl_is_active(cl) && !ets_class_is_strict(q, cl)) { + list_add_tail(&cl->alist, &q->active); + cl->deficit = cl->quantum; + } +-- +2.39.5 + diff --git a/queue-6.6/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-with.patch b/queue-6.6/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-with.patch new file mode 100644 index 0000000000..fd2d38eaed --- /dev/null +++ b/queue-6.6/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-with.patch @@ -0,0 +1,49 @@ +From dab87d27f963928ef7ac322bcc3baa69d973c552 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 19:07:06 -0300 +Subject: net_sched: hfsc: Fix a UAF vulnerability in class with netem as child + qdisc + +From: Victor Nogueira + +[ Upstream commit 141d34391abbb315d68556b7c67ad97885407547 ] + +As described in Gerrard's report [1], we have a UAF case when an hfsc class +has a netem child qdisc. The crux of the issue is that hfsc is assuming +that checking for cl->qdisc->q.qlen == 0 guarantees that it hasn't inserted +the class in the vttree or eltree (which is not true for the netem +duplicate case). + +This patch checks the n_active class variable to make sure that the code +won't insert the class in the vttree or eltree twice, catering for the +reentrant case. + +[1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/ + +Fixes: 37d9cf1a3ce3 ("sched: Fix detection of empty queues in child qdiscs") +Reported-by: Gerrard Tai +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Link: https://patch.msgid.link/20250425220710.3964791-3-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_hfsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c +index 371255e624332..4be8760b8bc3c 100644 +--- a/net/sched/sch_hfsc.c ++++ b/net/sched/sch_hfsc.c +@@ -1566,7 +1566,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) + return err; + } + +- if (first) { ++ if (first && !cl->cl_nactive) { + if (cl->cl_flags & HFSC_RSC) + init_ed(cl, len); + if (cl->cl_flags & HFSC_FSC) +-- +2.39.5 + diff --git a/queue-6.6/net_sched-qfq-fix-double-list-add-in-class-with-nete.patch b/queue-6.6/net_sched-qfq-fix-double-list-add-in-class-with-nete.patch new file mode 100644 index 0000000000..711ac0cf27 --- /dev/null +++ b/queue-6.6/net_sched-qfq-fix-double-list-add-in-class-with-nete.patch @@ -0,0 +1,77 @@ +From 5132749b535c241e6524eb1028f73f9ea2c9d4d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 19:07:08 -0300 +Subject: net_sched: qfq: Fix double list add in class with netem as child + qdisc + +From: Victor Nogueira + +[ Upstream commit f139f37dcdf34b67f5bf92bc8e0f7f6b3ac63aa4 ] + +As described in Gerrard's report [1], there are use cases where a netem +child qdisc will make the parent qdisc's enqueue callback reentrant. +In the case of qfq, there won't be a UAF, but the code will add the same +classifier to the list twice, which will cause memory corruption. + +This patch checks whether the class was already added to the agg->active +list (cl_is_active) before doing the addition to cater for the reentrant +case. + +[1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/ + +Fixes: 37d9cf1a3ce3 ("sched: Fix detection of empty queues in child qdiscs") +Acked-by: Jamal Hadi Salim +Signed-off-by: Victor Nogueira +Link: https://patch.msgid.link/20250425220710.3964791-5-victor@mojatatu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_qfq.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c +index 546c10adcacde..c7d4ee8cedff0 100644 +--- a/net/sched/sch_qfq.c ++++ b/net/sched/sch_qfq.c +@@ -202,6 +202,11 @@ struct qfq_sched { + */ + enum update_reason {enqueue, requeue}; + ++static bool cl_is_active(struct qfq_class *cl) ++{ ++ return !list_empty(&cl->alist); ++} ++ + static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid) + { + struct qfq_sched *q = qdisc_priv(sch); +@@ -1217,7 +1222,6 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct qfq_class *cl; + struct qfq_aggregate *agg; + int err = 0; +- bool first; + + cl = qfq_classify(skb, sch, &err); + if (cl == NULL) { +@@ -1239,7 +1243,6 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, + } + + gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1; +- first = !cl->qdisc->q.qlen; + err = qdisc_enqueue(skb, cl->qdisc, to_free); + if (unlikely(err != NET_XMIT_SUCCESS)) { + pr_debug("qfq_enqueue: enqueue failed %d\n", err); +@@ -1255,8 +1258,8 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, + ++sch->q.qlen; + + agg = cl->agg; +- /* if the queue was not empty, then done here */ +- if (!first) { ++ /* if the class is active, then done here */ ++ if (cl_is_active(cl)) { + if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) && + list_first_entry(&agg->active, struct qfq_class, alist) + == cl && cl->deficit < len) +-- +2.39.5 + diff --git a/queue-6.6/nvme-pci-fix-queue-unquiesce-check-on-slot_reset.patch b/queue-6.6/nvme-pci-fix-queue-unquiesce-check-on-slot_reset.patch new file mode 100644 index 0000000000..cad71b985a --- /dev/null +++ b/queue-6.6/nvme-pci-fix-queue-unquiesce-check-on-slot_reset.patch @@ -0,0 +1,38 @@ +From 1bea08369f8e9f64db409b5f2c1748b97d859256 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 10:18:01 -0700 +Subject: nvme-pci: fix queue unquiesce check on slot_reset + +From: Keith Busch + +[ Upstream commit a75401227eeb827b1a162df1aa9d5b33da921c43 ] + +A zero return means the reset was successfully scheduled. We don't want +to unquiesce the queues while the reset_work is pending, as that will +just flush out requeued requests to a failed completion. + +Fixes: 71a5bb153be104 ("nvme: ensure disabling pairs with unquiesce") +Reported-by: Dhankaran Singh Ajravat +Signed-off-by: Keith Busch +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c +index a763df0200ab4..fdde38903ebcd 100644 +--- a/drivers/nvme/host/pci.c ++++ b/drivers/nvme/host/pci.c +@@ -3377,7 +3377,7 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev) + + dev_info(dev->ctrl.device, "restart after slot reset\n"); + pci_restore_state(pdev); +- if (!nvme_try_sched_reset(&dev->ctrl)) ++ if (nvme_try_sched_reset(&dev->ctrl)) + nvme_unquiesce_io_queues(&dev->ctrl); + return PCI_ERS_RESULT_RECOVERED; + } +-- +2.39.5 + diff --git a/queue-6.6/nvme-tcp-fix-premature-queue-removal-and-i-o-failove.patch b/queue-6.6/nvme-tcp-fix-premature-queue-removal-and-i-o-failove.patch new file mode 100644 index 0000000000..d8a31ca9fb --- /dev/null +++ b/queue-6.6/nvme-tcp-fix-premature-queue-removal-and-i-o-failove.patch @@ -0,0 +1,112 @@ +From bbb73599f4b6eddbe4f6ea8f2af63836328620fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 10:42:01 -0600 +Subject: nvme-tcp: fix premature queue removal and I/O failover +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michael Liang + +[ Upstream commit 77e40bbce93059658aee02786a32c5c98a240a8a ] + +This patch addresses a data corruption issue observed in nvme-tcp during +testing. + +In an NVMe native multipath setup, when an I/O timeout occurs, all +inflight I/Os are canceled almost immediately after the kernel socket is +shut down. These canceled I/Os are reported as host path errors, +triggering a failover that succeeds on a different path. + +However, at this point, the original I/O may still be outstanding in the +host's network transmission path (e.g., the NIC’s TX queue). From the +user-space app's perspective, the buffer associated with the I/O is +considered completed since they're acked on the different path and may +be reused for new I/O requests. + +Because nvme-tcp enables zero-copy by default in the transmission path, +this can lead to corrupted data being sent to the original target, +ultimately causing data corruption. + +We can reproduce this data corruption by injecting delay on one path and +triggering i/o timeout. + +To prevent this issue, this change ensures that all inflight +transmissions are fully completed from host's perspective before +returning from queue stop. To handle concurrent I/O timeout from multiple +namespaces under the same controller, always wait in queue stop +regardless of queue's state. + +This aligns with the behavior of queue stopping in other NVMe fabric +transports. + +Fixes: 3f2304f8c6d6 ("nvme-tcp: add NVMe over TCP host driver") +Signed-off-by: Michael Liang +Reviewed-by: Mohamed Khalfella +Reviewed-by: Randy Jennings +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/tcp.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c +index 84db7f4f861cb..5b76670f34be2 100644 +--- a/drivers/nvme/host/tcp.c ++++ b/drivers/nvme/host/tcp.c +@@ -1710,7 +1710,7 @@ static void __nvme_tcp_stop_queue(struct nvme_tcp_queue *queue) + cancel_work_sync(&queue->io_work); + } + +-static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid) ++static void nvme_tcp_stop_queue_nowait(struct nvme_ctrl *nctrl, int qid) + { + struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); + struct nvme_tcp_queue *queue = &ctrl->queues[qid]; +@@ -1724,6 +1724,31 @@ static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid) + mutex_unlock(&queue->queue_lock); + } + ++static void nvme_tcp_wait_queue(struct nvme_ctrl *nctrl, int qid) ++{ ++ struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl); ++ struct nvme_tcp_queue *queue = &ctrl->queues[qid]; ++ int timeout = 100; ++ ++ while (timeout > 0) { ++ if (!test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags) || ++ !sk_wmem_alloc_get(queue->sock->sk)) ++ return; ++ msleep(2); ++ timeout -= 2; ++ } ++ dev_warn(nctrl->device, ++ "qid %d: timeout draining sock wmem allocation expired\n", ++ qid); ++} ++ ++static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid) ++{ ++ nvme_tcp_stop_queue_nowait(nctrl, qid); ++ nvme_tcp_wait_queue(nctrl, qid); ++} ++ ++ + static void nvme_tcp_setup_sock_ops(struct nvme_tcp_queue *queue) + { + write_lock_bh(&queue->sock->sk->sk_callback_lock); +@@ -1790,7 +1815,9 @@ static void nvme_tcp_stop_io_queues(struct nvme_ctrl *ctrl) + int i; + + for (i = 1; i < ctrl->queue_count; i++) +- nvme_tcp_stop_queue(ctrl, i); ++ nvme_tcp_stop_queue_nowait(ctrl, i); ++ for (i = 1; i < ctrl->queue_count; i++) ++ nvme_tcp_wait_queue(ctrl, i); + } + + static int nvme_tcp_start_io_queues(struct nvme_ctrl *ctrl, +-- +2.39.5 + diff --git a/queue-6.6/octeon_ep-fix-host-hang-issue-during-device-reboot.patch b/queue-6.6/octeon_ep-fix-host-hang-issue-during-device-reboot.patch new file mode 100644 index 0000000000..c70d9c4f06 --- /dev/null +++ b/queue-6.6/octeon_ep-fix-host-hang-issue-during-device-reboot.patch @@ -0,0 +1,47 @@ +From e6bcfca360b5983fb81056a69ccfadb1d3fb7dab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Apr 2025 04:46:24 -0700 +Subject: octeon_ep: Fix host hang issue during device reboot + +From: Sathesh B Edara + +[ Upstream commit 34f42736b325287a7b2ce37e415838f539767bda ] + +When the host loses heartbeat messages from the device, +the driver calls the device-specific ndo_stop function, +which frees the resources. If the driver is unloaded in +this scenario, it calls ndo_stop again, attempting to free +resources that have already been freed, leading to a host +hang issue. To resolve this, dev_close should be called +instead of the device-specific stop function.dev_close +internally calls ndo_stop to stop the network interface +and performs additional cleanup tasks. During the driver +unload process, if the device is already down, ndo_stop +is not called. + +Fixes: 5cb96c29aa0e ("octeon_ep: add heartbeat monitor") +Signed-off-by: Sathesh B Edara +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250429114624.19104-1-sedara@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeon_ep/octep_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +index 6f1fe7e283d4e..7a30095b3486f 100644 +--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c ++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c +@@ -917,7 +917,7 @@ static void octep_hb_timeout_task(struct work_struct *work) + miss_cnt); + rtnl_lock(); + if (netif_running(oct->netdev)) +- octep_stop(oct->netdev); ++ dev_close(oct->netdev); + rtnl_unlock(); + } + +-- +2.39.5 + diff --git a/queue-6.6/pds_core-check-health-in-devcmd-wait.patch b/queue-6.6/pds_core-check-health-in-devcmd-wait.patch new file mode 100644 index 0000000000..a825d0ca44 --- /dev/null +++ b/queue-6.6/pds_core-check-health-in-devcmd-wait.patch @@ -0,0 +1,87 @@ +From 066f17ecaf15b7203d9a9753adc8afe242c5c199 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Sep 2023 15:31:57 -0700 +Subject: pds_core: check health in devcmd wait + +From: Shannon Nelson + +[ Upstream commit f7b5bd725b737de3f2c4a836e07c82ba156d75df ] + +Similar to what we do in the AdminQ, check for devcmd health +while waiting for an answer. + +Signed-off-by: Shannon Nelson +Reviewed-by: Brett Creeley +Signed-off-by: David S. Miller +Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/dev.c | 11 +++++++++-- + include/linux/pds/pds_core_if.h | 1 + + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c +index f0e39ab400450..e65a1632df505 100644 +--- a/drivers/net/ethernet/amd/pds_core/dev.c ++++ b/drivers/net/ethernet/amd/pds_core/dev.c +@@ -42,6 +42,8 @@ int pdsc_err_to_errno(enum pds_core_status_code code) + return -ERANGE; + case PDS_RC_BAD_ADDR: + return -EFAULT; ++ case PDS_RC_BAD_PCI: ++ return -ENXIO; + case PDS_RC_EOPCODE: + case PDS_RC_EINTR: + case PDS_RC_DEV_CMD: +@@ -65,7 +67,7 @@ bool pdsc_is_fw_running(struct pdsc *pdsc) + /* Firmware is useful only if the running bit is set and + * fw_status != 0xff (bad PCI read) + */ +- return (pdsc->fw_status != 0xff) && ++ return (pdsc->fw_status != PDS_RC_BAD_PCI) && + (pdsc->fw_status & PDS_CORE_FW_STS_F_RUNNING); + } + +@@ -131,6 +133,7 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds) + unsigned long max_wait; + unsigned long duration; + int timeout = 0; ++ bool running; + int done = 0; + int err = 0; + int status; +@@ -139,6 +142,10 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds) + max_wait = start_time + (max_seconds * HZ); + + while (!done && !timeout) { ++ running = pdsc_is_fw_running(pdsc); ++ if (!running) ++ break; ++ + done = pdsc_devcmd_done(pdsc); + if (done) + break; +@@ -155,7 +162,7 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds) + dev_dbg(dev, "DEVCMD %d %s after %ld secs\n", + opcode, pdsc_devcmd_str(opcode), duration / HZ); + +- if (!done || timeout) { ++ if ((!done || timeout) && running) { + dev_err(dev, "DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n", + opcode, pdsc_devcmd_str(opcode), done, timeout, + max_seconds); +diff --git a/include/linux/pds/pds_core_if.h b/include/linux/pds/pds_core_if.h +index e838a2b90440c..17a87c1a55d7c 100644 +--- a/include/linux/pds/pds_core_if.h ++++ b/include/linux/pds/pds_core_if.h +@@ -79,6 +79,7 @@ enum pds_core_status_code { + PDS_RC_EVFID = 31, /* VF ID does not exist */ + PDS_RC_BAD_FW = 32, /* FW file is invalid or corrupted */ + PDS_RC_ECLIENT = 33, /* No such client id */ ++ PDS_RC_BAD_PCI = 255, /* Broken PCI when reading status */ + }; + + /** +-- +2.39.5 + diff --git a/queue-6.6/pds_core-delete-vf-dev-on-reset.patch b/queue-6.6/pds_core-delete-vf-dev-on-reset.patch new file mode 100644 index 0000000000..5bc216e607 --- /dev/null +++ b/queue-6.6/pds_core-delete-vf-dev-on-reset.patch @@ -0,0 +1,104 @@ +From cb031f57ca75bbd69f4beb77e4b03a094bd9fdd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Feb 2024 14:29:51 -0800 +Subject: pds_core: delete VF dev on reset + +From: Shannon Nelson + +[ Upstream commit 2dac60e062340c1e5c975ad6465192d11c40d47a ] + +When the VF is hit with a reset, remove the aux device in +the prepare for reset and try to restore it after the reset. +The userland mechanics will need to recover and rebuild whatever +uses the device afterwards. + +Reviewed-by: Brett Creeley +Signed-off-by: Shannon Nelson +Signed-off-by: David S. Miller +Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 18 +++++++++++++++++- + drivers/net/ethernet/amd/pds_core/main.c | 16 ++++++++++++++++ + 2 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index fb7a5403e630d..b76a9b7e0aed6 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -177,6 +177,9 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) + struct pds_auxiliary_dev *padev; + int err = 0; + ++ if (!cf) ++ return -ENODEV; ++ + mutex_lock(&pf->config_lock); + + padev = pf->vfs[cf->vf_id].padev; +@@ -195,14 +198,27 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) + int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) + { + struct pds_auxiliary_dev *padev; +- enum pds_core_vif_types vt; + char devname[PDS_DEVNAME_LEN]; ++ enum pds_core_vif_types vt; ++ unsigned long mask; + u16 vt_support; + int client_id; + int err = 0; + ++ if (!cf) ++ return -ENODEV; ++ + mutex_lock(&pf->config_lock); + ++ mask = BIT_ULL(PDSC_S_FW_DEAD) | ++ BIT_ULL(PDSC_S_STOPPING_DRIVER); ++ if (cf->state & mask) { ++ dev_err(pf->dev, "%s: can't add dev, VF client in bad state %#lx\n", ++ __func__, cf->state); ++ err = -ENXIO; ++ goto out_unlock; ++ } ++ + /* We only support vDPA so far, so it is the only one to + * be verified that it is available in the Core device and + * enabled in the devlink param. In the future this might +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index eddbf0acdde77..346a69e95c880 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -475,6 +475,14 @@ static void pdsc_reset_prepare(struct pci_dev *pdev) + pdsc_stop_health_thread(pdsc); + pdsc_fw_down(pdsc); + ++ if (pdev->is_virtfn) { ++ struct pdsc *pf; ++ ++ pf = pdsc_get_pf_struct(pdsc->pdev); ++ if (!IS_ERR(pf)) ++ pdsc_auxbus_dev_del(pdsc, pf); ++ } ++ + pdsc_unmap_bars(pdsc); + pci_release_regions(pdev); + pci_disable_device(pdev); +@@ -510,6 +518,14 @@ static void pdsc_reset_done(struct pci_dev *pdev) + + pdsc_fw_up(pdsc); + pdsc_restart_health_thread(pdsc); ++ ++ if (pdev->is_virtfn) { ++ struct pdsc *pf; ++ ++ pf = pdsc_get_pf_struct(pdsc->pdev); ++ if (!IS_ERR(pf)) ++ pdsc_auxbus_dev_add(pdsc, pf); ++ } + } + + static const struct pci_error_handlers pdsc_err_handler = { +-- +2.39.5 + diff --git a/queue-6.6/pds_core-make-pdsc_auxbus_dev_del-void.patch b/queue-6.6/pds_core-make-pdsc_auxbus_dev_del-void.patch new file mode 100644 index 0000000000..97e20a7bab --- /dev/null +++ b/queue-6.6/pds_core-make-pdsc_auxbus_dev_del-void.patch @@ -0,0 +1,87 @@ +From 19d3aae256b3a415e4c98424c5672f2755e954dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 12:44:07 -0700 +Subject: pds_core: make pdsc_auxbus_dev_del() void + +From: Shannon Nelson + +[ Upstream commit e8562da829432d04a0de1830146984c89844f35e ] + +Since there really is no useful return, advertising a return value +is rather misleading. Make pdsc_auxbus_dev_del() a void function. + +Link: https://patch.msgid.link/r/20250320194412.67983-2-shannon.nelson@amd.com +Reviewed-by: Leon Romanovsky +Reviewed-by: Jonathan Cameron +Reviewed-by: Kalesh AP +Reviewed-by: Dave Jiang +Signed-off-by: Shannon Nelson +Signed-off-by: Jason Gunthorpe +Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 7 +------ + drivers/net/ethernet/amd/pds_core/core.h | 2 +- + drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++-- + 3 files changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index b76a9b7e0aed6..d53b2124b1498 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -172,13 +172,9 @@ static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf, + return padev; + } + +-int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) ++void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) + { + struct pds_auxiliary_dev *padev; +- int err = 0; +- +- if (!cf) +- return -ENODEV; + + mutex_lock(&pf->config_lock); + +@@ -192,7 +188,6 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) + pf->vfs[cf->vf_id].padev = NULL; + + mutex_unlock(&pf->config_lock); +- return err; + } + + int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) +diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h +index 858bebf797762..480f9e8cbc4d5 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.h ++++ b/drivers/net/ethernet/amd/pds_core/core.h +@@ -301,7 +301,7 @@ int pdsc_register_notify(struct notifier_block *nb); + void pdsc_unregister_notify(struct notifier_block *nb); + void pdsc_notify(unsigned long event, void *data); + int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf); +-int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf); ++void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf); + + void pdsc_process_adminq(struct pdsc_qcq *qcq); + void pdsc_work_thread(struct work_struct *work); +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index 0032e8e351811..9b77bb73d25db 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -55,8 +55,10 @@ int pdsc_dl_enable_set(struct devlink *dl, u32 id, + for (vf_id = 0; vf_id < pdsc->num_vfs; vf_id++) { + struct pdsc *vf = pdsc->vfs[vf_id].vf; + +- err = ctx->val.vbool ? pdsc_auxbus_dev_add(vf, pdsc) : +- pdsc_auxbus_dev_del(vf, pdsc); ++ if (ctx->val.vbool) ++ err = pdsc_auxbus_dev_add(vf, pdsc); ++ else ++ pdsc_auxbus_dev_del(vf, pdsc); + } + + return err; +-- +2.39.5 + diff --git a/queue-6.6/pds_core-remove-write-after-free-of-client_id.patch b/queue-6.6/pds_core-remove-write-after-free-of-client_id.patch new file mode 100644 index 0000000000..d77de5cd95 --- /dev/null +++ b/queue-6.6/pds_core-remove-write-after-free-of-client_id.patch @@ -0,0 +1,52 @@ +From cbf3359b15d0d22cb7c3715578c4b425425aedfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Apr 2025 13:38:57 -0700 +Subject: pds_core: remove write-after-free of client_id + +From: Shannon Nelson + +[ Upstream commit dfd76010f8e821b66116dec3c7d90dd2403d1396 ] + +A use-after-free error popped up in stress testing: + +[Mon Apr 21 21:21:33 2025] BUG: KFENCE: use-after-free write in pdsc_auxbus_dev_del+0xef/0x160 [pds_core] +[Mon Apr 21 21:21:33 2025] Use-after-free write at 0x000000007013ecd1 (in kfence-#47): +[Mon Apr 21 21:21:33 2025] pdsc_auxbus_dev_del+0xef/0x160 [pds_core] +[Mon Apr 21 21:21:33 2025] pdsc_remove+0xc0/0x1b0 [pds_core] +[Mon Apr 21 21:21:33 2025] pci_device_remove+0x24/0x70 +[Mon Apr 21 21:21:33 2025] device_release_driver_internal+0x11f/0x180 +[Mon Apr 21 21:21:33 2025] driver_detach+0x45/0x80 +[Mon Apr 21 21:21:33 2025] bus_remove_driver+0x83/0xe0 +[Mon Apr 21 21:21:33 2025] pci_unregister_driver+0x1a/0x80 + +The actual device uninit usually happens on a separate thread +scheduled after this code runs, but there is no guarantee of order +of thread execution, so this could be a problem. There's no +actual need to clear the client_id at this point, so simply +remove the offending code. + +Fixes: 10659034c622 ("pds_core: add the aux client API") +Signed-off-by: Shannon Nelson +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250425203857.71547-1-shannon.nelson@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index 4d3387bebe6a4..889a18962270a 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -186,7 +186,6 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, + pds_client_unregister(pf, padev->client_id); + auxiliary_device_delete(&padev->aux_dev); + auxiliary_device_uninit(&padev->aux_dev); +- padev->client_id = 0; + *pd_ptr = NULL; + + mutex_unlock(&pf->config_lock); +-- +2.39.5 + diff --git a/queue-6.6/pds_core-specify-auxiliary_device-to-be-created.patch b/queue-6.6/pds_core-specify-auxiliary_device-to-be-created.patch new file mode 100644 index 0000000000..6aafb5ab22 --- /dev/null +++ b/queue-6.6/pds_core-specify-auxiliary_device-to-be-created.patch @@ -0,0 +1,195 @@ +From 4504297b35fc2d727079a6e9da0243249bfd61d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Mar 2025 12:44:08 -0700 +Subject: pds_core: specify auxiliary_device to be created + +From: Shannon Nelson + +[ Upstream commit b699bdc720c0255d1bb76cecba7382c1f2107af5 ] + +In preparation for adding a new auxiliary_device for the PF, +make the vif type an argument to pdsc_auxbus_dev_add(). Pass in +the address of the padev pointer so that the caller can specify +where to save it and keep the mutex usage within the function. + +Link: https://patch.msgid.link/r/20250320194412.67983-3-shannon.nelson@amd.com +Reviewed-by: Leon Romanovsky +Reviewed-by: Jonathan Cameron +Reviewed-by: Dave Jiang +Signed-off-by: Shannon Nelson +Signed-off-by: Jason Gunthorpe +Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 37 ++++++++++----------- + drivers/net/ethernet/amd/pds_core/core.h | 7 ++-- + drivers/net/ethernet/amd/pds_core/devlink.c | 5 +-- + drivers/net/ethernet/amd/pds_core/main.c | 11 +++--- + 4 files changed, 33 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index d53b2124b1498..4d3387bebe6a4 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -172,29 +172,32 @@ static struct pds_auxiliary_dev *pdsc_auxbus_dev_register(struct pdsc *cf, + return padev; + } + +-void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf) ++void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, ++ struct pds_auxiliary_dev **pd_ptr) + { + struct pds_auxiliary_dev *padev; + ++ if (!*pd_ptr) ++ return; ++ + mutex_lock(&pf->config_lock); + +- padev = pf->vfs[cf->vf_id].padev; +- if (padev) { +- pds_client_unregister(pf, padev->client_id); +- auxiliary_device_delete(&padev->aux_dev); +- auxiliary_device_uninit(&padev->aux_dev); +- padev->client_id = 0; +- } +- pf->vfs[cf->vf_id].padev = NULL; ++ padev = *pd_ptr; ++ pds_client_unregister(pf, padev->client_id); ++ auxiliary_device_delete(&padev->aux_dev); ++ auxiliary_device_uninit(&padev->aux_dev); ++ padev->client_id = 0; ++ *pd_ptr = NULL; + + mutex_unlock(&pf->config_lock); + } + +-int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) ++int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf, ++ enum pds_core_vif_types vt, ++ struct pds_auxiliary_dev **pd_ptr) + { + struct pds_auxiliary_dev *padev; + char devname[PDS_DEVNAME_LEN]; +- enum pds_core_vif_types vt; + unsigned long mask; + u16 vt_support; + int client_id; +@@ -203,6 +206,9 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) + if (!cf) + return -ENODEV; + ++ if (vt >= PDS_DEV_TYPE_MAX) ++ return -EINVAL; ++ + mutex_lock(&pf->config_lock); + + mask = BIT_ULL(PDSC_S_FW_DEAD) | +@@ -214,17 +220,10 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) + goto out_unlock; + } + +- /* We only support vDPA so far, so it is the only one to +- * be verified that it is available in the Core device and +- * enabled in the devlink param. In the future this might +- * become a loop for several VIF types. +- */ +- + /* Verify that the type is supported and enabled. It is not + * an error if there is no auxbus device support for this + * VF, it just means something else needs to happen with it. + */ +- vt = PDS_DEV_TYPE_VDPA; + vt_support = !!le16_to_cpu(pf->dev_ident.vif_types[vt]); + if (!(vt_support && + pf->viftype_status[vt].supported && +@@ -250,7 +249,7 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf) + err = PTR_ERR(padev); + goto out_unlock; + } +- pf->vfs[cf->vf_id].padev = padev; ++ *pd_ptr = padev; + + out_unlock: + mutex_unlock(&pf->config_lock); +diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h +index 480f9e8cbc4d5..61ee607ee48ac 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.h ++++ b/drivers/net/ethernet/amd/pds_core/core.h +@@ -300,8 +300,11 @@ void pdsc_health_thread(struct work_struct *work); + int pdsc_register_notify(struct notifier_block *nb); + void pdsc_unregister_notify(struct notifier_block *nb); + void pdsc_notify(unsigned long event, void *data); +-int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf); +-void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf); ++int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf, ++ enum pds_core_vif_types vt, ++ struct pds_auxiliary_dev **pd_ptr); ++void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, ++ struct pds_auxiliary_dev **pd_ptr); + + void pdsc_process_adminq(struct pdsc_qcq *qcq); + void pdsc_work_thread(struct work_struct *work); +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index 9b77bb73d25db..bee70e46e34c6 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -56,9 +56,10 @@ int pdsc_dl_enable_set(struct devlink *dl, u32 id, + struct pdsc *vf = pdsc->vfs[vf_id].vf; + + if (ctx->val.vbool) +- err = pdsc_auxbus_dev_add(vf, pdsc); ++ err = pdsc_auxbus_dev_add(vf, pdsc, vt_entry->vif_id, ++ &pdsc->vfs[vf_id].padev); + else +- pdsc_auxbus_dev_del(vf, pdsc); ++ pdsc_auxbus_dev_del(vf, pdsc, &pdsc->vfs[vf_id].padev); + } + + return err; +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index 346a69e95c880..76652e0e5b6d9 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -189,7 +189,8 @@ static int pdsc_init_vf(struct pdsc *vf) + devl_unlock(dl); + + pf->vfs[vf->vf_id].vf = vf; +- err = pdsc_auxbus_dev_add(vf, pf); ++ err = pdsc_auxbus_dev_add(vf, pf, PDS_DEV_TYPE_VDPA, ++ &pf->vfs[vf->vf_id].padev); + if (err) { + devl_lock(dl); + devl_unregister(dl); +@@ -415,7 +416,7 @@ static void pdsc_remove(struct pci_dev *pdev) + + pf = pdsc_get_pf_struct(pdsc->pdev); + if (!IS_ERR(pf)) { +- pdsc_auxbus_dev_del(pdsc, pf); ++ pdsc_auxbus_dev_del(pdsc, pf, &pf->vfs[pdsc->vf_id].padev); + pf->vfs[pdsc->vf_id].vf = NULL; + } + } else { +@@ -480,7 +481,8 @@ static void pdsc_reset_prepare(struct pci_dev *pdev) + + pf = pdsc_get_pf_struct(pdsc->pdev); + if (!IS_ERR(pf)) +- pdsc_auxbus_dev_del(pdsc, pf); ++ pdsc_auxbus_dev_del(pdsc, pf, ++ &pf->vfs[pdsc->vf_id].padev); + } + + pdsc_unmap_bars(pdsc); +@@ -524,7 +526,8 @@ static void pdsc_reset_done(struct pci_dev *pdev) + + pf = pdsc_get_pf_struct(pdsc->pdev); + if (!IS_ERR(pf)) +- pdsc_auxbus_dev_add(pdsc, pf); ++ pdsc_auxbus_dev_add(pdsc, pf, PDS_DEV_TYPE_VDPA, ++ &pf->vfs[pdsc->vf_id].padev); + } + } + +-- +2.39.5 + diff --git a/queue-6.6/pinctrl-core-add-a-convenient-define-pinctrl_group_d.patch b/queue-6.6/pinctrl-core-add-a-convenient-define-pinctrl_group_d.patch new file mode 100644 index 0000000000..910bdca463 --- /dev/null +++ b/queue-6.6/pinctrl-core-add-a-convenient-define-pinctrl_group_d.patch @@ -0,0 +1,61 @@ +From a1d821fd433ed86125ce6fc67f58a4416044546b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Dec 2023 20:57:54 +0200 +Subject: pinctrl: core: Add a convenient define PINCTRL_GROUP_DESC() + +From: Andy Shevchenko + +[ Upstream commit 383da0c7f25428de5ad09dc2cfed7cd43c4fb6ba ] + +Add PINCTRL_GROUP_DESC() macro for inline use. + +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20231211190321.307330-2-andriy.shevchenko@linux.intel.com +Signed-off-by: Linus Walleij +Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found") +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/core.c | 5 +---- + drivers/pinctrl/core.h | 9 +++++++++ + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index 7342148c65729..241face4ad077 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -659,10 +659,7 @@ int pinctrl_generic_add_group(struct pinctrl_dev *pctldev, const char *name, + if (!group) + return -ENOMEM; + +- group->name = name; +- group->pins = pins; +- group->num_pins = num_pins; +- group->data = data; ++ *group = PINCTRL_GROUP_DESC(name, pins, num_pins, data); + + error = radix_tree_insert(&pctldev->pin_group_tree, selector, group); + if (error) +diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h +index ece4b9c71c970..717ba75bb4cbf 100644 +--- a/drivers/pinctrl/core.h ++++ b/drivers/pinctrl/core.h +@@ -209,6 +209,15 @@ struct group_desc { + void *data; + }; + ++/* Convenience macro to define a generic pin group descriptor */ ++#define PINCTRL_GROUP_DESC(_name, _pins, _num_pins, _data) \ ++(struct group_desc) { \ ++ .name = _name, \ ++ .pins = _pins, \ ++ .num_pins = _num_pins, \ ++ .data = _data, \ ++} ++ + int pinctrl_generic_get_group_count(struct pinctrl_dev *pctldev); + + const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev, +-- +2.39.5 + diff --git a/queue-6.6/pinctrl-core-embed-struct-pingroup-into-struct-group.patch b/queue-6.6/pinctrl-core-embed-struct-pingroup-into-struct-group.patch new file mode 100644 index 0000000000..941c95ffac --- /dev/null +++ b/queue-6.6/pinctrl-core-embed-struct-pingroup-into-struct-group.patch @@ -0,0 +1,91 @@ +From 8b71dccff488d6d4939004007318c248c18b2030 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Dec 2023 20:57:57 +0200 +Subject: pinctrl: core: Embed struct pingroup into struct group_desc + +From: Andy Shevchenko + +[ Upstream commit 85174ad7c30fca29a354221e01fad82c0d00d644 ] + +struct group_desc is a particular version of the struct pingroup +with associated opaque data. Start switching pin control core and +drivers to use it explicitly. + +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20231211190321.307330-5-andriy.shevchenko@linux.intel.com +Signed-off-by: Linus Walleij +Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found") +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/core.c | 15 ++++++++++++--- + drivers/pinctrl/core.h | 5 +++++ + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index 241face4ad077..3f8e348668eb6 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -558,7 +558,10 @@ const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev, + if (!group) + return NULL; + +- return group->name; ++ if (group->name) ++ return group->name; ++ ++ return group->grp.name; + } + EXPORT_SYMBOL_GPL(pinctrl_generic_get_group_name); + +@@ -584,8 +587,14 @@ int pinctrl_generic_get_group_pins(struct pinctrl_dev *pctldev, + return -EINVAL; + } + +- *pins = group->pins; +- *num_pins = group->num_pins; ++ if (group->pins) { ++ *pins = group->pins; ++ *num_pins = group->num_pins; ++ return 0; ++ } ++ ++ *pins = group->grp.pins; ++ *num_pins = group->grp.npins; + + return 0; + } +diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h +index 717ba75bb4cbf..efc4c22367661 100644 +--- a/drivers/pinctrl/core.h ++++ b/drivers/pinctrl/core.h +@@ -195,14 +195,18 @@ struct pinctrl_maps { + + #ifdef CONFIG_GENERIC_PINCTRL_GROUPS + ++#include ++ + /** + * struct group_desc - generic pin group descriptor ++ * @grp: generic data of the pin group (name and pins) + * @name: name of the pin group + * @pins: array of pins that belong to the group + * @num_pins: number of pins in the group + * @data: pin controller driver specific data + */ + struct group_desc { ++ struct pingroup grp; + const char *name; + int *pins; + int num_pins; +@@ -212,6 +216,7 @@ struct group_desc { + /* Convenience macro to define a generic pin group descriptor */ + #define PINCTRL_GROUP_DESC(_name, _pins, _num_pins, _data) \ + (struct group_desc) { \ ++ .grp = PINCTRL_PINGROUP(_name, _pins, _num_pins), \ + .name = _name, \ + .pins = _pins, \ + .num_pins = _num_pins, \ +-- +2.39.5 + diff --git a/queue-6.6/pinctrl-imx-convert-to-use-grp-member.patch b/queue-6.6/pinctrl-imx-convert-to-use-grp-member.patch new file mode 100644 index 0000000000..902f99eb2f --- /dev/null +++ b/queue-6.6/pinctrl-imx-convert-to-use-grp-member.patch @@ -0,0 +1,125 @@ +From e6cfba815a3d278730952170acba316a86368c85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Dec 2023 20:58:00 +0200 +Subject: pinctrl: imx: Convert to use grp member + +From: Andy Shevchenko + +[ Upstream commit 390270f25b414fd54b307cd68851b36b52f952b5 ] + +Convert drivers to use grp member embedded in struct group_desc, +because other members will be removed to avoid duplication and +desynchronisation of the generic pin group description. + +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20231211190321.307330-8-andriy.shevchenko@linux.intel.com +Signed-off-by: Linus Walleij +Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found") +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/freescale/pinctrl-imx.c | 31 +++++++++++-------------- + 1 file changed, 14 insertions(+), 17 deletions(-) + +diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c +index 28164b04b1bed..2d3d80921c0d1 100644 +--- a/drivers/pinctrl/freescale/pinctrl-imx.c ++++ b/drivers/pinctrl/freescale/pinctrl-imx.c +@@ -42,7 +42,7 @@ static inline const struct group_desc *imx_pinctrl_find_group_by_name( + + for (i = 0; i < pctldev->num_groups; i++) { + grp = pinctrl_generic_get_group(pctldev, i); +- if (grp && !strcmp(grp->name, name)) ++ if (grp && !strcmp(grp->grp.name, name)) + break; + } + +@@ -79,9 +79,9 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, + } + + if (info->flags & IMX_USE_SCU) { +- map_num += grp->num_pins; ++ map_num += grp->grp.npins; + } else { +- for (i = 0; i < grp->num_pins; i++) { ++ for (i = 0; i < grp->grp.npins; i++) { + pin = &((struct imx_pin *)(grp->data))[i]; + if (!(pin->conf.mmio.config & IMX_NO_PAD_CTL)) + map_num++; +@@ -109,7 +109,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, + + /* create config map */ + new_map++; +- for (i = j = 0; i < grp->num_pins; i++) { ++ for (i = j = 0; i < grp->grp.npins; i++) { + pin = &((struct imx_pin *)(grp->data))[i]; + + /* +@@ -263,10 +263,10 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, + if (!func) + return -EINVAL; + +- npins = grp->num_pins; ++ npins = grp->grp.npins; + + dev_dbg(ipctl->dev, "enable function %s group %s\n", +- func->name, grp->name); ++ func->name, grp->grp.name); + + for (i = 0; i < npins; i++) { + /* +@@ -423,7 +423,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, + if (!grp) + return; + +- for (i = 0; i < grp->num_pins; i++) { ++ for (i = 0; i < grp->grp.npins; i++) { + struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i]; + + name = pin_get_name(pctldev, pin->pin); +@@ -526,7 +526,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np, + pin_size = FSL_PIN_SIZE; + + /* Initialise group */ +- grp->name = np->name; ++ grp->grp.name = np->name; + + /* + * the binding format is fsl,pins = , +@@ -554,19 +554,17 @@ static int imx_pinctrl_parse_groups(struct device_node *np, + return -EINVAL; + } + +- grp->num_pins = size / pin_size; +- grp->data = devm_kcalloc(ipctl->dev, +- grp->num_pins, sizeof(struct imx_pin), +- GFP_KERNEL); ++ grp->grp.npins = size / pin_size; ++ grp->data = devm_kcalloc(ipctl->dev, grp->grp.npins, sizeof(*pin), GFP_KERNEL); + if (!grp->data) + return -ENOMEM; + +- pins = devm_kcalloc(ipctl->dev, grp->num_pins, sizeof(*pins), GFP_KERNEL); ++ pins = devm_kcalloc(ipctl->dev, grp->grp.npins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; +- grp->pins = pins; ++ grp->grp.pins = pins; + +- for (i = 0; i < grp->num_pins; i++) { ++ for (i = 0; i < grp->grp.npins; i++) { + pin = &((struct imx_pin *)(grp->data))[i]; + if (info->flags & IMX_USE_SCU) + info->imx_pinctrl_parse_pin(ipctl, &pins[i], pin, &list); +@@ -613,8 +611,7 @@ static int imx_pinctrl_parse_functions(struct device_node *np, + + i = 0; + for_each_child_of_node(np, child) { +- grp = devm_kzalloc(ipctl->dev, sizeof(struct group_desc), +- GFP_KERNEL); ++ grp = devm_kzalloc(ipctl->dev, sizeof(*grp), GFP_KERNEL); + if (!grp) { + of_node_put(child); + return -ENOMEM; +-- +2.39.5 + diff --git a/queue-6.6/pinctrl-imx-return-null-if-no-group-is-matched-and-f.patch b/queue-6.6/pinctrl-imx-return-null-if-no-group-is-matched-and-f.patch new file mode 100644 index 0000000000..625e0465b6 --- /dev/null +++ b/queue-6.6/pinctrl-imx-return-null-if-no-group-is-matched-and-f.patch @@ -0,0 +1,50 @@ +From 05f0d2b7b49ff4006b4d218c02fdab185ec18380 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 11:16:00 +0800 +Subject: pinctrl: imx: Return NULL if no group is matched and found + +From: Hui Wang + +[ Upstream commit e64c0ff0d5d85791fbcd126ee558100a06a24a97 ] + +Currently if no group is matched and found, this function will return +the last grp to the caller, this is not expected, it is supposed to +return NULL in this case. + +Fixes: e566fc11ea76 ("pinctrl: imx: use generic pinctrl helpers for managing groups") +Signed-off-by: Hui Wang +Reviewed-by: Frank Li +Link: https://lore.kernel.org/20250327031600.99723-1-hui.wang@canonical.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/freescale/pinctrl-imx.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c +index 2d3d80921c0d1..bcc657af272a3 100644 +--- a/drivers/pinctrl/freescale/pinctrl-imx.c ++++ b/drivers/pinctrl/freescale/pinctrl-imx.c +@@ -37,16 +37,16 @@ static inline const struct group_desc *imx_pinctrl_find_group_by_name( + struct pinctrl_dev *pctldev, + const char *name) + { +- const struct group_desc *grp = NULL; ++ const struct group_desc *grp; + int i; + + for (i = 0; i < pctldev->num_groups; i++) { + grp = pinctrl_generic_get_group(pctldev, i); + if (grp && !strcmp(grp->grp.name, name)) +- break; ++ return grp; + } + +- return grp; ++ return NULL; + } + + static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, +-- +2.39.5 + diff --git a/queue-6.6/pinctrl-imx-use-temporary-variable-to-hold-pins.patch b/queue-6.6/pinctrl-imx-use-temporary-variable-to-hold-pins.patch new file mode 100644 index 0000000000..1a75264774 --- /dev/null +++ b/queue-6.6/pinctrl-imx-use-temporary-variable-to-hold-pins.patch @@ -0,0 +1,66 @@ +From b4342d35738d86e8ab37b28ac6789b54d875e2e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 18:06:28 +0200 +Subject: pinctrl: imx: Use temporary variable to hold pins + +From: Andy Shevchenko + +[ Upstream commit 26ea8229e7adb508133b078790990486c1657cc7 ] + +The pins are allocated from the heap, but in order to pass +them as constant object, we need to use non-constant pointer. +Achieve this by using a temporary variable. + +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20231129161459.1002323-6-andriy.shevchenko@linux.intel.com +Signed-off-by: Linus Walleij +Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found") +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/freescale/pinctrl-imx.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c +index 9bc16943014f0..28164b04b1bed 100644 +--- a/drivers/pinctrl/freescale/pinctrl-imx.c ++++ b/drivers/pinctrl/freescale/pinctrl-imx.c +@@ -511,6 +511,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np, + { + const struct imx_pinctrl_soc_info *info = ipctl->info; + struct imx_pin *pin; ++ unsigned int *pins; + int size, pin_size; + const __be32 *list; + int i; +@@ -557,20 +558,20 @@ static int imx_pinctrl_parse_groups(struct device_node *np, + grp->data = devm_kcalloc(ipctl->dev, + grp->num_pins, sizeof(struct imx_pin), + GFP_KERNEL); +- grp->pins = devm_kcalloc(ipctl->dev, +- grp->num_pins, sizeof(unsigned int), +- GFP_KERNEL); +- if (!grp->pins || !grp->data) ++ if (!grp->data) ++ return -ENOMEM; ++ ++ pins = devm_kcalloc(ipctl->dev, grp->num_pins, sizeof(*pins), GFP_KERNEL); ++ if (!pins) + return -ENOMEM; ++ grp->pins = pins; + + for (i = 0; i < grp->num_pins; i++) { + pin = &((struct imx_pin *)(grp->data))[i]; + if (info->flags & IMX_USE_SCU) +- info->imx_pinctrl_parse_pin(ipctl, &grp->pins[i], +- pin, &list); ++ info->imx_pinctrl_parse_pin(ipctl, &pins[i], pin, &list); + else +- imx_pinctrl_parse_pin_mmio(ipctl, &grp->pins[i], +- pin, &list, np); ++ imx_pinctrl_parse_pin_mmio(ipctl, &pins[i], pin, &list, np); + } + + return 0; +-- +2.39.5 + diff --git a/queue-6.6/pinctrl-mediatek-use-c99-initializers-in-pinctrl_pin.patch b/queue-6.6/pinctrl-mediatek-use-c99-initializers-in-pinctrl_pin.patch new file mode 100644 index 0000000000..d79dbc6704 --- /dev/null +++ b/queue-6.6/pinctrl-mediatek-use-c99-initializers-in-pinctrl_pin.patch @@ -0,0 +1,70 @@ +From 288b9c534a9089e765dbb919803fed4debb27e52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Dec 2023 20:57:55 +0200 +Subject: pinctrl: mediatek: Use C99 initializers in PINCTRL_PIN_GROUP() + +From: Andy Shevchenko + +[ Upstream commit bb5eace1562fcef3c7ac9d0bd3e01af1187e46d0 ] + +For the better flexibility use C99 initializers in PINCTRL_PIN_GROUP(). + +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20231211190321.307330-3-andriy.shevchenko@linux.intel.com +Signed-off-by: Linus Walleij +Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found") +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/mediatek/pinctrl-moore.h | 12 ++++++------ + drivers/pinctrl/mediatek/pinctrl-paris.h | 12 ++++++------ + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/pinctrl/mediatek/pinctrl-moore.h b/drivers/pinctrl/mediatek/pinctrl-moore.h +index e1b4b82b9d3db..36ee0021cf7ed 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-moore.h ++++ b/drivers/pinctrl/mediatek/pinctrl-moore.h +@@ -37,12 +37,12 @@ + .funcs = NULL, \ + } + +-#define PINCTRL_PIN_GROUP(name, id) \ +- { \ +- name, \ +- id##_pins, \ +- ARRAY_SIZE(id##_pins), \ +- id##_funcs, \ ++#define PINCTRL_PIN_GROUP(_name_, id) \ ++ { \ ++ .name = _name_, \ ++ .pins = id##_pins, \ ++ .num_pins = ARRAY_SIZE(id##_pins), \ ++ .data = id##_funcs, \ + } + + int mtk_moore_pinctrl_probe(struct platform_device *pdev, +diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h +index 8762ac5993292..5c4e5b74e43e2 100644 +--- a/drivers/pinctrl/mediatek/pinctrl-paris.h ++++ b/drivers/pinctrl/mediatek/pinctrl-paris.h +@@ -49,12 +49,12 @@ + __VA_ARGS__, { } }, \ + } + +-#define PINCTRL_PIN_GROUP(name, id) \ +- { \ +- name, \ +- id##_pins, \ +- ARRAY_SIZE(id##_pins), \ +- id##_funcs, \ ++#define PINCTRL_PIN_GROUP(_name_, id) \ ++ { \ ++ .name = _name_, \ ++ .pins = id##_pins, \ ++ .num_pins = ARRAY_SIZE(id##_pins), \ ++ .data = id##_funcs, \ + } + + int mtk_paris_pinctrl_probe(struct platform_device *pdev); +-- +2.39.5 + diff --git a/queue-6.6/powerpc-boot-check-for-ld-option-support.patch b/queue-6.6/powerpc-boot-check-for-ld-option-support.patch new file mode 100644 index 0000000000..9fba893d1d --- /dev/null +++ b/queue-6.6/powerpc-boot-check-for-ld-option-support.patch @@ -0,0 +1,53 @@ +From 207e357adf79777c665e3fbd65a45c077f84fe53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 06:12:18 +0530 +Subject: powerpc/boot: Check for ld-option support + +From: Madhavan Srinivasan + +[ Upstream commit b2accfe7ca5bc9f9af28e603b79bdd5ad8df5c0b ] + +Commit 579aee9fc594 ("powerpc: suppress some linker warnings in recent linker versions") +enabled support to add linker option "--no-warn-rwx-segments", +if the version is greater than 2.39. Similar build warning were +reported recently from linker version 2.35.2. + +ld: warning: arch/powerpc/boot/zImage.epapr has a LOAD segment with RWX permissions +ld: warning: arch/powerpc/boot/zImage.pseries has a LOAD segment with RWX permissions + +Fix the warning by checking for "--no-warn-rwx-segments" +option support in linker to enable it, instead of checking +for the version range. + +Fixes: 579aee9fc594 ("powerpc: suppress some linker warnings in recent linker versions") +Reported-by: Venkat Rao Bagalkote +Suggested-by: Christophe Leroy +Tested-by: Venkat Rao Bagalkote +Closes: https://lore.kernel.org/linuxppc-dev/61cf556c-4947-4bd6-af63-892fc0966dad@linux.ibm.com/ +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250401004218.24869-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/boot/wrapper | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper +index 352d7de24018f..fea9694f1047e 100755 +--- a/arch/powerpc/boot/wrapper ++++ b/arch/powerpc/boot/wrapper +@@ -234,10 +234,8 @@ fi + + # suppress some warnings in recent ld versions + nowarn="-z noexecstack" +-if ! ld_is_lld; then +- if [ "$LD_VERSION" -ge "$(echo 2.39 | ld_version)" ]; then +- nowarn="$nowarn --no-warn-rwx-segments" +- fi ++if [ $(${CROSS}ld -v --no-warn-rwx-segments &>/dev/null; echo $?) -eq 0 ]; then ++ nowarn="$nowarn --no-warn-rwx-segments" + fi + + platformo=$object/"$platform".o +-- +2.39.5 + diff --git a/queue-6.6/powerpc-boot-fix-dash-warning.patch b/queue-6.6/powerpc-boot-fix-dash-warning.patch new file mode 100644 index 0000000000..23d332a61c --- /dev/null +++ b/queue-6.6/powerpc-boot-fix-dash-warning.patch @@ -0,0 +1,53 @@ +From a25885f89fdcd98aae449934d4f5ce6b3fe1983c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 13:51:54 +0530 +Subject: powerpc/boot: Fix dash warning + +From: Madhavan Srinivasan + +[ Upstream commit e3f506b78d921e48a00d005bea5c45ec36a99240 ] + +'commit b2accfe7ca5b ("powerpc/boot: Check for ld-option support")' suppressed +linker warnings, but the expressed used did not go well with POSIX shell (dash) +resulting with this warning + +arch/powerpc/boot/wrapper: 237: [: 0: unexpected operator +ld: warning: arch/powerpc/boot/zImage.epapr has a LOAD segment with RWX permissions + +Fix the check to handle the reported warning. Patch also fixes +couple of shellcheck reported errors for the same line. + +In arch/powerpc/boot/wrapper line 237: +if [ $(${CROSS}ld -v --no-warn-rwx-segments &>/dev/null; echo $?) -eq 0 ]; then + ^-- SC2046 (warning): Quote this to prevent word splitting. + ^------^ SC2086 (info): Double quote to prevent globbing and word splitting. + ^---------^ SC3020 (warning): In POSIX sh, &> is undefined. + +Fixes: b2accfe7ca5b ("powerpc/boot: Check for ld-option support") +Reported-by: Stephen Rothwell +Suggested-by: Stephen Rothwell +Tested-by: Venkat Rao Bagalkote +Reviewed-by: Stephen Rothwell +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250423082154.30625-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/boot/wrapper | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper +index fea9694f1047e..ddb02cf0caaf5 100755 +--- a/arch/powerpc/boot/wrapper ++++ b/arch/powerpc/boot/wrapper +@@ -234,7 +234,7 @@ fi + + # suppress some warnings in recent ld versions + nowarn="-z noexecstack" +-if [ $(${CROSS}ld -v --no-warn-rwx-segments &>/dev/null; echo $?) -eq 0 ]; then ++if "${CROSS}ld" -v --no-warn-rwx-segments >/dev/null 2>&1; then + nowarn="$nowarn --no-warn-rwx-segments" + fi + +-- +2.39.5 + diff --git a/queue-6.6/series b/queue-6.6/series index 86622cd627..6e1079e535 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -44,3 +44,58 @@ revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch iommu-handle-race-with-default-domain-setup.patch +asoc-soc-pcm-fix-hw_params-and-dapm-widget-sequence.patch +book3s64-radix-align-section-vmemmap-start-address-t.patch +pinctrl-imx-use-temporary-variable-to-hold-pins.patch +pinctrl-core-add-a-convenient-define-pinctrl_group_d.patch +pinctrl-mediatek-use-c99-initializers-in-pinctrl_pin.patch +pinctrl-core-embed-struct-pingroup-into-struct-group.patch +pinctrl-imx-convert-to-use-grp-member.patch +pinctrl-imx-return-null-if-no-group-is-matched-and-f.patch +powerpc-boot-check-for-ld-option-support.patch +drm-i915-pxp-fix-undefined-reference-to-intel_pxp_gs.patch +wifi-plfxlc-remove-erroneous-assert-in-plfxlc_mac_re.patch +powerpc-boot-fix-dash-warning.patch +vxlan-vnifilter-fix-unlocked-deletion-of-default-fdb.patch +net-mlx5-e-switch-initialize-mac-address-for-default.patch +net-mlx5-e-switch-fix-error-handling-for-enabling-ro.patch +bluetooth-btusb-avoid-null-pointer-dereference-in-sk.patch +net-rename-mono_delivery_time-to-tstamp_type-for-sca.patch +bluetooth-l2cap-copy-rx-timestamp-to-new-fragments.patch +net-mscc-ocelot-treat-802.1ad-tagged-traffic-as-802..patch +net-mscc-ocelot-delete-pvid-vlan-when-readding-it-as.patch +net-ethernet-mtk-star-emac-fix-spinlock-recursion-is.patch +net-ethernet-mtk-star-emac-rearm-interrupts-in-rx_po.patch +pds_core-check-health-in-devcmd-wait.patch +pds_core-delete-vf-dev-on-reset.patch +pds_core-make-pdsc_auxbus_dev_del-void.patch +pds_core-specify-auxiliary_device-to-be-created.patch +pds_core-remove-write-after-free-of-client_id.patch +net_sched-drr-fix-double-list-add-in-class-with-nete.patch +net_sched-hfsc-fix-a-uaf-vulnerability-in-class-with.patch +net_sched-ets-fix-double-list-add-in-class-with-nete.patch +net_sched-qfq-fix-double-list-add-in-class-with-nete.patch +ice-check-vf-vsi-pointer-value-in-ice_vc_add_fdir_fl.patch +alsa-ump-fix-buffer-overflow-at-ump-sysex-message-co.patch +nvme-pci-fix-queue-unquiesce-check-on-slot_reset.patch +net-dlink-correct-endianness-handling-of-led_mode.patch +net-mdio-mux-meson-gxl-set-reversed-bit-when-using-i.patch +igc-fix-lock-order-in-igc_ptp_reset.patch +net-ethernet-mtk_eth_soc-fix-ser-panic-with-4gb-ram.patch +net-dsa-felix-fix-broken-taprio-gate-states-after-cl.patch +net-ipv6-fix-udpv6-gso-segmentation-with-nat.patch +bnxt_en-fix-coredump-logic-to-free-allocated-buffer.patch +bnxt_en-fix-out-of-bound-memcpy-during-ethtool-w.patch +bnxt_en-fix-ethtool-d-byte-order-for-32-bit-values.patch +nvme-tcp-fix-premature-queue-removal-and-i-o-failove.patch +net-lan743x-fix-memleak-issue-when-gso-enabled.patch +net-fec-err007885-workaround-for-conventional-tx.patch +octeon_ep-fix-host-hang-issue-during-device-reboot.patch +net-hns3-store-rx-vlan-tag-offload-state-for-vf.patch +net-hns3-fix-an-interrupt-residual-problem.patch +net-hns3-fixed-debugfs-tm_qset-size.patch +net-hns3-defer-calling-ptp_clock_register.patch +net-vertexcom-mse102x-fix-possible-stuck-of-spi-inte.patch +net-vertexcom-mse102x-fix-len_mask.patch +net-vertexcom-mse102x-add-range-check-for-cmd_rts.patch +net-vertexcom-mse102x-fix-rx-error-handling.patch diff --git a/queue-6.6/vxlan-vnifilter-fix-unlocked-deletion-of-default-fdb.patch b/queue-6.6/vxlan-vnifilter-fix-unlocked-deletion-of-default-fdb.patch new file mode 100644 index 0000000000..aab69c789d --- /dev/null +++ b/queue-6.6/vxlan-vnifilter-fix-unlocked-deletion-of-default-fdb.patch @@ -0,0 +1,87 @@ +From b4bde1f733095814062b5d89098f0c6ef14a422b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Apr 2025 17:51:31 +0300 +Subject: vxlan: vnifilter: Fix unlocked deletion of default FDB entry + +From: Ido Schimmel + +[ Upstream commit 087a9eb9e5978e3ba362e1163691e41097e8ca20 ] + +When a VNI is deleted from a VXLAN device in 'vnifilter' mode, the FDB +entry associated with the default remote (assuming one was configured) +is deleted without holding the hash lock. This is wrong and will result +in a warning [1] being generated by the lockdep annotation that was +added by commit ebe642067455 ("vxlan: Create wrappers for FDB lookup"). + +Reproducer: + + # ip link add vx0 up type vxlan dstport 4789 external vnifilter local 192.0.2.1 + # bridge vni add vni 10010 remote 198.51.100.1 dev vx0 + # bridge vni del vni 10010 dev vx0 + +Fix by acquiring the hash lock before the deletion and releasing it +afterwards. Blame the original commit that introduced the issue rather +than the one that exposed it. + +[1] +WARNING: CPU: 3 PID: 392 at drivers/net/vxlan/vxlan_core.c:417 vxlan_find_mac+0x17f/0x1a0 +[...] +RIP: 0010:vxlan_find_mac+0x17f/0x1a0 +[...] +Call Trace: + + __vxlan_fdb_delete+0xbe/0x560 + vxlan_vni_delete_group+0x2ba/0x940 + vxlan_vni_del.isra.0+0x15f/0x580 + vxlan_process_vni_filter+0x38b/0x7b0 + vxlan_vnifilter_process+0x3bb/0x510 + rtnetlink_rcv_msg+0x2f7/0xb70 + netlink_rcv_skb+0x131/0x360 + netlink_unicast+0x426/0x710 + netlink_sendmsg+0x75a/0xc20 + __sock_sendmsg+0xc1/0x150 + ____sys_sendmsg+0x5aa/0x7b0 + ___sys_sendmsg+0xfc/0x180 + __sys_sendmsg+0x121/0x1b0 + do_syscall_64+0xbb/0x1d0 + entry_SYSCALL_64_after_hwframe+0x4b/0x53 + +Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device") +Signed-off-by: Ido Schimmel +Reviewed-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250423145131.513029-1-idosch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vxlan/vxlan_vnifilter.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c +index 6e6e9f05509ab..06d19e90eadb5 100644 +--- a/drivers/net/vxlan/vxlan_vnifilter.c ++++ b/drivers/net/vxlan/vxlan_vnifilter.c +@@ -627,7 +627,11 @@ static void vxlan_vni_delete_group(struct vxlan_dev *vxlan, + * default dst remote_ip previously added for this vni + */ + if (!vxlan_addr_any(&vninode->remote_ip) || +- !vxlan_addr_any(&dst->remote_ip)) ++ !vxlan_addr_any(&dst->remote_ip)) { ++ u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, ++ vninode->vni); ++ ++ spin_lock_bh(&vxlan->hash_lock[hash_index]); + __vxlan_fdb_delete(vxlan, all_zeros_mac, + (vxlan_addr_any(&vninode->remote_ip) ? + dst->remote_ip : vninode->remote_ip), +@@ -635,6 +639,8 @@ static void vxlan_vni_delete_group(struct vxlan_dev *vxlan, + vninode->vni, vninode->vni, + dst->remote_ifindex, + true); ++ spin_unlock_bh(&vxlan->hash_lock[hash_index]); ++ } + + if (vxlan->dev->flags & IFF_UP) { + if (vxlan_addr_multicast(&vninode->remote_ip) && +-- +2.39.5 + diff --git a/queue-6.6/wifi-plfxlc-remove-erroneous-assert-in-plfxlc_mac_re.patch b/queue-6.6/wifi-plfxlc-remove-erroneous-assert-in-plfxlc_mac_re.patch new file mode 100644 index 0000000000..c73129697e --- /dev/null +++ b/queue-6.6/wifi-plfxlc-remove-erroneous-assert-in-plfxlc_mac_re.patch @@ -0,0 +1,89 @@ +From 28571eb2072b636fece4cdf3b024985ad185f578 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 21:52:25 +0300 +Subject: wifi: plfxlc: Remove erroneous assert in plfxlc_mac_release + +From: Murad Masimov + +[ Upstream commit 0fb15ae3b0a9221be01715dac0335647c79f3362 ] + +plfxlc_mac_release() asserts that mac->lock is held. This assertion is +incorrect, because even if it was possible, it would not be the valid +behaviour. The function is used when probe fails or after the device is +disconnected. In both cases mac->lock can not be held as the driver is +not working with the device at the moment. All functions that use mac->lock +unlock it just after it was held. There is also no need to hold mac->lock +for plfxlc_mac_release() itself, as mac data is not affected, except for +mac->flags, which is modified atomically. + +This bug leads to the following warning: +================================================================ +WARNING: CPU: 0 PID: 127 at drivers/net/wireless/purelifi/plfxlc/mac.c:106 plfxlc_mac_release+0x7d/0xa0 +Modules linked in: +CPU: 0 PID: 127 Comm: kworker/0:2 Not tainted 6.1.124-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 +Workqueue: usb_hub_wq hub_event +RIP: 0010:plfxlc_mac_release+0x7d/0xa0 drivers/net/wireless/purelifi/plfxlc/mac.c:106 +Call Trace: + + probe+0x941/0xbd0 drivers/net/wireless/purelifi/plfxlc/usb.c:694 + usb_probe_interface+0x5c0/0xaf0 drivers/usb/core/driver.c:396 + really_probe+0x2ab/0xcb0 drivers/base/dd.c:639 + __driver_probe_device+0x1a2/0x3d0 drivers/base/dd.c:785 + driver_probe_device+0x50/0x420 drivers/base/dd.c:815 + __device_attach_driver+0x2cf/0x510 drivers/base/dd.c:943 + bus_for_each_drv+0x183/0x200 drivers/base/bus.c:429 + __device_attach+0x359/0x570 drivers/base/dd.c:1015 + bus_probe_device+0xba/0x1e0 drivers/base/bus.c:489 + device_add+0xb48/0xfd0 drivers/base/core.c:3696 + usb_set_configuration+0x19dd/0x2020 drivers/usb/core/message.c:2165 + usb_generic_driver_probe+0x84/0x140 drivers/usb/core/generic.c:238 + usb_probe_device+0x130/0x260 drivers/usb/core/driver.c:293 + really_probe+0x2ab/0xcb0 drivers/base/dd.c:639 + __driver_probe_device+0x1a2/0x3d0 drivers/base/dd.c:785 + driver_probe_device+0x50/0x420 drivers/base/dd.c:815 + __device_attach_driver+0x2cf/0x510 drivers/base/dd.c:943 + bus_for_each_drv+0x183/0x200 drivers/base/bus.c:429 + __device_attach+0x359/0x570 drivers/base/dd.c:1015 + bus_probe_device+0xba/0x1e0 drivers/base/bus.c:489 + device_add+0xb48/0xfd0 drivers/base/core.c:3696 + usb_new_device+0xbdd/0x18f0 drivers/usb/core/hub.c:2620 + hub_port_connect drivers/usb/core/hub.c:5477 [inline] + hub_port_connect_change drivers/usb/core/hub.c:5617 [inline] + port_event drivers/usb/core/hub.c:5773 [inline] + hub_event+0x2efe/0x5730 drivers/usb/core/hub.c:5855 + process_one_work+0x8a9/0x11d0 kernel/workqueue.c:2292 + worker_thread+0xa47/0x1200 kernel/workqueue.c:2439 + kthread+0x28d/0x320 kernel/kthread.c:376 + ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295 + +================================================================ + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 68d57a07bfe5 ("wireless: add plfxlc driver for pureLiFi X, XL, XC devices") +Reported-by: syzbot+7d4f142f6c288de8abfe@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=7d4f142f6c288de8abfe +Signed-off-by: Murad Masimov +Link: https://patch.msgid.link/20250321185226.71-2-m.masimov@mt-integration.ru +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/purelifi/plfxlc/mac.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/wireless/purelifi/plfxlc/mac.c b/drivers/net/wireless/purelifi/plfxlc/mac.c +index 506d2f31efb5a..7ebc0df0944cb 100644 +--- a/drivers/net/wireless/purelifi/plfxlc/mac.c ++++ b/drivers/net/wireless/purelifi/plfxlc/mac.c +@@ -103,7 +103,6 @@ int plfxlc_mac_init_hw(struct ieee80211_hw *hw) + void plfxlc_mac_release(struct plfxlc_mac *mac) + { + plfxlc_chip_release(&mac->chip); +- lockdep_assert_held(&mac->lock); + } + + int plfxlc_op_start(struct ieee80211_hw *hw) +-- +2.39.5 +