]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Tue, 6 May 2025 11:50:06 +0000 (07:50 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 6 May 2025 11:50:06 +0000 (07:50 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
56 files changed:
queue-6.6/alsa-ump-fix-buffer-overflow-at-ump-sysex-message-co.patch [new file with mode: 0644]
queue-6.6/asoc-soc-pcm-fix-hw_params-and-dapm-widget-sequence.patch [new file with mode: 0644]
queue-6.6/bluetooth-btusb-avoid-null-pointer-dereference-in-sk.patch [new file with mode: 0644]
queue-6.6/bluetooth-l2cap-copy-rx-timestamp-to-new-fragments.patch [new file with mode: 0644]
queue-6.6/bnxt_en-fix-coredump-logic-to-free-allocated-buffer.patch [new file with mode: 0644]
queue-6.6/bnxt_en-fix-ethtool-d-byte-order-for-32-bit-values.patch [new file with mode: 0644]
queue-6.6/bnxt_en-fix-out-of-bound-memcpy-during-ethtool-w.patch [new file with mode: 0644]
queue-6.6/book3s64-radix-align-section-vmemmap-start-address-t.patch [new file with mode: 0644]
queue-6.6/drm-i915-pxp-fix-undefined-reference-to-intel_pxp_gs.patch [new file with mode: 0644]
queue-6.6/ice-check-vf-vsi-pointer-value-in-ice_vc_add_fdir_fl.patch [new file with mode: 0644]
queue-6.6/igc-fix-lock-order-in-igc_ptp_reset.patch [new file with mode: 0644]
queue-6.6/net-dlink-correct-endianness-handling-of-led_mode.patch [new file with mode: 0644]
queue-6.6/net-dsa-felix-fix-broken-taprio-gate-states-after-cl.patch [new file with mode: 0644]
queue-6.6/net-ethernet-mtk-star-emac-fix-spinlock-recursion-is.patch [new file with mode: 0644]
queue-6.6/net-ethernet-mtk-star-emac-rearm-interrupts-in-rx_po.patch [new file with mode: 0644]
queue-6.6/net-ethernet-mtk_eth_soc-fix-ser-panic-with-4gb-ram.patch [new file with mode: 0644]
queue-6.6/net-fec-err007885-workaround-for-conventional-tx.patch [new file with mode: 0644]
queue-6.6/net-hns3-defer-calling-ptp_clock_register.patch [new file with mode: 0644]
queue-6.6/net-hns3-fix-an-interrupt-residual-problem.patch [new file with mode: 0644]
queue-6.6/net-hns3-fixed-debugfs-tm_qset-size.patch [new file with mode: 0644]
queue-6.6/net-hns3-store-rx-vlan-tag-offload-state-for-vf.patch [new file with mode: 0644]
queue-6.6/net-ipv6-fix-udpv6-gso-segmentation-with-nat.patch [new file with mode: 0644]
queue-6.6/net-lan743x-fix-memleak-issue-when-gso-enabled.patch [new file with mode: 0644]
queue-6.6/net-mdio-mux-meson-gxl-set-reversed-bit-when-using-i.patch [new file with mode: 0644]
queue-6.6/net-mlx5-e-switch-fix-error-handling-for-enabling-ro.patch [new file with mode: 0644]
queue-6.6/net-mlx5-e-switch-initialize-mac-address-for-default.patch [new file with mode: 0644]
queue-6.6/net-mscc-ocelot-delete-pvid-vlan-when-readding-it-as.patch [new file with mode: 0644]
queue-6.6/net-mscc-ocelot-treat-802.1ad-tagged-traffic-as-802..patch [new file with mode: 0644]
queue-6.6/net-rename-mono_delivery_time-to-tstamp_type-for-sca.patch [new file with mode: 0644]
queue-6.6/net-vertexcom-mse102x-add-range-check-for-cmd_rts.patch [new file with mode: 0644]
queue-6.6/net-vertexcom-mse102x-fix-len_mask.patch [new file with mode: 0644]
queue-6.6/net-vertexcom-mse102x-fix-possible-stuck-of-spi-inte.patch [new file with mode: 0644]
queue-6.6/net-vertexcom-mse102x-fix-rx-error-handling.patch [new file with mode: 0644]
queue-6.6/net_sched-drr-fix-double-list-add-in-class-with-nete.patch [new file with mode: 0644]
queue-6.6/net_sched-ets-fix-double-list-add-in-class-with-nete.patch [new file with mode: 0644]
queue-6.6/net_sched-hfsc-fix-a-uaf-vulnerability-in-class-with.patch [new file with mode: 0644]
queue-6.6/net_sched-qfq-fix-double-list-add-in-class-with-nete.patch [new file with mode: 0644]
queue-6.6/nvme-pci-fix-queue-unquiesce-check-on-slot_reset.patch [new file with mode: 0644]
queue-6.6/nvme-tcp-fix-premature-queue-removal-and-i-o-failove.patch [new file with mode: 0644]
queue-6.6/octeon_ep-fix-host-hang-issue-during-device-reboot.patch [new file with mode: 0644]
queue-6.6/pds_core-check-health-in-devcmd-wait.patch [new file with mode: 0644]
queue-6.6/pds_core-delete-vf-dev-on-reset.patch [new file with mode: 0644]
queue-6.6/pds_core-make-pdsc_auxbus_dev_del-void.patch [new file with mode: 0644]
queue-6.6/pds_core-remove-write-after-free-of-client_id.patch [new file with mode: 0644]
queue-6.6/pds_core-specify-auxiliary_device-to-be-created.patch [new file with mode: 0644]
queue-6.6/pinctrl-core-add-a-convenient-define-pinctrl_group_d.patch [new file with mode: 0644]
queue-6.6/pinctrl-core-embed-struct-pingroup-into-struct-group.patch [new file with mode: 0644]
queue-6.6/pinctrl-imx-convert-to-use-grp-member.patch [new file with mode: 0644]
queue-6.6/pinctrl-imx-return-null-if-no-group-is-matched-and-f.patch [new file with mode: 0644]
queue-6.6/pinctrl-imx-use-temporary-variable-to-hold-pins.patch [new file with mode: 0644]
queue-6.6/pinctrl-mediatek-use-c99-initializers-in-pinctrl_pin.patch [new file with mode: 0644]
queue-6.6/powerpc-boot-check-for-ld-option-support.patch [new file with mode: 0644]
queue-6.6/powerpc-boot-fix-dash-warning.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/vxlan-vnifilter-fix-unlocked-deletion-of-default-fdb.patch [new file with mode: 0644]
queue-6.6/wifi-plfxlc-remove-erroneous-assert-in-plfxlc_mac_re.patch [new file with mode: 0644]

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 (file)
index 0000000..14fa92e
--- /dev/null
@@ -0,0 +1,45 @@
+From a4ce9d143baab6cf9620e242d78a27f4e70c8451 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Apr 2025 14:48:41 +0200
+Subject: ALSA: ump: Fix buffer overflow at UMP SysEx message conversion
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ 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 <vr@darknavy.com>
+Link: https://patch.msgid.link/20250429124845.25128-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..eed9d49
--- /dev/null
@@ -0,0 +1,69 @@
+From 6c127747c88ba1fcf2c19155f2bfecac340d2271 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Apr 2025 10:59:53 +0000
+Subject: ASoC: soc-pcm: Fix hw_params() and DAPM widget sequence
+
+From: Sheetal <sheetal@nvidia.com>
+
+[ 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 <sheetal@nvidia.com>
+Link: https://patch.msgid.link/20250404105953.2784819-1-sheetal@nvidia.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..77ae09e
--- /dev/null
@@ -0,0 +1,197 @@
+From d740bb2365a57f1407957c0ba867de1890f1a08f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 21:00:37 +0800
+Subject: Bluetooth: btusb: avoid NULL pointer dereference in skb_dequeue()
+
+From: En-Wei Wu <en-wei.wu@canonical.com>
+
+[ 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 <en-wei.wu@canonical.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e59cf87
--- /dev/null
@@ -0,0 +1,37 @@
+From 10d09db3e272a4a0b019314937cefb7ad2d9ed09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Apr 2025 22:51:03 +0300
+Subject: Bluetooth: L2CAP: copy RX timestamp to new fragments
+
+From: Pauli Virtanen <pav@iki.fi>
+
+[ 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 <pav@iki.fi>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1ba2c0c
--- /dev/null
@@ -0,0 +1,48 @@
+From 3dddebae4118bd5a4862a3ea1e72528f8148077e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Apr 2025 15:59:01 -0700
+Subject: bnxt_en: Fix coredump logic to free allocated buffer
+
+From: Shruti Parab <shruti.parab@broadcom.com>
+
+[ 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 <michael.chan@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Shruti Parab <shruti.parab@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..44478cc
--- /dev/null
@@ -0,0 +1,85 @@
+From bcca305ca1df074be5be33dc8781e508398734c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Apr 2025 15:59:03 -0700
+Subject: bnxt_en: Fix ethtool -d byte order for 32-bit values
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ 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 <shruti.parab@broadcom.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..cfed034
--- /dev/null
@@ -0,0 +1,95 @@
+From a1eda14e00448a63000dc73d277e74fac72cffbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Apr 2025 15:59:02 -0700
+Subject: bnxt_en: Fix out-of-bound memcpy() during ethtool -w
+
+From: Shruti Parab <shruti.parab@broadcom.com>
+
+[ 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 <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Shruti Parab <shruti.parab@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..0eb48b7
--- /dev/null
@@ -0,0 +1,160 @@
+From b59ecf3dceac1d0732746cf413598fc53c594dd2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 07:44:10 -0500
+Subject: book3s64/radix : Align section vmemmap start address to PAGE_SIZE
+
+From: Donet Tom <donettom@linux.ibm.com>
+
+[ 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 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE>  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) <ritesh.list@gmail.com>
+Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Signed-off-by: Donet Tom <donettom@linux.ibm.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/8f98ec2b442977c618f7256cec88eb17dde3f2b9.1741609795.git.donettom@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c974188
--- /dev/null
@@ -0,0 +1,67 @@
+From 4ee4ad7d62a10a717fbb95ff7ebbbcd38de628e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <chenlinxuan@uniontech.com>
+
+[ 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 <chenlinxuan@uniontech.com>
+Fixes: 99afb7cc8c44 ("drm/i915/pxp: Add ARB session creation and cleanup")
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://lore.kernel.org/r/20250415090616.2649889-1-jani.nikula@intel.com
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+(cherry picked from commit b484c1e225a6a582fc78c4d7af7b286408bb7d41)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..8bf2f56
--- /dev/null
@@ -0,0 +1,44 @@
+From ca89e8e30c573dc96d94716a636b9a57be311d22 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <luoxuanqiang@kylinos.cn>
+
+[ 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 <luoxuanqiang@kylinos.cn>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Link: https://patch.msgid.link/20250425222636.3188441-3-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..3c56aca
--- /dev/null
@@ -0,0 +1,82 @@
+From 2cf879932a2cc164be7decc446c9e5e8651e3d7c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Apr 2025 14:03:09 -0700
+Subject: igc: fix lock order in igc_ptp_reset
+
+From: Jacob Keller <jacob.e.keller@intel.com>
+
+[ 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 <jacob.e.keller@intel.com>
+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 <przemyslaw.kitszel@intel.com>
+Reviewed-by: Vitaly Lifshits <vitaly.lifshits@intel.com>
+Tested-by: Mor Bar-Gabay <morx.bar.gabay@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e57d488
--- /dev/null
@@ -0,0 +1,80 @@
+From f49adc4b8100c4cd63e0f052fb9ee730cabdbc92 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 16:50:47 +0100
+Subject: net: dlink: Correct endianness handling of led_mode
+
+From: Simon Horman <horms@kernel.org>
+
+[ 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 <horms@kernel.org>
+Link: https://patch.msgid.link/20250425-dlink-led-mode-v1-1-6bae3c36e736@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..52dfe8f
--- /dev/null
@@ -0,0 +1,197 @@
+From 1e8e2d9682d76b9f82448cbd8890501cd928f9af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Apr 2025 17:48:55 +0300
+Subject: net: dsa: felix: fix broken taprio gate states after clock jump
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ 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 <richard.pearn@nxp.com>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://patch.msgid.link/20250426144859.3128352-2-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..caf1f30
--- /dev/null
@@ -0,0 +1,124 @@
+From 11f588c2dbd469d926aed789dfcc65bc3c968680 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <louisalexis.eyraud@collabora.com>
+
+[ 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 <louisalexis.eyraud@collabora.com>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Link: https://patch.msgid.link/20250424-mtk_star_emac-fix-spinlock-recursion-issue-v2-1-f3fde2e529d8@collabora.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b11399a
--- /dev/null
@@ -0,0 +1,43 @@
+From 764077684459b830424a2ae2757fd569bb1857d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <louisalexis.eyraud@collabora.com>
+
+[ 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 <louisalexis.eyraud@collabora.com>
+Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Link: https://patch.msgid.link/20250424-mtk_star_emac-fix-spinlock-recursion-issue-v2-2-f3fde2e529d8@collabora.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b499685
--- /dev/null
@@ -0,0 +1,57 @@
+From f9cbf2b286291ee80de429c4b208edcded8b4b23 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Apr 2025 02:05:44 +0100
+Subject: net: ethernet: mtk_eth_soc: fix SER panic with 4GB+ RAM
+
+From: Chad Monroe <chad@monroe.io>
+
+[ 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 <chad@monroe.io>
+Link: https://patch.msgid.link/4adc2aaeb0fb1b9cdc56bf21cf8e7fa328daa345.1745715843.git.daniel@makrotopia.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..a500607
--- /dev/null
@@ -0,0 +1,55 @@
+From 855be65606981544820be681f8b95b780015107f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Apr 2025 11:08:26 +0200
+Subject: net: fec: ERR007885 Workaround for conventional TX
+
+From: Mattias Barthel <mattias.barthel@atlascopco.com>
+
+[ 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 <mattias.barthel@atlascopco.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250429090826.3101258-1-mattiasbarthel@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..0db6bf8
--- /dev/null
@@ -0,0 +1,59 @@
+From ec3f4beeeff72cd14c7e0f81b2786e14c64ec519 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 17:30:52 +0800
+Subject: net: hns3: defer calling ptp_clock_register()
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ 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 <shenjian15@huawei.com>
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Link: https://patch.msgid.link/20250430093052.2400464-5-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..1a6e2cf
--- /dev/null
@@ -0,0 +1,192 @@
+From 5d8719d7acd189367046f27028086fb1ec1bcf45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 17:30:50 +0800
+Subject: net: hns3: fix an interrupt residual problem
+
+From: Yonglong Liu <liuyonglong@huawei.com>
+
+[ 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 <liuyonglong@huawei.com>
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Link: https://patch.msgid.link/20250430093052.2400464-3-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..d51d468
--- /dev/null
@@ -0,0 +1,40 @@
+From 5c3556072bcb7ef12387c19cc45ff6d7fed9ebe3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 17:30:51 +0800
+Subject: net: hns3: fixed debugfs tm_qset size
+
+From: Hao Lan <lanhao@huawei.com>
+
+[ 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 <lanhao@huawei.com>
+Signed-off-by: Peiyang Wang <wangpeiyang1@huawei.com>
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Link: https://patch.msgid.link/20250430093052.2400464-4-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1a9770c
--- /dev/null
@@ -0,0 +1,113 @@
+From 5267e61e50f59b7e38f43be28c45f90f26da5a79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 17:30:49 +0800
+Subject: net: hns3: store rx VLAN tag offload state for VF
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ 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 <shenjian15@huawei.com>
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250430093052.2400464-2-shaojijie@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..a692101
--- /dev/null
@@ -0,0 +1,104 @@
+From 90b1d241213ed10e179ca0b922880f91f34301de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Apr 2025 17:32:09 +0200
+Subject: net: ipv6: fix UDPv6 GSO segmentation with NAT
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ 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 <nbd@nbd.name>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20250426153210.14044-1-nbd@nbd.name
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..92364e4
--- /dev/null
@@ -0,0 +1,81 @@
+From 9559b2c5798cbf4da0fd34aa1ca506353111f80d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Apr 2025 10:55:27 +0530
+Subject: net: lan743x: Fix memleak issue when GSO enabled
+
+From: Thangaraj Samynathan <thangaraj.s@microchip.com>
+
+[ 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 <thangaraj.s@microchip.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20250429052527.10031-1-thangaraj.s@microchip.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d9a1a9e
--- /dev/null
@@ -0,0 +1,51 @@
+From 017db693d4544f1572ec5ff1fc3ac34f790d08b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <da@libre.computer>
+
+[ 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 <da@libre.computer>
+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 <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d028bbd
--- /dev/null
@@ -0,0 +1,110 @@
+From 5dbb82b8cdd384cff548083b4f95752d83ee4850 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 11:36:11 +0300
+Subject: net/mlx5: E-switch, Fix error handling for enabling roce
+
+From: Chris Mi <cmi@nvidia.com>
+
+[ 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 <cmi@nvidia.com>
+Reviewed-by: Roi Dayan <roid@nvidia.com>
+Reviewed-by: Maor Gottlieb <maorg@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Link: https://patch.msgid.link/20250423083611.324567-6-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..fdd3657
--- /dev/null
@@ -0,0 +1,48 @@
+From 33f05fe5c3574e7c70f39c32b4dafbf861c73d17 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 11:36:08 +0300
+Subject: net/mlx5: E-Switch, Initialize MAC Address for Default GID
+
+From: Maor Gottlieb <maorg@nvidia.com>
+
+[ 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 <maorg@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Link: https://patch.msgid.link/20250423083611.324567-3-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..7d23034
--- /dev/null
@@ -0,0 +1,72 @@
+From 776888059231e2724b8441381788acaec193544e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <vladimir.oltean@nxp.com>
+
+[ 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 <vladimir.oltean@nxp.com>
+Link: https://patch.msgid.link/20250424223734.3096202-1-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..71b9c58
--- /dev/null
@@ -0,0 +1,324 @@
+From 50109b6edcde73686d9f604c110af860fb0e26d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <vladimir.oltean@nxp.com>
+
+[ 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 <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 5ec6d7d737a4 ("net: mscc: ocelot: delete PVID VLAN when readding it as non-PVID")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c0ac78e
--- /dev/null
@@ -0,0 +1,569 @@
+From 58e669afbd2ced4d71a434c562beff27ca46d833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 May 2024 14:18:32 -0700
+Subject: net: Rename mono_delivery_time to tstamp_type for scalabilty
+
+From: Abhishek Chauhan <quic_abchauha@quicinc.com>
+
+[ 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 <quic_abchauha@quicinc.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Martin KaFai Lau <martin.lau@kernel.org>
+Link: https://lore.kernel.org/r/20240509211834.3235191-2-quic_abchauha@quicinc.com
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Stable-dep-of: 3908feb1bd7f ("Bluetooth: L2CAP: copy RX timestamp to new fragments")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <store> */
+               *insn++ = BPF_JMP_A(2);
+-              /* <clear>: mono_delivery_time */
++              /* <clear>: 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 (file)
index 0000000..cba01d0
--- /dev/null
@@ -0,0 +1,50 @@
+From ba128defaca58e649a630a35828dd47b08fb5f89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 15:30:42 +0200
+Subject: net: vertexcom: mse102x: Add range check for CMD_RTS
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ 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 <wahrenst@gmx.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250430133043.7722-4-wahrenst@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/if_vlan.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -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 (file)
index 0000000..f3fd16a
--- /dev/null
@@ -0,0 +1,38 @@
+From a0f032294dc7cc7bdd44ddc478678c453cdfc5e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 15:30:41 +0200
+Subject: net: vertexcom: mse102x: Fix LEN_MASK
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ 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 <wahrenst@gmx.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250430133043.7722-3-wahrenst@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..6791054
--- /dev/null
@@ -0,0 +1,53 @@
+From 12d2c41333b1a593488a43a3cd979c96d06cf5e9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 15:30:40 +0200
+Subject: net: vertexcom: mse102x: Fix possible stuck of SPI interrupt
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ 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 <wahrenst@gmx.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250430133043.7722-2-wahrenst@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..12adb40
--- /dev/null
@@ -0,0 +1,95 @@
+From 5dbf5b53ecc96f352af3ab7f5591cabf143f37c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Apr 2025 15:30:43 +0200
+Subject: net: vertexcom: mse102x: Fix RX error handling
+
+From: Stefan Wahren <wahrenst@gmx.net>
+
+[ 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 <wahrenst@gmx.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250430133043.7722-5-wahrenst@gmx.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c5731cb
--- /dev/null
@@ -0,0 +1,75 @@
+From 9a925af1d2e04b589a5265d1b173d195232ef667 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <victor@mojatatu.com>
+
+[ 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 <jhs@mojatatu.com>
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20250425220710.3964791-2-victor@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..cc8f263
--- /dev/null
@@ -0,0 +1,75 @@
+From b2e8d1af710687ca85d6a7148ae04c8ae04b9949 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <victor@mojatatu.com>
+
+[ 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 <jhs@mojatatu.com>
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20250425220710.3964791-4-victor@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..fd2d38e
--- /dev/null
@@ -0,0 +1,49 @@
+From dab87d27f963928ef7ac322bcc3baa69d973c552 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <victor@mojatatu.com>
+
+[ 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 <gerrard.tai@starlabs.sg>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20250425220710.3964791-3-victor@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..711ac0c
--- /dev/null
@@ -0,0 +1,77 @@
+From 5132749b535c241e6524eb1028f73f9ea2c9d4d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <victor@mojatatu.com>
+
+[ 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 <jhs@mojatatu.com>
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20250425220710.3964791-5-victor@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..cad71b9
--- /dev/null
@@ -0,0 +1,38 @@
+From 1bea08369f8e9f64db409b5f2c1748b97d859256 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Apr 2025 10:18:01 -0700
+Subject: nvme-pci: fix queue unquiesce check on slot_reset
+
+From: Keith Busch <kbusch@kernel.org>
+
+[ 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 <dhankaran@meta.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d8a31ca
--- /dev/null
@@ -0,0 +1,112 @@
+From bbb73599f4b6eddbe4f6ea8f2af63836328620fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <mliang@purestorage.com>
+
+[ 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 <mliang@purestorage.com>
+Reviewed-by: Mohamed Khalfella <mkhalfella@purestorage.com>
+Reviewed-by: Randy Jennings <randyj@purestorage.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c70d9c4
--- /dev/null
@@ -0,0 +1,47 @@
+From e6bcfca360b5983fb81056a69ccfadb1d3fb7dab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Apr 2025 04:46:24 -0700
+Subject: octeon_ep: Fix host hang issue during device reboot
+
+From: Sathesh B Edara <sedara@marvell.com>
+
+[ 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 <sedara@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250429114624.19104-1-sedara@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..a825d0c
--- /dev/null
@@ -0,0 +1,87 @@
+From 066f17ecaf15b7203d9a9753adc8afe242c5c199 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 15:31:57 -0700
+Subject: pds_core: check health in devcmd wait
+
+From: Shannon Nelson <shannon.nelson@amd.com>
+
+[ 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 <shannon.nelson@amd.com>
+Reviewed-by: Brett Creeley <brett.creeley@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..5bc216e
--- /dev/null
@@ -0,0 +1,104 @@
+From cb031f57ca75bbd69f4beb77e4b03a094bd9fdd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Feb 2024 14:29:51 -0800
+Subject: pds_core: delete VF dev on reset
+
+From: Shannon Nelson <shannon.nelson@amd.com>
+
+[ 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 <brett.creeley@amd.com>
+Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..97e20a7
--- /dev/null
@@ -0,0 +1,87 @@
+From 19d3aae256b3a415e4c98424c5672f2755e954dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Mar 2025 12:44:07 -0700
+Subject: pds_core: make pdsc_auxbus_dev_del() void
+
+From: Shannon Nelson <shannon.nelson@amd.com>
+
+[ 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 <leonro@nvidia.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d77de5c
--- /dev/null
@@ -0,0 +1,52 @@
+From cbf3359b15d0d22cb7c3715578c4b425425aedfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Apr 2025 13:38:57 -0700
+Subject: pds_core: remove write-after-free of client_id
+
+From: Shannon Nelson <shannon.nelson@amd.com>
+
+[ 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 <shannon.nelson@amd.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250425203857.71547-1-shannon.nelson@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..6aafb5a
--- /dev/null
@@ -0,0 +1,195 @@
+From 4504297b35fc2d727079a6e9da0243249bfd61d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Mar 2025 12:44:08 -0700
+Subject: pds_core: specify auxiliary_device to be created
+
+From: Shannon Nelson <shannon.nelson@amd.com>
+
+[ 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 <leonro@nvidia.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Stable-dep-of: dfd76010f8e8 ("pds_core: remove write-after-free of client_id")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..910bdca
--- /dev/null
@@ -0,0 +1,61 @@
+From a1d821fd433ed86125ce6fc67f58a4416044546b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Dec 2023 20:57:54 +0200
+Subject: pinctrl: core: Add a convenient define PINCTRL_GROUP_DESC()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 383da0c7f25428de5ad09dc2cfed7cd43c4fb6ba ]
+
+Add PINCTRL_GROUP_DESC() macro for inline use.
+
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20231211190321.307330-2-andriy.shevchenko@linux.intel.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..941c95f
--- /dev/null
@@ -0,0 +1,91 @@
+From 8b71dccff488d6d4939004007318c248c18b2030 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Dec 2023 20:57:57 +0200
+Subject: pinctrl: core: Embed struct pingroup into struct group_desc
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ 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 <geert+renesas@glider.be>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20231211190321.307330-5-andriy.shevchenko@linux.intel.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/pinctrl/pinctrl.h>
++
+ /**
+  * 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 (file)
index 0000000..902f99e
--- /dev/null
@@ -0,0 +1,125 @@
+From e6cfba815a3d278730952170acba316a86368c85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Dec 2023 20:58:00 +0200
+Subject: pinctrl: imx: Convert to use grp member
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ 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 <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20231211190321.307330-8-andriy.shevchenko@linux.intel.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 = <PIN_FUNC_ID CONFIG ...>,
+@@ -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 (file)
index 0000000..625e046
--- /dev/null
@@ -0,0 +1,50 @@
+From 05f0d2b7b49ff4006b4d218c02fdab185ec18380 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 11:16:00 +0800
+Subject: pinctrl: imx: Return NULL if no group is matched and found
+
+From: Hui Wang <hui.wang@canonical.com>
+
+[ 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 <hui.wang@canonical.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/20250327031600.99723-1-hui.wang@canonical.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..1a75264
--- /dev/null
@@ -0,0 +1,66 @@
+From b4342d35738d86e8ab37b28ac6789b54d875e2e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 18:06:28 +0200
+Subject: pinctrl: imx: Use temporary variable to hold pins
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ 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 <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20231129161459.1002323-6-andriy.shevchenko@linux.intel.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d79dbc6
--- /dev/null
@@ -0,0 +1,70 @@
+From 288b9c534a9089e765dbb919803fed4debb27e52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Dec 2023 20:57:55 +0200
+Subject: pinctrl: mediatek: Use C99 initializers in PINCTRL_PIN_GROUP()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit bb5eace1562fcef3c7ac9d0bd3e01af1187e46d0 ]
+
+For the better flexibility use C99 initializers in PINCTRL_PIN_GROUP().
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20231211190321.307330-3-andriy.shevchenko@linux.intel.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Stable-dep-of: e64c0ff0d5d8 ("pinctrl: imx: Return NULL if no group is matched and found")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..9fba893
--- /dev/null
@@ -0,0 +1,53 @@
+From 207e357adf79777c665e3fbd65a45c077f84fe53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Apr 2025 06:12:18 +0530
+Subject: powerpc/boot: Check for ld-option support
+
+From: Madhavan Srinivasan <maddy@linux.ibm.com>
+
+[ 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 <venkat88@linux.ibm.com>
+Suggested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
+Closes: https://lore.kernel.org/linuxppc-dev/61cf556c-4947-4bd6-af63-892fc0966dad@linux.ibm.com/
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250401004218.24869-1-maddy@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..23d332a
--- /dev/null
@@ -0,0 +1,53 @@
+From a25885f89fdcd98aae449934d4f5ce6b3fe1983c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 13:51:54 +0530
+Subject: powerpc/boot: Fix dash warning
+
+From: Madhavan Srinivasan <maddy@linux.ibm.com>
+
+[ 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 <sfr@canb.auug.org.au>
+Suggested-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
+Reviewed-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250423082154.30625-1-maddy@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+
index 86622cd627a08c93062cfcb7667237a0af7bb60e..6e1079e535390f517e848fcc1fab6107a3af6bc9 100644 (file)
@@ -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 (file)
index 0000000..aab69c7
--- /dev/null
@@ -0,0 +1,87 @@
+From b4bde1f733095814062b5d89098f0c6ef14a422b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Apr 2025 17:51:31 +0300
+Subject: vxlan: vnifilter: Fix unlocked deletion of default FDB entry
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ 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:
+ <TASK>
+ __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 <idosch@nvidia.com>
+Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20250423145131.513029-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c731296
--- /dev/null
@@ -0,0 +1,89 @@
+From 28571eb2072b636fece4cdf3b024985ad185f578 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 21:52:25 +0300
+Subject: wifi: plfxlc: Remove erroneous assert in plfxlc_mac_release
+
+From: Murad Masimov <m.masimov@mt-integration.ru>
+
+[ 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:
+ <TASK>
+ 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
+ </TASK>
+================================================================
+
+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 <m.masimov@mt-integration.ru>
+Link: https://patch.msgid.link/20250321185226.71-2-m.masimov@mt-integration.ru
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+