--- /dev/null
+From b1149bd3ee99d61222771eea4449ce8fabf95d58 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 226969bc60f0e5d9165b4dcb763c2536e50f3f87 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 be70c644c8640a4474243e1301534885cf33dea7 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 6dd4665c82900..ec28d504ca666 100644
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -41,9 +41,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)
+ */
+@@ -326,6 +323,9 @@ struct gs_usb {
+ struct usb_device *udev;
+ unsigned int hf_size_rx;
+ u8 active_channels;
++
++ unsigned int pipe_in;
++ unsigned int pipe_out;
+ };
+
+ /* 'allocate' a tx context.
+@@ -644,7 +644,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);
+
+@@ -780,7 +780,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);
+
+@@ -885,8 +885,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);
+@@ -1330,6 +1329,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 = {
+@@ -1339,6 +1339,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,
+@@ -1383,6 +1390,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 fb6e247e34f32a65fa0a9fe00bcd931025e16bd7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 16:03:52 +0200
+Subject: can: gs_usb: add VID/PID for Xylanta SAINT3 product family
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 69e2326a21ef409d6c709cb990565331727b9f27 ]
+
+Add support for the Xylanta SAINT3 product family.
+
+Cc: Andy Jackson <andy@xylanta.com>
+Cc: Ken Aitchison <ken@xylanta.com>
+Tested-by: Andy Jackson <andy@xylanta.com>
+Link: https://lore.kernel.org/all/20240625140353.769373-1-mkl@pengutronix.de
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Stable-dep-of: 889b2ae9139a ("can: gs_usb: add usb endpoint address detection at driver probe step")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/gs_usb.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
+index 257e5f10ff1be..6dd4665c82900 100644
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -38,6 +38,9 @@
+ #define USB_ABE_CANDEBUGGER_FD_VENDOR_ID 0x16d0
+ #define USB_ABE_CANDEBUGGER_FD_PRODUCT_ID 0x10b8
+
++#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
+
+@@ -1448,6 +1451,8 @@ static const struct usb_device_id gs_usb_table[] = {
+ USB_CES_CANEXT_FD_PRODUCT_ID, 0) },
+ { USB_DEVICE_INTERFACE_NUMBER(USB_ABE_CANDEBUGGER_FD_VENDOR_ID,
+ USB_ABE_CANDEBUGGER_FD_PRODUCT_ID, 0) },
++ { USB_DEVICE_INTERFACE_NUMBER(USB_XYLANTA_SAINT3_VENDOR_ID,
++ USB_XYLANTA_SAINT3_PRODUCT_ID, 0) },
+ {} /* Terminating entry */
+ };
+
+--
+2.43.0
+
--- /dev/null
+From 74032955022464fd01facedef3de7d4f643b4fe1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 13:08:43 +0200
+Subject: can: gs_usb: gs_usb_probe(): align block comment
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 5780148bedd6aa7e51d3a18cd70f5b9b6cefb79e ]
+
+Indent block comment so that it aligns the * on each line.
+
+Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-2-c3b9154ec605@pengutronix.de
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Stable-dep-of: 889b2ae9139a ("can: gs_usb: add usb endpoint address detection at driver probe step")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/gs_usb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
+index 1d089c9b46410..cb96e42961109 100644
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -1400,8 +1400,8 @@ static int gs_usb_probe(struct usb_interface *intf,
+ dev->canch[i]->parent = dev;
+
+ /* set RX packet size based on FD and if hardware
+- * timestamps are supported.
+- */
++ * timestamps are supported.
++ */
+ if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
+ if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ hf_size_rx = struct_size(hf, canfd_ts, 1);
+--
+2.43.0
+
--- /dev/null
+From 2f40f76b78ee50e5d0b6ea938f6dfb6103f56e3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jul 2023 11:11:22 +0200
+Subject: can: gs_usb: remove leading space from goto labels
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit f1a14714bf48f87fa8e774f415ea9815daf3750d ]
+
+Remove leading spaces from goto labels in accordance with the kernel
+encoding style.
+
+Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-1-c3b9154ec605@pengutronix.de
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Stable-dep-of: 889b2ae9139a ("can: gs_usb: add usb endpoint address detection at driver probe step")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/gs_usb.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
+index 264a0f764e011..1d089c9b46410 100644
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -639,7 +639,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+ netif_rx(skb);
+ }
+
+- resubmit_urb:
++resubmit_urb:
+ usb_fill_bulk_urb(urb, usbcan->udev,
+ usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN),
+ hf, dev->parent->hf_size_rx,
+@@ -649,7 +649,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+
+ /* USB failure take down all interfaces */
+ if (rc == -ENODEV) {
+- device_detach:
++device_detach:
+ for (rc = 0; rc < GS_MAX_INTF; rc++) {
+ if (usbcan->canch[rc])
+ netif_device_detach(usbcan->canch[rc]->netdev);
+@@ -814,12 +814,12 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
+
+ return NETDEV_TX_OK;
+
+- badidx:
++badidx:
+ kfree(hf);
+- nomem_hf:
++nomem_hf:
+ usb_free_urb(urb);
+
+- nomem_urb:
++nomem_urb:
+ gs_free_tx_context(txc);
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+@@ -1311,7 +1311,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
+
+ return dev;
+
+- out_free_candev:
++out_free_candev:
+ free_candev(dev->netdev);
+ return ERR_PTR(rc);
+ }
+--
+2.43.0
+
--- /dev/null
+From da78baf2dd795f0758f6e6e1312f02692d4adbe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 16:16:33 +0200
+Subject: can: gs_usb: uniformly use "parent" as variable name for struct
+ gs_usb
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit b6980ad3a90c73c95cab97e9a33129b8f53e2a5b ]
+
+To ease readability and maintainability uniformly use the variable
+name "parent" for the struct gs_usb in the gs_usb driver.
+
+Link: https://lore.kernel.org/all/20230718-gs_usb-cleanups-v1-4-c3b9154ec605@pengutronix.de
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Stable-dep-of: 889b2ae9139a ("can: gs_usb: add usb endpoint address detection at driver probe step")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/can/usb/gs_usb.c | 62 ++++++++++++++++++------------------
+ 1 file changed, 31 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
+index cb96e42961109..257e5f10ff1be 100644
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -522,7 +522,7 @@ static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb,
+
+ static void gs_usb_receive_bulk_callback(struct urb *urb)
+ {
+- struct gs_usb *usbcan = urb->context;
++ struct gs_usb *parent = urb->context;
+ struct gs_can *dev;
+ struct net_device *netdev;
+ int rc;
+@@ -533,7 +533,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+ struct canfd_frame *cfd;
+ struct sk_buff *skb;
+
+- BUG_ON(!usbcan);
++ BUG_ON(!parent);
+
+ switch (urb->status) {
+ case 0: /* success */
+@@ -550,7 +550,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+ if (hf->channel >= GS_MAX_INTF)
+ goto device_detach;
+
+- dev = usbcan->canch[hf->channel];
++ dev = parent->canch[hf->channel];
+
+ netdev = dev->netdev;
+ stats = &netdev->stats;
+@@ -640,10 +640,10 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+ }
+
+ resubmit_urb:
+- usb_fill_bulk_urb(urb, usbcan->udev,
+- usb_rcvbulkpipe(usbcan->udev, GS_USB_ENDPOINT_IN),
++ usb_fill_bulk_urb(urb, parent->udev,
++ usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
+ hf, dev->parent->hf_size_rx,
+- gs_usb_receive_bulk_callback, usbcan);
++ gs_usb_receive_bulk_callback, parent);
+
+ rc = usb_submit_urb(urb, GFP_ATOMIC);
+
+@@ -651,8 +651,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
+ if (rc == -ENODEV) {
+ device_detach:
+ for (rc = 0; rc < GS_MAX_INTF; rc++) {
+- if (usbcan->canch[rc])
+- netif_device_detach(usbcan->canch[rc]->netdev);
++ if (parent->canch[rc])
++ netif_device_detach(parent->canch[rc]->netdev);
+ }
+ }
+ }
+@@ -1328,7 +1328,7 @@ static int gs_usb_probe(struct usb_interface *intf,
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct gs_host_frame *hf;
+- struct gs_usb *dev;
++ struct gs_usb *parent;
+ struct gs_host_config hconf = {
+ .byte_order = cpu_to_le32(0x0000beef),
+ };
+@@ -1371,49 +1371,49 @@ static int gs_usb_probe(struct usb_interface *intf,
+ return -EINVAL;
+ }
+
+- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+- if (!dev)
++ parent = kzalloc(sizeof(*parent), GFP_KERNEL);
++ if (!parent)
+ return -ENOMEM;
+
+- init_usb_anchor(&dev->rx_submitted);
++ init_usb_anchor(&parent->rx_submitted);
+
+- usb_set_intfdata(intf, dev);
+- dev->udev = udev;
++ usb_set_intfdata(intf, parent);
++ parent->udev = udev;
+
+ for (i = 0; i < icount; i++) {
+ unsigned int hf_size_rx = 0;
+
+- dev->canch[i] = gs_make_candev(i, intf, &dconf);
+- if (IS_ERR_OR_NULL(dev->canch[i])) {
++ parent->canch[i] = gs_make_candev(i, intf, &dconf);
++ if (IS_ERR_OR_NULL(parent->canch[i])) {
+ /* save error code to return later */
+- rc = PTR_ERR(dev->canch[i]);
++ rc = PTR_ERR(parent->canch[i]);
+
+ /* on failure destroy previously created candevs */
+ icount = i;
+ for (i = 0; i < icount; i++)
+- gs_destroy_candev(dev->canch[i]);
++ gs_destroy_candev(parent->canch[i]);
+
+- usb_kill_anchored_urbs(&dev->rx_submitted);
+- kfree(dev);
++ usb_kill_anchored_urbs(&parent->rx_submitted);
++ kfree(parent);
+ return rc;
+ }
+- dev->canch[i]->parent = dev;
++ parent->canch[i]->parent = parent;
+
+ /* set RX packet size based on FD and if hardware
+ * timestamps are supported.
+ */
+- if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
+- if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
++ if (parent->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
++ if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ hf_size_rx = struct_size(hf, canfd_ts, 1);
+ else
+ hf_size_rx = struct_size(hf, canfd, 1);
+ } else {
+- if (dev->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
++ if (parent->canch[i]->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+ hf_size_rx = struct_size(hf, classic_can_ts, 1);
+ else
+ hf_size_rx = struct_size(hf, classic_can, 1);
+ }
+- dev->hf_size_rx = max(dev->hf_size_rx, hf_size_rx);
++ parent->hf_size_rx = max(parent->hf_size_rx, hf_size_rx);
+ }
+
+ return 0;
+@@ -1421,22 +1421,22 @@ static int gs_usb_probe(struct usb_interface *intf,
+
+ static void gs_usb_disconnect(struct usb_interface *intf)
+ {
+- struct gs_usb *dev = usb_get_intfdata(intf);
++ struct gs_usb *parent = usb_get_intfdata(intf);
+ unsigned int i;
+
+ usb_set_intfdata(intf, NULL);
+
+- if (!dev) {
++ if (!parent) {
+ dev_err(&intf->dev, "Disconnect (nodata)\n");
+ return;
+ }
+
+ for (i = 0; i < GS_MAX_INTF; i++)
+- if (dev->canch[i])
+- gs_destroy_candev(dev->canch[i]);
++ if (parent->canch[i])
++ gs_destroy_candev(parent->canch[i]);
+
+- usb_kill_anchored_urbs(&dev->rx_submitted);
+- kfree(dev);
++ usb_kill_anchored_urbs(&parent->rx_submitted);
++ kfree(parent);
+ }
+
+ static const struct usb_device_id gs_usb_table[] = {
+--
+2.43.0
+
--- /dev/null
+From b0f21f7dc4884d4ecbb5fbbe39ecc582621a6fc3 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 e1b8533a602e2..fb58e294f7b79 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 54f639b2bd48d326f2752036ec908c521e72fe72 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 fb58e294f7b79..b757555ed4c4f 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 fc6061c2aa6ba29c08c4a25d5ab751e32f692044 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 07eaf724a5727..de26f5788ff5f 100644
+--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
++++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
+@@ -391,36 +391,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);
+@@ -428,6 +447,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 d375d8af0f2b0f65cd439e430e65416a140e69f1 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 5d2097e5ca3a8..a58f6f5dfcf8e 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 42a71e2a802db186e0c3d5f4d86fa6873063b3b8 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 e77b4b60f4e61..f28bdb5badd05 100644
+--- a/drivers/net/can/m_can/m_can.c
++++ b/drivers/net/can/m_can/m_can.c
+@@ -607,47 +607,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 ede71c5d582f0734cbd7fae3c67d23a8c5b3e64d 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 aac5956e4a532..26ec3c4e41100 100644
+--- a/drivers/net/can/sja1000/sja1000.c
++++ b/drivers/net/can/sja1000/sja1000.c
+@@ -399,8 +399,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
+ uint8_t ecc, alc;
+
+ 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);
+@@ -408,8 +406,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 */
+@@ -426,7 +427,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;
+@@ -434,33 +435,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 */
+@@ -476,8 +482,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) {
+@@ -490,6 +498,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 0;
+--
+2.43.0
+
--- /dev/null
+From 5f0af4591a82d511091648b98543ea3c57a63b71 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 c3a6b028ea4d6..6bf721eda65d2 100644
+--- a/drivers/net/can/sun4i_can.c
++++ b/drivers/net/can/sun4i_can.c
+@@ -630,10 +630,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 b3354910ea45d1fdce868ba6497a63fe0103fd46 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 6bf721eda65d2..4bec1e7e7b3e3 100644
+--- a/drivers/net/can/sun4i_can.c
++++ b/drivers/net/can/sun4i_can.c
+@@ -580,11 +580,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) {
+@@ -602,9 +600,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 66b8c6a576273c3388ba11d2cba69a1cfb714ecd 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 98bc40fcb130a258c67b6c18775c18ad04529dd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Feb 2024 16:42:36 +0000
+Subject: device property: Add cleanup.h based fwnode_handle_put() scope based
+ cleanup.
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 59ed5e2d505bf5f9b4af64d0021cd0c96aec1f7c ]
+
+Useful where the fwnode_handle was obtained from a call such as
+fwnode_find_reference() as it will safely do nothing if IS_ERR() is true
+and will automatically release the reference on the variable leaving
+scope.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240217164249.921878-3-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 73b03b27736e ("leds: flash: mt6360: Fix device_for_each_child_node() refcounting in error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/property.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/include/linux/property.h b/include/linux/property.h
+index ec3490591f934..f2e8590cefd89 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -11,6 +11,7 @@
+ #define _LINUX_PROPERTY_H_
+
+ #include <linux/bits.h>
++#include <linux/cleanup.h>
+ #include <linux/fwnode.h>
+ #include <linux/types.h>
+
+@@ -129,6 +130,8 @@ struct fwnode_handle *device_get_named_child_node(const struct device *dev,
+ struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
+ void fwnode_handle_put(struct fwnode_handle *fwnode);
+
++DEFINE_FREE(fwnode_handle, struct fwnode_handle *, fwnode_handle_put(_T))
++
+ int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
+ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
+
+--
+2.43.0
+
--- /dev/null
+From 2c594f63fcdee0aedf77f781f6e99aa0b642468c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Oct 2022 12:21:28 +0300
+Subject: device property: Constify device child node APIs
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 7952cd2b8213f20a1752634c25dfd215da537722 ]
+
+The device parameter is not altered in the device child node APIs,
+constify them.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Link: https://lore.kernel.org/r/20221004092129.19412-5-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 73b03b27736e ("leds: flash: mt6360: Fix device_for_each_child_node() refcounting in error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/property.c | 6 +++---
+ include/linux/property.h | 12 ++++++------
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/base/property.c b/drivers/base/property.c
+index eb9b01c2ff1d9..ba612087a278f 100644
+--- a/drivers/base/property.c
++++ b/drivers/base/property.c
+@@ -790,7 +790,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
+ * fwnode pointer. Note that this function also puts a reference to @child
+ * unconditionally.
+ */
+-struct fwnode_handle *device_get_next_child_node(struct device *dev,
++struct fwnode_handle *device_get_next_child_node(const struct device *dev,
+ struct fwnode_handle *child)
+ {
+ const struct fwnode_handle *fwnode = dev_fwnode(dev);
+@@ -833,7 +833,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
+ * The caller is responsible for calling fwnode_handle_put() on the returned
+ * fwnode pointer.
+ */
+-struct fwnode_handle *device_get_named_child_node(struct device *dev,
++struct fwnode_handle *device_get_named_child_node(const struct device *dev,
+ const char *childname)
+ {
+ return fwnode_get_named_child_node(dev_fwnode(dev), childname);
+@@ -899,7 +899,7 @@ EXPORT_SYMBOL_GPL(fwnode_device_is_available);
+ *
+ * Return: the number of child nodes for a given device.
+ */
+-unsigned int device_get_child_node_count(struct device *dev)
++unsigned int device_get_child_node_count(const struct device *dev)
+ {
+ struct fwnode_handle *child;
+ unsigned int count = 0;
+diff --git a/include/linux/property.h b/include/linux/property.h
+index 587b5b666b5bb..ec3490591f934 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -114,16 +114,16 @@ struct fwnode_handle *fwnode_get_next_available_child_node(
+ for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
+ child = fwnode_get_next_available_child_node(fwnode, child))
+
+-struct fwnode_handle *device_get_next_child_node(
+- struct device *dev, struct fwnode_handle *child);
++struct fwnode_handle *device_get_next_child_node(const struct device *dev,
++ struct fwnode_handle *child);
+
+ #define device_for_each_child_node(dev, child) \
+ for (child = device_get_next_child_node(dev, NULL); child; \
+ child = device_get_next_child_node(dev, child))
+
+-struct fwnode_handle *fwnode_get_named_child_node(
+- const struct fwnode_handle *fwnode, const char *childname);
+-struct fwnode_handle *device_get_named_child_node(struct device *dev,
++struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
++ const char *childname);
++struct fwnode_handle *device_get_named_child_node(const struct device *dev,
+ const char *childname);
+
+ struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
+@@ -132,7 +132,7 @@ void fwnode_handle_put(struct fwnode_handle *fwnode);
+ int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
+ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
+
+-unsigned int device_get_child_node_count(struct device *dev);
++unsigned int device_get_child_node_count(const struct device *dev);
+
+ static inline bool device_property_read_bool(struct device *dev,
+ const char *propname)
+--
+2.43.0
+
--- /dev/null
+From 01797588d8c33836e83ae931fefdc76a8bacbccb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Feb 2024 16:42:38 +0000
+Subject: device property: Introduce device_for_each_child_node_scoped()
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 365130fd47af6d4317aa16a407874b699ab8d8cb ]
+
+Similar to recently propose for_each_child_of_node_scoped() this
+new version of the loop macro instantiates a new local
+struct fwnode_handle * that uses the __free(fwnode_handle) auto
+cleanup handling so that if a reference to a node is held on early
+exit from the loop the reference will be released. If the loop
+runs to completion, the child pointer will be NULL and no action will
+be taken.
+
+The reason this is useful is that it removes the need for
+fwnode_handle_put() on early loop exits. If there is a need
+to retain the reference, then return_ptr(child) or no_free_ptr(child)
+may be used to safely disable the auto cleanup.
+
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240217164249.921878-5-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 73b03b27736e ("leds: flash: mt6360: Fix device_for_each_child_node() refcounting in error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/property.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/include/linux/property.h b/include/linux/property.h
+index f2e8590cefd89..fb685f0f702aa 100644
+--- a/include/linux/property.h
++++ b/include/linux/property.h
+@@ -122,6 +122,11 @@ struct fwnode_handle *device_get_next_child_node(const struct device *dev,
+ for (child = device_get_next_child_node(dev, NULL); child; \
+ child = device_get_next_child_node(dev, child))
+
++#define device_for_each_child_node_scoped(dev, child) \
++ for (struct fwnode_handle *child __free(fwnode_handle) = \
++ device_get_next_child_node(dev, NULL); \
++ child; child = device_get_next_child_node(dev, child))
++
+ struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
+ const char *childname);
+ struct fwnode_handle *device_get_named_child_node(const struct device *dev,
+--
+2.43.0
+
--- /dev/null
+From 4435b2daecbf49c4a7c59a2aef3436bb80b75162 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 21:04:55 -0800
+Subject: driver core: Add FWLINK_FLAG_IGNORE to completely ignore a fwnode
+ link
+
+From: Saravana Kannan <saravanak@google.com>
+
+[ Upstream commit b7e1241d8f77ed64404a5e4450f43a319310fc91 ]
+
+A fwnode link between specific supplier-consumer fwnodes can be added
+multiple times for multiple reasons. If that dependency doesn't exist,
+deleting the fwnode link once doesn't guarantee that it won't get created
+again.
+
+So, add FWLINK_FLAG_IGNORE flag to mark a fwnode link as one that needs to
+be completely ignored. Since a fwnode link's flags is an OR of all the
+flags passed to all the fwnode_link_add() calls to create that specific
+fwnode link, the FWLINK_FLAG_IGNORE flag is preserved and can be used to
+mark a fwnode link as on that need to be completely ignored until it is
+deleted.
+
+Signed-off-by: Saravana Kannan <saravanak@google.com>
+Acked-by: "Rafael J. Wysocki" <rafael@kernel.org>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20240305050458.1400667-3-saravanak@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: bac3b10b78e5 ("driver core: fw_devlink: Stop trying to optimize cycle detection logic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/core.c | 9 ++++++++-
+ include/linux/fwnode.h | 2 ++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index f0a66fec4fa75..e1436e351826c 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -1082,7 +1082,8 @@ static struct fwnode_handle *fwnode_links_check_suppliers(
+ return NULL;
+
+ list_for_each_entry(link, &fwnode->suppliers, c_hook)
+- if (!(link->flags & FWLINK_FLAG_CYCLE))
++ if (!(link->flags &
++ (FWLINK_FLAG_CYCLE | FWLINK_FLAG_IGNORE)))
+ return link->supplier;
+
+ return NULL;
+@@ -1973,6 +1974,9 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+ }
+
+ list_for_each_entry(link, &sup_handle->suppliers, c_hook) {
++ if (link->flags & FWLINK_FLAG_IGNORE)
++ continue;
++
+ if (__fw_devlink_relax_cycles(con, link->supplier)) {
+ __fwnode_link_cycle(link);
+ ret = true;
+@@ -2051,6 +2055,9 @@ static int fw_devlink_create_devlink(struct device *con,
+ int ret = 0;
+ u32 flags;
+
++ if (link->flags & FWLINK_FLAG_IGNORE)
++ return 0;
++
+ if (con->fwnode == link->consumer)
+ flags = fw_devlink_get_flags(link->flags);
+ else
+diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
+index 5700451b300fb..525cc031596b6 100644
+--- a/include/linux/fwnode.h
++++ b/include/linux/fwnode.h
+@@ -51,8 +51,10 @@ struct fwnode_handle {
+ * fwnode link flags
+ *
+ * CYCLE: The fwnode link is part of a cycle. Don't defer probe.
++ * IGNORE: Completely ignore this link, even during cycle detection.
+ */
+ #define FWLINK_FLAG_CYCLE BIT(0)
++#define FWLINK_FLAG_IGNORE BIT(1)
+
+ struct fwnode_link {
+ struct fwnode_handle *supplier;
+--
+2.43.0
+
--- /dev/null
+From b6b5cde89215b39b8dfced002015b23e2be736d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2024 01:56:35 -0800
+Subject: driver core: fw_devlink: Improve logs for cycle detection
+
+From: Saravana Kannan <saravanak@google.com>
+
+[ Upstream commit 6e7ad1aebb4fc9fed0217dd50ef6e58a53f17d81 ]
+
+The links in a cycle are not all logged in a consistent manner or not
+logged at all. Make them consistent by adding a "cycle:" string and log all
+the link in the cycles (even the child ==> parent dependency) so that it's
+easier to debug cycle detection code. Also, mark the start and end of a
+cycle so it's easy to tell when multiple cycles are logged back to back.
+
+Signed-off-by: Saravana Kannan <saravanak@google.com>
+Tested-by: Xu Yang <xu.yang_2@nxp.com>
+Link: https://lore.kernel.org/r/20240202095636.868578-4-saravanak@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: bac3b10b78e5 ("driver core: fw_devlink: Stop trying to optimize cycle detection logic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/core.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 30204e62497c2..f0a66fec4fa75 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -137,7 +137,7 @@ static void __fwnode_link_del(struct fwnode_link *link)
+ */
+ static void __fwnode_link_cycle(struct fwnode_link *link)
+ {
+- pr_debug("%pfwf: Relaxing link with %pfwf\n",
++ pr_debug("%pfwf: cycle: depends on %pfwf\n",
+ link->consumer, link->supplier);
+ link->flags |= FWLINK_FLAG_CYCLE;
+ }
+@@ -1956,6 +1956,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+
+ /* Termination condition. */
+ if (sup_dev == con) {
++ pr_debug("----- cycle: start -----\n");
+ ret = true;
+ goto out;
+ }
+@@ -1987,8 +1988,11 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+ else
+ par_dev = fwnode_get_next_parent_dev(sup_handle);
+
+- if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode))
++ if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode)) {
++ pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
++ par_dev->fwnode);
+ ret = true;
++ }
+
+ if (!sup_dev)
+ goto out;
+@@ -2004,6 +2008,8 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+
+ if (__fw_devlink_relax_cycles(con,
+ dev_link->supplier->fwnode)) {
++ pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
++ dev_link->supplier->fwnode);
+ fw_devlink_relax_link(dev_link);
+ dev_link->flags |= DL_FLAG_CYCLE;
+ ret = true;
+@@ -2083,6 +2089,7 @@ static int fw_devlink_create_devlink(struct device *con,
+ if (__fw_devlink_relax_cycles(con, sup_handle)) {
+ __fwnode_link_cycle(link);
+ flags = fw_devlink_get_flags(link->flags);
++ pr_debug("----- cycle: end -----\n");
+ dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
+ sup_handle);
+ }
+--
+2.43.0
+
--- /dev/null
+From 79c95c8fff70e86e216c48961edfaccff5bb1987 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Oct 2024 10:10:07 -0700
+Subject: driver core: fw_devlink: Stop trying to optimize cycle detection
+ logic
+
+From: Saravana Kannan <saravanak@google.com>
+
+[ Upstream commit bac3b10b78e54b7da3cede397258f75a2180609b ]
+
+In attempting to optimize fw_devlink runtime, I introduced numerous cycle
+detection bugs by foregoing cycle detection logic under specific
+conditions. Each fix has further narrowed the conditions for optimization.
+
+It's time to give up on these optimization attempts and just run the cycle
+detection logic every time fw_devlink tries to create a device link.
+
+The specific bug report that triggered this fix involved a supplier fwnode
+that never gets a device created for it. Instead, the supplier fwnode is
+represented by the device that corresponds to an ancestor fwnode.
+
+In this case, fw_devlink didn't do any cycle detection because the cycle
+detection logic is only run when a device link is created between the
+devices that correspond to the actual consumer and supplier fwnodes.
+
+With this change, fw_devlink will run cycle detection logic even when
+creating SYNC_STATE_ONLY proxy device links from a device that is an
+ancestor of a consumer fwnode.
+
+Reported-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Closes: https://lore.kernel.org/all/1a1ab663-d068-40fb-8c94-f0715403d276@ideasonboard.com/
+Fixes: 6442d79d880c ("driver core: fw_devlink: Improve detection of overlapping cycles")
+Cc: stable <stable@kernel.org>
+Tested-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Saravana Kannan <saravanak@google.com>
+Link: https://lore.kernel.org/r/20241030171009.1853340-1-saravanak@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/core.c | 55 ++++++++++++++++++++-------------------------
+ 1 file changed, 24 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index e1436e351826c..f21ceb93e50ef 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -1933,10 +1933,10 @@ static bool fwnode_ancestor_init_without_drv(struct fwnode_handle *fwnode)
+ *
+ * Return true if one or more cycles were found. Otherwise, return false.
+ */
+-static bool __fw_devlink_relax_cycles(struct device *con,
++static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
+ struct fwnode_handle *sup_handle)
+ {
+- struct device *sup_dev = NULL, *par_dev = NULL;
++ struct device *sup_dev = NULL, *par_dev = NULL, *con_dev = NULL;
+ struct fwnode_link *link;
+ struct device_link *dev_link;
+ bool ret = false;
+@@ -1953,22 +1953,22 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+
+ sup_handle->flags |= FWNODE_FLAG_VISITED;
+
+- sup_dev = get_dev_from_fwnode(sup_handle);
+-
+ /* Termination condition. */
+- if (sup_dev == con) {
++ if (sup_handle == con_handle) {
+ pr_debug("----- cycle: start -----\n");
+ ret = true;
+ goto out;
+ }
+
++ sup_dev = get_dev_from_fwnode(sup_handle);
++ con_dev = get_dev_from_fwnode(con_handle);
+ /*
+ * If sup_dev is bound to a driver and @con hasn't started binding to a
+ * driver, sup_dev can't be a consumer of @con. So, no need to check
+ * further.
+ */
+ if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND &&
+- con->links.status == DL_DEV_NO_DRIVER) {
++ con_dev && con_dev->links.status == DL_DEV_NO_DRIVER) {
+ ret = false;
+ goto out;
+ }
+@@ -1977,7 +1977,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+ if (link->flags & FWLINK_FLAG_IGNORE)
+ continue;
+
+- if (__fw_devlink_relax_cycles(con, link->supplier)) {
++ if (__fw_devlink_relax_cycles(con_handle, link->supplier)) {
+ __fwnode_link_cycle(link);
+ ret = true;
+ }
+@@ -1992,7 +1992,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+ else
+ par_dev = fwnode_get_next_parent_dev(sup_handle);
+
+- if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode)) {
++ if (par_dev && __fw_devlink_relax_cycles(con_handle, par_dev->fwnode)) {
+ pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
+ par_dev->fwnode);
+ ret = true;
+@@ -2010,7 +2010,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
+ !(dev_link->flags & DL_FLAG_CYCLE))
+ continue;
+
+- if (__fw_devlink_relax_cycles(con,
++ if (__fw_devlink_relax_cycles(con_handle,
+ dev_link->supplier->fwnode)) {
+ pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
+ dev_link->supplier->fwnode);
+@@ -2058,11 +2058,6 @@ static int fw_devlink_create_devlink(struct device *con,
+ if (link->flags & FWLINK_FLAG_IGNORE)
+ return 0;
+
+- if (con->fwnode == link->consumer)
+- flags = fw_devlink_get_flags(link->flags);
+- else
+- flags = FW_DEVLINK_FLAGS_PERMISSIVE;
+-
+ /*
+ * In some cases, a device P might also be a supplier to its child node
+ * C. However, this would defer the probe of C until the probe of P
+@@ -2083,25 +2078,23 @@ static int fw_devlink_create_devlink(struct device *con,
+ return -EINVAL;
+
+ /*
+- * SYNC_STATE_ONLY device links don't block probing and supports cycles.
+- * So, one might expect that cycle detection isn't necessary for them.
+- * However, if the device link was marked as SYNC_STATE_ONLY because
+- * it's part of a cycle, then we still need to do cycle detection. This
+- * is because the consumer and supplier might be part of multiple cycles
+- * and we need to detect all those cycles.
++ * Don't try to optimize by not calling the cycle detection logic under
++ * certain conditions. There's always some corner case that won't get
++ * detected.
+ */
+- if (!device_link_flag_is_sync_state_only(flags) ||
+- flags & DL_FLAG_CYCLE) {
+- device_links_write_lock();
+- if (__fw_devlink_relax_cycles(con, sup_handle)) {
+- __fwnode_link_cycle(link);
+- flags = fw_devlink_get_flags(link->flags);
+- pr_debug("----- cycle: end -----\n");
+- dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
+- sup_handle);
+- }
+- device_links_write_unlock();
++ device_links_write_lock();
++ if (__fw_devlink_relax_cycles(link->consumer, sup_handle)) {
++ __fwnode_link_cycle(link);
++ pr_debug("----- cycle: end -----\n");
++ pr_info("%pfwf: Fixed dependency cycle(s) with %pfwf\n",
++ link->consumer, sup_handle);
+ }
++ device_links_write_unlock();
++
++ if (con->fwnode == link->consumer)
++ flags = fw_devlink_get_flags(link->flags);
++ else
++ flags = FW_DEVLINK_FLAGS_PERMISSIVE;
+
+ if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
+ sup_dev = fwnode_get_next_parent_dev(sup_handle);
+--
+2.43.0
+
--- /dev/null
+From 76b02e563c1eef579a0105539cf5d14b2faf1b7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Oct 2024 17:54:10 +0800
+Subject: drm/bridge: it6505: Fix inverted reset polarity
+
+From: Chen-Yu Tsai <wenst@chromium.org>
+
+[ Upstream commit c5f3f21728b069412e8072b8b1d0a3d9d3ab0265 ]
+
+The IT6505 bridge chip has a active low reset line. Since it is a
+"reset" and not an "enable" line, the GPIO should be asserted to
+put it in reset and deasserted to bring it out of reset during
+the power on sequence.
+
+The polarity was inverted when the driver was first introduced, likely
+because the device family that was targeted had an inverting level
+shifter on the reset line.
+
+The MT8186 Corsola devices already have the IT6505 in their device tree,
+but the whole display pipeline is actually disabled and won't be enabled
+until some remaining issues are sorted out. The other known user is
+the MT8183 Kukui / Jacuzzi family; their device trees currently do not
+have the IT6505 included.
+
+Fix the polarity in the driver while there are no actual users.
+
+Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241029095411.657616-1-wenst@chromium.org
+Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/ite-it6505.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
+index aad750ad4798d..fbccf7835f700 100644
+--- a/drivers/gpu/drm/bridge/ite-it6505.c
++++ b/drivers/gpu/drm/bridge/ite-it6505.c
+@@ -2560,9 +2560,9 @@ static int it6505_poweron(struct it6505 *it6505)
+ /* time interval between OVDD and SYSRSTN at least be 10ms */
+ if (pdata->gpiod_reset) {
+ usleep_range(10000, 20000);
+- gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+- usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
++ usleep_range(1000, 2000);
++ gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+ usleep_range(25000, 35000);
+ }
+
+@@ -2589,7 +2589,7 @@ static int it6505_poweroff(struct it6505 *it6505)
+ }
+
+ if (pdata->gpiod_reset)
+- gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
++ gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+
+ if (pdata->pwr18) {
+ err = regulator_disable(pdata->pwr18);
+@@ -3050,7 +3050,7 @@ static int it6505_init_pdata(struct it6505 *it6505)
+ return PTR_ERR(pdata->ovdd);
+ }
+
+- pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
++ pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(pdata->gpiod_reset)) {
+ dev_err(dev, "gpiod_reset gpio not found");
+ return PTR_ERR(pdata->gpiod_reset);
+--
+2.43.0
+
--- /dev/null
+From 66afc84a89c42e65240e145b7f2092d48f51a81f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 10:44:05 +0800
+Subject: drm/bridge: it6505: update usleep_range for RC circuit charge time
+
+From: Kuro Chung <kuro.chung@ite.com.tw>
+
+[ Upstream commit 8814444e62b8a8b573fba2cbbb327d5817b74eb0 ]
+
+The spec of timing between IVDD/OVDD and SYSRTEN is 10ms, but SYSRSTN RC
+circuit need at least 25ms for rising time, update for match spec
+
+Signed-off-by: Kuro Chung <kuro.chung@ite.com.tw>
+Signed-off-by: Hermes Wu <hermes.wu@ite.com.tw>
+Reviewed-by: Robert Foss <rfoss@kernel.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240604024405.1122488-1-kuro.chung@ite.com.tw
+Stable-dep-of: c5f3f21728b0 ("drm/bridge: it6505: Fix inverted reset polarity")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/ite-it6505.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
+index 292c4f6da04af..aad750ad4798d 100644
+--- a/drivers/gpu/drm/bridge/ite-it6505.c
++++ b/drivers/gpu/drm/bridge/ite-it6505.c
+@@ -2563,7 +2563,7 @@ static int it6505_poweron(struct it6505 *it6505)
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+ usleep_range(1000, 2000);
+ gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+- usleep_range(10000, 20000);
++ usleep_range(25000, 35000);
+ }
+
+ it6505->powered = true;
+--
+2.43.0
+
--- /dev/null
+From 6c8d48cabea25c43d3ae3049a5ea7d4fc8f5b946 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 a393d15e0b6d9601226b57eba885697eb17d7f31 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 c4a49a75250e3..27b570678c9fc 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -990,7 +990,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 f6d4369298f048af98d0eebf680765d032579777 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 56b6808c3e4a9..b7a9e5edd566f 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 862c6a63ee883f3fa31fd9d6efb1fe85abfa75d4 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 bea0e32c195d4..56b6808c3e4a9 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 27c664c8ed642269e7d28a2cb01b1cbce6594636 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Mar 2023 00:33:07 +0100
+Subject: i3c: Make i3c_master_unregister() return void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 0f74f8b6675cc36d689abb4d9b3d75ab4049b7d7 ]
+
+The function returned zero unconditionally. Switch the return type to void
+and simplify the callers accordingly.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/r/20230318233311.265186-2-u.kleine-koenig@pengutronix.de
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 25bc99be5fe5 ("i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable counter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 6 +-----
+ drivers/i3c/master/dw-i3c-master.c | 5 +----
+ drivers/i3c/master/i3c-master-cdns.c | 5 +----
+ drivers/i3c/master/mipi-i3c-hci/core.c | 4 +++-
+ drivers/i3c/master/svc-i3c-master.c | 5 +----
+ include/linux/i3c/master.h | 2 +-
+ 6 files changed, 8 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index 2263bc066108f..c8aa0d27143cc 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -2696,17 +2696,13 @@ EXPORT_SYMBOL_GPL(i3c_master_register);
+ * @master: master used to send frames on the bus
+ *
+ * Basically undo everything done in i3c_master_register().
+- *
+- * Return: 0 in case of success, a negative error code otherwise.
+ */
+-int i3c_master_unregister(struct i3c_master_controller *master)
++void i3c_master_unregister(struct i3c_master_controller *master)
+ {
+ i3c_master_i2c_adapter_cleanup(master);
+ i3c_master_unregister_i3c_devs(master);
+ i3c_master_bus_cleanup(master);
+ device_unregister(&master->dev);
+-
+- return 0;
+ }
+ EXPORT_SYMBOL_GPL(i3c_master_unregister);
+
+diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
+index 51a8608203de7..b72f6dce18b48 100644
+--- a/drivers/i3c/master/dw-i3c-master.c
++++ b/drivers/i3c/master/dw-i3c-master.c
+@@ -1184,11 +1184,8 @@ static int dw_i3c_probe(struct platform_device *pdev)
+ static int dw_i3c_remove(struct platform_device *pdev)
+ {
+ struct dw_i3c_master *master = platform_get_drvdata(pdev);
+- int ret;
+
+- ret = i3c_master_unregister(&master->base);
+- if (ret)
+- return ret;
++ i3c_master_unregister(&master->base);
+
+ reset_control_assert(master->core_rst);
+
+diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
+index b9cfda6ae9ae5..35b90bb686ad3 100644
+--- a/drivers/i3c/master/i3c-master-cdns.c
++++ b/drivers/i3c/master/i3c-master-cdns.c
+@@ -1666,11 +1666,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
+ static int cdns_i3c_master_remove(struct platform_device *pdev)
+ {
+ struct cdns_i3c_master *master = platform_get_drvdata(pdev);
+- int ret;
+
+- ret = i3c_master_unregister(&master->base);
+- if (ret)
+- return ret;
++ i3c_master_unregister(&master->base);
+
+ clk_disable_unprepare(master->sysclk);
+ clk_disable_unprepare(master->pclk);
+diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
+index 6aef5ce43cc1f..f9bc58366a721 100644
+--- a/drivers/i3c/master/mipi-i3c-hci/core.c
++++ b/drivers/i3c/master/mipi-i3c-hci/core.c
+@@ -769,7 +769,9 @@ static int i3c_hci_remove(struct platform_device *pdev)
+ {
+ struct i3c_hci *hci = platform_get_drvdata(pdev);
+
+- return i3c_master_unregister(&hci->master);
++ i3c_master_unregister(&hci->master);
++
++ return 0;
+ }
+
+ static const __maybe_unused struct of_device_id i3c_hci_of_match[] = {
+diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
+index eca50705e9ce8..77bb7c0468250 100644
+--- a/drivers/i3c/master/svc-i3c-master.c
++++ b/drivers/i3c/master/svc-i3c-master.c
+@@ -1651,11 +1651,8 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
+ static int svc_i3c_master_remove(struct platform_device *pdev)
+ {
+ struct svc_i3c_master *master = platform_get_drvdata(pdev);
+- int ret;
+
+- ret = i3c_master_unregister(&master->base);
+- if (ret)
+- return ret;
++ i3c_master_unregister(&master->base);
+
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
+index 604a126b78c83..4b7bb43bf4307 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -541,7 +541,7 @@ int i3c_master_register(struct i3c_master_controller *master,
+ struct device *parent,
+ const struct i3c_master_controller_ops *ops,
+ bool secondary);
+-int i3c_master_unregister(struct i3c_master_controller *master);
++void i3c_master_unregister(struct i3c_master_controller *master);
+
+ /**
+ * i3c_dev_get_master_data() - get master private data attached to an I3C
+--
+2.43.0
+
--- /dev/null
+From 3367a0177f82ecfe298332c746bb32dce390ca69 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Dec 2023 17:25:27 -0500
+Subject: i3c: master: add enable(disable) hot join in sys entry
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 317bacf960a4879af22d12175f47d284930b3273 ]
+
+Add hotjoin entry in sys file system allow user enable/disable hotjoin
+feature.
+
+Add (*enable(disable)_hotjoin)() to i3c_master_controller_ops.
+Add api i3c_master_enable(disable)_hotjoin();
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20231201222532.2431484-2-Frank.Li@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 25bc99be5fe5 ("i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable counter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 83 ++++++++++++++++++++++++++++++++++++++
+ include/linux/i3c/master.h | 5 +++
+ 2 files changed, 88 insertions(+)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index c8aa0d27143cc..f5a289a39b1a2 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -514,6 +514,88 @@ static ssize_t i2c_scl_frequency_show(struct device *dev,
+ }
+ static DEVICE_ATTR_RO(i2c_scl_frequency);
+
++static int i3c_set_hotjoin(struct i3c_master_controller *master, bool enable)
++{
++ int ret;
++
++ if (!master || !master->ops)
++ return -EINVAL;
++
++ if (!master->ops->enable_hotjoin || !master->ops->disable_hotjoin)
++ return -EINVAL;
++
++ i3c_bus_normaluse_lock(&master->bus);
++
++ if (enable)
++ ret = master->ops->enable_hotjoin(master);
++ else
++ ret = master->ops->disable_hotjoin(master);
++
++ master->hotjoin = enable;
++
++ i3c_bus_normaluse_unlock(&master->bus);
++
++ return ret;
++}
++
++static ssize_t hotjoin_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
++ int ret;
++ bool res;
++
++ if (!i3cbus->cur_master)
++ return -EINVAL;
++
++ if (kstrtobool(buf, &res))
++ return -EINVAL;
++
++ ret = i3c_set_hotjoin(i3cbus->cur_master->common.master, res);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++/*
++ * i3c_master_enable_hotjoin - Enable hotjoin
++ * @master: I3C master object
++ *
++ * Return: a 0 in case of success, an negative error code otherwise.
++ */
++int i3c_master_enable_hotjoin(struct i3c_master_controller *master)
++{
++ return i3c_set_hotjoin(master, true);
++}
++EXPORT_SYMBOL_GPL(i3c_master_enable_hotjoin);
++
++/*
++ * i3c_master_disable_hotjoin - Disable hotjoin
++ * @master: I3C master object
++ *
++ * Return: a 0 in case of success, an negative error code otherwise.
++ */
++int i3c_master_disable_hotjoin(struct i3c_master_controller *master)
++{
++ return i3c_set_hotjoin(master, false);
++}
++EXPORT_SYMBOL_GPL(i3c_master_disable_hotjoin);
++
++static ssize_t hotjoin_show(struct device *dev, struct device_attribute *da, char *buf)
++{
++ struct i3c_bus *i3cbus = dev_to_i3cbus(dev);
++ ssize_t ret;
++
++ i3c_bus_normaluse_lock(i3cbus);
++ ret = sysfs_emit(buf, "%d\n", i3cbus->cur_master->common.master->hotjoin);
++ i3c_bus_normaluse_unlock(i3cbus);
++
++ return ret;
++}
++
++static DEVICE_ATTR_RW(hotjoin);
++
+ static struct attribute *i3c_masterdev_attrs[] = {
+ &dev_attr_mode.attr,
+ &dev_attr_current_master.attr,
+@@ -524,6 +606,7 @@ static struct attribute *i3c_masterdev_attrs[] = {
+ &dev_attr_pid.attr,
+ &dev_attr_dynamic_address.attr,
+ &dev_attr_hdrcap.attr,
++ &dev_attr_hotjoin.attr,
+ NULL,
+ };
+ ATTRIBUTE_GROUPS(i3c_masterdev);
+diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
+index 4b7bb43bf4307..b5a568caf4c80 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -451,6 +451,8 @@ struct i3c_master_controller_ops {
+ int (*disable_ibi)(struct i3c_dev_desc *dev);
+ void (*recycle_ibi_slot)(struct i3c_dev_desc *dev,
+ struct i3c_ibi_slot *slot);
++ int (*enable_hotjoin)(struct i3c_master_controller *master);
++ int (*disable_hotjoin)(struct i3c_master_controller *master);
+ };
+
+ /**
+@@ -486,6 +488,7 @@ struct i3c_master_controller {
+ const struct i3c_master_controller_ops *ops;
+ unsigned int secondary : 1;
+ unsigned int init_done : 1;
++ unsigned int hotjoin: 1;
+ struct {
+ struct list_head i3c;
+ struct list_head i2c;
+@@ -542,6 +545,8 @@ int i3c_master_register(struct i3c_master_controller *master,
+ const struct i3c_master_controller_ops *ops,
+ bool secondary);
+ void i3c_master_unregister(struct i3c_master_controller *master);
++int i3c_master_enable_hotjoin(struct i3c_master_controller *master);
++int i3c_master_disable_hotjoin(struct i3c_master_controller *master);
+
+ /**
+ * i3c_dev_get_master_data() - get master private data attached to an I3C
+--
+2.43.0
+
--- /dev/null
+From 612d5adb9282bbb26cc6255e8601629c297dd864 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 621881b6bf81c..a24264f275135 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -341,7 +341,7 @@ struct bus_type 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;
+@@ -352,11 +352,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;
+@@ -365,9 +371,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)
+@@ -379,13 +390,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;
+ }
+@@ -1860,9 +1902,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 706a583c45efc..2f731c6c16ea8 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -289,7 +289,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.
+ *
+@@ -302,9 +303,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 c06d408732a514053b4a604b91cc77d14d132d36 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 a24264f275135..41ecc0d898f0c 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -1491,16 +1491,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);
+@@ -1902,9 +1895,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);
+
+ /*
+@@ -2068,7 +2062,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 bc508b4541a2ce18a03f66ac4b72740c6c305637 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jan 2024 00:25:48 -0500
+Subject: i3c: master: fix kernel-doc check warning
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 34d946b723b53488ab39d8ac540ddf9db255317a ]
+
+Fix warning found by
+ 'scripts/kernel-doc -v -none include/linux/i3c/master.h'
+
+include/linux/i3c/master.h:457: warning: Function parameter or member 'enable_hotjoin' not described in 'i3c_master_controller_ops'
+include/linux/i3c/master.h:457: warning: Function parameter or member 'disable_hotjoin' not described in 'i3c_master_controller_ops'
+include/linux/i3c/master.h:499: warning: Function parameter or member 'hotjoin' not described in 'i3c_master_controller'
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/r/20240109052548.2128133-1-Frank.Li@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 25bc99be5fe5 ("i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable counter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/i3c/master.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
+index b5a568caf4c80..b6cbd00773a3c 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -425,6 +425,8 @@ struct i3c_bus {
+ * for a future IBI
+ * This method is mandatory only if ->request_ibi is not
+ * NULL.
++ * @enable_hotjoin: enable hot join event detect.
++ * @disable_hotjoin: disable hot join event detect.
+ */
+ struct i3c_master_controller_ops {
+ int (*bus_init)(struct i3c_master_controller *master);
+@@ -466,6 +468,7 @@ struct i3c_master_controller_ops {
+ * @ops: master operations. See &struct i3c_master_controller_ops
+ * @secondary: true if the master is a secondary master
+ * @init_done: true when the bus initialization is done
++ * @hotjoin: true if the master support hotjoin
+ * @boardinfo.i3c: list of I3C boardinfo objects
+ * @boardinfo.i2c: list of I2C boardinfo objects
+ * @boardinfo: board-level information attached to devices connected on the bus
+--
+2.43.0
+
--- /dev/null
+From a11955e7df9dbf331744da5f00506be4d2759e0b 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 103d3383e176d..621881b6bf81c 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -344,7 +344,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;
+@@ -358,7 +358,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 585b6c509802d..706a583c45efc 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -304,6 +304,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
+@@ -345,7 +347,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 ea809467cf2869be95d939ff2e0069ee2ffd17fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Sep 2024 13:16:25 +0800
+Subject: i3c: master: support to adjust first broadcast address speed
+
+From: Carlos Song <carlos.song@nxp.com>
+
+[ Upstream commit aef79e189ba2b32f78bd35daf2c0b41f3868a321 ]
+
+According to I3C spec 6.2 Timing Specification, the Open Drain High Period
+of SCL Clock timing for first broadcast address should be adjusted to 200ns
+at least. I3C device working as i2c device will see the broadcast to close
+its Spike Filter then change to work at I3C mode. After that I3C open drain
+SCL high level should be adjusted back.
+
+Signed-off-by: Carlos Song <carlos.song@nxp.com>
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20240910051626.4052552-1-carlos.song@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 25bc99be5fe5 ("i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable counter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master.c | 12 ++++++++++++
+ include/linux/i3c/master.h | 16 ++++++++++++++++
+ 2 files changed, 28 insertions(+)
+
+diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
+index f5a289a39b1a2..103d3383e176d 100644
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -1810,6 +1810,12 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+ goto err_bus_cleanup;
+ }
+
++ if (master->ops->set_speed) {
++ ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
++ if (ret)
++ goto err_bus_cleanup;
++ }
++
+ /*
+ * Reset all dynamic address that may have been assigned before
+ * (assigned by the bootloader for example).
+@@ -1818,6 +1824,12 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
+ if (ret && ret != I3C_ERROR_M2)
+ goto err_bus_cleanup;
+
++ if (master->ops->set_speed) {
++ master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED);
++ if (ret)
++ goto err_bus_cleanup;
++ }
++
+ /* Disable all slave events before starting DAA. */
+ ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
+ I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
+diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
+index b6cbd00773a3c..585b6c509802d 100644
+--- a/include/linux/i3c/master.h
++++ b/include/linux/i3c/master.h
+@@ -268,6 +268,20 @@ enum i3c_bus_mode {
+ I3C_BUS_MODE_MIXED_SLOW,
+ };
+
++/**
++ * enum i3c_open_drain_speed - I3C open-drain speed
++ * @I3C_OPEN_DRAIN_SLOW_SPEED: Slow open-drain speed for sending the first
++ * broadcast address. The first broadcast address at this speed
++ * will be visible to all devices on the I3C bus. I3C devices
++ * working in I2C mode will turn off their spike filter when
++ * switching into I3C mode.
++ * @I3C_OPEN_DRAIN_NORMAL_SPEED: Normal open-drain speed in I3C bus mode.
++ */
++enum i3c_open_drain_speed {
++ I3C_OPEN_DRAIN_SLOW_SPEED,
++ I3C_OPEN_DRAIN_NORMAL_SPEED,
++};
++
+ /**
+ * enum i3c_addr_slot_status - I3C address slot status
+ * @I3C_ADDR_SLOT_FREE: address is free
+@@ -427,6 +441,7 @@ struct i3c_bus {
+ * NULL.
+ * @enable_hotjoin: enable hot join event detect.
+ * @disable_hotjoin: disable hot join event detect.
++ * @set_speed: adjust I3C open drain mode timing.
+ */
+ struct i3c_master_controller_ops {
+ int (*bus_init)(struct i3c_master_controller *master);
+@@ -455,6 +470,7 @@ struct i3c_master_controller_ops {
+ struct i3c_ibi_slot *slot);
+ int (*enable_hotjoin)(struct i3c_master_controller *master);
+ int (*disable_hotjoin)(struct i3c_master_controller *master);
++ int (*set_speed)(struct i3c_master_controller *master, enum i3c_open_drain_speed speed);
+ };
+
+ /**
+--
+2.43.0
+
--- /dev/null
+From 82c7f63ac2e7a94ad1fd7dffa0294c3948b58caa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Dec 2023 17:25:28 -0500
+Subject: i3c: master: svc: add hot join support
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 05b26c31a4859af9e75b7de77458e99358364fe1 ]
+
+Add hot join support for svc master controller. Disable hot join by
+default.
+User can use sysfs entry to enable hot join.
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20231201222532.2431484-3-Frank.Li@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 25bc99be5fe5 ("i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable counter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/svc-i3c-master.c | 61 +++++++++++++++++++++++++++--
+ 1 file changed, 57 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
+index 77bb7c0468250..807a9fe647b7c 100644
+--- a/drivers/i3c/master/svc-i3c-master.c
++++ b/drivers/i3c/master/svc-i3c-master.c
+@@ -128,6 +128,9 @@
+ /* This parameter depends on the implementation and may be tuned */
+ #define SVC_I3C_FIFO_SIZE 16
+
++#define SVC_I3C_EVENT_IBI BIT(0)
++#define SVC_I3C_EVENT_HOTJOIN BIT(1)
++
+ struct svc_i3c_cmd {
+ u8 addr;
+ bool rnw;
+@@ -171,6 +174,7 @@ struct svc_i3c_xfer {
+ * @ibi.tbq_slot: To be queued IBI slot
+ * @ibi.lock: IBI lock
+ * @lock: Transfer lock, protect between IBI work thread and callbacks from master
++ * @enabled_events: Bit masks for enable events (IBI, HotJoin).
+ */
+ struct svc_i3c_master {
+ struct i3c_master_controller base;
+@@ -199,6 +203,7 @@ struct svc_i3c_master {
+ spinlock_t lock;
+ } ibi;
+ struct mutex lock;
++ int enabled_events;
+ };
+
+ /**
+@@ -213,6 +218,11 @@ struct svc_i3c_i2c_dev_data {
+ struct i3c_generic_ibi_pool *ibi_pool;
+ };
+
++static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
++{
++ return !!(master->enabled_events & mask);
++}
++
+ static bool svc_i3c_master_error(struct svc_i3c_master *master)
+ {
+ u32 mstatus, merrwarn;
+@@ -432,13 +442,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
+ switch (ibitype) {
+ case SVC_I3C_MSTATUS_IBITYPE_IBI:
+ dev = svc_i3c_master_dev_from_addr(master, ibiaddr);
+- if (!dev)
++ if (!dev || !is_events_enabled(master, SVC_I3C_EVENT_IBI))
+ svc_i3c_master_nack_ibi(master);
+ else
+ svc_i3c_master_handle_ibi(master, dev);
+ break;
+ case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
+- svc_i3c_master_ack_ibi(master, false);
++ if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
++ svc_i3c_master_ack_ibi(master, false);
++ else
++ svc_i3c_master_nack_ibi(master);
+ break;
+ case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
+ svc_i3c_master_nack_ibi(master);
+@@ -475,7 +488,9 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
+ svc_i3c_master_emit_stop(master);
+ break;
+ case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
+- queue_work(master->base.wq, &master->hj_work);
++ svc_i3c_master_emit_stop(master);
++ if (is_events_enabled(master, SVC_I3C_EVENT_HOTJOIN))
++ queue_work(master->base.wq, &master->hj_work);
+ break;
+ case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
+ default:
+@@ -1475,6 +1490,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
+ return ret;
+ }
+
++ master->enabled_events |= SVC_I3C_EVENT_IBI;
+ svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
+
+ return i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
+@@ -1486,7 +1502,9 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
+ struct svc_i3c_master *master = to_svc_i3c_master(m);
+ int ret;
+
+- svc_i3c_master_disable_interrupts(master);
++ master->enabled_events &= ~SVC_I3C_EVENT_IBI;
++ if (!master->enabled_events)
++ svc_i3c_master_disable_interrupts(master);
+
+ ret = i3c_master_disec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
+
+@@ -1496,6 +1514,39 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
+ return ret;
+ }
+
++static int svc_i3c_master_enable_hotjoin(struct i3c_master_controller *m)
++{
++ struct svc_i3c_master *master = to_svc_i3c_master(m);
++ int ret;
++
++ ret = pm_runtime_resume_and_get(master->dev);
++ if (ret < 0) {
++ dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
++ return ret;
++ }
++
++ master->enabled_events |= SVC_I3C_EVENT_HOTJOIN;
++
++ svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
++
++ return 0;
++}
++
++static int svc_i3c_master_disable_hotjoin(struct i3c_master_controller *m)
++{
++ struct svc_i3c_master *master = to_svc_i3c_master(m);
++
++ master->enabled_events &= ~SVC_I3C_EVENT_HOTJOIN;
++
++ if (!master->enabled_events)
++ svc_i3c_master_disable_interrupts(master);
++
++ pm_runtime_mark_last_busy(master->dev);
++ pm_runtime_put_autosuspend(master->dev);
++
++ return 0;
++}
++
+ static void svc_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev,
+ struct i3c_ibi_slot *slot)
+ {
+@@ -1522,6 +1573,8 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
+ .recycle_ibi_slot = svc_i3c_master_recycle_ibi_slot,
+ .enable_ibi = svc_i3c_master_enable_ibi,
+ .disable_ibi = svc_i3c_master_disable_ibi,
++ .enable_hotjoin = svc_i3c_master_enable_hotjoin,
++ .disable_hotjoin = svc_i3c_master_disable_hotjoin,
+ };
+
+ static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)
+--
+2.43.0
+
--- /dev/null
+From 5cdaa81a2156869b5af26770f22fc3e3d373744b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Nov 2024 12:50:02 -0400
+Subject: i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable
+ counter
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 25bc99be5fe53853053ceeaa328068c49dc1e799 ]
+
+Fix issue where disabling IBI on one device disables the entire IBI
+interrupt. Modify bit 7:0 of enabled_events to serve as an IBI enable
+counter, ensuring that the system IBI interrupt is disabled only when all
+I3C devices have IBI disabled.
+
+Cc: stable@kernel.org
+Fixes: 7ff730ca458e ("i3c: master: svc: enable the interrupt in the enable ibi function")
+Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20241101165002.2479794-1-Frank.Li@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/svc-i3c-master.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
+index 3dc34b31767d9..8f0da6e2d9d82 100644
+--- a/drivers/i3c/master/svc-i3c-master.c
++++ b/drivers/i3c/master/svc-i3c-master.c
+@@ -128,8 +128,8 @@
+ /* This parameter depends on the implementation and may be tuned */
+ #define SVC_I3C_FIFO_SIZE 16
+
+-#define SVC_I3C_EVENT_IBI BIT(0)
+-#define SVC_I3C_EVENT_HOTJOIN BIT(1)
++#define SVC_I3C_EVENT_IBI GENMASK(7, 0)
++#define SVC_I3C_EVENT_HOTJOIN BIT(31)
+
+ struct svc_i3c_cmd {
+ u8 addr;
+@@ -204,7 +204,7 @@ struct svc_i3c_master {
+ spinlock_t lock;
+ } ibi;
+ struct mutex lock;
+- int enabled_events;
++ u32 enabled_events;
+ u32 mctrl_config;
+ };
+
+@@ -1541,7 +1541,7 @@ static int svc_i3c_master_enable_ibi(struct i3c_dev_desc *dev)
+ return ret;
+ }
+
+- master->enabled_events |= SVC_I3C_EVENT_IBI;
++ master->enabled_events++;
+ svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
+
+ return i3c_master_enec_locked(m, dev->info.dyn_addr, I3C_CCC_EVENT_SIR);
+@@ -1553,7 +1553,7 @@ static int svc_i3c_master_disable_ibi(struct i3c_dev_desc *dev)
+ struct svc_i3c_master *master = to_svc_i3c_master(m);
+ int ret;
+
+- master->enabled_events &= ~SVC_I3C_EVENT_IBI;
++ master->enabled_events--;
+ if (!master->enabled_events)
+ svc_i3c_master_disable_interrupts(master);
+
+--
+2.43.0
+
--- /dev/null
+From 35e05150523a3ad2b615d2c73ec2746d2c20c23b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Sep 2024 13:16:26 +0800
+Subject: i3c: master: svc: use slow speed for first broadcast address
+
+From: Carlos Song <carlos.song@nxp.com>
+
+[ Upstream commit 20ade67bb1645f5ce8f37fa79ddfebbc5b5b24ef ]
+
+I3C controller should support adjusting open drain timing for the first
+broadcast address to make I3C device working as a i2c device can see slow
+broadcast address to close its Spike Filter to change working at i3c mode.
+
+Signed-off-by: Carlos Song <carlos.song@nxp.com>
+Reviewed-by: Frank Li <frank.li@nxp.com>
+Link: https://lore.kernel.org/r/20240910051626.4052552-2-carlos.song@nxp.com
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Stable-dep-of: 25bc99be5fe5 ("i3c: master: svc: Modify enabled_events bit 7:0 to act as IBI enable counter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i3c/master/svc-i3c-master.c | 52 +++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
+index 807a9fe647b7c..3dc34b31767d9 100644
+--- a/drivers/i3c/master/svc-i3c-master.c
++++ b/drivers/i3c/master/svc-i3c-master.c
+@@ -175,6 +175,7 @@ struct svc_i3c_xfer {
+ * @ibi.lock: IBI lock
+ * @lock: Transfer lock, protect between IBI work thread and callbacks from master
+ * @enabled_events: Bit masks for enable events (IBI, HotJoin).
++ * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
+ */
+ struct svc_i3c_master {
+ struct i3c_master_controller base;
+@@ -204,6 +205,7 @@ struct svc_i3c_master {
+ } ibi;
+ struct mutex lock;
+ int enabled_events;
++ u32 mctrl_config;
+ };
+
+ /**
+@@ -521,6 +523,54 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
++static int svc_i3c_master_set_speed(struct i3c_master_controller *m,
++ enum i3c_open_drain_speed speed)
++{
++ struct svc_i3c_master *master = to_svc_i3c_master(m);
++ struct i3c_bus *bus = i3c_master_get_bus(&master->base);
++ u32 ppbaud, odbaud, odhpp, mconfig;
++ unsigned long fclk_rate;
++ int ret;
++
++ ret = pm_runtime_resume_and_get(master->dev);
++ if (ret < 0) {
++ dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
++ return ret;
++ }
++
++ switch (speed) {
++ case I3C_OPEN_DRAIN_SLOW_SPEED:
++ fclk_rate = clk_get_rate(master->fclk);
++ if (!fclk_rate) {
++ ret = -EINVAL;
++ goto rpm_out;
++ }
++ /*
++ * Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first
++ * broadcast address is visible to all I2C/I3C devices on the I3C bus.
++ * I3C device working as a I2C device will turn off its 50ns Spike
++ * Filter to change to I3C mode.
++ */
++ mconfig = master->mctrl_config;
++ ppbaud = FIELD_GET(GENMASK(11, 8), mconfig);
++ odhpp = 0;
++ odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1;
++ mconfig &= ~GENMASK(24, 16);
++ mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp);
++ writel(mconfig, master->regs + SVC_I3C_MCONFIG);
++ break;
++ case I3C_OPEN_DRAIN_NORMAL_SPEED:
++ writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
++ break;
++ }
++
++rpm_out:
++ pm_runtime_mark_last_busy(master->dev);
++ pm_runtime_put_autosuspend(master->dev);
++
++ return ret;
++}
++
+ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
+ {
+ struct svc_i3c_master *master = to_svc_i3c_master(m);
+@@ -603,6 +653,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
+ SVC_I3C_MCONFIG_I2CBAUD(i2cbaud);
+ writel(reg, master->regs + SVC_I3C_MCONFIG);
+
++ master->mctrl_config = reg;
+ /* Master core's registration */
+ ret = i3c_master_get_free_addr(m, 0);
+ if (ret < 0)
+@@ -1575,6 +1626,7 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
+ .disable_ibi = svc_i3c_master_disable_ibi,
+ .enable_hotjoin = svc_i3c_master_enable_hotjoin,
+ .disable_hotjoin = svc_i3c_master_disable_hotjoin,
++ .set_speed = svc_i3c_master_set_speed,
+ };
+
+ static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master)
+--
+2.43.0
+
--- /dev/null
+From 38d9bd3a27a58dce984273cac11f05d631b4f091 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 2e2caf559d00a..d53076210f3aa 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -665,6 +665,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 32a2fd3f638632b6d5480fb7c1e03ec64ec9fe01 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 9c969d90b4ef1cb8d3580085484f8c9ddf428e05 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 e937b4dd28be7..35ae40b35f555 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 f84892da959fe302e4e4b43aa3138fdde42e994b 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 4b531e8ae38ae..afe8a64dbdd41 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+@@ -195,6 +195,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 198ab9d97618c..9132e73e41829 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+@@ -1051,7 +1051,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 3787ca4fbcf8be380614dd28bf45c942219b1841 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 9984ebc62d787..74c121d7abc90 100644
+--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
++++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+@@ -623,7 +623,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 6cb5ccbbd03a4a7d1e1f29250efad4ec107f15a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Apr 2024 16:05:22 +0100
+Subject: KVM: arm64: Change kvm_handle_mmio_return() return polarity
+
+From: Fuad Tabba <tabba@google.com>
+
+[ Upstream commit cc81b6dfc3bc82c3a2600eefbd3823bdb2190197 ]
+
+Most exit handlers return <= 0 to indicate that the host needs to
+handle the exit. Make kvm_handle_mmio_return() consistent with
+the exit handlers in handle_exit(). This makes the code easier to
+reason about, and makes it easier to add other handlers in future
+patches.
+
+No functional change intended.
+
+Signed-off-by: Fuad Tabba <tabba@google.com>
+Acked-by: Oliver Upton <oliver.upton@linux.dev>
+Link: https://lore.kernel.org/r/20240423150538.2103045-15-tabba@google.com
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Stable-dep-of: e735a5da6442 ("KVM: arm64: Don't retire aborted MMIO instruction")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kvm/arm.c | 2 +-
+ arch/arm64/kvm/mmio.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
+index cf7e10587fb09..3a05f364b4b6d 100644
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -876,7 +876,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
+
+ if (run->exit_reason == KVM_EXIT_MMIO) {
+ ret = kvm_handle_mmio_return(vcpu);
+- if (ret)
++ if (ret <= 0)
+ return ret;
+ }
+
+diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
+index 3dd38a151d2a6..886ef30e12196 100644
+--- a/arch/arm64/kvm/mmio.c
++++ b/arch/arm64/kvm/mmio.c
+@@ -86,7 +86,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
+
+ /* Detect an already handled MMIO return */
+ if (unlikely(!vcpu->mmio_needed))
+- return 0;
++ return 1;
+
+ vcpu->mmio_needed = 0;
+
+@@ -117,7 +117,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
+ */
+ kvm_incr_pc(vcpu);
+
+- return 0;
++ return 1;
+ }
+
+ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
+--
+2.43.0
+
--- /dev/null
+From 1b218b73877e31daf4cf3d0b4833a05b7a52c4eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Oct 2024 20:31:03 +0000
+Subject: KVM: arm64: Don't retire aborted MMIO instruction
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+[ Upstream commit e735a5da64420a86be370b216c269b5dd8e830e2 ]
+
+Returning an abort to the guest for an unsupported MMIO access is a
+documented feature of the KVM UAPI. Nevertheless, it's clear that this
+plumbing has seen limited testing, since userspace can trivially cause a
+WARN in the MMIO return:
+
+ WARNING: CPU: 0 PID: 30558 at arch/arm64/include/asm/kvm_emulate.h:536 kvm_handle_mmio_return+0x46c/0x5c4 arch/arm64/include/asm/kvm_emulate.h:536
+ Call trace:
+ kvm_handle_mmio_return+0x46c/0x5c4 arch/arm64/include/asm/kvm_emulate.h:536
+ kvm_arch_vcpu_ioctl_run+0x98/0x15b4 arch/arm64/kvm/arm.c:1133
+ kvm_vcpu_ioctl+0x75c/0xa78 virt/kvm/kvm_main.c:4487
+ __do_sys_ioctl fs/ioctl.c:51 [inline]
+ __se_sys_ioctl fs/ioctl.c:893 [inline]
+ __arm64_sys_ioctl+0x14c/0x1c8 fs/ioctl.c:893
+ __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
+ invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
+ el0_svc_common+0x1e0/0x23c arch/arm64/kernel/syscall.c:132
+ do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
+ el0_svc+0x38/0x68 arch/arm64/kernel/entry-common.c:712
+ el0t_64_sync_handler+0x90/0xfc arch/arm64/kernel/entry-common.c:730
+ el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598
+
+The splat is complaining that KVM is advancing PC while an exception is
+pending, i.e. that KVM is retiring the MMIO instruction despite a
+pending synchronous external abort. Womp womp.
+
+Fix the glaring UAPI bug by skipping over all the MMIO emulation in
+case there is a pending synchronous exception. Note that while userspace
+is capable of pending an asynchronous exception (SError, IRQ, or FIQ),
+it is still safe to retire the MMIO instruction in this case as (1) they
+are by definition asynchronous, and (2) KVM relies on hardware support
+for pending/delivering these exceptions instead of the software state
+machine for advancing PC.
+
+Cc: stable@vger.kernel.org
+Fixes: da345174ceca ("KVM: arm/arm64: Allow user injection of external data aborts")
+Reported-by: Alexander Potapenko <glider@google.com>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20241025203106.3529261-2-oliver.upton@linux.dev
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kvm/mmio.c | 32 ++++++++++++++++++++++++++++++--
+ 1 file changed, 30 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
+index 886ef30e12196..2aa503ff742ee 100644
+--- a/arch/arm64/kvm/mmio.c
++++ b/arch/arm64/kvm/mmio.c
+@@ -72,6 +72,31 @@ unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
+ return data;
+ }
+
++static bool kvm_pending_sync_exception(struct kvm_vcpu *vcpu)
++{
++ if (!vcpu_get_flag(vcpu, PENDING_EXCEPTION))
++ return false;
++
++ if (vcpu_el1_is_32bit(vcpu)) {
++ switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
++ case unpack_vcpu_flag(EXCEPT_AA32_UND):
++ case unpack_vcpu_flag(EXCEPT_AA32_IABT):
++ case unpack_vcpu_flag(EXCEPT_AA32_DABT):
++ return true;
++ default:
++ return false;
++ }
++ } else {
++ switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
++ case unpack_vcpu_flag(EXCEPT_AA64_EL1_SYNC):
++ case unpack_vcpu_flag(EXCEPT_AA64_EL2_SYNC):
++ return true;
++ default:
++ return false;
++ }
++ }
++}
++
+ /**
+ * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ * or in-kernel IO emulation
+@@ -84,8 +109,11 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
+ unsigned int len;
+ int mask;
+
+- /* Detect an already handled MMIO return */
+- if (unlikely(!vcpu->mmio_needed))
++ /*
++ * Detect if the MMIO return was already handled or if userspace aborted
++ * the MMIO access.
++ */
++ if (unlikely(!vcpu->mmio_needed || kvm_pending_sync_exception(vcpu)))
+ return 1;
+
+ vcpu->mmio_needed = 0;
+--
+2.43.0
+
--- /dev/null
+From 4034d08da67399cccd95a763c593c25bf429c95c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Sep 2024 01:20:52 +0200
+Subject: leds: flash: mt6360: Fix device_for_each_child_node() refcounting in
+ error paths
+
+From: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+
+[ Upstream commit 73b03b27736e440e3009fe1319cbc82d2cd1290c ]
+
+The device_for_each_child_node() macro requires explicit calls to
+fwnode_handle_put() upon early exits to avoid memory leaks, and in
+this case the error paths are handled after jumping to
+'out_flash_realease', which misses that required call to
+to decrement the refcount of the child node.
+
+A more elegant and robust solution is using the scoped variant of the
+loop, which automatically handles such early exits.
+
+Fix the child node refcounting in the error paths by using
+device_for_each_child_node_scoped().
+
+Cc: stable@vger.kernel.org
+Fixes: 679f8652064b ("leds: Add mt6360 driver")
+Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+Link: https://lore.kernel.org/r/20240927-leds_device_for_each_child_node_scoped-v1-1-95c0614b38c8@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/flash/leds-mt6360.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
+index 2fab335a64252..71c1ddd71f8ea 100644
+--- a/drivers/leds/flash/leds-mt6360.c
++++ b/drivers/leds/flash/leds-mt6360.c
+@@ -797,7 +797,6 @@ static void mt6360_v4l2_flash_release(struct mt6360_priv *priv)
+ static int mt6360_led_probe(struct platform_device *pdev)
+ {
+ struct mt6360_priv *priv;
+- struct fwnode_handle *child;
+ size_t count;
+ int i = 0, ret;
+
+@@ -824,7 +823,7 @@ static int mt6360_led_probe(struct platform_device *pdev)
+ return -ENODEV;
+ }
+
+- device_for_each_child_node(&pdev->dev, child) {
++ device_for_each_child_node_scoped(&pdev->dev, child) {
+ struct mt6360_led *led = priv->leds + i;
+ struct led_init_data init_data = { .fwnode = child, };
+ u32 reg, led_color;
+--
+2.43.0
+
--- /dev/null
+From e31a7087f3791f30c70ee1e3d8d54a827e91b639 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 0323ab5023c69..2790f3964d6bd 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -588,6 +588,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 75c3916466653203f227d69d3f6a06e17210f93c 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 5da0c83a3ee8f..5ae3ff6ffb7e9 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -2774,10 +2774,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 3a3733cae01e8002567a5520adb6f29bed2c5242 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 907ad6ffe7275..407556334495d 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
+@@ -4,6 +4,7 @@
+ #include <net/fib_notifier.h>
+ #include <net/nexthop.h>
+ #include "tc_tun_encap.h"
++#include "fs_core.h"
+ #include "en_tc.h"
+ #include "tc_tun.h"
+ #include "rep/tc.h"
+@@ -23,10 +24,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 20dc3b3770a54248f80b6c2127adb14737eb0b11 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 bded2b2759d86080c3e1c60e983cd52ab216fcfa 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 10e6ec0f94981..b4a7952c5d7da 100644
+--- a/net/sched/cls_flower.c
++++ b/net/sched/cls_flower.c
+@@ -1279,7 +1279,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)
+@@ -1308,9 +1307,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) {
+@@ -1319,10 +1318,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 fcaec2ec3fb3597cf776038f60624875aa2a78c7 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 277ad11f4d613..c4c91b55e98b0 100644
+--- a/net/sched/sch_tbf.c
++++ b/net/sched/sch_tbf.c
+@@ -207,7 +207,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);
+@@ -218,21 +218,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 70afe6c51b4ae3223d99eaa4934a99f028028b97 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 e86db21fef6e5..868e722aef064 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1860,6 +1860,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);
+@@ -2352,6 +2353,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 ba4588c09629d6a148c1c811d0fa347710cfad31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 03:04:28 -0800
+Subject: net-timestamp: make sk_tskey more predictable in error path
+
+From: Vadim Fedorenko <vadfed@meta.com>
+
+[ Upstream commit 488b6d91b07112eaaaa4454332c1480894d4e06e ]
+
+When SOF_TIMESTAMPING_OPT_ID is used to ambiguate timestamped datagrams,
+the sk_tskey can become unpredictable in case of any error happened
+during sendmsg(). Move increment later in the code and make decrement of
+sk_tskey in error path. This solution is still racy in case of multiple
+threads doing snedmsg() over the very same socket in parallel, but still
+makes error path much more predictable.
+
+Fixes: 09c2d251b707 ("net-timestamp: add key to disambiguate concurrent datagrams")
+Reported-by: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://lore.kernel.org/r/20240213110428.1681540-1-vadfed@meta.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 3301ab7d5aeb ("net/ipv6: release expired exception dst cached in socket")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_output.c | 13 ++++++++-----
+ net/ipv6/ip6_output.c | 13 ++++++++-----
+ 2 files changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index a6d460aaee794..c82107bbd9810 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -980,8 +980,8 @@ static int __ip_append_data(struct sock *sk,
+ unsigned int maxfraglen, fragheaderlen, maxnonfragsize;
+ int csummode = CHECKSUM_NONE;
+ struct rtable *rt = (struct rtable *)cork->dst;
++ bool paged, hold_tskey, extra_uref = false;
+ unsigned int wmem_alloc_delta = 0;
+- bool paged, extra_uref = false;
+ u32 tskey = 0;
+
+ skb = skb_peek_tail(queue);
+@@ -990,10 +990,6 @@ static int __ip_append_data(struct sock *sk,
+ mtu = cork->gso_size ? IP_MAX_MTU : cork->fragsize;
+ paged = !!cork->gso_size;
+
+- if (cork->tx_flags & SKBTX_ANY_TSTAMP &&
+- READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID)
+- tskey = atomic_inc_return(&sk->sk_tskey) - 1;
+-
+ hh_len = LL_RESERVED_SPACE(rt->dst.dev);
+
+ fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
+@@ -1051,6 +1047,11 @@ static int __ip_append_data(struct sock *sk,
+
+ cork->length += length;
+
++ hold_tskey = cork->tx_flags & SKBTX_ANY_TSTAMP &&
++ READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID;
++ if (hold_tskey)
++ tskey = atomic_inc_return(&sk->sk_tskey) - 1;
++
+ /* So, what's going on in the loop below?
+ *
+ * We use calculated fragment length to generate chained skb,
+@@ -1255,6 +1256,8 @@ static int __ip_append_data(struct sock *sk,
+ cork->length -= length;
+ IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
+ refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
++ if (hold_tskey)
++ atomic_dec(&sk->sk_tskey);
+ return err;
+ }
+
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index f2227e662d1cf..4082470803615 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1499,11 +1499,11 @@ static int __ip6_append_data(struct sock *sk,
+ bool zc = false;
+ u32 tskey = 0;
+ struct rt6_info *rt = (struct rt6_info *)cork->dst;
++ bool paged, hold_tskey, extra_uref = false;
+ struct ipv6_txoptions *opt = v6_cork->opt;
+ int csummode = CHECKSUM_NONE;
+ unsigned int maxnonfragsize, headersize;
+ unsigned int wmem_alloc_delta = 0;
+- bool paged, extra_uref = false;
+
+ skb = skb_peek_tail(queue);
+ if (!skb) {
+@@ -1515,10 +1515,6 @@ static int __ip6_append_data(struct sock *sk,
+ mtu = cork->gso_size ? IP6_MAX_MTU : cork->fragsize;
+ orig_mtu = mtu;
+
+- if (cork->tx_flags & SKBTX_ANY_TSTAMP &&
+- READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID)
+- tskey = atomic_inc_return(&sk->sk_tskey) - 1;
+-
+ hh_len = LL_RESERVED_SPACE(rt->dst.dev);
+
+ fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
+@@ -1606,6 +1602,11 @@ static int __ip6_append_data(struct sock *sk,
+ }
+ }
+
++ hold_tskey = cork->tx_flags & SKBTX_ANY_TSTAMP &&
++ READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID;
++ if (hold_tskey)
++ tskey = atomic_inc_return(&sk->sk_tskey) - 1;
++
+ /*
+ * Let's try using as much space as possible.
+ * Use MTU if total length of the message fits into the MTU.
+@@ -1844,6 +1845,8 @@ static int __ip6_append_data(struct sock *sk,
+ cork->length -= length;
+ IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
+ refcount_add(wmem_alloc_delta, &sk->sk_wmem_alloc);
++ if (hold_tskey)
++ atomic_dec(&sk->sk_tskey);
+ return err;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From c45105ae1e5ae2395f28feffbe5074ad75868d60 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 0b24b638bfd2e..56215fb63b645 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 26ef13e8b0473e051d646e732f0da4b77809066c 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 1fd3b413350dc..5c4209b49bda7 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -24,10 +24,12 @@
+ struct nft_rhash {
+ struct rhashtable ht;
+ struct delayed_work gc_work;
++ u32 wq_gc_seq;
+ };
+
+ struct nft_rhash_elem {
+ struct rhash_head node;
++ u32 wq_gc_seq;
+ struct nft_set_ext ext;
+ };
+
+@@ -339,6 +341,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);
+
+@@ -356,6 +362,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;
+
+@@ -372,6 +386,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 c04a43c11479115cf832226757a4584ec3c57384 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 4148df6d6a471..2d33674e9e5e9 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 5b658c5449f247bb128ff1b7abd3d29081e6a625 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 211bfa2a2ac04..c2c10a536cc68 100644
+--- a/net/netfilter/xt_LED.c
++++ b/net/netfilter/xt_LED.c
+@@ -97,7 +97,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 dc1a0747f25c931ab99f216fe2e2474ed89719c9 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 8e68a85996f7d..99213d931f63f 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) {
+@@ -688,7 +689,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();
+ }
+
+@@ -699,7 +700,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;
+ }
+@@ -721,7 +722,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);
+ }
+
+@@ -754,7 +755,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,
+@@ -798,8 +799,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;
+
+@@ -814,7 +814,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;
+@@ -845,17 +845,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 = {
+@@ -871,7 +875,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];
+@@ -882,7 +886,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];
+@@ -890,8 +894,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)
+ {
+@@ -904,8 +909,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)
+ {
+@@ -918,7 +924,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
+@@ -932,7 +939,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++;
+@@ -943,9 +950,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);
+@@ -957,13 +965,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)
+@@ -972,7 +981,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;
+@@ -982,17 +991,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.
+ */
+@@ -1003,13 +1013,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;
+ }
+
+@@ -1031,41 +1041,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 22f156896bbf977e00bdc352addf5fa72e60fdb3 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 99213d931f63f..eca9de85b0a76 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:
+@@ -834,10 +832,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;
+@@ -944,9 +940,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;
+ }
+
+@@ -960,8 +955,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();
+@@ -977,13 +971,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();
+ }
+@@ -1007,15 +999,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;
+ }
+@@ -1064,9 +1054,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 528b3e759c7b9e18f3f69e24f9095e960cec83d8 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 eca9de85b0a76..ef758aafdfd54 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 57103d282a874ed716f489b7b336b8d833ba43b2 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 477cb08062bc5..0222f8e460810 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)
+ {
+@@ -698,7 +704,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)
+@@ -739,13 +745,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.
+@@ -753,6 +758,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) {
+@@ -761,7 +767,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);
+@@ -774,15 +780,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,
+@@ -803,7 +809,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 */
+@@ -924,7 +930,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;
+@@ -971,7 +977,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;
+@@ -1022,6 +1028,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);
+
+@@ -1062,7 +1069,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 19e88efd3e57092a9811244c233570a4769231d6 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 0dba1179d81d2..8e68a85996f7d 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 322d8eef5fadffa49c0fcf8536bcb3d74d0843c1 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 0222f8e460810..6c5f684328c82 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 c52eeba3eda258130c696e0bd59c71bcd3bd86d8 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 6c5f684328c82..6d87f9889b039 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);
+ }
+
+ /*
+@@ -683,11 +680,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();
+@@ -697,26 +694,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;
+@@ -734,17 +730,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;
+@@ -780,7 +775,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);
+
+@@ -788,26 +783,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;
+@@ -815,26 +810,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;
+ }
+
+@@ -939,7 +934,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",
+@@ -958,7 +953,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 {
+@@ -977,7 +972,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);
+ }
+@@ -986,7 +981,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;
+@@ -1003,9 +998,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() */
+@@ -1035,10 +1030,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;
+
+ /*
+@@ -1059,7 +1054,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");
+@@ -1074,7 +1069,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 933db59179cf3c849249b1c26eef90e47f25da3e 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 ef758aafdfd54..477cb08062bc5 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 21e29d3ffe7a96085e3948dbc218e1730e5f8e99 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 6d87f9889b039..d1b7a3909de1d 100644
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -791,7 +791,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 4a8985fd682f4f7d3f2d93279fabcbf8addb67bb 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 8d2dd214ec682..0dba1179d81d2 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 67e112068a2bffdbc344d49f8933c872c3689626 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Nov 2024 08:53:09 +0800
+Subject: PCI: endpoint: Clear secondary (not primary) EPC in
+ pci_epc_remove_epf()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zijun Hu <quic_zijuhu@quicinc.com>
+
+[ Upstream commit 688d2eb4c6fcfdcdaed0592f9df9196573ff5ce2 ]
+
+In addition to a primary endpoint controller, an endpoint function may be
+associated with a secondary endpoint controller, epf->sec_epc, to provide
+NTB (non-transparent bridge) functionality.
+
+Previously, pci_epc_remove_epf() incorrectly cleared epf->epc instead of
+epf->sec_epc when removing from the secondary endpoint controller.
+
+Extend the epc->list_lock coverage and clear either epf->epc or
+epf->sec_epc as indicated.
+
+Link: https://lore.kernel.org/r/20241107-epc_rfc-v2-2-da5b6a99a66f@quicinc.com
+Fixes: 63840ff53223 ("PCI: endpoint: Add support to associate secondary EPC with EPF")
+Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+[mani: reworded subject and description]
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+[bhelgaas: commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/endpoint/pci-epc-core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
+index 6cce430d431b1..f5a5ec80d1943 100644
+--- a/drivers/pci/endpoint/pci-epc-core.c
++++ b/drivers/pci/endpoint/pci-epc-core.c
+@@ -664,18 +664,18 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
+ if (!epc || IS_ERR(epc) || !epf)
+ return;
+
++ mutex_lock(&epc->list_lock);
+ if (type == PRIMARY_INTERFACE) {
+ func_no = epf->func_no;
+ list = &epf->list;
++ epf->epc = NULL;
+ } else {
+ func_no = epf->sec_epc_func_no;
+ list = &epf->sec_epc_list;
++ epf->sec_epc = NULL;
+ }
+-
+- mutex_lock(&epc->list_lock);
+ clear_bit(func_no, &epc->function_num_map);
+ list_del(list);
+- epf->epc = NULL;
+ mutex_unlock(&epc->list_lock);
+ }
+ EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
+--
+2.43.0
+
--- /dev/null
+From 56121f3580a0240030f74947b95bebd37adddf0e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Jan 2023 12:41:56 +0530
+Subject: PCI: endpoint: Use a separate lock for protecting epc->pci_epf list
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+[ Upstream commit d6dd5bafaabf98a99a76227ab8dc9a89e76a198f ]
+
+The EPC controller maintains a list of EPF drivers added to it. For
+protecting this list against the concurrent accesses, the epc->lock
+(used for protecting epc_ops) has been used so far. Since there were
+no users trying to use epc_ops and modify the pci_epf list simultaneously,
+this was not an issue.
+
+But with the addition of callback mechanism for passing the events, this
+will be a problem. Because the pci_epf list needs to be iterated first
+for getting hold of the EPF driver and then the relevant event specific
+callback needs to be called for the driver.
+
+If the same epc->lock is used, then it will result in a deadlock scenario.
+
+For instance,
+
+...
+ mutex_lock(&epc->lock);
+ list_for_each_entry(epf, &epc->pci_epf, list) {
+ epf->event_ops->core_init(epf);
+ |
+ |-> pci_epc_set_bar();
+ |
+ |-> mutex_lock(&epc->lock) # DEADLOCK
+...
+
+So to fix this issue, use a separate lock called "list_lock" for
+protecting the pci_epf list against the concurrent accesses. This lock
+will also be used by the callback mechanism.
+
+Link: https://lore.kernel.org/linux-pci/20230124071158.5503-4-manivannan.sadhasivam@linaro.org
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
+Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
+Stable-dep-of: 688d2eb4c6fc ("PCI: endpoint: Clear secondary (not primary) EPC in pci_epc_remove_epf()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/endpoint/pci-epc-core.c | 9 +++++----
+ include/linux/pci-epc.h | 2 ++
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
+index 3bc9273d0a082..6cce430d431b1 100644
+--- a/drivers/pci/endpoint/pci-epc-core.c
++++ b/drivers/pci/endpoint/pci-epc-core.c
+@@ -613,7 +613,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
+ if (type == SECONDARY_INTERFACE && epf->sec_epc)
+ return -EBUSY;
+
+- mutex_lock(&epc->lock);
++ mutex_lock(&epc->list_lock);
+ func_no = find_first_zero_bit(&epc->function_num_map,
+ BITS_PER_LONG);
+ if (func_no >= BITS_PER_LONG) {
+@@ -640,7 +640,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf,
+
+ list_add_tail(list, &epc->pci_epf);
+ ret:
+- mutex_unlock(&epc->lock);
++ mutex_unlock(&epc->list_lock);
+
+ return ret;
+ }
+@@ -672,11 +672,11 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
+ list = &epf->sec_epc_list;
+ }
+
+- mutex_lock(&epc->lock);
++ mutex_lock(&epc->list_lock);
+ clear_bit(func_no, &epc->function_num_map);
+ list_del(list);
+ epf->epc = NULL;
+- mutex_unlock(&epc->lock);
++ mutex_unlock(&epc->list_lock);
+ }
+ EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
+
+@@ -773,6 +773,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
+ }
+
+ mutex_init(&epc->lock);
++ mutex_init(&epc->list_lock);
+ INIT_LIST_HEAD(&epc->pci_epf);
+ ATOMIC_INIT_NOTIFIER_HEAD(&epc->notifier);
+
+diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
+index a48778e1a4ee3..fe729dfe509b8 100644
+--- a/include/linux/pci-epc.h
++++ b/include/linux/pci-epc.h
+@@ -122,6 +122,7 @@ struct pci_epc_mem {
+ * struct pci_epc - represents the PCI EPC device
+ * @dev: PCI EPC device
+ * @pci_epf: list of endpoint functions present in this EPC device
++ * list_lock: Mutex for protecting pci_epf list
+ * @ops: function pointers for performing endpoint operations
+ * @windows: array of address space of the endpoint controller
+ * @mem: first window of the endpoint controller, which corresponds to
+@@ -139,6 +140,7 @@ struct pci_epc_mem {
+ struct pci_epc {
+ struct device dev;
+ struct list_head pci_epf;
++ struct mutex list_lock;
+ const struct pci_epc_ops *ops;
+ struct pci_epc_mem **windows;
+ struct pci_epc_mem *mem;
+--
+2.43.0
+
--- /dev/null
+From c03107cca7507b6ba89e59398dd1b1689baf8136 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Oct 2024 11:41:37 -0700
+Subject: powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with
+ clang
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit d677ce521334d8f1f327cafc8b1b7854b0833158 ]
+
+Under certain conditions, the 64-bit '-mstack-protector-guard' flags may
+end up in the 32-bit vDSO flags, resulting in build failures due to the
+structure of clang's argument parsing of the stack protector options,
+which validates the arguments of the stack protector guard flags
+unconditionally in the frontend, choking on the 64-bit values when
+targeting 32-bit:
+
+ clang: error: invalid value 'r13' in 'mstack-protector-guard-reg=', expected one of: r2
+ clang: error: invalid value 'r13' in 'mstack-protector-guard-reg=', expected one of: r2
+ make[3]: *** [arch/powerpc/kernel/vdso/Makefile:85: arch/powerpc/kernel/vdso/vgettimeofday-32.o] Error 1
+ make[3]: *** [arch/powerpc/kernel/vdso/Makefile:87: arch/powerpc/kernel/vdso/vgetrandom-32.o] Error 1
+
+Remove these flags by adding them to the CC32FLAGSREMOVE variable, which
+already handles situations similar to this. Additionally, reformat and
+align a comment better for the expanding CONFIG_CC_IS_CLANG block.
+
+Cc: stable@vger.kernel.org # v6.1+
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://patch.msgid.link/20241030-powerpc-vdso-drop-stackp-flags-clang-v1-1-d95e7376d29c@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index c12be984dccdf..ee9fd65dd8cb3 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -48,10 +48,14 @@ ldflags-y += $(filter-out $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
+
+ CC32FLAGS := -m32
+ CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
+- # This flag is supported by clang for 64-bit but not 32-bit so it will cause
+- # an unused command line flag warning for this file.
+ ifdef CONFIG_CC_IS_CLANG
++# This flag is supported by clang for 64-bit but not 32-bit so it will cause
++# an unused command line flag warning for this file.
+ CC32FLAGSREMOVE += -fno-stack-clash-protection
++# -mstack-protector-guard values from the 64-bit build are not valid for the
++# 32-bit one. clang validates the values passed to these arguments during
++# parsing, even when -fno-stack-protector is passed afterwards.
++CC32FLAGSREMOVE += -mstack-protector-guard%
+ endif
+ LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
+ AS32FLAGS := -D__VDSO32__
+--
+2.43.0
+
--- /dev/null
+From 71230a744a26de5d1bc5f2f738ec9be0599068a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jan 2023 20:05:04 -0700
+Subject: powerpc/vdso: Improve linker flags
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit f0a42fbab447ed9f55bbd99751183e71f3a1f6ec ]
+
+When clang's -Qunused-arguments is dropped from KBUILD_CPPFLAGS, there
+are several warnings in the PowerPC vDSO:
+
+ clang-16: error: -Wl,-soname=linux-vdso32.so.1: 'linker' input unused [-Werror,-Wunused-command-line-argument]
+ clang-16: error: -Wl,--hash-style=both: 'linker' input unused [-Werror,-Wunused-command-line-argument]
+ clang-16: error: argument unused during compilation: '-shared' [-Werror,-Wunused-command-line-argument]
+
+ clang-16: error: argument unused during compilation: '-nostdinc' [-Werror,-Wunused-command-line-argument]
+ clang-16: error: argument unused during compilation: '-Wa,-maltivec' [-Werror,-Wunused-command-line-argument]
+
+The first group of warnings point out that linker flags were being added
+to all invocations of $(CC), even though they will only be used during
+the final vDSO link. Move those flags to ldflags-y.
+
+The second group of warnings are compiler or assembler flags that will
+be unused during linking. Filter them out from KBUILD_CFLAGS so that
+they are not used during linking.
+
+Additionally, '-z noexecstack' was added directly to the ld_and_check
+rule in commit 1d53c0192b15 ("powerpc/vdso: link with -z noexecstack")
+but now that there is a common ldflags variable, it can be moved there.
+
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
+Tested-by: Anders Roxell <anders.roxell@linaro.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Stable-dep-of: d677ce521334 ("powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with clang")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index 45c0cc5d34b64..d4023bceec348 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -47,13 +47,17 @@ KCOV_INSTRUMENT := n
+ UBSAN_SANITIZE := n
+ KASAN_SANITIZE := n
+
+-ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both
+-ccflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
+-
+-CC32FLAGS := -Wl,-soname=linux-vdso32.so.1 -m32
++ccflags-y := -fno-common -fno-builtin
++ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack
++ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
++# Filter flags that clang will warn are unused for linking
++ldflags-y += $(filter-out $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
++
++CC32FLAGS := -m32
++LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
+ AS32FLAGS := -D__VDSO32__
+
+-CC64FLAGS := -Wl,-soname=linux-vdso64.so.1
++LD64FLAGS := -Wl,-soname=linux-vdso64.so.1
+ AS64FLAGS := -D__VDSO64__
+
+ targets += vdso32.lds
+@@ -92,15 +96,15 @@ include/generated/vdso64-offsets.h: $(obj)/vdso64.so.dbg FORCE
+
+ # actual build commands
+ quiet_cmd_vdso32ld_and_check = VDSO32L $@
+- cmd_vdso32ld_and_check = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) -z noexecstack ; $(cmd_vdso_check)
++ cmd_vdso32ld_and_check = $(VDSOCC) $(ldflags-y) $(CC32FLAGS) $(LD32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
+ quiet_cmd_vdso32as = VDSO32A $@
+ cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) $(AS32FLAGS) -c -o $@ $<
+ quiet_cmd_vdso32cc = VDSO32C $@
+ cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $<
+
+ quiet_cmd_vdso64ld_and_check = VDSO64L $@
+- cmd_vdso64ld_and_check = $(VDSOCC) $(c_flags) $(CC64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) -z noexecstack ; $(cmd_vdso_check)
++ cmd_vdso64ld_and_check = $(VDSOCC) $(ldflags-y) $(LD64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
+ quiet_cmd_vdso64as = VDSO64A $@
+- cmd_vdso64as = $(VDSOCC) $(a_flags) $(CC64FLAGS) $(AS64FLAGS) -c -o $@ $<
++ cmd_vdso64as = $(VDSOCC) $(a_flags) $(AS64FLAGS) -c -o $@ $<
+
+ OBJECT_FILES_NON_STANDARD := y
+--
+2.43.0
+
--- /dev/null
+From 4a8cf36d67782a9351c0c18912d2767c9c548559 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Jun 2023 11:46:33 -0700
+Subject: powerpc/vdso: Include CLANG_FLAGS explicitly in ldflags-y
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit a7e5eb53bf9b800d086e2ebcfebd9a3bb16bd1b0 ]
+
+A future change will move CLANG_FLAGS from KBUILD_{A,C}FLAGS to
+KBUILD_CPPFLAGS so that '--target' is available while preprocessing.
+When that occurs, the following error appears when building the compat
+PowerPC vDSO:
+
+ clang: error: unsupported option '-mbig-endian' for target 'x86_64-pc-linux-gnu'
+ make[3]: *** [.../arch/powerpc/kernel/vdso/Makefile:76: arch/powerpc/kernel/vdso/vdso32.so.dbg] Error 1
+
+Explicitly add CLANG_FLAGS to ldflags-y, so that '--target' will always
+be present.
+
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Stable-dep-of: d677ce521334 ("powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with clang")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index 7e69e87fbf744..84a513c1af331 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -53,7 +53,7 @@ UBSAN_SANITIZE := n
+ KASAN_SANITIZE := n
+
+ ccflags-y := -fno-common -fno-builtin
+-ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack
++ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)
+ ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
+ # Filter flags that clang will warn are unused for linking
+ ldflags-y += $(filter-out $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
+--
+2.43.0
+
--- /dev/null
+From bf56aaabb1f436fe82334fd6aee19dd623cb6691 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 21:17:20 +0200
+Subject: powerpc/vdso: Refactor CFLAGS for CVDSO build
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit a6b67eb09963af29991625862cbb4f56b85954ed ]
+
+In order to avoid two much duplication when we add new VDSO
+functionnalities in C like getrandom, refactor common CFLAGS.
+
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Stable-dep-of: d677ce521334 ("powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with clang")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 32 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 19 deletions(-)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index 84a513c1af331..c12be984dccdf 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -10,28 +10,11 @@ obj-vdso64 = sigtramp64-64.o gettimeofday-64.o datapage-64.o cacheflush-64.o not
+
+ ifneq ($(c-gettimeofday-y),)
+ CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y)
+- CFLAGS_vgettimeofday-32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+- CFLAGS_vgettimeofday-32.o += $(call cc-option, -fno-stack-protector)
+- CFLAGS_vgettimeofday-32.o += -DDISABLE_BRANCH_PROFILING
+- CFLAGS_vgettimeofday-32.o += -ffreestanding -fasynchronous-unwind-tables
+- CFLAGS_REMOVE_vgettimeofday-32.o = $(CC_FLAGS_FTRACE)
+- CFLAGS_REMOVE_vgettimeofday-32.o += -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
+- # This flag is supported by clang for 64-bit but not 32-bit so it will cause
+- # an unused command line flag warning for this file.
+- ifdef CONFIG_CC_IS_CLANG
+- CFLAGS_REMOVE_vgettimeofday-32.o += -fno-stack-clash-protection
+- endif
+- CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y)
+- CFLAGS_vgettimeofday-64.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+- CFLAGS_vgettimeofday-64.o += $(call cc-option, -fno-stack-protector)
+- CFLAGS_vgettimeofday-64.o += -DDISABLE_BRANCH_PROFILING
+- CFLAGS_vgettimeofday-64.o += -ffreestanding -fasynchronous-unwind-tables
+- CFLAGS_REMOVE_vgettimeofday-64.o = $(CC_FLAGS_FTRACE)
+ # Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code. That used to be true
+ # by accident when the VDSO was hand-written asm code, but may not be now that the VDSO is
+ # compiler generated. To avoid breaking Go tell GCC not to use r30. Impact on code
+ # generation is minimal, it will just use r29 instead.
+- CFLAGS_vgettimeofday-64.o += $(call cc-option, -ffixed-r30)
++ CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) $(call cc-option, -ffixed-r30)
+ endif
+
+ # Build rules
+@@ -53,12 +36,23 @@ UBSAN_SANITIZE := n
+ KASAN_SANITIZE := n
+
+ ccflags-y := -fno-common -fno-builtin
++ccflags-y += $(DISABLE_LATENT_ENTROPY_PLUGIN)
++ccflags-y += $(call cc-option, -fno-stack-protector)
++ccflags-y += -DDISABLE_BRANCH_PROFILING
++ccflags-y += -ffreestanding -fasynchronous-unwind-tables
++ccflags-remove-y := $(CC_FLAGS_FTRACE)
+ ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)
+ ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
+ # Filter flags that clang will warn are unused for linking
+ ldflags-y += $(filter-out $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CFLAGS))
+
+ CC32FLAGS := -m32
++CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
++ # This flag is supported by clang for 64-bit but not 32-bit so it will cause
++ # an unused command line flag warning for this file.
++ifdef CONFIG_CC_IS_CLANG
++CC32FLAGSREMOVE += -fno-stack-clash-protection
++endif
+ LD32FLAGS := -Wl,-soname=linux-vdso32.so.1
+ AS32FLAGS := -D__VDSO32__
+
+@@ -105,7 +99,7 @@ quiet_cmd_vdso32ld_and_check = VDSO32L $@
+ quiet_cmd_vdso32as = VDSO32A $@
+ cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) $(AS32FLAGS) -c -o $@ $<
+ quiet_cmd_vdso32cc = VDSO32C $@
+- cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $<
++ cmd_vdso32cc = $(VDSOCC) $(filter-out $(CC32FLAGSREMOVE), $(c_flags)) $(CC32FLAGS) -c -o $@ $<
+
+ quiet_cmd_vdso64ld_and_check = VDSO64L $@
+ cmd_vdso64ld_and_check = $(VDSOCC) $(ldflags-y) $(LD64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
+--
+2.43.0
+
--- /dev/null
+From a1fd4ceb1d8fb517404405ad41a1b758dcfa0b02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jan 2023 20:05:05 -0700
+Subject: powerpc/vdso: Remove an unsupported flag from vgettimeofday-32.o with
+ clang
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 05e05bfc92d196669a3d087fc34d3998b6ddb758 ]
+
+When clang's -Qunused-arguments is dropped from KBUILD_CPPFLAGS, it
+warns:
+
+ clang-16: error: argument unused during compilation: '-fno-stack-clash-protection' [-Werror,-Wunused-command-line-argument]
+
+This warning happens because vgettimeofday-32.c gets its base CFLAGS
+from the main kernel, which may contain flags that are only supported on
+a 64-bit target but not a 32-bit one, which is the case here.
+-fstack-clash-protection and its negation are only suppported by the
+64-bit powerpc target but that flag is included in an invocation for a
+32-bit powerpc target, so clang points out that while the flag is one
+that it recognizes, it is not actually used by this compiler job.
+
+To eliminate the warning, remove -fno-stack-clash-protection from
+vgettimeofday-32.c's CFLAGS when using clang, as has been done for other
+flags previously.
+
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
+Tested-by: Anders Roxell <anders.roxell@linaro.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Stable-dep-of: d677ce521334 ("powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with clang")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index d4023bceec348..7e69e87fbf744 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -16,6 +16,11 @@ ifneq ($(c-gettimeofday-y),)
+ CFLAGS_vgettimeofday-32.o += -ffreestanding -fasynchronous-unwind-tables
+ CFLAGS_REMOVE_vgettimeofday-32.o = $(CC_FLAGS_FTRACE)
+ CFLAGS_REMOVE_vgettimeofday-32.o += -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc
++ # This flag is supported by clang for 64-bit but not 32-bit so it will cause
++ # an unused command line flag warning for this file.
++ ifdef CONFIG_CC_IS_CLANG
++ CFLAGS_REMOVE_vgettimeofday-32.o += -fno-stack-clash-protection
++ endif
+ CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y)
+ CFLAGS_vgettimeofday-64.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+ CFLAGS_vgettimeofday-64.o += $(call cc-option, -fno-stack-protector)
+--
+2.43.0
+
--- /dev/null
+From eb833be76944a804930adbbc5863124213fe798b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jan 2023 20:05:03 -0700
+Subject: powerpc/vdso: Remove unused '-s' flag from ASFLAGS
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 024734d132846dcb27f07deb1ec5be64d4cbfae9 ]
+
+When clang's -Qunused-arguments is dropped from KBUILD_CPPFLAGS, it
+warns:
+
+ clang-16: error: argument unused during compilation: '-s' [-Werror,-Wunused-command-line-argument]
+
+The compiler's '-s' flag is a linking option (it is passed along to the
+linker directly), which means it does nothing when the linker is not
+invoked by the compiler. The kernel builds all .o files with '-c', which
+stops the compilation pipeline before linking, so '-s' can be safely
+dropped from ASFLAGS.
+
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>
+Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
+Tested-by: Anders Roxell <anders.roxell@linaro.org>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Stable-dep-of: d677ce521334 ("powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with clang")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index 6a977b0d8ffc3..45c0cc5d34b64 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -51,10 +51,10 @@ ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both
+ ccflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
+
+ CC32FLAGS := -Wl,-soname=linux-vdso32.so.1 -m32
+-AS32FLAGS := -D__VDSO32__ -s
++AS32FLAGS := -D__VDSO32__
+
+ CC64FLAGS := -Wl,-soname=linux-vdso64.so.1
+-AS64FLAGS := -D__VDSO64__ -s
++AS64FLAGS := -D__VDSO64__
+
+ targets += vdso32.lds
+ CPPFLAGS_vdso32.lds += -P -C -Upowerpc
+--
+2.43.0
+
--- /dev/null
+From 60cbfaca569d428afded71dd7450397a0a0ff801 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 23:27:45 +0530
+Subject: powerpc/vdso: Skip objtool from running on VDSO files
+
+From: Sathvika Vasireddy <sv@linux.ibm.com>
+
+[ Upstream commit d0160bd5d389da247fb5affb6a35ea393d22fedb ]
+
+Do not run objtool on VDSO files, by using OBJECT_FILES_NON_STANDARD.
+
+Suggested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Tested-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
+Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
+Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Signed-off-by: Sathvika Vasireddy <sv@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20221114175754.1131267-8-sv@linux.ibm.com
+Stable-dep-of: d677ce521334 ("powerpc/vdso: Drop -mstack-protector-guard flags in 32-bit files with clang")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/vdso/Makefile | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile
+index a2e7b0ce5b191..6a977b0d8ffc3 100644
+--- a/arch/powerpc/kernel/vdso/Makefile
++++ b/arch/powerpc/kernel/vdso/Makefile
+@@ -102,3 +102,5 @@ quiet_cmd_vdso64ld_and_check = VDSO64L $@
+ cmd_vdso64ld_and_check = $(VDSOCC) $(c_flags) $(CC64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) -z noexecstack ; $(cmd_vdso_check)
+ quiet_cmd_vdso64as = VDSO64A $@
+ cmd_vdso64as = $(VDSOCC) $(a_flags) $(CC64FLAGS) $(AS64FLAGS) -c -o $@ $<
++
++OBJECT_FILES_NON_STANDARD := y
+--
+2.43.0
+
--- /dev/null
+From 1bdf54b4b512cb9e6dc69a6bbcf331493692a9b4 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 3c3e4fbefebaf..389599bd13bbe 100644
+--- a/drivers/ptp/ptp_clock.c
++++ b/drivers/ptp/ptp_clock.c
+@@ -136,7 +136,8 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
+ err = ops->adjfine(ops, tx->freq);
+ else
+ err = ops->adjfreq(ops, ppb);
+- ptp->dialed_frequency = tx->freq;
++ if (!err)
++ ptp->dialed_frequency = tx->freq;
+ } else if (tx->modes & ADJ_OFFSET) {
+ if (ops->adjphase) {
+ s32 offset = tx->offset;
+--
+2.43.0
+
--- /dev/null
+From 569f5c098860ddc9f8b2bc02172857396afe62fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Nov 2022 15:09:44 -0800
+Subject: ptp: convert remaining drivers to adjfine interface
+
+From: Jacob Keller <jacob.e.keller@intel.com>
+
+[ Upstream commit e2bd9c76c89fbe25df351fc5902cbbcca6a7d372 ]
+
+Convert all remaining drivers that still use .adjfreq to the newer .adjfine
+implementation. These drivers are not straightforward, as they use
+non-standard methods of programming their hardware. They are all converted
+to use scaled_ppm_to_ppb to get the parts per billion value that their
+logic depends on.
+
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Cc: Ariel Elior <aelior@marvell.com>
+Cc: Sudarsana Kalluru <skalluru@marvell.com>
+Cc: Manish Chopra <manishc@marvell.com>
+Cc: Derek Chickles <dchickles@marvell.com>
+Cc: Satanand Burla <sburla@marvell.com>
+Cc: Felix Manlunas <fmanlunas@marvell.com>
+Cc: Raju Rangoju <rajur@chelsio.com>
+Cc: Joakim Zhang <qiangqing.zhang@nxp.com>
+Cc: Edward Cree <ecree.xilinx@gmail.com>
+Cc: Martin Habets <habetsm.xilinx@gmail.com>
+Cc: Richard Cochran <richardcochran@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 98337d7c8757 ("ptp: Add error handling for adjfine callback in ptp_clock_adjtime")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 9 +++++----
+ drivers/net/ethernet/cavium/liquidio/lio_main.c | 11 +++++++----
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c | 13 ++++++++-----
+ drivers/net/ethernet/freescale/fec_ptp.c | 13 ++++++++-----
+ drivers/net/ethernet/qlogic/qede/qede_ptp.c | 13 ++++++++-----
+ drivers/net/ethernet/sfc/ptp.c | 7 ++++---
+ drivers/net/ethernet/sfc/siena/ptp.c | 7 ++++---
+ drivers/net/ethernet/ti/am65-cpts.c | 5 +++--
+ drivers/ptp/ptp_dte.c | 5 +++--
+ 9 files changed, 50 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+index a1783faf4fe99..afa591ec7a13b 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+@@ -13671,19 +13671,20 @@ static int bnx2x_send_update_drift_ramrod(struct bnx2x *bp, int drift_dir,
+ return bnx2x_func_state_change(bp, &func_params);
+ }
+
+-static int bnx2x_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
++static int bnx2x_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+ struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info);
+ int rc;
+ int drift_dir = 1;
+ int val, period, period1, period2, dif, dif1, dif2;
+ int best_dif = BNX2X_MAX_PHC_DRIFT, best_period = 0, best_val = 0;
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+
+- DP(BNX2X_MSG_PTP, "PTP adjfreq called, ppb = %d\n", ppb);
++ DP(BNX2X_MSG_PTP, "PTP adjfine called, ppb = %d\n", ppb);
+
+ if (!netif_running(bp->dev)) {
+ DP(BNX2X_MSG_PTP,
+- "PTP adjfreq called while the interface is down\n");
++ "PTP adjfine called while the interface is down\n");
+ return -ENETDOWN;
+ }
+
+@@ -13818,7 +13819,7 @@ void bnx2x_register_phc(struct bnx2x *bp)
+ bp->ptp_clock_info.n_ext_ts = 0;
+ bp->ptp_clock_info.n_per_out = 0;
+ bp->ptp_clock_info.pps = 0;
+- bp->ptp_clock_info.adjfreq = bnx2x_ptp_adjfreq;
++ bp->ptp_clock_info.adjfine = bnx2x_ptp_adjfine;
+ bp->ptp_clock_info.adjtime = bnx2x_ptp_adjtime;
+ bp->ptp_clock_info.gettime64 = bnx2x_ptp_gettime;
+ bp->ptp_clock_info.settime64 = bnx2x_ptp_settime;
+diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
+index 98793b2ac2c72..fd7c80edb6e8a 100644
+--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
++++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
+@@ -1512,14 +1512,17 @@ static void free_netsgbuf_with_resp(void *buf)
+ }
+
+ /**
+- * liquidio_ptp_adjfreq - Adjust ptp frequency
++ * liquidio_ptp_adjfine - Adjust ptp frequency
+ * @ptp: PTP clock info
+- * @ppb: how much to adjust by, in parts-per-billion
++ * @scaled_ppm: how much to adjust by, in scaled parts-per-million
++ *
++ * Scaled parts per million is ppm with a 16-bit binary fractional field.
+ */
+-static int liquidio_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
++static int liquidio_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+ struct lio *lio = container_of(ptp, struct lio, ptp_info);
+ struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+ u64 comp, delta;
+ unsigned long flags;
+ bool neg_adj = false;
+@@ -1643,7 +1646,7 @@ static void oct_ptp_open(struct net_device *netdev)
+ lio->ptp_info.n_ext_ts = 0;
+ lio->ptp_info.n_per_out = 0;
+ lio->ptp_info.pps = 0;
+- lio->ptp_info.adjfreq = liquidio_ptp_adjfreq;
++ lio->ptp_info.adjfine = liquidio_ptp_adjfine;
+ lio->ptp_info.adjtime = liquidio_ptp_adjtime;
+ lio->ptp_info.gettime64 = liquidio_ptp_gettime;
+ lio->ptp_info.settime64 = liquidio_ptp_settime;
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
+index 5bf117d2179f4..cbd06d9b95d4e 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
+@@ -194,17 +194,20 @@ int cxgb4_ptp_redirect_rx_packet(struct adapter *adapter, struct port_info *pi)
+ }
+
+ /**
+- * cxgb4_ptp_adjfreq - Adjust frequency of PHC cycle counter
++ * cxgb4_ptp_adjfine - Adjust frequency of PHC cycle counter
+ * @ptp: ptp clock structure
+- * @ppb: Desired frequency change in parts per billion
++ * @scaled_ppm: Desired frequency in scaled parts per billion
+ *
+- * Adjust the frequency of the PHC cycle counter by the indicated ppb from
++ * Adjust the frequency of the PHC cycle counter by the indicated amount from
+ * the base frequency.
++ *
++ * Scaled parts per million is ppm with a 16-bit binary fractional field.
+ */
+-static int cxgb4_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
++static int cxgb4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+ struct adapter *adapter = (struct adapter *)container_of(ptp,
+ struct adapter, ptp_clock_info);
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+ struct fw_ptp_cmd c;
+ int err;
+
+@@ -404,7 +407,7 @@ static const struct ptp_clock_info cxgb4_ptp_clock_info = {
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+ .pps = 0,
+- .adjfreq = cxgb4_ptp_adjfreq,
++ .adjfine = cxgb4_ptp_adjfine,
+ .adjtime = cxgb4_ptp_adjtime,
+ .gettime64 = cxgb4_ptp_gettime,
+ .settime64 = cxgb4_ptp_settime,
+diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
+index 37d83ff5b30be..ade1d5041ae4e 100644
+--- a/drivers/net/ethernet/freescale/fec_ptp.c
++++ b/drivers/net/ethernet/freescale/fec_ptp.c
+@@ -262,18 +262,21 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
+ }
+
+ /**
+- * fec_ptp_adjfreq - adjust ptp cycle frequency
++ * fec_ptp_adjfine - adjust ptp cycle frequency
+ * @ptp: the ptp clock structure
+- * @ppb: parts per billion adjustment from base
++ * @scaled_ppm: scaled parts per million adjustment from base
+ *
+ * Adjust the frequency of the ptp cycle counter by the
+- * indicated ppb from the base frequency.
++ * indicated amount from the base frequency.
++ *
++ * Scaled parts per million is ppm with a 16-bit binary fractional field.
+ *
+ * Because ENET hardware frequency adjust is complex,
+ * using software method to do that.
+ */
+-static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
++static int fec_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+ unsigned long flags;
+ int neg_adj = 0;
+ u32 i, tmp;
+@@ -588,7 +591,7 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
+ fep->ptp_caps.n_per_out = 0;
+ fep->ptp_caps.n_pins = 0;
+ fep->ptp_caps.pps = 1;
+- fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
++ fep->ptp_caps.adjfine = fec_ptp_adjfine;
+ fep->ptp_caps.adjtime = fec_ptp_adjtime;
+ fep->ptp_caps.gettime64 = fec_ptp_gettime;
+ fep->ptp_caps.settime64 = fec_ptp_settime;
+diff --git a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
+index c9c8225f04d6e..747cc5e2bb788 100644
+--- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c
++++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
+@@ -28,16 +28,19 @@ struct qede_ptp {
+ };
+
+ /**
+- * qede_ptp_adjfreq() - Adjust the frequency of the PTP cycle counter.
++ * qede_ptp_adjfine() - Adjust the frequency of the PTP cycle counter.
+ *
+ * @info: The PTP clock info structure.
+- * @ppb: Parts per billion adjustment from base.
++ * @scaled_ppm: Scaled parts per million adjustment from base.
++ *
++ * Scaled parts per million is ppm with a 16-bit binary fractional field.
+ *
+ * Return: Zero on success, negative errno otherwise.
+ */
+-static int qede_ptp_adjfreq(struct ptp_clock_info *info, s32 ppb)
++static int qede_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
+ {
+ struct qede_ptp *ptp = container_of(info, struct qede_ptp, clock_info);
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+ struct qede_dev *edev = ptp->edev;
+ int rc;
+
+@@ -47,7 +50,7 @@ static int qede_ptp_adjfreq(struct ptp_clock_info *info, s32 ppb)
+ rc = ptp->ops->adjfreq(edev->cdev, ppb);
+ spin_unlock_bh(&ptp->lock);
+ } else {
+- DP_ERR(edev, "PTP adjfreq called while interface is down\n");
++ DP_ERR(edev, "PTP adjfine called while interface is down\n");
+ rc = -EFAULT;
+ }
+ __qede_unlock(edev);
+@@ -462,7 +465,7 @@ int qede_ptp_enable(struct qede_dev *edev)
+ ptp->clock_info.n_ext_ts = 0;
+ ptp->clock_info.n_per_out = 0;
+ ptp->clock_info.pps = 0;
+- ptp->clock_info.adjfreq = qede_ptp_adjfreq;
++ ptp->clock_info.adjfine = qede_ptp_adjfine;
+ ptp->clock_info.adjtime = qede_ptp_adjtime;
+ ptp->clock_info.gettime64 = qede_ptp_gettime;
+ ptp->clock_info.settime64 = qede_ptp_settime;
+diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
+index 692c7f132e9f9..4eb6234292b1e 100644
+--- a/drivers/net/ethernet/sfc/ptp.c
++++ b/drivers/net/ethernet/sfc/ptp.c
+@@ -351,7 +351,7 @@ struct efx_ptp_data {
+ void (*xmit_skb)(struct efx_nic *efx, struct sk_buff *skb);
+ };
+
+-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta);
++static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm);
+ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta);
+ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts);
+ static int efx_phc_settime(struct ptp_clock_info *ptp,
+@@ -1509,7 +1509,7 @@ static const struct ptp_clock_info efx_phc_clock_info = {
+ .n_per_out = 0,
+ .n_pins = 0,
+ .pps = 1,
+- .adjfreq = efx_phc_adjfreq,
++ .adjfine = efx_phc_adjfine,
+ .adjtime = efx_phc_adjtime,
+ .gettime64 = efx_phc_gettime,
+ .settime64 = efx_phc_settime,
+@@ -2138,11 +2138,12 @@ void __efx_rx_skb_attach_timestamp(struct efx_channel *channel,
+ ptp->ts_corrections.general_rx);
+ }
+
+-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
++static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+ struct efx_ptp_data *ptp_data = container_of(ptp,
+ struct efx_ptp_data,
+ phc_clock_info);
++ s32 delta = scaled_ppm_to_ppb(scaled_ppm);
+ struct efx_nic *efx = ptp_data->efx;
+ MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN);
+ s64 adjustment_ns;
+diff --git a/drivers/net/ethernet/sfc/siena/ptp.c b/drivers/net/ethernet/sfc/siena/ptp.c
+index 7c46752e6eae8..38e666561bcd9 100644
+--- a/drivers/net/ethernet/sfc/siena/ptp.c
++++ b/drivers/net/ethernet/sfc/siena/ptp.c
+@@ -347,7 +347,7 @@ struct efx_ptp_data {
+ void (*xmit_skb)(struct efx_nic *efx, struct sk_buff *skb);
+ };
+
+-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta);
++static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm);
+ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta);
+ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts);
+ static int efx_phc_settime(struct ptp_clock_info *ptp,
+@@ -1429,7 +1429,7 @@ static const struct ptp_clock_info efx_phc_clock_info = {
+ .n_per_out = 0,
+ .n_pins = 0,
+ .pps = 1,
+- .adjfreq = efx_phc_adjfreq,
++ .adjfine = efx_phc_adjfine,
+ .adjtime = efx_phc_adjtime,
+ .gettime64 = efx_phc_gettime,
+ .settime64 = efx_phc_settime,
+@@ -2044,11 +2044,12 @@ void __efx_siena_rx_skb_attach_timestamp(struct efx_channel *channel,
+ ptp->ts_corrections.general_rx);
+ }
+
+-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
++static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+ struct efx_ptp_data *ptp_data = container_of(ptp,
+ struct efx_ptp_data,
+ phc_clock_info);
++ s32 delta = scaled_ppm_to_ppb(scaled_ppm);
+ struct efx_nic *efx = ptp_data->efx;
+ MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN);
+ s64 adjustment_ns;
+diff --git a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/am65-cpts.c
+index c1bdf045e9815..d7ebc6e12143b 100644
+--- a/drivers/net/ethernet/ti/am65-cpts.c
++++ b/drivers/net/ethernet/ti/am65-cpts.c
+@@ -381,9 +381,10 @@ static irqreturn_t am65_cpts_interrupt(int irq, void *dev_id)
+ }
+
+ /* PTP clock operations */
+-static int am65_cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
++static int am65_cpts_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+ struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+ int neg_adj = 0;
+ u64 adj_period;
+ u32 val;
+@@ -615,7 +616,7 @@ static long am65_cpts_ts_work(struct ptp_clock_info *ptp);
+ static struct ptp_clock_info am65_ptp_info = {
+ .owner = THIS_MODULE,
+ .name = "CTPS timer",
+- .adjfreq = am65_cpts_ptp_adjfreq,
++ .adjfine = am65_cpts_ptp_adjfine,
+ .adjtime = am65_cpts_ptp_adjtime,
+ .gettimex64 = am65_cpts_ptp_gettimex,
+ .settime64 = am65_cpts_ptp_settime,
+diff --git a/drivers/ptp/ptp_dte.c b/drivers/ptp/ptp_dte.c
+index 8641fd060491a..7cc5a00e625bc 100644
+--- a/drivers/ptp/ptp_dte.c
++++ b/drivers/ptp/ptp_dte.c
+@@ -134,8 +134,9 @@ static s64 dte_read_nco_with_ovf(struct ptp_dte *ptp_dte)
+ return ns;
+ }
+
+-static int ptp_dte_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
++static int ptp_dte_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
++ s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+ u32 nco_incr;
+ unsigned long flags;
+ struct ptp_dte *ptp_dte = container_of(ptp, struct ptp_dte, caps);
+@@ -219,7 +220,7 @@ static const struct ptp_clock_info ptp_dte_caps = {
+ .n_ext_ts = 0,
+ .n_pins = 0,
+ .pps = 0,
+- .adjfreq = ptp_dte_adjfreq,
++ .adjfine = ptp_dte_adjfine,
+ .adjtime = ptp_dte_adjtime,
+ .gettime64 = ptp_dte_gettime,
+ .settime64 = ptp_dte_settime,
+--
+2.43.0
+
--- /dev/null
+From 75505d606117f2b58969fb31ba192168e10f27eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Nov 2024 14:56:29 +0530
+Subject: serial: amba-pl011: Fix RX stall when DMA is used
+
+From: Kartik Rajput <kkartik@nvidia.com>
+
+[ Upstream commit 2bcacc1c87acf9a8ebc17de18cb2b3cfeca547cf ]
+
+Function pl011_throttle_rx() calls pl011_stop_rx() to disable RX, which
+also disables the RX DMA by clearing the RXDMAE bit of the DMACR
+register. However, to properly unthrottle RX when DMA is used, the
+function pl011_unthrottle_rx() is expected to set the RXDMAE bit of
+the DMACR register, which it currently lacks. This causes RX to stall
+after the throttle API is called.
+
+Set RXDMAE bit in the DMACR register while unthrottling RX if RX DMA is
+used.
+
+Fixes: 211565b10099 ("serial: pl011: UPSTAT_AUTORTS requires .throttle/unthrottle")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Link: https://lore.kernel.org/r/20241113092629.60226-1-kkartik@nvidia.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/amba-pl011.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
+index c95351d24f363..3eb7185994134 100644
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -1837,6 +1837,11 @@ static void pl011_unthrottle_rx(struct uart_port *port)
+
+ pl011_write(uap->im, uap, REG_IMSC);
+
++ if (uap->using_rx_dma) {
++ uap->dmacr |= UART011_RXDMAE;
++ pl011_write(uap->dmacr, uap, REG_DMACR);
++ }
++
+ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+--
+2.43.0
+
--- /dev/null
+From b6548083500335b084be96718d58d161932b8332 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 20:43:34 +0206
+Subject: serial: amba-pl011: Use port lock wrappers
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 68ca3e72d7463d79d29b6e4961d6028df2a88e25 ]
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-18-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 2bcacc1c87ac ("serial: amba-pl011: Fix RX stall when DMA is used")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/amba-pl011.c | 72 ++++++++++++++++-----------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
+index 2f0f05259778a..c95351d24f363 100644
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -346,9 +346,9 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
+ flag = TTY_FRAME;
+ }
+
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ sysrq = uart_handle_sysrq_char(&uap->port, ch & 255);
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+
+ if (!sysrq)
+ uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
+@@ -543,7 +543,7 @@ static void pl011_dma_tx_callback(void *data)
+ unsigned long flags;
+ u16 dmacr;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ if (uap->dmatx.queued)
+ dma_unmap_single(dmatx->chan->device->dev, dmatx->dma,
+ dmatx->len, DMA_TO_DEVICE);
+@@ -564,7 +564,7 @@ static void pl011_dma_tx_callback(void *data)
+ if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) ||
+ uart_circ_empty(&uap->port.state->xmit)) {
+ uap->dmatx.queued = false;
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ return;
+ }
+
+@@ -575,7 +575,7 @@ static void pl011_dma_tx_callback(void *data)
+ */
+ pl011_start_tx_pio(uap);
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ /*
+@@ -1004,7 +1004,7 @@ static void pl011_dma_rx_callback(void *data)
+ * routine to flush out the secondary DMA buffer while
+ * we immediately trigger the next DMA job.
+ */
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+ /*
+ * Rx data can be taken by the UART interrupts during
+ * the DMA irq handler. So we check the residue here.
+@@ -1020,7 +1020,7 @@ static void pl011_dma_rx_callback(void *data)
+ ret = pl011_dma_rx_trigger_dma(uap);
+
+ pl011_dma_rx_chars(uap, pending, lastbuf, false);
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+ /*
+ * Do this check after we picked the DMA chars so we don't
+ * get some IRQ immediately from RX.
+@@ -1086,11 +1086,11 @@ static void pl011_dma_rx_poll(struct timer_list *t)
+ if (jiffies_to_msecs(jiffies - dmarx->last_jiffies)
+ > uap->dmarx.poll_timeout) {
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ pl011_dma_rx_stop(uap);
+ uap->im |= UART011_RXIM;
+ pl011_write(uap->im, uap, REG_IMSC);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+
+ uap->dmarx.running = false;
+ dmaengine_terminate_all(rxchan);
+@@ -1186,10 +1186,10 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
+ while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
+ cpu_relax();
+
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+ uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
+ pl011_write(uap->dmacr, uap, REG_DMACR);
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+
+ if (uap->using_tx_dma) {
+ /* In theory, this should already be done by pl011_dma_flush_buffer */
+@@ -1400,9 +1400,9 @@ static void pl011_throttle_rx(struct uart_port *port)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ pl011_stop_rx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void pl011_enable_ms(struct uart_port *port)
+@@ -1420,7 +1420,7 @@ __acquires(&uap->port.lock)
+ {
+ pl011_fifo_to_tty(uap);
+
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ tty_flip_buffer_push(&uap->port.state->port);
+ /*
+ * If we were temporarily out of DMA mode for a while,
+@@ -1445,7 +1445,7 @@ __acquires(&uap->port.lock)
+ #endif
+ }
+ }
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+ }
+
+ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
+@@ -1551,7 +1551,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
+ unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
+ int handled = 0;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ status = pl011_read(uap, REG_RIS) & uap->im;
+ if (status) {
+ do {
+@@ -1581,7 +1581,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
+ handled = 1;
+ }
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+
+ return IRQ_RETVAL(handled);
+ }
+@@ -1653,14 +1653,14 @@ static void pl011_break_ctl(struct uart_port *port, int break_state)
+ unsigned long flags;
+ unsigned int lcr_h;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ lcr_h = pl011_read(uap, REG_LCRH_TX);
+ if (break_state == -1)
+ lcr_h |= UART01x_LCRH_BRK;
+ else
+ lcr_h &= ~UART01x_LCRH_BRK;
+ pl011_write(lcr_h, uap, REG_LCRH_TX);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ #ifdef CONFIG_CONSOLE_POLL
+@@ -1799,7 +1799,7 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
+ unsigned long flags;
+ unsigned int i;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+
+ /* Clear out any spuriously appearing RX interrupts */
+ pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
+@@ -1821,7 +1821,7 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap)
+ if (!pl011_dma_rx_running(uap))
+ uap->im |= UART011_RXIM;
+ pl011_write(uap->im, uap, REG_IMSC);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ static void pl011_unthrottle_rx(struct uart_port *port)
+@@ -1829,7 +1829,7 @@ static void pl011_unthrottle_rx(struct uart_port *port)
+ struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+
+ uap->im = UART011_RTIM;
+ if (!pl011_dma_rx_running(uap))
+@@ -1837,7 +1837,7 @@ static void pl011_unthrottle_rx(struct uart_port *port)
+
+ pl011_write(uap->im, uap, REG_IMSC);
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ static int pl011_startup(struct uart_port *port)
+@@ -1857,7 +1857,7 @@ static int pl011_startup(struct uart_port *port)
+
+ pl011_write(uap->vendor->ifls, uap, REG_IFLS);
+
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+
+ cr = pl011_read(uap, REG_CR);
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
+@@ -1868,7 +1868,7 @@ static int pl011_startup(struct uart_port *port)
+
+ pl011_write(cr, uap, REG_CR);
+
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+
+ /*
+ * initialise the old status of the modem signals
+@@ -1929,12 +1929,12 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
+ unsigned int cr;
+
+ uap->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS);
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+ cr = pl011_read(uap, REG_CR);
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
+ cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
+ pl011_write(cr, uap, REG_CR);
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+
+ /*
+ * disable break condition and fifos
+@@ -1946,14 +1946,14 @@ static void pl011_disable_uart(struct uart_amba_port *uap)
+
+ static void pl011_disable_interrupts(struct uart_amba_port *uap)
+ {
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+
+ /* mask all interrupts and clear all pending ones */
+ uap->im = 0;
+ pl011_write(uap->im, uap, REG_IMSC);
+ pl011_write(0xffff, uap, REG_ICR);
+
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+ }
+
+ static void pl011_shutdown(struct uart_port *port)
+@@ -2098,7 +2098,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
+
+ bits = tty_get_frame_size(termios->c_cflag);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -2165,7 +2165,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
+ pl011_write_lcr_h(uap, lcr_h);
+ pl011_write(old_cr, uap, REG_CR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void
+@@ -2183,10 +2183,10 @@ sbsa_uart_set_termios(struct uart_port *port, struct ktermios *termios,
+ termios->c_cflag &= ~(CMSPAR | CRTSCTS);
+ termios->c_cflag |= CS8 | CLOCAL;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ uart_update_timeout(port, CS8, uap->fixed_baud);
+ pl011_setup_status_masks(port, termios);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *pl011_type(struct uart_port *port)
+@@ -2325,9 +2325,9 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&uap->port.lock);
++ locked = uart_port_trylock(&uap->port);
+ else
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+
+ /*
+ * First save the CR then disable the interrupts
+@@ -2353,7 +2353,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
+ pl011_write(old_cr, uap, REG_CR);
+
+ if (locked)
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ local_irq_restore(flags);
+
+ clk_disable(uap->clk);
+--
+2.43.0
+
drm-sti-avoid-potential-dereference-of-error-pointers.patch
drm-etnaviv-flush-shader-l1-cache-after-user-commandstream.patch
drm-amd-pm-update-current_socclk-and-current_uclk-in-gpu_metrics-on-smu-v13.0.7.patch
+itco_wdt-mask-nmi_now-bit-for-update_no_reboot_bit-c.patch
+watchdog-apple-actually-flush-writes-after-requestin.patch
+watchdog-mediatek-make-sure-system-reset-gets-assert.patch
+can-gs_usb-remove-leading-space-from-goto-labels.patch
+can-gs_usb-gs_usb_probe-align-block-comment.patch
+can-gs_usb-uniformly-use-parent-as-variable-name-for.patch
+can-gs_usb-add-vid-pid-for-xylanta-saint3-product-fa.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
+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
+ptp-convert-remaining-drivers-to-adjfine-interface.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
+can-j1939-j1939_session_new-fix-skb-reference-counti.patch
+net-timestamp-make-sk_tskey-more-predictable-in-erro.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-fix-lgr-and-link-use-after-free-issue.patch
+net-qed-allow-old-cards-not-supporting-num_images-to.patch
+ixgbevf-stop-attempting-ipsec-offload-on-mailbox-api.patch
+ixgbe-downgrade-logging-of-unsupported-vf-api-versio.patch
+igb-fix-potential-invalid-memory-access-in-igb_init_.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
+geneve-do-not-assume-mac-header-is-set-in-geneve_xmi.patch
+net-mlx5e-remove-workaround-to-avoid-syndrome-for-in.patch
+kvm-arm64-change-kvm_handle_mmio_return-return-polar.patch
+kvm-arm64-don-t-retire-aborted-mmio-instruction.patch
+gpio-grgpio-use-a-helper-variable-to-store-the-addre.patch
+gpio-grgpio-add-null-check-in-grgpio_probe.patch
+serial-amba-pl011-use-port-lock-wrappers.patch
+serial-amba-pl011-fix-rx-stall-when-dma-is-used.patch
+usb-dwc3-gadget-rewrite-endpoint-allocation-flow.patch
+usb-dwc3-ep0-don-t-reset-resource-alloc-flag-includi.patch
+usb-dwc3-ep0-don-t-clear-ep0-dwc3_ep_transfer_starte.patch
+powerpc-vdso-skip-objtool-from-running-on-vdso-files.patch
+powerpc-vdso-remove-unused-s-flag-from-asflags.patch
+powerpc-vdso-improve-linker-flags.patch
+powerpc-vdso-remove-an-unsupported-flag-from-vgettim.patch
+powerpc-vdso-include-clang_flags-explicitly-in-ldfla.patch
+powerpc-vdso-refactor-cflags-for-cvdso-build.patch
+powerpc-vdso-drop-mstack-protector-guard-flags-in-32.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
+driver-core-fw_devlink-improve-logs-for-cycle-detect.patch
+driver-core-add-fwlink_flag_ignore-to-completely-ign.patch
+driver-core-fw_devlink-stop-trying-to-optimize-cycle.patch
+i3c-make-i3c_master_unregister-return-void.patch
+i3c-master-add-enable-disable-hot-join-in-sys-entry.patch
+i3c-master-svc-add-hot-join-support.patch
+i3c-master-fix-kernel-doc-check-warning.patch
+i3c-master-support-to-adjust-first-broadcast-address.patch
+i3c-master-svc-use-slow-speed-for-first-broadcast-ad.patch
+i3c-master-svc-modify-enabled_events-bit-7-0-to-act-.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
+pci-endpoint-use-a-separate-lock-for-protecting-epc-.patch
+pci-endpoint-clear-secondary-not-primary-epc-in-pci_.patch
+device-property-constify-device-child-node-apis.patch
+device-property-add-cleanup.h-based-fwnode_handle_pu.patch
+device-property-introduce-device_for_each_child_node.patch
+leds-flash-mt6360-fix-device_for_each_child_node-ref.patch
+drm-bridge-it6505-update-usleep_range-for-rc-circuit.patch
+drm-bridge-it6505-fix-inverted-reset-polarity.patch
--- /dev/null
+From b8c0b6cd23db40bafc09f11ace5866d93694d048 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 73e461dc12d7b..3f5a12b85b2d3 100644
+--- a/net/tipc/udp_media.c
++++ b/net/tipc/udp_media.c
+@@ -818,10 +818,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 5d31c84bf5cd310b42057467fdc612be9f2dfb37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Nov 2024 01:02:06 +0000
+Subject: usb: dwc3: ep0: Don't clear ep0 DWC3_EP_TRANSFER_STARTED
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+[ Upstream commit 5d2fb074dea289c41f5aaf2c3f68286bee370634 ]
+
+The driver cannot issue the End Transfer command to the SETUP transfer.
+Don't clear DWC3_EP_TRANSFER_STARTED flag to make sure that the driver
+won't send Start Transfer command again, which can cause no-resource
+error. For example this can occur if the host issues a reset to the
+device.
+
+Cc: stable@vger.kernel.org
+Fixes: 76cb323f80ac ("usb: dwc3: ep0: clear all EP0 flags")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/d3d618185fd614bb7426352a9fc1199641d3b5f5.1731545781.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/ep0.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
+index 2da36f02a10e8..e87b37cb9a7af 100644
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -229,7 +229,7 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
+ /* stall is always issued on EP0 */
+ dep = dwc->eps[0];
+ __dwc3_gadget_ep_set_halt(dep, 1, false);
+- dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
++ dep->flags &= DWC3_EP_RESOURCE_ALLOCATED | DWC3_EP_TRANSFER_STARTED;
+ dep->flags |= DWC3_EP_ENABLED;
+ dwc->delayed_status = false;
+
+--
+2.43.0
+
--- /dev/null
+From 8dfec6c0b72cec8d0363d3ba2d2709188067bbfb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Aug 2024 08:40:29 +0200
+Subject: usb: dwc3: ep0: Don't reset resource alloc flag (including ep0)
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+[ Upstream commit 72fca8371f205d654f95b09cd023a71fd5307041 ]
+
+The DWC3_EP_RESOURCE_ALLOCATED flag ensures that the resource of an
+endpoint is only assigned once. Unless the endpoint is reset, don't
+clear this flag. Otherwise we may set endpoint resource again, which
+prevents the driver from initiate transfer after handling a STALL or
+endpoint halt to the control endpoint.
+
+Commit f2e0eee47038 ("usb: dwc3: ep0: Don't reset resource alloc flag")
+was fixing the initial issue, but did this only for physical ep1. Since
+the function dwc3_ep0_stall_and_restart is resetting the flags for both
+physical endpoints, this also has to be done for ep0.
+
+Cc: stable@vger.kernel.org
+Fixes: b311048c174d ("usb: dwc3: gadget: Rewrite endpoint allocation flow")
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Link: https://lore.kernel.org/r/20240814-dwc3hwep0reset-v2-1-29e1d7d923ea@pengutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 5d2fb074dea2 ("usb: dwc3: ep0: Don't clear ep0 DWC3_EP_TRANSFER_STARTED")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/ep0.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
+index afaaff33862bb..2da36f02a10e8 100644
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -229,7 +229,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
+ /* stall is always issued on EP0 */
+ dep = dwc->eps[0];
+ __dwc3_gadget_ep_set_halt(dep, 1, false);
+- dep->flags = DWC3_EP_ENABLED;
++ dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
++ dep->flags |= DWC3_EP_ENABLED;
+ dwc->delayed_status = false;
+
+ if (!list_empty(&dep->pending_list)) {
+--
+2.43.0
+
--- /dev/null
+From 15488c5da63d2526bb221c27b77ca852c035932b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Feb 2024 02:26:53 +0000
+Subject: usb: dwc3: gadget: Rewrite endpoint allocation flow
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+[ Upstream commit b311048c174da893f47fc09439bc1f6fa2a29589 ]
+
+The driver dwc3 deviates from the programming guide in regard to
+endpoint configuration. It does this command sequence:
+
+DEPSTARTCFG -> DEPXFERCFG -> DEPCFG
+
+Instead of the suggested flow:
+
+DEPSTARTCFG -> DEPCFG -> DEPXFERCFG
+
+The reasons for this deviation were as follow, quoted:
+
+ 1) The databook says to do %DWC3_DEPCMD_DEPSTARTCFG for every
+ %USB_REQ_SET_CONFIGURATION and %USB_REQ_SET_INTERFACE
+ (8.1.5). This is incorrect in the scenario of multiple
+ interfaces.
+
+ 2) The databook does not mention doing more
+ %DWC3_DEPCMD_DEPXFERCFG for new endpoint on alt setting
+ (8.1.6).
+
+Regarding 1), DEPSTARTCFG resets the endpoints' resource and can be a
+problem if used with SET_INTERFACE request of a multiple interface
+configuration. But we can still satisfy the programming guide
+requirement by assigning the endpoint resource as part of
+usb_ep_enable(). We will only reset endpoint resources on controller
+initialization and SET_CONFIGURATION request.
+
+Regarding 2), the later versions of the programming guide were updated
+to clarify this flow (see "Alternate Initialization on SetInterface
+Request" of the programming guide). As long as the platform has enough
+physical endpoints, we can assign resource to a new endpoint.
+
+The order of the command sequence will not be a problem to most
+platforms for the current implementation of the dwc3 driver. However,
+this order is required in different scenarios (such as initialization
+during controller's hibernation restore). Let's keep the flow consistent
+and follow the programming guide.
+
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/c143583a5afb087deb8c3aa5eb227ee23515f272.1706754219.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 5d2fb074dea2 ("usb: dwc3: ep0: Don't clear ep0 DWC3_EP_TRANSFER_STARTED")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/core.h | 1 +
+ drivers/usb/dwc3/ep0.c | 1 +
+ drivers/usb/dwc3/gadget.c | 89 +++++++++++++++++----------------------
+ drivers/usb/dwc3/gadget.h | 1 +
+ 4 files changed, 41 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
+index 1b496c8e7b809..5a7a862738832 100644
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -744,6 +744,7 @@ struct dwc3_ep {
+ #define DWC3_EP_PENDING_CLEAR_STALL BIT(11)
+ #define DWC3_EP_TXFIFO_RESIZED BIT(12)
+ #define DWC3_EP_DELAY_STOP BIT(13)
++#define DWC3_EP_RESOURCE_ALLOCATED BIT(14)
+
+ /* This last one is specific to EP0 */
+ #define DWC3_EP0_DIR_IN BIT(31)
+diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
+index ec3c33266547c..afaaff33862bb 100644
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -643,6 +643,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
+ return -EINVAL;
+
+ case USB_STATE_ADDRESS:
++ dwc3_gadget_start_config(dwc, 2);
+ dwc3_gadget_clear_tx_fifos(dwc);
+
+ ret = dwc3_ep0_delegate_req(dwc, ctrl);
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 8eb75cfd41622..90ad996fed69d 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -523,77 +523,56 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
+ static int dwc3_gadget_set_xfer_resource(struct dwc3_ep *dep)
+ {
+ struct dwc3_gadget_ep_cmd_params params;
++ int ret;
++
++ if (dep->flags & DWC3_EP_RESOURCE_ALLOCATED)
++ return 0;
+
+ memset(¶ms, 0x00, sizeof(params));
+
+ params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1);
+
+- return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETTRANSFRESOURCE,
++ ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETTRANSFRESOURCE,
+ ¶ms);
++ if (ret)
++ return ret;
++
++ dep->flags |= DWC3_EP_RESOURCE_ALLOCATED;
++ return 0;
+ }
+
+ /**
+- * dwc3_gadget_start_config - configure ep resources
+- * @dep: endpoint that is being enabled
+- *
+- * Issue a %DWC3_DEPCMD_DEPSTARTCFG command to @dep. After the command's
+- * completion, it will set Transfer Resource for all available endpoints.
+- *
+- * The assignment of transfer resources cannot perfectly follow the data book
+- * due to the fact that the controller driver does not have all knowledge of the
+- * configuration in advance. It is given this information piecemeal by the
+- * composite gadget framework after every SET_CONFIGURATION and
+- * SET_INTERFACE. Trying to follow the databook programming model in this
+- * scenario can cause errors. For two reasons:
+- *
+- * 1) The databook says to do %DWC3_DEPCMD_DEPSTARTCFG for every
+- * %USB_REQ_SET_CONFIGURATION and %USB_REQ_SET_INTERFACE (8.1.5). This is
+- * incorrect in the scenario of multiple interfaces.
+- *
+- * 2) The databook does not mention doing more %DWC3_DEPCMD_DEPXFERCFG for new
+- * endpoint on alt setting (8.1.6).
+- *
+- * The following simplified method is used instead:
++ * dwc3_gadget_start_config - reset endpoint resources
++ * @dwc: pointer to the DWC3 context
++ * @resource_index: DEPSTARTCFG.XferRscIdx value (must be 0 or 2)
+ *
+- * All hardware endpoints can be assigned a transfer resource and this setting
+- * will stay persistent until either a core reset or hibernation. So whenever we
+- * do a %DWC3_DEPCMD_DEPSTARTCFG(0) we can go ahead and do
+- * %DWC3_DEPCMD_DEPXFERCFG for every hardware endpoint as well. We are
+- * guaranteed that there are as many transfer resources as endpoints.
++ * Set resource_index=0 to reset all endpoints' resources allocation. Do this as
++ * part of the power-on/soft-reset initialization.
+ *
+- * This function is called for each endpoint when it is being enabled but is
+- * triggered only when called for EP0-out, which always happens first, and which
+- * should only happen in one of the above conditions.
++ * Set resource_index=2 to reset only non-control endpoints' resources. Do this
++ * on receiving the SET_CONFIGURATION request or hibernation resume.
+ */
+-static int dwc3_gadget_start_config(struct dwc3_ep *dep)
++int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index)
+ {
+ struct dwc3_gadget_ep_cmd_params params;
+- struct dwc3 *dwc;
+ u32 cmd;
+ int i;
+ int ret;
+
+- if (dep->number)
+- return 0;
++ if (resource_index != 0 && resource_index != 2)
++ return -EINVAL;
+
+ memset(¶ms, 0x00, sizeof(params));
+ cmd = DWC3_DEPCMD_DEPSTARTCFG;
+- dwc = dep->dwc;
++ cmd |= DWC3_DEPCMD_PARAM(resource_index);
+
+- ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
++ ret = dwc3_send_gadget_ep_cmd(dwc->eps[0], cmd, ¶ms);
+ if (ret)
+ return ret;
+
+- for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) {
+- struct dwc3_ep *dep = dwc->eps[i];
+-
+- if (!dep)
+- continue;
+-
+- ret = dwc3_gadget_set_xfer_resource(dep);
+- if (ret)
+- return ret;
+- }
++ /* Reset resource allocation flags */
++ for (i = resource_index; i < dwc->num_eps && dwc->eps[i]; i++)
++ dwc->eps[i]->flags &= ~DWC3_EP_RESOURCE_ALLOCATED;
+
+ return 0;
+ }
+@@ -888,16 +867,18 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
+ ret = dwc3_gadget_resize_tx_fifos(dep);
+ if (ret)
+ return ret;
+-
+- ret = dwc3_gadget_start_config(dep);
+- if (ret)
+- return ret;
+ }
+
+ ret = dwc3_gadget_set_ep_config(dep, action);
+ if (ret)
+ return ret;
+
++ if (!(dep->flags & DWC3_EP_RESOURCE_ALLOCATED)) {
++ ret = dwc3_gadget_set_xfer_resource(dep);
++ if (ret)
++ return ret;
++ }
++
+ if (!(dep->flags & DWC3_EP_ENABLED)) {
+ struct dwc3_trb *trb_st_hw;
+ struct dwc3_trb *trb_link;
+@@ -1051,7 +1032,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
+
+ dep->stream_capable = false;
+ dep->type = 0;
+- mask = DWC3_EP_TXFIFO_RESIZED;
++ mask = DWC3_EP_TXFIFO_RESIZED | DWC3_EP_RESOURCE_ALLOCATED;
+ /*
+ * dwc3_remove_requests() can exit early if DWC3 EP delayed stop is
+ * set. Do not clear DEP flags, so that the end transfer command will
+@@ -2810,6 +2791,12 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
+ /* Start with SuperSpeed Default */
+ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+
++ ret = dwc3_gadget_start_config(dwc, 0);
++ if (ret) {
++ dev_err(dwc->dev, "failed to config endpoints\n");
++ return ret;
++ }
++
+ dep = dwc->eps[0];
+ dep->flags = 0;
+ ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT);
+diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
+index 55a56cf67d736..d73e735e40810 100644
+--- a/drivers/usb/dwc3/gadget.h
++++ b/drivers/usb/dwc3/gadget.h
+@@ -119,6 +119,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
+ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
+ void dwc3_ep0_send_delayed_status(struct dwc3 *dwc);
+ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt);
++int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index);
+
+ /**
+ * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
+--
+2.43.0
+
--- /dev/null
+From 57f302e4b5c3540e7b30169e821368605e2a617f 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 16aca21f13d6a..a5af532c40867 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 1284f4de6e7f00086dcce7bc1ad2bddbf5aff21b 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 e977875367926..08763ff950c6d 100644
+--- a/drivers/watchdog/mtk_wdt.c
++++ b/drivers/watchdog/mtk_wdt.c
+@@ -175,9 +175,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
+