]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.12
authorSasha Levin <sashal@kernel.org>
Sun, 15 Jun 2025 13:01:11 +0000 (09:01 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 15 Jun 2025 13:01:11 +0000 (09:01 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
53 files changed:
queue-6.12/acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch [new file with mode: 0644]
queue-6.12/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch [new file with mode: 0644]
queue-6.12/bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch [new file with mode: 0644]
queue-6.12/bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch [new file with mode: 0644]
queue-6.12/bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch [new file with mode: 0644]
queue-6.12/bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch [new file with mode: 0644]
queue-6.12/bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch [new file with mode: 0644]
queue-6.12/bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch [new file with mode: 0644]
queue-6.12/bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-fix-sparse-errors.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch [new file with mode: 0644]
queue-6.12/bluetooth-mgmt-remove-unused-mgmt_pending_find_data.patch [new file with mode: 0644]
queue-6.12/drm-meson-fix-debug-log-statement-when-setting-the-h.patch [new file with mode: 0644]
queue-6.12/drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch [new file with mode: 0644]
queue-6.12/drm-meson-use-unsigned-long-long-hz-for-frequency-ty.patch [new file with mode: 0644]
queue-6.12/drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch [new file with mode: 0644]
queue-6.12/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch [new file with mode: 0644]
queue-6.12/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch [new file with mode: 0644]
queue-6.12/macsec-macsec-sci-assignment-for-es-0.patch [new file with mode: 0644]
queue-6.12/net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch [new file with mode: 0644]
queue-6.12/net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch [new file with mode: 0644]
queue-6.12/net-fix-toctou-issue-in-sk_is_readable.patch [new file with mode: 0644]
queue-6.12/net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch [new file with mode: 0644]
queue-6.12/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch [new file with mode: 0644]
queue-6.12/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch [new file with mode: 0644]
queue-6.12/net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch [new file with mode: 0644]
queue-6.12/net-mlx5-fix-return-value-when-searching-for-existin.patch [new file with mode: 0644]
queue-6.12/net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch [new file with mode: 0644]
queue-6.12/net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch [new file with mode: 0644]
queue-6.12/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch [new file with mode: 0644]
queue-6.12/net_sched-prio-fix-a-race-in-prio_tune.patch [new file with mode: 0644]
queue-6.12/net_sched-red-fix-a-race-in-__red_change.patch [new file with mode: 0644]
queue-6.12/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch [new file with mode: 0644]
queue-6.12/net_sched-tbf-fix-a-race-in-tbf_change.patch [new file with mode: 0644]
queue-6.12/pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch [new file with mode: 0644]
queue-6.12/powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch [new file with mode: 0644]
queue-6.12/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch [new file with mode: 0644]
queue-6.12/ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch [new file with mode: 0644]
queue-6.12/regulator-max20086-fix-refcount-leak-in-max20086_par.patch [new file with mode: 0644]
queue-6.12/scsi-core-ufs-fix-a-hang-in-the-error-handler.patch [new file with mode: 0644]
queue-6.12/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch [new file with mode: 0644]
queue-6.12/spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch [new file with mode: 0644]
queue-6.12/wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch [new file with mode: 0644]
queue-6.12/wifi-ath11k-convert-timeouts-to-secs_to_jiffies.patch [new file with mode: 0644]
queue-6.12/wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch [new file with mode: 0644]
queue-6.12/wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch [new file with mode: 0644]
queue-6.12/wifi-ath11k-move-some-firmware-stats-related-functio.patch [new file with mode: 0644]
queue-6.12/wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch [new file with mode: 0644]
queue-6.12/wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch [new file with mode: 0644]
queue-6.12/wifi-ath12k-refactor-ath12k_hw_regs-structure.patch [new file with mode: 0644]

diff --git a/queue-6.12/acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch b/queue-6.12/acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch
new file mode 100644 (file)
index 0000000..4771a59
--- /dev/null
@@ -0,0 +1,48 @@
+From 21495a124f7cab39f769655862d3aac41fd5cac0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Jun 2025 10:30:36 +0800
+Subject: ACPI: CPPC: Fix NULL pointer dereference when nosmp is used
+
+From: Yunhui Cui <cuiyunhui@bytedance.com>
+
+[ Upstream commit 15eece6c5b05e5f9db0711978c3e3b7f1a2cfe12 ]
+
+With nosmp in cmdline, other CPUs are not brought up, leaving
+their cpc_desc_ptr NULL. CPU0's iteration via for_each_possible_cpu()
+dereferences these NULL pointers, causing panic.
+
+Panic backtrace:
+
+[    0.401123] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000b8
+...
+[    0.403255] [<ffffffff809a5818>] cppc_allow_fast_switch+0x6a/0xd4
+...
+Kernel panic - not syncing: Attempted to kill init!
+
+Fixes: 3cc30dd00a58 ("cpufreq: CPPC: Enable fast_switch")
+Reported-by: Xu Lu <luxu.kernel@bytedance.com>
+Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
+Link: https://patch.msgid.link/20250604023036.99553-1-cuiyunhui@bytedance.com
+[ rjw: New subject ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/cppc_acpi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index e78e3754d99e1..dab941dc984a9 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -463,7 +463,7 @@ bool cppc_allow_fast_switch(void)
+       struct cpc_desc *cpc_ptr;
+       int cpu;
+-      for_each_possible_cpu(cpu) {
++      for_each_present_cpu(cpu) {
+               cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
+               desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF];
+               if (!CPC_IN_SYSTEM_MEMORY(desired_reg) &&
+-- 
+2.39.5
+
diff --git a/queue-6.12/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch b/queue-6.12/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch
new file mode 100644 (file)
index 0000000..91d7160
--- /dev/null
@@ -0,0 +1,49 @@
+From 8e5b3a2f87c0820130bf1ca93ac4ccccd3b72946 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 20:50:27 +0000
+Subject: ath10k: snoc: fix unbalanced IRQ enable in crash recovery
+
+From: Caleb Connolly <caleb.connolly@linaro.org>
+
+[ Upstream commit 1650d32b92b01db03a1a95d69ee74fcbc34d4b00 ]
+
+In ath10k_snoc_hif_stop() we skip disabling the IRQs in the crash
+recovery flow, but we still unconditionally call enable again in
+ath10k_snoc_hif_start().
+
+We can't check the ATH10K_FLAG_CRASH_FLUSH bit since it is cleared
+before hif_start() is called, so instead check the
+ATH10K_SNOC_FLAG_RECOVERY flag and skip enabling the IRQs during crash
+recovery.
+
+This fixes unbalanced IRQ enable splats that happen after recovering from
+a crash.
+
+Fixes: 0e622f67e041 ("ath10k: add support for WCN3990 firmware crash recovery")
+Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
+Tested-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250318205043.1043148-1-caleb.connolly@linaro.org
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath10k/snoc.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
+index 0fe47d51013c7..59f7ccb33fde3 100644
+--- a/drivers/net/wireless/ath/ath10k/snoc.c
++++ b/drivers/net/wireless/ath/ath10k/snoc.c
+@@ -937,7 +937,9 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)
+       dev_set_threaded(ar->napi_dev, true);
+       ath10k_core_napi_enable(ar);
+-      ath10k_snoc_irq_enable(ar);
++      /* IRQs are left enabled when we restart due to a firmware crash */
++      if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags))
++              ath10k_snoc_irq_enable(ar);
+       ath10k_snoc_rx_post(ar);
+       clear_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags);
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch b/queue-6.12/bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch
new file mode 100644 (file)
index 0000000..0b08f50
--- /dev/null
@@ -0,0 +1,77 @@
+From 2931df0101d6c0a47fda9449b9163d678d66e2cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Jun 2025 15:34:38 +0530
+Subject: Bluetooth: btintel_pcie: Fix driver not posting maximum rx buffers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kiran K <kiran.k@intel.com>
+
+[ Upstream commit daabd276985055250528da97e9ce6d277d7009c2 ]
+
+The driver was posting only 6 rx buffers, despite the maximum rx buffers
+being defined as 16. Having fewer RX buffers caused firmware exceptions
+in HID use cases when events arrived in bursts.
+
+Exception seen on android 6.12 kernel.
+
+E Bluetooth: hci0: Received hw exception interrupt
+E Bluetooth: hci0: Received gp1 mailbox interrupt
+D Bluetooth: hci0: 00000000: ff 3e 87 80 03 01 01 01 03 01 0c 0d 02 1c 10 0e
+D Bluetooth: hci0: 00000010: 01 00 05 14 66 b0 28 b0 c0 b0 28 b0 ac af 28 b0
+D Bluetooth: hci0: 00000020: 14 f1 28 b0 00 00 00 00 fa 04 00 00 00 00 40 10
+D Bluetooth: hci0: 00000030: 08 00 00 00 7a 7a 7a 7a 47 00 fb a0 10 00 00 00
+D Bluetooth: hci0: 00000000: 10 01 0a
+E Bluetooth: hci0: ---- Dump of debug registers —
+E Bluetooth: hci0: boot stage: 0xe0fb0047
+E Bluetooth: hci0: ipc status: 0x00000004
+E Bluetooth: hci0: ipc control: 0x00000000
+E Bluetooth: hci0: ipc sleep control: 0x00000000
+E Bluetooth: hci0: mbox_1: 0x00badbad
+E Bluetooth: hci0: mbox_2: 0x0000101c
+E Bluetooth: hci0: mbox_3: 0x00000008
+E Bluetooth: hci0: mbox_4: 0x7a7a7a7a
+
+Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btintel_pcie.c | 3 ++-
+ drivers/bluetooth/btintel_pcie.h | 3 ---
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
+index d225f0a37f985..b8065b7ec70b6 100644
+--- a/drivers/bluetooth/btintel_pcie.c
++++ b/drivers/bluetooth/btintel_pcie.c
+@@ -231,8 +231,9 @@ static int btintel_pcie_submit_rx(struct btintel_pcie_data *data)
+ static int btintel_pcie_start_rx(struct btintel_pcie_data *data)
+ {
+       int i, ret;
++      struct rxq *rxq = &data->rxq;
+-      for (i = 0; i < BTINTEL_PCIE_RX_MAX_QUEUE; i++) {
++      for (i = 0; i < rxq->count; i++) {
+               ret = btintel_pcie_submit_rx(data);
+               if (ret)
+                       return ret;
+diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
+index 8b7824ad005a2..5f7747f334ab8 100644
+--- a/drivers/bluetooth/btintel_pcie.h
++++ b/drivers/bluetooth/btintel_pcie.h
+@@ -104,9 +104,6 @@ enum {
+ /* Doorbell vector for TFD */
+ #define BTINTEL_PCIE_TX_DB_VEC        0
+-/* Number of pending RX requests for downlink */
+-#define BTINTEL_PCIE_RX_MAX_QUEUE     6
+-
+ /* Doorbell vector for FRBD */
+ #define BTINTEL_PCIE_RX_DB_VEC        513
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch b/queue-6.12/bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch
new file mode 100644 (file)
index 0000000..b73e055
--- /dev/null
@@ -0,0 +1,107 @@
+From f835c1dfca3710f7b0dc328d7181844689069ddf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Jun 2025 15:34:39 +0530
+Subject: Bluetooth: btintel_pcie: Increase the tx and rx descriptor count
+
+From: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
+
+[ Upstream commit 2dd711102ce69ae41f65d09c012441227d4aa983 ]
+
+This change addresses latency issues observed in HID use cases where
+events arrive in bursts. By increasing the Rx descriptor count to 64,
+the firmware can handle bursty data more effectively, reducing latency
+and preventing buffer overflows.
+
+Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btintel_pcie.c | 24 ++++++++++++------------
+ drivers/bluetooth/btintel_pcie.h |  7 +++++--
+ 2 files changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
+index b8065b7ec70b6..c02d671396e24 100644
+--- a/drivers/bluetooth/btintel_pcie.c
++++ b/drivers/bluetooth/btintel_pcie.c
+@@ -1148,8 +1148,8 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data)
+        *  + size of index * Number of queues(2) * type of index array(4)
+        *  + size of context information
+        */
+-      total = (sizeof(struct tfd) + sizeof(struct urbd0) + sizeof(struct frbd)
+-              + sizeof(struct urbd1)) * BTINTEL_DESCS_COUNT;
++      total = (sizeof(struct tfd) + sizeof(struct urbd0)) * BTINTEL_PCIE_TX_DESCS_COUNT;
++      total += (sizeof(struct frbd) + sizeof(struct urbd1)) * BTINTEL_PCIE_RX_DESCS_COUNT;
+       /* Add the sum of size of index array and size of ci struct */
+       total += (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4) + sizeof(struct ctx_info);
+@@ -1174,36 +1174,36 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data)
+       data->dma_v_addr = v_addr;
+       /* Setup descriptor count */
+-      data->txq.count = BTINTEL_DESCS_COUNT;
+-      data->rxq.count = BTINTEL_DESCS_COUNT;
++      data->txq.count = BTINTEL_PCIE_TX_DESCS_COUNT;
++      data->rxq.count = BTINTEL_PCIE_RX_DESCS_COUNT;
+       /* Setup tfds */
+       data->txq.tfds_p_addr = p_addr;
+       data->txq.tfds = v_addr;
+-      p_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT);
+-      v_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT);
++      p_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT);
++      v_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT);
+       /* Setup urbd0 */
+       data->txq.urbd0s_p_addr = p_addr;
+       data->txq.urbd0s = v_addr;
+-      p_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT);
+-      v_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT);
++      p_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT);
++      v_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT);
+       /* Setup FRBD*/
+       data->rxq.frbds_p_addr = p_addr;
+       data->rxq.frbds = v_addr;
+-      p_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT);
+-      v_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT);
++      p_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT);
++      v_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT);
+       /* Setup urbd1 */
+       data->rxq.urbd1s_p_addr = p_addr;
+       data->rxq.urbd1s = v_addr;
+-      p_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT);
+-      v_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT);
++      p_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT);
++      v_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT);
+       /* Setup data buffers for txq */
+       err = btintel_pcie_setup_txq_bufs(data, &data->txq);
+diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
+index 5f7747f334ab8..ee0eec0237afd 100644
+--- a/drivers/bluetooth/btintel_pcie.h
++++ b/drivers/bluetooth/btintel_pcie.h
+@@ -81,8 +81,11 @@ enum {
+ /* Default interrupt timeout in msec */
+ #define BTINTEL_DEFAULT_INTR_TIMEOUT_MS       3000
+-/* The number of descriptors in TX/RX queues */
+-#define BTINTEL_DESCS_COUNT   16
++/* The number of descriptors in TX queues */
++#define BTINTEL_PCIE_TX_DESCS_COUNT   32
++
++/* The number of descriptors in RX queues */
++#define BTINTEL_PCIE_RX_DESCS_COUNT   64
+ /* Number of Queue for TX and RX
+  * It indicates the index of the IA(Index Array)
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch b/queue-6.12/bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch
new file mode 100644 (file)
index 0000000..2a6628c
--- /dev/null
@@ -0,0 +1,44 @@
+From 08e26ca4796785b6e99ddb102b4609b18ac316bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Jun 2025 15:34:40 +0530
+Subject: Bluetooth: btintel_pcie: Reduce driver buffer posting to prevent race
+ condition
+
+From: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
+
+[ Upstream commit bf2ffc4d14db29cab781549912d2dc69127f4d3e ]
+
+Modify the driver to post 3 fewer buffers than the maximum rx buffers
+(64) allowed for the firmware. This change mitigates a hardware issue
+causing a race condition in the firmware, improving stability and data
+handling.
+
+Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bluetooth/btintel_pcie.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
+index c02d671396e24..34812bf7587d6 100644
+--- a/drivers/bluetooth/btintel_pcie.c
++++ b/drivers/bluetooth/btintel_pcie.c
+@@ -233,7 +233,11 @@ static int btintel_pcie_start_rx(struct btintel_pcie_data *data)
+       int i, ret;
+       struct rxq *rxq = &data->rxq;
+-      for (i = 0; i < rxq->count; i++) {
++      /* Post (BTINTEL_PCIE_RX_DESCS_COUNT - 3) buffers to overcome the
++       * hardware issues leading to race condition at the firmware.
++       */
++
++      for (i = 0; i < rxq->count - 3; i++) {
+               ret = btintel_pcie_submit_rx(data);
+               if (ret)
+                       return ret;
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch b/queue-6.12/bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch
new file mode 100644 (file)
index 0000000..92ef74a
--- /dev/null
@@ -0,0 +1,93 @@
+From ddd6ab1a39af148774b4cabddaacc7c48ab329c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 10:14:35 -0400
+Subject: Bluetooth: eir: Fix possible crashes on eir_create_adv_data
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 47c03902269aff377f959dc3fd94a9733aa31d6e ]
+
+eir_create_adv_data may attempt to add EIR_FLAGS and EIR_TX_POWER
+without checking if that would fit.
+
+Link: https://github.com/bluez/bluez/issues/1117#issuecomment-2958244066
+Fixes: 01ce70b0a274 ("Bluetooth: eir: Move EIR/Adv Data functions to its own file")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/eir.c      | 7 ++++---
+ net/bluetooth/eir.h      | 2 +-
+ net/bluetooth/hci_sync.c | 5 +++--
+ 3 files changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/eir.c b/net/bluetooth/eir.c
+index 3e1713673ecc9..3f72111ba651f 100644
+--- a/net/bluetooth/eir.c
++++ b/net/bluetooth/eir.c
+@@ -242,7 +242,7 @@ u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
+       return ad_len;
+ }
+-u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
++u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size)
+ {
+       struct adv_info *adv = NULL;
+       u8 ad_len = 0, flags = 0;
+@@ -286,7 +286,7 @@ u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
+               /* If flags would still be empty, then there is no need to
+                * include the "Flags" AD field".
+                */
+-              if (flags) {
++              if (flags && (ad_len + eir_precalc_len(1) <= size)) {
+                       ptr[0] = 0x02;
+                       ptr[1] = EIR_FLAGS;
+                       ptr[2] = flags;
+@@ -316,7 +316,8 @@ u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr)
+               }
+               /* Provide Tx Power only if we can provide a valid value for it */
+-              if (adv_tx_power != HCI_TX_POWER_INVALID) {
++              if (adv_tx_power != HCI_TX_POWER_INVALID &&
++                  (ad_len + eir_precalc_len(1) <= size)) {
+                       ptr[0] = 0x02;
+                       ptr[1] = EIR_TX_POWER;
+                       ptr[2] = (u8)adv_tx_power;
+diff --git a/net/bluetooth/eir.h b/net/bluetooth/eir.h
+index 5c89a05e8b290..9372db83f912f 100644
+--- a/net/bluetooth/eir.h
++++ b/net/bluetooth/eir.h
+@@ -9,7 +9,7 @@
+ void eir_create(struct hci_dev *hdev, u8 *data);
+-u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
++u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size);
+ u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr);
+ u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr);
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 3fb70b4ee8c8a..a00316d79dbf5 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -1846,7 +1846,8 @@ static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)
+                       return 0;
+       }
+-      len = eir_create_adv_data(hdev, instance, pdu->data);
++      len = eir_create_adv_data(hdev, instance, pdu->data,
++                                HCI_MAX_EXT_AD_LENGTH);
+       pdu->length = len;
+       pdu->handle = adv ? adv->handle : instance;
+@@ -1877,7 +1878,7 @@ static int hci_set_adv_data_sync(struct hci_dev *hdev, u8 instance)
+       memset(&cp, 0, sizeof(cp));
+-      len = eir_create_adv_data(hdev, instance, cp.data);
++      len = eir_create_adv_data(hdev, instance, cp.data, sizeof(cp.data));
+       /* There's nothing to do if the data hasn't changed */
+       if (hdev->adv_data_len == len &&
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch b/queue-6.12/bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch
new file mode 100644 (file)
index 0000000..c023fa3
--- /dev/null
@@ -0,0 +1,50 @@
+From bb298b3cdc547452e08756ea96f879d76eec947d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Jun 2025 11:14:25 -0400
+Subject: Bluetooth: Fix NULL pointer deference on eir_get_service_data
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 20a2aa01f5aeb6daad9aeaa7c33dd512c58d81eb ]
+
+The len parameter is considered optional so it can be NULL so it cannot
+be used for skipping to next entry of EIR_SERVICE_DATA.
+
+Fixes: 8f9ae5b3ae80 ("Bluetooth: eir: Add helpers for managing service data")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/eir.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/net/bluetooth/eir.c b/net/bluetooth/eir.c
+index 1bc51e2b05a34..3e1713673ecc9 100644
+--- a/net/bluetooth/eir.c
++++ b/net/bluetooth/eir.c
+@@ -366,17 +366,19 @@ u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr)
+ void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len)
+ {
+-      while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, len))) {
++      size_t dlen;
++
++      while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, &dlen))) {
+               u16 value = get_unaligned_le16(eir);
+               if (uuid == value) {
+                       if (len)
+-                              *len -= 2;
++                              *len = dlen - 2;
+                       return &eir[2];
+               }
+-              eir += *len;
+-              eir_len -= *len;
++              eir += dlen;
++              eir_len -= dlen;
+       }
+       return NULL;
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch b/queue-6.12/bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch
new file mode 100644 (file)
index 0000000..e1fe515
--- /dev/null
@@ -0,0 +1,57 @@
+From 5f061d82180d8c1e109e2df6e41bf90986a4cb61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 31 May 2025 18:24:58 +0300
+Subject: Bluetooth: hci_core: fix list_for_each_entry_rcu usage
+
+From: Pauli Virtanen <pav@iki.fi>
+
+[ Upstream commit 308a3a8ce8ea41b26c46169f3263e50f5997c28e ]
+
+Releasing + re-acquiring RCU lock inside list_for_each_entry_rcu() loop
+body is not correct.
+
+Fix by taking the update-side hdev->lock instead.
+
+Fixes: c7eaf80bfb0c ("Bluetooth: Fix hci_link_tx_to RCU lock usage")
+Signed-off-by: Pauli Virtanen <pav@iki.fi>
+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>
+---
+ net/bluetooth/hci_core.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 743b63287a18f..831f41f6bc6de 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -3416,23 +3416,18 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
+       bt_dev_err(hdev, "link tx timeout");
+-      rcu_read_lock();
++      hci_dev_lock(hdev);
+       /* Kill stalled connections */
+-      list_for_each_entry_rcu(c, &h->list, list) {
++      list_for_each_entry(c, &h->list, list) {
+               if (c->type == type && c->sent) {
+                       bt_dev_err(hdev, "killing stalled connection %pMR",
+                                  &c->dst);
+-                      /* hci_disconnect might sleep, so, we have to release
+-                       * the RCU read lock before calling it.
+-                       */
+-                      rcu_read_unlock();
+                       hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM);
+-                      rcu_read_lock();
+               }
+       }
+-      rcu_read_unlock();
++      hci_dev_unlock(hdev);
+ }
+ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch b/queue-6.12/bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch
new file mode 100644 (file)
index 0000000..1af8b30
--- /dev/null
@@ -0,0 +1,105 @@
+From bc6f0c3ee0ec8f0506b086d1aaee2a8a97a6ae36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Jun 2025 11:15:16 -0400
+Subject: Bluetooth: hci_sync: Fix broadcast/PA when using an existing instance
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 5725bc608252050ed8a4d47d59225b7dd73474c8 ]
+
+When using and existing adv_info instance for broadcast source it
+needs to be updated to periodic first before it can be reused, also in
+case the existing instance already have data hci_set_adv_instance_data
+cannot be used directly since it would overwrite the existing data so
+this reappend the original data after the Broadcast ID, if one was
+generated.
+
+Example:
+
+bluetoothctl># Add PBP to EA so it can be later referenced as the BIS ID
+bluetoothctl> advertise.service 0x1856 0x00 0x00
+bluetoothctl> advertise on
+...
+< HCI Command: LE Set Extended Advertising Data (0x08|0x0037) plen 13
+        Handle: 0x01
+        Operation: Complete extended advertising data (0x03)
+        Fragment preference: Minimize fragmentation (0x01)
+        Data length: 0x09
+        Service Data: Public Broadcast Announcement (0x1856)
+          Data[2]: 0000
+        Flags: 0x06
+          LE General Discoverable Mode
+          BR/EDR Not Supported
+...
+bluetoothctl># Attempt to acquire Broadcast Source transport
+bluetoothctl>transport.acquire /org/bluez/hci0/pac_bcast0/fd0
+...
+< HCI Command: LE Set Extended Advertising Data (0x08|0x0037) plen 255
+        Handle: 0x01
+        Operation: Complete extended advertising data (0x03)
+        Fragment preference: Minimize fragmentation (0x01)
+        Data length: 0x0e
+        Service Data: Broadcast Audio Announcement (0x1852)
+        Broadcast ID: 11371620 (0xad8464)
+        Service Data: Public Broadcast Announcement (0x1856)
+          Data[2]: 0000
+        Flags: 0x06
+          LE General Discoverable Mode
+          BR/EDR Not Supported
+
+Link: https://github.com/bluez/bluez/issues/1117
+Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 59011f45906a1..3fb70b4ee8c8a 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -1559,7 +1559,8 @@ static int hci_enable_per_advertising_sync(struct hci_dev *hdev, u8 instance)
+ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
+ {
+       u8 bid[3];
+-      u8 ad[4 + 3];
++      u8 ad[HCI_MAX_EXT_AD_LENGTH];
++      u8 len;
+       /* Skip if NULL adv as instance 0x00 is used for general purpose
+        * advertising so it cannot used for the likes of Broadcast Announcement
+@@ -1585,8 +1586,10 @@ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
+       /* Generate Broadcast ID */
+       get_random_bytes(bid, sizeof(bid));
+-      eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid));
+-      hci_set_adv_instance_data(hdev, adv->instance, sizeof(ad), ad, 0, NULL);
++      len = eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid));
++      memcpy(ad + len, adv->adv_data, adv->adv_data_len);
++      hci_set_adv_instance_data(hdev, adv->instance, len + adv->adv_data_len,
++                                ad, 0, NULL);
+       return hci_update_adv_data_sync(hdev, adv->instance);
+ }
+@@ -1603,8 +1606,15 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
+       if (instance) {
+               adv = hci_find_adv_instance(hdev, instance);
+-              /* Create an instance if that could not be found */
+-              if (!adv) {
++              if (adv) {
++                      /* Turn it into periodic advertising */
++                      adv->periodic = true;
++                      adv->per_adv_data_len = data_len;
++                      if (data)
++                              memcpy(adv->per_adv_data, data, data_len);
++                      adv->flags = flags;
++              } else if (!adv) {
++                      /* Create an instance if that could not be found */
+                       adv = hci_add_per_instance(hdev, instance, flags,
+                                                  data_len, data,
+                                                  sync_interval,
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-mgmt-fix-sparse-errors.patch b/queue-6.12/bluetooth-mgmt-fix-sparse-errors.patch
new file mode 100644 (file)
index 0000000..8f7dccf
--- /dev/null
@@ -0,0 +1,47 @@
+From 95270952a812c4a594f0ee404d56083ceb29b116 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jun 2025 16:36:27 -0400
+Subject: Bluetooth: MGMT: Fix sparse errors
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 7dd38ba4acbea9875b4ee061e20a26413e39d9f4 ]
+
+This fixes the following errors:
+
+net/bluetooth/mgmt.c:5400:59: sparse: sparse: incorrect type in argument 3
+(different base types) @@     expected unsigned short [usertype] handle @@
+got restricted __le16 [usertype] monitor_handle @@
+net/bluetooth/mgmt.c:5400:59: sparse:     expected unsigned short [usertype] handle
+net/bluetooth/mgmt.c:5400:59: sparse:     got restricted __le16 [usertype] monitor_handle
+
+Fixes: e6ed54e86aae ("Bluetooth: MGMT: Fix UAF on mgmt_remove_adv_monitor_complete")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202506060347.ux2O1p7L-lkp@intel.com/
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 70a26c895512f..7664e7ba372ce 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -5166,11 +5166,11 @@ static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
+ }
+ static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev,
+-                                   u16 handle)
++                                   __le16 handle)
+ {
+       struct mgmt_ev_adv_monitor_removed ev;
+-      ev.monitor_handle = cpu_to_le16(handle);
++      ev.monitor_handle = handle;
+       mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk);
+ }
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch b/queue-6.12/bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch
new file mode 100644 (file)
index 0000000..defa70b
--- /dev/null
@@ -0,0 +1,229 @@
+From 1b5bf4e452eb50fe555768eefc6eb0e952ef4d53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Jun 2025 16:12:39 -0400
+Subject: Bluetooth: MGMT: Fix UAF on mgmt_remove_adv_monitor_complete
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit e6ed54e86aae9e4f7286ce8d5c73780f91b48d1c ]
+
+This reworks MGMT_OP_REMOVE_ADV_MONITOR to not use mgmt_pending_add to
+avoid crashes like bellow:
+
+==================================================================
+BUG: KASAN: slab-use-after-free in mgmt_remove_adv_monitor_complete+0xe5/0x540 net/bluetooth/mgmt.c:5406
+Read of size 8 at addr ffff88801c53f318 by task kworker/u5:5/5341
+
+CPU: 0 UID: 0 PID: 5341 Comm: kworker/u5:5 Not tainted 6.15.0-syzkaller-10402-g4cb6c8af8591 #0 PREEMPT(full)
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+Workqueue: hci0 hci_cmd_sync_work
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:408 [inline]
+ print_report+0xd2/0x2b0 mm/kasan/report.c:521
+ kasan_report+0x118/0x150 mm/kasan/report.c:634
+ mgmt_remove_adv_monitor_complete+0xe5/0x540 net/bluetooth/mgmt.c:5406
+ hci_cmd_sync_work+0x261/0x3a0 net/bluetooth/hci_sync.c:334
+ process_one_work kernel/workqueue.c:3238 [inline]
+ process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3321
+ worker_thread+0x8a0/0xda0 kernel/workqueue.c:3402
+ kthread+0x711/0x8a0 kernel/kthread.c:464
+ ret_from_fork+0x3fc/0x770 arch/x86/kernel/process.c:148
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
+ </TASK>
+
+Allocated by task 5987:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3e/0x80 mm/kasan/common.c:68
+ poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
+ __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394
+ kasan_kmalloc include/linux/kasan.h:260 [inline]
+ __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4358
+ kmalloc_noprof include/linux/slab.h:905 [inline]
+ kzalloc_noprof include/linux/slab.h:1039 [inline]
+ mgmt_pending_new+0x65/0x240 net/bluetooth/mgmt_util.c:252
+ mgmt_pending_add+0x34/0x120 net/bluetooth/mgmt_util.c:279
+ remove_adv_monitor+0x103/0x1b0 net/bluetooth/mgmt.c:5454
+ hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719
+ hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839
+ sock_sendmsg_nosec net/socket.c:712 [inline]
+ __sock_sendmsg+0x219/0x270 net/socket.c:727
+ sock_write_iter+0x258/0x330 net/socket.c:1131
+ new_sync_write fs/read_write.c:593 [inline]
+ vfs_write+0x548/0xa90 fs/read_write.c:686
+ ksys_write+0x145/0x250 fs/read_write.c:738
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Freed by task 5989:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3e/0x80 mm/kasan/common.c:68
+ kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576
+ poison_slab_object mm/kasan/common.c:247 [inline]
+ __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264
+ kasan_slab_free include/linux/kasan.h:233 [inline]
+ slab_free_hook mm/slub.c:2380 [inline]
+ slab_free mm/slub.c:4642 [inline]
+ kfree+0x18e/0x440 mm/slub.c:4841
+ mgmt_pending_foreach+0xc9/0x120 net/bluetooth/mgmt_util.c:242
+ mgmt_index_removed+0x10d/0x2f0 net/bluetooth/mgmt.c:9366
+ hci_sock_bind+0xbe9/0x1000 net/bluetooth/hci_sock.c:1314
+ __sys_bind_socket net/socket.c:1810 [inline]
+ __sys_bind+0x2c3/0x3e0 net/socket.c:1841
+ __do_sys_bind net/socket.c:1846 [inline]
+ __se_sys_bind net/socket.c:1844 [inline]
+ __x64_sys_bind+0x7a/0x90 net/socket.c:1844
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 66bd095ab5d4 ("Bluetooth: advmon offload MSFT remove monitor")
+Closes: https://syzkaller.appspot.com/bug?extid=feb0dc579bbe30a13190
+Reported-by: syzbot+feb0dc579bbe30a13190@syzkaller.appspotmail.com
+Tested-by: syzbot+feb0dc579bbe30a13190@syzkaller.appspotmail.com
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci_core.h |  1 -
+ net/bluetooth/hci_core.c         |  4 +---
+ net/bluetooth/mgmt.c             | 37 ++++++++++----------------------
+ 3 files changed, 12 insertions(+), 30 deletions(-)
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index 4f3b537476e10..d81c3f7dd328e 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -2379,7 +2379,6 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev,
+                           u8 instance);
+ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
+                             u8 instance);
+-void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle);
+ int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
+ void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
+                                 bdaddr_t *bdaddr, u8 addr_type);
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 831f41f6bc6de..77fceec9039ed 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -1877,10 +1877,8 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
+       if (monitor->handle)
+               idr_remove(&hdev->adv_monitors_idr, monitor->handle);
+-      if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) {
++      if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED)
+               hdev->adv_monitors_cnt--;
+-              mgmt_adv_monitor_removed(hdev, monitor->handle);
+-      }
+       kfree(monitor);
+ }
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index d4700f940e8a1..7a086a9ad41fa 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -5172,24 +5172,14 @@ static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
+       mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk);
+ }
+-void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle)
++static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev,
++                                   u16 handle)
+ {
+       struct mgmt_ev_adv_monitor_removed ev;
+-      struct mgmt_pending_cmd *cmd;
+-      struct sock *sk_skip = NULL;
+-      struct mgmt_cp_remove_adv_monitor *cp;
+-
+-      cmd = pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev);
+-      if (cmd) {
+-              cp = cmd->param;
+-
+-              if (cp->monitor_handle)
+-                      sk_skip = cmd->sk;
+-      }
+       ev.monitor_handle = cpu_to_le16(handle);
+-      mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk_skip);
++      mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk);
+ }
+ static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
+@@ -5291,8 +5281,7 @@ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
+       if (pending_find(MGMT_OP_SET_LE, hdev) ||
+           pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
+-          pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) ||
+-          pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
++          pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) {
+               status = MGMT_STATUS_BUSY;
+               goto unlock;
+       }
+@@ -5462,8 +5451,7 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev,
+       struct mgmt_pending_cmd *cmd = data;
+       struct mgmt_cp_remove_adv_monitor *cp;
+-      if (status == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev))
++      if (status == -ECANCELED)
+               return;
+       hci_dev_lock(hdev);
+@@ -5472,12 +5460,14 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev,
+       rp.monitor_handle = cp->monitor_handle;
+-      if (!status)
++      if (!status) {
++              mgmt_adv_monitor_removed(cmd->sk, hdev, cp->monitor_handle);
+               hci_update_passive_scan(hdev);
++      }
+       mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
+                         mgmt_status(status), &rp, sizeof(rp));
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+       hci_dev_unlock(hdev);
+       bt_dev_dbg(hdev, "remove monitor %d complete, status %d",
+@@ -5487,10 +5477,6 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev,
+ static int mgmt_remove_adv_monitor_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-
+-      if (cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev))
+-              return -ECANCELED;
+-
+       struct mgmt_cp_remove_adv_monitor *cp = cmd->param;
+       u16 handle = __le16_to_cpu(cp->monitor_handle);
+@@ -5509,14 +5495,13 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
+       hci_dev_lock(hdev);
+       if (pending_find(MGMT_OP_SET_LE, hdev) ||
+-          pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) ||
+           pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
+           pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) {
+               status = MGMT_STATUS_BUSY;
+               goto unlock;
+       }
+-      cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len);
++      cmd = mgmt_pending_new(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len);
+       if (!cmd) {
+               status = MGMT_STATUS_NO_RESOURCES;
+               goto unlock;
+@@ -5526,7 +5511,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
+                                 mgmt_remove_adv_monitor_complete);
+       if (err) {
+-              mgmt_pending_remove(cmd);
++              mgmt_pending_free(cmd);
+               if (err == -ENOMEM)
+                       status = MGMT_STATUS_NO_RESOURCES;
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch b/queue-6.12/bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch
new file mode 100644 (file)
index 0000000..cab4d0b
--- /dev/null
@@ -0,0 +1,626 @@
+From 5cca1b65db00a3f922a9da05ae4ce1baf74e0817 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 May 2025 15:42:21 -0400
+Subject: Bluetooth: MGMT: Protect mgmt_pending list with its own lock
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 6fe26f694c824b8a4dbf50c635bee1302e3f099c ]
+
+This uses a mutex to protect from concurrent access of mgmt_pending
+list which can cause crashes like:
+
+==================================================================
+BUG: KASAN: slab-use-after-free in hci_sock_get_channel+0x60/0x68 net/bluetooth/hci_sock.c:91
+Read of size 2 at addr ffff0000c48885b2 by task syz.4.334/7318
+
+CPU: 0 UID: 0 PID: 7318 Comm: syz.4.334 Not tainted 6.15.0-rc7-syzkaller-g187899f4124a #0 PREEMPT
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025
+Call trace:
+ show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:466 (C)
+ __dump_stack+0x30/0x40 lib/dump_stack.c:94
+ dump_stack_lvl+0xd8/0x12c lib/dump_stack.c:120
+ print_address_description+0xa8/0x254 mm/kasan/report.c:408
+ print_report+0x68/0x84 mm/kasan/report.c:521
+ kasan_report+0xb0/0x110 mm/kasan/report.c:634
+ __asan_report_load2_noabort+0x20/0x2c mm/kasan/report_generic.c:379
+ hci_sock_get_channel+0x60/0x68 net/bluetooth/hci_sock.c:91
+ mgmt_pending_find+0x7c/0x140 net/bluetooth/mgmt_util.c:223
+ pending_find net/bluetooth/mgmt.c:947 [inline]
+ remove_adv_monitor+0x44/0x1a4 net/bluetooth/mgmt.c:5445
+ hci_mgmt_cmd+0x780/0xc00 net/bluetooth/hci_sock.c:1712
+ hci_sock_sendmsg+0x544/0xbb0 net/bluetooth/hci_sock.c:1832
+ sock_sendmsg_nosec net/socket.c:712 [inline]
+ __sock_sendmsg net/socket.c:727 [inline]
+ sock_write_iter+0x25c/0x378 net/socket.c:1131
+ new_sync_write fs/read_write.c:591 [inline]
+ vfs_write+0x62c/0x97c fs/read_write.c:684
+ ksys_write+0x120/0x210 fs/read_write.c:736
+ __do_sys_write fs/read_write.c:747 [inline]
+ __se_sys_write fs/read_write.c:744 [inline]
+ __arm64_sys_write+0x7c/0x90 fs/read_write.c:744
+ __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
+ invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
+ el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132
+ do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
+ el0_svc+0x58/0x17c arch/arm64/kernel/entry-common.c:767
+ el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:786
+ el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:600
+
+Allocated by task 7037:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x40/0x78 mm/kasan/common.c:68
+ kasan_save_alloc_info+0x44/0x54 mm/kasan/generic.c:562
+ poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
+ __kasan_kmalloc+0x9c/0xb4 mm/kasan/common.c:394
+ kasan_kmalloc include/linux/kasan.h:260 [inline]
+ __do_kmalloc_node mm/slub.c:4327 [inline]
+ __kmalloc_noprof+0x2fc/0x4c8 mm/slub.c:4339
+ kmalloc_noprof include/linux/slab.h:909 [inline]
+ sk_prot_alloc+0xc4/0x1f0 net/core/sock.c:2198
+ sk_alloc+0x44/0x3ac net/core/sock.c:2254
+ bt_sock_alloc+0x4c/0x300 net/bluetooth/af_bluetooth.c:148
+ hci_sock_create+0xa8/0x194 net/bluetooth/hci_sock.c:2202
+ bt_sock_create+0x14c/0x24c net/bluetooth/af_bluetooth.c:132
+ __sock_create+0x43c/0x91c net/socket.c:1541
+ sock_create net/socket.c:1599 [inline]
+ __sys_socket_create net/socket.c:1636 [inline]
+ __sys_socket+0xd4/0x1c0 net/socket.c:1683
+ __do_sys_socket net/socket.c:1697 [inline]
+ __se_sys_socket net/socket.c:1695 [inline]
+ __arm64_sys_socket+0x7c/0x94 net/socket.c:1695
+ __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline]
+ invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49
+ el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132
+ do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151
+ el0_svc+0x58/0x17c arch/arm64/kernel/entry-common.c:767
+ el0t_64_sync_handler+0x78/0x108 arch/arm64/kernel/entry-common.c:786
+ el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:600
+
+Freed by task 6607:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x40/0x78 mm/kasan/common.c:68
+ kasan_save_free_info+0x58/0x70 mm/kasan/generic.c:576
+ poison_slab_object mm/kasan/common.c:247 [inline]
+ __kasan_slab_free+0x68/0x88 mm/kasan/common.c:264
+ kasan_slab_free include/linux/kasan.h:233 [inline]
+ slab_free_hook mm/slub.c:2380 [inline]
+ slab_free mm/slub.c:4642 [inline]
+ kfree+0x17c/0x474 mm/slub.c:4841
+ sk_prot_free net/core/sock.c:2237 [inline]
+ __sk_destruct+0x4f4/0x760 net/core/sock.c:2332
+ sk_destruct net/core/sock.c:2360 [inline]
+ __sk_free+0x320/0x430 net/core/sock.c:2371
+ sk_free+0x60/0xc8 net/core/sock.c:2382
+ sock_put include/net/sock.h:1944 [inline]
+ mgmt_pending_free+0x88/0x118 net/bluetooth/mgmt_util.c:290
+ mgmt_pending_remove+0xec/0x104 net/bluetooth/mgmt_util.c:298
+ mgmt_set_powered_complete+0x418/0x5cc net/bluetooth/mgmt.c:1355
+ hci_cmd_sync_work+0x204/0x33c net/bluetooth/hci_sync.c:334
+ process_one_work+0x7e8/0x156c kernel/workqueue.c:3238
+ process_scheduled_works kernel/workqueue.c:3319 [inline]
+ worker_thread+0x958/0xed8 kernel/workqueue.c:3400
+ kthread+0x5fc/0x75c kernel/kthread.c:464
+ ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:847
+
+Fixes: a380b6cff1a2 ("Bluetooth: Add generic mgmt helper API")
+Closes: https://syzkaller.appspot.com/bug?extid=0a7039d5d9986ff4ecec
+Closes: https://syzkaller.appspot.com/bug?extid=cc0cc52e7f43dc9e6df1
+Reported-by: syzbot+0a7039d5d9986ff4ecec@syzkaller.appspotmail.com
+Tested-by: syzbot+0a7039d5d9986ff4ecec@syzkaller.appspotmail.com
+Tested-by: syzbot+cc0cc52e7f43dc9e6df1@syzkaller.appspotmail.com
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci_core.h |   1 +
+ net/bluetooth/hci_core.c         |   1 +
+ net/bluetooth/mgmt.c             | 101 +++++++++++++++----------------
+ net/bluetooth/mgmt_util.c        |  32 ++++++++--
+ net/bluetooth/mgmt_util.h        |   4 +-
+ 5 files changed, 80 insertions(+), 59 deletions(-)
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index d81c3f7dd328e..e9e3366d059ef 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -538,6 +538,7 @@ struct hci_dev {
+       struct hci_conn_hash    conn_hash;
+       struct list_head        mesh_pending;
++      struct mutex            mgmt_pending_lock;
+       struct list_head        mgmt_pending;
+       struct list_head        reject_list;
+       struct list_head        accept_list;
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 77fceec9039ed..0d3816c807588 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -2505,6 +2505,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
+       mutex_init(&hdev->lock);
+       mutex_init(&hdev->req_lock);
++      mutex_init(&hdev->mgmt_pending_lock);
+       ida_init(&hdev->unset_handle_ida);
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 7a086a9ad41fa..70a26c895512f 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -1440,22 +1440,17 @@ static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
+       send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
+-      list_del(&cmd->list);
+-
+       if (match->sk == NULL) {
+               match->sk = cmd->sk;
+               sock_hold(match->sk);
+       }
+-
+-      mgmt_pending_free(cmd);
+ }
+ static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
+ {
+       u8 *status = data;
+-      mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
+-      mgmt_pending_remove(cmd);
++      mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, *status);
+ }
+ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
+@@ -1469,8 +1464,6 @@ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
+       if (cmd->cmd_complete) {
+               cmd->cmd_complete(cmd, match->mgmt_status);
+-              mgmt_pending_remove(cmd);
+-
+               return;
+       }
+@@ -1479,13 +1472,13 @@ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
+ static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
+ {
+-      return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
++      return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status,
+                                cmd->param, cmd->param_len);
+ }
+ static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
+ {
+-      return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
++      return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status,
+                                cmd->param, sizeof(struct mgmt_addr_info));
+ }
+@@ -1525,7 +1518,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
+       if (err) {
+               u8 mgmt_err = mgmt_status(err);
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
+               hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
+               goto done;
+       }
+@@ -1700,7 +1693,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
+       if (err) {
+               u8 mgmt_err = mgmt_status(err);
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
+               goto done;
+       }
+@@ -1936,8 +1929,8 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+                       new_settings(hdev, NULL);
+               }
+-              mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
+-                                   &mgmt_err);
++              mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true,
++                                   cmd_status_rsp, &mgmt_err);
+               return;
+       }
+@@ -1947,7 +1940,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+               changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
+       }
+-      mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
++      mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, settings_rsp, &match);
+       if (changed)
+               new_settings(hdev, match.sk);
+@@ -2067,12 +2060,12 @@ static void set_le_complete(struct hci_dev *hdev, void *data, int err)
+       bt_dev_dbg(hdev, "err %d", err);
+       if (status) {
+-              mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
+-                                                      &status);
++              mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, cmd_status_rsp,
++                                   &status);
+               return;
+       }
+-      mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
++      mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, settings_rsp, &match);
+       new_settings(hdev, match.sk);
+@@ -2131,7 +2124,7 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
+       struct sock *sk = cmd->sk;
+       if (status) {
+-              mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev,
++              mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true,
+                                    cmd_status_rsp, &status);
+               return;
+       }
+@@ -2572,7 +2565,7 @@ static void mgmt_class_complete(struct hci_dev *hdev, void *data, int err)
+       bt_dev_dbg(hdev, "err %d", err);
+-      mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                         mgmt_status(err), hdev->dev_class, 3);
+       mgmt_pending_free(cmd);
+@@ -3360,7 +3353,7 @@ static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
+       bacpy(&rp.addr.bdaddr, &conn->dst);
+       rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+-      err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
++      err = mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_PAIR_DEVICE,
+                               status, &rp, sizeof(rp));
+       /* So we don't get further callbacks for this connection */
+@@ -5250,7 +5243,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
+               hci_update_passive_scan(hdev);
+       }
+-      mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                         mgmt_status(status), &rp, sizeof(rp));
+       mgmt_pending_remove(cmd);
+@@ -5465,7 +5458,7 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev,
+               hci_update_passive_scan(hdev);
+       }
+-      mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                         mgmt_status(status), &rp, sizeof(rp));
+       mgmt_pending_free(cmd);
+@@ -5864,7 +5857,7 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
+           cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
+               return;
+-      mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
+                         cmd->param, 1);
+       mgmt_pending_remove(cmd);
+@@ -6102,7 +6095,7 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
+       bt_dev_dbg(hdev, "err %d", err);
+-      mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
+                         cmd->param, 1);
+       mgmt_pending_remove(cmd);
+@@ -6327,7 +6320,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
+       u8 status = mgmt_status(err);
+       if (status) {
+-              mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
++              mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true,
+                                    cmd_status_rsp, &status);
+               return;
+       }
+@@ -6337,7 +6330,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
+       else
+               hci_dev_clear_flag(hdev, HCI_ADVERTISING);
+-      mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
++      mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, settings_rsp,
+                            &match);
+       new_settings(hdev, match.sk);
+@@ -6681,7 +6674,7 @@ static void set_bredr_complete(struct hci_dev *hdev, void *data, int err)
+                */
+               hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
+       } else {
+               send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
+               new_settings(hdev, cmd->sk);
+@@ -6818,7 +6811,7 @@ static void set_secure_conn_complete(struct hci_dev *hdev, void *data, int err)
+       if (err) {
+               u8 mgmt_err = mgmt_status(err);
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
+               goto done;
+       }
+@@ -7265,7 +7258,7 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err)
+               rp.max_tx_power = HCI_TX_POWER_INVALID;
+       }
+-      mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status,
+                         &rp, sizeof(rp));
+       mgmt_pending_free(cmd);
+@@ -7425,7 +7418,7 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err)
+       }
+ complete:
+-      mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
++      mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp,
+                         sizeof(rp));
+       mgmt_pending_free(cmd);
+@@ -8675,10 +8668,10 @@ static void add_advertising_complete(struct hci_dev *hdev, void *data, int err)
+       rp.instance = cp->instance;
+       if (err)
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode,
+                               mgmt_status(err));
+       else
+-              mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                                 mgmt_status(err), &rp, sizeof(rp));
+       add_adv_complete(hdev, cmd->sk, cp->instance, err);
+@@ -8866,10 +8859,10 @@ static void add_ext_adv_params_complete(struct hci_dev *hdev, void *data,
+               hci_remove_adv_instance(hdev, cp->instance);
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode,
+                               mgmt_status(err));
+       } else {
+-              mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                                 mgmt_status(err), &rp, sizeof(rp));
+       }
+@@ -9016,10 +9009,10 @@ static void add_ext_adv_data_complete(struct hci_dev *hdev, void *data, int err)
+       rp.instance = cp->instance;
+       if (err)
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode,
+                               mgmt_status(err));
+       else
+-              mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                                 mgmt_status(err), &rp, sizeof(rp));
+       mgmt_pending_free(cmd);
+@@ -9178,10 +9171,10 @@ static void remove_advertising_complete(struct hci_dev *hdev, void *data,
+       rp.instance = cp->instance;
+       if (err)
+-              mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode,
+                               mgmt_status(err));
+       else
+-              mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
++              mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
+                                 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
+       mgmt_pending_free(cmd);
+@@ -9452,7 +9445,7 @@ void mgmt_index_removed(struct hci_dev *hdev)
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+               return;
+-      mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
++      mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match);
+       if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
+               mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0,
+@@ -9490,7 +9483,8 @@ void mgmt_power_on(struct hci_dev *hdev, int err)
+               hci_update_passive_scan(hdev);
+       }
+-      mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
++      mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp,
++                           &match);
+       new_settings(hdev, match.sk);
+@@ -9505,7 +9499,8 @@ void __mgmt_power_off(struct hci_dev *hdev)
+       struct cmd_lookup match = { NULL, hdev };
+       u8 zero_cod[] = { 0, 0, 0 };
+-      mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
++      mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp,
++                           &match);
+       /* If the power off is because of hdev unregistration let
+        * use the appropriate INVALID_INDEX status. Otherwise use
+@@ -9519,7 +9514,7 @@ void __mgmt_power_off(struct hci_dev *hdev)
+       else
+               match.mgmt_status = MGMT_STATUS_NOT_POWERED;
+-      mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
++      mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match);
+       if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
+               mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
+@@ -9760,7 +9755,6 @@ static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
+       device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
+       cmd->cmd_complete(cmd, 0);
+-      mgmt_pending_remove(cmd);
+ }
+ bool mgmt_powering_down(struct hci_dev *hdev)
+@@ -9816,8 +9810,8 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
+       struct mgmt_cp_disconnect *cp;
+       struct mgmt_pending_cmd *cmd;
+-      mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
+-                           hdev);
++      mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, true,
++                           unpair_device_rsp, hdev);
+       cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
+       if (!cmd)
+@@ -10010,7 +10004,7 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
+       if (status) {
+               u8 mgmt_err = mgmt_status(status);
+-              mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
++              mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true,
+                                    cmd_status_rsp, &mgmt_err);
+               return;
+       }
+@@ -10020,8 +10014,8 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
+       else
+               changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
+-      mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
+-                           &match);
++      mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true,
++                           settings_rsp, &match);
+       if (changed)
+               new_settings(hdev, match.sk);
+@@ -10045,9 +10039,12 @@ void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
+ {
+       struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
+-      mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
+-      mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
+-      mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
++      mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, false, sk_lookup,
++                           &match);
++      mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, false, sk_lookup,
++                           &match);
++      mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, false, sk_lookup,
++                           &match);
+       if (!status) {
+               mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class,
+diff --git a/net/bluetooth/mgmt_util.c b/net/bluetooth/mgmt_util.c
+index 3713ff490c65d..a88a07da39473 100644
+--- a/net/bluetooth/mgmt_util.c
++++ b/net/bluetooth/mgmt_util.c
+@@ -217,30 +217,47 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
+ struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode,
+                                          struct hci_dev *hdev)
+ {
+-      struct mgmt_pending_cmd *cmd;
++      struct mgmt_pending_cmd *cmd, *tmp;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
+-      list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
++      list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
+               if (hci_sock_get_channel(cmd->sk) != channel)
+                       continue;
+-              if (cmd->opcode == opcode)
++
++              if (cmd->opcode == opcode) {
++                      mutex_unlock(&hdev->mgmt_pending_lock);
+                       return cmd;
++              }
+       }
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
+       return NULL;
+ }
+-void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
++void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove,
+                         void (*cb)(struct mgmt_pending_cmd *cmd, void *data),
+                         void *data)
+ {
+       struct mgmt_pending_cmd *cmd, *tmp;
++      mutex_lock(&hdev->mgmt_pending_lock);
++
+       list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
+               if (opcode > 0 && cmd->opcode != opcode)
+                       continue;
++              if (remove)
++                      list_del(&cmd->list);
++
+               cb(cmd, data);
++
++              if (remove)
++                      mgmt_pending_free(cmd);
+       }
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
+ }
+ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode,
+@@ -254,7 +271,7 @@ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode,
+               return NULL;
+       cmd->opcode = opcode;
+-      cmd->index = hdev->id;
++      cmd->hdev = hdev;
+       cmd->param = kmemdup(data, len, GFP_KERNEL);
+       if (!cmd->param) {
+@@ -280,7 +297,9 @@ struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
+       if (!cmd)
+               return NULL;
++      mutex_lock(&hdev->mgmt_pending_lock);
+       list_add_tail(&cmd->list, &hdev->mgmt_pending);
++      mutex_unlock(&hdev->mgmt_pending_lock);
+       return cmd;
+ }
+@@ -294,7 +313,10 @@ void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
+ void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
+ {
++      mutex_lock(&cmd->hdev->mgmt_pending_lock);
+       list_del(&cmd->list);
++      mutex_unlock(&cmd->hdev->mgmt_pending_lock);
++
+       mgmt_pending_free(cmd);
+ }
+diff --git a/net/bluetooth/mgmt_util.h b/net/bluetooth/mgmt_util.h
+index f2ba994ab1d84..024e51dd69375 100644
+--- a/net/bluetooth/mgmt_util.h
++++ b/net/bluetooth/mgmt_util.h
+@@ -33,7 +33,7 @@ struct mgmt_mesh_tx {
+ struct mgmt_pending_cmd {
+       struct list_head list;
+       u16 opcode;
+-      int index;
++      struct hci_dev *hdev;
+       void *param;
+       size_t param_len;
+       struct sock *sk;
+@@ -54,7 +54,7 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
+ struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode,
+                                          struct hci_dev *hdev);
+-void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
++void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove,
+                         void (*cb)(struct mgmt_pending_cmd *cmd, void *data),
+                         void *data);
+ struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
+-- 
+2.39.5
+
diff --git a/queue-6.12/bluetooth-mgmt-remove-unused-mgmt_pending_find_data.patch b/queue-6.12/bluetooth-mgmt-remove-unused-mgmt_pending_find_data.patch
new file mode 100644 (file)
index 0000000..50d6074
--- /dev/null
@@ -0,0 +1,70 @@
+From 17d285fbdeb9dabee6c6c348a528ac81ca65a6da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jan 2025 21:37:15 +0000
+Subject: Bluetooth: MGMT: Remove unused mgmt_pending_find_data
+
+From: Dr. David Alan Gilbert <linux@treblig.org>
+
+[ Upstream commit 276af34d82f13bda0b2a4d9786c90b8bbf1cd064 ]
+
+mgmt_pending_find_data() last use was removed in 2021 by
+commit 5a7501374664 ("Bluetooth: hci_sync: Convert MGMT_OP_GET_CLOCK_INFO")
+
+Remove it.
+
+Signed-off-by: Dr. David Alan Gilbert <linux@treblig.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 6fe26f694c82 ("Bluetooth: MGMT: Protect mgmt_pending list with its own lock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt_util.c | 17 -----------------
+ net/bluetooth/mgmt_util.h |  4 ----
+ 2 files changed, 21 deletions(-)
+
+diff --git a/net/bluetooth/mgmt_util.c b/net/bluetooth/mgmt_util.c
+index 67db32a60c6a9..3713ff490c65d 100644
+--- a/net/bluetooth/mgmt_util.c
++++ b/net/bluetooth/mgmt_util.c
+@@ -229,23 +229,6 @@ struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode,
+       return NULL;
+ }
+-struct mgmt_pending_cmd *mgmt_pending_find_data(unsigned short channel,
+-                                              u16 opcode,
+-                                              struct hci_dev *hdev,
+-                                              const void *data)
+-{
+-      struct mgmt_pending_cmd *cmd;
+-
+-      list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
+-              if (cmd->user_data != data)
+-                      continue;
+-              if (cmd->opcode == opcode)
+-                      return cmd;
+-      }
+-
+-      return NULL;
+-}
+-
+ void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
+                         void (*cb)(struct mgmt_pending_cmd *cmd, void *data),
+                         void *data)
+diff --git a/net/bluetooth/mgmt_util.h b/net/bluetooth/mgmt_util.h
+index bdf978605d5a8..f2ba994ab1d84 100644
+--- a/net/bluetooth/mgmt_util.h
++++ b/net/bluetooth/mgmt_util.h
+@@ -54,10 +54,6 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
+ struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode,
+                                          struct hci_dev *hdev);
+-struct mgmt_pending_cmd *mgmt_pending_find_data(unsigned short channel,
+-                                              u16 opcode,
+-                                              struct hci_dev *hdev,
+-                                              const void *data);
+ void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
+                         void (*cb)(struct mgmt_pending_cmd *cmd, void *data),
+                         void *data);
+-- 
+2.39.5
+
diff --git a/queue-6.12/drm-meson-fix-debug-log-statement-when-setting-the-h.patch b/queue-6.12/drm-meson-fix-debug-log-statement-when-setting-the-h.patch
new file mode 100644 (file)
index 0000000..0734227
--- /dev/null
@@ -0,0 +1,39 @@
+From c4f2c48e645e131d0f0692212db72e28cceff00d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jun 2025 22:37:29 +0200
+Subject: drm/meson: fix debug log statement when setting the HDMI clocks
+
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+[ Upstream commit d17e61ab63fb7747b340d6a66bf1408cd5c6562b ]
+
+The "phy" and "vclk" frequency labels were swapped, making it more
+difficult to debug driver errors. Swap the label order to make them
+match with the actual frequencies printed to correct this.
+
+Fixes: e5fab2ec9ca4 ("drm/meson: vclk: add support for YUV420 setup")
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/r/20250606203729.3311592-1-martin.blumenstingl@googlemail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/meson/meson_encoder_hdmi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+index ce8cea5d3a56b..2c49137e0deed 100644
+--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+@@ -108,7 +108,7 @@ static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi,
+               venc_freq /= 2;
+       dev_dbg(priv->dev,
+-              "vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n",
++              "phy:%lluHz vclk=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n",
+               phy_freq, vclk_freq, venc_freq, hdmi_freq,
+               priv->venc.hdmi_use_enci);
+-- 
+2.39.5
+
diff --git a/queue-6.12/drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch b/queue-6.12/drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch
new file mode 100644 (file)
index 0000000..4a2887a
--- /dev/null
@@ -0,0 +1,134 @@
+From 65c69d935ca297d1d9383dea9c0474e8edca2eed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jun 2025 22:27:51 +0200
+Subject: drm/meson: fix more rounding issues with 59.94Hz modes
+
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+[ Upstream commit 0cee6c4d3518b2e757aedae78771f17149f57653 ]
+
+Commit 1017560164b6 ("drm/meson: use unsigned long long / Hz for
+frequency types") attempts to resolve video playback using 59.94Hz.
+ using YUV420 by changing the clock calculation to use
+Hz instead of kHz (thus yielding more precision).
+
+The basic calculation itself is correct, however the comparisions in
+meson_vclk_vic_supported_freq() and meson_vclk_setup() don't work
+anymore for 59.94Hz modes (using the freq * 1000 / 1001 logic). For
+example, drm/edid specifies a 593407kHz clock for 3840x2160@59.94Hz.
+With the mentioend commit we convert this to Hz. Then meson_vclk
+tries to find a matchig "params" entry (as the clock setup code
+currently only supports specific frequencies) by taking the venc_freq
+from the params and calculating the "alt frequency" (used for the
+59.94Hz modes) from it, which is:
+  (594000000Hz * 1000) / 1001 = 593406593Hz
+
+Similar calculation is applied to the phy_freq (TMDS clock), which is 10
+times the pixel clock.
+
+Implement a new meson_vclk_freqs_are_matching_param() function whose
+purpose is to compare if the requested and calculated frequencies. They
+may not match exactly (for the reasons mentioned above). Allow the
+clocks to deviate slightly to make the 59.94Hz modes again.
+
+Fixes: 1017560164b6 ("drm/meson: use unsigned long long / Hz for frequency types")
+Reported-by: Christian Hewitt <christianshewitt@gmail.com>
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/r/20250609202751.962208-1-martin.blumenstingl@googlemail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/meson/meson_vclk.c | 55 ++++++++++++++++++------------
+ 1 file changed, 34 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
+index c4123bb958e4c..dfe0c28a0f054 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.c
++++ b/drivers/gpu/drm/meson/meson_vclk.c
+@@ -110,10 +110,7 @@
+ #define HDMI_PLL_LOCK         BIT(31)
+ #define HDMI_PLL_LOCK_G12A    (3 << 30)
+-#define PIXEL_FREQ_1000_1001(_freq)   \
+-      DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL)
+-#define PHY_FREQ_1000_1001(_freq)     \
+-      (PIXEL_FREQ_1000_1001(DIV_ROUND_DOWN_ULL(_freq, 10ULL)) * 10)
++#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL)
+ /* VID PLL Dividers */
+ enum {
+@@ -772,6 +769,36 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
+                 pll_freq);
+ }
++static bool meson_vclk_freqs_are_matching_param(unsigned int idx,
++                                              unsigned long long phy_freq,
++                                              unsigned long long vclk_freq)
++{
++      DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n",
++                       idx, params[idx].vclk_freq,
++                       FREQ_1000_1001(params[idx].vclk_freq));
++      DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n",
++                       idx, params[idx].phy_freq,
++                       FREQ_1000_1001(params[idx].phy_freq));
++
++      /* Match strict frequency */
++      if (phy_freq == params[idx].phy_freq &&
++          vclk_freq == params[idx].vclk_freq)
++              return true;
++
++      /* Match 1000/1001 variant: vclk deviation has to be less than 1kHz
++       * (drm EDID is defined in 1kHz steps, so everything smaller must be
++       * rounding error) and the PHY freq deviation has to be less than
++       * 10kHz (as the TMDS clock is 10 times the pixel clock, so anything
++       * smaller must be rounding error as well).
++       */
++      if (abs(vclk_freq - FREQ_1000_1001(params[idx].vclk_freq)) < 1000 &&
++          abs(phy_freq - FREQ_1000_1001(params[idx].phy_freq)) < 10000)
++              return true;
++
++      /* no match */
++      return false;
++}
++
+ enum drm_mode_status
+ meson_vclk_vic_supported_freq(struct meson_drm *priv,
+                             unsigned long long phy_freq,
+@@ -790,19 +817,7 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv,
+       }
+       for (i = 0 ; params[i].pixel_freq ; ++i) {
+-              DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n",
+-                               i, params[i].vclk_freq,
+-                               PIXEL_FREQ_1000_1001(params[i].vclk_freq));
+-              DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n",
+-                               i, params[i].phy_freq,
+-                               PHY_FREQ_1000_1001(params[i].phy_freq));
+-              /* Match strict frequency */
+-              if (phy_freq == params[i].phy_freq &&
+-                  vclk_freq == params[i].vclk_freq)
+-                      return MODE_OK;
+-              /* Match 1000/1001 variant */
+-              if (phy_freq == PHY_FREQ_1000_1001(params[i].phy_freq) &&
+-                  vclk_freq == PIXEL_FREQ_1000_1001(params[i].vclk_freq))
++              if (meson_vclk_freqs_are_matching_param(i, phy_freq, vclk_freq))
+                       return MODE_OK;
+       }
+@@ -1075,10 +1090,8 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+       }
+       for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
+-              if ((phy_freq == params[freq].phy_freq ||
+-                   phy_freq == PHY_FREQ_1000_1001(params[freq].phy_freq)) &&
+-                  (vclk_freq == params[freq].vclk_freq ||
+-                   vclk_freq == PIXEL_FREQ_1000_1001(params[freq].vclk_freq))) {
++              if (meson_vclk_freqs_are_matching_param(freq, phy_freq,
++                                                      vclk_freq)) {
+                       if (vclk_freq != params[freq].vclk_freq)
+                               vic_alternate_clock = true;
+                       else
+-- 
+2.39.5
+
diff --git a/queue-6.12/drm-meson-use-unsigned-long-long-hz-for-frequency-ty.patch b/queue-6.12/drm-meson-use-unsigned-long-long-hz-for-frequency-ty.patch
new file mode 100644 (file)
index 0000000..7f9dcb7
--- /dev/null
@@ -0,0 +1,650 @@
+From 7e2cee5a3751ab14f569095324ae30db72408587 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Apr 2025 22:13:00 +0200
+Subject: drm/meson: use unsigned long long / Hz for frequency types
+
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+[ Upstream commit 1017560164b6bbcbc93579266926e6e96675262a ]
+
+Christian reports that 4K output using YUV420 encoding fails with the
+following error:
+  Fatal Error, invalid HDMI vclk freq 593406
+
+Modetest shows the following:
+  3840x2160 59.94 3840 4016 4104 4400 2160 2168 2178 2250 593407 flags: xxxx, xxxx,
+  drm calculated value -------------------------------------^
+
+This indicates that there's a (1kHz) mismatch between the clock
+calculated by the drm framework and the meson driver.
+
+Relevant function call stack:
+(drm framework)
+  -> meson_encoder_hdmi_atomic_enable()
+    -> meson_encoder_hdmi_set_vclk()
+      -> meson_vclk_setup()
+
+The video clock requested by the drm framework is 593407kHz. This is
+passed by meson_encoder_hdmi_atomic_enable() to
+meson_encoder_hdmi_set_vclk() and the following formula is applied:
+- the frequency is halved (which would be 296703.5kHz) and rounded down
+  to the next full integer, which is 296703kHz
+- TMDS clock is calculated (296703kHz * 10)
+- video encoder clock is calculated - this needs to match a table from
+  meson_vclk.c and so it doubles the previously halved value again
+  (resulting in 593406kHz)
+- meson_vclk_setup() can't find (either directly, or by deriving it from
+  594000kHz * 1000 / 1001 and rounding to the closest integer value -
+  which is 593407kHz as originally requested by the drm framework) a
+  matching clock in it's internal table and errors out with "invalid
+  HDMI vclk freq"
+
+Fix the division precision by switching the whole meson driver to use
+unsigned long long (64-bit) Hz values for clock frequencies instead of
+unsigned int (32-bit) kHz to fix the rouding error.
+
+Fixes: e5fab2ec9ca4 ("drm/meson: vclk: add support for YUV420 setup")
+Reported-by: Christian Hewitt <christianshewitt@gmail.com>
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/r/20250421201300.778955-3-martin.blumenstingl@googlemail.com
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/r/20250421201300.778955-3-martin.blumenstingl@googlemail.com
+Stable-dep-of: d17e61ab63fb ("drm/meson: fix debug log statement when setting the HDMI clocks")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/meson/meson_drv.c          |   2 +-
+ drivers/gpu/drm/meson/meson_drv.h          |   2 +-
+ drivers/gpu/drm/meson/meson_encoder_hdmi.c |  29 +--
+ drivers/gpu/drm/meson/meson_vclk.c         | 195 +++++++++++----------
+ drivers/gpu/drm/meson/meson_vclk.h         |  13 +-
+ 5 files changed, 126 insertions(+), 115 deletions(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
+index 4bd0baa2a4f55..f59452e8fa6fb 100644
+--- a/drivers/gpu/drm/meson/meson_drv.c
++++ b/drivers/gpu/drm/meson/meson_drv.c
+@@ -168,7 +168,7 @@ static const struct meson_drm_soc_attr meson_drm_soc_attrs[] = {
+       /* S805X/S805Y HDMI PLL won't lock for HDMI PHY freq > 1,65GHz */
+       {
+               .limits = {
+-                      .max_hdmi_phy_freq = 1650000,
++                      .max_hdmi_phy_freq = 1650000000,
+               },
+               .attrs = (const struct soc_device_attribute []) {
+                       { .soc_id = "GXL (S805*)", },
+diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
+index 3f9345c14f31c..be4b0e4df6e13 100644
+--- a/drivers/gpu/drm/meson/meson_drv.h
++++ b/drivers/gpu/drm/meson/meson_drv.h
+@@ -37,7 +37,7 @@ struct meson_drm_match_data {
+ };
+ struct meson_drm_soc_limits {
+-      unsigned int max_hdmi_phy_freq;
++      unsigned long long max_hdmi_phy_freq;
+ };
+ struct meson_drm {
+diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+index 0593a1cde906f..ce8cea5d3a56b 100644
+--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+@@ -70,12 +70,12 @@ static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi,
+ {
+       struct meson_drm *priv = encoder_hdmi->priv;
+       int vic = drm_match_cea_mode(mode);
+-      unsigned int phy_freq;
+-      unsigned int vclk_freq;
+-      unsigned int venc_freq;
+-      unsigned int hdmi_freq;
++      unsigned long long phy_freq;
++      unsigned long long vclk_freq;
++      unsigned long long venc_freq;
++      unsigned long long hdmi_freq;
+-      vclk_freq = mode->clock;
++      vclk_freq = mode->clock * 1000;
+       /* For 420, pixel clock is half unlike venc clock */
+       if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+@@ -107,7 +107,8 @@ static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi,
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               venc_freq /= 2;
+-      dev_dbg(priv->dev, "vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
++      dev_dbg(priv->dev,
++              "vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n",
+               phy_freq, vclk_freq, venc_freq, hdmi_freq,
+               priv->venc.hdmi_use_enci);
+@@ -122,10 +123,11 @@ static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bri
+       struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
+       struct meson_drm *priv = encoder_hdmi->priv;
+       bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
+-      unsigned int phy_freq;
+-      unsigned int vclk_freq;
+-      unsigned int venc_freq;
+-      unsigned int hdmi_freq;
++      unsigned long long clock = mode->clock * 1000;
++      unsigned long long phy_freq;
++      unsigned long long vclk_freq;
++      unsigned long long venc_freq;
++      unsigned long long hdmi_freq;
+       int vic = drm_match_cea_mode(mode);
+       enum drm_mode_status status;
+@@ -144,12 +146,12 @@ static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bri
+               if (status != MODE_OK)
+                       return status;
+-              return meson_vclk_dmt_supported_freq(priv, mode->clock);
++              return meson_vclk_dmt_supported_freq(priv, clock);
+       /* Check against supported VIC modes */
+       } else if (!meson_venc_hdmi_supported_vic(vic))
+               return MODE_BAD;
+-      vclk_freq = mode->clock;
++      vclk_freq = clock;
+       /* For 420, pixel clock is half unlike venc clock */
+       if (drm_mode_is_420_only(display_info, mode) ||
+@@ -179,7 +181,8 @@ static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bri
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               venc_freq /= 2;
+-      dev_dbg(priv->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
++      dev_dbg(priv->dev,
++              "%s: vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz\n",
+               __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
+       return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
+diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
+index 2a82119eb58ed..3325580d885d0 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.c
++++ b/drivers/gpu/drm/meson/meson_vclk.c
+@@ -110,7 +110,10 @@
+ #define HDMI_PLL_LOCK         BIT(31)
+ #define HDMI_PLL_LOCK_G12A    (3 << 30)
+-#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
++#define PIXEL_FREQ_1000_1001(_freq)   \
++      DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL)
++#define PHY_FREQ_1000_1001(_freq)     \
++      (PIXEL_FREQ_1000_1001(DIV_ROUND_DOWN_ULL(_freq, 10ULL)) * 10)
+ /* VID PLL Dividers */
+ enum {
+@@ -360,11 +363,11 @@ enum {
+ };
+ struct meson_vclk_params {
+-      unsigned int pll_freq;
+-      unsigned int phy_freq;
+-      unsigned int vclk_freq;
+-      unsigned int venc_freq;
+-      unsigned int pixel_freq;
++      unsigned long long pll_freq;
++      unsigned long long phy_freq;
++      unsigned long long vclk_freq;
++      unsigned long long venc_freq;
++      unsigned long long pixel_freq;
+       unsigned int pll_od1;
+       unsigned int pll_od2;
+       unsigned int pll_od3;
+@@ -372,11 +375,11 @@ struct meson_vclk_params {
+       unsigned int vclk_div;
+ } params[] = {
+       [MESON_VCLK_HDMI_ENCI_54000] = {
+-              .pll_freq = 4320000,
+-              .phy_freq = 270000,
+-              .vclk_freq = 54000,
+-              .venc_freq = 54000,
+-              .pixel_freq = 54000,
++              .pll_freq = 4320000000,
++              .phy_freq = 270000000,
++              .vclk_freq = 54000000,
++              .venc_freq = 54000000,
++              .pixel_freq = 54000000,
+               .pll_od1 = 4,
+               .pll_od2 = 4,
+               .pll_od3 = 1,
+@@ -384,11 +387,11 @@ struct meson_vclk_params {
+               .vclk_div = 1,
+       },
+       [MESON_VCLK_HDMI_DDR_54000] = {
+-              .pll_freq = 4320000,
+-              .phy_freq = 270000,
+-              .vclk_freq = 54000,
+-              .venc_freq = 54000,
+-              .pixel_freq = 27000,
++              .pll_freq = 4320000000,
++              .phy_freq = 270000000,
++              .vclk_freq = 54000000,
++              .venc_freq = 54000000,
++              .pixel_freq = 27000000,
+               .pll_od1 = 4,
+               .pll_od2 = 4,
+               .pll_od3 = 1,
+@@ -396,11 +399,11 @@ struct meson_vclk_params {
+               .vclk_div = 1,
+       },
+       [MESON_VCLK_HDMI_DDR_148500] = {
+-              .pll_freq = 2970000,
+-              .phy_freq = 742500,
+-              .vclk_freq = 148500,
+-              .venc_freq = 148500,
+-              .pixel_freq = 74250,
++              .pll_freq = 2970000000,
++              .phy_freq = 742500000,
++              .vclk_freq = 148500000,
++              .venc_freq = 148500000,
++              .pixel_freq = 74250000,
+               .pll_od1 = 4,
+               .pll_od2 = 1,
+               .pll_od3 = 1,
+@@ -408,11 +411,11 @@ struct meson_vclk_params {
+               .vclk_div = 1,
+       },
+       [MESON_VCLK_HDMI_74250] = {
+-              .pll_freq = 2970000,
+-              .phy_freq = 742500,
+-              .vclk_freq = 74250,
+-              .venc_freq = 74250,
+-              .pixel_freq = 74250,
++              .pll_freq = 2970000000,
++              .phy_freq = 742500000,
++              .vclk_freq = 74250000,
++              .venc_freq = 74250000,
++              .pixel_freq = 74250000,
+               .pll_od1 = 2,
+               .pll_od2 = 2,
+               .pll_od3 = 2,
+@@ -420,11 +423,11 @@ struct meson_vclk_params {
+               .vclk_div = 1,
+       },
+       [MESON_VCLK_HDMI_148500] = {
+-              .pll_freq = 2970000,
+-              .phy_freq = 1485000,
+-              .vclk_freq = 148500,
+-              .venc_freq = 148500,
+-              .pixel_freq = 148500,
++              .pll_freq = 2970000000,
++              .phy_freq = 1485000000,
++              .vclk_freq = 148500000,
++              .venc_freq = 148500000,
++              .pixel_freq = 148500000,
+               .pll_od1 = 1,
+               .pll_od2 = 2,
+               .pll_od3 = 2,
+@@ -432,11 +435,11 @@ struct meson_vclk_params {
+               .vclk_div = 1,
+       },
+       [MESON_VCLK_HDMI_297000] = {
+-              .pll_freq = 5940000,
+-              .phy_freq = 2970000,
+-              .venc_freq = 297000,
+-              .vclk_freq = 297000,
+-              .pixel_freq = 297000,
++              .pll_freq = 5940000000,
++              .phy_freq = 2970000000,
++              .venc_freq = 297000000,
++              .vclk_freq = 297000000,
++              .pixel_freq = 297000000,
+               .pll_od1 = 2,
+               .pll_od2 = 1,
+               .pll_od3 = 1,
+@@ -444,11 +447,11 @@ struct meson_vclk_params {
+               .vclk_div = 2,
+       },
+       [MESON_VCLK_HDMI_594000] = {
+-              .pll_freq = 5940000,
+-              .phy_freq = 5940000,
+-              .venc_freq = 594000,
+-              .vclk_freq = 594000,
+-              .pixel_freq = 594000,
++              .pll_freq = 5940000000,
++              .phy_freq = 5940000000,
++              .venc_freq = 594000000,
++              .vclk_freq = 594000000,
++              .pixel_freq = 594000000,
+               .pll_od1 = 1,
+               .pll_od2 = 1,
+               .pll_od3 = 2,
+@@ -456,11 +459,11 @@ struct meson_vclk_params {
+               .vclk_div = 1,
+       },
+       [MESON_VCLK_HDMI_594000_YUV420] = {
+-              .pll_freq = 5940000,
+-              .phy_freq = 2970000,
+-              .venc_freq = 594000,
+-              .vclk_freq = 594000,
+-              .pixel_freq = 297000,
++              .pll_freq = 5940000000,
++              .phy_freq = 2970000000,
++              .venc_freq = 594000000,
++              .vclk_freq = 594000000,
++              .pixel_freq = 297000000,
+               .pll_od1 = 2,
+               .pll_od2 = 1,
+               .pll_od3 = 1,
+@@ -617,16 +620,16 @@ static void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
+                               3 << 20, pll_od_to_reg(od3) << 20);
+ }
+-#define XTAL_FREQ 24000
++#define XTAL_FREQ (24 * 1000 * 1000)
+ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
+-                                       unsigned int pll_freq)
++                                       unsigned long long pll_freq)
+ {
+       /* The GXBB PLL has a /2 pre-multiplier */
+       if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
+-              pll_freq /= 2;
++              pll_freq = DIV_ROUND_DOWN_ULL(pll_freq, 2);
+-      return pll_freq / XTAL_FREQ;
++      return DIV_ROUND_DOWN_ULL(pll_freq, XTAL_FREQ);
+ }
+ #define HDMI_FRAC_MAX_GXBB    4096
+@@ -635,12 +638,13 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
+ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
+                                           unsigned int m,
+-                                          unsigned int pll_freq)
++                                          unsigned long long pll_freq)
+ {
+-      unsigned int parent_freq = XTAL_FREQ;
++      unsigned long long parent_freq = XTAL_FREQ;
+       unsigned int frac_max = HDMI_FRAC_MAX_GXL;
+       unsigned int frac_m;
+       unsigned int frac;
++      u32 remainder;
+       /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
+       if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
+@@ -652,11 +656,11 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
+               frac_max = HDMI_FRAC_MAX_G12A;
+       /* We can have a perfect match !*/
+-      if (pll_freq / m == parent_freq &&
+-          pll_freq % m == 0)
++      if (div_u64_rem(pll_freq, m, &remainder) == parent_freq &&
++          remainder == 0)
+               return 0;
+-      frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
++      frac = mul_u64_u64_div_u64(pll_freq, frac_max, parent_freq);
+       frac_m = m * frac_max;
+       if (frac_m > frac)
+               return frac_max;
+@@ -666,7 +670,7 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
+ }
+ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
+-                                         unsigned int m,
++                                         unsigned long long m,
+                                          unsigned int frac)
+ {
+       if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
+@@ -694,7 +698,7 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
+ }
+ static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
+-                                     unsigned int freq,
++                                     unsigned long long freq,
+                                      unsigned int *m,
+                                      unsigned int *frac,
+                                      unsigned int *od)
+@@ -706,7 +710,7 @@ static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
+                       continue;
+               *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
+-              DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d\n",
++              DRM_DEBUG_DRIVER("PLL params for %lluHz: m=%x frac=%x od=%d\n",
+                                freq, *m, *frac, *od);
+               if (meson_hdmi_pll_validate_params(priv, *m, *frac))
+@@ -718,7 +722,7 @@ static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
+ /* pll_freq is the frequency after the OD dividers */
+ enum drm_mode_status
+-meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
++meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned long long freq)
+ {
+       unsigned int od, m, frac;
+@@ -741,7 +745,7 @@ EXPORT_SYMBOL_GPL(meson_vclk_dmt_supported_freq);
+ /* pll_freq is the frequency after the OD dividers */
+ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
+-                                     unsigned int pll_freq)
++                                     unsigned long long pll_freq)
+ {
+       unsigned int od, m, frac, od1, od2, od3;
+@@ -756,7 +760,7 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
+                       od1 = od / od2;
+               }
+-              DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
++              DRM_DEBUG_DRIVER("PLL params for %lluHz: m=%x frac=%x od=%d/%d/%d\n",
+                                pll_freq, m, frac, od1, od2, od3);
+               meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+@@ -764,17 +768,18 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
+               return;
+       }
+-      DRM_ERROR("Fatal, unable to find parameters for PLL freq %d\n",
++      DRM_ERROR("Fatal, unable to find parameters for PLL freq %lluHz\n",
+                 pll_freq);
+ }
+ enum drm_mode_status
+-meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
+-                            unsigned int vclk_freq)
++meson_vclk_vic_supported_freq(struct meson_drm *priv,
++                            unsigned long long phy_freq,
++                            unsigned long long vclk_freq)
+ {
+       int i;
+-      DRM_DEBUG_DRIVER("phy_freq = %d vclk_freq = %d\n",
++      DRM_DEBUG_DRIVER("phy_freq = %lluHz vclk_freq = %lluHz\n",
+                        phy_freq, vclk_freq);
+       /* Check against soc revision/package limits */
+@@ -785,19 +790,19 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
+       }
+       for (i = 0 ; params[i].pixel_freq ; ++i) {
+-              DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
++              DRM_DEBUG_DRIVER("i = %d pixel_freq = %lluHz alt = %lluHz\n",
+                                i, params[i].pixel_freq,
+-                               FREQ_1000_1001(params[i].pixel_freq));
+-              DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n",
++                               PIXEL_FREQ_1000_1001(params[i].pixel_freq));
++              DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n",
+                                i, params[i].phy_freq,
+-                               FREQ_1000_1001(params[i].phy_freq/10)*10);
++                               PHY_FREQ_1000_1001(params[i].phy_freq));
+               /* Match strict frequency */
+               if (phy_freq == params[i].phy_freq &&
+                   vclk_freq == params[i].vclk_freq)
+                       return MODE_OK;
+               /* Match 1000/1001 variant */
+-              if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) &&
+-                  vclk_freq == FREQ_1000_1001(params[i].vclk_freq))
++              if (phy_freq == PHY_FREQ_1000_1001(params[i].phy_freq) &&
++                  vclk_freq == PIXEL_FREQ_1000_1001(params[i].vclk_freq))
+                       return MODE_OK;
+       }
+@@ -805,8 +810,9 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
+ }
+ EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
+-static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+-                         unsigned int od1, unsigned int od2, unsigned int od3,
++static void meson_vclk_set(struct meson_drm *priv,
++                         unsigned long long pll_base_freq, unsigned int od1,
++                         unsigned int od2, unsigned int od3,
+                          unsigned int vid_pll_div, unsigned int vclk_div,
+                          unsigned int hdmi_tx_div, unsigned int venc_div,
+                          bool hdmi_use_enci, bool vic_alternate_clock)
+@@ -826,15 +832,15 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+               meson_hdmi_pll_generic_set(priv, pll_base_freq);
+       } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
+               switch (pll_base_freq) {
+-              case 2970000:
++              case 2970000000:
+                       m = 0x3d;
+                       frac = vic_alternate_clock ? 0xd02 : 0xe00;
+                       break;
+-              case 4320000:
++              case 4320000000:
+                       m = vic_alternate_clock ? 0x59 : 0x5a;
+                       frac = vic_alternate_clock ? 0xe8f : 0;
+                       break;
+-              case 5940000:
++              case 5940000000:
+                       m = 0x7b;
+                       frac = vic_alternate_clock ? 0xa05 : 0xc00;
+                       break;
+@@ -844,15 +850,15 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+       } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
+                  meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
+               switch (pll_base_freq) {
+-              case 2970000:
++              case 2970000000:
+                       m = 0x7b;
+                       frac = vic_alternate_clock ? 0x281 : 0x300;
+                       break;
+-              case 4320000:
++              case 4320000000:
+                       m = vic_alternate_clock ? 0xb3 : 0xb4;
+                       frac = vic_alternate_clock ? 0x347 : 0;
+                       break;
+-              case 5940000:
++              case 5940000000:
+                       m = 0xf7;
+                       frac = vic_alternate_clock ? 0x102 : 0x200;
+                       break;
+@@ -861,15 +867,15 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+               meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+       } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+               switch (pll_base_freq) {
+-              case 2970000:
++              case 2970000000:
+                       m = 0x7b;
+                       frac = vic_alternate_clock ? 0x140b4 : 0x18000;
+                       break;
+-              case 4320000:
++              case 4320000000:
+                       m = vic_alternate_clock ? 0xb3 : 0xb4;
+                       frac = vic_alternate_clock ? 0x1a3ee : 0;
+                       break;
+-              case 5940000:
++              case 5940000000:
+                       m = 0xf7;
+                       frac = vic_alternate_clock ? 0x8148 : 0x10000;
+                       break;
+@@ -1025,14 +1031,14 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+ }
+ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+-                    unsigned int phy_freq, unsigned int vclk_freq,
+-                    unsigned int venc_freq, unsigned int dac_freq,
++                    unsigned long long phy_freq, unsigned long long vclk_freq,
++                    unsigned long long venc_freq, unsigned long long dac_freq,
+                     bool hdmi_use_enci)
+ {
+       bool vic_alternate_clock = false;
+-      unsigned int freq;
+-      unsigned int hdmi_tx_div;
+-      unsigned int venc_div;
++      unsigned long long freq;
++      unsigned long long hdmi_tx_div;
++      unsigned long long venc_div;
+       if (target == MESON_VCLK_TARGET_CVBS) {
+               meson_venci_cvbs_clock_config(priv);
+@@ -1052,27 +1058,27 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+               return;
+       }
+-      hdmi_tx_div = vclk_freq / dac_freq;
++      hdmi_tx_div = DIV_ROUND_DOWN_ULL(vclk_freq, dac_freq);
+       if (hdmi_tx_div == 0) {
+-              pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
++              pr_err("Fatal Error, invalid HDMI-TX freq %lluHz\n",
+                      dac_freq);
+               return;
+       }
+-      venc_div = vclk_freq / venc_freq;
++      venc_div = DIV_ROUND_DOWN_ULL(vclk_freq, venc_freq);
+       if (venc_div == 0) {
+-              pr_err("Fatal Error, invalid HDMI venc freq %d\n",
++              pr_err("Fatal Error, invalid HDMI venc freq %lluHz\n",
+                      venc_freq);
+               return;
+       }
+       for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
+               if ((phy_freq == params[freq].phy_freq ||
+-                   phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) &&
++                   phy_freq == PHY_FREQ_1000_1001(params[freq].phy_freq)) &&
+                   (vclk_freq == params[freq].vclk_freq ||
+-                   vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) {
++                   vclk_freq == PIXEL_FREQ_1000_1001(params[freq].vclk_freq))) {
+                       if (vclk_freq != params[freq].vclk_freq)
+                               vic_alternate_clock = true;
+                       else
+@@ -1098,7 +1104,8 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+       }
+       if (!params[freq].pixel_freq) {
+-              pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
++              pr_err("Fatal Error, invalid HDMI vclk freq %lluHz\n",
++                     vclk_freq);
+               return;
+       }
+diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
+index 60617aaf18dd1..7ac55744e5749 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.h
++++ b/drivers/gpu/drm/meson/meson_vclk.h
+@@ -20,17 +20,18 @@ enum {
+ };
+ /* 27MHz is the CVBS Pixel Clock */
+-#define MESON_VCLK_CVBS                       27000
++#define MESON_VCLK_CVBS                       (27 * 1000 * 1000)
+ enum drm_mode_status
+-meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
++meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned long long freq);
+ enum drm_mode_status
+-meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
+-                            unsigned int vclk_freq);
++meson_vclk_vic_supported_freq(struct meson_drm *priv,
++                            unsigned long long phy_freq,
++                            unsigned long long vclk_freq);
+ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+-                    unsigned int phy_freq, unsigned int vclk_freq,
+-                    unsigned int venc_freq, unsigned int dac_freq,
++                    unsigned long long phy_freq, unsigned long long vclk_freq,
++                    unsigned long long venc_freq, unsigned long long dac_freq,
+                     bool hdmi_use_enci);
+ #endif /* __MESON_VCLK_H */
+-- 
+2.39.5
+
diff --git a/queue-6.12/drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch b/queue-6.12/drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch
new file mode 100644 (file)
index 0000000..76dbd95
--- /dev/null
@@ -0,0 +1,46 @@
+From 2b228ef23159f6a49b32819667d9f59a012326b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Jun 2025 00:10:31 +0200
+Subject: drm/meson: use vclk_freq instead of pixel_freq in debug print
+
+From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+[ Upstream commit faf2f8382088e8c74bd6eeb236c8c9190e61615e ]
+
+meson_vclk_vic_supported_freq() has a debug print which includes the
+pixel freq. However, within the whole function the pixel freq is
+irrelevant, other than checking the end of the params array. Switch to
+printing the vclk_freq which is being compared / matched against the
+inputs to the function to avoid confusion when analyzing error reports
+from users.
+
+Fixes: e5fab2ec9ca4 ("drm/meson: vclk: add support for YUV420 setup")
+Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://lore.kernel.org/r/20250606221031.3419353-1-martin.blumenstingl@googlemail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/meson/meson_vclk.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
+index 3325580d885d0..c4123bb958e4c 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.c
++++ b/drivers/gpu/drm/meson/meson_vclk.c
+@@ -790,9 +790,9 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv,
+       }
+       for (i = 0 ; params[i].pixel_freq ; ++i) {
+-              DRM_DEBUG_DRIVER("i = %d pixel_freq = %lluHz alt = %lluHz\n",
+-                               i, params[i].pixel_freq,
+-                               PIXEL_FREQ_1000_1001(params[i].pixel_freq));
++              DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n",
++                               i, params[i].vclk_freq,
++                               PIXEL_FREQ_1000_1001(params[i].vclk_freq));
+               DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n",
+                                i, params[i].phy_freq,
+                                PHY_FREQ_1000_1001(params[i].phy_freq));
+-- 
+2.39.5
+
diff --git a/queue-6.12/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch b/queue-6.12/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch
new file mode 100644 (file)
index 0000000..ae63a10
--- /dev/null
@@ -0,0 +1,44 @@
+From fae629b7300ec6850bcb4f6c3c1bbffc896945f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 May 2025 10:31:52 +0200
+Subject: i40e: retry VFLR handling if there is ongoing VF reset
+
+From: Robert Malz <robert.malz@canonical.com>
+
+[ Upstream commit fb4e9239e029954a37a00818b21e837cebf2aa10 ]
+
+When a VFLR interrupt is received during a VF reset initiated from a
+different source, the VFLR may be not fully handled. This can
+leave the VF in an undefined state.
+To address this, set the I40E_VFLR_EVENT_PENDING bit again during VFLR
+handling if the reset is not yet complete. This ensures the driver
+will properly complete the VF reset in such scenarios.
+
+Fixes: 52424f974bc5 ("i40e: Fix VF hang when reset is triggered on another VF")
+Signed-off-by: Robert Malz <robert.malz@canonical.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index bde41d30c69ee..625fa93fc18bb 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -4328,7 +4328,10 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)
+               reg = rd32(hw, I40E_GLGEN_VFLRSTAT(reg_idx));
+               if (reg & BIT(bit_idx))
+                       /* i40e_reset_vf will clear the bit in GLGEN_VFLRSTAT */
+-                      i40e_reset_vf(vf, true);
++                      if (!i40e_reset_vf(vf, true)) {
++                              /* At least one VF did not finish resetting, retry next time */
++                              set_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
++                      }
+       }
+       return 0;
+-- 
+2.39.5
+
diff --git a/queue-6.12/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch b/queue-6.12/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch
new file mode 100644 (file)
index 0000000..7efcb93
--- /dev/null
@@ -0,0 +1,55 @@
+From ae7d9c6a851e064a1d97ad8fa00c526e9dc5b4bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 May 2025 10:31:51 +0200
+Subject: i40e: return false from i40e_reset_vf if reset is in progress
+
+From: Robert Malz <robert.malz@canonical.com>
+
+[ Upstream commit a2c90d63b71223d69a813333c1abf4fdacddbbe5 ]
+
+The function i40e_vc_reset_vf attempts, up to 20 times, to handle a
+VF reset request, using the return value of i40e_reset_vf as an indicator
+of whether the reset was successfully triggered. Currently, i40e_reset_vf
+always returns true, which causes new reset requests to be ignored if a
+different VF reset is already in progress.
+
+This patch updates the return value of i40e_reset_vf to reflect when
+another VF reset is in progress, allowing the caller to properly use
+the retry mechanism.
+
+Fixes: 52424f974bc5 ("i40e: Fix VF hang when reset is triggered on another VF")
+Signed-off-by: Robert Malz <robert.malz@canonical.com>
+Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index dfa785e39458d..bde41d30c69ee 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -1546,8 +1546,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
+  * @vf: pointer to the VF structure
+  * @flr: VFLR was issued or not
+  *
+- * Returns true if the VF is in reset, resets successfully, or resets
+- * are disabled and false otherwise.
++ * Return: True if reset was performed successfully or if resets are disabled.
++ * False if reset is already in progress.
+  **/
+ bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
+ {
+@@ -1566,7 +1566,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
+       /* If VF is being reset already we don't need to continue. */
+       if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+-              return true;
++              return false;
+       i40e_trigger_vf_reset(vf, flr);
+-- 
+2.39.5
+
diff --git a/queue-6.12/macsec-macsec-sci-assignment-for-es-0.patch b/queue-6.12/macsec-macsec-sci-assignment-for-es-0.patch
new file mode 100644 (file)
index 0000000..ca33cbc
--- /dev/null
@@ -0,0 +1,128 @@
+From 9ae2255a50ee299607ea005d50cccc5b9ea2368d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jun 2025 09:26:26 +0200
+Subject: macsec: MACsec SCI assignment for ES = 0
+
+From: Carlos Fernandez <carlos.fernandez@technica-engineering.de>
+
+[ Upstream commit d9816ec74e6d6aa29219d010bba3f780ba1d9d75 ]
+
+According to 802.1AE standard, when ES and SC flags in TCI are zero,
+used SCI should be the current active SC_RX. Current code uses the
+header MAC address. Without this patch, when ES flag is 0 (using a
+bridge or switch), header MAC will not fit the SCI and MACSec frames
+will be discarted.
+
+In order to test this issue, MACsec link should be stablished between
+two interfaces, setting SC and ES flags to zero and a port identifier
+different than one. For example, using ip macsec tools:
+
+ip link add link $ETH0 macsec0 type macsec port 11 send_sci off
+end_station off
+ip macsec add macsec0 tx sa 0 pn 2 on key 01 $ETH1_KEY
+ip macsec add macsec0 rx port 11 address $ETH1_MAC
+ip macsec add macsec0 rx port 11 address $ETH1_MAC sa 0 pn 2 on key 02
+ip link set dev macsec0 up
+
+ip link add link $ETH1 macsec1 type macsec port 11 send_sci off
+end_station off
+ip macsec add macsec1 tx sa 0 pn 2 on key 01 $ETH0_KEY
+ip macsec add macsec1 rx port 11 address $ETH0_MAC
+ip macsec add macsec1 rx port 11 address $ETH0_MAC sa 0 pn 2 on key 02
+ip link set dev macsec1 up
+
+Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
+Co-developed-by: Andreu Montiel <Andreu.Montiel@technica-engineering.de>
+Signed-off-by: Andreu Montiel <Andreu.Montiel@technica-engineering.de>
+Signed-off-by: Carlos Fernandez <carlos.fernandez@technica-engineering.de>
+Reviewed-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/macsec.c | 40 ++++++++++++++++++++++++++++++++++------
+ 1 file changed, 34 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index ee21592825738..090a56a5e456a 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -246,15 +246,39 @@ static sci_t make_sci(const u8 *addr, __be16 port)
+       return sci;
+ }
+-static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present)
++static sci_t macsec_active_sci(struct macsec_secy *secy)
+ {
+-      sci_t sci;
++      struct macsec_rx_sc *rx_sc = rcu_dereference_bh(secy->rx_sc);
++
++      /* Case single RX SC */
++      if (rx_sc && !rcu_dereference_bh(rx_sc->next))
++              return (rx_sc->active) ? rx_sc->sci : 0;
++      /* Case no RX SC or multiple */
++      else
++              return 0;
++}
++
++static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present,
++                            struct macsec_rxh_data *rxd)
++{
++      struct macsec_dev *macsec;
++      sci_t sci = 0;
+-      if (sci_present)
++      /* SC = 1 */
++      if (sci_present) {
+               memcpy(&sci, hdr->secure_channel_id,
+                      sizeof(hdr->secure_channel_id));
+-      else
++      /* SC = 0; ES = 0 */
++      } else if ((!(hdr->tci_an & (MACSEC_TCI_ES | MACSEC_TCI_SC))) &&
++                 (list_is_singular(&rxd->secys))) {
++              /* Only one SECY should exist on this scenario */
++              macsec = list_first_or_null_rcu(&rxd->secys, struct macsec_dev,
++                                              secys);
++              if (macsec)
++                      return macsec_active_sci(&macsec->secy);
++      } else {
+               sci = make_sci(hdr->eth.h_source, MACSEC_PORT_ES);
++      }
+       return sci;
+ }
+@@ -1108,7 +1132,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
+       struct macsec_rxh_data *rxd;
+       struct macsec_dev *macsec;
+       unsigned int len;
+-      sci_t sci;
++      sci_t sci = 0;
+       u32 hdr_pn;
+       bool cbit;
+       struct pcpu_rx_sc_stats *rxsc_stats;
+@@ -1155,11 +1179,14 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
+       macsec_skb_cb(skb)->has_sci = !!(hdr->tci_an & MACSEC_TCI_SC);
+       macsec_skb_cb(skb)->assoc_num = hdr->tci_an & MACSEC_AN_MASK;
+-      sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci);
+       rcu_read_lock();
+       rxd = macsec_data_rcu(skb->dev);
++      sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci, rxd);
++      if (!sci)
++              goto drop_nosc;
++
+       list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
+               struct macsec_rx_sc *sc = find_rx_sc(&macsec->secy, sci);
+@@ -1282,6 +1309,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
+       macsec_rxsa_put(rx_sa);
+ drop_nosa:
+       macsec_rxsc_put(rx_sc);
++drop_nosc:
+       rcu_read_unlock();
+ drop_direct:
+       kfree_skb(skb);
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch b/queue-6.12/net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch
new file mode 100644 (file)
index 0000000..c32485d
--- /dev/null
@@ -0,0 +1,46 @@
+From c3da0620105a69bae9c3cf483b2c9f4ba2590d36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jun 2025 10:46:43 -0700
+Subject: net: drv: netdevsim: don't napi_complete() from netpoll
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 1264971017b4d7141352a7fe29021bdfce5d885d ]
+
+netdevsim supports netpoll. Make sure we don't call napi_complete()
+from it, since it may not be scheduled. Breno reports hitting a
+warning in napi_complete_done():
+
+WARNING: CPU: 14 PID: 104 at net/core/dev.c:6592 napi_complete_done+0x2cc/0x560
+  __napi_poll+0x2d8/0x3a0
+  handle_softirqs+0x1fe/0x710
+
+This is presumably after netpoll stole the SCHED bit prematurely.
+
+Reported-by: Breno Leitao <leitao@debian.org>
+Fixes: 3762ec05a9fb ("netdevsim: add NAPI support")
+Tested-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20250611174643.2769263-1-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/netdevsim/netdev.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
+index 1b29d1d794a20..79b898311819d 100644
+--- a/drivers/net/netdevsim/netdev.c
++++ b/drivers/net/netdevsim/netdev.c
+@@ -353,7 +353,8 @@ static int nsim_poll(struct napi_struct *napi, int budget)
+       int done;
+       done = nsim_rcv(rq, budget);
+-      napi_complete(napi);
++      if (done < budget)
++              napi_complete_done(napi, done);
+       return done;
+ }
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch b/queue-6.12/net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch
new file mode 100644 (file)
index 0000000..ad315dc
--- /dev/null
@@ -0,0 +1,69 @@
+From 51c23c400d41b0414697621e60cbe1949404992e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Jun 2025 21:49:14 +0200
+Subject: net: dsa: b53: fix untagged traffic sent via cpu tagged with VID 0
+
+From: Jonas Gorski <jonas.gorski@gmail.com>
+
+[ Upstream commit 692eb9f8a5b71d852e873375d20cf5da7a046ea6 ]
+
+When Linux sends out untagged traffic from a port, it will enter the CPU
+port without any VLAN tag, even if the port is a member of a vlan
+filtering bridge with a PVID egress untagged VLAN.
+
+This makes the CPU port's PVID take effect, and the PVID's VLAN
+table entry controls if the packet will be tagged on egress.
+
+Since commit 45e9d59d3950 ("net: dsa: b53: do not allow to configure
+VLAN 0") we remove bridged ports from VLAN 0 when joining or leaving a
+VLAN aware bridge. But we also clear the untagged bit, causing untagged
+traffic from the controller to become tagged with VID 0 (and priority
+0).
+
+Fix this by not touching the untagged map of VLAN 0. Additionally,
+always keep the CPU port as a member, as the untag map is only effective
+as long as there is at least one member, and we would remove it when
+bridging all ports and leaving no standalone ports.
+
+Since Linux (and the switch) treats VLAN 0 tagged traffic like untagged,
+the actual impact of this is rather low, but this also prevented earlier
+detection of the issue.
+
+Fixes: 45e9d59d3950 ("net: dsa: b53: do not allow to configure VLAN 0")
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://patch.msgid.link/20250602194914.1011890-1-jonas.gorski@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/b53/b53_common.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
+index 79039c0941c20..71c30a81c36db 100644
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -2036,9 +2036,6 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
+               b53_get_vlan_entry(dev, pvid, vl);
+               vl->members &= ~BIT(port);
+-              if (vl->members == BIT(cpu_port))
+-                      vl->members &= ~BIT(cpu_port);
+-              vl->untag = vl->members;
+               b53_set_vlan_entry(dev, pvid, vl);
+       }
+@@ -2117,8 +2114,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
+               }
+               b53_get_vlan_entry(dev, pvid, vl);
+-              vl->members |= BIT(port) | BIT(cpu_port);
+-              vl->untag |= BIT(port) | BIT(cpu_port);
++              vl->members |= BIT(port);
+               b53_set_vlan_entry(dev, pvid, vl);
+       }
+ }
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-fix-toctou-issue-in-sk_is_readable.patch b/queue-6.12/net-fix-toctou-issue-in-sk_is_readable.patch
new file mode 100644 (file)
index 0000000..28ef0c6
--- /dev/null
@@ -0,0 +1,52 @@
+From dcbecbbb181510e4ce2cb2d7f0d9ca239d8e91b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jun 2025 19:08:03 +0200
+Subject: net: Fix TOCTOU issue in sk_is_readable()
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 2660a544fdc0940bba15f70508a46cf9a6491230 ]
+
+sk->sk_prot->sock_is_readable is a valid function pointer when sk resides
+in a sockmap. After the last sk_psock_put() (which usually happens when
+socket is removed from sockmap), sk->sk_prot gets restored and
+sk->sk_prot->sock_is_readable becomes NULL.
+
+This makes sk_is_readable() racy, if the value of sk->sk_prot is reloaded
+after the initial check. Which in turn may lead to a null pointer
+dereference.
+
+Ensure the function pointer does not turn NULL after the check.
+
+Fixes: 8934ce2fd081 ("bpf: sockmap redirect ingress support")
+Suggested-by: Jakub Sitnicki <jakub@cloudflare.com>
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20250609-skisreadable-toctou-v1-1-d0dfb2d62c37@rbox.co
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sock.h | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index fa9b9dadbe170..b7270b6b9e9cc 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2942,8 +2942,11 @@ int sock_ioctl_inout(struct sock *sk, unsigned int cmd,
+ int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+ static inline bool sk_is_readable(struct sock *sk)
+ {
+-      if (sk->sk_prot->sock_is_readable)
+-              return sk->sk_prot->sock_is_readable(sk);
++      const struct proto *prot = READ_ONCE(sk->sk_prot);
++
++      if (prot->sock_is_readable)
++              return prot->sock_is_readable(sk);
++
+       return false;
+ }
+ #endif        /* _SOCK_H */
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch b/queue-6.12/net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch
new file mode 100644 (file)
index 0000000..6f88a12
--- /dev/null
@@ -0,0 +1,59 @@
+From 7e9f8c07ab9571bbbc30558c1c046299176ff883 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jun 2025 17:31:47 +0200
+Subject: net/mdiobus: Fix potential out-of-bounds clause 45 read/write access
+
+From: Jakub Raczynski <j.raczynski@samsung.com>
+
+[ Upstream commit 260388f79e94fb3026c419a208ece8358bb7b555 ]
+
+When using publicly available tools like 'mdio-tools' to read/write data
+from/to network interface and its PHY via C45 (clause 45) mdiobus,
+there is no verification of parameters passed to the ioctl and
+it accepts any mdio address.
+Currently there is support for 32 addresses in kernel via PHY_MAX_ADDR define,
+but it is possible to pass higher value than that via ioctl.
+While read/write operation should generally fail in this case,
+mdiobus provides stats array, where wrong address may allow out-of-bounds
+read/write.
+
+Fix that by adding address verification before C45 read/write operation.
+While this excludes this access from any statistics, it improves security of
+read/write operation.
+
+Fixes: 4e4aafcddbbf ("net: mdio: Add dedicated C45 API to MDIO bus drivers")
+Signed-off-by: Jakub Raczynski <j.raczynski@samsung.com>
+Reported-by: Wenjing Shan <wenjing.shan@samsung.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/mdio_bus.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index 7d2616435ce9e..591e8fd33d8ea 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -985,6 +985,9 @@ int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
+       lockdep_assert_held_once(&bus->mdio_lock);
++      if (addr >= PHY_MAX_ADDR)
++              return -ENXIO;
++
+       if (bus->read_c45)
+               retval = bus->read_c45(bus, addr, devad, regnum);
+       else
+@@ -1016,6 +1019,9 @@ int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
+       lockdep_assert_held_once(&bus->mdio_lock);
++      if (addr >= PHY_MAX_ADDR)
++              return -ENXIO;
++
+       if (bus->write_c45)
+               err = bus->write_c45(bus, addr, devad, regnum, val);
+       else
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch b/queue-6.12/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch
new file mode 100644 (file)
index 0000000..7760e26
--- /dev/null
@@ -0,0 +1,58 @@
+From cf086fc037718ad9776d698d95fd556689c94a06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jun 2025 17:31:46 +0200
+Subject: net/mdiobus: Fix potential out-of-bounds read/write access
+
+From: Jakub Raczynski <j.raczynski@samsung.com>
+
+[ Upstream commit 0e629694126ca388916f059453a1c36adde219c4 ]
+
+When using publicly available tools like 'mdio-tools' to read/write data
+from/to network interface and its PHY via mdiobus, there is no verification of
+parameters passed to the ioctl and it accepts any mdio address.
+Currently there is support for 32 addresses in kernel via PHY_MAX_ADDR define,
+but it is possible to pass higher value than that via ioctl.
+While read/write operation should generally fail in this case,
+mdiobus provides stats array, where wrong address may allow out-of-bounds
+read/write.
+
+Fix that by adding address verification before read/write operation.
+While this excludes this access from any statistics, it improves security of
+read/write operation.
+
+Fixes: 080bb352fad00 ("net: phy: Maintain MDIO device and bus statistics")
+Signed-off-by: Jakub Raczynski <j.raczynski@samsung.com>
+Reported-by: Wenjing Shan <wenjing.shan@samsung.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/mdio_bus.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index 7e2f10182c0cf..7d2616435ce9e 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -889,6 +889,9 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
+       lockdep_assert_held_once(&bus->mdio_lock);
++      if (addr >= PHY_MAX_ADDR)
++              return -ENXIO;
++
+       if (bus->read)
+               retval = bus->read(bus, addr, regnum);
+       else
+@@ -918,6 +921,9 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
+       lockdep_assert_held_once(&bus->mdio_lock);
++      if (addr >= PHY_MAX_ADDR)
++              return -ENXIO;
++
+       if (bus->write)
+               err = bus->write(bus, addr, regnum, val);
+       else
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch b/queue-6.12/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch
new file mode 100644 (file)
index 0000000..5574570
--- /dev/null
@@ -0,0 +1,43 @@
+From c21ae7b0f2eae55867a343c58457e43ac6aa93c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 18:15:06 +0300
+Subject: net/mlx5: Ensure fw pages are always allocated on same NUMA
+
+From: Moshe Shemesh <moshe@nvidia.com>
+
+[ Upstream commit f37258133c1e95e61db532e14067e28b4881bf24 ]
+
+When firmware asks the driver to allocate more pages, using event of
+give_pages, the driver should always allocate it from same NUMA, the
+original device NUMA. Current code uses dev_to_node() which can result
+in different NUMA as it is changed by other driver flows, such as
+mlx5_dma_zalloc_coherent_node(). Instead, use saved numa node for
+allocating firmware pages.
+
+Fixes: 311c7c71c9bb ("net/mlx5e: Allocate DMA coherent memory on reader NUMA node")
+Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Link: https://patch.msgid.link/20250610151514.1094735-2-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+index 972e8e9df585b..9bc9bd83c2324 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+@@ -291,7 +291,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr, u32 function)
+ static int alloc_system_page(struct mlx5_core_dev *dev, u32 function)
+ {
+       struct device *device = mlx5_core_dma_dev(dev);
+-      int nid = dev_to_node(device);
++      int nid = dev->priv.numa_node;
+       struct page *page;
+       u64 zero_addr = 1;
+       u64 addr;
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch b/queue-6.12/net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch
new file mode 100644 (file)
index 0000000..cf7b3db
--- /dev/null
@@ -0,0 +1,106 @@
+From e28e5086704a187715675917a7601c29c1f120d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 18:15:07 +0300
+Subject: net/mlx5: Fix ECVF vports unload on shutdown flow
+
+From: Amir Tzin <amirtz@nvidia.com>
+
+[ Upstream commit 687560d8a9a2d654829ad0da1ec24242f1de711d ]
+
+Fix shutdown flow UAF when a virtual function is created on the embedded
+chip (ECVF) of a BlueField device. In such case the vport acl ingress
+table is not properly destroyed.
+
+ECVF functionality is independent of ecpf_vport_exists capability and
+thus functions mlx5_eswitch_(enable|disable)_pf_vf_vports() should not
+test it when enabling/disabling ECVF vports.
+
+kernel log:
+[] refcount_t: underflow; use-after-free.
+[] WARNING: CPU: 3 PID: 1 at lib/refcount.c:28
+   refcount_warn_saturate+0x124/0x220
+----------------
+[] Call trace:
+[] refcount_warn_saturate+0x124/0x220
+[] tree_put_node+0x164/0x1e0 [mlx5_core]
+[] mlx5_destroy_flow_table+0x98/0x2c0 [mlx5_core]
+[] esw_acl_ingress_table_destroy+0x28/0x40 [mlx5_core]
+[] esw_acl_ingress_lgcy_cleanup+0x80/0xf4 [mlx5_core]
+[] esw_legacy_vport_acl_cleanup+0x44/0x60 [mlx5_core]
+[] esw_vport_cleanup+0x64/0x90 [mlx5_core]
+[] mlx5_esw_vport_disable+0xc0/0x1d0 [mlx5_core]
+[] mlx5_eswitch_unload_ec_vf_vports+0xcc/0x150 [mlx5_core]
+[] mlx5_eswitch_disable_sriov+0x198/0x2a0 [mlx5_core]
+[] mlx5_device_disable_sriov+0xb8/0x1e0 [mlx5_core]
+[] mlx5_sriov_detach+0x40/0x50 [mlx5_core]
+[] mlx5_unload+0x40/0xc4 [mlx5_core]
+[] mlx5_unload_one_devl_locked+0x6c/0xe4 [mlx5_core]
+[] mlx5_unload_one+0x3c/0x60 [mlx5_core]
+[] shutdown+0x7c/0xa4 [mlx5_core]
+[] pci_device_shutdown+0x3c/0xa0
+[] device_shutdown+0x170/0x340
+[] __do_sys_reboot+0x1f4/0x2a0
+[] __arm64_sys_reboot+0x2c/0x40
+[] invoke_syscall+0x78/0x100
+[] el0_svc_common.constprop.0+0x54/0x184
+[] do_el0_svc+0x30/0xac
+[] el0_svc+0x48/0x160
+[] el0t_64_sync_handler+0xa4/0x12c
+[] el0t_64_sync+0x1a4/0x1a8
+[] --[ end trace 9c4601d68c70030e ]---
+
+Fixes: a7719b29a821 ("net/mlx5: Add management of EC VF vports")
+Reviewed-by: Daniel Jurgens <danielj@nvidia.com>
+Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
+Signed-off-by: Amir Tzin <amirtz@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Link: https://patch.msgid.link/20250610151514.1094735-3-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/eswitch.c | 21 ++++++++++++-------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+index 7aef30dbd82d6..6544546a1153f 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+@@ -1295,12 +1295,15 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
+               ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events);
+               if (ret)
+                       goto ecpf_err;
+-              if (mlx5_core_ec_sriov_enabled(esw->dev)) {
+-                      ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs,
+-                                                           enabled_events);
+-                      if (ret)
+-                              goto ec_vf_err;
+-              }
++      }
++
++      /* Enable ECVF vports */
++      if (mlx5_core_ec_sriov_enabled(esw->dev)) {
++              ret = mlx5_eswitch_load_ec_vf_vports(esw,
++                                                   esw->esw_funcs.num_ec_vfs,
++                                                   enabled_events);
++              if (ret)
++                      goto ec_vf_err;
+       }
+       /* Enable VF vports */
+@@ -1331,9 +1334,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
+ {
+       mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
++      if (mlx5_core_ec_sriov_enabled(esw->dev))
++              mlx5_eswitch_unload_ec_vf_vports(esw,
++                                               esw->esw_funcs.num_ec_vfs);
++
+       if (mlx5_ecpf_vport_exists(esw->dev)) {
+-              if (mlx5_core_ec_sriov_enabled(esw->dev))
+-                      mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs);
+               mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF);
+       }
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mlx5-fix-return-value-when-searching-for-existin.patch b/queue-6.12/net-mlx5-fix-return-value-when-searching-for-existin.patch
new file mode 100644 (file)
index 0000000..9c2d8ff
--- /dev/null
@@ -0,0 +1,61 @@
+From f74d1fa3fe36a866d26620d45463c3f510458572 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 18:15:08 +0300
+Subject: net/mlx5: Fix return value when searching for existing flow group
+
+From: Patrisious Haddad <phaddad@nvidia.com>
+
+[ Upstream commit 8ec40e3f1f72bf8f8accf18020d487caa99f46a4 ]
+
+When attempting to add a rule to an existing flow group, if a matching
+flow group exists but is not active, the error code returned should be
+EAGAIN, so that the rule can be added to the matching flow group once
+it is active, rather than ENOENT, which indicates that no matching
+flow group was found.
+
+Fixes: bd71b08ec2ee ("net/mlx5: Support multiple updates of steering rules in parallel")
+Signed-off-by: Gavi Teitz <gavi@nvidia.com>
+Signed-off-by: Roi Dayan <roid@nvidia.com>
+Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Link: https://patch.msgid.link/20250610151514.1094735-4-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index 0ce999706d412..1bc88743d2dfa 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -2200,6 +2200,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
+       struct mlx5_flow_handle *rule;
+       struct match_list *iter;
+       bool take_write = false;
++      bool try_again = false;
+       struct fs_fte *fte;
+       u64  version = 0;
+       int err;
+@@ -2264,6 +2265,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
+               nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
+               if (!g->node.active) {
++                      try_again = true;
+                       up_write_ref_node(&g->node, false);
+                       continue;
+               }
+@@ -2285,7 +2287,8 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
+                       tree_put_node(&fte->node, false);
+               return rule;
+       }
+-      rule = ERR_PTR(-ENOENT);
++      err = try_again ? -EAGAIN : -ENOENT;
++      rule = ERR_PTR(err);
+ out:
+       kmem_cache_free(steering->ftes_cache, fte);
+       return rule;
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch b/queue-6.12/net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch
new file mode 100644 (file)
index 0000000..43f147a
--- /dev/null
@@ -0,0 +1,38 @@
+From b7eeda42129971c48ef326adc0e689198b5f0416 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 18:15:10 +0300
+Subject: net/mlx5: HWS, fix missing ip_version handling in definer
+
+From: Yevgeny Kliteynik <kliteyn@nvidia.com>
+
+[ Upstream commit b5e3c76f35ee7e814c2469c73406c5bbf110d89c ]
+
+Fix missing field handling in definer - outer IP version.
+
+Fixes: 74a778b4a63f ("net/mlx5: HWS, added definers handling")
+Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Link: https://patch.msgid.link/20250610151514.1094735-6-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c
+index ab5f8f07f1f7e..72b19b05c0cf4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_definer.c
+@@ -558,6 +558,9 @@ hws_definer_conv_outer(struct mlx5hws_definer_conv_data *cd,
+       HWS_SET_HDR(fc, match_param, IP_PROTOCOL_O,
+                   outer_headers.ip_protocol,
+                   eth_l3_outer.protocol_next_header);
++      HWS_SET_HDR(fc, match_param, IP_VERSION_O,
++                  outer_headers.ip_version,
++                  eth_l3_outer.ip_version);
+       HWS_SET_HDR(fc, match_param, IP_TTL_O,
+                   outer_headers.ttl_hoplimit,
+                   eth_l3_outer.time_to_live_hop_limit);
+-- 
+2.39.5
+
diff --git a/queue-6.12/net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch b/queue-6.12/net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch
new file mode 100644 (file)
index 0000000..b70c80a
--- /dev/null
@@ -0,0 +1,79 @@
+From 4cb16147cdb58b21d686ec4481d7a69a3214d596 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 18:15:13 +0300
+Subject: net/mlx5e: Fix leak of Geneve TLV option object
+
+From: Jianbo Liu <jianbol@nvidia.com>
+
+[ Upstream commit aa9c44b842096c553871bc68a8cebc7861fa192b ]
+
+Previously, a unique tunnel id was added for the matching on TC
+non-zero chains, to support inner header rewrite with goto action.
+Later, it was used to support VF tunnel offload for vxlan, then for
+Geneve and GRE. To support VF tunnel, a temporary mlx5_flow_spec is
+used to parse tunnel options. For Geneve, if there is TLV option, a
+object is created, or refcnt is added if already exists. But the
+temporary mlx5_flow_spec is directly freed after parsing, which causes
+the leak because no information regarding the object is saved in
+flow's mlx5_flow_spec, which is used to free the object when deleting
+the flow.
+
+To fix the leak, call mlx5_geneve_tlv_option_del() before free the
+temporary spec if it has TLV object.
+
+Fixes: 521933cdc4aa ("net/mlx5e: Support Geneve and GRE with VF tunnel offload")
+Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Alex Lazar <alazar@nvidia.com>
+Signed-off-by: Mark Bloch <mbloch@nvidia.com>
+Link: https://patch.msgid.link/20250610151514.1094735-9-mbloch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 218d5402cd1a6..4d766eea32a37 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -2028,9 +2028,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+       return err;
+ }
+-static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow)
++static bool mlx5_flow_has_geneve_opt(struct mlx5_flow_spec *spec)
+ {
+-      struct mlx5_flow_spec *spec = &flow->attr->parse_attr->spec;
+       void *headers_v = MLX5_ADDR_OF(fte_match_param,
+                                      spec->match_value,
+                                      misc_parameters_3);
+@@ -2069,7 +2068,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
+       }
+       complete_all(&flow->del_hw_done);
+-      if (mlx5_flow_has_geneve_opt(flow))
++      if (mlx5_flow_has_geneve_opt(&attr->parse_attr->spec))
+               mlx5_geneve_tlv_option_del(priv->mdev->geneve);
+       if (flow->decap_route)
+@@ -2574,12 +2573,13 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
+               err = mlx5e_tc_tun_parse(filter_dev, priv, tmp_spec, f, match_level);
+               if (err) {
+-                      kvfree(tmp_spec);
+                       NL_SET_ERR_MSG_MOD(extack, "Failed to parse tunnel attributes");
+                       netdev_warn(priv->netdev, "Failed to parse tunnel attributes");
+-                      return err;
++              } else {
++                      err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec);
+               }
+-              err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec);
++              if (mlx5_flow_has_geneve_opt(tmp_spec))
++                      mlx5_geneve_tlv_option_del(priv->mdev->geneve);
+               kvfree(tmp_spec);
+               if (err)
+                       return err;
+-- 
+2.39.5
+
diff --git a/queue-6.12/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch b/queue-6.12/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch
new file mode 100644 (file)
index 0000000..d338cc8
--- /dev/null
@@ -0,0 +1,58 @@
+From 55f395ede0e6cec0f9bc648d7c90740d17b70eb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jun 2025 11:15:14 +0000
+Subject: net_sched: ets: fix a race in ets_qdisc_change()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d92adacdd8c2960be856e0b82acc5b7c5395fddb ]
+
+Gerrard Tai reported a race condition in ETS, whenever SFQ perturb timer
+fires at the wrong time.
+
+The race is as follows:
+
+CPU 0                                 CPU 1
+[1]: lock root
+[2]: qdisc_tree_flush_backlog()
+[3]: unlock root
+ |
+ |                                    [5]: lock root
+ |                                    [6]: rehash
+ |                                    [7]: qdisc_tree_reduce_backlog()
+ |
+[4]: qdisc_put()
+
+This can be abused to underflow a parent's qlen.
+
+Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog()
+should fix the race, because all packets will be purged from the qdisc
+before releasing the lock.
+
+Fixes: b05972f01e7d ("net: sched: tbf: don't call qdisc_put() while holding tree lock")
+Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Suggested-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250611111515.1983366-5-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_ets.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c
+index 2c069f0181c62..037f764822b96 100644
+--- a/net/sched/sch_ets.c
++++ b/net/sched/sch_ets.c
+@@ -661,7 +661,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
+       for (i = q->nbands; i < oldbands; i++) {
+               if (i >= q->nstrict && q->classes[i].qdisc->q.qlen)
+                       list_del_init(&q->classes[i].alist);
+-              qdisc_tree_flush_backlog(q->classes[i].qdisc);
++              qdisc_purge_queue(q->classes[i].qdisc);
+       }
+       WRITE_ONCE(q->nstrict, nstrict);
+       memcpy(q->prio2band, priomap, sizeof(priomap));
+-- 
+2.39.5
+
diff --git a/queue-6.12/net_sched-prio-fix-a-race-in-prio_tune.patch b/queue-6.12/net_sched-prio-fix-a-race-in-prio_tune.patch
new file mode 100644 (file)
index 0000000..571eb2d
--- /dev/null
@@ -0,0 +1,58 @@
+From 6506388d10c54e66a64a1145e622db9bc1e4cee7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jun 2025 11:15:11 +0000
+Subject: net_sched: prio: fix a race in prio_tune()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d35acc1be3480505b5931f17e4ea9b7617fea4d3 ]
+
+Gerrard Tai reported a race condition in PRIO, whenever SFQ perturb timer
+fires at the wrong time.
+
+The race is as follows:
+
+CPU 0                                 CPU 1
+[1]: lock root
+[2]: qdisc_tree_flush_backlog()
+[3]: unlock root
+ |
+ |                                    [5]: lock root
+ |                                    [6]: rehash
+ |                                    [7]: qdisc_tree_reduce_backlog()
+ |
+[4]: qdisc_put()
+
+This can be abused to underflow a parent's qlen.
+
+Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog()
+should fix the race, because all packets will be purged from the qdisc
+before releasing the lock.
+
+Fixes: 7b8e0b6e6599 ("net: sched: prio: delay destroying child qdiscs on change")
+Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Suggested-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250611111515.1983366-2-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_prio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
+index cc30f7a32f1a7..9e2b9a490db23 100644
+--- a/net/sched/sch_prio.c
++++ b/net/sched/sch_prio.c
+@@ -211,7 +211,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
+       memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
+       for (i = q->bands; i < oldbands; i++)
+-              qdisc_tree_flush_backlog(q->queues[i]);
++              qdisc_purge_queue(q->queues[i]);
+       for (i = oldbands; i < q->bands; i++) {
+               q->queues[i] = queues[i];
+-- 
+2.39.5
+
diff --git a/queue-6.12/net_sched-red-fix-a-race-in-__red_change.patch b/queue-6.12/net_sched-red-fix-a-race-in-__red_change.patch
new file mode 100644 (file)
index 0000000..9f2a775
--- /dev/null
@@ -0,0 +1,58 @@
+From 724af82f2d3ceaae6ae7851f7580799218df29f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jun 2025 11:15:12 +0000
+Subject: net_sched: red: fix a race in __red_change()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 85a3e0ede38450ea3053b8c45d28cf55208409b8 ]
+
+Gerrard Tai reported a race condition in RED, whenever SFQ perturb timer
+fires at the wrong time.
+
+The race is as follows:
+
+CPU 0                                 CPU 1
+[1]: lock root
+[2]: qdisc_tree_flush_backlog()
+[3]: unlock root
+ |
+ |                                    [5]: lock root
+ |                                    [6]: rehash
+ |                                    [7]: qdisc_tree_reduce_backlog()
+ |
+[4]: qdisc_put()
+
+This can be abused to underflow a parent's qlen.
+
+Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog()
+should fix the race, because all packets will be purged from the qdisc
+before releasing the lock.
+
+Fixes: 0c8d13ac9607 ("net: sched: red: delay destroying child qdisc on replace")
+Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Suggested-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20250611111515.1983366-3-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_red.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
+index b5f096588fae6..0f0701ed397e9 100644
+--- a/net/sched/sch_red.c
++++ b/net/sched/sch_red.c
+@@ -283,7 +283,7 @@ static int __red_change(struct Qdisc *sch, struct nlattr **tb,
+       q->userbits = userbits;
+       q->limit = ctl->limit;
+       if (child) {
+-              qdisc_tree_flush_backlog(q->qdisc);
++              qdisc_purge_queue(q->qdisc);
+               old_child = q->qdisc;
+               q->qdisc = child;
+       }
+-- 
+2.39.5
+
diff --git a/queue-6.12/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch b/queue-6.12/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch
new file mode 100644 (file)
index 0000000..2592519
--- /dev/null
@@ -0,0 +1,70 @@
+From 2271baebd5bd9fe4ff1a756aaba1eb68e43ba7fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jun 2025 16:51:27 +0000
+Subject: net_sched: sch_sfq: fix a potential crash on gso_skb handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 82ffbe7776d0ac084031f114167712269bf3d832 ]
+
+SFQ has an assumption of always being able to queue at least one packet.
+
+However, after the blamed commit, sch->q.len can be inflated by packets
+in sch->gso_skb, and an enqueue() on an empty SFQ qdisc can be followed
+by an immediate drop.
+
+Fix sfq_drop() to properly clear q->tail in this situation.
+
+Tested:
+
+ip netns add lb
+ip link add dev to-lb type veth peer name in-lb netns lb
+ethtool -K to-lb tso off                 # force qdisc to requeue gso_skb
+ip netns exec lb ethtool -K in-lb gro on # enable NAPI
+ip link set dev to-lb up
+ip -netns lb link set dev in-lb up
+ip addr add dev to-lb 192.168.20.1/24
+ip -netns lb addr add dev in-lb 192.168.20.2/24
+tc qdisc replace dev to-lb root sfq limit 100
+
+ip netns exec lb netserver
+
+netperf -H 192.168.20.2 -l 100 &
+netperf -H 192.168.20.2 -l 100 &
+netperf -H 192.168.20.2 -l 100 &
+netperf -H 192.168.20.2 -l 100 &
+
+Fixes: a53851e2c321 ("net: sched: explicit locking in gso_cpu fallback")
+Reported-by: Marcus Wichelmann <marcus.wichelmann@hetzner-cloud.de>
+Closes: https://lore.kernel.org/netdev/9da42688-bfaa-4364-8797-e9271f3bdaef@hetzner-cloud.de/
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Link: https://patch.msgid.link/20250606165127.3629486-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_sfq.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
+index 58b42dcf8f201..a903b3c468050 100644
+--- a/net/sched/sch_sfq.c
++++ b/net/sched/sch_sfq.c
+@@ -310,7 +310,10 @@ static unsigned int sfq_drop(struct Qdisc *sch, struct sk_buff **to_free)
+               /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
+               x = q->tail->next;
+               slot = &q->slots[x];
+-              q->tail->next = slot->next;
++              if (slot->next == x)
++                      q->tail = NULL; /* no more active slots */
++              else
++                      q->tail->next = slot->next;
+               q->ht[slot->hash] = SFQ_EMPTY_SLOT;
+               goto drop;
+       }
+-- 
+2.39.5
+
diff --git a/queue-6.12/net_sched-tbf-fix-a-race-in-tbf_change.patch b/queue-6.12/net_sched-tbf-fix-a-race-in-tbf_change.patch
new file mode 100644 (file)
index 0000000..146eab6
--- /dev/null
@@ -0,0 +1,59 @@
+From 702cb171ba10fcb28011508dbaaf0b49407dedd6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Jun 2025 11:15:13 +0000
+Subject: net_sched: tbf: fix a race in tbf_change()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 43eb466041216d25dedaef1c383ad7bd89929cbc ]
+
+Gerrard Tai reported a race condition in TBF, whenever SFQ perturb timer
+fires at the wrong time.
+
+The race is as follows:
+
+CPU 0                                 CPU 1
+[1]: lock root
+[2]: qdisc_tree_flush_backlog()
+[3]: unlock root
+ |
+ |                                    [5]: lock root
+ |                                    [6]: rehash
+ |                                    [7]: qdisc_tree_reduce_backlog()
+ |
+[4]: qdisc_put()
+
+This can be abused to underflow a parent's qlen.
+
+Calling qdisc_purge_queue() instead of qdisc_tree_flush_backlog()
+should fix the race, because all packets will be purged from the qdisc
+before releasing the lock.
+
+Fixes: b05972f01e7d ("net: sched: tbf: don't call qdisc_put() while holding tree lock")
+Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Suggested-by: Gerrard Tai <gerrard.tai@starlabs.sg>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Zhengchao Shao <shaozhengchao@huawei.com>
+Link: https://patch.msgid.link/20250611111515.1983366-4-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_tbf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
+index dc26b22d53c73..4c977f049670a 100644
+--- a/net/sched/sch_tbf.c
++++ b/net/sched/sch_tbf.c
+@@ -452,7 +452,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
+       sch_tree_lock(sch);
+       if (child) {
+-              qdisc_tree_flush_backlog(q->qdisc);
++              qdisc_purge_queue(q->qdisc);
+               old = q->qdisc;
+               q->qdisc = child;
+       }
+-- 
+2.39.5
+
diff --git a/queue-6.12/pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch b/queue-6.12/pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch
new file mode 100644 (file)
index 0000000..5a68683
--- /dev/null
@@ -0,0 +1,57 @@
+From ba495d5f91e9fe5ee4af644c716a86bac4be77f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 May 2025 12:14:37 +0200
+Subject: pinctrl: qcom: pinctrl-qcm2290: Add missing pins
+
+From: Wojciech Slenska <wojciech.slenska@gmail.com>
+
+[ Upstream commit 315345610faee8a0568b522dba9e35067d1732ab ]
+
+Added the missing pins to the qcm2290_pins table.
+
+Signed-off-by: Wojciech Slenska <wojciech.slenska@gmail.com>
+Fixes: 48e049ef1238 ("pinctrl: qcom: Add QCM2290 pinctrl driver")
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://lore.kernel.org/20250523101437.59092-1-wojciech.slenska@gmail.com
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/qcom/pinctrl-qcm2290.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
+index f5c1c427b44e9..61b7c22e963c2 100644
+--- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c
++++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
+@@ -165,6 +165,10 @@ static const struct pinctrl_pin_desc qcm2290_pins[] = {
+       PINCTRL_PIN(62, "GPIO_62"),
+       PINCTRL_PIN(63, "GPIO_63"),
+       PINCTRL_PIN(64, "GPIO_64"),
++      PINCTRL_PIN(65, "GPIO_65"),
++      PINCTRL_PIN(66, "GPIO_66"),
++      PINCTRL_PIN(67, "GPIO_67"),
++      PINCTRL_PIN(68, "GPIO_68"),
+       PINCTRL_PIN(69, "GPIO_69"),
+       PINCTRL_PIN(70, "GPIO_70"),
+       PINCTRL_PIN(71, "GPIO_71"),
+@@ -179,12 +183,17 @@ static const struct pinctrl_pin_desc qcm2290_pins[] = {
+       PINCTRL_PIN(80, "GPIO_80"),
+       PINCTRL_PIN(81, "GPIO_81"),
+       PINCTRL_PIN(82, "GPIO_82"),
++      PINCTRL_PIN(83, "GPIO_83"),
++      PINCTRL_PIN(84, "GPIO_84"),
++      PINCTRL_PIN(85, "GPIO_85"),
+       PINCTRL_PIN(86, "GPIO_86"),
+       PINCTRL_PIN(87, "GPIO_87"),
+       PINCTRL_PIN(88, "GPIO_88"),
+       PINCTRL_PIN(89, "GPIO_89"),
+       PINCTRL_PIN(90, "GPIO_90"),
+       PINCTRL_PIN(91, "GPIO_91"),
++      PINCTRL_PIN(92, "GPIO_92"),
++      PINCTRL_PIN(93, "GPIO_93"),
+       PINCTRL_PIN(94, "GPIO_94"),
+       PINCTRL_PIN(95, "GPIO_95"),
+       PINCTRL_PIN(96, "GPIO_96"),
+-- 
+2.39.5
+
diff --git a/queue-6.12/powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch b/queue-6.12/powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch
new file mode 100644 (file)
index 0000000..025fe77
--- /dev/null
@@ -0,0 +1,48 @@
+From 2710bea75160a50ddb601a9a7cb889c60eb81930 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 07:42:26 +0530
+Subject: powerpc/powernv/memtrace: Fix out of bounds issue in memtrace mmap
+
+From: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+
+[ Upstream commit cd097df4596f3a1e9d75eb8520162de1eb8485b2 ]
+
+memtrace mmap issue has an out of bounds issue. This patch fixes the by
+checking that the requested mapping region size should stay within the
+allocated region size.
+
+Reported-by: Jonathan Greental <yonatan02greental@gmail.com>
+Fixes: 08a022ad3dfa ("powerpc/powernv/memtrace: Allow mmaping trace buffers")
+Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250610021227.361980-1-maddy@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/powernv/memtrace.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c
+index 877720c645151..35471b679638a 100644
+--- a/arch/powerpc/platforms/powernv/memtrace.c
++++ b/arch/powerpc/platforms/powernv/memtrace.c
+@@ -48,11 +48,15 @@ static ssize_t memtrace_read(struct file *filp, char __user *ubuf,
+ static int memtrace_mmap(struct file *filp, struct vm_area_struct *vma)
+ {
+       struct memtrace_entry *ent = filp->private_data;
++      unsigned long ent_nrpages = ent->size >> PAGE_SHIFT;
++      unsigned long vma_nrpages = vma_pages(vma);
+-      if (ent->size < vma->vm_end - vma->vm_start)
++      /* The requested page offset should be within object's page count */
++      if (vma->vm_pgoff >= ent_nrpages)
+               return -EINVAL;
+-      if (vma->vm_pgoff << PAGE_SHIFT >= ent->size)
++      /* The requested mapping range should remain within the bounds */
++      if (vma_nrpages > ent_nrpages - vma->vm_pgoff)
+               return -EINVAL;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+-- 
+2.39.5
+
diff --git a/queue-6.12/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch b/queue-6.12/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch
new file mode 100644 (file)
index 0000000..c2dbaa1
--- /dev/null
@@ -0,0 +1,52 @@
+From 608207ae32f6a9e8808e361ea9983208595f7a1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jun 2025 07:42:27 +0530
+Subject: powerpc/vas: Return -EINVAL if the offset is non-zero in mmap()
+
+From: Haren Myneni <haren@linux.ibm.com>
+
+[ Upstream commit 0d67f0dee6c9176bc09a5482dd7346e3a0f14d0b ]
+
+The user space calls mmap() to map VAS window paste address
+and the kernel returns the complete mapped page for each
+window. So return -EINVAL if non-zero is passed for offset
+parameter to mmap().
+
+See Documentation/arch/powerpc/vas-api.rst for mmap()
+restrictions.
+
+Co-developed-by: Jonathan Greental <yonatan02greental@gmail.com>
+Signed-off-by: Jonathan Greental <yonatan02greental@gmail.com>
+Reported-by: Jonathan Greental <yonatan02greental@gmail.com>
+Fixes: dda44eb29c23 ("powerpc/vas: Add VAS user space API")
+Signed-off-by: Haren Myneni <haren@linux.ibm.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20250610021227.361980-2-maddy@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/book3s/vas-api.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
+index 0b6365d85d117..dc6f75d3ac6ef 100644
+--- a/arch/powerpc/platforms/book3s/vas-api.c
++++ b/arch/powerpc/platforms/book3s/vas-api.c
+@@ -521,6 +521,15 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
+               return -EINVAL;
+       }
++      /*
++       * Map complete page to the paste address. So the user
++       * space should pass 0ULL to the offset parameter.
++       */
++      if (vma->vm_pgoff) {
++              pr_debug("Page offset unsupported to map paste address\n");
++              return -EINVAL;
++      }
++
+       /* Ensure instance has an open send window */
+       if (!txwin) {
+               pr_err("No send window open?\n");
+-- 
+2.39.5
+
diff --git a/queue-6.12/ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch b/queue-6.12/ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch
new file mode 100644 (file)
index 0000000..9467092
--- /dev/null
@@ -0,0 +1,90 @@
+From 79ef324154b62ca2d99bde049d197c20a69dc99d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 May 2025 01:07:17 +0900
+Subject: ptp: remove ptp->n_vclocks check logic in ptp_vclock_in_use()
+
+From: Jeongjun Park <aha310510@gmail.com>
+
+[ Upstream commit 87f7ce260a3c838b49e1dc1ceedf1006795157a2 ]
+
+There is no disagreement that we should check both ptp->is_virtual_clock
+and ptp->n_vclocks to check if the ptp virtual clock is in use.
+
+However, when we acquire ptp->n_vclocks_mux to read ptp->n_vclocks in
+ptp_vclock_in_use(), we observe a recursive lock in the call trace
+starting from n_vclocks_store().
+
+============================================
+WARNING: possible recursive locking detected
+6.15.0-rc6 #1 Not tainted
+--------------------------------------------
+syz.0.1540/13807 is trying to acquire lock:
+ffff888035a24868 (&ptp->n_vclocks_mux){+.+.}-{4:4}, at:
+ ptp_vclock_in_use drivers/ptp/ptp_private.h:103 [inline]
+ffff888035a24868 (&ptp->n_vclocks_mux){+.+.}-{4:4}, at:
+ ptp_clock_unregister+0x21/0x250 drivers/ptp/ptp_clock.c:415
+
+but task is already holding lock:
+ffff888030704868 (&ptp->n_vclocks_mux){+.+.}-{4:4}, at:
+ n_vclocks_store+0xf1/0x6d0 drivers/ptp/ptp_sysfs.c:215
+
+other info that might help us debug this:
+ Possible unsafe locking scenario:
+
+       CPU0
+       ----
+  lock(&ptp->n_vclocks_mux);
+  lock(&ptp->n_vclocks_mux);
+
+ *** DEADLOCK ***
+....
+============================================
+
+The best way to solve this is to remove the logic that checks
+ptp->n_vclocks in ptp_vclock_in_use().
+
+The reason why this is appropriate is that any path that uses
+ptp->n_vclocks must unconditionally check if ptp->n_vclocks is greater
+than 0 before unregistering vclocks, and all functions are already
+written this way. And in the function that uses ptp->n_vclocks, we
+already get ptp->n_vclocks_mux before unregistering vclocks.
+
+Therefore, we need to remove the redundant check for ptp->n_vclocks in
+ptp_vclock_in_use() to prevent recursive locking.
+
+Fixes: 73f37068d540 ("ptp: support ptp physical/virtual clocks conversion")
+Signed-off-by: Jeongjun Park <aha310510@gmail.com>
+Acked-by: Richard Cochran <richardcochran@gmail.com>
+Link: https://patch.msgid.link/20250520160717.7350-1-aha310510@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ptp/ptp_private.h | 12 +-----------
+ 1 file changed, 1 insertion(+), 11 deletions(-)
+
+diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h
+index 18934e28469ee..528d86a33f37d 100644
+--- a/drivers/ptp/ptp_private.h
++++ b/drivers/ptp/ptp_private.h
+@@ -98,17 +98,7 @@ static inline int queue_cnt(const struct timestamp_event_queue *q)
+ /* Check if ptp virtual clock is in use */
+ static inline bool ptp_vclock_in_use(struct ptp_clock *ptp)
+ {
+-      bool in_use = false;
+-
+-      if (mutex_lock_interruptible(&ptp->n_vclocks_mux))
+-              return true;
+-
+-      if (!ptp->is_virtual_clock && ptp->n_vclocks)
+-              in_use = true;
+-
+-      mutex_unlock(&ptp->n_vclocks_mux);
+-
+-      return in_use;
++      return !ptp->is_virtual_clock;
+ }
+ /* Check if ptp clock shall be free running */
+-- 
+2.39.5
+
diff --git a/queue-6.12/regulator-max20086-fix-refcount-leak-in-max20086_par.patch b/queue-6.12/regulator-max20086-fix-refcount-leak-in-max20086_par.patch
new file mode 100644 (file)
index 0000000..341e71f
--- /dev/null
@@ -0,0 +1,61 @@
+From b2aab4d76d0daf9bd7b4b024b333432c96a25a75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 May 2025 08:44:14 +0300
+Subject: regulator: max20086: Fix refcount leak in
+ max20086_parse_regulators_dt()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 06118ae36855b7d3d22688298e74a766ccf0cb7a ]
+
+There is a missing call to of_node_put() if devm_kcalloc() fails.
+Fix this by changing the code to use cleanup.h magic to drop the
+refcount.
+
+Fixes: 6b0cd72757c6 ("regulator: max20086: fix invalid memory access")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Link: https://patch.msgid.link/aDVRLqgJWMxYU03G@stanley.mountain
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/max20086-regulator.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c
+index 198d45f8e8849..3d333b61fb18c 100644
+--- a/drivers/regulator/max20086-regulator.c
++++ b/drivers/regulator/max20086-regulator.c
+@@ -5,6 +5,7 @@
+ // Copyright (C) 2022 Laurent Pinchart <laurent.pinchart@idesonboard.com>
+ // Copyright (C) 2018 Avnet, Inc.
++#include <linux/cleanup.h>
+ #include <linux/err.h>
+ #include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+@@ -133,11 +134,11 @@ static int max20086_regulators_register(struct max20086 *chip)
+ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on)
+ {
+       struct of_regulator_match *matches;
+-      struct device_node *node;
+       unsigned int i;
+       int ret;
+-      node = of_get_child_by_name(chip->dev->of_node, "regulators");
++      struct device_node *node __free(device_node) =
++              of_get_child_by_name(chip->dev->of_node, "regulators");
+       if (!node) {
+               dev_err(chip->dev, "regulators node not found\n");
+               return -ENODEV;
+@@ -153,7 +154,6 @@ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on)
+       ret = of_regulator_match(chip->dev, node, matches,
+                                chip->info->num_outputs);
+-      of_node_put(node);
+       if (ret < 0) {
+               dev_err(chip->dev, "Failed to match regulators\n");
+               return -EINVAL;
+-- 
+2.39.5
+
diff --git a/queue-6.12/scsi-core-ufs-fix-a-hang-in-the-error-handler.patch b/queue-6.12/scsi-core-ufs-fix-a-hang-in-the-error-handler.patch
new file mode 100644 (file)
index 0000000..744c0b8
--- /dev/null
@@ -0,0 +1,73 @@
+From 21f8162b2c756483d6326f63c70e466e591277e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 May 2025 13:14:01 -0700
+Subject: scsi: core: ufs: Fix a hang in the error handler
+
+From: Sanjeev Yadav <sanjeev.y@mediatek.com>
+
+[ Upstream commit 8a3514d348de87a9d5e2ac00fbac4faae0b97996 ]
+
+ufshcd_err_handling_prepare() calls ufshcd_rpm_get_sync(). The latter
+function can only succeed if UFSHCD_EH_IN_PROGRESS is not set because
+resuming involves submitting a SCSI command and ufshcd_queuecommand()
+returns SCSI_MLQUEUE_HOST_BUSY if UFSHCD_EH_IN_PROGRESS is set. Fix this
+hang by setting UFSHCD_EH_IN_PROGRESS after ufshcd_rpm_get_sync() has
+been called instead of before.
+
+Backtrace:
+__switch_to+0x174/0x338
+__schedule+0x600/0x9e4
+schedule+0x7c/0xe8
+schedule_timeout+0xa4/0x1c8
+io_schedule_timeout+0x48/0x70
+wait_for_common_io+0xa8/0x160 //waiting on START_STOP
+wait_for_completion_io_timeout+0x10/0x20
+blk_execute_rq+0xe4/0x1e4
+scsi_execute_cmd+0x108/0x244
+ufshcd_set_dev_pwr_mode+0xe8/0x250
+__ufshcd_wl_resume+0x94/0x354
+ufshcd_wl_runtime_resume+0x3c/0x174
+scsi_runtime_resume+0x64/0xa4
+rpm_resume+0x15c/0xa1c
+__pm_runtime_resume+0x4c/0x90 // Runtime resume ongoing
+ufshcd_err_handler+0x1a0/0xd08
+process_one_work+0x174/0x808
+worker_thread+0x15c/0x490
+kthread+0xf4/0x1ec
+ret_from_fork+0x10/0x20
+
+Signed-off-by: Sanjeev Yadav <sanjeev.y@mediatek.com>
+[ bvanassche: rewrote patch description ]
+Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver")
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20250523201409.1676055-1-bvanassche@acm.org
+Reviewed-by: Peter Wang <peter.wang@mediatek.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ufs/core/ufshcd.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index 247e425428c88..374f505fec3d1 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -6577,9 +6577,14 @@ static void ufshcd_err_handler(struct work_struct *work)
+               up(&hba->host_sem);
+               return;
+       }
+-      ufshcd_set_eh_in_progress(hba);
+       spin_unlock_irqrestore(hba->host->host_lock, flags);
++
+       ufshcd_err_handling_prepare(hba);
++
++      spin_lock_irqsave(hba->host->host_lock, flags);
++      ufshcd_set_eh_in_progress(hba);
++      spin_unlock_irqrestore(hba->host->host_lock, flags);
++
+       /* Complete requests that have door-bell cleared by h/w */
+       ufshcd_complete_requests(hba, false);
+       spin_lock_irqsave(hba->host->host_lock, flags);
+-- 
+2.39.5
+
diff --git a/queue-6.12/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch b/queue-6.12/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch
new file mode 100644 (file)
index 0000000..9709ec5
--- /dev/null
@@ -0,0 +1,99 @@
+From 2debae57e024b9ecba19e9b7a4d71523b9c4c6b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 May 2025 12:29:35 -0700
+Subject: scsi: iscsi: Fix incorrect error path labels for flashnode operations
+
+From: Alok Tiwari <alok.a.tiwari@oracle.com>
+
+[ Upstream commit 9b17621366d210ffee83262a8754086ebbde5e55 ]
+
+Correct the error handling goto labels used when host lookup fails in
+various flashnode-related event handlers:
+
+ - iscsi_new_flashnode()
+ - iscsi_del_flashnode()
+ - iscsi_login_flashnode()
+ - iscsi_logout_flashnode()
+ - iscsi_logout_flashnode_sid()
+
+scsi_host_put() is not required when shost is NULL, so jumping to the
+correct label avoids unnecessary operations. These functions previously
+jumped to the wrong goto label (put_host), which did not match the
+intended cleanup logic.
+
+Use the correct exit labels (exit_new_fnode, exit_del_fnode, etc.) to
+ensure proper error handling.  Also remove the unused put_host label
+under iscsi_new_flashnode() as it is no longer needed.
+
+No functional changes beyond accurate error path correction.
+
+Fixes: c6a4bb2ef596 ("[SCSI] scsi_transport_iscsi: Add flash node mgmt support")
+Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
+Link: https://lore.kernel.org/r/20250530193012.3312911-1-alok.a.tiwari@oracle.com
+Reviewed-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 8274fe0ec7146..7a5bebf5b096c 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -3526,7 +3526,7 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport,
+               pr_err("%s could not find host no %u\n",
+                      __func__, ev->u.new_flashnode.host_no);
+               err = -ENODEV;
+-              goto put_host;
++              goto exit_new_fnode;
+       }
+       index = transport->new_flashnode(shost, data, len);
+@@ -3536,7 +3536,6 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport,
+       else
+               err = -EIO;
+-put_host:
+       scsi_host_put(shost);
+ exit_new_fnode:
+@@ -3561,7 +3560,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport,
+               pr_err("%s could not find host no %u\n",
+                      __func__, ev->u.del_flashnode.host_no);
+               err = -ENODEV;
+-              goto put_host;
++              goto exit_del_fnode;
+       }
+       idx = ev->u.del_flashnode.flashnode_idx;
+@@ -3603,7 +3602,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport,
+               pr_err("%s could not find host no %u\n",
+                      __func__, ev->u.login_flashnode.host_no);
+               err = -ENODEV;
+-              goto put_host;
++              goto exit_login_fnode;
+       }
+       idx = ev->u.login_flashnode.flashnode_idx;
+@@ -3655,7 +3654,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport,
+               pr_err("%s could not find host no %u\n",
+                      __func__, ev->u.logout_flashnode.host_no);
+               err = -ENODEV;
+-              goto put_host;
++              goto exit_logout_fnode;
+       }
+       idx = ev->u.logout_flashnode.flashnode_idx;
+@@ -3705,7 +3704,7 @@ static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
+               pr_err("%s could not find host no %u\n",
+                      __func__, ev->u.logout_flashnode.host_no);
+               err = -ENODEV;
+-              goto put_host;
++              goto exit_logout_sid;
+       }
+       session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid);
+-- 
+2.39.5
+
index 37b9c59a45cfa1e863d87966f9024c8ef604cdac..0e07e466d77b35da79aa2170b76d2a802d80264b 100644 (file)
@@ -420,3 +420,55 @@ dt-bindings-pwm-adi-axi-pwmgen-fix-clocks.patch
 serial-sh-sci-move-runtime-pm-enable-to-sci_probe_si.patch
 serial-sh-sci-clean-sci_ports-0-after-at-earlycon-ex.patch
 serial-sh-sci-increment-the-runtime-usage-counter-fo.patch
+scsi-core-ufs-fix-a-hang-in-the-error-handler.patch
+bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch
+bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch
+bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch
+bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch
+bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch
+bluetooth-mgmt-remove-unused-mgmt_pending_find_data.patch
+bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch
+net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch
+ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch
+ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch
+wifi-ath11k-convert-timeouts-to-secs_to_jiffies.patch
+wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch
+wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch
+wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch
+wifi-ath11k-move-some-firmware-stats-related-functio.patch
+wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch
+wifi-ath12k-refactor-ath12k_hw_regs-structure.patch
+wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch
+regulator-max20086-fix-refcount-leak-in-max20086_par.patch
+spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch
+spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch
+pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch
+scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch
+net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch
+powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch
+powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch
+drm-meson-use-unsigned-long-long-hz-for-frequency-ty.patch
+drm-meson-fix-debug-log-statement-when-setting-the-h.patch
+drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch
+drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch
+i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch
+i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch
+acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch
+net-fix-toctou-issue-in-sk_is_readable.patch
+macsec-macsec-sci-assignment-for-es-0.patch
+net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch
+net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch
+bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch
+bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch
+bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch
+bluetooth-mgmt-fix-sparse-errors.patch
+net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch
+net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch
+net-mlx5-fix-return-value-when-searching-for-existin.patch
+net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch
+net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch
+net_sched-prio-fix-a-race-in-prio_tune.patch
+net_sched-red-fix-a-race-in-__red_change.patch
+net_sched-tbf-fix-a-race-in-tbf_change.patch
+net_sched-ets-fix-a-race-in-ets_qdisc_change.patch
+net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch
diff --git a/queue-6.12/spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch b/queue-6.12/spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch
new file mode 100644 (file)
index 0000000..32c8572
--- /dev/null
@@ -0,0 +1,55 @@
+From 162b557ef24b8a78dfb43fb64e8881b29dfa15b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jun 2025 15:37:24 +0200
+Subject: spi: omap2-mcspi: Disable multi mode when CS should be kept asserted
+ after message
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Félix Piédallu <felix.piedallu@non.se.com>
+
+[ Upstream commit a5bf5272295d3f058adeee025d2a0b6625f8ba7b ]
+
+When the last transfer of a SPI message has the cs_change flag, the CS is kept
+asserted after the message.
+Multi-mode can't respect this as CS is deasserted by the hardware at the end of
+the message.
+
+Disable multi-mode when not applicable to the current message.
+
+Fixes: d153ff4056cb ("spi: omap2-mcspi: Add support for MULTI-mode")
+Signed-off-by: Félix Piédallu <felix.piedallu@non.se.com>
+Link: https://patch.msgid.link/20250606-cs_change_fix-v1-1-27191a98a2e5@non.se.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-omap2-mcspi.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
+index 532b2e9c31d0d..05766b98de36f 100644
+--- a/drivers/spi/spi-omap2-mcspi.c
++++ b/drivers/spi/spi-omap2-mcspi.c
+@@ -1287,9 +1287,15 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
+                       mcspi->use_multi_mode = false;
+               }
+-              /* Check if transfer asks to change the CS status after the transfer */
+-              if (!tr->cs_change)
+-                      mcspi->use_multi_mode = false;
++              if (list_is_last(&tr->transfer_list, &msg->transfers)) {
++                      /* Check if transfer asks to keep the CS status after the whole message */
++                      if (tr->cs_change)
++                              mcspi->use_multi_mode = false;
++              } else {
++                      /* Check if transfer asks to change the CS status after the transfer */
++                      if (!tr->cs_change)
++                              mcspi->use_multi_mode = false;
++              }
+               /*
+                * If at least one message is not compatible, switch back to single mode
+-- 
+2.39.5
+
diff --git a/queue-6.12/spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch b/queue-6.12/spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch
new file mode 100644 (file)
index 0000000..9af6287
--- /dev/null
@@ -0,0 +1,84 @@
+From 5b5eaf2e420cc12934bde76c08819baff19483f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jun 2025 15:37:25 +0200
+Subject: spi: omap2-mcspi: Disable multi-mode when the previous message kept
+ CS asserted
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Félix Piédallu <felix.piedallu@non.se.com>
+
+[ Upstream commit 10c24e0d2f7cd2bc8a847cf750f01301ce67dbc8 ]
+
+When the last transfer of a SPI message has the cs_change flag, the CS is kept
+asserted after the message.
+The next message can't use multi-mode because the CS will be briefly deasserted
+before the first transfer.
+
+Remove the early exit of the list_for_each_entry because the last transfer
+actually needs to be always checked.
+
+Fixes: d153ff4056cb ("spi: omap2-mcspi: Add support for MULTI-mode")
+Signed-off-by: Félix Piédallu <felix.piedallu@non.se.com>
+Link: https://patch.msgid.link/20250606-cs_change_fix-v1-2-27191a98a2e5@non.se.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-omap2-mcspi.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
+index 05766b98de36f..4c5f12b76de6a 100644
+--- a/drivers/spi/spi-omap2-mcspi.c
++++ b/drivers/spi/spi-omap2-mcspi.c
+@@ -134,6 +134,7 @@ struct omap2_mcspi {
+       size_t                  max_xfer_len;
+       u32                     ref_clk_hz;
+       bool                    use_multi_mode;
++      bool                    last_msg_kept_cs;
+ };
+ struct omap2_mcspi_cs {
+@@ -1269,6 +1270,10 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
+        * multi-mode is applicable.
+        */
+       mcspi->use_multi_mode = true;
++
++      if (mcspi->last_msg_kept_cs)
++              mcspi->use_multi_mode = false;
++
+       list_for_each_entry(tr, &msg->transfers, transfer_list) {
+               if (!tr->bits_per_word)
+                       bits_per_word = msg->spi->bits_per_word;
+@@ -1289,22 +1294,17 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr,
+               if (list_is_last(&tr->transfer_list, &msg->transfers)) {
+                       /* Check if transfer asks to keep the CS status after the whole message */
+-                      if (tr->cs_change)
++                      if (tr->cs_change) {
+                               mcspi->use_multi_mode = false;
++                              mcspi->last_msg_kept_cs = true;
++                      } else {
++                              mcspi->last_msg_kept_cs = false;
++                      }
+               } else {
+                       /* Check if transfer asks to change the CS status after the transfer */
+                       if (!tr->cs_change)
+                               mcspi->use_multi_mode = false;
+               }
+-
+-              /*
+-               * If at least one message is not compatible, switch back to single mode
+-               *
+-               * The bits_per_word of certain transfer can be different, but it will have no
+-               * impact on the signal itself.
+-               */
+-              if (!mcspi->use_multi_mode)
+-                      break;
+       }
+       omap2_mcspi_set_mode(ctlr);
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch b/queue-6.12/wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch
new file mode 100644 (file)
index 0000000..4beb766
--- /dev/null
@@ -0,0 +1,231 @@
+From a95e759747127e81e04f83c915ff7d7ada16f0fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 16:24:42 +0800
+Subject: wifi: ath11k: avoid burning CPU in ath11k_debugfs_fw_stats_request()
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 9f6e82d11bb9692a90d20b10f87345598945c803 ]
+
+We get report [1] that CPU is running a hot loop in
+ath11k_debugfs_fw_stats_request():
+
+94.60%     0.00%  i3status         [kernel.kallsyms]                 [k] do_syscall_64
+        |
+         --94.60%--do_syscall_64
+                   |
+                    --94.55%--__sys_sendmsg
+                              ___sys_sendmsg
+                              ____sys_sendmsg
+                              netlink_sendmsg
+                              netlink_unicast
+                              genl_rcv
+                              netlink_rcv_skb
+                              genl_rcv_msg
+                              |
+                               --94.55%--genl_family_rcv_msg_dumpit
+                                         __netlink_dump_start
+                                         netlink_dump
+                                         genl_dumpit
+                                         nl80211_dump_station
+                                         |
+                                          --94.55%--ieee80211_dump_station
+                                                    sta_set_sinfo
+                                                    |
+                                                     --94.55%--ath11k_mac_op_sta_statistics
+                                                               ath11k_debugfs_get_fw_stats
+                                                               |
+                                                                --94.55%--ath11k_debugfs_fw_stats_request
+                                                                          |
+                                                                          |--41.73%--_raw_spin_lock_bh
+                                                                          |
+                                                                          |--22.74%--__local_bh_enable_ip
+                                                                          |
+                                                                          |--9.22%--_raw_spin_unlock_bh
+                                                                          |
+                                                                           --6.66%--srso_alias_safe_ret
+
+This is because, if for whatever reason ar->fw_stats_done is not set by
+ath11k_update_stats_event(), ath11k_debugfs_fw_stats_request() won't yield
+CPU before an up to 3s timeout.
+
+Change to completion mechanism to avoid CPU burning.
+
+Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37
+
+Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
+Reported-by: Yury Vostrikov <mon@unformed.ru>
+Closes: https://lore.kernel.org/all/7324ac7a-8b7a-42a5-aa19-de52138ff638@app.fastmail.com/ # [1]
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250220082448.31039-2-quic_bqiang@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/core.c    |  1 +
+ drivers/net/wireless/ath/ath11k/core.h    |  2 +-
+ drivers/net/wireless/ath/ath11k/debugfs.c | 38 +++++++++--------------
+ drivers/net/wireless/ath/ath11k/mac.c     |  2 +-
+ drivers/net/wireless/ath/ath11k/wmi.c     |  2 +-
+ 5 files changed, 18 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
+index 674c4763333f3..d08f40f77031a 100644
+--- a/drivers/net/wireless/ath/ath11k/core.c
++++ b/drivers/net/wireless/ath/ath11k/core.c
+@@ -855,6 +855,7 @@ void ath11k_fw_stats_init(struct ath11k *ar)
+       INIT_LIST_HEAD(&ar->fw_stats.bcn);
+       init_completion(&ar->fw_stats_complete);
++      init_completion(&ar->fw_stats_done);
+ }
+ void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)
+diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
+index 09c37e19a1680..bbf2ccfee3fc0 100644
+--- a/drivers/net/wireless/ath/ath11k/core.h
++++ b/drivers/net/wireless/ath/ath11k/core.h
+@@ -780,7 +780,7 @@ struct ath11k {
+       u8 alpha2[REG_ALPHA2_LEN + 1];
+       struct ath11k_fw_stats fw_stats;
+       struct completion fw_stats_complete;
+-      bool fw_stats_done;
++      struct completion fw_stats_done;
+       /* protected by conf_mutex */
+       bool ps_state_enable;
+diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
+index bf192529e3fe2..1d03e3aab011d 100644
+--- a/drivers/net/wireless/ath/ath11k/debugfs.c
++++ b/drivers/net/wireless/ath/ath11k/debugfs.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #include <linux/vmalloc.h>
+@@ -96,7 +96,6 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
+ static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
+ {
+       spin_lock_bh(&ar->data_lock);
+-      ar->fw_stats_done = false;
+       ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
+       ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
+       spin_unlock_bh(&ar->data_lock);
+@@ -114,7 +113,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+       /* WMI_REQUEST_PDEV_STAT request has been already processed */
+       if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
+-              ar->fw_stats_done = true;
++              complete(&ar->fw_stats_done);
+               return;
+       }
+@@ -138,7 +137,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+                                     &ar->fw_stats.vdevs);
+               if (is_end) {
+-                      ar->fw_stats_done = true;
++                      complete(&ar->fw_stats_done);
+                       num_vdev = 0;
+               }
+               return;
+@@ -158,7 +157,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+                                     &ar->fw_stats.bcn);
+               if (is_end) {
+-                      ar->fw_stats_done = true;
++                      complete(&ar->fw_stats_done);
+                       num_bcn = 0;
+               }
+       }
+@@ -168,21 +167,15 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
+                                          struct stats_request_params *req_param)
+ {
+       struct ath11k_base *ab = ar->ab;
+-      unsigned long timeout, time_left;
++      unsigned long time_left;
+       int ret;
+       lockdep_assert_held(&ar->conf_mutex);
+-      /* FW stats can get split when exceeding the stats data buffer limit.
+-       * In that case, since there is no end marking for the back-to-back
+-       * received 'update stats' event, we keep a 3 seconds timeout in case,
+-       * fw_stats_done is not marked yet
+-       */
+-      timeout = jiffies + secs_to_jiffies(3);
+-
+       ath11k_debugfs_fw_stats_reset(ar);
+       reinit_completion(&ar->fw_stats_complete);
++      reinit_completion(&ar->fw_stats_done);
+       ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
+@@ -193,21 +186,18 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
+       }
+       time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
+-
+       if (!time_left)
+               return -ETIMEDOUT;
+-      for (;;) {
+-              if (time_after(jiffies, timeout))
+-                      break;
++      /* FW stats can get split when exceeding the stats data buffer limit.
++       * In that case, since there is no end marking for the back-to-back
++       * received 'update stats' event, we keep a 3 seconds timeout in case,
++       * fw_stats_done is not marked yet
++       */
++      time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
++      if (!time_left)
++              return -ETIMEDOUT;
+-              spin_lock_bh(&ar->data_lock);
+-              if (ar->fw_stats_done) {
+-                      spin_unlock_bh(&ar->data_lock);
+-                      break;
+-              }
+-              spin_unlock_bh(&ar->data_lock);
+-      }
+       return 0;
+ }
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index f8068d2e848c3..78c825244613b 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -9331,11 +9331,11 @@ static int ath11k_fw_stats_request(struct ath11k *ar,
+       lockdep_assert_held(&ar->conf_mutex);
+       spin_lock_bh(&ar->data_lock);
+-      ar->fw_stats_done = false;
+       ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
+       spin_unlock_bh(&ar->data_lock);
+       reinit_completion(&ar->fw_stats_complete);
++      reinit_completion(&ar->fw_stats_done);
+       ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
+       if (ret) {
+diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
+index 87abfa5475295..e2203f668d7cf 100644
+--- a/drivers/net/wireless/ath/ath11k/wmi.c
++++ b/drivers/net/wireless/ath/ath11k/wmi.c
+@@ -8188,7 +8188,7 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
+        */
+       if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
+               list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs);
+-              ar->fw_stats_done = true;
++              complete(&ar->fw_stats_done);
+               goto complete;
+       }
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath11k-convert-timeouts-to-secs_to_jiffies.patch b/queue-6.12/wifi-ath11k-convert-timeouts-to-secs_to_jiffies.patch
new file mode 100644 (file)
index 0000000..0b346e1
--- /dev/null
@@ -0,0 +1,120 @@
+From 23b70a2a10508c5f38ae070702b7ffbb79d2e646 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Dec 2024 22:02:45 +0000
+Subject: wifi: ath11k: convert timeouts to secs_to_jiffies()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Easwar Hariharan <eahariha@linux.microsoft.com>
+
+[ Upstream commit b29425972c5234a59b6fb634125420ed74266377 ]
+
+Commit b35108a51cf7 ("jiffies: Define secs_to_jiffies()") introduced
+secs_to_jiffies().  As the value here is a multiple of 1000, use
+secs_to_jiffies() instead of msecs_to_jiffies to avoid the multiplication.
+
+This is converted using scripts/coccinelle/misc/secs_to_jiffies.cocci with
+the following Coccinelle rules:
+
+@@ constant C; @@
+
+- msecs_to_jiffies(C * 1000)
++ secs_to_jiffies(C)
+
+@@ constant C; @@
+
+- msecs_to_jiffies(C * MSEC_PER_SEC)
++ secs_to_jiffies(C)
+
+Link: https://lkml.kernel.org/r/20241210-converge-secs-to-jiffies-v3-14-ddfefd7e9f2a@linux.microsoft.com
+Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Easwar Hariharan <eahariha@linux.microsoft.com>
+Cc: Alexander Gordeev <agordeev@linux.ibm.com>
+Cc: Andrew Lunn <andrew+netdev@lunn.ch>
+Cc: Anna-Maria Behnsen <anna-maria@linutronix.de>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Daniel Mack <daniel@zonque.org>
+Cc: David Airlie <airlied@gmail.com>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Dick Kennedy <dick.kennedy@broadcom.com>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Florian Fainelli <florian.fainelli@broadcom.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
+Cc: Heiko Carstens <hca@linux.ibm.com>
+Cc: Ilya Dryomov <idryomov@gmail.com>
+Cc: Jack Wang <jinpu.wang@cloud.ionos.com>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: James Smart <james.smart@broadcom.com>
+Cc: Jaroslav Kysela <perex@perex.cz>
+Cc: Jeff Johnson <jjohnson@kernel.org>
+Cc: Jens Axboe <axboe@kernel.dk>
+Cc: Jeroen de Borst <jeroendb@google.com>
+Cc: Jiri Kosina <jikos@kernel.org>
+Cc: Joe Lawrence <joe.lawrence@redhat.com>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Josh Poimboeuf <jpoimboe@kernel.org>
+Cc: Jozsef Kadlecsik <kadlec@netfilter.org>
+Cc: Julia Lawall <julia.lawall@inria.fr>
+Cc: Kalle Valo <kvalo@kernel.org>
+Cc: Louis Peens <louis.peens@corigine.com>
+Cc: Lucas De Marchi <lucas.demarchi@intel.com>
+Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Martin K. Petersen <martin.petersen@oracle.com>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Miroslav Benes <mbenes@suse.cz>
+Cc: Naveen N Rao <naveen@kernel.org>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Nicolas Palix <nicolas.palix@imag.fr>
+Cc: Oded Gabbay <ogabbay@kernel.org>
+Cc: Ofir Bitton <obitton@habana.ai>
+Cc: Pablo Neira Ayuso <pablo@netfilter.org>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Cc: Petr Mladek <pmladek@suse.com>
+Cc: Praveen Kaligineedi <pkaligineedi@google.com>
+Cc: Ray Jui <rjui@broadcom.com>
+Cc: Robert Jarzmik <robert.jarzmik@free.fr>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Cc: Roger Pau Monné <roger.pau@citrix.com>
+Cc: Russell King <linux@armlinux.org.uk>
+Cc: Scott Branden <sbranden@broadcom.com>
+Cc: Shailend Chand <shailend@google.com>
+Cc: Simona Vetter <simona@ffwll.ch>
+Cc: Simon Horman <horms@kernel.org>
+Cc: Sven Schnelle <svens@linux.ibm.com>
+Cc: Takashi Iwai <tiwai@suse.com>
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: Vasily Gorbik <gor@linux.ibm.com>
+Cc: Xiubo Li <xiubli@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 9f6e82d11bb9 ("wifi: ath11k: avoid burning CPU in ath11k_debugfs_fw_stats_request()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/debugfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
+index 57281a135dd7f..bf192529e3fe2 100644
+--- a/drivers/net/wireless/ath/ath11k/debugfs.c
++++ b/drivers/net/wireless/ath/ath11k/debugfs.c
+@@ -178,7 +178,7 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
+        * received 'update stats' event, we keep a 3 seconds timeout in case,
+        * fw_stats_done is not marked yet
+        */
+-      timeout = jiffies + msecs_to_jiffies(3 * 1000);
++      timeout = jiffies + secs_to_jiffies(3);
+       ath11k_debugfs_fw_stats_reset(ar);
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch b/queue-6.12/wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch
new file mode 100644 (file)
index 0000000..7789310
--- /dev/null
@@ -0,0 +1,129 @@
+From a2af06199b104ea5bec1be74fcdfe338195915b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 16:24:43 +0800
+Subject: wifi: ath11k: don't use static variables in
+ ath11k_debugfs_fw_stats_process()
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 2bcf73b2612dda7432f2c2eaad6679bd291791f2 ]
+
+Currently ath11k_debugfs_fw_stats_process() is using static variables to count
+firmware stat events. Taking num_vdev as an example, if for whatever reason (
+say ar->num_started_vdevs is 0 or firmware bug etc.) the following condition
+
+       (++num_vdev) == total_vdevs_started
+
+is not met, is_end is not set thus num_vdev won't be cleared. Next time when
+firmware stats is requested again, even if everything is working fine, we will
+fail due to the condition above will never be satisfied.
+
+The same applies to num_bcn as well.
+
+Change to use non-static counters so that we have a chance to clear them each
+time firmware stats is requested. Currently only ath11k_fw_stats_request() and
+ath11k_debugfs_fw_stats_request() are requesting firmware stats, so clear
+counters there.
+
+Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37
+
+Fixes: da3a9d3c1576 ("ath11k: refactor debugfs code into debugfs.c")
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Acked-by: Kalle Valo <kvalo@kernel.org>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250220082448.31039-3-quic_bqiang@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/core.h    |  2 ++
+ drivers/net/wireless/ath/ath11k/debugfs.c | 16 +++++++---------
+ drivers/net/wireless/ath/ath11k/mac.c     |  2 ++
+ 3 files changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
+index bbf2ccfee3fc0..fcdec14eb3cfa 100644
+--- a/drivers/net/wireless/ath/ath11k/core.h
++++ b/drivers/net/wireless/ath/ath11k/core.h
+@@ -599,6 +599,8 @@ struct ath11k_fw_stats {
+       struct list_head pdevs;
+       struct list_head vdevs;
+       struct list_head bcn;
++      u32 num_vdev_recvd;
++      u32 num_bcn_recvd;
+ };
+ struct ath11k_dbg_htt_stats {
+diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
+index 1d03e3aab011d..27c93c0b4c223 100644
+--- a/drivers/net/wireless/ath/ath11k/debugfs.c
++++ b/drivers/net/wireless/ath/ath11k/debugfs.c
+@@ -98,6 +98,8 @@ static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
+       spin_lock_bh(&ar->data_lock);
+       ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
+       ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
++      ar->fw_stats.num_vdev_recvd = 0;
++      ar->fw_stats.num_bcn_recvd = 0;
+       spin_unlock_bh(&ar->data_lock);
+ }
+@@ -106,7 +108,6 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+       struct ath11k_base *ab = ar->ab;
+       struct ath11k_pdev *pdev;
+       bool is_end;
+-      static unsigned int num_vdev, num_bcn;
+       size_t total_vdevs_started = 0;
+       int i;
+@@ -131,15 +132,14 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+                               total_vdevs_started += ar->num_started_vdevs;
+               }
+-              is_end = ((++num_vdev) == total_vdevs_started);
++              is_end = ((++ar->fw_stats.num_vdev_recvd) == total_vdevs_started);
+               list_splice_tail_init(&stats->vdevs,
+                                     &ar->fw_stats.vdevs);
+-              if (is_end) {
++              if (is_end)
+                       complete(&ar->fw_stats_done);
+-                      num_vdev = 0;
+-              }
++
+               return;
+       }
+@@ -151,15 +151,13 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+               /* Mark end until we reached the count of all started VDEVs
+                * within the PDEV
+                */
+-              is_end = ((++num_bcn) == ar->num_started_vdevs);
++              is_end = ((++ar->fw_stats.num_bcn_recvd) == ar->num_started_vdevs);
+               list_splice_tail_init(&stats->bcn,
+                                     &ar->fw_stats.bcn);
+-              if (is_end) {
++              if (is_end)
+                       complete(&ar->fw_stats_done);
+-                      num_bcn = 0;
+-              }
+       }
+ }
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index 78c825244613b..9159ee20a33b8 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -9332,6 +9332,8 @@ static int ath11k_fw_stats_request(struct ath11k *ar,
+       spin_lock_bh(&ar->data_lock);
+       ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
++      ar->fw_stats.num_vdev_recvd = 0;
++      ar->fw_stats.num_bcn_recvd = 0;
+       spin_unlock_bh(&ar->data_lock);
+       reinit_completion(&ar->fw_stats_complete);
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch b/queue-6.12/wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch
new file mode 100644 (file)
index 0000000..d0aa5cd
--- /dev/null
@@ -0,0 +1,76 @@
+From d77c8da5603db4a2a9c75f5bef467112f7cc06cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 16:24:44 +0800
+Subject: wifi: ath11k: don't wait when there is no vdev started
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 3b6d00fa883075dcaf49221538230e038a9c0b43 ]
+
+For WMI_REQUEST_VDEV_STAT request, firmware might split response into
+multiple events dut to buffer limit, hence currently in
+ath11k_debugfs_fw_stats_process() we wait until all events received.
+In case there is no vdev started, this results in that below condition
+would never get satisfied
+
+       ((++ar->fw_stats.num_vdev_recvd) == total_vdevs_started)
+
+finally the requestor would be blocked until wait time out.
+
+The same applies to WMI_REQUEST_BCN_STAT request as well due to:
+
+       ((++ar->fw_stats.num_bcn_recvd) == ar->num_started_vdevs)
+
+Change to check the number of started vdev first: if it is zero, finish
+wait directly; if not, follow the old way.
+
+Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37
+
+Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250220082448.31039-4-quic_bqiang@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/debugfs.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
+index 27c93c0b4c223..ccf0e62c7d7ae 100644
+--- a/drivers/net/wireless/ath/ath11k/debugfs.c
++++ b/drivers/net/wireless/ath/ath11k/debugfs.c
+@@ -107,7 +107,7 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+ {
+       struct ath11k_base *ab = ar->ab;
+       struct ath11k_pdev *pdev;
+-      bool is_end;
++      bool is_end = true;
+       size_t total_vdevs_started = 0;
+       int i;
+@@ -132,7 +132,9 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+                               total_vdevs_started += ar->num_started_vdevs;
+               }
+-              is_end = ((++ar->fw_stats.num_vdev_recvd) == total_vdevs_started);
++              if (total_vdevs_started)
++                      is_end = ((++ar->fw_stats.num_vdev_recvd) ==
++                                total_vdevs_started);
+               list_splice_tail_init(&stats->vdevs,
+                                     &ar->fw_stats.vdevs);
+@@ -151,7 +153,9 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+               /* Mark end until we reached the count of all started VDEVs
+                * within the PDEV
+                */
+-              is_end = ((++ar->fw_stats.num_bcn_recvd) == ar->num_started_vdevs);
++              if (ar->num_started_vdevs)
++                      is_end = ((++ar->fw_stats.num_bcn_recvd) ==
++                                ar->num_started_vdevs);
+               list_splice_tail_init(&stats->bcn,
+                                     &ar->fw_stats.bcn);
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath11k-move-some-firmware-stats-related-functio.patch b/queue-6.12/wifi-ath11k-move-some-firmware-stats-related-functio.patch
new file mode 100644 (file)
index 0000000..1348903
--- /dev/null
@@ -0,0 +1,448 @@
+From aebcf687d1c8dbaed3f5f094ad30553ec176d5a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Feb 2025 16:24:45 +0800
+Subject: wifi: ath11k: move some firmware stats related functions outside of
+ debugfs
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 72610ed7d79da17ee09102534d6c696a4ea8a08e ]
+
+Commit b488c766442f ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855")
+and commit c3b39553fc77 ("ath11k: add signal report to mac80211 for QCA6390 and WCN6855")
+call debugfs functions in mac ops. Those functions are no-ops if CONFIG_ATH11K_DEBUGFS is
+not enabled, thus cause wrong status reported.
+
+Move them to mac.c.
+
+Besides, since WMI_REQUEST_RSSI_PER_CHAIN_STAT and WMI_REQUEST_VDEV_STAT stats could also
+be requested via mac ops, process them directly in ath11k_update_stats_event().
+
+Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37
+
+Fixes: b488c766442f ("ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855")
+Fixes: c3b39553fc77 ("ath11k: add signal report to mac80211 for QCA6390 and WCN6855")
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250220082448.31039-5-quic_bqiang@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/debugfs.c | 126 ++--------------------
+ drivers/net/wireless/ath/ath11k/debugfs.h |  10 +-
+ drivers/net/wireless/ath/ath11k/mac.c     |  88 ++++++++++++++-
+ drivers/net/wireless/ath/ath11k/mac.h     |   4 +-
+ drivers/net/wireless/ath/ath11k/wmi.c     |  45 +++++++-
+ 5 files changed, 135 insertions(+), 138 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
+index ccf0e62c7d7ae..5d46f8e4c231f 100644
+--- a/drivers/net/wireless/ath/ath11k/debugfs.c
++++ b/drivers/net/wireless/ath/ath11k/debugfs.c
+@@ -93,58 +93,14 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
+       spin_unlock_bh(&dbr_data->lock);
+ }
+-static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
+-{
+-      spin_lock_bh(&ar->data_lock);
+-      ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
+-      ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
+-      ar->fw_stats.num_vdev_recvd = 0;
+-      ar->fw_stats.num_bcn_recvd = 0;
+-      spin_unlock_bh(&ar->data_lock);
+-}
+-
+ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats)
+ {
+       struct ath11k_base *ab = ar->ab;
+-      struct ath11k_pdev *pdev;
+       bool is_end = true;
+-      size_t total_vdevs_started = 0;
+-      int i;
+-
+-      /* WMI_REQUEST_PDEV_STAT request has been already processed */
+-
+-      if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
+-              complete(&ar->fw_stats_done);
+-              return;
+-      }
+-
+-      if (stats->stats_id == WMI_REQUEST_VDEV_STAT) {
+-              if (list_empty(&stats->vdevs)) {
+-                      ath11k_warn(ab, "empty vdev stats");
+-                      return;
+-              }
+-              /* FW sends all the active VDEV stats irrespective of PDEV,
+-               * hence limit until the count of all VDEVs started
+-               */
+-              for (i = 0; i < ab->num_radios; i++) {
+-                      pdev = rcu_dereference(ab->pdevs_active[i]);
+-                      if (pdev && pdev->ar)
+-                              total_vdevs_started += ar->num_started_vdevs;
+-              }
+-
+-              if (total_vdevs_started)
+-                      is_end = ((++ar->fw_stats.num_vdev_recvd) ==
+-                                total_vdevs_started);
+-
+-              list_splice_tail_init(&stats->vdevs,
+-                                    &ar->fw_stats.vdevs);
+-
+-              if (is_end)
+-                      complete(&ar->fw_stats_done);
+-
+-              return;
+-      }
++      /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_RSSI_PER_CHAIN_STAT and
++       * WMI_REQUEST_VDEV_STAT requests have been already processed.
++       */
+       if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
+               if (list_empty(&stats->bcn)) {
+                       ath11k_warn(ab, "empty bcn stats");
+@@ -165,76 +121,6 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *
+       }
+ }
+-static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
+-                                         struct stats_request_params *req_param)
+-{
+-      struct ath11k_base *ab = ar->ab;
+-      unsigned long time_left;
+-      int ret;
+-
+-      lockdep_assert_held(&ar->conf_mutex);
+-
+-      ath11k_debugfs_fw_stats_reset(ar);
+-
+-      reinit_completion(&ar->fw_stats_complete);
+-      reinit_completion(&ar->fw_stats_done);
+-
+-      ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
+-
+-      if (ret) {
+-              ath11k_warn(ab, "could not request fw stats (%d)\n",
+-                          ret);
+-              return ret;
+-      }
+-
+-      time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
+-      if (!time_left)
+-              return -ETIMEDOUT;
+-
+-      /* FW stats can get split when exceeding the stats data buffer limit.
+-       * In that case, since there is no end marking for the back-to-back
+-       * received 'update stats' event, we keep a 3 seconds timeout in case,
+-       * fw_stats_done is not marked yet
+-       */
+-      time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
+-      if (!time_left)
+-              return -ETIMEDOUT;
+-
+-      return 0;
+-}
+-
+-int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
+-                              u32 vdev_id, u32 stats_id)
+-{
+-      struct ath11k_base *ab = ar->ab;
+-      struct stats_request_params req_param;
+-      int ret;
+-
+-      mutex_lock(&ar->conf_mutex);
+-
+-      if (ar->state != ATH11K_STATE_ON) {
+-              ret = -ENETDOWN;
+-              goto err_unlock;
+-      }
+-
+-      req_param.pdev_id = pdev_id;
+-      req_param.vdev_id = vdev_id;
+-      req_param.stats_id = stats_id;
+-
+-      ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
+-      if (ret)
+-              ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
+-
+-      ath11k_dbg(ab, ATH11K_DBG_WMI,
+-                 "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
+-                 pdev_id, vdev_id, stats_id);
+-
+-err_unlock:
+-      mutex_unlock(&ar->conf_mutex);
+-
+-      return ret;
+-}
+-
+ static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
+ {
+       struct ath11k *ar = inode->i_private;
+@@ -260,7 +146,7 @@ static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
+       req_param.vdev_id = 0;
+       req_param.stats_id = WMI_REQUEST_PDEV_STAT;
+-      ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
++      ret = ath11k_mac_fw_stats_request(ar, &req_param);
+       if (ret) {
+               ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
+               goto err_free;
+@@ -331,7 +217,7 @@ static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
+       req_param.vdev_id = 0;
+       req_param.stats_id = WMI_REQUEST_VDEV_STAT;
+-      ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
++      ret = ath11k_mac_fw_stats_request(ar, &req_param);
+       if (ret) {
+               ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
+               goto err_free;
+@@ -407,7 +293,7 @@ static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
+                       continue;
+               req_param.vdev_id = arvif->vdev_id;
+-              ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
++              ret = ath11k_mac_fw_stats_request(ar, &req_param);
+               if (ret) {
+                       ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
+                       goto err_free;
+diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h
+index a39e458637b01..ed7fec177588f 100644
+--- a/drivers/net/wireless/ath/ath11k/debugfs.h
++++ b/drivers/net/wireless/ath/ath11k/debugfs.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
+ /*
+  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2022, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #ifndef _ATH11K_DEBUGFS_H_
+@@ -273,8 +273,6 @@ void ath11k_debugfs_unregister(struct ath11k *ar);
+ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats);
+ void ath11k_debugfs_fw_stats_init(struct ath11k *ar);
+-int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
+-                              u32 vdev_id, u32 stats_id);
+ static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar)
+ {
+@@ -381,12 +379,6 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
+       return 0;
+ }
+-static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar,
+-                                            u32 pdev_id, u32 vdev_id, u32 stats_id)
+-{
+-      return 0;
+-}
+-
+ static inline void
+ ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
+                               enum wmi_direct_buffer_module id,
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index 9159ee20a33b8..7ead581f5bfd1 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -8938,6 +8938,86 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
+       }
+ }
++static void ath11k_mac_fw_stats_reset(struct ath11k *ar)
++{
++      spin_lock_bh(&ar->data_lock);
++      ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs);
++      ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs);
++      ar->fw_stats.num_vdev_recvd = 0;
++      ar->fw_stats.num_bcn_recvd = 0;
++      spin_unlock_bh(&ar->data_lock);
++}
++
++int ath11k_mac_fw_stats_request(struct ath11k *ar,
++                              struct stats_request_params *req_param)
++{
++      struct ath11k_base *ab = ar->ab;
++      unsigned long time_left;
++      int ret;
++
++      lockdep_assert_held(&ar->conf_mutex);
++
++      ath11k_mac_fw_stats_reset(ar);
++
++      reinit_completion(&ar->fw_stats_complete);
++      reinit_completion(&ar->fw_stats_done);
++
++      ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
++
++      if (ret) {
++              ath11k_warn(ab, "could not request fw stats (%d)\n",
++                          ret);
++              return ret;
++      }
++
++      time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ);
++      if (!time_left)
++              return -ETIMEDOUT;
++
++      /* FW stats can get split when exceeding the stats data buffer limit.
++       * In that case, since there is no end marking for the back-to-back
++       * received 'update stats' event, we keep a 3 seconds timeout in case,
++       * fw_stats_done is not marked yet
++       */
++      time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ);
++      if (!time_left)
++              return -ETIMEDOUT;
++
++      return 0;
++}
++
++static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id,
++                                 u32 vdev_id, u32 stats_id)
++{
++      struct ath11k_base *ab = ar->ab;
++      struct stats_request_params req_param;
++      int ret;
++
++      mutex_lock(&ar->conf_mutex);
++
++      if (ar->state != ATH11K_STATE_ON) {
++              ret = -ENETDOWN;
++              goto err_unlock;
++      }
++
++      req_param.pdev_id = pdev_id;
++      req_param.vdev_id = vdev_id;
++      req_param.stats_id = stats_id;
++
++      ret = ath11k_mac_fw_stats_request(ar, &req_param);
++      if (ret)
++              ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
++
++      ath11k_dbg(ab, ATH11K_DBG_WMI,
++                 "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
++                 pdev_id, vdev_id, stats_id);
++
++err_unlock:
++      mutex_unlock(&ar->conf_mutex);
++
++      return ret;
++}
++
+ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
+                                        struct ieee80211_vif *vif,
+                                        struct ieee80211_sta *sta,
+@@ -8975,8 +9055,8 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
+       if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) &&
+           arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+           ar->ab->hw_params.supports_rssi_stats &&
+-          !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
+-                                       WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
++          !ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0,
++                                   WMI_REQUEST_RSSI_PER_CHAIN_STAT)) {
+               ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true);
+       }
+@@ -8984,8 +9064,8 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
+       if (!signal &&
+           arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+           ar->ab->hw_params.supports_rssi_stats &&
+-          !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0,
+-                                      WMI_REQUEST_VDEV_STAT)))
++          !(ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0,
++                                    WMI_REQUEST_VDEV_STAT)))
+               signal = arsta->rssi_beacon;
+       ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
+diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
+index f5800fbecff89..5e61eea1bb037 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.h
++++ b/drivers/net/wireless/ath/ath11k/mac.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
+ /*
+  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #ifndef ATH11K_MAC_H
+@@ -179,4 +179,6 @@ int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,
+ void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar,
+                                 struct ieee80211_vif *vif,
+                                 struct ieee80211_chanctx_conf *ctx);
++int ath11k_mac_fw_stats_request(struct ath11k *ar,
++                              struct stats_request_params *req_param);
+ #endif
+diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
+index e2203f668d7cf..5f7edf622de7a 100644
+--- a/drivers/net/wireless/ath/ath11k/wmi.c
++++ b/drivers/net/wireless/ath/ath11k/wmi.c
+@@ -8157,6 +8157,11 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff
+ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb)
+ {
+       struct ath11k_fw_stats stats = {};
++      size_t total_vdevs_started = 0;
++      struct ath11k_pdev *pdev;
++      bool is_end = true;
++      int i;
++
+       struct ath11k *ar;
+       int ret;
+@@ -8183,7 +8188,8 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
+       spin_lock_bh(&ar->data_lock);
+-      /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via
++      /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_VDEV_STAT and
++       * WMI_REQUEST_RSSI_PER_CHAIN_STAT can be requested via mac ops or via
+        * debugfs fw stats. Therefore, processing it separately.
+        */
+       if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
+@@ -8192,9 +8198,40 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk
+               goto complete;
+       }
+-      /* WMI_REQUEST_VDEV_STAT, WMI_REQUEST_BCN_STAT and WMI_REQUEST_RSSI_PER_CHAIN_STAT
+-       * are currently requested only via debugfs fw stats. Hence, processing these
+-       * in debugfs context
++      if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
++              complete(&ar->fw_stats_done);
++              goto complete;
++      }
++
++      if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
++              if (list_empty(&stats.vdevs)) {
++                      ath11k_warn(ab, "empty vdev stats");
++                      goto complete;
++              }
++              /* FW sends all the active VDEV stats irrespective of PDEV,
++               * hence limit until the count of all VDEVs started
++               */
++              for (i = 0; i < ab->num_radios; i++) {
++                      pdev = rcu_dereference(ab->pdevs_active[i]);
++                      if (pdev && pdev->ar)
++                              total_vdevs_started += ar->num_started_vdevs;
++              }
++
++              if (total_vdevs_started)
++                      is_end = ((++ar->fw_stats.num_vdev_recvd) ==
++                                total_vdevs_started);
++
++              list_splice_tail_init(&stats.vdevs,
++                                    &ar->fw_stats.vdevs);
++
++              if (is_end)
++                      complete(&ar->fw_stats_done);
++
++              goto complete;
++      }
++
++      /* WMI_REQUEST_BCN_STAT is currently requested only via debugfs fw stats.
++       * Hence, processing it in debugfs context
+        */
+       ath11k_debugfs_fw_stats_process(ar, &stats);
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch b/queue-6.12/wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch
new file mode 100644 (file)
index 0000000..ebd51ad
--- /dev/null
@@ -0,0 +1,80 @@
+From 30adc51ebaf5cfa6151b492c252096aa4c8335de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 May 2025 17:01:12 -0300
+Subject: wifi: ath11k: validate ath11k_crypto_mode on top of
+ ath11k_core_qmi_firmware_ready
+
+From: Rodrigo Gobbi <rodrigo.gobbi.7@gmail.com>
+
+[ Upstream commit b0d226a60856a1b765bb9a3848c7b2322fd08c47 ]
+
+if ath11k_crypto_mode is invalid (not ATH11K_CRYPT_MODE_SW/ATH11K_CRYPT_MODE_HW),
+ath11k_core_qmi_firmware_ready() will not undo some actions that was previously
+started/configured. Do the validation as soon as possible in order to avoid
+undoing actions in that case and also to fix the following smatch warning:
+
+drivers/net/wireless/ath/ath11k/core.c:2166 ath11k_core_qmi_firmware_ready()
+warn: missing unwind goto?
+
+Signed-off-by: Rodrigo Gobbi <rodrigo.gobbi.7@gmail.com>
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <error27@gmail.com>
+Closes: https://lore.kernel.org/r/202304151955.oqAetVFd-lkp@intel.com/
+Fixes: aa2092a9bab3 ("ath11k: add raw mode and software crypto support")
+Reviewed-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Link: https://patch.msgid.link/20250522200519.16858-1-rodrigo.gobbi.7@gmail.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/core.c | 28 +++++++++++++-------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
+index d08f40f77031a..8002fb32a2cc1 100644
+--- a/drivers/net/wireless/ath/ath11k/core.c
++++ b/drivers/net/wireless/ath/ath11k/core.c
+@@ -1812,6 +1812,20 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
+ {
+       int ret;
++      switch (ath11k_crypto_mode) {
++      case ATH11K_CRYPT_MODE_SW:
++              set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
++              set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
++              break;
++      case ATH11K_CRYPT_MODE_HW:
++              clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
++              clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
++              break;
++      default:
++              ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
++              return -EINVAL;
++      }
++
+       ret = ath11k_core_start_firmware(ab, ab->fw_mode);
+       if (ret) {
+               ath11k_err(ab, "failed to start firmware: %d\n", ret);
+@@ -1830,20 +1844,6 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
+               goto err_firmware_stop;
+       }
+-      switch (ath11k_crypto_mode) {
+-      case ATH11K_CRYPT_MODE_SW:
+-              set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
+-              set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
+-              break;
+-      case ATH11K_CRYPT_MODE_HW:
+-              clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
+-              clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
+-              break;
+-      default:
+-              ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
+-              return -EINVAL;
+-      }
+-
+       if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)
+               set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch b/queue-6.12/wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch
new file mode 100644 (file)
index 0000000..19edb66
--- /dev/null
@@ -0,0 +1,116 @@
+From 3311c9a1775ed53dc3649d99cfd06cd433734aed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 May 2025 10:23:05 +0800
+Subject: wifi: ath12k: fix GCC_GCC_PCIE_HOT_RST definition for WCN7850
+
+From: Baochen Qiang <quic_bqiang@quicinc.com>
+
+[ Upstream commit 7588a893cde5385ad308400ff167d29a29913b3a ]
+
+GCC_GCC_PCIE_HOT_RST is wrongly defined for WCN7850, causing kernel crash
+on some specific platforms.
+
+Since this register is divergent for WCN7850 and QCN9274, move it to
+register table to allow different definitions. Then correct the register
+address for WCN7850 to fix this issue.
+
+Note IPQ5332 is not affected as it is not PCIe based device.
+
+Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
+
+Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Reported-by: Parth Pancholi <parth.pancholi@toradex.com>
+Closes: https://lore.kernel.org/all/86899b2235a59c9134603beebe08f2bb0b244ea0.camel@gmail.com
+Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
+Tested-by: Parth Pancholi <parth.pancholi@toradex.com>
+Link: https://patch.msgid.link/20250523-ath12k-wrong-global-reset-addr-v1-1-3b06eb556196@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/hw.c  | 6 ++++++
+ drivers/net/wireless/ath/ath12k/hw.h  | 2 ++
+ drivers/net/wireless/ath/ath12k/pci.c | 6 +++---
+ drivers/net/wireless/ath/ath12k/pci.h | 4 +++-
+ 4 files changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
+index 5bffc428f19f5..e3eb22bb9e1cb 100644
+--- a/drivers/net/wireless/ath/ath12k/hw.c
++++ b/drivers/net/wireless/ath/ath12k/hw.c
+@@ -686,6 +686,8 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = {
+       .hal_umac_ce0_dest_reg_base = 0x01b81000,
+       .hal_umac_ce1_src_reg_base = 0x01b82000,
+       .hal_umac_ce1_dest_reg_base = 0x01b83000,
++
++      .gcc_gcc_pcie_hot_rst = 0x1e38338,
+ };
+ static const struct ath12k_hw_regs qcn9274_v2_regs = {
+@@ -775,6 +777,8 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = {
+       .hal_umac_ce0_dest_reg_base = 0x01b81000,
+       .hal_umac_ce1_src_reg_base = 0x01b82000,
+       .hal_umac_ce1_dest_reg_base = 0x01b83000,
++
++      .gcc_gcc_pcie_hot_rst = 0x1e38338,
+ };
+ static const struct ath12k_hw_regs wcn7850_regs = {
+@@ -860,6 +864,8 @@ static const struct ath12k_hw_regs wcn7850_regs = {
+       .hal_umac_ce0_dest_reg_base = 0x01b81000,
+       .hal_umac_ce1_src_reg_base = 0x01b82000,
+       .hal_umac_ce1_dest_reg_base = 0x01b83000,
++
++      .gcc_gcc_pcie_hot_rst = 0x1e40304,
+ };
+ static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = {
+diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
+index acb81b5798ac1..862b11325a902 100644
+--- a/drivers/net/wireless/ath/ath12k/hw.h
++++ b/drivers/net/wireless/ath/ath12k/hw.h
+@@ -355,6 +355,8 @@ struct ath12k_hw_regs {
+       u32 hal_reo_cmd_ring_base;
+       u32 hal_reo_status_ring_base;
++
++      u32 gcc_gcc_pcie_hot_rst;
+ };
+ static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type)
+diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
+index 1068cc07bc9f6..26f4b440c26d2 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.c
++++ b/drivers/net/wireless/ath/ath12k/pci.c
+@@ -290,10 +290,10 @@ static void ath12k_pci_enable_ltssm(struct ath12k_base *ab)
+       ath12k_dbg(ab, ATH12K_DBG_PCI, "pci ltssm 0x%x\n", val);
+-      val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
++      val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab));
+       val |= GCC_GCC_PCIE_HOT_RST_VAL;
+-      ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val);
+-      val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST);
++      ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST(ab), val);
++      val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab));
+       ath12k_dbg(ab, ATH12K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val);
+diff --git a/drivers/net/wireless/ath/ath12k/pci.h b/drivers/net/wireless/ath/ath12k/pci.h
+index 31584a7ad80eb..9321674eef8b8 100644
+--- a/drivers/net/wireless/ath/ath12k/pci.h
++++ b/drivers/net/wireless/ath/ath12k/pci.h
+@@ -28,7 +28,9 @@
+ #define PCIE_PCIE_PARF_LTSSM                  0x1e081b0
+ #define PARM_LTSSM_VALUE                      0x111
+-#define GCC_GCC_PCIE_HOT_RST                  0x1e38338
++#define GCC_GCC_PCIE_HOT_RST(ab) \
++      ((ab)->hw_params->regs->gcc_gcc_pcie_hot_rst)
++
+ #define GCC_GCC_PCIE_HOT_RST_VAL              0x10
+ #define PCIE_PCIE_INT_ALL_CLEAR                       0x1e08228
+-- 
+2.39.5
+
diff --git a/queue-6.12/wifi-ath12k-refactor-ath12k_hw_regs-structure.patch b/queue-6.12/wifi-ath12k-refactor-ath12k_hw_regs-structure.patch
new file mode 100644 (file)
index 0000000..7813ad6
--- /dev/null
@@ -0,0 +1,405 @@
+From e6abd42eee38d95bc48fc4d2ee6cb8d1e327d71c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Mar 2025 16:22:40 +0530
+Subject: wifi: ath12k: refactor ath12k_hw_regs structure
+
+From: P Praneesh <quic_ppranees@quicinc.com>
+
+[ Upstream commit 5257324583e32fd5bd6bbb6c82b4f5880b842f99 ]
+
+IPQ5332 device have different register address values for the below
+registers:
+
+HAL_TCL1_RING_BASE_LSB
+HAL_TCL1_RING_BASE_MSB
+HAL_TCL2_RING_BASE_LSB
+
+HAL_SEQ_WCSS_UMAC_CE0_SRC_REG
+HAL_SEQ_WCSS_UMAC_CE0_DST_REG
+HAL_SEQ_WCSS_UMAC_CE1_SRC_REG
+HAL_SEQ_WCSS_UMAC_CE1_DST_REG
+
+Hence, refactor ath12k_hw_regs structure to accommodate these changes
+in IPQ5332.
+
+Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.3.1-00130-QCAHKSWPL_SILICONZ-1
+Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00210-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
+Co-developed-by: Balamurugan S <quic_bselvara@quicinc.com>
+Signed-off-by: Balamurugan S <quic_bselvara@quicinc.com>
+Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
+Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
+Link: https://patch.msgid.link/20250321-ath12k-ahb-v12-3-bb389ed76ae5@quicinc.com
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Stable-dep-of: 7588a893cde5 ("wifi: ath12k: fix GCC_GCC_PCIE_HOT_RST definition for WCN7850")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath12k/hal.c | 84 +++++++++++++--------------
+ drivers/net/wireless/ath/ath12k/hal.h | 63 +++++++++++---------
+ drivers/net/wireless/ath/ath12k/hw.c  | 29 ++++++++-
+ drivers/net/wireless/ath/ath12k/hw.h  | 10 +++-
+ 4 files changed, 114 insertions(+), 72 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
+index 2e3fce70386f8..bfa404997710e 100644
+--- a/drivers/net/wireless/ath/ath12k/hal.c
++++ b/drivers/net/wireless/ath/ath12k/hal.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #include <linux/dma-mapping.h>
+ #include "hal_tx.h"
+@@ -547,9 +547,9 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP;
+       s = &hal->srng_config[HAL_TCL_DATA];
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB;
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
+-      s->reg_size[0] = HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB;
++      s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
+       s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
+       s = &hal->srng_config[HAL_TCL_CMD];
+@@ -561,29 +561,29 @@ static int ath12k_hal_srng_create_config_qcn9274(struct ath12k_base *ab)
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
+       s = &hal->srng_config[HAL_CE_SRC];
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_BASE_LSB;
+-      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP;
+-      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
+-      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
++      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
++      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
++      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
+       s = &hal->srng_config[HAL_CE_DST];
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_BASE_LSB;
+-      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP;
+-      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
+-      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
++      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
++      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
++      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
+       s = &hal->srng_config[HAL_CE_DST_STATUS];
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
+               HAL_CE_DST_STATUS_RING_BASE_LSB;
+-      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_STATUS_RING_HP;
+-      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
+-      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
++      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
++      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
++      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
+       s = &hal->srng_config[HAL_WBM_IDLE_LINK];
+       s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab);
+@@ -1353,9 +1353,9 @@ static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab)
+       s = &hal->srng_config[HAL_TCL_DATA];
+       s->max_rings = 5;
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB;
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
+-      s->reg_size[0] = HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB;
++      s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
+       s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
+       s = &hal->srng_config[HAL_TCL_CMD];
+@@ -1368,31 +1368,31 @@ static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_base *ab)
+       s = &hal->srng_config[HAL_CE_SRC];
+       s->max_rings = 12;
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_BASE_LSB;
+-      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG + HAL_CE_DST_RING_HP;
+-      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
+-      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG;
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
++      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
++      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
++      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
+       s = &hal->srng_config[HAL_CE_DST];
+       s->max_rings = 12;
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_BASE_LSB;
+-      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_RING_HP;
+-      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
+-      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
++      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
++      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
++      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
+       s = &hal->srng_config[HAL_CE_DST_STATUS];
+       s->max_rings = 12;
+-      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG +
++      s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
+               HAL_CE_DST_STATUS_RING_BASE_LSB;
+-      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG + HAL_CE_DST_STATUS_RING_HP;
+-      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
+-      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG -
+-              HAL_SEQ_WCSS_UMAC_CE0_DST_REG;
++      s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
++      s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
++      s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
++              HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
+       s = &hal->srng_config[HAL_WBM_IDLE_LINK];
+       s->reg_start[0] = HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_BASE_LSB(ab);
+@@ -1737,7 +1737,7 @@ static void ath12k_hal_srng_src_hw_init(struct ath12k_base *ab,
+                             HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB) |
+             u32_encode_bits((srng->entry_size * srng->num_entries),
+                             HAL_TCL1_RING_BASE_MSB_RING_SIZE);
+-      ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET, val);
++      ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET(ab), val);
+       val = u32_encode_bits(srng->entry_size, HAL_REO1_RING_ID_ENTRY_SIZE);
+       ath12k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET(ab), val);
+diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
+index 1fdd573532b93..fb7ec6fce07d3 100644
+--- a/drivers/net/wireless/ath/ath12k/hal.h
++++ b/drivers/net/wireless/ath/ath12k/hal.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
+ /*
+  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #ifndef ATH12K_HAL_H
+@@ -44,10 +44,14 @@ struct ath12k_base;
+ #define HAL_SEQ_WCSS_UMAC_OFFSET              0x00a00000
+ #define HAL_SEQ_WCSS_UMAC_REO_REG             0x00a38000
+ #define HAL_SEQ_WCSS_UMAC_TCL_REG             0x00a44000
+-#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG         0x01b80000
+-#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG         0x01b81000
+-#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG         0x01b82000
+-#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG         0x01b83000
++#define HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) \
++      ((ab)->hw_params->regs->hal_umac_ce0_src_reg_base)
++#define HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) \
++      ((ab)->hw_params->regs->hal_umac_ce0_dest_reg_base)
++#define HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) \
++      ((ab)->hw_params->regs->hal_umac_ce1_src_reg_base)
++#define HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) \
++      ((ab)->hw_params->regs->hal_umac_ce1_dest_reg_base)
+ #define HAL_SEQ_WCSS_UMAC_WBM_REG             0x00a34000
+ #define HAL_CE_WFSS_CE_REG_BASE                       0x01b80000
+@@ -57,8 +61,10 @@ struct ath12k_base;
+ /* SW2TCL(x) R0 ring configuration address */
+ #define HAL_TCL1_RING_CMN_CTRL_REG            0x00000020
+ #define HAL_TCL1_RING_DSCP_TID_MAP            0x00000240
+-#define HAL_TCL1_RING_BASE_LSB                        0x00000900
+-#define HAL_TCL1_RING_BASE_MSB                        0x00000904
++#define HAL_TCL1_RING_BASE_LSB(ab) \
++      ((ab)->hw_params->regs->hal_tcl1_ring_base_lsb)
++#define HAL_TCL1_RING_BASE_MSB(ab) \
++      ((ab)->hw_params->regs->hal_tcl1_ring_base_msb)
+ #define HAL_TCL1_RING_ID(ab)                  ((ab)->hw_params->regs->hal_tcl1_ring_id)
+ #define HAL_TCL1_RING_MISC(ab) \
+       ((ab)->hw_params->regs->hal_tcl1_ring_misc)
+@@ -76,30 +82,31 @@ struct ath12k_base;
+       ((ab)->hw_params->regs->hal_tcl1_ring_msi1_base_msb)
+ #define HAL_TCL1_RING_MSI1_DATA(ab) \
+       ((ab)->hw_params->regs->hal_tcl1_ring_msi1_data)
+-#define HAL_TCL2_RING_BASE_LSB                        0x00000978
++#define HAL_TCL2_RING_BASE_LSB(ab) \
++      ((ab)->hw_params->regs->hal_tcl2_ring_base_lsb)
+ #define HAL_TCL_RING_BASE_LSB(ab) \
+       ((ab)->hw_params->regs->hal_tcl_ring_base_lsb)
+-#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab)                                \
+-      (HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab)                                \
+-      (HAL_TCL1_RING_MSI1_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab)                            \
+-      (HAL_TCL1_RING_MSI1_DATA(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_BASE_MSB_OFFSET                         \
+-      (HAL_TCL1_RING_BASE_MSB - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_ID_OFFSET(ab)                           \
+-      (HAL_TCL1_RING_ID(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab)                  \
+-      (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) \
+-              (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) \
+-              (HAL_TCL1_RING_TP_ADDR_LSB(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) \
+-              (HAL_TCL1_RING_TP_ADDR_MSB(ab) - HAL_TCL1_RING_BASE_LSB)
+-#define HAL_TCL1_RING_MISC_OFFSET(ab) \
+-              (HAL_TCL1_RING_MISC(ab) - HAL_TCL1_RING_BASE_LSB)
++#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_MSI1_BASE_LSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab)        ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_MSI1_BASE_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_MSI1_DATA(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_BASE_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_BASE_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_ID_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_ID(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_TP_ADDR_LSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_TP_ADDR_MSB(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
++#define HAL_TCL1_RING_MISC_OFFSET(ab) ({ typeof(ab) _ab = (ab); \
++      (HAL_TCL1_RING_MISC(_ab) - HAL_TCL1_RING_BASE_LSB(_ab)); })
+ /* SW2TCL(x) R2 ring pointers (head/tail) address */
+ #define HAL_TCL1_RING_HP                      0x00002000
+diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
+index ec1bda95e555d..5bffc428f19f5 100644
+--- a/drivers/net/wireless/ath/ath12k/hw.c
++++ b/drivers/net/wireless/ath/ath12k/hw.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #include <linux/types.h>
+@@ -615,6 +615,9 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = {
+       .hal_tcl1_ring_msi1_base_msb = 0x0000094c,
+       .hal_tcl1_ring_msi1_data = 0x00000950,
+       .hal_tcl_ring_base_lsb = 0x00000b58,
++      .hal_tcl1_ring_base_lsb = 0x00000900,
++      .hal_tcl1_ring_base_msb = 0x00000904,
++      .hal_tcl2_ring_base_lsb = 0x00000978,
+       /* TCL STATUS ring address */
+       .hal_tcl_status_ring_base_lsb = 0x00000d38,
+@@ -677,6 +680,12 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = {
+       /* REO status ring address */
+       .hal_reo_status_ring_base = 0x00000a84,
++
++      /* CE base address */
++      .hal_umac_ce0_src_reg_base = 0x01b80000,
++      .hal_umac_ce0_dest_reg_base = 0x01b81000,
++      .hal_umac_ce1_src_reg_base = 0x01b82000,
++      .hal_umac_ce1_dest_reg_base = 0x01b83000,
+ };
+ static const struct ath12k_hw_regs qcn9274_v2_regs = {
+@@ -691,6 +700,9 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = {
+       .hal_tcl1_ring_msi1_base_msb = 0x0000094c,
+       .hal_tcl1_ring_msi1_data = 0x00000950,
+       .hal_tcl_ring_base_lsb = 0x00000b58,
++      .hal_tcl1_ring_base_lsb = 0x00000900,
++      .hal_tcl1_ring_base_msb = 0x00000904,
++      .hal_tcl2_ring_base_lsb = 0x00000978,
+       /* TCL STATUS ring address */
+       .hal_tcl_status_ring_base_lsb = 0x00000d38,
+@@ -757,6 +769,12 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = {
+       /* REO status ring address */
+       .hal_reo_status_ring_base = 0x00000aa0,
++
++      /* CE base address */
++      .hal_umac_ce0_src_reg_base = 0x01b80000,
++      .hal_umac_ce0_dest_reg_base = 0x01b81000,
++      .hal_umac_ce1_src_reg_base = 0x01b82000,
++      .hal_umac_ce1_dest_reg_base = 0x01b83000,
+ };
+ static const struct ath12k_hw_regs wcn7850_regs = {
+@@ -771,6 +789,9 @@ static const struct ath12k_hw_regs wcn7850_regs = {
+       .hal_tcl1_ring_msi1_base_msb = 0x0000094c,
+       .hal_tcl1_ring_msi1_data = 0x00000950,
+       .hal_tcl_ring_base_lsb = 0x00000b58,
++      .hal_tcl1_ring_base_lsb = 0x00000900,
++      .hal_tcl1_ring_base_msb = 0x00000904,
++      .hal_tcl2_ring_base_lsb = 0x00000978,
+       /* TCL STATUS ring address */
+       .hal_tcl_status_ring_base_lsb = 0x00000d38,
+@@ -833,6 +854,12 @@ static const struct ath12k_hw_regs wcn7850_regs = {
+       /* REO status ring address */
+       .hal_reo_status_ring_base = 0x00000a84,
++
++      /* CE base address */
++      .hal_umac_ce0_src_reg_base = 0x01b80000,
++      .hal_umac_ce0_dest_reg_base = 0x01b81000,
++      .hal_umac_ce1_src_reg_base = 0x01b82000,
++      .hal_umac_ce1_dest_reg_base = 0x01b83000,
+ };
+ static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = {
+diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
+index 8d52182e28aef..acb81b5798ac1 100644
+--- a/drivers/net/wireless/ath/ath12k/hw.h
++++ b/drivers/net/wireless/ath/ath12k/hw.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
+ /*
+  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+  */
+ #ifndef ATH12K_HW_H
+@@ -293,6 +293,9 @@ struct ath12k_hw_regs {
+       u32 hal_tcl1_ring_msi1_base_msb;
+       u32 hal_tcl1_ring_msi1_data;
+       u32 hal_tcl_ring_base_lsb;
++      u32 hal_tcl1_ring_base_lsb;
++      u32 hal_tcl1_ring_base_msb;
++      u32 hal_tcl2_ring_base_lsb;
+       u32 hal_tcl_status_ring_base_lsb;
+@@ -316,6 +319,11 @@ struct ath12k_hw_regs {
+       u32 pcie_qserdes_sysclk_en_sel;
+       u32 pcie_pcs_osc_dtct_config_base;
++      u32 hal_umac_ce0_src_reg_base;
++      u32 hal_umac_ce0_dest_reg_base;
++      u32 hal_umac_ce1_src_reg_base;
++      u32 hal_umac_ce1_dest_reg_base;
++
+       u32 hal_ppe_rel_ring_base;
+       u32 hal_reo2_ring_base;
+-- 
+2.39.5
+