]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Sat, 31 Aug 2024 23:13:49 +0000 (19:13 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 31 Aug 2024 23:13:49 +0000 (19:13 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
23 files changed:
queue-6.6/bluetooth-btnxpuart-fix-random-crash-seen-while-remo.patch [new file with mode: 0644]
queue-6.6/bluetooth-btnxpuart-handle-fw-download-abort-scenari.patch [new file with mode: 0644]
queue-6.6/bluetooth-btnxpuart-resolve-tx-timeout-error-in-powe.patch [new file with mode: 0644]
queue-6.6/bluetooth-hci_core-fix-not-handling-hibernation-acti.patch [new file with mode: 0644]
queue-6.6/bonding-change-ipsec_lock-from-spin-lock-to-mutex.patch [new file with mode: 0644]
queue-6.6/bonding-extract-the-use-of-real_device-into-local-va.patch [new file with mode: 0644]
queue-6.6/bonding-implement-xdo_dev_state_free-and-call-it-aft.patch [new file with mode: 0644]
queue-6.6/dmaengine-dw-add-memory-bus-width-verification.patch [new file with mode: 0644]
queue-6.6/dmaengine-dw-add-peripheral-bus-width-verification.patch [new file with mode: 0644]
queue-6.6/drm-amd-display-avoid-using-null-object-of-framebuff.patch [new file with mode: 0644]
queue-6.6/ethtool-check-device-is-present-when-getting-link-se.patch [new file with mode: 0644]
queue-6.6/gtp-fix-a-potential-null-pointer-dereference.patch [new file with mode: 0644]
queue-6.6/iommu-do-not-return-0-from-map_pages-if-it-doesn-t-d.patch [new file with mode: 0644]
queue-6.6/net-busy-poll-use-ktime_get_ns-instead-of-local_cloc.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables-restore-ip-sanity-checks-for-net.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables_ipv6-consider-network-offset-in-.patch [new file with mode: 0644]
queue-6.6/nfc-pn533-add-poll-mod-list-filling-check.patch [new file with mode: 0644]
queue-6.6/phy-xilinx-phy-zynqmp-fix-sgmii-linkup-failure-on-re.patch [new file with mode: 0644]
queue-6.6/sctp-fix-association-labeling-in-the-duplicate-cooki.patch [new file with mode: 0644]
queue-6.6/selftests-forwarding-local_termination-down-ports-on.patch [new file with mode: 0644]
queue-6.6/selftests-forwarding-no_forwarding-down-ports-on-cle.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/wifi-iwlwifi-fw-fix-wgds-rev-3-exact-size.patch [new file with mode: 0644]

diff --git a/queue-6.6/bluetooth-btnxpuart-fix-random-crash-seen-while-remo.patch b/queue-6.6/bluetooth-btnxpuart-fix-random-crash-seen-while-remo.patch
new file mode 100644 (file)
index 0000000..808556b
--- /dev/null
@@ -0,0 +1,126 @@
+From 11b754ddbd3686b92de4cf305e473fe245440bc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Aug 2024 15:51:13 +0530
+Subject: Bluetooth: btnxpuart: Fix random crash seen while removing driver
+
+From: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+
+[ Upstream commit 35237475384ab3622f63c3c09bdf6af6dacfe9c3 ]
+
+This fixes the random kernel crash seen while removing the driver, when
+running the load/unload test over multiple iterations.
+
+1) modprobe btnxpuart
+2) hciconfig hci0 reset
+3) hciconfig (check hci0 interface up with valid BD address)
+4) modprobe -r btnxpuart
+Repeat steps 1 to 4
+
+The ps_wakeup() call in btnxpuart_close() schedules the psdata->work(),
+which gets scheduled after module is removed, causing a kernel crash.
+
+This hidden issue got highlighted after enabling Power Save by default
+in 4183a7be7700 (Bluetooth: btnxpuart: Enable Power Save feature on
+startup)
+
+The new ps_cleanup() deasserts UART break immediately while closing
+serdev device, cancels any scheduled ps_work and destroys the ps_lock
+mutex.
+
+[   85.884604] Unable to handle kernel paging request at virtual address ffffd4a61638f258
+[   85.884624] Mem abort info:
+[   85.884625]   ESR = 0x0000000086000007
+[   85.884628]   EC = 0x21: IABT (current EL), IL = 32 bits
+[   85.884633]   SET = 0, FnV = 0
+[   85.884636]   EA = 0, S1PTW = 0
+[   85.884638]   FSC = 0x07: level 3 translation fault
+[   85.884642] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000041dd0000
+[   85.884646] [ffffd4a61638f258] pgd=1000000095fff003, p4d=1000000095fff003, pud=100000004823d003, pmd=100000004823e003, pte=0000000000000000
+[   85.884662] Internal error: Oops: 0000000086000007 [#1] PREEMPT SMP
+[   85.890932] Modules linked in: algif_hash algif_skcipher af_alg overlay fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc caamalg_desc crypto_engine authenc libdes crct10dif_ce polyval_ce polyval_generic snd_soc_imx_spdif snd_soc_imx_card snd_soc_ak5558 snd_soc_ak4458 caam secvio error snd_soc_fsl_spdif snd_soc_fsl_micfil snd_soc_fsl_sai snd_soc_fsl_utils gpio_ir_recv rc_core fuse [last unloaded: btnxpuart(O)]
+[   85.927297] CPU: 1 PID: 67 Comm: kworker/1:3 Tainted: G           O       6.1.36+g937b1be4345a #1
+[   85.936176] Hardware name: FSL i.MX8MM EVK board (DT)
+[   85.936182] Workqueue: events 0xffffd4a61638f380
+[   85.936198] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[   85.952817] pc : 0xffffd4a61638f258
+[   85.952823] lr : 0xffffd4a61638f258
+[   85.952827] sp : ffff8000084fbd70
+[   85.952829] x29: ffff8000084fbd70 x28: 0000000000000000 x27: 0000000000000000
+[   85.963112] x26: ffffd4a69133f000 x25: ffff4bf1c8540990 x24: ffff4bf215b87305
+[   85.963119] x23: ffff4bf215b87300 x22: ffff4bf1c85409d0 x21: ffff4bf1c8540970
+[   85.977382] x20: 0000000000000000 x19: ffff4bf1c8540880 x18: 0000000000000000
+[   85.977391] x17: 0000000000000000 x16: 0000000000000133 x15: 0000ffffe2217090
+[   85.977399] x14: 0000000000000001 x13: 0000000000000133 x12: 0000000000000139
+[   85.977407] x11: 0000000000000001 x10: 0000000000000a60 x9 : ffff8000084fbc50
+[   85.977417] x8 : ffff4bf215b7d000 x7 : ffff4bf215b83b40 x6 : 00000000000003e8
+[   85.977424] x5 : 00000000410fd030 x4 : 0000000000000000 x3 : 0000000000000000
+[   85.977432] x2 : 0000000000000000 x1 : ffff4bf1c4265880 x0 : 0000000000000000
+[   85.977443] Call trace:
+[   85.977446]  0xffffd4a61638f258
+[   85.977451]  0xffffd4a61638f3e8
+[   85.977455]  process_one_work+0x1d4/0x330
+[   85.977464]  worker_thread+0x6c/0x430
+[   85.977471]  kthread+0x108/0x10c
+[   85.977476]  ret_from_fork+0x10/0x20
+[   85.977488] Code: bad PC value
+[   85.977491] ---[ end trace 0000000000000000 ]---
+
+Preset since v6.9.11
+Fixes: 86d55f124b52 ("Bluetooth: btnxpuart: Deasset UART break before closing serdev device")
+Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btnxpuart.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
+index f72086ee614fb..814dd966b1a45 100644
+--- a/drivers/bluetooth/btnxpuart.c
++++ b/drivers/bluetooth/btnxpuart.c
+@@ -438,6 +438,23 @@ static bool ps_wakeup(struct btnxpuart_dev *nxpdev)
+       return false;
+ }
++static void ps_cleanup(struct btnxpuart_dev *nxpdev)
++{
++      struct ps_data *psdata = &nxpdev->psdata;
++      u8 ps_state;
++
++      mutex_lock(&psdata->ps_lock);
++      ps_state = psdata->ps_state;
++      mutex_unlock(&psdata->ps_lock);
++
++      if (ps_state != PS_STATE_AWAKE)
++              ps_control(psdata->hdev, PS_STATE_AWAKE);
++
++      ps_cancel_timer(nxpdev);
++      cancel_work_sync(&psdata->work);
++      mutex_destroy(&psdata->ps_lock);
++}
++
+ static int send_ps_cmd(struct hci_dev *hdev, void *data)
+ {
+       struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+@@ -1307,7 +1324,6 @@ static int btnxpuart_close(struct hci_dev *hdev)
+ {
+       struct btnxpuart_dev *nxpdev = hci_get_drvdata(hdev);
+-      ps_wakeup(nxpdev);
+       serdev_device_close(nxpdev->serdev);
+       skb_queue_purge(&nxpdev->txq);
+       kfree_skb(nxpdev->rx_skb);
+@@ -1457,8 +1473,8 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
+                       nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
+                       nxp_set_baudrate_cmd(hdev, NULL);
+               }
+-              ps_cancel_timer(nxpdev);
+       }
++      ps_cleanup(nxpdev);
+       hci_unregister_dev(hdev);
+       hci_free_dev(hdev);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/bluetooth-btnxpuart-handle-fw-download-abort-scenari.patch b/queue-6.6/bluetooth-btnxpuart-handle-fw-download-abort-scenari.patch
new file mode 100644 (file)
index 0000000..e558eff
--- /dev/null
@@ -0,0 +1,131 @@
+From 6e531e78d5a1d12e18d42da97f4d9c9e137cf054 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 May 2024 12:36:57 +0530
+Subject: Bluetooth: btnxpuart: Handle FW Download Abort scenario
+
+From: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+
+[ Upstream commit e3c4891098c875a63ab0c3b31d584f6d4f1895fd ]
+
+This adds a new flag BTNXPUART_FW_DOWNLOAD_ABORT which handles the
+situation where driver is removed while firmware download is in
+progress.
+
+logs:
+modprobe btnxpuart
+[65239.230431] Bluetooth: hci0: ChipID: 7601, Version: 0
+[65239.236670] Bluetooth: hci0: Request Firmware: nxp/uartspi_n61x_v1.bin.se
+rmmod btnxpuart
+[65241.425300] Bluetooth: hci0: FW Download Aborted
+
+Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+Tested-by: Guillaume Legoupil <guillaume.legoupil@nxp.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 35237475384a ("Bluetooth: btnxpuart: Fix random crash seen while removing driver")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btnxpuart.c | 47 ++++++++++++++++++++++++-----------
+ 1 file changed, 33 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
+index 2e18f89a931b8..f72086ee614fb 100644
+--- a/drivers/bluetooth/btnxpuart.c
++++ b/drivers/bluetooth/btnxpuart.c
+@@ -29,6 +29,7 @@
+ #define BTNXPUART_CHECK_BOOT_SIGNATURE        3
+ #define BTNXPUART_SERDEV_OPEN         4
+ #define BTNXPUART_IR_IN_PROGRESS      5
++#define BTNXPUART_FW_DOWNLOAD_ABORT   6
+ /* NXP HW err codes */
+ #define BTNXPUART_IR_HW_ERR           0xb0
+@@ -159,6 +160,7 @@ struct btnxpuart_dev {
+       u8 fw_name[MAX_FW_FILE_NAME_LEN];
+       u32 fw_dnld_v1_offset;
+       u32 fw_v1_sent_bytes;
++      u32 fw_dnld_v3_offset;
+       u32 fw_v3_offset_correction;
+       u32 fw_v1_expected_len;
+       u32 boot_reg_offset;
+@@ -566,6 +568,7 @@ static int nxp_download_firmware(struct hci_dev *hdev)
+       nxpdev->fw_v1_sent_bytes = 0;
+       nxpdev->fw_v1_expected_len = HDR_LEN;
+       nxpdev->boot_reg_offset = 0;
++      nxpdev->fw_dnld_v3_offset = 0;
+       nxpdev->fw_v3_offset_correction = 0;
+       nxpdev->baudrate_changed = false;
+       nxpdev->timeout_changed = false;
+@@ -580,14 +583,23 @@ static int nxp_download_firmware(struct hci_dev *hdev)
+                                              !test_bit(BTNXPUART_FW_DOWNLOADING,
+                                                        &nxpdev->tx_state),
+                                              msecs_to_jiffies(60000));
++
++      release_firmware(nxpdev->fw);
++      memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
++
+       if (err == 0) {
+-              bt_dev_err(hdev, "FW Download Timeout.");
++              bt_dev_err(hdev, "FW Download Timeout. offset: %d",
++                              nxpdev->fw_dnld_v1_offset ?
++                              nxpdev->fw_dnld_v1_offset :
++                              nxpdev->fw_dnld_v3_offset);
+               return -ETIMEDOUT;
+       }
++      if (test_bit(BTNXPUART_FW_DOWNLOAD_ABORT, &nxpdev->tx_state)) {
++              bt_dev_err(hdev, "FW Download Aborted");
++              return -EINTR;
++      }
+       serdev_device_set_flow_control(nxpdev->serdev, true);
+-      release_firmware(nxpdev->fw);
+-      memset(nxpdev->fw_name, 0, sizeof(nxpdev->fw_name));
+       /* Allow the downloaded FW to initialize */
+       msleep(1200);
+@@ -998,8 +1010,9 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
+               goto free_skb;
+       }
+-      serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data + offset -
+-                              nxpdev->fw_v3_offset_correction, len);
++      nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
++      serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
++                              nxpdev->fw_dnld_v3_offset, len);
+ free_skb:
+       kfree_skb(skb);
+@@ -1430,16 +1443,22 @@ static void nxp_serdev_remove(struct serdev_device *serdev)
+       struct btnxpuart_dev *nxpdev = serdev_device_get_drvdata(serdev);
+       struct hci_dev *hdev = nxpdev->hdev;
+-      /* Restore FW baudrate to fw_init_baudrate if changed.
+-       * This will ensure FW baudrate is in sync with
+-       * driver baudrate in case this driver is re-inserted.
+-       */
+-      if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
+-              nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
+-              nxp_set_baudrate_cmd(hdev, NULL);
++      if (is_fw_downloading(nxpdev)) {
++              set_bit(BTNXPUART_FW_DOWNLOAD_ABORT, &nxpdev->tx_state);
++              clear_bit(BTNXPUART_FW_DOWNLOADING, &nxpdev->tx_state);
++              wake_up_interruptible(&nxpdev->check_boot_sign_wait_q);
++              wake_up_interruptible(&nxpdev->fw_dnld_done_wait_q);
++      } else {
++              /* Restore FW baudrate to fw_init_baudrate if changed.
++               * This will ensure FW baudrate is in sync with
++               * driver baudrate in case this driver is re-inserted.
++               */
++              if (nxpdev->current_baudrate != nxpdev->fw_init_baudrate) {
++                      nxpdev->new_baudrate = nxpdev->fw_init_baudrate;
++                      nxp_set_baudrate_cmd(hdev, NULL);
++              }
++              ps_cancel_timer(nxpdev);
+       }
+-
+-      ps_cancel_timer(nxpdev);
+       hci_unregister_dev(hdev);
+       hci_free_dev(hdev);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/bluetooth-btnxpuart-resolve-tx-timeout-error-in-powe.patch b/queue-6.6/bluetooth-btnxpuart-resolve-tx-timeout-error-in-powe.patch
new file mode 100644 (file)
index 0000000..82d44a8
--- /dev/null
@@ -0,0 +1,153 @@
+From 9e3cbe604b3c1bf8c4be8aaa9a5afc207ff6072d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Dec 2023 18:59:27 +0530
+Subject: Bluetooth: btnxpuart: Resolve TX timeout error in power save stress
+ test
+
+From: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+
+[ Upstream commit e4db90e4eb8d5487098712ffb1048f3fa6d25e98 ]
+
+This fixes the tx timeout issue seen while running a stress test on
+btnxpuart for couple of hours, such that the interval between two HCI
+commands coincide with the power save timeout value of 2 seconds.
+
+Test procedure using bash script:
+<load btnxpuart.ko>
+hciconfig hci0 up
+//Enable Power Save feature
+hcitool -i hci0 cmd 3f 23 02 00 00
+while (true)
+do
+    hciconfig hci0 leadv
+    sleep 2
+    hciconfig hci0 noleadv
+    sleep 2
+done
+
+Error log, after adding few more debug prints:
+Bluetooth: btnxpuart_queue_skb(): 01 0A 20 01 00
+Bluetooth: hci0: Set UART break: on, status=0
+Bluetooth: hci0: btnxpuart_tx_wakeup() tx_work scheduled
+Bluetooth: hci0: btnxpuart_tx_work() dequeue: 01 0A 20 01 00
+Can't set advertise mode on hci0: Connection timed out (110)
+Bluetooth: hci0: command 0x200a tx timeout
+
+When the power save mechanism turns on UART break, and btnxpuart_tx_work()
+is scheduled simultaneously, psdata->ps_state is read as PS_STATE_AWAKE,
+which prevents the psdata->work from being scheduled, which is responsible
+to turn OFF UART break.
+
+This issue is fixed by adding a ps_lock mutex around UART break on/off as
+well as around ps_state read/write.
+btnxpuart_tx_wakeup() will now read updated ps_state value. If ps_state is
+PS_STATE_SLEEP, it will first schedule psdata->work, and then it will
+reschedule itself once UART break has been turned off and ps_state is
+PS_STATE_AWAKE.
+
+Tested above script for 50,000 iterations and TX timeout error was not
+observed anymore.
+
+Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 35237475384a ("Bluetooth: btnxpuart: Fix random crash seen while removing driver")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btnxpuart.c | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
+index b5d40e0e05f31..2e18f89a931b8 100644
+--- a/drivers/bluetooth/btnxpuart.c
++++ b/drivers/bluetooth/btnxpuart.c
+@@ -126,6 +126,7 @@ struct ps_data {
+       struct hci_dev *hdev;
+       struct work_struct work;
+       struct timer_list ps_timer;
++      struct mutex ps_lock;
+ };
+ struct wakeup_cmd_payload {
+@@ -333,6 +334,9 @@ static void ps_start_timer(struct btnxpuart_dev *nxpdev)
+       if (psdata->cur_psmode == PS_MODE_ENABLE)
+               mod_timer(&psdata->ps_timer, jiffies + msecs_to_jiffies(psdata->h2c_ps_interval));
++
++      if (psdata->ps_state == PS_STATE_AWAKE && psdata->ps_cmd == PS_CMD_ENTER_PS)
++              cancel_work_sync(&psdata->work);
+ }
+ static void ps_cancel_timer(struct btnxpuart_dev *nxpdev)
+@@ -353,6 +357,7 @@ static void ps_control(struct hci_dev *hdev, u8 ps_state)
+           !test_bit(BTNXPUART_SERDEV_OPEN, &nxpdev->tx_state))
+               return;
++      mutex_lock(&psdata->ps_lock);
+       switch (psdata->cur_h2c_wakeupmode) {
+       case WAKEUP_METHOD_DTR:
+               if (ps_state == PS_STATE_AWAKE)
+@@ -366,12 +371,15 @@ static void ps_control(struct hci_dev *hdev, u8 ps_state)
+                       status = serdev_device_break_ctl(nxpdev->serdev, 0);
+               else
+                       status = serdev_device_break_ctl(nxpdev->serdev, -1);
++              msleep(20); /* Allow chip to detect UART-break and enter sleep */
+               bt_dev_dbg(hdev, "Set UART break: %s, status=%d",
+                          str_on_off(ps_state == PS_STATE_SLEEP), status);
+               break;
+       }
+       if (!status)
+               psdata->ps_state = ps_state;
++      mutex_unlock(&psdata->ps_lock);
++
+       if (ps_state == PS_STATE_AWAKE)
+               btnxpuart_tx_wakeup(nxpdev);
+ }
+@@ -407,17 +415,25 @@ static void ps_setup(struct hci_dev *hdev)
+       psdata->hdev = hdev;
+       INIT_WORK(&psdata->work, ps_work_func);
++      mutex_init(&psdata->ps_lock);
+       timer_setup(&psdata->ps_timer, ps_timeout_func, 0);
+ }
+-static void ps_wakeup(struct btnxpuart_dev *nxpdev)
++static bool ps_wakeup(struct btnxpuart_dev *nxpdev)
+ {
+       struct ps_data *psdata = &nxpdev->psdata;
++      u8 ps_state;
+-      if (psdata->ps_state != PS_STATE_AWAKE) {
++      mutex_lock(&psdata->ps_lock);
++      ps_state = psdata->ps_state;
++      mutex_unlock(&psdata->ps_lock);
++
++      if (ps_state != PS_STATE_AWAKE) {
+               psdata->ps_cmd = PS_CMD_EXIT_PS;
+               schedule_work(&psdata->work);
++              return true;
+       }
++      return false;
+ }
+ static int send_ps_cmd(struct hci_dev *hdev, void *data)
+@@ -1215,7 +1231,6 @@ static struct sk_buff *nxp_dequeue(void *data)
+ {
+       struct btnxpuart_dev *nxpdev = (struct btnxpuart_dev *)data;
+-      ps_wakeup(nxpdev);
+       ps_start_timer(nxpdev);
+       return skb_dequeue(&nxpdev->txq);
+ }
+@@ -1230,6 +1245,9 @@ static void btnxpuart_tx_work(struct work_struct *work)
+       struct sk_buff *skb;
+       int len;
++      if (ps_wakeup(nxpdev))
++              return;
++
+       while ((skb = nxp_dequeue(nxpdev))) {
+               len = serdev_device_write_buf(serdev, skb->data, skb->len);
+               hdev->stat.byte_tx += len;
+-- 
+2.43.0
+
diff --git a/queue-6.6/bluetooth-hci_core-fix-not-handling-hibernation-acti.patch b/queue-6.6/bluetooth-hci_core-fix-not-handling-hibernation-acti.patch
new file mode 100644 (file)
index 0000000..730263e
--- /dev/null
@@ -0,0 +1,45 @@
+From e847cb630b2caf0990dc44008c0f493e57f44ea5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 14:41:52 -0400
+Subject: Bluetooth: hci_core: Fix not handling hibernation actions
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 18b3256db76bd1130965acd99fbd38f87c3e6950 ]
+
+This fixes not handling hibernation actions on suspend notifier so they
+are treated in the same way as regular suspend actions.
+
+Fixes: 9952d90ea288 ("Bluetooth: Handle PM_SUSPEND_PREPARE and PM_POST_SUSPEND")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index e660b3d661dae..1b56355c40eaf 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -2394,10 +2394,16 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action,
+       /* To avoid a potential race with hci_unregister_dev. */
+       hci_dev_hold(hdev);
+-      if (action == PM_SUSPEND_PREPARE)
++      switch (action) {
++      case PM_HIBERNATION_PREPARE:
++      case PM_SUSPEND_PREPARE:
+               ret = hci_suspend_dev(hdev);
+-      else if (action == PM_POST_SUSPEND)
++              break;
++      case PM_POST_HIBERNATION:
++      case PM_POST_SUSPEND:
+               ret = hci_resume_dev(hdev);
++              break;
++      }
+       if (ret)
+               bt_dev_err(hdev, "Suspend notifier action (%lu) failed: %d",
+-- 
+2.43.0
+
diff --git a/queue-6.6/bonding-change-ipsec_lock-from-spin-lock-to-mutex.patch b/queue-6.6/bonding-change-ipsec_lock-from-spin-lock-to-mutex.patch
new file mode 100644 (file)
index 0000000..d675cd2
--- /dev/null
@@ -0,0 +1,296 @@
+From 79fc51bddb6e6b369a5004e3052435ea575feb02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 06:10:56 +0300
+Subject: bonding: change ipsec_lock from spin lock to mutex
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit 2aeeef906d5a526dc60cf4af92eda69836c39b1f ]
+
+In the cited commit, bond->ipsec_lock is added to protect ipsec_list,
+hence xdo_dev_state_add and xdo_dev_state_delete are called inside
+this lock. As ipsec_lock is a spin lock and such xfrmdev ops may sleep,
+"scheduling while atomic" will be triggered when changing bond's
+active slave.
+
+[  101.055189] BUG: scheduling while atomic: bash/902/0x00000200
+[  101.055726] Modules linked in:
+[  101.058211] CPU: 3 PID: 902 Comm: bash Not tainted 6.9.0-rc4+ #1
+[  101.058760] Hardware name:
+[  101.059434] Call Trace:
+[  101.059436]  <TASK>
+[  101.060873]  dump_stack_lvl+0x51/0x60
+[  101.061275]  __schedule_bug+0x4e/0x60
+[  101.061682]  __schedule+0x612/0x7c0
+[  101.062078]  ? __mod_timer+0x25c/0x370
+[  101.062486]  schedule+0x25/0xd0
+[  101.062845]  schedule_timeout+0x77/0xf0
+[  101.063265]  ? asm_common_interrupt+0x22/0x40
+[  101.063724]  ? __bpf_trace_itimer_state+0x10/0x10
+[  101.064215]  __wait_for_common+0x87/0x190
+[  101.064648]  ? usleep_range_state+0x90/0x90
+[  101.065091]  cmd_exec+0x437/0xb20 [mlx5_core]
+[  101.065569]  mlx5_cmd_do+0x1e/0x40 [mlx5_core]
+[  101.066051]  mlx5_cmd_exec+0x18/0x30 [mlx5_core]
+[  101.066552]  mlx5_crypto_create_dek_key+0xea/0x120 [mlx5_core]
+[  101.067163]  ? bonding_sysfs_store_option+0x4d/0x80 [bonding]
+[  101.067738]  ? kmalloc_trace+0x4d/0x350
+[  101.068156]  mlx5_ipsec_create_sa_ctx+0x33/0x100 [mlx5_core]
+[  101.068747]  mlx5e_xfrm_add_state+0x47b/0xaa0 [mlx5_core]
+[  101.069312]  bond_change_active_slave+0x392/0x900 [bonding]
+[  101.069868]  bond_option_active_slave_set+0x1c2/0x240 [bonding]
+[  101.070454]  __bond_opt_set+0xa6/0x430 [bonding]
+[  101.070935]  __bond_opt_set_notify+0x2f/0x90 [bonding]
+[  101.071453]  bond_opt_tryset_rtnl+0x72/0xb0 [bonding]
+[  101.071965]  bonding_sysfs_store_option+0x4d/0x80 [bonding]
+[  101.072567]  kernfs_fop_write_iter+0x10c/0x1a0
+[  101.073033]  vfs_write+0x2d8/0x400
+[  101.073416]  ? alloc_fd+0x48/0x180
+[  101.073798]  ksys_write+0x5f/0xe0
+[  101.074175]  do_syscall_64+0x52/0x110
+[  101.074576]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+As bond_ipsec_add_sa_all and bond_ipsec_del_sa_all are only called
+from bond_change_active_slave, which requires holding the RTNL lock.
+And bond_ipsec_add_sa and bond_ipsec_del_sa are xfrm state
+xdo_dev_state_add and xdo_dev_state_delete APIs, which are in user
+context. So ipsec_lock doesn't have to be spin lock, change it to
+mutex, and thus the above issue can be resolved.
+
+Fixes: 9a5605505d9c ("bonding: Add struct bond_ipesc to manage SA")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Hangbin Liu <liuhangbin@gmail.com>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20240823031056.110999-4-jianbol@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 79 ++++++++++++++++++---------------
+ include/net/bonding.h           |  2 +-
+ 2 files changed, 44 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 6f61bb2f4b901..53a7b53618d94 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -428,6 +428,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+ {
+       struct net_device *bond_dev = xs->xso.dev;
+       struct net_device *real_dev;
++      netdevice_tracker tracker;
+       struct bond_ipsec *ipsec;
+       struct bonding *bond;
+       struct slave *slave;
+@@ -439,24 +440,26 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+       rcu_read_lock();
+       bond = netdev_priv(bond_dev);
+       slave = rcu_dereference(bond->curr_active_slave);
+-      if (!slave) {
+-              rcu_read_unlock();
+-              return -ENODEV;
++      real_dev = slave ? slave->dev : NULL;
++      netdev_hold(real_dev, &tracker, GFP_ATOMIC);
++      rcu_read_unlock();
++      if (!real_dev) {
++              err = -ENODEV;
++              goto out;
+       }
+-      real_dev = slave->dev;
+       if (!real_dev->xfrmdev_ops ||
+           !real_dev->xfrmdev_ops->xdo_dev_state_add ||
+           netif_is_bond_master(real_dev)) {
+               NL_SET_ERR_MSG_MOD(extack, "Slave does not support ipsec offload");
+-              rcu_read_unlock();
+-              return -EINVAL;
++              err = -EINVAL;
++              goto out;
+       }
+-      ipsec = kmalloc(sizeof(*ipsec), GFP_ATOMIC);
++      ipsec = kmalloc(sizeof(*ipsec), GFP_KERNEL);
+       if (!ipsec) {
+-              rcu_read_unlock();
+-              return -ENOMEM;
++              err = -ENOMEM;
++              goto out;
+       }
+       xs->xso.real_dev = real_dev;
+@@ -464,13 +467,14 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+       if (!err) {
+               ipsec->xs = xs;
+               INIT_LIST_HEAD(&ipsec->list);
+-              spin_lock_bh(&bond->ipsec_lock);
++              mutex_lock(&bond->ipsec_lock);
+               list_add(&ipsec->list, &bond->ipsec_list);
+-              spin_unlock_bh(&bond->ipsec_lock);
++              mutex_unlock(&bond->ipsec_lock);
+       } else {
+               kfree(ipsec);
+       }
+-      rcu_read_unlock();
++out:
++      netdev_put(real_dev, &tracker);
+       return err;
+ }
+@@ -481,35 +485,35 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
+       struct bond_ipsec *ipsec;
+       struct slave *slave;
+-      rcu_read_lock();
+-      slave = rcu_dereference(bond->curr_active_slave);
+-      if (!slave)
+-              goto out;
++      slave = rtnl_dereference(bond->curr_active_slave);
++      real_dev = slave ? slave->dev : NULL;
++      if (!real_dev)
++              return;
+-      real_dev = slave->dev;
++      mutex_lock(&bond->ipsec_lock);
+       if (!real_dev->xfrmdev_ops ||
+           !real_dev->xfrmdev_ops->xdo_dev_state_add ||
+           netif_is_bond_master(real_dev)) {
+-              spin_lock_bh(&bond->ipsec_lock);
+               if (!list_empty(&bond->ipsec_list))
+                       slave_warn(bond_dev, real_dev,
+                                  "%s: no slave xdo_dev_state_add\n",
+                                  __func__);
+-              spin_unlock_bh(&bond->ipsec_lock);
+               goto out;
+       }
+-      spin_lock_bh(&bond->ipsec_lock);
+       list_for_each_entry(ipsec, &bond->ipsec_list, list) {
++              /* If new state is added before ipsec_lock acquired */
++              if (ipsec->xs->xso.real_dev == real_dev)
++                      continue;
++
+               ipsec->xs->xso.real_dev = real_dev;
+               if (real_dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
+                       slave_warn(bond_dev, real_dev, "%s: failed to add SA\n", __func__);
+                       ipsec->xs->xso.real_dev = NULL;
+               }
+       }
+-      spin_unlock_bh(&bond->ipsec_lock);
+ out:
+-      rcu_read_unlock();
++      mutex_unlock(&bond->ipsec_lock);
+ }
+ /**
+@@ -520,6 +524,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+ {
+       struct net_device *bond_dev = xs->xso.dev;
+       struct net_device *real_dev;
++      netdevice_tracker tracker;
+       struct bond_ipsec *ipsec;
+       struct bonding *bond;
+       struct slave *slave;
+@@ -530,6 +535,9 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+       rcu_read_lock();
+       bond = netdev_priv(bond_dev);
+       slave = rcu_dereference(bond->curr_active_slave);
++      real_dev = slave ? slave->dev : NULL;
++      netdev_hold(real_dev, &tracker, GFP_ATOMIC);
++      rcu_read_unlock();
+       if (!slave)
+               goto out;
+@@ -537,7 +545,6 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+       if (!xs->xso.real_dev)
+               goto out;
+-      real_dev = slave->dev;
+       WARN_ON(xs->xso.real_dev != real_dev);
+       if (!real_dev->xfrmdev_ops ||
+@@ -549,7 +556,8 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+       real_dev->xfrmdev_ops->xdo_dev_state_delete(xs);
+ out:
+-      spin_lock_bh(&bond->ipsec_lock);
++      netdev_put(real_dev, &tracker);
++      mutex_lock(&bond->ipsec_lock);
+       list_for_each_entry(ipsec, &bond->ipsec_list, list) {
+               if (ipsec->xs == xs) {
+                       list_del(&ipsec->list);
+@@ -557,8 +565,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+                       break;
+               }
+       }
+-      spin_unlock_bh(&bond->ipsec_lock);
+-      rcu_read_unlock();
++      mutex_unlock(&bond->ipsec_lock);
+ }
+ static void bond_ipsec_del_sa_all(struct bonding *bond)
+@@ -568,15 +575,12 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
+       struct bond_ipsec *ipsec;
+       struct slave *slave;
+-      rcu_read_lock();
+-      slave = rcu_dereference(bond->curr_active_slave);
+-      if (!slave) {
+-              rcu_read_unlock();
++      slave = rtnl_dereference(bond->curr_active_slave);
++      real_dev = slave ? slave->dev : NULL;
++      if (!real_dev)
+               return;
+-      }
+-      real_dev = slave->dev;
+-      spin_lock_bh(&bond->ipsec_lock);
++      mutex_lock(&bond->ipsec_lock);
+       list_for_each_entry(ipsec, &bond->ipsec_list, list) {
+               if (!ipsec->xs->xso.real_dev)
+                       continue;
+@@ -593,8 +597,7 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
+                               real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
+               }
+       }
+-      spin_unlock_bh(&bond->ipsec_lock);
+-      rcu_read_unlock();
++      mutex_unlock(&bond->ipsec_lock);
+ }
+ static void bond_ipsec_free_sa(struct xfrm_state *xs)
+@@ -5941,7 +5944,7 @@ void bond_setup(struct net_device *bond_dev)
+       /* set up xfrm device ops (only supported in active-backup right now) */
+       bond_dev->xfrmdev_ops = &bond_xfrmdev_ops;
+       INIT_LIST_HEAD(&bond->ipsec_list);
+-      spin_lock_init(&bond->ipsec_lock);
++      mutex_init(&bond->ipsec_lock);
+ #endif /* CONFIG_XFRM_OFFLOAD */
+       /* don't acquire bond device's netif_tx_lock when transmitting */
+@@ -5990,6 +5993,10 @@ static void bond_uninit(struct net_device *bond_dev)
+               __bond_release_one(bond_dev, slave->dev, true, true);
+       netdev_info(bond_dev, "Released all slaves\n");
++#ifdef CONFIG_XFRM_OFFLOAD
++      mutex_destroy(&bond->ipsec_lock);
++#endif /* CONFIG_XFRM_OFFLOAD */
++
+       bond_set_slave_arr(bond, NULL, NULL);
+       list_del(&bond->bond_list);
+diff --git a/include/net/bonding.h b/include/net/bonding.h
+index 5b8b1b644a2db..94594026a5c55 100644
+--- a/include/net/bonding.h
++++ b/include/net/bonding.h
+@@ -258,7 +258,7 @@ struct bonding {
+ #ifdef CONFIG_XFRM_OFFLOAD
+       struct list_head ipsec_list;
+       /* protecting ipsec_list */
+-      spinlock_t ipsec_lock;
++      struct mutex ipsec_lock;
+ #endif /* CONFIG_XFRM_OFFLOAD */
+       struct bpf_prog *xdp_prog;
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.6/bonding-extract-the-use-of-real_device-into-local-va.patch b/queue-6.6/bonding-extract-the-use-of-real_device-into-local-va.patch
new file mode 100644 (file)
index 0000000..1130a9d
--- /dev/null
@@ -0,0 +1,175 @@
+From b178c921797c1e94e9710763600bc6d4dd8506a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 06:10:55 +0300
+Subject: bonding: extract the use of real_device into local variable
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit 907ed83a7583e8ffede88c5ac088392701a7d458 ]
+
+Add a local variable for slave->dev, to prepare for the lock change in
+the next patch. There is no functionality change.
+
+Fixes: 9a5605505d9c ("bonding: Add struct bond_ipesc to manage SA")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Hangbin Liu <liuhangbin@gmail.com>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20240823031056.110999-3-jianbol@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 58 +++++++++++++++++++--------------
+ 1 file changed, 33 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index c166c4b8cee78..6f61bb2f4b901 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -427,6 +427,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+                            struct netlink_ext_ack *extack)
+ {
+       struct net_device *bond_dev = xs->xso.dev;
++      struct net_device *real_dev;
+       struct bond_ipsec *ipsec;
+       struct bonding *bond;
+       struct slave *slave;
+@@ -443,9 +444,10 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+               return -ENODEV;
+       }
+-      if (!slave->dev->xfrmdev_ops ||
+-          !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
+-          netif_is_bond_master(slave->dev)) {
++      real_dev = slave->dev;
++      if (!real_dev->xfrmdev_ops ||
++          !real_dev->xfrmdev_ops->xdo_dev_state_add ||
++          netif_is_bond_master(real_dev)) {
+               NL_SET_ERR_MSG_MOD(extack, "Slave does not support ipsec offload");
+               rcu_read_unlock();
+               return -EINVAL;
+@@ -456,9 +458,9 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+               rcu_read_unlock();
+               return -ENOMEM;
+       }
+-      xs->xso.real_dev = slave->dev;
+-      err = slave->dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
++      xs->xso.real_dev = real_dev;
++      err = real_dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
+       if (!err) {
+               ipsec->xs = xs;
+               INIT_LIST_HEAD(&ipsec->list);
+@@ -475,6 +477,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
+ static void bond_ipsec_add_sa_all(struct bonding *bond)
+ {
+       struct net_device *bond_dev = bond->dev;
++      struct net_device *real_dev;
+       struct bond_ipsec *ipsec;
+       struct slave *slave;
+@@ -483,12 +486,13 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
+       if (!slave)
+               goto out;
+-      if (!slave->dev->xfrmdev_ops ||
+-          !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
+-          netif_is_bond_master(slave->dev)) {
++      real_dev = slave->dev;
++      if (!real_dev->xfrmdev_ops ||
++          !real_dev->xfrmdev_ops->xdo_dev_state_add ||
++          netif_is_bond_master(real_dev)) {
+               spin_lock_bh(&bond->ipsec_lock);
+               if (!list_empty(&bond->ipsec_list))
+-                      slave_warn(bond_dev, slave->dev,
++                      slave_warn(bond_dev, real_dev,
+                                  "%s: no slave xdo_dev_state_add\n",
+                                  __func__);
+               spin_unlock_bh(&bond->ipsec_lock);
+@@ -497,9 +501,9 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
+       spin_lock_bh(&bond->ipsec_lock);
+       list_for_each_entry(ipsec, &bond->ipsec_list, list) {
+-              ipsec->xs->xso.real_dev = slave->dev;
+-              if (slave->dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
+-                      slave_warn(bond_dev, slave->dev, "%s: failed to add SA\n", __func__);
++              ipsec->xs->xso.real_dev = real_dev;
++              if (real_dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
++                      slave_warn(bond_dev, real_dev, "%s: failed to add SA\n", __func__);
+                       ipsec->xs->xso.real_dev = NULL;
+               }
+       }
+@@ -515,6 +519,7 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
+ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+ {
+       struct net_device *bond_dev = xs->xso.dev;
++      struct net_device *real_dev;
+       struct bond_ipsec *ipsec;
+       struct bonding *bond;
+       struct slave *slave;
+@@ -532,16 +537,17 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+       if (!xs->xso.real_dev)
+               goto out;
+-      WARN_ON(xs->xso.real_dev != slave->dev);
++      real_dev = slave->dev;
++      WARN_ON(xs->xso.real_dev != real_dev);
+-      if (!slave->dev->xfrmdev_ops ||
+-          !slave->dev->xfrmdev_ops->xdo_dev_state_delete ||
+-          netif_is_bond_master(slave->dev)) {
+-              slave_warn(bond_dev, slave->dev, "%s: no slave xdo_dev_state_delete\n", __func__);
++      if (!real_dev->xfrmdev_ops ||
++          !real_dev->xfrmdev_ops->xdo_dev_state_delete ||
++          netif_is_bond_master(real_dev)) {
++              slave_warn(bond_dev, real_dev, "%s: no slave xdo_dev_state_delete\n", __func__);
+               goto out;
+       }
+-      slave->dev->xfrmdev_ops->xdo_dev_state_delete(xs);
++      real_dev->xfrmdev_ops->xdo_dev_state_delete(xs);
+ out:
+       spin_lock_bh(&bond->ipsec_lock);
+       list_for_each_entry(ipsec, &bond->ipsec_list, list) {
+@@ -558,6 +564,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
+ static void bond_ipsec_del_sa_all(struct bonding *bond)
+ {
+       struct net_device *bond_dev = bond->dev;
++      struct net_device *real_dev;
+       struct bond_ipsec *ipsec;
+       struct slave *slave;
+@@ -568,21 +575,22 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
+               return;
+       }
++      real_dev = slave->dev;
+       spin_lock_bh(&bond->ipsec_lock);
+       list_for_each_entry(ipsec, &bond->ipsec_list, list) {
+               if (!ipsec->xs->xso.real_dev)
+                       continue;
+-              if (!slave->dev->xfrmdev_ops ||
+-                  !slave->dev->xfrmdev_ops->xdo_dev_state_delete ||
+-                  netif_is_bond_master(slave->dev)) {
+-                      slave_warn(bond_dev, slave->dev,
++              if (!real_dev->xfrmdev_ops ||
++                  !real_dev->xfrmdev_ops->xdo_dev_state_delete ||
++                  netif_is_bond_master(real_dev)) {
++                      slave_warn(bond_dev, real_dev,
+                                  "%s: no slave xdo_dev_state_delete\n",
+                                  __func__);
+               } else {
+-                      slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
+-                      if (slave->dev->xfrmdev_ops->xdo_dev_state_free)
+-                              slave->dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
++                      real_dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
++                      if (real_dev->xfrmdev_ops->xdo_dev_state_free)
++                              real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
+               }
+       }
+       spin_unlock_bh(&bond->ipsec_lock);
+-- 
+2.43.0
+
diff --git a/queue-6.6/bonding-implement-xdo_dev_state_free-and-call-it-aft.patch b/queue-6.6/bonding-implement-xdo_dev_state_free-and-call-it-aft.patch
new file mode 100644 (file)
index 0000000..8e79f42
--- /dev/null
@@ -0,0 +1,94 @@
+From 5dc8ae40e807a1e2204b383975113ba41b56fc16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 06:10:54 +0300
+Subject: bonding: implement xdo_dev_state_free and call it after deletion
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit ec13009472f4a756288eb4e18e20a7845da98d10 ]
+
+Add this implementation for bonding, so hardware resources can be
+freed from the active slave after xfrm state is deleted. The netdev
+used to invoke xdo_dev_state_free callback, is saved in the xfrm state
+(xs->xso.real_dev), which is also the bond's active slave. To prevent
+it from being freed, acquire netdev reference before leaving RCU
+read-side critical section, and release it after callback is done.
+
+And call it when deleting all SAs from old active real interface while
+switching current active slave.
+
+Fixes: 9a5605505d9c ("bonding: Add struct bond_ipesc to manage SA")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Hangbin Liu <liuhangbin@gmail.com>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20240823031056.110999-2-jianbol@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 36 +++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 566b02ca78261..c166c4b8cee78 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -581,12 +581,47 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
+                                  __func__);
+               } else {
+                       slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
++                      if (slave->dev->xfrmdev_ops->xdo_dev_state_free)
++                              slave->dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
+               }
+       }
+       spin_unlock_bh(&bond->ipsec_lock);
+       rcu_read_unlock();
+ }
++static void bond_ipsec_free_sa(struct xfrm_state *xs)
++{
++      struct net_device *bond_dev = xs->xso.dev;
++      struct net_device *real_dev;
++      netdevice_tracker tracker;
++      struct bonding *bond;
++      struct slave *slave;
++
++      if (!bond_dev)
++              return;
++
++      rcu_read_lock();
++      bond = netdev_priv(bond_dev);
++      slave = rcu_dereference(bond->curr_active_slave);
++      real_dev = slave ? slave->dev : NULL;
++      netdev_hold(real_dev, &tracker, GFP_ATOMIC);
++      rcu_read_unlock();
++
++      if (!slave)
++              goto out;
++
++      if (!xs->xso.real_dev)
++              goto out;
++
++      WARN_ON(xs->xso.real_dev != real_dev);
++
++      if (real_dev && real_dev->xfrmdev_ops &&
++          real_dev->xfrmdev_ops->xdo_dev_state_free)
++              real_dev->xfrmdev_ops->xdo_dev_state_free(xs);
++out:
++      netdev_put(real_dev, &tracker);
++}
++
+ /**
+  * bond_ipsec_offload_ok - can this packet use the xfrm hw offload
+  * @skb: current data packet
+@@ -627,6 +662,7 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
+ static const struct xfrmdev_ops bond_xfrmdev_ops = {
+       .xdo_dev_state_add = bond_ipsec_add_sa,
+       .xdo_dev_state_delete = bond_ipsec_del_sa,
++      .xdo_dev_state_free = bond_ipsec_free_sa,
+       .xdo_dev_offload_ok = bond_ipsec_offload_ok,
+ };
+ #endif /* CONFIG_XFRM_OFFLOAD */
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-dw-add-memory-bus-width-verification.patch b/queue-6.6/dmaengine-dw-add-memory-bus-width-verification.patch
new file mode 100644 (file)
index 0000000..6e987f8
--- /dev/null
@@ -0,0 +1,186 @@
+From 42ca9a06ea5cc2b2f45e3612b43598c7b46ad796 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 10:50:47 +0300
+Subject: dmaengine: dw: Add memory bus width verification
+
+From: Serge Semin <fancer.lancer@gmail.com>
+
+[ Upstream commit d04b21bfa1c50a2ade4816cab6fdc91827b346b1 ]
+
+Currently in case of the DEV_TO_MEM or MEM_TO_DEV DMA transfers the memory
+data width (single transfer width) is determined based on the buffer
+length, buffer base address or DMA master-channel max address width
+capability. It isn't enough in case of the channel disabling prior the
+block transfer is finished. Here is what DW AHB DMA IP-core databook says
+regarding the port suspension (DMA-transfer pause) implementation in the
+controller:
+
+"When CTLx.SRC_TR_WIDTH < CTLx.DST_TR_WIDTH and the CFGx.CH_SUSP bit is
+high, the CFGx.FIFO_EMPTY is asserted once the contents of the FIFO do not
+permit a single word of CTLx.DST_TR_WIDTH to be formed. However, there may
+still be data in the channel FIFO, but not enough to form a single
+transfer of CTLx.DST_TR_WIDTH. In this scenario, once the channel is
+disabled, the remaining data in the channel FIFO is not transferred to the
+destination peripheral."
+
+So in case if the port gets to be suspended and then disabled it's
+possible to have the data silently discarded even though the controller
+reported that FIFO is empty and the CTLx.BLOCK_TS indicated the dropped
+data already received from the source device. This looks as if the data
+somehow got lost on a way from the peripheral device to memory and causes
+problems for instance in the DW APB UART driver, which pauses and disables
+the DMA-transfer as soon as the recv data timeout happens. Here is the way
+it looks:
+
+ Memory <------- DMA FIFO <------ UART FIFO <---------------- UART
+  DST_TR_WIDTH -+--------|       |         |
+                |        |       |         |                No more data
+   Current lvl -+--------|       |---------+- DMA-burst lvl
+                |        |       |---------+- Leftover data
+                |        |       |---------+- SRC_TR_WIDTH
+               -+--------+-------+---------+
+
+In the example above: no more data is getting received over the UART port
+and BLOCK_TS is not even close to be fully received; some data is left in
+the UART FIFO, but not enough to perform a bursted DMA-xfer to the DMA
+FIFO; some data is left in the DMA FIFO, but not enough to be passed
+further to the system memory in a single transfer. In this situation the
+8250 UART driver catches the recv timeout interrupt, pauses the
+DMA-transfer and terminates it completely, after which the IRQ handler
+manually fetches the leftover data from the UART FIFO into the
+recv-buffer. But since the DMA-channel has been disabled with the data
+left in the DMA FIFO, that data will be just discarded and the recv-buffer
+will have a gap of the "current lvl" size in the recv-buffer at the tail
+of the lately received data portion. So the data will be lost just due to
+the misconfigured DMA transfer.
+
+Note this is only relevant for the case of the transfer suspension and
+_disabling_. No problem will happen if the transfer will be re-enabled
+afterwards or the block transfer is fully completed. In the later case the
+"FIFO flush mode" will be executed at the transfer final stage in order to
+push out the data left in the DMA FIFO.
+
+In order to fix the denoted problem the DW AHB DMA-engine driver needs to
+make sure that the _bursted_ source transfer width is greater or equal to
+the single destination transfer (note the HW databook describes more
+strict constraint than actually required). Since the peripheral-device
+side is prescribed by the client driver logic, the memory-side can be only
+used for that. The solution can be easily implemented for the DEV_TO_MEM
+transfers just by adjusting the memory-channel address width. Sadly it's
+not that easy for the MEM_TO_DEV transfers since the mem-to-dma burst size
+is normally dynamically determined by the controller. So the only thing
+that can be done is to make sure that memory-side address width is greater
+than the peripheral device address width.
+
+Fixes: a09820043c9e ("dw_dmac: autoconfigure data_width or get it via platform data")
+Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20240802075100.6475-3-fancer.lancer@gmail.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/dw/core.c | 51 +++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 44 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
+index 11e269a31a092..b341a6f1b0438 100644
+--- a/drivers/dma/dw/core.c
++++ b/drivers/dma/dw/core.c
+@@ -622,12 +622,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+       struct dw_desc          *prev;
+       struct dw_desc          *first;
+       u32                     ctllo, ctlhi;
+-      u8                      m_master = dwc->dws.m_master;
+-      u8                      lms = DWC_LLP_LMS(m_master);
++      u8                      lms = DWC_LLP_LMS(dwc->dws.m_master);
+       dma_addr_t              reg;
+       unsigned int            reg_width;
+       unsigned int            mem_width;
+-      unsigned int            data_width = dw->pdata->data_width[m_master];
+       unsigned int            i;
+       struct scatterlist      *sg;
+       size_t                  total_len = 0;
+@@ -661,7 +659,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+                       mem = sg_dma_address(sg);
+                       len = sg_dma_len(sg);
+-                      mem_width = __ffs(data_width | mem | len);
++                      mem_width = __ffs(sconfig->src_addr_width | mem | len);
+ slave_sg_todev_fill_desc:
+                       desc = dwc_desc_get(dwc);
+@@ -721,7 +719,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+                       lli_write(desc, sar, reg);
+                       lli_write(desc, dar, mem);
+                       lli_write(desc, ctlhi, ctlhi);
+-                      mem_width = __ffs(data_width | mem);
++                      mem_width = __ffs(sconfig->dst_addr_width | mem);
+                       lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width));
+                       desc->len = dlen;
+@@ -813,6 +811,41 @@ static int dwc_verify_p_buswidth(struct dma_chan *chan)
+       return 0;
+ }
++static int dwc_verify_m_buswidth(struct dma_chan *chan)
++{
++      struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
++      struct dw_dma *dw = to_dw_dma(chan->device);
++      u32 reg_width, reg_burst, mem_width;
++
++      mem_width = dw->pdata->data_width[dwc->dws.m_master];
++
++      /*
++       * It's possible to have a data portion locked in the DMA FIFO in case
++       * of the channel suspension. Subsequent channel disabling will cause
++       * that data silent loss. In order to prevent that maintain the src and
++       * dst transfer widths coherency by means of the relation:
++       * (CTLx.SRC_TR_WIDTH * CTLx.SRC_MSIZE >= CTLx.DST_TR_WIDTH)
++       * Look for the details in the commit message that brings this change.
++       *
++       * Note the DMA configs utilized in the calculations below must have
++       * been verified to have correct values by this method call.
++       */
++      if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV) {
++              reg_width = dwc->dma_sconfig.dst_addr_width;
++              if (mem_width < reg_width)
++                      return -EINVAL;
++
++              dwc->dma_sconfig.src_addr_width = mem_width;
++      } else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) {
++              reg_width = dwc->dma_sconfig.src_addr_width;
++              reg_burst = rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst);
++
++              dwc->dma_sconfig.dst_addr_width = min(mem_width, reg_width * reg_burst);
++      }
++
++      return 0;
++}
++
+ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
+ {
+       struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+@@ -822,14 +855,18 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
+       memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
+       dwc->dma_sconfig.src_maxburst =
+-              clamp(dwc->dma_sconfig.src_maxburst, 0U, dwc->max_burst);
++              clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst);
+       dwc->dma_sconfig.dst_maxburst =
+-              clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst);
++              clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst);
+       ret = dwc_verify_p_buswidth(chan);
+       if (ret)
+               return ret;
++      ret = dwc_verify_m_buswidth(chan);
++      if (ret)
++              return ret;
++
+       dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst);
+       dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst);
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-dw-add-peripheral-bus-width-verification.patch b/queue-6.6/dmaengine-dw-add-peripheral-bus-width-verification.patch
new file mode 100644 (file)
index 0000000..fe39e52
--- /dev/null
@@ -0,0 +1,112 @@
+From 32a9e8097932d7c85f5a0a55fa4a1272affc7d2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 10:50:46 +0300
+Subject: dmaengine: dw: Add peripheral bus width verification
+
+From: Serge Semin <fancer.lancer@gmail.com>
+
+[ Upstream commit b336268dde75cb09bd795cb24893d52152a9191f ]
+
+Currently the src_addr_width and dst_addr_width fields of the
+dma_slave_config structure are mapped to the CTLx.SRC_TR_WIDTH and
+CTLx.DST_TR_WIDTH fields of the peripheral bus side in order to have the
+properly aligned data passed to the target device. It's done just by
+converting the passed peripheral bus width to the encoded value using the
+__ffs() function. This implementation has several problematic sides:
+
+1. __ffs() is undefined if no bit exist in the passed value. Thus if the
+specified addr-width is DMA_SLAVE_BUSWIDTH_UNDEFINED, __ffs() may return
+unexpected value depending on the platform-specific implementation.
+
+2. DW AHB DMA-engine permits having the power-of-2 transfer width limited
+by the DMAH_Mk_HDATA_WIDTH IP-core synthesize parameter. Specifying
+bus-width out of that constraints scope will definitely cause unexpected
+result since the destination reg will be only partly touched than the
+client driver implied.
+
+Let's fix all of that by adding the peripheral bus width verification
+method and calling it in dwc_config() which is supposed to be executed
+before preparing any transfer. The new method will make sure that the
+passed source or destination address width is valid and if undefined then
+the driver will just fallback to the 1-byte width transfer.
+
+Fixes: 029a40e97d0d ("dmaengine: dw: provide DMA capabilities")
+Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
+Acked-by: Andy Shevchenko <andy@kernel.org>
+Link: https://lore.kernel.org/r/20240802075100.6475-2-fancer.lancer@gmail.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/dw/core.c | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
+index 5f7d690e3dbae..11e269a31a092 100644
+--- a/drivers/dma/dw/core.c
++++ b/drivers/dma/dw/core.c
+@@ -16,6 +16,7 @@
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
++#include <linux/log2.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+@@ -780,10 +781,43 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
+ }
+ EXPORT_SYMBOL_GPL(dw_dma_filter);
++static int dwc_verify_p_buswidth(struct dma_chan *chan)
++{
++      struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
++      struct dw_dma *dw = to_dw_dma(chan->device);
++      u32 reg_width, max_width;
++
++      if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
++              reg_width = dwc->dma_sconfig.dst_addr_width;
++      else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
++              reg_width = dwc->dma_sconfig.src_addr_width;
++      else /* DMA_MEM_TO_MEM */
++              return 0;
++
++      max_width = dw->pdata->data_width[dwc->dws.p_master];
++
++      /* Fall-back to 1-byte transfer width if undefined */
++      if (reg_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
++              reg_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
++      else if (!is_power_of_2(reg_width) || reg_width > max_width)
++              return -EINVAL;
++      else /* bus width is valid */
++              return 0;
++
++      /* Update undefined addr width value */
++      if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
++              dwc->dma_sconfig.dst_addr_width = reg_width;
++      else /* DMA_DEV_TO_MEM */
++              dwc->dma_sconfig.src_addr_width = reg_width;
++
++      return 0;
++}
++
+ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
+ {
+       struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+       struct dw_dma *dw = to_dw_dma(chan->device);
++      int ret;
+       memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
+@@ -792,6 +826,10 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
+       dwc->dma_sconfig.dst_maxburst =
+               clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst);
++      ret = dwc_verify_p_buswidth(chan);
++      if (ret)
++              return ret;
++
+       dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst);
+       dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst);
+-- 
+2.43.0
+
diff --git a/queue-6.6/drm-amd-display-avoid-using-null-object-of-framebuff.patch b/queue-6.6/drm-amd-display-avoid-using-null-object-of-framebuff.patch
new file mode 100644 (file)
index 0000000..70f4a78
--- /dev/null
@@ -0,0 +1,54 @@
+From 66f4a98d5ffdf6f20869c72018607d1d60ae0abc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 12:27:24 +0800
+Subject: drm/amd/display: avoid using null object of framebuffer
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+[ Upstream commit 3b9a33235c773c7a3768060cf1d2cf8a9153bc37 ]
+
+Instead of using state->fb->obj[0] directly, get object from framebuffer
+by calling drm_gem_fb_get_obj() and return error code when object is
+null to avoid using null object of framebuffer.
+
+Fixes: 5d945cbcd4b1 ("drm/amd/display: Create a file dedicated to planes")
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 73dd0ad9e5dad53766ea3e631303430116f834b3)
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+index cc74dd69acf2b..fa9f53b310793 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+@@ -28,6 +28,7 @@
+ #include <drm/drm_blend.h>
+ #include <drm/drm_gem_atomic_helper.h>
+ #include <drm/drm_plane_helper.h>
++#include <drm/drm_gem_framebuffer_helper.h>
+ #include <drm/drm_fourcc.h>
+ #include "amdgpu.h"
+@@ -848,10 +849,14 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
+       }
+       afb = to_amdgpu_framebuffer(new_state->fb);
+-      obj = new_state->fb->obj[0];
++      obj = drm_gem_fb_get_obj(new_state->fb, 0);
++      if (!obj) {
++              DRM_ERROR("Failed to get obj from framebuffer\n");
++              return -EINVAL;
++      }
++
+       rbo = gem_to_amdgpu_bo(obj);
+       adev = amdgpu_ttm_adev(rbo->tbo.bdev);
+-
+       r = amdgpu_bo_reserve(rbo, true);
+       if (r) {
+               dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
+-- 
+2.43.0
+
diff --git a/queue-6.6/ethtool-check-device-is-present-when-getting-link-se.patch b/queue-6.6/ethtool-check-device-is-present-when-getting-link-se.patch
new file mode 100644 (file)
index 0000000..6e036a9
--- /dev/null
@@ -0,0 +1,79 @@
+From c0cbec7bc59154ce89964cec2996b2dcfbf57fa2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 16:26:58 +1000
+Subject: ethtool: check device is present when getting link settings
+
+From: Jamie Bainbridge <jamie.bainbridge@gmail.com>
+
+[ Upstream commit a699781c79ecf6cfe67fb00a0331b4088c7c8466 ]
+
+A sysfs reader can race with a device reset or removal, attempting to
+read device state when the device is not actually present. eg:
+
+     [exception RIP: qed_get_current_link+17]
+  #8 [ffffb9e4f2907c48] qede_get_link_ksettings at ffffffffc07a994a [qede]
+  #9 [ffffb9e4f2907cd8] __rh_call_get_link_ksettings at ffffffff992b01a3
+ #10 [ffffb9e4f2907d38] __ethtool_get_link_ksettings at ffffffff992b04e4
+ #11 [ffffb9e4f2907d90] duplex_show at ffffffff99260300
+ #12 [ffffb9e4f2907e38] dev_attr_show at ffffffff9905a01c
+ #13 [ffffb9e4f2907e50] sysfs_kf_seq_show at ffffffff98e0145b
+ #14 [ffffb9e4f2907e68] seq_read at ffffffff98d902e3
+ #15 [ffffb9e4f2907ec8] vfs_read at ffffffff98d657d1
+ #16 [ffffb9e4f2907f00] ksys_read at ffffffff98d65c3f
+ #17 [ffffb9e4f2907f38] do_syscall_64 at ffffffff98a052fb
+
+ crash> struct net_device.state ffff9a9d21336000
+    state = 5,
+
+state 5 is __LINK_STATE_START (0b1) and __LINK_STATE_NOCARRIER (0b100).
+The device is not present, note lack of __LINK_STATE_PRESENT (0b10).
+
+This is the same sort of panic as observed in commit 4224cfd7fb65
+("net-sysfs: add check for netdevice being present to speed_show").
+
+There are many other callers of __ethtool_get_link_ksettings() which
+don't have a device presence check.
+
+Move this check into ethtool to protect all callers.
+
+Fixes: d519e17e2d01 ("net: export device speed and duplex via sysfs")
+Fixes: 4224cfd7fb65 ("net-sysfs: add check for netdevice being present to speed_show")
+Signed-off-by: Jamie Bainbridge <jamie.bainbridge@gmail.com>
+Link: https://patch.msgid.link/8bae218864beaa44ed01628140475b9bf641c5b0.1724393671.git.jamie.bainbridge@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/net-sysfs.c | 2 +-
+ net/ethtool/ioctl.c  | 3 +++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index 5a9487af44e00..f7404bc679746 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -216,7 +216,7 @@ static ssize_t speed_show(struct device *dev,
+       if (!rtnl_trylock())
+               return restart_syscall();
+-      if (netif_running(netdev) && netif_device_present(netdev)) {
++      if (netif_running(netdev)) {
+               struct ethtool_link_ksettings cmd;
+               if (!__ethtool_get_link_ksettings(netdev, &cmd))
+diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
+index 7cb23bcf8ef7a..4486cbe2faf0c 100644
+--- a/net/ethtool/ioctl.c
++++ b/net/ethtool/ioctl.c
+@@ -438,6 +438,9 @@ int __ethtool_get_link_ksettings(struct net_device *dev,
+       if (!dev->ethtool_ops->get_link_ksettings)
+               return -EOPNOTSUPP;
++      if (!netif_device_present(dev))
++              return -ENODEV;
++
+       memset(link_ksettings, 0, sizeof(*link_ksettings));
+       return dev->ethtool_ops->get_link_ksettings(dev, link_ksettings);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/gtp-fix-a-potential-null-pointer-dereference.patch b/queue-6.6/gtp-fix-a-potential-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..700f83a
--- /dev/null
@@ -0,0 +1,47 @@
+From 6b32829b640ba515d43feab8691119ee66a8c7c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 25 Aug 2024 12:16:38 -0700
+Subject: gtp: fix a potential NULL pointer dereference
+
+From: Cong Wang <cong.wang@bytedance.com>
+
+[ Upstream commit defd8b3c37b0f9cb3e0f60f47d3d78d459d57fda ]
+
+When sockfd_lookup() fails, gtp_encap_enable_socket() returns a
+NULL pointer, but its callers only check for error pointers thus miss
+the NULL pointer case.
+
+Fix it by returning an error pointer with the error code carried from
+sockfd_lookup().
+
+(I found this bug during code inspection.)
+
+Fixes: 1e3a3abd8b28 ("gtp: make GTP sockets in gtp_newlink optional")
+Cc: Andreas Schultz <aschultz@tpip.net>
+Cc: Harald Welte <laforge@gnumonks.org>
+Signed-off-by: Cong Wang <cong.wang@bytedance.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Link: https://patch.msgid.link/20240825191638.146748-1-xiyou.wangcong@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/gtp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
+index 931b65591f4d1..9b0b22b65cb25 100644
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1220,7 +1220,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
+       sock = sockfd_lookup(fd, &err);
+       if (!sock) {
+               pr_debug("gtp socket fd=%d not found\n", fd);
+-              return NULL;
++              return ERR_PTR(err);
+       }
+       sk = sock->sk;
+-- 
+2.43.0
+
diff --git a/queue-6.6/iommu-do-not-return-0-from-map_pages-if-it-doesn-t-d.patch b/queue-6.6/iommu-do-not-return-0-from-map_pages-if-it-doesn-t-d.patch
new file mode 100644 (file)
index 0000000..368805b
--- /dev/null
@@ -0,0 +1,84 @@
+From eec24b3bfac998ce642f177660ae1b24ebf897f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Aug 2024 11:45:55 -0300
+Subject: iommu: Do not return 0 from map_pages if it doesn't do anything
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 6093cd582f8e027117a8d4ad5d129a1aacdc53d2 ]
+
+These three implementations of map_pages() all succeed if a mapping is
+requested with no read or write. Since they return back to __iommu_map()
+leaving the mapped output as 0 it triggers an infinite loop. Therefore
+nothing is using no-access protection bits.
+
+Further, VFIO and iommufd rely on iommu_iova_to_phys() to get back PFNs
+stored by map, if iommu_map() succeeds but iommu_iova_to_phys() fails that
+will create serious bugs.
+
+Thus remove this never used "nothing to do" concept and just fail map
+immediately.
+
+Fixes: e5fc9753b1a8 ("iommu/io-pgtable: Add ARMv7 short descriptor support")
+Fixes: e1d3c0fd701d ("iommu: add ARM LPAE page table allocator")
+Fixes: 745ef1092bcf ("iommu/io-pgtable: Move Apple DART support to its own file")
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Acked-by: Will Deacon <will@kernel.org>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/2-v1-1211e1294c27+4b1-iommu_no_prot_jgg@nvidia.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/io-pgtable-arm-v7s.c | 3 +--
+ drivers/iommu/io-pgtable-arm.c     | 3 +--
+ drivers/iommu/io-pgtable-dart.c    | 3 +--
+ 3 files changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c
+index 75f244a3e12df..06ffc683b28fe 100644
+--- a/drivers/iommu/io-pgtable-arm-v7s.c
++++ b/drivers/iommu/io-pgtable-arm-v7s.c
+@@ -552,9 +552,8 @@ static int arm_v7s_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+                   paddr >= (1ULL << data->iop.cfg.oas)))
+               return -ERANGE;
+-      /* If no access, then nothing to do */
+       if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
+-              return 0;
++              return -EINVAL;
+       while (pgcount--) {
+               ret = __arm_v7s_map(data, iova, paddr, pgsize, prot, 1, data->pgd,
+diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
+index 72dcdd468cf30..934dc97f5df9e 100644
+--- a/drivers/iommu/io-pgtable-arm.c
++++ b/drivers/iommu/io-pgtable-arm.c
+@@ -480,9 +480,8 @@ static int arm_lpae_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+       if (WARN_ON(iaext || paddr >> cfg->oas))
+               return -ERANGE;
+-      /* If no access, then nothing to do */
+       if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
+-              return 0;
++              return -EINVAL;
+       prot = arm_lpae_prot_to_pte(data, iommu_prot);
+       ret = __arm_lpae_map(data, iova, paddr, pgsize, pgcount, prot, lvl,
+diff --git a/drivers/iommu/io-pgtable-dart.c b/drivers/iommu/io-pgtable-dart.c
+index 74b1ef2b96bee..10811e0b773d3 100644
+--- a/drivers/iommu/io-pgtable-dart.c
++++ b/drivers/iommu/io-pgtable-dart.c
+@@ -250,9 +250,8 @@ static int dart_map_pages(struct io_pgtable_ops *ops, unsigned long iova,
+       if (WARN_ON(paddr >> cfg->oas))
+               return -ERANGE;
+-      /* If no access, then nothing to do */
+       if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE)))
+-              return 0;
++              return -EINVAL;
+       tbl = dart_get_table(data, iova);
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-busy-poll-use-ktime_get_ns-instead-of-local_cloc.patch b/queue-6.6/net-busy-poll-use-ktime_get_ns-instead-of-local_cloc.patch
new file mode 100644 (file)
index 0000000..73841a4
--- /dev/null
@@ -0,0 +1,48 @@
+From 1b5926becffbdbe026b537da608706deef2e9f07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 11:49:16 +0000
+Subject: net: busy-poll: use ktime_get_ns() instead of local_clock()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 0870b0d8b393dde53106678a1e2cec9dfa52f9b7 ]
+
+Typically, busy-polling durations are below 100 usec.
+
+When/if the busy-poller thread migrates to another cpu,
+local_clock() can be off by +/-2msec or more for small
+values of HZ, depending on the platform.
+
+Use ktimer_get_ns() to ensure deterministic behavior,
+which is the whole point of busy-polling.
+
+Fixes: 060212928670 ("net: add low latency socket poll")
+Fixes: 9a3c71aa8024 ("net: convert low latency sockets to sched_clock()")
+Fixes: 37089834528b ("sched, net: Fixup busy_loop_us_clock()")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Mina Almasry <almasrymina@google.com>
+Cc: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Joe Damato <jdamato@fastly.com>
+Link: https://patch.msgid.link/20240827114916.223377-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/busy_poll.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h
+index 4dabeb6c76d31..9f2ce4d05c265 100644
+--- a/include/net/busy_poll.h
++++ b/include/net/busy_poll.h
+@@ -64,7 +64,7 @@ static inline bool sk_can_busy_loop(struct sock *sk)
+ static inline unsigned long busy_loop_current_time(void)
+ {
+ #ifdef CONFIG_NET_RX_BUSY_POLL
+-      return (unsigned long)(local_clock() >> 10);
++      return (unsigned long)(ktime_get_ns() >> 10);
+ #else
+       return 0;
+ #endif
+-- 
+2.43.0
+
diff --git a/queue-6.6/netfilter-nf_tables-restore-ip-sanity-checks-for-net.patch b/queue-6.6/netfilter-nf_tables-restore-ip-sanity-checks-for-net.patch
new file mode 100644 (file)
index 0000000..51b2702
--- /dev/null
@@ -0,0 +1,67 @@
+From ae26c6ba30f0ff17723b7e5d545e4faaa2b9b1df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 12:45:22 +0200
+Subject: netfilter: nf_tables: restore IP sanity checks for netdev/egress
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 5fd0628918977a0afdc2e6bc562d8751b5d3b8c5 ]
+
+Subtract network offset to skb->len before performing IPv4 header sanity
+checks, then adjust transport offset from offset from mac header.
+
+Jorge Ortiz says:
+
+When small UDP packets (< 4 bytes payload) are sent from eth0,
+`meta l4proto udp` condition is not met because `NFT_PKTINFO_L4PROTO` is
+not set. This happens because there is a comparison that checks if the
+transport header offset exceeds the total length.  This comparison does
+not take into account the fact that the skb network offset might be
+non-zero in egress mode (e.g., 14 bytes for Ethernet header).
+
+Fixes: 0ae8e4cca787 ("netfilter: nf_tables: set transport offset from mac header for netdev/egress")
+Reported-by: Jorge Ortiz <jorge.ortiz.escribano@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables_ipv4.h | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h
+index 60a7d0ce30804..fcf967286e37c 100644
+--- a/include/net/netfilter/nf_tables_ipv4.h
++++ b/include/net/netfilter/nf_tables_ipv4.h
+@@ -19,7 +19,7 @@ static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt)
+ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
+ {
+       struct iphdr *iph, _iph;
+-      u32 len, thoff;
++      u32 len, thoff, skb_len;
+       iph = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
+                                sizeof(*iph), &_iph);
+@@ -30,8 +30,10 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
+               return -1;
+       len = iph_totlen(pkt->skb, iph);
+-      thoff = skb_network_offset(pkt->skb) + (iph->ihl * 4);
+-      if (pkt->skb->len < len)
++      thoff = iph->ihl * 4;
++      skb_len = pkt->skb->len - skb_network_offset(pkt->skb);
++
++      if (skb_len < len)
+               return -1;
+       else if (len < thoff)
+               return -1;
+@@ -40,7 +42,7 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
+       pkt->flags = NFT_PKTINFO_L4PROTO;
+       pkt->tprot = iph->protocol;
+-      pkt->thoff = thoff;
++      pkt->thoff = skb_network_offset(pkt->skb) + thoff;
+       pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/netfilter-nf_tables_ipv6-consider-network-offset-in-.patch b/queue-6.6/netfilter-nf_tables_ipv6-consider-network-offset-in-.patch
new file mode 100644 (file)
index 0000000..dd21759
--- /dev/null
@@ -0,0 +1,47 @@
+From 50900654b260404970596b2a6a977cf0c69323c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 15:03:23 +0200
+Subject: netfilter: nf_tables_ipv6: consider network offset in netdev/egress
+ validation
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 70c261d500951cf3ea0fcf32651aab9a65a91471 ]
+
+From netdev/egress, skb->len can include the ethernet header, therefore,
+subtract network offset from skb->len when validating IPv6 packet length.
+
+Fixes: 42df6e1d221d ("netfilter: Introduce egress hook")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables_ipv6.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h
+index 467d59b9e5334..a0633eeaec977 100644
+--- a/include/net/netfilter/nf_tables_ipv6.h
++++ b/include/net/netfilter/nf_tables_ipv6.h
+@@ -31,8 +31,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
+       struct ipv6hdr *ip6h, _ip6h;
+       unsigned int thoff = 0;
+       unsigned short frag_off;
++      u32 pkt_len, skb_len;
+       int protohdr;
+-      u32 pkt_len;
+       ip6h = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
+                                 sizeof(*ip6h), &_ip6h);
+@@ -43,7 +43,8 @@ static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
+               return -1;
+       pkt_len = ntohs(ip6h->payload_len);
+-      if (pkt_len + sizeof(*ip6h) > pkt->skb->len)
++      skb_len = pkt->skb->len - skb_network_offset(pkt->skb);
++      if (pkt_len + sizeof(*ip6h) > skb_len)
+               return -1;
+       protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
+-- 
+2.43.0
+
diff --git a/queue-6.6/nfc-pn533-add-poll-mod-list-filling-check.patch b/queue-6.6/nfc-pn533-add-poll-mod-list-filling-check.patch
new file mode 100644 (file)
index 0000000..73ee989
--- /dev/null
@@ -0,0 +1,62 @@
+From f72dcdb5c3b86ced312e3a7562ea587c5d720fb7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Aug 2024 11:48:22 +0300
+Subject: nfc: pn533: Add poll mod list filling check
+
+From: Aleksandr Mishin <amishin@t-argos.ru>
+
+[ Upstream commit febccb39255f9df35527b88c953b2e0deae50e53 ]
+
+In case of im_protocols value is 1 and tm_protocols value is 0 this
+combination successfully passes the check
+'if (!im_protocols && !tm_protocols)' in the nfc_start_poll().
+But then after pn533_poll_create_mod_list() call in pn533_start_poll()
+poll mod list will remain empty and dev->poll_mod_count will remain 0
+which lead to division by zero.
+
+Normally no im protocol has value 1 in the mask, so this combination is
+not expected by driver. But these protocol values actually come from
+userspace via Netlink interface (NFC_CMD_START_POLL operation). So a
+broken or malicious program may pass a message containing a "bad"
+combination of protocol parameter values so that dev->poll_mod_count
+is not incremented inside pn533_poll_create_mod_list(), thus leading
+to division by zero.
+Call trace looks like:
+nfc_genl_start_poll()
+  nfc_start_poll()
+    ->start_poll()
+    pn533_start_poll()
+
+Add poll mod list filling check.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: dfccd0f58044 ("NFC: pn533: Add some polling entropy")
+Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20240827084822.18785-1-amishin@t-argos.ru
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/pn533/pn533.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c
+index b19c39dcfbd93..e2bc67300a915 100644
+--- a/drivers/nfc/pn533/pn533.c
++++ b/drivers/nfc/pn533/pn533.c
+@@ -1723,6 +1723,11 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
+       }
+       pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
++      if (!dev->poll_mod_count) {
++              nfc_err(dev->dev,
++                      "Poll mod list is empty\n");
++              return -EINVAL;
++      }
+       /* Do not always start polling from the same modulation */
+       get_random_bytes(&rand_mod, sizeof(rand_mod));
+-- 
+2.43.0
+
diff --git a/queue-6.6/phy-xilinx-phy-zynqmp-fix-sgmii-linkup-failure-on-re.patch b/queue-6.6/phy-xilinx-phy-zynqmp-fix-sgmii-linkup-failure-on-re.patch
new file mode 100644 (file)
index 0000000..8786df5
--- /dev/null
@@ -0,0 +1,140 @@
+From ffaf9eb83a3d1630152e5f54092924bf5e7c8941 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 11:29:07 +0530
+Subject: phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume
+
+From: Piyush Mehta <piyush.mehta@amd.com>
+
+[ Upstream commit 5af9b304bc6010723c02f74de0bfd24ff19b1a10 ]
+
+On a few Kria KR260 Robotics Starter Kit the PS-GEM SGMII linkup is not
+happening after the resume. This is because serdes registers are reset
+when FPD is off (in suspend state) and needs to be reprogrammed in the
+resume path with the same default initialization as done in the first
+stage bootloader psu_init routine.
+
+To address the failure introduce a set of serdes registers to be saved in
+the suspend path and then restore it on resume.
+
+Fixes: 4a33bea00314 ("phy: zynqmp: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver")
+Signed-off-by: Piyush Mehta <piyush.mehta@amd.com>
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Link: https://lore.kernel.org/r/1722837547-2578381-1-git-send-email-radhey.shyam.pandey@amd.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/xilinx/phy-zynqmp.c | 56 +++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
+index 0cb5088e460b5..8c8b1ca31e4c4 100644
+--- a/drivers/phy/xilinx/phy-zynqmp.c
++++ b/drivers/phy/xilinx/phy-zynqmp.c
+@@ -166,6 +166,24 @@
+ /* Timeout values */
+ #define TIMEOUT_US                    1000
++/* Lane 0/1/2/3 offset */
++#define DIG_8(n)              ((0x4000 * (n)) + 0x1074)
++#define ILL13(n)              ((0x4000 * (n)) + 0x1994)
++#define DIG_10(n)             ((0x4000 * (n)) + 0x107c)
++#define RST_DLY(n)            ((0x4000 * (n)) + 0x19a4)
++#define BYP_15(n)             ((0x4000 * (n)) + 0x1038)
++#define BYP_12(n)             ((0x4000 * (n)) + 0x102c)
++#define MISC3(n)              ((0x4000 * (n)) + 0x19ac)
++#define EQ11(n)                       ((0x4000 * (n)) + 0x1978)
++
++static u32 save_reg_address[] = {
++      /* Lane 0/1/2/3 Register */
++      DIG_8(0), ILL13(0), DIG_10(0), RST_DLY(0), BYP_15(0), BYP_12(0), MISC3(0), EQ11(0),
++      DIG_8(1), ILL13(1), DIG_10(1), RST_DLY(1), BYP_15(1), BYP_12(1), MISC3(1), EQ11(1),
++      DIG_8(2), ILL13(2), DIG_10(2), RST_DLY(2), BYP_15(2), BYP_12(2), MISC3(2), EQ11(2),
++      DIG_8(3), ILL13(3), DIG_10(3), RST_DLY(3), BYP_15(3), BYP_12(3), MISC3(3), EQ11(3),
++};
++
+ struct xpsgtr_dev;
+ /**
+@@ -214,6 +232,7 @@ struct xpsgtr_phy {
+  * @tx_term_fix: fix for GT issue
+  * @saved_icm_cfg0: stored value of ICM CFG0 register
+  * @saved_icm_cfg1: stored value of ICM CFG1 register
++ * @saved_regs: registers to be saved/restored during suspend/resume
+  */
+ struct xpsgtr_dev {
+       struct device *dev;
+@@ -226,6 +245,7 @@ struct xpsgtr_dev {
+       bool tx_term_fix;
+       unsigned int saved_icm_cfg0;
+       unsigned int saved_icm_cfg1;
++      u32 *saved_regs;
+ };
+ /*
+@@ -299,6 +319,32 @@ static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy,
+       writel((readl(addr) & ~clr) | set, addr);
+ }
++/**
++ * xpsgtr_save_lane_regs - Saves registers on suspend
++ * @gtr_dev: pointer to phy controller context structure
++ */
++static void xpsgtr_save_lane_regs(struct xpsgtr_dev *gtr_dev)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
++              gtr_dev->saved_regs[i] = xpsgtr_read(gtr_dev,
++                                                   save_reg_address[i]);
++}
++
++/**
++ * xpsgtr_restore_lane_regs - Restores registers on resume
++ * @gtr_dev: pointer to phy controller context structure
++ */
++static void xpsgtr_restore_lane_regs(struct xpsgtr_dev *gtr_dev)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
++              xpsgtr_write(gtr_dev, save_reg_address[i],
++                           gtr_dev->saved_regs[i]);
++}
++
+ /*
+  * Hardware Configuration
+  */
+@@ -839,6 +885,8 @@ static int xpsgtr_runtime_suspend(struct device *dev)
+       gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
+       gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
++      xpsgtr_save_lane_regs(gtr_dev);
++
+       return 0;
+ }
+@@ -849,6 +897,8 @@ static int xpsgtr_runtime_resume(struct device *dev)
+       unsigned int i;
+       bool skip_phy_init;
++      xpsgtr_restore_lane_regs(gtr_dev);
++
+       icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
+       icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
+@@ -994,6 +1044,12 @@ static int xpsgtr_probe(struct platform_device *pdev)
+               return ret;
+       }
++      gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
++                                         sizeof(save_reg_address),
++                                         GFP_KERNEL);
++      if (!gtr_dev->saved_regs)
++              return -ENOMEM;
++
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/sctp-fix-association-labeling-in-the-duplicate-cooki.patch b/queue-6.6/sctp-fix-association-labeling-in-the-duplicate-cooki.patch
new file mode 100644 (file)
index 0000000..ed8b923
--- /dev/null
@@ -0,0 +1,96 @@
+From ba58735d357a00e24cbad494a465e474f65210af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 15:07:11 +0200
+Subject: sctp: fix association labeling in the duplicate COOKIE-ECHO case
+
+From: Ondrej Mosnacek <omosnace@redhat.com>
+
+[ Upstream commit 3a0504d54b3b57f0d7bf3d9184a00c9f8887f6d7 ]
+
+sctp_sf_do_5_2_4_dupcook() currently calls security_sctp_assoc_request()
+on new_asoc, but as it turns out, this association is always discarded
+and the LSM labels never get into the final association (asoc).
+
+This can be reproduced by having two SCTP endpoints try to initiate an
+association with each other at approximately the same time and then peel
+off the association into a new socket, which exposes the unitialized
+labels and triggers SELinux denials.
+
+Fix it by calling security_sctp_assoc_request() on asoc instead of
+new_asoc. Xin Long also suggested limit calling the hook only to cases
+A, B, and D, since in cases C and E the COOKIE ECHO chunk is discarded
+and the association doesn't enter the ESTABLISHED state, so rectify that
+as well.
+
+One related caveat with SELinux and peer labeling: When an SCTP
+connection is set up simultaneously in this way, we will end up with an
+association that is initialized with security_sctp_assoc_request() on
+both sides, so the MLS component of the security context of the
+association will get swapped between the peers, instead of just one side
+setting it to the other's MLS component. However, at that point
+security_sctp_assoc_request() had already been called on both sides in
+sctp_sf_do_unexpected_init() (on a temporary association) and thus if
+the exchange didn't fail before due to MLS, it won't fail now either
+(most likely both endpoints have the same MLS range).
+
+Tested by:
+ - reproducer from https://src.fedoraproject.org/tests/selinux/pull-request/530
+ - selinux-testsuite (https://github.com/SELinuxProject/selinux-testsuite/)
+ - sctp-tests (https://github.com/sctp/sctp-tests) - no tests failed
+   that wouldn't fail also without the patch applied
+
+Fixes: c081d53f97a1 ("security: pass asoc to sctp_assoc_request and sctp_sk_clone")
+Suggested-by: Xin Long <lucien.xin@gmail.com>
+Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Paul Moore <paul@paul-moore.com> (LSM/SELinux)
+Link: https://patch.msgid.link/20240826130711.141271-1-omosnace@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/sm_statefuns.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
+index 08fdf1251f46a..3649a4e1eb9de 100644
+--- a/net/sctp/sm_statefuns.c
++++ b/net/sctp/sm_statefuns.c
+@@ -2259,12 +2259,6 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
+               }
+       }
+-      /* Update socket peer label if first association. */
+-      if (security_sctp_assoc_request(new_asoc, chunk->head_skb ?: chunk->skb)) {
+-              sctp_association_free(new_asoc);
+-              return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+-      }
+-
+       /* Set temp so that it won't be added into hashtable */
+       new_asoc->temp = 1;
+@@ -2273,6 +2267,22 @@ enum sctp_disposition sctp_sf_do_5_2_4_dupcook(
+        */
+       action = sctp_tietags_compare(new_asoc, asoc);
++      /* In cases C and E the association doesn't enter the ESTABLISHED
++       * state, so there is no need to call security_sctp_assoc_request().
++       */
++      switch (action) {
++      case 'A': /* Association restart. */
++      case 'B': /* Collision case B. */
++      case 'D': /* Collision case D. */
++              /* Update socket peer label if first association. */
++              if (security_sctp_assoc_request((struct sctp_association *)asoc,
++                                              chunk->head_skb ?: chunk->skb)) {
++                      sctp_association_free(new_asoc);
++                      return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
++              }
++              break;
++      }
++
+       switch (action) {
+       case 'A': /* Association restart. */
+               retval = sctp_sf_do_dupcook_a(net, ep, asoc, chunk, commands,
+-- 
+2.43.0
+
diff --git a/queue-6.6/selftests-forwarding-local_termination-down-ports-on.patch b/queue-6.6/selftests-forwarding-local_termination-down-ports-on.patch
new file mode 100644 (file)
index 0000000..d904c59
--- /dev/null
@@ -0,0 +1,38 @@
+From 804c2686a43e741cedde79c9a511844a84d3bc79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Aug 2024 19:15:11 +0200
+Subject: selftests: forwarding: local_termination: Down ports on cleanup
+
+From: Petr Machata <petrm@nvidia.com>
+
+[ Upstream commit 65a3cce43d5b4c53cf16b0be1a03991f665a0806 ]
+
+This test neglects to put ports down on cleanup. Fix it.
+
+Fixes: 90b9566aa5cd ("selftests: forwarding: add a test for local_termination.sh")
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/bf9b79f45de378f88344d44550f0a5052b386199.1724692132.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/forwarding/local_termination.sh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/tools/testing/selftests/net/forwarding/local_termination.sh b/tools/testing/selftests/net/forwarding/local_termination.sh
+index c5b0cbc85b3e0..9b5a63519b949 100755
+--- a/tools/testing/selftests/net/forwarding/local_termination.sh
++++ b/tools/testing/selftests/net/forwarding/local_termination.sh
+@@ -278,6 +278,10 @@ bridge()
+ cleanup()
+ {
+       pre_cleanup
++
++      ip link set $h2 down
++      ip link set $h1 down
++
+       vrf_cleanup
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/selftests-forwarding-no_forwarding-down-ports-on-cle.patch b/queue-6.6/selftests-forwarding-no_forwarding-down-ports-on-cle.patch
new file mode 100644 (file)
index 0000000..8f90731
--- /dev/null
@@ -0,0 +1,38 @@
+From 9cd2a1b268a723e1d4028149a68adeebaf977aab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Aug 2024 18:25:37 +0200
+Subject: selftests: forwarding: no_forwarding: Down ports on cleanup
+
+From: Petr Machata <petrm@nvidia.com>
+
+[ Upstream commit e8497d6951ee8541d73784f9aac9942a7f239980 ]
+
+This test neglects to put ports down on cleanup. Fix it.
+
+Fixes: 476a4f05d9b8 ("selftests: forwarding: add a no_forwarding.sh test")
+Signed-off-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/0baf91dc24b95ae0cadfdf5db05b74888e6a228a.1724430120.git.petrm@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/forwarding/no_forwarding.sh | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tools/testing/selftests/net/forwarding/no_forwarding.sh b/tools/testing/selftests/net/forwarding/no_forwarding.sh
+index af3b398d13f01..9e677aa64a06a 100755
+--- a/tools/testing/selftests/net/forwarding/no_forwarding.sh
++++ b/tools/testing/selftests/net/forwarding/no_forwarding.sh
+@@ -233,6 +233,9 @@ cleanup()
+ {
+       pre_cleanup
++      ip link set dev $swp2 down
++      ip link set dev $swp1 down
++
+       h2_destroy
+       h1_destroy
+-- 
+2.43.0
+
index aaf9ca967dbe791b6a92be041bc18b71efbf5f72..531d5a385be38c4a1ee9e3501a5eda61c2734c79 100644 (file)
@@ -45,3 +45,25 @@ phy-fsl-imx8mq-usb-fix-tuning-parameter-name.patch
 soundwire-stream-fix-programming-slave-ports-for-non-continous-port-maps.patch
 dmaengine-dw-edma-fix-unmasking-stop-and-abort-interrupts-for-hdma.patch
 dmaengine-dw-edma-do-not-enable-watermark-interrupts-for-hdma.patch
+phy-xilinx-phy-zynqmp-fix-sgmii-linkup-failure-on-re.patch
+dmaengine-dw-add-peripheral-bus-width-verification.patch
+dmaengine-dw-add-memory-bus-width-verification.patch
+bluetooth-btnxpuart-resolve-tx-timeout-error-in-powe.patch
+bluetooth-btnxpuart-handle-fw-download-abort-scenari.patch
+bluetooth-btnxpuart-fix-random-crash-seen-while-remo.patch
+bluetooth-hci_core-fix-not-handling-hibernation-acti.patch
+iommu-do-not-return-0-from-map_pages-if-it-doesn-t-d.patch
+netfilter-nf_tables-restore-ip-sanity-checks-for-net.patch
+wifi-iwlwifi-fw-fix-wgds-rev-3-exact-size.patch
+ethtool-check-device-is-present-when-getting-link-se.patch
+netfilter-nf_tables_ipv6-consider-network-offset-in-.patch
+selftests-forwarding-no_forwarding-down-ports-on-cle.patch
+selftests-forwarding-local_termination-down-ports-on.patch
+bonding-implement-xdo_dev_state_free-and-call-it-aft.patch
+bonding-extract-the-use-of-real_device-into-local-va.patch
+bonding-change-ipsec_lock-from-spin-lock-to-mutex.patch
+gtp-fix-a-potential-null-pointer-dereference.patch
+sctp-fix-association-labeling-in-the-duplicate-cooki.patch
+drm-amd-display-avoid-using-null-object-of-framebuff.patch
+net-busy-poll-use-ktime_get_ns-instead-of-local_cloc.patch
+nfc-pn533-add-poll-mod-list-filling-check.patch
diff --git a/queue-6.6/wifi-iwlwifi-fw-fix-wgds-rev-3-exact-size.patch b/queue-6.6/wifi-iwlwifi-fw-fix-wgds-rev-3-exact-size.patch
new file mode 100644 (file)
index 0000000..b6f5f42
--- /dev/null
@@ -0,0 +1,63 @@
+From f7e7be27fb6c7c161c18fa8746f6cd0b20cd18d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 25 Aug 2024 19:17:08 +0300
+Subject: wifi: iwlwifi: fw: fix wgds rev 3 exact size
+
+From: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
+
+[ Upstream commit 3ee22f07a35b76939c5b8d17d6af292f5fafb509 ]
+
+Check size of WGDS revision 3 is equal to 8 entries size with some header,
+but doesn't depend on the number of used entries. Check that used entries
+are between min and max but allow more to be present than are used to fix
+operation with some BIOSes that have such data.
+
+Fixes: 97f8a3d1610b ("iwlwifi: ACPI: support revision 3 WGDS tables")
+Signed-off-by: Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
+Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
+Link: https://patch.msgid.link/20240825191257.cc71dfc67ec3.Ic27ee15ac6128b275c210b6de88f2145bd83ca7b@changeid
+[edit commit message]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+index 2cda1dcfd059a..9943e2d21a8f5 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+@@ -867,22 +867,25 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
+                               entry = &wifi_pkg->package.elements[entry_idx];
+                               entry_idx++;
+                               if (entry->type != ACPI_TYPE_INTEGER ||
+-                                  entry->integer.value > num_profiles) {
++                                  entry->integer.value > num_profiles ||
++                                  entry->integer.value <
++                                      rev_data[idx].min_profiles) {
+                                       ret = -EINVAL;
+                                       goto out_free;
+                               }
+-                              num_profiles = entry->integer.value;
+                               /*
+-                               * this also validates >= min_profiles since we
+-                               * otherwise wouldn't have gotten the data when
+-                               * looking up in ACPI
++                               * Check to see if we received package count
++                               * same as max # of profiles
+                                */
+                               if (wifi_pkg->package.count !=
+                                   hdr_size + profile_size * num_profiles) {
+                                       ret = -EINVAL;
+                                       goto out_free;
+                               }
++
++                              /* Number of valid profiles */
++                              num_profiles = entry->integer.value;
+                       }
+                       goto read_table;
+               }
+-- 
+2.43.0
+