From: Sasha Levin Date: Fri, 14 Nov 2025 18:59:52 +0000 (-0500) Subject: Fixes for all trees X-Git-Tag: v6.6.117~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bf41f68c92dad3c93f1de5bd833bbd34121b13e8;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-5.10/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..bad8659c95 --- /dev/null +++ b/queue-5.10/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From e0c6d46992960e3fe5acd2c6db1320898ef1b322 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index d035bb927aec2..9486d66863264 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -52,6 +52,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -60,6 +65,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1051,41 +1058,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-5.10/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..7ce929c435 --- /dev/null +++ b/queue-5.10/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From f17e2d5982671cafa5e72003ca18c32e7f3a7681 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 32dc74115dcbc..d035bb927aec2 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -994,10 +994,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -1008,13 +1009,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1141,7 +1161,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1178,7 +1198,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-5.10/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..30606fd063 --- /dev/null +++ b/queue-5.10/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From e9bd6577e7120434851234063ac312ef29c057ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 7e698b0ac7bc7..32dc74115dcbc 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -317,6 +317,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-5.10/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..b267aca0e0 --- /dev/null +++ b/queue-5.10/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From c96eea07fa30e016339a73e309743b1f62092de4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index cf0a0b3eaf886..155eaaf0485a1 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4391,6 +4391,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4401,17 +4406,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-5.10/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-5.10/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..7605c2ddcd --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 3b40a4326c92c7f0324f8245aaf46a80b4a9b42e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index b6345996fc022..166623372d0f5 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -518,6 +518,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-5.10/hsr-fix-supervision-frame-sending-on-hsrv0.patch b/queue-5.10/hsr-fix-supervision-frame-sending-on-hsrv0.patch new file mode 100644 index 0000000000..1b244f22d1 --- /dev/null +++ b/queue-5.10/hsr-fix-supervision-frame-sending-on-hsrv0.patch @@ -0,0 +1,50 @@ +From fe87cde8c7ce6d7f18918d0d0a12182c4d576754 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:32 +0100 +Subject: hsr: Fix supervision frame sending on HSRv0 + +From: Felix Maurer + +[ Upstream commit 96a3a03abf3d8cc38cd9cb0d280235fbcf7c3f7f ] + +On HSRv0, no supervision frames were sent. The supervison frames were +generated successfully, but failed the check for a sufficiently long mac +header, i.e., at least sizeof(struct hsr_ethhdr), in hsr_fill_frame_info() +because the mac header only contained the ethernet header. + +Fix this by including the HSR header in the mac header when generating HSR +supervision frames. Note that the mac header now also includes the TLV +fields. This matches how we set the headers on rx and also the size of +struct hsrv0_ethhdr_sp. + +Reported-by: Hangbin Liu +Closes: https://lore.kernel.org/netdev/aMONxDXkzBZZRfE5@fedora/ +Fixes: 9cfb5e7f0ded ("net: hsr: fix hsr_init_sk() vs network/transport headers.") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Tested-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/4354114fea9a642fe71f49aeeb6c6159d1d61840.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 505eb58f7e081..5a54a18892080 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -296,6 +296,9 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + } + + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); ++ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); ++ skb_reset_mac_len(skb); ++ + set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + +-- +2.51.0 + diff --git a/queue-5.10/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-5.10/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..94376a84c0 --- /dev/null +++ b/queue-5.10/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From 384d08113c807c059e18246b77631262d91881be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 9905e65621004..dfe3e7b1fae51 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1525,6 +1525,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + skb = rxq->rx_skbuff[index]; +-- +2.51.0 + diff --git a/queue-5.10/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-5.10/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..c667dd9ddc --- /dev/null +++ b/queue-5.10/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From fe561f8ae901065fc596939078f159a85e891956 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index d15deb3281edb..d7a65a5c855e5 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -80,8 +80,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-5.10/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-5.10/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..8383c4eaed --- /dev/null +++ b/queue-5.10/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From 3d1d19114ad26f0dfa65137b88ed448785a37722 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index c25fb0cbde274..4f1ce1287cdae 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -587,18 +587,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-5.10/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-5.10/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..e5828a72b8 --- /dev/null +++ b/queue-5.10/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From d755938167a6ecc4d6039fc8fdffa3945877d191 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 4f1ce1287cdae..5c48a4872f35d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -588,11 +588,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -604,10 +606,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-5.10/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-5.10/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..8211fee433 --- /dev/null +++ b/queue-5.10/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From 4f72780ed17c95d0bbf5edf6535ce40184eec623 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index 99548b2a1bc83..892d4824d81d5 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -643,13 +643,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-5.10/net-smc-fix-mismatch-between-clc-header-and-proposal.patch b/queue-5.10/net-smc-fix-mismatch-between-clc-header-and-proposal.patch new file mode 100644 index 0000000000..d7f3ea69e2 --- /dev/null +++ b/queue-5.10/net-smc-fix-mismatch-between-clc-header-and-proposal.patch @@ -0,0 +1,55 @@ +From 224991e38a78418eb1dceea96ea5a4a8b43ac1f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 10:40:29 +0800 +Subject: net/smc: fix mismatch between CLC header and proposal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: D. Wythe + +[ Upstream commit ec33f2e5a2d0dbbfd71435209aee812fdc9369b8 ] + +The current CLC proposal message construction uses a mix of +`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether +to include optional extensions (IPv6 prefix extension for v1, and v2 +extension). This leads to a critical inconsistency: when +`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with +only link-local addresses, or when the local IP address and the outgoing +interface’s network address are not in the same subnet. + +As a result, the proposal message is assembled using the stale +`ini->smc_type_v1` value—causing the IPv6 prefix extension to be +included even though the header indicates v1 is not supported. +The peer then receives a malformed CLC proposal where the header type +does not match the payload, and immediately resets the connection. + +The fix ensures consistency between the CLC header flags and the actual +payload by synchronizing `ini->smc_type_v1` with `pclc_base->hdr.typev1` +when prefix setup fails. + +Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal") +Signed-off-by: D. Wythe +Reviewed-by: Alexandra Winter +Link: https://patch.msgid.link/20251107024029.88753-1-alibuda@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_clc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c +index 2aa69e29fa1d5..dca448c98c9de 100644 +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -529,6 +529,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) + return SMC_CLC_DECL_CNFERR; + } + pclc_base->hdr.typev1 = SMC_TYPE_N; ++ ini->smc_type_v1 = SMC_TYPE_N; + } else { + pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); + plen += sizeof(*pclc_prfx) + +-- +2.51.0 + diff --git a/queue-5.10/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-5.10/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..c77fab1f4a --- /dev/null +++ b/queue-5.10/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From ff87e1f0cbff855300fc4a36fe39f505635de971 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index ecdd9e83f2f49..243a1d6b349c7 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -172,9 +172,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -185,8 +186,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -220,7 +223,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -287,7 +290,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -379,7 +382,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -388,7 +391,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -406,7 +409,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + __netif_schedule(q); +-- +2.51.0 + diff --git a/queue-5.10/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-5.10/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..6fe72441dd --- /dev/null +++ b/queue-5.10/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From 64bf65b7ac8bfd167b281c532d3960dbdcebffe8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 9c721d70df9c6..9921041079781 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -337,6 +337,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -348,10 +349,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 1a1ddf827d..f6c0ec8420 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -175,3 +175,19 @@ risc-v-clear-hot-unplugged-cores-from-all-task-mm_cp.patch nfs4-fix-state-renewals-missing-after-boot.patch hid-quirks-avoid-cooler-master-mm712-dongle-wakeup-b.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +net-smc-fix-mismatch-between-clc-header-and-proposal.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +hsr-fix-supervision-frame-sending-on-hsrv0.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch diff --git a/queue-5.10/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-5.10/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..c38b074637 --- /dev/null +++ b/queue-5.10/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From 72f27d389b1b404163e4381629e1be685c7ba099 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 671cb4f9d5633..95aa3a97b53a8 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -141,7 +141,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-5.10/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-5.10/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..20d63cff93 --- /dev/null +++ b/queue-5.10/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From 0fd012e21ba0a2278925a92592e9590b3cad5e47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index b46c4c770608c..98f06563d184c 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4779,10 +4779,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-5.15/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..e67d4e1eec --- /dev/null +++ b/queue-5.15/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From 33ae781f65ebdcec7f33bc052b61846206ef6038 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index db3e2d5290966..b70d3a38fdedc 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -52,6 +52,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -60,6 +65,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1012,41 +1019,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-5.15/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..31eedb91f2 --- /dev/null +++ b/queue-5.15/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From 31a8112f3b92a85d991985e4e71f580b8705760d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index cfe3753a6f160..db3e2d5290966 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -955,10 +955,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -969,13 +970,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1102,7 +1122,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1139,7 +1159,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-5.15/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..ee28420bc2 --- /dev/null +++ b/queue-5.15/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From c3c926410a862887d31f8b914ce05b6ece70d3dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index c4a1b478cf3e9..cfe3753a6f160 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -288,6 +288,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-5.15/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..960e334ba6 --- /dev/null +++ b/queue-5.15/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From a101ca3d2bdd1b539cb8a39759837dc51ef30a05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 4a5b937f78d91..c8c638aa47262 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4126,6 +4126,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4136,17 +4141,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-5.15/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-5.15/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..97881119d0 --- /dev/null +++ b/queue-5.15/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 57877b557e6e8cc6b66e5d2e94c9d6039eb31b03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 1af639f1dd8d1..06be471ce0c04 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -518,6 +518,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-5.15/hsr-fix-supervision-frame-sending-on-hsrv0.patch b/queue-5.15/hsr-fix-supervision-frame-sending-on-hsrv0.patch new file mode 100644 index 0000000000..2f5115560a --- /dev/null +++ b/queue-5.15/hsr-fix-supervision-frame-sending-on-hsrv0.patch @@ -0,0 +1,50 @@ +From 1484479a502adc2bfb3935f72230aa94dbb11cf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:32 +0100 +Subject: hsr: Fix supervision frame sending on HSRv0 + +From: Felix Maurer + +[ Upstream commit 96a3a03abf3d8cc38cd9cb0d280235fbcf7c3f7f ] + +On HSRv0, no supervision frames were sent. The supervison frames were +generated successfully, but failed the check for a sufficiently long mac +header, i.e., at least sizeof(struct hsr_ethhdr), in hsr_fill_frame_info() +because the mac header only contained the ethernet header. + +Fix this by including the HSR header in the mac header when generating HSR +supervision frames. Note that the mac header now also includes the TLV +fields. This matches how we set the headers on rx and also the size of +struct hsrv0_ethhdr_sp. + +Reported-by: Hangbin Liu +Closes: https://lore.kernel.org/netdev/aMONxDXkzBZZRfE5@fedora/ +Fixes: 9cfb5e7f0ded ("net: hsr: fix hsr_init_sk() vs network/transport headers.") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Tested-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/4354114fea9a642fe71f49aeeb6c6159d1d61840.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 503f2064e7323..85537b245aaeb 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -316,6 +316,9 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + } + + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); ++ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); ++ skb_reset_mac_len(skb); ++ + set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + +-- +2.51.0 + diff --git a/queue-5.15/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-5.15/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..d44a3f5b53 --- /dev/null +++ b/queue-5.15/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From be344fdafe7134096abc3cc8c60748791c853cb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index d457af64f8357..263e3755f5c3a 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1566,6 +1566,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + skb = rxq->rx_skbuff[index]; +-- +2.51.0 + diff --git a/queue-5.15/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-5.15/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..36967110ab --- /dev/null +++ b/queue-5.15/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From 21d0d2d6349d33e77147829e1f28547000e0b50b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 95536c5e541da..a8a4cd68f6886 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -80,8 +80,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-5.15/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-5.15/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..217e62ae6e --- /dev/null +++ b/queue-5.15/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From fcfc5b8ffd1e1b4a6f2bf528f892a7f86dadb834 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index f2862100d1a2e..51fadfcda35a5 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -587,18 +587,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-5.15/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-5.15/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..b6cc9ad69d --- /dev/null +++ b/queue-5.15/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From 9bf844322946c5e711bdc07e6221e71f399e102a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 51fadfcda35a5..86545554abb4e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -588,11 +588,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -604,10 +606,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-5.15/net-sched-act-move-global-static-variable-net_id-to-.patch b/queue-5.15/net-sched-act-move-global-static-variable-net_id-to-.patch new file mode 100644 index 0000000000..cae3cfb884 --- /dev/null +++ b/queue-5.15/net-sched-act-move-global-static-variable-net_id-to-.patch @@ -0,0 +1,1374 @@ +From 1cae21faf8f608694e9c8b9d05869baa4d755a0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 12:14:33 +0800 +Subject: net: sched: act: move global static variable net_id to tc_action_ops + +From: Zhengchao Shao + +[ Upstream commit acd0a7ab6334f35c3720120d53f79eb8e9b3ac2e ] + +Each tc action module has a corresponding net_id, so put net_id directly +into the structure tc_action_ops. + +Signed-off-by: Zhengchao Shao +Acked-by: Jamal Hadi Salim +Signed-off-by: David S. Miller +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/act_api.h | 1 + + net/sched/act_bpf.c | 13 ++++++------- + net/sched/act_connmark.c | 13 ++++++------- + net/sched/act_csum.c | 13 ++++++------- + net/sched/act_ct.c | 17 ++++++++--------- + net/sched/act_ctinfo.c | 13 ++++++------- + net/sched/act_gact.c | 13 ++++++------- + net/sched/act_gate.c | 13 ++++++------- + net/sched/act_ife.c | 13 ++++++------- + net/sched/act_ipt.c | 31 ++++++++++++++----------------- + net/sched/act_mirred.c | 13 ++++++------- + net/sched/act_mpls.c | 13 ++++++------- + net/sched/act_nat.c | 13 ++++++------- + net/sched/act_pedit.c | 13 ++++++------- + net/sched/act_police.c | 13 ++++++------- + net/sched/act_sample.c | 13 ++++++------- + net/sched/act_simple.c | 13 ++++++------- + net/sched/act_skbedit.c | 13 ++++++------- + net/sched/act_skbmod.c | 13 ++++++------- + net/sched/act_tunnel_key.c | 13 ++++++------- + net/sched/act_vlan.c | 13 ++++++------- + 21 files changed, 131 insertions(+), 152 deletions(-) + +diff --git a/include/net/act_api.h b/include/net/act_api.h +index f19f7f4a463cd..5cd184ae91cc6 100644 +--- a/include/net/act_api.h ++++ b/include/net/act_api.h +@@ -99,6 +99,7 @@ struct tc_action_ops { + struct list_head head; + char kind[IFNAMSIZ]; + enum tca_id id; /* identifier should match kind */ ++ unsigned int net_id; + size_t size; + struct module *owner; + int (*act)(struct sk_buff *, const struct tc_action *, +diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c +index 2a05bad56ef3e..5576eb97d39e0 100644 +--- a/net/sched/act_bpf.c ++++ b/net/sched/act_bpf.c +@@ -29,7 +29,6 @@ struct tcf_bpf_cfg { + bool is_ebpf; + }; + +-static unsigned int bpf_net_id; + static struct tc_action_ops act_bpf_ops; + + static int tcf_bpf_act(struct sk_buff *skb, const struct tc_action *act, +@@ -278,7 +277,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, bpf_net_id); ++ struct tc_action_net *tn = net_generic(net, act_bpf_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -393,14 +392,14 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, bpf_net_id); ++ struct tc_action_net *tn = net_generic(net, act_bpf_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, bpf_net_id); ++ struct tc_action_net *tn = net_generic(net, act_bpf_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -420,20 +419,20 @@ static struct tc_action_ops act_bpf_ops __read_mostly = { + + static __net_init int bpf_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, bpf_net_id); ++ struct tc_action_net *tn = net_generic(net, act_bpf_ops.net_id); + + return tc_action_net_init(net, tn, &act_bpf_ops); + } + + static void __net_exit bpf_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, bpf_net_id); ++ tc_action_net_exit(net_list, act_bpf_ops.net_id); + } + + static struct pernet_operations bpf_net_ops = { + .init = bpf_init_net, + .exit_batch = bpf_exit_net, +- .id = &bpf_net_id, ++ .id = &act_bpf_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 0deb4e96a6c2e..16b3d56ef2f43 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -25,7 +25,6 @@ + #include + #include + +-static unsigned int connmark_net_id; + static struct tc_action_ops act_connmark_ops; + + static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, +@@ -99,7 +98,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, connmark_net_id); ++ struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); + struct nlattr *tb[TCA_CONNMARK_MAX + 1]; + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct tcf_chain *goto_ch = NULL; +@@ -205,14 +204,14 @@ static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, connmark_net_id); ++ struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, connmark_net_id); ++ struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -231,20 +230,20 @@ static struct tc_action_ops act_connmark_ops = { + + static __net_init int connmark_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, connmark_net_id); ++ struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); + + return tc_action_net_init(net, tn, &act_connmark_ops); + } + + static void __net_exit connmark_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, connmark_net_id); ++ tc_action_net_exit(net_list, act_connmark_ops.net_id); + } + + static struct pernet_operations connmark_net_ops = { + .init = connmark_init_net, + .exit_batch = connmark_exit_net, +- .id = &connmark_net_id, ++ .id = &act_connmark_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c +index a15ec95e69c36..2f2fb0f7cc714 100644 +--- a/net/sched/act_csum.c ++++ b/net/sched/act_csum.c +@@ -37,7 +37,6 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { + [TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), }, + }; + +-static unsigned int csum_net_id; + static struct tc_action_ops act_csum_ops; + + static int tcf_csum_init(struct net *net, struct nlattr *nla, +@@ -45,7 +44,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, csum_net_id); ++ struct tc_action_net *tn = net_generic(net, act_csum_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct tcf_csum_params *params_new; + struct nlattr *tb[TCA_CSUM_MAX + 1]; +@@ -678,14 +677,14 @@ static int tcf_csum_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, csum_net_id); ++ struct tc_action_net *tn = net_generic(net, act_csum_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, csum_net_id); ++ struct tc_action_net *tn = net_generic(net, act_csum_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -711,20 +710,20 @@ static struct tc_action_ops act_csum_ops = { + + static __net_init int csum_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, csum_net_id); ++ struct tc_action_net *tn = net_generic(net, act_csum_ops.net_id); + + return tc_action_net_init(net, tn, &act_csum_ops); + } + + static void __net_exit csum_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, csum_net_id); ++ tc_action_net_exit(net_list, act_csum_ops.net_id); + } + + static struct pernet_operations csum_net_ops = { + .init = csum_init_net, + .exit_batch = csum_exit_net, +- .id = &csum_net_id, ++ .id = &act_csum_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c +index a6c3b7145a105..d50977ef83c67 100644 +--- a/net/sched/act_ct.c ++++ b/net/sched/act_ct.c +@@ -574,7 +574,6 @@ static void tcf_ct_flow_tables_uninit(void) + } + + static struct tc_action_ops act_ct_ops; +-static unsigned int ct_net_id; + + struct tc_ct_action_net { + struct tc_action_net tn; /* Must be first */ +@@ -1184,7 +1183,7 @@ static int tcf_ct_fill_params(struct net *net, + struct nlattr **tb, + struct netlink_ext_ack *extack) + { +- struct tc_ct_action_net *tn = net_generic(net, ct_net_id); ++ struct tc_ct_action_net *tn = net_generic(net, act_ct_ops.net_id); + struct nf_conntrack_zone zone; + struct nf_conn *tmpl; + int err; +@@ -1259,7 +1258,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ct_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ct_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct tcf_ct_params *params = NULL; + struct nlattr *tb[TCA_CT_MAX + 1]; +@@ -1495,14 +1494,14 @@ static int tcf_ct_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ct_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ct_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_ct_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, ct_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ct_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -1533,7 +1532,7 @@ static struct tc_action_ops act_ct_ops = { + static __net_init int ct_init_net(struct net *net) + { + unsigned int n_bits = sizeof_field(struct tcf_ct_params, labels) * 8; +- struct tc_ct_action_net *tn = net_generic(net, ct_net_id); ++ struct tc_ct_action_net *tn = net_generic(net, act_ct_ops.net_id); + + if (nf_connlabels_get(net, n_bits - 1)) { + tn->labels = false; +@@ -1551,20 +1550,20 @@ static void __net_exit ct_exit_net(struct list_head *net_list) + + rtnl_lock(); + list_for_each_entry(net, net_list, exit_list) { +- struct tc_ct_action_net *tn = net_generic(net, ct_net_id); ++ struct tc_ct_action_net *tn = net_generic(net, act_ct_ops.net_id); + + if (tn->labels) + nf_connlabels_put(net); + } + rtnl_unlock(); + +- tc_action_net_exit(net_list, ct_net_id); ++ tc_action_net_exit(net_list, act_ct_ops.net_id); + } + + static struct pernet_operations ct_net_ops = { + .init = ct_init_net, + .exit_batch = ct_exit_net, +- .id = &ct_net_id, ++ .id = &act_ct_ops.net_id, + .size = sizeof(struct tc_ct_action_net), + }; + +diff --git a/net/sched/act_ctinfo.c b/net/sched/act_ctinfo.c +index ddacd4fa442c6..dd6347c4d4eb2 100644 +--- a/net/sched/act_ctinfo.c ++++ b/net/sched/act_ctinfo.c +@@ -25,7 +25,6 @@ + #include + + static struct tc_action_ops act_ctinfo_ops; +-static unsigned int ctinfo_net_id; + + static void tcf_ctinfo_dscp_set(struct nf_conn *ct, struct tcf_ctinfo *ca, + struct tcf_ctinfo_params *cp, +@@ -157,7 +156,7 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ctinfo_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ctinfo_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + u32 dscpmask = 0, dscpstatemask, index; + struct nlattr *tb[TCA_CTINFO_MAX + 1]; +@@ -350,14 +349,14 @@ static int tcf_ctinfo_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ctinfo_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ctinfo_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_ctinfo_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, ctinfo_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ctinfo_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -387,20 +386,20 @@ static struct tc_action_ops act_ctinfo_ops = { + + static __net_init int ctinfo_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, ctinfo_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ctinfo_ops.net_id); + + return tc_action_net_init(net, tn, &act_ctinfo_ops); + } + + static void __net_exit ctinfo_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, ctinfo_net_id); ++ tc_action_net_exit(net_list, act_ctinfo_ops.net_id); + } + + static struct pernet_operations ctinfo_net_ops = { + .init = ctinfo_init_net, + .exit_batch = ctinfo_exit_net, +- .id = &ctinfo_net_id, ++ .id = &act_ctinfo_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c +index d8dce173df374..82148ca7d7541 100644 +--- a/net/sched/act_gact.c ++++ b/net/sched/act_gact.c +@@ -19,7 +19,6 @@ + #include + #include + +-static unsigned int gact_net_id; + static struct tc_action_ops act_gact_ops; + + #ifdef CONFIG_GACT_PROB +@@ -55,7 +54,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, gact_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gact_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_GACT_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -227,14 +226,14 @@ static int tcf_gact_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, gact_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gact_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, gact_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gact_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -268,20 +267,20 @@ static struct tc_action_ops act_gact_ops = { + + static __net_init int gact_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, gact_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gact_ops.net_id); + + return tc_action_net_init(net, tn, &act_gact_ops); + } + + static void __net_exit gact_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, gact_net_id); ++ tc_action_net_exit(net_list, act_gact_ops.net_id); + } + + static struct pernet_operations gact_net_ops = { + .init = gact_init_net, + .exit_batch = gact_exit_net, +- .id = &gact_net_id, ++ .id = &act_gact_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_gate.c b/net/sched/act_gate.c +index ac985c53ebafe..12b8fdbd9df1f 100644 +--- a/net/sched/act_gate.c ++++ b/net/sched/act_gate.c +@@ -15,7 +15,6 @@ + #include + #include + +-static unsigned int gate_net_id; + static struct tc_action_ops act_gate_ops; + + static ktime_t gate_get_time(struct tcf_gate *gact) +@@ -298,7 +297,7 @@ static int tcf_gate_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, gate_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gate_ops.net_id); + enum tk_offsets tk_offset = TK_OFFS_TAI; + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_GATE_MAX + 1]; +@@ -570,7 +569,7 @@ static int tcf_gate_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, gate_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gate_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } +@@ -587,7 +586,7 @@ static void tcf_gate_stats_update(struct tc_action *a, u64 bytes, u64 packets, + + static int tcf_gate_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, gate_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gate_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -614,20 +613,20 @@ static struct tc_action_ops act_gate_ops = { + + static __net_init int gate_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, gate_net_id); ++ struct tc_action_net *tn = net_generic(net, act_gate_ops.net_id); + + return tc_action_net_init(net, tn, &act_gate_ops); + } + + static void __net_exit gate_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, gate_net_id); ++ tc_action_net_exit(net_list, act_gate_ops.net_id); + } + + static struct pernet_operations gate_net_ops = { + .init = gate_init_net, + .exit_batch = gate_exit_net, +- .id = &gate_net_id, ++ .id = &act_gate_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index ec987ec758070..ca53783ea0c4d 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -30,7 +30,6 @@ + #include + #include + +-static unsigned int ife_net_id; + static int max_metacnt = IFE_META_MAX + 1; + static struct tc_action_ops act_ife_ops; + +@@ -482,7 +481,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ife_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ife_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_IFE_MAX + 1]; + struct nlattr *tb2[IFE_META_MAX + 1]; +@@ -883,14 +882,14 @@ static int tcf_ife_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ife_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ife_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, ife_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ife_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -910,20 +909,20 @@ static struct tc_action_ops act_ife_ops = { + + static __net_init int ife_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, ife_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ife_ops.net_id); + + return tc_action_net_init(net, tn, &act_ife_ops); + } + + static void __net_exit ife_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, ife_net_id); ++ tc_action_net_exit(net_list, act_ife_ops.net_id); + } + + static struct pernet_operations ife_net_ops = { + .init = ife_init_net, + .exit_batch = ife_exit_net, +- .id = &ife_net_id, ++ .id = &act_ife_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c +index ebd403f571ea5..6f04b35eb6539 100644 +--- a/net/sched/act_ipt.c ++++ b/net/sched/act_ipt.c +@@ -24,10 +24,7 @@ + #include + + +-static unsigned int ipt_net_id; + static struct tc_action_ops act_ipt_ops; +- +-static unsigned int xt_net_id; + static struct tc_action_ops act_xt_ops; + + static int ipt_init_target(struct net *net, struct xt_entry_target *t, +@@ -219,8 +216,8 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) + { +- return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, +- tp, flags); ++ return __tcf_ipt_init(net, act_ipt_ops.net_id, nla, est, ++ a, &act_ipt_ops, tp, flags); + } + + static int tcf_xt_init(struct net *net, struct nlattr *nla, +@@ -228,8 +225,8 @@ static int tcf_xt_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) + { +- return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, +- tp, flags); ++ return __tcf_ipt_init(net, act_xt_ops.net_id, nla, est, ++ a, &act_xt_ops, tp, flags); + } + + static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a, +@@ -334,14 +331,14 @@ static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, ipt_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ipt_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, ipt_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ipt_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -361,20 +358,20 @@ static struct tc_action_ops act_ipt_ops = { + + static __net_init int ipt_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, ipt_net_id); ++ struct tc_action_net *tn = net_generic(net, act_ipt_ops.net_id); + + return tc_action_net_init(net, tn, &act_ipt_ops); + } + + static void __net_exit ipt_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, ipt_net_id); ++ tc_action_net_exit(net_list, act_ipt_ops.net_id); + } + + static struct pernet_operations ipt_net_ops = { + .init = ipt_init_net, + .exit_batch = ipt_exit_net, +- .id = &ipt_net_id, ++ .id = &act_ipt_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +@@ -383,14 +380,14 @@ static int tcf_xt_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, xt_net_id); ++ struct tc_action_net *tn = net_generic(net, act_xt_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, xt_net_id); ++ struct tc_action_net *tn = net_generic(net, act_xt_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -410,20 +407,20 @@ static struct tc_action_ops act_xt_ops = { + + static __net_init int xt_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, xt_net_id); ++ struct tc_action_net *tn = net_generic(net, act_xt_ops.net_id); + + return tc_action_net_init(net, tn, &act_xt_ops); + } + + static void __net_exit xt_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, xt_net_id); ++ tc_action_net_exit(net_list, act_xt_ops.net_id); + } + + static struct pernet_operations xt_net_ops = { + .init = xt_init_net, + .exit_batch = xt_exit_net, +- .id = &xt_net_id, ++ .id = &act_xt_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c +index 1aa1d10de30e4..1daa1622c6a0b 100644 +--- a/net/sched/act_mirred.c ++++ b/net/sched/act_mirred.c +@@ -86,7 +86,6 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { + [TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) }, + }; + +-static unsigned int mirred_net_id; + static struct tc_action_ops act_mirred_ops; + + static int tcf_mirred_init(struct net *net, struct nlattr *nla, +@@ -94,7 +93,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, mirred_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mirred_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_MIRRED_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -387,14 +386,14 @@ static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, mirred_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mirred_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, mirred_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mirred_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -477,20 +476,20 @@ static struct tc_action_ops act_mirred_ops = { + + static __net_init int mirred_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, mirred_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mirred_ops.net_id); + + return tc_action_net_init(net, tn, &act_mirred_ops); + } + + static void __net_exit mirred_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, mirred_net_id); ++ tc_action_net_exit(net_list, act_mirred_ops.net_id); + } + + static struct pernet_operations mirred_net_ops = { + .init = mirred_init_net, + .exit_batch = mirred_exit_net, +- .id = &mirred_net_id, ++ .id = &act_mirred_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c +index d010c5b8e83b1..75a87a068c536 100644 +--- a/net/sched/act_mpls.c ++++ b/net/sched/act_mpls.c +@@ -15,7 +15,6 @@ + #include + #include + +-static unsigned int mpls_net_id; + static struct tc_action_ops act_mpls_ops; + + #define ACT_MPLS_TTL_DEFAULT 255 +@@ -161,7 +160,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, mpls_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mpls_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_MPLS_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -386,14 +385,14 @@ static int tcf_mpls_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, mpls_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mpls_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_mpls_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, mpls_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mpls_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -413,20 +412,20 @@ static struct tc_action_ops act_mpls_ops = { + + static __net_init int mpls_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, mpls_net_id); ++ struct tc_action_net *tn = net_generic(net, act_mpls_ops.net_id); + + return tc_action_net_init(net, tn, &act_mpls_ops); + } + + static void __net_exit mpls_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, mpls_net_id); ++ tc_action_net_exit(net_list, act_mpls_ops.net_id); + } + + static struct pernet_operations mpls_net_ops = { + .init = mpls_init_net, + .exit_batch = mpls_exit_net, +- .id = &mpls_net_id, ++ .id = &act_mpls_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c +index 2a39b3729e844..f5810387ce9ae 100644 +--- a/net/sched/act_nat.c ++++ b/net/sched/act_nat.c +@@ -26,7 +26,6 @@ + #include + + +-static unsigned int nat_net_id; + static struct tc_action_ops act_nat_ops; + + static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { +@@ -37,7 +36,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, + struct tc_action **a, struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, nat_net_id); ++ struct tc_action_net *tn = net_generic(net, act_nat_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_NAT_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -294,14 +293,14 @@ static int tcf_nat_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, nat_net_id); ++ struct tc_action_net *tn = net_generic(net, act_nat_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, nat_net_id); ++ struct tc_action_net *tn = net_generic(net, act_nat_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -320,20 +319,20 @@ static struct tc_action_ops act_nat_ops = { + + static __net_init int nat_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, nat_net_id); ++ struct tc_action_net *tn = net_generic(net, act_nat_ops.net_id); + + return tc_action_net_init(net, tn, &act_nat_ops); + } + + static void __net_exit nat_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, nat_net_id); ++ tc_action_net_exit(net_list, act_nat_ops.net_id); + } + + static struct pernet_operations nat_net_ops = { + .init = nat_init_net, + .exit_batch = nat_exit_net, +- .id = &nat_net_id, ++ .id = &act_nat_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c +index df9ff123a7eec..d800e0285d5c2 100644 +--- a/net/sched/act_pedit.c ++++ b/net/sched/act_pedit.c +@@ -24,7 +24,6 @@ + #include + #include + +-static unsigned int pedit_net_id; + static struct tc_action_ops act_pedit_ops; + + static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { +@@ -154,7 +153,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, pedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_pedit_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct tcf_chain *goto_ch = NULL; + struct tcf_pedit_parms *oparms, *nparms; +@@ -548,14 +547,14 @@ static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, pedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_pedit_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, pedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_pedit_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -576,20 +575,20 @@ static struct tc_action_ops act_pedit_ops = { + + static __net_init int pedit_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, pedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_pedit_ops.net_id); + + return tc_action_net_init(net, tn, &act_pedit_ops); + } + + static void __net_exit pedit_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, pedit_net_id); ++ tc_action_net_exit(net_list, act_pedit_ops.net_id); + } + + static struct pernet_operations pedit_net_ops = { + .init = pedit_init_net, + .exit_batch = pedit_exit_net, +- .id = &pedit_net_id, ++ .id = &act_pedit_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_police.c b/net/sched/act_police.c +index db1d021c16be8..13878b0520f36 100644 +--- a/net/sched/act_police.c ++++ b/net/sched/act_police.c +@@ -22,7 +22,6 @@ + + /* Each policer is serialized by its individual spinlock */ + +-static unsigned int police_net_id; + static struct tc_action_ops act_police_ops; + + static int tcf_police_walker(struct net *net, struct sk_buff *skb, +@@ -30,7 +29,7 @@ static int tcf_police_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, police_net_id); ++ struct tc_action_net *tn = net_generic(net, act_police_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } +@@ -58,7 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, + struct tc_police *parm; + struct tcf_police *police; + struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; +- struct tc_action_net *tn = net_generic(net, police_net_id); ++ struct tc_action_net *tn = net_generic(net, act_police_ops.net_id); + struct tcf_police_params *new; + bool exists = false; + u32 index; +@@ -414,7 +413,7 @@ static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a, + + static int tcf_police_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, police_net_id); ++ struct tc_action_net *tn = net_generic(net, act_police_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -439,20 +438,20 @@ static struct tc_action_ops act_police_ops = { + + static __net_init int police_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, police_net_id); ++ struct tc_action_net *tn = net_generic(net, act_police_ops.net_id); + + return tc_action_net_init(net, tn, &act_police_ops); + } + + static void __net_exit police_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, police_net_id); ++ tc_action_net_exit(net_list, act_police_ops.net_id); + } + + static struct pernet_operations police_net_ops = { + .init = police_init_net, + .exit_batch = police_exit_net, +- .id = &police_net_id, ++ .id = &act_police_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c +index ca67d96449176..aa0b1215b58f4 100644 +--- a/net/sched/act_sample.c ++++ b/net/sched/act_sample.c +@@ -23,7 +23,6 @@ + + #include + +-static unsigned int sample_net_id; + static struct tc_action_ops act_sample_ops; + + static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = { +@@ -38,7 +37,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, + u32 flags, struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, sample_net_id); ++ struct tc_action_net *tn = net_generic(net, act_sample_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_SAMPLE_MAX + 1]; + struct psample_group *psample_group; +@@ -253,14 +252,14 @@ static int tcf_sample_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, sample_net_id); ++ struct tc_action_net *tn = net_generic(net, act_sample_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, sample_net_id); ++ struct tc_action_net *tn = net_generic(net, act_sample_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -306,20 +305,20 @@ static struct tc_action_ops act_sample_ops = { + + static __net_init int sample_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, sample_net_id); ++ struct tc_action_net *tn = net_generic(net, act_sample_ops.net_id); + + return tc_action_net_init(net, tn, &act_sample_ops); + } + + static void __net_exit sample_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, sample_net_id); ++ tc_action_net_exit(net_list, act_sample_ops.net_id); + } + + static struct pernet_operations sample_net_ops = { + .init = sample_init_net, + .exit_batch = sample_exit_net, +- .id = &sample_net_id, ++ .id = &act_sample_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c +index 7885271540259..2188554dac8d8 100644 +--- a/net/sched/act_simple.c ++++ b/net/sched/act_simple.c +@@ -18,7 +18,6 @@ + #include + #include + +-static unsigned int simp_net_id; + static struct tc_action_ops act_simp_ops; + + #define SIMP_MAX_DATA 32 +@@ -88,7 +87,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, simp_net_id); ++ struct tc_action_net *tn = net_generic(net, act_simp_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_DEF_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -202,14 +201,14 @@ static int tcf_simp_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, simp_net_id); ++ struct tc_action_net *tn = net_generic(net, act_simp_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, simp_net_id); ++ struct tc_action_net *tn = net_generic(net, act_simp_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -229,20 +228,20 @@ static struct tc_action_ops act_simp_ops = { + + static __net_init int simp_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, simp_net_id); ++ struct tc_action_net *tn = net_generic(net, act_simp_ops.net_id); + + return tc_action_net_init(net, tn, &act_simp_ops); + } + + static void __net_exit simp_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, simp_net_id); ++ tc_action_net_exit(net_list, act_simp_ops.net_id); + } + + static struct pernet_operations simp_net_ops = { + .init = simp_init_net, + .exit_batch = simp_exit_net, +- .id = &simp_net_id, ++ .id = &act_simp_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c +index 6088ceaf582e8..0c91f88476baf 100644 +--- a/net/sched/act_skbedit.c ++++ b/net/sched/act_skbedit.c +@@ -20,7 +20,6 @@ + #include + #include + +-static unsigned int skbedit_net_id; + static struct tc_action_ops act_skbedit_ops; + + static int tcf_skbedit_act(struct sk_buff *skb, const struct tc_action *a, +@@ -99,7 +98,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 act_flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, skbedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbedit_ops.net_id); + bool bind = act_flags & TCA_ACT_FLAGS_BIND; + struct tcf_skbedit_params *params_new; + struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; +@@ -304,14 +303,14 @@ static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, skbedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbedit_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, skbedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbedit_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -344,20 +343,20 @@ static struct tc_action_ops act_skbedit_ops = { + + static __net_init int skbedit_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, skbedit_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbedit_ops.net_id); + + return tc_action_net_init(net, tn, &act_skbedit_ops); + } + + static void __net_exit skbedit_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, skbedit_net_id); ++ tc_action_net_exit(net_list, act_skbedit_ops.net_id); + } + + static struct pernet_operations skbedit_net_ops = { + .init = skbedit_init_net, + .exit_batch = skbedit_exit_net, +- .id = &skbedit_net_id, ++ .id = &act_skbedit_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c +index d5b421072b998..37395ab1df472 100644 +--- a/net/sched/act_skbmod.c ++++ b/net/sched/act_skbmod.c +@@ -19,7 +19,6 @@ + #include + #include + +-static unsigned int skbmod_net_id; + static struct tc_action_ops act_skbmod_ops; + + static int tcf_skbmod_act(struct sk_buff *skb, const struct tc_action *a, +@@ -103,7 +102,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, skbmod_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbmod_ops.net_id); + bool ovr = flags & TCA_ACT_FLAGS_REPLACE; + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_SKBMOD_MAX + 1]; +@@ -281,14 +280,14 @@ static int tcf_skbmod_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, skbmod_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbmod_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, skbmod_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbmod_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -308,20 +307,20 @@ static struct tc_action_ops act_skbmod_ops = { + + static __net_init int skbmod_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, skbmod_net_id); ++ struct tc_action_net *tn = net_generic(net, act_skbmod_ops.net_id); + + return tc_action_net_init(net, tn, &act_skbmod_ops); + } + + static void __net_exit skbmod_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, skbmod_net_id); ++ tc_action_net_exit(net_list, act_skbmod_ops.net_id); + } + + static struct pernet_operations skbmod_net_ops = { + .init = skbmod_init_net, + .exit_batch = skbmod_exit_net, +- .id = &skbmod_net_id, ++ .id = &act_skbmod_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c +index 64277ce3c5eb9..c79f23367dfb3 100644 +--- a/net/sched/act_tunnel_key.c ++++ b/net/sched/act_tunnel_key.c +@@ -20,7 +20,6 @@ + #include + #include + +-static unsigned int tunnel_key_net_id; + static struct tc_action_ops act_tunnel_key_ops; + + static int tunnel_key_act(struct sk_buff *skb, const struct tc_action *a, +@@ -358,7 +357,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 act_flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); ++ struct tc_action_net *tn = net_generic(net, act_tunnel_key_ops.net_id); + bool bind = act_flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; + struct tcf_tunnel_key_params *params_new; +@@ -775,14 +774,14 @@ static int tunnel_key_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); ++ struct tc_action_net *tn = net_generic(net, act_tunnel_key_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } + + static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); ++ struct tc_action_net *tn = net_generic(net, act_tunnel_key_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -802,20 +801,20 @@ static struct tc_action_ops act_tunnel_key_ops = { + + static __net_init int tunnel_key_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); ++ struct tc_action_net *tn = net_generic(net, act_tunnel_key_ops.net_id); + + return tc_action_net_init(net, tn, &act_tunnel_key_ops); + } + + static void __net_exit tunnel_key_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, tunnel_key_net_id); ++ tc_action_net_exit(net_list, act_tunnel_key_ops.net_id); + } + + static struct pernet_operations tunnel_key_net_ops = { + .init = tunnel_key_init_net, + .exit_batch = tunnel_key_exit_net, +- .id = &tunnel_key_net_id, ++ .id = &act_tunnel_key_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c +index e4dc5a555bd85..61a38ae2064ce 100644 +--- a/net/sched/act_vlan.c ++++ b/net/sched/act_vlan.c +@@ -16,7 +16,6 @@ + #include + #include + +-static unsigned int vlan_net_id; + static struct tc_action_ops act_vlan_ops; + + static int tcf_vlan_act(struct sk_buff *skb, const struct tc_action *a, +@@ -117,7 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, + struct tcf_proto *tp, u32 flags, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, vlan_net_id); ++ struct tc_action_net *tn = net_generic(net, act_vlan_ops.net_id); + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct nlattr *tb[TCA_VLAN_MAX + 1]; + struct tcf_chain *goto_ch = NULL; +@@ -338,7 +337,7 @@ static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, + const struct tc_action_ops *ops, + struct netlink_ext_ack *extack) + { +- struct tc_action_net *tn = net_generic(net, vlan_net_id); ++ struct tc_action_net *tn = net_generic(net, act_vlan_ops.net_id); + + return tcf_generic_walker(tn, skb, cb, type, ops, extack); + } +@@ -355,7 +354,7 @@ static void tcf_vlan_stats_update(struct tc_action *a, u64 bytes, u64 packets, + + static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index) + { +- struct tc_action_net *tn = net_generic(net, vlan_net_id); ++ struct tc_action_net *tn = net_generic(net, act_vlan_ops.net_id); + + return tcf_idr_search(tn, a, index); + } +@@ -385,20 +384,20 @@ static struct tc_action_ops act_vlan_ops = { + + static __net_init int vlan_init_net(struct net *net) + { +- struct tc_action_net *tn = net_generic(net, vlan_net_id); ++ struct tc_action_net *tn = net_generic(net, act_vlan_ops.net_id); + + return tc_action_net_init(net, tn, &act_vlan_ops); + } + + static void __net_exit vlan_exit_net(struct list_head *net_list) + { +- tc_action_net_exit(net_list, vlan_net_id); ++ tc_action_net_exit(net_list, act_vlan_ops.net_id); + } + + static struct pernet_operations vlan_net_ops = { + .init = vlan_init_net, + .exit_batch = vlan_exit_net, +- .id = &vlan_net_id, ++ .id = &act_vlan_ops.net_id, + .size = sizeof(struct tc_action_net), + }; + +-- +2.51.0 + diff --git a/queue-5.15/net-sched-act_connmark-get-rid-of-tcf_connmark_walke.patch b/queue-5.15/net-sched-act_connmark-get-rid-of-tcf_connmark_walke.patch new file mode 100644 index 0000000000..741d12f581 --- /dev/null +++ b/queue-5.15/net-sched-act_connmark-get-rid-of-tcf_connmark_walke.patch @@ -0,0 +1,62 @@ +From 93929765eff6563550f5752774b3ff53de8888ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 12:14:36 +0800 +Subject: net: sched: act_connmark: get rid of tcf_connmark_walker and + tcf_connmark_search + +From: Zhengchao Shao + +[ Upstream commit c4d2497032ae31d234425648bf2720dfb1688796 ] + +tcf_connmark_walker() and tcf_connmark_search() do the same thing as +generic walk/search function, so remove them. + +Signed-off-by: Zhengchao Shao +Acked-by: Jamal Hadi Salim +Signed-off-by: David S. Miller +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + net/sched/act_connmark.c | 19 ------------------- + 1 file changed, 19 deletions(-) + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 16b3d56ef2f43..d41002e4613ff 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -199,23 +199,6 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + return -1; + } + +-static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, +- struct netlink_callback *cb, int type, +- const struct tc_action_ops *ops, +- struct netlink_ext_ack *extack) +-{ +- struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); +- +- return tcf_generic_walker(tn, skb, cb, type, ops, extack); +-} +- +-static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index) +-{ +- struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); +- +- return tcf_idr_search(tn, a, index); +-} +- + static struct tc_action_ops act_connmark_ops = { + .kind = "connmark", + .id = TCA_ID_CONNMARK, +@@ -223,8 +206,6 @@ static struct tc_action_ops act_connmark_ops = { + .act = tcf_connmark_act, + .dump = tcf_connmark_dump, + .init = tcf_connmark_init, +- .walk = tcf_connmark_walker, +- .lookup = tcf_connmark_search, + .size = sizeof(struct tcf_connmark_info), + }; + +-- +2.51.0 + diff --git a/queue-5.15/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch b/queue-5.15/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch new file mode 100644 index 0000000000..e3baddf655 --- /dev/null +++ b/queue-5.15/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch @@ -0,0 +1,59 @@ +From f6912c7eee964bbc3cac787806f641c5897f1f06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:35 +0530 +Subject: net: sched: act_connmark: initialize struct tc_ife to fix kernel leak + +From: Ranganath V N + +[ Upstream commit 62b656e43eaeae445a39cd8021a4f47065af4389 ] + +In tcf_connmark_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: 22a5dc0e5e3e ("net: sched: Introduce connmark action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-2-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_connmark.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 79cfe51a09e74..4d75d2ae0d8ce 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -190,13 +190,15 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); + const struct tcf_connmark_parms *parms; +- struct tc_connmark opt = { +- .index = ci->tcf_index, +- .refcnt = refcount_read(&ci->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, +- }; ++ struct tc_connmark opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ci->tcf_index; ++ opt.refcnt = refcount_read(&ci->tcf_refcnt) - ref; ++ opt.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind; ++ + rcu_read_lock(); + parms = rcu_dereference(ci->parms); + +-- +2.51.0 + diff --git a/queue-5.15/net-sched-act_connmark-transition-to-percpu-stats-an.patch b/queue-5.15/net-sched-act_connmark-transition-to-percpu-stats-an.patch new file mode 100644 index 0000000000..4a60553cc2 --- /dev/null +++ b/queue-5.15/net-sched-act_connmark-transition-to-percpu-stats-an.patch @@ -0,0 +1,277 @@ +From 39102d64bf0016236184ff0e564c1c7f4b5a11b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Feb 2023 18:15:32 -0300 +Subject: net/sched: act_connmark: transition to percpu stats and rcu + +From: Pedro Tammela + +[ Upstream commit 288864effe33885988d53faf7830b35cb9a84c7a ] + +The tc action act_connmark was using shared stats and taking the per +action lock in the datapath. Improve it by using percpu stats and rcu. + +perf before: +- 13.55% tcf_connmark_act + - 81.18% _raw_spin_lock + 80.46% native_queued_spin_lock_slowpath + +perf after: +- 2.85% tcf_connmark_act + +tdc results: +1..15 +ok 1 2002 - Add valid connmark action with defaults +ok 2 56a5 - Add valid connmark action with control pass +ok 3 7c66 - Add valid connmark action with control drop +ok 4 a913 - Add valid connmark action with control pipe +ok 5 bdd8 - Add valid connmark action with control reclassify +ok 6 b8be - Add valid connmark action with control continue +ok 7 d8a6 - Add valid connmark action with control jump +ok 8 aae8 - Add valid connmark action with zone argument +ok 9 2f0b - Add valid connmark action with invalid zone argument +ok 10 9305 - Add connmark action with unsupported argument +ok 11 71ca - Add valid connmark action and replace it +ok 12 5f8f - Add valid connmark action with cookie +ok 13 c506 - Replace connmark with invalid goto chain control +ok 14 6571 - Delete connmark action with valid index +ok 15 3426 - Delete connmark action with invalid index + +Reviewed-by: Jamal Hadi Salim +Signed-off-by: Pedro Tammela +Signed-off-by: Paolo Abeni +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/tc_act/tc_connmark.h | 9 ++- + net/sched/act_connmark.c | 107 ++++++++++++++++++++----------- + 2 files changed, 75 insertions(+), 41 deletions(-) + +diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h +index 1f4cb477bb5d6..e8dd77a967480 100644 +--- a/include/net/tc_act/tc_connmark.h ++++ b/include/net/tc_act/tc_connmark.h +@@ -4,10 +4,15 @@ + + #include + +-struct tcf_connmark_info { +- struct tc_action common; ++struct tcf_connmark_parms { + struct net *net; + u16 zone; ++ struct rcu_head rcu; ++}; ++ ++struct tcf_connmark_info { ++ struct tc_action common; ++ struct tcf_connmark_parms __rcu *parms; + }; + + #define to_connmark(a) ((struct tcf_connmark_info *)a) +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index d41002e4613ff..418d60435b9d4 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -34,13 +34,15 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + struct nf_conntrack_tuple tuple; + enum ip_conntrack_info ctinfo; + struct tcf_connmark_info *ca = to_connmark(a); ++ struct tcf_connmark_parms *parms; + struct nf_conntrack_zone zone; + struct nf_conn *c; + int proto; + +- spin_lock(&ca->tcf_lock); + tcf_lastuse_update(&ca->tcf_tm); +- bstats_update(&ca->tcf_bstats, skb); ++ tcf_action_update_bstats(&ca->common, skb); ++ ++ parms = rcu_dereference_bh(ca->parms); + + switch (skb_protocol(skb, true)) { + case htons(ETH_P_IP): +@@ -62,31 +64,29 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + c = nf_ct_get(skb, &ctinfo); + if (c) { + skb->mark = READ_ONCE(c->mark); +- /* using overlimits stats to count how many packets marked */ +- ca->tcf_qstats.overlimits++; +- goto out; ++ goto count; + } + +- if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), +- proto, ca->net, &tuple)) ++ if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, parms->net, ++ &tuple)) + goto out; + +- zone.id = ca->zone; ++ zone.id = parms->zone; + zone.dir = NF_CT_DEFAULT_ZONE_DIR; + +- thash = nf_conntrack_find_get(ca->net, &zone, &tuple); ++ thash = nf_conntrack_find_get(parms->net, &zone, &tuple); + if (!thash) + goto out; + + c = nf_ct_tuplehash_to_ctrack(thash); +- /* using overlimits stats to count how many packets marked */ +- ca->tcf_qstats.overlimits++; + skb->mark = READ_ONCE(c->mark); + nf_ct_put(c); + ++count: ++ /* using overlimits stats to count how many packets marked */ ++ tcf_action_inc_overlimit_qstats(&ca->common); + out: +- spin_unlock(&ca->tcf_lock); +- return ca->tcf_action; ++ return READ_ONCE(ca->tcf_action); + } + + static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { +@@ -99,6 +99,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + struct netlink_ext_ack *extack) + { + struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); ++ struct tcf_connmark_parms *nparms, *oparms; + struct nlattr *tb[TCA_CONNMARK_MAX + 1]; + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct tcf_chain *goto_ch = NULL; +@@ -118,52 +119,66 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + if (!tb[TCA_CONNMARK_PARMS]) + return -EINVAL; + ++ nparms = kzalloc(sizeof(*nparms), GFP_KERNEL); ++ if (!nparms) ++ return -ENOMEM; ++ + parm = nla_data(tb[TCA_CONNMARK_PARMS]); + index = parm->index; + ret = tcf_idr_check_alloc(tn, &index, a, bind); + if (!ret) { +- ret = tcf_idr_create(tn, index, est, a, +- &act_connmark_ops, bind, false, flags); ++ ret = tcf_idr_create_from_flags(tn, index, est, a, ++ &act_connmark_ops, bind, flags); + if (ret) { + tcf_idr_cleanup(tn, index); +- return ret; ++ err = ret; ++ goto out_free; + } + + ci = to_connmark(*a); +- err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, +- extack); +- if (err < 0) +- goto release_idr; +- tcf_action_set_ctrlact(*a, parm->action, goto_ch); +- ci->net = net; +- ci->zone = parm->zone; ++ ++ nparms->net = net; ++ nparms->zone = parm->zone; + + ret = ACT_P_CREATED; + } else if (ret > 0) { + ci = to_connmark(*a); +- if (bind) +- return 0; +- if (!(flags & TCA_ACT_FLAGS_REPLACE)) { +- tcf_idr_release(*a, bind); +- return -EEXIST; ++ if (bind) { ++ err = 0; ++ goto out_free; + } +- err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, +- extack); +- if (err < 0) ++ if (!(flags & TCA_ACT_FLAGS_REPLACE)) { ++ err = -EEXIST; + goto release_idr; +- /* replacing action and zone */ +- spin_lock_bh(&ci->tcf_lock); +- goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); +- ci->zone = parm->zone; +- spin_unlock_bh(&ci->tcf_lock); +- if (goto_ch) +- tcf_chain_put_by_act(goto_ch); ++ } ++ ++ nparms->net = rtnl_dereference(ci->parms)->net; ++ nparms->zone = parm->zone; ++ + ret = 0; + } + ++ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); ++ if (err < 0) ++ goto release_idr; ++ ++ spin_lock_bh(&ci->tcf_lock); ++ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); ++ oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock)); ++ spin_unlock_bh(&ci->tcf_lock); ++ ++ if (goto_ch) ++ tcf_chain_put_by_act(goto_ch); ++ ++ if (oparms) ++ kfree_rcu(oparms, rcu); ++ + return ret; ++ + release_idr: + tcf_idr_release(*a, bind); ++out_free: ++ kfree(nparms); + return err; + } + +@@ -177,11 +192,14 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + .refcnt = refcount_read(&ci->tcf_refcnt) - ref, + .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, + }; ++ struct tcf_connmark_parms *parms; + struct tcf_t t; + + spin_lock_bh(&ci->tcf_lock); ++ parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock)); ++ + opt.action = ci->tcf_action; +- opt.zone = ci->zone; ++ opt.zone = parms->zone; + if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; + +@@ -199,6 +217,16 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + return -1; + } + ++static void tcf_connmark_cleanup(struct tc_action *a) ++{ ++ struct tcf_connmark_info *ci = to_connmark(a); ++ struct tcf_connmark_parms *parms; ++ ++ parms = rcu_dereference_protected(ci->parms, 1); ++ if (parms) ++ kfree_rcu(parms, rcu); ++} ++ + static struct tc_action_ops act_connmark_ops = { + .kind = "connmark", + .id = TCA_ID_CONNMARK, +@@ -206,6 +234,7 @@ static struct tc_action_ops act_connmark_ops = { + .act = tcf_connmark_act, + .dump = tcf_connmark_dump, + .init = tcf_connmark_init, ++ .cleanup = tcf_connmark_cleanup, + .size = sizeof(struct tcf_connmark_info), + }; + +-- +2.51.0 + diff --git a/queue-5.15/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-5.15/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..613f940e3c --- /dev/null +++ b/queue-5.15/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From 44f0d2f6df8a78e345222122da2806111441acc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index ca53783ea0c4d..a8a5dbd7221b0 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -643,13 +643,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-5.15/net-smc-fix-mismatch-between-clc-header-and-proposal.patch b/queue-5.15/net-smc-fix-mismatch-between-clc-header-and-proposal.patch new file mode 100644 index 0000000000..f9b4e3f6ba --- /dev/null +++ b/queue-5.15/net-smc-fix-mismatch-between-clc-header-and-proposal.patch @@ -0,0 +1,55 @@ +From e7fd45ade724c0773bcf9a85ec67529dc27ddb4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 10:40:29 +0800 +Subject: net/smc: fix mismatch between CLC header and proposal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: D. Wythe + +[ Upstream commit ec33f2e5a2d0dbbfd71435209aee812fdc9369b8 ] + +The current CLC proposal message construction uses a mix of +`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether +to include optional extensions (IPv6 prefix extension for v1, and v2 +extension). This leads to a critical inconsistency: when +`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with +only link-local addresses, or when the local IP address and the outgoing +interface’s network address are not in the same subnet. + +As a result, the proposal message is assembled using the stale +`ini->smc_type_v1` value—causing the IPv6 prefix extension to be +included even though the header indicates v1 is not supported. +The peer then receives a malformed CLC proposal where the header type +does not match the payload, and immediately resets the connection. + +The fix ensures consistency between the CLC header flags and the actual +payload by synchronizing `ini->smc_type_v1` with `pclc_base->hdr.typev1` +when prefix setup fails. + +Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal") +Signed-off-by: D. Wythe +Reviewed-by: Alexandra Winter +Link: https://patch.msgid.link/20251107024029.88753-1-alibuda@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_clc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c +index 52a0ba939c91c..ec8c4cfdb1471 100644 +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -529,6 +529,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) + return SMC_CLC_DECL_CNFERR; + } + pclc_base->hdr.typev1 = SMC_TYPE_N; ++ ini->smc_type_v1 = SMC_TYPE_N; + } else { + pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); + plen += sizeof(*pclc_prfx) + +-- +2.51.0 + diff --git a/queue-5.15/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch b/queue-5.15/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch new file mode 100644 index 0000000000..767327033c --- /dev/null +++ b/queue-5.15/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch @@ -0,0 +1,100 @@ +From 8051440b049a5d1a6bf975a6e0dc4c032f21c6a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 09:01:54 +0000 +Subject: net_sched: act_connmark: use RCU in tcf_connmark_dump() + +From: Eric Dumazet + +[ Upstream commit 0d752877705c0252ef2726e4c63c5573f048951c ] + +Also storing tcf_action into struct tcf_connmark_parms +makes sure there is no discrepancy in tcf_connmark_act(). + +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250709090204.797558-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/tc_act/tc_connmark.h | 1 + + net/sched/act_connmark.c | 18 ++++++++++-------- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h +index e8dd77a967480..a5ce83f3eea4b 100644 +--- a/include/net/tc_act/tc_connmark.h ++++ b/include/net/tc_act/tc_connmark.h +@@ -7,6 +7,7 @@ + struct tcf_connmark_parms { + struct net *net; + u16 zone; ++ int action; + struct rcu_head rcu; + }; + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 418d60435b9d4..79cfe51a09e74 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -86,7 +86,7 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + /* using overlimits stats to count how many packets marked */ + tcf_action_inc_overlimit_qstats(&ca->common); + out: +- return READ_ONCE(ca->tcf_action); ++ return parms->action; + } + + static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { +@@ -162,6 +162,8 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + if (err < 0) + goto release_idr; + ++ nparms->action = parm->action; ++ + spin_lock_bh(&ci->tcf_lock); + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); + oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock)); +@@ -185,20 +187,20 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + int bind, int ref) + { ++ const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); +- struct tcf_connmark_info *ci = to_connmark(a); ++ const struct tcf_connmark_parms *parms; + struct tc_connmark opt = { + .index = ci->tcf_index, + .refcnt = refcount_read(&ci->tcf_refcnt) - ref, + .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, + }; +- struct tcf_connmark_parms *parms; + struct tcf_t t; + +- spin_lock_bh(&ci->tcf_lock); +- parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock)); ++ rcu_read_lock(); ++ parms = rcu_dereference(ci->parms); + +- opt.action = ci->tcf_action; ++ opt.action = parms->action; + opt.zone = parms->zone; + if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; +@@ -207,12 +209,12 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t, + TCA_CONNMARK_PAD)) + goto nla_put_failure; +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + + return skb->len; + + nla_put_failure: +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + nlmsg_trim(skb, b); + return -1; + } +-- +2.51.0 + diff --git a/queue-5.15/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-5.15/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..5bceafeb3a --- /dev/null +++ b/queue-5.15/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From 2a7f9da7ed60a55e9f5d9ff51977105569062c23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 02299785209c1..565970cca295b 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -178,9 +178,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -191,8 +192,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -226,7 +229,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -293,7 +296,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -385,7 +388,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -394,7 +397,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -412,7 +415,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + if (q->flags & TCQ_F_NOLOCK) +-- +2.51.0 + diff --git a/queue-5.15/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-5.15/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..fd5d907cb1 --- /dev/null +++ b/queue-5.15/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From b2cf18523d1543175325cdc868dcf0b562efc83c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 687e6a43d049d..d279dda07b1ba 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -501,6 +501,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -512,10 +513,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-5.15/series b/queue-5.15/series index f744700af6..cb445c495b 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -235,3 +235,24 @@ nfs4-fix-state-renewals-missing-after-boot.patch hid-quirks-avoid-cooler-master-mm712-dongle-wakeup-b.patch nfs-check-if-suid-sgid-was-cleared-after-a-write-as-.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +net-smc-fix-mismatch-between-clc-header-and-proposal.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +net-sched-act-move-global-static-variable-net_id-to-.patch +net-sched-act_connmark-get-rid-of-tcf_connmark_walke.patch +net-sched-act_connmark-transition-to-percpu-stats-an.patch +net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch +net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +hsr-fix-supervision-frame-sending-on-hsrv0.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch diff --git a/queue-5.15/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-5.15/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..e0c9409728 --- /dev/null +++ b/queue-5.15/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From b252125f5438fa7928e0f6f5b5bbcf5c0cf7690f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 0e95572e56b41..7e65d0b0c4a8d 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -145,7 +145,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-5.15/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-5.15/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..eacc9a9544 --- /dev/null +++ b/queue-5.15/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From 78339150625c94d4fccbc43c57c1364f8c27a50f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 6c160ff2aab90..aa3442761ad05 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4911,10 +4911,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 + diff --git a/queue-5.4/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-5.4/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..463d3f0402 --- /dev/null +++ b/queue-5.4/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From 123ac1bf171a1d313268157a97fdb0304dc7c8d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 2df218b454cc0..c7cdb5c1273a1 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -52,6 +52,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -60,6 +65,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1043,41 +1050,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-5.4/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-5.4/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..1d4b5e9d16 --- /dev/null +++ b/queue-5.4/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From a9681ec2c4ef1bc2a2df2f639f566e0f13344983 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index dd7fdfd155c6f..2df218b454cc0 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -986,10 +986,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -1000,13 +1001,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1133,7 +1153,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1170,7 +1190,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-5.4/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-5.4/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..90c47a8f76 --- /dev/null +++ b/queue-5.4/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From 14eb67292df9e45369c9a929f91d30b59f5f074e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 12052b7664414..dd7fdfd155c6f 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -317,6 +317,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-5.4/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-5.4/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..c2e3fc13de --- /dev/null +++ b/queue-5.4/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From 6dbece2e8daa8d56113eb071a32f00a7e43db5e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 9f71f9135f9e3..3d79637a56cc4 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4004,6 +4004,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4014,17 +4019,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-5.4/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-5.4/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..f1412b5932 --- /dev/null +++ b/queue-5.4/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 0bc9c8154c3f8735a24cad27c85dc58a3cb54b97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 1272ad73e4011..4c82770173aad 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -517,6 +517,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-5.4/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-5.4/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..54572fbba6 --- /dev/null +++ b/queue-5.4/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From 9d16070048bc32aa640da6e4d7628899ed267674 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 7b2ab0cc562cc..cd2fd2926f2f5 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1530,6 +1530,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + skb = rxq->rx_skbuff[index]; +-- +2.51.0 + diff --git a/queue-5.4/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-5.4/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..d284c76ec4 --- /dev/null +++ b/queue-5.4/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From d8e028d20c7b5b60d9573d849e6f787497d1b79b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 931b9a6c5dc50..bdce184759eff 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -89,8 +89,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-5.4/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-5.4/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..ee30b0a7fa --- /dev/null +++ b/queue-5.4/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From 2c8033e91ab6c8bcd359dc96a7154feb48d01b06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index f1952e14c8042..3379f99a44dd6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -579,18 +579,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-5.4/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-5.4/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..6a72646f9f --- /dev/null +++ b/queue-5.4/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From 50c49830eced9030389c76f65361c8c82fa611c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 3379f99a44dd6..4acab31f53ac0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -580,11 +580,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -596,10 +598,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-5.4/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-5.4/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..d31db5981e --- /dev/null +++ b/queue-5.4/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From 71eeb246134ac7efcfd665f7bb04cd949ff34fdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index 488d10476e850..8f82842ad8cb5 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -642,13 +642,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-5.4/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-5.4/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..6374a3eb40 --- /dev/null +++ b/queue-5.4/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From e3e36dbb4d98e19b99af39119c92c4bb6ae3d215 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 19fe5078a8d13..d52001d958cbc 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -172,9 +172,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -185,8 +186,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -220,7 +223,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -287,7 +290,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -379,7 +382,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -388,7 +391,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -406,7 +409,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + __netif_schedule(q); +-- +2.51.0 + diff --git a/queue-5.4/net_sched-remove-need_resched-from-qdisc_run.patch b/queue-5.4/net_sched-remove-need_resched-from-qdisc_run.patch new file mode 100644 index 0000000000..7dcafe6391 --- /dev/null +++ b/queue-5.4/net_sched-remove-need_resched-from-qdisc_run.patch @@ -0,0 +1,89 @@ +From 44244e775326539ee463420056f3a5e6c0b84e3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Oct 2019 14:02:36 -0700 +Subject: net_sched: remove need_resched() from qdisc_run() + +From: Eric Dumazet + +[ Upstream commit b60fa1c5d01a10e358c509b904d4bead6114d593 ] + +The introduction of this schedule point was done in commit +2ba2506ca7ca ("[NET]: Add preemption point in qdisc_run") +at a time the loop was not bounded. + +Then later in commit d5b8aa1d246f ("net_sched: fix dequeuer fairness") +we added a limit on the number of packets. + +Now is the time to remove the schedule point, since the default +limit of 64 packets matches the number of packets a typical NAPI +poll can process in a row. + +This solves a latency problem for most TCP receivers under moderate load : + +1) host receives a packet. + NET_RX_SOFTIRQ is raised by NIC hard IRQ handler + +2) __do_softirq() does its first loop, handling NET_RX_SOFTIRQ + and calling the driver napi->loop() function + +3) TCP stores the skb in socket receive queue: + +4) TCP calls sk->sk_data_ready() and wakeups a user thread + waiting for EPOLLIN (as a result, need_resched() might now be true) + +5) TCP cooks an ACK and sends it. + +6) qdisc_run() processes one packet from qdisc, and sees need_resched(), + this raises NET_TX_SOFTIRQ (even if there are no more packets in + the qdisc) + +Then we go back to the __do_softirq() in 2), and we see that new +softirqs were raised. Since need_resched() is true, we end up waking +ksoftirqd in this path : + + if (pending) { + if (time_before(jiffies, end) && !need_resched() && + --max_restart) + goto restart; + + wakeup_softirqd(); + } + +So we have many wakeups of ksoftirqd kernel threads, +and more calls to qdisc_run() with associated lock overhead. + +Note that another way to solve the issue would be to change TCP +to first send the ACK packet, then signal the EPOLLIN, +but this changes P99 latencies, as sending the ACK packet +can add a long delay. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: 0345552a653c ("net_sched: limit try_bulk_dequeue_skb() batches") +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 4250f3cf30e72..19fe5078a8d13 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -407,13 +407,8 @@ void __qdisc_run(struct Qdisc *q) + int packets; + + while (qdisc_restart(q, &packets)) { +- /* +- * Ordered by possible occurrence: Postpone processing if +- * 1. we've exceeded packet quota +- * 2. another process needs the CPU; +- */ + quota -= packets; +- if (quota <= 0 || need_resched()) { ++ if (quota <= 0) { + __netif_schedule(q); + break; + } +-- +2.51.0 + diff --git a/queue-5.4/sctp-get-netns-from-asoc-and-ep-base.patch b/queue-5.4/sctp-get-netns-from-asoc-and-ep-base.patch new file mode 100644 index 0000000000..c8a112d817 --- /dev/null +++ b/queue-5.4/sctp-get-netns-from-asoc-and-ep-base.patch @@ -0,0 +1,517 @@ +From f24b2806f5a2d262a34ab0dec482b5398a46b7d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Dec 2019 13:45:18 +0800 +Subject: sctp: get netns from asoc and ep base + +From: Xin Long + +[ Upstream commit 4e7696d90b51a1a73ce0e8174f3aff58b914619c ] + +Commit 312434617cb1 ("sctp: cache netns in sctp_ep_common") set netns +in asoc and ep base since they're created, and it will never change. +It's a better way to get netns from asoc and ep base, comparing to +calling sock_net(). + +This patch is to replace them. + +v1->v2: + - no change. + +Suggested-by: Marcelo Ricardo Leitner +Signed-off-by: Xin Long +Acked-by: Neil Horman +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Stable-dep-of: 1534ff77757e ("sctp: prevent possible shift-out-of-bounds in sctp_transport_update_rto") +Signed-off-by: Sasha Levin +--- + net/sctp/associola.c | 10 +++++----- + net/sctp/chunk.c | 2 +- + net/sctp/endpointola.c | 6 +++--- + net/sctp/input.c | 5 ++--- + net/sctp/output.c | 2 +- + net/sctp/outqueue.c | 6 +++--- + net/sctp/sm_make_chunk.c | 7 +++---- + net/sctp/sm_sideeffect.c | 16 ++++++---------- + net/sctp/sm_statefuns.c | 2 +- + net/sctp/socket.c | 12 +++++------- + net/sctp/stream.c | 3 +-- + net/sctp/stream_interleave.c | 23 ++++++++++------------- + net/sctp/transport.c | 2 +- + net/sctp/ulpqueue.c | 15 +++++++-------- + 14 files changed, 49 insertions(+), 62 deletions(-) + +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index bc9a62744feca..253ab788cffca 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -579,7 +579,6 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, + const gfp_t gfp, + const int peer_state) + { +- struct net *net = sock_net(asoc->base.sk); + struct sctp_transport *peer; + struct sctp_sock *sp; + unsigned short port; +@@ -609,7 +608,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, + return peer; + } + +- peer = sctp_transport_new(net, addr, gfp); ++ peer = sctp_transport_new(asoc->base.net, addr, gfp); + if (!peer) + return NULL; + +@@ -978,7 +977,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) + struct sctp_association *asoc = + container_of(work, struct sctp_association, + base.inqueue.immediate); +- struct net *net = sock_net(asoc->base.sk); ++ struct net *net = asoc->base.net; + union sctp_subtype subtype; + struct sctp_endpoint *ep; + struct sctp_chunk *chunk; +@@ -1445,7 +1444,8 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc) + /* Should we send a SACK to update our peer? */ + static inline bool sctp_peer_needs_update(struct sctp_association *asoc) + { +- struct net *net = sock_net(asoc->base.sk); ++ struct net *net = asoc->base.net; ++ + switch (asoc->state) { + case SCTP_STATE_ESTABLISHED: + case SCTP_STATE_SHUTDOWN_PENDING: +@@ -1582,7 +1582,7 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, + if (asoc->peer.ipv6_address) + flags |= SCTP_ADDR6_PEERSUPP; + +- return sctp_bind_addr_copy(sock_net(asoc->base.sk), ++ return sctp_bind_addr_copy(asoc->base.net, + &asoc->base.bind_addr, + &asoc->ep->base.bind_addr, + scope, gfp, flags); +diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c +index cc0405c79dfc0..064675bc7b54c 100644 +--- a/net/sctp/chunk.c ++++ b/net/sctp/chunk.c +@@ -227,7 +227,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, + if (msg_len >= first_len) { + msg->can_delay = 0; + if (msg_len > first_len) +- SCTP_INC_STATS(sock_net(asoc->base.sk), ++ SCTP_INC_STATS(asoc->base.net, + SCTP_MIB_FRAGUSRMSGS); + } else { + /* Which may be the only one... */ +diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c +index 665a22d5c725b..208b121d5a783 100644 +--- a/net/sctp/endpointola.c ++++ b/net/sctp/endpointola.c +@@ -251,7 +251,7 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, + struct sctp_endpoint *retval = NULL; + + if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) && +- net_eq(sock_net(ep->base.sk), net)) { ++ net_eq(ep->base.net, net)) { + if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, + sctp_sk(ep->base.sk))) + retval = ep; +@@ -299,8 +299,8 @@ bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, + const union sctp_addr *paddr) + { + struct sctp_sockaddr_entry *addr; ++ struct net *net = ep->base.net; + struct sctp_bind_addr *bp; +- struct net *net = sock_net(ep->base.sk); + + bp = &ep->base.bind_addr; + /* This function is called with the socket lock held, +@@ -391,7 +391,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work) + if (asoc && sctp_chunk_is_data(chunk)) + asoc->peer.last_data_from = chunk->transport; + else { +- SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS); ++ SCTP_INC_STATS(ep->base.net, SCTP_MIB_INCTRLCHUNKS); + if (asoc) + asoc->stats.ictrlchunks++; + } +diff --git a/net/sctp/input.c b/net/sctp/input.c +index 9013257cf3df3..28e0e110804ad 100644 +--- a/net/sctp/input.c ++++ b/net/sctp/input.c +@@ -935,7 +935,7 @@ int sctp_hash_transport(struct sctp_transport *t) + if (t->asoc->temp) + return 0; + +- arg.net = sock_net(t->asoc->base.sk); ++ arg.net = t->asoc->base.net; + arg.paddr = &t->ipaddr; + arg.lport = htons(t->asoc->base.bind_addr.port); + +@@ -1002,12 +1002,11 @@ struct sctp_transport *sctp_epaddr_lookup_transport( + const struct sctp_endpoint *ep, + const union sctp_addr *paddr) + { +- struct net *net = sock_net(ep->base.sk); + struct rhlist_head *tmp, *list; + struct sctp_transport *t; + struct sctp_hash_cmp_arg arg = { + .paddr = paddr, +- .net = net, ++ .net = ep->base.net, + .lport = htons(ep->base.bind_addr.port), + }; + +diff --git a/net/sctp/output.c b/net/sctp/output.c +index dbda7e7927fd9..1441eaf460bb3 100644 +--- a/net/sctp/output.c ++++ b/net/sctp/output.c +@@ -282,7 +282,7 @@ static enum sctp_xmit sctp_packet_bundle_sack(struct sctp_packet *pkt, + sctp_chunk_free(sack); + goto out; + } +- SCTP_INC_STATS(sock_net(asoc->base.sk), ++ SCTP_INC_STATS(asoc->base.net, + SCTP_MIB_OUTCTRLCHUNKS); + asoc->stats.octrlchunks++; + asoc->peer.sack_needed = 0; +diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c +index adceb226ffab3..6b0b3bad4daa6 100644 +--- a/net/sctp/outqueue.c ++++ b/net/sctp/outqueue.c +@@ -280,7 +280,7 @@ void sctp_outq_free(struct sctp_outq *q) + /* Put a new chunk in an sctp_outq. */ + void sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk, gfp_t gfp) + { +- struct net *net = sock_net(q->asoc->base.sk); ++ struct net *net = q->asoc->base.net; + + pr_debug("%s: outq:%p, chunk:%p[%s]\n", __func__, q, chunk, + chunk && chunk->chunk_hdr ? +@@ -534,7 +534,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, + void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, + enum sctp_retransmit_reason reason) + { +- struct net *net = sock_net(q->asoc->base.sk); ++ struct net *net = q->asoc->base.net; + + switch (reason) { + case SCTP_RTXR_T3_RTX: +@@ -1890,6 +1890,6 @@ void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) + + if (ftsn_chunk) { + list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); +- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS); ++ SCTP_INC_STATS(asoc->base.net, SCTP_MIB_OUTCTRLCHUNKS); + } + } +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index 0c112134d9e32..d3cc5a59b0fec 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -2319,7 +2319,6 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, + const union sctp_addr *peer_addr, + struct sctp_init_chunk *peer_init, gfp_t gfp) + { +- struct net *net = sock_net(asoc->base.sk); + struct sctp_transport *transport; + struct list_head *pos, *temp; + union sctp_params param; +@@ -2377,8 +2376,8 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, + * also give us an option to silently ignore the packet, which + * is what we'll do here. + */ +- if (!net->sctp.addip_noauth && +- (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) { ++ if (!asoc->base.net->sctp.addip_noauth && ++ (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) { + asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP | + SCTP_PARAM_DEL_IP | + SCTP_PARAM_SET_PRIMARY); +@@ -2505,9 +2504,9 @@ static int sctp_process_param(struct sctp_association *asoc, + const union sctp_addr *peer_addr, + gfp_t gfp) + { +- struct net *net = sock_net(asoc->base.sk); + struct sctp_endpoint *ep = asoc->ep; + union sctp_addr_param *addr_param; ++ struct net *net = asoc->base.net; + struct sctp_transport *t; + enum sctp_scope scope; + union sctp_addr addr; +diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c +index c964e7ca6f7e5..3ecd246feb76a 100644 +--- a/net/sctp/sm_sideeffect.c ++++ b/net/sctp/sm_sideeffect.c +@@ -520,8 +520,6 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands, + struct sctp_transport *transport, + int is_hb) + { +- struct net *net = sock_net(asoc->base.sk); +- + /* The check for association's overall error counter exceeding the + * threshold is done in the state function. + */ +@@ -548,10 +546,10 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands, + * is SCTP_ACTIVE, then mark this transport as Partially Failed, + * see SCTP Quick Failover Draft, section 5.1 + */ +- if (net->sctp.pf_enable && +- (transport->state == SCTP_ACTIVE) && +- (transport->error_count < transport->pathmaxrxt) && +- (transport->error_count > transport->pf_retrans)) { ++ if (asoc->base.net->sctp.pf_enable && ++ transport->state == SCTP_ACTIVE && ++ transport->error_count < transport->pathmaxrxt && ++ transport->error_count > transport->pf_retrans) { + + sctp_assoc_control_transport(asoc, transport, + SCTP_TRANSPORT_PF, +@@ -797,10 +795,8 @@ static int sctp_cmd_process_sack(struct sctp_cmd_seq *cmds, + int err = 0; + + if (sctp_outq_sack(&asoc->outqueue, chunk)) { +- struct net *net = sock_net(asoc->base.sk); +- + /* There are no more TSNs awaiting SACK. */ +- err = sctp_do_sm(net, SCTP_EVENT_T_OTHER, ++ err = sctp_do_sm(asoc->base.net, SCTP_EVENT_T_OTHER, + SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), + asoc->state, asoc->ep, asoc, NULL, + GFP_ATOMIC); +@@ -833,7 +829,7 @@ static void sctp_cmd_assoc_update(struct sctp_cmd_seq *cmds, + struct sctp_association *asoc, + struct sctp_association *new) + { +- struct net *net = sock_net(asoc->base.sk); ++ struct net *net = asoc->base.net; + struct sctp_chunk *abort; + + if (!sctp_assoc_update(asoc, new)) +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 876c18f70df89..7808dd812a72a 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -1342,7 +1342,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, + struct sctp_chunk *init, + struct sctp_cmd_seq *commands) + { +- struct net *net = sock_net(new_asoc->base.sk); ++ struct net *net = new_asoc->base.net; + struct sctp_transport *new_addr; + int ret = 1; + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 1ac05147dc304..722f8a940c2df 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -466,8 +466,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) + static int sctp_send_asconf(struct sctp_association *asoc, + struct sctp_chunk *chunk) + { +- struct net *net = sock_net(asoc->base.sk); +- int retval = 0; ++ int retval = 0; + + /* If there is an outstanding ASCONF chunk, queue it for later + * transmission. +@@ -479,7 +478,7 @@ static int sctp_send_asconf(struct sctp_association *asoc, + + /* Hold the chunk until an ASCONF_ACK is received. */ + sctp_chunk_hold(chunk); +- retval = sctp_primitive_ASCONF(net, asoc, chunk); ++ retval = sctp_primitive_ASCONF(asoc->base.net, asoc, chunk); + if (retval) + sctp_chunk_free(chunk); + else +@@ -2462,9 +2461,8 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, + int error; + + if (params->spp_flags & SPP_HB_DEMAND && trans) { +- struct net *net = sock_net(trans->asoc->base.sk); +- +- error = sctp_primitive_REQUESTHEARTBEAT(net, trans->asoc, trans); ++ error = sctp_primitive_REQUESTHEARTBEAT(trans->asoc->base.net, ++ trans->asoc, trans); + if (error) + return error; + } +@@ -5334,7 +5332,7 @@ struct sctp_transport *sctp_transport_get_next(struct net *net, + if (!sctp_transport_hold(t)) + continue; + +- if (net_eq(sock_net(t->asoc->base.sk), net) && ++ if (net_eq(t->asoc->base.net, net) && + t->asoc->peer.primary_path == t) + break; + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index 08cd06078fab1..0527728aee986 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -229,10 +229,9 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new) + static int sctp_send_reconf(struct sctp_association *asoc, + struct sctp_chunk *chunk) + { +- struct net *net = sock_net(asoc->base.sk); + int retval = 0; + +- retval = sctp_primitive_RECONF(net, asoc, chunk); ++ retval = sctp_primitive_RECONF(asoc->base.net, asoc, chunk); + if (retval) + sctp_chunk_free(chunk); + +diff --git a/net/sctp/stream_interleave.c b/net/sctp/stream_interleave.c +index c982f99099dec..e3aad75cb11d9 100644 +--- a/net/sctp/stream_interleave.c ++++ b/net/sctp/stream_interleave.c +@@ -241,9 +241,8 @@ static struct sctp_ulpevent *sctp_intl_retrieve_partial( + if (!first_frag) + return NULL; + +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), +- &ulpq->reasm, first_frag, +- last_frag); ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, ++ first_frag, last_frag); + if (retval) { + sin->fsn = next_fsn; + if (is_last) { +@@ -326,7 +325,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_reassembled( + + pd_point = sctp_sk(asoc->base.sk)->pd_point; + if (pd_point && pd_point <= pd_len) { +- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), ++ retval = sctp_make_reassembled_event(asoc->base.net, + &ulpq->reasm, + pd_first, pd_last); + if (retval) { +@@ -337,8 +336,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_reassembled( + goto out; + + found: +- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), +- &ulpq->reasm, ++ retval = sctp_make_reassembled_event(asoc->base.net, &ulpq->reasm, + first_frag, pos); + if (retval) + retval->msg_flags |= MSG_EOR; +@@ -630,7 +628,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_partial_uo( + if (!first_frag) + return NULL; + +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, + &ulpq->reasm_uo, first_frag, + last_frag); + if (retval) { +@@ -716,7 +714,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_reassembled_uo( + + pd_point = sctp_sk(asoc->base.sk)->pd_point; + if (pd_point && pd_point <= pd_len) { +- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), ++ retval = sctp_make_reassembled_event(asoc->base.net, + &ulpq->reasm_uo, + pd_first, pd_last); + if (retval) { +@@ -727,8 +725,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_reassembled_uo( + goto out; + + found: +- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), +- &ulpq->reasm_uo, ++ retval = sctp_make_reassembled_event(asoc->base.net, &ulpq->reasm_uo, + first_frag, pos); + if (retval) + retval->msg_flags |= MSG_EOR; +@@ -814,7 +811,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_first_uo(struct sctp_ulpq *ulpq) + return NULL; + + out: +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, + &ulpq->reasm_uo, first_frag, + last_frag); + if (retval) { +@@ -921,7 +918,7 @@ static struct sctp_ulpevent *sctp_intl_retrieve_first(struct sctp_ulpq *ulpq) + return NULL; + + out: +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, + &ulpq->reasm, first_frag, + last_frag); + if (retval) { +@@ -1159,7 +1156,7 @@ static void sctp_generate_iftsn(struct sctp_outq *q, __u32 ctsn) + + if (ftsn_chunk) { + list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); +- SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS); ++ SCTP_INC_STATS(asoc->base.net, SCTP_MIB_OUTCTRLCHUNKS); + } + } + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 80251c8d2225f..9c721d70df9c6 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -336,7 +336,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + pr_debug("%s: rto_pending not set on transport %p!\n", __func__, tp); + + if (tp->rttvar || tp->srtt) { +- struct net *net = sock_net(tp->asoc->base.sk); ++ struct net *net = tp->asoc->base.net; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c +index b6536b7f14c0d..1c6c640607c5c 100644 +--- a/net/sctp/ulpqueue.c ++++ b/net/sctp/ulpqueue.c +@@ -486,10 +486,9 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul + cevent = sctp_skb2event(pd_first); + pd_point = sctp_sk(asoc->base.sk)->pd_point; + if (pd_point && pd_point <= pd_len) { +- retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), ++ retval = sctp_make_reassembled_event(asoc->base.net, + &ulpq->reasm, +- pd_first, +- pd_last); ++ pd_first, pd_last); + if (retval) + sctp_ulpq_set_pd(ulpq); + } +@@ -497,7 +496,7 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul + done: + return retval; + found: +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, + &ulpq->reasm, first_frag, pos); + if (retval) + retval->msg_flags |= MSG_EOR; +@@ -563,8 +562,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq) + * further. + */ + done: +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), +- &ulpq->reasm, first_frag, last_frag); ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, ++ first_frag, last_frag); + if (retval && is_last) + retval->msg_flags |= MSG_EOR; + +@@ -664,8 +663,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq) + * further. + */ + done: +- retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), +- &ulpq->reasm, first_frag, last_frag); ++ retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, ++ first_frag, last_frag); + return retval; + } + +-- +2.51.0 + diff --git a/queue-5.4/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-5.4/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..a745a84cb6 --- /dev/null +++ b/queue-5.4/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From 2a606e1787723adf2fb72c67aeea3b09f3db6434 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 9c721d70df9c6..9921041079781 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -337,6 +337,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -348,10 +349,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-5.4/series b/queue-5.4/series index 7fca1c3187..8f9ac8aa37 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -126,3 +126,20 @@ compiler_types-move-unused-static-inline-functions-w.patch nfs4-fix-state-renewals-missing-after-boot.patch hid-quirks-avoid-cooler-master-mm712-dongle-wakeup-b.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +sctp-get-netns-from-asoc-and-ep-base.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +tipc-simplify-the-finalize-work-queue.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net_sched-remove-need_resched-from-qdisc_run.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch diff --git a/queue-5.4/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-5.4/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..b90be331b0 --- /dev/null +++ b/queue-5.4/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From eb932dbd9cd940e1f035dbaffed183fafe409fdf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 3807ead54d3d5..81c0b123875ae 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -141,7 +141,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-5.4/tipc-simplify-the-finalize-work-queue.patch b/queue-5.4/tipc-simplify-the-finalize-work-queue.patch new file mode 100644 index 0000000000..b6cb4637ce --- /dev/null +++ b/queue-5.4/tipc-simplify-the-finalize-work-queue.patch @@ -0,0 +1,164 @@ +From fa200a99d84c1cf6f84dfd187553e3d7f5df8807 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 May 2021 10:09:08 +0800 +Subject: tipc: simplify the finalize work queue + +From: Xin Long + +[ Upstream commit be07f056396d6bb40963c45a02951c566ddeef8e ] + +This patch is to use "struct work_struct" for the finalize work queue +instead of "struct tipc_net_work", as it can get the "net" and "addr" +from tipc_net's other members and there is no need to add extra net +and addr in tipc_net by defining "struct tipc_net_work". + +Note that it's safe to get net from tn->bcl as bcl is always released +after the finalize work queue is done. + +Signed-off-by: Xin Long +Acked-by: Jon Maloy +Signed-off-by: David S. Miller +Stable-dep-of: 0725e6afb551 ("tipc: Fix use-after-free in tipc_mon_reinit_self().") +Signed-off-by: Sasha Levin +--- + net/tipc/core.c | 4 ++-- + net/tipc/core.h | 8 +------- + net/tipc/discover.c | 4 ++-- + net/tipc/link.c | 5 +++++ + net/tipc/link.h | 1 + + net/tipc/net.c | 15 +++------------ + 6 files changed, 14 insertions(+), 23 deletions(-) + +diff --git a/net/tipc/core.c b/net/tipc/core.c +index 58ee5ee707816..cce4cde3f5f18 100644 +--- a/net/tipc/core.c ++++ b/net/tipc/core.c +@@ -59,7 +59,7 @@ static int __net_init tipc_init_net(struct net *net) + tn->trial_addr = 0; + tn->addr_trial_end = 0; + tn->capabilities = TIPC_NODE_CAPABILITIES; +- INIT_WORK(&tn->final_work.work, tipc_net_finalize_work); ++ INIT_WORK(&tn->work, tipc_net_finalize_work); + memset(tn->node_id, 0, sizeof(tn->node_id)); + memset(tn->node_id_string, 0, sizeof(tn->node_id_string)); + tn->mon_threshold = TIPC_DEF_MON_THRESHOLD; +@@ -101,7 +101,7 @@ static void __net_exit tipc_exit_net(struct net *net) + + tipc_detach_loopback(net); + /* Make sure the tipc_net_finalize_work() finished */ +- cancel_work_sync(&tn->final_work.work); ++ cancel_work_sync(&tn->work); + tipc_net_stop(net); + + tipc_bcast_stop(net); +diff --git a/net/tipc/core.h b/net/tipc/core.h +index 59f97ef12e60d..32c5945c89338 100644 +--- a/net/tipc/core.h ++++ b/net/tipc/core.h +@@ -87,12 +87,6 @@ extern unsigned int tipc_net_id __read_mostly; + extern int sysctl_tipc_rmem[3] __read_mostly; + extern int sysctl_tipc_named_timeout __read_mostly; + +-struct tipc_net_work { +- struct work_struct work; +- struct net *net; +- u32 addr; +-}; +- + struct tipc_net { + u8 node_id[NODE_ID_LEN]; + u32 node_addr; +@@ -143,7 +137,7 @@ struct tipc_net { + struct packet_type loopback_pt; + + /* Work item for net finalize */ +- struct tipc_net_work final_work; ++ struct work_struct work; + /* The numbers of work queues in schedule */ + atomic_t wq_count; + }; +diff --git a/net/tipc/discover.c b/net/tipc/discover.c +index 9c64567f8a741..a6aa9ecc4a0bb 100644 +--- a/net/tipc/discover.c ++++ b/net/tipc/discover.c +@@ -167,7 +167,7 @@ static bool tipc_disc_addr_trial_msg(struct tipc_discoverer *d, + + /* Apply trial address if we just left trial period */ + if (!trial && !self) { +- tipc_sched_net_finalize(net, tn->trial_addr); ++ schedule_work(&tn->work); + msg_set_prevnode(buf_msg(d->skb), tn->trial_addr); + msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); + } +@@ -310,7 +310,7 @@ static void tipc_disc_timeout(struct timer_list *t) + if (!time_before(jiffies, tn->addr_trial_end) && !tipc_own_addr(net)) { + mod_timer(&d->timer, jiffies + TIPC_DISC_INIT); + spin_unlock_bh(&d->lock); +- tipc_sched_net_finalize(net, tn->trial_addr); ++ schedule_work(&tn->work); + return; + } + +diff --git a/net/tipc/link.c b/net/tipc/link.c +index 2052649fb537e..bf7e6fd855485 100644 +--- a/net/tipc/link.c ++++ b/net/tipc/link.c +@@ -332,6 +332,11 @@ char tipc_link_plane(struct tipc_link *l) + return l->net_plane; + } + ++struct net *tipc_link_net(struct tipc_link *l) ++{ ++ return l->net; ++} ++ + void tipc_link_update_caps(struct tipc_link *l, u16 capabilities) + { + l->peer_caps = capabilities; +diff --git a/net/tipc/link.h b/net/tipc/link.h +index adcad65e761ce..5ac43acce958a 100644 +--- a/net/tipc/link.h ++++ b/net/tipc/link.h +@@ -151,4 +151,5 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, + int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, + struct sk_buff_head *xmitq); + bool tipc_link_too_silent(struct tipc_link *l); ++struct net *tipc_link_net(struct tipc_link *l); + #endif +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 2498ce8b83c1a..3807ead54d3d5 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -41,6 +41,7 @@ + #include "socket.h" + #include "node.h" + #include "bcast.h" ++#include "link.h" + #include "netlink.h" + #include "monitor.h" + +@@ -138,19 +139,9 @@ static void tipc_net_finalize(struct net *net, u32 addr) + + void tipc_net_finalize_work(struct work_struct *work) + { +- struct tipc_net_work *fwork; ++ struct tipc_net *tn = container_of(work, struct tipc_net, work); + +- fwork = container_of(work, struct tipc_net_work, work); +- tipc_net_finalize(fwork->net, fwork->addr); +-} +- +-void tipc_sched_net_finalize(struct net *net, u32 addr) +-{ +- struct tipc_net *tn = tipc_net(net); +- +- tn->final_work.net = net; +- tn->final_work.addr = addr; +- schedule_work(&tn->final_work.work); ++ tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-5.4/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-5.4/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..c15c517170 --- /dev/null +++ b/queue-5.4/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From 800e8b73c1e6c7f429b54828067b77e7e624fcf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 4c805530edfb6..e8e72271fbb8f 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -4669,10 +4669,14 @@ void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 + diff --git a/queue-6.1/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch b/queue-6.1/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch new file mode 100644 index 0000000000..282476b48b --- /dev/null +++ b/queue-6.1/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch @@ -0,0 +1,49 @@ +From b37830869162339e719afc3e29f8f098e4b331a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:42 +0530 +Subject: ACPI: CPPC: Check _CPC validity for only the online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 6dd3b8a709a130a4d55c866af9804c81b8486d28 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function acpi_cpc_valid() checks for the validity of the +_CPC object for all the present CPUs. This breaks when the kernel is +booted with "nosmt=force". + +Hence check the validity of the _CPC objects of only the online CPUs. + +Fixes: 2aeca6bd0277 ("ACPI: CPPC: Check present CPUs for determining _CPC is valid") +Reported-by: Christopher Harris +Closes: https://lore.kernel.org/lkml/CAM+eXpdDT7KjLV0AxEwOLkSJ2QtrsvGvjA2cCHvt1d0k2_C4Cw@mail.gmail.com/ +Suggested-by: Mario Limonciello +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Tested-by: Chrisopher Harris +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-3-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 504fe14c566e3..6d89299af3bbe 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -440,7 +440,7 @@ bool acpi_cpc_valid(void) + if (acpi_disabled) + return false; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + if (!cpc_ptr) + return false; +-- +2.51.0 + diff --git a/queue-6.1/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch b/queue-6.1/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch new file mode 100644 index 0000000000..a2c0995beb --- /dev/null +++ b/queue-6.1/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch @@ -0,0 +1,45 @@ +From 6e34396a3b84db1d9e0c3fb003552a3c9e13cc7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:44 +0530 +Subject: ACPI: CPPC: Limit perf ctrs in PCC check only to online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 0fce75870666b46b700cfbd3216380b422f975da ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPU via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_perf_ctrs_in_pcc() checks if the CPPC +perf-ctrs are in a PCC region for all the present CPUs, which breaks +when the kernel is booted with "nosmt=force". + +Hence, limit the check only to the online CPUs. + +Fixes: ae2df912d1a5 ("ACPI: CPPC: Disable FIE if registers in PCC regions") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-5-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 3aa4c489ca5bc..27729a1f34cb0 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -1336,7 +1336,7 @@ bool cppc_perf_ctrs_in_pcc(void) + { + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + struct cpc_register_resource *ref_perf_reg; + struct cpc_desc *cpc_desc; + +-- +2.51.0 + diff --git a/queue-6.1/acpi-cppc-perform-fast-check-switch-only-for-online-.patch b/queue-6.1/acpi-cppc-perform-fast-check-switch-only-for-online-.patch new file mode 100644 index 0000000000..c2169ba4e4 --- /dev/null +++ b/queue-6.1/acpi-cppc-perform-fast-check-switch-only-for-online-.patch @@ -0,0 +1,45 @@ +From 728c3e233ac332a97b4facc3f3ae149c2f819178 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:43 +0530 +Subject: ACPI: CPPC: Perform fast check switch only for online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 8821c8e80a65bc4eb73daf63b34aac6b8ad69461 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_allow_fast_switch() checks for the validity +of the _CPC object for all the present CPUs. This breaks when the +kernel is booted with "nosmt=force". + +Check fast_switch capability only on online CPUs + +Fixes: 15eece6c5b05 ("ACPI: CPPC: Fix NULL pointer dereference when nosmp is used") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-4-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 6d89299af3bbe..3aa4c489ca5bc 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -456,7 +456,7 @@ bool cppc_allow_fast_switch(void) + struct cpc_desc *cpc_ptr; + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF]; + if (!CPC_IN_SYSTEM_MEMORY(desired_reg) && +-- +2.51.0 + diff --git a/queue-6.1/af_unix-initialise-scc_index-in-unix_add_edge.patch b/queue-6.1/af_unix-initialise-scc_index-in-unix_add_edge.patch new file mode 100644 index 0000000000..cacf39e13c --- /dev/null +++ b/queue-6.1/af_unix-initialise-scc_index-in-unix_add_edge.patch @@ -0,0 +1,139 @@ +From 8d9bbdfc02ac8d6c73a08b9d80f93bb02c09135a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 02:52:22 +0000 +Subject: af_unix: Initialise scc_index in unix_add_edge(). + +From: Kuniyuki Iwashima + +[ Upstream commit 60e6489f8e3b086bd1130ad4450a2c112e863791 ] + +Quang Le reported that the AF_UNIX GC could garbage-collect a +receive queue of an alive in-flight socket, with a nice repro. + +The repro consists of three stages. + + 1) + 1-a. Create a single cyclic reference with many sockets + 1-b. close() all sockets + 1-c. Trigger GC + + 2) + 2-a. Pass sk-A to an embryo sk-B + 2-b. Pass sk-X to sk-X + 2-c. Trigger GC + + 3) + 3-a. accept() the embryo sk-B + 3-b. Pass sk-B to sk-C + 3-c. close() the in-flight sk-A + 3-d. Trigger GC + +As of 2-c, sk-A and sk-X are linked to unix_unvisited_vertices, +and unix_walk_scc() groups them into two different SCCs: + + unix_sk(sk-A)->vertex->scc_index = 2 (UNIX_VERTEX_INDEX_START) + unix_sk(sk-X)->vertex->scc_index = 3 + +Once GC completes, unix_graph_grouped is set to true. +Also, unix_graph_maybe_cyclic is set to true due to sk-X's +cyclic self-reference, which makes close() trigger GC. + +At 3-b, unix_add_edge() allocates unix_sk(sk-B)->vertex and +links it to unix_unvisited_vertices. + +unix_update_graph() is called at 3-a. and 3-b., but neither +unix_graph_grouped nor unix_graph_maybe_cyclic is changed +because both sk-B's listener and sk-C are not in-flight. + +3-c decrements sk-A's file refcnt to 1. + +Since unix_graph_grouped is true at 3-d, unix_walk_scc_fast() +is finally called and iterates 3 sockets sk-A, sk-B, and sk-X: + + sk-A -> sk-B (-> sk-C) + sk-X -> sk-X + +This is totally fine. All of them are not yet close()d and +should be grouped into different SCCs. + +However, unix_vertex_dead() misjudges that sk-A and sk-B are +in the same SCC and sk-A is dead. + + unix_sk(sk-A)->scc_index == unix_sk(sk-B)->scc_index <-- Wrong! + && + sk-A's file refcnt == unix_sk(sk-A)->vertex->out_degree + ^-- 1 in-flight count for sk-B + -> sk-A is dead !? + +The problem is that unix_add_edge() does not initialise scc_index. + +Stage 1) is used for heap spraying, making a newly allocated +vertex have vertex->scc_index == 2 (UNIX_VERTEX_INDEX_START) +set by unix_walk_scc() at 1-c. + +Let's track the max SCC index from the previous unix_walk_scc() +call and assign the max + 1 to a new vertex's scc_index. + +This way, we can continue to avoid Tarjan's algorithm while +preventing misjudgments. + +Fixes: ad081928a8b0 ("af_unix: Avoid Tarjan's algorithm if unnecessary.") +Reported-by: Quang Le +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20251109025233.3659187-1-kuniyu@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/garbage.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 0068e758be4dd..66fd606c43f45 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -136,6 +136,7 @@ enum unix_vertex_index { + }; + + static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1; ++static unsigned long unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + { +@@ -144,6 +145,7 @@ static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + if (!vertex) { + vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry); + vertex->index = unix_vertex_unvisited_index; ++ vertex->scc_index = ++unix_vertex_max_scc_index; + vertex->out_degree = 0; + INIT_LIST_HEAD(&vertex->edges); + INIT_LIST_HEAD(&vertex->scc_entry); +@@ -480,10 +482,15 @@ static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_inde + scc_dead = unix_vertex_dead(v); + } + +- if (scc_dead) ++ if (scc_dead) { + unix_collect_skb(&scc, hitlist); +- else if (!unix_graph_maybe_cyclic) +- unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } else { ++ if (unix_vertex_max_scc_index < vertex->scc_index) ++ unix_vertex_max_scc_index = vertex->scc_index; ++ ++ if (!unix_graph_maybe_cyclic) ++ unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } + + list_del(&scc); + } +@@ -498,6 +505,7 @@ static void unix_walk_scc(struct sk_buff_head *hitlist) + unsigned long last_index = UNIX_VERTEX_INDEX_START; + + unix_graph_maybe_cyclic = false; ++ unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + /* Visit every vertex exactly once. + * __unix_walk_scc() moves visited vertices to unix_visited_vertices. +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-6.1/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..1bb354c11f --- /dev/null +++ b/queue-6.1/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From f833b8e78661757e60bec78776cac5be633f4ee0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 57553abde4180..347361ff0cc87 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -52,6 +52,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -60,6 +65,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1013,41 +1020,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-6.1/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..7946302a1a --- /dev/null +++ b/queue-6.1/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From b6a617bb1ccac14562c18f0b28356adee0c7995c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 003c8ae104f29..57553abde4180 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -956,10 +956,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -970,13 +971,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1103,7 +1123,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1140,7 +1160,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-6.1/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..1736168f73 --- /dev/null +++ b/queue-6.1/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From 57b482ac6b391c05a154d191e621a0115cfd30aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index db119071a0ea0..003c8ae104f29 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -288,6 +288,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-6.1/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..4c8b807259 --- /dev/null +++ b/queue-6.1/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From a3e0b8c4cc233e9faae9c2a0641705b68b08b3ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 29130160066a5..70cdcef684138 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4204,6 +4204,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4214,17 +4219,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-6.1/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..b4f2706522 --- /dev/null +++ b/queue-6.1/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 80c1d177b47316d89ea31b76394fa4401a3e43f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 8bb6d2690e2b9..ea82a468b314a 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -521,6 +521,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-6.1/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch b/queue-6.1/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch new file mode 100644 index 0000000000..89d9f54d3e --- /dev/null +++ b/queue-6.1/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch @@ -0,0 +1,56 @@ +From cb4f8ffc3eee952cab3c4f000317485fb6ea5ead Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Nov 2025 20:16:12 +0200 +Subject: Bluetooth: MGMT: cancel mesh send timer when hdev removed + +From: Pauli Virtanen + +[ Upstream commit 55fb52ffdd62850d667ebed842815e072d3c9961 ] + +mesh_send_done timer is not canceled when hdev is removed, which causes +crash if the timer triggers after hdev is gone. + +Cancel the timer when MGMT removes the hdev, like other MGMT timers. + +Should fix the BUG: sporadically seen by BlueZ test bot +(in "Mesh - Send cancel - 1" test). + +Log: +------ +BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 +... +Freed by task 36: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3a/0x60 + __kasan_slab_free+0x43/0x70 + kfree+0x103/0x500 + device_release+0x9a/0x210 + kobject_put+0x100/0x1e0 + vhci_release+0x18b/0x240 +------ + +Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh") +Link: https://lore.kernel.org/linux-bluetooth/67364c09.0c0a0220.113cba.39ff@mx.google.com/ +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 9bd4d5bc84db1..b89c3fc364b83 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9501,6 +9501,7 @@ void mgmt_index_removed(struct hci_dev *hdev) + cancel_delayed_work_sync(&hdev->discov_off); + cancel_delayed_work_sync(&hdev->service_cache); + cancel_delayed_work_sync(&hdev->rpa_expired); ++ cancel_delayed_work_sync(&hdev->mesh_send_done); + } + + void mgmt_power_on(struct hci_dev *hdev, int err) +-- +2.51.0 + diff --git a/queue-6.1/hsr-fix-supervision-frame-sending-on-hsrv0.patch b/queue-6.1/hsr-fix-supervision-frame-sending-on-hsrv0.patch new file mode 100644 index 0000000000..1ea1266a4a --- /dev/null +++ b/queue-6.1/hsr-fix-supervision-frame-sending-on-hsrv0.patch @@ -0,0 +1,50 @@ +From 5a34eaeca220b8e7ee2a3c715f0c99ecc4e13b8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:32 +0100 +Subject: hsr: Fix supervision frame sending on HSRv0 + +From: Felix Maurer + +[ Upstream commit 96a3a03abf3d8cc38cd9cb0d280235fbcf7c3f7f ] + +On HSRv0, no supervision frames were sent. The supervison frames were +generated successfully, but failed the check for a sufficiently long mac +header, i.e., at least sizeof(struct hsr_ethhdr), in hsr_fill_frame_info() +because the mac header only contained the ethernet header. + +Fix this by including the HSR header in the mac header when generating HSR +supervision frames. Note that the mac header now also includes the TLV +fields. This matches how we set the headers on rx and also the size of +struct hsrv0_ethhdr_sp. + +Reported-by: Hangbin Liu +Closes: https://lore.kernel.org/netdev/aMONxDXkzBZZRfE5@fedora/ +Fixes: 9cfb5e7f0ded ("net: hsr: fix hsr_init_sk() vs network/transport headers.") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Tested-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/4354114fea9a642fe71f49aeeb6c6159d1d61840.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 0b23d52b8d87a..81eaae4c19da1 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -313,6 +313,9 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + } + + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); ++ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); ++ skb_reset_mac_len(skb); ++ + set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + +-- +2.51.0 + diff --git a/queue-6.1/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-6.1/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..e106e05104 --- /dev/null +++ b/queue-6.1/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From f2259a4c9c4bf1d7703036dd2a88a1b7772b3c29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index ca271d7a388b4..c8f897afb30a6 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1681,6 +1681,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + page = rxq->rx_skb_info[index].page; +-- +2.51.0 + diff --git a/queue-6.1/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-6.1/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..a7c928f80e --- /dev/null +++ b/queue-6.1/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From 372570c2edecc20a316a1107677840010f1ff178 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 7a2dce8d12433..726799b1e7faf 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -80,8 +80,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5-expose-shared-buffer-registers-bits-and-str.patch b/queue-6.1/net-mlx5-expose-shared-buffer-registers-bits-and-str.patch new file mode 100644 index 0000000000..dcb3c0f6d7 --- /dev/null +++ b/queue-6.1/net-mlx5-expose-shared-buffer-registers-bits-and-str.patch @@ -0,0 +1,111 @@ +From 54ad4fc7e71950f760342ad99c028e73aa388ab3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 18:00:17 +0200 +Subject: net/mlx5: Expose shared buffer registers bits and structs + +From: Maher Sanalla + +[ Upstream commit 8d231dbc3b10155727bcfa9e543d397ad357f14f ] + +Add the shared receive buffer management and configuration registers: +1. SBPR - Shared Buffer Pools Register +2. SBCM - Shared Buffer Class Management Register + +Signed-off-by: Maher Sanalla +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: 9fcc2b6c1052 ("net/mlx5e: Fix potentially misleading debug message") +Signed-off-by: Sasha Levin +--- + include/linux/mlx5/driver.h | 2 ++ + include/linux/mlx5/mlx5_ifc.h | 61 +++++++++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index b05f69a8306c9..9af7180eac9e3 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -100,6 +100,8 @@ enum { + }; + + enum { ++ MLX5_REG_SBPR = 0xb001, ++ MLX5_REG_SBCM = 0xb002, + MLX5_REG_QPTS = 0x4002, + MLX5_REG_QETCR = 0x4005, + MLX5_REG_QTCT = 0x400a, +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 271c5a87751fe..4df7b3d358607 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -10930,6 +10930,67 @@ struct mlx5_ifc_pbmc_reg_bits { + u8 reserved_at_2e0[0x80]; + }; + ++struct mlx5_ifc_sbpr_reg_bits { ++ u8 desc[0x1]; ++ u8 snap[0x1]; ++ u8 reserved_at_2[0x4]; ++ u8 dir[0x2]; ++ u8 reserved_at_8[0x14]; ++ u8 pool[0x4]; ++ ++ u8 infi_size[0x1]; ++ u8 reserved_at_21[0x7]; ++ u8 size[0x18]; ++ ++ u8 reserved_at_40[0x1c]; ++ u8 mode[0x4]; ++ ++ u8 reserved_at_60[0x8]; ++ u8 buff_occupancy[0x18]; ++ ++ u8 clr[0x1]; ++ u8 reserved_at_81[0x7]; ++ u8 max_buff_occupancy[0x18]; ++ ++ u8 reserved_at_a0[0x8]; ++ u8 ext_buff_occupancy[0x18]; ++}; ++ ++struct mlx5_ifc_sbcm_reg_bits { ++ u8 desc[0x1]; ++ u8 snap[0x1]; ++ u8 reserved_at_2[0x6]; ++ u8 local_port[0x8]; ++ u8 pnat[0x2]; ++ u8 pg_buff[0x6]; ++ u8 reserved_at_18[0x6]; ++ u8 dir[0x2]; ++ ++ u8 reserved_at_20[0x1f]; ++ u8 exc[0x1]; ++ ++ u8 reserved_at_40[0x40]; ++ ++ u8 reserved_at_80[0x8]; ++ u8 buff_occupancy[0x18]; ++ ++ u8 clr[0x1]; ++ u8 reserved_at_a1[0x7]; ++ u8 max_buff_occupancy[0x18]; ++ ++ u8 reserved_at_c0[0x8]; ++ u8 min_buff[0x18]; ++ ++ u8 infi_max[0x1]; ++ u8 reserved_at_e1[0x7]; ++ u8 max_buff[0x18]; ++ ++ u8 reserved_at_100[0x20]; ++ ++ u8 reserved_at_120[0x1c]; ++ u8 pool[0x4]; ++}; ++ + struct mlx5_ifc_qtct_reg_bits { + u8 reserved_at_0[0x8]; + u8 port_number[0x8]; +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-add-api-to-query-modify-sbpr-and-sbcm-regi.patch b/queue-6.1/net-mlx5e-add-api-to-query-modify-sbpr-and-sbcm-regi.patch new file mode 100644 index 0000000000..9f21970fb8 --- /dev/null +++ b/queue-6.1/net-mlx5e-add-api-to-query-modify-sbpr-and-sbcm-regi.patch @@ -0,0 +1,126 @@ +From 24139235afbb4735298eb34296763a73d9d0e1c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 18:23:40 +0200 +Subject: net/mlx5e: Add API to query/modify SBPR and SBCM registers + +From: Maher Sanalla + +[ Upstream commit 11f0996d5c6023f4889882c8d088ec76a050d704 ] + +To allow users to configure shared receive buffer parameters through +dcbnl callbacks, expose an API to query and modify SBPR and SBCM registers, +which will be used in the upcoming patch. + +Signed-off-by: Maher Sanalla +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: 9fcc2b6c1052 ("net/mlx5e: Fix potentially misleading debug message") +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/en/port.c | 72 +++++++++++++++++++ + .../net/ethernet/mellanox/mlx5/core/en/port.h | 6 ++ + 2 files changed, 78 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c +index 89510cac46c22..505ba41195b93 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c +@@ -287,6 +287,78 @@ int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in) + return err; + } + ++int mlx5e_port_query_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir, ++ u8 pool_idx, void *out, int size_out) ++{ ++ u32 in[MLX5_ST_SZ_DW(sbpr_reg)] = {}; ++ ++ MLX5_SET(sbpr_reg, in, desc, desc); ++ MLX5_SET(sbpr_reg, in, dir, dir); ++ MLX5_SET(sbpr_reg, in, pool, pool_idx); ++ ++ return mlx5_core_access_reg(mdev, in, sizeof(in), out, size_out, MLX5_REG_SBPR, 0, 0); ++} ++ ++int mlx5e_port_set_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir, ++ u8 pool_idx, u32 infi_size, u32 size) ++{ ++ u32 out[MLX5_ST_SZ_DW(sbpr_reg)] = {}; ++ u32 in[MLX5_ST_SZ_DW(sbpr_reg)] = {}; ++ ++ MLX5_SET(sbpr_reg, in, desc, desc); ++ MLX5_SET(sbpr_reg, in, dir, dir); ++ MLX5_SET(sbpr_reg, in, pool, pool_idx); ++ MLX5_SET(sbpr_reg, in, infi_size, infi_size); ++ MLX5_SET(sbpr_reg, in, size, size); ++ MLX5_SET(sbpr_reg, in, mode, 1); ++ ++ return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_SBPR, 0, 1); ++} ++ ++static int mlx5e_port_query_sbcm(struct mlx5_core_dev *mdev, u32 desc, ++ u8 pg_buff_idx, u8 dir, void *out, ++ int size_out) ++{ ++ u32 in[MLX5_ST_SZ_DW(sbcm_reg)] = {}; ++ ++ MLX5_SET(sbcm_reg, in, desc, desc); ++ MLX5_SET(sbcm_reg, in, local_port, 1); ++ MLX5_SET(sbcm_reg, in, pg_buff, pg_buff_idx); ++ MLX5_SET(sbcm_reg, in, dir, dir); ++ ++ return mlx5_core_access_reg(mdev, in, sizeof(in), out, size_out, MLX5_REG_SBCM, 0, 0); ++} ++ ++int mlx5e_port_set_sbcm(struct mlx5_core_dev *mdev, u32 desc, u8 pg_buff_idx, ++ u8 dir, u8 infi_size, u32 max_buff, u8 pool_idx) ++{ ++ u32 out[MLX5_ST_SZ_DW(sbcm_reg)] = {}; ++ u32 in[MLX5_ST_SZ_DW(sbcm_reg)] = {}; ++ u32 min_buff; ++ int err; ++ u8 exc; ++ ++ err = mlx5e_port_query_sbcm(mdev, desc, pg_buff_idx, dir, out, ++ sizeof(out)); ++ if (err) ++ return err; ++ ++ exc = MLX5_GET(sbcm_reg, out, exc); ++ min_buff = MLX5_GET(sbcm_reg, out, min_buff); ++ ++ MLX5_SET(sbcm_reg, in, desc, desc); ++ MLX5_SET(sbcm_reg, in, local_port, 1); ++ MLX5_SET(sbcm_reg, in, pg_buff, pg_buff_idx); ++ MLX5_SET(sbcm_reg, in, dir, dir); ++ MLX5_SET(sbcm_reg, in, exc, exc); ++ MLX5_SET(sbcm_reg, in, min_buff, min_buff); ++ MLX5_SET(sbcm_reg, in, infi_max, infi_size); ++ MLX5_SET(sbcm_reg, in, max_buff, max_buff); ++ MLX5_SET(sbcm_reg, in, pool, pool_idx); ++ ++ return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_SBCM, 0, 1); ++} ++ + /* buffer[i]: buffer that priority i mapped to */ + int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) + { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h +index 7a7defe607926..3f474e370828d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h +@@ -57,6 +57,12 @@ u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed, + bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev); + int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out); + int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in); ++int mlx5e_port_query_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir, ++ u8 pool_idx, void *out, int size_out); ++int mlx5e_port_set_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir, ++ u8 pool_idx, u32 infi_size, u32 size); ++int mlx5e_port_set_sbcm(struct mlx5_core_dev *mdev, u32 desc, u8 pg_buff_idx, ++ u8 dir, u8 infi_size, u32 max_buff, u8 pool_idx); + int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer); + int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer); + +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-consider-internal-buffers-size-in-port-buf.patch b/queue-6.1/net-mlx5e-consider-internal-buffers-size-in-port-buf.patch new file mode 100644 index 0000000000..9fe172b86d --- /dev/null +++ b/queue-6.1/net-mlx5e-consider-internal-buffers-size-in-port-buf.patch @@ -0,0 +1,209 @@ +From c292ae93098bfd55c817b8fceeebcc029464d45f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 May 2023 17:31:40 +0300 +Subject: net/mlx5e: Consider internal buffers size in port buffer calculations + +From: Maher Sanalla + +[ Upstream commit 81fe2be062915e2a2fdc494c3cd90e946e946c25 ] + +Currently, when a user triggers a change in port buffer headroom +(buffers 0-7), the driver checks that the requested headroom does +not exceed the total port buffer size. However, this check does not +take into account the internal buffers (buffers 8-9), which are also +part of the total port buffer. This can result in treating invalid port +buffer change requests as valid, causing unintended changes to the shared +buffer. + +To address this, include the internal buffers size in the calculation of +available port buffer space which ensures that port buffer requests do not +exceed the correct limit. + +Furthermore, remove internal buffers (8-9) size from the total_size +calculation as these buffers are reserved for internal use and are not +exposed to the user. + +While at it, add verbosity to the debug prints in +mlx5e_port_query_buffer() function to ease future debugging. + +Fixes: ecdf2dadee8e ("net/mlx5e: Receive buffer support for DCBX") +Signed-off-by: Maher Sanalla +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: 9fcc2b6c1052 ("net/mlx5e: Fix potentially misleading debug message") +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.c | 42 ++++++++++++------- + .../mellanox/mlx5/core/en/port_buffer.h | 8 ++-- + .../ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 ++-- + 3 files changed, 36 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index e846417a8ca94..b02cba086b366 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -51,7 +51,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + if (err) + goto out; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]); + port_buffer->buffer[i].lossy = + MLX5_GET(bufferx_reg, buffer, lossy); +@@ -73,14 +73,24 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + port_buffer->buffer[i].lossy); + } + +- port_buffer->headroom_size = total_used; ++ port_buffer->internal_buffers_size = 0; ++ for (i = MLX5E_MAX_NETWORK_BUFFER; i < MLX5E_TOTAL_BUFFERS; i++) { ++ buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]); ++ port_buffer->internal_buffers_size += ++ MLX5_GET(bufferx_reg, buffer, size) * port_buff_cell_sz; ++ } ++ + port_buffer->port_buffer_size = + MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz; +- port_buffer->spare_buffer_size = +- port_buffer->port_buffer_size - total_used; +- +- mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n", +- port_buffer->port_buffer_size, ++ port_buffer->headroom_size = total_used; ++ port_buffer->spare_buffer_size = port_buffer->port_buffer_size - ++ port_buffer->internal_buffers_size - ++ port_buffer->headroom_size; ++ ++ mlx5e_dbg(HW, priv, ++ "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n", ++ port_buffer->port_buffer_size, port_buffer->headroom_size, ++ port_buffer->internal_buffers_size, + port_buffer->spare_buffer_size); + out: + kfree(out); +@@ -206,11 +216,11 @@ static int port_update_pool_cfg(struct mlx5_core_dev *mdev, + if (!MLX5_CAP_GEN(mdev, sbcam_reg)) + return 0; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) + lossless_buff_count += ((port_buffer->buffer[i].size) && + (!(port_buffer->buffer[i].lossy))); + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + p = select_sbcm_params(&port_buffer->buffer[i], lossless_buff_count); + err = mlx5e_port_set_sbcm(mdev, 0, i, + MLX5_INGRESS_DIR, +@@ -293,7 +303,7 @@ static int port_set_buffer(struct mlx5e_priv *priv, + if (err) + goto out; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); + u64 size = port_buffer->buffer[i].size; + u64 xoff = port_buffer->buffer[i].xoff; +@@ -351,7 +361,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer, + { + int i; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + if (port_buffer->buffer[i].lossy) { + port_buffer->buffer[i].xoff = 0; + port_buffer->buffer[i].xon = 0; +@@ -408,7 +418,7 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev, + int err; + int i; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + prio_count = 0; + lossy_count = 0; + +@@ -515,7 +525,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + + if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { + update_prio2buffer = true; +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) + mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n", + __func__, i, prio2buffer[i]); + +@@ -530,7 +540,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + } + + if (change & MLX5E_PORT_BUFFER_SIZE) { +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); + if (!port_buffer.buffer[i].lossy && !buffer_size[i]) { + mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n", +@@ -544,7 +554,9 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + + mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used); + +- if (total_used > port_buffer.port_buffer_size) ++ if (total_used > port_buffer.headroom_size && ++ (total_used - port_buffer.headroom_size) > ++ port_buffer.spare_buffer_size) + return -EINVAL; + + update_buffer = true; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index a6ef118de758f..f4a19ffbb641c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -35,7 +35,8 @@ + #include "en.h" + #include "port.h" + +-#define MLX5E_MAX_BUFFER 8 ++#define MLX5E_MAX_NETWORK_BUFFER 8 ++#define MLX5E_TOTAL_BUFFERS 10 + #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */ + + #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \ +@@ -60,8 +61,9 @@ struct mlx5e_bufferx_reg { + struct mlx5e_port_buffer { + u32 port_buffer_size; + u32 spare_buffer_size; +- u32 headroom_size; +- struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; ++ u32 headroom_size; /* Buffers 0-7 */ ++ u32 internal_buffers_size; /* Buffers 8-9 */ ++ struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; + }; + + int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 2d20e2ff29677..55ceb6740291d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -935,9 +935,10 @@ static int mlx5e_dcbnl_getbuffer(struct net_device *dev, + if (err) + return err; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) + dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size; +- dcb_buffer->total_size = port_buffer.port_buffer_size; ++ dcb_buffer->total_size = port_buffer.port_buffer_size - ++ port_buffer.internal_buffers_size; + + return 0; + } +@@ -979,7 +980,7 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev, + if (err) + return err; + +- for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { + if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) { + changed |= MLX5E_PORT_BUFFER_SIZE; + buffer_size = dcb_buffer->buffer_size; +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-6.1/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..3bd11d8ba8 --- /dev/null +++ b/queue-6.1/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From 43c6e05267a40a2d7bcfad00bc9769b49572a7e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 89de92d064836..cfbf39f0f8727 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -587,18 +587,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-fix-potentially-misleading-debug-message.patch b/queue-6.1/net-mlx5e-fix-potentially-misleading-debug-message.patch new file mode 100644 index 0000000000..c453b14768 --- /dev/null +++ b/queue-6.1/net-mlx5e-fix-potentially-misleading-debug-message.patch @@ -0,0 +1,62 @@ +From fbb3fee62dfc56b8326a8b3a675a954443a2a579 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:53 +0200 +Subject: net/mlx5e: Fix potentially misleading debug message + +From: Gal Pressman + +[ Upstream commit 9fcc2b6c10523f7e75db6387946c86fcf19dc97e ] + +Change the debug message to print the correct units instead of always +assuming Gbps, as the value can be in either 100 Mbps or 1 Gbps units. + +Fixes: 5da8bc3effb6 ("net/mlx5e: DCBNL, Add debug messages log") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index ca096d8bcca60..29e633e6dd3f0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -590,6 +590,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + __u64 upper_limit_mbps; + __u64 upper_limit_gbps; + int i; ++ struct { ++ int scale; ++ const char *units_str; ++ } units[] = { ++ [MLX5_100_MBPS_UNIT] = { ++ .scale = 100, ++ .units_str = "Mbps", ++ }, ++ [MLX5_GBPS_UNIT] = { ++ .scale = 1, ++ .units_str = "Gbps", ++ }, ++ }; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); +@@ -620,8 +633,9 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", +- __func__, i, max_bw_value[i]); ++ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i, ++ max_bw_value[i] * units[max_bw_unit[i]].scale, ++ units[max_bw_unit[i]].units_str); + } + + return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit); +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-6.1/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..80200be6ee --- /dev/null +++ b/queue-6.1/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From 441f0a8a7dc86e36a288163858273422bd7ba3d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index cfbf39f0f8727..2d20e2ff29677 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -588,11 +588,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -604,10 +606,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-remove-mlx5e_dbg-and-msglvl-support.patch b/queue-6.1/net-mlx5e-remove-mlx5e_dbg-and-msglvl-support.patch new file mode 100644 index 0000000000..75b6ae30f1 --- /dev/null +++ b/queue-6.1/net-mlx5e-remove-mlx5e_dbg-and-msglvl-support.patch @@ -0,0 +1,321 @@ +From ff2411a9baa9cbaf9d6105c6464e78292c91f7f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Apr 2023 14:29:26 +0300 +Subject: net/mlx5e: Remove mlx5e_dbg() and msglvl support + +From: Gal Pressman + +[ Upstream commit 559f4c32ebff40a25199b5178d58c9283ac5eb9c ] + +The msglvl support was implemented using the mlx5e_dbg() macro which is +rarely used in the driver, and is not very useful when you can just use +dynamic debug instead. +Remove mlx5e_dbg() and convert its usages to netdev_dbg(). + +Signed-off-by: Gal Pressman +Reviewed-by: Tariq Toukan +Signed-off-by: Saeed Mahameed +Stable-dep-of: 9fcc2b6c1052 ("net/mlx5e: Fix potentially misleading debug message") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en.h | 10 ----- + .../mellanox/mlx5/core/en/port_buffer.c | 44 ++++++++++--------- + .../net/ethernet/mellanox/mlx5/core/en_arfs.c | 8 ++-- + .../ethernet/mellanox/mlx5/core/en_dcbnl.c | 26 +++++------ + .../ethernet/mellanox/mlx5/core/en_ethtool.c | 18 ++------ + .../net/ethernet/mellanox/mlx5/core/en_main.c | 5 +-- + 6 files changed, 45 insertions(+), 66 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index 0ee456480a488..906bf327cdef8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -165,15 +165,6 @@ struct page_pool; + #define MLX5E_MAX_KLM_PER_WQE(mdev) \ + MLX5E_KLM_ENTRIES_PER_WQE(MLX5_SEND_WQE_BB * mlx5e_get_max_sq_aligned_wqebbs(mdev)) + +-#define MLX5E_MSG_LEVEL NETIF_MSG_LINK +- +-#define mlx5e_dbg(mlevel, priv, format, ...) \ +-do { \ +- if (NETIF_MSG_##mlevel & (priv)->msglevel) \ +- netdev_warn(priv->netdev, format, \ +- ##__VA_ARGS__); \ +-} while (0) +- + #define mlx5e_state_dereference(priv, p) \ + rcu_dereference_protected((p), lockdep_is_held(&(priv)->state_lock)) + +@@ -901,7 +892,6 @@ struct mlx5e_priv { + #endif + /* priv data path fields - end */ + +- u32 msglevel; + unsigned long state; + struct mutex state_lock; /* Protects Interface state */ + struct mlx5e_rq drop_rq; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index b02cba086b366..9be06df2d6e82 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -65,12 +65,13 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + MLX5_GET(bufferx_reg, buffer, xoff_threshold) * port_buff_cell_sz; + total_used += port_buffer->buffer[i].size; + +- mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i, +- port_buffer->buffer[i].size, +- port_buffer->buffer[i].xon, +- port_buffer->buffer[i].xoff, +- port_buffer->buffer[i].epsb, +- port_buffer->buffer[i].lossy); ++ netdev_dbg(priv->netdev, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", ++ i, ++ port_buffer->buffer[i].size, ++ port_buffer->buffer[i].xon, ++ port_buffer->buffer[i].xoff, ++ port_buffer->buffer[i].epsb, ++ port_buffer->buffer[i].lossy); + } + + port_buffer->internal_buffers_size = 0; +@@ -87,11 +88,11 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + port_buffer->internal_buffers_size - + port_buffer->headroom_size; + +- mlx5e_dbg(HW, priv, +- "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n", +- port_buffer->port_buffer_size, port_buffer->headroom_size, +- port_buffer->internal_buffers_size, +- port_buffer->spare_buffer_size); ++ netdev_dbg(priv->netdev, ++ "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n", ++ port_buffer->port_buffer_size, port_buffer->headroom_size, ++ port_buffer->internal_buffers_size, ++ port_buffer->spare_buffer_size); + out: + kfree(out); + return err; +@@ -352,7 +353,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu) + + xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100; + +- mlx5e_dbg(HW, priv, "%s: xoff=%d\n", __func__, xoff); ++ netdev_dbg(priv->netdev, "%s: xoff=%d\n", __func__, xoff); + return xoff; + } + +@@ -484,6 +485,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + u8 *prio2buffer) + { + u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; ++ struct net_device *netdev = priv->netdev; + struct mlx5e_port_buffer port_buffer; + u32 xoff = calculate_xoff(priv, mtu); + bool update_prio2buffer = false; +@@ -495,7 +497,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + int err; + int i; + +- mlx5e_dbg(HW, priv, "%s: change=%x\n", __func__, change); ++ netdev_dbg(netdev, "%s: change=%x\n", __func__, change); + max_mtu = max_t(unsigned int, priv->netdev->max_mtu, MINIMUM_MAX_MTU); + + err = mlx5e_port_query_buffer(priv, &port_buffer); +@@ -510,8 +512,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + } + + if (change & MLX5E_PORT_BUFFER_PFC) { +- mlx5e_dbg(HW, priv, "%s: requested PFC per priority bitmask: 0x%x\n", +- __func__, pfc->pfc_en); ++ netdev_dbg(netdev, "%s: requested PFC per priority bitmask: 0x%x\n", ++ __func__, pfc->pfc_en); + err = mlx5e_port_query_priority2buffer(priv->mdev, buffer); + if (err) + return err; +@@ -526,8 +528,8 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { + update_prio2buffer = true; + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) +- mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n", +- __func__, i, prio2buffer[i]); ++ netdev_dbg(priv->netdev, "%s: requested to map prio[%d] to buffer %d\n", ++ __func__, i, prio2buffer[i]); + + err = fill_pfc_en(priv->mdev, &curr_pfc_en); + if (err) +@@ -541,10 +543,10 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + + if (change & MLX5E_PORT_BUFFER_SIZE) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { +- mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); ++ netdev_dbg(priv->netdev, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); + if (!port_buffer.buffer[i].lossy && !buffer_size[i]) { +- mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n", +- __func__, i); ++ netdev_dbg(priv->netdev, "%s: lossless buffer[%d] size cannot be zero\n", ++ __func__, i); + return -EINVAL; + } + +@@ -552,7 +554,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + total_used += buffer_size[i]; + } + +- mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used); ++ netdev_dbg(priv->netdev, "%s: total buffer requested=%d\n", __func__, total_used); + + if (total_used > port_buffer.headroom_size && + (total_used - port_buffer.headroom_size) > +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +index ad51edf553185..16fade5b2d7ea 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +@@ -595,10 +595,10 @@ static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv, + if (IS_ERR(rule)) { + err = PTR_ERR(rule); + priv->channel_stats[arfs_rule->rxq]->rq.arfs_err++; +- mlx5e_dbg(HW, priv, +- "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n", +- __func__, arfs_rule->filter_id, arfs_rule->rxq, +- tuple->ip_proto, err); ++ netdev_dbg(priv->netdev, ++ "%s: add rule(filter id=%d, rq idx=%d, ip proto=0x%x) failed,err=%d\n", ++ __func__, arfs_rule->filter_id, arfs_rule->rxq, ++ tuple->ip_proto, err); + } + + out: +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 55ceb6740291d..ca096d8bcca60 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -275,10 +275,10 @@ static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets + memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa)); + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- mlx5e_dbg(HW, priv, "%s: prio_%d <=> tc_%d\n", +- __func__, i, ets->prio_tc[i]); +- mlx5e_dbg(HW, priv, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n", +- __func__, i, tc_tx_bw[i], tc_group[i]); ++ netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n", ++ __func__, i, ets->prio_tc[i]); ++ netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n", ++ __func__, i, tc_tx_bw[i], tc_group[i]); + } + + return err; +@@ -399,9 +399,9 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev, + } + + if (!ret) { +- mlx5e_dbg(HW, priv, +- "%s: PFC per priority bit mask: 0x%x\n", +- __func__, pfc->pfc_en); ++ netdev_dbg(dev, ++ "%s: PFC per priority bit mask: 0x%x\n", ++ __func__, pfc->pfc_en); + } + return ret; + } +@@ -620,8 +620,8 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- mlx5e_dbg(HW, priv, "%s: tc_%d <=> max_bw %d Gbps\n", +- __func__, i, max_bw_value[i]); ++ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", ++ __func__, i, max_bw_value[i]); + } + + return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit); +@@ -649,10 +649,10 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev) + ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i]; + ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; + ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i]; +- mlx5e_dbg(HW, priv, +- "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n", +- __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i], +- ets.prio_tc[i]); ++ netdev_dbg(netdev, ++ "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n", ++ __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i], ++ ets.prio_tc[i]); + } + + err = mlx5e_dbcnl_validate_ets(netdev, &ets, true); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index 8cb127a6fabfe..35f33feee4dec 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -1703,16 +1703,6 @@ static int mlx5e_set_fecparam(struct net_device *netdev, + return 0; + } + +-static u32 mlx5e_get_msglevel(struct net_device *dev) +-{ +- return ((struct mlx5e_priv *)netdev_priv(dev))->msglevel; +-} +- +-static void mlx5e_set_msglevel(struct net_device *dev, u32 val) +-{ +- ((struct mlx5e_priv *)netdev_priv(dev))->msglevel = val; +-} +- + static int mlx5e_set_phys_id(struct net_device *dev, + enum ethtool_phys_id_state state) + { +@@ -1966,9 +1956,9 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val + if (err) + return err; + +- mlx5e_dbg(DRV, priv, "MLX5E: RxCqeCmprss was turned %s\n", +- MLX5E_GET_PFLAG(&priv->channels.params, +- MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF"); ++ netdev_dbg(priv->netdev, "MLX5E: RxCqeCmprss was turned %s\n", ++ MLX5E_GET_PFLAG(&priv->channels.params, ++ MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF"); + + return 0; + } +@@ -2450,8 +2440,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = { + .get_priv_flags = mlx5e_get_priv_flags, + .set_priv_flags = mlx5e_set_priv_flags, + .self_test = mlx5e_self_test, +- .get_msglevel = mlx5e_get_msglevel, +- .set_msglevel = mlx5e_set_msglevel, + .get_fec_stats = mlx5e_get_fec_stats, + .get_fecparam = mlx5e_get_fecparam, + .set_fecparam = mlx5e_set_fecparam, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 887d446354006..0c1f89196f6c1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2339,7 +2339,7 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_priv *priv, int ix, int cpu) + /* Asymmetric dynamic memory allocation. + * Freed in mlx5e_priv_arrays_free, not on channel closure. + */ +- mlx5e_dbg(DRV, priv, "Creating channel stats %d\n", ix); ++ netdev_dbg(priv->netdev, "Creating channel stats %d\n", ix); + priv->channel_stats[ix] = kvzalloc_node(sizeof(**priv->channel_stats), + GFP_KERNEL, cpu_to_node(cpu)); + if (!priv->channel_stats[ix]) +@@ -2714,7 +2714,7 @@ int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv) + if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS)) + num_txqs += ntc; + +- mlx5e_dbg(DRV, priv, "Setting num_txqs %d\n", num_txqs); ++ netdev_dbg(priv->netdev, "Setting num_txqs %d\n", num_txqs); + err = netif_set_real_num_tx_queues(priv->netdev, num_txqs); + if (err) + netdev_warn(priv->netdev, "netif_set_real_num_tx_queues failed, %d\n", err); +@@ -5515,7 +5515,6 @@ int mlx5e_priv_init(struct mlx5e_priv *priv, + /* priv init */ + priv->mdev = mdev; + priv->netdev = netdev; +- priv->msglevel = MLX5E_MSG_LEVEL; + priv->max_nch = nch; + priv->max_opened_tc = 1; + +-- +2.51.0 + diff --git a/queue-6.1/net-mlx5e-update-shared-buffer-along-with-device-buf.patch b/queue-6.1/net-mlx5e-update-shared-buffer-along-with-device-buf.patch new file mode 100644 index 0000000000..a86fdd0e14 --- /dev/null +++ b/queue-6.1/net-mlx5e-update-shared-buffer-along-with-device-buf.patch @@ -0,0 +1,366 @@ +From 57e618b3d95f270b0bcb979ad2050aae4c9a6d7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 19:03:07 +0200 +Subject: net/mlx5e: Update shared buffer along with device buffer changes + +From: Maher Sanalla + +[ Upstream commit a440030d8946bfe3fd44b6da685e33ffe0ecd1ff ] + +Currently, the user can modify device's receive buffer size, modify the +mapping between QoS priority groups to buffers and change the buffer +state to become lossy/lossless via pfc command. + +However, the shared receive buffer pool alignments, as a result of +such commands, is performed only when the shared buffer is in FW ownership. +When a user changes the mapping of priority groups or buffer size, +the shared buffer is moved to SW ownership. + +Therefore, for devices that support shared buffer, handle the shared buffer +alignments in accordance to user's desired configurations. + +Meaning, the following will be performed: +1. For every change of buffer's headroom, recalculate the size of shared + buffer to be equal to "total_buffer_size" - "new_headroom_size". + The new shared buffer size will be split in ratio of 3:1 between + lossy and lossless pools, respectively. + +2. For each port buffer change, count the number of lossless buffers. + If there is only one lossless buffer, then set its lossless pool + usage threshold to be infinite. Otherwise, if there is more than + one lossless buffer, set a usage threshold for each lossless buffer. + +While at it, add more verbosity to debug prints when handling user +commands, to assist in future debug. + +Signed-off-by: Maher Sanalla +Reviewed-by: Moshe Shemesh +Signed-off-by: Saeed Mahameed +Stable-dep-of: 9fcc2b6c1052 ("net/mlx5e: Fix potentially misleading debug message") +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/en/port_buffer.c | 222 +++++++++++++++++- + .../mellanox/mlx5/core/en/port_buffer.h | 1 + + 2 files changed, 219 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +index 7899a7230299d..e846417a8ca94 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +@@ -73,6 +73,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + port_buffer->buffer[i].lossy); + } + ++ port_buffer->headroom_size = total_used; + port_buffer->port_buffer_size = + MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz; + port_buffer->spare_buffer_size = +@@ -86,16 +87,204 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, + return err; + } + ++struct mlx5e_buffer_pool { ++ u32 infi_size; ++ u32 size; ++ u32 buff_occupancy; ++}; ++ ++static int mlx5e_port_query_pool(struct mlx5_core_dev *mdev, ++ struct mlx5e_buffer_pool *buffer_pool, ++ u32 desc, u8 dir, u8 pool_idx) ++{ ++ u32 out[MLX5_ST_SZ_DW(sbpr_reg)] = {}; ++ int err; ++ ++ err = mlx5e_port_query_sbpr(mdev, desc, dir, pool_idx, out, ++ sizeof(out)); ++ if (err) ++ return err; ++ ++ buffer_pool->size = MLX5_GET(sbpr_reg, out, size); ++ buffer_pool->infi_size = MLX5_GET(sbpr_reg, out, infi_size); ++ buffer_pool->buff_occupancy = MLX5_GET(sbpr_reg, out, buff_occupancy); ++ ++ return err; ++} ++ ++enum { ++ MLX5_INGRESS_DIR = 0, ++ MLX5_EGRESS_DIR = 1, ++}; ++ ++enum { ++ MLX5_LOSSY_POOL = 0, ++ MLX5_LOSSLESS_POOL = 1, ++}; ++ ++/* No limit on usage of shared buffer pool (max_buff=0) */ ++#define MLX5_SB_POOL_NO_THRESHOLD 0 ++/* Shared buffer pool usage threshold when calculated ++ * dynamically in alpha units. alpha=13 is equivalent to ++ * HW_alpha of [(1/128) * 2 ^ (alpha-1)] = 32, where HW_alpha ++ * equates to the following portion of the shared buffer pool: ++ * [32 / (1 + n * 32)] While *n* is the number of buffers ++ * that are using the shared buffer pool. ++ */ ++#define MLX5_SB_POOL_THRESHOLD 13 ++ ++/* Shared buffer class management parameters */ ++struct mlx5_sbcm_params { ++ u8 pool_idx; ++ u8 max_buff; ++ u8 infi_size; ++}; ++ ++static const struct mlx5_sbcm_params sbcm_default = { ++ .pool_idx = MLX5_LOSSY_POOL, ++ .max_buff = MLX5_SB_POOL_NO_THRESHOLD, ++ .infi_size = 0, ++}; ++ ++static const struct mlx5_sbcm_params sbcm_lossy = { ++ .pool_idx = MLX5_LOSSY_POOL, ++ .max_buff = MLX5_SB_POOL_NO_THRESHOLD, ++ .infi_size = 1, ++}; ++ ++static const struct mlx5_sbcm_params sbcm_lossless = { ++ .pool_idx = MLX5_LOSSLESS_POOL, ++ .max_buff = MLX5_SB_POOL_THRESHOLD, ++ .infi_size = 0, ++}; ++ ++static const struct mlx5_sbcm_params sbcm_lossless_no_threshold = { ++ .pool_idx = MLX5_LOSSLESS_POOL, ++ .max_buff = MLX5_SB_POOL_NO_THRESHOLD, ++ .infi_size = 1, ++}; ++ ++/** ++ * select_sbcm_params() - selects the shared buffer pool configuration ++ * ++ * @buffer: port buffer to retrieve params of ++ * @lossless_buff_count: number of lossless buffers in total ++ * ++ * The selection is based on the following rules: ++ * 1. If buffer size is 0, no shared buffer pool is used. ++ * 2. If buffer is lossy, use lossy shared buffer pool. ++ * 3. If there are more than 1 lossless buffers, use lossless shared buffer pool ++ * with threshold. ++ * 4. If there is only 1 lossless buffer, use lossless shared buffer pool ++ * without threshold. ++ * ++ * @return const struct mlx5_sbcm_params* selected values ++ */ ++static const struct mlx5_sbcm_params * ++select_sbcm_params(struct mlx5e_bufferx_reg *buffer, u8 lossless_buff_count) ++{ ++ if (buffer->size == 0) ++ return &sbcm_default; ++ ++ if (buffer->lossy) ++ return &sbcm_lossy; ++ ++ if (lossless_buff_count > 1) ++ return &sbcm_lossless; ++ ++ return &sbcm_lossless_no_threshold; ++} ++ ++static int port_update_pool_cfg(struct mlx5_core_dev *mdev, ++ struct mlx5e_port_buffer *port_buffer) ++{ ++ const struct mlx5_sbcm_params *p; ++ u8 lossless_buff_count = 0; ++ int err; ++ int i; ++ ++ if (!MLX5_CAP_GEN(mdev, sbcam_reg)) ++ return 0; ++ ++ for (i = 0; i < MLX5E_MAX_BUFFER; i++) ++ lossless_buff_count += ((port_buffer->buffer[i].size) && ++ (!(port_buffer->buffer[i].lossy))); ++ ++ for (i = 0; i < MLX5E_MAX_BUFFER; i++) { ++ p = select_sbcm_params(&port_buffer->buffer[i], lossless_buff_count); ++ err = mlx5e_port_set_sbcm(mdev, 0, i, ++ MLX5_INGRESS_DIR, ++ p->infi_size, ++ p->max_buff, ++ p->pool_idx); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int port_update_shared_buffer(struct mlx5_core_dev *mdev, ++ u32 current_headroom_size, ++ u32 new_headroom_size) ++{ ++ struct mlx5e_buffer_pool lossless_ipool; ++ struct mlx5e_buffer_pool lossy_epool; ++ u32 lossless_ipool_size; ++ u32 shared_buffer_size; ++ u32 total_buffer_size; ++ u32 lossy_epool_size; ++ int err; ++ ++ if (!MLX5_CAP_GEN(mdev, sbcam_reg)) ++ return 0; ++ ++ err = mlx5e_port_query_pool(mdev, &lossy_epool, 0, MLX5_EGRESS_DIR, ++ MLX5_LOSSY_POOL); ++ if (err) ++ return err; ++ ++ err = mlx5e_port_query_pool(mdev, &lossless_ipool, 0, MLX5_INGRESS_DIR, ++ MLX5_LOSSLESS_POOL); ++ if (err) ++ return err; ++ ++ total_buffer_size = current_headroom_size + lossy_epool.size + ++ lossless_ipool.size; ++ shared_buffer_size = total_buffer_size - new_headroom_size; ++ ++ if (shared_buffer_size < 4) { ++ pr_err("Requested port buffer is too large, not enough space left for shared buffer\n"); ++ return -EINVAL; ++ } ++ ++ /* Total shared buffer size is split in a ratio of 3:1 between ++ * lossy and lossless pools respectively. ++ */ ++ lossy_epool_size = (shared_buffer_size / 4) * 3; ++ lossless_ipool_size = shared_buffer_size / 4; ++ ++ mlx5e_port_set_sbpr(mdev, 0, MLX5_EGRESS_DIR, MLX5_LOSSY_POOL, 0, ++ lossy_epool_size); ++ mlx5e_port_set_sbpr(mdev, 0, MLX5_INGRESS_DIR, MLX5_LOSSLESS_POOL, 0, ++ lossless_ipool_size); ++ return 0; ++} ++ + static int port_set_buffer(struct mlx5e_priv *priv, + struct mlx5e_port_buffer *port_buffer) + { + u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; + struct mlx5_core_dev *mdev = priv->mdev; + int sz = MLX5_ST_SZ_BYTES(pbmc_reg); ++ u32 new_headroom_size = 0; ++ u32 current_headroom_size; + void *in; + int err; + int i; + ++ current_headroom_size = port_buffer->headroom_size; ++ + in = kzalloc(sz, GFP_KERNEL); + if (!in) + return -ENOMEM; +@@ -110,6 +299,7 @@ static int port_set_buffer(struct mlx5e_priv *priv, + u64 xoff = port_buffer->buffer[i].xoff; + u64 xon = port_buffer->buffer[i].xon; + ++ new_headroom_size += size; + do_div(size, port_buff_cell_sz); + do_div(xoff, port_buff_cell_sz); + do_div(xon, port_buff_cell_sz); +@@ -119,6 +309,17 @@ static int port_set_buffer(struct mlx5e_priv *priv, + MLX5_SET(bufferx_reg, buffer, xon_threshold, xon); + } + ++ new_headroom_size /= port_buff_cell_sz; ++ current_headroom_size /= port_buff_cell_sz; ++ err = port_update_shared_buffer(priv->mdev, current_headroom_size, ++ new_headroom_size); ++ if (err) ++ return err; ++ ++ err = port_update_pool_cfg(priv->mdev, port_buffer); ++ if (err) ++ return err; ++ + err = mlx5e_port_set_pbmc(mdev, in); + out: + kfree(in); +@@ -174,6 +375,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer, + + /** + * update_buffer_lossy - Update buffer configuration based on pfc ++ * @mdev: port function core device + * @max_mtu: netdev's max_mtu + * @pfc_en: current pfc configuration + * @buffer: current prio to buffer mapping +@@ -192,7 +394,8 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer, + * @return: 0 if no error, + * sets change to true if buffer configuration was modified. + */ +-static int update_buffer_lossy(unsigned int max_mtu, ++static int update_buffer_lossy(struct mlx5_core_dev *mdev, ++ unsigned int max_mtu, + u8 pfc_en, u8 *buffer, u32 xoff, u16 port_buff_cell_sz, + struct mlx5e_port_buffer *port_buffer, + bool *change) +@@ -229,6 +432,10 @@ static int update_buffer_lossy(unsigned int max_mtu, + } + + if (changed) { ++ err = port_update_pool_cfg(mdev, port_buffer); ++ if (err) ++ return err; ++ + err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz); + if (err) + return err; +@@ -293,23 +500,30 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, + } + + if (change & MLX5E_PORT_BUFFER_PFC) { ++ mlx5e_dbg(HW, priv, "%s: requested PFC per priority bitmask: 0x%x\n", ++ __func__, pfc->pfc_en); + err = mlx5e_port_query_priority2buffer(priv->mdev, buffer); + if (err) + return err; + +- err = update_buffer_lossy(max_mtu, pfc->pfc_en, buffer, xoff, port_buff_cell_sz, +- &port_buffer, &update_buffer); ++ err = update_buffer_lossy(priv->mdev, max_mtu, pfc->pfc_en, buffer, xoff, ++ port_buff_cell_sz, &port_buffer, ++ &update_buffer); + if (err) + return err; + } + + if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { + update_prio2buffer = true; ++ for (i = 0; i < MLX5E_MAX_BUFFER; i++) ++ mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n", ++ __func__, i, prio2buffer[i]); ++ + err = fill_pfc_en(priv->mdev, &curr_pfc_en); + if (err) + return err; + +- err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, xoff, ++ err = update_buffer_lossy(priv->mdev, max_mtu, curr_pfc_en, prio2buffer, xoff, + port_buff_cell_sz, &port_buffer, &update_buffer); + if (err) + return err; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +index 80af7a5ac6046..a6ef118de758f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +@@ -60,6 +60,7 @@ struct mlx5e_bufferx_reg { + struct mlx5e_port_buffer { + u32 port_buffer_size; + u32 spare_buffer_size; ++ u32 headroom_size; + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; + }; + +-- +2.51.0 + diff --git a/queue-6.1/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch b/queue-6.1/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch new file mode 100644 index 0000000000..4a7ca90f6a --- /dev/null +++ b/queue-6.1/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch @@ -0,0 +1,59 @@ +From 3bcc8c4640f768d6629d160dc7419778af0b5080 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:35 +0530 +Subject: net: sched: act_connmark: initialize struct tc_ife to fix kernel leak + +From: Ranganath V N + +[ Upstream commit 62b656e43eaeae445a39cd8021a4f47065af4389 ] + +In tcf_connmark_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: 22a5dc0e5e3e ("net: sched: Introduce connmark action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-2-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_connmark.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 79cfe51a09e74..4d75d2ae0d8ce 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -190,13 +190,15 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); + const struct tcf_connmark_parms *parms; +- struct tc_connmark opt = { +- .index = ci->tcf_index, +- .refcnt = refcount_read(&ci->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, +- }; ++ struct tc_connmark opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ci->tcf_index; ++ opt.refcnt = refcount_read(&ci->tcf_refcnt) - ref; ++ opt.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind; ++ + rcu_read_lock(); + parms = rcu_dereference(ci->parms); + +-- +2.51.0 + diff --git a/queue-6.1/net-sched-act_connmark-transition-to-percpu-stats-an.patch b/queue-6.1/net-sched-act_connmark-transition-to-percpu-stats-an.patch new file mode 100644 index 0000000000..ed98cc192c --- /dev/null +++ b/queue-6.1/net-sched-act_connmark-transition-to-percpu-stats-an.patch @@ -0,0 +1,277 @@ +From 7d3f72250e8a70a87d043f1f35a70e2cb5dcacca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Feb 2023 18:15:32 -0300 +Subject: net/sched: act_connmark: transition to percpu stats and rcu + +From: Pedro Tammela + +[ Upstream commit 288864effe33885988d53faf7830b35cb9a84c7a ] + +The tc action act_connmark was using shared stats and taking the per +action lock in the datapath. Improve it by using percpu stats and rcu. + +perf before: +- 13.55% tcf_connmark_act + - 81.18% _raw_spin_lock + 80.46% native_queued_spin_lock_slowpath + +perf after: +- 2.85% tcf_connmark_act + +tdc results: +1..15 +ok 1 2002 - Add valid connmark action with defaults +ok 2 56a5 - Add valid connmark action with control pass +ok 3 7c66 - Add valid connmark action with control drop +ok 4 a913 - Add valid connmark action with control pipe +ok 5 bdd8 - Add valid connmark action with control reclassify +ok 6 b8be - Add valid connmark action with control continue +ok 7 d8a6 - Add valid connmark action with control jump +ok 8 aae8 - Add valid connmark action with zone argument +ok 9 2f0b - Add valid connmark action with invalid zone argument +ok 10 9305 - Add connmark action with unsupported argument +ok 11 71ca - Add valid connmark action and replace it +ok 12 5f8f - Add valid connmark action with cookie +ok 13 c506 - Replace connmark with invalid goto chain control +ok 14 6571 - Delete connmark action with valid index +ok 15 3426 - Delete connmark action with invalid index + +Reviewed-by: Jamal Hadi Salim +Signed-off-by: Pedro Tammela +Signed-off-by: Paolo Abeni +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/tc_act/tc_connmark.h | 9 ++- + net/sched/act_connmark.c | 107 ++++++++++++++++++++----------- + 2 files changed, 75 insertions(+), 41 deletions(-) + +diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h +index 1f4cb477bb5d6..e8dd77a967480 100644 +--- a/include/net/tc_act/tc_connmark.h ++++ b/include/net/tc_act/tc_connmark.h +@@ -4,10 +4,15 @@ + + #include + +-struct tcf_connmark_info { +- struct tc_action common; ++struct tcf_connmark_parms { + struct net *net; + u16 zone; ++ struct rcu_head rcu; ++}; ++ ++struct tcf_connmark_info { ++ struct tc_action common; ++ struct tcf_connmark_parms __rcu *parms; + }; + + #define to_connmark(a) ((struct tcf_connmark_info *)a) +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index d41002e4613ff..418d60435b9d4 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -34,13 +34,15 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + struct nf_conntrack_tuple tuple; + enum ip_conntrack_info ctinfo; + struct tcf_connmark_info *ca = to_connmark(a); ++ struct tcf_connmark_parms *parms; + struct nf_conntrack_zone zone; + struct nf_conn *c; + int proto; + +- spin_lock(&ca->tcf_lock); + tcf_lastuse_update(&ca->tcf_tm); +- bstats_update(&ca->tcf_bstats, skb); ++ tcf_action_update_bstats(&ca->common, skb); ++ ++ parms = rcu_dereference_bh(ca->parms); + + switch (skb_protocol(skb, true)) { + case htons(ETH_P_IP): +@@ -62,31 +64,29 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + c = nf_ct_get(skb, &ctinfo); + if (c) { + skb->mark = READ_ONCE(c->mark); +- /* using overlimits stats to count how many packets marked */ +- ca->tcf_qstats.overlimits++; +- goto out; ++ goto count; + } + +- if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), +- proto, ca->net, &tuple)) ++ if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, parms->net, ++ &tuple)) + goto out; + +- zone.id = ca->zone; ++ zone.id = parms->zone; + zone.dir = NF_CT_DEFAULT_ZONE_DIR; + +- thash = nf_conntrack_find_get(ca->net, &zone, &tuple); ++ thash = nf_conntrack_find_get(parms->net, &zone, &tuple); + if (!thash) + goto out; + + c = nf_ct_tuplehash_to_ctrack(thash); +- /* using overlimits stats to count how many packets marked */ +- ca->tcf_qstats.overlimits++; + skb->mark = READ_ONCE(c->mark); + nf_ct_put(c); + ++count: ++ /* using overlimits stats to count how many packets marked */ ++ tcf_action_inc_overlimit_qstats(&ca->common); + out: +- spin_unlock(&ca->tcf_lock); +- return ca->tcf_action; ++ return READ_ONCE(ca->tcf_action); + } + + static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { +@@ -99,6 +99,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + struct netlink_ext_ack *extack) + { + struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id); ++ struct tcf_connmark_parms *nparms, *oparms; + struct nlattr *tb[TCA_CONNMARK_MAX + 1]; + bool bind = flags & TCA_ACT_FLAGS_BIND; + struct tcf_chain *goto_ch = NULL; +@@ -118,52 +119,66 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + if (!tb[TCA_CONNMARK_PARMS]) + return -EINVAL; + ++ nparms = kzalloc(sizeof(*nparms), GFP_KERNEL); ++ if (!nparms) ++ return -ENOMEM; ++ + parm = nla_data(tb[TCA_CONNMARK_PARMS]); + index = parm->index; + ret = tcf_idr_check_alloc(tn, &index, a, bind); + if (!ret) { +- ret = tcf_idr_create(tn, index, est, a, +- &act_connmark_ops, bind, false, flags); ++ ret = tcf_idr_create_from_flags(tn, index, est, a, ++ &act_connmark_ops, bind, flags); + if (ret) { + tcf_idr_cleanup(tn, index); +- return ret; ++ err = ret; ++ goto out_free; + } + + ci = to_connmark(*a); +- err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, +- extack); +- if (err < 0) +- goto release_idr; +- tcf_action_set_ctrlact(*a, parm->action, goto_ch); +- ci->net = net; +- ci->zone = parm->zone; ++ ++ nparms->net = net; ++ nparms->zone = parm->zone; + + ret = ACT_P_CREATED; + } else if (ret > 0) { + ci = to_connmark(*a); +- if (bind) +- return 0; +- if (!(flags & TCA_ACT_FLAGS_REPLACE)) { +- tcf_idr_release(*a, bind); +- return -EEXIST; ++ if (bind) { ++ err = 0; ++ goto out_free; + } +- err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, +- extack); +- if (err < 0) ++ if (!(flags & TCA_ACT_FLAGS_REPLACE)) { ++ err = -EEXIST; + goto release_idr; +- /* replacing action and zone */ +- spin_lock_bh(&ci->tcf_lock); +- goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); +- ci->zone = parm->zone; +- spin_unlock_bh(&ci->tcf_lock); +- if (goto_ch) +- tcf_chain_put_by_act(goto_ch); ++ } ++ ++ nparms->net = rtnl_dereference(ci->parms)->net; ++ nparms->zone = parm->zone; ++ + ret = 0; + } + ++ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); ++ if (err < 0) ++ goto release_idr; ++ ++ spin_lock_bh(&ci->tcf_lock); ++ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); ++ oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock)); ++ spin_unlock_bh(&ci->tcf_lock); ++ ++ if (goto_ch) ++ tcf_chain_put_by_act(goto_ch); ++ ++ if (oparms) ++ kfree_rcu(oparms, rcu); ++ + return ret; ++ + release_idr: + tcf_idr_release(*a, bind); ++out_free: ++ kfree(nparms); + return err; + } + +@@ -177,11 +192,14 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + .refcnt = refcount_read(&ci->tcf_refcnt) - ref, + .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, + }; ++ struct tcf_connmark_parms *parms; + struct tcf_t t; + + spin_lock_bh(&ci->tcf_lock); ++ parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock)); ++ + opt.action = ci->tcf_action; +- opt.zone = ci->zone; ++ opt.zone = parms->zone; + if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; + +@@ -199,6 +217,16 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + return -1; + } + ++static void tcf_connmark_cleanup(struct tc_action *a) ++{ ++ struct tcf_connmark_info *ci = to_connmark(a); ++ struct tcf_connmark_parms *parms; ++ ++ parms = rcu_dereference_protected(ci->parms, 1); ++ if (parms) ++ kfree_rcu(parms, rcu); ++} ++ + static struct tc_action_ops act_connmark_ops = { + .kind = "connmark", + .id = TCA_ID_CONNMARK, +@@ -206,6 +234,7 @@ static struct tc_action_ops act_connmark_ops = { + .act = tcf_connmark_act, + .dump = tcf_connmark_dump, + .init = tcf_connmark_init, ++ .cleanup = tcf_connmark_cleanup, + .size = sizeof(struct tcf_connmark_info), + }; + +-- +2.51.0 + diff --git a/queue-6.1/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-6.1/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..f2ca228948 --- /dev/null +++ b/queue-6.1/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From c32a656102ee5f3a64199ae3d9d5d76a188ac40d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index 41d63b33461dc..a4505b926a1e4 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -643,13 +643,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-6.1/net-smc-fix-mismatch-between-clc-header-and-proposal.patch b/queue-6.1/net-smc-fix-mismatch-between-clc-header-and-proposal.patch new file mode 100644 index 0000000000..27580e53a0 --- /dev/null +++ b/queue-6.1/net-smc-fix-mismatch-between-clc-header-and-proposal.patch @@ -0,0 +1,55 @@ +From 881a97329ee69be344506da71f64235665454c45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 10:40:29 +0800 +Subject: net/smc: fix mismatch between CLC header and proposal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: D. Wythe + +[ Upstream commit ec33f2e5a2d0dbbfd71435209aee812fdc9369b8 ] + +The current CLC proposal message construction uses a mix of +`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether +to include optional extensions (IPv6 prefix extension for v1, and v2 +extension). This leads to a critical inconsistency: when +`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with +only link-local addresses, or when the local IP address and the outgoing +interface’s network address are not in the same subnet. + +As a result, the proposal message is assembled using the stale +`ini->smc_type_v1` value—causing the IPv6 prefix extension to be +included even though the header indicates v1 is not supported. +The peer then receives a malformed CLC proposal where the header type +does not match the payload, and immediately resets the connection. + +The fix ensures consistency between the CLC header flags and the actual +payload by synchronizing `ini->smc_type_v1` with `pclc_base->hdr.typev1` +when prefix setup fails. + +Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal") +Signed-off-by: D. Wythe +Reviewed-by: Alexandra Winter +Link: https://patch.msgid.link/20251107024029.88753-1-alibuda@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_clc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c +index 6ed77f02ceac0..4a9a7ecf973ca 100644 +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -862,6 +862,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) + return SMC_CLC_DECL_CNFERR; + } + pclc_base->hdr.typev1 = SMC_TYPE_N; ++ ini->smc_type_v1 = SMC_TYPE_N; + } else { + pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); + plen += sizeof(*pclc_prfx) + +-- +2.51.0 + diff --git a/queue-6.1/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch b/queue-6.1/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch new file mode 100644 index 0000000000..bcca045066 --- /dev/null +++ b/queue-6.1/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch @@ -0,0 +1,100 @@ +From 806c79ba861400e43810e973978c4cc37c150db1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 09:01:54 +0000 +Subject: net_sched: act_connmark: use RCU in tcf_connmark_dump() + +From: Eric Dumazet + +[ Upstream commit 0d752877705c0252ef2726e4c63c5573f048951c ] + +Also storing tcf_action into struct tcf_connmark_parms +makes sure there is no discrepancy in tcf_connmark_act(). + +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250709090204.797558-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/tc_act/tc_connmark.h | 1 + + net/sched/act_connmark.c | 18 ++++++++++-------- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h +index e8dd77a967480..a5ce83f3eea4b 100644 +--- a/include/net/tc_act/tc_connmark.h ++++ b/include/net/tc_act/tc_connmark.h +@@ -7,6 +7,7 @@ + struct tcf_connmark_parms { + struct net *net; + u16 zone; ++ int action; + struct rcu_head rcu; + }; + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 418d60435b9d4..79cfe51a09e74 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -86,7 +86,7 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + /* using overlimits stats to count how many packets marked */ + tcf_action_inc_overlimit_qstats(&ca->common); + out: +- return READ_ONCE(ca->tcf_action); ++ return parms->action; + } + + static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { +@@ -162,6 +162,8 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + if (err < 0) + goto release_idr; + ++ nparms->action = parm->action; ++ + spin_lock_bh(&ci->tcf_lock); + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); + oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock)); +@@ -185,20 +187,20 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + int bind, int ref) + { ++ const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); +- struct tcf_connmark_info *ci = to_connmark(a); ++ const struct tcf_connmark_parms *parms; + struct tc_connmark opt = { + .index = ci->tcf_index, + .refcnt = refcount_read(&ci->tcf_refcnt) - ref, + .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, + }; +- struct tcf_connmark_parms *parms; + struct tcf_t t; + +- spin_lock_bh(&ci->tcf_lock); +- parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock)); ++ rcu_read_lock(); ++ parms = rcu_dereference(ci->parms); + +- opt.action = ci->tcf_action; ++ opt.action = parms->action; + opt.zone = parms->zone; + if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; +@@ -207,12 +209,12 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t, + TCA_CONNMARK_PAD)) + goto nla_put_failure; +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + + return skb->len; + + nla_put_failure: +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + nlmsg_trim(skb, b); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.1/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-6.1/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..c0bc4908de --- /dev/null +++ b/queue-6.1/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From 5ad2f483fcc4cc8ba54ab9179dc1a87b4d0eff9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index b51af871a621c..1b51b3038b4bd 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -178,9 +178,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -191,8 +192,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -226,7 +229,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -293,7 +296,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -385,7 +388,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -394,7 +397,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -412,7 +415,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + if (q->flags & TCQ_F_NOLOCK) +-- +2.51.0 + diff --git a/queue-6.1/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-6.1/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..b265164da3 --- /dev/null +++ b/queue-6.1/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From 615699f91654db03dea388c9b9a287314e0efe4a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 87ed33b9db1b3..52c872839f234 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -495,6 +495,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -506,10 +507,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-6.1/selftests-net-local_termination-wait-for-interfaces-.patch b/queue-6.1/selftests-net-local_termination-wait-for-interfaces-.patch new file mode 100644 index 0000000000..a81c7bf556 --- /dev/null +++ b/queue-6.1/selftests-net-local_termination-wait-for-interfaces-.patch @@ -0,0 +1,48 @@ +From a8287bda2b52e26d166d160fcf7bd501c41ae83f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 17:12:09 +0100 +Subject: selftests: net: local_termination: Wait for interfaces to come up + +From: Alexander Sverdlin + +[ Upstream commit 57531b3416448d1ced36a2a974a4085ec43d57b0 ] + +It seems that most of the tests prepare the interfaces once before the test +run (setup_prepare()), rely on setup_wait() to wait for link and only then +run the test(s). + +local_termination brings the physical interfaces down and up during test +run but never wait for them to come up. If the auto-negotiation takes +some seconds, first test packets are being lost, which leads to +false-negative test results. + +Use setup_wait() in run_test() to make sure auto-negotiation has been +completed after all simple_if_init() calls on physical interfaces and test +packets will not be lost because of the race against link establishment. + +Fixes: 90b9566aa5cd3f ("selftests: forwarding: add a test for local_termination.sh") +Reviewed-by: Vladimir Oltean +Signed-off-by: Alexander Sverdlin +Link: https://patch.msgid.link/20251106161213.459501-1-alexander.sverdlin@siemens.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/forwarding/local_termination.sh | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/net/forwarding/local_termination.sh b/tools/testing/selftests/net/forwarding/local_termination.sh +index 9b5a63519b949..6cde61f10fd0e 100755 +--- a/tools/testing/selftests/net/forwarding/local_termination.sh ++++ b/tools/testing/selftests/net/forwarding/local_termination.sh +@@ -108,6 +108,8 @@ run_test() + local smac=$(mac_get $h1) + local rcv_dmac=$(mac_get $rcv_if_name) + ++ setup_wait ++ + tcpdump_start $rcv_if_name + + mc_route_prepare $h1 +-- +2.51.0 + diff --git a/queue-6.1/series b/queue-6.1/series index a0ee287aff..9de2495055 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -345,3 +345,36 @@ nfs-check-if-suid-sgid-was-cleared-after-a-write-as-.patch smb-server-fix-possible-memory-leak-in-smb2_read.patch smb-server-fix-possible-refcount-leak-in-smb2_sess_s.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch +wifi-ath11k-add-tx-ack-signal-support-for-management.patch +wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch +selftests-net-local_termination-wait-for-interfaces-.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +net-smc-fix-mismatch-between-clc-header-and-proposal.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +af_unix-initialise-scc_index-in-unix_add_edge.patch +net-sched-act_connmark-transition-to-percpu-stats-an.patch +net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch +net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net-mlx5-expose-shared-buffer-registers-bits-and-str.patch +net-mlx5e-add-api-to-query-modify-sbpr-and-sbcm-regi.patch +net-mlx5e-update-shared-buffer-along-with-device-buf.patch +net-mlx5e-consider-internal-buffers-size-in-port-buf.patch +net-mlx5e-remove-mlx5e_dbg-and-msglvl-support.patch +net-mlx5e-fix-potentially-misleading-debug-message.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +hsr-fix-supervision-frame-sending-on-hsrv0.patch +acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch +acpi-cppc-perform-fast-check-switch-only-for-online-.patch +acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch diff --git a/queue-6.1/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-6.1/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..9fa62141c5 --- /dev/null +++ b/queue-6.1/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From 9d1ab7806693502d7bdf1e0893b2421ac3fb087d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 0e95572e56b41..7e65d0b0c4a8d 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -145,7 +145,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-6.1/wifi-ath11k-add-tx-ack-signal-support-for-management.patch b/queue-6.1/wifi-ath11k-add-tx-ack-signal-support-for-management.patch new file mode 100644 index 0000000000..4163b3f2d1 --- /dev/null +++ b/queue-6.1/wifi-ath11k-add-tx-ack-signal-support-for-management.patch @@ -0,0 +1,166 @@ +From abb915cca28fff68f221e845a58e4258d11ca749 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Dec 2022 11:08:44 +0530 +Subject: wifi: ath11k: Add tx ack signal support for management packets + +From: Abinaya Kalaiselvan + +[ Upstream commit 01c6c9fccbd51c1d9eab0f5794b0271b026178df ] + +Add support to notify tx ack signal values for management +packets to userspace through nl80211 interface. + +Advertise NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT flag +to enable this feature and it will be used for data +packets as well. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Abinaya Kalaiselvan +Signed-off-by: Maharaja Kennadyrajan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221219053844.4084486-1-quic_mkenna@quicinc.com +Stable-dep-of: 9065b9687523 ("wifi: ath11k: zero init info->status in wmi_process_mgmt_tx_comp()") +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/hw.c | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 5 +++++ + drivers/net/wireless/ath/ath11k/wmi.c | 27 ++++++++++++++++----------- + drivers/net/wireless/ath/ath11k/wmi.h | 3 +++ + 4 files changed, 25 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c +index dbcc0c4035b62..332664643c7b4 100644 +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -201,6 +201,7 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab, + config->twt_ap_pdev_count = ab->num_radios; + config->twt_ap_sta_count = 1000; + config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; ++ config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI; + } + + static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 8be42227dd943..4cab480f85a8d 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9045,6 +9045,11 @@ static int __ath11k_mac_register(struct ath11k *ar) + goto err_free_if_combs; + } + ++ if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, ++ ar->ab->wmi_ab.svc_map)) ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); ++ + ar->hw->queues = ATH11K_HW_MAX_QUEUES; + ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; + ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 38756ed48082c..1b58979bdfdc6 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5221,8 +5221,8 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab, + return 0; + } + +-static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, +- u32 status) ++static int wmi_process_mgmt_tx_comp(struct ath11k *ar, ++ struct wmi_mgmt_tx_compl_event *tx_compl_param) + { + struct sk_buff *msdu; + struct ieee80211_tx_info *info; +@@ -5230,24 +5230,29 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, + int num_mgmt; + + spin_lock_bh(&ar->txmgmt_idr_lock); +- msdu = idr_find(&ar->txmgmt_idr, desc_id); ++ msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id); + + if (!msdu) { + ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n", +- desc_id); ++ tx_compl_param->desc_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); + return -ENOENT; + } + +- idr_remove(&ar->txmgmt_idr, desc_id); ++ idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); + + skb_cb = ATH11K_SKB_CB(msdu); + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); +- if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) ++ if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && ++ !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; ++ if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, ++ ar->ab->wmi_ab.svc_map)) ++ info->status.ack_signal = tx_compl_param->ack_rssi; ++ } + + ieee80211_tx_status_irqsafe(ar->hw, msdu); + +@@ -5259,7 +5264,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi mgmt tx comp pending %d desc id %d\n", +- num_mgmt, desc_id); ++ num_mgmt, tx_compl_param->desc_id); + + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); +@@ -5292,6 +5297,7 @@ static int ath11k_pull_mgmt_tx_compl_param_tlv(struct ath11k_base *ab, + param->pdev_id = ev->pdev_id; + param->desc_id = ev->desc_id; + param->status = ev->status; ++ param->ack_rssi = ev->ack_rssi; + + kfree(tb); + return 0; +@@ -7062,13 +7068,12 @@ static void ath11k_mgmt_tx_compl_event(struct ath11k_base *ab, struct sk_buff *s + goto exit; + } + +- wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id, +- tx_compl_param.status); ++ wmi_process_mgmt_tx_comp(ar, &tx_compl_param); + + ath11k_dbg(ab, ATH11K_DBG_MGMT, +- "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", ++ "mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d", + tx_compl_param.pdev_id, tx_compl_param.desc_id, +- tx_compl_param.status); ++ tx_compl_param.status, tx_compl_param.ack_rssi); + + exit: + rcu_read_unlock(); +diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h +index 8f2c07d70a4a2..31d14e15ebc1d 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2309,6 +2309,7 @@ struct wmi_init_cmd { + } __packed; + + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) ++#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) + + struct wmi_resource_config { + u32 tlv_header; +@@ -4541,6 +4542,8 @@ struct wmi_mgmt_tx_compl_event { + u32 desc_id; + u32 status; + u32 pdev_id; ++ u32 ppdu_id; ++ u32 ack_rssi; + } __packed; + + struct wmi_scan_event { +-- +2.51.0 + diff --git a/queue-6.1/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch b/queue-6.1/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch new file mode 100644 index 0000000000..20720cc879 --- /dev/null +++ b/queue-6.1/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch @@ -0,0 +1,53 @@ +From d8d77101cb0aa9d721dc457e06328a0f4447fd6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Nov 2025 09:39:57 +0100 +Subject: wifi: ath11k: zero init info->status in wmi_process_mgmt_tx_comp() + +From: Nicolas Escande + +[ Upstream commit 9065b968752334f972e0d48e50c4463a172fc2a7 ] + +When reporting tx completion using ieee80211_tx_status_xxx() family of +functions, the status part of the struct ieee80211_tx_info nested in the +skb is used to report things like transmit rates & retry count to mac80211 + +On the TX data path, this is correctly memset to 0 before calling +ieee80211_tx_status_ext(), but on the tx mgmt path this was not done. + +This leads to mac80211 treating garbage values as valid transmit counters +(like tx retries for example) and accounting them as real statistics that +makes their way to userland via station dump. + +The same issue was resolved in ath12k by commit 9903c0986f78 ("wifi: +ath12k: Add memset and update default rate value in wmi tx completion") + +Tested-on: QCN9074 PCI WLAN.HK.2.9.0.1-01977-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20251104083957.717825-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/wmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 1b58979bdfdc6..ed12bbb11fe89 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5246,6 +5246,9 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); ++ memset(&info->status, 0, sizeof(info->status)); ++ info->status.rates[0].idx = -1; ++ + if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && + !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; +-- +2.51.0 + diff --git a/queue-6.1/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-6.1/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..c27d2bc6ff --- /dev/null +++ b/queue-6.1/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From 44a2123796cc1390a5b99377e438399a07f181c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 776f9fcf05abe..1cd75c200cfe6 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -5228,10 +5228,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 + diff --git a/queue-6.12/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch b/queue-6.12/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch new file mode 100644 index 0000000000..36f08d09d8 --- /dev/null +++ b/queue-6.12/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch @@ -0,0 +1,49 @@ +From 1d7b0081f30bc1d73359d2e9012027d5c8064888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:42 +0530 +Subject: ACPI: CPPC: Check _CPC validity for only the online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 6dd3b8a709a130a4d55c866af9804c81b8486d28 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function acpi_cpc_valid() checks for the validity of the +_CPC object for all the present CPUs. This breaks when the kernel is +booted with "nosmt=force". + +Hence check the validity of the _CPC objects of only the online CPUs. + +Fixes: 2aeca6bd0277 ("ACPI: CPPC: Check present CPUs for determining _CPC is valid") +Reported-by: Christopher Harris +Closes: https://lore.kernel.org/lkml/CAM+eXpdDT7KjLV0AxEwOLkSJ2QtrsvGvjA2cCHvt1d0k2_C4Cw@mail.gmail.com/ +Suggested-by: Mario Limonciello +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Tested-by: Chrisopher Harris +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-3-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index dab941dc984a9..3ce5bb87d25b7 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -447,7 +447,7 @@ bool acpi_cpc_valid(void) + if (acpi_disabled) + return false; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + if (!cpc_ptr) + return false; +-- +2.51.0 + diff --git a/queue-6.12/acpi-cppc-detect-preferred-core-availability-on-onli.patch b/queue-6.12/acpi-cppc-detect-preferred-core-availability-on-onli.patch new file mode 100644 index 0000000000..9d74d77e7f --- /dev/null +++ b/queue-6.12/acpi-cppc-detect-preferred-core-availability-on-onli.patch @@ -0,0 +1,49 @@ +From 64d06bde4f8a0e98eba6e5df1afae66b9da2caa6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:41 +0530 +Subject: ACPI: CPPC: Detect preferred core availability on online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 4fe5934db4a7187d358f1af1b3ef9b6dd59bce58 ] + +Commit 279f838a61f9 ("x86/amd: Detect preferred cores in +amd_get_boost_ratio_numerator()") introduced the ability to detect the +preferred core on AMD platforms by checking if there at least two +distinct highest_perf values. + +However, it uses for_each_present_cpu() to iterate through all the +CPUs in the platform, which is problematic when the kernel is booted +with "nosmt=force" commandline option. + +Hence limit the search to only the online CPUs. + +Fixes: 279f838a61f9 ("x86/amd: Detect preferred cores in amd_get_boost_ratio_numerator()") +Reported-by: Christopher Harris +Closes: https://lore.kernel.org/lkml/CAM+eXpdDT7KjLV0AxEwOLkSJ2QtrsvGvjA2cCHvt1d0k2_C4Cw@mail.gmail.com/ +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Tested-by: Chrisopher Harris +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-2-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/acpi/cppc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c +index aab9d0570841a..147f0d8d54d86 100644 +--- a/arch/x86/kernel/acpi/cppc.c ++++ b/arch/x86/kernel/acpi/cppc.c +@@ -194,7 +194,7 @@ int amd_detect_prefcore(bool *detected) + break; + } + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + u32 tmp; + int ret; + +-- +2.51.0 + diff --git a/queue-6.12/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch b/queue-6.12/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch new file mode 100644 index 0000000000..69b8f4ac9c --- /dev/null +++ b/queue-6.12/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch @@ -0,0 +1,45 @@ +From 1b9990ca335dbecf8a507c50db454cbbf11021ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:44 +0530 +Subject: ACPI: CPPC: Limit perf ctrs in PCC check only to online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 0fce75870666b46b700cfbd3216380b422f975da ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPU via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_perf_ctrs_in_pcc() checks if the CPPC +perf-ctrs are in a PCC region for all the present CPUs, which breaks +when the kernel is booted with "nosmt=force". + +Hence, limit the check only to the online CPUs. + +Fixes: ae2df912d1a5 ("ACPI: CPPC: Disable FIE if registers in PCC regions") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-5-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index c4a1fee4b4873..62b723f6c48df 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -1366,7 +1366,7 @@ bool cppc_perf_ctrs_in_pcc(void) + { + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + struct cpc_register_resource *ref_perf_reg; + struct cpc_desc *cpc_desc; + +-- +2.51.0 + diff --git a/queue-6.12/acpi-cppc-perform-fast-check-switch-only-for-online-.patch b/queue-6.12/acpi-cppc-perform-fast-check-switch-only-for-online-.patch new file mode 100644 index 0000000000..c20bba7b27 --- /dev/null +++ b/queue-6.12/acpi-cppc-perform-fast-check-switch-only-for-online-.patch @@ -0,0 +1,45 @@ +From 62012c3d08c0680408d3b462b0bf3a6dc35fca2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:43 +0530 +Subject: ACPI: CPPC: Perform fast check switch only for online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 8821c8e80a65bc4eb73daf63b34aac6b8ad69461 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_allow_fast_switch() checks for the validity +of the _CPC object for all the present CPUs. This breaks when the +kernel is booted with "nosmt=force". + +Check fast_switch capability only on online CPUs + +Fixes: 15eece6c5b05 ("ACPI: CPPC: Fix NULL pointer dereference when nosmp is used") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-4-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 3ce5bb87d25b7..c4a1fee4b4873 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -463,7 +463,7 @@ bool cppc_allow_fast_switch(void) + struct cpc_desc *cpc_ptr; + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF]; + if (!CPC_IN_SYSTEM_MEMORY(desired_reg) && +-- +2.51.0 + diff --git a/queue-6.12/af_unix-initialise-scc_index-in-unix_add_edge.patch b/queue-6.12/af_unix-initialise-scc_index-in-unix_add_edge.patch new file mode 100644 index 0000000000..94b6f3587e --- /dev/null +++ b/queue-6.12/af_unix-initialise-scc_index-in-unix_add_edge.patch @@ -0,0 +1,139 @@ +From c07d75bc5fe196efda55f6e2fa5c88967d3b563a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 02:52:22 +0000 +Subject: af_unix: Initialise scc_index in unix_add_edge(). + +From: Kuniyuki Iwashima + +[ Upstream commit 60e6489f8e3b086bd1130ad4450a2c112e863791 ] + +Quang Le reported that the AF_UNIX GC could garbage-collect a +receive queue of an alive in-flight socket, with a nice repro. + +The repro consists of three stages. + + 1) + 1-a. Create a single cyclic reference with many sockets + 1-b. close() all sockets + 1-c. Trigger GC + + 2) + 2-a. Pass sk-A to an embryo sk-B + 2-b. Pass sk-X to sk-X + 2-c. Trigger GC + + 3) + 3-a. accept() the embryo sk-B + 3-b. Pass sk-B to sk-C + 3-c. close() the in-flight sk-A + 3-d. Trigger GC + +As of 2-c, sk-A and sk-X are linked to unix_unvisited_vertices, +and unix_walk_scc() groups them into two different SCCs: + + unix_sk(sk-A)->vertex->scc_index = 2 (UNIX_VERTEX_INDEX_START) + unix_sk(sk-X)->vertex->scc_index = 3 + +Once GC completes, unix_graph_grouped is set to true. +Also, unix_graph_maybe_cyclic is set to true due to sk-X's +cyclic self-reference, which makes close() trigger GC. + +At 3-b, unix_add_edge() allocates unix_sk(sk-B)->vertex and +links it to unix_unvisited_vertices. + +unix_update_graph() is called at 3-a. and 3-b., but neither +unix_graph_grouped nor unix_graph_maybe_cyclic is changed +because both sk-B's listener and sk-C are not in-flight. + +3-c decrements sk-A's file refcnt to 1. + +Since unix_graph_grouped is true at 3-d, unix_walk_scc_fast() +is finally called and iterates 3 sockets sk-A, sk-B, and sk-X: + + sk-A -> sk-B (-> sk-C) + sk-X -> sk-X + +This is totally fine. All of them are not yet close()d and +should be grouped into different SCCs. + +However, unix_vertex_dead() misjudges that sk-A and sk-B are +in the same SCC and sk-A is dead. + + unix_sk(sk-A)->scc_index == unix_sk(sk-B)->scc_index <-- Wrong! + && + sk-A's file refcnt == unix_sk(sk-A)->vertex->out_degree + ^-- 1 in-flight count for sk-B + -> sk-A is dead !? + +The problem is that unix_add_edge() does not initialise scc_index. + +Stage 1) is used for heap spraying, making a newly allocated +vertex have vertex->scc_index == 2 (UNIX_VERTEX_INDEX_START) +set by unix_walk_scc() at 1-c. + +Let's track the max SCC index from the previous unix_walk_scc() +call and assign the max + 1 to a new vertex's scc_index. + +This way, we can continue to avoid Tarjan's algorithm while +preventing misjudgments. + +Fixes: ad081928a8b0 ("af_unix: Avoid Tarjan's algorithm if unnecessary.") +Reported-by: Quang Le +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20251109025233.3659187-1-kuniyu@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/garbage.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 0068e758be4dd..66fd606c43f45 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -136,6 +136,7 @@ enum unix_vertex_index { + }; + + static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1; ++static unsigned long unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + { +@@ -144,6 +145,7 @@ static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + if (!vertex) { + vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry); + vertex->index = unix_vertex_unvisited_index; ++ vertex->scc_index = ++unix_vertex_max_scc_index; + vertex->out_degree = 0; + INIT_LIST_HEAD(&vertex->edges); + INIT_LIST_HEAD(&vertex->scc_entry); +@@ -480,10 +482,15 @@ static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_inde + scc_dead = unix_vertex_dead(v); + } + +- if (scc_dead) ++ if (scc_dead) { + unix_collect_skb(&scc, hitlist); +- else if (!unix_graph_maybe_cyclic) +- unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } else { ++ if (unix_vertex_max_scc_index < vertex->scc_index) ++ unix_vertex_max_scc_index = vertex->scc_index; ++ ++ if (!unix_graph_maybe_cyclic) ++ unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } + + list_del(&scc); + } +@@ -498,6 +505,7 @@ static void unix_walk_scc(struct sk_buff_head *hitlist) + unsigned long last_index = UNIX_VERTEX_INDEX_START; + + unix_graph_maybe_cyclic = false; ++ unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + /* Visit every vertex exactly once. + * __unix_walk_scc() moves visited vertices to unix_visited_vertices. +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-6.12/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..622966185e --- /dev/null +++ b/queue-6.12/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From 6d180a8011781667b73c6554055c17a69190d2c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 73fe151a52a12..e5186a438290a 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -52,6 +52,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -60,6 +65,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1013,41 +1020,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-6.12/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..0ee7fcde3f --- /dev/null +++ b/queue-6.12/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From a49f68bdc68fcce36f25f502bdf2e114d4ec1dc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index e313b066733f8..73fe151a52a12 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -956,10 +956,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -970,13 +971,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1103,7 +1123,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1140,7 +1160,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-6.12/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..ae1bd60bd2 --- /dev/null +++ b/queue-6.12/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From 270194a2234b20cf75e2942f919e86e196c44b14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 3c29778171c58..e313b066733f8 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -288,6 +288,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-6.12/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..9fbc0c547f --- /dev/null +++ b/queue-6.12/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From 11af6c70bed6b48ff39396a08c43c18f2a648494 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index a734c5135a8be..aedb478614000 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4179,6 +4179,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4189,17 +4194,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-6.12/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..04eaaa2a63 --- /dev/null +++ b/queue-6.12/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 59117a5eae2a6f457418b4a6b2d38b7aba3d000d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 7dafc3e0a15aa..41197f9fdf980 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -497,6 +497,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-6.12/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch b/queue-6.12/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch new file mode 100644 index 0000000000..5d553b9271 --- /dev/null +++ b/queue-6.12/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch @@ -0,0 +1,56 @@ +From a7a477abfa1410aa927641b3de3715f25d854b8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Nov 2025 20:16:12 +0200 +Subject: Bluetooth: MGMT: cancel mesh send timer when hdev removed + +From: Pauli Virtanen + +[ Upstream commit 55fb52ffdd62850d667ebed842815e072d3c9961 ] + +mesh_send_done timer is not canceled when hdev is removed, which causes +crash if the timer triggers after hdev is gone. + +Cancel the timer when MGMT removes the hdev, like other MGMT timers. + +Should fix the BUG: sporadically seen by BlueZ test bot +(in "Mesh - Send cancel - 1" test). + +Log: +------ +BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 +... +Freed by task 36: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3a/0x60 + __kasan_slab_free+0x43/0x70 + kfree+0x103/0x500 + device_release+0x9a/0x210 + kobject_put+0x100/0x1e0 + vhci_release+0x18b/0x240 +------ + +Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh") +Link: https://lore.kernel.org/linux-bluetooth/67364c09.0c0a0220.113cba.39ff@mx.google.com/ +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 57295c3a8920f..c54cc701cdd48 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9492,6 +9492,7 @@ void mgmt_index_removed(struct hci_dev *hdev) + cancel_delayed_work_sync(&hdev->discov_off); + cancel_delayed_work_sync(&hdev->service_cache); + cancel_delayed_work_sync(&hdev->rpa_expired); ++ cancel_delayed_work_sync(&hdev->mesh_send_done); + } + + void mgmt_power_on(struct hci_dev *hdev, int err) +-- +2.51.0 + diff --git a/queue-6.12/erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch b/queue-6.12/erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch new file mode 100644 index 0000000000..3ef6f4c5dd --- /dev/null +++ b/queue-6.12/erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch @@ -0,0 +1,60 @@ +From 125fc46e444092130ac1e6afab4c568a333943f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Oct 2025 13:47:39 +0800 +Subject: erofs: avoid infinite loop due to incomplete zstd-compressed data + +From: Gao Xiang + +[ Upstream commit f2a12cc3b97f062186568a7b94ddb7aa2ef68140 ] + +Currently, the decompression logic incorrectly spins if compressed +data is truncated in crafted (deliberately corrupted) images. + +Fixes: 7c35de4df105 ("erofs: Zstandard compression support") +Reported-by: Robert Morris +Closes: https://lore.kernel.org/r/50958.1761605413@localhost +Signed-off-by: Gao Xiang +Reviewed-by: Chunhai Guo +Reviewed-by: Chao Yu +Signed-off-by: Sasha Levin +--- + fs/erofs/decompressor_zstd.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/erofs/decompressor_zstd.c b/fs/erofs/decompressor_zstd.c +index 7e177304967e1..24f4731a7a6d4 100644 +--- a/fs/erofs/decompressor_zstd.c ++++ b/fs/erofs/decompressor_zstd.c +@@ -178,7 +178,6 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, + dctx.bounce = strm->bounce; + + do { +- dctx.avail_out = out_buf.size - out_buf.pos; + dctx.inbuf_sz = in_buf.size; + dctx.inbuf_pos = in_buf.pos; + err = z_erofs_stream_switch_bufs(&dctx, &out_buf.dst, +@@ -194,14 +193,18 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, + in_buf.pos = dctx.inbuf_pos; + + zerr = zstd_decompress_stream(stream, &out_buf, &in_buf); +- if (zstd_is_error(zerr) || (!zerr && rq->outputsize)) { ++ dctx.avail_out = out_buf.size - out_buf.pos; ++ if (zstd_is_error(zerr) || ++ ((rq->outputsize + dctx.avail_out) && (!zerr || (zerr > 0 && ++ !(rq->inputsize + in_buf.size - in_buf.pos))))) { + erofs_err(sb, "failed to decompress in[%u] out[%u]: %s", + rq->inputsize, rq->outputsize, +- zerr ? zstd_get_error_name(zerr) : "unexpected end of stream"); ++ zstd_is_error(zerr) ? zstd_get_error_name(zerr) : ++ "unexpected end of stream"); + err = -EFSCORRUPTED; + break; + } +- } while (rq->outputsize || out_buf.pos < out_buf.size); ++ } while (rq->outputsize + dctx.avail_out); + + if (dctx.kout) + kunmap_local(dctx.kout); +-- +2.51.0 + diff --git a/queue-6.12/hsr-fix-supervision-frame-sending-on-hsrv0.patch b/queue-6.12/hsr-fix-supervision-frame-sending-on-hsrv0.patch new file mode 100644 index 0000000000..16abe64352 --- /dev/null +++ b/queue-6.12/hsr-fix-supervision-frame-sending-on-hsrv0.patch @@ -0,0 +1,50 @@ +From a69f071fdec75172c71e4b55b611e4664286d1c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:32 +0100 +Subject: hsr: Fix supervision frame sending on HSRv0 + +From: Felix Maurer + +[ Upstream commit 96a3a03abf3d8cc38cd9cb0d280235fbcf7c3f7f ] + +On HSRv0, no supervision frames were sent. The supervison frames were +generated successfully, but failed the check for a sufficiently long mac +header, i.e., at least sizeof(struct hsr_ethhdr), in hsr_fill_frame_info() +because the mac header only contained the ethernet header. + +Fix this by including the HSR header in the mac header when generating HSR +supervision frames. Note that the mac header now also includes the TLV +fields. This matches how we set the headers on rx and also the size of +struct hsrv0_ethhdr_sp. + +Reported-by: Hangbin Liu +Closes: https://lore.kernel.org/netdev/aMONxDXkzBZZRfE5@fedora/ +Fixes: 9cfb5e7f0ded ("net: hsr: fix hsr_init_sk() vs network/transport headers.") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Tested-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/4354114fea9a642fe71f49aeeb6c6159d1d61840.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index d2ae9fbed9e30..ae368cdcbd936 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -320,6 +320,9 @@ static void send_hsr_supervision_frame(struct hsr_port *port, + } + + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); ++ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); ++ skb_reset_mac_len(skb); ++ + set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + +-- +2.51.0 + diff --git a/queue-6.12/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch b/queue-6.12/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch new file mode 100644 index 0000000000..3b27d01888 --- /dev/null +++ b/queue-6.12/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch @@ -0,0 +1,77 @@ +From 842f90f7e3f2a527ae5bf7419339fc219607f942 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:53:04 +0530 +Subject: net: ethernet: ti: am65-cpsw-qos: fix IET verify/response timeout + +From: Aksh Garg + +[ Upstream commit 49b3916465176a5abcb29a0e464825f553d55d58 ] + +The CPSW module uses the MAC_VERIFY_CNT bit field in the +CPSW_PN_IET_VERIFY_REG_k register to set the verify/response timeout +count. This register specifies the number of clock cycles to wait before +resending a verify packet if the verification fails. + +The verify/response timeout count, as being set by the function +am65_cpsw_iet_set_verify_timeout_count() is hardcoded for 125MHz +clock frequency, which varies based on PHY mode and link speed. + +The respective clock frequencies are as follows: +- RGMII mode: + * 1000 Mbps: 125 MHz + * 100 Mbps: 25 MHz + * 10 Mbps: 2.5 MHz +- QSGMII/SGMII mode: 125 MHz (all speeds) + +Fix this by adding logic to calculate the correct timeout counts +based on the actual PHY interface mode and link speed. + +Fixes: 49a2eb9068246 ("net: ethernet: ti: am65-cpsw-qos: Add Frame Preemption MAC Merge support") +Signed-off-by: Aksh Garg +Link: https://patch.msgid.link/20251106092305.1437347-2-a-garg7@ti.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/am65-cpsw-qos.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c +index fa96db7c1a130..ad06942ce461a 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c +@@ -276,9 +276,31 @@ static int am65_cpsw_iet_set_verify_timeout_count(struct am65_cpsw_port *port) + /* The number of wireside clocks contained in the verify + * timeout counter. The default is 0x1312d0 + * (10ms at 125Mhz in 1G mode). ++ * The frequency of the clock depends on the link speed ++ * and the PHY interface. + */ +- val = 125 * HZ_PER_MHZ; /* assuming 125MHz wireside clock */ ++ switch (port->slave.phy_if) { ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ if (port->qos.link_speed == SPEED_1000) ++ val = 125 * HZ_PER_MHZ; /* 125 MHz at 1000Mbps*/ ++ else if (port->qos.link_speed == SPEED_100) ++ val = 25 * HZ_PER_MHZ; /* 25 MHz at 100Mbps*/ ++ else ++ val = (25 * HZ_PER_MHZ) / 10; /* 2.5 MHz at 10Mbps*/ ++ break; ++ ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ val = 125 * HZ_PER_MHZ; /* 125 MHz */ ++ break; + ++ default: ++ netdev_err(port->ndev, "selected mode does not supported IET\n"); ++ return -EOPNOTSUPP; ++ } + val /= MILLIHZ_PER_HZ; /* count per ms timeout */ + val *= verify_time_ms; /* count for timeout ms */ + +-- +2.51.0 + diff --git a/queue-6.12/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch b/queue-6.12/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch new file mode 100644 index 0000000000..c445ae429e --- /dev/null +++ b/queue-6.12/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch @@ -0,0 +1,87 @@ +From 70853305503f1e3d51db50b7e4769eb038f3d2e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:53:05 +0530 +Subject: net: ethernet: ti: am65-cpsw-qos: fix IET verify retry mechanism + +From: Aksh Garg + +[ Upstream commit d4b00d132d7cb70a74bc039c91c1d6120943c71b ] + +The am65_cpsw_iet_verify_wait() function attempts verification 20 times, +toggling the AM65_CPSW_PN_IET_MAC_LINKFAIL bit in each iteration. When +the LINKFAIL bit transitions from 1 to 0, the MAC merge layer initiates +the verification process and waits for the timeout configured in +MAC_VERIFY_CNT before automatically retransmitting. The MAC_VERIFY_CNT +register is configured according to the user-defined verify/response +timeout in am65_cpsw_iet_set_verify_timeout_count(). As per IEEE 802.3 +Clause 99, the hardware performs this automatic retry up to 3 times. + +Current implementation toggles LINKFAIL after the user-configured +verify/response timeout in each iteration, forcing the hardware to +restart verification instead of respecting the MAC_VERIFY_CNT timeout. +This bypasses the hardware's automatic retry mechanism. + +Fix this by moving the LINKFAIL bit toggle outside the retry loop and +reducing the retry count from 20 to 3. The software now only monitors +the status register while the hardware autonomously handles the 3 +verification attempts at proper MAC_VERIFY_CNT intervals. + +Fixes: 49a2eb9068246 ("net: ethernet: ti: am65-cpsw-qos: Add Frame Preemption MAC Merge support") +Signed-off-by: Aksh Garg +Link: https://patch.msgid.link/20251106092305.1437347-3-a-garg7@ti.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/am65-cpsw-qos.c | 27 +++++++++++++------------ + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c +index ad06942ce461a..66e8b224827b6 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c +@@ -317,20 +317,21 @@ static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port) + u32 ctrl, status; + int try; + +- try = 20; +- do { +- /* Reset the verify state machine by writing 1 +- * to LINKFAIL +- */ +- ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); +- ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL; +- writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ try = 3; + +- /* Clear MAC_LINKFAIL bit to start Verify. */ +- ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); +- ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; +- writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ /* Reset the verify state machine by writing 1 ++ * to LINKFAIL ++ */ ++ ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); + ++ /* Clear MAC_LINKFAIL bit to start Verify. */ ++ ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ++ do { + msleep(port->qos.iet.verify_time_ms); + + status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); +@@ -352,7 +353,7 @@ static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port) + netdev_dbg(port->ndev, "MAC Merge verify error\n"); + return -ENODEV; + } +- } while (try-- > 0); ++ } while (--try > 0); + + netdev_dbg(port->ndev, "MAC Merge verify timeout\n"); + return -ETIMEDOUT; +-- +2.51.0 + diff --git a/queue-6.12/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-6.12/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..9e95bedd6d --- /dev/null +++ b/queue-6.12/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From a18da66c62811918aa45efd6cf2e9d3d10f28192 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index d144494f97e91..d1800868c2e01 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1799,6 +1799,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + page = rxq->rx_skb_info[index].page; +-- +2.51.0 + diff --git a/queue-6.12/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch b/queue-6.12/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch new file mode 100644 index 0000000000..ccca5df3ba --- /dev/null +++ b/queue-6.12/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch @@ -0,0 +1,42 @@ +From f74065b398664b7e8e985f8d1997ec938f146b03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:45:11 +0000 +Subject: net/handshake: Fix memory leak in tls_handshake_accept() + +From: Zilin Guan + +[ Upstream commit 3072f00bba764082fa41b3c3a2a7b013335353d2 ] + +In tls_handshake_accept(), a netlink message is allocated using +genlmsg_new(). In the error handling path, genlmsg_cancel() is called +to cancel the message construction, but the message itself is not freed. +This leads to a memory leak. + +Fix this by calling nlmsg_free() in the error path after genlmsg_cancel() +to release the allocated memory. + +Fixes: 2fd5532044a89 ("net/handshake: Add a kernel API for requesting a TLSv1.3 handshake") +Signed-off-by: Zilin Guan +Reviewed-by: Chuck Lever +Link: https://patch.msgid.link/20251106144511.3859535-1-zilin@seu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/handshake/tlshd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c +index d6f52839827ea..822507b87447c 100644 +--- a/net/handshake/tlshd.c ++++ b/net/handshake/tlshd.c +@@ -253,6 +253,7 @@ static int tls_handshake_accept(struct handshake_req *req, + + out_cancel: + genlmsg_cancel(msg, hdr); ++ nlmsg_free(msg); + out: + return ret; + } +-- +2.51.0 + diff --git a/queue-6.12/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-6.12/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..e5f4d3e4fa --- /dev/null +++ b/queue-6.12/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From 8588c17e710c20d563d7d3f8efc14d989b1a4b86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index a508cd81cd4ed..d80b80ba20a1d 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -79,8 +79,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-6.12/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..97ecc7278a --- /dev/null +++ b/queue-6.12/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From 3c5bf2929917d81580e03af824dd2725c8912110 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index b08328fe1aa30..99ee288ed43a4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -595,18 +595,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5e-fix-potentially-misleading-debug-message.patch b/queue-6.12/net-mlx5e-fix-potentially-misleading-debug-message.patch new file mode 100644 index 0000000000..bbcfe62759 --- /dev/null +++ b/queue-6.12/net-mlx5e-fix-potentially-misleading-debug-message.patch @@ -0,0 +1,62 @@ +From 6beb5e8bfab17a20261a606352931c756c451f09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:53 +0200 +Subject: net/mlx5e: Fix potentially misleading debug message + +From: Gal Pressman + +[ Upstream commit 9fcc2b6c10523f7e75db6387946c86fcf19dc97e ] + +Change the debug message to print the correct units instead of always +assuming Gbps, as the value can be in either 100 Mbps or 1 Gbps units. + +Fixes: 5da8bc3effb6 ("net/mlx5e: DCBNL, Add debug messages log") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 154f8d9eec02a..2ca32fb1961e1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -598,6 +598,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + __u64 upper_limit_mbps; + __u64 upper_limit_gbps; + int i; ++ struct { ++ int scale; ++ const char *units_str; ++ } units[] = { ++ [MLX5_100_MBPS_UNIT] = { ++ .scale = 100, ++ .units_str = "Mbps", ++ }, ++ [MLX5_GBPS_UNIT] = { ++ .scale = 1, ++ .units_str = "Gbps", ++ }, ++ }; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); +@@ -628,8 +641,9 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", +- __func__, i, max_bw_value[i]); ++ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i, ++ max_bw_value[i] * units[max_bw_unit[i]].scale, ++ units[max_bw_unit[i]].units_str); + } + + return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit); +-- +2.51.0 + diff --git a/queue-6.12/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-6.12/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..fcfc968d24 --- /dev/null +++ b/queue-6.12/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From d3229ae9dde02db1ee881e09699a7e7b086f12b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 99ee288ed43a4..154f8d9eec02a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -596,11 +596,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -612,10 +614,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-6.12/net-phy-micrel-introduce-lanphy_modify_page_reg.patch b/queue-6.12/net-phy-micrel-introduce-lanphy_modify_page_reg.patch new file mode 100644 index 0000000000..809d9d5d88 --- /dev/null +++ b/queue-6.12/net-phy-micrel-introduce-lanphy_modify_page_reg.patch @@ -0,0 +1,414 @@ +From 741f2ff018b456c95def08719431165660612835 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Aug 2025 09:51:19 +0200 +Subject: net: phy: micrel: Introduce lanphy_modify_page_reg + +From: Horatiu Vultur + +[ Upstream commit a0de636ed7a264a329c6a9c7d50727af02138536 ] + +As the name suggests this function modifies the register in an +extended page. It has the same parameters as phy_modify_mmd. +This function was introduce because there are many places in the +code where the registers was read then the value was modified and +written back. So replace all this code with this function to make +it clear. + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Horatiu Vultur +Link: https://patch.msgid.link/20250818075121.1298170-3-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 231 ++++++++++++++++++++------------------- + 1 file changed, 116 insertions(+), 115 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index f60cf630bdb3d..0ab3f813d29e4 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -2591,6 +2591,27 @@ static int lanphy_write_page_reg(struct phy_device *phydev, int page, u16 addr, + return val; + } + ++static int lanphy_modify_page_reg(struct phy_device *phydev, int page, u16 addr, ++ u16 mask, u16 set) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ __phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page); ++ __phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, addr); ++ __phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, ++ (page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC)); ++ ret = __phy_modify_changed(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, ++ mask, set); ++ phy_unlock_mdio_bus(phydev); ++ ++ if (ret < 0) ++ phydev_err(phydev, "__phy_modify_changed() failed: %pe\n", ++ ERR_PTR(ret)); ++ ++ return ret; ++} ++ + static int lan8814_config_ts_intr(struct phy_device *phydev, bool enable) + { + u16 val = 0; +@@ -2680,7 +2701,6 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, + struct lan8814_ptp_rx_ts *rx_ts, *tmp; + int txcfg = 0, rxcfg = 0; + int pkt_ts_enable; +- int tx_mod; + + ptp_priv->hwts_tx_type = config->tx_type; + ptp_priv->rx_filter = config->rx_filter; +@@ -2727,13 +2747,14 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, + lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_TIMESTAMP_EN, pkt_ts_enable); + lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_TIMESTAMP_EN, pkt_ts_enable); + +- tx_mod = lanphy_read_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD); + if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, +- tx_mod | PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); ++ lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, ++ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); + } else if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ON) { +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, +- tx_mod & ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); ++ lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, ++ 0); + } + + if (config->rx_filter != HWTSTAMP_FILTER_NONE) +@@ -3136,73 +3157,66 @@ static void lan8814_ptp_set_reload(struct phy_device *phydev, int event, + static void lan8814_ptp_enable_event(struct phy_device *phydev, int event, + int pulse_width) + { +- u16 val; +- +- val = lanphy_read_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG); +- /* Set the pulse width of the event */ +- val &= ~(LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_MASK(event)); +- /* Make sure that the target clock will be incremented each time when ++ /* Set the pulse width of the event, ++ * Make sure that the target clock will be incremented each time when + * local time reaches or pass it ++ * Set the polarity high + */ +- val |= LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width); +- val &= ~(LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event)); +- /* Set the polarity high */ +- val |= LAN8814_PTP_GENERAL_CONFIG_POLARITY_X(event); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_MASK(event) | ++ LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width) | ++ LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event) | ++ LAN8814_PTP_GENERAL_CONFIG_POLARITY_X(event), ++ LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width) | ++ LAN8814_PTP_GENERAL_CONFIG_POLARITY_X(event)); + } + + static void lan8814_ptp_disable_event(struct phy_device *phydev, int event) + { +- u16 val; +- + /* Set target to too far in the future, effectively disabling it */ + lan8814_ptp_set_target(phydev, event, 0xFFFFFFFF, 0); + + /* And then reload once it recheas the target */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG); +- val |= LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event), ++ LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event)); + } + + static void lan8814_ptp_perout_off(struct phy_device *phydev, int pin) + { +- u16 val; +- + /* Disable gpio alternate function, + * 1: select as gpio, + * 0: select alt func + */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); +- val |= LAN8814_GPIO_EN_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ LAN8814_GPIO_EN_BIT(pin), ++ LAN8814_GPIO_EN_BIT(pin)); + +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- val &= ~LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ 0); + +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin)); +- val &= ~LAN8814_GPIO_BUF_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ LAN8814_GPIO_BUF_BIT(pin), ++ 0); + } + + static void lan8814_ptp_perout_on(struct phy_device *phydev, int pin) + { +- int val; +- + /* Set as gpio output */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- val |= LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable gpio 0:for alternate function, 1:gpio */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); +- val &= ~LAN8814_GPIO_EN_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ LAN8814_GPIO_EN_BIT(pin), ++ 0); + + /* Set buffer type to push pull */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin)); +- val |= LAN8814_GPIO_BUF_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ LAN8814_GPIO_BUF_BIT(pin), ++ LAN8814_GPIO_BUF_BIT(pin)); + } + + static int lan8814_ptp_perout(struct ptp_clock_info *ptpci, +@@ -3321,61 +3335,59 @@ static int lan8814_ptp_perout(struct ptp_clock_info *ptpci, + + static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) + { +- u16 tmp; +- + /* Set as gpio input */ +- tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- tmp &= ~LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), tmp); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ 0); + + /* Map the pin to ltc pin 0 of the capture map registers */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO); +- tmp |= pin; +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, ++ pin, ++ pin); + + /* Enable capture on the edges of the ltc pin */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_EN); + if (flags & PTP_RISING_EDGE) +- tmp |= PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0), ++ PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0)); + if (flags & PTP_FALLING_EDGE) +- tmp |= PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_EN, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0), ++ PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0)); + + /* Enable interrupt top interrupt */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_COMMON_INT_ENA); +- tmp |= PTP_COMMON_INT_ENA_GPIO_CAP_EN; +- lanphy_write_page_reg(phydev, 4, PTP_COMMON_INT_ENA, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ PTP_COMMON_INT_ENA_GPIO_CAP_EN, ++ PTP_COMMON_INT_ENA_GPIO_CAP_EN); + } + + static void lan8814_ptp_extts_off(struct phy_device *phydev, int pin) + { +- u16 tmp; +- + /* Set as gpio out */ +- tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- tmp |= LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), tmp); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable alternate, 0:for alternate function, 1:gpio */ +- tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); +- tmp &= ~LAN8814_GPIO_EN_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), tmp); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ LAN8814_GPIO_EN_BIT(pin), ++ 0); + + /* Clear the mapping of pin to registers 0 of the capture registers */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO); +- tmp &= ~GENMASK(3, 0); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, ++ GENMASK(3, 0), ++ 0); + + /* Disable capture on both of the edges */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_EN); +- tmp &= ~PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin); +- tmp &= ~PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_EN, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin) | ++ PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin), ++ 0); + + /* Disable interrupt top interrupt */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_COMMON_INT_ENA); +- tmp &= ~PTP_COMMON_INT_ENA_GPIO_CAP_EN; +- lanphy_write_page_reg(phydev, 4, PTP_COMMON_INT_ENA, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ PTP_COMMON_INT_ENA_GPIO_CAP_EN, ++ 0); + } + + static int lan8814_ptp_extts(struct ptp_clock_info *ptpci, +@@ -3620,9 +3632,9 @@ static int lan8814_gpio_process_cap(struct lan8814_shared_priv *shared) + /* This is 0 because whatever was the input pin it was mapped it to + * ltc gpio pin 0 + */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_SEL); +- tmp |= PTP_GPIO_SEL_GPIO_SEL(0); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_SEL, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_SEL, ++ PTP_GPIO_SEL_GPIO_SEL(0), ++ PTP_GPIO_SEL_GPIO_SEL(0)); + + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_STS); + if (!(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_RE_STS(0)) && +@@ -3669,13 +3681,10 @@ static int lan8814_handle_gpio_interrupt(struct phy_device *phydev, u16 status) + + static int lan8804_config_init(struct phy_device *phydev) + { +- int val; +- + /* MDI-X setting for swap A,B transmit */ +- val = lanphy_read_page_reg(phydev, 2, LAN8804_ALIGN_SWAP); +- val &= ~LAN8804_ALIGN_TX_A_B_SWAP_MASK; +- val |= LAN8804_ALIGN_TX_A_B_SWAP; +- lanphy_write_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, val); ++ lanphy_modify_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, ++ LAN8804_ALIGN_TX_A_B_SWAP_MASK, ++ LAN8804_ALIGN_TX_A_B_SWAP); + + /* Make sure that the PHY will not stop generating the clock when the + * link partner goes down +@@ -3817,7 +3826,6 @@ static void lan8814_ptp_init(struct phy_device *phydev) + { + struct kszphy_priv *priv = phydev->priv; + struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv; +- u32 temp; + + if (!IS_ENABLED(CONFIG_PTP_1588_CLOCK) || + !IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) +@@ -3825,13 +3833,13 @@ static void lan8814_ptp_init(struct phy_device *phydev) + + lanphy_write_page_reg(phydev, 5, TSU_HARD_RESET, TSU_HARD_RESET_); + +- temp = lanphy_read_page_reg(phydev, 5, PTP_TX_MOD); +- temp |= PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_; +- lanphy_write_page_reg(phydev, 5, PTP_TX_MOD, temp); ++ lanphy_modify_page_reg(phydev, 5, PTP_TX_MOD, ++ PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, ++ PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + +- temp = lanphy_read_page_reg(phydev, 5, PTP_RX_MOD); +- temp |= PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_; +- lanphy_write_page_reg(phydev, 5, PTP_RX_MOD, temp); ++ lanphy_modify_page_reg(phydev, 5, PTP_RX_MOD, ++ PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, ++ PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + + lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_CONFIG, 0); + lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_CONFIG, 0); +@@ -3953,23 +3961,21 @@ static void lan8814_setup_led(struct phy_device *phydev, int val) + static int lan8814_config_init(struct phy_device *phydev) + { + struct kszphy_priv *lan8814 = phydev->priv; +- int val; + + /* Reset the PHY */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET); +- val |= LAN8814_QSGMII_SOFT_RESET_BIT; +- lanphy_write_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET, ++ LAN8814_QSGMII_SOFT_RESET_BIT, ++ LAN8814_QSGMII_SOFT_RESET_BIT); + + /* Disable ANEG with QSGMII PCS Host side */ +- val = lanphy_read_page_reg(phydev, 5, LAN8814_QSGMII_PCS1G_ANEG_CONFIG); +- val &= ~LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA; +- lanphy_write_page_reg(phydev, 5, LAN8814_QSGMII_PCS1G_ANEG_CONFIG, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_PCS1G_ANEG_CONFIG, ++ LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA, ++ 0); + + /* MDI-X setting for swap A,B transmit */ +- val = lanphy_read_page_reg(phydev, 2, LAN8814_ALIGN_SWAP); +- val &= ~LAN8814_ALIGN_TX_A_B_SWAP_MASK; +- val |= LAN8814_ALIGN_TX_A_B_SWAP; +- lanphy_write_page_reg(phydev, 2, LAN8814_ALIGN_SWAP, val); ++ lanphy_modify_page_reg(phydev, 2, LAN8814_ALIGN_SWAP, ++ LAN8814_ALIGN_TX_A_B_SWAP_MASK, ++ LAN8814_ALIGN_TX_A_B_SWAP); + + if (lan8814->led_mode >= 0) + lan8814_setup_led(phydev, lan8814->led_mode); +@@ -4000,29 +4006,24 @@ static int lan8814_release_coma_mode(struct phy_device *phydev) + + static void lan8814_clear_2psp_bit(struct phy_device *phydev) + { +- u16 val; +- + /* It was noticed that when traffic is passing through the PHY and the + * cable is removed then the LED was still one even though there is no + * link + */ +- val = lanphy_read_page_reg(phydev, 2, LAN8814_EEE_STATE); +- val &= ~LAN8814_EEE_STATE_MASK2P5P; +- lanphy_write_page_reg(phydev, 2, LAN8814_EEE_STATE, val); ++ lanphy_modify_page_reg(phydev, 2, LAN8814_EEE_STATE, ++ LAN8814_EEE_STATE_MASK2P5P, ++ 0); + } + + static void lan8814_update_meas_time(struct phy_device *phydev) + { +- u16 val; +- + /* By setting the measure time to a value of 0xb this will allow cables + * longer than 100m to be used. This configuration can be used + * regardless of the mode of operation of the PHY + */ +- val = lanphy_read_page_reg(phydev, 1, LAN8814_PD_CONTROLS); +- val &= ~LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK; +- val |= LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL; +- lanphy_write_page_reg(phydev, 1, LAN8814_PD_CONTROLS, val); ++ lanphy_modify_page_reg(phydev, 1, LAN8814_PD_CONTROLS, ++ LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK, ++ LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL); + } + + static int lan8814_probe(struct phy_device *phydev) +-- +2.51.0 + diff --git a/queue-6.12/net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch b/queue-6.12/net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch new file mode 100644 index 0000000000..7416d367f7 --- /dev/null +++ b/queue-6.12/net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch @@ -0,0 +1,59 @@ +From 11051c097e6a608f388139cbba90c302e20253a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:06:37 +0100 +Subject: net: phy: micrel: lan8814 fix reset of the QSGMII interface + +From: Horatiu Vultur + +[ Upstream commit 96a9178a29a6b84bb632ebeb4e84cf61191c73d5 ] + +The lan8814 is a quad-phy and it is using QSGMII towards the MAC. +The problem is that everytime when one of the ports is configured then +the PCS is reseted for all the PHYs. Meaning that the other ports can +loose traffic until the link is establish again. +To fix this, do the reset one time for the entire PHY package. + +Fixes: ece19502834d ("net: phy: micrel: 1588 support for LAN8814 phy") +Signed-off-by: Horatiu Vultur +Reviewed-by: Andrew Lunn +Reviewed-by: Divya Koppera +Link: https://patch.msgid.link/20251106090637.2030625-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index e12040cf10eae..030e559a2cf15 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -4084,12 +4084,6 @@ static int lan8814_config_init(struct phy_device *phydev) + { + struct kszphy_priv *lan8814 = phydev->priv; + +- /* Reset the PHY */ +- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, +- LAN8814_QSGMII_SOFT_RESET, +- LAN8814_QSGMII_SOFT_RESET_BIT, +- LAN8814_QSGMII_SOFT_RESET_BIT); +- + /* Disable ANEG with QSGMII PCS Host side */ + lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG, +@@ -4175,6 +4169,12 @@ static int lan8814_probe(struct phy_device *phydev) + addr, sizeof(struct lan8814_shared_priv)); + + if (phy_package_init_once(phydev)) { ++ /* Reset the PHY */ ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_SOFT_RESET, ++ LAN8814_QSGMII_SOFT_RESET_BIT, ++ LAN8814_QSGMII_SOFT_RESET_BIT); ++ + err = lan8814_release_coma_mode(phydev); + if (err) + return err; +-- +2.51.0 + diff --git a/queue-6.12/net-phy-micrel-replace-hardcoded-pages-with-defines.patch b/queue-6.12/net-phy-micrel-replace-hardcoded-pages-with-defines.patch new file mode 100644 index 0000000000..18b6067364 --- /dev/null +++ b/queue-6.12/net-phy-micrel-replace-hardcoded-pages-with-defines.patch @@ -0,0 +1,741 @@ +From a78cd2db7a05979d58923f15302de22d297189eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Aug 2025 09:51:20 +0200 +Subject: net: phy: micrel: Replace hardcoded pages with defines + +From: Horatiu Vultur + +[ Upstream commit d471793a9b67bbe3d7198ff695004190fd7b6bc7 ] + +The functions lan_*_page_reg gets as a second parameter the page +where the register is. In all the functions the page was hardcoded. +Replace the hardcoded values with defines to make it more clear +what are those parameters. + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Horatiu Vultur +Link: https://patch.msgid.link/20250818075121.1298170-4-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 342 ++++++++++++++++++++++++++------------- + 1 file changed, 233 insertions(+), 109 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 0ab3f813d29e4..e12040cf10eae 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -2541,6 +2541,52 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev, + return ret; + } + ++/** ++ * LAN8814_PAGE_AFE_PMA - Selects Extended Page 1. ++ * ++ * This page appears to control the Analog Front-End (AFE) and Physical ++ * Medium Attachment (PMA) layers. It is used to access registers like ++ * LAN8814_PD_CONTROLS and LAN8814_LINK_QUALITY. ++ */ ++#define LAN8814_PAGE_AFE_PMA 1 ++ ++/** ++ * LAN8814_PAGE_PCS_DIGITAL - Selects Extended Page 2. ++ * ++ * This page seems dedicated to the Physical Coding Sublayer (PCS) and other ++ * digital logic. It is used for MDI-X alignment (LAN8814_ALIGN_SWAP) and EEE ++ * state (LAN8814_EEE_STATE) in the LAN8814, and is repurposed for statistics ++ * and self-test counters in the LAN8842. ++ */ ++#define LAN8814_PAGE_PCS_DIGITAL 2 ++ ++/** ++ * LAN8814_PAGE_COMMON_REGS - Selects Extended Page 4. ++ * ++ * This page contains device-common registers that affect the entire chip. ++ * It includes controls for chip-level resets, strap status, GPIO, ++ * QSGMII, the shared 1588 PTP block, and the PVT monitor. ++ */ ++#define LAN8814_PAGE_COMMON_REGS 4 ++ ++/** ++ * LAN8814_PAGE_PORT_REGS - Selects Extended Page 5. ++ * ++ * This page contains port-specific registers that must be accessed ++ * on a per-port basis. It includes controls for port LEDs, QSGMII PCS, ++ * rate adaptation FIFOs, and the per-port 1588 TSU block. ++ */ ++#define LAN8814_PAGE_PORT_REGS 5 ++ ++/** ++ * LAN8814_PAGE_SYSTEM_CTRL - Selects Extended Page 31. ++ * ++ * This page appears to hold fundamental system or global controls. In the ++ * driver, it is used by the related LAN8804 to access the ++ * LAN8814_CLOCK_MANAGEMENT register. ++ */ ++#define LAN8814_PAGE_SYSTEM_CTRL 31 ++ + #define LAN_EXT_PAGE_ACCESS_CONTROL 0x16 + #define LAN_EXT_PAGE_ACCESS_ADDRESS_DATA 0x17 + #define LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC 0x4000 +@@ -2622,35 +2668,46 @@ static int lan8814_config_ts_intr(struct phy_device *phydev, bool enable) + PTP_TSU_INT_EN_PTP_RX_TS_EN_ | + PTP_TSU_INT_EN_PTP_RX_TS_OVRFL_EN_; + +- return lanphy_write_page_reg(phydev, 5, PTP_TSU_INT_EN, val); ++ return lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TSU_INT_EN, val); + } + + static void lan8814_ptp_rx_ts_get(struct phy_device *phydev, + u32 *seconds, u32 *nano_seconds, u16 *seq_id) + { +- *seconds = lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_SEC_HI); ++ *seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_SEC_HI); + *seconds = (*seconds << 16) | +- lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_SEC_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_SEC_LO); + +- *nano_seconds = lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_NS_HI); ++ *nano_seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_NS_HI); + *nano_seconds = ((*nano_seconds & 0x3fff) << 16) | +- lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_NS_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_NS_LO); + +- *seq_id = lanphy_read_page_reg(phydev, 5, PTP_RX_MSG_HEADER2); ++ *seq_id = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_MSG_HEADER2); + } + + static void lan8814_ptp_tx_ts_get(struct phy_device *phydev, + u32 *seconds, u32 *nano_seconds, u16 *seq_id) + { +- *seconds = lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_SEC_HI); ++ *seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_SEC_HI); + *seconds = *seconds << 16 | +- lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_SEC_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_SEC_LO); + +- *nano_seconds = lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_NS_HI); ++ *nano_seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_NS_HI); + *nano_seconds = ((*nano_seconds & 0x3fff) << 16) | +- lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_NS_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_NS_LO); + +- *seq_id = lanphy_read_page_reg(phydev, 5, PTP_TX_MSG_HEADER2); ++ *seq_id = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_MSG_HEADER2); + } + + static int lan8814_ts_info(struct mii_timestamper *mii_ts, struct kernel_ethtool_ts_info *info) +@@ -2685,11 +2742,11 @@ static void lan8814_flush_fifo(struct phy_device *phydev, bool egress) + int i; + + for (i = 0; i < FIFO_SIZE; ++i) +- lanphy_read_page_reg(phydev, 5, ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, + egress ? PTP_TX_MSG_HEADER2 : PTP_RX_MSG_HEADER2); + + /* Read to clear overflow status bit */ +- lanphy_read_page_reg(phydev, 5, PTP_TSU_INT_STS); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_TSU_INT_STS); + } + + static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, +@@ -2739,20 +2796,26 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, + rxcfg |= PTP_RX_PARSE_CONFIG_IPV4_EN_ | PTP_RX_PARSE_CONFIG_IPV6_EN_; + txcfg |= PTP_TX_PARSE_CONFIG_IPV4_EN_ | PTP_TX_PARSE_CONFIG_IPV6_EN_; + } +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg); +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_CONFIG, rxcfg); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_CONFIG, txcfg); + + pkt_ts_enable = PTP_TIMESTAMP_EN_SYNC_ | PTP_TIMESTAMP_EN_DREQ_ | + PTP_TIMESTAMP_EN_PDREQ_ | PTP_TIMESTAMP_EN_PDRES_; +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_TIMESTAMP_EN, pkt_ts_enable); +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_TIMESTAMP_EN, pkt_ts_enable); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_TIMESTAMP_EN, pkt_ts_enable); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_TIMESTAMP_EN, pkt_ts_enable); + + if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { +- lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ lanphy_modify_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_MOD, + PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, + PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); + } else if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ON) { +- lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ lanphy_modify_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_MOD, + PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, + 0); + } +@@ -2876,29 +2939,41 @@ static bool lan8814_rxtstamp(struct mii_timestamper *mii_ts, struct sk_buff *skb + static void lan8814_ptp_clock_set(struct phy_device *phydev, + time64_t sec, u32 nsec) + { +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_LO, lower_16_bits(sec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_MID, upper_16_bits(sec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_HI, upper_32_bits(sec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_NS_LO, lower_16_bits(nsec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_NS_HI, upper_16_bits(nsec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_SEC_LO, lower_16_bits(sec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_SEC_MID, upper_16_bits(sec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_SEC_HI, upper_32_bits(sec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_NS_LO, lower_16_bits(nsec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_NS_HI, upper_16_bits(nsec)); + +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_LOAD_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, ++ PTP_CMD_CTL_PTP_CLOCK_LOAD_); + } + + static void lan8814_ptp_clock_get(struct phy_device *phydev, + time64_t *sec, u32 *nsec) + { +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, ++ PTP_CMD_CTL_PTP_CLOCK_READ_); + +- *sec = lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_HI); ++ *sec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_SEC_HI); + *sec <<= 16; +- *sec |= lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_MID); ++ *sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_SEC_MID); + *sec <<= 16; +- *sec |= lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_LO); ++ *sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_SEC_LO); + +- *nsec = lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_NS_HI); ++ *nsec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_NS_HI); + *nsec <<= 16; +- *nsec |= lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_NS_LO); ++ *nsec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_NS_LO); + } + + static int lan8814_ptpci_gettime64(struct ptp_clock_info *ptpci, +@@ -2937,14 +3012,18 @@ static void lan8814_ptp_set_target(struct phy_device *phydev, int event, + s64 start_sec, u32 start_nsec) + { + /* Set the start time */ +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_SEC_LO(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_SEC_LO(event), + lower_16_bits(start_sec)); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_SEC_HI(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_SEC_HI(event), + upper_16_bits(start_sec)); + +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_NS_LO(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_NS_LO(event), + lower_16_bits(start_nsec)); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_NS_HI(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_NS_HI(event), + upper_16_bits(start_nsec) & 0x3fff); + } + +@@ -3042,9 +3121,11 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + adjustment_value_lo = adjustment_value & 0xffff; + adjustment_value_hi = (adjustment_value >> 16) & 0x3fff; + +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_LO, + adjustment_value_lo); +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_HI, + PTP_LTC_STEP_ADJ_DIR_ | + adjustment_value_hi); + seconds -= ((s32)adjustment_value); +@@ -3062,9 +3143,11 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + adjustment_value_lo = adjustment_value & 0xffff; + adjustment_value_hi = (adjustment_value >> 16) & 0x3fff; + +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_LO, + adjustment_value_lo); +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_HI, + adjustment_value_hi); + seconds += ((s32)adjustment_value); + +@@ -3072,8 +3155,8 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + set_seconds += adjustment_value; + lan8814_ptp_update_target(phydev, set_seconds); + } +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, +- PTP_CMD_CTL_PTP_LTC_STEP_SEC_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CMD_CTL, PTP_CMD_CTL_PTP_LTC_STEP_SEC_); + } + if (nano_seconds) { + u16 nano_seconds_lo; +@@ -3082,12 +3165,14 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + nano_seconds_lo = nano_seconds & 0xffff; + nano_seconds_hi = (nano_seconds >> 16) & 0x3fff; + +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_LO, + nano_seconds_lo); +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_HI, + PTP_LTC_STEP_ADJ_DIR_ | + nano_seconds_hi); +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, + PTP_CMD_CTL_PTP_LTC_STEP_NSEC_); + } + } +@@ -3129,8 +3214,10 @@ static int lan8814_ptpci_adjfine(struct ptp_clock_info *ptpci, long scaled_ppm) + kszphy_rate_adj_hi |= PTP_CLOCK_RATE_ADJ_DIR_; + + mutex_lock(&shared->shared_lock); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_HI, kszphy_rate_adj_hi); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_LO, kszphy_rate_adj_lo); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CLOCK_RATE_ADJ_HI, ++ kszphy_rate_adj_hi); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CLOCK_RATE_ADJ_LO, ++ kszphy_rate_adj_lo); + mutex_unlock(&shared->shared_lock); + + return 0; +@@ -3139,17 +3226,17 @@ static int lan8814_ptpci_adjfine(struct ptp_clock_info *ptpci, long scaled_ppm) + static void lan8814_ptp_set_reload(struct phy_device *phydev, int event, + s64 period_sec, u32 period_nsec) + { +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_LO(event), + lower_16_bits(period_sec)); +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_HI(event), + upper_16_bits(period_sec)); + +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_LO(event), + lower_16_bits(period_nsec)); +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_HI(event), + upper_16_bits(period_nsec) & 0x3fff); + } +@@ -3162,7 +3249,7 @@ static void lan8814_ptp_enable_event(struct phy_device *phydev, int event, + * local time reaches or pass it + * Set the polarity high + */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, LAN8814_PTP_GENERAL_CONFIG, + LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_MASK(event) | + LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width) | + LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event) | +@@ -3177,7 +3264,7 @@ static void lan8814_ptp_disable_event(struct phy_device *phydev, int event) + lan8814_ptp_set_target(phydev, event, 0xFFFFFFFF, 0); + + /* And then reload once it recheas the target */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, LAN8814_PTP_GENERAL_CONFIG, + LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event), + LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event)); + } +@@ -3188,15 +3275,18 @@ static void lan8814_ptp_perout_off(struct phy_device *phydev, int pin) + * 1: select as gpio, + * 0: select alt func + */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_EN_ADDR(pin), + LAN8814_GPIO_EN_BIT(pin), + LAN8814_GPIO_EN_BIT(pin)); + +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + 0); + +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_BUF_ADDR(pin), + LAN8814_GPIO_BUF_BIT(pin), + 0); + } +@@ -3204,17 +3294,20 @@ static void lan8814_ptp_perout_off(struct phy_device *phydev, int pin) + static void lan8814_ptp_perout_on(struct phy_device *phydev, int pin) + { + /* Set as gpio output */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable gpio 0:for alternate function, 1:gpio */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_EN_ADDR(pin), + LAN8814_GPIO_EN_BIT(pin), + 0); + + /* Set buffer type to push pull */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_BUF_ADDR(pin), + LAN8814_GPIO_BUF_BIT(pin), + LAN8814_GPIO_BUF_BIT(pin)); + } +@@ -3336,27 +3429,29 @@ static int lan8814_ptp_perout(struct ptp_clock_info *ptpci, + static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) + { + /* Set as gpio input */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + 0); + + /* Map the pin to ltc pin 0 of the capture map registers */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, +- pin, +- pin); ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_MAP_LO, pin, pin); + + /* Enable capture on the edges of the ltc pin */ + if (flags & PTP_RISING_EDGE) +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_EN, + PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0), + PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0)); + if (flags & PTP_FALLING_EDGE) +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_EN, + PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0), + PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0)); + + /* Enable interrupt top interrupt */ +- lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_COMMON_INT_ENA, + PTP_COMMON_INT_ENA_GPIO_CAP_EN, + PTP_COMMON_INT_ENA_GPIO_CAP_EN); + } +@@ -3364,28 +3459,31 @@ static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) + static void lan8814_ptp_extts_off(struct phy_device *phydev, int pin) + { + /* Set as gpio out */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable alternate, 0:for alternate function, 1:gpio */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_EN_ADDR(pin), + LAN8814_GPIO_EN_BIT(pin), + 0); + + /* Clear the mapping of pin to registers 0 of the capture registers */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_MAP_LO, + GENMASK(3, 0), + 0); + + /* Disable capture on both of the edges */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_GPIO_CAP_EN, + PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin) | + PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin), + 0); + + /* Disable interrupt top interrupt */ +- lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_COMMON_INT_ENA, + PTP_COMMON_INT_ENA_GPIO_CAP_EN, + 0); + } +@@ -3522,7 +3620,8 @@ static void lan8814_get_tx_ts(struct kszphy_ptp_priv *ptp_priv) + /* If other timestamps are available in the FIFO, + * process them. + */ +- reg = lanphy_read_page_reg(phydev, 5, PTP_CAP_INFO); ++ reg = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_CAP_INFO); + } while (PTP_CAP_INFO_TX_TS_CNT_GET_(reg) > 0); + } + +@@ -3595,7 +3694,8 @@ static void lan8814_get_rx_ts(struct kszphy_ptp_priv *ptp_priv) + /* If other timestamps are available in the FIFO, + * process them. + */ +- reg = lanphy_read_page_reg(phydev, 5, PTP_CAP_INFO); ++ reg = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_CAP_INFO); + } while (PTP_CAP_INFO_RX_TS_CNT_GET_(reg) > 0); + } + +@@ -3632,31 +3732,40 @@ static int lan8814_gpio_process_cap(struct lan8814_shared_priv *shared) + /* This is 0 because whatever was the input pin it was mapped it to + * ltc gpio pin 0 + */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_SEL, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_GPIO_SEL, + PTP_GPIO_SEL_GPIO_SEL(0), + PTP_GPIO_SEL_GPIO_SEL(0)); + +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_STS); ++ tmp = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_STS); + if (!(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_RE_STS(0)) && + !(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_FE_STS(0))) + return -1; + + if (tmp & BIT(0)) { +- sec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_SEC_HI_CAP); ++ sec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_SEC_HI_CAP); + sec <<= 16; +- sec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_SEC_LO_CAP); ++ sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_SEC_LO_CAP); + +- nsec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_HI_CAP) & 0x3fff; ++ nsec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_NS_HI_CAP) & 0x3fff; + nsec <<= 16; +- nsec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_LO_CAP); ++ nsec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_NS_LO_CAP); + } else { +- sec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_SEC_HI_CAP); ++ sec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_FE_LTC_SEC_HI_CAP); + sec <<= 16; +- sec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_SEC_LO_CAP); ++ sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_FE_LTC_SEC_LO_CAP); + +- nsec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_NS_HI_CAP) & 0x3fff; ++ nsec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_FE_LTC_NS_HI_CAP) & 0x3fff; + nsec <<= 16; +- nsec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_LO_CAP); ++ nsec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_NS_LO_CAP); + } + + ptp_event.index = 0; +@@ -3682,15 +3791,16 @@ static int lan8814_handle_gpio_interrupt(struct phy_device *phydev, u16 status) + static int lan8804_config_init(struct phy_device *phydev) + { + /* MDI-X setting for swap A,B transmit */ +- lanphy_modify_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, LAN8804_ALIGN_SWAP, + LAN8804_ALIGN_TX_A_B_SWAP_MASK, + LAN8804_ALIGN_TX_A_B_SWAP); + + /* Make sure that the PHY will not stop generating the clock when the + * link partner goes down + */ +- lanphy_write_page_reg(phydev, 31, LAN8814_CLOCK_MANAGEMENT, 0x27e); +- lanphy_read_page_reg(phydev, 1, LAN8814_LINK_QUALITY); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_SYSTEM_CTRL, ++ LAN8814_CLOCK_MANAGEMENT, 0x27e); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_AFE_PMA, LAN8814_LINK_QUALITY); + + return 0; + } +@@ -3772,7 +3882,8 @@ static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev) + } + + while (true) { +- irq_status = lanphy_read_page_reg(phydev, 5, PTP_TSU_INT_STS); ++ irq_status = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TSU_INT_STS); + if (!irq_status) + break; + +@@ -3800,7 +3911,7 @@ static int lan8814_config_intr(struct phy_device *phydev) + { + int err; + +- lanphy_write_page_reg(phydev, 4, LAN8814_INTR_CTRL_REG, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, LAN8814_INTR_CTRL_REG, + LAN8814_INTR_CTRL_REG_POLARITY | + LAN8814_INTR_CTRL_REG_INTR_ENABLE); + +@@ -3831,29 +3942,36 @@ static void lan8814_ptp_init(struct phy_device *phydev) + !IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) + return; + +- lanphy_write_page_reg(phydev, 5, TSU_HARD_RESET, TSU_HARD_RESET_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ TSU_HARD_RESET, TSU_HARD_RESET_); + +- lanphy_modify_page_reg(phydev, 5, PTP_TX_MOD, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_TX_MOD, + PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, + PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + +- lanphy_modify_page_reg(phydev, 5, PTP_RX_MOD, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_RX_MOD, + PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, + PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + +- lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_CONFIG, 0); +- lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_CONFIG, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_CONFIG, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_CONFIG, 0); + + /* Removing default registers configs related to L2 and IP */ +- lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_L2_ADDR_EN, 0); +- lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_L2_ADDR_EN, 0); +- lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_IP_ADDR_EN, 0); +- lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_IP_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_L2_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_L2_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_IP_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_IP_ADDR_EN, 0); + + /* Disable checking for minorVersionPTP field */ +- lanphy_write_page_reg(phydev, 5, PTP_RX_VERSION, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_RX_VERSION, + PTP_MAX_VERSION(0xff) | PTP_MIN_VERSION(0x0)); +- lanphy_write_page_reg(phydev, 5, PTP_TX_VERSION, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_TX_VERSION, + PTP_MAX_VERSION(0xff) | PTP_MIN_VERSION(0x0)); + + skb_queue_head_init(&ptp_priv->tx_queue); +@@ -3934,12 +4052,14 @@ static int lan8814_ptp_probe_once(struct phy_device *phydev) + /* The EP.4 is shared between all the PHYs in the package and also it + * can be accessed by any of the PHYs + */ +- lanphy_write_page_reg(phydev, 4, LTC_HARD_RESET, LTC_HARD_RESET_); +- lanphy_write_page_reg(phydev, 4, PTP_OPERATING_MODE, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LTC_HARD_RESET, LTC_HARD_RESET_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_OPERATING_MODE, + PTP_OPERATING_MODE_STANDALONE_); + + /* Enable ptp to run LTC clock for ptp and gpio 1PPS operation */ +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, ++ PTP_CMD_CTL_PTP_ENABLE_); + + return 0; + } +@@ -3948,14 +4068,16 @@ static void lan8814_setup_led(struct phy_device *phydev, int val) + { + int temp; + +- temp = lanphy_read_page_reg(phydev, 5, LAN8814_LED_CTRL_1); ++ temp = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ LAN8814_LED_CTRL_1); + + if (val) + temp |= LAN8814_LED_CTRL_1_KSZ9031_LED_MODE_; + else + temp &= ~LAN8814_LED_CTRL_1_KSZ9031_LED_MODE_; + +- lanphy_write_page_reg(phydev, 5, LAN8814_LED_CTRL_1, temp); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ LAN8814_LED_CTRL_1, temp); + } + + static int lan8814_config_init(struct phy_device *phydev) +@@ -3963,17 +4085,19 @@ static int lan8814_config_init(struct phy_device *phydev) + struct kszphy_priv *lan8814 = phydev->priv; + + /* Reset the PHY */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_SOFT_RESET, + LAN8814_QSGMII_SOFT_RESET_BIT, + LAN8814_QSGMII_SOFT_RESET_BIT); + + /* Disable ANEG with QSGMII PCS Host side */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_PCS1G_ANEG_CONFIG, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_PCS1G_ANEG_CONFIG, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA, + 0); + + /* MDI-X setting for swap A,B transmit */ +- lanphy_modify_page_reg(phydev, 2, LAN8814_ALIGN_SWAP, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, LAN8814_ALIGN_SWAP, + LAN8814_ALIGN_TX_A_B_SWAP_MASK, + LAN8814_ALIGN_TX_A_B_SWAP); + +@@ -4010,7 +4134,7 @@ static void lan8814_clear_2psp_bit(struct phy_device *phydev) + * cable is removed then the LED was still one even though there is no + * link + */ +- lanphy_modify_page_reg(phydev, 2, LAN8814_EEE_STATE, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, LAN8814_EEE_STATE, + LAN8814_EEE_STATE_MASK2P5P, + 0); + } +@@ -4021,7 +4145,7 @@ static void lan8814_update_meas_time(struct phy_device *phydev) + * longer than 100m to be used. This configuration can be used + * regardless of the mode of operation of the PHY + */ +- lanphy_modify_page_reg(phydev, 1, LAN8814_PD_CONTROLS, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_AFE_PMA, LAN8814_PD_CONTROLS, + LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK, + LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL); + } +@@ -4046,7 +4170,7 @@ static int lan8814_probe(struct phy_device *phydev) + /* Strap-in value for PHY address, below register read gives starting + * phy address value + */ +- addr = lanphy_read_page_reg(phydev, 4, 0) & 0x1F; ++ addr = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, 0) & 0x1F; + devm_phy_package_join(&phydev->mdio.dev, phydev, + addr, sizeof(struct lan8814_shared_priv)); + +-- +2.51.0 + diff --git a/queue-6.12/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch b/queue-6.12/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch new file mode 100644 index 0000000000..7bd35c9fe5 --- /dev/null +++ b/queue-6.12/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch @@ -0,0 +1,59 @@ +From ecfbb5dbd7b8097f4c9bab1cbcc62cbe5d30640d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:35 +0530 +Subject: net: sched: act_connmark: initialize struct tc_ife to fix kernel leak + +From: Ranganath V N + +[ Upstream commit 62b656e43eaeae445a39cd8021a4f47065af4389 ] + +In tcf_connmark_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: 22a5dc0e5e3e ("net: sched: Introduce connmark action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-2-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_connmark.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 3e89927d71164..26ba8c2d20abf 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -195,13 +195,15 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); + const struct tcf_connmark_parms *parms; +- struct tc_connmark opt = { +- .index = ci->tcf_index, +- .refcnt = refcount_read(&ci->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, +- }; ++ struct tc_connmark opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ci->tcf_index; ++ opt.refcnt = refcount_read(&ci->tcf_refcnt) - ref; ++ opt.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind; ++ + rcu_read_lock(); + parms = rcu_dereference(ci->parms); + +-- +2.51.0 + diff --git a/queue-6.12/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-6.12/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..f6b3cdcb9f --- /dev/null +++ b/queue-6.12/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From 0b020ccbdccbcd6c84656b735c17b3fe58a73817 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index 107c6d83dc5c4..7c6975632fc2e 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -644,13 +644,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-6.12/net-smc-fix-mismatch-between-clc-header-and-proposal.patch b/queue-6.12/net-smc-fix-mismatch-between-clc-header-and-proposal.patch new file mode 100644 index 0000000000..60b2d240a6 --- /dev/null +++ b/queue-6.12/net-smc-fix-mismatch-between-clc-header-and-proposal.patch @@ -0,0 +1,55 @@ +From d21a504269984e4c1e6f6a2bd5ed21cf3c20e9a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 10:40:29 +0800 +Subject: net/smc: fix mismatch between CLC header and proposal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: D. Wythe + +[ Upstream commit ec33f2e5a2d0dbbfd71435209aee812fdc9369b8 ] + +The current CLC proposal message construction uses a mix of +`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether +to include optional extensions (IPv6 prefix extension for v1, and v2 +extension). This leads to a critical inconsistency: when +`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with +only link-local addresses, or when the local IP address and the outgoing +interface’s network address are not in the same subnet. + +As a result, the proposal message is assembled using the stale +`ini->smc_type_v1` value—causing the IPv6 prefix extension to be +included even though the header indicates v1 is not supported. +The peer then receives a malformed CLC proposal where the header type +does not match the payload, and immediately resets the connection. + +The fix ensures consistency between the CLC header flags and the actual +payload by synchronizing `ini->smc_type_v1` with `pclc_base->hdr.typev1` +when prefix setup fails. + +Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal") +Signed-off-by: D. Wythe +Reviewed-by: Alexandra Winter +Link: https://patch.msgid.link/20251107024029.88753-1-alibuda@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_clc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c +index 8a794333e9927..b3a8053d4ab4b 100644 +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -887,6 +887,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) + return SMC_CLC_DECL_CNFERR; + } + pclc_base->hdr.typev1 = SMC_TYPE_N; ++ ini->smc_type_v1 = SMC_TYPE_N; + } else { + pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); + plen += sizeof(*pclc_prfx) + +-- +2.51.0 + diff --git a/queue-6.12/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch b/queue-6.12/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch new file mode 100644 index 0000000000..90ed466aae --- /dev/null +++ b/queue-6.12/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch @@ -0,0 +1,100 @@ +From c4bc9a5527eda644bff316fdc837a91db6dd37c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 09:01:54 +0000 +Subject: net_sched: act_connmark: use RCU in tcf_connmark_dump() + +From: Eric Dumazet + +[ Upstream commit 0d752877705c0252ef2726e4c63c5573f048951c ] + +Also storing tcf_action into struct tcf_connmark_parms +makes sure there is no discrepancy in tcf_connmark_act(). + +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250709090204.797558-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/tc_act/tc_connmark.h | 1 + + net/sched/act_connmark.c | 18 ++++++++++-------- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h +index e8dd77a967480..a5ce83f3eea4b 100644 +--- a/include/net/tc_act/tc_connmark.h ++++ b/include/net/tc_act/tc_connmark.h +@@ -7,6 +7,7 @@ + struct tcf_connmark_parms { + struct net *net; + u16 zone; ++ int action; + struct rcu_head rcu; + }; + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 0fce631e7c911..3e89927d71164 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -88,7 +88,7 @@ TC_INDIRECT_SCOPE int tcf_connmark_act(struct sk_buff *skb, + /* using overlimits stats to count how many packets marked */ + tcf_action_inc_overlimit_qstats(&ca->common); + out: +- return READ_ONCE(ca->tcf_action); ++ return parms->action; + } + + static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { +@@ -167,6 +167,8 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + if (err < 0) + goto release_idr; + ++ nparms->action = parm->action; ++ + spin_lock_bh(&ci->tcf_lock); + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); + oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock)); +@@ -190,20 +192,20 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + int bind, int ref) + { ++ const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); +- struct tcf_connmark_info *ci = to_connmark(a); ++ const struct tcf_connmark_parms *parms; + struct tc_connmark opt = { + .index = ci->tcf_index, + .refcnt = refcount_read(&ci->tcf_refcnt) - ref, + .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, + }; +- struct tcf_connmark_parms *parms; + struct tcf_t t; + +- spin_lock_bh(&ci->tcf_lock); +- parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock)); ++ rcu_read_lock(); ++ parms = rcu_dereference(ci->parms); + +- opt.action = ci->tcf_action; ++ opt.action = parms->action; + opt.zone = parms->zone; + if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; +@@ -212,12 +214,12 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t, + TCA_CONNMARK_PAD)) + goto nla_put_failure; +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + + return skb->len; + + nla_put_failure: +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + nlmsg_trim(skb, b); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.12/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-6.12/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..9e9b30424c --- /dev/null +++ b/queue-6.12/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From 0813feb97ee108670df339c3f80b9c18f7ce46f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 8874ae6680952..d27383c54b70b 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -179,9 +179,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -192,8 +193,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -227,7 +230,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -294,7 +297,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -386,7 +389,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -395,7 +398,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -413,7 +416,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(net_hotdata.dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + if (q->flags & TCQ_F_NOLOCK) +-- +2.51.0 + diff --git a/queue-6.12/nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch b/queue-6.12/nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch new file mode 100644 index 0000000000..43773ff9d0 --- /dev/null +++ b/queue-6.12/nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch @@ -0,0 +1,43 @@ +From 6c137d9f6518fd7462e599a8c83d246849ca52bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Oct 2025 09:49:55 -0400 +Subject: NFSD: Skip close replay processing if XDR encoding fails + +From: Chuck Lever + +[ Upstream commit ff8141e49cf70d2d093a5228f5299ce188de6142 ] + +The replay logic added by commit 9411b1d4c7df ("nfsd4: cleanup +handling of nfsv4.0 closed stateid's") cannot be done if encoding +failed due to a short send buffer; there's no guarantee that the +operation encoder has actually encoded the data that is being copied +to the replay cache. + +Reported-by: rtm@csail.mit.edu +Closes: https://lore.kernel.org/linux-nfs/c3628d57-94ae-48cf-8c9e-49087a28cec9@oracle.com/T/#t +Fixes: 9411b1d4c7df ("nfsd4: cleanup handling of nfsv4.0 closed stateid's") +Reviewed-by: Jeff Layton +Reviewed-by: NeilBrown +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4xdr.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 66383eeeed15a..e6b000a4a31aa 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -5800,8 +5800,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) + */ + warn_on_nonidempotent_op(op); + xdr_truncate_encode(xdr, op_status_offset + XDR_UNIT); +- } +- if (so) { ++ } else if (so) { + int len = xdr->buf->len - (op_status_offset + XDR_UNIT); + + so->so_replay.rp_status = op->status; +-- +2.51.0 + diff --git a/queue-6.12/rust-add-fno-isolate-erroneous-paths-dereference-to-.patch b/queue-6.12/rust-add-fno-isolate-erroneous-paths-dereference-to-.patch new file mode 100644 index 0000000000..27b57047fc --- /dev/null +++ b/queue-6.12/rust-add-fno-isolate-erroneous-paths-dereference-to-.patch @@ -0,0 +1,41 @@ +From 0b8d183229f2be157cf7233098cafc6f6057ee64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:01:50 +0800 +Subject: rust: Add -fno-isolate-erroneous-paths-dereference to + bindgen_skip_c_flags + +From: Xi Ruoyao + +[ Upstream commit fe4b3a34e9a9654d98d274218dac0270779db0ae ] + +It's used to work around an objtool issue since commit abb2a5572264 +("LoongArch: Add cflag -fno-isolate-erroneous-paths-dereference"), but +it's then passed to bindgen and cause an error because Clang does not +have this option. + +Fixes: abb2a5572264 ("LoongArch: Add cflag -fno-isolate-erroneous-paths-dereference") +Acked-by: Miguel Ojeda +Tested-by: Mingcong Bai +Signed-off-by: Xi Ruoyao +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + rust/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rust/Makefile b/rust/Makefile +index 07c13100000cd..c68c147205ed8 100644 +--- a/rust/Makefile ++++ b/rust/Makefile +@@ -249,7 +249,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ + -fno-inline-functions-called-once -fsanitize=bounds-strict \ + -fstrict-flex-arrays=% -fmin-function-alignment=% \ + -fzero-init-padding-bits=% -mno-fdpic \ +- --param=% --param asan-% ++ --param=% --param asan-% -fno-isolate-erroneous-paths-dereference + + # Derived from `scripts/Makefile.clang`. + BINDGEN_TARGET_x86 := x86_64-linux-gnu +-- +2.51.0 + diff --git a/queue-6.12/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-6.12/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..9a81dbc6a8 --- /dev/null +++ b/queue-6.12/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From 13523c400b92a12c6eef373217c3c791991f2a7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 31eca29b6cfbf..abb44c0ac1a0b 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -495,6 +495,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -506,10 +507,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-6.12/selftests-net-local_termination-wait-for-interfaces-.patch b/queue-6.12/selftests-net-local_termination-wait-for-interfaces-.patch new file mode 100644 index 0000000000..6419f8e254 --- /dev/null +++ b/queue-6.12/selftests-net-local_termination-wait-for-interfaces-.patch @@ -0,0 +1,48 @@ +From 226eb306c1f6d4317d5f7d7763de90e30da0225c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 17:12:09 +0100 +Subject: selftests: net: local_termination: Wait for interfaces to come up + +From: Alexander Sverdlin + +[ Upstream commit 57531b3416448d1ced36a2a974a4085ec43d57b0 ] + +It seems that most of the tests prepare the interfaces once before the test +run (setup_prepare()), rely on setup_wait() to wait for link and only then +run the test(s). + +local_termination brings the physical interfaces down and up during test +run but never wait for them to come up. If the auto-negotiation takes +some seconds, first test packets are being lost, which leads to +false-negative test results. + +Use setup_wait() in run_test() to make sure auto-negotiation has been +completed after all simple_if_init() calls on physical interfaces and test +packets will not be lost because of the race against link establishment. + +Fixes: 90b9566aa5cd3f ("selftests: forwarding: add a test for local_termination.sh") +Reviewed-by: Vladimir Oltean +Signed-off-by: Alexander Sverdlin +Link: https://patch.msgid.link/20251106161213.459501-1-alexander.sverdlin@siemens.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/forwarding/local_termination.sh | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/net/forwarding/local_termination.sh b/tools/testing/selftests/net/forwarding/local_termination.sh +index ecd34f364125c..892895659c7e4 100755 +--- a/tools/testing/selftests/net/forwarding/local_termination.sh ++++ b/tools/testing/selftests/net/forwarding/local_termination.sh +@@ -176,6 +176,8 @@ run_test() + local rcv_dmac=$(mac_get $rcv_if_name) + local should_receive + ++ setup_wait ++ + tcpdump_start $rcv_if_name + + mc_route_prepare $send_if_name +-- +2.51.0 + diff --git a/queue-6.12/series b/queue-6.12/series index e885a5bf4e..bb4a5c4152 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -27,3 +27,40 @@ smb-server-fix-possible-memory-leak-in-smb2_read.patch smb-server-fix-possible-refcount-leak-in-smb2_sess_s.patch hid-logitech-hidpp-add-hidpp_quirk_reset_hi_res_scro.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch +wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch +erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch +selftests-net-local_termination-wait-for-interfaces-.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +net-phy-micrel-introduce-lanphy_modify_page_reg.patch +net-phy-micrel-replace-hardcoded-pages-with-defines.patch +net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch +rust-add-fno-isolate-erroneous-paths-dereference-to-.patch +nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch +bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +net-smc-fix-mismatch-between-clc-header-and-proposal.patch +net-handshake-fix-memory-leak-in-tls_handshake_accep.patch +net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch +net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +af_unix-initialise-scc_index-in-unix_add_edge.patch +net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch +net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net-mlx5e-fix-potentially-misleading-debug-message.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +virtio-net-fix-incorrect-flags-recording-in-big-mode.patch +hsr-fix-supervision-frame-sending-on-hsrv0.patch +acpi-cppc-detect-preferred-core-availability-on-onli.patch +acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch +acpi-cppc-perform-fast-check-switch-only-for-online-.patch +acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch diff --git a/queue-6.12/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-6.12/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..bffcf6c9f9 --- /dev/null +++ b/queue-6.12/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From 72093695720e6b7501550d9b6ce9763249f83d16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 0e95572e56b41..7e65d0b0c4a8d 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -145,7 +145,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-6.12/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch b/queue-6.12/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch new file mode 100644 index 0000000000..31a26ea086 --- /dev/null +++ b/queue-6.12/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch @@ -0,0 +1,72 @@ +From b4b3c41c2e7e0291e69c4b1b242b9c78a90080a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:08:28 +0800 +Subject: virtio-net: fix incorrect flags recording in big mode + +From: Xuan Zhuo + +[ Upstream commit 0eff2eaa5322b5b141ff5d5ded26fac4a52b5f7b ] + +The purpose of commit 703eec1b2422 ("virtio_net: fixing XDP for fully +checksummed packets handling") is to record the flags in advance, as +their value may be overwritten in the XDP case. However, the flags +recorded under big mode are incorrect, because in big mode, the passed +buf does not point to the rx buffer, but rather to the page of the +submitted buffer. This commit fixes this issue. + +For the small mode, the commit c11a49d58ad2 ("virtio_net: Fix mismatched +buf address when unmapping for small packets") fixed it. + +Tested-by: Alyssa Ross +Fixes: 703eec1b2422 ("virtio_net: fixing XDP for fully checksummed packets handling") +Signed-off-by: Xuan Zhuo +Acked-by: Jason Wang +Acked-by: Michael S. Tsirkin +Link: https://patch.msgid.link/20251111090828.23186-1-xuanzhuo@linux.alibaba.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/virtio_net.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 259e3a35dce93..97c49f33122c1 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -2455,22 +2455,28 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, + return; + } + +- /* 1. Save the flags early, as the XDP program might overwrite them. ++ /* About the flags below: ++ * 1. Save the flags early, as the XDP program might overwrite them. + * These flags ensure packets marked as VIRTIO_NET_HDR_F_DATA_VALID + * stay valid after XDP processing. + * 2. XDP doesn't work with partially checksummed packets (refer to + * virtnet_xdp_set()), so packets marked as + * VIRTIO_NET_HDR_F_NEEDS_CSUM get dropped during XDP processing. + */ +- flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + +- if (vi->mergeable_rx_bufs) ++ if (vi->mergeable_rx_bufs) { ++ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit, + stats); +- else if (vi->big_packets) ++ } else if (vi->big_packets) { ++ void *p = page_address((struct page *)buf); ++ ++ flags = ((struct virtio_net_common_hdr *)p)->hdr.flags; + skb = receive_big(dev, vi, rq, buf, len, stats); +- else ++ } else { ++ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, stats); ++ } + + if (unlikely(!skb)) + return; +-- +2.51.0 + diff --git a/queue-6.12/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch b/queue-6.12/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch new file mode 100644 index 0000000000..c8c9a0e8ee --- /dev/null +++ b/queue-6.12/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch @@ -0,0 +1,53 @@ +From 9fe74e87cb63b31cff138dfff45de06be82316c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Nov 2025 09:39:57 +0100 +Subject: wifi: ath11k: zero init info->status in wmi_process_mgmt_tx_comp() + +From: Nicolas Escande + +[ Upstream commit 9065b968752334f972e0d48e50c4463a172fc2a7 ] + +When reporting tx completion using ieee80211_tx_status_xxx() family of +functions, the status part of the struct ieee80211_tx_info nested in the +skb is used to report things like transmit rates & retry count to mac80211 + +On the TX data path, this is correctly memset to 0 before calling +ieee80211_tx_status_ext(), but on the tx mgmt path this was not done. + +This leads to mac80211 treating garbage values as valid transmit counters +(like tx retries for example) and accounting them as real statistics that +makes their way to userland via station dump. + +The same issue was resolved in ath12k by commit 9903c0986f78 ("wifi: +ath12k: Add memset and update default rate value in wmi tx completion") + +Tested-on: QCN9074 PCI WLAN.HK.2.9.0.1-01977-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20251104083957.717825-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/wmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 98811726d33bf..bfca9d3639810 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5961,6 +5961,9 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); ++ memset(&info->status, 0, sizeof(info->status)); ++ info->status.rates[0].idx = -1; ++ + if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && + !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; +-- +2.51.0 + diff --git a/queue-6.12/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-6.12/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..1332f4ff0d --- /dev/null +++ b/queue-6.12/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From beb1369c90f054fcbbb77722ab2f4c602966d7c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 538c6eea645f2..ea6fe21c96c55 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -5402,10 +5402,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 + diff --git a/queue-6.17/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch b/queue-6.17/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch new file mode 100644 index 0000000000..1e451a14b7 --- /dev/null +++ b/queue-6.17/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch @@ -0,0 +1,49 @@ +From b410fb536ef1677c559f594b5c59b16325b5398a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:42 +0530 +Subject: ACPI: CPPC: Check _CPC validity for only the online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 6dd3b8a709a130a4d55c866af9804c81b8486d28 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function acpi_cpc_valid() checks for the validity of the +_CPC object for all the present CPUs. This breaks when the kernel is +booted with "nosmt=force". + +Hence check the validity of the _CPC objects of only the online CPUs. + +Fixes: 2aeca6bd0277 ("ACPI: CPPC: Check present CPUs for determining _CPC is valid") +Reported-by: Christopher Harris +Closes: https://lore.kernel.org/lkml/CAM+eXpdDT7KjLV0AxEwOLkSJ2QtrsvGvjA2cCHvt1d0k2_C4Cw@mail.gmail.com/ +Suggested-by: Mario Limonciello +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Tested-by: Chrisopher Harris +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-3-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 6b649031808f8..6694412a1e139 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -460,7 +460,7 @@ bool acpi_cpc_valid(void) + if (acpi_disabled) + return false; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + if (!cpc_ptr) + return false; +-- +2.51.0 + diff --git a/queue-6.17/acpi-cppc-detect-preferred-core-availability-on-onli.patch b/queue-6.17/acpi-cppc-detect-preferred-core-availability-on-onli.patch new file mode 100644 index 0000000000..a3a153147d --- /dev/null +++ b/queue-6.17/acpi-cppc-detect-preferred-core-availability-on-onli.patch @@ -0,0 +1,49 @@ +From 37db71e64b506a38ae3450fd756ed4ba151b6d64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:41 +0530 +Subject: ACPI: CPPC: Detect preferred core availability on online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 4fe5934db4a7187d358f1af1b3ef9b6dd59bce58 ] + +Commit 279f838a61f9 ("x86/amd: Detect preferred cores in +amd_get_boost_ratio_numerator()") introduced the ability to detect the +preferred core on AMD platforms by checking if there at least two +distinct highest_perf values. + +However, it uses for_each_present_cpu() to iterate through all the +CPUs in the platform, which is problematic when the kernel is booted +with "nosmt=force" commandline option. + +Hence limit the search to only the online CPUs. + +Fixes: 279f838a61f9 ("x86/amd: Detect preferred cores in amd_get_boost_ratio_numerator()") +Reported-by: Christopher Harris +Closes: https://lore.kernel.org/lkml/CAM+eXpdDT7KjLV0AxEwOLkSJ2QtrsvGvjA2cCHvt1d0k2_C4Cw@mail.gmail.com/ +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Tested-by: Chrisopher Harris +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-2-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/acpi/cppc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c +index 7047124490f64..d7c8ef1e354d3 100644 +--- a/arch/x86/kernel/acpi/cppc.c ++++ b/arch/x86/kernel/acpi/cppc.c +@@ -196,7 +196,7 @@ int amd_detect_prefcore(bool *detected) + break; + } + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + u32 tmp; + int ret; + +-- +2.51.0 + diff --git a/queue-6.17/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch b/queue-6.17/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch new file mode 100644 index 0000000000..f4a7425886 --- /dev/null +++ b/queue-6.17/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch @@ -0,0 +1,45 @@ +From 9da33072c6bc661deaec130a255ca80c044072d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:44 +0530 +Subject: ACPI: CPPC: Limit perf ctrs in PCC check only to online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 0fce75870666b46b700cfbd3216380b422f975da ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPU via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_perf_ctrs_in_pcc() checks if the CPPC +perf-ctrs are in a PCC region for all the present CPUs, which breaks +when the kernel is booted with "nosmt=force". + +Hence, limit the check only to the online CPUs. + +Fixes: ae2df912d1a5 ("ACPI: CPPC: Disable FIE if registers in PCC regions") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-5-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 51e925f289bf3..002c3dde283ff 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -1435,7 +1435,7 @@ bool cppc_perf_ctrs_in_pcc(void) + { + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + struct cpc_register_resource *ref_perf_reg; + struct cpc_desc *cpc_desc; + +-- +2.51.0 + diff --git a/queue-6.17/acpi-cppc-perform-fast-check-switch-only-for-online-.patch b/queue-6.17/acpi-cppc-perform-fast-check-switch-only-for-online-.patch new file mode 100644 index 0000000000..207a95776d --- /dev/null +++ b/queue-6.17/acpi-cppc-perform-fast-check-switch-only-for-online-.patch @@ -0,0 +1,45 @@ +From 5d3d305539664831a5bd2864eb56b2dde92c3ae5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:43 +0530 +Subject: ACPI: CPPC: Perform fast check switch only for online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 8821c8e80a65bc4eb73daf63b34aac6b8ad69461 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_allow_fast_switch() checks for the validity +of the _CPC object for all the present CPUs. This breaks when the +kernel is booted with "nosmt=force". + +Check fast_switch capability only on online CPUs + +Fixes: 15eece6c5b05 ("ACPI: CPPC: Fix NULL pointer dereference when nosmp is used") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-4-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 6694412a1e139..51e925f289bf3 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -476,7 +476,7 @@ bool cppc_allow_fast_switch(void) + struct cpc_desc *cpc_ptr; + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF]; + if (!CPC_IN_SYSTEM_MEMORY(desired_reg) && +-- +2.51.0 + diff --git a/queue-6.17/af_unix-initialise-scc_index-in-unix_add_edge.patch b/queue-6.17/af_unix-initialise-scc_index-in-unix_add_edge.patch new file mode 100644 index 0000000000..e61d8f2d19 --- /dev/null +++ b/queue-6.17/af_unix-initialise-scc_index-in-unix_add_edge.patch @@ -0,0 +1,139 @@ +From 70631e205e17748fd9120c924f9ff0b9e5abc1bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 02:52:22 +0000 +Subject: af_unix: Initialise scc_index in unix_add_edge(). + +From: Kuniyuki Iwashima + +[ Upstream commit 60e6489f8e3b086bd1130ad4450a2c112e863791 ] + +Quang Le reported that the AF_UNIX GC could garbage-collect a +receive queue of an alive in-flight socket, with a nice repro. + +The repro consists of three stages. + + 1) + 1-a. Create a single cyclic reference with many sockets + 1-b. close() all sockets + 1-c. Trigger GC + + 2) + 2-a. Pass sk-A to an embryo sk-B + 2-b. Pass sk-X to sk-X + 2-c. Trigger GC + + 3) + 3-a. accept() the embryo sk-B + 3-b. Pass sk-B to sk-C + 3-c. close() the in-flight sk-A + 3-d. Trigger GC + +As of 2-c, sk-A and sk-X are linked to unix_unvisited_vertices, +and unix_walk_scc() groups them into two different SCCs: + + unix_sk(sk-A)->vertex->scc_index = 2 (UNIX_VERTEX_INDEX_START) + unix_sk(sk-X)->vertex->scc_index = 3 + +Once GC completes, unix_graph_grouped is set to true. +Also, unix_graph_maybe_cyclic is set to true due to sk-X's +cyclic self-reference, which makes close() trigger GC. + +At 3-b, unix_add_edge() allocates unix_sk(sk-B)->vertex and +links it to unix_unvisited_vertices. + +unix_update_graph() is called at 3-a. and 3-b., but neither +unix_graph_grouped nor unix_graph_maybe_cyclic is changed +because both sk-B's listener and sk-C are not in-flight. + +3-c decrements sk-A's file refcnt to 1. + +Since unix_graph_grouped is true at 3-d, unix_walk_scc_fast() +is finally called and iterates 3 sockets sk-A, sk-B, and sk-X: + + sk-A -> sk-B (-> sk-C) + sk-X -> sk-X + +This is totally fine. All of them are not yet close()d and +should be grouped into different SCCs. + +However, unix_vertex_dead() misjudges that sk-A and sk-B are +in the same SCC and sk-A is dead. + + unix_sk(sk-A)->scc_index == unix_sk(sk-B)->scc_index <-- Wrong! + && + sk-A's file refcnt == unix_sk(sk-A)->vertex->out_degree + ^-- 1 in-flight count for sk-B + -> sk-A is dead !? + +The problem is that unix_add_edge() does not initialise scc_index. + +Stage 1) is used for heap spraying, making a newly allocated +vertex have vertex->scc_index == 2 (UNIX_VERTEX_INDEX_START) +set by unix_walk_scc() at 1-c. + +Let's track the max SCC index from the previous unix_walk_scc() +call and assign the max + 1 to a new vertex's scc_index. + +This way, we can continue to avoid Tarjan's algorithm while +preventing misjudgments. + +Fixes: ad081928a8b0 ("af_unix: Avoid Tarjan's algorithm if unnecessary.") +Reported-by: Quang Le +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20251109025233.3659187-1-kuniyu@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/garbage.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 01e2b9452c75b..358fcaba9a732 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -145,6 +145,7 @@ enum unix_vertex_index { + }; + + static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1; ++static unsigned long unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + { +@@ -153,6 +154,7 @@ static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + if (!vertex) { + vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry); + vertex->index = unix_vertex_unvisited_index; ++ vertex->scc_index = ++unix_vertex_max_scc_index; + vertex->out_degree = 0; + INIT_LIST_HEAD(&vertex->edges); + INIT_LIST_HEAD(&vertex->scc_entry); +@@ -489,10 +491,15 @@ static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_inde + scc_dead = unix_vertex_dead(v); + } + +- if (scc_dead) ++ if (scc_dead) { + unix_collect_skb(&scc, hitlist); +- else if (!unix_graph_maybe_cyclic) +- unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } else { ++ if (unix_vertex_max_scc_index < vertex->scc_index) ++ unix_vertex_max_scc_index = vertex->scc_index; ++ ++ if (!unix_graph_maybe_cyclic) ++ unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } + + list_del(&scc); + } +@@ -507,6 +514,7 @@ static void unix_walk_scc(struct sk_buff_head *hitlist) + unsigned long last_index = UNIX_VERTEX_INDEX_START; + + unix_graph_maybe_cyclic = false; ++ unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + /* Visit every vertex exactly once. + * __unix_walk_scc() moves visited vertices to unix_visited_vertices. +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-6.17/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..8408f95658 --- /dev/null +++ b/queue-6.17/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From 32a55af5b354717c02f7d786bc2b66a2b7b223eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 0d8c2e2e9a6cf..588d7e94e6069 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -53,6 +53,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -61,6 +66,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1014,41 +1021,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-6.17/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..a13a31d791 --- /dev/null +++ b/queue-6.17/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From 8f328addb48774e08700b63dda304ecb94036860 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index f1d29fa4b4119..0d8c2e2e9a6cf 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -957,10 +957,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -971,13 +972,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1104,7 +1124,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1141,7 +1161,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-6.17/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..c24488804e --- /dev/null +++ b/queue-6.17/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From 36b7edb73edd73828f6824a8419fde3e6eb56543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index f0c862091bff2..f1d29fa4b4119 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -289,6 +289,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-6.17/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..8c44de9126 --- /dev/null +++ b/queue-6.17/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From 2328930334ad146d6ff2ad06da94a8d1628f4127 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 5e9ebf0c53125..a722446ec73dd 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4361,6 +4361,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4371,17 +4376,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-hci_conn-fix-not-cleaning-up-pa_link-conne.patch b/queue-6.17/bluetooth-hci_conn-fix-not-cleaning-up-pa_link-conne.patch new file mode 100644 index 0000000000..f3efb62d98 --- /dev/null +++ b/queue-6.17/bluetooth-hci_conn-fix-not-cleaning-up-pa_link-conne.patch @@ -0,0 +1,149 @@ +From ac037a84362c9073e93ffeca412bbcfa524c94b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Nov 2025 17:02:04 -0500 +Subject: Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections + +From: Luiz Augusto von Dentz + +[ Upstream commit 41bf23338a501e745c398e0faee948dd05d0be98 ] + +Contrary to what was stated on d36349ea73d8 ("Bluetooth: hci_conn: +Fix running bis_cleanup for hci_conn->type PA_LINK") the PA_LINK does +in fact needs to run bis_cleanup in order to terminate the PA Sync, +since that is bond to the listening socket which is the entity that +controls the lifetime of PA Sync, so if it is closed/released the PA +Sync shall be terminated, terminating the PA Sync shall not result in +the BIG Sync being terminated since once the later is established it +doesn't depend on the former anymore. + +If the use user wants to reconnect/rebind a number of BIS(s) it shall +keep the socket open until it no longer needs the PA Sync, which means +it retains full control of the lifetime of both PA and BIG Syncs. + +Fixes: d36349ea73d8 ("Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK") +Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_conn.c | 33 +++++++++++++++++++-------------- + net/bluetooth/hci_event.c | 7 +------ + net/bluetooth/hci_sync.c | 2 +- + 3 files changed, 21 insertions(+), 21 deletions(-) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index c021c6cb3d9a5..5846b4bae77a3 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -769,21 +769,23 @@ static void find_bis(struct hci_conn *conn, void *data) + d->count++; + } + +-static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn) ++static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn) + { + struct iso_list_data *d; + int ret; + +- bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, conn->sync_handle); ++ bt_dev_dbg(hdev, "hcon %p big 0x%2.2x sync_handle 0x%4.4x", conn, ++ conn->iso_qos.bcast.big, conn->sync_handle); + + d = kzalloc(sizeof(*d), GFP_KERNEL); + if (!d) + return -ENOMEM; + +- d->big = big; ++ d->big = conn->iso_qos.bcast.big; + d->sync_handle = conn->sync_handle; + +- if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) { ++ if (conn->type == PA_LINK && ++ test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) { + hci_conn_hash_list_flag(hdev, find_bis, PA_LINK, + HCI_CONN_PA_SYNC, d); + +@@ -801,6 +803,9 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c + d->big_sync_term = true; + } + ++ if (!d->pa_sync_term && !d->big_sync_term) ++ return 0; ++ + ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d, + terminate_big_destroy); + if (ret) +@@ -852,8 +857,7 @@ static void bis_cleanup(struct hci_conn *conn) + + hci_le_terminate_big(hdev, conn); + } else { +- hci_le_big_terminate(hdev, conn->iso_qos.bcast.big, +- conn); ++ hci_le_big_terminate(hdev, conn); + } + } + +@@ -995,19 +999,20 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t + conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu; + break; + case CIS_LINK: +- case BIS_LINK: +- case PA_LINK: + /* conn->src should reflect the local identity address */ + hci_copy_identity_address(hdev, &conn->src, &conn->src_type); + +- /* set proper cleanup function */ +- if (!bacmp(dst, BDADDR_ANY)) +- conn->cleanup = bis_cleanup; +- else if (conn->role == HCI_ROLE_MASTER) ++ if (conn->role == HCI_ROLE_MASTER) + conn->cleanup = cis_cleanup; + +- conn->mtu = hdev->iso_mtu ? hdev->iso_mtu : +- hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu; ++ conn->mtu = hdev->iso_mtu; ++ break; ++ case PA_LINK: ++ case BIS_LINK: ++ /* conn->src should reflect the local identity address */ ++ hci_copy_identity_address(hdev, &conn->src, &conn->src_type); ++ conn->cleanup = bis_cleanup; ++ conn->mtu = hdev->iso_mtu; + break; + case SCO_LINK: + if (lmp_esco_capable(hdev)) +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 7ee8bc7ac5a2a..0380d2f596c97 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -7011,14 +7011,9 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, + continue; + } + +- if (ev->status != 0x42) { ++ if (ev->status != 0x42) + /* Mark PA sync as established */ + set_bit(HCI_CONN_PA_SYNC, &bis->flags); +- /* Reset cleanup callback of PA Sync so it doesn't +- * terminate the sync when deleting the connection. +- */ +- conn->cleanup = NULL; +- } + + bis->sync_handle = conn->sync_handle; + bis->iso_qos.bcast.big = ev->handle; +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 73fc41b68b687..6e76798ec786b 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -6999,7 +6999,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err) + + hci_dev_lock(hdev); + +- if (!hci_conn_valid(hdev, conn)) ++ if (hci_conn_valid(hdev, conn)) + clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); + + if (!err) +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-hci_event-fix-not-handling-pa-sync-lost-ev.patch b/queue-6.17/bluetooth-hci_event-fix-not-handling-pa-sync-lost-ev.patch new file mode 100644 index 0000000000..3feaa14d0b --- /dev/null +++ b/queue-6.17/bluetooth-hci_event-fix-not-handling-pa-sync-lost-ev.patch @@ -0,0 +1,123 @@ +From 5333adefff9750184878aee17a2fb6d7981cd04b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 13:05:35 -0500 +Subject: Bluetooth: hci_event: Fix not handling PA Sync Lost event + +From: Luiz Augusto von Dentz + +[ Upstream commit 485e0626e58768f3c53ba61ab9e09d6b60a455f4 ] + +This handles PA Sync Lost event which previously was assumed to be +handled with BIG Sync Lost but their lifetime are not the same thus why +there are 2 different events to inform when each sync is lost. + +Fixes: b2a5f2e1c127 ("Bluetooth: hci_event: Add support for handling LE BIG Sync Lost event") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci.h | 5 ++++ + net/bluetooth/hci_event.c | 49 ++++++++++++++++++++++++++----------- + 2 files changed, 40 insertions(+), 14 deletions(-) + +diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h +index dca650cede3c4..63160cfcf2b22 100644 +--- a/include/net/bluetooth/hci.h ++++ b/include/net/bluetooth/hci.h +@@ -2782,6 +2782,11 @@ struct hci_ev_le_per_adv_report { + __u8 data[]; + } __packed; + ++#define HCI_EV_LE_PA_SYNC_LOST 0x10 ++struct hci_ev_le_pa_sync_lost { ++ __le16 handle; ++} __packed; ++ + #define LE_PA_DATA_COMPLETE 0x00 + #define LE_PA_DATA_MORE_TO_COME 0x01 + #define LE_PA_DATA_TRUNCATED 0x02 +diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c +index 0380d2f596c97..a9a5d12943fa0 100644 +--- a/net/bluetooth/hci_event.c ++++ b/net/bluetooth/hci_event.c +@@ -5853,6 +5853,29 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data, + le16_to_cpu(ev->supervision_timeout)); + } + ++static void hci_le_pa_sync_lost_evt(struct hci_dev *hdev, void *data, ++ struct sk_buff *skb) ++{ ++ struct hci_ev_le_pa_sync_lost *ev = data; ++ u16 handle = le16_to_cpu(ev->handle); ++ struct hci_conn *conn; ++ ++ bt_dev_dbg(hdev, "sync handle 0x%4.4x", handle); ++ ++ hci_dev_lock(hdev); ++ ++ /* Delete the pa sync connection */ ++ conn = hci_conn_hash_lookup_pa_sync_handle(hdev, handle); ++ if (conn) { ++ clear_bit(HCI_CONN_BIG_SYNC, &conn->flags); ++ clear_bit(HCI_CONN_PA_SYNC, &conn->flags); ++ hci_disconn_cfm(conn, HCI_ERROR_REMOTE_USER_TERM); ++ hci_conn_del(conn); ++ } ++ ++ hci_dev_unlock(hdev); ++} ++ + static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { +@@ -7056,29 +7079,24 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) + { + struct hci_evt_le_big_sync_lost *ev = data; +- struct hci_conn *bis, *conn; +- bool mgmt_conn; ++ struct hci_conn *bis; ++ bool mgmt_conn = false; + + bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); + + hci_dev_lock(hdev); + +- /* Delete the pa sync connection */ +- bis = hci_conn_hash_lookup_pa_sync_big_handle(hdev, ev->handle); +- if (bis) { +- conn = hci_conn_hash_lookup_pa_sync_handle(hdev, +- bis->sync_handle); +- if (conn) +- hci_conn_del(conn); +- } +- + /* Delete each bis connection */ + while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, + BT_CONNECTED, + HCI_ROLE_SLAVE))) { +- mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); +- mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, +- ev->reason, mgmt_conn); ++ if (!mgmt_conn) { ++ mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, ++ &bis->flags); ++ mgmt_device_disconnected(hdev, &bis->dst, bis->type, ++ bis->dst_type, ev->reason, ++ mgmt_conn); ++ } + + clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); + hci_disconn_cfm(bis, ev->reason); +@@ -7192,6 +7210,9 @@ static const struct hci_le_ev { + hci_le_per_adv_report_evt, + sizeof(struct hci_ev_le_per_adv_report), + HCI_MAX_EVENT_SIZE), ++ /* [0x10 = HCI_EV_LE_PA_SYNC_LOST] */ ++ HCI_LE_EV(HCI_EV_LE_PA_SYNC_LOST, hci_le_pa_sync_lost_evt, ++ sizeof(struct hci_ev_le_pa_sync_lost)), + /* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */ + HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt, + sizeof(struct hci_evt_le_ext_adv_set_term)), +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-6.17/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..41f86a033e --- /dev/null +++ b/queue-6.17/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 2a29a39362eeacff2f6dd597924f3bb521b29403 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index d08320380ad67..35c57657bcf4e 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -497,6 +497,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-6.17/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch b/queue-6.17/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch new file mode 100644 index 0000000000..1fd1e7a31c --- /dev/null +++ b/queue-6.17/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch @@ -0,0 +1,56 @@ +From 01497d25c7f3d53dadb79f3824637f568c1cbe7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Nov 2025 20:16:12 +0200 +Subject: Bluetooth: MGMT: cancel mesh send timer when hdev removed + +From: Pauli Virtanen + +[ Upstream commit 55fb52ffdd62850d667ebed842815e072d3c9961 ] + +mesh_send_done timer is not canceled when hdev is removed, which causes +crash if the timer triggers after hdev is gone. + +Cancel the timer when MGMT removes the hdev, like other MGMT timers. + +Should fix the BUG: sporadically seen by BlueZ test bot +(in "Mesh - Send cancel - 1" test). + +Log: +------ +BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 +... +Freed by task 36: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3a/0x60 + __kasan_slab_free+0x43/0x70 + kfree+0x103/0x500 + device_release+0x9a/0x210 + kobject_put+0x100/0x1e0 + vhci_release+0x18b/0x240 +------ + +Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh") +Link: https://lore.kernel.org/linux-bluetooth/67364c09.0c0a0220.113cba.39ff@mx.google.com/ +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 79762bfaea5ff..262bf984d2aaf 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9497,6 +9497,7 @@ void mgmt_index_removed(struct hci_dev *hdev) + cancel_delayed_work_sync(&hdev->discov_off); + cancel_delayed_work_sync(&hdev->service_cache); + cancel_delayed_work_sync(&hdev->rpa_expired); ++ cancel_delayed_work_sync(&hdev->mesh_send_done); + } + + void mgmt_power_on(struct hci_dev *hdev, int err) +-- +2.51.0 + diff --git a/queue-6.17/cpufreq-intel_pstate-check-ida-only-before-msr_ia32_.patch b/queue-6.17/cpufreq-intel_pstate-check-ida-only-before-msr_ia32_.patch new file mode 100644 index 0000000000..9ecdf05098 --- /dev/null +++ b/queue-6.17/cpufreq-intel_pstate-check-ida-only-before-msr_ia32_.patch @@ -0,0 +1,72 @@ +From 0e12f0fdd167723fb50a9207b43259e7312877c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 17:08:40 -0800 +Subject: cpufreq: intel_pstate: Check IDA only before MSR_IA32_PERF_CTL writes + +From: Srinivas Pandruvada + +[ Upstream commit 4b747cc628d8f500d56cf1338280eacc66362ff3 ] + +Commit ac4e04d9e378 ("cpufreq: intel_pstate: Unchecked MSR aceess in +legacy mode") introduced a check for feature X86_FEATURE_IDA to verify +turbo mode support. Although this is the correct way to check for turbo +mode support, it causes issues on some platforms that disable turbo +during OS boot, but enable it later [1]. Before adding this feature +check, users were able to get turbo mode frequencies by writing 0 to +/sys/devices/system/cpu/intel_pstate/no_turbo post-boot. + +To restore the old behavior on the affected systems while still +addressing the unchecked MSR issue on some Skylake-X systems, check +X86_FEATURE_IDA only immediately before updates of MSR_IA32_PERF_CTL +that may involve setting the Turbo Engage Bit (bit 32). + +Fixes: ac4e04d9e378 ("cpufreq: intel_pstate: Unchecked MSR aceess in legacy mode") +Reported-by: Aaron Rainbolt +Closes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2122531 [1] +Tested-by: Aaron Rainbolt +Signed-off-by: Srinivas Pandruvada +[ rjw: Subject adjustment, changelog edits ] +Link: https://patch.msgid.link/20251111010840.141490-1-srinivas.pandruvada@linux.intel.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/intel_pstate.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index fc02a3542f656..99c80249fde88 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -603,9 +603,6 @@ static bool turbo_is_disabled(void) + { + u64 misc_en; + +- if (!cpu_feature_enabled(X86_FEATURE_IDA)) +- return true; +- + rdmsrq(MSR_IA32_MISC_ENABLE, misc_en); + + return !!(misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE); +@@ -2141,7 +2138,8 @@ static u64 atom_get_val(struct cpudata *cpudata, int pstate) + u32 vid; + + val = (u64)pstate << 8; +- if (READ_ONCE(global.no_turbo) && !READ_ONCE(global.turbo_disabled)) ++ if (READ_ONCE(global.no_turbo) && !READ_ONCE(global.turbo_disabled) && ++ cpu_feature_enabled(X86_FEATURE_IDA)) + val |= (u64)1 << 32; + + vid_fp = cpudata->vid.min + mul_fp( +@@ -2306,7 +2304,8 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate) + u64 val; + + val = (u64)pstate << 8; +- if (READ_ONCE(global.no_turbo) && !READ_ONCE(global.turbo_disabled)) ++ if (READ_ONCE(global.no_turbo) && !READ_ONCE(global.turbo_disabled) && ++ cpu_feature_enabled(X86_FEATURE_IDA)) + val |= (u64)1 << 32; + + return val; +-- +2.51.0 + diff --git a/queue-6.17/erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch b/queue-6.17/erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch new file mode 100644 index 0000000000..69f73aac4f --- /dev/null +++ b/queue-6.17/erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch @@ -0,0 +1,60 @@ +From bc73d9bfaa0aad4612cae530c0e3bde6f24f0955 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 Oct 2025 13:47:39 +0800 +Subject: erofs: avoid infinite loop due to incomplete zstd-compressed data + +From: Gao Xiang + +[ Upstream commit f2a12cc3b97f062186568a7b94ddb7aa2ef68140 ] + +Currently, the decompression logic incorrectly spins if compressed +data is truncated in crafted (deliberately corrupted) images. + +Fixes: 7c35de4df105 ("erofs: Zstandard compression support") +Reported-by: Robert Morris +Closes: https://lore.kernel.org/r/50958.1761605413@localhost +Signed-off-by: Gao Xiang +Reviewed-by: Chunhai Guo +Reviewed-by: Chao Yu +Signed-off-by: Sasha Levin +--- + fs/erofs/decompressor_zstd.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/erofs/decompressor_zstd.c b/fs/erofs/decompressor_zstd.c +index b4bfe14229f9f..e38d93bb21048 100644 +--- a/fs/erofs/decompressor_zstd.c ++++ b/fs/erofs/decompressor_zstd.c +@@ -172,7 +172,6 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, + dctx.bounce = strm->bounce; + + do { +- dctx.avail_out = out_buf.size - out_buf.pos; + dctx.inbuf_sz = in_buf.size; + dctx.inbuf_pos = in_buf.pos; + err = z_erofs_stream_switch_bufs(&dctx, &out_buf.dst, +@@ -188,14 +187,18 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, + in_buf.pos = dctx.inbuf_pos; + + zerr = zstd_decompress_stream(stream, &out_buf, &in_buf); +- if (zstd_is_error(zerr) || (!zerr && rq->outputsize)) { ++ dctx.avail_out = out_buf.size - out_buf.pos; ++ if (zstd_is_error(zerr) || ++ ((rq->outputsize + dctx.avail_out) && (!zerr || (zerr > 0 && ++ !(rq->inputsize + in_buf.size - in_buf.pos))))) { + erofs_err(sb, "failed to decompress in[%u] out[%u]: %s", + rq->inputsize, rq->outputsize, +- zerr ? zstd_get_error_name(zerr) : "unexpected end of stream"); ++ zstd_is_error(zerr) ? zstd_get_error_name(zerr) : ++ "unexpected end of stream"); + err = -EFSCORRUPTED; + break; + } +- } while (rq->outputsize || out_buf.pos < out_buf.size); ++ } while (rq->outputsize + dctx.avail_out); + + if (dctx.kout) + kunmap_local(dctx.kout); +-- +2.51.0 + diff --git a/queue-6.17/hsr-fix-supervision-frame-sending-on-hsrv0.patch b/queue-6.17/hsr-fix-supervision-frame-sending-on-hsrv0.patch new file mode 100644 index 0000000000..ff397a8b69 --- /dev/null +++ b/queue-6.17/hsr-fix-supervision-frame-sending-on-hsrv0.patch @@ -0,0 +1,50 @@ +From be848105ac9a247c121f87079ed4fc0e2fe7ed4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:32 +0100 +Subject: hsr: Fix supervision frame sending on HSRv0 + +From: Felix Maurer + +[ Upstream commit 96a3a03abf3d8cc38cd9cb0d280235fbcf7c3f7f ] + +On HSRv0, no supervision frames were sent. The supervison frames were +generated successfully, but failed the check for a sufficiently long mac +header, i.e., at least sizeof(struct hsr_ethhdr), in hsr_fill_frame_info() +because the mac header only contained the ethernet header. + +Fix this by including the HSR header in the mac header when generating HSR +supervision frames. Note that the mac header now also includes the TLV +fields. This matches how we set the headers on rx and also the size of +struct hsrv0_ethhdr_sp. + +Reported-by: Hangbin Liu +Closes: https://lore.kernel.org/netdev/aMONxDXkzBZZRfE5@fedora/ +Fixes: 9cfb5e7f0ded ("net: hsr: fix hsr_init_sk() vs network/transport headers.") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Tested-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/4354114fea9a642fe71f49aeeb6c6159d1d61840.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index fbbc3ccf9df64..1235abb2d79fa 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -320,6 +320,9 @@ static void send_hsr_supervision_frame(struct hsr_port *port, + } + + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); ++ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); ++ skb_reset_mac_len(skb); ++ + set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + +-- +2.51.0 + diff --git a/queue-6.17/hsr-follow-standard-for-hsrv0-supervision-frames.patch b/queue-6.17/hsr-follow-standard-for-hsrv0-supervision-frames.patch new file mode 100644 index 0000000000..23350a332f --- /dev/null +++ b/queue-6.17/hsr-follow-standard-for-hsrv0-supervision-frames.patch @@ -0,0 +1,111 @@ +From 981a4012df7aa3988d4f7e8e6914c948d3b067d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:33 +0100 +Subject: hsr: Follow standard for HSRv0 supervision frames + +From: Felix Maurer + +[ Upstream commit b2c26c82f7a94ec4da096f370e3612ee14424450 ] + +For HSRv0, the path_id has the following meaning: +- 0000: PRP supervision frame +- 0001-1001: HSR ring identifier +- 1010-1011: Frames from PRP network (A/B, with RedBoxes) +- 1111: HSR supervision frame + +Follow the IEC 62439-3:2010 standard more closely by setting the right +path_id for HSRv0 supervision frames (actually, it is correctly set when +the frame is constructed, but hsr_set_path_id() overwrites it) and set a +fixed HSR ring identifier of 1. The ring identifier seems to be generally +unused and we ignore it anyways on reception, but some fixed identifier is +definitely better than using one identifier in one direction and a wrong +identifier in the other. + +This was also the behavior before commit f266a683a480 ("net/hsr: Better +frame dispatch") which introduced the alternating path_id. This was later +moved to hsr_set_path_id() in commit 451d8123f897 ("net: prp: add packet +handling support"). + +The IEC 62439-3:2010 also contains 6 unused bytes after the MacAddressA in +the HSRv0 supervision frames. Adjust a TODO comment accordingly. + +Fixes: f266a683a480 ("net/hsr: Better frame dispatch") +Fixes: 451d8123f897 ("net: prp: add packet handling support") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/ea0d5133cd593856b2fa673d6e2067bf1d4d1794.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 2 +- + net/hsr/hsr_forward.c | 22 +++++++++++++++------- + 2 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 1235abb2d79fa..492cbc78ab75a 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -337,7 +337,7 @@ static void send_hsr_supervision_frame(struct hsr_port *port, + } + + hsr_stag->tlv.HSR_TLV_type = type; +- /* TODO: Why 12 in HSRv0? */ ++ /* HSRv0 has 6 unused bytes after the MAC */ + hsr_stag->tlv.HSR_TLV_length = hsr->prot_version ? + sizeof(struct hsr_sup_payload) : 12; + +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index c67c0d35921de..339f0d2202129 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -262,15 +262,23 @@ static struct sk_buff *prp_fill_rct(struct sk_buff *skb, + return skb; + } + +-static void hsr_set_path_id(struct hsr_ethhdr *hsr_ethhdr, ++static void hsr_set_path_id(struct hsr_frame_info *frame, ++ struct hsr_ethhdr *hsr_ethhdr, + struct hsr_port *port) + { + int path_id; + +- if (port->type == HSR_PT_SLAVE_A) +- path_id = 0; +- else +- path_id = 1; ++ if (port->hsr->prot_version) { ++ if (port->type == HSR_PT_SLAVE_A) ++ path_id = 0; ++ else ++ path_id = 1; ++ } else { ++ if (frame->is_supervision) ++ path_id = 0xf; ++ else ++ path_id = 1; ++ } + + set_hsr_tag_path(&hsr_ethhdr->hsr_tag, path_id); + } +@@ -304,7 +312,7 @@ static struct sk_buff *hsr_fill_tag(struct sk_buff *skb, + else + hsr_ethhdr = (struct hsr_ethhdr *)pc; + +- hsr_set_path_id(hsr_ethhdr, port); ++ hsr_set_path_id(frame, hsr_ethhdr, port); + set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); + hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr); + hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; +@@ -330,7 +338,7 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame, + (struct hsr_ethhdr *)skb_mac_header(frame->skb_hsr); + + /* set the lane id properly */ +- hsr_set_path_id(hsr_ethhdr, port); ++ hsr_set_path_id(frame, hsr_ethhdr, port); + return skb_clone(frame->skb_hsr, GFP_ATOMIC); + } else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) { + return skb_clone(frame->skb_std, GFP_ATOMIC); +-- +2.51.0 + diff --git a/queue-6.17/mlx5-fix-default-values-in-create-cq.patch b/queue-6.17/mlx5-fix-default-values-in-create-cq.patch new file mode 100644 index 0000000000..690a94ab75 --- /dev/null +++ b/queue-6.17/mlx5-fix-default-values-in-create-cq.patch @@ -0,0 +1,303 @@ +From 7b568ee912dcecbf3b3e7695da57beb3e6f311f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:49:03 +0200 +Subject: mlx5: Fix default values in create CQ + +From: Akiva Goldberger + +[ Upstream commit e5eba42f01340f73888dfe560be2806057c25913 ] + +Currently, CQs without a completion function are assigned the +mlx5_add_cq_to_tasklet function by default. This is problematic since +only user CQs created through the mlx5_ib driver are intended to use +this function. + +Additionally, all CQs that will use doorbells instead of polling for +completions must call mlx5_cq_arm. However, the default CQ creation flow +leaves a valid value in the CQ's arm_db field, allowing FW to send +interrupts to polling-only CQs in certain corner cases. + +These two factors would allow a polling-only kernel CQ to be triggered +by an EQ interrupt and call a completion function intended only for user +CQs, causing a null pointer exception. + +Some areas in the driver have prevented this issue with one-off fixes +but did not address the root cause. + +This patch fixes the described issue by adding defaults to the create CQ +flow. It adds a default dummy completion function to protect against +null pointer exceptions, and it sets an invalid command sequence number +by default in kernel CQs to prevent the FW from sending an interrupt to +the CQ until it is armed. User CQs are responsible for their own +initialization values. + +Callers of mlx5_core_create_cq are responsible for changing the +completion function and arming the CQ per their needs. + +Fixes: cdd04f4d4d71 ("net/mlx5: Add support to create SQ and CQ for ASO") +Signed-off-by: Akiva Goldberger +Reviewed-by: Moshe Shemesh +Signed-off-by: Tariq Toukan +Acked-by: Leon Romanovsky +Link: https://patch.msgid.link/1762681743-1084694-1-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/cq.c | 11 +++++--- + drivers/net/ethernet/mellanox/mlx5/core/cq.c | 23 +++++++++++++-- + .../net/ethernet/mellanox/mlx5/core/en_main.c | 1 - + .../ethernet/mellanox/mlx5/core/fpga/conn.c | 15 +++++----- + .../mellanox/mlx5/core/steering/hws/send.c | 7 ----- + .../mellanox/mlx5/core/steering/sws/dr_send.c | 28 +++++-------------- + drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 ++-- + include/linux/mlx5/cq.h | 1 + + 8 files changed, 44 insertions(+), 48 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c +index a23b364e24ffe..651d76bca114d 100644 +--- a/drivers/infiniband/hw/mlx5/cq.c ++++ b/drivers/infiniband/hw/mlx5/cq.c +@@ -1020,15 +1020,18 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, + if (cq->create_flags & IB_UVERBS_CQ_FLAGS_IGNORE_OVERRUN) + MLX5_SET(cqc, cqc, oi, 1); + ++ if (udata) { ++ cq->mcq.comp = mlx5_add_cq_to_tasklet; ++ cq->mcq.tasklet_ctx.comp = mlx5_ib_cq_comp; ++ } else { ++ cq->mcq.comp = mlx5_ib_cq_comp; ++ } ++ + err = mlx5_core_create_cq(dev->mdev, &cq->mcq, cqb, inlen, out, sizeof(out)); + if (err) + goto err_cqb; + + mlx5_ib_dbg(dev, "cqn 0x%x\n", cq->mcq.cqn); +- if (udata) +- cq->mcq.tasklet_ctx.comp = mlx5_ib_cq_comp; +- else +- cq->mcq.comp = mlx5_ib_cq_comp; + cq->mcq.event = mlx5_ib_cq_event; + + INIT_LIST_HEAD(&cq->wc_list); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +index e9f319a9bdd6b..60f7ab1d72e78 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +@@ -66,8 +66,8 @@ void mlx5_cq_tasklet_cb(struct tasklet_struct *t) + tasklet_schedule(&ctx->task); + } + +-static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq, +- struct mlx5_eqe *eqe) ++void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq, ++ struct mlx5_eqe *eqe) + { + unsigned long flags; + struct mlx5_eq_tasklet *tasklet_ctx = cq->tasklet_ctx.priv; +@@ -95,7 +95,15 @@ static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq, + if (schedule_tasklet) + tasklet_schedule(&tasklet_ctx->task); + } ++EXPORT_SYMBOL(mlx5_add_cq_to_tasklet); + ++static void mlx5_core_cq_dummy_cb(struct mlx5_core_cq *cq, struct mlx5_eqe *eqe) ++{ ++ mlx5_core_err(cq->eq->core.dev, ++ "CQ default completion callback, CQ #%u\n", cq->cqn); ++} ++ ++#define MLX5_CQ_INIT_CMD_SN cpu_to_be32(2 << 28) + /* Callers must verify outbox status in case of err */ + int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + u32 *in, int inlen, u32 *out, int outlen) +@@ -121,10 +129,19 @@ int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + cq->arm_sn = 0; + cq->eq = eq; + cq->uid = MLX5_GET(create_cq_in, in, uid); ++ ++ /* Kernel CQs must set the arm_db address prior to calling ++ * this function, allowing for the proper value to be ++ * initialized. User CQs are responsible for their own ++ * initialization since they do not use the arm_db field. ++ */ ++ if (cq->arm_db) ++ *cq->arm_db = MLX5_CQ_INIT_CMD_SN; ++ + refcount_set(&cq->refcount, 1); + init_completion(&cq->free); + if (!cq->comp) +- cq->comp = mlx5_add_cq_to_tasklet; ++ cq->comp = mlx5_core_cq_dummy_cb; + /* assuming CQ will be deleted before the EQ */ + cq->tasklet_ctx.priv = &eq->tasklet_ctx; + INIT_LIST_HEAD(&cq->tasklet_ctx.list); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 110d654796de9..885ffb1e718a8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2218,7 +2218,6 @@ static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev, + mcq->set_ci_db = cq->wq_ctrl.db.db; + mcq->arm_db = cq->wq_ctrl.db.db + 1; + *mcq->set_ci_db = 0; +- *mcq->arm_db = 0; + mcq->vector = param->eq_ix; + mcq->comp = mlx5e_completion_event; + mcq->event = mlx5e_cq_error_event; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +index cb1319974f83f..ccef64fb40b66 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +@@ -421,6 +421,13 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size) + __be64 *pas; + u32 i; + ++ conn->cq.mcq.cqe_sz = 64; ++ conn->cq.mcq.set_ci_db = conn->cq.wq_ctrl.db.db; ++ conn->cq.mcq.arm_db = conn->cq.wq_ctrl.db.db + 1; ++ *conn->cq.mcq.set_ci_db = 0; ++ conn->cq.mcq.vector = 0; ++ conn->cq.mcq.comp = mlx5_fpga_conn_cq_complete; ++ + cq_size = roundup_pow_of_two(cq_size); + MLX5_SET(cqc, temp_cqc, log_cq_size, ilog2(cq_size)); + +@@ -468,15 +475,7 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size) + if (err) + goto err_cqwq; + +- conn->cq.mcq.cqe_sz = 64; +- conn->cq.mcq.set_ci_db = conn->cq.wq_ctrl.db.db; +- conn->cq.mcq.arm_db = conn->cq.wq_ctrl.db.db + 1; +- *conn->cq.mcq.set_ci_db = 0; +- *conn->cq.mcq.arm_db = 0; +- conn->cq.mcq.vector = 0; +- conn->cq.mcq.comp = mlx5_fpga_conn_cq_complete; + tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet); +- + mlx5_fpga_dbg(fdev, "Created CQ #0x%x\n", conn->cq.mcq.cqn); + + goto out; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c +index 24ef7d66fa8aa..7510c46e58a57 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c +@@ -873,12 +873,6 @@ static int hws_send_ring_open_sq(struct mlx5hws_context *ctx, + return err; + } + +-static void hws_cq_complete(struct mlx5_core_cq *mcq, +- struct mlx5_eqe *eqe) +-{ +- pr_err("CQ completion CQ: #%u\n", mcq->cqn); +-} +- + static int hws_send_ring_alloc_cq(struct mlx5_core_dev *mdev, + int numa_node, + struct mlx5hws_send_engine *queue, +@@ -901,7 +895,6 @@ static int hws_send_ring_alloc_cq(struct mlx5_core_dev *mdev, + mcq->cqe_sz = 64; + mcq->set_ci_db = cq->wq_ctrl.db.db; + mcq->arm_db = cq->wq_ctrl.db.db + 1; +- mcq->comp = hws_cq_complete; + + for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) { + cqe = mlx5_cqwq_get_wqe(&cq->wq, i); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c +index 077a77fde670e..d034372fa0476 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c +@@ -1049,12 +1049,6 @@ static int dr_prepare_qp_to_rts(struct mlx5dr_domain *dmn) + return 0; + } + +-static void dr_cq_complete(struct mlx5_core_cq *mcq, +- struct mlx5_eqe *eqe) +-{ +- pr_err("CQ completion CQ: #%u\n", mcq->cqn); +-} +- + static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, + struct mlx5_uars_page *uar, + size_t ncqe) +@@ -1089,6 +1083,13 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, + cqe->op_own = MLX5_CQE_INVALID << 4 | MLX5_CQE_OWNER_MASK; + } + ++ cq->mcq.cqe_sz = 64; ++ cq->mcq.set_ci_db = cq->wq_ctrl.db.db; ++ cq->mcq.arm_db = cq->wq_ctrl.db.db + 1; ++ *cq->mcq.set_ci_db = 0; ++ cq->mcq.vector = 0; ++ cq->mdev = mdev; ++ + inlen = MLX5_ST_SZ_BYTES(create_cq_in) + + sizeof(u64) * cq->wq_ctrl.buf.npages; + in = kvzalloc(inlen, GFP_KERNEL); +@@ -1112,27 +1113,12 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, + pas = (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas); + mlx5_fill_page_frag_array(&cq->wq_ctrl.buf, pas); + +- cq->mcq.comp = dr_cq_complete; +- + err = mlx5_core_create_cq(mdev, &cq->mcq, in, inlen, out, sizeof(out)); + kvfree(in); + + if (err) + goto err_cqwq; + +- cq->mcq.cqe_sz = 64; +- cq->mcq.set_ci_db = cq->wq_ctrl.db.db; +- cq->mcq.arm_db = cq->wq_ctrl.db.db + 1; +- *cq->mcq.set_ci_db = 0; +- +- /* set no-zero value, in order to avoid the HW to run db-recovery on +- * CQ that used in polling mode. +- */ +- *cq->mcq.arm_db = cpu_to_be32(2 << 28); +- +- cq->mcq.vector = 0; +- cq->mdev = mdev; +- + return cq; + + err_cqwq: +diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c +index 0ed2fc28e1cef..53cc9ef01e9f7 100644 +--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c ++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c +@@ -573,6 +573,8 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent) + vcq->mcq.set_ci_db = vcq->db.db; + vcq->mcq.arm_db = vcq->db.db + 1; + vcq->mcq.cqe_sz = 64; ++ vcq->mcq.comp = mlx5_vdpa_cq_comp; ++ vcq->cqe = num_ent; + + err = cq_frag_buf_alloc(ndev, &vcq->buf, num_ent); + if (err) +@@ -612,10 +614,6 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent) + if (err) + goto err_vec; + +- vcq->mcq.comp = mlx5_vdpa_cq_comp; +- vcq->cqe = num_ent; +- vcq->mcq.set_ci_db = vcq->db.db; +- vcq->mcq.arm_db = vcq->db.db + 1; + mlx5_cq_arm(&mvq->cq.mcq, MLX5_CQ_DB_REQ_NOT, uar_page, mvq->cq.mcq.cons_index); + kfree(in); + return 0; +diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h +index 7ef2c7c7d803d..9d47cdc727ad0 100644 +--- a/include/linux/mlx5/cq.h ++++ b/include/linux/mlx5/cq.h +@@ -183,6 +183,7 @@ static inline void mlx5_cq_put(struct mlx5_core_cq *cq) + complete(&cq->free); + } + ++void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq, struct mlx5_eqe *eqe); + int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + u32 *in, int inlen, u32 *out, int outlen); + int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, +-- +2.51.0 + diff --git a/queue-6.17/net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-o.patch b/queue-6.17/net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-o.patch new file mode 100644 index 0000000000..7b5a37284d --- /dev/null +++ b/queue-6.17/net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-o.patch @@ -0,0 +1,68 @@ +From a03cf96e1576f3f9266131e56b3316ba00a472c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:46:35 +0100 +Subject: net: dsa: tag_brcm: do not mark link local traffic as offloaded + +From: Jonas Gorski + +[ Upstream commit 762e7e174da91cf4babfe77e45bc6b67334b1503 ] + +Broadcom switches locally terminate link local traffic and do not +forward it, so we should not mark it as offloaded. + +In some situations we still want/need to flood this traffic, e.g. if STP +is disabled, or it is explicitly enabled via the group_fwd_mask. But if +the skb is marked as offloaded, the kernel will assume this was already +done in hardware, and the packets never reach other bridge ports. + +So ensure that link local traffic is never marked as offloaded, so that +the kernel can forward/flood these packets in software if needed. + +Since the local termination in not configurable, check the destination +MAC, and never mark packets as offloaded if it is a link local ether +address. + +While modern switches set the tag reason code to BRCM_EG_RC_PROT_TERM +for trapped link local traffic, they also set it for link local traffic +that is flooded (01:80:c2:00:00:10 to 01:80:c2:00:00:2f), so we cannot +use it and need to look at the destination address for them as well. + +Fixes: 964dbf186eaa ("net: dsa: tag_brcm: add support for legacy tags") +Fixes: 0e62f543bed0 ("net: dsa: Fix duplicate frames flooded by learning") +Signed-off-by: Jonas Gorski +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://patch.msgid.link/20251109134635.243951-1-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_brcm.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c +index d9c77fa553b53..eadb358179ce3 100644 +--- a/net/dsa/tag_brcm.c ++++ b/net/dsa/tag_brcm.c +@@ -176,7 +176,8 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb, + /* Remove Broadcom tag and update checksum */ + skb_pull_rcsum(skb, BRCM_TAG_LEN); + +- dsa_default_offload_fwd_mark(skb); ++ if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) ++ dsa_default_offload_fwd_mark(skb); + + return skb; + } +@@ -250,7 +251,8 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, + /* Remove Broadcom tag and update checksum */ + skb_pull_rcsum(skb, len); + +- dsa_default_offload_fwd_mark(skb); ++ if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) ++ dsa_default_offload_fwd_mark(skb); + + dsa_strip_etype_header(skb, len); + +-- +2.51.0 + diff --git a/queue-6.17/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch b/queue-6.17/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch new file mode 100644 index 0000000000..094d3d009b --- /dev/null +++ b/queue-6.17/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch @@ -0,0 +1,77 @@ +From f5062809f3f6124a7cdff538ad938a2abb91e65d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:53:04 +0530 +Subject: net: ethernet: ti: am65-cpsw-qos: fix IET verify/response timeout + +From: Aksh Garg + +[ Upstream commit 49b3916465176a5abcb29a0e464825f553d55d58 ] + +The CPSW module uses the MAC_VERIFY_CNT bit field in the +CPSW_PN_IET_VERIFY_REG_k register to set the verify/response timeout +count. This register specifies the number of clock cycles to wait before +resending a verify packet if the verification fails. + +The verify/response timeout count, as being set by the function +am65_cpsw_iet_set_verify_timeout_count() is hardcoded for 125MHz +clock frequency, which varies based on PHY mode and link speed. + +The respective clock frequencies are as follows: +- RGMII mode: + * 1000 Mbps: 125 MHz + * 100 Mbps: 25 MHz + * 10 Mbps: 2.5 MHz +- QSGMII/SGMII mode: 125 MHz (all speeds) + +Fix this by adding logic to calculate the correct timeout counts +based on the actual PHY interface mode and link speed. + +Fixes: 49a2eb9068246 ("net: ethernet: ti: am65-cpsw-qos: Add Frame Preemption MAC Merge support") +Signed-off-by: Aksh Garg +Link: https://patch.msgid.link/20251106092305.1437347-2-a-garg7@ti.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/am65-cpsw-qos.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c +index fa96db7c1a130..ad06942ce461a 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c +@@ -276,9 +276,31 @@ static int am65_cpsw_iet_set_verify_timeout_count(struct am65_cpsw_port *port) + /* The number of wireside clocks contained in the verify + * timeout counter. The default is 0x1312d0 + * (10ms at 125Mhz in 1G mode). ++ * The frequency of the clock depends on the link speed ++ * and the PHY interface. + */ +- val = 125 * HZ_PER_MHZ; /* assuming 125MHz wireside clock */ ++ switch (port->slave.phy_if) { ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ if (port->qos.link_speed == SPEED_1000) ++ val = 125 * HZ_PER_MHZ; /* 125 MHz at 1000Mbps*/ ++ else if (port->qos.link_speed == SPEED_100) ++ val = 25 * HZ_PER_MHZ; /* 25 MHz at 100Mbps*/ ++ else ++ val = (25 * HZ_PER_MHZ) / 10; /* 2.5 MHz at 10Mbps*/ ++ break; ++ ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_SGMII: ++ val = 125 * HZ_PER_MHZ; /* 125 MHz */ ++ break; + ++ default: ++ netdev_err(port->ndev, "selected mode does not supported IET\n"); ++ return -EOPNOTSUPP; ++ } + val /= MILLIHZ_PER_HZ; /* count per ms timeout */ + val *= verify_time_ms; /* count for timeout ms */ + +-- +2.51.0 + diff --git a/queue-6.17/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch b/queue-6.17/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch new file mode 100644 index 0000000000..b07fbd4450 --- /dev/null +++ b/queue-6.17/net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch @@ -0,0 +1,87 @@ +From ad7551026fbedcd2df863bf092018e07e91a66f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:53:05 +0530 +Subject: net: ethernet: ti: am65-cpsw-qos: fix IET verify retry mechanism + +From: Aksh Garg + +[ Upstream commit d4b00d132d7cb70a74bc039c91c1d6120943c71b ] + +The am65_cpsw_iet_verify_wait() function attempts verification 20 times, +toggling the AM65_CPSW_PN_IET_MAC_LINKFAIL bit in each iteration. When +the LINKFAIL bit transitions from 1 to 0, the MAC merge layer initiates +the verification process and waits for the timeout configured in +MAC_VERIFY_CNT before automatically retransmitting. The MAC_VERIFY_CNT +register is configured according to the user-defined verify/response +timeout in am65_cpsw_iet_set_verify_timeout_count(). As per IEEE 802.3 +Clause 99, the hardware performs this automatic retry up to 3 times. + +Current implementation toggles LINKFAIL after the user-configured +verify/response timeout in each iteration, forcing the hardware to +restart verification instead of respecting the MAC_VERIFY_CNT timeout. +This bypasses the hardware's automatic retry mechanism. + +Fix this by moving the LINKFAIL bit toggle outside the retry loop and +reducing the retry count from 20 to 3. The software now only monitors +the status register while the hardware autonomously handles the 3 +verification attempts at proper MAC_VERIFY_CNT intervals. + +Fixes: 49a2eb9068246 ("net: ethernet: ti: am65-cpsw-qos: Add Frame Preemption MAC Merge support") +Signed-off-by: Aksh Garg +Link: https://patch.msgid.link/20251106092305.1437347-3-a-garg7@ti.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/am65-cpsw-qos.c | 27 +++++++++++++------------ + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c +index ad06942ce461a..66e8b224827b6 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c +@@ -317,20 +317,21 @@ static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port) + u32 ctrl, status; + int try; + +- try = 20; +- do { +- /* Reset the verify state machine by writing 1 +- * to LINKFAIL +- */ +- ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); +- ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL; +- writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ try = 3; + +- /* Clear MAC_LINKFAIL bit to start Verify. */ +- ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); +- ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; +- writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ /* Reset the verify state machine by writing 1 ++ * to LINKFAIL ++ */ ++ ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); + ++ /* Clear MAC_LINKFAIL bit to start Verify. */ ++ ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ++ do { + msleep(port->qos.iet.verify_time_ms); + + status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); +@@ -352,7 +353,7 @@ static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port) + netdev_dbg(port->ndev, "MAC Merge verify error\n"); + return -ENODEV; + } +- } while (try-- > 0); ++ } while (--try > 0); + + netdev_dbg(port->ndev, "MAC Merge verify timeout\n"); + return -ETIMEDOUT; +-- +2.51.0 + diff --git a/queue-6.17/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-6.17/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..c44447ea9c --- /dev/null +++ b/queue-6.17/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From f783c9a26326a1f4cf357da4275b2412a2f67e3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index adf1f2bbcbb16..c404ca590b73c 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1820,6 +1820,8 @@ fec_enet_rx_queue(struct net_device *ndev, u16 queue_id, int budget) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + page = rxq->rx_skb_info[index].page; +-- +2.51.0 + diff --git a/queue-6.17/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch b/queue-6.17/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch new file mode 100644 index 0000000000..f42e4d12cb --- /dev/null +++ b/queue-6.17/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch @@ -0,0 +1,42 @@ +From 6ecac7f08b743aa1d52b6e7114cd8038c31b0e30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:45:11 +0000 +Subject: net/handshake: Fix memory leak in tls_handshake_accept() + +From: Zilin Guan + +[ Upstream commit 3072f00bba764082fa41b3c3a2a7b013335353d2 ] + +In tls_handshake_accept(), a netlink message is allocated using +genlmsg_new(). In the error handling path, genlmsg_cancel() is called +to cancel the message construction, but the message itself is not freed. +This leads to a memory leak. + +Fix this by calling nlmsg_free() in the error path after genlmsg_cancel() +to release the allocated memory. + +Fixes: 2fd5532044a89 ("net/handshake: Add a kernel API for requesting a TLSv1.3 handshake") +Signed-off-by: Zilin Guan +Reviewed-by: Chuck Lever +Link: https://patch.msgid.link/20251106144511.3859535-1-zilin@seu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/handshake/tlshd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c +index 081093dfd5533..8f9532a15f43f 100644 +--- a/net/handshake/tlshd.c ++++ b/net/handshake/tlshd.c +@@ -259,6 +259,7 @@ static int tls_handshake_accept(struct handshake_req *req, + + out_cancel: + genlmsg_cancel(msg, hdr); ++ nlmsg_free(msg); + out: + return ret; + } +-- +2.51.0 + diff --git a/queue-6.17/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-6.17/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..c3c45a98ed --- /dev/null +++ b/queue-6.17/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From 0ec2298f91972a8b50399fa676efa3826365bd82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index cad6ed3aa10b6..4354241137d50 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -73,8 +73,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5-fix-typo-of-mlx5_eq_doorbel_offset.patch b/queue-6.17/net-mlx5-fix-typo-of-mlx5_eq_doorbel_offset.patch new file mode 100644 index 0000000000..388ef22f2c --- /dev/null +++ b/queue-6.17/net-mlx5-fix-typo-of-mlx5_eq_doorbel_offset.patch @@ -0,0 +1,49 @@ +From 6ac2d76198123549667d914304fcb743a2ebb22c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Sep 2025 17:11:35 +0300 +Subject: net/mlx5: Fix typo of MLX5_EQ_DOORBEL_OFFSET + +From: Cosmin Ratiu + +[ Upstream commit 917449e7c3cdc7a0dfe429de997e39098d9cdd20 ] + +Also convert it to a simple define. + +Signed-off-by: Cosmin Ratiu +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +Stable-dep-of: e5eba42f0134 ("mlx5: Fix default values in create CQ") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/eq.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c +index 1ab77159409d6..f3c714ebd9cb4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c +@@ -32,9 +32,7 @@ enum { + MLX5_EQ_STATE_ALWAYS_ARMED = 0xb, + }; + +-enum { +- MLX5_EQ_DOORBEL_OFFSET = 0x40, +-}; ++#define MLX5_EQ_DOORBELL_OFFSET 0x40 + + /* budget must be smaller than MLX5_NUM_SPARE_EQE to guarantee that we update + * the ci before we polled all the entries in the EQ. MLX5_NUM_SPARE_EQE is +@@ -322,7 +320,7 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + eq->eqn = MLX5_GET(create_eq_out, out, eq_number); + eq->irqn = pci_irq_vector(dev->pdev, vecidx); + eq->dev = dev; +- eq->doorbell = priv->uar->map + MLX5_EQ_DOORBEL_OFFSET; ++ eq->doorbell = priv->uar->map + MLX5_EQ_DOORBELL_OFFSET; + + err = mlx5_debug_eq_add(dev, eq); + if (err) +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5-store-the-global-doorbell-in-mlx5_priv.patch b/queue-6.17/net-mlx5-store-the-global-doorbell-in-mlx5_priv.patch new file mode 100644 index 0000000000..1b1b49939e --- /dev/null +++ b/queue-6.17/net-mlx5-store-the-global-doorbell-in-mlx5_priv.patch @@ -0,0 +1,381 @@ +From e2ac326c10755ccf9ca4d8a6e890a653b19d1d16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Sep 2025 17:11:38 +0300 +Subject: net/mlx5: Store the global doorbell in mlx5_priv + +From: Cosmin Ratiu + +[ Upstream commit aa4595d0ada65d5d44fa924a42a87c175d9d88e3 ] + +The global doorbell is used for more than just Ethernet resources, so +move it out of mlx5e_hw_objs into a common place (mlx5_priv), to avoid +non-Ethernet modules (e.g. HWS, ASO) depending on Ethernet structs. + +Use this opportunity to consolidate it with the 'uar' pointer already +there, which was used as an RX doorbell. Underneath the 'uar' pointer is +identical to 'bfreg->up', so store a single resource and use that +instead. + +For CQ doorbells, care is taken to always use bfreg->up->index instead +of bfreg->index, which may refer to a subsequent UAR page from the same +ALLOC_UAR batch on some NICs. + +This paves the way for cleanly supporting multiple doorbells in the +Ethernet driver. + +Signed-off-by: Cosmin Ratiu +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +Stable-dep-of: e5eba42f0134 ("mlx5: Fix default values in create CQ") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/cq.c | 4 ++-- + drivers/net/ethernet/mellanox/mlx5/core/cq.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/en/params.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/en_common.c | 11 +---------- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 10 +++++----- + drivers/net/ethernet/mellanox/mlx5/core/eq.c | 4 ++-- + drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c | 8 ++++---- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 11 +++++------ + .../ethernet/mellanox/mlx5/core/steering/hws/send.c | 8 ++++---- + drivers/net/ethernet/mellanox/mlx5/core/wc.c | 4 ++-- + include/linux/mlx5/driver.h | 3 +-- + 12 files changed, 29 insertions(+), 40 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c +index 9c8003a783343..a23b364e24ffe 100644 +--- a/drivers/infiniband/hw/mlx5/cq.c ++++ b/drivers/infiniband/hw/mlx5/cq.c +@@ -648,7 +648,7 @@ int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) + { + struct mlx5_core_dev *mdev = to_mdev(ibcq->device)->mdev; + struct mlx5_ib_cq *cq = to_mcq(ibcq); +- void __iomem *uar_page = mdev->priv.uar->map; ++ void __iomem *uar_page = mdev->priv.bfreg.up->map; + unsigned long irq_flags; + int ret = 0; + +@@ -923,7 +923,7 @@ static int create_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq, + cq->buf.frag_buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + +- *index = dev->mdev->priv.uar->index; ++ *index = dev->mdev->priv.bfreg.up->index; + + return 0; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +index 1fd403713bafc..35039a95dcfd4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +@@ -145,7 +145,7 @@ int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + mlx5_core_dbg(dev, "failed adding CP 0x%x to debug file system\n", + cq->cqn); + +- cq->uar = dev->priv.uar; ++ cq->uar = dev->priv.bfreg.up; + cq->irqn = eq->core.irqn; + + return 0; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +index 06e1a04e693f3..c24cb2ab91cb1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +@@ -810,7 +810,7 @@ static void mlx5e_build_common_cq_param(struct mlx5_core_dev *mdev, + { + void *cqc = param->cqc; + +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); + if (MLX5_CAP_GEN(mdev, cqe_128_always) && cache_line_size() >= 128) + MLX5_SET(cqc, cqc, cqe_sz, CQE_STRIDE_128_PAD); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +index 391b4e9c9dc49..7c1d9a9ea4645 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +@@ -334,7 +334,7 @@ static int mlx5e_ptp_alloc_txqsq(struct mlx5e_ptp *c, int txq_ix, + sq->mdev = mdev; + sq->ch_ix = MLX5E_PTP_CHANNEL_IX; + sq->txq_ix = txq_ix; +- sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; ++ sq->uar_map = mdev->priv.bfreg.map; + sq->min_inline_mode = params->tx_min_inline_mode; + sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); + sq->stats = &c->priv->ptp_stats.sq[tc]; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +index 6ed3a32b7e226..e9e36358c39d1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +@@ -163,17 +163,11 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises) + goto err_dealloc_transport_domain; + } + +- err = mlx5_alloc_bfreg(mdev, &res->bfreg, false, false); +- if (err) { +- mlx5_core_err(mdev, "alloc bfreg failed, %d\n", err); +- goto err_destroy_mkey; +- } +- + if (create_tises) { + err = mlx5e_create_tises(mdev, res->tisn); + if (err) { + mlx5_core_err(mdev, "alloc tises failed, %d\n", err); +- goto err_destroy_bfreg; ++ goto err_destroy_mkey; + } + res->tisn_valid = true; + } +@@ -190,8 +184,6 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises) + + return 0; + +-err_destroy_bfreg: +- mlx5_free_bfreg(mdev, &res->bfreg); + err_destroy_mkey: + mlx5_core_destroy_mkey(mdev, res->mkey); + err_dealloc_transport_domain: +@@ -209,7 +201,6 @@ void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev) + mdev->mlx5e_res.dek_priv = NULL; + if (res->tisn_valid) + mlx5e_destroy_tises(mdev, res->tisn); +- mlx5_free_bfreg(mdev, &res->bfreg); + mlx5_core_destroy_mkey(mdev, res->mkey); + mlx5_core_dealloc_transport_domain(mdev, res->td.tdn); + mlx5_core_dealloc_pd(mdev, res->pdn); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 2c82c5100af3c..1a90fd1d44edb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -1551,7 +1551,7 @@ static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c, + sq->pdev = c->pdev; + sq->mkey_be = c->mkey_be; + sq->channel = c; +- sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; ++ sq->uar_map = mdev->priv.bfreg.map; + sq->min_inline_mode = params->tx_min_inline_mode; + sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu) - ETH_FCS_LEN; + sq->xsk_pool = xsk_pool; +@@ -1636,7 +1636,7 @@ static int mlx5e_alloc_icosq(struct mlx5e_channel *c, + int err; + + sq->channel = c; +- sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; ++ sq->uar_map = mdev->priv.bfreg.map; + sq->reserved_room = param->stop_room; + + param->wq.db_numa_node = cpu_to_node(c->cpu); +@@ -1721,7 +1721,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, + sq->priv = c->priv; + sq->ch_ix = c->ix; + sq->txq_ix = txq_ix; +- sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; ++ sq->uar_map = mdev->priv.bfreg.map; + sq->min_inline_mode = params->tx_min_inline_mode; + sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); + sq->max_sq_mpw_wqebbs = mlx5e_get_max_sq_aligned_wqebbs(mdev); +@@ -1797,7 +1797,7 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev, + MLX5_SET(sqc, sqc, flush_in_error_en, 1); + + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); +- MLX5_SET(wq, wq, uar_page, mdev->mlx5e_res.hw_objs.bfreg.index); ++ MLX5_SET(wq, wq, uar_page, mdev->priv.bfreg.index); + MLX5_SET(wq, wq, log_wq_pg_sz, csp->wq_ctrl->buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(wq, wq, dbr_addr, csp->wq_ctrl->db.dma); +@@ -2292,7 +2292,7 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param) + MLX5_SET(cqc, cqc, cq_period_mode, mlx5e_cq_period_mode(param->cq_period_mode)); + + MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn); +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); + MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c +index f3c714ebd9cb4..25499da177bc4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c +@@ -307,7 +307,7 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + + eqc = MLX5_ADDR_OF(create_eq_in, in, eq_context_entry); + MLX5_SET(eqc, eqc, log_eq_size, eq->fbc.log_sz); +- MLX5_SET(eqc, eqc, uar_page, priv->uar->index); ++ MLX5_SET(eqc, eqc, uar_page, priv->bfreg.up->index); + MLX5_SET(eqc, eqc, intr, vecidx); + MLX5_SET(eqc, eqc, log_page_size, + eq->frag_buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT); +@@ -320,7 +320,7 @@ create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + eq->eqn = MLX5_GET(create_eq_out, out, eq_number); + eq->irqn = pci_irq_vector(dev->pdev, vecidx); + eq->dev = dev; +- eq->doorbell = priv->uar->map + MLX5_EQ_DOORBELL_OFFSET; ++ eq->doorbell = priv->bfreg.up->map + MLX5_EQ_DOORBELL_OFFSET; + + err = mlx5_debug_eq_add(dev, eq); + if (err) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c +index 58bd749b5e4de..129725159a935 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/aso.c +@@ -100,7 +100,7 @@ static int create_aso_cq(struct mlx5_aso_cq *cq, void *cqc_data) + + MLX5_SET(cqc, cqc, cq_period_mode, MLX5_CQ_PERIOD_MODE_START_FROM_EQE); + MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn); +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); + MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma); +@@ -129,7 +129,7 @@ static int mlx5_aso_create_cq(struct mlx5_core_dev *mdev, int numa_node, + return -ENOMEM; + + MLX5_SET(cqc, cqc_data, log_cq_size, 1); +- MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.bfreg.up->index); + if (MLX5_CAP_GEN(mdev, cqe_128_always) && cache_line_size() >= 128) + MLX5_SET(cqc, cqc_data, cqe_sz, CQE_STRIDE_128_PAD); + +@@ -163,7 +163,7 @@ static int mlx5_aso_alloc_sq(struct mlx5_core_dev *mdev, int numa_node, + struct mlx5_wq_param param; + int err; + +- sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; ++ sq->uar_map = mdev->priv.bfreg.map; + + param.db_numa_node = numa_node; + param.buf_numa_node = numa_node; +@@ -203,7 +203,7 @@ static int create_aso_sq(struct mlx5_core_dev *mdev, int pdn, + MLX5_SET(sqc, sqc, ts_format, ts_format); + + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); +- MLX5_SET(wq, wq, uar_page, mdev->mlx5e_res.hw_objs.bfreg.index); ++ MLX5_SET(wq, wq, uar_page, mdev->priv.bfreg.index); + MLX5_SET(wq, wq, log_wq_pg_sz, sq->wq_ctrl.buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(wq, wq, dbr_addr, sq->wq_ctrl.db.dma); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index 8517d4e5d5efc..3df7401f2256c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1340,10 +1340,9 @@ static int mlx5_load(struct mlx5_core_dev *dev) + { + int err; + +- dev->priv.uar = mlx5_get_uars_page(dev); +- if (IS_ERR(dev->priv.uar)) { +- mlx5_core_err(dev, "Failed allocating uar, aborting\n"); +- err = PTR_ERR(dev->priv.uar); ++ err = mlx5_alloc_bfreg(dev, &dev->priv.bfreg, false, false); ++ if (err) { ++ mlx5_core_err(dev, "Failed allocating bfreg, %d\n", err); + return err; + } + +@@ -1454,7 +1453,7 @@ static int mlx5_load(struct mlx5_core_dev *dev) + err_irq_table: + mlx5_pagealloc_stop(dev); + mlx5_events_stop(dev); +- mlx5_put_uars_page(dev, dev->priv.uar); ++ mlx5_free_bfreg(dev, &dev->priv.bfreg); + return err; + } + +@@ -1479,7 +1478,7 @@ static void mlx5_unload(struct mlx5_core_dev *dev) + mlx5_irq_table_destroy(dev); + mlx5_pagealloc_stop(dev); + mlx5_events_stop(dev); +- mlx5_put_uars_page(dev, dev->priv.uar); ++ mlx5_free_bfreg(dev, &dev->priv.bfreg); + } + + int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev) +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c +index b0595c9b09e42..24ef7d66fa8aa 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c +@@ -690,7 +690,7 @@ static int hws_send_ring_alloc_sq(struct mlx5_core_dev *mdev, + size_t buf_sz; + int err; + +- sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; ++ sq->uar_map = mdev->priv.bfreg.map; + sq->mdev = mdev; + + param.db_numa_node = numa_node; +@@ -764,7 +764,7 @@ static int hws_send_ring_create_sq(struct mlx5_core_dev *mdev, u32 pdn, + MLX5_SET(sqc, sqc, ts_format, ts_format); + + MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC); +- MLX5_SET(wq, wq, uar_page, mdev->mlx5e_res.hw_objs.bfreg.index); ++ MLX5_SET(wq, wq, uar_page, mdev->priv.bfreg.index); + MLX5_SET(wq, wq, log_wq_pg_sz, sq->wq_ctrl.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(wq, wq, dbr_addr, sq->wq_ctrl.db.dma); + +@@ -940,7 +940,7 @@ static int hws_send_ring_create_cq(struct mlx5_core_dev *mdev, + (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas)); + + MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn); +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); + MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma); + +@@ -963,7 +963,7 @@ static int hws_send_ring_open_cq(struct mlx5_core_dev *mdev, + if (!cqc_data) + return -ENOMEM; + +- MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.bfreg.up->index); + MLX5_SET(cqc, cqc_data, log_cq_size, ilog2(queue->num_entries)); + + err = hws_send_ring_alloc_cq(mdev, numa_node, queue, cqc_data, cq); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/wc.c b/drivers/net/ethernet/mellanox/mlx5/core/wc.c +index 2f0316616fa40..0d3591ff22733 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/wc.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/wc.c +@@ -94,7 +94,7 @@ static int create_wc_cq(struct mlx5_wc_cq *cq, void *cqc_data) + + MLX5_SET(cqc, cqc, cq_period_mode, MLX5_CQ_PERIOD_MODE_START_FROM_EQE); + MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn); +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); + MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma); +@@ -116,7 +116,7 @@ static int mlx5_wc_create_cq(struct mlx5_core_dev *mdev, struct mlx5_wc_cq *cq) + return -ENOMEM; + + MLX5_SET(cqc, cqc, log_cq_size, TEST_WC_LOG_CQ_SZ); +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); ++ MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); + if (MLX5_CAP_GEN(mdev, cqe_128_always) && cache_line_size() >= 128) + MLX5_SET(cqc, cqc, cqe_sz, CQE_STRIDE_128_PAD); + +diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h +index 10fe492e1fedc..c185f082748ae 100644 +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -611,7 +611,7 @@ struct mlx5_priv { + struct mlx5_ft_pool *ft_pool; + + struct mlx5_bfreg_data bfregs; +- struct mlx5_uars_page *uar; ++ struct mlx5_sq_bfreg bfreg; + #ifdef CONFIG_MLX5_SF + struct mlx5_vhca_state_notifier *vhca_state_notifier; + struct mlx5_sf_dev_table *sf_dev_table; +@@ -657,7 +657,6 @@ struct mlx5e_resources { + u32 pdn; + struct mlx5_td td; + u32 mkey; +- struct mlx5_sq_bfreg bfreg; + #define MLX5_MAX_NUM_TC 8 + u32 tisn[MLX5_MAX_PORTS][MLX5_MAX_NUM_TC]; + bool tisn_valid; +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-6.17/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..4c26741ac3 --- /dev/null +++ b/queue-6.17/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From 71dd34345a1092d61ab76e70d902beb23368feb4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index d166c0d5189e1..3456144710528 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -595,18 +595,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5e-fix-missing-error-assignment-in-mlx5e_xfrm.patch b/queue-6.17/net-mlx5e-fix-missing-error-assignment-in-mlx5e_xfrm.patch new file mode 100644 index 0000000000..a0c1728887 --- /dev/null +++ b/queue-6.17/net-mlx5e-fix-missing-error-assignment-in-mlx5e_xfrm.patch @@ -0,0 +1,44 @@ +From ae8f261fdc9b3b48813c8781da042a5219b6b835 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:49 +0200 +Subject: net/mlx5e: Fix missing error assignment in mlx5e_xfrm_add_state() + +From: Carolina Jubran + +[ Upstream commit 0bcd5b3b50cc1fcbf775479322cc37c15d35a489 ] + +Assign the return value of mlx5_eswitch_block_mode() to 'err' before +checking it to avoid returning an uninitialized error code. + +Fixes: 22239eb258bc ("net/mlx5e: Prevent tunnel reformat when tunnel mode not allowed") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202510271649.uwsIxD6O-lkp@intel.com/ +Closes: http://lore.kernel.org/linux-rdma/aPIEK4rLB586FdDt@stanley.mountain/ +Signed-off-by: Carolina Jubran +Reviewed-by: Jianbo Liu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +index 0a4fb8c922684..35d9530037a65 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +@@ -804,7 +804,8 @@ static int mlx5e_xfrm_add_state(struct net_device *dev, + goto err_xfrm; + } + +- if (mlx5_eswitch_block_mode(priv->mdev)) ++ err = mlx5_eswitch_block_mode(priv->mdev); ++ if (err) + goto unblock_ipsec; + + if (x->props.mode == XFRM_MODE_TUNNEL && +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5e-fix-potentially-misleading-debug-message.patch b/queue-6.17/net-mlx5e-fix-potentially-misleading-debug-message.patch new file mode 100644 index 0000000000..829d9cfcba --- /dev/null +++ b/queue-6.17/net-mlx5e-fix-potentially-misleading-debug-message.patch @@ -0,0 +1,62 @@ +From 054dfd26f74f6b360ab83cf95c173ed219784f9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:53 +0200 +Subject: net/mlx5e: Fix potentially misleading debug message + +From: Gal Pressman + +[ Upstream commit 9fcc2b6c10523f7e75db6387946c86fcf19dc97e ] + +Change the debug message to print the correct units instead of always +assuming Gbps, as the value can be in either 100 Mbps or 1 Gbps units. + +Fixes: 5da8bc3effb6 ("net/mlx5e: DCBNL, Add debug messages log") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index d88a48210fdcb..9b93da4d52f64 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -598,6 +598,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + __u64 upper_limit_mbps; + __u64 upper_limit_gbps; + int i; ++ struct { ++ int scale; ++ const char *units_str; ++ } units[] = { ++ [MLX5_100_MBPS_UNIT] = { ++ .scale = 100, ++ .units_str = "Mbps", ++ }, ++ [MLX5_GBPS_UNIT] = { ++ .scale = 1, ++ .units_str = "Gbps", ++ }, ++ }; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); +@@ -628,8 +641,9 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", +- __func__, i, max_bw_value[i]); ++ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i, ++ max_bw_value[i] * units[max_bw_unit[i]].scale, ++ units[max_bw_unit[i]].units_str); + } + + return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit); +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-6.17/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..29a1e46018 --- /dev/null +++ b/queue-6.17/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From 65ddef48acba089281868d75e058497234ee1311 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 3456144710528..d88a48210fdcb 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -596,11 +596,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -612,10 +614,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-6.17/net-mlx5e-prepare-for-using-different-cq-doorbells.patch b/queue-6.17/net-mlx5e-prepare-for-using-different-cq-doorbells.patch new file mode 100644 index 0000000000..2b0cebd5ae --- /dev/null +++ b/queue-6.17/net-mlx5e-prepare-for-using-different-cq-doorbells.patch @@ -0,0 +1,173 @@ +From 3106aa072478c75163333b14088e5c27c15f0fec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Sep 2025 17:11:40 +0300 +Subject: net/mlx5e: Prepare for using different CQ doorbells + +From: Cosmin Ratiu + +[ Upstream commit a315b723e87ba4e4573e1e5c759d512f38bdc0b3 ] + +Completion queues (CQs) in mlx5 use the same global doorbell, which may +become contended when accessed concurrently from many cores. + +This patch prepares the CQ management code for supporting different +doorbells per CQ. This will be used in downstream patches to allow +separate doorbells to be used by channels CQs. + +The main change is moving the 'uar' pointer from struct mlx5_core_cq to +struct mlx5e_cq, as the uar page to be used is better off stored +directly there. Other users of mlx5_core_cq also store the UAR to be +used separately and therefore the pointer being removed is dead weight +for them. As evidence, in this patch there are two users which set the +mcq.uar pointer but didn't use it, Software Steering and old Innova CQ +creation code. Instead, they rang the doorbell directly from another +pointer. + +The 'uar' pointer added to struct mlx5e_cq remains in a hot cacheline +(as before), because it may get accessed for each packet. + +Signed-off-by: Cosmin Ratiu +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +Stable-dep-of: e5eba42f0134 ("mlx5: Fix default values in create CQ") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/cq.c | 1 - + drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + + drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h | 5 +---- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 10 +++++++--- + drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c | 1 - + .../ethernet/mellanox/mlx5/core/steering/sws/dr_send.c | 1 - + include/linux/mlx5/cq.h | 1 - + 7 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +index 35039a95dcfd4..e9f319a9bdd6b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c +@@ -145,7 +145,6 @@ int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + mlx5_core_dbg(dev, "failed adding CP 0x%x to debug file system\n", + cq->cqn); + +- cq->uar = dev->priv.bfreg.up; + cq->irqn = eq->core.irqn; + + return 0; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h +index ff4a68648e604..4fc102d18354f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h +@@ -344,6 +344,7 @@ struct mlx5e_cq { + /* data path - accessed per napi poll */ + u16 event_ctr; + struct napi_struct *napi; ++ struct mlx5_uars_page *uar; + struct mlx5_core_cq mcq; + struct mlx5e_ch_stats *ch_stats; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +index 5dc04bbfc71bb..6760bb0336df9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +@@ -309,10 +309,7 @@ mlx5e_notify_hw(struct mlx5_wq_cyc *wq, u16 pc, void __iomem *uar_map, + + static inline void mlx5e_cq_arm(struct mlx5e_cq *cq) + { +- struct mlx5_core_cq *mcq; +- +- mcq = &cq->mcq; +- mlx5_cq_arm(mcq, MLX5_CQ_DB_REQ_NOT, mcq->uar->map, cq->wq.cc); ++ mlx5_cq_arm(&cq->mcq, MLX5_CQ_DB_REQ_NOT, cq->uar->map, cq->wq.cc); + } + + static inline struct mlx5e_sq_dma * +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 1a90fd1d44edb..110d654796de9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -2201,6 +2201,7 @@ static void mlx5e_close_xdpredirect_sq(struct mlx5e_xdpsq *xdpsq) + static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev, + struct net_device *netdev, + struct workqueue_struct *workqueue, ++ struct mlx5_uars_page *uar, + struct mlx5e_cq_param *param, + struct mlx5e_cq *cq) + { +@@ -2232,6 +2233,7 @@ static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev, + cq->mdev = mdev; + cq->netdev = netdev; + cq->workqueue = workqueue; ++ cq->uar = uar; + + return 0; + } +@@ -2247,7 +2249,8 @@ static int mlx5e_alloc_cq(struct mlx5_core_dev *mdev, + param->wq.db_numa_node = ccp->node; + param->eq_ix = ccp->ix; + +- err = mlx5e_alloc_cq_common(mdev, ccp->netdev, ccp->wq, param, cq); ++ err = mlx5e_alloc_cq_common(mdev, ccp->netdev, ccp->wq, ++ mdev->priv.bfreg.up, param, cq); + + cq->napi = ccp->napi; + cq->ch_stats = ccp->ch_stats; +@@ -2292,7 +2295,7 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param) + MLX5_SET(cqc, cqc, cq_period_mode, mlx5e_cq_period_mode(param->cq_period_mode)); + + MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn); +- MLX5_SET(cqc, cqc, uar_page, mdev->priv.bfreg.up->index); ++ MLX5_SET(cqc, cqc, uar_page, cq->uar->index); + MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - + MLX5_ADAPTER_PAGE_SHIFT); + MLX5_SET64(cqc, cqc, dbr_addr, cq->wq_ctrl.db.dma); +@@ -3584,7 +3587,8 @@ static int mlx5e_alloc_drop_cq(struct mlx5e_priv *priv, + param->wq.buf_numa_node = dev_to_node(mlx5_core_dma_dev(mdev)); + param->wq.db_numa_node = dev_to_node(mlx5_core_dma_dev(mdev)); + +- return mlx5e_alloc_cq_common(priv->mdev, priv->netdev, priv->wq, param, cq); ++ return mlx5e_alloc_cq_common(priv->mdev, priv->netdev, priv->wq, ++ mdev->priv.bfreg.up, param, cq); + } + + int mlx5e_open_drop_rq(struct mlx5e_priv *priv, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +index c4de6bf8d1b65..cb1319974f83f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c +@@ -475,7 +475,6 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size) + *conn->cq.mcq.arm_db = 0; + conn->cq.mcq.vector = 0; + conn->cq.mcq.comp = mlx5_fpga_conn_cq_complete; +- conn->cq.mcq.uar = fdev->conn_res.uar; + tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet); + + mlx5_fpga_dbg(fdev, "Created CQ #0x%x\n", conn->cq.mcq.cqn); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c +index 4fd4e8483382c..077a77fde670e 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c +@@ -1131,7 +1131,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev, + *cq->mcq.arm_db = cpu_to_be32(2 << 28); + + cq->mcq.vector = 0; +- cq->mcq.uar = uar; + cq->mdev = mdev; + + return cq; +diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h +index 991526039ccbd..7ef2c7c7d803d 100644 +--- a/include/linux/mlx5/cq.h ++++ b/include/linux/mlx5/cq.h +@@ -41,7 +41,6 @@ struct mlx5_core_cq { + int cqe_sz; + __be32 *set_ci_db; + __be32 *arm_db; +- struct mlx5_uars_page *uar; + refcount_t refcount; + struct completion free; + unsigned vector; +-- +2.51.0 + diff --git a/queue-6.17/net-phy-micrel-introduce-lanphy_modify_page_reg.patch b/queue-6.17/net-phy-micrel-introduce-lanphy_modify_page_reg.patch new file mode 100644 index 0000000000..0a6af3dce3 --- /dev/null +++ b/queue-6.17/net-phy-micrel-introduce-lanphy_modify_page_reg.patch @@ -0,0 +1,414 @@ +From ff1c48b677374ea49d1ff97e1ad37cabf6c33f33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Aug 2025 09:51:19 +0200 +Subject: net: phy: micrel: Introduce lanphy_modify_page_reg + +From: Horatiu Vultur + +[ Upstream commit a0de636ed7a264a329c6a9c7d50727af02138536 ] + +As the name suggests this function modifies the register in an +extended page. It has the same parameters as phy_modify_mmd. +This function was introduce because there are many places in the +code where the registers was read then the value was modified and +written back. So replace all this code with this function to make +it clear. + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Horatiu Vultur +Link: https://patch.msgid.link/20250818075121.1298170-3-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 231 ++++++++++++++++++++------------------- + 1 file changed, 116 insertions(+), 115 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 99f8374fd32a7..0efc5adbf789d 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -2840,6 +2840,27 @@ static int lanphy_write_page_reg(struct phy_device *phydev, int page, u16 addr, + return val; + } + ++static int lanphy_modify_page_reg(struct phy_device *phydev, int page, u16 addr, ++ u16 mask, u16 set) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ __phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, page); ++ __phy_write(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, addr); ++ __phy_write(phydev, LAN_EXT_PAGE_ACCESS_CONTROL, ++ (page | LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC)); ++ ret = __phy_modify_changed(phydev, LAN_EXT_PAGE_ACCESS_ADDRESS_DATA, ++ mask, set); ++ phy_unlock_mdio_bus(phydev); ++ ++ if (ret < 0) ++ phydev_err(phydev, "__phy_modify_changed() failed: %pe\n", ++ ERR_PTR(ret)); ++ ++ return ret; ++} ++ + static int lan8814_config_ts_intr(struct phy_device *phydev, bool enable) + { + u16 val = 0; +@@ -2928,7 +2949,6 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, + struct lan8814_ptp_rx_ts *rx_ts, *tmp; + int txcfg = 0, rxcfg = 0; + int pkt_ts_enable; +- int tx_mod; + + ptp_priv->hwts_tx_type = config->tx_type; + ptp_priv->rx_filter = config->rx_filter; +@@ -2975,13 +2995,14 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, + lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_TIMESTAMP_EN, pkt_ts_enable); + lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_TIMESTAMP_EN, pkt_ts_enable); + +- tx_mod = lanphy_read_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD); + if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, +- tx_mod | PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); ++ lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, ++ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); + } else if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ON) { +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, +- tx_mod & ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); ++ lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, ++ 0); + } + + if (config->rx_filter != HWTSTAMP_FILTER_NONE) +@@ -3384,73 +3405,66 @@ static void lan8814_ptp_set_reload(struct phy_device *phydev, int event, + static void lan8814_ptp_enable_event(struct phy_device *phydev, int event, + int pulse_width) + { +- u16 val; +- +- val = lanphy_read_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG); +- /* Set the pulse width of the event */ +- val &= ~(LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_MASK(event)); +- /* Make sure that the target clock will be incremented each time when ++ /* Set the pulse width of the event, ++ * Make sure that the target clock will be incremented each time when + * local time reaches or pass it ++ * Set the polarity high + */ +- val |= LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width); +- val &= ~(LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event)); +- /* Set the polarity high */ +- val |= LAN8814_PTP_GENERAL_CONFIG_POLARITY_X(event); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_MASK(event) | ++ LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width) | ++ LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event) | ++ LAN8814_PTP_GENERAL_CONFIG_POLARITY_X(event), ++ LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width) | ++ LAN8814_PTP_GENERAL_CONFIG_POLARITY_X(event)); + } + + static void lan8814_ptp_disable_event(struct phy_device *phydev, int event) + { +- u16 val; +- + /* Set target to too far in the future, effectively disabling it */ + lan8814_ptp_set_target(phydev, event, 0xFFFFFFFF, 0); + + /* And then reload once it recheas the target */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG); +- val |= LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event), ++ LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event)); + } + + static void lan8814_ptp_perout_off(struct phy_device *phydev, int pin) + { +- u16 val; +- + /* Disable gpio alternate function, + * 1: select as gpio, + * 0: select alt func + */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); +- val |= LAN8814_GPIO_EN_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ LAN8814_GPIO_EN_BIT(pin), ++ LAN8814_GPIO_EN_BIT(pin)); + +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- val &= ~LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ 0); + +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin)); +- val &= ~LAN8814_GPIO_BUF_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ LAN8814_GPIO_BUF_BIT(pin), ++ 0); + } + + static void lan8814_ptp_perout_on(struct phy_device *phydev, int pin) + { +- int val; +- + /* Set as gpio output */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- val |= LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable gpio 0:for alternate function, 1:gpio */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); +- val &= ~LAN8814_GPIO_EN_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ LAN8814_GPIO_EN_BIT(pin), ++ 0); + + /* Set buffer type to push pull */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin)); +- val |= LAN8814_GPIO_BUF_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ LAN8814_GPIO_BUF_BIT(pin), ++ LAN8814_GPIO_BUF_BIT(pin)); + } + + static int lan8814_ptp_perout(struct ptp_clock_info *ptpci, +@@ -3565,61 +3579,59 @@ static int lan8814_ptp_perout(struct ptp_clock_info *ptpci, + + static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) + { +- u16 tmp; +- + /* Set as gpio input */ +- tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- tmp &= ~LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), tmp); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ 0); + + /* Map the pin to ltc pin 0 of the capture map registers */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO); +- tmp |= pin; +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, ++ pin, ++ pin); + + /* Enable capture on the edges of the ltc pin */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_EN); + if (flags & PTP_RISING_EDGE) +- tmp |= PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0), ++ PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0)); + if (flags & PTP_FALLING_EDGE) +- tmp |= PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_EN, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0), ++ PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0)); + + /* Enable interrupt top interrupt */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_COMMON_INT_ENA); +- tmp |= PTP_COMMON_INT_ENA_GPIO_CAP_EN; +- lanphy_write_page_reg(phydev, 4, PTP_COMMON_INT_ENA, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ PTP_COMMON_INT_ENA_GPIO_CAP_EN, ++ PTP_COMMON_INT_ENA_GPIO_CAP_EN); + } + + static void lan8814_ptp_extts_off(struct phy_device *phydev, int pin) + { +- u16 tmp; +- + /* Set as gpio out */ +- tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); +- tmp |= LAN8814_GPIO_DIR_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), tmp); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ LAN8814_GPIO_DIR_BIT(pin), ++ LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable alternate, 0:for alternate function, 1:gpio */ +- tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); +- tmp &= ~LAN8814_GPIO_EN_BIT(pin); +- lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), tmp); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ LAN8814_GPIO_EN_BIT(pin), ++ 0); + + /* Clear the mapping of pin to registers 0 of the capture registers */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO); +- tmp &= ~GENMASK(3, 0); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, ++ GENMASK(3, 0), ++ 0); + + /* Disable capture on both of the edges */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_EN); +- tmp &= ~PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin); +- tmp &= ~PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_EN, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin) | ++ PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin), ++ 0); + + /* Disable interrupt top interrupt */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_COMMON_INT_ENA); +- tmp &= ~PTP_COMMON_INT_ENA_GPIO_CAP_EN; +- lanphy_write_page_reg(phydev, 4, PTP_COMMON_INT_ENA, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ PTP_COMMON_INT_ENA_GPIO_CAP_EN, ++ 0); + } + + static int lan8814_ptp_extts(struct ptp_clock_info *ptpci, +@@ -3859,9 +3871,9 @@ static int lan8814_gpio_process_cap(struct lan8814_shared_priv *shared) + /* This is 0 because whatever was the input pin it was mapped it to + * ltc gpio pin 0 + */ +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_SEL); +- tmp |= PTP_GPIO_SEL_GPIO_SEL(0); +- lanphy_write_page_reg(phydev, 4, PTP_GPIO_SEL, tmp); ++ lanphy_modify_page_reg(phydev, 4, PTP_GPIO_SEL, ++ PTP_GPIO_SEL_GPIO_SEL(0), ++ PTP_GPIO_SEL_GPIO_SEL(0)); + + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_STS); + if (!(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_RE_STS(0)) && +@@ -3908,13 +3920,10 @@ static int lan8814_handle_gpio_interrupt(struct phy_device *phydev, u16 status) + + static int lan8804_config_init(struct phy_device *phydev) + { +- int val; +- + /* MDI-X setting for swap A,B transmit */ +- val = lanphy_read_page_reg(phydev, 2, LAN8804_ALIGN_SWAP); +- val &= ~LAN8804_ALIGN_TX_A_B_SWAP_MASK; +- val |= LAN8804_ALIGN_TX_A_B_SWAP; +- lanphy_write_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, val); ++ lanphy_modify_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, ++ LAN8804_ALIGN_TX_A_B_SWAP_MASK, ++ LAN8804_ALIGN_TX_A_B_SWAP); + + /* Make sure that the PHY will not stop generating the clock when the + * link partner goes down +@@ -4056,7 +4065,6 @@ static void lan8814_ptp_init(struct phy_device *phydev) + { + struct kszphy_priv *priv = phydev->priv; + struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv; +- u32 temp; + + if (!IS_ENABLED(CONFIG_PTP_1588_CLOCK) || + !IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) +@@ -4064,13 +4072,13 @@ static void lan8814_ptp_init(struct phy_device *phydev) + + lanphy_write_page_reg(phydev, 5, TSU_HARD_RESET, TSU_HARD_RESET_); + +- temp = lanphy_read_page_reg(phydev, 5, PTP_TX_MOD); +- temp |= PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_; +- lanphy_write_page_reg(phydev, 5, PTP_TX_MOD, temp); ++ lanphy_modify_page_reg(phydev, 5, PTP_TX_MOD, ++ PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, ++ PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + +- temp = lanphy_read_page_reg(phydev, 5, PTP_RX_MOD); +- temp |= PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_; +- lanphy_write_page_reg(phydev, 5, PTP_RX_MOD, temp); ++ lanphy_modify_page_reg(phydev, 5, PTP_RX_MOD, ++ PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, ++ PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + + lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_CONFIG, 0); + lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_CONFIG, 0); +@@ -4196,23 +4204,21 @@ static void lan8814_setup_led(struct phy_device *phydev, int val) + static int lan8814_config_init(struct phy_device *phydev) + { + struct kszphy_priv *lan8814 = phydev->priv; +- int val; + + /* Reset the PHY */ +- val = lanphy_read_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET); +- val |= LAN8814_QSGMII_SOFT_RESET_BIT; +- lanphy_write_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET, ++ LAN8814_QSGMII_SOFT_RESET_BIT, ++ LAN8814_QSGMII_SOFT_RESET_BIT); + + /* Disable ANEG with QSGMII PCS Host side */ +- val = lanphy_read_page_reg(phydev, 5, LAN8814_QSGMII_PCS1G_ANEG_CONFIG); +- val &= ~LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA; +- lanphy_write_page_reg(phydev, 5, LAN8814_QSGMII_PCS1G_ANEG_CONFIG, val); ++ lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_PCS1G_ANEG_CONFIG, ++ LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA, ++ 0); + + /* MDI-X setting for swap A,B transmit */ +- val = lanphy_read_page_reg(phydev, 2, LAN8814_ALIGN_SWAP); +- val &= ~LAN8814_ALIGN_TX_A_B_SWAP_MASK; +- val |= LAN8814_ALIGN_TX_A_B_SWAP; +- lanphy_write_page_reg(phydev, 2, LAN8814_ALIGN_SWAP, val); ++ lanphy_modify_page_reg(phydev, 2, LAN8814_ALIGN_SWAP, ++ LAN8814_ALIGN_TX_A_B_SWAP_MASK, ++ LAN8814_ALIGN_TX_A_B_SWAP); + + if (lan8814->led_mode >= 0) + lan8814_setup_led(phydev, lan8814->led_mode); +@@ -4243,29 +4249,24 @@ static int lan8814_release_coma_mode(struct phy_device *phydev) + + static void lan8814_clear_2psp_bit(struct phy_device *phydev) + { +- u16 val; +- + /* It was noticed that when traffic is passing through the PHY and the + * cable is removed then the LED was still one even though there is no + * link + */ +- val = lanphy_read_page_reg(phydev, 2, LAN8814_EEE_STATE); +- val &= ~LAN8814_EEE_STATE_MASK2P5P; +- lanphy_write_page_reg(phydev, 2, LAN8814_EEE_STATE, val); ++ lanphy_modify_page_reg(phydev, 2, LAN8814_EEE_STATE, ++ LAN8814_EEE_STATE_MASK2P5P, ++ 0); + } + + static void lan8814_update_meas_time(struct phy_device *phydev) + { +- u16 val; +- + /* By setting the measure time to a value of 0xb this will allow cables + * longer than 100m to be used. This configuration can be used + * regardless of the mode of operation of the PHY + */ +- val = lanphy_read_page_reg(phydev, 1, LAN8814_PD_CONTROLS); +- val &= ~LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK; +- val |= LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL; +- lanphy_write_page_reg(phydev, 1, LAN8814_PD_CONTROLS, val); ++ lanphy_modify_page_reg(phydev, 1, LAN8814_PD_CONTROLS, ++ LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK, ++ LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL); + } + + static int lan8814_probe(struct phy_device *phydev) +-- +2.51.0 + diff --git a/queue-6.17/net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch b/queue-6.17/net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch new file mode 100644 index 0000000000..361c050725 --- /dev/null +++ b/queue-6.17/net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch @@ -0,0 +1,59 @@ +From 536d742e7db7d446504340049fdcccd18b60dbf1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:06:37 +0100 +Subject: net: phy: micrel: lan8814 fix reset of the QSGMII interface + +From: Horatiu Vultur + +[ Upstream commit 96a9178a29a6b84bb632ebeb4e84cf61191c73d5 ] + +The lan8814 is a quad-phy and it is using QSGMII towards the MAC. +The problem is that everytime when one of the ports is configured then +the PCS is reseted for all the PHYs. Meaning that the other ports can +loose traffic until the link is establish again. +To fix this, do the reset one time for the entire PHY package. + +Fixes: ece19502834d ("net: phy: micrel: 1588 support for LAN8814 phy") +Signed-off-by: Horatiu Vultur +Reviewed-by: Andrew Lunn +Reviewed-by: Divya Koppera +Link: https://patch.msgid.link/20251106090637.2030625-1-horatiu.vultur@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 107e5c4c7da3b..39d2cd7cf4382 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -4327,12 +4327,6 @@ static int lan8814_config_init(struct phy_device *phydev) + { + struct kszphy_priv *lan8814 = phydev->priv; + +- /* Reset the PHY */ +- lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, +- LAN8814_QSGMII_SOFT_RESET, +- LAN8814_QSGMII_SOFT_RESET_BIT, +- LAN8814_QSGMII_SOFT_RESET_BIT); +- + /* Disable ANEG with QSGMII PCS Host side */ + lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG, +@@ -4418,6 +4412,12 @@ static int lan8814_probe(struct phy_device *phydev) + addr, sizeof(struct lan8814_shared_priv)); + + if (phy_package_init_once(phydev)) { ++ /* Reset the PHY */ ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_SOFT_RESET, ++ LAN8814_QSGMII_SOFT_RESET_BIT, ++ LAN8814_QSGMII_SOFT_RESET_BIT); ++ + err = lan8814_release_coma_mode(phydev); + if (err) + return err; +-- +2.51.0 + diff --git a/queue-6.17/net-phy-micrel-replace-hardcoded-pages-with-defines.patch b/queue-6.17/net-phy-micrel-replace-hardcoded-pages-with-defines.patch new file mode 100644 index 0000000000..89dd46f205 --- /dev/null +++ b/queue-6.17/net-phy-micrel-replace-hardcoded-pages-with-defines.patch @@ -0,0 +1,741 @@ +From f862a8bc07a49e8c15e9eb360be0200d1d073c54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Aug 2025 09:51:20 +0200 +Subject: net: phy: micrel: Replace hardcoded pages with defines + +From: Horatiu Vultur + +[ Upstream commit d471793a9b67bbe3d7198ff695004190fd7b6bc7 ] + +The functions lan_*_page_reg gets as a second parameter the page +where the register is. In all the functions the page was hardcoded. +Replace the hardcoded values with defines to make it more clear +what are those parameters. + +Reviewed-by: Russell King (Oracle) +Signed-off-by: Horatiu Vultur +Link: https://patch.msgid.link/20250818075121.1298170-4-horatiu.vultur@microchip.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 96a9178a29a6 ("net: phy: micrel: lan8814 fix reset of the QSGMII interface") +Signed-off-by: Sasha Levin +--- + drivers/net/phy/micrel.c | 342 ++++++++++++++++++++++++++------------- + 1 file changed, 233 insertions(+), 109 deletions(-) + +diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c +index 0efc5adbf789d..107e5c4c7da3b 100644 +--- a/drivers/net/phy/micrel.c ++++ b/drivers/net/phy/micrel.c +@@ -2790,6 +2790,52 @@ static int ksz886x_cable_test_get_status(struct phy_device *phydev, + return ret; + } + ++/** ++ * LAN8814_PAGE_AFE_PMA - Selects Extended Page 1. ++ * ++ * This page appears to control the Analog Front-End (AFE) and Physical ++ * Medium Attachment (PMA) layers. It is used to access registers like ++ * LAN8814_PD_CONTROLS and LAN8814_LINK_QUALITY. ++ */ ++#define LAN8814_PAGE_AFE_PMA 1 ++ ++/** ++ * LAN8814_PAGE_PCS_DIGITAL - Selects Extended Page 2. ++ * ++ * This page seems dedicated to the Physical Coding Sublayer (PCS) and other ++ * digital logic. It is used for MDI-X alignment (LAN8814_ALIGN_SWAP) and EEE ++ * state (LAN8814_EEE_STATE) in the LAN8814, and is repurposed for statistics ++ * and self-test counters in the LAN8842. ++ */ ++#define LAN8814_PAGE_PCS_DIGITAL 2 ++ ++/** ++ * LAN8814_PAGE_COMMON_REGS - Selects Extended Page 4. ++ * ++ * This page contains device-common registers that affect the entire chip. ++ * It includes controls for chip-level resets, strap status, GPIO, ++ * QSGMII, the shared 1588 PTP block, and the PVT monitor. ++ */ ++#define LAN8814_PAGE_COMMON_REGS 4 ++ ++/** ++ * LAN8814_PAGE_PORT_REGS - Selects Extended Page 5. ++ * ++ * This page contains port-specific registers that must be accessed ++ * on a per-port basis. It includes controls for port LEDs, QSGMII PCS, ++ * rate adaptation FIFOs, and the per-port 1588 TSU block. ++ */ ++#define LAN8814_PAGE_PORT_REGS 5 ++ ++/** ++ * LAN8814_PAGE_SYSTEM_CTRL - Selects Extended Page 31. ++ * ++ * This page appears to hold fundamental system or global controls. In the ++ * driver, it is used by the related LAN8804 to access the ++ * LAN8814_CLOCK_MANAGEMENT register. ++ */ ++#define LAN8814_PAGE_SYSTEM_CTRL 31 ++ + #define LAN_EXT_PAGE_ACCESS_CONTROL 0x16 + #define LAN_EXT_PAGE_ACCESS_ADDRESS_DATA 0x17 + #define LAN_EXT_PAGE_ACCESS_CTRL_EP_FUNC 0x4000 +@@ -2871,35 +2917,46 @@ static int lan8814_config_ts_intr(struct phy_device *phydev, bool enable) + PTP_TSU_INT_EN_PTP_RX_TS_EN_ | + PTP_TSU_INT_EN_PTP_RX_TS_OVRFL_EN_; + +- return lanphy_write_page_reg(phydev, 5, PTP_TSU_INT_EN, val); ++ return lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TSU_INT_EN, val); + } + + static void lan8814_ptp_rx_ts_get(struct phy_device *phydev, + u32 *seconds, u32 *nano_seconds, u16 *seq_id) + { +- *seconds = lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_SEC_HI); ++ *seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_SEC_HI); + *seconds = (*seconds << 16) | +- lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_SEC_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_SEC_LO); + +- *nano_seconds = lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_NS_HI); ++ *nano_seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_NS_HI); + *nano_seconds = ((*nano_seconds & 0x3fff) << 16) | +- lanphy_read_page_reg(phydev, 5, PTP_RX_INGRESS_NS_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_INGRESS_NS_LO); + +- *seq_id = lanphy_read_page_reg(phydev, 5, PTP_RX_MSG_HEADER2); ++ *seq_id = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_MSG_HEADER2); + } + + static void lan8814_ptp_tx_ts_get(struct phy_device *phydev, + u32 *seconds, u32 *nano_seconds, u16 *seq_id) + { +- *seconds = lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_SEC_HI); ++ *seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_SEC_HI); + *seconds = *seconds << 16 | +- lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_SEC_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_SEC_LO); + +- *nano_seconds = lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_NS_HI); ++ *nano_seconds = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_NS_HI); + *nano_seconds = ((*nano_seconds & 0x3fff) << 16) | +- lanphy_read_page_reg(phydev, 5, PTP_TX_EGRESS_NS_LO); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_EGRESS_NS_LO); + +- *seq_id = lanphy_read_page_reg(phydev, 5, PTP_TX_MSG_HEADER2); ++ *seq_id = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_MSG_HEADER2); + } + + static int lan8814_ts_info(struct mii_timestamper *mii_ts, struct kernel_ethtool_ts_info *info) +@@ -2933,11 +2990,11 @@ static void lan8814_flush_fifo(struct phy_device *phydev, bool egress) + int i; + + for (i = 0; i < FIFO_SIZE; ++i) +- lanphy_read_page_reg(phydev, 5, ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, + egress ? PTP_TX_MSG_HEADER2 : PTP_RX_MSG_HEADER2); + + /* Read to clear overflow status bit */ +- lanphy_read_page_reg(phydev, 5, PTP_TSU_INT_STS); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_TSU_INT_STS); + } + + static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, +@@ -2987,20 +3044,26 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, + rxcfg |= PTP_RX_PARSE_CONFIG_IPV4_EN_ | PTP_RX_PARSE_CONFIG_IPV6_EN_; + txcfg |= PTP_TX_PARSE_CONFIG_IPV4_EN_ | PTP_TX_PARSE_CONFIG_IPV6_EN_; + } +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg); +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_CONFIG, rxcfg); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_CONFIG, txcfg); + + pkt_ts_enable = PTP_TIMESTAMP_EN_SYNC_ | PTP_TIMESTAMP_EN_DREQ_ | + PTP_TIMESTAMP_EN_PDREQ_ | PTP_TIMESTAMP_EN_PDRES_; +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_TIMESTAMP_EN, pkt_ts_enable); +- lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_TIMESTAMP_EN, pkt_ts_enable); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_TIMESTAMP_EN, pkt_ts_enable); ++ lanphy_write_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_TIMESTAMP_EN, pkt_ts_enable); + + if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { +- lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ lanphy_modify_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_MOD, + PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, + PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); + } else if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ON) { +- lanphy_modify_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, ++ lanphy_modify_page_reg(ptp_priv->phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_MOD, + PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_, + 0); + } +@@ -3124,29 +3187,41 @@ static bool lan8814_rxtstamp(struct mii_timestamper *mii_ts, struct sk_buff *skb + static void lan8814_ptp_clock_set(struct phy_device *phydev, + time64_t sec, u32 nsec) + { +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_LO, lower_16_bits(sec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_MID, upper_16_bits(sec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_HI, upper_32_bits(sec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_NS_LO, lower_16_bits(nsec)); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_SET_NS_HI, upper_16_bits(nsec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_SEC_LO, lower_16_bits(sec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_SEC_MID, upper_16_bits(sec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_SEC_HI, upper_32_bits(sec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_NS_LO, lower_16_bits(nsec)); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_SET_NS_HI, upper_16_bits(nsec)); + +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_LOAD_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, ++ PTP_CMD_CTL_PTP_CLOCK_LOAD_); + } + + static void lan8814_ptp_clock_get(struct phy_device *phydev, + time64_t *sec, u32 *nsec) + { +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, ++ PTP_CMD_CTL_PTP_CLOCK_READ_); + +- *sec = lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_HI); ++ *sec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_SEC_HI); + *sec <<= 16; +- *sec |= lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_MID); ++ *sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_SEC_MID); + *sec <<= 16; +- *sec |= lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_LO); ++ *sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_SEC_LO); + +- *nsec = lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_NS_HI); ++ *nsec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_NS_HI); + *nsec <<= 16; +- *nsec |= lanphy_read_page_reg(phydev, 4, PTP_CLOCK_READ_NS_LO); ++ *nsec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CLOCK_READ_NS_LO); + } + + static int lan8814_ptpci_gettime64(struct ptp_clock_info *ptpci, +@@ -3185,14 +3260,18 @@ static void lan8814_ptp_set_target(struct phy_device *phydev, int event, + s64 start_sec, u32 start_nsec) + { + /* Set the start time */ +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_SEC_LO(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_SEC_LO(event), + lower_16_bits(start_sec)); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_SEC_HI(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_SEC_HI(event), + upper_16_bits(start_sec)); + +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_NS_LO(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_NS_LO(event), + lower_16_bits(start_nsec)); +- lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_NS_HI(event), ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_PTP_CLOCK_TARGET_NS_HI(event), + upper_16_bits(start_nsec) & 0x3fff); + } + +@@ -3290,9 +3369,11 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + adjustment_value_lo = adjustment_value & 0xffff; + adjustment_value_hi = (adjustment_value >> 16) & 0x3fff; + +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_LO, + adjustment_value_lo); +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_HI, + PTP_LTC_STEP_ADJ_DIR_ | + adjustment_value_hi); + seconds -= ((s32)adjustment_value); +@@ -3310,9 +3391,11 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + adjustment_value_lo = adjustment_value & 0xffff; + adjustment_value_hi = (adjustment_value >> 16) & 0x3fff; + +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_LO, + adjustment_value_lo); +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_HI, + adjustment_value_hi); + seconds += ((s32)adjustment_value); + +@@ -3320,8 +3403,8 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + set_seconds += adjustment_value; + lan8814_ptp_update_target(phydev, set_seconds); + } +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, +- PTP_CMD_CTL_PTP_LTC_STEP_SEC_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_CMD_CTL, PTP_CMD_CTL_PTP_LTC_STEP_SEC_); + } + if (nano_seconds) { + u16 nano_seconds_lo; +@@ -3330,12 +3413,14 @@ static void lan8814_ptp_clock_step(struct phy_device *phydev, + nano_seconds_lo = nano_seconds & 0xffff; + nano_seconds_hi = (nano_seconds >> 16) & 0x3fff; + +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_LO, + nano_seconds_lo); +- lanphy_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_LTC_STEP_ADJ_HI, + PTP_LTC_STEP_ADJ_DIR_ | + nano_seconds_hi); +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, + PTP_CMD_CTL_PTP_LTC_STEP_NSEC_); + } + } +@@ -3377,8 +3462,10 @@ static int lan8814_ptpci_adjfine(struct ptp_clock_info *ptpci, long scaled_ppm) + kszphy_rate_adj_hi |= PTP_CLOCK_RATE_ADJ_DIR_; + + mutex_lock(&shared->shared_lock); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_HI, kszphy_rate_adj_hi); +- lanphy_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_LO, kszphy_rate_adj_lo); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CLOCK_RATE_ADJ_HI, ++ kszphy_rate_adj_hi); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CLOCK_RATE_ADJ_LO, ++ kszphy_rate_adj_lo); + mutex_unlock(&shared->shared_lock); + + return 0; +@@ -3387,17 +3474,17 @@ static int lan8814_ptpci_adjfine(struct ptp_clock_info *ptpci, long scaled_ppm) + static void lan8814_ptp_set_reload(struct phy_device *phydev, int event, + s64 period_sec, u32 period_nsec) + { +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_LO(event), + lower_16_bits(period_sec)); +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_HI(event), + upper_16_bits(period_sec)); + +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_LO(event), + lower_16_bits(period_nsec)); +- lanphy_write_page_reg(phydev, 4, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, + LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_HI(event), + upper_16_bits(period_nsec) & 0x3fff); + } +@@ -3410,7 +3497,7 @@ static void lan8814_ptp_enable_event(struct phy_device *phydev, int event, + * local time reaches or pass it + * Set the polarity high + */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, LAN8814_PTP_GENERAL_CONFIG, + LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_MASK(event) | + LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_SET(event, pulse_width) | + LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event) | +@@ -3425,7 +3512,7 @@ static void lan8814_ptp_disable_event(struct phy_device *phydev, int event) + lan8814_ptp_set_target(phydev, event, 0xFFFFFFFF, 0); + + /* And then reload once it recheas the target */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, LAN8814_PTP_GENERAL_CONFIG, + LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event), + LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X(event)); + } +@@ -3436,15 +3523,18 @@ static void lan8814_ptp_perout_off(struct phy_device *phydev, int pin) + * 1: select as gpio, + * 0: select alt func + */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_EN_ADDR(pin), + LAN8814_GPIO_EN_BIT(pin), + LAN8814_GPIO_EN_BIT(pin)); + +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + 0); + +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_BUF_ADDR(pin), + LAN8814_GPIO_BUF_BIT(pin), + 0); + } +@@ -3452,17 +3542,20 @@ static void lan8814_ptp_perout_off(struct phy_device *phydev, int pin) + static void lan8814_ptp_perout_on(struct phy_device *phydev, int pin) + { + /* Set as gpio output */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable gpio 0:for alternate function, 1:gpio */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_EN_ADDR(pin), + LAN8814_GPIO_EN_BIT(pin), + 0); + + /* Set buffer type to push pull */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_BUF_ADDR(pin), + LAN8814_GPIO_BUF_BIT(pin), + LAN8814_GPIO_BUF_BIT(pin)); + } +@@ -3580,27 +3673,29 @@ static int lan8814_ptp_perout(struct ptp_clock_info *ptpci, + static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) + { + /* Set as gpio input */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + 0); + + /* Map the pin to ltc pin 0 of the capture map registers */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, +- pin, +- pin); ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_MAP_LO, pin, pin); + + /* Enable capture on the edges of the ltc pin */ + if (flags & PTP_RISING_EDGE) +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_EN, + PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0), + PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0)); + if (flags & PTP_FALLING_EDGE) +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_EN, + PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0), + PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0)); + + /* Enable interrupt top interrupt */ +- lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_COMMON_INT_ENA, + PTP_COMMON_INT_ENA_GPIO_CAP_EN, + PTP_COMMON_INT_ENA_GPIO_CAP_EN); + } +@@ -3608,28 +3703,31 @@ static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) + static void lan8814_ptp_extts_off(struct phy_device *phydev, int pin) + { + /* Set as gpio out */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_DIR_ADDR(pin), + LAN8814_GPIO_DIR_BIT(pin), + LAN8814_GPIO_DIR_BIT(pin)); + + /* Enable alternate, 0:for alternate function, 1:gpio */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_GPIO_EN_ADDR(pin), + LAN8814_GPIO_EN_BIT(pin), + 0); + + /* Clear the mapping of pin to registers 0 of the capture registers */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_MAP_LO, + GENMASK(3, 0), + 0); + + /* Disable capture on both of the edges */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_CAP_EN, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_GPIO_CAP_EN, + PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin) | + PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin), + 0); + + /* Disable interrupt top interrupt */ +- lanphy_modify_page_reg(phydev, 4, PTP_COMMON_INT_ENA, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_COMMON_INT_ENA, + PTP_COMMON_INT_ENA_GPIO_CAP_EN, + 0); + } +@@ -3761,7 +3859,8 @@ static void lan8814_get_tx_ts(struct kszphy_ptp_priv *ptp_priv) + /* If other timestamps are available in the FIFO, + * process them. + */ +- reg = lanphy_read_page_reg(phydev, 5, PTP_CAP_INFO); ++ reg = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_CAP_INFO); + } while (PTP_CAP_INFO_TX_TS_CNT_GET_(reg) > 0); + } + +@@ -3834,7 +3933,8 @@ static void lan8814_get_rx_ts(struct kszphy_ptp_priv *ptp_priv) + /* If other timestamps are available in the FIFO, + * process them. + */ +- reg = lanphy_read_page_reg(phydev, 5, PTP_CAP_INFO); ++ reg = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_CAP_INFO); + } while (PTP_CAP_INFO_RX_TS_CNT_GET_(reg) > 0); + } + +@@ -3871,31 +3971,40 @@ static int lan8814_gpio_process_cap(struct lan8814_shared_priv *shared) + /* This is 0 because whatever was the input pin it was mapped it to + * ltc gpio pin 0 + */ +- lanphy_modify_page_reg(phydev, 4, PTP_GPIO_SEL, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_GPIO_SEL, + PTP_GPIO_SEL_GPIO_SEL(0), + PTP_GPIO_SEL_GPIO_SEL(0)); + +- tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_STS); ++ tmp = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_CAP_STS); + if (!(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_RE_STS(0)) && + !(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_FE_STS(0))) + return -1; + + if (tmp & BIT(0)) { +- sec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_SEC_HI_CAP); ++ sec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_SEC_HI_CAP); + sec <<= 16; +- sec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_SEC_LO_CAP); ++ sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_SEC_LO_CAP); + +- nsec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_HI_CAP) & 0x3fff; ++ nsec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_NS_HI_CAP) & 0x3fff; + nsec <<= 16; +- nsec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_LO_CAP); ++ nsec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_NS_LO_CAP); + } else { +- sec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_SEC_HI_CAP); ++ sec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_FE_LTC_SEC_HI_CAP); + sec <<= 16; +- sec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_SEC_LO_CAP); ++ sec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_FE_LTC_SEC_LO_CAP); + +- nsec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_NS_HI_CAP) & 0x3fff; ++ nsec = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_FE_LTC_NS_HI_CAP) & 0x3fff; + nsec <<= 16; +- nsec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_LO_CAP); ++ nsec |= lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ PTP_GPIO_RE_LTC_NS_LO_CAP); + } + + ptp_event.index = 0; +@@ -3921,15 +4030,16 @@ static int lan8814_handle_gpio_interrupt(struct phy_device *phydev, u16 status) + static int lan8804_config_init(struct phy_device *phydev) + { + /* MDI-X setting for swap A,B transmit */ +- lanphy_modify_page_reg(phydev, 2, LAN8804_ALIGN_SWAP, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, LAN8804_ALIGN_SWAP, + LAN8804_ALIGN_TX_A_B_SWAP_MASK, + LAN8804_ALIGN_TX_A_B_SWAP); + + /* Make sure that the PHY will not stop generating the clock when the + * link partner goes down + */ +- lanphy_write_page_reg(phydev, 31, LAN8814_CLOCK_MANAGEMENT, 0x27e); +- lanphy_read_page_reg(phydev, 1, LAN8814_LINK_QUALITY); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_SYSTEM_CTRL, ++ LAN8814_CLOCK_MANAGEMENT, 0x27e); ++ lanphy_read_page_reg(phydev, LAN8814_PAGE_AFE_PMA, LAN8814_LINK_QUALITY); + + return 0; + } +@@ -4011,7 +4121,8 @@ static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev) + } + + while (true) { +- irq_status = lanphy_read_page_reg(phydev, 5, PTP_TSU_INT_STS); ++ irq_status = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TSU_INT_STS); + if (!irq_status) + break; + +@@ -4039,7 +4150,7 @@ static int lan8814_config_intr(struct phy_device *phydev) + { + int err; + +- lanphy_write_page_reg(phydev, 4, LAN8814_INTR_CTRL_REG, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, LAN8814_INTR_CTRL_REG, + LAN8814_INTR_CTRL_REG_POLARITY | + LAN8814_INTR_CTRL_REG_INTR_ENABLE); + +@@ -4070,29 +4181,36 @@ static void lan8814_ptp_init(struct phy_device *phydev) + !IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) + return; + +- lanphy_write_page_reg(phydev, 5, TSU_HARD_RESET, TSU_HARD_RESET_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ TSU_HARD_RESET, TSU_HARD_RESET_); + +- lanphy_modify_page_reg(phydev, 5, PTP_TX_MOD, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_TX_MOD, + PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, + PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + +- lanphy_modify_page_reg(phydev, 5, PTP_RX_MOD, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_RX_MOD, + PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_, + PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_); + +- lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_CONFIG, 0); +- lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_CONFIG, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_CONFIG, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_CONFIG, 0); + + /* Removing default registers configs related to L2 and IP */ +- lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_L2_ADDR_EN, 0); +- lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_L2_ADDR_EN, 0); +- lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_IP_ADDR_EN, 0); +- lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_IP_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_L2_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_L2_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_TX_PARSE_IP_ADDR_EN, 0); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ PTP_RX_PARSE_IP_ADDR_EN, 0); + + /* Disable checking for minorVersionPTP field */ +- lanphy_write_page_reg(phydev, 5, PTP_RX_VERSION, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_RX_VERSION, + PTP_MAX_VERSION(0xff) | PTP_MIN_VERSION(0x0)); +- lanphy_write_page_reg(phydev, 5, PTP_TX_VERSION, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, PTP_TX_VERSION, + PTP_MAX_VERSION(0xff) | PTP_MIN_VERSION(0x0)); + + skb_queue_head_init(&ptp_priv->tx_queue); +@@ -4177,12 +4295,14 @@ static int lan8814_ptp_probe_once(struct phy_device *phydev) + /* The EP.4 is shared between all the PHYs in the package and also it + * can be accessed by any of the PHYs + */ +- lanphy_write_page_reg(phydev, 4, LTC_HARD_RESET, LTC_HARD_RESET_); +- lanphy_write_page_reg(phydev, 4, PTP_OPERATING_MODE, ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LTC_HARD_RESET, LTC_HARD_RESET_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_OPERATING_MODE, + PTP_OPERATING_MODE_STANDALONE_); + + /* Enable ptp to run LTC clock for ptp and gpio 1PPS operation */ +- lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, PTP_CMD_CTL, ++ PTP_CMD_CTL_PTP_ENABLE_); + + return 0; + } +@@ -4191,14 +4311,16 @@ static void lan8814_setup_led(struct phy_device *phydev, int val) + { + int temp; + +- temp = lanphy_read_page_reg(phydev, 5, LAN8814_LED_CTRL_1); ++ temp = lanphy_read_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ LAN8814_LED_CTRL_1); + + if (val) + temp |= LAN8814_LED_CTRL_1_KSZ9031_LED_MODE_; + else + temp &= ~LAN8814_LED_CTRL_1_KSZ9031_LED_MODE_; + +- lanphy_write_page_reg(phydev, 5, LAN8814_LED_CTRL_1, temp); ++ lanphy_write_page_reg(phydev, LAN8814_PAGE_PORT_REGS, ++ LAN8814_LED_CTRL_1, temp); + } + + static int lan8814_config_init(struct phy_device *phydev) +@@ -4206,17 +4328,19 @@ static int lan8814_config_init(struct phy_device *phydev) + struct kszphy_priv *lan8814 = phydev->priv; + + /* Reset the PHY */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_SOFT_RESET, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_SOFT_RESET, + LAN8814_QSGMII_SOFT_RESET_BIT, + LAN8814_QSGMII_SOFT_RESET_BIT); + + /* Disable ANEG with QSGMII PCS Host side */ +- lanphy_modify_page_reg(phydev, 4, LAN8814_QSGMII_PCS1G_ANEG_CONFIG, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, ++ LAN8814_QSGMII_PCS1G_ANEG_CONFIG, + LAN8814_QSGMII_PCS1G_ANEG_CONFIG_ANEG_ENA, + 0); + + /* MDI-X setting for swap A,B transmit */ +- lanphy_modify_page_reg(phydev, 2, LAN8814_ALIGN_SWAP, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, LAN8814_ALIGN_SWAP, + LAN8814_ALIGN_TX_A_B_SWAP_MASK, + LAN8814_ALIGN_TX_A_B_SWAP); + +@@ -4253,7 +4377,7 @@ static void lan8814_clear_2psp_bit(struct phy_device *phydev) + * cable is removed then the LED was still one even though there is no + * link + */ +- lanphy_modify_page_reg(phydev, 2, LAN8814_EEE_STATE, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_PCS_DIGITAL, LAN8814_EEE_STATE, + LAN8814_EEE_STATE_MASK2P5P, + 0); + } +@@ -4264,7 +4388,7 @@ static void lan8814_update_meas_time(struct phy_device *phydev) + * longer than 100m to be used. This configuration can be used + * regardless of the mode of operation of the PHY + */ +- lanphy_modify_page_reg(phydev, 1, LAN8814_PD_CONTROLS, ++ lanphy_modify_page_reg(phydev, LAN8814_PAGE_AFE_PMA, LAN8814_PD_CONTROLS, + LAN8814_PD_CONTROLS_PD_MEAS_TIME_MASK, + LAN8814_PD_CONTROLS_PD_MEAS_TIME_VAL); + } +@@ -4289,7 +4413,7 @@ static int lan8814_probe(struct phy_device *phydev) + /* Strap-in value for PHY address, below register read gives starting + * phy address value + */ +- addr = lanphy_read_page_reg(phydev, 4, 0) & 0x1F; ++ addr = lanphy_read_page_reg(phydev, LAN8814_PAGE_COMMON_REGS, 0) & 0x1F; + devm_phy_package_join(&phydev->mdio.dev, phydev, + addr, sizeof(struct lan8814_shared_priv)); + +-- +2.51.0 + diff --git a/queue-6.17/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch b/queue-6.17/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch new file mode 100644 index 0000000000..bba9e92b80 --- /dev/null +++ b/queue-6.17/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch @@ -0,0 +1,59 @@ +From e13b7be2646cd24a2b011fd17fd7b6b5c73c54de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:35 +0530 +Subject: net: sched: act_connmark: initialize struct tc_ife to fix kernel leak + +From: Ranganath V N + +[ Upstream commit 62b656e43eaeae445a39cd8021a4f47065af4389 ] + +In tcf_connmark_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: 22a5dc0e5e3e ("net: sched: Introduce connmark action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-2-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_connmark.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 3e89927d71164..26ba8c2d20abf 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -195,13 +195,15 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); + const struct tcf_connmark_parms *parms; +- struct tc_connmark opt = { +- .index = ci->tcf_index, +- .refcnt = refcount_read(&ci->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, +- }; ++ struct tc_connmark opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ci->tcf_index; ++ opt.refcnt = refcount_read(&ci->tcf_refcnt) - ref; ++ opt.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind; ++ + rcu_read_lock(); + parms = rcu_dereference(ci->parms); + +-- +2.51.0 + diff --git a/queue-6.17/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-6.17/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..a3b29877a5 --- /dev/null +++ b/queue-6.17/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From 7b38a77b36ef67c02aab445fa9772107d263b7d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index 107c6d83dc5c4..7c6975632fc2e 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -644,13 +644,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-6.17/net-smc-fix-mismatch-between-clc-header-and-proposal.patch b/queue-6.17/net-smc-fix-mismatch-between-clc-header-and-proposal.patch new file mode 100644 index 0000000000..f44630a31b --- /dev/null +++ b/queue-6.17/net-smc-fix-mismatch-between-clc-header-and-proposal.patch @@ -0,0 +1,55 @@ +From 53e1c1027042a62c658b41504a433e068e7791c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 10:40:29 +0800 +Subject: net/smc: fix mismatch between CLC header and proposal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: D. Wythe + +[ Upstream commit ec33f2e5a2d0dbbfd71435209aee812fdc9369b8 ] + +The current CLC proposal message construction uses a mix of +`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether +to include optional extensions (IPv6 prefix extension for v1, and v2 +extension). This leads to a critical inconsistency: when +`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with +only link-local addresses, or when the local IP address and the outgoing +interface’s network address are not in the same subnet. + +As a result, the proposal message is assembled using the stale +`ini->smc_type_v1` value—causing the IPv6 prefix extension to be +included even though the header indicates v1 is not supported. +The peer then receives a malformed CLC proposal where the header type +does not match the payload, and immediately resets the connection. + +The fix ensures consistency between the CLC header flags and the actual +payload by synchronizing `ini->smc_type_v1` with `pclc_base->hdr.typev1` +when prefix setup fails. + +Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal") +Signed-off-by: D. Wythe +Reviewed-by: Alexandra Winter +Link: https://patch.msgid.link/20251107024029.88753-1-alibuda@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_clc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c +index 09745baa10170..27750a695ed8b 100644 +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -890,6 +890,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) + return SMC_CLC_DECL_CNFERR; + } + pclc_base->hdr.typev1 = SMC_TYPE_N; ++ ini->smc_type_v1 = SMC_TYPE_N; + } else { + pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); + plen += sizeof(*pclc_prfx) + +-- +2.51.0 + diff --git a/queue-6.17/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-6.17/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..21e5bb3766 --- /dev/null +++ b/queue-6.17/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From 2df456a23f3ec51853d77de1f9ca593929c9a774 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 1e008a228ebdf..7dee9748a56be 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -180,9 +180,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -193,8 +194,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -228,7 +231,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -295,7 +298,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -387,7 +390,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -396,7 +399,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -414,7 +417,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(net_hotdata.dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + if (q->flags & TCQ_F_NOLOCK) +-- +2.51.0 + diff --git a/queue-6.17/netfilter-nft_ct-add-seqadj-extension-for-natted-con.patch b/queue-6.17/netfilter-nft_ct-add-seqadj-extension-for-natted-con.patch new file mode 100644 index 0000000000..ac6b6d8bf1 --- /dev/null +++ b/queue-6.17/netfilter-nft_ct-add-seqadj-extension-for-natted-con.patch @@ -0,0 +1,113 @@ +From 2fdce4a177dff1a44823fd39813f73c5b7798ce9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Oct 2025 18:22:16 +0200 +Subject: netfilter: nft_ct: add seqadj extension for natted connections + +From: Andrii Melnychenko + +[ Upstream commit 90918e3b6404c2a37837b8f11692471b4c512de2 ] + +Sequence adjustment may be required for FTP traffic with PASV/EPSV modes. +due to need to re-write packet payload (IP, port) on the ftp control +connection. This can require changes to the TCP length and expected +seq / ack_seq. + +The easiest way to reproduce this issue is with PASV mode. +Example ruleset: +table inet ftp_nat { + ct helper ftp_helper { + type "ftp" protocol tcp + l3proto inet + } + + chain prerouting { + type filter hook prerouting priority 0; policy accept; + tcp dport 21 ct state new ct helper set "ftp_helper" + } +} +table ip nat { + chain prerouting { + type nat hook prerouting priority -100; policy accept; + tcp dport 21 dnat ip prefix to ip daddr map { + 192.168.100.1 : 192.168.13.2/32 } + } + + chain postrouting { + type nat hook postrouting priority 100 ; policy accept; + tcp sport 21 snat ip prefix to ip saddr map { + 192.168.13.2 : 192.168.100.1/32 } + } +} + +Note that the ftp helper gets assigned *after* the dnat setup. + +The inverse (nat after helper assign) is handled by an existing +check in nf_nat_setup_info() and will not show the problem. + +Topoloy: + + +-------------------+ +----------------------------------+ + | FTP: 192.168.13.2 | <-> | NAT: 192.168.13.3, 192.168.100.1 | + +-------------------+ +----------------------------------+ + | + +-----------------------+ + | Client: 192.168.100.2 | + +-----------------------+ + +ftp nat changes do not work as expected in this case: +Connected to 192.168.100.1. +[..] +ftp> epsv +EPSV/EPRT on IPv4 off. +ftp> ls +227 Entering passive mode (192,168,100,1,209,129). +421 Service not available, remote server has closed connection. + +Kernel logs: +Missing nfct_seqadj_ext_add() setup call +WARNING: CPU: 1 PID: 0 at net/netfilter/nf_conntrack_seqadj.c:41 +[..] + __nf_nat_mangle_tcp_packet+0x100/0x160 [nf_nat] + nf_nat_ftp+0x142/0x280 [nf_nat_ftp] + help+0x4d1/0x880 [nf_conntrack_ftp] + nf_confirm+0x122/0x2e0 [nf_conntrack] + nf_hook_slow+0x3c/0xb0 + .. + +Fix this by adding the required extension when a conntrack helper is assigned +to a connection that has a nat binding. + +Fixes: 1a64edf54f55 ("netfilter: nft_ct: add helper set support") +Signed-off-by: Andrii Melnychenko +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_ct.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c +index d526e69a2a2b8..f358cdc5e6926 100644 +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + struct nft_ct_helper_obj { + struct nf_conntrack_helper *helper4; +@@ -1173,6 +1174,10 @@ static void nft_ct_helper_obj_eval(struct nft_object *obj, + if (help) { + rcu_assign_pointer(help->helper, to_assign); + set_bit(IPS_HELPER_BIT, &ct->status); ++ ++ if ((ct->status & IPS_NAT_MASK) && !nfct_seqadj(ct)) ++ if (!nfct_seqadj_ext_add(ct)) ++ regs->verdict.code = NF_DROP; + } + } + +-- +2.51.0 + diff --git a/queue-6.17/nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch b/queue-6.17/nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch new file mode 100644 index 0000000000..f42d526d00 --- /dev/null +++ b/queue-6.17/nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch @@ -0,0 +1,43 @@ +From 6ae90462da09069524543f23aa61e0db10b58102 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Oct 2025 09:49:55 -0400 +Subject: NFSD: Skip close replay processing if XDR encoding fails + +From: Chuck Lever + +[ Upstream commit ff8141e49cf70d2d093a5228f5299ce188de6142 ] + +The replay logic added by commit 9411b1d4c7df ("nfsd4: cleanup +handling of nfsv4.0 closed stateid's") cannot be done if encoding +failed due to a short send buffer; there's no guarantee that the +operation encoder has actually encoded the data that is being copied +to the replay cache. + +Reported-by: rtm@csail.mit.edu +Closes: https://lore.kernel.org/linux-nfs/c3628d57-94ae-48cf-8c9e-49087a28cec9@oracle.com/T/#t +Fixes: 9411b1d4c7df ("nfsd4: cleanup handling of nfsv4.0 closed stateid's") +Reviewed-by: Jeff Layton +Reviewed-by: NeilBrown +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4xdr.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 1f6c3db3bc6e5..37541ea408fc0 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -5928,8 +5928,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) + */ + warn_on_nonidempotent_op(op); + xdr_truncate_encode(xdr, op_status_offset + XDR_UNIT); +- } +- if (so) { ++ } else if (so) { + int len = xdr->buf->len - (op_status_offset + XDR_UNIT); + + so->so_replay.rp_status = op->status; +-- +2.51.0 + diff --git a/queue-6.17/rust-add-fno-isolate-erroneous-paths-dereference-to-.patch b/queue-6.17/rust-add-fno-isolate-erroneous-paths-dereference-to-.patch new file mode 100644 index 0000000000..26cb64ac11 --- /dev/null +++ b/queue-6.17/rust-add-fno-isolate-erroneous-paths-dereference-to-.patch @@ -0,0 +1,41 @@ +From 0b00d93bb4967eb990e4b68ec2c373bca9a1028d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:01:50 +0800 +Subject: rust: Add -fno-isolate-erroneous-paths-dereference to + bindgen_skip_c_flags + +From: Xi Ruoyao + +[ Upstream commit fe4b3a34e9a9654d98d274218dac0270779db0ae ] + +It's used to work around an objtool issue since commit abb2a5572264 +("LoongArch: Add cflag -fno-isolate-erroneous-paths-dereference"), but +it's then passed to bindgen and cause an error because Clang does not +have this option. + +Fixes: abb2a5572264 ("LoongArch: Add cflag -fno-isolate-erroneous-paths-dereference") +Acked-by: Miguel Ojeda +Tested-by: Mingcong Bai +Signed-off-by: Xi Ruoyao +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + rust/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rust/Makefile b/rust/Makefile +index 9ec1119c02d39..403ce8518381d 100644 +--- a/rust/Makefile ++++ b/rust/Makefile +@@ -299,7 +299,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ + -fno-inline-functions-called-once -fsanitize=bounds-strict \ + -fstrict-flex-arrays=% -fmin-function-alignment=% \ + -fzero-init-padding-bits=% -mno-fdpic \ +- --param=% --param asan-% ++ --param=% --param asan-% -fno-isolate-erroneous-paths-dereference + + # Derived from `scripts/Makefile.clang`. + BINDGEN_TARGET_x86 := x86_64-linux-gnu +-- +2.51.0 + diff --git a/queue-6.17/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-6.17/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..84fb0f9540 --- /dev/null +++ b/queue-6.17/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From 5f5525c3374f2dfa741c9fd6a2817bc21a8dfe14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 4d258a6e8033c..e0cf9a41e0e43 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -495,6 +495,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -506,10 +507,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-6.17/selftests-net-local_termination-wait-for-interfaces-.patch b/queue-6.17/selftests-net-local_termination-wait-for-interfaces-.patch new file mode 100644 index 0000000000..370566db17 --- /dev/null +++ b/queue-6.17/selftests-net-local_termination-wait-for-interfaces-.patch @@ -0,0 +1,48 @@ +From d0059d0e9a9a1104f73ab13d6013fe990663b2f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 17:12:09 +0100 +Subject: selftests: net: local_termination: Wait for interfaces to come up + +From: Alexander Sverdlin + +[ Upstream commit 57531b3416448d1ced36a2a974a4085ec43d57b0 ] + +It seems that most of the tests prepare the interfaces once before the test +run (setup_prepare()), rely on setup_wait() to wait for link and only then +run the test(s). + +local_termination brings the physical interfaces down and up during test +run but never wait for them to come up. If the auto-negotiation takes +some seconds, first test packets are being lost, which leads to +false-negative test results. + +Use setup_wait() in run_test() to make sure auto-negotiation has been +completed after all simple_if_init() calls on physical interfaces and test +packets will not be lost because of the race against link establishment. + +Fixes: 90b9566aa5cd3f ("selftests: forwarding: add a test for local_termination.sh") +Reviewed-by: Vladimir Oltean +Signed-off-by: Alexander Sverdlin +Link: https://patch.msgid.link/20251106161213.459501-1-alexander.sverdlin@siemens.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/forwarding/local_termination.sh | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/net/forwarding/local_termination.sh b/tools/testing/selftests/net/forwarding/local_termination.sh +index ecd34f364125c..892895659c7e4 100755 +--- a/tools/testing/selftests/net/forwarding/local_termination.sh ++++ b/tools/testing/selftests/net/forwarding/local_termination.sh +@@ -176,6 +176,8 @@ run_test() + local rcv_dmac=$(mac_get $rcv_if_name) + local should_receive + ++ setup_wait ++ + tcpdump_start $rcv_if_name + + mc_route_prepare $send_if_name +-- +2.51.0 + diff --git a/queue-6.17/series b/queue-6.17/series index a50b5a0191..c20ea3f45d 100644 --- a/queue-6.17/series +++ b/queue-6.17/series @@ -43,3 +43,52 @@ hid-logitech-hidpp-add-hidpp_quirk_reset_hi_res_scro.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch alsa-hda-realtek-fix-mute-led-for-hp-omen-17-cb0xxx.patch ixgbe-handle-ixgbe_vf_features_negotiate-mbox-cmd.patch +wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch +erofs-avoid-infinite-loop-due-to-incomplete-zstd-com.patch +selftests-net-local_termination-wait-for-interfaces-.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +net-phy-micrel-introduce-lanphy_modify_page_reg.patch +net-phy-micrel-replace-hardcoded-pages-with-defines.patch +net-phy-micrel-lan8814-fix-reset-of-the-qsgmii-inter.patch +rust-add-fno-isolate-erroneous-paths-dereference-to-.patch +nfsd-skip-close-replay-processing-if-xdr-encoding-fa.patch +bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +bluetooth-hci_conn-fix-not-cleaning-up-pa_link-conne.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +net-dsa-tag_brcm-do-not-mark-link-local-traffic-as-o.patch +net-smc-fix-mismatch-between-clc-header-and-proposal.patch +net-handshake-fix-memory-leak-in-tls_handshake_accep.patch +net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-respons.patch +net-ethernet-ti-am65-cpsw-qos-fix-iet-verify-retry-m.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +af_unix-initialise-scc_index-in-unix_add_edge.patch +bluetooth-hci_event-fix-not-handling-pa-sync-lost-ev.patch +net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-missing-error-assignment-in-mlx5e_xfrm.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net-mlx5e-fix-potentially-misleading-debug-message.patch +net-mlx5-fix-typo-of-mlx5_eq_doorbel_offset.patch +net-mlx5-store-the-global-doorbell-in-mlx5_priv.patch +net-mlx5e-prepare-for-using-different-cq-doorbells.patch +mlx5-fix-default-values-in-create-cq.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +wifi-iwlwifi-mvm-fix-beacon-template-fixed-rate.patch +wifi-iwlwifi-mld-always-take-beacon-ies-in-link-grad.patch +virtio-net-fix-incorrect-flags-recording-in-big-mode.patch +hsr-fix-supervision-frame-sending-on-hsrv0.patch +hsr-follow-standard-for-hsrv0-supervision-frames.patch +acpi-cppc-detect-preferred-core-availability-on-onli.patch +acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch +acpi-cppc-perform-fast-check-switch-only-for-online-.patch +acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch +cpufreq-intel_pstate-check-ida-only-before-msr_ia32_.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch +netfilter-nft_ct-add-seqadj-extension-for-natted-con.patch diff --git a/queue-6.17/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-6.17/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..c27e12914d --- /dev/null +++ b/queue-6.17/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From e3ab22bbb46ed5ba04746f30ea15a76756e6776f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 0e95572e56b41..7e65d0b0c4a8d 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -145,7 +145,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-6.17/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch b/queue-6.17/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch new file mode 100644 index 0000000000..f0c88d5b6f --- /dev/null +++ b/queue-6.17/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch @@ -0,0 +1,72 @@ +From d5ee579a041d63cdf1caf281c860c588504eb23f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:08:28 +0800 +Subject: virtio-net: fix incorrect flags recording in big mode + +From: Xuan Zhuo + +[ Upstream commit 0eff2eaa5322b5b141ff5d5ded26fac4a52b5f7b ] + +The purpose of commit 703eec1b2422 ("virtio_net: fixing XDP for fully +checksummed packets handling") is to record the flags in advance, as +their value may be overwritten in the XDP case. However, the flags +recorded under big mode are incorrect, because in big mode, the passed +buf does not point to the rx buffer, but rather to the page of the +submitted buffer. This commit fixes this issue. + +For the small mode, the commit c11a49d58ad2 ("virtio_net: Fix mismatched +buf address when unmapping for small packets") fixed it. + +Tested-by: Alyssa Ross +Fixes: 703eec1b2422 ("virtio_net: fixing XDP for fully checksummed packets handling") +Signed-off-by: Xuan Zhuo +Acked-by: Jason Wang +Acked-by: Michael S. Tsirkin +Link: https://patch.msgid.link/20251111090828.23186-1-xuanzhuo@linux.alibaba.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/virtio_net.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 35bdbf1f45ee6..36b1bc0d56846 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -2632,22 +2632,28 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, + return; + } + +- /* 1. Save the flags early, as the XDP program might overwrite them. ++ /* About the flags below: ++ * 1. Save the flags early, as the XDP program might overwrite them. + * These flags ensure packets marked as VIRTIO_NET_HDR_F_DATA_VALID + * stay valid after XDP processing. + * 2. XDP doesn't work with partially checksummed packets (refer to + * virtnet_xdp_set()), so packets marked as + * VIRTIO_NET_HDR_F_NEEDS_CSUM get dropped during XDP processing. + */ +- flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + +- if (vi->mergeable_rx_bufs) ++ if (vi->mergeable_rx_bufs) { ++ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit, + stats); +- else if (vi->big_packets) ++ } else if (vi->big_packets) { ++ void *p = page_address((struct page *)buf); ++ ++ flags = ((struct virtio_net_common_hdr *)p)->hdr.flags; + skb = receive_big(dev, vi, rq, buf, len, stats); +- else ++ } else { ++ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, stats); ++ } + + if (unlikely(!skb)) + return; +-- +2.51.0 + diff --git a/queue-6.17/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch b/queue-6.17/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch new file mode 100644 index 0000000000..48790b6b70 --- /dev/null +++ b/queue-6.17/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch @@ -0,0 +1,53 @@ +From 6550220f791a341056cc6a756e5f277b4bb46777 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Nov 2025 09:39:57 +0100 +Subject: wifi: ath11k: zero init info->status in wmi_process_mgmt_tx_comp() + +From: Nicolas Escande + +[ Upstream commit 9065b968752334f972e0d48e50c4463a172fc2a7 ] + +When reporting tx completion using ieee80211_tx_status_xxx() family of +functions, the status part of the struct ieee80211_tx_info nested in the +skb is used to report things like transmit rates & retry count to mac80211 + +On the TX data path, this is correctly memset to 0 before calling +ieee80211_tx_status_ext(), but on the tx mgmt path this was not done. + +This leads to mac80211 treating garbage values as valid transmit counters +(like tx retries for example) and accounting them as real statistics that +makes their way to userland via station dump. + +The same issue was resolved in ath12k by commit 9903c0986f78 ("wifi: +ath12k: Add memset and update default rate value in wmi tx completion") + +Tested-on: QCN9074 PCI WLAN.HK.2.9.0.1-01977-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20251104083957.717825-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/wmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 0491e3fd6b5e1..e3b444333deed 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5961,6 +5961,9 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); ++ memset(&info->status, 0, sizeof(info->status)); ++ info->status.rates[0].idx = -1; ++ + if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && + !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; +-- +2.51.0 + diff --git a/queue-6.17/wifi-iwlwifi-mld-always-take-beacon-ies-in-link-grad.patch b/queue-6.17/wifi-iwlwifi-mld-always-take-beacon-ies-in-link-grad.patch new file mode 100644 index 0000000000..1d35f113ba --- /dev/null +++ b/queue-6.17/wifi-iwlwifi-mld-always-take-beacon-ies-in-link-grad.patch @@ -0,0 +1,71 @@ +From 2fc407a45f4ccbfa7644cd4532b14bd3030da409 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:57:00 +0200 +Subject: wifi: iwlwifi: mld: always take beacon ies in link grading + +From: Miri Korenblit + +[ Upstream commit 1a222625b468effd13d1ebb662c36a41c28a835a ] + +One of the factors of a link's grade is the channel load, which is +calculated from the AP's bss load element. +The current code takes this element from the beacon for an active link, +and from bss->ies for an inactive link. + +bss->ies is set to either the beacon's ies or to the probe response +ones, with preference to the probe response (meaning that if there was +even one probe response, the ies of it will be stored in bss->ies and +won't be overiden by the beacon ies). + +The probe response can be very old, i.e. from the connection time, +where a beacon is updated before each link selection (which is +triggered only after a passive scan). + +In such case, the bss load element in the probe response will not +include the channel load caused by the STA, where the beacon will. + +This will cause the inactive link to always have a lower channel +load, and therefore an higher grade than the active link's one. + +This causes repeated link switches, causing the throughput to drop. + +Fix this by always taking the ies from the beacon, as those are for +sure new. + +Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver") +Reviewed-by: Johannes Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110145652.b493dbb1853a.I058ba7309c84159f640cc9682d1bda56dd56a536@changeid +Signed-off-by: Miri Korenblit +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mld/link.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c +index 131190977d4b0..5b10e1e443178 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c ++++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c +@@ -701,18 +701,13 @@ static int + iwl_mld_get_chan_load_from_element(struct iwl_mld *mld, + struct ieee80211_bss_conf *link_conf) + { +- struct ieee80211_vif *vif = link_conf->vif; + const struct cfg80211_bss_ies *ies; + const struct element *bss_load_elem = NULL; + const struct ieee80211_bss_load_elem *bss_load; + + guard(rcu)(); + +- if (ieee80211_vif_link_active(vif, link_conf->link_id)) +- ies = rcu_dereference(link_conf->bss->beacon_ies); +- else +- ies = rcu_dereference(link_conf->bss->ies); +- ++ ies = rcu_dereference(link_conf->bss->beacon_ies); + if (ies) + bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD, + ies->data, ies->len); +-- +2.51.0 + diff --git a/queue-6.17/wifi-iwlwifi-mvm-fix-beacon-template-fixed-rate.patch b/queue-6.17/wifi-iwlwifi-mvm-fix-beacon-template-fixed-rate.patch new file mode 100644 index 0000000000..a5c5ae933b --- /dev/null +++ b/queue-6.17/wifi-iwlwifi-mvm-fix-beacon-template-fixed-rate.patch @@ -0,0 +1,81 @@ +From b78dcff69c41699a5d20983995601033b6425084 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Oct 2025 11:20:44 +0200 +Subject: wifi: iwlwifi: mvm: fix beacon template/fixed rate + +From: Johannes Berg + +[ Upstream commit 3592c0083fb29cca13cd9978b8844d58b4eff548 ] + +During the development of the rate changes, I evidently made +some changes that shouldn't have been there; beacon templates +with rate_n_flags are only in old versions, so no changes to +them should have been necessary, and evidently broke on some +devices. This also would have broken fixed (injection) rates, +it would seem. Restore the old handling of this. + +Fixes: dabc88cb3b78 ("wifi: iwlwifi: handle v3 rates") +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220558 +Reviewed-by: Benjamin Berg +Signed-off-by: Johannes Berg +Link: https://patch.msgid.link/20251008112044.3bb8ea849d8d.I90f4d2b2c1f62eaedaf304a61d2ab9e50c491c2d@changeid +Signed-off-by: Miri Korenblit +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 13 +++---------- + drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 12 +++++++++--- + 2 files changed, 12 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +index 8805ab344895a..0065c2ead56b1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +@@ -938,19 +938,12 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm, + + u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx) + { ++ u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx); + bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10; +- u16 flags, cck_flag; +- +- if (is_new_rate) { +- flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx); +- cck_flag = IWL_MAC_BEACON_CCK; +- } else { +- cck_flag = IWL_MAC_BEACON_CCK_V1; +- flags = iwl_fw_rate_idx_to_plcp(rate_idx); +- } + + if (rate_idx <= IWL_LAST_CCK_RATE) +- flags |= cck_flag; ++ flags |= is_new_rate ? IWL_MAC_BEACON_CCK ++ : IWL_MAC_BEACON_CCK_V1; + + return flags; + } +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +index 62da0132f3838..a62f5288dfd06 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +@@ -169,9 +169,15 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, + + u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx) + { +- return (rate_idx >= IWL_FIRST_OFDM_RATE ? +- rate_idx - IWL_FIRST_OFDM_RATE : +- rate_idx); ++ if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8) ++ /* In the new rate legacy rates are indexed: ++ * 0 - 3 for CCK and 0 - 7 for OFDM. ++ */ ++ return (rate_idx >= IWL_FIRST_OFDM_RATE ? ++ rate_idx - IWL_FIRST_OFDM_RATE : ++ rate_idx); ++ ++ return iwl_fw_rate_idx_to_plcp(rate_idx); + } + + u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac) +-- +2.51.0 + diff --git a/queue-6.17/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-6.17/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..14aa1e1f95 --- /dev/null +++ b/queue-6.17/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From 4f638436e2df59343159ab515838879d9940c972 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 59baca24aa6b9..dcf4b24cc39cf 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -5352,10 +5352,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 + diff --git a/queue-6.6/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch b/queue-6.6/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch new file mode 100644 index 0000000000..dce26b5bbd --- /dev/null +++ b/queue-6.6/acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch @@ -0,0 +1,49 @@ +From c385bc7c8d8a21b3aa9fbd14be2efcabe216b62c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:42 +0530 +Subject: ACPI: CPPC: Check _CPC validity for only the online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 6dd3b8a709a130a4d55c866af9804c81b8486d28 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function acpi_cpc_valid() checks for the validity of the +_CPC object for all the present CPUs. This breaks when the kernel is +booted with "nosmt=force". + +Hence check the validity of the _CPC objects of only the online CPUs. + +Fixes: 2aeca6bd0277 ("ACPI: CPPC: Check present CPUs for determining _CPC is valid") +Reported-by: Christopher Harris +Closes: https://lore.kernel.org/lkml/CAM+eXpdDT7KjLV0AxEwOLkSJ2QtrsvGvjA2cCHvt1d0k2_C4Cw@mail.gmail.com/ +Suggested-by: Mario Limonciello +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Tested-by: Chrisopher Harris +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-3-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 10d531427ba77..39f248be9611f 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -445,7 +445,7 @@ bool acpi_cpc_valid(void) + if (acpi_disabled) + return false; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + if (!cpc_ptr) + return false; +-- +2.51.0 + diff --git a/queue-6.6/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch b/queue-6.6/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch new file mode 100644 index 0000000000..b2c0ac2d4c --- /dev/null +++ b/queue-6.6/acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch @@ -0,0 +1,45 @@ +From bc12c0ed9f731afd8572d30afddf4deb477d1d7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:44 +0530 +Subject: ACPI: CPPC: Limit perf ctrs in PCC check only to online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 0fce75870666b46b700cfbd3216380b422f975da ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPU via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_perf_ctrs_in_pcc() checks if the CPPC +perf-ctrs are in a PCC region for all the present CPUs, which breaks +when the kernel is booted with "nosmt=force". + +Hence, limit the check only to the online CPUs. + +Fixes: ae2df912d1a5 ("ACPI: CPPC: Disable FIE if registers in PCC regions") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-5-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 6e579be36a1eb..888c7838579a8 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -1368,7 +1368,7 @@ bool cppc_perf_ctrs_in_pcc(void) + { + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + struct cpc_register_resource *ref_perf_reg; + struct cpc_desc *cpc_desc; + +-- +2.51.0 + diff --git a/queue-6.6/acpi-cppc-perform-fast-check-switch-only-for-online-.patch b/queue-6.6/acpi-cppc-perform-fast-check-switch-only-for-online-.patch new file mode 100644 index 0000000000..0d82fa700d --- /dev/null +++ b/queue-6.6/acpi-cppc-perform-fast-check-switch-only-for-online-.patch @@ -0,0 +1,45 @@ +From 2cdf07510768aaf87bd57de54860de5701ab207e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 13:11:43 +0530 +Subject: ACPI: CPPC: Perform fast check switch only for online CPUs + +From: Gautham R. Shenoy + +[ Upstream commit 8821c8e80a65bc4eb73daf63b34aac6b8ad69461 ] + +per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online +CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> +acpi_cppc_processor_probe(). + +However the function cppc_allow_fast_switch() checks for the validity +of the _CPC object for all the present CPUs. This breaks when the +kernel is booted with "nosmt=force". + +Check fast_switch capability only on online CPUs + +Fixes: 15eece6c5b05 ("ACPI: CPPC: Fix NULL pointer dereference when nosmp is used") +Reviewed-by: "Mario Limonciello (AMD) (kernel.org)" +Signed-off-by: Gautham R. Shenoy +Link: https://patch.msgid.link/20251107074145.2340-4-gautham.shenoy@amd.com +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index 39f248be9611f..6e579be36a1eb 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -461,7 +461,7 @@ bool cppc_allow_fast_switch(void) + struct cpc_desc *cpc_ptr; + int cpu; + +- for_each_present_cpu(cpu) { ++ for_each_online_cpu(cpu) { + cpc_ptr = per_cpu(cpc_desc_ptr, cpu); + desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF]; + if (!CPC_IN_SYSTEM_MEMORY(desired_reg) && +-- +2.51.0 + diff --git a/queue-6.6/af_unix-initialise-scc_index-in-unix_add_edge.patch b/queue-6.6/af_unix-initialise-scc_index-in-unix_add_edge.patch new file mode 100644 index 0000000000..679f156df1 --- /dev/null +++ b/queue-6.6/af_unix-initialise-scc_index-in-unix_add_edge.patch @@ -0,0 +1,139 @@ +From d2ea2f960a58f5a9cfcd92e25ee20ba26c74372e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 02:52:22 +0000 +Subject: af_unix: Initialise scc_index in unix_add_edge(). + +From: Kuniyuki Iwashima + +[ Upstream commit 60e6489f8e3b086bd1130ad4450a2c112e863791 ] + +Quang Le reported that the AF_UNIX GC could garbage-collect a +receive queue of an alive in-flight socket, with a nice repro. + +The repro consists of three stages. + + 1) + 1-a. Create a single cyclic reference with many sockets + 1-b. close() all sockets + 1-c. Trigger GC + + 2) + 2-a. Pass sk-A to an embryo sk-B + 2-b. Pass sk-X to sk-X + 2-c. Trigger GC + + 3) + 3-a. accept() the embryo sk-B + 3-b. Pass sk-B to sk-C + 3-c. close() the in-flight sk-A + 3-d. Trigger GC + +As of 2-c, sk-A and sk-X are linked to unix_unvisited_vertices, +and unix_walk_scc() groups them into two different SCCs: + + unix_sk(sk-A)->vertex->scc_index = 2 (UNIX_VERTEX_INDEX_START) + unix_sk(sk-X)->vertex->scc_index = 3 + +Once GC completes, unix_graph_grouped is set to true. +Also, unix_graph_maybe_cyclic is set to true due to sk-X's +cyclic self-reference, which makes close() trigger GC. + +At 3-b, unix_add_edge() allocates unix_sk(sk-B)->vertex and +links it to unix_unvisited_vertices. + +unix_update_graph() is called at 3-a. and 3-b., but neither +unix_graph_grouped nor unix_graph_maybe_cyclic is changed +because both sk-B's listener and sk-C are not in-flight. + +3-c decrements sk-A's file refcnt to 1. + +Since unix_graph_grouped is true at 3-d, unix_walk_scc_fast() +is finally called and iterates 3 sockets sk-A, sk-B, and sk-X: + + sk-A -> sk-B (-> sk-C) + sk-X -> sk-X + +This is totally fine. All of them are not yet close()d and +should be grouped into different SCCs. + +However, unix_vertex_dead() misjudges that sk-A and sk-B are +in the same SCC and sk-A is dead. + + unix_sk(sk-A)->scc_index == unix_sk(sk-B)->scc_index <-- Wrong! + && + sk-A's file refcnt == unix_sk(sk-A)->vertex->out_degree + ^-- 1 in-flight count for sk-B + -> sk-A is dead !? + +The problem is that unix_add_edge() does not initialise scc_index. + +Stage 1) is used for heap spraying, making a newly allocated +vertex have vertex->scc_index == 2 (UNIX_VERTEX_INDEX_START) +set by unix_walk_scc() at 1-c. + +Let's track the max SCC index from the previous unix_walk_scc() +call and assign the max + 1 to a new vertex's scc_index. + +This way, we can continue to avoid Tarjan's algorithm while +preventing misjudgments. + +Fixes: ad081928a8b0 ("af_unix: Avoid Tarjan's algorithm if unnecessary.") +Reported-by: Quang Le +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20251109025233.3659187-1-kuniyu@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/garbage.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 0068e758be4dd..66fd606c43f45 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -136,6 +136,7 @@ enum unix_vertex_index { + }; + + static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1; ++static unsigned long unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + { +@@ -144,6 +145,7 @@ static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge) + if (!vertex) { + vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry); + vertex->index = unix_vertex_unvisited_index; ++ vertex->scc_index = ++unix_vertex_max_scc_index; + vertex->out_degree = 0; + INIT_LIST_HEAD(&vertex->edges); + INIT_LIST_HEAD(&vertex->scc_entry); +@@ -480,10 +482,15 @@ static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_inde + scc_dead = unix_vertex_dead(v); + } + +- if (scc_dead) ++ if (scc_dead) { + unix_collect_skb(&scc, hitlist); +- else if (!unix_graph_maybe_cyclic) +- unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } else { ++ if (unix_vertex_max_scc_index < vertex->scc_index) ++ unix_vertex_max_scc_index = vertex->scc_index; ++ ++ if (!unix_graph_maybe_cyclic) ++ unix_graph_maybe_cyclic = unix_scc_cyclic(&scc); ++ } + + list_del(&scc); + } +@@ -498,6 +505,7 @@ static void unix_walk_scc(struct sk_buff_head *hitlist) + unsigned long last_index = UNIX_VERTEX_INDEX_START; + + unix_graph_maybe_cyclic = false; ++ unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START; + + /* Visit every vertex exactly once. + * __unix_walk_scc() moves visited vertices to unix_visited_vertices. +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch b/queue-6.6/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch new file mode 100644 index 0000000000..de63d46a44 --- /dev/null +++ b/queue-6.6/bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch @@ -0,0 +1,149 @@ +From 60b30019aa99bafdc4926aa4fd9104ee905a4307 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:49 +0200 +Subject: Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions + +From: Pauli Virtanen + +[ Upstream commit 98454bc812f3611551e4b1f81732da4aa7b9597e ] + +disconnect_all_peers() calls sleeping function (l2cap_chan_close) under +spinlock. Holding the lock doesn't actually do any good -- we work on a +local copy of the list, and the lock doesn't protect against peer->chan +having already been freed. + +Fix by taking refcounts of peer->chan instead. Clean up the code and +old comments a bit. + +Take devices_lock instead of RCU, because the kfree_rcu(); +l2cap_chan_put(); construct in chan_close_cb() does not guarantee +peer->chan is necessarily valid in RCU. + +Also take l2cap_chan_lock() which is required for l2cap_chan_close(). + +Log: (bluez 6lowpan-tester Client Connect - Disable) +------ +BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575 +... + +... +l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495) +... +? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809) +do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068) +------ + +Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 68 ++++++++++++++++++++++++++--------------- + 1 file changed, 43 insertions(+), 25 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 820376eee8bc3..e65d4754c94f4 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -52,6 +52,11 @@ static bool enable_6lowpan; + static struct l2cap_chan *listen_chan; + static DEFINE_MUTEX(set_lock); + ++enum { ++ LOWPAN_PEER_CLOSING, ++ LOWPAN_PEER_MAXBITS ++}; ++ + struct lowpan_peer { + struct list_head list; + struct rcu_head rcu; +@@ -60,6 +65,8 @@ struct lowpan_peer { + /* peer addresses in various formats */ + unsigned char lladdr[ETH_ALEN]; + struct in6_addr peer_addr; ++ ++ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS); + }; + + struct lowpan_btle_dev { +@@ -1013,41 +1020,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + static void disconnect_all_peers(void) + { + struct lowpan_btle_dev *entry; +- struct lowpan_peer *peer, *tmp_peer, *new_peer; +- struct list_head peers; +- +- INIT_LIST_HEAD(&peers); ++ struct lowpan_peer *peer; ++ int nchans; + +- /* We make a separate list of peers as the close_cb() will +- * modify the device peers list so it is better not to mess +- * with the same list at the same time. ++ /* l2cap_chan_close() cannot be called from RCU, and lock ordering ++ * chan->lock > devices_lock prevents taking write side lock, so copy ++ * then close. + */ + + rcu_read_lock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) ++ list_for_each_entry_rcu(peer, &entry->peers, list) ++ clear_bit(LOWPAN_PEER_CLOSING, peer->flags); ++ rcu_read_unlock(); + +- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { +- list_for_each_entry_rcu(peer, &entry->peers, list) { +- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); +- if (!new_peer) +- break; ++ do { ++ struct l2cap_chan *chans[32]; ++ int i; + +- new_peer->chan = peer->chan; +- INIT_LIST_HEAD(&new_peer->list); ++ nchans = 0; + +- list_add(&new_peer->list, &peers); +- } +- } ++ spin_lock(&devices_lock); + +- rcu_read_unlock(); ++ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) { ++ list_for_each_entry_rcu(peer, &entry->peers, list) { ++ if (test_and_set_bit(LOWPAN_PEER_CLOSING, ++ peer->flags)) ++ continue; + +- spin_lock(&devices_lock); +- list_for_each_entry_safe(peer, tmp_peer, &peers, list) { +- l2cap_chan_close(peer->chan, ENOENT); ++ l2cap_chan_hold(peer->chan); ++ chans[nchans++] = peer->chan; + +- list_del_rcu(&peer->list); +- kfree_rcu(peer, rcu); +- } +- spin_unlock(&devices_lock); ++ if (nchans >= ARRAY_SIZE(chans)) ++ goto done; ++ } ++ } ++ ++done: ++ spin_unlock(&devices_lock); ++ ++ for (i = 0; i < nchans; ++i) { ++ l2cap_chan_lock(chans[i]); ++ l2cap_chan_close(chans[i], ENOENT); ++ l2cap_chan_unlock(chans[i]); ++ l2cap_chan_put(chans[i]); ++ } ++ } while (nchans); + } + + struct set_enable { +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch b/queue-6.6/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch new file mode 100644 index 0000000000..ee493bcd55 --- /dev/null +++ b/queue-6.6/bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch @@ -0,0 +1,103 @@ +From aeda6762922ffdbdffc825d713f2bff71ad522b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:47 +0200 +Subject: Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type + confusion + +From: Pauli Virtanen + +[ Upstream commit b454505bf57a2e4f5d49951d4deb03730a9348d9 ] + +Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types, +e.g. debugfs "connect" command takes the former, and "disconnect" and +"connect" to already connected device take the latter. This is due to +using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le +which take different dst_type values. + +Fix address type passed to hci_conn_hash_lookup_le(). + +Retain the debugfs API difference between "connect" and "disconnect" +commands since it's been like this since 2015 and nobody apparently +complained. + +Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 50ed3a6b0b0c4..820376eee8bc3 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -956,10 +956,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void) + } + + static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, +- struct l2cap_conn **conn) ++ struct l2cap_conn **conn, bool disconnect) + { + struct hci_conn *hcon; + struct hci_dev *hdev; ++ int le_addr_type; + int n; + + n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", +@@ -970,13 +971,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, + if (n < 7) + return -EINVAL; + ++ if (disconnect) { ++ /* The "disconnect" debugfs command has used different address ++ * type constants than "connect" since 2015. Let's retain that ++ * for now even though it's obviously buggy... ++ */ ++ *addr_type += 1; ++ } ++ ++ switch (*addr_type) { ++ case BDADDR_LE_PUBLIC: ++ le_addr_type = ADDR_LE_DEV_PUBLIC; ++ break; ++ case BDADDR_LE_RANDOM: ++ le_addr_type = ADDR_LE_DEV_RANDOM; ++ break; ++ default: ++ return -EINVAL; ++ } ++ + /* The LE_PUBLIC address type is ignored because of BDADDR_ANY */ + hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC); + if (!hdev) + return -ENOENT; + + hci_dev_lock(hdev); +- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); ++ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + +@@ -1103,7 +1123,7 @@ static ssize_t lowpan_control_write(struct file *fp, + buf[buf_size] = '\0'; + + if (memcmp(buf, "connect ", 8) == 0) { +- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false); + if (ret == -EINVAL) + return ret; + +@@ -1140,7 +1160,7 @@ static ssize_t lowpan_control_write(struct file *fp, + } + + if (memcmp(buf, "disconnect ", 11) == 0) { +- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); ++ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true); + if (ret < 0) + return ret; + +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch b/queue-6.6/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch new file mode 100644 index 0000000000..732f9a0904 --- /dev/null +++ b/queue-6.6/bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch @@ -0,0 +1,54 @@ +From 66ab66f6cdfbdf58630153712486a832153f53a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:46 +0200 +Subject: Bluetooth: 6lowpan: reset link-local header on ipv6 recv path + +From: Pauli Virtanen + +[ Upstream commit 3b78f50918276ab28fb22eac9aa49401ac436a3b ] + +Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local +header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW + +Add missing skb_reset_mac_header() for uncompressed ipv6 RX path. + +For the compressed one, it is done in lowpan_header_decompress(). + +Log: (BlueZ 6lowpan-tester Client Recv Raw - Success) +------ +kernel BUG at net/core/skbuff.c:212! +Call Trace: + +... +packet_rcv (net/packet/af_packet.c:2152) +... + +__local_bh_enable_ip (kernel/softirq.c:407) +netif_rx (net/core/dev.c:5648) +chan_recv_cb (net/bluetooth/6lowpan.c:294 net/bluetooth/6lowpan.c:359) +------ + +Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices") +Reviewed-by: Paul Menzel +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/6lowpan.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c +index 13b752c169bed..50ed3a6b0b0c4 100644 +--- a/net/bluetooth/6lowpan.c ++++ b/net/bluetooth/6lowpan.c +@@ -288,6 +288,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, + local_skb->pkt_type = PACKET_HOST; + local_skb->dev = dev; + ++ skb_reset_mac_header(local_skb); + skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); + + if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) { +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch b/queue-6.6/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch new file mode 100644 index 0000000000..344a3545ad --- /dev/null +++ b/queue-6.6/bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch @@ -0,0 +1,65 @@ +From 76bd76c7fe0bc189b5d005d889ea46a823d845f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Nov 2025 14:28:41 -0500 +Subject: Bluetooth: btusb: reorder cleanup in btusb_disconnect to avoid UAF + +From: Raphael Pinsonneault-Thibeault + +[ Upstream commit 23d22f2f71768034d6ef86168213843fc49bf550 ] + +There is a KASAN: slab-use-after-free read in btusb_disconnect(). +Calling "usb_driver_release_interface(&btusb_driver, data->intf)" will +free the btusb data associated with the interface. The same data is +then used later in the function, hence the UAF. + +Fix by moving the accesses to btusb data to before the data is free'd. + +Reported-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=2fc81b50a4f8263a159b +Tested-by: syzbot+2fc81b50a4f8263a159b@syzkaller.appspotmail.com +Fixes: fd913ef7ce619 ("Bluetooth: btusb: Add out-of-band wakeup support") +Signed-off-by: Raphael Pinsonneault-Thibeault +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 23a9a221056a4..74d264b64b534 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -4713,6 +4713,11 @@ static void btusb_disconnect(struct usb_interface *intf) + + hci_unregister_dev(hdev); + ++ if (data->oob_wake_irq) ++ device_init_wakeup(&data->udev->dev, false); ++ if (data->reset_gpio) ++ gpiod_put(data->reset_gpio); ++ + if (intf == data->intf) { + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); +@@ -4723,17 +4728,11 @@ static void btusb_disconnect(struct usb_interface *intf) + usb_driver_release_interface(&btusb_driver, data->diag); + usb_driver_release_interface(&btusb_driver, data->intf); + } else if (intf == data->diag) { +- usb_driver_release_interface(&btusb_driver, data->intf); + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); ++ usb_driver_release_interface(&btusb_driver, data->intf); + } + +- if (data->oob_wake_irq) +- device_init_wakeup(&data->udev->dev, false); +- +- if (data->reset_gpio) +- gpiod_put(data->reset_gpio); +- + hci_free_dev(hdev); + } + +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch b/queue-6.6/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch new file mode 100644 index 0000000000..dbe01ddc3f --- /dev/null +++ b/queue-6.6/bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch @@ -0,0 +1,37 @@ +From 67b57fc4c2847e83e94de3ab508feb5470301f3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 20:29:48 +0200 +Subject: Bluetooth: L2CAP: export l2cap_chan_hold for modules + +From: Pauli Virtanen + +[ Upstream commit e060088db0bdf7932e0e3c2d24b7371c4c5b867c ] + +l2cap_chan_put() is exported, so export also l2cap_chan_hold() for +modules. + +l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c + +Signed-off-by: Pauli Virtanen +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index dabc07700197c..ad46112cb596b 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -497,6 +497,7 @@ void l2cap_chan_hold(struct l2cap_chan *c) + + kref_get(&c->kref); + } ++EXPORT_SYMBOL_GPL(l2cap_chan_hold); + + struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c) + { +-- +2.51.0 + diff --git a/queue-6.6/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch b/queue-6.6/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch new file mode 100644 index 0000000000..bd6def5bc9 --- /dev/null +++ b/queue-6.6/bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch @@ -0,0 +1,56 @@ +From d5b472fc11f45bd11bc559cb82f9c93a4d4d77de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Nov 2025 20:16:12 +0200 +Subject: Bluetooth: MGMT: cancel mesh send timer when hdev removed + +From: Pauli Virtanen + +[ Upstream commit 55fb52ffdd62850d667ebed842815e072d3c9961 ] + +mesh_send_done timer is not canceled when hdev is removed, which causes +crash if the timer triggers after hdev is gone. + +Cancel the timer when MGMT removes the hdev, like other MGMT timers. + +Should fix the BUG: sporadically seen by BlueZ test bot +(in "Mesh - Send cancel - 1" test). + +Log: +------ +BUG: KASAN: slab-use-after-free in run_timer_softirq+0x76b/0x7d0 +... +Freed by task 36: + kasan_save_stack+0x24/0x50 + kasan_save_track+0x14/0x30 + __kasan_save_free_info+0x3a/0x60 + __kasan_slab_free+0x43/0x70 + kfree+0x103/0x500 + device_release+0x9a/0x210 + kobject_put+0x100/0x1e0 + vhci_release+0x18b/0x240 +------ + +Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh") +Link: https://lore.kernel.org/linux-bluetooth/67364c09.0c0a0220.113cba.39ff@mx.google.com/ +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index 600518293b864..7de0a0d752629 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -9440,6 +9440,7 @@ void mgmt_index_removed(struct hci_dev *hdev) + cancel_delayed_work_sync(&hdev->discov_off); + cancel_delayed_work_sync(&hdev->service_cache); + cancel_delayed_work_sync(&hdev->rpa_expired); ++ cancel_delayed_work_sync(&hdev->mesh_send_done); + } + + void mgmt_power_on(struct hci_dev *hdev, int err) +-- +2.51.0 + diff --git a/queue-6.6/cifs-stop-writeback-extension-when-change-of-size-is.patch b/queue-6.6/cifs-stop-writeback-extension-when-change-of-size-is.patch new file mode 100644 index 0000000000..0308ee8c2d --- /dev/null +++ b/queue-6.6/cifs-stop-writeback-extension-when-change-of-size-is.patch @@ -0,0 +1,99 @@ +From 2a2b12769d424fa67a160a6ad598424521e67f4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Nov 2025 14:30:55 +0530 +Subject: cifs: stop writeback extension when change of size is detected + +From: Shyam Prasad N + +cifs_extend_writeback can pick up a folio on an extending write which +has been dirtied, but we have aclamp on the writeback to an i_size +local variable, which can cause short writes, yet mark the page as clean. +This can cause a data corruption. + +As an example, consider this scenario: +1. First write to the file happens offset 0 len 5k. +2. Writeback starts for the range (0-5k). +3. Writeback locks page 1 in cifs_writepages_begin. But does not lock +page 2 yet. +4. Page 2 is now written to by the next write, which extends the file +by another 5k. Page 2 and 3 are now marked dirty. +5. Now we reach cifs_extend_writeback, where we extend to include the +next folio (even if it should be partially written). We will mark page +2 for writeback. +6. But after exiting cifs_extend_writeback, we will clamp the +writeback to i_size, which was 5k when it started. So we write only 1k +bytes in page 2. +7. We still will now mark page 2 as flushed and mark it clean. So +remaining contents of page 2 will not be written to the server (hence +the hole in that gap, unless that range gets overwritten). + +With this patch, we will make sure not extend the writeback anymore +when a change in the file size is detected. + +This fix also changes the error handling of cifs_extend_writeback when +a folio get fails. We will now stop the extension when a folio get fails. + +Cc: stable@kernel.org # v6.3~v6.9 +Signed-off-by: Shyam Prasad N +Acked-by: David Howells +Reported-by: Mark A Whiting +Signed-off-by: Shyam Prasad N +Signed-off-by: Sasha Levin +--- + fs/smb/client/file.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index 1058066913dd6..1f0a53738426e 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -2747,8 +2747,10 @@ static void cifs_extend_writeback(struct address_space *mapping, + loff_t start, + int max_pages, + loff_t max_len, +- size_t *_len) ++ size_t *_len, ++ unsigned long long i_size) + { ++ struct inode *inode = mapping->host; + struct folio_batch batch; + struct folio *folio; + unsigned int nr_pages; +@@ -2779,7 +2781,7 @@ static void cifs_extend_writeback(struct address_space *mapping, + + if (!folio_try_get(folio)) { + xas_reset(xas); +- continue; ++ break; + } + nr_pages = folio_nr_pages(folio); + if (nr_pages > max_pages) { +@@ -2799,6 +2801,15 @@ static void cifs_extend_writeback(struct address_space *mapping, + xas_reset(xas); + break; + } ++ ++ /* if file size is changing, stop extending */ ++ if (i_size_read(inode) != i_size) { ++ folio_unlock(folio); ++ folio_put(folio); ++ xas_reset(xas); ++ break; ++ } ++ + if (!folio_test_dirty(folio) || + folio_test_writeback(folio)) { + folio_unlock(folio); +@@ -2934,7 +2945,8 @@ static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping, + + if (max_pages > 0) + cifs_extend_writeback(mapping, xas, &count, start, +- max_pages, max_len, &len); ++ max_pages, max_len, &len, ++ i_size); + } + } + len = min_t(unsigned long long, len, i_size - start); +-- +2.51.0 + diff --git a/queue-6.6/hsr-fix-supervision-frame-sending-on-hsrv0.patch b/queue-6.6/hsr-fix-supervision-frame-sending-on-hsrv0.patch new file mode 100644 index 0000000000..3991136d2e --- /dev/null +++ b/queue-6.6/hsr-fix-supervision-frame-sending-on-hsrv0.patch @@ -0,0 +1,50 @@ +From 415b90a67dcd50b38fd70278c8269b6fae5a8af0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:29:32 +0100 +Subject: hsr: Fix supervision frame sending on HSRv0 + +From: Felix Maurer + +[ Upstream commit 96a3a03abf3d8cc38cd9cb0d280235fbcf7c3f7f ] + +On HSRv0, no supervision frames were sent. The supervison frames were +generated successfully, but failed the check for a sufficiently long mac +header, i.e., at least sizeof(struct hsr_ethhdr), in hsr_fill_frame_info() +because the mac header only contained the ethernet header. + +Fix this by including the HSR header in the mac header when generating HSR +supervision frames. Note that the mac header now also includes the TLV +fields. This matches how we set the headers on rx and also the size of +struct hsrv0_ethhdr_sp. + +Reported-by: Hangbin Liu +Closes: https://lore.kernel.org/netdev/aMONxDXkzBZZRfE5@fedora/ +Fixes: 9cfb5e7f0ded ("net: hsr: fix hsr_init_sk() vs network/transport headers.") +Signed-off-by: Felix Maurer +Reviewed-by: Sebastian Andrzej Siewior +Tested-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/4354114fea9a642fe71f49aeeb6c6159d1d61840.1762876095.git.fmaurer@redhat.com +Tested-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index 5514b5bedc929..70e958caa956d 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -313,6 +313,9 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + } + + hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); ++ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); ++ skb_reset_mac_len(skb); ++ + set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf)); + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + +-- +2.51.0 + diff --git a/queue-6.6/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch b/queue-6.6/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch new file mode 100644 index 0000000000..d4161f5cf2 --- /dev/null +++ b/queue-6.6/net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch @@ -0,0 +1,39 @@ +From bb54828b79a9a3d235d352b424db16953bb22fa5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 10:14:21 +0800 +Subject: net: fec: correct rx_bytes statistic for the case SHIFT16 is set + +From: Wei Fang + +[ Upstream commit ad17e7e92a7c52ce70bb764813fcf99464f96903 ] + +Two additional bytes in front of each frame received into the RX FIFO if +SHIFT16 is set, so we need to subtract the extra two bytes from pkt_len +to correct the statistic of rx_bytes. + +Fixes: 3ac72b7b63d5 ("net: fec: align IP header in hardware") +Signed-off-by: Wei Fang +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20251106021421.2096585-1-wei.fang@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fec_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 64cd72c194783..ee0306ab97714 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1776,6 +1776,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_packets++; + pkt_len = fec16_to_cpu(bdp->cbd_datlen); + ndev->stats.rx_bytes += pkt_len; ++ if (fep->quirks & FEC_QUIRK_HAS_RACC) ++ ndev->stats.rx_bytes -= 2; + + index = fec_enet_get_bd_index(bdp, &rxq->bd); + page = rxq->rx_skb_info[index].page; +-- +2.51.0 + diff --git a/queue-6.6/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch b/queue-6.6/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch new file mode 100644 index 0000000000..bc31008111 --- /dev/null +++ b/queue-6.6/net-handshake-fix-memory-leak-in-tls_handshake_accep.patch @@ -0,0 +1,42 @@ +From cbc01ecc0d75ccb4017be497f586e95771572334 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 14:45:11 +0000 +Subject: net/handshake: Fix memory leak in tls_handshake_accept() + +From: Zilin Guan + +[ Upstream commit 3072f00bba764082fa41b3c3a2a7b013335353d2 ] + +In tls_handshake_accept(), a netlink message is allocated using +genlmsg_new(). In the error handling path, genlmsg_cancel() is called +to cancel the message construction, but the message itself is not freed. +This leads to a memory leak. + +Fix this by calling nlmsg_free() in the error path after genlmsg_cancel() +to release the allocated memory. + +Fixes: 2fd5532044a89 ("net/handshake: Add a kernel API for requesting a TLSv1.3 handshake") +Signed-off-by: Zilin Guan +Reviewed-by: Chuck Lever +Link: https://patch.msgid.link/20251106144511.3859535-1-zilin@seu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/handshake/tlshd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c +index bbfb4095ddd6b..06916a80cc130 100644 +--- a/net/handshake/tlshd.c ++++ b/net/handshake/tlshd.c +@@ -254,6 +254,7 @@ static int tls_handshake_accept(struct handshake_req *req, + + out_cancel: + genlmsg_cancel(msg, hdr); ++ nlmsg_free(msg); + out: + return ret; + } +-- +2.51.0 + diff --git a/queue-6.6/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch b/queue-6.6/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch new file mode 100644 index 0000000000..9965d299fa --- /dev/null +++ b/queue-6.6/net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch @@ -0,0 +1,45 @@ +From 212a54f8a59a23b9fa0579d979e0b669b2d3dff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Nov 2025 07:49:22 +0100 +Subject: net: mdio: fix resource leak in mdiobus_register_device() + +From: Buday Csaba + +[ Upstream commit e6ca8f533ed41129fcf052297718f417f021cc7d ] + +Fix a possible leak in mdiobus_register_device() when both a +reset-gpio and a reset-controller are present. +Clean up the already claimed reset-gpio, when the registration of +the reset-controller fails, so when an error code is returned, the +device retains its state before the registration attempt. + +Link: https://lore.kernel.org/all/20251106144603.39053c81@kernel.org/ +Fixes: 71dd6c0dff51 ("net: phy: add support for reset-controller") +Signed-off-by: Buday Csaba +Link: https://patch.msgid.link/4b419377f8dd7d2f63f919d0f74a336c734f8fff.1762584481.git.buday.csaba@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/mdio_bus.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index f1fac89721ed9..7da30a6752bee 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -81,8 +81,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev) + return err; + + err = mdiobus_register_reset(mdiodev); +- if (err) ++ if (err) { ++ gpiod_put(mdiodev->reset_gpio); ++ mdiodev->reset_gpio = NULL; + return err; ++ } + + /* Assert the reset signal */ + mdio_device_reset(mdiodev, 1); +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch b/queue-6.6/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch new file mode 100644 index 0000000000..824f03badd --- /dev/null +++ b/queue-6.6/net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch @@ -0,0 +1,58 @@ +From dfc242f9bbb0c1cdb8df5d2f376e1b12958bc0fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:51 +0200 +Subject: net/mlx5e: Fix maxrate wraparound in threshold between units + +From: Gal Pressman + +[ Upstream commit a7bf4d5063c7837096aab2853224eb23628514d9 ] + +The previous calculation used roundup() which caused an overflow for +rates between 25.5Gbps and 26Gbps. +For example, a rate of 25.6Gbps would result in using 100Mbps units with +value of 256, which would overflow the 8 bits field. + +Simplify the upper_limit_mbps calculation by removing the +unnecessary roundup, and adjust the comparison to use <= to correctly +handle the boundary condition. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-4-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 8705cffc747ff..5e388cd518be9 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -587,18 +587,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; +- __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB); ++ __u64 upper_limit_mbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); ++ upper_limit_mbps = 255 * MLX5E_100MB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { + max_bw_unit[i] = MLX5_BW_NO_LIMIT; + continue; + } +- if (maxrate->tc_maxrate[i] < upper_limit_mbps) { ++ if (maxrate->tc_maxrate[i] <= upper_limit_mbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5e-fix-potentially-misleading-debug-message.patch b/queue-6.6/net-mlx5e-fix-potentially-misleading-debug-message.patch new file mode 100644 index 0000000000..94e0c58505 --- /dev/null +++ b/queue-6.6/net-mlx5e-fix-potentially-misleading-debug-message.patch @@ -0,0 +1,62 @@ +From 114109c0f7fc8f840471d99219c410113e96f550 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:53 +0200 +Subject: net/mlx5e: Fix potentially misleading debug message + +From: Gal Pressman + +[ Upstream commit 9fcc2b6c10523f7e75db6387946c86fcf19dc97e ] + +Change the debug message to print the correct units instead of always +assuming Gbps, as the value can be in either 100 Mbps or 1 Gbps units. + +Fixes: 5da8bc3effb6 ("net/mlx5e: DCBNL, Add debug messages log") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-6-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index ca096d8bcca60..29e633e6dd3f0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -590,6 +590,19 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + __u64 upper_limit_mbps; + __u64 upper_limit_gbps; + int i; ++ struct { ++ int scale; ++ const char *units_str; ++ } units[] = { ++ [MLX5_100_MBPS_UNIT] = { ++ .scale = 100, ++ .units_str = "Mbps", ++ }, ++ [MLX5_GBPS_UNIT] = { ++ .scale = 1, ++ .units_str = "Gbps", ++ }, ++ }; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); +@@ -620,8 +633,9 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + } + + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { +- netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n", +- __func__, i, max_bw_value[i]); ++ netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i, ++ max_bw_value[i] * units[max_bw_unit[i]].scale, ++ units[max_bw_unit[i]].units_str); + } + + return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit); +-- +2.51.0 + diff --git a/queue-6.6/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch b/queue-6.6/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch new file mode 100644 index 0000000000..0413bcdebe --- /dev/null +++ b/queue-6.6/net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch @@ -0,0 +1,62 @@ +From 20ff333f1148e64a40fe5d90e31c17b77a0f2276 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 11:37:52 +0200 +Subject: net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps + +From: Gal Pressman + +[ Upstream commit 43b27d1bd88a4bce34ec2437d103acfae9655f9e ] + +Add validation to reject rates exceeding 255 Gbps that would overflow +the 8 bits max bandwidth field. + +Fixes: d8880795dabf ("net/mlx5e: Implement DCBNL IEEE max rate") +Signed-off-by: Gal Pressman +Reviewed-by: Nimrod Oren +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1762681073-1084058-5-git-send-email-tariqt@nvidia.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 5e388cd518be9..ca096d8bcca60 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -588,11 +588,13 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + u8 max_bw_value[IEEE_8021QAZ_MAX_TCS]; + u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS]; + __u64 upper_limit_mbps; ++ __u64 upper_limit_gbps; + int i; + + memset(max_bw_value, 0, sizeof(max_bw_value)); + memset(max_bw_unit, 0, sizeof(max_bw_unit)); + upper_limit_mbps = 255 * MLX5E_100MB; ++ upper_limit_gbps = 255 * MLX5E_1GB; + + for (i = 0; i <= mlx5_max_tc(mdev); i++) { + if (!maxrate->tc_maxrate[i]) { +@@ -604,10 +606,16 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev, + MLX5E_100MB); + max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1; + max_bw_unit[i] = MLX5_100_MBPS_UNIT; +- } else { ++ } else if (max_bw_value[i] <= upper_limit_gbps) { + max_bw_value[i] = div_u64(maxrate->tc_maxrate[i], + MLX5E_1GB); + max_bw_unit[i] = MLX5_GBPS_UNIT; ++ } else { ++ netdev_err(netdev, ++ "tc_%d maxrate %llu Kbps exceeds limit %llu\n", ++ i, maxrate->tc_maxrate[i], ++ upper_limit_gbps); ++ return -EINVAL; + } + } + +-- +2.51.0 + diff --git a/queue-6.6/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch b/queue-6.6/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch new file mode 100644 index 0000000000..452deca1f0 --- /dev/null +++ b/queue-6.6/net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch @@ -0,0 +1,59 @@ +From 383e81d69ad2a8f78f159e86ae3095306193d426 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:35 +0530 +Subject: net: sched: act_connmark: initialize struct tc_ife to fix kernel leak + +From: Ranganath V N + +[ Upstream commit 62b656e43eaeae445a39cd8021a4f47065af4389 ] + +In tcf_connmark_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: 22a5dc0e5e3e ("net: sched: Introduce connmark action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-2-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_connmark.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 31719a113ed31..d90a2fa5966b7 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -195,13 +195,15 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); + const struct tcf_connmark_parms *parms; +- struct tc_connmark opt = { +- .index = ci->tcf_index, +- .refcnt = refcount_read(&ci->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, +- }; ++ struct tc_connmark opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ci->tcf_index; ++ opt.refcnt = refcount_read(&ci->tcf_refcnt) - ref; ++ opt.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind; ++ + rcu_read_lock(); + parms = rcu_dereference(ci->parms); + +-- +2.51.0 + diff --git a/queue-6.6/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch b/queue-6.6/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch new file mode 100644 index 0000000000..4e5968aa9a --- /dev/null +++ b/queue-6.6/net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch @@ -0,0 +1,70 @@ +From 2647a90f7dab248e33ea28ebbb5fa1652855f9e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 14:43:36 +0530 +Subject: net: sched: act_ife: initialize struct tc_ife to fix KMSAN + kernel-infoleak + +From: Ranganath V N + +[ Upstream commit ce50039be49eea9b4cd8873ca6eccded1b4a130a ] + +Fix a KMSAN kernel-infoleak detected by the syzbot . + +[net?] KMSAN: kernel-infoleak in __skb_datagram_iter + +In tcf_ife_dump(), the variable 'opt' was partially initialized using a +designatied initializer. While the padding bytes are reamined +uninitialized. nla_put() copies the entire structure into a +netlink message, these uninitialized bytes leaked to userspace. + +Initialize the structure with memset before assigning its fields +to ensure all members and padding are cleared prior to beign copied. + +This change silences the KMSAN report and prevents potential information +leaks from the kernel memory. + +This fix has been tested and validated by syzbot. This patch closes the +bug reported at the following syzkaller link and ensures no infoleak. + +Reported-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=0c85cae3350b7d486aee +Tested-by: syzbot+0c85cae3350b7d486aee@syzkaller.appspotmail.com +Fixes: ef6980b6becb ("introduce IFE action") +Signed-off-by: Ranganath V N +Reviewed-by: Eric Dumazet +Link: https://patch.msgid.link/20251109091336.9277-3-vnranganath.20@gmail.com +Acked-by: Cong Wang +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/act_ife.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c +index bc7611b0744c4..431921204f660 100644 +--- a/net/sched/act_ife.c ++++ b/net/sched/act_ife.c +@@ -644,13 +644,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind, + unsigned char *b = skb_tail_pointer(skb); + struct tcf_ife_info *ife = to_ife(a); + struct tcf_ife_params *p; +- struct tc_ife opt = { +- .index = ife->tcf_index, +- .refcnt = refcount_read(&ife->tcf_refcnt) - ref, +- .bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, +- }; ++ struct tc_ife opt; + struct tcf_t t; + ++ memset(&opt, 0, sizeof(opt)); ++ ++ opt.index = ife->tcf_index, ++ opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref, ++ opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind, ++ + spin_lock_bh(&ife->tcf_lock); + opt.action = ife->tcf_action; + p = rcu_dereference_protected(ife->params, +-- +2.51.0 + diff --git a/queue-6.6/net-smc-fix-mismatch-between-clc-header-and-proposal.patch b/queue-6.6/net-smc-fix-mismatch-between-clc-header-and-proposal.patch new file mode 100644 index 0000000000..737035ff19 --- /dev/null +++ b/queue-6.6/net-smc-fix-mismatch-between-clc-header-and-proposal.patch @@ -0,0 +1,55 @@ +From d25dbc79bf0592e41546d87cc49126d733bf4d3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 10:40:29 +0800 +Subject: net/smc: fix mismatch between CLC header and proposal +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: D. Wythe + +[ Upstream commit ec33f2e5a2d0dbbfd71435209aee812fdc9369b8 ] + +The current CLC proposal message construction uses a mix of +`ini->smc_type_v1/v2` and `pclc_base->hdr.typev1/v2` to decide whether +to include optional extensions (IPv6 prefix extension for v1, and v2 +extension). This leads to a critical inconsistency: when +`smc_clc_prfx_set()` fails - for example, in IPv6-only environments with +only link-local addresses, or when the local IP address and the outgoing +interface’s network address are not in the same subnet. + +As a result, the proposal message is assembled using the stale +`ini->smc_type_v1` value—causing the IPv6 prefix extension to be +included even though the header indicates v1 is not supported. +The peer then receives a malformed CLC proposal where the header type +does not match the payload, and immediately resets the connection. + +The fix ensures consistency between the CLC header flags and the actual +payload by synchronizing `ini->smc_type_v1` with `pclc_base->hdr.typev1` +when prefix setup fails. + +Fixes: 8c3dca341aea ("net/smc: build and send V2 CLC proposal") +Signed-off-by: D. Wythe +Reviewed-by: Alexandra Winter +Link: https://patch.msgid.link/20251107024029.88753-1-alibuda@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/smc/smc_clc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c +index 4f485b9b31b28..2f748226f1433 100644 +--- a/net/smc/smc_clc.c ++++ b/net/smc/smc_clc.c +@@ -883,6 +883,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini) + return SMC_CLC_DECL_CNFERR; + } + pclc_base->hdr.typev1 = SMC_TYPE_N; ++ ini->smc_type_v1 = SMC_TYPE_N; + } else { + pclc_base->iparea_offset = htons(sizeof(*pclc_smcd)); + plen += sizeof(*pclc_prfx) + +-- +2.51.0 + diff --git a/queue-6.6/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch b/queue-6.6/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch new file mode 100644 index 0000000000..ba5f3f842b --- /dev/null +++ b/queue-6.6/net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch @@ -0,0 +1,100 @@ +From c7eedb2c0b8379f1b8ae26fbfdbc0a5af895260a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 09:01:54 +0000 +Subject: net_sched: act_connmark: use RCU in tcf_connmark_dump() + +From: Eric Dumazet + +[ Upstream commit 0d752877705c0252ef2726e4c63c5573f048951c ] + +Also storing tcf_action into struct tcf_connmark_parms +makes sure there is no discrepancy in tcf_connmark_act(). + +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250709090204.797558-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 62b656e43eae ("net: sched: act_connmark: initialize struct tc_ife to fix kernel leak") +Signed-off-by: Sasha Levin +--- + include/net/tc_act/tc_connmark.h | 1 + + net/sched/act_connmark.c | 18 ++++++++++-------- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h +index e8dd77a967480..a5ce83f3eea4b 100644 +--- a/include/net/tc_act/tc_connmark.h ++++ b/include/net/tc_act/tc_connmark.h +@@ -7,6 +7,7 @@ + struct tcf_connmark_parms { + struct net *net; + u16 zone; ++ int action; + struct rcu_head rcu; + }; + +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 0d7aee8933c5f..31719a113ed31 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -88,7 +88,7 @@ TC_INDIRECT_SCOPE int tcf_connmark_act(struct sk_buff *skb, + /* using overlimits stats to count how many packets marked */ + tcf_action_inc_overlimit_qstats(&ca->common); + out: +- return READ_ONCE(ca->tcf_action); ++ return parms->action; + } + + static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = { +@@ -167,6 +167,8 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + if (err < 0) + goto release_idr; + ++ nparms->action = parm->action; ++ + spin_lock_bh(&ci->tcf_lock); + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); + oparms = rcu_replace_pointer(ci->parms, nparms, lockdep_is_held(&ci->tcf_lock)); +@@ -190,20 +192,20 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, + static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + int bind, int ref) + { ++ const struct tcf_connmark_info *ci = to_connmark(a); + unsigned char *b = skb_tail_pointer(skb); +- struct tcf_connmark_info *ci = to_connmark(a); ++ const struct tcf_connmark_parms *parms; + struct tc_connmark opt = { + .index = ci->tcf_index, + .refcnt = refcount_read(&ci->tcf_refcnt) - ref, + .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind, + }; +- struct tcf_connmark_parms *parms; + struct tcf_t t; + +- spin_lock_bh(&ci->tcf_lock); +- parms = rcu_dereference_protected(ci->parms, lockdep_is_held(&ci->tcf_lock)); ++ rcu_read_lock(); ++ parms = rcu_dereference(ci->parms); + +- opt.action = ci->tcf_action; ++ opt.action = parms->action; + opt.zone = parms->zone; + if (nla_put(skb, TCA_CONNMARK_PARMS, sizeof(opt), &opt)) + goto nla_put_failure; +@@ -212,12 +214,12 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a, + if (nla_put_64bit(skb, TCA_CONNMARK_TM, sizeof(t), &t, + TCA_CONNMARK_PAD)) + goto nla_put_failure; +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + + return skb->len; + + nla_put_failure: +- spin_unlock_bh(&ci->tcf_lock); ++ rcu_read_unlock(); + nlmsg_trim(skb, b); + return -1; + } +-- +2.51.0 + diff --git a/queue-6.6/net_sched-limit-try_bulk_dequeue_skb-batches.patch b/queue-6.6/net_sched-limit-try_bulk_dequeue_skb-batches.patch new file mode 100644 index 0000000000..74307923a9 --- /dev/null +++ b/queue-6.6/net_sched-limit-try_bulk_dequeue_skb-batches.patch @@ -0,0 +1,143 @@ +From 30357356860a72801a08c556a39098610083439d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Nov 2025 16:12:15 +0000 +Subject: net_sched: limit try_bulk_dequeue_skb() batches +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric Dumazet + +[ Upstream commit 0345552a653ce5542affeb69ac5aa52177a5199b ] + +After commit 100dfa74cad9 ("inet: dev_queue_xmit() llist adoption") +I started seeing many qdisc requeues on IDPF under high TX workload. + +$ tc -s qd sh dev eth1 handle 1: ; sleep 1; tc -s qd sh dev eth1 handle 1: +qdisc mq 1: root + Sent 43534617319319 bytes 268186451819 pkt (dropped 0, overlimits 0 requeues 3532840114) + backlog 1056Kb 6675p requeues 3532840114 +qdisc mq 1: root + Sent 43554665866695 bytes 268309964788 pkt (dropped 0, overlimits 0 requeues 3537737653) + backlog 781164b 4822p requeues 3537737653 + +This is caused by try_bulk_dequeue_skb() being only limited by BQL budget. + +perf record -C120-239 -e qdisc:qdisc_dequeue sleep 1 ; perf script +... + netperf 75332 [146] 2711.138269: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1292 skbaddr=0xff378005a1e9f200 + netperf 75332 [146] 2711.138953: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1213 skbaddr=0xff378004d607a500 + netperf 75330 [144] 2711.139631: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1233 skbaddr=0xff3780046be20100 + netperf 75333 [147] 2711.140356: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1093 skbaddr=0xff37800514845b00 + netperf 75337 [151] 2711.141037: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1353 skbaddr=0xff37800460753300 + netperf 75337 [151] 2711.141877: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1367 skbaddr=0xff378004e72c7b00 + netperf 75330 [144] 2711.142643: qdisc:qdisc_dequeue: dequeue ifindex=5 qdisc handle=0x80150000 parent=0x10013 txq_state=0x0 packets=1202 skbaddr=0xff3780045bd60000 +... + +This is bad because : + +1) Large batches hold one victim cpu for a very long time. + +2) Driver often hit their own TX ring limit (all slots are used). + +3) We call dev_requeue_skb() + +4) Requeues are using a FIFO (q->gso_skb), breaking qdisc ability to + implement FQ or priority scheduling. + +5) dequeue_skb() gets packets from q->gso_skb one skb at a time + with no xmit_more support. This is causing many spinlock games + between the qdisc and the device driver. + +Requeues were supposed to be very rare, lets keep them this way. + +Limit batch sizes to /proc/sys/net/core/dev_weight (default 64) as +__qdisc_run() was designed to use. + +Fixes: 5772e9a3463b ("qdisc: bulk dequeue support for qdiscs with TCQ_F_ONETXQUEUE") +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Acked-by: Jesper Dangaard Brouer +Link: https://patch.msgid.link/20251109161215.2574081-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index b51af871a621c..1b51b3038b4bd 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -178,9 +178,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) + static void try_bulk_dequeue_skb(struct Qdisc *q, + struct sk_buff *skb, + const struct netdev_queue *txq, +- int *packets) ++ int *packets, int budget) + { + int bytelimit = qdisc_avail_bulklimit(txq) - skb->len; ++ int cnt = 0; + + while (bytelimit > 0) { + struct sk_buff *nskb = q->dequeue(q); +@@ -191,8 +192,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q, + bytelimit -= nskb->len; /* covers GSO len */ + skb->next = nskb; + skb = nskb; +- (*packets)++; /* GSO counts as one pkt */ ++ if (++cnt >= budget) ++ break; + } ++ (*packets) += cnt; + skb_mark_not_on_list(skb); + } + +@@ -226,7 +229,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q, + * A requeued skb (via q->gso_skb) can also be a SKB list. + */ + static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, +- int *packets) ++ int *packets, int budget) + { + const struct netdev_queue *txq = q->dev_queue; + struct sk_buff *skb = NULL; +@@ -293,7 +296,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, + if (skb) { + bulk: + if (qdisc_may_bulk(q)) +- try_bulk_dequeue_skb(q, skb, txq, packets); ++ try_bulk_dequeue_skb(q, skb, txq, packets, budget); + else + try_bulk_dequeue_skb_slow(q, skb, packets); + } +@@ -385,7 +388,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, + * >0 - queue is not empty. + * + */ +-static inline bool qdisc_restart(struct Qdisc *q, int *packets) ++static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget) + { + spinlock_t *root_lock = NULL; + struct netdev_queue *txq; +@@ -394,7 +397,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets) + bool validate; + + /* Dequeue packet */ +- skb = dequeue_skb(q, &validate, packets); ++ skb = dequeue_skb(q, &validate, packets, budget); + if (unlikely(!skb)) + return false; + +@@ -412,7 +415,7 @@ void __qdisc_run(struct Qdisc *q) + int quota = READ_ONCE(dev_tx_weight); + int packets; + +- while (qdisc_restart(q, &packets)) { ++ while (qdisc_restart(q, &packets, quota)) { + quota -= packets; + if (quota <= 0) { + if (q->flags & TCQ_F_NOLOCK) +-- +2.51.0 + diff --git a/queue-6.6/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch b/queue-6.6/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch new file mode 100644 index 0000000000..95f04a3645 --- /dev/null +++ b/queue-6.6/sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch @@ -0,0 +1,86 @@ +From 5a52dba8bcb12fcabeb2662da0a952a7e6ceaf02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 11:10:54 +0000 +Subject: sctp: prevent possible shift-out-of-bounds in + sctp_transport_update_rto + +From: Eric Dumazet + +[ Upstream commit 1534ff77757e44bcc4b98d0196bc5c0052fce5fa ] + +syzbot reported a possible shift-out-of-bounds [1] + +Blamed commit added rto_alpha_max and rto_beta_max set to 1000. + +It is unclear if some sctp users are setting very large rto_alpha +and/or rto_beta. + +In order to prevent user regression, perform the test at run time. + +Also add READ_ONCE() annotations as sysctl values can change under us. + +[1] + +UBSAN: shift-out-of-bounds in net/sctp/transport.c:509:41 +shift exponent 64 is too large for 32-bit type 'unsigned int' +CPU: 0 UID: 0 PID: 16704 Comm: syz.2.2320 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/02/2025 +Call Trace: + + __dump_stack lib/dump_stack.c:94 [inline] + dump_stack_lvl+0x16c/0x1f0 lib/dump_stack.c:120 + ubsan_epilogue lib/ubsan.c:233 [inline] + __ubsan_handle_shift_out_of_bounds+0x27f/0x420 lib/ubsan.c:494 + sctp_transport_update_rto.cold+0x1c/0x34b net/sctp/transport.c:509 + sctp_check_transmitted+0x11c4/0x1c30 net/sctp/outqueue.c:1502 + sctp_outq_sack+0x4ef/0x1b20 net/sctp/outqueue.c:1338 + sctp_cmd_process_sack net/sctp/sm_sideeffect.c:840 [inline] + sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1372 [inline] + +Fixes: b58537a1f562 ("net: sctp: fix permissions for rto_alpha and rto_beta knobs") +Reported-by: syzbot+f8c46c8b2b7f6e076e99@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c81ae.050a0220.3d0d33.014e.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Cc: Daniel Borkmann +Acked-by: Xin Long +Link: https://patch.msgid.link/20251106111054.3288127-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/transport.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 31eca29b6cfbf..abb44c0ac1a0b 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -495,6 +495,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + + if (tp->rttvar || tp->srtt) { + struct net *net = tp->asoc->base.net; ++ unsigned int rto_beta, rto_alpha; + /* 6.3.1 C3) When a new RTT measurement R' is made, set + * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| + * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' +@@ -506,10 +507,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) + * For example, assuming the default value of RTO.Alpha of + * 1/8, rto_alpha would be expressed as 3. + */ +- tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) +- + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta); +- tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) +- + (rtt >> net->sctp.rto_alpha); ++ rto_beta = READ_ONCE(net->sctp.rto_beta); ++ if (rto_beta < 32) ++ tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta) ++ + (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta); ++ rto_alpha = READ_ONCE(net->sctp.rto_alpha); ++ if (rto_alpha < 32) ++ tp->srtt = tp->srtt - (tp->srtt >> rto_alpha) ++ + (rtt >> rto_alpha); + } else { + /* 6.3.1 C2) When the first RTT measurement R is made, set + * SRTT <- R, RTTVAR <- R/2. +-- +2.51.0 + diff --git a/queue-6.6/selftests-net-local_termination-wait-for-interfaces-.patch b/queue-6.6/selftests-net-local_termination-wait-for-interfaces-.patch new file mode 100644 index 0000000000..1bf1e2f28b --- /dev/null +++ b/queue-6.6/selftests-net-local_termination-wait-for-interfaces-.patch @@ -0,0 +1,48 @@ +From 9b04f3512a91858667fefa89dbb20cf8056343f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Nov 2025 17:12:09 +0100 +Subject: selftests: net: local_termination: Wait for interfaces to come up + +From: Alexander Sverdlin + +[ Upstream commit 57531b3416448d1ced36a2a974a4085ec43d57b0 ] + +It seems that most of the tests prepare the interfaces once before the test +run (setup_prepare()), rely on setup_wait() to wait for link and only then +run the test(s). + +local_termination brings the physical interfaces down and up during test +run but never wait for them to come up. If the auto-negotiation takes +some seconds, first test packets are being lost, which leads to +false-negative test results. + +Use setup_wait() in run_test() to make sure auto-negotiation has been +completed after all simple_if_init() calls on physical interfaces and test +packets will not be lost because of the race against link establishment. + +Fixes: 90b9566aa5cd3f ("selftests: forwarding: add a test for local_termination.sh") +Reviewed-by: Vladimir Oltean +Signed-off-by: Alexander Sverdlin +Link: https://patch.msgid.link/20251106161213.459501-1-alexander.sverdlin@siemens.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/forwarding/local_termination.sh | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/net/forwarding/local_termination.sh b/tools/testing/selftests/net/forwarding/local_termination.sh +index 9b5a63519b949..6cde61f10fd0e 100755 +--- a/tools/testing/selftests/net/forwarding/local_termination.sh ++++ b/tools/testing/selftests/net/forwarding/local_termination.sh +@@ -108,6 +108,8 @@ run_test() + local smac=$(mac_get $h1) + local rcv_dmac=$(mac_get $rcv_if_name) + ++ setup_wait ++ + tcpdump_start $rcv_if_name + + mc_route_prepare $h1 +-- +2.51.0 + diff --git a/queue-6.6/series b/queue-6.6/series index 3fbc1596ea..085f4fd3bb 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -391,3 +391,32 @@ hid-quirks-add-always_poll-quirk-for-vrs-r295-steeri.patch smb-server-fix-possible-memory-leak-in-smb2_read.patch smb-server-fix-possible-refcount-leak-in-smb2_sess_s.patch asoc-max98090-91-fixed-max98091-alsa-widget-powering.patch +wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch +selftests-net-local_termination-wait-for-interfaces-.patch +net-fec-correct-rx_bytes-statistic-for-the-case-shif.patch +bluetooth-mgmt-cancel-mesh-send-timer-when-hdev-remo.patch +bluetooth-btusb-reorder-cleanup-in-btusb_disconnect-.patch +bluetooth-6lowpan-reset-link-local-header-on-ipv6-re.patch +bluetooth-6lowpan-fix-bdaddr_le-vs-addr_le_dev-addre.patch +bluetooth-6lowpan-don-t-hold-spin-lock-over-sleeping.patch +sctp-prevent-possible-shift-out-of-bounds-in-sctp_tr.patch +net-smc-fix-mismatch-between-clc-header-and-proposal.patch +net-handshake-fix-memory-leak-in-tls_handshake_accep.patch +tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch +net-mdio-fix-resource-leak-in-mdiobus_register_devic.patch +wifi-mac80211-skip-rate-verification-for-not-capture.patch +af_unix-initialise-scc_index-in-unix_add_edge.patch +net_sched-act_connmark-use-rcu-in-tcf_connmark_dump.patch +net-sched-act_connmark-initialize-struct-tc_ife-to-f.patch +net-sched-act_ife-initialize-struct-tc_ife-to-fix-km.patch +net-mlx5e-fix-maxrate-wraparound-in-threshold-betwee.patch +net-mlx5e-fix-wraparound-in-rate-limiting-for-values.patch +net-mlx5e-fix-potentially-misleading-debug-message.patch +net_sched-limit-try_bulk_dequeue_skb-batches.patch +virtio-net-fix-incorrect-flags-recording-in-big-mode.patch +hsr-fix-supervision-frame-sending-on-hsrv0.patch +acpi-cppc-check-_cpc-validity-for-only-the-online-cp.patch +acpi-cppc-perform-fast-check-switch-only-for-online-.patch +acpi-cppc-limit-perf-ctrs-in-pcc-check-only-to-onlin.patch +bluetooth-l2cap-export-l2cap_chan_hold-for-modules.patch +cifs-stop-writeback-extension-when-change-of-size-is.patch diff --git a/queue-6.6/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch b/queue-6.6/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch new file mode 100644 index 0000000000..4584f1c409 --- /dev/null +++ b/queue-6.6/tipc-fix-use-after-free-in-tipc_mon_reinit_self.patch @@ -0,0 +1,150 @@ +From 28f3b7033d2bfb89095e826858c572233382610e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Nov 2025 06:40:25 +0000 +Subject: tipc: Fix use-after-free in tipc_mon_reinit_self(). + +From: Kuniyuki Iwashima + +[ Upstream commit 0725e6afb55128be21a2ca36e9674f573ccec173 ] + +syzbot reported use-after-free of tipc_net(net)->monitors[] +in tipc_mon_reinit_self(). [0] + +The array is protected by RTNL, but tipc_mon_reinit_self() +iterates over it without RTNL. + +tipc_mon_reinit_self() is called from tipc_net_finalize(), +which is always under RTNL except for tipc_net_finalize_work(). + +Let's hold RTNL in tipc_net_finalize_work(). + +[0]: +BUG: KASAN: slab-use-after-free in __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] +BUG: KASAN: slab-use-after-free in _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 +Read of size 1 at addr ffff88805eae1030 by task kworker/0:7/5989 + +CPU: 0 UID: 0 PID: 5989 Comm: kworker/0:7 Not tainted syzkaller #0 PREEMPT_{RT,(full)} +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025 +Workqueue: events tipc_net_finalize_work +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_address_description mm/kasan/report.c:378 [inline] + print_report+0xca/0x240 mm/kasan/report.c:482 + kasan_report+0x118/0x150 mm/kasan/report.c:595 + __kasan_check_byte+0x2a/0x40 mm/kasan/common.c:568 + kasan_check_byte include/linux/kasan.h:399 [inline] + lock_acquire+0x8d/0x360 kernel/locking/lockdep.c:5842 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0xa7/0xf0 kernel/locking/spinlock.c:162 + rtlock_slowlock kernel/locking/rtmutex.c:1894 [inline] + rwbase_rtmutex_lock_state kernel/locking/spinlock_rt.c:160 [inline] + rwbase_write_lock+0xd3/0x7e0 kernel/locking/rwbase_rt.c:244 + rt_write_lock+0x76/0x110 kernel/locking/spinlock_rt.c:243 + write_lock_bh include/linux/rwlock_rt.h:99 [inline] + tipc_mon_reinit_self+0x79/0x430 net/tipc/monitor.c:718 + tipc_net_finalize+0x115/0x190 net/tipc/net.c:140 + process_one_work kernel/workqueue.c:3236 [inline] + process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3319 + worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x439/0x7d0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +Allocated by task 6089: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:388 [inline] + __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:405 + kasan_kmalloc include/linux/kasan.h:260 [inline] + __kmalloc_cache_noprof+0x1a8/0x320 mm/slub.c:4407 + kmalloc_noprof include/linux/slab.h:905 [inline] + kzalloc_noprof include/linux/slab.h:1039 [inline] + tipc_mon_create+0xc3/0x4d0 net/tipc/monitor.c:657 + tipc_enable_bearer net/tipc/bearer.c:357 [inline] + __tipc_nl_bearer_enable+0xe16/0x13f0 net/tipc/bearer.c:1047 + __tipc_nl_compat_doit net/tipc/netlink_compat.c:371 [inline] + tipc_nl_compat_doit+0x3bc/0x5f0 net/tipc/netlink_compat.c:393 + tipc_nl_compat_handle net/tipc/netlink_compat.c:-1 [inline] + tipc_nl_compat_recv+0x83c/0xbe0 net/tipc/netlink_compat.c:1321 + genl_family_rcv_msg_doit+0x215/0x300 net/netlink/genetlink.c:1115 + genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline] + genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210 + netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219 + netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline] + netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346 + netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896 + sock_sendmsg_nosec net/socket.c:714 [inline] + __sock_sendmsg+0x21c/0x270 net/socket.c:729 + ____sys_sendmsg+0x508/0x820 net/socket.c:2614 + ___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668 + __sys_sendmsg net/socket.c:2700 [inline] + __do_sys_sendmsg net/socket.c:2705 [inline] + __se_sys_sendmsg net/socket.c:2703 [inline] + __x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2703 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 6088: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 + poison_slab_object mm/kasan/common.c:243 [inline] + __kasan_slab_free+0x5b/0x80 mm/kasan/common.c:275 + kasan_slab_free include/linux/kasan.h:233 [inline] + slab_free_hook mm/slub.c:2422 [inline] + slab_free mm/slub.c:4695 [inline] + kfree+0x195/0x550 mm/slub.c:4894 + tipc_l2_device_event+0x380/0x650 net/tipc/bearer.c:-1 + notifier_call_chain+0x1b3/0x3e0 kernel/notifier.c:85 + call_netdevice_notifiers_extack net/core/dev.c:2267 [inline] + call_netdevice_notifiers net/core/dev.c:2281 [inline] + unregister_netdevice_many_notify+0x14d7/0x1fe0 net/core/dev.c:12166 + unregister_netdevice_many net/core/dev.c:12229 [inline] + unregister_netdevice_queue+0x33c/0x380 net/core/dev.c:12073 + unregister_netdevice include/linux/netdevice.h:3385 [inline] + __tun_detach+0xe4d/0x1620 drivers/net/tun.c:621 + tun_detach drivers/net/tun.c:637 [inline] + tun_chr_close+0x10d/0x1c0 drivers/net/tun.c:3433 + __fput+0x458/0xa80 fs/file_table.c:468 + task_work_run+0x1d4/0x260 kernel/task_work.c:227 + resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] + exit_to_user_mode_loop+0xec/0x110 kernel/entry/common.c:43 + exit_to_user_mode_prepare include/linux/irq-entry-common.h:225 [inline] + syscall_exit_to_user_mode_work include/linux/entry-common.h:175 [inline] + syscall_exit_to_user_mode include/linux/entry-common.h:210 [inline] + do_syscall_64+0x2bd/0x3b0 arch/x86/entry/syscall_64.c:100 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") +Reported-by: syzbot+d7dad7fd4b3921104957@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/690c323a.050a0220.baf87.007f.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251107064038.2361188-1-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/net.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tipc/net.c b/net/tipc/net.c +index 0e95572e56b41..7e65d0b0c4a8d 100644 +--- a/net/tipc/net.c ++++ b/net/tipc/net.c +@@ -145,7 +145,9 @@ void tipc_net_finalize_work(struct work_struct *work) + { + struct tipc_net *tn = container_of(work, struct tipc_net, work); + ++ rtnl_lock(); + tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr); ++ rtnl_unlock(); + } + + void tipc_net_stop(struct net *net) +-- +2.51.0 + diff --git a/queue-6.6/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch b/queue-6.6/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch new file mode 100644 index 0000000000..e38b0c8dcc --- /dev/null +++ b/queue-6.6/virtio-net-fix-incorrect-flags-recording-in-big-mode.patch @@ -0,0 +1,72 @@ +From 517d347ea2ed5a044f154f04fa7ee59be2bbae78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Nov 2025 17:08:28 +0800 +Subject: virtio-net: fix incorrect flags recording in big mode + +From: Xuan Zhuo + +[ Upstream commit 0eff2eaa5322b5b141ff5d5ded26fac4a52b5f7b ] + +The purpose of commit 703eec1b2422 ("virtio_net: fixing XDP for fully +checksummed packets handling") is to record the flags in advance, as +their value may be overwritten in the XDP case. However, the flags +recorded under big mode are incorrect, because in big mode, the passed +buf does not point to the rx buffer, but rather to the page of the +submitted buffer. This commit fixes this issue. + +For the small mode, the commit c11a49d58ad2 ("virtio_net: Fix mismatched +buf address when unmapping for small packets") fixed it. + +Tested-by: Alyssa Ross +Fixes: 703eec1b2422 ("virtio_net: fixing XDP for fully checksummed packets handling") +Signed-off-by: Xuan Zhuo +Acked-by: Jason Wang +Acked-by: Michael S. Tsirkin +Link: https://patch.msgid.link/20251111090828.23186-1-xuanzhuo@linux.alibaba.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/virtio_net.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index fd5663075bd77..caae11ba2f8be 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1821,22 +1821,28 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, + return; + } + +- /* 1. Save the flags early, as the XDP program might overwrite them. ++ /* About the flags below: ++ * 1. Save the flags early, as the XDP program might overwrite them. + * These flags ensure packets marked as VIRTIO_NET_HDR_F_DATA_VALID + * stay valid after XDP processing. + * 2. XDP doesn't work with partially checksummed packets (refer to + * virtnet_xdp_set()), so packets marked as + * VIRTIO_NET_HDR_F_NEEDS_CSUM get dropped during XDP processing. + */ +- flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + +- if (vi->mergeable_rx_bufs) ++ if (vi->mergeable_rx_bufs) { ++ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit, + stats); +- else if (vi->big_packets) ++ } else if (vi->big_packets) { ++ void *p = page_address((struct page *)buf); ++ ++ flags = ((struct virtio_net_common_hdr *)p)->hdr.flags; + skb = receive_big(dev, vi, rq, buf, len, stats); +- else ++ } else { ++ flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags; + skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, stats); ++ } + + if (unlikely(!skb)) + return; +-- +2.51.0 + diff --git a/queue-6.6/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch b/queue-6.6/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch new file mode 100644 index 0000000000..a18f6d1906 --- /dev/null +++ b/queue-6.6/wifi-ath11k-zero-init-info-status-in-wmi_process_mgm.patch @@ -0,0 +1,53 @@ +From d1c7bc9cb4b5b649e597e98602fb99d0fe9a109b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Nov 2025 09:39:57 +0100 +Subject: wifi: ath11k: zero init info->status in wmi_process_mgmt_tx_comp() + +From: Nicolas Escande + +[ Upstream commit 9065b968752334f972e0d48e50c4463a172fc2a7 ] + +When reporting tx completion using ieee80211_tx_status_xxx() family of +functions, the status part of the struct ieee80211_tx_info nested in the +skb is used to report things like transmit rates & retry count to mac80211 + +On the TX data path, this is correctly memset to 0 before calling +ieee80211_tx_status_ext(), but on the tx mgmt path this was not done. + +This leads to mac80211 treating garbage values as valid transmit counters +(like tx retries for example) and accounting them as real statistics that +makes their way to userland via station dump. + +The same issue was resolved in ath12k by commit 9903c0986f78 ("wifi: +ath12k: Add memset and update default rate value in wmi tx completion") + +Tested-on: QCN9074 PCI WLAN.HK.2.9.0.1-01977-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Nicolas Escande +Reviewed-by: Vasanthakumar Thiagarajan +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20251104083957.717825-1-nico.escande@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/wmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index 31dbabc9eaf33..16687223bdcba 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5841,6 +5841,9 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); ++ memset(&info->status, 0, sizeof(info->status)); ++ info->status.rates[0].idx = -1; ++ + if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && + !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; +-- +2.51.0 + diff --git a/queue-6.6/wifi-mac80211-skip-rate-verification-for-not-capture.patch b/queue-6.6/wifi-mac80211-skip-rate-verification-for-not-capture.patch new file mode 100644 index 0000000000..0e20f30940 --- /dev/null +++ b/queue-6.6/wifi-mac80211-skip-rate-verification-for-not-capture.patch @@ -0,0 +1,48 @@ +From 39e572516a0bb0e41fd4b0b3cc4da92d6045e3ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Nov 2025 14:26:18 +0200 +Subject: wifi: mac80211: skip rate verification for not captured PSDUs + +From: Benjamin Berg + +[ Upstream commit 7fe0d21f5633af8c3fab9f0ef0706c6156623484 ] + +If for example the sniffer did not follow any AIDs in an MU frame, then +some of the information may not be filled in or is even expected to be +invalid. As an example, in that case it is expected that Nss is zero. + +Fixes: 2ff5e52e7836 ("radiotap: add 0-length PSDU "not captured" type") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20251110142554.83a2858ee15b.I9f78ce7984872f474722f9278691ae16378f0a3e@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 164c6e8049826..e6a0a65d4d43a 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -5341,10 +5341,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + if (WARN_ON(!local->started)) + goto drop; + +- if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { ++ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) && ++ !(status->flag & RX_FLAG_NO_PSDU && ++ status->zero_length_psdu_type == ++ IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) { + /* +- * Validate the rate, unless a PLCP error means that +- * we probably can't have a valid rate here anyway. ++ * Validate the rate, unless there was a PLCP error which may ++ * have an invalid rate or the PSDU was not capture and may be ++ * missing rate information. + */ + + switch (status->encoding) { +-- +2.51.0 +