--- /dev/null
+From fe8d58a113948c59d42428b75d6b626e7165a99b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2024 15:58:29 -0700
+Subject: bnxt_en: ethtool: Supply ntuple rss context action
+
+From: Daniel Xu <dxu@dxuuu.xyz>
+
+[ Upstream commit be75cda92a65a13db242117d674cd5584477a168 ]
+
+Commit 2f4f9fe5bf5f ("bnxt_en: Support adding ntuple rules on RSS
+contexts") added support for redirecting to an RSS context as an ntuple
+rule action. However, it forgot to update the ETHTOOL_GRXCLSRULE
+codepath. This caused `ethtool -n` to always report the action as
+"Action: Direct to queue 0" which is wrong.
+
+Fix by teaching bnxt driver to report the RSS context when applicable.
+
+Fixes: 2f4f9fe5bf5f ("bnxt_en: Support adding ntuple rules on RSS contexts")
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
+Link: https://patch.msgid.link/2e884ae39e08dc5123be7c170a6089cefe6a78f7.1732748253.git.dxu@dxuuu.xyz
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index 20ba14eb87e00..b901ecb57f255 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -1193,10 +1193,14 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+ }
+ }
+
+- if (fltr->base.flags & BNXT_ACT_DROP)
++ if (fltr->base.flags & BNXT_ACT_DROP) {
+ fs->ring_cookie = RX_CLS_FLOW_DISC;
+- else
++ } else if (fltr->base.flags & BNXT_ACT_RSS_CTX) {
++ fs->flow_type |= FLOW_RSS;
++ cmd->rss_context = fltr->base.fw_vnic_id;
++ } else {
+ fs->ring_cookie = fltr->base.rxq;
++ }
+ rc = 0;
+
+ fltr_err:
+--
+2.43.0
+
--- /dev/null
+From bb7da28168cb1191435aef56f61d466f44a21441 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:42 +0100
+Subject: can: c_can: c_can_handle_bus_err(): update statistics if skb
+ allocation fails
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 9e66242504f49e17481d8e197730faba7d99c934 ]
+
+Ensure that the statistics are always updated, even if the skb
+allocation fails.
+
+Fixes: 4d6d26537940 ("can: c_can: fix {rx,tx}_errors statistics")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-2-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/c_can/c_can_main.c | 26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c
+index 511615dc33419..cc371d0c9f3c7 100644
+--- a/drivers/net/can/c_can/c_can_main.c
++++ b/drivers/net/can/c_can/c_can_main.c
+@@ -1014,49 +1014,57 @@ static int c_can_handle_bus_err(struct net_device *dev,
+
+ /* propagate the error condition to the CAN stack */
+ skb = alloc_can_err_skb(dev, &cf);
+- if (unlikely(!skb))
+- return 0;
+
+ /* check for 'last error code' which tells us the
+ * type of the last error to occur on the CAN bus
+ */
+- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
++ if (likely(skb))
++ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ switch (lec_type) {
+ case LEC_STUFF_ERROR:
+ netdev_dbg(dev, "stuff error\n");
+- cf->data[2] |= CAN_ERR_PROT_STUFF;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ stats->rx_errors++;
+ break;
+ case LEC_FORM_ERROR:
+ netdev_dbg(dev, "form error\n");
+- cf->data[2] |= CAN_ERR_PROT_FORM;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_FORM;
+ stats->rx_errors++;
+ break;
+ case LEC_ACK_ERROR:
+ netdev_dbg(dev, "ack error\n");
+- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
++ if (likely(skb))
++ cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ stats->tx_errors++;
+ break;
+ case LEC_BIT1_ERROR:
+ netdev_dbg(dev, "bit1 error\n");
+- cf->data[2] |= CAN_ERR_PROT_BIT1;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ stats->tx_errors++;
+ break;
+ case LEC_BIT0_ERROR:
+ netdev_dbg(dev, "bit0 error\n");
+- cf->data[2] |= CAN_ERR_PROT_BIT0;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ stats->tx_errors++;
+ break;
+ case LEC_CRC_ERROR:
+ netdev_dbg(dev, "CRC error\n");
+- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
++ if (likely(skb))
++ cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ stats->rx_errors++;
+ break;
+ default:
+ break;
+ }
+
++ if (unlikely(!skb))
++ return 0;
++
+ netif_receive_skb(skb);
+ return 1;
+ }
+--
+2.43.0
+
--- /dev/null
+From 5b443529ec7ce701abd2b88140814c05a197ede2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:52 +0100
+Subject: can: ems_usb: ems_usb_rx_err(): fix {rx,tx}_errors statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 72a7e2e74b3075959f05e622bae09b115957dffe ]
+
+The ems_usb_rx_err() function only incremented the receive error counter
+and never the transmit error counter, even if the ECC_DIR flag reported
+that an error had occurred during transmission.
+
+Increment the receive/transmit error counter based on the value of the
+ECC_DIR flag.
+
+Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-12-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/ems_usb.c | 58 ++++++++++++++++++++---------------
+ 1 file changed, 33 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
+index 050c0b49938a4..5355bac4dccbe 100644
+--- a/drivers/net/can/usb/ems_usb.c
++++ b/drivers/net/can/usb/ems_usb.c
+@@ -335,15 +335,14 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
+ struct net_device_stats *stats = &dev->netdev->stats;
+
+ skb = alloc_can_err_skb(dev->netdev, &cf);
+- if (skb == NULL)
+- return;
+
+ if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
+ u8 state = msg->msg.can_state;
+
+ if (state & SJA1000_SR_BS) {
+ dev->can.state = CAN_STATE_BUS_OFF;
+- cf->can_id |= CAN_ERR_BUSOFF;
++ if (skb)
++ cf->can_id |= CAN_ERR_BUSOFF;
+
+ dev->can.can_stats.bus_off++;
+ can_bus_off(dev->netdev);
+@@ -361,44 +360,53 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
+
+ /* bus error interrupt */
+ dev->can.can_stats.bus_error++;
+- stats->rx_errors++;
+
+- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
++ if (skb) {
++ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+- switch (ecc & SJA1000_ECC_MASK) {
+- case SJA1000_ECC_BIT:
+- cf->data[2] |= CAN_ERR_PROT_BIT;
+- break;
+- case SJA1000_ECC_FORM:
+- cf->data[2] |= CAN_ERR_PROT_FORM;
+- break;
+- case SJA1000_ECC_STUFF:
+- cf->data[2] |= CAN_ERR_PROT_STUFF;
+- break;
+- default:
+- cf->data[3] = ecc & SJA1000_ECC_SEG;
+- break;
++ switch (ecc & SJA1000_ECC_MASK) {
++ case SJA1000_ECC_BIT:
++ cf->data[2] |= CAN_ERR_PROT_BIT;
++ break;
++ case SJA1000_ECC_FORM:
++ cf->data[2] |= CAN_ERR_PROT_FORM;
++ break;
++ case SJA1000_ECC_STUFF:
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
++ break;
++ default:
++ cf->data[3] = ecc & SJA1000_ECC_SEG;
++ break;
++ }
+ }
+
+ /* Error occurred during transmission? */
+- if ((ecc & SJA1000_ECC_DIR) == 0)
+- cf->data[2] |= CAN_ERR_PROT_TX;
++ if ((ecc & SJA1000_ECC_DIR) == 0) {
++ stats->tx_errors++;
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_TX;
++ } else {
++ stats->rx_errors++;
++ }
+
+- if (dev->can.state == CAN_STATE_ERROR_WARNING ||
+- dev->can.state == CAN_STATE_ERROR_PASSIVE) {
++ if (skb && (dev->can.state == CAN_STATE_ERROR_WARNING ||
++ dev->can.state == CAN_STATE_ERROR_PASSIVE)) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = (txerr > rxerr) ?
+ CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
+ }
+ } else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
+- cf->can_id |= CAN_ERR_CRTL;
+- cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ if (skb) {
++ cf->can_id |= CAN_ERR_CRTL;
++ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ }
+
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+ }
+
+- netif_rx(skb);
++ if (skb)
++ netif_rx(skb);
+ }
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 185e4893409ec4d56dff35ea62ab6f96fb169604 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:53 +0100
+Subject: can: f81604: f81604_handle_can_bus_errors(): fix {rx,tx}_errors
+ statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit d7b916540c2ba3d2a88c27b2a6287b39d8eac052 ]
+
+The f81604_handle_can_bus_errors() function only incremented the receive
+error counter and never the transmit error counter, even if the ECC_DIR
+flag reported that an error had occurred during transmission.
+
+Increment the receive/transmit error counter based on the value of the
+ECC_DIR flag.
+
+Fixes: 88da17436973 ("can: usb: f81604: add Fintek F81604 support")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-13-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/f81604.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c
+index bc0c8903fe779..e0cfa1460b0b8 100644
+--- a/drivers/net/can/usb/f81604.c
++++ b/drivers/net/can/usb/f81604.c
+@@ -526,7 +526,6 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
+ netdev_dbg(netdev, "bus error interrupt\n");
+
+ priv->can.can_stats.bus_error++;
+- stats->rx_errors++;
+
+ if (skb) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+@@ -548,10 +547,15 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
+
+ /* set error location */
+ cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
++ }
+
+- /* Error occurred during transmission? */
+- if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0)
++ /* Error occurred during transmission? */
++ if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) {
++ stats->tx_errors++;
++ if (skb)
+ cf->data[2] |= CAN_ERR_PROT_TX;
++ } else {
++ stats->rx_errors++;
+ }
+
+ set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
+--
+2.43.0
+
--- /dev/null
+From 52bef541cfcb0090c4c57bf06eb011d0e0c90492 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Oct 2024 23:24:26 +0200
+Subject: can: gs_usb: add usb endpoint address detection at driver probe step
+
+From: Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
+
+[ Upstream commit 889b2ae9139a87b3390f7003cb1bb3d65bf90a26 ]
+
+There is an approach made to implement gs_usb firmware/driver based on
+Zephyr RTOS. It was found that USB stack of Zephyr RTOS overwrites USB
+EP addresses, if they have different last 4 bytes in absence of other
+endpoints.
+
+For example in case of gs_usb candlelight firmware EP-IN is 0x81 and
+EP-OUT 0x02. If there are no additional USB endpoints, Zephyr RTOS will
+overwrite EP-OUT to 0x01. More information can be found in the
+discussion with Zephyr RTOS USB stack maintainer here:
+
+https://github.com/zephyrproject-rtos/zephyr/issues/67812
+
+There are already two different gs_usb FW driver implementations based
+on Zephyr RTOS:
+
+1. https://github.com/CANnectivity/cannectivity
+ (by: https://github.com/henrikbrixandersen)
+2. https://github.com/zephyrproject-rtos/zephyr/compare/main...KozhinovAlexander:zephyr:gs_usb
+ (by: https://github.com/KozhinovAlexander)
+
+At the moment both Zephyr RTOS implementations use dummy USB endpoint,
+to overcome described USB stack behavior from Zephyr itself. Since
+Zephyr RTOS is intended to be used on microcontrollers with very
+constrained amount of resources (ROM, RAM) and additional endpoint
+requires memory, it is more convenient to update the gs_usb driver in
+the Linux kernel.
+
+To fix this problem, update the gs_usb driver from using hard coded
+endpoint numbers to evaluate the endpoint descriptors and use the
+endpoints provided there.
+
+Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
+Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
+Signed-off-by: Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
+Link: https://patch.msgid.link/20241018212450.31746-1-ak.alexander.kozhinov@gmail.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/gs_usb.c | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
+index bc86e9b329fd1..b6f4de375df75 100644
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -43,9 +43,6 @@
+ #define USB_XYLANTA_SAINT3_VENDOR_ID 0x16d0
+ #define USB_XYLANTA_SAINT3_PRODUCT_ID 0x0f30
+
+-#define GS_USB_ENDPOINT_IN 1
+-#define GS_USB_ENDPOINT_OUT 2
+-
+ /* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts
+ * for timer overflow (will be after ~71 minutes)
+ */
+@@ -336,6 +333,9 @@ struct gs_usb {
+
+ unsigned int hf_size_rx;
+ u8 active_channels;
++
++ unsigned int pipe_in;
++ unsigned int pipe_out;
+ };
+
+ /* 'allocate' a tx context.
+@@ -687,7 +687,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+
+ resubmit_urb:
+ usb_fill_bulk_urb(urb, parent->udev,
+- usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
++ parent->pipe_in,
+ hf, dev->parent->hf_size_rx,
+ gs_usb_receive_bulk_callback, parent);
+
+@@ -819,7 +819,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
+ }
+
+ usb_fill_bulk_urb(urb, dev->udev,
+- usb_sndbulkpipe(dev->udev, GS_USB_ENDPOINT_OUT),
++ dev->parent->pipe_out,
+ hf, dev->hf_size_tx,
+ gs_usb_xmit_callback, txc);
+
+@@ -925,8 +925,7 @@ static int gs_can_open(struct net_device *netdev)
+ /* fill, anchor, and submit rx urb */
+ usb_fill_bulk_urb(urb,
+ dev->udev,
+- usb_rcvbulkpipe(dev->udev,
+- GS_USB_ENDPOINT_IN),
++ dev->parent->pipe_in,
+ buf,
+ dev->parent->hf_size_rx,
+ gs_usb_receive_bulk_callback, parent);
+@@ -1413,6 +1412,7 @@ static int gs_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
++ struct usb_endpoint_descriptor *ep_in, *ep_out;
+ struct gs_host_frame *hf;
+ struct gs_usb *parent;
+ struct gs_host_config hconf = {
+@@ -1422,6 +1422,13 @@ static int gs_usb_probe(struct usb_interface *intf,
+ unsigned int icount, i;
+ int rc;
+
++ rc = usb_find_common_endpoints(intf->cur_altsetting,
++ &ep_in, &ep_out, NULL, NULL);
++ if (rc) {
++ dev_err(&intf->dev, "Required endpoints not found\n");
++ return rc;
++ }
++
+ /* send host config */
+ rc = usb_control_msg_send(udev, 0,
+ GS_USB_BREQ_HOST_FORMAT,
+@@ -1466,6 +1473,10 @@ static int gs_usb_probe(struct usb_interface *intf,
+ usb_set_intfdata(intf, parent);
+ parent->udev = udev;
+
++ /* store the detected endpoints */
++ parent->pipe_in = usb_rcvbulkpipe(parent->udev, ep_in->bEndpointAddress);
++ parent->pipe_out = usb_sndbulkpipe(parent->udev, ep_out->bEndpointAddress);
++
+ for (i = 0; i < icount; i++) {
+ unsigned int hf_size_rx = 0;
+
+--
+2.43.0
+
--- /dev/null
+From fc4e2784aec05478af3969371804e38f4b010cc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:45 +0100
+Subject: can: hi311x: hi3110_can_ist(): fix potential use-after-free
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 9ad86d377ef4a19c75a9c639964879a5b25a433b ]
+
+The commit a22bd630cfff ("can: hi311x: do not report txerr and rxerr
+during bus-off") removed the reporting of rxerr and txerr even in case
+of correct operation (i. e. not bus-off).
+
+The error count information added to the CAN frame after netif_rx() is
+a potential use after free, since there is no guarantee that the skb
+is in the same state. It might be freed or reused.
+
+Fix the issue by postponing the netif_rx() call in case of txerr and
+rxerr reporting.
+
+Fixes: a22bd630cfff ("can: hi311x: do not report txerr and rxerr during bus-off")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-5-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/spi/hi311x.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
+index 148d974ebb210..b67464df25ffe 100644
+--- a/drivers/net/can/spi/hi311x.c
++++ b/drivers/net/can/spi/hi311x.c
+@@ -671,9 +671,9 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
+ tx_state = txerr >= rxerr ? new_state : 0;
+ rx_state = txerr <= rxerr ? new_state : 0;
+ can_change_state(net, cf, tx_state, rx_state);
+- netif_rx(skb);
+
+ if (new_state == CAN_STATE_BUS_OFF) {
++ netif_rx(skb);
+ can_bus_off(net);
+ if (priv->can.restart_ms == 0) {
+ priv->force_quit = 1;
+@@ -684,6 +684,7 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
+ cf->can_id |= CAN_ERR_CNT;
+ cf->data[6] = txerr;
+ cf->data[7] = rxerr;
++ netif_rx(skb);
+ }
+ }
+
+--
+2.43.0
+
--- /dev/null
+From daf5a7161f4d57a0a023480f7db2694753a3cb91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:49 +0100
+Subject: can: hi311x: hi3110_can_ist(): fix {rx,tx}_errors statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 3e4645931655776e757f9fb5ae29371cd7cb21a2 ]
+
+The hi3110_can_ist() function was incorrectly incrementing only the
+receive error counter, even in cases of bit or acknowledgment errors that
+occur during transmission.
+
+The fix the issue by incrementing the appropriate counter based on the
+type of error.
+
+Fixes: 57e83fb9b746 ("can: hi311x: Add Holt HI-311x CAN driver")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-9-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/spi/hi311x.c | 47 ++++++++++++++++++++++--------------
+ 1 file changed, 29 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
+index b67464df25ffe..1b9501ee10deb 100644
+--- a/drivers/net/can/spi/hi311x.c
++++ b/drivers/net/can/spi/hi311x.c
+@@ -697,27 +697,38 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
+ /* Check for protocol errors */
+ if (eflag & HI3110_ERR_PROTOCOL_MASK) {
+ skb = alloc_can_err_skb(net, &cf);
+- if (!skb)
+- break;
++ if (skb)
++ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ priv->can.can_stats.bus_error++;
+- priv->net->stats.rx_errors++;
+- if (eflag & HI3110_ERR_BITERR)
+- cf->data[2] |= CAN_ERR_PROT_BIT;
+- else if (eflag & HI3110_ERR_FRMERR)
+- cf->data[2] |= CAN_ERR_PROT_FORM;
+- else if (eflag & HI3110_ERR_STUFERR)
+- cf->data[2] |= CAN_ERR_PROT_STUFF;
+- else if (eflag & HI3110_ERR_CRCERR)
+- cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
+- else if (eflag & HI3110_ERR_ACKERR)
+- cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
+-
+- cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
+- cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
++ if (eflag & HI3110_ERR_BITERR) {
++ priv->net->stats.tx_errors++;
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_BIT;
++ } else if (eflag & HI3110_ERR_FRMERR) {
++ priv->net->stats.rx_errors++;
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_FORM;
++ } else if (eflag & HI3110_ERR_STUFERR) {
++ priv->net->stats.rx_errors++;
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
++ } else if (eflag & HI3110_ERR_CRCERR) {
++ priv->net->stats.rx_errors++;
++ if (skb)
++ cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
++ } else if (eflag & HI3110_ERR_ACKERR) {
++ priv->net->stats.tx_errors++;
++ if (skb)
++ cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
++ }
++
+ netdev_dbg(priv->net, "Bus Error\n");
+- netif_rx(skb);
++ if (skb) {
++ cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
++ cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
++ netif_rx(skb);
++ }
+ }
+ }
+
+--
+2.43.0
+
--- /dev/null
+From b6e39db85b26587a2df27ec628e33de6490a0aa8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:48 +0100
+Subject: can: ifi_canfd: ifi_canfd_handle_lec_err(): fix {rx,tx}_errors
+ statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit bb03d568bb21b4afe7935d1943bcf68ddea3ea45 ]
+
+The ifi_canfd_handle_lec_err() function was incorrectly incrementing only
+the receive error counter, even in cases of bit or acknowledgment errors
+that occur during transmission.
+
+Fix the issue by incrementing the appropriate counter based on the
+type of error.
+
+Fixes: 5bbd655a8bd0 ("can: ifi: Add more detailed error reporting")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Reviewed-by: Marek Vasut <marex@denx.de>
+Link: https://patch.msgid.link/20241122221650.633981-8-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/ifi_canfd/ifi_canfd.c | 58 ++++++++++++++++++---------
+ 1 file changed, 40 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
+index d32b10900d2f6..c86b57d47085f 100644
+--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
++++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
+@@ -390,36 +390,55 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
+ return 0;
+
+ priv->can.can_stats.bus_error++;
+- stats->rx_errors++;
+
+ /* Propagate the error condition to the CAN stack. */
+ skb = alloc_can_err_skb(ndev, &cf);
+- if (unlikely(!skb))
+- return 0;
+
+ /* Read the error counter register and check for new errors. */
+- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
++ if (likely(skb))
++ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+- if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
+- cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
++ if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST) {
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
++ }
+
+- if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST)
+- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
++ if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST) {
++ stats->tx_errors++;
++ if (likely(skb))
++ cf->data[3] = CAN_ERR_PROT_LOC_ACK;
++ }
+
+- if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST)
+- cf->data[2] |= CAN_ERR_PROT_BIT0;
++ if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST) {
++ stats->tx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_BIT0;
++ }
+
+- if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST)
+- cf->data[2] |= CAN_ERR_PROT_BIT1;
++ if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST) {
++ stats->tx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_BIT1;
++ }
+
+- if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST)
+- cf->data[2] |= CAN_ERR_PROT_STUFF;
++ if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST) {
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
++ }
+
+- if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST)
+- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
++ if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST) {
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
++ }
+
+- if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST)
+- cf->data[2] |= CAN_ERR_PROT_FORM;
++ if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST) {
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_FORM;
++ }
+
+ /* Reset the error counter, ack the IRQ and re-enable the counter. */
+ writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
+@@ -427,6 +446,9 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
+ priv->base + IFI_CANFD_INTERRUPT);
+ writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
+
++ if (unlikely(!skb))
++ return 0;
++
+ netif_receive_skb(skb);
+
+ return 1;
+--
+2.43.0
+
--- /dev/null
+From d7500b2671038638c8f18b18ac873eb62b59135b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Nov 2024 12:48:23 +0300
+Subject: can: j1939: j1939_session_new(): fix skb reference counting
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit a8c695005bfe6569acd73d777ca298ddddd66105 ]
+
+Since j1939_session_skb_queue() does an extra skb_get() for each new
+skb, do the same for the initial one in j1939_session_new() to avoid
+refcount underflow.
+
+Reported-by: syzbot+d4e8dc385d9258220c31@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=d4e8dc385d9258220c31
+Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol")
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Tested-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20241105094823.2403806-1-dmantipov@yandex.ru
+[mkl: clean up commit message]
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/can/j1939/transport.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
+index 319f47df33300..95f7a7e65a73f 100644
+--- a/net/can/j1939/transport.c
++++ b/net/can/j1939/transport.c
+@@ -1505,7 +1505,7 @@ static struct j1939_session *j1939_session_new(struct j1939_priv *priv,
+ session->state = J1939_SESSION_NEW;
+
+ skb_queue_head_init(&session->skb_queue);
+- skb_queue_tail(&session->skb_queue, skb);
++ skb_queue_tail(&session->skb_queue, skb_get(skb));
+
+ skcb = j1939_skb_to_cb(skb);
+ memcpy(&session->skcb, skcb, sizeof(session->skcb));
+--
+2.43.0
+
--- /dev/null
+From 39373b30def1a3d0dd11113a6aae5fecc42b20a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:47 +0100
+Subject: can: m_can: m_can_handle_lec_err(): fix {rx,tx}_errors statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 988d4222bf9039a875a3d48f2fe35c317831ff68 ]
+
+The m_can_handle_lec_err() function was incorrectly incrementing only the
+receive error counter, even in cases of bit or acknowledgment errors that
+occur during transmission.
+
+Fix the issue by incrementing the appropriate counter based on the
+type of error.
+
+Fixes: e0d1f4816f2a ("can: m_can: add Bosch M_CAN controller support")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-7-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/m_can/m_can.c | 33 +++++++++++++++++++++++----------
+ 1 file changed, 23 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
+index 16e9e7d7527d9..533bcb77c9f93 100644
+--- a/drivers/net/can/m_can/m_can.c
++++ b/drivers/net/can/m_can/m_can.c
+@@ -695,47 +695,60 @@ static int m_can_handle_lec_err(struct net_device *dev,
+ u32 timestamp = 0;
+
+ cdev->can.can_stats.bus_error++;
+- stats->rx_errors++;
+
+ /* propagate the error condition to the CAN stack */
+ skb = alloc_can_err_skb(dev, &cf);
+- if (unlikely(!skb))
+- return 0;
+
+ /* check for 'last error code' which tells us the
+ * type of the last error to occur on the CAN bus
+ */
+- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
++ if (likely(skb))
++ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ switch (lec_type) {
+ case LEC_STUFF_ERROR:
+ netdev_dbg(dev, "stuff error\n");
+- cf->data[2] |= CAN_ERR_PROT_STUFF;
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ case LEC_FORM_ERROR:
+ netdev_dbg(dev, "form error\n");
+- cf->data[2] |= CAN_ERR_PROT_FORM;
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case LEC_ACK_ERROR:
+ netdev_dbg(dev, "ack error\n");
+- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
++ stats->tx_errors++;
++ if (likely(skb))
++ cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ break;
+ case LEC_BIT1_ERROR:
+ netdev_dbg(dev, "bit1 error\n");
+- cf->data[2] |= CAN_ERR_PROT_BIT1;
++ stats->tx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ break;
+ case LEC_BIT0_ERROR:
+ netdev_dbg(dev, "bit0 error\n");
+- cf->data[2] |= CAN_ERR_PROT_BIT0;
++ stats->tx_errors++;
++ if (likely(skb))
++ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ break;
+ case LEC_CRC_ERROR:
+ netdev_dbg(dev, "CRC error\n");
+- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
++ stats->rx_errors++;
++ if (likely(skb))
++ cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ break;
+ default:
+ break;
+ }
+
++ if (unlikely(!skb))
++ return 0;
++
+ if (cdev->is_peripheral)
+ timestamp = m_can_get_timestamp(cdev);
+
+--
+2.43.0
+
--- /dev/null
+From 77f69760893c7f94c801aa06259d72fa747e270e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:50 +0100
+Subject: can: sja1000: sja1000_err(): fix {rx,tx}_errors statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 2c4ef3af4b028a0eaaf378df511d3b425b1df61f ]
+
+The sja1000_err() function only incremented the receive error counter
+and never the transmit error counter, even if the ECC_DIR flag reported
+that an error had occurred during transmission.
+
+Increment the receive/transmit error counter based on the value of the
+ECC_DIR flag.
+
+Fixes: 429da1cc841b ("can: Driver for the SJA1000 CAN controller")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-10-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/sja1000/sja1000.c | 67 ++++++++++++++++++-------------
+ 1 file changed, 39 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
+index ddb3247948ad2..4d245857ef1ce 100644
+--- a/drivers/net/can/sja1000/sja1000.c
++++ b/drivers/net/can/sja1000/sja1000.c
+@@ -416,8 +416,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ int ret = 0;
+
+ skb = alloc_can_err_skb(dev, &cf);
+- if (skb == NULL)
+- return -ENOMEM;
+
+ txerr = priv->read_reg(priv, SJA1000_TXERR);
+ rxerr = priv->read_reg(priv, SJA1000_RXERR);
+@@ -425,8 +423,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ if (isrc & IRQ_DOI) {
+ /* data overrun interrupt */
+ netdev_dbg(dev, "data overrun interrupt\n");
+- cf->can_id |= CAN_ERR_CRTL;
+- cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ if (skb) {
++ cf->can_id |= CAN_ERR_CRTL;
++ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ }
++
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+ sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
+@@ -452,7 +453,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ else
+ state = CAN_STATE_ERROR_ACTIVE;
+ }
+- if (state != CAN_STATE_BUS_OFF) {
++ if (state != CAN_STATE_BUS_OFF && skb) {
+ cf->can_id |= CAN_ERR_CNT;
+ cf->data[6] = txerr;
+ cf->data[7] = rxerr;
+@@ -460,33 +461,38 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ if (isrc & IRQ_BEI) {
+ /* bus error interrupt */
+ priv->can.can_stats.bus_error++;
+- stats->rx_errors++;
+
+ ecc = priv->read_reg(priv, SJA1000_ECC);
++ if (skb) {
++ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+-
+- /* set error type */
+- switch (ecc & ECC_MASK) {
+- case ECC_BIT:
+- cf->data[2] |= CAN_ERR_PROT_BIT;
+- break;
+- case ECC_FORM:
+- cf->data[2] |= CAN_ERR_PROT_FORM;
+- break;
+- case ECC_STUFF:
+- cf->data[2] |= CAN_ERR_PROT_STUFF;
+- break;
+- default:
+- break;
+- }
++ /* set error type */
++ switch (ecc & ECC_MASK) {
++ case ECC_BIT:
++ cf->data[2] |= CAN_ERR_PROT_BIT;
++ break;
++ case ECC_FORM:
++ cf->data[2] |= CAN_ERR_PROT_FORM;
++ break;
++ case ECC_STUFF:
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
++ break;
++ default:
++ break;
++ }
+
+- /* set error location */
+- cf->data[3] = ecc & ECC_SEG;
++ /* set error location */
++ cf->data[3] = ecc & ECC_SEG;
++ }
+
+ /* Error occurred during transmission? */
+- if ((ecc & ECC_DIR) == 0)
+- cf->data[2] |= CAN_ERR_PROT_TX;
++ if ((ecc & ECC_DIR) == 0) {
++ stats->tx_errors++;
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_TX;
++ } else {
++ stats->rx_errors++;
++ }
+ }
+ if (isrc & IRQ_EPI) {
+ /* error passive interrupt */
+@@ -502,8 +508,10 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ netdev_dbg(dev, "arbitration lost interrupt\n");
+ alc = priv->read_reg(priv, SJA1000_ALC);
+ priv->can.can_stats.arbitration_lost++;
+- cf->can_id |= CAN_ERR_LOSTARB;
+- cf->data[0] = alc & 0x1f;
++ if (skb) {
++ cf->can_id |= CAN_ERR_LOSTARB;
++ cf->data[0] = alc & 0x1f;
++ }
+ }
+
+ if (state != priv->can.state) {
+@@ -516,6 +524,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ can_bus_off(dev);
+ }
+
++ if (!skb)
++ return -ENOMEM;
++
+ netif_rx(skb);
+
+ return ret;
+--
+2.43.0
+
--- /dev/null
+From ee11b32d7c1f9e6c1a1047d7eabf58c04b740219 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:43 +0100
+Subject: can: sun4i_can: sun4i_can_err(): call can_change_state() even if cf
+ is NULL
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit ee6bf3677ae03569d833795064e17f605c2163c7 ]
+
+Call the function can_change_state() if the allocation of the skb
+fails, as it handles the cf parameter when it is null.
+
+Additionally, this ensures that the statistics related to state error
+counters (i. e. warning, passive, and bus-off) are updated.
+
+Fixes: 0738eff14d81 ("can: Allwinner A10/A20 CAN Controller support - Kernel module")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-3-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/sun4i_can.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
+index 360158c295d34..17f94cca93fbc 100644
+--- a/drivers/net/can/sun4i_can.c
++++ b/drivers/net/can/sun4i_can.c
+@@ -629,10 +629,10 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
+ tx_state = txerr >= rxerr ? state : 0;
+ rx_state = txerr <= rxerr ? state : 0;
+
+- if (likely(skb))
+- can_change_state(dev, cf, tx_state, rx_state);
+- else
+- priv->can.state = state;
++ /* The skb allocation might fail, but can_change_state()
++ * handles cf == NULL.
++ */
++ can_change_state(dev, cf, tx_state, rx_state);
+ if (state == CAN_STATE_BUS_OFF)
+ can_bus_off(dev);
+ }
+--
+2.43.0
+
--- /dev/null
+From c9a882f74a14d9ad77482a52fe6650f6c377ac62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Nov 2024 23:15:51 +0100
+Subject: can: sun4i_can: sun4i_can_err(): fix {rx,tx}_errors statistics
+
+From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+
+[ Upstream commit 595a81988a6fe06eb5849e972c8b9cb21c4e0d54 ]
+
+The sun4i_can_err() function only incremented the receive error counter
+and never the transmit error counter, even if the STA_ERR_DIR flag
+reported that an error had occurred during transmission.
+
+Increment the receive/transmit error counter based on the value of the
+STA_ERR_DIR flag.
+
+Fixes: 0738eff14d81 ("can: Allwinner A10/A20 CAN Controller support - Kernel module")
+Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
+Link: https://patch.msgid.link/20241122221650.633981-11-dario.binacchi@amarulasolutions.com
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/sun4i_can.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
+index 17f94cca93fbc..4311c1f0eafd8 100644
+--- a/drivers/net/can/sun4i_can.c
++++ b/drivers/net/can/sun4i_can.c
+@@ -579,11 +579,9 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
+ /* bus error interrupt */
+ netdev_dbg(dev, "bus error interrupt\n");
+ priv->can.can_stats.bus_error++;
+- stats->rx_errors++;
++ ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
+
+ if (likely(skb)) {
+- ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
+-
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ switch (ecc & SUN4I_STA_MASK_ERR) {
+@@ -601,9 +599,15 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
+ >> 16;
+ break;
+ }
+- /* error occurred during transmission? */
+- if ((ecc & SUN4I_STA_ERR_DIR) == 0)
++ }
++
++ /* error occurred during transmission? */
++ if ((ecc & SUN4I_STA_ERR_DIR) == 0) {
++ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_TX;
++ stats->tx_errors++;
++ } else {
++ stats->rx_errors++;
+ }
+ }
+ if (isrc & SUN4I_INT_ERR_PASSIVE) {
+--
+2.43.0
+
--- /dev/null
+From 6c8c7e0d1ea6e35bfa166451f847b4305ef2514a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 17:39:02 +0300
+Subject: dccp: Fix memory leak in dccp_feat_change_recv
+
+From: Ivan Solodovnikov <solodovnikov.ia@phystech.edu>
+
+[ Upstream commit 22be4727a8f898442066bcac34f8a1ad0bc72e14 ]
+
+If dccp_feat_push_confirm() fails after new value for SP feature was accepted
+without reconciliation ('entry == NULL' branch), memory allocated for that value
+with dccp_feat_clone_sp_val() is never freed.
+
+Here is the kmemleak stack for this:
+
+unreferenced object 0xffff88801d4ab488 (size 8):
+ comm "syz-executor310", pid 1127, jiffies 4295085598 (age 41.666s)
+ hex dump (first 8 bytes):
+ 01 b4 4a 1d 80 88 ff ff ..J.....
+ backtrace:
+ [<00000000db7cabfe>] kmemdup+0x23/0x50 mm/util.c:128
+ [<0000000019b38405>] kmemdup include/linux/string.h:465 [inline]
+ [<0000000019b38405>] dccp_feat_clone_sp_val net/dccp/feat.c:371 [inline]
+ [<0000000019b38405>] dccp_feat_clone_sp_val net/dccp/feat.c:367 [inline]
+ [<0000000019b38405>] dccp_feat_change_recv net/dccp/feat.c:1145 [inline]
+ [<0000000019b38405>] dccp_feat_parse_options+0x1196/0x2180 net/dccp/feat.c:1416
+ [<00000000b1f6d94a>] dccp_parse_options+0xa2a/0x1260 net/dccp/options.c:125
+ [<0000000030d7b621>] dccp_rcv_state_process+0x197/0x13d0 net/dccp/input.c:650
+ [<000000001f74c72e>] dccp_v4_do_rcv+0xf9/0x1a0 net/dccp/ipv4.c:688
+ [<00000000a6c24128>] sk_backlog_rcv include/net/sock.h:1041 [inline]
+ [<00000000a6c24128>] __release_sock+0x139/0x3b0 net/core/sock.c:2570
+ [<00000000cf1f3a53>] release_sock+0x54/0x1b0 net/core/sock.c:3111
+ [<000000008422fa23>] inet_wait_for_connect net/ipv4/af_inet.c:603 [inline]
+ [<000000008422fa23>] __inet_stream_connect+0x5d0/0xf70 net/ipv4/af_inet.c:696
+ [<0000000015b6f64d>] inet_stream_connect+0x53/0xa0 net/ipv4/af_inet.c:735
+ [<0000000010122488>] __sys_connect_file+0x15c/0x1a0 net/socket.c:1865
+ [<00000000b4b70023>] __sys_connect+0x165/0x1a0 net/socket.c:1882
+ [<00000000f4cb3815>] __do_sys_connect net/socket.c:1892 [inline]
+ [<00000000f4cb3815>] __se_sys_connect net/socket.c:1889 [inline]
+ [<00000000f4cb3815>] __x64_sys_connect+0x6e/0xb0 net/socket.c:1889
+ [<00000000e7b1e839>] do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
+ [<0000000055e91434>] entry_SYSCALL_64_after_hwframe+0x67/0xd1
+
+Clean up the allocated memory in case of dccp_feat_push_confirm() failure
+and bail out with an error reset code.
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: e77b8363b2ea ("dccp: Process incoming Change feature-negotiation options")
+Signed-off-by: Ivan Solodovnikov <solodovnikov.ia@phystech.edu>
+Link: https://patch.msgid.link/20241126143902.190853-1-solodovnikov.ia@phystech.edu
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dccp/feat.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/dccp/feat.c b/net/dccp/feat.c
+index 54086bb05c42c..f7554dcdaaba9 100644
+--- a/net/dccp/feat.c
++++ b/net/dccp/feat.c
+@@ -1166,8 +1166,12 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
+ goto not_valid_or_not_known;
+ }
+
+- return dccp_feat_push_confirm(fn, feat, local, &fval);
++ if (dccp_feat_push_confirm(fn, feat, local, &fval)) {
++ kfree(fval.sp.vec);
++ return DCCP_RESET_CODE_TOO_BUSY;
++ }
+
++ return 0;
+ } else if (entry->state == FEAT_UNSTABLE) { /* 6.6.2 */
+ return 0;
+ }
+--
+2.43.0
+
--- /dev/null
+From e3b1aadd004c6b247289cd6089928f35f8d0573b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Sep 2024 09:49:25 -0400
+Subject: drm/amd/display: calculate final viewport before TAP optimization
+
+From: Yihan Zhu <Yihan.Zhu@amd.com>
+
+[ Upstream commit e982310c9ce074e428abc260dc3cba1b1ea62b78 ]
+
+Viewport size excess surface size observed sometime with some timings or
+resizing the MPO video window to cause MPO unsupported. Calculate final
+viewport size first with a 100x100 dummy viewport to get the max TAP
+support and then re-run final viewport calculation if TAP value changed.
+Removed obsolete preliminary viewport calculation for TAP validation.
+
+Reviewed-by: Dmytro Laktyushkin <dmytro.laktyushkin@amd.com>
+Signed-off-by: Yihan Zhu <Yihan.Zhu@amd.com>
+Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: c33a93201ca0 ("drm/amd/display: Ignore scalar validation failure if pipe is phantom")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/core/dc_resource.c | 49 +++++++++----------
+ 1 file changed, 23 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index c7599c40d4be3..df513dbd32bdf 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -765,25 +765,6 @@ static inline void get_vp_scan_direction(
+ *flip_horz_scan_dir = !*flip_horz_scan_dir;
+ }
+
+-/*
+- * This is a preliminary vp size calculation to allow us to check taps support.
+- * The result is completely overridden afterwards.
+- */
+-static void calculate_viewport_size(struct pipe_ctx *pipe_ctx)
+-{
+- struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
+-
+- data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width));
+- data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height));
+- data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width));
+- data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height));
+- if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
+- pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
+- swap(data->viewport.width, data->viewport.height);
+- swap(data->viewport_c.width, data->viewport_c.height);
+- }
+-}
+-
+ static struct rect intersect_rec(const struct rect *r0, const struct rect *r1)
+ {
+ struct rect rec;
+@@ -1468,6 +1449,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
+ const struct rect odm_slice_src = resource_get_odm_slice_src_rect(pipe_ctx);
++ struct scaling_taps temp = {0};
+ bool res = false;
+
+ DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
+@@ -1525,8 +1507,6 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ calculate_recout(pipe_ctx);
+ /* depends on pixel format */
+ calculate_scaling_ratios(pipe_ctx);
+- /* depends on scaling ratios and recout, does not calculate offset yet */
+- calculate_viewport_size(pipe_ctx);
+
+ /*
+ * LB calculations depend on vp size, h/v_active and scaling ratios
+@@ -1547,6 +1527,24 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+
+ pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
+
++ // get TAP value with 100x100 dummy data for max scaling qualify, override
++ // if a new scaling quality required
++ pipe_ctx->plane_res.scl_data.viewport.width = 100;
++ pipe_ctx->plane_res.scl_data.viewport.height = 100;
++ pipe_ctx->plane_res.scl_data.viewport_c.width = 100;
++ pipe_ctx->plane_res.scl_data.viewport_c.height = 100;
++ if (pipe_ctx->plane_res.xfm != NULL)
++ res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
++ pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
++
++ if (pipe_ctx->plane_res.dpp != NULL)
++ res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
++ pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
++
++ temp = pipe_ctx->plane_res.scl_data.taps;
++
++ calculate_inits_and_viewports(pipe_ctx);
++
+ if (pipe_ctx->plane_res.xfm != NULL)
+ res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
+ pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
+@@ -1573,11 +1571,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ &plane_state->scaling_quality);
+ }
+
+- /*
+- * Depends on recout, scaling ratios, h_active and taps
+- * May need to re-check lb size after this in some obscure scenario
+- */
+- if (res)
++ if (res && (pipe_ctx->plane_res.scl_data.taps.v_taps != temp.v_taps ||
++ pipe_ctx->plane_res.scl_data.taps.h_taps != temp.h_taps ||
++ pipe_ctx->plane_res.scl_data.taps.v_taps_c != temp.v_taps_c ||
++ pipe_ctx->plane_res.scl_data.taps.h_taps_c != temp.h_taps_c))
+ calculate_inits_and_viewports(pipe_ctx);
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From a9c76d61a5eabc84637a21287b954a28e3be4827 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Nov 2024 13:18:39 -0500
+Subject: drm/amd/display: Ignore scalar validation failure if pipe is phantom
+
+From: Chris Park <chris.park@amd.com>
+
+[ Upstream commit c33a93201ca07119de90e8c952fbdf65920ab55d ]
+
+[Why]
+There are some pipe scaler validation failure when the pipe is phantom
+and causes crash in DML validation. Since, scalar parameters are not
+as important in phantom pipe and we require this plane to do successful
+MCLK switches, the failure condition can be ignored.
+
+[How]
+Ignore scalar validation failure if the pipe validation is marked as
+phantom pipe.
+
+Cc: stable@vger.kernel.org # 6.11+
+Reviewed-by: Dillon Varone <dillon.varone@amd.com>
+Signed-off-by: Chris Park <chris.park@amd.com>
+Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index df513dbd32bdf..d915020a42958 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -1501,6 +1501,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ res = spl_calculate_scaler_params(spl_in, spl_out);
+ // Convert respective out params from SPL to scaler data
+ translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out);
++
++ /* Ignore scaler failure if pipe context plane is phantom plane */
++ if (!res && plane_state->is_phantom)
++ res = true;
+ } else {
+ #endif
+ /* depends on h_active */
+@@ -1571,6 +1575,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ &plane_state->scaling_quality);
+ }
+
++ /* Ignore scaler failure if pipe context plane is phantom plane */
++ if (!res && plane_state->is_phantom)
++ res = true;
++
+ if (res && (pipe_ctx->plane_res.scl_data.taps.v_taps != temp.v_taps ||
+ pipe_ctx->plane_res.scl_data.taps.h_taps != temp.h_taps ||
+ pipe_ctx->plane_res.scl_data.taps.v_taps_c != temp.v_taps_c ||
+--
+2.43.0
+
--- /dev/null
+From 82076afe3c375a02cf88a5b911dc7322db7ecc54 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Dec 2024 16:33:57 +0100
+Subject: ethtool: Fix wrong mod state in case of verbose and no_mask bitset
+
+From: Kory Maincent <kory.maincent@bootlin.com>
+
+[ Upstream commit 910c4788d6155b2202ec88273376cd7ecdc24f0a ]
+
+A bitset without mask in a _SET request means we want exactly the bits in
+the bitset to be set. This works correctly for compact format but when
+verbose format is parsed, ethnl_update_bitset32_verbose() only sets the
+bits present in the request bitset but does not clear the rest. The commit
+6699170376ab ("ethtool: fix application of verbose no_mask bitset") fixes
+this issue by clearing the whole target bitmap before we start iterating.
+The solution proposed brought an issue with the behavior of the mod
+variable. As the bitset is always cleared the old value will always
+differ to the new value.
+
+Fix it by adding a new function to compare bitmaps and a temporary variable
+which save the state of the old bitmap.
+
+Fixes: 6699170376ab ("ethtool: fix application of verbose no_mask bitset")
+Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20241202153358.1142095-1-kory.maincent@bootlin.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/bitset.c | 48 ++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 44 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/bitset.c b/net/ethtool/bitset.c
+index 0515d6604b3b9..f0883357d12e5 100644
+--- a/net/ethtool/bitset.c
++++ b/net/ethtool/bitset.c
+@@ -425,12 +425,32 @@ static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits,
+ return 0;
+ }
+
++/**
++ * ethnl_bitmap32_equal() - Compare two bitmaps
++ * @map1: first bitmap
++ * @map2: second bitmap
++ * @nbits: bit size to compare
++ *
++ * Return: true if first @nbits are equal, false if not
++ */
++static bool ethnl_bitmap32_equal(const u32 *map1, const u32 *map2,
++ unsigned int nbits)
++{
++ if (memcmp(map1, map2, nbits / 32 * sizeof(u32)))
++ return false;
++ if (nbits % 32 == 0)
++ return true;
++ return !((map1[nbits / 32] ^ map2[nbits / 32]) &
++ ethnl_lower_bits(nbits % 32));
++}
++
+ static int
+ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
+ const struct nlattr *attr, struct nlattr **tb,
+ ethnl_string_array_t names,
+ struct netlink_ext_ack *extack, bool *mod)
+ {
++ u32 *saved_bitmap = NULL;
+ struct nlattr *bit_attr;
+ bool no_mask;
+ int rem;
+@@ -448,8 +468,20 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
+ }
+
+ no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
+- if (no_mask)
+- ethnl_bitmap32_clear(bitmap, 0, nbits, mod);
++ if (no_mask) {
++ unsigned int nwords = DIV_ROUND_UP(nbits, 32);
++ unsigned int nbytes = nwords * sizeof(u32);
++ bool dummy;
++
++ /* The bitmap size is only the size of the map part without
++ * its mask part.
++ */
++ saved_bitmap = kcalloc(nwords, sizeof(u32), GFP_KERNEL);
++ if (!saved_bitmap)
++ return -ENOMEM;
++ memcpy(saved_bitmap, bitmap, nbytes);
++ ethnl_bitmap32_clear(bitmap, 0, nbits, &dummy);
++ }
+
+ nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
+ bool old_val, new_val;
+@@ -458,22 +490,30 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
+ if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) {
+ NL_SET_ERR_MSG_ATTR(extack, bit_attr,
+ "only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS");
++ kfree(saved_bitmap);
+ return -EINVAL;
+ }
+ ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask,
+ names, extack);
+- if (ret < 0)
++ if (ret < 0) {
++ kfree(saved_bitmap);
+ return ret;
++ }
+ old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32));
+ if (new_val != old_val) {
+ if (new_val)
+ bitmap[idx / 32] |= ((u32)1 << (idx % 32));
+ else
+ bitmap[idx / 32] &= ~((u32)1 << (idx % 32));
+- *mod = true;
++ if (!no_mask)
++ *mod = true;
+ }
+ }
+
++ if (no_mask && !ethnl_bitmap32_equal(saved_bitmap, bitmap, nbits))
++ *mod = true;
++
++ kfree(saved_bitmap);
+ return 0;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 24110b6ff71ed7d2c95b776ba4373372964387f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Nov 2024 09:25:55 +0800
+Subject: f2fs: clean up w/ F2FS_{BLK_TO_BYTES,BTYES_TO_BLK}
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 7461f37094180200cb2f98e60ef99a0cea97beec ]
+
+f2fs doesn't support different blksize in one instance, so
+bytes_to_blks() and blks_to_bytes() are equal to F2FS_BYTES_TO_BLK
+and F2FS_BLK_TO_BYTES, let's use F2FS_BYTES_TO_BLK/F2FS_BLK_TO_BYTES
+instead for cleanup.
+
+Reviewed-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 6787a8224585 ("f2fs: fix to requery extent which cross boundary of inquiry")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c | 68 +++++++++++++++++++++-----------------------------
+ 1 file changed, 29 insertions(+), 39 deletions(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 9efe4c00d75bb..0f9728e0d5631 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -1819,16 +1819,6 @@ bool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len)
+ return true;
+ }
+
+-static inline u64 bytes_to_blks(struct inode *inode, u64 bytes)
+-{
+- return (bytes >> inode->i_blkbits);
+-}
+-
+-static inline u64 blks_to_bytes(struct inode *inode, u64 blks)
+-{
+- return (blks << inode->i_blkbits);
+-}
+-
+ static int f2fs_xattr_fiemap(struct inode *inode,
+ struct fiemap_extent_info *fieinfo)
+ {
+@@ -1854,7 +1844,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
+ return err;
+ }
+
+- phys = blks_to_bytes(inode, ni.blk_addr);
++ phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
+ offset = offsetof(struct f2fs_inode, i_addr) +
+ sizeof(__le32) * (DEF_ADDRS_PER_INODE -
+ get_inline_xattr_addrs(inode));
+@@ -1886,7 +1876,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
+ return err;
+ }
+
+- phys = blks_to_bytes(inode, ni.blk_addr);
++ phys = F2FS_BLK_TO_BYTES(ni.blk_addr);
+ len = inode->i_sb->s_blocksize;
+
+ f2fs_put_page(page, 1);
+@@ -1948,16 +1938,16 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ goto out;
+ }
+
+- if (bytes_to_blks(inode, len) == 0)
+- len = blks_to_bytes(inode, 1);
++ if (F2FS_BYTES_TO_BLK(len) == 0)
++ len = F2FS_BLKSIZE;
+
+- start_blk = bytes_to_blks(inode, start);
+- last_blk = bytes_to_blks(inode, start + len - 1);
++ start_blk = F2FS_BYTES_TO_BLK(start);
++ last_blk = F2FS_BYTES_TO_BLK(start + len - 1);
+
+ next:
+ memset(&map, 0, sizeof(map));
+ map.m_lblk = start_blk;
+- map.m_len = bytes_to_blks(inode, len);
++ map.m_len = F2FS_BYTES_TO_BLK(len);
+ map.m_next_pgofs = &next_pgofs;
+ map.m_seg_type = NO_CHECK_TYPE;
+
+@@ -1974,7 +1964,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) {
+ start_blk = next_pgofs;
+
+- if (blks_to_bytes(inode, start_blk) < maxbytes)
++ if (F2FS_BLK_TO_BYTES(start_blk) < maxbytes)
+ goto prep_next;
+
+ flags |= FIEMAP_EXTENT_LAST;
+@@ -2011,14 +2001,14 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ } else if (compr_appended) {
+ unsigned int appended_blks = cluster_size -
+ count_in_cluster + 1;
+- size += blks_to_bytes(inode, appended_blks);
++ size += F2FS_BLK_TO_BYTES(appended_blks);
+ start_blk += appended_blks;
+ compr_cluster = false;
+ } else {
+- logical = blks_to_bytes(inode, start_blk);
++ logical = F2FS_BLK_TO_BYTES(start_blk);
+ phys = __is_valid_data_blkaddr(map.m_pblk) ?
+- blks_to_bytes(inode, map.m_pblk) : 0;
+- size = blks_to_bytes(inode, map.m_len);
++ F2FS_BLK_TO_BYTES(map.m_pblk) : 0;
++ size = F2FS_BLK_TO_BYTES(map.m_len);
+ flags = 0;
+
+ if (compr_cluster) {
+@@ -2026,13 +2016,13 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ count_in_cluster += map.m_len;
+ if (count_in_cluster == cluster_size) {
+ compr_cluster = false;
+- size += blks_to_bytes(inode, 1);
++ size += F2FS_BLKSIZE;
+ }
+ } else if (map.m_flags & F2FS_MAP_DELALLOC) {
+ flags = FIEMAP_EXTENT_UNWRITTEN;
+ }
+
+- start_blk += bytes_to_blks(inode, size);
++ start_blk += F2FS_BYTES_TO_BLK(size);
+ }
+
+ prep_next:
+@@ -2070,7 +2060,7 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
+ struct readahead_control *rac)
+ {
+ struct bio *bio = *bio_ret;
+- const unsigned blocksize = blks_to_bytes(inode, 1);
++ const unsigned int blocksize = F2FS_BLKSIZE;
+ sector_t block_in_file;
+ sector_t last_block;
+ sector_t last_block_in_file;
+@@ -2080,8 +2070,8 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
+
+ block_in_file = (sector_t)index;
+ last_block = block_in_file + nr_pages;
+- last_block_in_file = bytes_to_blks(inode,
+- f2fs_readpage_limit(inode) + blocksize - 1);
++ last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) +
++ blocksize - 1);
+ if (last_block > last_block_in_file)
+ last_block = last_block_in_file;
+
+@@ -2181,7 +2171,7 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
+ struct bio *bio = *bio_ret;
+ unsigned int start_idx = cc->cluster_idx << cc->log_cluster_size;
+ sector_t last_block_in_file;
+- const unsigned blocksize = blks_to_bytes(inode, 1);
++ const unsigned int blocksize = F2FS_BLKSIZE;
+ struct decompress_io_ctx *dic = NULL;
+ struct extent_info ei = {};
+ bool from_dnode = true;
+@@ -2190,8 +2180,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
+
+ f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc));
+
+- last_block_in_file = bytes_to_blks(inode,
+- f2fs_readpage_limit(inode) + blocksize - 1);
++ last_block_in_file = F2FS_BYTES_TO_BLK(f2fs_readpage_limit(inode) +
++ blocksize - 1);
+
+ /* get rid of pages beyond EOF */
+ for (i = 0; i < cc->cluster_size; i++) {
+@@ -3952,7 +3942,7 @@ static int check_swap_activate(struct swap_info_struct *sis,
+ * to be very smart.
+ */
+ cur_lblock = 0;
+- last_lblock = bytes_to_blks(inode, i_size_read(inode));
++ last_lblock = F2FS_BYTES_TO_BLK(i_size_read(inode));
+
+ while (cur_lblock < last_lblock && cur_lblock < sis->max) {
+ struct f2fs_map_blocks map;
+@@ -4195,8 +4185,8 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+ pgoff_t next_pgofs = 0;
+ int err;
+
+- map.m_lblk = bytes_to_blks(inode, offset);
+- map.m_len = bytes_to_blks(inode, offset + length - 1) - map.m_lblk + 1;
++ map.m_lblk = F2FS_BYTES_TO_BLK(offset);
++ map.m_len = F2FS_BYTES_TO_BLK(offset + length - 1) - map.m_lblk + 1;
+ map.m_next_pgofs = &next_pgofs;
+ map.m_seg_type = f2fs_rw_hint_to_seg_type(F2FS_I_SB(inode),
+ inode->i_write_hint);
+@@ -4207,7 +4197,7 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+ if (err)
+ return err;
+
+- iomap->offset = blks_to_bytes(inode, map.m_lblk);
++ iomap->offset = F2FS_BLK_TO_BYTES(map.m_lblk);
+
+ /*
+ * When inline encryption is enabled, sometimes I/O to an encrypted file
+@@ -4227,21 +4217,21 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+ if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR))
+ return -EINVAL;
+
+- iomap->length = blks_to_bytes(inode, map.m_len);
++ iomap->length = F2FS_BLK_TO_BYTES(map.m_len);
+ iomap->type = IOMAP_MAPPED;
+ iomap->flags |= IOMAP_F_MERGED;
+ iomap->bdev = map.m_bdev;
+- iomap->addr = blks_to_bytes(inode, map.m_pblk);
++ iomap->addr = F2FS_BLK_TO_BYTES(map.m_pblk);
+ } else {
+ if (flags & IOMAP_WRITE)
+ return -ENOTBLK;
+
+ if (map.m_pblk == NULL_ADDR) {
+- iomap->length = blks_to_bytes(inode, next_pgofs) -
+- iomap->offset;
++ iomap->length = F2FS_BLK_TO_BYTES(next_pgofs) -
++ iomap->offset;
+ iomap->type = IOMAP_HOLE;
+ } else if (map.m_pblk == NEW_ADDR) {
+- iomap->length = blks_to_bytes(inode, map.m_len);
++ iomap->length = F2FS_BLK_TO_BYTES(map.m_len);
+ iomap->type = IOMAP_UNWRITTEN;
+ } else {
+ f2fs_bug_on(F2FS_I_SB(inode), 1);
+--
+2.43.0
+
--- /dev/null
+From 81e2825b514f3afa828b9682bda351ebc4a2bc06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Nov 2024 09:25:56 +0800
+Subject: f2fs: fix to adjust appropriate length for fiemap
+
+From: Zhiguo Niu <zhiguo.niu@unisoc.com>
+
+[ Upstream commit 77569f785c8624fa4189795fb52e635a973672e5 ]
+
+If user give a file size as "length" parameter for fiemap
+operations, but if this size is non-block size aligned,
+it will show 2 segments fiemap results even this whole file
+is contiguous on disk, such as the following results:
+
+ ./f2fs_io fiemap 0 19034 ylog/analyzer.py
+Fiemap: offset = 0 len = 19034
+ logical addr. physical addr. length flags
+0 0000000000000000 0000000020baa000 0000000000004000 00001000
+1 0000000000004000 0000000020bae000 0000000000001000 00001001
+
+after this patch:
+./f2fs_io fiemap 0 19034 ylog/analyzer.py
+Fiemap: offset = 0 len = 19034
+ logical addr. physical addr. length flags
+0 0000000000000000 00000000315f3000 0000000000005000 00001001
+
+Signed-off-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 6787a8224585 ("f2fs: fix to requery extent which cross boundary of inquiry")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c | 6 +++---
+ include/linux/f2fs_fs.h | 1 +
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 0f9728e0d5631..a126fecc808c4 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -1938,12 +1938,12 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ goto out;
+ }
+
+- if (F2FS_BYTES_TO_BLK(len) == 0)
+- len = F2FS_BLKSIZE;
+-
+ start_blk = F2FS_BYTES_TO_BLK(start);
+ last_blk = F2FS_BYTES_TO_BLK(start + len - 1);
+
++ if (len & F2FS_BLKSIZE_MASK)
++ len = round_up(len, F2FS_BLKSIZE);
++
+ next:
+ memset(&map, 0, sizeof(map));
+ map.m_lblk = start_blk;
+diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
+index 3b2ad444c002e..c24f8bc01045d 100644
+--- a/include/linux/f2fs_fs.h
++++ b/include/linux/f2fs_fs.h
+@@ -24,6 +24,7 @@
+ #define NEW_ADDR ((block_t)-1) /* used as block_t addresses */
+ #define COMPRESS_ADDR ((block_t)-2) /* used as compressed data flag */
+
++#define F2FS_BLKSIZE_MASK (F2FS_BLKSIZE - 1)
+ #define F2FS_BYTES_TO_BLK(bytes) ((unsigned long long)(bytes) >> F2FS_BLKSIZE_BITS)
+ #define F2FS_BLK_TO_BYTES(blk) ((unsigned long long)(blk) << F2FS_BLKSIZE_BITS)
+ #define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1)
+--
+2.43.0
+
--- /dev/null
+From 0e1b4e1c9387f614dd2687737983a70ced92b42f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Nov 2024 09:25:57 +0800
+Subject: f2fs: fix to requery extent which cross boundary of inquiry
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 6787a82245857271133b63ae7f72f1dc9f29e985 ]
+
+dd if=/dev/zero of=file bs=4k count=5
+xfs_io file -c "fiemap -v 2 16384"
+file:
+ EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS
+ 0: [0..31]: 139272..139303 32 0x1000
+ 1: [32..39]: 139304..139311 8 0x1001
+xfs_io file -c "fiemap -v 0 16384"
+file:
+ EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS
+ 0: [0..31]: 139272..139303 32 0x1000
+xfs_io file -c "fiemap -v 0 16385"
+file:
+ EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS
+ 0: [0..39]: 139272..139311 40 0x1001
+
+There are two problems:
+- continuous extent is split to two
+- FIEMAP_EXTENT_LAST is missing in last extent
+
+The root cause is: if upper boundary of inquiry crosses extent,
+f2fs_map_blocks() will truncate length of returned extent to
+F2FS_BYTES_TO_BLK(len), and also, it will stop to query latter
+extent or hole to make sure current extent is last or not.
+
+In order to fix this issue, once we found an extent locates
+in the end of inquiry range by f2fs_map_blocks(), we need to
+expand inquiry range to requiry.
+
+Cc: stable@vger.kernel.org
+Fixes: 7f63eb77af7b ("f2fs: report unwritten area in f2fs_fiemap")
+Reported-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/data.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index a126fecc808c4..da0960d496ae0 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -1896,7 +1896,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ u64 start, u64 len)
+ {
+ struct f2fs_map_blocks map;
+- sector_t start_blk, last_blk;
++ sector_t start_blk, last_blk, blk_len, max_len;
+ pgoff_t next_pgofs;
+ u64 logical = 0, phys = 0, size = 0;
+ u32 flags = 0;
+@@ -1940,14 +1940,13 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+
+ start_blk = F2FS_BYTES_TO_BLK(start);
+ last_blk = F2FS_BYTES_TO_BLK(start + len - 1);
+-
+- if (len & F2FS_BLKSIZE_MASK)
+- len = round_up(len, F2FS_BLKSIZE);
++ blk_len = last_blk - start_blk + 1;
++ max_len = F2FS_BYTES_TO_BLK(maxbytes) - start_blk;
+
+ next:
+ memset(&map, 0, sizeof(map));
+ map.m_lblk = start_blk;
+- map.m_len = F2FS_BYTES_TO_BLK(len);
++ map.m_len = blk_len;
+ map.m_next_pgofs = &next_pgofs;
+ map.m_seg_type = NO_CHECK_TYPE;
+
+@@ -1970,6 +1969,17 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+ flags |= FIEMAP_EXTENT_LAST;
+ }
+
++ /*
++ * current extent may cross boundary of inquiry, increase len to
++ * requery.
++ */
++ if (!compr_cluster && (map.m_flags & F2FS_MAP_MAPPED) &&
++ map.m_lblk + map.m_len - 1 == last_blk &&
++ blk_len != max_len) {
++ blk_len = max_len;
++ goto next;
++ }
++
+ compr_appended = false;
+ /* In a case of compressed cluster, append this to the last extent */
+ if (compr_cluster && ((map.m_flags & F2FS_MAP_DELALLOC) ||
+--
+2.43.0
+
--- /dev/null
+From 11ed063191ef1aef9e1f0d140870d3bd31f79bb4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 18:21:21 +0000
+Subject: geneve: do not assume mac header is set in geneve_xmit_skb()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 8588c99c7d47448fcae39e3227d6e2bb97aad86d ]
+
+We should not assume mac header is set in output path.
+
+Use skb_eth_hdr() instead of eth_hdr() to fix the issue.
+
+sysbot reported the following :
+
+ WARNING: CPU: 0 PID: 11635 at include/linux/skbuff.h:3052 skb_mac_header include/linux/skbuff.h:3052 [inline]
+ WARNING: CPU: 0 PID: 11635 at include/linux/skbuff.h:3052 eth_hdr include/linux/if_ether.h:24 [inline]
+ WARNING: CPU: 0 PID: 11635 at include/linux/skbuff.h:3052 geneve_xmit_skb drivers/net/geneve.c:898 [inline]
+ WARNING: CPU: 0 PID: 11635 at include/linux/skbuff.h:3052 geneve_xmit+0x4c38/0x5730 drivers/net/geneve.c:1039
+Modules linked in:
+CPU: 0 UID: 0 PID: 11635 Comm: syz.4.1423 Not tainted 6.12.0-syzkaller-10296-gaaf20f870da0 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
+ RIP: 0010:skb_mac_header include/linux/skbuff.h:3052 [inline]
+ RIP: 0010:eth_hdr include/linux/if_ether.h:24 [inline]
+ RIP: 0010:geneve_xmit_skb drivers/net/geneve.c:898 [inline]
+ RIP: 0010:geneve_xmit+0x4c38/0x5730 drivers/net/geneve.c:1039
+Code: 21 c6 02 e9 35 d4 ff ff e8 a5 48 4c fb 90 0f 0b 90 e9 fd f5 ff ff e8 97 48 4c fb 90 0f 0b 90 e9 d8 f5 ff ff e8 89 48 4c fb 90 <0f> 0b 90 e9 41 e4 ff ff e8 7b 48 4c fb 90 0f 0b 90 e9 cd e7 ff ff
+RSP: 0018:ffffc90003b2f870 EFLAGS: 00010283
+RAX: 000000000000037a RBX: 000000000000ffff RCX: ffffc9000dc3d000
+RDX: 0000000000080000 RSI: ffffffff86428417 RDI: 0000000000000003
+RBP: ffffc90003b2f9f0 R08: 0000000000000003 R09: 000000000000ffff
+R10: 000000000000ffff R11: 0000000000000002 R12: ffff88806603c000
+R13: 0000000000000000 R14: ffff8880685b2780 R15: 0000000000000e23
+FS: 00007fdc2deed6c0(0000) GS:ffff8880b8600000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000001b30a1dff8 CR3: 0000000056b8c000 CR4: 00000000003526f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ __netdev_start_xmit include/linux/netdevice.h:5002 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5011 [inline]
+ __dev_direct_xmit+0x58a/0x720 net/core/dev.c:4490
+ dev_direct_xmit include/linux/netdevice.h:3181 [inline]
+ packet_xmit+0x1e4/0x360 net/packet/af_packet.c:285
+ packet_snd net/packet/af_packet.c:3146 [inline]
+ packet_sendmsg+0x2700/0x5660 net/packet/af_packet.c:3178
+ sock_sendmsg_nosec net/socket.c:711 [inline]
+ __sock_sendmsg net/socket.c:726 [inline]
+ __sys_sendto+0x488/0x4f0 net/socket.c:2197
+ __do_sys_sendto net/socket.c:2204 [inline]
+ __se_sys_sendto net/socket.c:2200 [inline]
+ __x64_sys_sendto+0xe0/0x1c0 net/socket.c:2200
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: a025fb5f49ad ("geneve: Allow configuration of DF behaviour")
+Reported-by: syzbot+3ec5271486d7cb2d242a@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/674f4b72.050a0220.17bd51.004a.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20241203182122.2725517-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/geneve.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 7f611c74eb629..ba15a0a4ce629 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -895,7 +895,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ if (geneve->cfg.df == GENEVE_DF_SET) {
+ df = htons(IP_DF);
+ } else if (geneve->cfg.df == GENEVE_DF_INHERIT) {
+- struct ethhdr *eth = eth_hdr(skb);
++ struct ethhdr *eth = skb_eth_hdr(skb);
+
+ if (ntohs(eth->h_proto) == ETH_P_IPV6) {
+ df = htons(IP_DF);
+--
+2.43.0
+
--- /dev/null
+From 3234dc21a42450e21e6211f247c7eded54678f19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Nov 2024 17:18:22 +0800
+Subject: gpio: grgpio: Add NULL check in grgpio_probe
+
+From: Charles Han <hanchunchao@inspur.com>
+
+[ Upstream commit 050b23d081da0f29474de043e9538c1f7a351b3b ]
+
+devm_kasprintf() can return a NULL pointer on failure,but this
+returned value in grgpio_probe is not checked.
+Add NULL check in grgpio_probe, to handle kernel NULL
+pointer dereference error.
+
+Cc: stable@vger.kernel.org
+Fixes: 7eb6ce2f2723 ("gpio: Convert to using %pOF instead of full_name")
+Signed-off-by: Charles Han <hanchunchao@inspur.com>
+Link: https://lore.kernel.org/r/20241114091822.78199-1-hanchunchao@inspur.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-grgpio.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
+index 2d16ce13a804d..620793740c668 100644
+--- a/drivers/gpio/gpio-grgpio.c
++++ b/drivers/gpio/gpio-grgpio.c
+@@ -362,6 +362,9 @@ static int grgpio_probe(struct platform_device *ofdev)
+ gc->owner = THIS_MODULE;
+ gc->to_irq = grgpio_to_irq;
+ gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
++ if (!gc->label)
++ return -ENOMEM;
++
+ gc->base = -1;
+
+ err = of_property_read_u32(np, "nbits", &prop);
+--
+2.43.0
+
--- /dev/null
+From e7fb56a1fb8b5a0e1fff7e6989d2385e4b5ba398 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 15:18:31 +0200
+Subject: gpio: grgpio: use a helper variable to store the address of
+ ofdev->dev
+
+From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+[ Upstream commit d036ae41cebdfae92666024163c109b8fef516fa ]
+
+Instead of dereferencing the platform device pointer repeatedly, just
+store its address in a helper variable.
+
+Link: https://lore.kernel.org/r/20241015131832.44678-3-brgl@bgdev.pl
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Stable-dep-of: 050b23d081da ("gpio: grgpio: Add NULL check in grgpio_probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-grgpio.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c
+index 017c7170eb57c..2d16ce13a804d 100644
+--- a/drivers/gpio/gpio-grgpio.c
++++ b/drivers/gpio/gpio-grgpio.c
+@@ -328,6 +328,7 @@ static const struct irq_domain_ops grgpio_irq_domain_ops = {
+ static int grgpio_probe(struct platform_device *ofdev)
+ {
+ struct device_node *np = ofdev->dev.of_node;
++ struct device *dev = &ofdev->dev;
+ void __iomem *regs;
+ struct gpio_chip *gc;
+ struct grgpio_priv *priv;
+@@ -337,7 +338,7 @@ static int grgpio_probe(struct platform_device *ofdev)
+ int size;
+ int i;
+
+- priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL);
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+@@ -346,28 +347,28 @@ static int grgpio_probe(struct platform_device *ofdev)
+ return PTR_ERR(regs);
+
+ gc = &priv->gc;
+- err = bgpio_init(gc, &ofdev->dev, 4, regs + GRGPIO_DATA,
++ err = bgpio_init(gc, dev, 4, regs + GRGPIO_DATA,
+ regs + GRGPIO_OUTPUT, NULL, regs + GRGPIO_DIR, NULL,
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+ if (err) {
+- dev_err(&ofdev->dev, "bgpio_init() failed\n");
++ dev_err(dev, "bgpio_init() failed\n");
+ return err;
+ }
+
+ priv->regs = regs;
+ priv->imask = gc->read_reg(regs + GRGPIO_IMASK);
+- priv->dev = &ofdev->dev;
++ priv->dev = dev;
+
+ gc->owner = THIS_MODULE;
+ gc->to_irq = grgpio_to_irq;
+- gc->label = devm_kasprintf(&ofdev->dev, GFP_KERNEL, "%pOF", np);
++ gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
+ gc->base = -1;
+
+ err = of_property_read_u32(np, "nbits", &prop);
+ if (err || prop <= 0 || prop > GRGPIO_MAX_NGPIO) {
+ gc->ngpio = GRGPIO_MAX_NGPIO;
+- dev_dbg(&ofdev->dev,
+- "No or invalid nbits property: assume %d\n", gc->ngpio);
++ dev_dbg(dev, "No or invalid nbits property: assume %d\n",
++ gc->ngpio);
+ } else {
+ gc->ngpio = prop;
+ }
+@@ -379,7 +380,7 @@ static int grgpio_probe(struct platform_device *ofdev)
+ irqmap = (s32 *)of_get_property(np, "irqmap", &size);
+ if (irqmap) {
+ if (size < gc->ngpio) {
+- dev_err(&ofdev->dev,
++ dev_err(dev,
+ "irqmap shorter than ngpio (%d < %d)\n",
+ size, gc->ngpio);
+ return -EINVAL;
+@@ -389,7 +390,7 @@ static int grgpio_probe(struct platform_device *ofdev)
+ &grgpio_irq_domain_ops,
+ priv);
+ if (!priv->domain) {
+- dev_err(&ofdev->dev, "Could not add irq domain\n");
++ dev_err(dev, "Could not add irq domain\n");
+ return -EINVAL;
+ }
+
+@@ -419,13 +420,13 @@ static int grgpio_probe(struct platform_device *ofdev)
+
+ err = gpiochip_add_data(gc, priv);
+ if (err) {
+- dev_err(&ofdev->dev, "Could not add gpiochip\n");
++ dev_err(dev, "Could not add gpiochip\n");
+ if (priv->domain)
+ irq_domain_remove(priv->domain);
+ return err;
+ }
+
+- dev_info(&ofdev->dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
++ dev_info(dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
+ priv->regs, gc->base, gc->ngpio, priv->domain ? "on" : "off");
+
+ return 0;
+--
+2.43.0
+
--- /dev/null
+From f8d72905f920016f40b117b002896f4798e031a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 11:45:07 -0400
+Subject: i3c: master: Extend address status bit to 4 and add
+ I3C_ADDR_SLOT_EXT_DESIRED
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 2f552fa280590e61bd3dbe66a7b54b99caa642a4 ]
+
+Extend the address status bit to 4 and introduce the
+I3C_ADDR_SLOT_EXT_DESIRED macro to indicate that a device prefers a
+specific address. This is generally set by the 'assigned-address' in the
+device tree source (dts) file.
+
+ ┌────┬─────────────┬───┬─────────┬───┐
+ │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA │ T ├────┐
+ └────┴─────────────┴───┴─────────┴───┘ │
+ ┌─────────────────────────────────────────┘
+ │ ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────┐
+ └─►│Sr│7'h7E RnW=1 │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│
+ └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘
+
+Some master controllers (such as HCI) need to prepare the entire above
+transaction before sending it out to the I3C bus. This means that a 7-bit
+dynamic address needs to be allocated before knowing the target device's
+UID information.
+
+However, some I3C targets may request specific addresses (called as
+"init_dyn_addr"), which is typically specified by the DT-'s
+assigned-address property. Lower addresses having higher IBI priority. If
+it is available, i3c_bus_get_free_addr() preferably return a free address
+that is not in the list of desired addresses (called as "init_dyn_addr").
+This allows the device with the "init_dyn_addr" to switch to its
+"init_dyn_addr" when it hot-joins the I3C bus. Otherwise, if the
+"init_dyn_addr" is already in use by another I3C device, the target device
+will not be able to switch to its desired address.
+
+If the previous step fails, fallback returning one of the remaining
+unassigned address, regardless of its state in the desired list.
+
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20241021-i3c_dts_assign-v8-2-4098b8bde01e@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 851bd21cdb55 ("i3c: master: Fix dynamic address leak when 'assigned-address' is present")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 65 +++++++++++++++++++++++++++++++-------
+ include/linux/i3c/master.h | 7 ++--
+ 2 files changed, 59 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index 53f3959e602c8..c022b93cd592e 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -345,7 +345,7 @@ const struct bus_type i3c_bus_type = {
+ EXPORT_SYMBOL_GPL(i3c_bus_type);
+
+ static enum i3c_addr_slot_status
+-i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
++i3c_bus_get_addr_slot_status_mask(struct i3c_bus *bus, u16 addr, u32 mask)
+ {
+ unsigned long status;
+ int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
+@@ -356,11 +356,17 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+ status = bus->addrslots[bitpos / BITS_PER_LONG];
+ status >>= bitpos % BITS_PER_LONG;
+
+- return status & I3C_ADDR_SLOT_STATUS_MASK;
++ return status & mask;
+ }
+
+-static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
+- enum i3c_addr_slot_status status)
++static enum i3c_addr_slot_status
++i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
++{
++ return i3c_bus_get_addr_slot_status_mask(bus, addr, I3C_ADDR_SLOT_STATUS_MASK);
++}
++
++static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,
++ enum i3c_addr_slot_status status, u32 mask)
+ {
+ int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
+ unsigned long *ptr;
+@@ -369,9 +375,14 @@ static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
+ return;
+
+ ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
+- *ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
+- (bitpos % BITS_PER_LONG));
+- *ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
++ *ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));
++ *ptr |= ((unsigned long)status & mask) << (bitpos % BITS_PER_LONG);
++}
++
++static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
++ enum i3c_addr_slot_status status)
++{
++ i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);
+ }
+
+ static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
+@@ -383,13 +394,44 @@ static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
+ return status == I3C_ADDR_SLOT_FREE;
+ }
+
++/*
++ * ┌────┬─────────────┬───┬─────────┬───┐
++ * │S/Sr│ 7'h7E RnW=0 │ACK│ ENTDAA │ T ├────┐
++ * └────┴─────────────┴───┴─────────┴───┘ │
++ * ┌─────────────────────────────────────────┘
++ * │ ┌──┬─────────────┬───┬─────────────────┬────────────────┬───┬─────────┐
++ * └─►│Sr│7'h7E RnW=1 │ACK│48bit UID BCR DCR│Assign 7bit Addr│PAR│ ACK/NACK│
++ * └──┴─────────────┴───┴─────────────────┴────────────────┴───┴─────────┘
++ * Some master controllers (such as HCI) need to prepare the entire above transaction before
++ * sending it out to the I3C bus. This means that a 7-bit dynamic address needs to be allocated
++ * before knowing the target device's UID information.
++ *
++ * However, some I3C targets may request specific addresses (called as "init_dyn_addr"), which is
++ * typically specified by the DT-'s assigned-address property. Lower addresses having higher IBI
++ * priority. If it is available, i3c_bus_get_free_addr() preferably return a free address that is
++ * not in the list of desired addresses (called as "init_dyn_addr"). This allows the device with
++ * the "init_dyn_addr" to switch to its "init_dyn_addr" when it hot-joins the I3C bus. Otherwise,
++ * if the "init_dyn_addr" is already in use by another I3C device, the target device will not be
++ * able to switch to its desired address.
++ *
++ * If the previous step fails, fallback returning one of the remaining unassigned address,
++ * regardless of its state in the desired list.
++ */
+ static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
+ {
+ enum i3c_addr_slot_status status;
+ u8 addr;
+
+ for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
+- status = i3c_bus_get_addr_slot_status(bus, addr);
++ status = i3c_bus_get_addr_slot_status_mask(bus, addr,
++ I3C_ADDR_SLOT_EXT_STATUS_MASK);
++ if (status == I3C_ADDR_SLOT_FREE)
++ return addr;
++ }
++
++ for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
++ status = i3c_bus_get_addr_slot_status_mask(bus, addr,
++ I3C_ADDR_SLOT_STATUS_MASK);
+ if (status == I3C_ADDR_SLOT_FREE)
+ return addr;
+ }
+@@ -1918,9 +1960,10 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+ goto err_rstdaa;
+ }
+
+- i3c_bus_set_addr_slot_status(&master->bus,
+- i3cboardinfo->init_dyn_addr,
+- I3C_ADDR_SLOT_I3C_DEV);
++ i3c_bus_set_addr_slot_status_mask(&master->bus,
++ i3cboardinfo->init_dyn_addr,
++ I3C_ADDR_SLOT_I3C_DEV | I3C_ADDR_SLOT_EXT_DESIRED,
++ I3C_ADDR_SLOT_EXT_STATUS_MASK);
+
+ /*
+ * Only try to create/attach devices that have a static
+diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
+index 2100547b2d8d2..6e5328c6c6afd 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -298,7 +298,8 @@ enum i3c_open_drain_speed {
+ * @I3C_ADDR_SLOT_I2C_DEV: address is assigned to an I2C device
+ * @I3C_ADDR_SLOT_I3C_DEV: address is assigned to an I3C device
+ * @I3C_ADDR_SLOT_STATUS_MASK: address slot mask
+- *
++ * @I3C_ADDR_SLOT_EXT_DESIRED: the bitmask represents addresses that are preferred by some devices,
++ * such as the "assigned-address" property in a device tree source.
+ * On an I3C bus, addresses are assigned dynamically, and we need to know which
+ * addresses are free to use and which ones are already assigned.
+ *
+@@ -311,9 +312,11 @@ enum i3c_addr_slot_status {
+ I3C_ADDR_SLOT_I2C_DEV,
+ I3C_ADDR_SLOT_I3C_DEV,
+ I3C_ADDR_SLOT_STATUS_MASK = 3,
++ I3C_ADDR_SLOT_EXT_STATUS_MASK = 7,
++ I3C_ADDR_SLOT_EXT_DESIRED = BIT(2),
+ };
+
+-#define I3C_ADDR_SLOT_STATUS_BITS 2
++#define I3C_ADDR_SLOT_STATUS_BITS 4
+
+ /**
+ * struct i3c_bus - I3C bus object
+--
+2.43.0
+
--- /dev/null
+From d1cc100971a6b2baa70eb81eef75000f574c0545 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 11:45:08 -0400
+Subject: i3c: master: Fix dynamic address leak when 'assigned-address' is
+ present
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 851bd21cdb55e727ab29280bc9f6b678164f802a ]
+
+If the DTS contains 'assigned-address', a dynamic address leak occurs
+during hotjoin events.
+
+Assume a device have assigned-address 0xb.
+ - Device issue Hotjoin
+ - Call i3c_master_do_daa()
+ - Call driver xxx_do_daa()
+ - Call i3c_master_get_free_addr() to get dynamic address 0x9
+ - i3c_master_add_i3c_dev_locked(0x9)
+ - expected_dyn_addr = newdev->boardinfo->init_dyn_addr (0xb);
+ - i3c_master_reattach_i3c_dev(newdev(0xb), old_dyn_addr(0x9));
+ - if (dev->info.dyn_addr != old_dyn_addr &&
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0xb != 0x9 -> TRUE
+ (!dev->boardinfo ||
+ ^^^^^^^^^^^^^^^ -> FALSE
+ dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 0xb != 0xb -> FALSE
+ ...
+ i3c_bus_set_addr_slot_status(&master->bus, old_dyn_addr,
+ I3C_ADDR_SLOT_FREE);
+ ^^^
+ This will be skipped. So old_dyn_addr never free
+ }
+
+ - i3c_master_get_free_addr() will return increased sequence number.
+
+Remove dev->info.dyn_addr != dev->boardinfo->init_dyn_addr condition check.
+dev->info.dyn_addr should be checked before calling this function because
+i3c_master_setnewda_locked() has already been called and the target device
+has already accepted dyn_addr. It is too late to check if dyn_addr is free
+in i3c_master_reattach_i3c_dev().
+
+Add check to ensure expected_dyn_addr is free before
+i3c_master_setnewda_locked().
+
+Fixes: cc3a392d69b6 ("i3c: master: fix for SETDASA and DAA process")
+Cc: stable@kernel.org
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20241021-i3c_dts_assign-v8-3-4098b8bde01e@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index c022b93cd592e..770908cff2434 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -1548,16 +1548,9 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
+ u8 old_dyn_addr)
+ {
+ struct i3c_master_controller *master = i3c_dev_get_master(dev);
+- enum i3c_addr_slot_status status;
+ int ret;
+
+- if (dev->info.dyn_addr != old_dyn_addr &&
+- (!dev->boardinfo ||
+- dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
+- status = i3c_bus_get_addr_slot_status(&master->bus,
+- dev->info.dyn_addr);
+- if (status != I3C_ADDR_SLOT_FREE)
+- return -EBUSY;
++ if (dev->info.dyn_addr != old_dyn_addr) {
+ i3c_bus_set_addr_slot_status(&master->bus,
+ dev->info.dyn_addr,
+ I3C_ADDR_SLOT_I3C_DEV);
+@@ -1960,9 +1953,10 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+ goto err_rstdaa;
+ }
+
++ /* Do not mark as occupied until real device exist in bus */
+ i3c_bus_set_addr_slot_status_mask(&master->bus,
+ i3cboardinfo->init_dyn_addr,
+- I3C_ADDR_SLOT_I3C_DEV | I3C_ADDR_SLOT_EXT_DESIRED,
++ I3C_ADDR_SLOT_EXT_DESIRED,
+ I3C_ADDR_SLOT_EXT_STATUS_MASK);
+
+ /*
+@@ -2131,7 +2125,8 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
+ else
+ expected_dyn_addr = newdev->info.dyn_addr;
+
+- if (newdev->info.dyn_addr != expected_dyn_addr) {
++ if (newdev->info.dyn_addr != expected_dyn_addr &&
++ i3c_bus_get_addr_slot_status(&master->bus, expected_dyn_addr) == I3C_ADDR_SLOT_FREE) {
+ /*
+ * Try to apply the expected dynamic address. If it fails, keep
+ * the address assigned by the master.
+--
+2.43.0
+
--- /dev/null
+From 9427eccbcf87aa692cc332284dca70e8387c2a47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 11:45:06 -0400
+Subject: i3c: master: Replace hard code 2 with macro I3C_ADDR_SLOT_STATUS_BITS
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 16aed0a6520ba01b7d22c32e193fc1ec674f92d4 ]
+
+Replace the hardcoded value 2, which indicates 2 bits for I3C address
+status, with the predefined macro I3C_ADDR_SLOT_STATUS_BITS.
+
+Improve maintainability and extensibility of the code.
+
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20241021-i3c_dts_assign-v8-1-4098b8bde01e@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 851bd21cdb55 ("i3c: master: Fix dynamic address leak when 'assigned-address' is present")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 4 ++--
+ include/linux/i3c/master.h | 4 +++-
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index da83c49223b33..53f3959e602c8 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -348,7 +348,7 @@ static enum i3c_addr_slot_status
+ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+ {
+ unsigned long status;
+- int bitpos = addr * 2;
++ int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
+
+ if (addr > I2C_MAX_ADDR)
+ return I3C_ADDR_SLOT_RSVD;
+@@ -362,7 +362,7 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+ static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
+ enum i3c_addr_slot_status status)
+ {
+- int bitpos = addr * 2;
++ int bitpos = addr * I3C_ADDR_SLOT_STATUS_BITS;
+ unsigned long *ptr;
+
+ if (addr > I2C_MAX_ADDR)
+diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
+index 2a1ed05d5782a..2100547b2d8d2 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -313,6 +313,8 @@ enum i3c_addr_slot_status {
+ I3C_ADDR_SLOT_STATUS_MASK = 3,
+ };
+
++#define I3C_ADDR_SLOT_STATUS_BITS 2
++
+ /**
+ * struct i3c_bus - I3C bus object
+ * @cur_master: I3C master currently driving the bus. Since I3C is multi-master
+@@ -354,7 +356,7 @@ enum i3c_addr_slot_status {
+ struct i3c_bus {
+ struct i3c_dev_desc *cur_master;
+ int id;
+- unsigned long addrslots[((I2C_MAX_ADDR + 1) * 2) / BITS_PER_LONG];
++ unsigned long addrslots[((I2C_MAX_ADDR + 1) * I3C_ADDR_SLOT_STATUS_BITS) / BITS_PER_LONG];
+ enum i3c_bus_mode mode;
+ struct {
+ unsigned long i3c;
+--
+2.43.0
+
--- /dev/null
+From 8cab8d6d363870405cb691fe0b0e6b3bb91282a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Sep 2024 20:36:22 +0200
+Subject: ice: fix PHY Clock Recovery availability check
+
+From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+
+[ Upstream commit 01fd68e54794fb1e1fe95be38facf9bbafee9ca3 ]
+
+To check if PHY Clock Recovery mechanic is available for a device, there
+is a need to verify if given PHY is available within the netlist, but the
+netlist node type used for the search is wrong, also the search context
+shall be specified.
+
+Modify the search function to allow specifying the context in the
+search.
+
+Use the PHY node type instead of CLOCK CONTROLLER type, also use proper
+search context which for PHY search is PORT, as defined in E810
+Datasheet [1] ('3.3.8.2.4 Node Part Number and Node Options (0x0003)' and
+'Table 3-105. Program Topology Device NVM Admin Command').
+
+[1] https://cdrdv2.intel.com/v1/dl/getContent/613875?explicitVersion=true
+
+Fixes: 91e43ca0090b ("ice: fix linking when CONFIG_PTP_1588_CLOCK=n")
+Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_common.c | 25 ++++++++++++++-------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
+index 009716a12a26a..f1324e25b2af1 100644
+--- a/drivers/net/ethernet/intel/ice/ice_common.c
++++ b/drivers/net/ethernet/intel/ice/ice_common.c
+@@ -542,7 +542,8 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
+ /**
+ * ice_find_netlist_node
+ * @hw: pointer to the hw struct
+- * @node_type_ctx: type of netlist node to look for
++ * @node_type: type of netlist node to look for
++ * @ctx: context of the search
+ * @node_part_number: node part number to look for
+ * @node_handle: output parameter if node found - optional
+ *
+@@ -552,10 +553,12 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
+ * valid if the function returns zero, and should be ignored on any non-zero
+ * return value.
+ *
+- * Returns: 0 if the node is found, -ENOENT if no handle was found, and
+- * a negative error code on failure to access the AQ.
++ * Return:
++ * * 0 if the node is found,
++ * * -ENOENT if no handle was found,
++ * * negative error code on failure to access the AQ.
+ */
+-static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
++static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type, u8 ctx,
+ u8 node_part_number, u16 *node_handle)
+ {
+ u8 idx;
+@@ -566,8 +569,8 @@ static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
+ int status;
+
+ cmd.addr.topo_params.node_type_ctx =
+- FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M,
+- node_type_ctx);
++ FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, node_type) |
++ FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ctx);
+ cmd.addr.topo_params.index = idx;
+
+ status = ice_aq_get_netlist_node(hw, &cmd,
+@@ -2726,9 +2729,11 @@ bool ice_is_pf_c827(struct ice_hw *hw)
+ */
+ bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw)
+ {
+- if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
++ if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY,
++ ICE_AQC_LINK_TOPO_NODE_CTX_PORT,
+ ICE_AQC_GET_LINK_TOPO_NODE_NR_C827, NULL) &&
+- ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
++ ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY,
++ ICE_AQC_LINK_TOPO_NODE_CTX_PORT,
+ ICE_AQC_GET_LINK_TOPO_NODE_NR_E822_PHY, NULL))
+ return false;
+
+@@ -2744,6 +2749,7 @@ bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw)
+ bool ice_is_clock_mux_in_netlist(struct ice_hw *hw)
+ {
+ if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX,
++ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
+ ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX,
+ NULL))
+ return false;
+@@ -2764,12 +2770,14 @@ bool ice_is_clock_mux_in_netlist(struct ice_hw *hw)
+ bool ice_is_cgu_in_netlist(struct ice_hw *hw)
+ {
+ if (!ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
++ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
+ ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032,
+ NULL)) {
+ hw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032;
+ return true;
+ } else if (!ice_find_netlist_node(hw,
+ ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
++ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
+ ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384,
+ NULL)) {
+ hw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384;
+@@ -2788,6 +2796,7 @@ bool ice_is_cgu_in_netlist(struct ice_hw *hw)
+ bool ice_is_gps_in_netlist(struct ice_hw *hw)
+ {
+ if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_GPS,
++ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
+ ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_GPS, NULL))
+ return false;
+
+--
+2.43.0
+
--- /dev/null
+From 5838a151a5ecfdced0e22e03797f109ac7de2ab1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Nov 2024 13:25:37 +0100
+Subject: ice: fix PHY timestamp extraction for ETH56G
+
+From: Przemyslaw Korba <przemyslaw.korba@intel.com>
+
+[ Upstream commit 3214fae85e8336fe13e20cf78fc9b6a668bdedff ]
+
+Fix incorrect PHY timestamp extraction for ETH56G.
+It's better to use FIELD_PREP() than manual shift.
+
+Fixes: 7cab44f1c35f ("ice: Introduce ETH56G PHY model for E825C products")
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 3 ++-
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 5 ++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+index ec8db830ac73a..3816e45b6ab44 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+@@ -1495,7 +1495,8 @@ static int ice_read_ptp_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx,
+ * lower 8 bits in the low register, and the upper 32 bits in the high
+ * register.
+ */
+- *tstamp = ((u64)hi) << TS_PHY_HIGH_S | ((u64)lo & TS_PHY_LOW_M);
++ *tstamp = FIELD_PREP(TS_PHY_HIGH_M, hi) |
++ FIELD_PREP(TS_PHY_LOW_M, lo);
+
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+index 6cedc1a906afb..4c8b845713442 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+@@ -663,9 +663,8 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
+ #define TS_HIGH_M 0xFF
+ #define TS_HIGH_S 32
+
+-#define TS_PHY_LOW_M 0xFF
+-#define TS_PHY_HIGH_M 0xFFFFFFFF
+-#define TS_PHY_HIGH_S 8
++#define TS_PHY_LOW_M GENMASK(7, 0)
++#define TS_PHY_HIGH_M GENMASK_ULL(39, 8)
+
+ #define BYTES_PER_IDX_ADDR_L_U 8
+ #define BYTES_PER_IDX_ADDR_L 4
+--
+2.43.0
+
--- /dev/null
+From a944d5a70ad2c022843bcc1a19dcc6fe15bc04df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Nov 2024 19:49:09 +0100
+Subject: ice: Fix VLAN pruning in switchdev mode
+
+From: Marcin Szycik <marcin.szycik@linux.intel.com>
+
+[ Upstream commit 761e0be2888a931465e0d7bbeecce797f9c311a3 ]
+
+In switchdev mode the uplink VSI should receive all unmatched packets,
+including VLANs. Therefore, VLAN pruning should be disabled if uplink is
+in switchdev mode. It is already being done in ice_eswitch_setup_env(),
+however the addition of ice_up() in commit 44ba608db509 ("ice: do
+switchdev slow-path Rx using PF VSI") caused VLAN pruning to be
+re-enabled after disabling it.
+
+Add a check to ice_set_vlan_filtering_features() to ensure VLAN
+filtering will not be enabled if uplink is in switchdev mode. Note that
+ice_is_eswitch_mode_switchdev() is being used instead of
+ice_is_switchdev_running(), as the latter would only return true after
+the whole switchdev setup completes.
+
+Fixes: 44ba608db509 ("ice: do switchdev slow-path Rx using PF VSI")
+Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
+Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
+Tested-by: Priya Singh <priyax.singh@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_main.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index b1e7727b8677f..8f2e758c39427 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -6361,10 +6361,12 @@ ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
+ int err = 0;
+
+ /* support Single VLAN Mode (SVM) and Double VLAN Mode (DVM) by checking
+- * if either bit is set
++ * if either bit is set. In switchdev mode Rx filtering should never be
++ * enabled.
+ */
+- if (features &
+- (NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER))
++ if ((features &
++ (NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)) &&
++ !ice_is_eswitch_mode_switchdev(vsi->back))
+ err = vlan_ops->ena_rx_filtering(vsi);
+ else
+ err = vlan_ops->dis_rx_filtering(vsi);
+--
+2.43.0
+
--- /dev/null
+From 506124d7ea213c98d3a4210fb848e14521f9c886 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Oct 2024 13:24:35 -0700
+Subject: idpf: set completion tag for "empty" bufs associated with a packet
+
+From: Joshua Hay <joshua.a.hay@intel.com>
+
+[ Upstream commit 4c69c77aafe74cf755af55070584b643e5c4e4d8 ]
+
+Commit d9028db618a6 ("idpf: convert to libeth Tx buffer completion")
+inadvertently removed code that was necessary for the tx buffer cleaning
+routine to iterate over all buffers associated with a packet.
+
+When a frag is too large for a single data descriptor, it will be split
+across multiple data descriptors. This means the frag will span multiple
+buffers in the buffer ring in order to keep the descriptor and buffer
+ring indexes aligned. The buffer entries in the ring are technically
+empty and no cleaning actions need to be performed. These empty buffers
+can precede other frags associated with the same packet. I.e. a single
+packet on the buffer ring can look like:
+
+ buf[0]=skb0.frag0
+ buf[1]=skb0.frag1
+ buf[2]=empty
+ buf[3]=skb0.frag2
+
+The cleaning routine iterates through these buffers based on a matching
+completion tag. If the completion tag is not set for buf2, the loop will
+end prematurely. Frag2 will be left uncleaned and next_to_clean will be
+left pointing to the end of packet, which will break the cleaning logic
+for subsequent cleans. This consequently leads to tx timeouts.
+
+Assign the empty bufs the same completion tag for the packet to ensure
+the cleaning routine iterates over all of the buffers associated with
+the packet.
+
+Fixes: d9028db618a6 ("idpf: convert to libeth Tx buffer completion")
+Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
+Acked-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Reviewed-by: Madhu chittim <madhu.chittim@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Krishneil Singh <krishneil.k.singh@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/idpf/idpf_txrx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+index d4e6f0e104872..60d15b3e6e2fa 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+@@ -2448,6 +2448,7 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q,
+ * rest of the packet.
+ */
+ tx_buf->type = LIBETH_SQE_EMPTY;
++ idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag;
+
+ /* Adjust the DMA offset and the remaining size of the
+ * fragment. On the first iteration of this loop,
+--
+2.43.0
+
--- /dev/null
+From 61b91f2ab24611b8086dd041953b96e5951ac114 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Oct 2024 20:10:48 +0800
+Subject: igb: Fix potential invalid memory access in igb_init_module()
+
+From: Yuan Can <yuancan@huawei.com>
+
+[ Upstream commit 0566f83d206c7a864abcd741fe39d6e0ae5eef29 ]
+
+The pci_register_driver() can fail and when this happened, the dca_notifier
+needs to be unregistered, otherwise the dca_notifier can be called when
+igb fails to install, resulting to invalid memory access.
+
+Fixes: bbd98fe48a43 ("igb: Fix DCA errors and do not use context index for 82576")
+Signed-off-by: Yuan Can <yuancan@huawei.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igb/igb_main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index f1d0881687233..18284a838e242 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -637,6 +637,10 @@ static int __init igb_init_module(void)
+ dca_register_notify(&dca_notifier);
+ #endif
+ ret = pci_register_driver(&igb_driver);
++#ifdef CONFIG_IGB_DCA
++ if (ret)
++ dca_unregister_notify(&dca_notifier);
++#endif
+ return ret;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 0b601c145c6156a7f2f47b3d5e95fc1d32ed49b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 19:28:27 +0000
+Subject: ipv6: avoid possible NULL deref in modify_prefix_route()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit a747e02430dfb3657141f99aa6b09331283fa493 ]
+
+syzbot found a NULL deref [1] in modify_prefix_route(), caused by one
+fib6_info without a fib6_table pointer set.
+
+This can happen for net->ipv6.fib6_null_entry
+
+[1]
+Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN NOPTI
+KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
+CPU: 1 UID: 0 PID: 5837 Comm: syz-executor888 Not tainted 6.12.0-syzkaller-09567-g7eef7e306d3c #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
+ RIP: 0010:__lock_acquire+0xe4/0x3c40 kernel/locking/lockdep.c:5089
+Code: 08 84 d2 0f 85 15 14 00 00 44 8b 0d ca 98 f5 0e 45 85 c9 0f 84 b4 0e 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 e2 48 c1 ea 03 <80> 3c 02 00 0f 85 96 2c 00 00 49 8b 04 24 48 3d a0 07 7f 93 0f 84
+RSP: 0018:ffffc900035d7268 EFLAGS: 00010006
+RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
+RDX: 0000000000000006 RSI: 1ffff920006bae5f RDI: 0000000000000030
+RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000001
+R10: ffffffff90608e17 R11: 0000000000000001 R12: 0000000000000030
+R13: ffff888036334880 R14: 0000000000000000 R15: 0000000000000000
+FS: 0000555579e90380(0000) GS:ffff8880b8700000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007ffc59cc4278 CR3: 0000000072b54000 CR4: 00000000003526f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5849
+ __raw_spin_lock_bh include/linux/spinlock_api_smp.h:126 [inline]
+ _raw_spin_lock_bh+0x33/0x40 kernel/locking/spinlock.c:178
+ spin_lock_bh include/linux/spinlock.h:356 [inline]
+ modify_prefix_route+0x30b/0x8b0 net/ipv6/addrconf.c:4831
+ inet6_addr_modify net/ipv6/addrconf.c:4923 [inline]
+ inet6_rtm_newaddr+0x12c7/0x1ab0 net/ipv6/addrconf.c:5055
+ rtnetlink_rcv_msg+0x3c7/0xea0 net/core/rtnetlink.c:6920
+ netlink_rcv_skb+0x16b/0x440 net/netlink/af_netlink.c:2541
+ netlink_unicast_kernel net/netlink/af_netlink.c:1321 [inline]
+ netlink_unicast+0x53c/0x7f0 net/netlink/af_netlink.c:1347
+ netlink_sendmsg+0x8b8/0xd70 net/netlink/af_netlink.c:1891
+ sock_sendmsg_nosec net/socket.c:711 [inline]
+ __sock_sendmsg net/socket.c:726 [inline]
+ ____sys_sendmsg+0xaaf/0xc90 net/socket.c:2583
+ ___sys_sendmsg+0x135/0x1e0 net/socket.c:2637
+ __sys_sendmsg+0x16e/0x220 net/socket.c:2669
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7fd1dcef8b79
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 c1 17 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007ffc59cc4378 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fd1dcef8b79
+RDX: 0000000000040040 RSI: 0000000020000140 RDI: 0000000000000004
+RBP: 00000000000113fd R08: 0000000000000006 R09: 0000000000000006
+R10: 0000000000000006 R11: 0000000000000246 R12: 00007ffc59cc438c
+R13: 431bde82d7b634db R14: 0000000000000001 R15: 0000000000000001
+ </TASK>
+
+Fixes: 5eb902b8e719 ("net/ipv6: Remove expired routes with a separated list of routes.")
+Reported-by: syzbot+1de74b0794c40c8eb300@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/67461f7f.050a0220.1286eb.0021.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+CC: Kui-Feng Lee <thinker.li@gmail.com>
+Cc: David Ahern <dsahern@kernel.org>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/addrconf.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 01115e1a34cb6..f7c17388ff6aa 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -4821,7 +4821,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
+ ifm->ifa_prefixlen, extack);
+ }
+
+-static int modify_prefix_route(struct inet6_ifaddr *ifp,
++static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
+ unsigned long expires, u32 flags,
+ bool modify_peer)
+ {
+@@ -4845,7 +4845,9 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
+ ifp->prefix_len,
+ ifp->rt_priority, ifp->idev->dev,
+ expires, flags, GFP_KERNEL);
+- } else {
++ return 0;
++ }
++ if (f6i != net->ipv6.fib6_null_entry) {
+ table = f6i->fib6_table;
+ spin_lock_bh(&table->tb6_lock);
+
+@@ -4858,9 +4860,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
+ }
+
+ spin_unlock_bh(&table->tb6_lock);
+-
+- fib6_info_release(f6i);
+ }
++ fib6_info_release(f6i);
+
+ return 0;
+ }
+@@ -4939,7 +4940,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
+ int rc = -ENOENT;
+
+ if (had_prefixroute)
+- rc = modify_prefix_route(ifp, expires, flags, false);
++ rc = modify_prefix_route(net, ifp, expires, flags, false);
+
+ /* prefix route could have been deleted; if so restore it */
+ if (rc == -ENOENT) {
+@@ -4949,7 +4950,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
+ }
+
+ if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
+- rc = modify_prefix_route(ifp, expires, flags, true);
++ rc = modify_prefix_route(net, ifp, expires, flags, true);
+
+ if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
+ addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,
+--
+2.43.0
+
--- /dev/null
+From 3b388a5e5023e11cf02e0e3afe9a0e2fa4c22e4a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Nov 2024 03:42:56 -0600
+Subject: ipvs: fix UB due to uninitialized stack access in
+ ip_vs_protocol_init()
+
+From: Jinghao Jia <jinghao7@illinois.edu>
+
+[ Upstream commit 146b6f1112eb30a19776d6c323c994e9d67790db ]
+
+Under certain kernel configurations when building with Clang/LLVM, the
+compiler does not generate a return or jump as the terminator
+instruction for ip_vs_protocol_init(), triggering the following objtool
+warning during build time:
+
+ vmlinux.o: warning: objtool: ip_vs_protocol_init() falls through to next function __initstub__kmod_ip_vs_rr__935_123_ip_vs_rr_init6()
+
+At runtime, this either causes an oops when trying to load the ipvs
+module or a boot-time panic if ipvs is built-in. This same issue has
+been reported by the Intel kernel test robot previously.
+
+Digging deeper into both LLVM and the kernel code reveals this to be a
+undefined behavior problem. ip_vs_protocol_init() uses a on-stack buffer
+of 64 chars to store the registered protocol names and leaves it
+uninitialized after definition. The function calls strnlen() when
+concatenating protocol names into the buffer. With CONFIG_FORTIFY_SOURCE
+strnlen() performs an extra step to check whether the last byte of the
+input char buffer is a null character (commit 3009f891bb9f ("fortify:
+Allow strlen() and strnlen() to pass compile-time known lengths")).
+This, together with possibly other configurations, cause the following
+IR to be generated:
+
+ define hidden i32 @ip_vs_protocol_init() local_unnamed_addr #5 section ".init.text" align 16 !kcfi_type !29 {
+ %1 = alloca [64 x i8], align 16
+ ...
+
+ 14: ; preds = %11
+ %15 = getelementptr inbounds i8, ptr %1, i64 63
+ %16 = load i8, ptr %15, align 1
+ %17 = tail call i1 @llvm.is.constant.i8(i8 %16)
+ %18 = icmp eq i8 %16, 0
+ %19 = select i1 %17, i1 %18, i1 false
+ br i1 %19, label %20, label %23
+
+ 20: ; preds = %14
+ %21 = call i64 @strlen(ptr noundef nonnull dereferenceable(1) %1) #23
+ ...
+
+ 23: ; preds = %14, %11, %20
+ %24 = call i64 @strnlen(ptr noundef nonnull dereferenceable(1) %1, i64 noundef 64) #24
+ ...
+ }
+
+The above code calculates the address of the last char in the buffer
+(value %15) and then loads from it (value %16). Because the buffer is
+never initialized, the LLVM GVN pass marks value %16 as undefined:
+
+ %13 = getelementptr inbounds i8, ptr %1, i64 63
+ br i1 undef, label %14, label %17
+
+This gives later passes (SCCP, in particular) more DCE opportunities by
+propagating the undef value further, and eventually removes everything
+after the load on the uninitialized stack location:
+
+ define hidden i32 @ip_vs_protocol_init() local_unnamed_addr #0 section ".init.text" align 16 !kcfi_type !11 {
+ %1 = alloca [64 x i8], align 16
+ ...
+
+ 12: ; preds = %11
+ %13 = getelementptr inbounds i8, ptr %1, i64 63
+ unreachable
+ }
+
+In this way, the generated native code will just fall through to the
+next function, as LLVM does not generate any code for the unreachable IR
+instruction and leaves the function without a terminator.
+
+Zero the on-stack buffer to avoid this possible UB.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202402100205.PWXIz1ZK-lkp@intel.com/
+Co-developed-by: Ruowen Qin <ruqin@redhat.com>
+Signed-off-by: Ruowen Qin <ruqin@redhat.com>
+Signed-off-by: Jinghao Jia <jinghao7@illinois.edu>
+Acked-by: Julian Anastasov <ja@ssi.bg>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/ipvs/ip_vs_proto.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
+index f100da4ba3bc3..a9fd1d3fc2cbf 100644
+--- a/net/netfilter/ipvs/ip_vs_proto.c
++++ b/net/netfilter/ipvs/ip_vs_proto.c
+@@ -340,7 +340,7 @@ void __net_exit ip_vs_protocol_net_cleanup(struct netns_ipvs *ipvs)
+
+ int __init ip_vs_protocol_init(void)
+ {
+- char protocols[64];
++ char protocols[64] = { 0 };
+ #define REGISTER_PROTOCOL(p) \
+ do { \
+ register_ip_vs_protocol(p); \
+@@ -348,8 +348,6 @@ int __init ip_vs_protocol_init(void)
+ strcat(protocols, (p)->name); \
+ } while (0)
+
+- protocols[0] = '\0';
+- protocols[2] = '\0';
+ #ifdef CONFIG_IP_VS_PROTO_TCP
+ REGISTER_PROTOCOL(&ip_vs_protocol_tcp);
+ #endif
+--
+2.43.0
+
--- /dev/null
+From 514fd52c34db7e22d1dc62fc602d6fde937b69c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Sep 2024 12:14:03 -0700
+Subject: iTCO_wdt: mask NMI_NOW bit for update_no_reboot_bit() call
+
+From: Oleksandr Ocheretnyi <oocheret@cisco.com>
+
+[ Upstream commit daa814d784ac034c62ab3fb0ef83daeafef527e2 ]
+
+Commit da23b6faa8bf ("watchdog: iTCO: Add support for Cannon Lake
+PCH iTCO") does not mask NMI_NOW bit during TCO1_CNT register's
+value comparison for update_no_reboot_bit() call causing following
+failure:
+
+ ...
+ iTCO_vendor_support: vendor-support=0
+ iTCO_wdt iTCO_wdt: unable to reset NO_REBOOT flag, device
+ disabled by hardware/BIOS
+ ...
+
+and this can lead to unexpected NMIs later during regular
+crashkernel's workflow because of watchdog probe call failures.
+
+This change masks NMI_NOW bit for TCO1_CNT register values to
+avoid unexpected NMI_NOW bit inversions.
+
+Fixes: da23b6faa8bf ("watchdog: iTCO: Add support for Cannon Lake PCH iTCO")
+Signed-off-by: Oleksandr Ocheretnyi <oocheret@cisco.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Link: https://lore.kernel.org/r/20240913191403.2560805-1-oocheret@cisco.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/iTCO_wdt.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
+index 35b358bcf94ce..f01ed38aba675 100644
+--- a/drivers/watchdog/iTCO_wdt.c
++++ b/drivers/watchdog/iTCO_wdt.c
+@@ -82,6 +82,13 @@
+ #define TCO2_CNT(p) (TCOBASE(p) + 0x0a) /* TCO2 Control Register */
+ #define TCOv2_TMR(p) (TCOBASE(p) + 0x12) /* TCOv2 Timer Initial Value*/
+
++/*
++ * NMI_NOW is bit 8 of TCO1_CNT register
++ * Read/Write
++ * This bit is implemented as RW but has no effect on HW.
++ */
++#define NMI_NOW BIT(8)
++
+ /* internal variables */
+ struct iTCO_wdt_private {
+ struct watchdog_device wddev;
+@@ -219,13 +226,23 @@ static int update_no_reboot_bit_cnt(void *priv, bool set)
+ struct iTCO_wdt_private *p = priv;
+ u16 val, newval;
+
+- val = inw(TCO1_CNT(p));
++ /*
++ * writing back 1b1 to NMI_NOW of TCO1_CNT register
++ * causes NMI_NOW bit inversion what consequently does
++ * not allow to perform the register's value comparison
++ * properly.
++ *
++ * NMI_NOW bit masking for TCO1_CNT register values
++ * helps to avoid possible NMI_NOW bit inversions on
++ * following write operation.
++ */
++ val = inw(TCO1_CNT(p)) & ~NMI_NOW;
+ if (set)
+ val |= BIT(0);
+ else
+ val &= ~BIT(0);
+ outw(val, TCO1_CNT(p));
+- newval = inw(TCO1_CNT(p));
++ newval = inw(TCO1_CNT(p)) & ~NMI_NOW;
+
+ /* make sure the update is successful */
+ return val != newval ? -EIO : 0;
+--
+2.43.0
+
--- /dev/null
+From 6fc4fd37840aaba8987dcfce4d1e04fd5fad806c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Nov 2024 14:17:36 +0000
+Subject: ixgbe: Correct BASE-BX10 compliance code
+
+From: Tore Amundsen <tore@amundsen.org>
+
+[ Upstream commit f72ce14b231f7bf06088e4e50f1875f1e35f79d7 ]
+
+SFF-8472 (section 5.4 Transceiver Compliance Codes) defines bit 6 as
+BASE-BX10. Bit 6 means a value of 0x40 (decimal 64).
+
+The current value in the source code is 0x64, which appears to be a
+mix-up of hex and decimal values. A value of 0x64 (binary 01100100)
+incorrectly sets bit 2 (1000BASE-CX) and bit 5 (100BASE-FX) as well.
+
+Fixes: 1b43e0d20f2d ("ixgbe: Add 1000BASE-BX support")
+Signed-off-by: Tore Amundsen <tore@amundsen.org>
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Acked-by: Ernesto Castellotti <ernesto@castellotti.net>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+index 14aa2ca51f70e..81179c60af4e0 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+@@ -40,7 +40,7 @@
+ #define IXGBE_SFF_1GBASESX_CAPABLE 0x1
+ #define IXGBE_SFF_1GBASELX_CAPABLE 0x2
+ #define IXGBE_SFF_1GBASET_CAPABLE 0x8
+-#define IXGBE_SFF_BASEBX10_CAPABLE 0x64
++#define IXGBE_SFF_BASEBX10_CAPABLE 0x40
+ #define IXGBE_SFF_10GBASESR_CAPABLE 0x10
+ #define IXGBE_SFF_10GBASELR_CAPABLE 0x20
+ #define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8
+--
+2.43.0
+
--- /dev/null
+From 311be07e00dcec2fe578e1f1c9c2483f6d618238 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Nov 2024 16:05:43 -0700
+Subject: ixgbe: downgrade logging of unsupported VF API version to debug
+
+From: Jacob Keller <jacob.e.keller@intel.com>
+
+[ Upstream commit 15915b43a7fb938934bb7fc4290127218859d795 ]
+
+The ixgbe PF driver logs an info message when a VF attempts to negotiate an
+API version which it does not support:
+
+ VF 0 requested invalid api version 6
+
+The ixgbevf driver attempts to load with mailbox API v1.5, which is
+required for best compatibility with other hosts such as the ESX VMWare PF.
+
+The Linux PF only supports API v1.4, and does not currently have support
+for the v1.5 API.
+
+The logged message can confuse users, as the v1.5 API is valid, but just
+happens to not currently be supported by the Linux PF.
+
+Downgrade the info message to a debug message, and fix the language to
+use 'unsupported' instead of 'invalid' to improve message clarity.
+
+Long term, we should investigate whether the improvements in the v1.5 API
+make sense for the Linux PF, and if so implement them properly. This may
+require yet another API version to resolve issues with negotiating IPSEC
+offload support.
+
+Fixes: 339f28964147 ("ixgbevf: Add support for new mailbox communication between PF and VF")
+Reported-by: Yifei Liu <yifei.l.liu@oracle.com>
+Link: https://lore.kernel.org/intel-wired-lan/20240301235837.3741422-1-yifei.l.liu@oracle.com/
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 2 ++
+ drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+index 6493abf189de5..6639069ad5283 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+@@ -194,6 +194,8 @@ u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg);
+ dev_err(&adapter->pdev->dev, format, ## arg)
+ #define e_dev_notice(format, arg...) \
+ dev_notice(&adapter->pdev->dev, format, ## arg)
++#define e_dbg(msglvl, format, arg...) \
++ netif_dbg(adapter, msglvl, adapter->netdev, format, ## arg)
+ #define e_info(msglvl, format, arg...) \
+ netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
+ #define e_err(msglvl, format, arg...) \
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+index e71715f5da228..20415c1238ef8 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+@@ -1047,7 +1047,7 @@ static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
+ break;
+ }
+
+- e_info(drv, "VF %d requested invalid api version %u\n", vf, api);
++ e_dbg(drv, "VF %d requested unsupported api version %u\n", vf, api);
+
+ return -1;
+ }
+--
+2.43.0
+
--- /dev/null
+From d9f356294af6d5563894fb1e55a1ecc0796dc077 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Nov 2024 16:05:42 -0700
+Subject: ixgbevf: stop attempting IPSEC offload on Mailbox API 1.5
+
+From: Jacob Keller <jacob.e.keller@intel.com>
+
+[ Upstream commit d0725312adf5a803de8f621bd1b12ba7a6464a29 ]
+
+Commit 339f28964147 ("ixgbevf: Add support for new mailbox communication
+between PF and VF") added support for v1.5 of the PF to VF mailbox
+communication API. This commit mistakenly enabled IPSEC offload for API
+v1.5.
+
+No implementation of the v1.5 API has support for IPSEC offload. This
+offload is only supported by the Linux PF as mailbox API v1.4. In fact, the
+v1.5 API is not implemented in any Linux PF.
+
+Attempting to enable IPSEC offload on a PF which supports v1.5 API will not
+work. Only the Linux upstream ixgbe and ixgbevf support IPSEC offload, and
+only as part of the v1.4 API.
+
+Fix the ixgbevf Linux driver to stop attempting IPSEC offload when
+the mailbox API does not support it.
+
+The existing API design choice makes it difficult to support future API
+versions, as other non-Linux hosts do not implement IPSEC offload. If we
+add support for v1.5 to the Linux PF, then we lose support for IPSEC
+offload.
+
+A full solution likely requires a new mailbox API with a proper negotiation
+to check that IPSEC is actually supported by the host.
+
+Fixes: 339f28964147 ("ixgbevf: Add support for new mailbox communication between PF and VF")
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ixgbevf/ipsec.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+index 66cf17f194082..f804b35d79c72 100644
+--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
++++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+@@ -629,7 +629,6 @@ void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter)
+
+ switch (adapter->hw.api_version) {
+ case ixgbe_mbox_api_14:
+- case ixgbe_mbox_api_15:
+ break;
+ default:
+ return;
+--
+2.43.0
+
--- /dev/null
+From e95af35359135522911014580eedeb5713111fdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Oct 2024 07:26:05 +0200
+Subject: mlxsw: spectrum_acl_flex_keys: Constify struct mlxsw_afk_element_inst
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit bec2a32145d5cc066df29182fa0e5b0d4329b1a1 ]
+
+'struct mlxsw_afk_element_inst' are not modified in these drivers.
+
+Constifying these structures moves some data to a read-only section, so
+increases overall security.
+
+Update a few functions and struct mlxsw_afk_block accordingly.
+
+On a x86_64, with allmodconfig, as an example:
+Before:
+======
+ text data bss dec hex filename
+ 4278 4032 0 8310 2076 drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.o
+
+After:
+=====
+ text data bss dec hex filename
+ 7934 352 0 8286 205e drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.o
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/8ccfc7bfb2365dcee5b03c81ebe061a927d6da2e.1727541677.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 217bbf156f93 ("mlxsw: spectrum_acl_flex_keys: Use correct key block on Spectrum-4")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../mellanox/mlxsw/core_acl_flex_keys.c | 6 +-
+ .../mellanox/mlxsw/core_acl_flex_keys.h | 2 +-
+ .../mellanox/mlxsw/spectrum_acl_flex_keys.c | 66 +++++++++----------
+ 3 files changed, 37 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+index 947500f8ed714..7aa1a462a1035 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+@@ -67,7 +67,7 @@ static bool mlxsw_afk_blocks_check(struct mlxsw_afk *mlxsw_afk)
+
+ for (j = 0; j < block->instances_count; j++) {
+ const struct mlxsw_afk_element_info *elinfo;
+- struct mlxsw_afk_element_inst *elinst;
++ const struct mlxsw_afk_element_inst *elinst;
+
+ elinst = &block->instances[j];
+ elinfo = &mlxsw_afk_element_infos[elinst->element];
+@@ -154,7 +154,7 @@ static void mlxsw_afk_picker_count_hits(struct mlxsw_afk *mlxsw_afk,
+ const struct mlxsw_afk_block *block = &mlxsw_afk->blocks[i];
+
+ for (j = 0; j < block->instances_count; j++) {
+- struct mlxsw_afk_element_inst *elinst;
++ const struct mlxsw_afk_element_inst *elinst;
+
+ elinst = &block->instances[j];
+ if (elinst->element == element) {
+@@ -386,7 +386,7 @@ mlxsw_afk_block_elinst_get(const struct mlxsw_afk_block *block,
+ int i;
+
+ for (i = 0; i < block->instances_count; i++) {
+- struct mlxsw_afk_element_inst *elinst;
++ const struct mlxsw_afk_element_inst *elinst;
+
+ elinst = &block->instances[i];
+ if (elinst->element == element)
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
+index 98a05598178b3..5aa1afb3f2ca8 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
++++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
+@@ -117,7 +117,7 @@ struct mlxsw_afk_element_inst { /* element instance in actual block */
+
+ struct mlxsw_afk_block {
+ u16 encoding; /* block ID */
+- struct mlxsw_afk_element_inst *instances;
++ const struct mlxsw_afk_element_inst *instances;
+ unsigned int instances_count;
+ bool high_entropy;
+ };
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+index eaad786056027..6fe185ea6732c 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+@@ -7,7 +7,7 @@
+ #include "item.h"
+ #include "core_acl_flex_keys.h"
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x00, 2),
+ MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x02, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
+@@ -15,7 +15,7 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x00, 2),
+ MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x02, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
+@@ -23,27 +23,27 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x02, 2),
+ MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x0C, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
+ MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
+ MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8),
+@@ -51,35 +51,35 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
+ MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
+ MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
+ MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
+ };
+
+@@ -124,90 +124,90 @@ const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
+ .clear_block = mlxsw_sp1_afk_clear_block,
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
+ MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
+ MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
+ MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
+ MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
+ MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
+ MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
+ MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 8, -1, true), /* RX_ACL_SYSTEM_PORT */
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
+ MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5[] = {
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER, 0x04, 20, 11, 0, true),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_0_3, 0x00, 0, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_4_7, 0x00, 0, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
+ MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
+ MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 0, 16),
+ };
+@@ -319,16 +319,16 @@ const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
+ .clear_block = mlxsw_sp2_afk_clear_block,
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 18, 12),
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 9, -1, true), /* RX_ACL_SYSTEM_PORT */
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER, 0x04, 20, 12),
+ };
+
+-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x00, 0, 4),
+ MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
+ };
+--
+2.43.0
+
--- /dev/null
+From 960f8c551b5c594a48b17297561bc38d4096847d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 16:16:05 +0100
+Subject: mlxsw: spectrum_acl_flex_keys: Use correct key block on Spectrum-4
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 217bbf156f93ada86b91617489e7ba8a0904233c ]
+
+The driver is currently using an ACL key block that is not supported by
+Spectrum-4. This works because the driver is only using a single field
+from this key block which is located in the same offset in the
+equivalent Spectrum-4 key block.
+
+The issue was discovered when the firmware started rejecting the use of
+the unsupported key block. The change has been reverted to avoid
+breaking users that only update their firmware.
+
+Nonetheless, fix the issue by using the correct key block.
+
+Fixes: 07ff135958dd ("mlxsw: Introduce flex key elements for Spectrum-4")
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/35e72c97bdd3bc414fb8e4d747e5fb5d26c29658.1733237440.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+index 6fe185ea6732c..1850a975b3804 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+@@ -324,6 +324,10 @@ static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] =
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 9, -1, true), /* RX_ACL_SYSTEM_PORT */
+ };
+
++static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1b[] = {
++ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
++};
++
+ static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER, 0x04, 20, 12),
+ };
+@@ -341,7 +345,7 @@ static const struct mlxsw_afk_block mlxsw_sp4_afk_blocks[] = {
+ MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x1A, mlxsw_sp_afk_element_info_mac_5b),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x38, mlxsw_sp_afk_element_info_ipv4_0),
+- MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x39, mlxsw_sp_afk_element_info_ipv4_1),
++ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x3F, mlxsw_sp_afk_element_info_ipv4_1b),
+ MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
+ MLXSW_AFK_BLOCK(0x36, mlxsw_sp_afk_element_info_ipv4_5b),
+ MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
+--
+2.43.0
+
--- /dev/null
+From e7923caeddb263280e8fe0c1d2bdf50ea737c61c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 6 Oct 2024 08:11:45 +0300
+Subject: mmc: core: Adjust ACMD22 to SDUC
+
+From: Avri Altman <avri.altman@wdc.com>
+
+[ Upstream commit 449f34a34088d02457fa0f3216747e8a35bc03ae ]
+
+ACMD22 is used to verify the previously write operation. Normally, it
+returns the number of written sectors as u32. SDUC, however, returns it
+as u64. This is not a superfluous requirement, because SDUC writes may
+exceeds 2TB. For Linux mmc however, the previously write operation
+could not be more than the block layer limits, thus we make room for a
+u64 and cast the returning value to u32.
+
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Avri Altman <avri.altman@wdc.com>
+Link: https://lore.kernel.org/r/20241006051148.160278-8-avri.altman@wdc.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+[Stephen Rothwell: Fix build error when moving to new rc from Linus's tree]
+Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Stable-dep-of: 869d37475788 ("mmc: core: Use GFP_NOIO in ACMD22")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/core/block.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
+index ef06a4d5d65bb..64ae6116b1fa0 100644
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -50,6 +50,7 @@
+ #include <linux/mmc/sd.h>
+
+ #include <linux/uaccess.h>
++#include <linux/unaligned.h>
+
+ #include "queue.h"
+ #include "block.h"
+@@ -993,11 +994,10 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
+ int err;
+ u32 result;
+ __be32 *blocks;
+-
++ u8 resp_sz = mmc_card_ult_capacity(card) ? 8 : 4;
+ struct mmc_request mrq = {};
+ struct mmc_command cmd = {};
+ struct mmc_data data = {};
+-
+ struct scatterlist sg;
+
+ err = mmc_app_cmd(card->host, card);
+@@ -1008,7 +1008,7 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+
+- data.blksz = 4;
++ data.blksz = resp_sz;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+@@ -1018,15 +1018,27 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
+- blocks = kmalloc(4, GFP_KERNEL);
++ blocks = kmalloc(resp_sz, GFP_KERNEL);
+ if (!blocks)
+ return -ENOMEM;
+
+- sg_init_one(&sg, blocks, 4);
++ sg_init_one(&sg, blocks, resp_sz);
+
+ mmc_wait_for_req(card->host, &mrq);
+
+- result = ntohl(*blocks);
++ if (mmc_card_ult_capacity(card)) {
++ /*
++ * Normally, ACMD22 returns the number of written sectors as
++ * u32. SDUC, however, returns it as u64. This is not a
++ * superfluous requirement, because SDUC writes may exceed 2TB.
++ * For Linux mmc however, the previously write operation could
++ * not be more than the block layer limits, thus just make room
++ * for a u64 and cast the response back to u32.
++ */
++ result = clamp_val(get_unaligned_be64(blocks), 0, UINT_MAX);
++ } else {
++ result = ntohl(*blocks);
++ }
+ kfree(blocks);
+
+ if (cmd.error || data.error)
+--
+2.43.0
+
--- /dev/null
+From ee08aec3bc7711cd95a18718fc2198a90fd0d708 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 18:32:27 +0300
+Subject: mmc: core: Use GFP_NOIO in ACMD22
+
+From: Avri Altman <avri.altman@wdc.com>
+
+[ Upstream commit 869d37475788b0044bec1a33335e24abaf5e8884 ]
+
+While reviewing the SDUC series, Adrian made a comment concerning the
+memory allocation code in mmc_sd_num_wr_blocks() - see [1].
+Prevent memory allocations from triggering I/O operations while ACMD22
+is in progress.
+
+[1] https://lore.kernel.org/linux-mmc/3016fd71-885b-4ef9-97ed-46b4b0cb0e35@intel.com/
+
+Suggested-by: Adrian Hunter <adrian.hunter@intel.com>
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Fixes: 051913dada04 ("mmc_block: do not DMA to stack")
+Signed-off-by: Avri Altman <avri.altman@wdc.com>
+Cc: stable@vger.kernel.org
+Message-ID: <20241021153227.493970-1-avri.altman@wdc.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/core/block.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
+index 64ae6116b1fa0..1d08009f2bd83 100644
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -995,6 +995,8 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
+ u32 result;
+ __be32 *blocks;
+ u8 resp_sz = mmc_card_ult_capacity(card) ? 8 : 4;
++ unsigned int noio_flag;
++
+ struct mmc_request mrq = {};
+ struct mmc_command cmd = {};
+ struct mmc_data data = {};
+@@ -1018,7 +1020,9 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)
+ mrq.cmd = &cmd;
+ mrq.data = &data;
+
++ noio_flag = memalloc_noio_save();
+ blocks = kmalloc(resp_sz, GFP_KERNEL);
++ memalloc_noio_restore(noio_flag);
+ if (!blocks)
+ return -ENOMEM;
+
+--
+2.43.0
+
--- /dev/null
+From b573d9f7552a0ed07565c032329a1b7074da5d4b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Sep 2024 15:49:19 -0700
+Subject: mmc: mtk-sd: fix devm_clk_get_optional usage
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit ed299eda8fbb37cb0e05c7001ab6a6b2627ec087 ]
+
+This already returns NULL when not found. However, it can return
+EPROBE_DEFER and should thus return here.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://lore.kernel.org/r/20240930224919.355359-4-rosenp@gmail.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 2508925fb346 ("mmc: mtk-sd: Fix MMC_CAP2_CRYPTO flag setting")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/mtk-sd.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 73f97f985daf4..83e7291481861 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -2773,9 +2773,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ if (!(mmc->caps2 & MMC_CAP2_NO_MMC)) {
+ host->crypto_clk = devm_clk_get_optional(&pdev->dev, "crypto");
+ if (IS_ERR(host->crypto_clk))
+- host->crypto_clk = NULL;
+- else
+- mmc->caps2 |= MMC_CAP2_CRYPTO;
++ return PTR_ERR(host->crypto_clk);
++ mmc->caps2 |= MMC_CAP2_CRYPTO;
+ }
+
+ host->irq = platform_get_irq(pdev, 0);
+--
+2.43.0
+
--- /dev/null
+From 4600bcb7eff10e87dfd858f566908b3279001945 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Nov 2024 20:11:21 +0800
+Subject: mmc: mtk-sd: Fix error handle of probe function
+
+From: Andy-ld Lu <andy-ld.lu@mediatek.com>
+
+[ Upstream commit 291220451c775a054cedc4fab4578a1419eb6256 ]
+
+In the probe function, it goes to 'release_mem' label and returns after
+some procedure failure. But if the clocks (partial or all) have been
+enabled previously, they would not be disabled in msdc_runtime_suspend,
+since runtime PM is not yet enabled for this case.
+
+That cause mmc related clocks always on during system suspend and block
+suspend flow. Below log is from a SDCard issue of MT8196 chromebook, it
+returns -ETIMEOUT while polling clock stable in the msdc_ungate_clock()
+and probe failed, but the enabled clocks could not be disabled anyway.
+
+[ 129.059253] clk_chk_dev_pm_suspend()
+[ 129.350119] suspend warning: msdcpll is on
+[ 129.354494] [ck_msdc30_1_sel : enabled, 1, 1, 191999939, ck_msdcpll_d2]
+[ 129.362787] [ck_msdcpll_d2 : enabled, 1, 1, 191999939, msdcpll]
+[ 129.371041] [ck_msdc30_1_ck : enabled, 1, 1, 191999939, ck_msdc30_1_sel]
+[ 129.379295] [msdcpll : enabled, 1, 1, 383999878, clk26m]
+
+Add a new 'release_clk' label and reorder the error handle functions to
+make sure the clocks be disabled after probe failure.
+
+Fixes: ffaea6ebfe9c ("mmc: mtk-sd: Use readl_poll_timeout instead of open-coded polling")
+Fixes: 7a2fa8eed936 ("mmc: mtk-sd: use devm_mmc_alloc_host")
+Signed-off-by: Andy-ld Lu <andy-ld.lu@mediatek.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Cc: stable@vger.kernel.org
+Message-ID: <20241107121215.5201-1-andy-ld.lu@mediatek.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/mtk-sd.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index c607312dfe078..73f97f985daf4 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -2875,7 +2875,7 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ ret = msdc_ungate_clock(host);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot ungate clocks!\n");
+- goto release_mem;
++ goto release_clk;
+ }
+ msdc_init_hw(host);
+
+@@ -2885,14 +2885,14 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ GFP_KERNEL);
+ if (!host->cq_host) {
+ ret = -ENOMEM;
+- goto release_mem;
++ goto release;
+ }
+ host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
+ host->cq_host->mmio = host->base + 0x800;
+ host->cq_host->ops = &msdc_cmdq_ops;
+ ret = cqhci_init(host->cq_host, mmc, true);
+ if (ret)
+- goto release_mem;
++ goto release;
+ mmc->max_segs = 128;
+ /* cqhci 16bit length */
+ /* 0 size, means 65536 so we don't have to -1 here */
+@@ -2919,9 +2919,10 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ end:
+ pm_runtime_disable(host->dev);
+ release:
+- platform_set_drvdata(pdev, NULL);
+ msdc_deinit_hw(host);
++release_clk:
+ msdc_gate_clock(host);
++ platform_set_drvdata(pdev, NULL);
+ release_mem:
+ if (host->dma.gpd)
+ dma_free_coherent(&pdev->dev,
+--
+2.43.0
+
--- /dev/null
+From 1b6c03bbcd2070bcf7afdb9019bb429088c1237b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Nov 2024 16:49:31 +0800
+Subject: mmc: mtk-sd: Fix MMC_CAP2_CRYPTO flag setting
+
+From: Andy-ld Lu <andy-ld.lu@mediatek.com>
+
+[ Upstream commit 2508925fb346661bad9f50b497d7ac7d0b6085d0 ]
+
+Currently, the MMC_CAP2_CRYPTO flag is set by default for eMMC hosts.
+However, this flag should not be set for hosts that do not support inline
+encryption.
+
+The 'crypto' clock, as described in the documentation, is used for data
+encryption and decryption. Therefore, only hosts that are configured with
+this 'crypto' clock should have the MMC_CAP2_CRYPTO flag set.
+
+Fixes: 7b438d0377fb ("mmc: mtk-sd: add Inline Crypto Engine clock control")
+Fixes: ed299eda8fbb ("mmc: mtk-sd: fix devm_clk_get_optional usage")
+Signed-off-by: Andy-ld Lu <andy-ld.lu@mediatek.com>
+Cc: stable@vger.kernel.org
+Message-ID: <20241111085039.26527-1-andy-ld.lu@mediatek.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/mtk-sd.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 83e7291481861..813bc20cfb5a6 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -2774,7 +2774,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ host->crypto_clk = devm_clk_get_optional(&pdev->dev, "crypto");
+ if (IS_ERR(host->crypto_clk))
+ return PTR_ERR(host->crypto_clk);
+- mmc->caps2 |= MMC_CAP2_CRYPTO;
++ else if (host->crypto_clk)
++ mmc->caps2 |= MMC_CAP2_CRYPTO;
+ }
+
+ host->irq = platform_get_irq(pdev, 0);
+--
+2.43.0
+
--- /dev/null
+From ae715696e299a644574a070c8ca3bdf5018b0741 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Sep 2024 15:49:17 -0700
+Subject: mmc: mtk-sd: use devm_mmc_alloc_host
+
+From: Rosen Penev <rosenp@gmail.com>
+
+[ Upstream commit 7a2fa8eed936b33b22e49b1d2349cd7d02f22710 ]
+
+Allows removing several gotos.
+
+Also fixed some wrong ones.
+
+Added dev_err_probe where EPROBE_DEFER is possible.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+Link: https://lore.kernel.org/r/20240930224919.355359-2-rosenp@gmail.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 291220451c77 ("mmc: mtk-sd: Fix error handle of probe function")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/mtk-sd.c | 55 ++++++++++++++-------------------------
+ 1 file changed, 20 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 89018b6c97b9a..c607312dfe078 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -2736,20 +2736,18 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ }
+
+ /* Allocate MMC host for this device */
+- mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
++ mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct msdc_host));
+ if (!mmc)
+ return -ENOMEM;
+
+ host = mmc_priv(mmc);
+ ret = mmc_of_parse(mmc);
+ if (ret)
+- goto host_free;
++ return ret;
+
+ host->base = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(host->base)) {
+- ret = PTR_ERR(host->base);
+- goto host_free;
+- }
++ if (IS_ERR(host->base))
++ return PTR_ERR(host->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+@@ -2760,18 +2758,16 @@ static int msdc_drv_probe(struct platform_device *pdev)
+
+ ret = mmc_regulator_get_supply(mmc);
+ if (ret)
+- goto host_free;
++ return ret;
+
+ ret = msdc_of_clock_parse(pdev, host);
+ if (ret)
+- goto host_free;
++ return ret;
+
+ host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
+ "hrst");
+- if (IS_ERR(host->reset)) {
+- ret = PTR_ERR(host->reset);
+- goto host_free;
+- }
++ if (IS_ERR(host->reset))
++ return PTR_ERR(host->reset);
+
+ /* only eMMC has crypto property */
+ if (!(mmc->caps2 & MMC_CAP2_NO_MMC)) {
+@@ -2783,30 +2779,24 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ }
+
+ host->irq = platform_get_irq(pdev, 0);
+- if (host->irq < 0) {
+- ret = host->irq;
+- goto host_free;
+- }
++ if (host->irq < 0)
++ return host->irq;
+
+ host->pinctrl = devm_pinctrl_get(&pdev->dev);
+- if (IS_ERR(host->pinctrl)) {
+- ret = PTR_ERR(host->pinctrl);
+- dev_err(&pdev->dev, "Cannot find pinctrl!\n");
+- goto host_free;
+- }
++ if (IS_ERR(host->pinctrl))
++ return dev_err_probe(&pdev->dev, PTR_ERR(host->pinctrl),
++ "Cannot find pinctrl");
+
+ host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
+ if (IS_ERR(host->pins_default)) {
+- ret = PTR_ERR(host->pins_default);
+ dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
+- goto host_free;
++ return PTR_ERR(host->pins_default);
+ }
+
+ host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
+ if (IS_ERR(host->pins_uhs)) {
+- ret = PTR_ERR(host->pins_uhs);
+ dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
+- goto host_free;
++ return PTR_ERR(host->pins_uhs);
+ }
+
+ /* Support for SDIO eint irq ? */
+@@ -2895,14 +2885,14 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ GFP_KERNEL);
+ if (!host->cq_host) {
+ ret = -ENOMEM;
+- goto host_free;
++ goto release_mem;
+ }
+ host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
+ host->cq_host->mmio = host->base + 0x800;
+ host->cq_host->ops = &msdc_cmdq_ops;
+ ret = cqhci_init(host->cq_host, mmc, true);
+ if (ret)
+- goto host_free;
++ goto release_mem;
+ mmc->max_segs = 128;
+ /* cqhci 16bit length */
+ /* 0 size, means 65536 so we don't have to -1 here */
+@@ -2939,11 +2929,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
+ host->dma.gpd, host->dma.gpd_addr);
+ if (host->dma.bd)
+ dma_free_coherent(&pdev->dev,
+- MAX_BD_NUM * sizeof(struct mt_bdma_desc),
+- host->dma.bd, host->dma.bd_addr);
+-host_free:
+- mmc_free_host(mmc);
+-
++ MAX_BD_NUM * sizeof(struct mt_bdma_desc),
++ host->dma.bd, host->dma.bd_addr);
+ return ret;
+ }
+
+@@ -2968,9 +2955,7 @@ static void msdc_drv_remove(struct platform_device *pdev)
+ 2 * sizeof(struct mt_gpdma_desc),
+ host->dma.gpd, host->dma.gpd_addr);
+ dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
+- host->dma.bd, host->dma.bd_addr);
+-
+- mmc_free_host(mmc);
++ host->dma.bd, host->dma.bd_addr);
+ }
+
+ static void msdc_save_reg(struct msdc_host *host)
+--
+2.43.0
+
--- /dev/null
+From 67bc965d660760bd68981c067932c4bd807ebf95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 6 Oct 2024 08:11:39 +0300
+Subject: mmc: sd: SDUC Support Recognition
+
+From: Avri Altman <avri.altman@wdc.com>
+
+[ Upstream commit fce2ce78af1e14dc1316aaddb5b3308be05cf452 ]
+
+Ultra Capacity SD cards (SDUC) was already introduced in SD7.0. Those
+cards support capacity larger than 2TB and up to including 128TB.
+
+ACMD41 was extended to support the host-card handshake during
+initialization. The card expects that the HCS & HO2T bits to be set in
+the command argument, and sets the applicable bits in the R3 returned
+response. On the contrary, if a SDUC card is inserted to a
+non-supporting host, it will never respond to this ACMD41 until
+eventually, the host will timed out and give up.
+
+Also, add SD CSD version 3.0 - designated for SDUC, and properly parse
+the csd register as the c_size field got expanded to 28 bits.
+
+Do not enable SDUC for now - leave it to the last patch in the series.
+
+Tested-by: Ricky WU <ricky_wu@realtek.com>
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Avri Altman <avri.altman@wdc.com>
+Link: https://lore.kernel.org/r/20241006051148.160278-2-avri.altman@wdc.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 869d37475788 ("mmc: core: Use GFP_NOIO in ACMD22")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/core/bus.c | 4 +++-
+ drivers/mmc/core/card.h | 3 +++
+ drivers/mmc/core/sd.c | 28 +++++++++++++++++-----------
+ drivers/mmc/core/sd.h | 2 +-
+ drivers/mmc/core/sdio.c | 2 +-
+ include/linux/mmc/card.h | 2 +-
+ include/linux/mmc/sd.h | 1 +
+ 7 files changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
+index 0ddaee0eae54f..30763b342bd36 100644
+--- a/drivers/mmc/core/bus.c
++++ b/drivers/mmc/core/bus.c
+@@ -321,7 +321,9 @@ int mmc_add_card(struct mmc_card *card)
+ case MMC_TYPE_SD:
+ type = "SD";
+ if (mmc_card_blockaddr(card)) {
+- if (mmc_card_ext_capacity(card))
++ if (mmc_card_ult_capacity(card))
++ type = "SDUC";
++ else if (mmc_card_ext_capacity(card))
+ type = "SDXC";
+ else
+ type = "SDHC";
+diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
+index b7754a1b8d978..64dcb463a4f49 100644
+--- a/drivers/mmc/core/card.h
++++ b/drivers/mmc/core/card.h
+@@ -23,6 +23,7 @@
+ #define MMC_CARD_SDXC (1<<3) /* card is SDXC */
+ #define MMC_CARD_REMOVED (1<<4) /* card has been removed */
+ #define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */
++#define MMC_CARD_SDUC (1<<6) /* card is SDUC */
+
+ #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
+ #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
+@@ -30,11 +31,13 @@
+ #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
+ #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
+ #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
++#define mmc_card_ult_capacity(c) ((c)->state & MMC_CARD_SDUC)
+
+ #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
+ #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+ #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
+ #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
++#define mmc_card_set_ult_capacity(c) ((c)->state |= MMC_CARD_SDUC)
+ #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
+ #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
+ #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
+diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
+index 12fe282bea77e..1d09f0f2e7697 100644
+--- a/drivers/mmc/core/sd.c
++++ b/drivers/mmc/core/sd.c
+@@ -100,7 +100,7 @@ void mmc_decode_cid(struct mmc_card *card)
+ /*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+-static int mmc_decode_csd(struct mmc_card *card)
++static int mmc_decode_csd(struct mmc_card *card, bool is_sduc)
+ {
+ struct mmc_csd *csd = &card->csd;
+ unsigned int e, m, csd_struct;
+@@ -144,9 +144,10 @@ static int mmc_decode_csd(struct mmc_card *card)
+ mmc_card_set_readonly(card);
+ break;
+ case 1:
++ case 2:
+ /*
+- * This is a block-addressed SDHC or SDXC card. Most
+- * interesting fields are unused and have fixed
++ * This is a block-addressed SDHC, SDXC or SDUC card.
++ * Most interesting fields are unused and have fixed
+ * values. To avoid getting tripped by buggy cards,
+ * we assume those fixed values ourselves.
+ */
+@@ -159,14 +160,19 @@ static int mmc_decode_csd(struct mmc_card *card)
+ e = unstuff_bits(resp, 96, 3);
+ csd->max_dtr = tran_exp[e] * tran_mant[m];
+ csd->cmdclass = unstuff_bits(resp, 84, 12);
+- csd->c_size = unstuff_bits(resp, 48, 22);
+
+- /* SDXC cards have a minimum C_SIZE of 0x00FFFF */
+- if (csd->c_size >= 0xFFFF)
++ if (csd_struct == 1)
++ m = unstuff_bits(resp, 48, 22);
++ else
++ m = unstuff_bits(resp, 48, 28);
++ csd->c_size = m;
++
++ if (csd->c_size >= 0x400000 && is_sduc)
++ mmc_card_set_ult_capacity(card);
++ else if (csd->c_size >= 0xFFFF)
+ mmc_card_set_ext_capacity(card);
+
+- m = unstuff_bits(resp, 48, 22);
+- csd->capacity = (1 + m) << 10;
++ csd->capacity = (1 + (typeof(sector_t))m) << 10;
+
+ csd->read_blkbits = 9;
+ csd->read_partial = 0;
+@@ -876,7 +882,7 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
+ return err;
+ }
+
+-int mmc_sd_get_csd(struct mmc_card *card)
++int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc)
+ {
+ int err;
+
+@@ -887,7 +893,7 @@ int mmc_sd_get_csd(struct mmc_card *card)
+ if (err)
+ return err;
+
+- err = mmc_decode_csd(card);
++ err = mmc_decode_csd(card, is_sduc);
+ if (err)
+ return err;
+
+@@ -1442,7 +1448,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+ }
+
+ if (!oldcard) {
+- err = mmc_sd_get_csd(card);
++ err = mmc_sd_get_csd(card, false);
+ if (err)
+ goto free_card;
+
+diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h
+index fe6dd46927a42..7e8beface2ca6 100644
+--- a/drivers/mmc/core/sd.h
++++ b/drivers/mmc/core/sd.h
+@@ -10,7 +10,7 @@ struct mmc_host;
+ struct mmc_card;
+
+ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr);
+-int mmc_sd_get_csd(struct mmc_card *card);
++int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc);
+ void mmc_decode_cid(struct mmc_card *card);
+ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
+ bool reinit);
+diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
+index 4fb247fde5c08..9566837c9848e 100644
+--- a/drivers/mmc/core/sdio.c
++++ b/drivers/mmc/core/sdio.c
+@@ -769,7 +769,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
+ * Read CSD, before selecting the card
+ */
+ if (!oldcard && mmc_card_sd_combo(card)) {
+- err = mmc_sd_get_csd(card);
++ err = mmc_sd_get_csd(card, false);
+ if (err)
+ goto remove;
+
+diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
+index f34407cc27888..f39bce3223654 100644
+--- a/include/linux/mmc/card.h
++++ b/include/linux/mmc/card.h
+@@ -35,7 +35,7 @@ struct mmc_csd {
+ unsigned int wp_grp_size;
+ unsigned int read_blkbits;
+ unsigned int write_blkbits;
+- unsigned int capacity;
++ sector_t capacity;
+ unsigned int read_partial:1,
+ read_misalign:1,
+ write_partial:1,
+diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
+index 6727576a87555..865cc0ca8543d 100644
+--- a/include/linux/mmc/sd.h
++++ b/include/linux/mmc/sd.h
+@@ -36,6 +36,7 @@
+ /* OCR bit definitions */
+ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
+ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
++#define SD_OCR_2T (1 << 27) /* HO2T/CO2T - SDUC support */
+ #define SD_OCR_XPC (1 << 28) /* SDXC power control */
+ #define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
+
+--
+2.43.0
+
--- /dev/null
+From d5e292f58583470e1987eecd6039f2bb1611899e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 17:09:33 +0000
+Subject: net: avoid potential UAF in default_operstate()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 750e51603395e755537da08f745864c93e3ce741 ]
+
+syzbot reported an UAF in default_operstate() [1]
+
+Issue is a race between device and netns dismantles.
+
+After calling __rtnl_unlock() from netdev_run_todo(),
+we can not assume the netns of each device is still alive.
+
+Make sure the device is not in NETREG_UNREGISTERED state,
+and add an ASSERT_RTNL() before the call to
+__dev_get_by_index().
+
+We might move this ASSERT_RTNL() in __dev_get_by_index()
+in the future.
+
+[1]
+
+BUG: KASAN: slab-use-after-free in __dev_get_by_index+0x5d/0x110 net/core/dev.c:852
+Read of size 8 at addr ffff888043eba1b0 by task syz.0.0/5339
+
+CPU: 0 UID: 0 PID: 5339 Comm: syz.0.0 Not tainted 6.12.0-syzkaller-10296-gaaf20f870da0 #0
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:378 [inline]
+ print_report+0x169/0x550 mm/kasan/report.c:489
+ kasan_report+0x143/0x180 mm/kasan/report.c:602
+ __dev_get_by_index+0x5d/0x110 net/core/dev.c:852
+ default_operstate net/core/link_watch.c:51 [inline]
+ rfc2863_policy+0x224/0x300 net/core/link_watch.c:67
+ linkwatch_do_dev+0x3e/0x170 net/core/link_watch.c:170
+ netdev_run_todo+0x461/0x1000 net/core/dev.c:10894
+ rtnl_unlock net/core/rtnetlink.c:152 [inline]
+ rtnl_net_unlock include/linux/rtnetlink.h:133 [inline]
+ rtnl_dellink+0x760/0x8d0 net/core/rtnetlink.c:3520
+ rtnetlink_rcv_msg+0x791/0xcf0 net/core/rtnetlink.c:6911
+ netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2541
+ netlink_unicast_kernel net/netlink/af_netlink.c:1321 [inline]
+ netlink_unicast+0x7f6/0x990 net/netlink/af_netlink.c:1347
+ netlink_sendmsg+0x8e4/0xcb0 net/netlink/af_netlink.c:1891
+ sock_sendmsg_nosec net/socket.c:711 [inline]
+ __sock_sendmsg+0x221/0x270 net/socket.c:726
+ ____sys_sendmsg+0x52a/0x7e0 net/socket.c:2583
+ ___sys_sendmsg net/socket.c:2637 [inline]
+ __sys_sendmsg+0x269/0x350 net/socket.c:2669
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f2a3cb80809
+Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f2a3d9cd058 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f2a3cd45fa0 RCX: 00007f2a3cb80809
+RDX: 0000000000000000 RSI: 0000000020000000 RDI: 0000000000000008
+RBP: 00007f2a3cbf393e R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 0000000000000000 R14: 00007f2a3cd45fa0 R15: 00007ffd03bc65c8
+ </TASK>
+
+Allocated by task 5339:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
+ poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
+ __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
+ kasan_kmalloc include/linux/kasan.h:260 [inline]
+ __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4314
+ kmalloc_noprof include/linux/slab.h:901 [inline]
+ kmalloc_array_noprof include/linux/slab.h:945 [inline]
+ netdev_create_hash net/core/dev.c:11870 [inline]
+ netdev_init+0x10c/0x250 net/core/dev.c:11890
+ ops_init+0x31e/0x590 net/core/net_namespace.c:138
+ setup_net+0x287/0x9e0 net/core/net_namespace.c:362
+ copy_net_ns+0x33f/0x570 net/core/net_namespace.c:500
+ create_new_namespaces+0x425/0x7b0 kernel/nsproxy.c:110
+ unshare_nsproxy_namespaces+0x124/0x180 kernel/nsproxy.c:228
+ ksys_unshare+0x57d/0xa70 kernel/fork.c:3314
+ __do_sys_unshare kernel/fork.c:3385 [inline]
+ __se_sys_unshare kernel/fork.c:3383 [inline]
+ __x64_sys_unshare+0x38/0x40 kernel/fork.c:3383
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Freed by task 12:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
+ kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
+ poison_slab_object mm/kasan/common.c:247 [inline]
+ __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
+ kasan_slab_free include/linux/kasan.h:233 [inline]
+ slab_free_hook mm/slub.c:2338 [inline]
+ slab_free mm/slub.c:4598 [inline]
+ kfree+0x196/0x420 mm/slub.c:4746
+ netdev_exit+0x65/0xd0 net/core/dev.c:11992
+ ops_exit_list net/core/net_namespace.c:172 [inline]
+ cleanup_net+0x802/0xcc0 net/core/net_namespace.c:632
+ process_one_work kernel/workqueue.c:3229 [inline]
+ process_scheduled_works+0xa63/0x1850 kernel/workqueue.c:3310
+ worker_thread+0x870/0xd30 kernel/workqueue.c:3391
+ kthread+0x2f0/0x390 kernel/kthread.c:389
+ ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+
+The buggy address belongs to the object at ffff888043eba000
+ which belongs to the cache kmalloc-2k of size 2048
+The buggy address is located 432 bytes inside of
+ freed 2048-byte region [ffff888043eba000, ffff888043eba800)
+
+The buggy address belongs to the physical page:
+page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x43eb8
+head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
+flags: 0x4fff00000000040(head|node=1|zone=1|lastcpupid=0x7ff)
+page_type: f5(slab)
+raw: 04fff00000000040 ffff88801ac42000 dead000000000122 0000000000000000
+raw: 0000000000000000 0000000000080008 00000001f5000000 0000000000000000
+head: 04fff00000000040 ffff88801ac42000 dead000000000122 0000000000000000
+head: 0000000000000000 0000000000080008 00000001f5000000 0000000000000000
+head: 04fff00000000003 ffffea00010fae01 ffffffffffffffff 0000000000000000
+head: 0000000000000008 0000000000000000 00000000ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+page_owner tracks the page as allocated
+page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 5339, tgid 5338 (syz.0.0), ts 69674195892, free_ts 69663220888
+ set_page_owner include/linux/page_owner.h:32 [inline]
+ post_alloc_hook+0x1f3/0x230 mm/page_alloc.c:1556
+ prep_new_page mm/page_alloc.c:1564 [inline]
+ get_page_from_freelist+0x3649/0x3790 mm/page_alloc.c:3474
+ __alloc_pages_noprof+0x292/0x710 mm/page_alloc.c:4751
+ alloc_pages_mpol_noprof+0x3e8/0x680 mm/mempolicy.c:2265
+ alloc_slab_page+0x6a/0x140 mm/slub.c:2408
+ allocate_slab+0x5a/0x2f0 mm/slub.c:2574
+ new_slab mm/slub.c:2627 [inline]
+ ___slab_alloc+0xcd1/0x14b0 mm/slub.c:3815
+ __slab_alloc+0x58/0xa0 mm/slub.c:3905
+ __slab_alloc_node mm/slub.c:3980 [inline]
+ slab_alloc_node mm/slub.c:4141 [inline]
+ __do_kmalloc_node mm/slub.c:4282 [inline]
+ __kmalloc_noprof+0x2e6/0x4c0 mm/slub.c:4295
+ kmalloc_noprof include/linux/slab.h:905 [inline]
+ sk_prot_alloc+0xe0/0x210 net/core/sock.c:2165
+ sk_alloc+0x38/0x370 net/core/sock.c:2218
+ __netlink_create+0x65/0x260 net/netlink/af_netlink.c:629
+ __netlink_kernel_create+0x174/0x6f0 net/netlink/af_netlink.c:2015
+ netlink_kernel_create include/linux/netlink.h:62 [inline]
+ uevent_net_init+0xed/0x2d0 lib/kobject_uevent.c:783
+ ops_init+0x31e/0x590 net/core/net_namespace.c:138
+ setup_net+0x287/0x9e0 net/core/net_namespace.c:362
+page last free pid 1032 tgid 1032 stack trace:
+ reset_page_owner include/linux/page_owner.h:25 [inline]
+ free_pages_prepare mm/page_alloc.c:1127 [inline]
+ free_unref_page+0xdf9/0x1140 mm/page_alloc.c:2657
+ __slab_free+0x31b/0x3d0 mm/slub.c:4509
+ qlink_free mm/kasan/quarantine.c:163 [inline]
+ qlist_free_all+0x9a/0x140 mm/kasan/quarantine.c:179
+ kasan_quarantine_reduce+0x14f/0x170 mm/kasan/quarantine.c:286
+ __kasan_slab_alloc+0x23/0x80 mm/kasan/common.c:329
+ kasan_slab_alloc include/linux/kasan.h:250 [inline]
+ slab_post_alloc_hook mm/slub.c:4104 [inline]
+ slab_alloc_node mm/slub.c:4153 [inline]
+ kmem_cache_alloc_node_noprof+0x1d9/0x380 mm/slub.c:4205
+ __alloc_skb+0x1c3/0x440 net/core/skbuff.c:668
+ alloc_skb include/linux/skbuff.h:1323 [inline]
+ alloc_skb_with_frags+0xc3/0x820 net/core/skbuff.c:6612
+ sock_alloc_send_pskb+0x91a/0xa60 net/core/sock.c:2881
+ sock_alloc_send_skb include/net/sock.h:1797 [inline]
+ mld_newpack+0x1c3/0xaf0 net/ipv6/mcast.c:1747
+ add_grhead net/ipv6/mcast.c:1850 [inline]
+ add_grec+0x1492/0x19a0 net/ipv6/mcast.c:1988
+ mld_send_initial_cr+0x228/0x4b0 net/ipv6/mcast.c:2234
+ ipv6_mc_dad_complete+0x88/0x490 net/ipv6/mcast.c:2245
+ addrconf_dad_completed+0x712/0xcd0 net/ipv6/addrconf.c:4342
+ addrconf_dad_work+0xdc2/0x16f0
+ process_one_work kernel/workqueue.c:3229 [inline]
+ process_scheduled_works+0xa63/0x1850 kernel/workqueue.c:3310
+
+Memory state around the buggy address:
+ ffff888043eba080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff888043eba100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+>ffff888043eba180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ^
+ ffff888043eba200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+ ffff888043eba280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
+
+Fixes: 8c55facecd7a ("net: linkwatch: only report IF_OPER_LOWERLAYERDOWN if iflink is actually down")
+Reported-by: syzbot+1939f24bdb783e9e43d9@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/674f3a18.050a0220.48a03.0041.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://patch.msgid.link/20241203170933.2449307-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/link_watch.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/net/core/link_watch.c b/net/core/link_watch.c
+index ab150641142aa..1b4d39e380842 100644
+--- a/net/core/link_watch.c
++++ b/net/core/link_watch.c
+@@ -45,9 +45,14 @@ static unsigned int default_operstate(const struct net_device *dev)
+ int iflink = dev_get_iflink(dev);
+ struct net_device *peer;
+
+- if (iflink == dev->ifindex)
++ /* If called from netdev_run_todo()/linkwatch_sync_dev(),
++ * dev_net(dev) can be already freed, and RTNL is not held.
++ */
++ if (dev->reg_state == NETREG_UNREGISTERED ||
++ iflink == dev->ifindex)
+ return IF_OPER_DOWN;
+
++ ASSERT_RTNL();
+ peer = __dev_get_by_index(dev_net(dev), iflink);
+ if (!peer)
+ return IF_OPER_DOWN;
+--
+2.43.0
+
--- /dev/null
+From 7eee109b2ee6f97ef9d16bd789d33bf1a35979e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 17:07:19 +0800
+Subject: net: enetc: Do not configure preemptible TCs if SIs do not support
+
+From: Wei Fang <wei.fang@nxp.com>
+
+[ Upstream commit b2420b8c81ec674552d00c55d46245e5c184b260 ]
+
+Both ENETC PF and VF drivers share enetc_setup_tc_mqprio() to configure
+MQPRIO. And enetc_setup_tc_mqprio() calls enetc_change_preemptible_tcs()
+to configure preemptible TCs. However, only PF is able to configure
+preemptible TCs. Because only PF has related registers, while VF does not
+have these registers. So for VF, its hw->port pointer is NULL. Therefore,
+VF will access an invalid pointer when accessing a non-existent register,
+which will cause a crash issue. The simplified log is as follows.
+
+root@ls1028ardb:~# tc qdisc add dev eno0vf0 parent root handle 100: \
+mqprio num_tc 4 map 0 0 1 1 2 2 3 3 queues 1@0 1@1 1@2 1@3 hw 1
+[ 187.290775] Unable to handle kernel paging request at virtual address 0000000000001f00
+[ 187.424831] pc : enetc_mm_commit_preemptible_tcs+0x1c4/0x400
+[ 187.430518] lr : enetc_mm_commit_preemptible_tcs+0x30c/0x400
+[ 187.511140] Call trace:
+[ 187.513588] enetc_mm_commit_preemptible_tcs+0x1c4/0x400
+[ 187.518918] enetc_setup_tc_mqprio+0x180/0x214
+[ 187.523374] enetc_vf_setup_tc+0x1c/0x30
+[ 187.527306] mqprio_enable_offload+0x144/0x178
+[ 187.531766] mqprio_init+0x3ec/0x668
+[ 187.535351] qdisc_create+0x15c/0x488
+[ 187.539023] tc_modify_qdisc+0x398/0x73c
+[ 187.542958] rtnetlink_rcv_msg+0x128/0x378
+[ 187.547064] netlink_rcv_skb+0x60/0x130
+[ 187.550910] rtnetlink_rcv+0x18/0x24
+[ 187.554492] netlink_unicast+0x300/0x36c
+[ 187.558425] netlink_sendmsg+0x1a8/0x420
+[ 187.606759] ---[ end trace 0000000000000000 ]---
+
+In addition, some PFs also do not support configuring preemptible TCs,
+such as eno1 and eno3 on LS1028A. It won't crash like it does for VFs,
+but we should prevent these PFs from accessing these unimplemented
+registers.
+
+Fixes: 827145392a4a ("net: enetc: only commit preemptible TCs to hardware when MM TX is active")
+Signed-off-by: Wei Fang <wei.fang@nxp.com>
+Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/enetc/enetc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
+index c09370eab319b..16a7908c79f70 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc.c
+@@ -28,6 +28,9 @@ EXPORT_SYMBOL_GPL(enetc_port_mac_wr);
+ static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
+ u8 preemptible_tcs)
+ {
++ if (!(priv->si->hw_features & ENETC_SI_F_QBU))
++ return;
++
+ priv->preemptible_tcs = preemptible_tcs;
+ enetc_mm_commit_preemptible_tcs(priv);
+ }
+--
+2.43.0
+
--- /dev/null
+From 58a12937c639b9bf1dd53b3d2bf186250370faa6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2024 12:08:50 +0800
+Subject: net: Fix icmp host relookup triggering ip_rt_bug
+
+From: Dong Chenchen <dongchenchen2@huawei.com>
+
+[ Upstream commit c44daa7e3c73229f7ac74985acb8c7fb909c4e0a ]
+
+arp link failure may trigger ip_rt_bug while xfrm enabled, call trace is:
+
+WARNING: CPU: 0 PID: 0 at net/ipv4/route.c:1241 ip_rt_bug+0x14/0x20
+Modules linked in:
+CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.12.0-rc6-00077-g2e1b3cc9d7f7
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
+BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+RIP: 0010:ip_rt_bug+0x14/0x20
+Call Trace:
+ <IRQ>
+ ip_send_skb+0x14/0x40
+ __icmp_send+0x42d/0x6a0
+ ipv4_link_failure+0xe2/0x1d0
+ arp_error_report+0x3c/0x50
+ neigh_invalidate+0x8d/0x100
+ neigh_timer_handler+0x2e1/0x330
+ call_timer_fn+0x21/0x120
+ __run_timer_base.part.0+0x1c9/0x270
+ run_timer_softirq+0x4c/0x80
+ handle_softirqs+0xac/0x280
+ irq_exit_rcu+0x62/0x80
+ sysvec_apic_timer_interrupt+0x77/0x90
+
+The script below reproduces this scenario:
+ip xfrm policy add src 0.0.0.0/0 dst 0.0.0.0/0 \
+ dir out priority 0 ptype main flag localok icmp
+ip l a veth1 type veth
+ip a a 192.168.141.111/24 dev veth0
+ip l s veth0 up
+ping 192.168.141.155 -c 1
+
+icmp_route_lookup() create input routes for locally generated packets
+while xfrm relookup ICMP traffic.Then it will set input route
+(dst->out = ip_rt_bug) to skb for DESTUNREACH.
+
+For ICMP err triggered by locally generated packets, dst->dev of output
+route is loopback. Generally, xfrm relookup verification is not required
+on loopback interfaces (net.ipv4.conf.lo.disable_xfrm = 1).
+
+Skip icmp relookup for locally generated packets to fix it.
+
+Fixes: 8b7817f3a959 ("[IPSEC]: Add ICMP host relookup support")
+Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20241127040850.1513135-1-dongchenchen2@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/icmp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
+index e1384e7331d82..c3ad41573b33e 100644
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -519,6 +519,9 @@ static struct rtable *icmp_route_lookup(struct net *net,
+ if (!IS_ERR(dst)) {
+ if (rt != rt2)
+ return rt;
++ if (inet_addr_type_dev_table(net, route_lookup_dev,
++ fl4->daddr) == RTN_LOCAL)
++ return rt;
+ } else if (PTR_ERR(dst) == -EPERM) {
+ rt = NULL;
+ } else {
+--
+2.43.0
+
--- /dev/null
+From 734dd9fc6620a304c7f0085c9a06cb4651f14f39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 14:43:44 +0000
+Subject: net: hsr: avoid potential out-of-bound access in fill_frame_info()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b9653d19e556c6afd035602927a93d100a0d7644 ]
+
+syzbot is able to feed a packet with 14 bytes, pretending
+it is a vlan one.
+
+Since fill_frame_info() is relying on skb->mac_len already,
+extend the check to cover this case.
+
+BUG: KMSAN: uninit-value in fill_frame_info net/hsr/hsr_forward.c:709 [inline]
+ BUG: KMSAN: uninit-value in hsr_forward_skb+0x9ee/0x3b10 net/hsr/hsr_forward.c:724
+ fill_frame_info net/hsr/hsr_forward.c:709 [inline]
+ hsr_forward_skb+0x9ee/0x3b10 net/hsr/hsr_forward.c:724
+ hsr_dev_xmit+0x2f0/0x350 net/hsr/hsr_device.c:235
+ __netdev_start_xmit include/linux/netdevice.h:5002 [inline]
+ netdev_start_xmit include/linux/netdevice.h:5011 [inline]
+ xmit_one net/core/dev.c:3590 [inline]
+ dev_hard_start_xmit+0x247/0xa20 net/core/dev.c:3606
+ __dev_queue_xmit+0x366a/0x57d0 net/core/dev.c:4434
+ dev_queue_xmit include/linux/netdevice.h:3168 [inline]
+ packet_xmit+0x9c/0x6c0 net/packet/af_packet.c:276
+ packet_snd net/packet/af_packet.c:3146 [inline]
+ packet_sendmsg+0x91ae/0xa6f0 net/packet/af_packet.c:3178
+ sock_sendmsg_nosec net/socket.c:711 [inline]
+ __sock_sendmsg+0x30f/0x380 net/socket.c:726
+ __sys_sendto+0x594/0x750 net/socket.c:2197
+ __do_sys_sendto net/socket.c:2204 [inline]
+ __se_sys_sendto net/socket.c:2200 [inline]
+ __x64_sys_sendto+0x125/0x1d0 net/socket.c:2200
+ x64_sys_call+0x346a/0x3c30 arch/x86/include/generated/asm/syscalls_64.h:45
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Uninit was created at:
+ slab_post_alloc_hook mm/slub.c:4091 [inline]
+ slab_alloc_node mm/slub.c:4134 [inline]
+ kmem_cache_alloc_node_noprof+0x6bf/0xb80 mm/slub.c:4186
+ kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:587
+ __alloc_skb+0x363/0x7b0 net/core/skbuff.c:678
+ alloc_skb include/linux/skbuff.h:1323 [inline]
+ alloc_skb_with_frags+0xc8/0xd00 net/core/skbuff.c:6612
+ sock_alloc_send_pskb+0xa81/0xbf0 net/core/sock.c:2881
+ packet_alloc_skb net/packet/af_packet.c:2995 [inline]
+ packet_snd net/packet/af_packet.c:3089 [inline]
+ packet_sendmsg+0x74c6/0xa6f0 net/packet/af_packet.c:3178
+ sock_sendmsg_nosec net/socket.c:711 [inline]
+ __sock_sendmsg+0x30f/0x380 net/socket.c:726
+ __sys_sendto+0x594/0x750 net/socket.c:2197
+ __do_sys_sendto net/socket.c:2204 [inline]
+ __se_sys_sendto net/socket.c:2200 [inline]
+ __x64_sys_sendto+0x125/0x1d0 net/socket.c:2200
+ x64_sys_call+0x346a/0x3c30 arch/x86/include/generated/asm/syscalls_64.h:45
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 48b491a5cc74 ("net: hsr: fix mac_len checks")
+Reported-by: syzbot+671e2853f9851d039551@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/6745dc7f.050a0220.21d33d.0018.GAE@google.com/T/#u
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: WingMan Kwok <w-kwok2@ti.com>
+Cc: Murali Karicheri <m-karicheri2@ti.com>
+Cc: MD Danish Anwar <danishanwar@ti.com>
+Cc: Jiri Pirko <jiri@nvidia.com>
+Cc: George McCollister <george.mccollister@gmail.com>
+Link: https://patch.msgid.link/20241126144344.4177332-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_forward.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index b38060246e62e..40c5fbbd155d6 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -688,6 +688,8 @@ static int fill_frame_info(struct hsr_frame_info *frame,
+ frame->is_vlan = true;
+
+ if (frame->is_vlan) {
++ if (skb->mac_len < offsetofend(struct hsr_vlan_ethhdr, vlanhdr))
++ return -EINVAL;
+ vlan_hdr = (struct hsr_vlan_ethhdr *)ethhdr;
+ proto = vlan_hdr->vlanhdr.h_vlan_encapsulated_proto;
+ /* FIXME: */
+--
+2.43.0
+
--- /dev/null
+From 24bcc28271c5e52282dc347327f89bf60ddb7fa2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Dec 2024 10:05:58 +0000
+Subject: net: hsr: must allocate more bytes for RedBox support
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit af8edaeddbc52e53207d859c912b017fd9a77629 ]
+
+Blamed commit forgot to change hsr_init_skb() to allocate
+larger skb for RedBox case.
+
+Indeed, send_hsr_supervision_frame() will add
+two additional components (struct hsr_sup_tlv
+and struct hsr_sup_payload)
+
+syzbot reported the following crash:
+skbuff: skb_over_panic: text:ffffffff8afd4b0a len:34 put:6 head:ffff88802ad29e00 data:ffff88802ad29f22 tail:0x144 end:0x140 dev:gretap0
+------------[ cut here ]------------
+ kernel BUG at net/core/skbuff.c:206 !
+Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI
+CPU: 2 UID: 0 PID: 7611 Comm: syz-executor Not tainted 6.12.0-syzkaller #0
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+ RIP: 0010:skb_panic+0x157/0x1d0 net/core/skbuff.c:206
+Code: b6 04 01 84 c0 74 04 3c 03 7e 21 8b 4b 70 41 56 45 89 e8 48 c7 c7 a0 7d 9b 8c 41 57 56 48 89 ee 52 4c 89 e2 e8 9a 76 79 f8 90 <0f> 0b 4c 89 4c 24 10 48 89 54 24 08 48 89 34 24 e8 94 76 fb f8 4c
+RSP: 0018:ffffc90000858ab8 EFLAGS: 00010282
+RAX: 0000000000000087 RBX: ffff8880598c08c0 RCX: ffffffff816d3e69
+RDX: 0000000000000000 RSI: ffffffff816de786 RDI: 0000000000000005
+RBP: ffffffff8c9b91c0 R08: 0000000000000005 R09: 0000000000000000
+R10: 0000000000000302 R11: ffffffff961cc1d0 R12: ffffffff8afd4b0a
+R13: 0000000000000006 R14: ffff88804b938130 R15: 0000000000000140
+FS: 000055558a3d6500(0000) GS:ffff88806a800000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f1295974ff8 CR3: 000000002ab6e000 CR4: 0000000000352ef0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <IRQ>
+ skb_over_panic net/core/skbuff.c:211 [inline]
+ skb_put+0x174/0x1b0 net/core/skbuff.c:2617
+ send_hsr_supervision_frame+0x6fa/0x9e0 net/hsr/hsr_device.c:342
+ hsr_proxy_announce+0x1a3/0x4a0 net/hsr/hsr_device.c:436
+ call_timer_fn+0x1a0/0x610 kernel/time/timer.c:1794
+ expire_timers kernel/time/timer.c:1845 [inline]
+ __run_timers+0x6e8/0x930 kernel/time/timer.c:2419
+ __run_timer_base kernel/time/timer.c:2430 [inline]
+ __run_timer_base kernel/time/timer.c:2423 [inline]
+ run_timer_base+0x111/0x190 kernel/time/timer.c:2439
+ run_timer_softirq+0x1a/0x40 kernel/time/timer.c:2449
+ handle_softirqs+0x213/0x8f0 kernel/softirq.c:554
+ __do_softirq kernel/softirq.c:588 [inline]
+ invoke_softirq kernel/softirq.c:428 [inline]
+ __irq_exit_rcu kernel/softirq.c:637 [inline]
+ irq_exit_rcu+0xbb/0x120 kernel/softirq.c:649
+ instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline]
+ sysvec_apic_timer_interrupt+0xa4/0xc0 arch/x86/kernel/apic/apic.c:1049
+ </IRQ>
+
+Fixes: 5055cccfc2d1 ("net: hsr: Provide RedBox support (HSR-SAN)")
+Reported-by: syzbot+7f4643b267cc680bfa1c@syzkaller.appspotmail.com
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Lukasz Majewski <lukma@denx.de>
+Link: https://patch.msgid.link/20241202100558.507765-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_device.c | 19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
+index f630d6645636d..44048d7538ddc 100644
+--- a/net/hsr/hsr_device.c
++++ b/net/hsr/hsr_device.c
+@@ -246,20 +246,22 @@ static const struct header_ops hsr_header_ops = {
+ .parse = eth_header_parse,
+ };
+
+-static struct sk_buff *hsr_init_skb(struct hsr_port *master)
++static struct sk_buff *hsr_init_skb(struct hsr_port *master, int extra)
+ {
+ struct hsr_priv *hsr = master->hsr;
+ struct sk_buff *skb;
+ int hlen, tlen;
++ int len;
+
+ hlen = LL_RESERVED_SPACE(master->dev);
+ tlen = master->dev->needed_tailroom;
++ len = sizeof(struct hsr_sup_tag) + sizeof(struct hsr_sup_payload);
+ /* skb size is same for PRP/HSR frames, only difference
+ * being, for PRP it is a trailer and for HSR it is a
+- * header
++ * header.
++ * RedBox might use @extra more bytes.
+ */
+- skb = dev_alloc_skb(sizeof(struct hsr_sup_tag) +
+- sizeof(struct hsr_sup_payload) + hlen + tlen);
++ skb = dev_alloc_skb(len + extra + hlen + tlen);
+
+ if (!skb)
+ return skb;
+@@ -295,6 +297,7 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
+ struct hsr_sup_tlv *hsr_stlv;
+ struct hsr_sup_tag *hsr_stag;
+ struct sk_buff *skb;
++ int extra = 0;
+
+ *interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
+ if (hsr->announce_count < 3 && hsr->prot_version == 0) {
+@@ -303,7 +306,11 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
+ hsr->announce_count++;
+ }
+
+- skb = hsr_init_skb(port);
++ if (hsr->redbox)
++ extra = sizeof(struct hsr_sup_tlv) +
++ sizeof(struct hsr_sup_payload);
++
++ skb = hsr_init_skb(port, extra);
+ if (!skb) {
+ netdev_warn_once(port->dev, "HSR: Could not send supervision frame\n");
+ return;
+@@ -362,7 +369,7 @@ static void send_prp_supervision_frame(struct hsr_port *master,
+ struct hsr_sup_tag *hsr_stag;
+ struct sk_buff *skb;
+
+- skb = hsr_init_skb(master);
++ skb = hsr_init_skb(master, 0);
+ if (!skb) {
+ netdev_warn_once(master->dev, "PRP: Could not send supervision frame\n");
+ return;
+--
+2.43.0
+
--- /dev/null
+From 8ce3861b564bf03449b648f1b725bbef7c41024c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Nov 2024 09:59:50 +0100
+Subject: net/ipv6: release expired exception dst cached in socket
+
+From: Jiri Wiesner <jwiesner@suse.de>
+
+[ Upstream commit 3301ab7d5aeb0fe270f73a3d4810c9d1b6a9f045 ]
+
+Dst objects get leaked in ip6_negative_advice() when this function is
+executed for an expired IPv6 route located in the exception table. There
+are several conditions that must be fulfilled for the leak to occur:
+* an ICMPv6 packet indicating a change of the MTU for the path is received,
+ resulting in an exception dst being created
+* a TCP connection that uses the exception dst for routing packets must
+ start timing out so that TCP begins retransmissions
+* after the exception dst expires, the FIB6 garbage collector must not run
+ before TCP executes ip6_negative_advice() for the expired exception dst
+
+When TCP executes ip6_negative_advice() for an exception dst that has
+expired and if no other socket holds a reference to the exception dst, the
+refcount of the exception dst is 2, which corresponds to the increment
+made by dst_init() and the increment made by the TCP socket for which the
+connection is timing out. The refcount made by the socket is never
+released. The refcount of the dst is decremented in sk_dst_reset() but
+that decrement is counteracted by a dst_hold() intentionally placed just
+before the sk_dst_reset() in ip6_negative_advice(). After
+ip6_negative_advice() has finished, there is no other object tied to the
+dst. The socket lost its reference stored in sk_dst_cache and the dst is
+no longer in the exception table. The exception dst becomes a leaked
+object.
+
+As a result of this dst leak, an unbalanced refcount is reported for the
+loopback device of a net namespace being destroyed under kernels that do
+not contain e5f80fcf869a ("ipv6: give an IPv6 dev to blackhole_netdev"):
+unregister_netdevice: waiting for lo to become free. Usage count = 2
+
+Fix the dst leak by removing the dst_hold() in ip6_negative_advice(). The
+patch that introduced the dst_hold() in ip6_negative_advice() was
+92f1655aa2b22 ("net: fix __dst_negative_advice() race"). But 92f1655aa2b22
+merely refactored the code with regards to the dst refcount so the issue
+was present even before 92f1655aa2b22. The bug was introduced in
+54c1a859efd9f ("ipv6: Don't drop cache route entry unless timer actually
+expired.") where the expired cached route is deleted and the sk_dst_cache
+member of the socket is set to NULL by calling dst_negative_advice() but
+the refcount belonging to the socket is left unbalanced.
+
+The IPv4 version - ipv4_negative_advice() - is not affected by this bug.
+When the TCP connection times out ipv4_negative_advice() merely resets the
+sk_dst_cache of the socket while decrementing the refcount of the
+exception dst.
+
+Fixes: 92f1655aa2b22 ("net: fix __dst_negative_advice() race")
+Fixes: 54c1a859efd9f ("ipv6: Don't drop cache route entry unless timer actually expired.")
+Link: https://lore.kernel.org/netdev/20241113105611.GA6723@incl/T/#u
+Signed-off-by: Jiri Wiesner <jwiesner@suse.de>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20241128085950.GA4505@incl
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index cff4fbbc66efb..8ebfed5d63232 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -2780,10 +2780,10 @@ static void ip6_negative_advice(struct sock *sk,
+ if (rt->rt6i_flags & RTF_CACHE) {
+ rcu_read_lock();
+ if (rt6_check_expired(rt)) {
+- /* counteract the dst_release() in sk_dst_reset() */
+- dst_hold(dst);
++ /* rt/dst can not be destroyed yet,
++ * because of rcu_read_lock()
++ */
+ sk_dst_reset(sk);
+-
+ rt6_remove_exception_rt(rt);
+ }
+ rcu_read_unlock();
+--
+2.43.0
+
--- /dev/null
+From 8cc84cd2c364b48fc84e868bc50e360273a4a51e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 22:49:15 +0200
+Subject: net/mlx5: HWS: Fix memory leak in mlx5hws_definer_calc_layout
+
+From: Cosmin Ratiu <cratiu@nvidia.com>
+
+[ Upstream commit 530b69a26952c95ffc9e6dcd1cff6f249032780a ]
+
+It allocates a match template, which creates a compressed definer fc
+struct, but that is not deallocated.
+
+This commit fixes that.
+
+Fixes: 74a778b4a63f ("net/mlx5: HWS, added definers handling")
+Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
+Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20241203204920.232744-2-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c
+index 601fad5fc54a3..ee4058bafe119 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc_complex.c
+@@ -39,6 +39,8 @@ bool mlx5hws_bwc_match_params_is_complex(struct mlx5hws_context *ctx,
+ } else {
+ mlx5hws_err(ctx, "Failed to calculate matcher definer layout\n");
+ }
++ } else {
++ kfree(mt->fc);
+ }
+
+ mlx5hws_match_template_destroy(mt);
+--
+2.43.0
+
--- /dev/null
+From 7a7bedb371e5654ecaaad4fc1b633635b563a681 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 22:49:16 +0200
+Subject: net/mlx5: HWS: Properly set bwc queue locks lock classes
+
+From: Cosmin Ratiu <cratiu@nvidia.com>
+
+[ Upstream commit 10e0f0c018d5ce5ba4f349875c67f99c3253b5c3 ]
+
+The mentioned "Fixes" patch forgot to do that.
+
+Fixes: 9addffa34359 ("net/mlx5: HWS, use lock classes for bwc locks")
+Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
+Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20241203204920.232744-3-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c
+index 6d443e6ee8d9e..08be034bd1e16 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_send.c
+@@ -990,6 +990,7 @@ static int hws_bwc_send_queues_init(struct mlx5hws_context *ctx)
+ for (i = 0; i < bwc_queues; i++) {
+ mutex_init(&ctx->bwc_send_queue_locks[i]);
+ lockdep_register_key(ctx->bwc_lock_class_keys + i);
++ lockdep_set_class(ctx->bwc_send_queue_locks + i, ctx->bwc_lock_class_keys + i);
+ }
+
+ return 0;
+--
+2.43.0
+
--- /dev/null
+From 13ba80d60ec499b0661d061bf8422c6d5e56dc9e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 22:49:20 +0200
+Subject: net/mlx5e: Remove workaround to avoid syndrome for internal port
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit 5085f861b414e4a51ce28a891dfa32a10a54b64e ]
+
+Previously a workaround was added to avoid syndrome 0xcdb051. It is
+triggered when offload a rule with tunnel encapsulation, and
+forwarding to another table, but not matching on the internal port in
+firmware steering mode. The original workaround skips internal tunnel
+port logic, which is not correct as not all cases are considered. As
+an example, if vlan is configured on the uplink port, traffic can't
+pass because vlan header is not added with this workaround. Besides,
+there is no such issue for software steering. So, this patch removes
+that, and returns error directly if trying to offload such rule for
+firmware steering.
+
+Fixes: 06b4eac9c4be ("net/mlx5e: Don't offload internal port if filter device is out device")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Tested-by: Frode Nordahl <frode.nordahl@canonical.com>
+Reviewed-by: Chris Mi <cmi@nvidia.com>
+Reviewed-by: Ariel Levkovich <lariel@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20241203204920.232744-7-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/en/tc_tun_encap.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+index 878cbdbf5ec8b..e7e01f3298efb 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+@@ -5,6 +5,7 @@
+ #include <net/nexthop.h>
+ #include <net/ip_tunnels.h>
+ #include "tc_tun_encap.h"
++#include "fs_core.h"
+ #include "en_tc.h"
+ #include "tc_tun.h"
+ #include "rep/tc.h"
+@@ -24,10 +25,18 @@ static int mlx5e_set_int_port_tunnel(struct mlx5e_priv *priv,
+
+ route_dev = dev_get_by_index(dev_net(e->out_dev), e->route_dev_ifindex);
+
+- if (!route_dev || !netif_is_ovs_master(route_dev) ||
+- attr->parse_attr->filter_dev == e->out_dev)
++ if (!route_dev || !netif_is_ovs_master(route_dev))
+ goto out;
+
++ if (priv->mdev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_DMFS &&
++ mlx5e_eswitch_uplink_rep(attr->parse_attr->filter_dev) &&
++ (attr->esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) {
++ mlx5_core_warn(priv->mdev,
++ "Matching on external port with encap + fwd to table actions is not allowed for firmware steering\n");
++ err = -EINVAL;
++ goto out;
++ }
++
+ err = mlx5e_set_fwd_to_int_port_actions(priv, attr, e->route_dev_ifindex,
+ MLX5E_TC_INT_PORT_EGRESS,
+ &attr->action, out_index);
+--
+2.43.0
+
--- /dev/null
+From d9a180539ececa75ab28891467e3f014d4717212 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 22:49:19 +0200
+Subject: net/mlx5e: SD, Use correct mdev to build channel param
+
+From: Tariq Toukan <tariqt@nvidia.com>
+
+[ Upstream commit 31f114c3d158dacbeda33f2afb0ca41f4ec6c9f9 ]
+
+In a multi-PF netdev, each traffic channel creates its own resources
+against a specific PF.
+In the cited commit, where this support was added, the channel_param
+logic was mistakenly kept unchanged, so it always used the primary PF
+which is found at priv->mdev.
+In this patch we fix this by moving the logic to be per-channel, and
+passing the correct mdev instance.
+
+This bug happened to be usually harmless, as the resulting cparam
+structures would be the same for all channels, due to identical FW logic
+and decisions.
+However, in some use cases, like fwreset, this gets broken.
+
+This could lead to different symptoms. Example:
+Error cqe on cqn 0x428, ci 0x0, qn 0x10a9, opcode 0xe, syndrome 0x4,
+vendor syndrome 0x32
+
+Fixes: e4f9686bdee7 ("net/mlx5e: Let channels be SD-aware")
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Lama Kayal <lkayal@nvidia.com>
+Reviewed-by: Gal Pressman <gal@nvidia.com>
+Link: https://patch.msgid.link/20241203204920.232744-6-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/en_main.c | 32 ++++++++++---------
+ 1 file changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index 13a3fa8dc0cb0..c14bef83d84d0 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -2652,11 +2652,11 @@ void mlx5e_trigger_napi_sched(struct napi_struct *napi)
+
+ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
+ struct mlx5e_params *params,
+- struct mlx5e_channel_param *cparam,
+ struct xsk_buff_pool *xsk_pool,
+ struct mlx5e_channel **cp)
+ {
+ struct net_device *netdev = priv->netdev;
++ struct mlx5e_channel_param *cparam;
+ struct mlx5_core_dev *mdev;
+ struct mlx5e_xsk_param xsk;
+ struct mlx5e_channel *c;
+@@ -2678,8 +2678,15 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
+ return err;
+
+ c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
+- if (!c)
+- return -ENOMEM;
++ cparam = kvzalloc(sizeof(*cparam), GFP_KERNEL);
++ if (!c || !cparam) {
++ err = -ENOMEM;
++ goto err_free;
++ }
++
++ err = mlx5e_build_channel_param(mdev, params, cparam);
++ if (err)
++ goto err_free;
+
+ c->priv = priv;
+ c->mdev = mdev;
+@@ -2713,6 +2720,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
+
+ *cp = c;
+
++ kvfree(cparam);
+ return 0;
+
+ err_close_queues:
+@@ -2721,6 +2729,8 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
+ err_napi_del:
+ netif_napi_del(&c->napi);
+
++err_free:
++ kvfree(cparam);
+ kvfree(c);
+
+ return err;
+@@ -2779,20 +2789,14 @@ static void mlx5e_close_channel(struct mlx5e_channel *c)
+ int mlx5e_open_channels(struct mlx5e_priv *priv,
+ struct mlx5e_channels *chs)
+ {
+- struct mlx5e_channel_param *cparam;
+ int err = -ENOMEM;
+ int i;
+
+ chs->num = chs->params.num_channels;
+
+ chs->c = kcalloc(chs->num, sizeof(struct mlx5e_channel *), GFP_KERNEL);
+- cparam = kvzalloc(sizeof(struct mlx5e_channel_param), GFP_KERNEL);
+- if (!chs->c || !cparam)
+- goto err_free;
+-
+- err = mlx5e_build_channel_param(priv->mdev, &chs->params, cparam);
+- if (err)
+- goto err_free;
++ if (!chs->c)
++ goto err_out;
+
+ for (i = 0; i < chs->num; i++) {
+ struct xsk_buff_pool *xsk_pool = NULL;
+@@ -2800,7 +2804,7 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
+ if (chs->params.xdp_prog)
+ xsk_pool = mlx5e_xsk_get_pool(&chs->params, chs->params.xsk, i);
+
+- err = mlx5e_open_channel(priv, i, &chs->params, cparam, xsk_pool, &chs->c[i]);
++ err = mlx5e_open_channel(priv, i, &chs->params, xsk_pool, &chs->c[i]);
+ if (err)
+ goto err_close_channels;
+ }
+@@ -2818,7 +2822,6 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
+ }
+
+ mlx5e_health_channels_update(priv);
+- kvfree(cparam);
+ return 0;
+
+ err_close_ptp:
+@@ -2829,9 +2832,8 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
+ for (i--; i >= 0; i--)
+ mlx5e_close_channel(chs->c[i]);
+
+-err_free:
+ kfree(chs->c);
+- kvfree(cparam);
++err_out:
+ chs->num = 0;
+ return err;
+ }
+--
+2.43.0
+
--- /dev/null
+From 23a740629c48b72a71ac94e3aa34786ccce9a7ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 09:40:50 +0100
+Subject: net: phy: microchip: Reset LAN88xx PHY to ensure clean link state on
+ LAN7800/7850
+
+From: Oleksij Rempel <o.rempel@pengutronix.de>
+
+[ Upstream commit ccb989e4d1efe0dd81b28c437443532d80d9ecee ]
+
+Fix outdated MII_LPA data in the LAN88xx PHY, which is used in LAN7800
+and LAN7850 USB Ethernet controllers. Due to a hardware limitation, the
+PHY cannot reliably update link status after parallel detection when the
+link partner does not support auto-negotiation. To mitigate this, add a
+PHY reset in `lan88xx_link_change_notify()` when `phydev->state` is
+`PHY_NOLINK`, ensuring the PHY starts in a clean state and reports
+accurate fixed link parallel detection results.
+
+Fixes: 792aec47d59d9 ("add microchip LAN88xx phy driver")
+Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
+Link: https://patch.msgid.link/20241125084050.414352-1-o.rempel@pengutronix.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/microchip.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c
+index d3273bc0da4a1..691969a4910f2 100644
+--- a/drivers/net/phy/microchip.c
++++ b/drivers/net/phy/microchip.c
+@@ -351,6 +351,22 @@ static int lan88xx_config_aneg(struct phy_device *phydev)
+ static void lan88xx_link_change_notify(struct phy_device *phydev)
+ {
+ int temp;
++ int ret;
++
++ /* Reset PHY to ensure MII_LPA provides up-to-date information. This
++ * issue is reproducible only after parallel detection, as described
++ * in IEEE 802.3-2022, Section 28.2.3.1 ("Parallel detection function"),
++ * where the link partner does not support auto-negotiation.
++ */
++ if (phydev->state == PHY_NOLINK) {
++ ret = phy_init_hw(phydev);
++ if (ret < 0)
++ goto link_change_notify_failed;
++
++ ret = _phy_start_aneg(phydev);
++ if (ret < 0)
++ goto link_change_notify_failed;
++ }
+
+ /* At forced 100 F/H mode, chip may fail to set mode correctly
+ * when cable is switched between long(~50+m) and short one.
+@@ -377,6 +393,11 @@ static void lan88xx_link_change_notify(struct phy_device *phydev)
+ temp |= LAN88XX_INT_MASK_MDINTPIN_EN_;
+ phy_write(phydev, LAN88XX_INT_MASK, temp);
+ }
++
++ return;
++
++link_change_notify_failed:
++ phydev_err(phydev, "Link change process failed %pe\n", ERR_PTR(ret));
+ }
+
+ /**
+--
+2.43.0
+
--- /dev/null
+From d08029ff6d5b91c0cc29c98ede2a909b1fe19cd7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Nov 2024 09:33:58 +0100
+Subject: net/qed: allow old cards not supporting "num_images" to work
+
+From: Louis Leseur <louis.leseur@gmail.com>
+
+[ Upstream commit 7a0ea70da56ee8c2716d0b79e9959d3c47efab62 ]
+
+Commit 43645ce03e00 ("qed: Populate nvm image attribute shadow.")
+added support for populating flash image attributes, notably
+"num_images". However, some cards were not able to return this
+information. In such cases, the driver would return EINVAL, causing the
+driver to exit.
+
+Add check to return EOPNOTSUPP instead of EINVAL when the card is not
+able to return these information. The caller function already handles
+EOPNOTSUPP without error.
+
+Fixes: 43645ce03e00 ("qed: Populate nvm image attribute shadow.")
+Co-developed-by: Florian Forestier <florian@forestier.re>
+Signed-off-by: Florian Forestier <florian@forestier.re>
+Signed-off-by: Louis Leseur <louis.leseur@gmail.com>
+Link: https://patch.msgid.link/20241128083633.26431-1-louis.leseur@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+index 16e6bd4661433..6218d9c268554 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+@@ -3314,7 +3314,9 @@ int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn,
+ if (rc)
+ return rc;
+
+- if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
++ if (((rsp & FW_MSG_CODE_MASK) == FW_MSG_CODE_UNSUPPORTED))
++ rc = -EOPNOTSUPP;
++ else if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
+ rc = -EINVAL;
+
+ return rc;
+--
+2.43.0
+
--- /dev/null
+From 2aa423f4ec3703b41cb1236e0ecfb2b89d9c148c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Dec 2024 10:21:38 -0500
+Subject: net: sched: fix erspan_opt settings in cls_flower
+
+From: Xin Long <lucien.xin@gmail.com>
+
+[ Upstream commit 292207809486d99c78068d3f459cbbbffde88415 ]
+
+When matching erspan_opt in cls_flower, only the (version, dir, hwid)
+fields are relevant. However, in fl_set_erspan_opt() it initializes
+all bits of erspan_opt and its mask to 1. This inadvertently requires
+packets to match not only the (version, dir, hwid) fields but also the
+other fields that are unexpectedly set to 1.
+
+This patch resolves the issue by ensuring that only the (version, dir,
+hwid) fields are configured in fl_set_erspan_opt(), leaving the other
+fields to 0 in erspan_opt.
+
+Fixes: 79b1011cb33d ("net: sched: allow flower to match erspan options")
+Reported-by: Shuang Li <shuali@redhat.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Reviewed-by: Cong Wang <cong.wang@bytedance.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_flower.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
+index e280c27cb9f9a..1008ec8a464c9 100644
+--- a/net/sched/cls_flower.c
++++ b/net/sched/cls_flower.c
+@@ -1369,7 +1369,6 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
+ int err;
+
+ md = (struct erspan_metadata *)&key->enc_opts.data[key->enc_opts.len];
+- memset(md, 0xff, sizeof(*md));
+ md->version = 1;
+
+ if (!depth)
+@@ -1398,9 +1397,9 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
+ NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option index");
+ return -EINVAL;
+ }
++ memset(&md->u.index, 0xff, sizeof(md->u.index));
+ if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]) {
+ nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX];
+- memset(&md->u, 0x00, sizeof(md->u));
+ md->u.index = nla_get_be32(nla);
+ }
+ } else if (md->version == 2) {
+@@ -1409,10 +1408,12 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
+ NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option dir or hwid");
+ return -EINVAL;
+ }
++ md->u.md2.dir = 1;
+ if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR]) {
+ nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR];
+ md->u.md2.dir = nla_get_u8(nla);
+ }
++ set_hwid(&md->u.md2, 0xff);
+ if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID]) {
+ nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID];
+ set_hwid(&md->u.md2, nla_get_u8(nla));
+--
+2.43.0
+
--- /dev/null
+From 972bc384e359af5b677af6781e3c0c2b6940b027 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 18:46:07 +0100
+Subject: net/sched: tbf: correct backlog statistic for GSO packets
+
+From: Martin Ottens <martin.ottens@fau.de>
+
+[ Upstream commit 1596a135e3180c92e42dd1fbcad321f4fb3e3b17 ]
+
+When the length of a GSO packet in the tbf qdisc is larger than the burst
+size configured the packet will be segmented by the tbf_segment function.
+Whenever this function is used to enqueue SKBs, the backlog statistic of
+the tbf is not increased correctly. This can lead to underflows of the
+'backlog' byte-statistic value when these packets are dequeued from tbf.
+
+Reproduce the bug:
+Ensure that the sender machine has GSO enabled. Configured the tbf on
+the outgoing interface of the machine as follows (burstsize = 1 MTU):
+$ tc qdisc add dev <oif> root handle 1: tbf rate 50Mbit burst 1514 latency 50ms
+
+Send bulk TCP traffic out via this interface, e.g., by running an iPerf3
+client on this machine. Check the qdisc statistics:
+$ tc -s qdisc show dev <oif>
+
+The 'backlog' byte-statistic has incorrect values while traffic is
+transferred, e.g., high values due to u32 underflows. When the transfer
+is stopped, the value is != 0, which should never happen.
+
+This patch fixes this bug by updating the statistics correctly, even if
+single SKBs of a GSO SKB cannot be enqueued.
+
+Fixes: e43ac79a4bc6 ("sch_tbf: segment too big GSO packets")
+Signed-off-by: Martin Ottens <martin.ottens@fau.de>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20241125174608.1484356-1-martin.ottens@fau.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_tbf.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
+index f1d09183ae632..dc26b22d53c73 100644
+--- a/net/sched/sch_tbf.c
++++ b/net/sched/sch_tbf.c
+@@ -208,7 +208,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
+ struct tbf_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *segs, *nskb;
+ netdev_features_t features = netif_skb_features(skb);
+- unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
++ unsigned int len = 0, prev_len = qdisc_pkt_len(skb), seg_len;
+ int ret, nb;
+
+ segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+@@ -219,21 +219,27 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
+ nb = 0;
+ skb_list_walk_safe(segs, segs, nskb) {
+ skb_mark_not_on_list(segs);
+- qdisc_skb_cb(segs)->pkt_len = segs->len;
+- len += segs->len;
++ seg_len = segs->len;
++ qdisc_skb_cb(segs)->pkt_len = seg_len;
+ ret = qdisc_enqueue(segs, q->qdisc, to_free);
+ if (ret != NET_XMIT_SUCCESS) {
+ if (net_xmit_drop_count(ret))
+ qdisc_qstats_drop(sch);
+ } else {
+ nb++;
++ len += seg_len;
+ }
+ }
+ sch->q.qlen += nb;
+- if (nb > 1)
++ sch->qstats.backlog += len;
++ if (nb > 0) {
+ qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
+- consume_skb(skb);
+- return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
++ consume_skb(skb);
++ return NET_XMIT_SUCCESS;
++ }
++
++ kfree_skb(skb);
++ return NET_XMIT_DROP;
+ }
+
+ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+--
+2.43.0
+
--- /dev/null
+From b4d855855a45f244760430d3f42ff72466aa7f06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2024 21:30:14 +0800
+Subject: net/smc: fix LGR and link use-after-free issue
+
+From: Wen Gu <guwen@linux.alibaba.com>
+
+[ Upstream commit 2c7f14ed9c19ec0f149479d1c2842ec1f9bf76d7 ]
+
+We encountered a LGR/link use-after-free issue, which manifested as
+the LGR/link refcnt reaching 0 early and entering the clear process,
+making resource access unsafe.
+
+ refcount_t: addition on 0; use-after-free.
+ WARNING: CPU: 14 PID: 107447 at lib/refcount.c:25 refcount_warn_saturate+0x9c/0x140
+ Workqueue: events smc_lgr_terminate_work [smc]
+ Call trace:
+ refcount_warn_saturate+0x9c/0x140
+ __smc_lgr_terminate.part.45+0x2a8/0x370 [smc]
+ smc_lgr_terminate_work+0x28/0x30 [smc]
+ process_one_work+0x1b8/0x420
+ worker_thread+0x158/0x510
+ kthread+0x114/0x118
+
+or
+
+ refcount_t: underflow; use-after-free.
+ WARNING: CPU: 6 PID: 93140 at lib/refcount.c:28 refcount_warn_saturate+0xf0/0x140
+ Workqueue: smc_hs_wq smc_listen_work [smc]
+ Call trace:
+ refcount_warn_saturate+0xf0/0x140
+ smcr_link_put+0x1cc/0x1d8 [smc]
+ smc_conn_free+0x110/0x1b0 [smc]
+ smc_conn_abort+0x50/0x60 [smc]
+ smc_listen_find_device+0x75c/0x790 [smc]
+ smc_listen_work+0x368/0x8a0 [smc]
+ process_one_work+0x1b8/0x420
+ worker_thread+0x158/0x510
+ kthread+0x114/0x118
+
+It is caused by repeated release of LGR/link refcnt. One suspect is that
+smc_conn_free() is called repeatedly because some smc_conn_free() from
+server listening path are not protected by sock lock.
+
+e.g.
+
+Calls under socklock | smc_listen_work
+-------------------------------------------------------
+lock_sock(sk) | smc_conn_abort
+smc_conn_free | \- smc_conn_free
+\- smcr_link_put | \- smcr_link_put (duplicated)
+release_sock(sk)
+
+So here add sock lock protection in smc_listen_work() path, making it
+exclusive with other connection operations.
+
+Fixes: 3b2dec2603d5 ("net/smc: restructure client and server code in af_smc")
+Co-developed-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
+Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
+Co-developed-by: Kai <KaiShen@linux.alibaba.com>
+Signed-off-by: Kai <KaiShen@linux.alibaba.com>
+Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
+Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index ed6d4d520bc7a..9e6c69d18581c 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1900,6 +1900,7 @@ static void smc_listen_out(struct smc_sock *new_smc)
+ if (tcp_sk(new_smc->clcsock->sk)->syn_smc)
+ atomic_dec(&lsmc->queued_smc_hs);
+
++ release_sock(newsmcsk); /* lock in smc_listen_work() */
+ if (lsmc->sk.sk_state == SMC_LISTEN) {
+ lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
+ smc_accept_enqueue(&lsmc->sk, newsmcsk);
+@@ -2421,6 +2422,7 @@ static void smc_listen_work(struct work_struct *work)
+ u8 accept_version;
+ int rc = 0;
+
++ lock_sock(&new_smc->sk); /* release in smc_listen_out() */
+ if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
+ return smc_listen_out_err(new_smc);
+
+--
+2.43.0
+
--- /dev/null
+From 9f9c38173cb2bea4fd2214dbffce14f24a1715cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2024 21:30:13 +0800
+Subject: net/smc: initialize close_work early to avoid warning
+
+From: Wen Gu <guwen@linux.alibaba.com>
+
+[ Upstream commit 0541db8ee32c09463a72d0987382b3a3336b0043 ]
+
+We encountered a warning that close_work was canceled before
+initialization.
+
+ WARNING: CPU: 7 PID: 111103 at kernel/workqueue.c:3047 __flush_work+0x19e/0x1b0
+ Workqueue: events smc_lgr_terminate_work [smc]
+ RIP: 0010:__flush_work+0x19e/0x1b0
+ Call Trace:
+ ? __wake_up_common+0x7a/0x190
+ ? work_busy+0x80/0x80
+ __cancel_work_timer+0xe3/0x160
+ smc_close_cancel_work+0x1a/0x70 [smc]
+ smc_close_active_abort+0x207/0x360 [smc]
+ __smc_lgr_terminate.part.38+0xc8/0x180 [smc]
+ process_one_work+0x19e/0x340
+ worker_thread+0x30/0x370
+ ? process_one_work+0x340/0x340
+ kthread+0x117/0x130
+ ? __kthread_cancel_work+0x50/0x50
+ ret_from_fork+0x22/0x30
+
+This is because when smc_close_cancel_work is triggered, e.g. the RDMA
+driver is rmmod and the LGR is terminated, the conn->close_work is
+flushed before initialization, resulting in WARN_ON(!work->func).
+
+__smc_lgr_terminate | smc_connect_{rdma|ism}
+-------------------------------------------------------------
+ | smc_conn_create
+ | \- smc_lgr_register_conn
+for conn in lgr->conns_all |
+\- smc_conn_kill |
+ \- smc_close_active_abort |
+ \- smc_close_cancel_work |
+ \- cancel_work_sync |
+ \- __flush_work |
+ (close_work) |
+ | smc_close_init
+ | \- INIT_WORK(&close_work)
+
+So fix this by initializing close_work before establishing the
+connection.
+
+Fixes: 46c28dbd4c23 ("net/smc: no socket state changes in tasklet context")
+Fixes: 413498440e30 ("net/smc: add SMC-D support in af_smc")
+Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
+Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 9d76e902fd770..ed6d4d520bc7a 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -383,6 +383,7 @@ void smc_sk_init(struct net *net, struct sock *sk, int protocol)
+ smc->limit_smc_hs = net->smc.limit_smc_hs;
+ smc->use_fallback = false; /* assume rdma capability first */
+ smc->fallback_rsn = 0;
++ smc_close_init(smc);
+ }
+
+ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
+@@ -1299,7 +1300,6 @@ static int smc_connect_rdma(struct smc_sock *smc,
+ goto connect_abort;
+ }
+
+- smc_close_init(smc);
+ smc_rx_init(smc);
+
+ if (ini->first_contact_local) {
+@@ -1435,7 +1435,6 @@ static int smc_connect_ism(struct smc_sock *smc,
+ goto connect_abort;
+ }
+ }
+- smc_close_init(smc);
+ smc_rx_init(smc);
+ smc_tx_init(smc);
+
+@@ -2479,7 +2478,6 @@ static void smc_listen_work(struct work_struct *work)
+ goto out_decl;
+
+ mutex_lock(&smc_server_lgr_pending);
+- smc_close_init(new_smc);
+ smc_rx_init(new_smc);
+ smc_tx_init(new_smc);
+
+--
+2.43.0
+
--- /dev/null
+From 431a2802e6e1bed538f5ad8c118151ca72e941f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Nov 2024 16:30:38 +0100
+Subject: netfilter: ipset: Hold module reference while requesting a module
+
+From: Phil Sutter <phil@nwl.cc>
+
+[ Upstream commit 456f010bfaefde84d3390c755eedb1b0a5857c3c ]
+
+User space may unload ip_set.ko while it is itself requesting a set type
+backend module, leading to a kernel crash. The race condition may be
+provoked by inserting an mdelay() right after the nfnl_unlock() call.
+
+Fixes: a7b4f989a629 ("netfilter: ipset: IP set core support")
+Signed-off-by: Phil Sutter <phil@nwl.cc>
+Acked-by: Jozsef Kadlecsik <kadlec@netfilter.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/ipset/ip_set_core.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index 61431690cbd5f..cc20e6d56807c 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -104,14 +104,19 @@ find_set_type(const char *name, u8 family, u8 revision)
+ static bool
+ load_settype(const char *name)
+ {
++ if (!try_module_get(THIS_MODULE))
++ return false;
++
+ nfnl_unlock(NFNL_SUBSYS_IPSET);
+ pr_debug("try to load ip_set_%s\n", name);
+ if (request_module("ip_set_%s", name) < 0) {
+ pr_warn("Can't find ip_set type %s\n", name);
+ nfnl_lock(NFNL_SUBSYS_IPSET);
++ module_put(THIS_MODULE);
+ return false;
+ }
+ nfnl_lock(NFNL_SUBSYS_IPSET);
++ module_put(THIS_MODULE);
+ return true;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 1687199e15d45a57d3971a6e1b80f6cba6cbbb8f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2024 12:46:54 +0100
+Subject: netfilter: nft_inner: incorrect percpu area handling under softirq
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 7b1d83da254be3bf054965c8f3b1ad976f460ae5 ]
+
+Softirq can interrupt ongoing packet from process context that is
+walking over the percpu area that contains inner header offsets.
+
+Disable bh and perform three checks before restoring the percpu inner
+header offsets to validate that the percpu area is valid for this
+skbuff:
+
+1) If the NFT_PKTINFO_INNER_FULL flag is set on, then this skbuff
+ has already been parsed before for inner header fetching to
+ register.
+
+2) Validate that the percpu area refers to this skbuff using the
+ skbuff pointer as a cookie. If there is a cookie mismatch, then
+ this skbuff needs to be parsed again.
+
+3) Finally, validate if the percpu area refers to this tunnel type.
+
+Only after these three checks the percpu area is restored to a on-stack
+copy and bh is enabled again.
+
+After inner header fetching, the on-stack copy is stored back to the
+percpu area.
+
+Fixes: 3a07327d10a0 ("netfilter: nft_inner: support for inner tunnel header matching")
+Reported-by: syzbot+84d0441b9860f0d63285@syzkaller.appspotmail.com
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables_core.h | 1 +
+ net/netfilter/nft_inner.c | 57 ++++++++++++++++++++------
+ 2 files changed, 46 insertions(+), 12 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
+index ff27cb2e16620..03b6165756fc5 100644
+--- a/include/net/netfilter/nf_tables_core.h
++++ b/include/net/netfilter/nf_tables_core.h
+@@ -161,6 +161,7 @@ enum {
+ };
+
+ struct nft_inner_tun_ctx {
++ unsigned long cookie;
+ u16 type;
+ u16 inner_tunoff;
+ u16 inner_lloff;
+diff --git a/net/netfilter/nft_inner.c b/net/netfilter/nft_inner.c
+index 928312d01eb1d..817ab978d24a1 100644
+--- a/net/netfilter/nft_inner.c
++++ b/net/netfilter/nft_inner.c
+@@ -210,35 +210,66 @@ static int nft_inner_parse(const struct nft_inner *priv,
+ struct nft_pktinfo *pkt,
+ struct nft_inner_tun_ctx *tun_ctx)
+ {
+- struct nft_inner_tun_ctx ctx = {};
+ u32 off = pkt->inneroff;
+
+ if (priv->flags & NFT_INNER_HDRSIZE &&
+- nft_inner_parse_tunhdr(priv, pkt, &ctx, &off) < 0)
++ nft_inner_parse_tunhdr(priv, pkt, tun_ctx, &off) < 0)
+ return -1;
+
+ if (priv->flags & (NFT_INNER_LL | NFT_INNER_NH)) {
+- if (nft_inner_parse_l2l3(priv, pkt, &ctx, off) < 0)
++ if (nft_inner_parse_l2l3(priv, pkt, tun_ctx, off) < 0)
+ return -1;
+ } else if (priv->flags & NFT_INNER_TH) {
+- ctx.inner_thoff = off;
+- ctx.flags |= NFT_PAYLOAD_CTX_INNER_TH;
++ tun_ctx->inner_thoff = off;
++ tun_ctx->flags |= NFT_PAYLOAD_CTX_INNER_TH;
+ }
+
+- *tun_ctx = ctx;
+ tun_ctx->type = priv->type;
++ tun_ctx->cookie = (unsigned long)pkt->skb;
+ pkt->flags |= NFT_PKTINFO_INNER_FULL;
+
+ return 0;
+ }
+
++static bool nft_inner_restore_tun_ctx(const struct nft_pktinfo *pkt,
++ struct nft_inner_tun_ctx *tun_ctx)
++{
++ struct nft_inner_tun_ctx *this_cpu_tun_ctx;
++
++ local_bh_disable();
++ this_cpu_tun_ctx = this_cpu_ptr(&nft_pcpu_tun_ctx);
++ if (this_cpu_tun_ctx->cookie != (unsigned long)pkt->skb) {
++ local_bh_enable();
++ return false;
++ }
++ *tun_ctx = *this_cpu_tun_ctx;
++ local_bh_enable();
++
++ return true;
++}
++
++static void nft_inner_save_tun_ctx(const struct nft_pktinfo *pkt,
++ const struct nft_inner_tun_ctx *tun_ctx)
++{
++ struct nft_inner_tun_ctx *this_cpu_tun_ctx;
++
++ local_bh_disable();
++ this_cpu_tun_ctx = this_cpu_ptr(&nft_pcpu_tun_ctx);
++ if (this_cpu_tun_ctx->cookie != tun_ctx->cookie)
++ *this_cpu_tun_ctx = *tun_ctx;
++ local_bh_enable();
++}
++
+ static bool nft_inner_parse_needed(const struct nft_inner *priv,
+ const struct nft_pktinfo *pkt,
+- const struct nft_inner_tun_ctx *tun_ctx)
++ struct nft_inner_tun_ctx *tun_ctx)
+ {
+ if (!(pkt->flags & NFT_PKTINFO_INNER_FULL))
+ return true;
+
++ if (!nft_inner_restore_tun_ctx(pkt, tun_ctx))
++ return true;
++
+ if (priv->type != tun_ctx->type)
+ return true;
+
+@@ -248,27 +279,29 @@ static bool nft_inner_parse_needed(const struct nft_inner *priv,
+ static void nft_inner_eval(const struct nft_expr *expr, struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+ {
+- struct nft_inner_tun_ctx *tun_ctx = this_cpu_ptr(&nft_pcpu_tun_ctx);
+ const struct nft_inner *priv = nft_expr_priv(expr);
++ struct nft_inner_tun_ctx tun_ctx = {};
+
+ if (nft_payload_inner_offset(pkt) < 0)
+ goto err;
+
+- if (nft_inner_parse_needed(priv, pkt, tun_ctx) &&
+- nft_inner_parse(priv, (struct nft_pktinfo *)pkt, tun_ctx) < 0)
++ if (nft_inner_parse_needed(priv, pkt, &tun_ctx) &&
++ nft_inner_parse(priv, (struct nft_pktinfo *)pkt, &tun_ctx) < 0)
+ goto err;
+
+ switch (priv->expr_type) {
+ case NFT_INNER_EXPR_PAYLOAD:
+- nft_payload_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, tun_ctx);
++ nft_payload_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, &tun_ctx);
+ break;
+ case NFT_INNER_EXPR_META:
+- nft_meta_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, tun_ctx);
++ nft_meta_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, &tun_ctx);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ goto err;
+ }
++ nft_inner_save_tun_ctx(pkt, &tun_ctx);
++
+ return;
+ err:
+ regs->verdict.code = NFT_BREAK;
+--
+2.43.0
+
--- /dev/null
+From 7054911dee973c8b9a100359ee62e33c9fa94c24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Dec 2024 00:04:49 +0100
+Subject: netfilter: nft_set_hash: skip duplicated elements pending gc run
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 7ffc7481153bbabf3332c6a19b289730c7e1edf5 ]
+
+rhashtable does not provide stable walk, duplicated elements are
+possible in case of resizing. I considered that checking for errors when
+calling rhashtable_walk_next() was sufficient to detect the resizing.
+However, rhashtable_walk_next() returns -EAGAIN only at the end of the
+iteration, which is too late, because a gc work containing duplicated
+elements could have been already scheduled for removal to the worker.
+
+Add a u32 gc worker sequence number per set, bump it on every workqueue
+run. Annotate gc worker sequence number on the expired element. Use it
+to skip those already seen in this gc workqueue run.
+
+Note that this new field is never reset in case gc transaction fails, so
+next gc worker run on the expired element overrides it. Wraparound of gc
+worker sequence number should not be an issue with stale gc worker
+sequence number in the element, that would just postpone the element
+removal in one gc run.
+
+Note that it is not possible to use flags to annotate that element is
+pending gc run to detect duplicates, given that gc transaction can be
+invalidated in case of update from the control plane, therefore, not
+allowing to clear such flag.
+
+On x86_64, pahole reports no changes in the size of nft_rhash_elem.
+
+Fixes: f6c383b8c31a ("netfilter: nf_tables: adapt set backend to use GC transaction API")
+Reported-by: Laurent Fasnacht <laurent.fasnacht@proton.ch>
+Tested-by: Laurent Fasnacht <laurent.fasnacht@proton.ch>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_set_hash.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index daa56dda737ae..b93f046ac7d1e 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -24,11 +24,13 @@
+ struct nft_rhash {
+ struct rhashtable ht;
+ struct delayed_work gc_work;
++ u32 wq_gc_seq;
+ };
+
+ struct nft_rhash_elem {
+ struct nft_elem_priv priv;
+ struct rhash_head node;
++ u32 wq_gc_seq;
+ struct nft_set_ext ext;
+ };
+
+@@ -338,6 +340,10 @@ static void nft_rhash_gc(struct work_struct *work)
+ if (!gc)
+ goto done;
+
++ /* Elements never collected use a zero gc worker sequence number. */
++ if (unlikely(++priv->wq_gc_seq == 0))
++ priv->wq_gc_seq++;
++
+ rhashtable_walk_enter(&priv->ht, &hti);
+ rhashtable_walk_start(&hti);
+
+@@ -355,6 +361,14 @@ static void nft_rhash_gc(struct work_struct *work)
+ goto try_later;
+ }
+
++ /* rhashtable walk is unstable, already seen in this gc run?
++ * Then, skip this element. In case of (unlikely) sequence
++ * wraparound and stale element wq_gc_seq, next gc run will
++ * just find this expired element.
++ */
++ if (he->wq_gc_seq == priv->wq_gc_seq)
++ continue;
++
+ if (nft_set_elem_is_dead(&he->ext))
+ goto dead_elem;
+
+@@ -371,6 +385,8 @@ static void nft_rhash_gc(struct work_struct *work)
+ if (!gc)
+ goto try_later;
+
++ /* annotate gc sequence for this attempt. */
++ he->wq_gc_seq = priv->wq_gc_seq;
+ nft_trans_gc_elem_add(gc, he);
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 3750957685f341895efbc27d0be8af4fc0ffd8b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 11:59:06 +0100
+Subject: netfilter: nft_socket: remove WARN_ON_ONCE on maximum cgroup level
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit b7529880cb961d515642ce63f9d7570869bbbdc3 ]
+
+cgroup maximum depth is INT_MAX by default, there is a cgroup toggle to
+restrict this maximum depth to a more reasonable value not to harm
+performance. Remove unnecessary WARN_ON_ONCE which is reachable from
+userspace.
+
+Fixes: 7f3287db6543 ("netfilter: nft_socket: make cgroupsv2 matching work with namespaces")
+Reported-by: syzbot+57bac0866ddd99fe47c0@syzkaller.appspotmail.com
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_socket.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
+index f5da0c1775f2e..35d0409b00950 100644
+--- a/net/netfilter/nft_socket.c
++++ b/net/netfilter/nft_socket.c
+@@ -68,7 +68,7 @@ static noinline int nft_socket_cgroup_subtree_level(void)
+
+ cgroup_put(cgrp);
+
+- if (WARN_ON_ONCE(level > 255))
++ if (level > 255)
+ return -ERANGE;
+
+ if (WARN_ON_ONCE(level < 0))
+--
+2.43.0
+
--- /dev/null
+From 6975d5ee6c1ca9daa4cc09e3f12f0c9d2dbf0796 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Nov 2024 09:55:42 +0300
+Subject: netfilter: x_tables: fix LED ID check in led_tg_check()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 04317f4eb2aad312ad85c1a17ad81fe75f1f9bc7 ]
+
+Syzbot has reported the following BUG detected by KASAN:
+
+BUG: KASAN: slab-out-of-bounds in strlen+0x58/0x70
+Read of size 1 at addr ffff8881022da0c8 by task repro/5879
+...
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x241/0x360
+ ? __pfx_dump_stack_lvl+0x10/0x10
+ ? __pfx__printk+0x10/0x10
+ ? _printk+0xd5/0x120
+ ? __virt_addr_valid+0x183/0x530
+ ? __virt_addr_valid+0x183/0x530
+ print_report+0x169/0x550
+ ? __virt_addr_valid+0x183/0x530
+ ? __virt_addr_valid+0x183/0x530
+ ? __virt_addr_valid+0x45f/0x530
+ ? __phys_addr+0xba/0x170
+ ? strlen+0x58/0x70
+ kasan_report+0x143/0x180
+ ? strlen+0x58/0x70
+ strlen+0x58/0x70
+ kstrdup+0x20/0x80
+ led_tg_check+0x18b/0x3c0
+ xt_check_target+0x3bb/0xa40
+ ? __pfx_xt_check_target+0x10/0x10
+ ? stack_depot_save_flags+0x6e4/0x830
+ ? nft_target_init+0x174/0xc30
+ nft_target_init+0x82d/0xc30
+ ? __pfx_nft_target_init+0x10/0x10
+ ? nf_tables_newrule+0x1609/0x2980
+ ? nf_tables_newrule+0x1609/0x2980
+ ? rcu_is_watching+0x15/0xb0
+ ? nf_tables_newrule+0x1609/0x2980
+ ? nf_tables_newrule+0x1609/0x2980
+ ? __kmalloc_noprof+0x21a/0x400
+ nf_tables_newrule+0x1860/0x2980
+ ? __pfx_nf_tables_newrule+0x10/0x10
+ ? __nla_parse+0x40/0x60
+ nfnetlink_rcv+0x14e5/0x2ab0
+ ? __pfx_validate_chain+0x10/0x10
+ ? __pfx_nfnetlink_rcv+0x10/0x10
+ ? __lock_acquire+0x1384/0x2050
+ ? netlink_deliver_tap+0x2e/0x1b0
+ ? __pfx_lock_release+0x10/0x10
+ ? netlink_deliver_tap+0x2e/0x1b0
+ netlink_unicast+0x7f8/0x990
+ ? __pfx_netlink_unicast+0x10/0x10
+ ? __virt_addr_valid+0x183/0x530
+ ? __check_object_size+0x48e/0x900
+ netlink_sendmsg+0x8e4/0xcb0
+ ? __pfx_netlink_sendmsg+0x10/0x10
+ ? aa_sock_msg_perm+0x91/0x160
+ ? __pfx_netlink_sendmsg+0x10/0x10
+ __sock_sendmsg+0x223/0x270
+ ____sys_sendmsg+0x52a/0x7e0
+ ? __pfx_____sys_sendmsg+0x10/0x10
+ __sys_sendmsg+0x292/0x380
+ ? __pfx___sys_sendmsg+0x10/0x10
+ ? lockdep_hardirqs_on_prepare+0x43d/0x780
+ ? __pfx_lockdep_hardirqs_on_prepare+0x10/0x10
+ ? exc_page_fault+0x590/0x8c0
+ ? do_syscall_64+0xb6/0x230
+ do_syscall_64+0xf3/0x230
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+...
+ </TASK>
+
+Since an invalid (without '\0' byte at all) byte sequence may be passed
+from userspace, add an extra check to ensure that such a sequence is
+rejected as possible ID and so never passed to 'kstrdup()' and further.
+
+Reported-by: syzbot+6c8215822f35fdb35667@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=6c8215822f35fdb35667
+Fixes: 268cb38e1802 ("netfilter: x_tables: add LED trigger target")
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_LED.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c
+index f7b0286d106ac..8a80fd76fe45b 100644
+--- a/net/netfilter/xt_LED.c
++++ b/net/netfilter/xt_LED.c
+@@ -96,7 +96,9 @@ static int led_tg_check(const struct xt_tgchk_param *par)
+ struct xt_led_info_internal *ledinternal;
+ int err;
+
+- if (ledinfo->id[0] == '\0')
++ /* Bail out if empty string or not a string at all. */
++ if (ledinfo->id[0] == '\0' ||
++ !memchr(ledinfo->id, '\0', sizeof(ledinfo->id)))
+ return -EINVAL;
+
+ mutex_lock(&xt_led_mutex);
+--
+2.43.0
+
--- /dev/null
+From a9b8629d8b0fcd0dbbb1de442cb0a47f72510704 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:39 +0200
+Subject: ntp: Clean up comments
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit a0581cdb2e5d3ad633e51a945b6f0527ce70b68a ]
+
+Usage of different comment formatting makes fast reading and parsing the
+code harder. There are several multi-line comments which do not follow the
+coding style by starting with a line only containing '/*'. There are also
+comments which do not start with capitals.
+
+Clean up all those comments to be consistent and remove comments which
+document the obvious.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-3-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 144 +++++++++++++++++++++++++---------------------
+ 1 file changed, 78 insertions(+), 66 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index ed15ec993a829..e78d3cd1ec321 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -119,7 +119,8 @@ static long pps_stbcnt; /* stability limit exceeded */
+ static long pps_errcnt; /* calibration errors */
+
+
+-/* PPS kernel consumer compensates the whole phase error immediately.
++/*
++ * PPS kernel consumer compensates the whole phase error immediately.
+ * Otherwise, reduce the offset by a fixed factor times the time constant.
+ */
+ static inline s64 ntp_offset_chunk(s64 offset)
+@@ -132,8 +133,7 @@ static inline s64 ntp_offset_chunk(s64 offset)
+
+ static inline void pps_reset_freq_interval(void)
+ {
+- /* the PPS calibration interval may end
+- surprisingly early */
++ /* The PPS calibration interval may end surprisingly early */
+ pps_shift = PPS_INTMIN;
+ pps_intcnt = 0;
+ }
+@@ -151,9 +151,9 @@ static inline void pps_clear(void)
+ pps_freq = 0;
+ }
+
+-/* Decrease pps_valid to indicate that another second has passed since
+- * the last PPS signal. When it reaches 0, indicate that PPS signal is
+- * missing.
++/*
++ * Decrease pps_valid to indicate that another second has passed since the
++ * last PPS signal. When it reaches 0, indicate that PPS signal is missing.
+ */
+ static inline void pps_dec_valid(void)
+ {
+@@ -174,17 +174,21 @@ static inline void pps_set_freq(s64 freq)
+ static inline int is_error_status(int status)
+ {
+ return (status & (STA_UNSYNC|STA_CLOCKERR))
+- /* PPS signal lost when either PPS time or
+- * PPS frequency synchronization requested
++ /*
++ * PPS signal lost when either PPS time or PPS frequency
++ * synchronization requested
+ */
+ || ((status & (STA_PPSFREQ|STA_PPSTIME))
+ && !(status & STA_PPSSIGNAL))
+- /* PPS jitter exceeded when
+- * PPS time synchronization requested */
++ /*
++ * PPS jitter exceeded when PPS time synchronization
++ * requested
++ */
+ || ((status & (STA_PPSTIME|STA_PPSJITTER))
+ == (STA_PPSTIME|STA_PPSJITTER))
+- /* PPS wander exceeded or calibration error when
+- * PPS frequency synchronization requested
++ /*
++ * PPS wander exceeded or calibration error when PPS
++ * frequency synchronization requested
+ */
+ || ((status & STA_PPSFREQ)
+ && (status & (STA_PPSWANDER|STA_PPSERROR)));
+@@ -270,8 +274,8 @@ static void ntp_update_frequency(void)
+ new_base = div_u64(second_length, NTP_INTERVAL_FREQ);
+
+ /*
+- * Don't wait for the next second_overflow, apply
+- * the change to the tick length immediately:
++ * Don't wait for the next second_overflow, apply the change to the
++ * tick length immediately:
+ */
+ tick_length += new_base - tick_length_base;
+ tick_length_base = new_base;
+@@ -307,10 +311,7 @@ static void ntp_update_offset(long offset)
+ offset *= NSEC_PER_USEC;
+ }
+
+- /*
+- * Scale the phase adjustment and
+- * clamp to the operating range.
+- */
++ /* Scale the phase adjustment and clamp to the operating range. */
+ offset = clamp(offset, -MAXPHASE, MAXPHASE);
+
+ /*
+@@ -349,7 +350,8 @@ static void ntp_update_offset(long offset)
+ */
+ void ntp_clear(void)
+ {
+- time_adjust = 0; /* stop active adjtime() */
++ /* Stop active adjtime() */
++ time_adjust = 0;
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+@@ -387,7 +389,7 @@ ktime_t ntp_get_next_leap(void)
+ }
+
+ /*
+- * this routine handles the overflow of the microsecond field
++ * This routine handles the overflow of the microsecond field
+ *
+ * The tricky bits of code to handle the accurate clock support
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+@@ -452,7 +454,6 @@ int second_overflow(time64_t secs)
+ break;
+ }
+
+-
+ /* Bump the maxerror field */
+ time_maxerror += MAXFREQ / NSEC_PER_USEC;
+ if (time_maxerror > NTP_PHASE_LIMIT) {
+@@ -696,7 +697,7 @@ static inline void process_adj_status(const struct __kernel_timex *txc)
+ time_state = TIME_OK;
+ time_status = STA_UNSYNC;
+ ntp_next_leap_sec = TIME64_MAX;
+- /* restart PPS frequency calibration */
++ /* Restart PPS frequency calibration */
+ pps_reset_freq_interval();
+ }
+
+@@ -707,7 +708,7 @@ static inline void process_adj_status(const struct __kernel_timex *txc)
+ if (!(time_status & STA_PLL) && (txc->status & STA_PLL))
+ time_reftime = __ktime_get_real_seconds();
+
+- /* only set allowed bits */
++ /* Only set allowed bits */
+ time_status &= STA_RONLY;
+ time_status |= txc->status & ~STA_RONLY;
+ }
+@@ -729,7 +730,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
+ time_freq = txc->freq * PPM_SCALE;
+ time_freq = min(time_freq, MAXFREQ_SCALED);
+ time_freq = max(time_freq, -MAXFREQ_SCALED);
+- /* update pps_freq */
++ /* Update pps_freq */
+ pps_set_freq(time_freq);
+ }
+
+@@ -762,7 +763,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
+
+
+ /*
+- * adjtimex mainly allows reading (and writing, if superuser) of
++ * adjtimex() mainly allows reading (and writing, if superuser) of
+ * kernel time-keeping variables. used by xntpd.
+ */
+ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+@@ -806,8 +807,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ txc->offset = (u32)txc->offset / NSEC_PER_USEC;
+ }
+
+- result = time_state; /* mostly `TIME_OK' */
+- /* check for errors */
++ result = time_state;
+ if (is_error_status(time_status))
+ result = TIME_ERROR;
+
+@@ -822,7 +822,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ txc->tick = tick_usec;
+ txc->tai = *time_tai;
+
+- /* fill PPS status fields */
++ /* Fill PPS status fields */
+ pps_fill_timex(txc);
+
+ txc->time.tv_sec = ts->tv_sec;
+@@ -853,17 +853,21 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+
+ #ifdef CONFIG_NTP_PPS
+
+-/* actually struct pps_normtime is good old struct timespec, but it is
++/*
++ * struct pps_normtime is basically a struct timespec, but it is
+ * semantically different (and it is the reason why it was invented):
+ * pps_normtime.nsec has a range of ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ]
+- * while timespec.tv_nsec has a range of [0, NSEC_PER_SEC) */
++ * while timespec.tv_nsec has a range of [0, NSEC_PER_SEC)
++ */
+ struct pps_normtime {
+ s64 sec; /* seconds */
+ long nsec; /* nanoseconds */
+ };
+
+-/* normalize the timestamp so that nsec is in the
+- ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval */
++/*
++ * Normalize the timestamp so that nsec is in the
++ * [ -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval
++ */
+ static inline struct pps_normtime pps_normalize_ts(struct timespec64 ts)
+ {
+ struct pps_normtime norm = {
+@@ -879,7 +883,7 @@ static inline struct pps_normtime pps_normalize_ts(struct timespec64 ts)
+ return norm;
+ }
+
+-/* get current phase correction and jitter */
++/* Get current phase correction and jitter */
+ static inline long pps_phase_filter_get(long *jitter)
+ {
+ *jitter = pps_tf[0] - pps_tf[1];
+@@ -890,7 +894,7 @@ static inline long pps_phase_filter_get(long *jitter)
+ return pps_tf[0];
+ }
+
+-/* add the sample to the phase filter */
++/* Add the sample to the phase filter */
+ static inline void pps_phase_filter_add(long err)
+ {
+ pps_tf[2] = pps_tf[1];
+@@ -898,8 +902,9 @@ static inline void pps_phase_filter_add(long err)
+ pps_tf[0] = err;
+ }
+
+-/* decrease frequency calibration interval length.
+- * It is halved after four consecutive unstable intervals.
++/*
++ * Decrease frequency calibration interval length. It is halved after four
++ * consecutive unstable intervals.
+ */
+ static inline void pps_dec_freq_interval(void)
+ {
+@@ -912,8 +917,9 @@ static inline void pps_dec_freq_interval(void)
+ }
+ }
+
+-/* increase frequency calibration interval length.
+- * It is doubled after four consecutive stable intervals.
++/*
++ * Increase frequency calibration interval length. It is doubled after
++ * four consecutive stable intervals.
+ */
+ static inline void pps_inc_freq_interval(void)
+ {
+@@ -926,7 +932,8 @@ static inline void pps_inc_freq_interval(void)
+ }
+ }
+
+-/* update clock frequency based on MONOTONIC_RAW clock PPS signal
++/*
++ * Update clock frequency based on MONOTONIC_RAW clock PPS signal
+ * timestamps
+ *
+ * At the end of the calibration interval the difference between the
+@@ -940,7 +947,7 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ long delta, delta_mod;
+ s64 ftemp;
+
+- /* check if the frequency interval was too long */
++ /* Check if the frequency interval was too long */
+ if (freq_norm.sec > (2 << pps_shift)) {
+ time_status |= STA_PPSERROR;
+ pps_errcnt++;
+@@ -951,9 +958,10 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ return 0;
+ }
+
+- /* here the raw frequency offset and wander (stability) is
+- * calculated. If the wander is less than the wander threshold
+- * the interval is increased; otherwise it is decreased.
++ /*
++ * Here the raw frequency offset and wander (stability) is
++ * calculated. If the wander is less than the wander threshold the
++ * interval is increased; otherwise it is decreased.
+ */
+ ftemp = div_s64(((s64)(-freq_norm.nsec)) << NTP_SCALE_SHIFT,
+ freq_norm.sec);
+@@ -965,13 +973,14 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ time_status |= STA_PPSWANDER;
+ pps_stbcnt++;
+ pps_dec_freq_interval();
+- } else { /* good sample */
++ } else {
++ /* Good sample */
+ pps_inc_freq_interval();
+ }
+
+- /* the stability metric is calculated as the average of recent
+- * frequency changes, but is used only for performance
+- * monitoring
++ /*
++ * The stability metric is calculated as the average of recent
++ * frequency changes, but is used only for performance monitoring
+ */
+ delta_mod = delta;
+ if (delta_mod < 0)
+@@ -980,7 +989,7 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ (NTP_SCALE_SHIFT - SHIFT_USEC),
+ NSEC_PER_USEC) - pps_stabil) >> PPS_INTMIN;
+
+- /* if enabled, the system clock frequency is updated */
++ /* If enabled, the system clock frequency is updated */
+ if ((time_status & STA_PPSFREQ) != 0 &&
+ (time_status & STA_FREQHOLD) == 0) {
+ time_freq = pps_freq;
+@@ -990,17 +999,18 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ return delta;
+ }
+
+-/* correct REALTIME clock phase error against PPS signal */
++/* Correct REALTIME clock phase error against PPS signal */
+ static void hardpps_update_phase(long error)
+ {
+ long correction = -error;
+ long jitter;
+
+- /* add the sample to the median filter */
++ /* Add the sample to the median filter */
+ pps_phase_filter_add(correction);
+ correction = pps_phase_filter_get(&jitter);
+
+- /* Nominal jitter is due to PPS signal noise. If it exceeds the
++ /*
++ * Nominal jitter is due to PPS signal noise. If it exceeds the
+ * threshold, the sample is discarded; otherwise, if so enabled,
+ * the time offset is updated.
+ */
+@@ -1011,13 +1021,13 @@ static void hardpps_update_phase(long error)
+ time_status |= STA_PPSJITTER;
+ pps_jitcnt++;
+ } else if (time_status & STA_PPSTIME) {
+- /* correct the time using the phase offset */
++ /* Correct the time using the phase offset */
+ time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT,
+ NTP_INTERVAL_FREQ);
+- /* cancel running adjtime() */
++ /* Cancel running adjtime() */
+ time_adjust = 0;
+ }
+- /* update jitter */
++ /* Update jitter */
+ pps_jitter += (jitter - pps_jitter) >> PPS_INTMIN;
+ }
+
+@@ -1039,41 +1049,43 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
+
+ pts_norm = pps_normalize_ts(*phase_ts);
+
+- /* clear the error bits, they will be set again if needed */
++ /* Clear the error bits, they will be set again if needed */
+ time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
+
+- /* indicate signal presence */
++ /* Indicate signal presence */
+ time_status |= STA_PPSSIGNAL;
+ pps_valid = PPS_VALID;
+
+- /* when called for the first time,
+- * just start the frequency interval */
++ /*
++ * When called for the first time, just start the frequency
++ * interval
++ */
+ if (unlikely(pps_fbase.tv_sec == 0)) {
+ pps_fbase = *raw_ts;
+ return;
+ }
+
+- /* ok, now we have a base for frequency calculation */
++ /* Ok, now we have a base for frequency calculation */
+ freq_norm = pps_normalize_ts(timespec64_sub(*raw_ts, pps_fbase));
+
+- /* check that the signal is in the range
+- * [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it */
++ /*
++ * Check that the signal is in the range
++ * [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it
++ */
+ if ((freq_norm.sec == 0) ||
+ (freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
+ (freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
+ time_status |= STA_PPSJITTER;
+- /* restart the frequency calibration interval */
++ /* Restart the frequency calibration interval */
+ pps_fbase = *raw_ts;
+ printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse\n");
+ return;
+ }
+
+- /* signal is ok */
+-
+- /* check if the current frequency interval is finished */
++ /* Signal is ok. Check if the current frequency interval is finished */
+ if (freq_norm.sec >= (1 << pps_shift)) {
+ pps_calcnt++;
+- /* restart the frequency calibration interval */
++ /* Restart the frequency calibration interval */
+ pps_fbase = *raw_ts;
+ hardpps_update_freq(freq_norm);
+ }
+--
+2.43.0
+
--- /dev/null
+From 672b574b314ea108894d168fe91d11d12fb4afc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:40 +0200
+Subject: ntp: Cleanup formatting of code
+
+From: Anna-Maria Behnsen <anna-maria@linutronix.de>
+
+[ Upstream commit 38007dc032bd90920463c5d2e6a27d89f7617d6d ]
+
+Code is partially formatted in a creative way which makes reading
+harder. Examples are function calls over several lines where the
+indentation does not start at the same height then the open bracket after
+the function name.
+
+Improve formatting but do not make a functional change.
+
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-4-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 37 +++++++++++++------------------------
+ 1 file changed, 13 insertions(+), 24 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index e78d3cd1ec321..bf2f6ee23a2ec 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -428,8 +428,7 @@ int second_overflow(time64_t secs)
+ } else if (secs == ntp_next_leap_sec) {
+ leap = -1;
+ time_state = TIME_OOP;
+- printk(KERN_NOTICE
+- "Clock: inserting leap second 23:59:60 UTC\n");
++ pr_notice("Clock: inserting leap second 23:59:60 UTC\n");
+ }
+ break;
+ case TIME_DEL:
+@@ -440,8 +439,7 @@ int second_overflow(time64_t secs)
+ leap = 1;
+ ntp_next_leap_sec = TIME64_MAX;
+ time_state = TIME_WAIT;
+- printk(KERN_NOTICE
+- "Clock: deleting leap second 23:59:59 UTC\n");
++ pr_notice("Clock: deleting leap second 23:59:59 UTC\n");
+ }
+ break;
+ case TIME_OOP:
+@@ -842,10 +840,8 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ txc->tai--;
+ txc->time.tv_sec++;
+ }
+- if ((time_state == TIME_OOP) &&
+- (ts->tv_sec == ntp_next_leap_sec)) {
++ if ((time_state == TIME_OOP) && (ts->tv_sec == ntp_next_leap_sec))
+ result = TIME_WAIT;
+- }
+ }
+
+ return result;
+@@ -952,9 +948,8 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ time_status |= STA_PPSERROR;
+ pps_errcnt++;
+ pps_dec_freq_interval();
+- printk_deferred(KERN_ERR
+- "hardpps: PPSERROR: interval too long - %lld s\n",
+- freq_norm.sec);
++ printk_deferred(KERN_ERR "hardpps: PPSERROR: interval too long - %lld s\n",
++ freq_norm.sec);
+ return 0;
+ }
+
+@@ -968,8 +963,7 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ delta = shift_right(ftemp - pps_freq, NTP_SCALE_SHIFT);
+ pps_freq = ftemp;
+ if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
+- printk_deferred(KERN_WARNING
+- "hardpps: PPSWANDER: change=%ld\n", delta);
++ printk_deferred(KERN_WARNING "hardpps: PPSWANDER: change=%ld\n", delta);
+ time_status |= STA_PPSWANDER;
+ pps_stbcnt++;
+ pps_dec_freq_interval();
+@@ -985,13 +979,11 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ delta_mod = delta;
+ if (delta_mod < 0)
+ delta_mod = -delta_mod;
+- pps_stabil += (div_s64(((s64)delta_mod) <<
+- (NTP_SCALE_SHIFT - SHIFT_USEC),
+- NSEC_PER_USEC) - pps_stabil) >> PPS_INTMIN;
++ pps_stabil += (div_s64(((s64)delta_mod) << (NTP_SCALE_SHIFT - SHIFT_USEC),
++ NSEC_PER_USEC) - pps_stabil) >> PPS_INTMIN;
+
+ /* If enabled, the system clock frequency is updated */
+- if ((time_status & STA_PPSFREQ) != 0 &&
+- (time_status & STA_FREQHOLD) == 0) {
++ if ((time_status & STA_PPSFREQ) && !(time_status & STA_FREQHOLD)) {
+ time_freq = pps_freq;
+ ntp_update_frequency();
+ }
+@@ -1015,15 +1007,13 @@ static void hardpps_update_phase(long error)
+ * the time offset is updated.
+ */
+ if (jitter > (pps_jitter << PPS_POPCORN)) {
+- printk_deferred(KERN_WARNING
+- "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
++ printk_deferred(KERN_WARNING "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
+ jitter, (pps_jitter << PPS_POPCORN));
+ time_status |= STA_PPSJITTER;
+ pps_jitcnt++;
+ } else if (time_status & STA_PPSTIME) {
+ /* Correct the time using the phase offset */
+- time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT,
+- NTP_INTERVAL_FREQ);
++ time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
+ /* Cancel running adjtime() */
+ time_adjust = 0;
+ }
+@@ -1072,9 +1062,8 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
+ * Check that the signal is in the range
+ * [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it
+ */
+- if ((freq_norm.sec == 0) ||
+- (freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
+- (freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
++ if ((freq_norm.sec == 0) || (freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
++ (freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
+ time_status |= STA_PPSJITTER;
+ /* Restart the frequency calibration interval */
+ pps_fbase = *raw_ts;
+--
+2.43.0
+
--- /dev/null
+From 8c08827798816b95f2e47f8b916684f622fb0bc8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:41 +0200
+Subject: ntp: Convert functions with only two states to bool
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 48c3c65f64b01164f1704b40b38f60837d484f13 ]
+
+is_error_status() and ntp_synced() return whether a state is set or
+not. Both functions use unsigned int for it even if it would be a perfect
+job for a bool.
+
+Use bool instead of unsigned int. And while at it, move ntp_synced()
+function to the place where it is used.
+
+No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-5-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 28 +++++++++++-----------------
+ 1 file changed, 11 insertions(+), 17 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index bf2f6ee23a2ec..905b0216b12dc 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -171,7 +171,7 @@ static inline void pps_set_freq(s64 freq)
+ pps_freq = freq;
+ }
+
+-static inline int is_error_status(int status)
++static inline bool is_error_status(int status)
+ {
+ return (status & (STA_UNSYNC|STA_CLOCKERR))
+ /*
+@@ -221,7 +221,7 @@ static inline void pps_clear(void) {}
+ static inline void pps_dec_valid(void) {}
+ static inline void pps_set_freq(s64 freq) {}
+
+-static inline int is_error_status(int status)
++static inline bool is_error_status(int status)
+ {
+ return status & (STA_UNSYNC|STA_CLOCKERR);
+ }
+@@ -241,21 +241,6 @@ static inline void pps_fill_timex(struct __kernel_timex *txc)
+
+ #endif /* CONFIG_NTP_PPS */
+
+-
+-/**
+- * ntp_synced - Returns 1 if the NTP status is not UNSYNC
+- *
+- */
+-static inline int ntp_synced(void)
+-{
+- return !(time_status & STA_UNSYNC);
+-}
+-
+-
+-/*
+- * NTP methods:
+- */
+-
+ /*
+ * Update tick_length and tick_length_base, based on tick_usec, ntp_tick_adj and
+ * time_freq:
+@@ -609,6 +594,15 @@ static inline int update_rtc(struct timespec64 *to_set, unsigned long *offset_ns
+ }
+ #endif
+
++/**
++ * ntp_synced - Tells whether the NTP status is not UNSYNC
++ * Returns: true if not UNSYNC, false otherwise
++ */
++static inline bool ntp_synced(void)
++{
++ return !(time_status & STA_UNSYNC);
++}
++
+ /*
+ * If we have an externally synchronized Linux clock, then update RTC clock
+ * accordingly every ~11 minutes. Generally RTCs can only store second
+--
+2.43.0
+
--- /dev/null
+From 02cd24be54639c8c10474b3749b74e92b928e376 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:43 +0200
+Subject: ntp: Introduce struct ntp_data
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 68f66f97c5689825012877f58df65964056d4b5d ]
+
+All NTP data is held in static variables. That prevents the NTP code from
+being reuasble for non-system time timekeepers, e.g. per PTP clock
+timekeeping.
+
+Introduce struct ntp_data and move tick_usec into it for a start.
+
+No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-7-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 65 ++++++++++++++++++++++++++---------------------
+ 1 file changed, 36 insertions(+), 29 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index 0bfd07de202a5..f95f23385a62a 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -22,16 +22,19 @@
+ #include "ntp_internal.h"
+ #include "timekeeping_internal.h"
+
+-
+-/*
+- * NTP timekeeping variables:
++/**
++ * struct ntp_data - Structure holding all NTP related state
++ * @tick_usec: USER_HZ period in microseconds
+ *
+- * Note: All of the NTP state is protected by the timekeeping locks.
++ * Protected by the timekeeping locks.
+ */
++struct ntp_data {
++ unsigned long tick_usec;
++};
+
+-
+-/* USER_HZ period (usecs): */
+-static unsigned long tick_usec = USER_TICK_USEC;
++static struct ntp_data tk_ntp_data = {
++ .tick_usec = USER_TICK_USEC,
++};
+
+ static u64 tick_length;
+ static u64 tick_length_base;
+@@ -245,13 +248,11 @@ static inline void pps_fill_timex(struct __kernel_timex *txc)
+ * Update tick_length and tick_length_base, based on tick_usec, ntp_tick_adj and
+ * time_freq:
+ */
+-static void ntp_update_frequency(void)
++static void ntp_update_frequency(struct ntp_data *ntpdata)
+ {
+- u64 second_length;
+- u64 new_base;
++ u64 second_length, new_base, tick_usec = (u64)ntpdata->tick_usec;
+
+- second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
+- << NTP_SCALE_SHIFT;
++ second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << NTP_SCALE_SHIFT;
+
+ second_length += ntp_tick_adj;
+ second_length += time_freq;
+@@ -330,10 +331,7 @@ static void ntp_update_offset(long offset)
+ time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
+ }
+
+-/**
+- * ntp_clear - Clears the NTP state variables
+- */
+-void ntp_clear(void)
++static void __ntp_clear(struct ntp_data *ntpdata)
+ {
+ /* Stop active adjtime() */
+ time_adjust = 0;
+@@ -341,7 +339,7 @@ void ntp_clear(void)
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+
+- ntp_update_frequency();
++ ntp_update_frequency(ntpdata);
+
+ tick_length = tick_length_base;
+ time_offset = 0;
+@@ -351,6 +349,14 @@ void ntp_clear(void)
+ pps_clear();
+ }
+
++/**
++ * ntp_clear - Clears the NTP state variables
++ */
++void ntp_clear(void)
++{
++ __ntp_clear(&tk_ntp_data);
++}
++
+
+ u64 ntp_tick_length(void)
+ {
+@@ -706,7 +712,7 @@ static inline void process_adj_status(const struct __kernel_timex *txc)
+ }
+
+
+-static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
++static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct __kernel_timex *txc,
+ s32 *time_tai)
+ {
+ if (txc->modes & ADJ_STATUS)
+@@ -747,13 +753,12 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
+ ntp_update_offset(txc->offset);
+
+ if (txc->modes & ADJ_TICK)
+- tick_usec = txc->tick;
++ ntpdata->tick_usec = txc->tick;
+
+ if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
+- ntp_update_frequency();
++ ntp_update_frequency(ntpdata);
+ }
+
+-
+ /*
+ * adjtimex() mainly allows reading (and writing, if superuser) of
+ * kernel time-keeping variables. used by xntpd.
+@@ -761,6 +766,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
+ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ s32 *time_tai, struct audit_ntp_data *ad)
+ {
++ struct ntp_data *ntpdata = &tk_ntp_data;
+ int result;
+
+ if (txc->modes & ADJ_ADJTIME) {
+@@ -769,7 +775,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ if (!(txc->modes & ADJ_OFFSET_READONLY)) {
+ /* adjtime() is independent from ntp_adjtime() */
+ time_adjust = txc->offset;
+- ntp_update_frequency();
++ ntp_update_frequency(ntpdata);
+
+ audit_ntp_set_old(ad, AUDIT_NTP_ADJUST, save_adjust);
+ audit_ntp_set_new(ad, AUDIT_NTP_ADJUST, time_adjust);
+@@ -782,15 +788,15 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ audit_ntp_set_old(ad, AUDIT_NTP_FREQ, time_freq);
+ audit_ntp_set_old(ad, AUDIT_NTP_STATUS, time_status);
+ audit_ntp_set_old(ad, AUDIT_NTP_TAI, *time_tai);
+- audit_ntp_set_old(ad, AUDIT_NTP_TICK, tick_usec);
++ audit_ntp_set_old(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
+
+- process_adjtimex_modes(txc, time_tai);
++ process_adjtimex_modes(ntpdata, txc, time_tai);
+
+ audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, time_offset);
+ audit_ntp_set_new(ad, AUDIT_NTP_FREQ, time_freq);
+ audit_ntp_set_new(ad, AUDIT_NTP_STATUS, time_status);
+ audit_ntp_set_new(ad, AUDIT_NTP_TAI, *time_tai);
+- audit_ntp_set_new(ad, AUDIT_NTP_TICK, tick_usec);
++ audit_ntp_set_new(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
+ }
+
+ txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
+@@ -811,7 +817,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ txc->constant = time_constant;
+ txc->precision = 1;
+ txc->tolerance = MAXFREQ_SCALED / PPM_SCALE;
+- txc->tick = tick_usec;
++ txc->tick = ntpdata->tick_usec;
+ txc->tai = *time_tai;
+
+ /* Fill PPS status fields */
+@@ -932,7 +938,7 @@ static inline void pps_inc_freq_interval(void)
+ * too long, the data are discarded.
+ * Returns the difference between old and new frequency values.
+ */
+-static long hardpps_update_freq(struct pps_normtime freq_norm)
++static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime freq_norm)
+ {
+ long delta, delta_mod;
+ s64 ftemp;
+@@ -979,7 +985,7 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
+ /* If enabled, the system clock frequency is updated */
+ if ((time_status & STA_PPSFREQ) && !(time_status & STA_FREQHOLD)) {
+ time_freq = pps_freq;
+- ntp_update_frequency();
++ ntp_update_frequency(ntpdata);
+ }
+
+ return delta;
+@@ -1030,6 +1036,7 @@ static void hardpps_update_phase(long error)
+ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
+ {
+ struct pps_normtime pts_norm, freq_norm;
++ struct ntp_data *ntpdata = &tk_ntp_data;
+
+ pts_norm = pps_normalize_ts(*phase_ts);
+
+@@ -1070,7 +1077,7 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
+ pps_calcnt++;
+ /* Restart the frequency calibration interval */
+ pps_fbase = *raw_ts;
+- hardpps_update_freq(freq_norm);
++ hardpps_update_freq(ntpdata, freq_norm);
+ }
+
+ hardpps_update_phase(pts_norm.nsec);
+--
+2.43.0
+
--- /dev/null
+From bc82cd48fc9998b95d1e07b709738796c6ad93d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:38 +0200
+Subject: ntp: Make tick_usec static
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 66606a93849bfe3cbe9f0b801b40f60b87c54e11 ]
+
+There are no users of tick_usec outside of the NTP core code. Therefore
+make tick_usec static.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-2-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/timex.h | 7 -------
+ kernel/time/ntp.c | 5 ++++-
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/include/linux/timex.h b/include/linux/timex.h
+index 7f7a12fd8200c..4ee32eff3f221 100644
+--- a/include/linux/timex.h
++++ b/include/linux/timex.h
+@@ -139,13 +139,6 @@ unsigned long random_get_entropy_fallback(void);
+ #define MAXSEC 2048 /* max interval between updates (s) */
+ #define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */
+
+-/*
+- * kernel variables
+- * Note: maximum error = NTP sync distance = dispersion + delay / 2;
+- * estimated error = NTP dispersion.
+- */
+-extern unsigned long tick_usec; /* USER_HZ period (usec) */
+-
+ /* Required to safely shift negative values */
+ #define shift_right(x, s) ({ \
+ __typeof__(x) __x = (x); \
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index c17cc9d857bc1..ed15ec993a829 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -31,7 +31,7 @@
+
+
+ /* USER_HZ period (usecs): */
+-unsigned long tick_usec = USER_TICK_USEC;
++static unsigned long tick_usec = USER_TICK_USEC;
+
+ static u64 tick_length;
+ static u64 tick_length_base;
+@@ -44,6 +44,9 @@ static u64 tick_length_base;
+
+ /*
+ * phase-lock loop variables
++ *
++ * Note: maximum error = NTP sync distance = dispersion + delay / 2;
++ * estimated error = NTP dispersion.
+ */
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 0fe1bb3a8028f7ec5c74ee3aefa142db84098dcf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:44 +0200
+Subject: ntp: Move tick_length* into ntp_data
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit ec93ec22aa10fb5311c0f068ee66c5b6d39788fe ]
+
+Continue the conversion from static variables to struct based data.
+
+No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-8-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 34 ++++++++++++++++++----------------
+ 1 file changed, 18 insertions(+), 16 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index f95f23385a62a..2430e69743ee2 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -25,20 +25,21 @@
+ /**
+ * struct ntp_data - Structure holding all NTP related state
+ * @tick_usec: USER_HZ period in microseconds
++ * @tick_length: Adjusted tick length
++ * @tick_length_base: Base value for @tick_length
+ *
+ * Protected by the timekeeping locks.
+ */
+ struct ntp_data {
+ unsigned long tick_usec;
++ u64 tick_length;
++ u64 tick_length_base;
+ };
+
+ static struct ntp_data tk_ntp_data = {
+ .tick_usec = USER_TICK_USEC,
+ };
+
+-static u64 tick_length;
+-static u64 tick_length_base;
+-
+ #define SECS_PER_DAY 86400
+ #define MAX_TICKADJ 500LL /* usecs */
+ #define MAX_TICKADJ_SCALED \
+@@ -263,8 +264,8 @@ static void ntp_update_frequency(struct ntp_data *ntpdata)
+ * Don't wait for the next second_overflow, apply the change to the
+ * tick length immediately:
+ */
+- tick_length += new_base - tick_length_base;
+- tick_length_base = new_base;
++ ntpdata->tick_length += new_base - ntpdata->tick_length_base;
++ ntpdata->tick_length_base = new_base;
+ }
+
+ static inline s64 ntp_update_offset_fll(s64 offset64, long secs)
+@@ -341,8 +342,8 @@ static void __ntp_clear(struct ntp_data *ntpdata)
+
+ ntp_update_frequency(ntpdata);
+
+- tick_length = tick_length_base;
+- time_offset = 0;
++ ntpdata->tick_length = ntpdata->tick_length_base;
++ time_offset = 0;
+
+ ntp_next_leap_sec = TIME64_MAX;
+ /* Clear PPS state variables */
+@@ -360,7 +361,7 @@ void ntp_clear(void)
+
+ u64 ntp_tick_length(void)
+ {
+- return tick_length;
++ return tk_ntp_data.tick_length;
+ }
+
+ /**
+@@ -391,6 +392,7 @@ ktime_t ntp_get_next_leap(void)
+ */
+ int second_overflow(time64_t secs)
+ {
++ struct ntp_data *ntpdata = &tk_ntp_data;
+ s64 delta;
+ int leap = 0;
+ s32 rem;
+@@ -451,11 +453,11 @@ int second_overflow(time64_t secs)
+ }
+
+ /* Compute the phase adjustment for the next second */
+- tick_length = tick_length_base;
++ ntpdata->tick_length = ntpdata->tick_length_base;
+
+- delta = ntp_offset_chunk(time_offset);
+- time_offset -= delta;
+- tick_length += delta;
++ delta = ntp_offset_chunk(time_offset);
++ time_offset -= delta;
++ ntpdata->tick_length += delta;
+
+ /* Check PPS signal */
+ pps_dec_valid();
+@@ -465,18 +467,18 @@ int second_overflow(time64_t secs)
+
+ if (time_adjust > MAX_TICKADJ) {
+ time_adjust -= MAX_TICKADJ;
+- tick_length += MAX_TICKADJ_SCALED;
++ ntpdata->tick_length += MAX_TICKADJ_SCALED;
+ goto out;
+ }
+
+ if (time_adjust < -MAX_TICKADJ) {
+ time_adjust += MAX_TICKADJ;
+- tick_length -= MAX_TICKADJ_SCALED;
++ ntpdata->tick_length -= MAX_TICKADJ_SCALED;
+ goto out;
+ }
+
+- tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
+- << NTP_SCALE_SHIFT;
++ ntpdata->tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
++ << NTP_SCALE_SHIFT;
+ time_adjust = 0;
+
+ out:
+--
+2.43.0
+
--- /dev/null
+From e5cd0013fd4580d589578a01e182bf6809e45672 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:45 +0200
+Subject: ntp: Move tick_stat* into ntp_data
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit bee18a2301f97465a464176767f3a3a64f900d93 ]
+
+Continue the conversion from static variables to struct based data.
+
+No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-9-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 175 ++++++++++++++++++++++------------------------
+ 1 file changed, 85 insertions(+), 90 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index 2430e69743ee2..42c039ab8139a 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -27,6 +27,8 @@
+ * @tick_usec: USER_HZ period in microseconds
+ * @tick_length: Adjusted tick length
+ * @tick_length_base: Base value for @tick_length
++ * @time_state: State of the clock synchronization
++ * @time_status: Clock status bits
+ *
+ * Protected by the timekeeping locks.
+ */
+@@ -34,10 +36,14 @@ struct ntp_data {
+ unsigned long tick_usec;
+ u64 tick_length;
+ u64 tick_length_base;
++ int time_state;
++ int time_status;
+ };
+
+ static struct ntp_data tk_ntp_data = {
+ .tick_usec = USER_TICK_USEC,
++ .time_state = TIME_OK,
++ .time_status = STA_UNSYNC,
+ };
+
+ #define SECS_PER_DAY 86400
+@@ -53,16 +59,6 @@ static struct ntp_data tk_ntp_data = {
+ * estimated error = NTP dispersion.
+ */
+
+-/*
+- * clock synchronization status
+- *
+- * (TIME_ERROR prevents overwriting the CMOS clock)
+- */
+-static int time_state = TIME_OK;
+-
+-/* clock status bits: */
+-static int time_status = STA_UNSYNC;
+-
+ /* time adjustment (nsecs): */
+ static s64 time_offset;
+
+@@ -127,9 +123,9 @@ static long pps_errcnt; /* calibration errors */
+ * PPS kernel consumer compensates the whole phase error immediately.
+ * Otherwise, reduce the offset by a fixed factor times the time constant.
+ */
+-static inline s64 ntp_offset_chunk(s64 offset)
++static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset)
+ {
+- if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL)
++ if (ntpdata->time_status & STA_PPSTIME && ntpdata->time_status & STA_PPSSIGNAL)
+ return offset;
+ else
+ return shift_right(offset, SHIFT_PLL + time_constant);
+@@ -159,13 +155,13 @@ static inline void pps_clear(void)
+ * Decrease pps_valid to indicate that another second has passed since the
+ * last PPS signal. When it reaches 0, indicate that PPS signal is missing.
+ */
+-static inline void pps_dec_valid(void)
++static inline void pps_dec_valid(struct ntp_data *ntpdata)
+ {
+ if (pps_valid > 0)
+ pps_valid--;
+ else {
+- time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
+- STA_PPSWANDER | STA_PPSERROR);
++ ntpdata->time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
++ STA_PPSWANDER | STA_PPSERROR);
+ pps_clear();
+ }
+ }
+@@ -198,12 +194,12 @@ static inline bool is_error_status(int status)
+ && (status & (STA_PPSWANDER|STA_PPSERROR)));
+ }
+
+-static inline void pps_fill_timex(struct __kernel_timex *txc)
++static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc)
+ {
+ txc->ppsfreq = shift_right((pps_freq >> PPM_SCALE_INV_SHIFT) *
+ PPM_SCALE_INV, NTP_SCALE_SHIFT);
+ txc->jitter = pps_jitter;
+- if (!(time_status & STA_NANO))
++ if (!(ntpdata->time_status & STA_NANO))
+ txc->jitter = pps_jitter / NSEC_PER_USEC;
+ txc->shift = pps_shift;
+ txc->stabil = pps_stabil;
+@@ -215,14 +211,14 @@ static inline void pps_fill_timex(struct __kernel_timex *txc)
+
+ #else /* !CONFIG_NTP_PPS */
+
+-static inline s64 ntp_offset_chunk(s64 offset)
++static inline s64 ntp_offset_chunk(struct ntp_data *ntp, s64 offset)
+ {
+ return shift_right(offset, SHIFT_PLL + time_constant);
+ }
+
+ static inline void pps_reset_freq_interval(void) {}
+ static inline void pps_clear(void) {}
+-static inline void pps_dec_valid(void) {}
++static inline void pps_dec_valid(struct ntp_data *ntpdata) {}
+ static inline void pps_set_freq(s64 freq) {}
+
+ static inline bool is_error_status(int status)
+@@ -230,7 +226,7 @@ static inline bool is_error_status(int status)
+ return status & (STA_UNSYNC|STA_CLOCKERR);
+ }
+
+-static inline void pps_fill_timex(struct __kernel_timex *txc)
++static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc)
+ {
+ /* PPS is not implemented, so these are zero */
+ txc->ppsfreq = 0;
+@@ -268,30 +264,30 @@ static void ntp_update_frequency(struct ntp_data *ntpdata)
+ ntpdata->tick_length_base = new_base;
+ }
+
+-static inline s64 ntp_update_offset_fll(s64 offset64, long secs)
++static inline s64 ntp_update_offset_fll(struct ntp_data *ntpdata, s64 offset64, long secs)
+ {
+- time_status &= ~STA_MODE;
++ ntpdata->time_status &= ~STA_MODE;
+
+ if (secs < MINSEC)
+ return 0;
+
+- if (!(time_status & STA_FLL) && (secs <= MAXSEC))
++ if (!(ntpdata->time_status & STA_FLL) && (secs <= MAXSEC))
+ return 0;
+
+- time_status |= STA_MODE;
++ ntpdata->time_status |= STA_MODE;
+
+ return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
+ }
+
+-static void ntp_update_offset(long offset)
++static void ntp_update_offset(struct ntp_data *ntpdata, long offset)
+ {
+ s64 freq_adj, offset64;
+ long secs, real_secs;
+
+- if (!(time_status & STA_PLL))
++ if (!(ntpdata->time_status & STA_PLL))
+ return;
+
+- if (!(time_status & STA_NANO)) {
++ if (!(ntpdata->time_status & STA_NANO)) {
+ /* Make sure the multiplication below won't overflow */
+ offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC);
+ offset *= NSEC_PER_USEC;
+@@ -306,13 +302,13 @@ static void ntp_update_offset(long offset)
+ */
+ real_secs = __ktime_get_real_seconds();
+ secs = (long)(real_secs - time_reftime);
+- if (unlikely(time_status & STA_FREQHOLD))
++ if (unlikely(ntpdata->time_status & STA_FREQHOLD))
+ secs = 0;
+
+ time_reftime = real_secs;
+
+ offset64 = offset;
+- freq_adj = ntp_update_offset_fll(offset64, secs);
++ freq_adj = ntp_update_offset_fll(ntpdata, offset64, secs);
+
+ /*
+ * Clamp update interval to reduce PLL gain with low
+@@ -335,10 +331,10 @@ static void ntp_update_offset(long offset)
+ static void __ntp_clear(struct ntp_data *ntpdata)
+ {
+ /* Stop active adjtime() */
+- time_adjust = 0;
+- time_status |= STA_UNSYNC;
+- time_maxerror = NTP_PHASE_LIMIT;
+- time_esterror = NTP_PHASE_LIMIT;
++ time_adjust = 0;
++ ntpdata->time_status |= STA_UNSYNC;
++ time_maxerror = NTP_PHASE_LIMIT;
++ time_esterror = NTP_PHASE_LIMIT;
+
+ ntp_update_frequency(ntpdata);
+
+@@ -372,9 +368,10 @@ u64 ntp_tick_length(void)
+ */
+ ktime_t ntp_get_next_leap(void)
+ {
++ struct ntp_data *ntpdata = &tk_ntp_data;
+ ktime_t ret;
+
+- if ((time_state == TIME_INS) && (time_status & STA_INS))
++ if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
+ return ktime_set(ntp_next_leap_sec, 0);
+ ret = KTIME_MAX;
+ return ret;
+@@ -402,46 +399,46 @@ int second_overflow(time64_t secs)
+ * day, the system clock is set back one second; if in leap-delete
+ * state, the system clock is set ahead one second.
+ */
+- switch (time_state) {
++ switch (ntpdata->time_state) {
+ case TIME_OK:
+- if (time_status & STA_INS) {
+- time_state = TIME_INS;
++ if (ntpdata->time_status & STA_INS) {
++ ntpdata->time_state = TIME_INS;
+ div_s64_rem(secs, SECS_PER_DAY, &rem);
+ ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
+- } else if (time_status & STA_DEL) {
+- time_state = TIME_DEL;
++ } else if (ntpdata->time_status & STA_DEL) {
++ ntpdata->time_state = TIME_DEL;
+ div_s64_rem(secs + 1, SECS_PER_DAY, &rem);
+ ntp_next_leap_sec = secs + SECS_PER_DAY - rem;
+ }
+ break;
+ case TIME_INS:
+- if (!(time_status & STA_INS)) {
++ if (!(ntpdata->time_status & STA_INS)) {
+ ntp_next_leap_sec = TIME64_MAX;
+- time_state = TIME_OK;
++ ntpdata->time_state = TIME_OK;
+ } else if (secs == ntp_next_leap_sec) {
+ leap = -1;
+- time_state = TIME_OOP;
++ ntpdata->time_state = TIME_OOP;
+ pr_notice("Clock: inserting leap second 23:59:60 UTC\n");
+ }
+ break;
+ case TIME_DEL:
+- if (!(time_status & STA_DEL)) {
++ if (!(ntpdata->time_status & STA_DEL)) {
+ ntp_next_leap_sec = TIME64_MAX;
+- time_state = TIME_OK;
++ ntpdata->time_state = TIME_OK;
+ } else if (secs == ntp_next_leap_sec) {
+ leap = 1;
+ ntp_next_leap_sec = TIME64_MAX;
+- time_state = TIME_WAIT;
++ ntpdata->time_state = TIME_WAIT;
+ pr_notice("Clock: deleting leap second 23:59:59 UTC\n");
+ }
+ break;
+ case TIME_OOP:
+ ntp_next_leap_sec = TIME64_MAX;
+- time_state = TIME_WAIT;
++ ntpdata->time_state = TIME_WAIT;
+ break;
+ case TIME_WAIT:
+- if (!(time_status & (STA_INS | STA_DEL)))
+- time_state = TIME_OK;
++ if (!(ntpdata->time_status & (STA_INS | STA_DEL)))
++ ntpdata->time_state = TIME_OK;
+ break;
+ }
+
+@@ -449,18 +446,18 @@ int second_overflow(time64_t secs)
+ time_maxerror += MAXFREQ / NSEC_PER_USEC;
+ if (time_maxerror > NTP_PHASE_LIMIT) {
+ time_maxerror = NTP_PHASE_LIMIT;
+- time_status |= STA_UNSYNC;
++ ntpdata->time_status |= STA_UNSYNC;
+ }
+
+ /* Compute the phase adjustment for the next second */
+ ntpdata->tick_length = ntpdata->tick_length_base;
+
+- delta = ntp_offset_chunk(time_offset);
++ delta = ntp_offset_chunk(ntpdata, time_offset);
+ time_offset -= delta;
+ ntpdata->tick_length += delta;
+
+ /* Check PPS signal */
+- pps_dec_valid();
++ pps_dec_valid(ntpdata);
+
+ if (!time_adjust)
+ goto out;
+@@ -608,7 +605,7 @@ static inline int update_rtc(struct timespec64 *to_set, unsigned long *offset_ns
+ */
+ static inline bool ntp_synced(void)
+ {
+- return !(time_status & STA_UNSYNC);
++ return !(tk_ntp_data.time_status & STA_UNSYNC);
+ }
+
+ /*
+@@ -691,11 +688,11 @@ static inline void __init ntp_init_cmos_sync(void) { }
+ /*
+ * Propagate a new txc->status value into the NTP state:
+ */
+-static inline void process_adj_status(const struct __kernel_timex *txc)
++static inline void process_adj_status(struct ntp_data *ntpdata, const struct __kernel_timex *txc)
+ {
+- if ((time_status & STA_PLL) && !(txc->status & STA_PLL)) {
+- time_state = TIME_OK;
+- time_status = STA_UNSYNC;
++ if ((ntpdata->time_status & STA_PLL) && !(txc->status & STA_PLL)) {
++ ntpdata->time_state = TIME_OK;
++ ntpdata->time_status = STA_UNSYNC;
+ ntp_next_leap_sec = TIME64_MAX;
+ /* Restart PPS frequency calibration */
+ pps_reset_freq_interval();
+@@ -705,26 +702,25 @@ static inline void process_adj_status(const struct __kernel_timex *txc)
+ * If we turn on PLL adjustments then reset the
+ * reference time to current time.
+ */
+- if (!(time_status & STA_PLL) && (txc->status & STA_PLL))
++ if (!(ntpdata->time_status & STA_PLL) && (txc->status & STA_PLL))
+ time_reftime = __ktime_get_real_seconds();
+
+- /* Only set allowed bits */
+- time_status &= STA_RONLY;
+- time_status |= txc->status & ~STA_RONLY;
++ /* only set allowed bits */
++ ntpdata->time_status &= STA_RONLY;
++ ntpdata->time_status |= txc->status & ~STA_RONLY;
+ }
+
+-
+ static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct __kernel_timex *txc,
+ s32 *time_tai)
+ {
+ if (txc->modes & ADJ_STATUS)
+- process_adj_status(txc);
++ process_adj_status(ntpdata, txc);
+
+ if (txc->modes & ADJ_NANO)
+- time_status |= STA_NANO;
++ ntpdata->time_status |= STA_NANO;
+
+ if (txc->modes & ADJ_MICRO)
+- time_status &= ~STA_NANO;
++ ntpdata->time_status &= ~STA_NANO;
+
+ if (txc->modes & ADJ_FREQUENCY) {
+ time_freq = txc->freq * PPM_SCALE;
+@@ -742,17 +738,16 @@ static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct
+
+ if (txc->modes & ADJ_TIMECONST) {
+ time_constant = clamp(txc->constant, 0, MAXTC);
+- if (!(time_status & STA_NANO))
++ if (!(ntpdata->time_status & STA_NANO))
+ time_constant += 4;
+ time_constant = clamp(time_constant, 0, MAXTC);
+ }
+
+- if (txc->modes & ADJ_TAI &&
+- txc->constant >= 0 && txc->constant <= MAX_TAI_OFFSET)
++ if (txc->modes & ADJ_TAI && txc->constant >= 0 && txc->constant <= MAX_TAI_OFFSET)
+ *time_tai = txc->constant;
+
+ if (txc->modes & ADJ_OFFSET)
+- ntp_update_offset(txc->offset);
++ ntp_update_offset(ntpdata, txc->offset);
+
+ if (txc->modes & ADJ_TICK)
+ ntpdata->tick_usec = txc->tick;
+@@ -788,7 +783,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ if (txc->modes) {
+ audit_ntp_set_old(ad, AUDIT_NTP_OFFSET, time_offset);
+ audit_ntp_set_old(ad, AUDIT_NTP_FREQ, time_freq);
+- audit_ntp_set_old(ad, AUDIT_NTP_STATUS, time_status);
++ audit_ntp_set_old(ad, AUDIT_NTP_STATUS, ntpdata->time_status);
+ audit_ntp_set_old(ad, AUDIT_NTP_TAI, *time_tai);
+ audit_ntp_set_old(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
+
+@@ -796,26 +791,26 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+
+ audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, time_offset);
+ audit_ntp_set_new(ad, AUDIT_NTP_FREQ, time_freq);
+- audit_ntp_set_new(ad, AUDIT_NTP_STATUS, time_status);
++ audit_ntp_set_new(ad, AUDIT_NTP_STATUS, ntpdata->time_status);
+ audit_ntp_set_new(ad, AUDIT_NTP_TAI, *time_tai);
+ audit_ntp_set_new(ad, AUDIT_NTP_TICK, ntpdata->tick_usec);
+ }
+
+ txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
+ NTP_SCALE_SHIFT);
+- if (!(time_status & STA_NANO))
++ if (!(ntpdata->time_status & STA_NANO))
+ txc->offset = (u32)txc->offset / NSEC_PER_USEC;
+ }
+
+- result = time_state;
+- if (is_error_status(time_status))
++ result = ntpdata->time_state;
++ if (is_error_status(ntpdata->time_status))
+ result = TIME_ERROR;
+
+ txc->freq = shift_right((time_freq >> PPM_SCALE_INV_SHIFT) *
+ PPM_SCALE_INV, NTP_SCALE_SHIFT);
+ txc->maxerror = time_maxerror;
+ txc->esterror = time_esterror;
+- txc->status = time_status;
++ txc->status = ntpdata->time_status;
+ txc->constant = time_constant;
+ txc->precision = 1;
+ txc->tolerance = MAXFREQ_SCALED / PPM_SCALE;
+@@ -823,26 +818,26 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ txc->tai = *time_tai;
+
+ /* Fill PPS status fields */
+- pps_fill_timex(txc);
++ pps_fill_timex(ntpdata, txc);
+
+ txc->time.tv_sec = ts->tv_sec;
+ txc->time.tv_usec = ts->tv_nsec;
+- if (!(time_status & STA_NANO))
++ if (!(ntpdata->time_status & STA_NANO))
+ txc->time.tv_usec = ts->tv_nsec / NSEC_PER_USEC;
+
+ /* Handle leapsec adjustments */
+ if (unlikely(ts->tv_sec >= ntp_next_leap_sec)) {
+- if ((time_state == TIME_INS) && (time_status & STA_INS)) {
++ if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS)) {
+ result = TIME_OOP;
+ txc->tai++;
+ txc->time.tv_sec--;
+ }
+- if ((time_state == TIME_DEL) && (time_status & STA_DEL)) {
++ if ((ntpdata->time_state == TIME_DEL) && (ntpdata->time_status & STA_DEL)) {
+ result = TIME_WAIT;
+ txc->tai--;
+ txc->time.tv_sec++;
+ }
+- if ((time_state == TIME_OOP) && (ts->tv_sec == ntp_next_leap_sec))
++ if ((ntpdata->time_state == TIME_OOP) && (ts->tv_sec == ntp_next_leap_sec))
+ result = TIME_WAIT;
+ }
+
+@@ -947,7 +942,7 @@ static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime fr
+
+ /* Check if the frequency interval was too long */
+ if (freq_norm.sec > (2 << pps_shift)) {
+- time_status |= STA_PPSERROR;
++ ntpdata->time_status |= STA_PPSERROR;
+ pps_errcnt++;
+ pps_dec_freq_interval();
+ printk_deferred(KERN_ERR "hardpps: PPSERROR: interval too long - %lld s\n",
+@@ -966,7 +961,7 @@ static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime fr
+ pps_freq = ftemp;
+ if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
+ printk_deferred(KERN_WARNING "hardpps: PPSWANDER: change=%ld\n", delta);
+- time_status |= STA_PPSWANDER;
++ ntpdata->time_status |= STA_PPSWANDER;
+ pps_stbcnt++;
+ pps_dec_freq_interval();
+ } else {
+@@ -985,7 +980,7 @@ static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime fr
+ NSEC_PER_USEC) - pps_stabil) >> PPS_INTMIN;
+
+ /* If enabled, the system clock frequency is updated */
+- if ((time_status & STA_PPSFREQ) && !(time_status & STA_FREQHOLD)) {
++ if ((ntpdata->time_status & STA_PPSFREQ) && !(ntpdata->time_status & STA_FREQHOLD)) {
+ time_freq = pps_freq;
+ ntp_update_frequency(ntpdata);
+ }
+@@ -994,7 +989,7 @@ static long hardpps_update_freq(struct ntp_data *ntpdata, struct pps_normtime fr
+ }
+
+ /* Correct REALTIME clock phase error against PPS signal */
+-static void hardpps_update_phase(long error)
++static void hardpps_update_phase(struct ntp_data *ntpdata, long error)
+ {
+ long correction = -error;
+ long jitter;
+@@ -1011,9 +1006,9 @@ static void hardpps_update_phase(long error)
+ if (jitter > (pps_jitter << PPS_POPCORN)) {
+ printk_deferred(KERN_WARNING "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
+ jitter, (pps_jitter << PPS_POPCORN));
+- time_status |= STA_PPSJITTER;
++ ntpdata->time_status |= STA_PPSJITTER;
+ pps_jitcnt++;
+- } else if (time_status & STA_PPSTIME) {
++ } else if (ntpdata->time_status & STA_PPSTIME) {
+ /* Correct the time using the phase offset */
+ time_offset = div_s64(((s64)correction) << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
+ /* Cancel running adjtime() */
+@@ -1043,10 +1038,10 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
+ pts_norm = pps_normalize_ts(*phase_ts);
+
+ /* Clear the error bits, they will be set again if needed */
+- time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
++ ntpdata->time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
+
+- /* Indicate signal presence */
+- time_status |= STA_PPSSIGNAL;
++ /* indicate signal presence */
++ ntpdata->time_status |= STA_PPSSIGNAL;
+ pps_valid = PPS_VALID;
+
+ /*
+@@ -1067,7 +1062,7 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
+ */
+ if ((freq_norm.sec == 0) || (freq_norm.nsec > MAXFREQ * freq_norm.sec) ||
+ (freq_norm.nsec < -MAXFREQ * freq_norm.sec)) {
+- time_status |= STA_PPSJITTER;
++ ntpdata->time_status |= STA_PPSJITTER;
+ /* Restart the frequency calibration interval */
+ pps_fbase = *raw_ts;
+ printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse\n");
+@@ -1082,7 +1077,7 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
+ hardpps_update_freq(ntpdata, freq_norm);
+ }
+
+- hardpps_update_phase(pts_norm.nsec);
++ hardpps_update_phase(ntpdata, pts_norm.nsec);
+
+ }
+ #endif /* CONFIG_NTP_PPS */
+--
+2.43.0
+
--- /dev/null
+From 615a20c1b427738e2cd85b339363d4a9a164152f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:42 +0200
+Subject: ntp: Read reference time only once
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 136bccbc2e78d3cd0bd8831e4c5a4509c0ddd945 ]
+
+The reference time is required twice in ntp_update_offset(). It will not
+change in the meantime as the calling code holds the timekeeper lock. Read
+it only once and store it into a local variable.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-6-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index 905b0216b12dc..0bfd07de202a5 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -283,9 +283,8 @@ static inline s64 ntp_update_offset_fll(s64 offset64, long secs)
+
+ static void ntp_update_offset(long offset)
+ {
+- s64 freq_adj;
+- s64 offset64;
+- long secs;
++ s64 freq_adj, offset64;
++ long secs, real_secs;
+
+ if (!(time_status & STA_PLL))
+ return;
+@@ -303,11 +302,12 @@ static void ntp_update_offset(long offset)
+ * Select how the frequency is to be controlled
+ * and in which mode (PLL or FLL).
+ */
+- secs = (long)(__ktime_get_real_seconds() - time_reftime);
++ real_secs = __ktime_get_real_seconds();
++ secs = (long)(real_secs - time_reftime);
+ if (unlikely(time_status & STA_FREQHOLD))
+ secs = 0;
+
+- time_reftime = __ktime_get_real_seconds();
++ time_reftime = real_secs;
+
+ offset64 = offset;
+ freq_adj = ntp_update_offset_fll(offset64, secs);
+--
+2.43.0
+
--- /dev/null
+From d6835449c2cb9aff1a34a9b12ee43a4d66b80d4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 12:16:09 +0000
+Subject: ntp: Remove invalid cast in time offset math
+
+From: Marcelo Dalmas <marcelo.dalmas@ge.com>
+
+[ Upstream commit f5807b0606da7ac7c1b74a386b22134ec7702d05 ]
+
+Due to an unsigned cast, adjtimex() returns the wrong offest when using
+ADJ_MICRO and the offset is negative. In this case a small negative offset
+returns approximately 4.29 seconds (~ 2^32/1000 milliseconds) due to the
+unsigned cast of the negative offset.
+
+This cast was added when the kernel internal struct timex was changed to
+use type long long for the time offset value to address the problem of a
+64bit/32bit division on 32bit systems.
+
+The correct cast would have been (s32), which is correct as time_offset can
+only be in the range of [INT_MIN..INT_MAX] because the shift constant used
+for calculating it is 32. But that's non-obvious.
+
+Remove the cast and use div_s64() to cure the issue.
+
+[ tglx: Fix white space damage, use div_s64() and amend the change log ]
+
+Fixes: ead25417f82e ("timex: use __kernel_timex internally")
+Signed-off-by: Marcelo Dalmas <marcelo.dalmas@ge.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/all/SJ0P101MB03687BF7D5A10FD3C49C51E5F42E2@SJ0P101MB0368.NAMP101.PROD.OUTLOOK.COM
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/ntp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index 42c039ab8139a..15bc5c592ebbe 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -799,7 +799,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+ txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
+ NTP_SCALE_SHIFT);
+ if (!(ntpdata->time_status & STA_NANO))
+- txc->offset = (u32)txc->offset / NSEC_PER_USEC;
++ txc->offset = div_s64(txc->offset, NSEC_PER_USEC);
+ }
+
+ result = ntpdata->time_state;
+--
+2.43.0
+
--- /dev/null
+From 47820bd8951cecde2a46e794efb818bf82555ccc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Sep 2024 15:17:37 +0200
+Subject: ntp: Remove unused tick_nsec
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit a849a0273d0f73a252d14d31c5003a8059ea51fc ]
+
+tick_nsec is only updated in the NTP core, but there are no users.
+
+Remove it.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/all/20240911-devel-anna-maria-b4-timers-ptp-ntp-v1-1-2d52f4e13476@linutronix.de
+Stable-dep-of: f5807b0606da ("ntp: Remove invalid cast in time offset math")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/timer.h | 2 --
+ include/linux/timex.h | 1 -
+ kernel/time/ntp.c | 8 ++------
+ 3 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
+index 7365dd4acffb6..23baf8c9b34ca 100644
+--- a/arch/x86/include/asm/timer.h
++++ b/arch/x86/include/asm/timer.h
+@@ -6,8 +6,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/math64.h>
+
+-#define TICK_SIZE (tick_nsec / 1000)
+-
+ unsigned long long native_sched_clock(void);
+ extern void recalibrate_cpu_khz(void);
+
+diff --git a/include/linux/timex.h b/include/linux/timex.h
+index 3871b06bd302c..7f7a12fd8200c 100644
+--- a/include/linux/timex.h
++++ b/include/linux/timex.h
+@@ -145,7 +145,6 @@ unsigned long random_get_entropy_fallback(void);
+ * estimated error = NTP dispersion.
+ */
+ extern unsigned long tick_usec; /* USER_HZ period (usec) */
+-extern unsigned long tick_nsec; /* SHIFTED_HZ period (nsec) */
+
+ /* Required to safely shift negative values */
+ #define shift_right(x, s) ({ \
+diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
+index 802b336f4b8c2..c17cc9d857bc1 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -33,9 +33,6 @@
+ /* USER_HZ period (usecs): */
+ unsigned long tick_usec = USER_TICK_USEC;
+
+-/* SHIFTED_HZ period (nsecs): */
+-unsigned long tick_nsec;
+-
+ static u64 tick_length;
+ static u64 tick_length_base;
+
+@@ -253,8 +250,8 @@ static inline int ntp_synced(void)
+ */
+
+ /*
+- * Update (tick_length, tick_length_base, tick_nsec), based
+- * on (tick_usec, ntp_tick_adj, time_freq):
++ * Update tick_length and tick_length_base, based on tick_usec, ntp_tick_adj and
++ * time_freq:
+ */
+ static void ntp_update_frequency(void)
+ {
+@@ -267,7 +264,6 @@ static void ntp_update_frequency(void)
+ second_length += ntp_tick_adj;
+ second_length += time_freq;
+
+- tick_nsec = div_u64(second_length, HZ) >> NTP_SCALE_SHIFT;
+ new_base = div_u64(second_length, NTP_INTERVAL_FREQ);
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 6e7d479467380f94a95e98ed89b86923cd1e1932 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Nov 2024 18:19:41 +0100
+Subject: platform/x86: asus-wmi: Ignore return value when writing thermal
+ policy
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+[ Upstream commit 25fb5f47f34d90aceda2c47a4230315536e97fa8 ]
+
+On some machines like the ASUS Vivobook S14 writing the thermal policy
+returns the currently writen thermal policy instead of an error code.
+
+Ignore the return code to avoid falsely returning an error when the
+thermal policy was written successfully.
+
+Reported-by: auslands-kv@gmx.de
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219517
+Fixes: 2daa86e78c49 ("platform/x86: asus_wmi: Support throttle thermal policy")
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20241124171941.29789-1-W_Armin@gmx.de
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/asus-wmi.c | 11 ++---------
+ 1 file changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
+index 89f5f44857d55..1101e5b2488e5 100644
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -3696,7 +3696,6 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
+ /* Throttle thermal policy ****************************************************/
+ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+ {
+- u32 retval;
+ u8 value;
+ int err;
+
+@@ -3718,8 +3717,8 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+ value = asus->throttle_thermal_policy_mode;
+ }
+
+- err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev,
+- value, &retval);
++ /* Some machines do not return an error code as a result, so we ignore it */
++ err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, value, NULL);
+
+ sysfs_notify(&asus->platform_device->dev.kobj, NULL,
+ "throttle_thermal_policy");
+@@ -3729,12 +3728,6 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
+ return err;
+ }
+
+- if (retval != 1) {
+- pr_warn("Failed to set throttle thermal policy (retval): 0x%x\n",
+- retval);
+- return -EIO;
+- }
+-
+ /* Must set to disabled if mode is toggled */
+ if (asus->cpu_fan_curve_available)
+ asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false;
+--
+2.43.0
+
--- /dev/null
+From 7975c206eaeb33af926d7d3f1d5c8dd8785afef6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 10:59:54 +0000
+Subject: ptp: Add error handling for adjfine callback in ptp_clock_adjtime
+
+From: Ajay Kaher <ajay.kaher@broadcom.com>
+
+[ Upstream commit 98337d7c87577ded71114f6976edb70a163e27bc ]
+
+ptp_clock_adjtime sets ptp->dialed_frequency even when adjfine
+callback returns an error. This causes subsequent reads to return
+an incorrect value.
+
+Fix this by adding error check before ptp->dialed_frequency is set.
+
+Fixes: 39a8cbd9ca05 ("ptp: remember the adjusted frequency")
+Signed-off-by: Ajay Kaher <ajay.kaher@broadcom.com>
+Acked-by: Richard Cochran <richardcochran@gmail.com>
+Link: https://patch.msgid.link/20241125105954.1509971-1-ajay.kaher@broadcom.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_clock.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
+index c56cd0f63909a..77a36e7bddd54 100644
+--- a/drivers/ptp/ptp_clock.c
++++ b/drivers/ptp/ptp_clock.c
+@@ -150,7 +150,8 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
+ if (ppb > ops->max_adj || ppb < -ops->max_adj)
+ return -ERANGE;
+ err = ops->adjfine(ops, tx->freq);
+- ptp->dialed_frequency = tx->freq;
++ if (!err)
++ ptp->dialed_frequency = tx->freq;
+ } else if (tx->modes & ADJ_OFFSET) {
+ if (ops->adjphase) {
+ s32 max_phase_adj = ops->getmaxphase(ops);
+--
+2.43.0
+
--- /dev/null
+From 81a411dd59fd54e3b9545d683d8f23e57ca040e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Dec 2024 15:56:08 +0000
+Subject: Revert "udp: avoid calling sock_def_readable() if possible"
+
+From: Fernando Fernandez Mancera <ffmancera@riseup.net>
+
+[ Upstream commit 3d501f562f63b290351169e3e9931ffe3d57b2ae ]
+
+This reverts commit 612b1c0dec5bc7367f90fc508448b8d0d7c05414. On a
+scenario with multiple threads blocking on a recvfrom(), we need to call
+sock_def_readable() on every __udp_enqueue_schedule_skb() otherwise the
+threads won't be woken up as __skb_wait_for_more_packets() is using
+prepare_to_wait_exclusive().
+
+Link: https://bugzilla.redhat.com/2308477
+Fixes: 612b1c0dec5b ("udp: avoid calling sock_def_readable() if possible")
+Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20241202155620.1719-1-ffmancera@riseup.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/udp.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 2849b273b1310..ff85242720a0a 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1516,7 +1516,6 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
+ struct sk_buff_head *list = &sk->sk_receive_queue;
+ int rmem, err = -ENOMEM;
+ spinlock_t *busy = NULL;
+- bool becomes_readable;
+ int size, rcvbuf;
+
+ /* Immediately drop when the receive queue is full.
+@@ -1557,19 +1556,12 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
+ */
+ sock_skb_set_dropcount(sk, skb);
+
+- becomes_readable = skb_queue_empty(list);
+ __skb_queue_tail(list, skb);
+ spin_unlock(&list->lock);
+
+- if (!sock_flag(sk, SOCK_DEAD)) {
+- if (becomes_readable ||
+- sk->sk_data_ready != sock_def_readable ||
+- READ_ONCE(sk->sk_peek_off) >= 0)
+- INDIRECT_CALL_1(sk->sk_data_ready,
+- sock_def_readable, sk);
+- else
+- sk_wake_async_rcu(sk, SOCK_WAKE_WAITD, POLL_IN);
+- }
++ if (!sock_flag(sk, SOCK_DEAD))
++ INDIRECT_CALL_1(sk->sk_data_ready, sock_def_readable, sk);
++
+ busylock_release(busy);
+ return 0;
+
+--
+2.43.0
+
--- /dev/null
+From 06bcfecf192ceb9bc4456baf8ddadad95c03be01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 13:58:50 +0000
+Subject: selftests: hid: fix typo and exit code
+
+From: Maximilian Heyne <mheyne@amazon.de>
+
+[ Upstream commit e8f34747bddedaf3895e5d5066e0f71713fff811 ]
+
+The correct exit code to mark a test as skipped is 4.
+
+Fixes: ffb85d5c9e80 ("selftests: hid: import hid-tools hid-core tests")
+Signed-off-by: Maximilian Heyne <mheyne@amazon.de>
+Link: https://patch.msgid.link/20241126135850.76493-1-mheyne@amazon.de
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../testing/selftests/hid/run-hid-tools-tests.sh | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/tools/testing/selftests/hid/run-hid-tools-tests.sh b/tools/testing/selftests/hid/run-hid-tools-tests.sh
+index bdae8464da865..af1682a53c27e 100755
+--- a/tools/testing/selftests/hid/run-hid-tools-tests.sh
++++ b/tools/testing/selftests/hid/run-hid-tools-tests.sh
+@@ -2,24 +2,26 @@
+ # SPDX-License-Identifier: GPL-2.0
+ # Runs tests for the HID subsystem
+
++KSELFTEST_SKIP_TEST=4
++
+ if ! command -v python3 > /dev/null 2>&1; then
+ echo "hid-tools: [SKIP] python3 not installed"
+- exit 77
++ exit $KSELFTEST_SKIP_TEST
+ fi
+
+ if ! python3 -c "import pytest" > /dev/null 2>&1; then
+- echo "hid: [SKIP/ pytest module not installed"
+- exit 77
++ echo "hid: [SKIP] pytest module not installed"
++ exit $KSELFTEST_SKIP_TEST
+ fi
+
+ if ! python3 -c "import pytest_tap" > /dev/null 2>&1; then
+- echo "hid: [SKIP/ pytest_tap module not installed"
+- exit 77
++ echo "hid: [SKIP] pytest_tap module not installed"
++ exit $KSELFTEST_SKIP_TEST
+ fi
+
+ if ! python3 -c "import hidtools" > /dev/null 2>&1; then
+- echo "hid: [SKIP/ hid-tools module not installed"
+- exit 77
++ echo "hid: [SKIP] hid-tools module not installed"
++ exit $KSELFTEST_SKIP_TEST
+ fi
+
+ TARGET=${TARGET:=.}
+--
+2.43.0
+
--- /dev/null
+itco_wdt-mask-nmi_now-bit-for-update_no_reboot_bit-c.patch
+watchdog-xilinx_wwdt-calculate-max_hw_heartbeat_ms-u.patch
+watchdog-apple-actually-flush-writes-after-requestin.patch
+watchdog-mediatek-make-sure-system-reset-gets-assert.patch
+can-gs_usb-add-usb-endpoint-address-detection-at-dri.patch
+can-c_can-c_can_handle_bus_err-update-statistics-if-.patch
+can-sun4i_can-sun4i_can_err-call-can_change_state-ev.patch
+can-hi311x-hi3110_can_ist-fix-potential-use-after-fr.patch
+can-m_can-m_can_handle_lec_err-fix-rx-tx-_errors-sta.patch
+can-ifi_canfd-ifi_canfd_handle_lec_err-fix-rx-tx-_er.patch
+can-hi311x-hi3110_can_ist-fix-rx-tx-_errors-statisti.patch
+can-sja1000-sja1000_err-fix-rx-tx-_errors-statistics.patch
+can-sun4i_can-sun4i_can_err-fix-rx-tx-_errors-statis.patch
+can-ems_usb-ems_usb_rx_err-fix-rx-tx-_errors-statist.patch
+can-f81604-f81604_handle_can_bus_errors-fix-rx-tx-_e.patch
+ipvs-fix-ub-due-to-uninitialized-stack-access-in-ip_.patch
+netfilter-x_tables-fix-led-id-check-in-led_tg_check.patch
+netfilter-nft_socket-remove-warn_on_once-on-maximum-.patch
+selftests-hid-fix-typo-and-exit-code.patch
+net-enetc-do-not-configure-preemptible-tcs-if-sis-do.patch
+ptp-add-error-handling-for-adjfine-callback-in-ptp_c.patch
+net-sched-tbf-correct-backlog-statistic-for-gso-pack.patch
+net-hsr-avoid-potential-out-of-bound-access-in-fill_.patch
+bnxt_en-ethtool-supply-ntuple-rss-context-action.patch
+net-fix-icmp-host-relookup-triggering-ip_rt_bug.patch
+ipv6-avoid-possible-null-deref-in-modify_prefix_rout.patch
+can-j1939-j1939_session_new-fix-skb-reference-counti.patch
+platform-x86-asus-wmi-ignore-return-value-when-writi.patch
+net-phy-microchip-reset-lan88xx-phy-to-ensure-clean-.patch
+net-ipv6-release-expired-exception-dst-cached-in-soc.patch
+dccp-fix-memory-leak-in-dccp_feat_change_recv.patch
+tipc-fix-use-after-free-of-kernel-socket-in-cleanup_.patch
+net-smc-initialize-close_work-early-to-avoid-warning.patch
+net-smc-fix-lgr-and-link-use-after-free-issue.patch
+net-qed-allow-old-cards-not-supporting-num_images-to.patch
+net-hsr-must-allocate-more-bytes-for-redbox-support.patch
+ice-fix-phy-clock-recovery-availability-check.patch
+ice-fix-phy-timestamp-extraction-for-eth56g.patch
+ice-fix-vlan-pruning-in-switchdev-mode.patch
+idpf-set-completion-tag-for-empty-bufs-associated-wi.patch
+ixgbevf-stop-attempting-ipsec-offload-on-mailbox-api.patch
+ixgbe-downgrade-logging-of-unsupported-vf-api-versio.patch
+ixgbe-correct-base-bx10-compliance-code.patch
+igb-fix-potential-invalid-memory-access-in-igb_init_.patch
+netfilter-nft_inner-incorrect-percpu-area-handling-u.patch
+revert-udp-avoid-calling-sock_def_readable-if-possib.patch
+net-sched-fix-erspan_opt-settings-in-cls_flower.patch
+netfilter-ipset-hold-module-reference-while-requesti.patch
+netfilter-nft_set_hash-skip-duplicated-elements-pend.patch
+ethtool-fix-wrong-mod-state-in-case-of-verbose-and-n.patch
+mlxsw-spectrum_acl_flex_keys-constify-struct-mlxsw_a.patch
+mlxsw-spectrum_acl_flex_keys-use-correct-key-block-o.patch
+geneve-do-not-assume-mac-header-is-set-in-geneve_xmi.patch
+net-mlx5-hws-fix-memory-leak-in-mlx5hws_definer_calc.patch
+net-mlx5-hws-properly-set-bwc-queue-locks-lock-class.patch
+net-mlx5e-sd-use-correct-mdev-to-build-channel-param.patch
+net-mlx5e-remove-workaround-to-avoid-syndrome-for-in.patch
+vsock-test-fix-failures-due-to-wrong-so_rcvlowat-par.patch
+vsock-test-fix-parameter-types-in-so_vm_sockets_-cal.patch
+net-avoid-potential-uaf-in-default_operstate.patch
+gpio-grgpio-use-a-helper-variable-to-store-the-addre.patch
+gpio-grgpio-add-null-check-in-grgpio_probe.patch
+mmc-mtk-sd-use-devm_mmc_alloc_host.patch
+mmc-mtk-sd-fix-error-handle-of-probe-function.patch
+mmc-mtk-sd-fix-devm_clk_get_optional-usage.patch
+mmc-mtk-sd-fix-mmc_cap2_crypto-flag-setting.patch
+mmc-sd-sduc-support-recognition.patch
+mmc-core-adjust-acmd22-to-sduc.patch
+mmc-core-use-gfp_noio-in-acmd22.patch
+zram-do-not-mark-idle-slots-that-cannot-be-idle.patch
+zram-clear-idle-flag-in-mark_idle.patch
+ntp-remove-unused-tick_nsec.patch
+ntp-make-tick_usec-static.patch
+ntp-clean-up-comments.patch
+ntp-cleanup-formatting-of-code.patch
+ntp-convert-functions-with-only-two-states-to-bool.patch
+ntp-read-reference-time-only-once.patch
+ntp-introduce-struct-ntp_data.patch
+ntp-move-tick_length-into-ntp_data.patch
+ntp-move-tick_stat-into-ntp_data.patch
+ntp-remove-invalid-cast-in-time-offset-math.patch
+f2fs-clean-up-w-f2fs_-blk_to_bytes-btyes_to_blk.patch
+f2fs-fix-to-adjust-appropriate-length-for-fiemap.patch
+f2fs-fix-to-requery-extent-which-cross-boundary-of-i.patch
+i3c-master-replace-hard-code-2-with-macro-i3c_addr_s.patch
+i3c-master-extend-address-status-bit-to-4-and-add-i3.patch
+i3c-master-fix-dynamic-address-leak-when-assigned-ad.patch
+drm-amd-display-calculate-final-viewport-before-tap-.patch
+drm-amd-display-ignore-scalar-validation-failure-if-.patch
--- /dev/null
+From 898cf6544cfa285b8161cf92a738ba1994f67349 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Nov 2024 14:05:12 +0900
+Subject: tipc: Fix use-after-free of kernel socket in cleanup_bearer().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 6a2fa13312e51a621f652d522d7e2df7066330b6 ]
+
+syzkaller reported a use-after-free of UDP kernel socket
+in cleanup_bearer() without repro. [0][1]
+
+When bearer_disable() calls tipc_udp_disable(), cleanup
+of the UDP kernel socket is deferred by work calling
+cleanup_bearer().
+
+tipc_net_stop() waits for such works to finish by checking
+tipc_net(net)->wq_count. However, the work decrements the
+count too early before releasing the kernel socket,
+unblocking cleanup_net() and resulting in use-after-free.
+
+Let's move the decrement after releasing the socket in
+cleanup_bearer().
+
+[0]:
+ref_tracker: net notrefcnt@000000009b3d1faf has 1/1 users at
+ sk_alloc+0x438/0x608
+ inet_create+0x4c8/0xcb0
+ __sock_create+0x350/0x6b8
+ sock_create_kern+0x58/0x78
+ udp_sock_create4+0x68/0x398
+ udp_sock_create+0x88/0xc8
+ tipc_udp_enable+0x5e8/0x848
+ __tipc_nl_bearer_enable+0x84c/0xed8
+ tipc_nl_bearer_enable+0x38/0x60
+ genl_family_rcv_msg_doit+0x170/0x248
+ genl_rcv_msg+0x400/0x5b0
+ netlink_rcv_skb+0x1dc/0x398
+ genl_rcv+0x44/0x68
+ netlink_unicast+0x678/0x8b0
+ netlink_sendmsg+0x5e4/0x898
+ ____sys_sendmsg+0x500/0x830
+
+[1]:
+BUG: KMSAN: use-after-free in udp_hashslot include/net/udp.h:85 [inline]
+BUG: KMSAN: use-after-free in udp_lib_unhash+0x3b8/0x930 net/ipv4/udp.c:1979
+ udp_hashslot include/net/udp.h:85 [inline]
+ udp_lib_unhash+0x3b8/0x930 net/ipv4/udp.c:1979
+ sk_common_release+0xaf/0x3f0 net/core/sock.c:3820
+ inet_release+0x1e0/0x260 net/ipv4/af_inet.c:437
+ inet6_release+0x6f/0xd0 net/ipv6/af_inet6.c:489
+ __sock_release net/socket.c:658 [inline]
+ sock_release+0xa0/0x210 net/socket.c:686
+ cleanup_bearer+0x42d/0x4c0 net/tipc/udp_media.c:819
+ process_one_work kernel/workqueue.c:3229 [inline]
+ process_scheduled_works+0xcaf/0x1c90 kernel/workqueue.c:3310
+ worker_thread+0xf6c/0x1510 kernel/workqueue.c:3391
+ kthread+0x531/0x6b0 kernel/kthread.c:389
+ ret_from_fork+0x60/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:244
+
+Uninit was created at:
+ slab_free_hook mm/slub.c:2269 [inline]
+ slab_free mm/slub.c:4580 [inline]
+ kmem_cache_free+0x207/0xc40 mm/slub.c:4682
+ net_free net/core/net_namespace.c:454 [inline]
+ cleanup_net+0x16f2/0x19d0 net/core/net_namespace.c:647
+ process_one_work kernel/workqueue.c:3229 [inline]
+ process_scheduled_works+0xcaf/0x1c90 kernel/workqueue.c:3310
+ worker_thread+0xf6c/0x1510 kernel/workqueue.c:3391
+ kthread+0x531/0x6b0 kernel/kthread.c:389
+ ret_from_fork+0x60/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:244
+
+CPU: 0 UID: 0 PID: 54 Comm: kworker/0:2 Not tainted 6.12.0-rc1-00131-gf66ebf37d69c #7 91723d6f74857f70725e1583cba3cf4adc716cfa
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+Workqueue: events cleanup_bearer
+
+Fixes: 26abe14379f8 ("net: Modify sk_alloc to not reference count the netns of kernel sockets.")
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://patch.msgid.link/20241127050512.28438-1-kuniyu@amazon.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tipc/udp_media.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
+index 439f755399772..b7e25e7e9933b 100644
+--- a/net/tipc/udp_media.c
++++ b/net/tipc/udp_media.c
+@@ -814,10 +814,10 @@ static void cleanup_bearer(struct work_struct *work)
+ kfree_rcu(rcast, rcu);
+ }
+
+- atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
+ dst_cache_destroy(&ub->rcast.dst_cache);
+ udp_tunnel_sock_release(ub->ubsock);
+ synchronize_net();
++ atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
+ kfree(ub);
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 210c2a174fb18aa35092205ddf1992f331a58e73 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 09:06:54 -0600
+Subject: vsock/test: fix failures due to wrong SO_RCVLOWAT parameter
+
+From: Konstantin Shkolnyy <kshk@linux.ibm.com>
+
+[ Upstream commit 7ce1c0921a806ee7d4bb24f74a3b30c89fc5fb39 ]
+
+This happens on 64-bit big-endian machines.
+SO_RCVLOWAT requires an int parameter. However, instead of int, the test
+uses unsigned long in one place and size_t in another. Both are 8 bytes
+long on 64-bit machines. The kernel, having received the 8 bytes, doesn't
+test for the exact size of the parameter, it only cares that it's >=
+sizeof(int), and casts the 4 lower-addressed bytes to an int, which, on
+a big-endian machine, contains 0. 0 doesn't trigger an error, SO_RCVLOWAT
+returns with success and the socket stays with the default SO_RCVLOWAT = 1,
+which results in vsock_test failures, while vsock_perf doesn't even notice
+that it's failed to change it.
+
+Fixes: b1346338fbae ("vsock_test: POLLIN + SO_RCVLOWAT test")
+Fixes: 542e893fbadc ("vsock/test: two tests to check credit update logic")
+Fixes: 8abbffd27ced ("test/vsock: vsock_perf utility")
+Signed-off-by: Konstantin Shkolnyy <kshk@linux.ibm.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/vsock/vsock_perf.c | 6 +++---
+ tools/testing/vsock/vsock_test.c | 4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/tools/testing/vsock/vsock_perf.c b/tools/testing/vsock/vsock_perf.c
+index 4e8578f815e08..22633c2848cc7 100644
+--- a/tools/testing/vsock/vsock_perf.c
++++ b/tools/testing/vsock/vsock_perf.c
+@@ -133,7 +133,7 @@ static float get_gbps(unsigned long bits, time_t ns_delta)
+ ((float)ns_delta / NSEC_PER_SEC);
+ }
+
+-static void run_receiver(unsigned long rcvlowat_bytes)
++static void run_receiver(int rcvlowat_bytes)
+ {
+ unsigned int read_cnt;
+ time_t rx_begin_ns;
+@@ -163,7 +163,7 @@ static void run_receiver(unsigned long rcvlowat_bytes)
+ printf("Listen port %u\n", port);
+ printf("RX buffer %lu bytes\n", buf_size_bytes);
+ printf("vsock buffer %lu bytes\n", vsock_buf_bytes);
+- printf("SO_RCVLOWAT %lu bytes\n", rcvlowat_bytes);
++ printf("SO_RCVLOWAT %d bytes\n", rcvlowat_bytes);
+
+ fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+
+@@ -439,7 +439,7 @@ static long strtolx(const char *arg)
+ int main(int argc, char **argv)
+ {
+ unsigned long to_send_bytes = DEFAULT_TO_SEND_BYTES;
+- unsigned long rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;
++ int rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;
+ int peer_cid = -1;
+ bool sender = false;
+
+diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
+index 8d38dbf8f41f0..7fd25b814b4b6 100644
+--- a/tools/testing/vsock/vsock_test.c
++++ b/tools/testing/vsock/vsock_test.c
+@@ -835,7 +835,7 @@ static void test_stream_poll_rcvlowat_server(const struct test_opts *opts)
+
+ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
+ {
+- unsigned long lowat_val = RCVLOWAT_BUF_SIZE;
++ int lowat_val = RCVLOWAT_BUF_SIZE;
+ char buf[RCVLOWAT_BUF_SIZE];
+ struct pollfd fds;
+ short poll_flags;
+@@ -1357,7 +1357,7 @@ static void test_stream_rcvlowat_def_cred_upd_client(const struct test_opts *opt
+ static void test_stream_credit_update_test(const struct test_opts *opts,
+ bool low_rx_bytes_test)
+ {
+- size_t recv_buf_size;
++ int recv_buf_size;
+ struct pollfd fds;
+ size_t buf_size;
+ void *buf;
+--
+2.43.0
+
--- /dev/null
+From d101cf1618eced7059dc847ca316b243a2e436cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Dec 2024 09:06:55 -0600
+Subject: vsock/test: fix parameter types in SO_VM_SOCKETS_* calls
+
+From: Konstantin Shkolnyy <kshk@linux.ibm.com>
+
+[ Upstream commit 3f36ee29e732b68044d531f47d31f22d265954c6 ]
+
+Change parameters of SO_VM_SOCKETS_* to unsigned long long as documented
+in the vm_sockets.h, because the corresponding kernel code requires them
+to be at least 64-bit, no matter what architecture. Otherwise they are
+too small on 32-bit machines.
+
+Fixes: 5c338112e48a ("test/vsock: rework message bounds test")
+Fixes: 685a21c314a8 ("test/vsock: add big message test")
+Fixes: 542e893fbadc ("vsock/test: two tests to check credit update logic")
+Fixes: 8abbffd27ced ("test/vsock: vsock_perf utility")
+Signed-off-by: Konstantin Shkolnyy <kshk@linux.ibm.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/vsock/vsock_perf.c | 4 ++--
+ tools/testing/vsock/vsock_test.c | 22 +++++++++++++++++-----
+ 2 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/tools/testing/vsock/vsock_perf.c b/tools/testing/vsock/vsock_perf.c
+index 22633c2848cc7..8e0a6c0770d37 100644
+--- a/tools/testing/vsock/vsock_perf.c
++++ b/tools/testing/vsock/vsock_perf.c
+@@ -33,7 +33,7 @@
+
+ static unsigned int port = DEFAULT_PORT;
+ static unsigned long buf_size_bytes = DEFAULT_BUF_SIZE_BYTES;
+-static unsigned long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
++static unsigned long long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
+ static bool zerocopy;
+
+ static void error(const char *s)
+@@ -162,7 +162,7 @@ static void run_receiver(int rcvlowat_bytes)
+ printf("Run as receiver\n");
+ printf("Listen port %u\n", port);
+ printf("RX buffer %lu bytes\n", buf_size_bytes);
+- printf("vsock buffer %lu bytes\n", vsock_buf_bytes);
++ printf("vsock buffer %llu bytes\n", vsock_buf_bytes);
+ printf("SO_RCVLOWAT %d bytes\n", rcvlowat_bytes);
+
+ fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
+index 7fd25b814b4b6..0b7f5bf546da5 100644
+--- a/tools/testing/vsock/vsock_test.c
++++ b/tools/testing/vsock/vsock_test.c
+@@ -429,7 +429,7 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
+
+ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
+ {
+- unsigned long sock_buf_size;
++ unsigned long long sock_buf_size;
+ unsigned long remote_hash;
+ unsigned long curr_hash;
+ int fd;
+@@ -634,7 +634,8 @@ static void test_seqpacket_timeout_server(const struct test_opts *opts)
+
+ static void test_seqpacket_bigmsg_client(const struct test_opts *opts)
+ {
+- unsigned long sock_buf_size;
++ unsigned long long sock_buf_size;
++ size_t buf_size;
+ socklen_t len;
+ void *data;
+ int fd;
+@@ -655,13 +656,20 @@ static void test_seqpacket_bigmsg_client(const struct test_opts *opts)
+
+ sock_buf_size++;
+
+- data = malloc(sock_buf_size);
++ /* size_t can be < unsigned long long */
++ buf_size = (size_t)sock_buf_size;
++ if (buf_size != sock_buf_size) {
++ fprintf(stderr, "Returned BUFFER_SIZE too large\n");
++ exit(EXIT_FAILURE);
++ }
++
++ data = malloc(buf_size);
+ if (!data) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
+- send_buf(fd, data, sock_buf_size, 0, -EMSGSIZE);
++ send_buf(fd, data, buf_size, 0, -EMSGSIZE);
+
+ control_writeln("CLISENT");
+
+@@ -1360,6 +1368,7 @@ static void test_stream_credit_update_test(const struct test_opts *opts,
+ int recv_buf_size;
+ struct pollfd fds;
+ size_t buf_size;
++ unsigned long long sock_buf_size;
+ void *buf;
+ int fd;
+
+@@ -1371,8 +1380,11 @@ static void test_stream_credit_update_test(const struct test_opts *opts,
+
+ buf_size = RCVLOWAT_CREDIT_UPD_BUF_SIZE;
+
++ /* size_t can be < unsigned long long */
++ sock_buf_size = buf_size;
++
+ if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+- &buf_size, sizeof(buf_size))) {
++ &sock_buf_size, sizeof(sock_buf_size))) {
+ perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
+ exit(EXIT_FAILURE);
+ }
+--
+2.43.0
+
--- /dev/null
+From 4b55c6b904ae83c8ecdc9f735b825bafc1afc595 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Oct 2024 00:59:51 +0800
+Subject: watchdog: apple: Actually flush writes after requesting watchdog
+ restart
+
+From: Nick Chan <towinchenmi@gmail.com>
+
+[ Upstream commit 51dfe714c03c066aabc815a2bb2adcc998dfcb30 ]
+
+Although there is an existing code comment about flushing the writes,
+writes were not actually being flushed.
+
+Actually flush the writes by changing readl_relaxed() to readl().
+
+Fixes: 4ed224aeaf661 ("watchdog: Add Apple SoC watchdog driver")
+Suggested-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Nick Chan <towinchenmi@gmail.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20241001170018.20139-2-towinchenmi@gmail.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/apple_wdt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/watchdog/apple_wdt.c b/drivers/watchdog/apple_wdt.c
+index d4f739932f0be..62dabf223d909 100644
+--- a/drivers/watchdog/apple_wdt.c
++++ b/drivers/watchdog/apple_wdt.c
+@@ -130,7 +130,7 @@ static int apple_wdt_restart(struct watchdog_device *wdd, unsigned long mode,
+ * can take up to ~20-25ms until the SoC is actually reset. Just wait
+ * 50ms here to be safe.
+ */
+- (void)readl_relaxed(wdt->regs + APPLE_WDT_WD1_CUR_TIME);
++ (void)readl(wdt->regs + APPLE_WDT_WD1_CUR_TIME);
+ mdelay(50);
+
+ return 0;
+--
+2.43.0
+
--- /dev/null
+From 247bf2e3213699f81755f9b81f425d16a8531423 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Nov 2024 10:47:51 +0000
+Subject: watchdog: mediatek: Make sure system reset gets asserted in
+ mtk_wdt_restart()
+
+From: Yassine Oudjana <y.oudjana@protonmail.com>
+
+[ Upstream commit a1495a21e0b8aad92132dfcf9c6fffc1bde9d5b2 ]
+
+Clear the IRQ enable bit of WDT_MODE before asserting software reset
+in order to make TOPRGU issue a system reset signal instead of an IRQ.
+
+Fixes: a44a45536f7b ("watchdog: Add driver for Mediatek watchdog")
+Signed-off-by: Yassine Oudjana <y.oudjana@protonmail.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20241106104738.195968-2-y.oudjana@protonmail.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/mtk_wdt.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
+index c35f85ce8d69c..e2d7a57d6ea2e 100644
+--- a/drivers/watchdog/mtk_wdt.c
++++ b/drivers/watchdog/mtk_wdt.c
+@@ -225,9 +225,15 @@ static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
+ {
+ struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
+ void __iomem *wdt_base;
++ u32 reg;
+
+ wdt_base = mtk_wdt->wdt_base;
+
++ /* Enable reset in order to issue a system reset instead of an IRQ */
++ reg = readl(wdt_base + WDT_MODE);
++ reg &= ~WDT_MODE_IRQ_EN;
++ writel(reg | WDT_MODE_KEY, wdt_base + WDT_MODE);
++
+ while (1) {
+ writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
+ mdelay(5);
+--
+2.43.0
+
--- /dev/null
+From 65be01bb8325f377af36e133be209f1588609505 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Sep 2024 17:02:30 +0530
+Subject: watchdog: xilinx_wwdt: Calculate max_hw_heartbeat_ms using clock
+ frequency
+
+From: Harini T <harini.t@amd.com>
+
+[ Upstream commit 006778844c2c132c28cfa90e3570560351e01b9a ]
+
+In the current implementation, the value of max_hw_heartbeat_ms is set
+to the timeout period expressed in milliseconds and fails to verify if
+the close window percentage exceeds the maximum value that the hardware
+supports.
+
+1. Calculate max_hw_heartbeat_ms based on input clock frequency.
+2. Update frequency check to require a minimum frequency of 1Mhz.
+3. Limit the close and open window percent to hardware supported value
+to avoid truncation.
+4. If the user input timeout exceeds the maximum timeout supported, use
+only open window and the framework supports the higher timeouts.
+
+Fixes: 12984cea1b8c ("watchdog: xilinx_wwdt: Add Versal window watchdog support")
+Signed-off-by: Harini T <harini.t@amd.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20240913113230.1939373-1-harini.t@amd.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/watchdog/xilinx_wwdt.c | 75 ++++++++++++++++++++++++++++------
+ 1 file changed, 63 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c
+index d271e2e8d6e27..3d2a156f71800 100644
+--- a/drivers/watchdog/xilinx_wwdt.c
++++ b/drivers/watchdog/xilinx_wwdt.c
+@@ -2,7 +2,7 @@
+ /*
+ * Window watchdog device driver for Xilinx Versal WWDT
+ *
+- * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
++ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
+ */
+
+ #include <linux/clk.h>
+@@ -36,6 +36,12 @@
+
+ #define XWWDT_CLOSE_WINDOW_PERCENT 50
+
++/* Maximum count value of each 32 bit window */
++#define XWWDT_MAX_COUNT_WINDOW GENMASK(31, 0)
++
++/* Maximum count value of closed and open window combined */
++#define XWWDT_MAX_COUNT_WINDOW_COMBINED GENMASK_ULL(32, 1)
++
+ static int wwdt_timeout;
+ static int closed_window_percent;
+
+@@ -54,6 +60,8 @@ MODULE_PARM_DESC(closed_window_percent,
+ * @xilinx_wwdt_wdd: watchdog device structure
+ * @freq: source clock frequency of WWDT
+ * @close_percent: Closed window percent
++ * @closed_timeout: Closed window timeout in ticks
++ * @open_timeout: Open window timeout in ticks
+ */
+ struct xwwdt_device {
+ void __iomem *base;
+@@ -61,27 +69,22 @@ struct xwwdt_device {
+ struct watchdog_device xilinx_wwdt_wdd;
+ unsigned long freq;
+ u32 close_percent;
++ u64 closed_timeout;
++ u64 open_timeout;
+ };
+
+ static int xilinx_wwdt_start(struct watchdog_device *wdd)
+ {
+ struct xwwdt_device *xdev = watchdog_get_drvdata(wdd);
+ struct watchdog_device *xilinx_wwdt_wdd = &xdev->xilinx_wwdt_wdd;
+- u64 time_out, closed_timeout, open_timeout;
+ u32 control_status_reg;
+
+- /* Calculate timeout count */
+- time_out = xdev->freq * wdd->timeout;
+- closed_timeout = div_u64(time_out * xdev->close_percent, 100);
+- open_timeout = time_out - closed_timeout;
+- wdd->min_hw_heartbeat_ms = xdev->close_percent * 10 * wdd->timeout;
+-
+ spin_lock(&xdev->spinlock);
+
+ iowrite32(XWWDT_MWR_MASK, xdev->base + XWWDT_MWR_OFFSET);
+ iowrite32(~(u32)XWWDT_ESR_WEN_MASK, xdev->base + XWWDT_ESR_OFFSET);
+- iowrite32((u32)closed_timeout, xdev->base + XWWDT_FWR_OFFSET);
+- iowrite32((u32)open_timeout, xdev->base + XWWDT_SWR_OFFSET);
++ iowrite32((u32)xdev->closed_timeout, xdev->base + XWWDT_FWR_OFFSET);
++ iowrite32((u32)xdev->open_timeout, xdev->base + XWWDT_SWR_OFFSET);
+
+ /* Enable the window watchdog timer */
+ control_status_reg = ioread32(xdev->base + XWWDT_ESR_OFFSET);
+@@ -133,7 +136,12 @@ static int xwwdt_probe(struct platform_device *pdev)
+ struct watchdog_device *xilinx_wwdt_wdd;
+ struct device *dev = &pdev->dev;
+ struct xwwdt_device *xdev;
++ u64 max_per_window_ms;
++ u64 min_per_window_ms;
++ u64 timeout_count;
+ struct clk *clk;
++ u32 timeout_ms;
++ u64 ms_count;
+ int ret;
+
+ xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
+@@ -154,12 +162,13 @@ static int xwwdt_probe(struct platform_device *pdev)
+ return PTR_ERR(clk);
+
+ xdev->freq = clk_get_rate(clk);
+- if (!xdev->freq)
++ if (xdev->freq < 1000000)
+ return -EINVAL;
+
+ xilinx_wwdt_wdd->min_timeout = XWWDT_MIN_TIMEOUT;
+ xilinx_wwdt_wdd->timeout = XWWDT_DEFAULT_TIMEOUT;
+- xilinx_wwdt_wdd->max_hw_heartbeat_ms = 1000 * xilinx_wwdt_wdd->timeout;
++ xilinx_wwdt_wdd->max_hw_heartbeat_ms =
++ div64_u64(XWWDT_MAX_COUNT_WINDOW_COMBINED, xdev->freq) * 1000;
+
+ if (closed_window_percent == 0 || closed_window_percent >= 100)
+ xdev->close_percent = XWWDT_CLOSE_WINDOW_PERCENT;
+@@ -167,6 +176,48 @@ static int xwwdt_probe(struct platform_device *pdev)
+ xdev->close_percent = closed_window_percent;
+
+ watchdog_init_timeout(xilinx_wwdt_wdd, wwdt_timeout, &pdev->dev);
++
++ /* Calculate ticks for 1 milli-second */
++ ms_count = div_u64(xdev->freq, 1000);
++ timeout_ms = xilinx_wwdt_wdd->timeout * 1000;
++ timeout_count = timeout_ms * ms_count;
++
++ if (timeout_ms > xilinx_wwdt_wdd->max_hw_heartbeat_ms) {
++ /*
++ * To avoid ping restrictions until the minimum hardware heartbeat,
++ * we will solely rely on the open window and
++ * adjust the minimum hardware heartbeat to 0.
++ */
++ xdev->closed_timeout = 0;
++ xdev->open_timeout = XWWDT_MAX_COUNT_WINDOW;
++ xilinx_wwdt_wdd->min_hw_heartbeat_ms = 0;
++ xilinx_wwdt_wdd->max_hw_heartbeat_ms = xilinx_wwdt_wdd->max_hw_heartbeat_ms / 2;
++ } else {
++ xdev->closed_timeout = div64_u64(timeout_count * xdev->close_percent, 100);
++ xilinx_wwdt_wdd->min_hw_heartbeat_ms =
++ div64_u64(timeout_ms * xdev->close_percent, 100);
++
++ if (timeout_ms > xilinx_wwdt_wdd->max_hw_heartbeat_ms / 2) {
++ max_per_window_ms = xilinx_wwdt_wdd->max_hw_heartbeat_ms / 2;
++ min_per_window_ms = timeout_ms - max_per_window_ms;
++
++ if (xilinx_wwdt_wdd->min_hw_heartbeat_ms > max_per_window_ms) {
++ dev_info(xilinx_wwdt_wdd->parent,
++ "Closed window cannot be set to %d%%. Using maximum supported value.\n",
++ xdev->close_percent);
++ xdev->closed_timeout = max_per_window_ms * ms_count;
++ xilinx_wwdt_wdd->min_hw_heartbeat_ms = max_per_window_ms;
++ } else if (xilinx_wwdt_wdd->min_hw_heartbeat_ms < min_per_window_ms) {
++ dev_info(xilinx_wwdt_wdd->parent,
++ "Closed window cannot be set to %d%%. Using minimum supported value.\n",
++ xdev->close_percent);
++ xdev->closed_timeout = min_per_window_ms * ms_count;
++ xilinx_wwdt_wdd->min_hw_heartbeat_ms = min_per_window_ms;
++ }
++ }
++ xdev->open_timeout = timeout_count - xdev->closed_timeout;
++ }
++
+ spin_lock_init(&xdev->spinlock);
+ watchdog_set_drvdata(xilinx_wwdt_wdd, xdev);
+ watchdog_set_nowayout(xilinx_wwdt_wdd, 1);
+--
+2.43.0
+
--- /dev/null
+From a53e51e43e8bf477c319392e3a35edfa39d786fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Oct 2024 00:36:15 +0900
+Subject: zram: clear IDLE flag in mark_idle()
+
+From: Sergey Senozhatsky <senozhatsky@chromium.org>
+
+[ Upstream commit d37da422edb0664a2037e6d7d42fe6d339aae78a ]
+
+If entry does not fulfill current mark_idle() parameters, e.g. cutoff
+time, then we should clear its ZRAM_IDLE from previous mark_idle()
+invocations.
+
+Consider the following case:
+- mark_idle() cutoff time 8h
+- mark_idle() cutoff time 4h
+- writeback() idle - will writeback entries with cutoff time 8h,
+ while it should only pick entries with cutoff time 4h
+
+The bug was reported by Shin Kawamura.
+
+Link: https://lkml.kernel.org/r/20241028153629.1479791-3-senozhatsky@chromium.org
+Fixes: 755804d16965 ("zram: introduce an aged idle interface")
+Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reported-by: Shin Kawamura <kawasin@google.com>
+Acked-by: Brian Geffon <bgeffon@google.com>
+Cc: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/zram/zram_drv.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
+index d7f7cc31aaa69..d0432b1707ceb 100644
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -320,6 +320,8 @@ static void mark_idle(struct zram *zram, ktime_t cutoff)
+ #endif
+ if (is_idle)
+ zram_set_flag(zram, index, ZRAM_IDLE);
++ else
++ zram_clear_flag(zram, index, ZRAM_IDLE);
+ zram_slot_unlock(zram, index);
+ }
+ }
+--
+2.43.0
+
--- /dev/null
+From 360d8c21c81e463e8705da5e29ebd02b5f1d4f63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 17 Sep 2024 11:09:10 +0900
+Subject: zram: do not mark idle slots that cannot be idle
+
+From: Sergey Senozhatsky <senozhatsky@chromium.org>
+
+[ Upstream commit b967fa1ba72b5da2b6d9bf95f0b13420a59e0701 ]
+
+ZRAM_SAME slots cannot be post-processed (writeback or recompress) so do
+not mark them ZRAM_IDLE. Same with ZRAM_WB slots, they cannot be
+ZRAM_IDLE because they are not in zsmalloc pool anymore.
+
+Link: https://lkml.kernel.org/r/20240917021020.883356-6-senozhatsky@chromium.org
+Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: d37da422edb0 ("zram: clear IDLE flag in mark_idle()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/zram/zram_drv.c | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
+index d6a1ba969266a..d7f7cc31aaa69 100644
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -298,17 +298,28 @@ static void mark_idle(struct zram *zram, ktime_t cutoff)
+ /*
+ * Do not mark ZRAM_UNDER_WB slot as ZRAM_IDLE to close race.
+ * See the comment in writeback_store.
++ *
++ * Also do not mark ZRAM_SAME slots as ZRAM_IDLE, because no
++ * post-processing (recompress, writeback) happens to the
++ * ZRAM_SAME slot.
++ *
++ * And ZRAM_WB slots simply cannot be ZRAM_IDLE.
+ */
+ zram_slot_lock(zram, index);
+- if (zram_allocated(zram, index) &&
+- !zram_test_flag(zram, index, ZRAM_UNDER_WB)) {
++ if (!zram_allocated(zram, index) ||
++ zram_test_flag(zram, index, ZRAM_WB) ||
++ zram_test_flag(zram, index, ZRAM_UNDER_WB) ||
++ zram_test_flag(zram, index, ZRAM_SAME)) {
++ zram_slot_unlock(zram, index);
++ continue;
++ }
++
+ #ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME
+- is_idle = !cutoff || ktime_after(cutoff,
+- zram->table[index].ac_time);
++ is_idle = !cutoff ||
++ ktime_after(cutoff, zram->table[index].ac_time);
+ #endif
+- if (is_idle)
+- zram_set_flag(zram, index, ZRAM_IDLE);
+- }
++ if (is_idle)
++ zram_set_flag(zram, index, ZRAM_IDLE);
+ zram_slot_unlock(zram, index);
+ }
+ }
+--
+2.43.0
+