From: Sasha Levin Date: Sun, 15 Jun 2025 13:01:10 +0000 (-0400) Subject: Fixes for 6.15 X-Git-Tag: v6.6.94~65 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c3536007f1de1f5257f8b608edd2cbdb6dc2df9c;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.15 Signed-off-by: Sasha Levin --- diff --git a/queue-6.15/accel-amdxdna-fix-incorrect-psp-firmware-size.patch b/queue-6.15/accel-amdxdna-fix-incorrect-psp-firmware-size.patch new file mode 100644 index 0000000000..5c96856bcc --- /dev/null +++ b/queue-6.15/accel-amdxdna-fix-incorrect-psp-firmware-size.patch @@ -0,0 +1,39 @@ +From 8a114385dd2a3792dd7ba9dbd7cb71ea84557d5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Jun 2025 07:32:17 -0700 +Subject: accel/amdxdna: Fix incorrect PSP firmware size + +From: Lizhi Hou + +[ Upstream commit 779a0c9e06a91d0007f2a4f4071e3b9a8102b15e ] + +The incorrect PSP firmware size is used for initializing. It may +cause error for newer version firmware. + +Fixes: 8c9ff1b181ba ("accel/amdxdna: Add a new driver for AMD AI Engine") +Acked-by: Alex Deucher +Signed-off-by: Lizhi Hou +Link: https://lore.kernel.org/r/20250604143217.1386272-1-lizhi.hou@amd.com +Signed-off-by: Sasha Levin +--- + drivers/accel/amdxdna/aie2_psp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/accel/amdxdna/aie2_psp.c b/drivers/accel/amdxdna/aie2_psp.c +index dc3a072ce3b6d..f28a060a88109 100644 +--- a/drivers/accel/amdxdna/aie2_psp.c ++++ b/drivers/accel/amdxdna/aie2_psp.c +@@ -126,8 +126,8 @@ struct psp_device *aie2m_psp_create(struct drm_device *ddev, struct psp_config * + psp->ddev = ddev; + memcpy(psp->psp_regs, conf->psp_regs, sizeof(psp->psp_regs)); + +- psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN) + PSP_FW_ALIGN; +- psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz, GFP_KERNEL); ++ psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN); ++ psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz + PSP_FW_ALIGN, GFP_KERNEL); + if (!psp->fw_buffer) { + drm_err(ddev, "no memory for fw buffer"); + return NULL; +-- +2.39.5 + diff --git a/queue-6.15/acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch b/queue-6.15/acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch new file mode 100644 index 0000000000..fafa776cb8 --- /dev/null +++ b/queue-6.15/acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch @@ -0,0 +1,48 @@ +From d22e4258c45ad55eccc551136d072a2b6aa94f9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Jun 2025 10:30:36 +0800 +Subject: ACPI: CPPC: Fix NULL pointer dereference when nosmp is used + +From: Yunhui Cui + +[ 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] [] 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 +Signed-off-by: Yunhui Cui +Link: https://patch.msgid.link/20250604023036.99553-1-cuiyunhui@bytedance.com +[ rjw: New subject ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/cppc_acpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index f193e713825ac..ff23b6edb2df3 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.15/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch b/queue-6.15/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch new file mode 100644 index 0000000000..d341619e67 --- /dev/null +++ b/queue-6.15/ath10k-snoc-fix-unbalanced-irq-enable-in-crash-recov.patch @@ -0,0 +1,49 @@ +From 35707a8b18df5d8f188c98f611a1a6bb3f3ccf1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 20:50:27 +0000 +Subject: ath10k: snoc: fix unbalanced IRQ enable in crash recovery + +From: Caleb Connolly + +[ 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 +Tested-by: Loic Poulain +Link: https://patch.msgid.link/20250318205043.1043148-1-caleb.connolly@linaro.org +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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 866bad2db3348..65673b1aba55d 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.15/bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch b/queue-6.15/bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch new file mode 100644 index 0000000000..70464d8c85 --- /dev/null +++ b/queue-6.15/bluetooth-btintel_pcie-fix-driver-not-posting-maximu.patch @@ -0,0 +1,77 @@ +From 1cf8e4076b1a43315a70d2226c74d78fedd32301 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Kiran K +Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 0a759ea26fd38..a1bfc76fa29b2 100644 +--- a/drivers/bluetooth/btintel_pcie.c ++++ b/drivers/bluetooth/btintel_pcie.c +@@ -303,8 +303,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 873178019cad0..3f59138dfcca4 100644 +--- a/drivers/bluetooth/btintel_pcie.h ++++ b/drivers/bluetooth/btintel_pcie.h +@@ -158,9 +158,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.15/bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch b/queue-6.15/bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch new file mode 100644 index 0000000000..f92483ec0c --- /dev/null +++ b/queue-6.15/bluetooth-btintel_pcie-increase-the-tx-and-rx-descri.patch @@ -0,0 +1,107 @@ +From 4f9f0362a2de60f005ded55b8424ecd7f241f698 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Jun 2025 15:34:39 +0530 +Subject: Bluetooth: btintel_pcie: Increase the tx and rx descriptor count + +From: Chandrashekar Devegowda + +[ 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 +Signed-off-by: Kiran K +Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 a1bfc76fa29b2..a4883523ccc9e 100644 +--- a/drivers/bluetooth/btintel_pcie.c ++++ b/drivers/bluetooth/btintel_pcie.c +@@ -1665,8 +1665,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); +@@ -1691,36 +1691,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 3f59138dfcca4..a94910ccd5d3c 100644 +--- a/drivers/bluetooth/btintel_pcie.h ++++ b/drivers/bluetooth/btintel_pcie.h +@@ -135,8 +135,11 @@ enum btintel_pcie_tlv_type { + /* 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.15/bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch b/queue-6.15/bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch new file mode 100644 index 0000000000..27ad9f5e02 --- /dev/null +++ b/queue-6.15/bluetooth-btintel_pcie-reduce-driver-buffer-posting-.patch @@ -0,0 +1,44 @@ +From d4b5d92578778908f3d4e92654de89981fc84d36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Jun 2025 15:34:40 +0530 +Subject: Bluetooth: btintel_pcie: Reduce driver buffer posting to prevent race + condition + +From: Chandrashekar Devegowda + +[ 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 +Signed-off-by: Kiran K +Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 a4883523ccc9e..385e29367dd1d 100644 +--- a/drivers/bluetooth/btintel_pcie.c ++++ b/drivers/bluetooth/btintel_pcie.c +@@ -305,7 +305,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.15/bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch b/queue-6.15/bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch new file mode 100644 index 0000000000..b8627d23d4 --- /dev/null +++ b/queue-6.15/bluetooth-eir-fix-possible-crashes-on-eir_create_adv.patch @@ -0,0 +1,93 @@ +From 0a3ab637832e25e1e3da6202453262b7b57ebba0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 8ba1c3aa7801a..83de3847c8eaf 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1822,7 +1822,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; +@@ -1853,7 +1854,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.15/bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch b/queue-6.15/bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch new file mode 100644 index 0000000000..6fabca1a95 --- /dev/null +++ b/queue-6.15/bluetooth-fix-null-pointer-deference-on-eir_get_serv.patch @@ -0,0 +1,50 @@ +From a33012533254a2a4dd43a7535d01d2d3a5cc4455 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sasha Levin +--- + 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.15/bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch b/queue-6.15/bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch new file mode 100644 index 0000000000..e5add79f4f --- /dev/null +++ b/queue-6.15/bluetooth-hci_core-fix-list_for_each_entry_rcu-usage.patch @@ -0,0 +1,57 @@ +From 3947ec9fb936cf839a222201001f918f55264df8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 31 May 2025 18:24:58 +0300 +Subject: Bluetooth: hci_core: fix list_for_each_entry_rcu usage + +From: Pauli Virtanen + +[ 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 +Reviewed-by: Paul Menzel +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 2668e0e563c43..67c7e0656ff71 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -3406,23 +3406,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.15/bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch b/queue-6.15/bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch new file mode 100644 index 0000000000..2e16fbbeec --- /dev/null +++ b/queue-6.15/bluetooth-hci_sync-fix-broadcast-pa-when-using-an-ex.patch @@ -0,0 +1,105 @@ +From 4970c0d0b500ea5c60866270ea67e0577b333f31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 62d1ff951ebe6..8ba1c3aa7801a 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.15/bluetooth-mgmt-fix-sparse-errors.patch b/queue-6.15/bluetooth-mgmt-fix-sparse-errors.patch new file mode 100644 index 0000000000..8a8c4276d0 --- /dev/null +++ b/queue-6.15/bluetooth-mgmt-fix-sparse-errors.patch @@ -0,0 +1,47 @@ +From 9de8d0f682e3f36672aa95115dce39959b647a6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 16:36:27 -0400 +Subject: Bluetooth: MGMT: Fix sparse errors + +From: Luiz Augusto von Dentz + +[ 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 +Closes: https://lore.kernel.org/oe-kbuild-all/202506060347.ux2O1p7L-lkp@intel.com/ +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 de7adb9a47f97..d540f7b4f75fb 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -5102,11 +5102,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.15/bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch b/queue-6.15/bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch new file mode 100644 index 0000000000..cc772d0d25 --- /dev/null +++ b/queue-6.15/bluetooth-mgmt-fix-uaf-on-mgmt_remove_adv_monitor_co.patch @@ -0,0 +1,229 @@ +From f52b7ae189be8abe678eb2b76e1bc02cae06e32b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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 + + +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 +Signed-off-by: Sasha Levin +--- + 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 fc66d9b61198e..1743bde8528b2 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -2397,7 +2397,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 67c7e0656ff71..7317efb6306ec 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 14a9462fced5e..feaeec2423ae8 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -5108,24 +5108,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, +@@ -5227,8 +5217,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; + } +@@ -5398,8 +5387,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); +@@ -5408,12 +5396,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", +@@ -5423,10 +5413,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); + +@@ -5445,14 +5431,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; +@@ -5462,7 +5447,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.15/bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch b/queue-6.15/bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch new file mode 100644 index 0000000000..7bcb3f7372 --- /dev/null +++ b/queue-6.15/bluetooth-mgmt-protect-mgmt_pending-list-with-its-ow.patch @@ -0,0 +1,626 @@ +From 4c314c50eebbfb820ff09574a0f0cdf1f9332373 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 1743bde8528b2..d15316bffd70b 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -545,6 +545,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 7317efb6306ec..af30a420bab75 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -2485,6 +2485,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 feaeec2423ae8..de7adb9a47f97 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -1447,22 +1447,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) +@@ -1476,8 +1471,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; + } + +@@ -1486,13 +1479,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)); + } + +@@ -1532,7 +1525,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; + } +@@ -1707,7 +1700,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; + } + +@@ -1943,8 +1936,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; + } + +@@ -1954,7 +1947,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); +@@ -2074,12 +2067,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); + +@@ -2138,7 +2131,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; + } +@@ -2638,7 +2631,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); +@@ -3427,7 +3420,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 */ +@@ -5186,7 +5179,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); + +@@ -5401,7 +5394,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); + +@@ -5777,7 +5770,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); + +@@ -5998,7 +5991,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); + +@@ -6223,7 +6216,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; + } +@@ -6233,7 +6226,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); +@@ -6577,7 +6570,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); +@@ -6714,7 +6707,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; + } + +@@ -7161,7 +7154,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); +@@ -7321,7 +7314,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); +@@ -8571,10 +8564,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); +@@ -8762,10 +8755,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)); + } + +@@ -8912,10 +8905,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); +@@ -9074,10 +9067,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); +@@ -9349,7 +9342,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, +@@ -9387,7 +9380,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); + +@@ -9402,7 +9396,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 +@@ -9416,7 +9411,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, +@@ -9657,7 +9652,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) +@@ -9713,8 +9707,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) +@@ -9907,7 +9901,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; + } +@@ -9917,8 +9911,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); +@@ -9942,9 +9936,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.15/drm-meson-fix-debug-log-statement-when-setting-the-h.patch b/queue-6.15/drm-meson-fix-debug-log-statement-when-setting-the-h.patch new file mode 100644 index 0000000000..0dd7c84966 --- /dev/null +++ b/queue-6.15/drm-meson-fix-debug-log-statement-when-setting-the-h.patch @@ -0,0 +1,39 @@ +From cf9f749665723c290265789aed48924ff93f827e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Jun 2025 22:37:29 +0200 +Subject: drm/meson: fix debug log statement when setting the HDMI clocks + +From: Martin Blumenstingl + +[ 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 +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://lore.kernel.org/r/20250606203729.3311592-1-martin.blumenstingl@googlemail.com +Signed-off-by: Sasha Levin +--- + 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 c08fa93e50a30..2bccda1e52a17 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.15/drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch b/queue-6.15/drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch new file mode 100644 index 0000000000..a8b444ffaa --- /dev/null +++ b/queue-6.15/drm-meson-fix-more-rounding-issues-with-59.94hz-mode.patch @@ -0,0 +1,134 @@ +From a8ae54a27faf609e6777f84ef0d2699766179403 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 22:27:51 +0200 +Subject: drm/meson: fix more rounding issues with 59.94Hz modes + +From: Martin Blumenstingl + +[ 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 +Signed-off-by: Martin Blumenstingl +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://lore.kernel.org/r/20250609202751.962208-1-martin.blumenstingl@googlemail.com +Signed-off-by: Sasha Levin +--- + 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.15/drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch b/queue-6.15/drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch new file mode 100644 index 0000000000..ea2770d4e7 --- /dev/null +++ b/queue-6.15/drm-meson-use-vclk_freq-instead-of-pixel_freq-in-deb.patch @@ -0,0 +1,46 @@ +From 7f2707a4395da2f1944e049bd3deada8017c61d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://lore.kernel.org/r/20250606221031.3419353-1-martin.blumenstingl@googlemail.com +Signed-off-by: Sasha Levin +--- + 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.15/drm-vc4-fix-infinite-eprobe_defer-loop.patch b/queue-6.15/drm-vc4-fix-infinite-eprobe_defer-loop.patch new file mode 100644 index 0000000000..35335a87bf --- /dev/null +++ b/queue-6.15/drm-vc4-fix-infinite-eprobe_defer-loop.patch @@ -0,0 +1,58 @@ +From 122a849ac14f2ac9d210cd5de070078a540ef9c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Jun 2025 12:45:36 -0400 +Subject: drm/vc4: fix infinite EPROBE_DEFER loop + +From: Gabriel Dalimonte + +[ Upstream commit c0317ad44f45b3c1f0ff46a4e28d14c7bccdedf4 ] + +`vc4_hdmi_audio_init` calls `devm_snd_dmaengine_pcm_register` which may +return EPROBE_DEFER. Calling `drm_connector_hdmi_audio_init` adds a +child device. The driver model docs[1] state that adding a child device +prior to returning EPROBE_DEFER may result in an infinite loop. + +[1] https://www.kernel.org/doc/html/v6.14/driver-api/driver-model/driver.html + +Fixes: 9640f1437a88 ("drm/vc4: hdmi: switch to using generic HDMI Codec infrastructure") +Signed-off-by: Gabriel Dalimonte +Link: https://lore.kernel.org/r/20250601-vc4-audio-inf-probe-v2-1-9ad43c7b6147@gmail.com +Signed-off-by: Maxime Ripard +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index 37a7d45695f23..176aba27b03d3 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -559,12 +559,6 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, + if (ret) + return ret; + +- ret = drm_connector_hdmi_audio_init(connector, dev->dev, +- &vc4_hdmi_audio_funcs, +- 8, false, -1); +- if (ret) +- return ret; +- + drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); + + /* +@@ -2274,6 +2268,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) + return ret; + } + ++ ret = drm_connector_hdmi_audio_init(&vc4_hdmi->connector, dev, ++ &vc4_hdmi_audio_funcs, 8, false, ++ -1); ++ if (ret) ++ return ret; ++ + dai_link->cpus = &vc4_hdmi->audio.cpu; + dai_link->codecs = &vc4_hdmi->audio.codec; + dai_link->platforms = &vc4_hdmi->audio.platform; +-- +2.39.5 + diff --git a/queue-6.15/drm-xe-lrc-use-a-temporary-buffer-for-wa-bb.patch b/queue-6.15/drm-xe-lrc-use-a-temporary-buffer-for-wa-bb.patch new file mode 100644 index 0000000000..5a651e5e9e --- /dev/null +++ b/queue-6.15/drm-xe-lrc-use-a-temporary-buffer-for-wa-bb.patch @@ -0,0 +1,89 @@ +From 089021895a7c12aca820cca1c3c8b3db56655342 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Jun 2025 08:03:05 -0700 +Subject: drm/xe/lrc: Use a temporary buffer for WA BB +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lucas De Marchi + +[ Upstream commit 9c7632faad434c98f1f2cc06f3647a5a5d05ddbf ] + +In case the BO is in iomem, we can't simply take the vaddr and write to +it. Instead, prepare a separate buffer that is later copied into io +memory. Right now it's just a few words that could be using +xe_map_write32(), but the intention is to grow the WA BB for other +uses. + +Fixes: 617d824c5323 ("drm/xe: Add WA BB to capture active context utilization") +Cc: Umesh Nerlige Ramappa +Cc: Tvrtko Ursulin +Reviewed-by: Matthew Brost +Reviewed-by: Umesh Nerlige Ramappa +Link: https://lore.kernel.org/r/20250604-wa-bb-fix-v1-1-0dfc5dafcef0@intel.com +Signed-off-by: Lucas De Marchi +(cherry picked from commit ef48715b2d3df17c060e23b9aa636af3d95652f8) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_lrc.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c +index 03bfba696b378..16e20b5ad325f 100644 +--- a/drivers/gpu/drm/xe/xe_lrc.c ++++ b/drivers/gpu/drm/xe/xe_lrc.c +@@ -941,11 +941,18 @@ static void xe_lrc_finish(struct xe_lrc *lrc) + * store it in the PPHSWP. + */ + #define CONTEXT_ACTIVE 1ULL +-static void xe_lrc_setup_utilization(struct xe_lrc *lrc) ++static int xe_lrc_setup_utilization(struct xe_lrc *lrc) + { +- u32 *cmd; ++ u32 *cmd, *buf = NULL; + +- cmd = lrc->bb_per_ctx_bo->vmap.vaddr; ++ if (lrc->bb_per_ctx_bo->vmap.is_iomem) { ++ buf = kmalloc(lrc->bb_per_ctx_bo->size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ cmd = buf; ++ } else { ++ cmd = lrc->bb_per_ctx_bo->vmap.vaddr; ++ } + + *cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; + *cmd++ = ENGINE_ID(0).addr; +@@ -966,9 +973,16 @@ static void xe_lrc_setup_utilization(struct xe_lrc *lrc) + + *cmd++ = MI_BATCH_BUFFER_END; + ++ if (buf) { ++ xe_map_memcpy_to(gt_to_xe(lrc->gt), &lrc->bb_per_ctx_bo->vmap, 0, ++ buf, (cmd - buf) * sizeof(*cmd)); ++ kfree(buf); ++ } ++ + xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, + xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1); + ++ return 0; + } + + #define PVC_CTX_ASID (0x2e + 1) +@@ -1123,7 +1137,9 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, + map = __xe_lrc_start_seqno_map(lrc); + xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); + +- xe_lrc_setup_utilization(lrc); ++ err = xe_lrc_setup_utilization(lrc); ++ if (err) ++ goto err_lrc_finish; + + return 0; + +-- +2.39.5 + diff --git a/queue-6.15/e1000-move-cancel_work_sync-to-avoid-deadlock.patch b/queue-6.15/e1000-move-cancel_work_sync-to-avoid-deadlock.patch new file mode 100644 index 0000000000..657954a3db --- /dev/null +++ b/queue-6.15/e1000-move-cancel_work_sync-to-avoid-deadlock.patch @@ -0,0 +1,74 @@ +From f41c9b00de835e0998941ca56b586cfdaddad51e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Jun 2025 16:34:01 +0000 +Subject: e1000: Move cancel_work_sync to avoid deadlock + +From: Joe Damato + +[ Upstream commit b4a8085ceefb7bbb12c2b71c55e71fc946c6929f ] + +Previously, e1000_down called cancel_work_sync for the e1000 reset task +(via e1000_down_and_stop), which takes RTNL. + +As reported by users and syzbot, a deadlock is possible in the following +scenario: + +CPU 0: + - RTNL is held + - e1000_close + - e1000_down + - cancel_work_sync (cancel / wait for e1000_reset_task()) + +CPU 1: + - process_one_work + - e1000_reset_task + - take RTNL + +To remedy this, avoid calling cancel_work_sync from e1000_down +(e1000_reset_task does nothing if the device is down anyway). Instead, +call cancel_work_sync for e1000_reset_task when the device is being +removed. + +Fixes: e400c7444d84 ("e1000: Hold RTNL when e1000_down can be called") +Reported-by: syzbot+846bb38dc67fe62cc733@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/683837bf.a00a0220.52848.0003.GAE@google.com/ +Reported-by: John +Closes: https://lore.kernel.org/netdev/CAP=Rh=OEsn4y_2LvkO3UtDWurKcGPnZ_NPSXK=FbgygNXL37Sw@mail.gmail.com/ +Signed-off-by: Joe Damato +Acked-by: Stanislav Fomichev +Acked-by: Jacob Keller +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/e1000/e1000_main.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c +index 3f089c3d47b23..d8595e84326db 100644 +--- a/drivers/net/ethernet/intel/e1000/e1000_main.c ++++ b/drivers/net/ethernet/intel/e1000/e1000_main.c +@@ -477,10 +477,6 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter) + + cancel_delayed_work_sync(&adapter->phy_info_task); + cancel_delayed_work_sync(&adapter->fifo_stall_task); +- +- /* Only kill reset task if adapter is not resetting */ +- if (!test_bit(__E1000_RESETTING, &adapter->flags)) +- cancel_work_sync(&adapter->reset_task); + } + + void e1000_down(struct e1000_adapter *adapter) +@@ -1266,6 +1262,10 @@ static void e1000_remove(struct pci_dev *pdev) + + unregister_netdev(netdev); + ++ /* Only kill reset task if adapter is not resetting */ ++ if (!test_bit(__E1000_RESETTING, &adapter->flags)) ++ cancel_work_sync(&adapter->reset_task); ++ + e1000_phy_hw_reset(hw); + + kfree(adapter->tx_ring); +-- +2.39.5 + diff --git a/queue-6.15/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch b/queue-6.15/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch new file mode 100644 index 0000000000..ded472ae8c --- /dev/null +++ b/queue-6.15/i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch @@ -0,0 +1,44 @@ +From 4eb126cdf16877a8f6a0580b9344b0724f38fadc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 May 2025 10:31:52 +0200 +Subject: i40e: retry VFLR handling if there is ongoing VF reset + +From: Robert Malz + +[ 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 +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 22d5b1ec2289f..88e6bef69342c 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.15/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch b/queue-6.15/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch new file mode 100644 index 0000000000..00456cf718 --- /dev/null +++ b/queue-6.15/i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch @@ -0,0 +1,55 @@ +From 5d1964bcb4f6874c5df3a083a9a0d3379322c46d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 1120f8e4bb670..22d5b1ec2289f 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.15/iavf-fix-reset_task-for-early-reset-event.patch b/queue-6.15/iavf-fix-reset_task-for-early-reset-event.patch new file mode 100644 index 0000000000..f85d08a9d2 --- /dev/null +++ b/queue-6.15/iavf-fix-reset_task-for-early-reset-event.patch @@ -0,0 +1,95 @@ +From 29a99de2d13061ab633f1f045f1307a43e0c93a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Apr 2025 15:50:13 +0200 +Subject: iavf: fix reset_task for early reset event + +From: Ahmed Zaki + +[ Upstream commit 0c6f4631436ecea841f1583b98255aedd7495b18 ] + +If a reset event is received from the PF early in the init cycle, the +state machine hangs for about 25 seconds. + +Reproducer: + echo 1 > /sys/class/net/$PF0/device/sriov_numvfs + ip link set dev $PF0 vf 0 mac $NEW_MAC + +The log shows: + [792.620416] ice 0000:5e:00.0: Enabling 1 VFs + [792.738812] iavf 0000:5e:01.0: enabling device (0000 -> 0002) + [792.744182] ice 0000:5e:00.0: Enabling 1 VFs with 17 vectors and 16 queues per VF + [792.839964] ice 0000:5e:00.0: Setting MAC 52:54:00:00:00:11 on VF 0. VF driver will be reinitialized + [813.389684] iavf 0000:5e:01.0: Failed to communicate with PF; waiting before retry + [818.635918] iavf 0000:5e:01.0: Hardware came out of reset. Attempting reinit. + [818.766273] iavf 0000:5e:01.0: Multiqueue Enabled: Queue pair count = 16 + +Fix it by scheduling the reset task and making the reset task capable of +resetting early in the init cycle. + +Fixes: ef8693eb90ae3 ("i40evf: refactor reset handling") +Signed-off-by: Ahmed Zaki +Tested-by: Przemek Kitszel +Reviewed-by: Przemek Kitszel +Signed-off-by: Marcin Szycik +Reviewed-by: Simon Horman +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 11 +++++++++++ + drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 17 +++++++++++++++++ + 2 files changed, 28 insertions(+) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 2c0bb41809a41..81d7249d1149c 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -3209,6 +3209,17 @@ static void iavf_reset_task(struct work_struct *work) + } + + continue_reset: ++ /* If we are still early in the state machine, just restart. */ ++ if (adapter->state <= __IAVF_INIT_FAILED) { ++ iavf_shutdown_adminq(hw); ++ iavf_change_state(adapter, __IAVF_STARTUP); ++ iavf_startup(adapter); ++ queue_delayed_work(adapter->wq, &adapter->watchdog_task, ++ msecs_to_jiffies(30)); ++ netdev_unlock(netdev); ++ return; ++ } ++ + /* We don't use netif_running() because it may be true prior to + * ndo_open() returning, so we can't assume it means all our open + * tasks have finished, since we're not holding the rtnl_lock here. +diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +index a6f0e5990be25..07f0d0a0f1e28 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +@@ -79,6 +79,23 @@ iavf_poll_virtchnl_msg(struct iavf_hw *hw, struct iavf_arq_event_info *event, + return iavf_status_to_errno(status); + received_op = + (enum virtchnl_ops)le32_to_cpu(event->desc.cookie_high); ++ ++ if (received_op == VIRTCHNL_OP_EVENT) { ++ struct iavf_adapter *adapter = hw->back; ++ struct virtchnl_pf_event *vpe = ++ (struct virtchnl_pf_event *)event->msg_buf; ++ ++ if (vpe->event != VIRTCHNL_EVENT_RESET_IMPENDING) ++ continue; ++ ++ dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n"); ++ if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) ++ iavf_schedule_reset(adapter, ++ IAVF_FLAG_RESET_PENDING); ++ ++ return -EIO; ++ } ++ + if (op_to_poll == received_op) + break; + } +-- +2.39.5 + diff --git a/queue-6.15/ice-ptp-fix-crosstimestamp-reporting.patch b/queue-6.15/ice-ptp-fix-crosstimestamp-reporting.patch new file mode 100644 index 0000000000..4ab0bb7ed2 --- /dev/null +++ b/queue-6.15/ice-ptp-fix-crosstimestamp-reporting.patch @@ -0,0 +1,48 @@ +From f6ba6730ac0713941f600e065a64595b7a09df11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 May 2025 10:42:16 +0200 +Subject: ice/ptp: fix crosstimestamp reporting + +From: Anton Nadezhdin + +[ Upstream commit a5a441ae283d54ec329aadc7426991dc32786d52 ] + +Set use_nsecs=true as timestamp is reported in ns. Lack of this result +in smaller timestamp error window which cause error during phc2sys +execution on E825 NICs: +phc2sys[1768.256]: ioctl PTP_SYS_OFFSET_PRECISE: Invalid argument + +This problem was introduced in the cited commit which omitted setting +use_nsecs to true when converting the ice driver to use +convert_base_to_cs(). + +Testing hints (ethX is PF netdev): +phc2sys -s ethX -c CLOCK_REALTIME -O 37 -m +phc2sys[1769.256]: CLOCK_REALTIME phc offset -5 s0 freq -0 delay 0 + +Fixes: d4bea547ebb57 ("ice/ptp: Remove convert_art_to_tsc()") +Signed-off-by: Anton Nadezhdin +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Arkadiusz Kubalewski +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_ptp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c +index 1fd1ae03eb909..11ed48a62b536 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ptp.c ++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c +@@ -2307,6 +2307,7 @@ static int ice_capture_crosststamp(ktime_t *device, + ts = ((u64)ts_hi << 32) | ts_lo; + system->cycles = ts; + system->cs_id = CSID_X86_ART; ++ system->use_nsecs = true; + + /* Read Device source clock time */ + ts_lo = rd32(hw, cfg->dev_time_l[tmr_idx]); +-- +2.39.5 + diff --git a/queue-6.15/macsec-macsec-sci-assignment-for-es-0.patch b/queue-6.15/macsec-macsec-sci-assignment-for-es-0.patch new file mode 100644 index 0000000000..74cf40bff5 --- /dev/null +++ b/queue-6.15/macsec-macsec-sci-assignment-for-es-0.patch @@ -0,0 +1,128 @@ +From d8886e43b4cff6981473dbe83ee4fb81fe17f10f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 09:26:26 +0200 +Subject: macsec: MACsec SCI assignment for ES = 0 + +From: Carlos Fernandez + +[ 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 +Signed-off-by: Andreu Montiel +Signed-off-by: Carlos Fernandez +Reviewed-by: Subbaraya Sundeep +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 3d315e30ee472..7edbe76b5455a 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -247,15 +247,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; + } +@@ -1109,7 +1133,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; +@@ -1156,11 +1180,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); + +@@ -1283,6 +1310,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.15/net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch b/queue-6.15/net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch new file mode 100644 index 0000000000..885e3b07d9 --- /dev/null +++ b/queue-6.15/net-drv-netdevsim-don-t-napi_complete-from-netpoll.patch @@ -0,0 +1,46 @@ +From c0e3e3ef1638434dce74d8e753d85c3715f9d939 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 10:46:43 -0700 +Subject: net: drv: netdevsim: don't napi_complete() from netpoll + +From: Jakub Kicinski + +[ 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 +Fixes: 3762ec05a9fb ("netdevsim: add NAPI support") +Tested-by: Breno Leitao +Link: https://patch.msgid.link/20250611174643.2769263-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 0e0321a7ddd71..31a06e71be25b 100644 +--- a/drivers/net/netdevsim/netdev.c ++++ b/drivers/net/netdevsim/netdev.c +@@ -369,7 +369,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.15/net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch b/queue-6.15/net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch new file mode 100644 index 0000000000..2ee3691b64 --- /dev/null +++ b/queue-6.15/net-dsa-b53-fix-untagged-traffic-sent-via-cpu-tagged.patch @@ -0,0 +1,69 @@ +From 821d8128ec7d81290930a128497e76f1129625e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Florian Fainelli +Reviewed-by: Vladimir Oltean +Link: https://patch.msgid.link/20250602194914.1011890-1-jonas.gorski@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 862bdccb74397..dc2f4adac9bc9 100644 +--- a/drivers/net/dsa/b53/b53_common.c ++++ b/drivers/net/dsa/b53/b53_common.c +@@ -2034,9 +2034,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); + } + +@@ -2115,8 +2112,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.15/net-ethtool-don-t-check-if-rss-context-exists-in-cas.patch b/queue-6.15/net-ethtool-don-t-check-if-rss-context-exists-in-cas.patch new file mode 100644 index 0000000000..b2adb6153c --- /dev/null +++ b/queue-6.15/net-ethtool-don-t-check-if-rss-context-exists-in-cas.patch @@ -0,0 +1,59 @@ +From d06e9b3ec8d6b6a647fb091ed4b9fcf0bfeb98ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Jun 2025 10:19:57 +0300 +Subject: net: ethtool: Don't check if RSS context exists in case of context 0 + +From: Gal Pressman + +[ Upstream commit d78ebc772c7ceccf6e655ddb93099f49a1268af4 ] + +Context 0 (default context) always exists, there is no need to check +whether it exists or not when adding a flow steering rule. + +The existing check fails when creating a flow steering rule for context +0 as it is not stored in the rss_ctx xarray. + +For example: +$ ethtool --config-ntuple eth2 flow-type tcp4 dst-ip 194.237.147.23 dst-port 19983 context 0 loc 618 +rmgr: Cannot insert RX class rule: Invalid argument +Cannot insert classification rule + +An example usecase for this could be: +- A high-priority rule (loc 0) directing specific port traffic to + context 0. +- A low-priority rule (loc 1) directing all other TCP traffic to context + 1. + +This is a user-visible regression that was caught in our testing +environment, it was not reported by a user yet. + +Fixes: de7f7582dff2 ("net: ethtool: prevent flow steering to RSS contexts which don't exist") +Reviewed-by: Tariq Toukan +Reviewed-by: Nimrod Oren +Signed-off-by: Gal Pressman +Reviewed-by: Joe Damato +Reviewed-by: Edward Cree +Link: https://patch.msgid.link/20250612071958.1696361-2-gal@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index 8262cc10f98db..4b1badeebc741 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1001,7 +1001,8 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, + ethtool_get_flow_spec_ring(info.fs.ring_cookie)) + return -EINVAL; + +- if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) ++ if (info.rss_context && ++ !xa_load(&dev->ethtool->rss_ctx, info.rss_context)) + return -EINVAL; + } + +-- +2.39.5 + diff --git a/queue-6.15/net-fix-toctou-issue-in-sk_is_readable.patch b/queue-6.15/net-fix-toctou-issue-in-sk_is_readable.patch new file mode 100644 index 0000000000..b382be2c4b --- /dev/null +++ b/queue-6.15/net-fix-toctou-issue-in-sk_is_readable.patch @@ -0,0 +1,52 @@ +From 61e451846dd107f85bf3985502957112ea8791b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 19:08:03 +0200 +Subject: net: Fix TOCTOU issue in sk_is_readable() + +From: Michal Luczaj + +[ 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 +Signed-off-by: Michal Luczaj +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20250609-skisreadable-toctou-v1-1-d0dfb2d62c37@rbox.co +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 694f954258d43..99470c6d24de8 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -2978,8 +2978,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.15/net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch b/queue-6.15/net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch new file mode 100644 index 0000000000..fcd0d36247 --- /dev/null +++ b/queue-6.15/net-mdiobus-fix-potential-out-of-bounds-clause-45-re.patch @@ -0,0 +1,59 @@ +From ca56742d8cf1bdcfdc2029b023f2da3d12acb89f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: Wenjing Shan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 adb17ec937151..909b4d53fdacd 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -999,6 +999,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 +@@ -1030,6 +1033,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.15/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch b/queue-6.15/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch new file mode 100644 index 0000000000..da680d88b8 --- /dev/null +++ b/queue-6.15/net-mdiobus-fix-potential-out-of-bounds-read-write-a.patch @@ -0,0 +1,58 @@ +From f1a7a35e30a8d8341d96e6d6823844954c26f90a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 17:31:46 +0200 +Subject: net/mdiobus: Fix potential out-of-bounds read/write access + +From: Jakub Raczynski + +[ 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 +Reported-by: Wenjing Shan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 ede596c1a69d1..adb17ec937151 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -903,6 +903,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 +@@ -932,6 +935,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.15/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch b/queue-6.15/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch new file mode 100644 index 0000000000..0110db8484 --- /dev/null +++ b/queue-6.15/net-mlx5-ensure-fw-pages-are-always-allocated-on-sam.patch @@ -0,0 +1,43 @@ +From 86dfa264539d2ec7d5ed5d84cf1ecdc15f21aec2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:06 +0300 +Subject: net/mlx5: Ensure fw pages are always allocated on same NUMA + +From: Moshe Shemesh + +[ 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 +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-2-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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.15/net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch b/queue-6.15/net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch new file mode 100644 index 0000000000..83ef6e08ab --- /dev/null +++ b/queue-6.15/net-mlx5-fix-ecvf-vports-unload-on-shutdown-flow.patch @@ -0,0 +1,106 @@ +From 3ce96948524fc338e27e29a51a3befc3bfb87cd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:07 +0300 +Subject: net/mlx5: Fix ECVF vports unload on shutdown flow + +From: Amir Tzin + +[ 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 +Reviewed-by: Moshe Shemesh +Signed-off-by: Amir Tzin +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-3-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../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 7fb8a3381f849..4917d185d0c35 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.15/net-mlx5-fix-return-value-when-searching-for-existin.patch b/queue-6.15/net-mlx5-fix-return-value-when-searching-for-existin.patch new file mode 100644 index 0000000000..1b172044f3 --- /dev/null +++ b/queue-6.15/net-mlx5-fix-return-value-when-searching-for-existin.patch @@ -0,0 +1,61 @@ +From 3e95678b1e4b778c25f77d317dcf907fd9953a5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:08 +0300 +Subject: net/mlx5: Fix return value when searching for existing flow group + +From: Patrisious Haddad + +[ 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 +Signed-off-by: Roi Dayan +Signed-off-by: Patrisious Haddad +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-4-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 6163bc98d94a9..445301ea70426 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +@@ -2207,6 +2207,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; +@@ -2271,6 +2272,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; + } +@@ -2292,7 +2294,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.15/net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch b/queue-6.15/net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch new file mode 100644 index 0000000000..951b4aa268 --- /dev/null +++ b/queue-6.15/net-mlx5-hws-fix-missing-ip_version-handling-in-defi.patch @@ -0,0 +1,38 @@ +From f45a768607e3f7e4ca3c177dd8fa5c28f3f4ecaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:10 +0300 +Subject: net/mlx5: HWS, fix missing ip_version handling in definer + +From: Yevgeny Kliteynik + +[ 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 +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-6-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c +index c8cc0c8115f53..293459458cc5f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c +@@ -559,6 +559,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.15/net-mlx5-hws-make-sure-the-uplink-is-the-last-destin.patch b/queue-6.15/net-mlx5-hws-make-sure-the-uplink-is-the-last-destin.patch new file mode 100644 index 0000000000..ab7052ba8b --- /dev/null +++ b/queue-6.15/net-mlx5-hws-make-sure-the-uplink-is-the-last-destin.patch @@ -0,0 +1,98 @@ +From f08c7bd13b446dbb0d55d3ebeecf669dc11f5a1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:11 +0300 +Subject: net/mlx5: HWS, make sure the uplink is the last destination + +From: Vlad Dogaru + +[ Upstream commit b8335829518ec5988294280e37d735799209d70d ] + +When there are more than one destinations, we create a FW flow +table and provide it with all the destinations. FW requires to +have wire as the last destination in the list (if it exists), +otherwise the operation fails with FW syndrome. + +This patch fixes the destination array action creation: if it +contains a wire destination, it is moved to the end. + +Fixes: 504e536d9010 ("net/mlx5: HWS, added actions handling") +Signed-off-by: Vlad Dogaru +Reviewed-by: Yevgeny Kliteynik +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-7-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../mellanox/mlx5/core/steering/hws/action.c | 14 +++++++------- + .../mellanox/mlx5/core/steering/hws/fs_hws.c | 3 +++ + .../mellanox/mlx5/core/steering/hws/mlx5hws.h | 1 + + 3 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c +index b5332c54d4fb0..17b8a3beb1173 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c +@@ -1361,8 +1361,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, + struct mlx5hws_cmd_set_fte_attr fte_attr = {0}; + struct mlx5hws_cmd_forward_tbl *fw_island; + struct mlx5hws_action *action; +- u32 i /*, packet_reformat_id*/; +- int ret; ++ int ret, last_dest_idx = -1; ++ u32 i; + + if (num_dest <= 1) { + mlx5hws_err(ctx, "Action must have multiple dests\n"); +@@ -1392,11 +1392,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, + dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id; + fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + fte_attr.ignore_flow_level = ignore_flow_level; +- /* ToDo: In SW steering we have a handling of 'go to WIRE' +- * destination here by upper layer setting 'is_wire_ft' flag +- * if the destination is wire. +- * This is because uplink should be last dest in the list. +- */ ++ if (dests[i].is_wire_ft) ++ last_dest_idx = i; + break; + case MLX5HWS_ACTION_TYP_VPORT: + dest_list[i].destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT; +@@ -1420,6 +1417,9 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, + } + } + ++ if (last_dest_idx != -1) ++ swap(dest_list[last_dest_idx], dest_list[num_dest - 1]); ++ + fte_attr.dests_num = num_dest; + fte_attr.dests = dest_list; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c +index 1b787cd66e6fd..29c5e00af1aa0 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c +@@ -966,6 +966,9 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns, + switch (attr->type) { + case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: + dest_action = mlx5_fs_get_dest_action_ft(fs_ctx, dst); ++ if (dst->dest_attr.ft->flags & ++ MLX5_FLOW_TABLE_UPLINK_VPORT) ++ dest_actions[num_dest_actions].is_wire_ft = true; + break; + case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: + dest_action = mlx5_fs_get_dest_action_table_num(fs_ctx, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h +index 8ed8a715a2eb2..173f7ed1c17c3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h +@@ -211,6 +211,7 @@ struct mlx5hws_action_dest_attr { + struct mlx5hws_action *dest; + /* Optional reformat action */ + struct mlx5hws_action *reformat; ++ bool is_wire_ft; + }; + + /** +-- +2.39.5 + diff --git a/queue-6.15/net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch b/queue-6.15/net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch new file mode 100644 index 0000000000..078203d0c3 --- /dev/null +++ b/queue-6.15/net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch @@ -0,0 +1,79 @@ +From d70c5870a0c1d5e753b8056026b4cf70d5d24ec6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:13 +0300 +Subject: net/mlx5e: Fix leak of Geneve TLV option object + +From: Jianbo Liu + +[ 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 +Reviewed-by: Tariq Toukan +Reviewed-by: Alex Lazar +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-9-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 f1d908f611349..fef418e1ed1a0 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.15/net-mlx5e-fix-number-of-lanes-to-unknown-when-using-.patch b/queue-6.15/net-mlx5e-fix-number-of-lanes-to-unknown-when-using-.patch new file mode 100644 index 0000000000..8cc302b129 --- /dev/null +++ b/queue-6.15/net-mlx5e-fix-number-of-lanes-to-unknown-when-using-.patch @@ -0,0 +1,62 @@ +From c57883a21259f372fbe3668140e43d76d051d971 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 18:15:14 +0300 +Subject: net/mlx5e: Fix number of lanes to UNKNOWN when using data_rate_oper + +From: Shahar Shitrit + +[ Upstream commit 875d7c160d60616ff06dedb70470ad199661efe7 ] + +When the link is up, either eth_proto_oper or ext_eth_proto_oper +typically reports the active link protocol, from which both speed +and number of lanes can be retrieved. However, in certain cases, +such as when a NIC is connected via a non-standard cable, the +firmware may not report the protocol. + +In such scenarios, the speed can still be obtained from the +data_rate_oper field in PTYS register. Since data_rate_oper +provides only speed information and lacks lane details, it is +incorrect to derive the number of lanes from it. + +This patch corrects the behavior by setting the number of lanes to +UNKNOWN instead of incorrectly using MAX_LANES when relying on +data_rate_oper. + +Fixes: 7e959797f021 ("net/mlx5e: Enable lanes configuration when auto-negotiation is off") +Signed-off-by: Shahar Shitrit +Reviewed-by: Tariq Toukan +Signed-off-by: Mark Bloch +Link: https://patch.msgid.link/20250610151514.1094735-10-mbloch@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index fdf9e9bb99ace..6253ea4e99a44 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -43,7 +43,6 @@ + #include "en/fs_ethtool.h" + + #define LANES_UNKNOWN 0 +-#define MAX_LANES 8 + + void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, + struct ethtool_drvinfo *drvinfo) +@@ -1098,10 +1097,8 @@ static void get_link_properties(struct net_device *netdev, + speed = info->speed; + lanes = info->lanes; + duplex = DUPLEX_FULL; +- } else if (data_rate_oper) { ++ } else if (data_rate_oper) + speed = 100 * data_rate_oper; +- lanes = MAX_LANES; +- } + + out: + link_ksettings->base.duplex = duplex; +-- +2.39.5 + diff --git a/queue-6.15/net-phy-phy_caps-don-t-skip-better-duplex-macth-on-n.patch b/queue-6.15/net-phy-phy_caps-don-t-skip-better-duplex-macth-on-n.patch new file mode 100644 index 0000000000..9b68111000 --- /dev/null +++ b/queue-6.15/net-phy-phy_caps-don-t-skip-better-duplex-macth-on-n.patch @@ -0,0 +1,81 @@ +From 06813c9b394142c21266523af60fd1979b9ab8b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Jun 2025 11:43:20 +0200 +Subject: net: phy: phy_caps: Don't skip better duplex macth on non-exact match + +From: Maxime Chevallier + +[ Upstream commit d4e6cb324dcc952618fec6b25aa3fc7bfc2750b4 ] + +When performing a non-exact phy_caps lookup, we are looking for a +supported mode that matches as closely as possible the passed speed/duplex. + +Blamed patch broke that logic by returning a match too early in case +the caller asks for half-duplex, as a full-duplex linkmode may match +first, and returned as a non-exact match without even trying to mach on +half-duplex modes. + +Reported-by: Jijie Shao +Closes: https://lore.kernel.org/netdev/20250603102500.4ec743cf@fedora/T/#m22ed60ca635c67dc7d9cbb47e8995b2beb5c1576 +Tested-by: Jijie Shao +Reviewed-by: Larysa Zaremba +Fixes: fc81e257d19f ("net: phy: phy_caps: Allow looking-up link caps based on speed and duplex") +Signed-off-by: Maxime Chevallier +Link: https://patch.msgid.link/20250606094321.483602-1-maxime.chevallier@bootlin.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/phy_caps.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c +index 7033216897264..38417e2886118 100644 +--- a/drivers/net/phy/phy_caps.c ++++ b/drivers/net/phy/phy_caps.c +@@ -188,6 +188,9 @@ phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only) + * When @exact is not set, we return either an exact match, or matching capabilities + * at lower speed, or the lowest matching speed, or NULL. + * ++ * Non-exact matches will try to return an exact speed and duplex match, but may ++ * return matching capabilities with same speed but a different duplex. ++ * + * Returns: a matched link_capabilities according to the above process, NULL + * otherwise. + */ +@@ -195,7 +198,7 @@ const struct link_capabilities * + phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, + bool exact) + { +- const struct link_capabilities *lcap, *last = NULL; ++ const struct link_capabilities *lcap, *match = NULL, *last = NULL; + + for_each_link_caps_desc_speed(lcap) { + if (linkmode_intersects(lcap->linkmodes, supported)) { +@@ -204,16 +207,19 @@ phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, + if (lcap->speed == speed && lcap->duplex == duplex) { + return lcap; + } else if (!exact) { +- if (lcap->speed <= speed) +- return lcap; ++ if (!match && lcap->speed <= speed) ++ match = lcap; ++ ++ if (lcap->speed < speed) ++ break; + } + } + } + +- if (!exact) +- return last; ++ if (!match && !exact) ++ match = last; + +- return NULL; ++ return match; + } + EXPORT_SYMBOL_GPL(phy_caps_lookup); + +-- +2.39.5 + diff --git a/queue-6.15/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch b/queue-6.15/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch new file mode 100644 index 0000000000..24a8a20392 --- /dev/null +++ b/queue-6.15/net_sched-ets-fix-a-race-in-ets_qdisc_change.patch @@ -0,0 +1,58 @@ +From aa0aa1e57d1258fb267f7785082b87d7c5fb27c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:14 +0000 +Subject: net_sched: ets: fix a race in ets_qdisc_change() + +From: Eric Dumazet + +[ 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 +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250611111515.1983366-5-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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.15/net_sched-prio-fix-a-race-in-prio_tune.patch b/queue-6.15/net_sched-prio-fix-a-race-in-prio_tune.patch new file mode 100644 index 0000000000..17fcbb2baa --- /dev/null +++ b/queue-6.15/net_sched-prio-fix-a-race-in-prio_tune.patch @@ -0,0 +1,58 @@ +From bd213ea983712d7cd3dd58a911ea19b7f9f92e38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:11 +0000 +Subject: net_sched: prio: fix a race in prio_tune() + +From: Eric Dumazet + +[ 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 +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250611111515.1983366-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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.15/net_sched-red-fix-a-race-in-__red_change.patch b/queue-6.15/net_sched-red-fix-a-race-in-__red_change.patch new file mode 100644 index 0000000000..fd79147df3 --- /dev/null +++ b/queue-6.15/net_sched-red-fix-a-race-in-__red_change.patch @@ -0,0 +1,58 @@ +From 527b168132ad185e7aa825f79a7557d68798ef92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:12 +0000 +Subject: net_sched: red: fix a race in __red_change() + +From: Eric Dumazet + +[ 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 +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20250611111515.1983366-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 1ba3e0bba54f0..4696c893cf553 100644 +--- a/net/sched/sch_red.c ++++ b/net/sched/sch_red.c +@@ -285,7 +285,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.15/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch b/queue-6.15/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch new file mode 100644 index 0000000000..c9f33ebc2d --- /dev/null +++ b/queue-6.15/net_sched-sch_sfq-fix-a-potential-crash-on-gso_skb-h.patch @@ -0,0 +1,70 @@ +From a26a7a1d975ff3d1dc7c214469e212980a64c54a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/netdev/9da42688-bfaa-4364-8797-e9271f3bdaef@hetzner-cloud.de/ +Signed-off-by: Eric Dumazet +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250606165127.3629486-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 b912ad99aa15d..77fa02f2bfcd5 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.15/net_sched-tbf-fix-a-race-in-tbf_change.patch b/queue-6.15/net_sched-tbf-fix-a-race-in-tbf_change.patch new file mode 100644 index 0000000000..73d7ae4cee --- /dev/null +++ b/queue-6.15/net_sched-tbf-fix-a-race-in-tbf_change.patch @@ -0,0 +1,59 @@ +From 0eb2369530a79448b2de027cf96f813a2a2f9786 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 Jun 2025 11:15:13 +0000 +Subject: net_sched: tbf: fix a race in tbf_change() + +From: Eric Dumazet + +[ 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 +Suggested-by: Gerrard Tai +Signed-off-by: Eric Dumazet +Cc: Zhengchao Shao +Link: https://patch.msgid.link/20250611111515.1983366-4-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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.15/netconsole-fix-appending-sysdata-when-sysdata_fields.patch b/queue-6.15/netconsole-fix-appending-sysdata-when-sysdata_fields.patch new file mode 100644 index 0000000000..c56e4cefdd --- /dev/null +++ b/queue-6.15/netconsole-fix-appending-sysdata-when-sysdata_fields.patch @@ -0,0 +1,58 @@ +From 13e74c218d39c61b2caaf92bb2cbf2259507a290 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 Jun 2025 11:24:20 -0700 +Subject: netconsole: fix appending sysdata when sysdata_fields == + SYSDATA_RELEASE + +From: Gustavo Luiz Duarte + +[ Upstream commit c85bf1975108d2e2431c11d1cb7e95aca587dfbe ] + +Before appending sysdata, prepare_extradata() checks if any feature is +enabled in sysdata_fields (and exits early if none is enabled). + +When SYSDATA_RELEASE was introduced, we missed adding it to the list of +features being checked against sysdata_fields in prepare_extradata(). +The result was that, if only SYSDATA_RELEASE is enabled in +sysdata_fields, we incorreclty exit early and fail to append the +release. + +Instead of checking specific bits in sysdata_fields, check if +sysdata_fields has ALL bit zeroed and exit early if true. This fixes +case when only SYSDATA_RELEASE enabled and makes the code more general / +less error prone in future feature implementation. + +Signed-off-by: Gustavo Luiz Duarte +Reviewed-by: Breno Leitao +Fixes: cfcc9239e78a ("netconsole: append release to sysdata") +Link: https://patch.msgid.link/20250609-netconsole-fix-v1-1-17543611ae31@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/netconsole.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c +index 4289ccd3e41bf..176935a8645ff 100644 +--- a/drivers/net/netconsole.c ++++ b/drivers/net/netconsole.c +@@ -1252,7 +1252,6 @@ static int sysdata_append_release(struct netconsole_target *nt, int offset) + */ + static int prepare_extradata(struct netconsole_target *nt) + { +- u32 fields = SYSDATA_CPU_NR | SYSDATA_TASKNAME; + int extradata_len; + + /* userdata was appended when configfs write helper was called +@@ -1260,7 +1259,7 @@ static int prepare_extradata(struct netconsole_target *nt) + */ + extradata_len = nt->userdata_length; + +- if (!(nt->sysdata_fields & fields)) ++ if (!nt->sysdata_fields) + goto out; + + if (nt->sysdata_fields & SYSDATA_CPU_NR) +-- +2.39.5 + diff --git a/queue-6.15/pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch b/queue-6.15/pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch new file mode 100644 index 0000000000..5af08ed1aa --- /dev/null +++ b/queue-6.15/pinctrl-qcom-pinctrl-qcm2290-add-missing-pins.patch @@ -0,0 +1,57 @@ +From 29ff291dbea1458765394b4f104c5599854409db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 May 2025 12:14:37 +0200 +Subject: pinctrl: qcom: pinctrl-qcm2290: Add missing pins + +From: Wojciech Slenska + +[ Upstream commit 315345610faee8a0568b522dba9e35067d1732ab ] + +Added the missing pins to the qcm2290_pins table. + +Signed-off-by: Wojciech Slenska +Fixes: 48e049ef1238 ("pinctrl: qcom: Add QCM2290 pinctrl driver") +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/20250523101437.59092-1-wojciech.slenska@gmail.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + 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 ba699eac9ee8b..20e9bccda4cd6 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.15/pinctrl-sunxi-dt-consider-pin-base-when-calculating-.patch b/queue-6.15/pinctrl-sunxi-dt-consider-pin-base-when-calculating-.patch new file mode 100644 index 0000000000..0725c0b022 --- /dev/null +++ b/queue-6.15/pinctrl-sunxi-dt-consider-pin-base-when-calculating-.patch @@ -0,0 +1,70 @@ +From 2fc7b1391d969d2afdfb5789f8d3d0aafd5435e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Jun 2025 21:52:03 +0800 +Subject: pinctrl: sunxi: dt: Consider pin base when calculating bank number + from pin + +From: Chen-Yu Tsai + +[ Upstream commit 5558f27a58459a4038ebb23bcb5bd40c1e345c57 ] + +In prepare_function_table() when the pinctrl function table IRQ entries +are generated, the pin bank is calculated from the absolute pin number; +however the IRQ bank mux array is indexed from the first pin bank of the +controller. For R_PIO controllers, this means the absolute pin bank is +way off from the relative pin bank used for array indexing. + +Correct this by taking into account the pin base of the controller. + +Fixes: f5e2cd34b12f ("pinctrl: sunxi: allow reading mux values from DT") +Signed-off-by: Chen-Yu Tsai +Link: https://lore.kernel.org/20250607135203.2085226-1-wens@kernel.org +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c +index 1833078f68776..4e34b0cd3b73a 100644 +--- a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c ++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c +@@ -143,7 +143,7 @@ static struct sunxi_desc_pin *init_pins_table(struct device *dev, + */ + static int prepare_function_table(struct device *dev, struct device_node *pnode, + struct sunxi_desc_pin *pins, int npins, +- const u8 *irq_bank_muxes) ++ unsigned pin_base, const u8 *irq_bank_muxes) + { + struct device_node *node; + struct property *prop; +@@ -166,7 +166,7 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode, + */ + for (i = 0; i < npins; i++) { + struct sunxi_desc_pin *pin = &pins[i]; +- int bank = pin->pin.number / PINS_PER_BANK; ++ int bank = (pin->pin.number - pin_base) / PINS_PER_BANK; + + if (irq_bank_muxes[bank]) { + pin->variant++; +@@ -211,7 +211,7 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode, + last_bank = 0; + for (i = 0; i < npins; i++) { + struct sunxi_desc_pin *pin = &pins[i]; +- int bank = pin->pin.number / PINS_PER_BANK; ++ int bank = (pin->pin.number - pin_base) / PINS_PER_BANK; + int lastfunc = pin->variant + 1; + int irq_mux = irq_bank_muxes[bank]; + +@@ -353,7 +353,7 @@ int sunxi_pinctrl_dt_table_init(struct platform_device *pdev, + return PTR_ERR(pins); + + ret = prepare_function_table(&pdev->dev, pnode, pins, desc->npins, +- irq_bank_muxes); ++ desc->pin_base, irq_bank_muxes); + if (ret) + return ret; + +-- +2.39.5 + diff --git a/queue-6.15/powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch b/queue-6.15/powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch new file mode 100644 index 0000000000..fa5ece1645 --- /dev/null +++ b/queue-6.15/powerpc-powernv-memtrace-fix-out-of-bounds-issue-in-.patch @@ -0,0 +1,48 @@ +From feb54016669f3cbf15fe6a27b8de6e1519eec425 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Fixes: 08a022ad3dfa ("powerpc/powernv/memtrace: Allow mmaping trace buffers") +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250610021227.361980-1-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + 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 4ac9808e55a44..2ea30b3433541 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.15/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch b/queue-6.15/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch new file mode 100644 index 0000000000..6bfff984e6 --- /dev/null +++ b/queue-6.15/powerpc-vas-return-einval-if-the-offset-is-non-zero-.patch @@ -0,0 +1,52 @@ +From 30a0af4997404f24f6e4daa831a9bd8d39838787 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Jonathan Greental +Reported-by: Jonathan Greental +Fixes: dda44eb29c23 ("powerpc/vas: Add VAS user space API") +Signed-off-by: Haren Myneni +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250610021227.361980-2-maddy@linux.ibm.com +Signed-off-by: Sasha Levin +--- + 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.15/ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch b/queue-6.15/ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch new file mode 100644 index 0000000000..633d8abc6a --- /dev/null +++ b/queue-6.15/ptp-remove-ptp-n_vclocks-check-logic-in-ptp_vclock_i.patch @@ -0,0 +1,90 @@ +From 2c70b84d961e993179118c88fe3c534206c6c4df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Richard Cochran +Link: https://patch.msgid.link/20250520160717.7350-1-aha310510@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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.15/regulator-max20086-fix-refcount-leak-in-max20086_par.patch b/queue-6.15/regulator-max20086-fix-refcount-leak-in-max20086_par.patch new file mode 100644 index 0000000000..6ae944ad38 --- /dev/null +++ b/queue-6.15/regulator-max20086-fix-refcount-leak-in-max20086_par.patch @@ -0,0 +1,61 @@ +From ff15dce06ef6152e2b2bf98b76590b41f38e9dad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 May 2025 08:44:14 +0300 +Subject: regulator: max20086: Fix refcount leak in + max20086_parse_regulators_dt() + +From: Dan Carpenter + +[ 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 +Link: https://patch.msgid.link/aDVRLqgJWMxYU03G@stanley.mountain +Reviewed-by: Laurent Pinchart +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + // Copyright (C) 2018 Avnet, Inc. + ++#include + #include + #include + #include +@@ -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.15/scsi-core-ufs-fix-a-hang-in-the-error-handler.patch b/queue-6.15/scsi-core-ufs-fix-a-hang-in-the-error-handler.patch new file mode 100644 index 0000000000..a2ab59fa8c --- /dev/null +++ b/queue-6.15/scsi-core-ufs-fix-a-hang-in-the-error-handler.patch @@ -0,0 +1,73 @@ +From 8e31fc493b7b1deeddfd84b2474316cf143d3602 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 May 2025 13:14:01 -0700 +Subject: scsi: core: ufs: Fix a hang in the error handler + +From: Sanjeev Yadav + +[ 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 +[ bvanassche: rewrote patch description ] +Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20250523201409.1676055-1-bvanassche@acm.org +Reviewed-by: Peter Wang +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 7735421e39918..04f769d907a44 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -6587,9 +6587,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.15/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch b/queue-6.15/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch new file mode 100644 index 0000000000..05aac56515 --- /dev/null +++ b/queue-6.15/scsi-iscsi-fix-incorrect-error-path-labels-for-flash.patch @@ -0,0 +1,99 @@ +From b1730cd977af4ae607afe002b028fbbd4eb11754 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 May 2025 12:29:35 -0700 +Subject: scsi: iscsi: Fix incorrect error path labels for flashnode operations + +From: Alok Tiwari + +[ 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 +Link: https://lore.kernel.org/r/20250530193012.3312911-1-alok.a.tiwari@oracle.com +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 0b8c91bf793fc..c75a806496d67 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -3499,7 +3499,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); +@@ -3509,7 +3509,6 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport, + else + err = -EIO; + +-put_host: + scsi_host_put(shost); + + exit_new_fnode: +@@ -3534,7 +3533,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; +@@ -3576,7 +3575,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; +@@ -3628,7 +3627,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; +@@ -3678,7 +3677,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 + diff --git a/queue-6.15/series b/queue-6.15/series index d1df0a6ae8..be9206b5e5 100644 --- a/queue-6.15/series +++ b/queue-6.15/series @@ -660,3 +660,65 @@ tools-power-turbostat-fix-amd-package-energy-reporti.patch pinctrl-samsung-refactor-drvdata-suspend-resume-call.patch pinctrl-samsung-add-dedicated-soc-eint-suspend-resum.patch pinctrl-samsung-add-gs101-specific-eint-suspend-resu.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-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-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 +wifi-ath12k-fix-uaf-in-ath12k_core_init.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 +accel-amdxdna-fix-incorrect-psp-firmware-size.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-vc4-fix-infinite-eprobe_defer-loop.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 +pinctrl-sunxi-dt-consider-pin-base-when-calculating-.patch +i40e-return-false-from-i40e_reset_vf-if-reset-is-in-.patch +i40e-retry-vflr-handling-if-there-is-ongoing-vf-rese.patch +iavf-fix-reset_task-for-early-reset-event.patch +ice-ptp-fix-crosstimestamp-reporting.patch +e1000-move-cancel_work_sync-to-avoid-deadlock.patch +acpi-cppc-fix-null-pointer-dereference-when-nosmp-is.patch +net-fix-toctou-issue-in-sk_is_readable.patch +netconsole-fix-appending-sysdata-when-sysdata_fields.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-mlx5-hws-make-sure-the-uplink-is-the-last-destin.patch +net-mlx5e-fix-leak-of-geneve-tlv-option-object.patch +net-mlx5e-fix-number-of-lanes-to-unknown-when-using-.patch +net-phy-phy_caps-don-t-skip-better-duplex-macth-on-n.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 +net-ethtool-don-t-check-if-rss-context-exists-in-cas.patch +drm-xe-lrc-use-a-temporary-buffer-for-wa-bb.patch diff --git a/queue-6.15/spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch b/queue-6.15/spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch new file mode 100644 index 0000000000..209bf7efe1 --- /dev/null +++ b/queue-6.15/spi-omap2-mcspi-disable-multi-mode-when-cs-should-be.patch @@ -0,0 +1,55 @@ +From 6664eaeb62a828552924cd33fa52393a572fd6c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/20250606-cs_change_fix-v1-1-27191a98a2e5@non.se.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 29c616e2c408c..e834fb42fd4ba 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.15/spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch b/queue-6.15/spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch new file mode 100644 index 0000000000..026f24cc49 --- /dev/null +++ b/queue-6.15/spi-omap2-mcspi-disable-multi-mode-when-the-previous.patch @@ -0,0 +1,84 @@ +From 3c313c84804c2d67a8b43e4d228f3e4ea5b1d31c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://patch.msgid.link/20250606-cs_change_fix-v1-2-27191a98a2e5@non.se.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 e834fb42fd4ba..70bb74b3bd9c3 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.15/wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch b/queue-6.15/wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch new file mode 100644 index 0000000000..d8f38ac67c --- /dev/null +++ b/queue-6.15/wifi-ath11k-avoid-burning-cpu-in-ath11k_debugfs_fw_s.patch @@ -0,0 +1,231 @@ +From de3c721d2cb7cca28c6b420fa35a168fb1e58bbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 16:24:42 +0800 +Subject: wifi: ath11k: avoid burning CPU in ath11k_debugfs_fw_stats_request() + +From: Baochen Qiang + +[ 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 +Closes: https://lore.kernel.org/all/7324ac7a-8b7a-42a5-aa19-de52138ff638@app.fastmail.com/ # [1] +Signed-off-by: Baochen Qiang +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250220082448.31039-2-quic_bqiang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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 8d08dd47bde9c..6c346a8df2df1 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -951,6 +951,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 1a3d0de4afde8..6abbb29034f07 100644 +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -783,7 +783,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 +@@ -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 97816916abac9..8a018c0190c8a 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9384,11 +9384,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 d7f852bebf4aa..27cb0bb06b93c 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -8189,7 +8189,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.15/wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch b/queue-6.15/wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch new file mode 100644 index 0000000000..cacea78ef2 --- /dev/null +++ b/queue-6.15/wifi-ath11k-don-t-use-static-variables-in-ath11k_deb.patch @@ -0,0 +1,129 @@ +From a0be0d0b9884271a3c83889e8cda8c7212118e9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Kalle Valo +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250220082448.31039-3-quic_bqiang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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 6abbb29034f07..529aca4f40621 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 8a018c0190c8a..d97273b205d9f 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9385,6 +9385,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.15/wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch b/queue-6.15/wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch new file mode 100644 index 0000000000..96484f007c --- /dev/null +++ b/queue-6.15/wifi-ath11k-don-t-wait-when-there-is-no-vdev-started.patch @@ -0,0 +1,76 @@ +From 317bd21e1f63223e5f05178474523224cef9b048 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 16:24:44 +0800 +Subject: wifi: ath11k: don't wait when there is no vdev started + +From: Baochen Qiang + +[ 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 +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250220082448.31039-4-quic_bqiang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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.15/wifi-ath11k-move-some-firmware-stats-related-functio.patch b/queue-6.15/wifi-ath11k-move-some-firmware-stats-related-functio.patch new file mode 100644 index 0000000000..26a061f9e3 --- /dev/null +++ b/queue-6.15/wifi-ath11k-move-some-firmware-stats-related-functio.patch @@ -0,0 +1,448 @@ +From 495480938264f8357075868bdb56ade32bec3553 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 16:24:45 +0800 +Subject: wifi: ath11k: move some firmware stats related functions outside of + debugfs + +From: Baochen Qiang + +[ 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 +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20250220082448.31039-5-quic_bqiang@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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 d97273b205d9f..4763b271309aa 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8991,6 +8991,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, +@@ -9028,8 +9108,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); + } + +@@ -9037,8 +9117,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 27cb0bb06b93c..98811726d33bf 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -8158,6 +8158,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; + +@@ -8184,7 +8189,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) { +@@ -8193,9 +8199,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.15/wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch b/queue-6.15/wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch new file mode 100644 index 0000000000..653b291f43 --- /dev/null +++ b/queue-6.15/wifi-ath11k-validate-ath11k_crypto_mode-on-top-of-at.patch @@ -0,0 +1,80 @@ +From 65855a34f5e02521f25e7306a27abb33b1cfdb8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: kernel test robot +Reported-by: Dan Carpenter +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 +Link: https://patch.msgid.link/20250522200519.16858-1-rodrigo.gobbi.7@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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 6c346a8df2df1..22eb1b0377ffe 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1947,6 +1947,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); +@@ -1965,20 +1979,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.15/wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch b/queue-6.15/wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch new file mode 100644 index 0000000000..34994134f8 --- /dev/null +++ b/queue-6.15/wifi-ath12k-fix-gcc_gcc_pcie_hot_rst-definition-for-.patch @@ -0,0 +1,116 @@ +From fba244bacc8482b2f71fa675ab10799f884c83e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 May 2025 10:23:05 +0800 +Subject: wifi: ath12k: fix GCC_GCC_PCIE_HOT_RST definition for WCN7850 + +From: Baochen Qiang + +[ 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 +Reviewed-by: Vasanthakumar Thiagarajan +Reported-by: Parth Pancholi +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 +Link: https://patch.msgid.link/20250523-ath12k-wrong-global-reset-addr-v1-1-3b06eb556196@quicinc.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + 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 4c9d6c42fbb92..1bfb11bae7add 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.c ++++ b/drivers/net/wireless/ath/ath12k/hw.c +@@ -690,6 +690,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 = { +@@ -779,6 +781,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 = { +@@ -864,6 +868,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 273f4bc260bfe..2e7d302ace679 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -292,10 +292,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.15/wifi-ath12k-fix-uaf-in-ath12k_core_init.patch b/queue-6.15/wifi-ath12k-fix-uaf-in-ath12k_core_init.patch new file mode 100644 index 0000000000..f9be070106 --- /dev/null +++ b/queue-6.15/wifi-ath12k-fix-uaf-in-ath12k_core_init.patch @@ -0,0 +1,88 @@ +From 3a6a5cb5aa26b9ef64a89ca1ce1d578cc97db3f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Jun 2025 13:52:50 +0800 +Subject: wifi: ath12k: fix uaf in ath12k_core_init() + +From: Miaoqing Pan + +[ Upstream commit f3fe49dbddd73f0155a8935af47cb63693069dbe ] + +When the execution of ath12k_core_hw_group_assign() or +ath12k_core_hw_group_create() fails, the registered notifier chain is not +unregistered properly. Its memory is freed after rmmod, which may trigger +to a use-after-free (UAF) issue if there is a subsequent access to this +notifier chain. + +Fixes the issue by calling ath12k_core_panic_notifier_unregister() in +failure cases. + +Call trace: + notifier_chain_register+0x4c/0x1f0 (P) + atomic_notifier_chain_register+0x38/0x68 + ath12k_core_init+0x50/0x4e8 [ath12k] + ath12k_pci_probe+0x5f8/0xc28 [ath12k] + pci_device_probe+0xbc/0x1a8 + really_probe+0xc8/0x3a0 + __driver_probe_device+0x84/0x1b0 + driver_probe_device+0x44/0x130 + __driver_attach+0xcc/0x208 + bus_for_each_dev+0x84/0x100 + driver_attach+0x2c/0x40 + bus_add_driver+0x130/0x260 + driver_register+0x70/0x138 + __pci_register_driver+0x68/0x80 + ath12k_pci_init+0x30/0x68 [ath12k] + ath12k_init+0x28/0x78 [ath12k] + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 + +Fixes: 6f245ea0ec6c ("wifi: ath12k: introduce device group abstraction") +Signed-off-by: Miaoqing Pan +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20250604055250.1228501-1-miaoqing.pan@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c +index 770156347ffad..261f52b327e89 100644 +--- a/drivers/net/wireless/ath/ath12k/core.c ++++ b/drivers/net/wireless/ath/ath12k/core.c +@@ -1902,7 +1902,8 @@ int ath12k_core_init(struct ath12k_base *ab) + if (!ag) { + mutex_unlock(&ath12k_hw_group_mutex); + ath12k_warn(ab, "unable to get hw group\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto err_unregister_notifier; + } + + mutex_unlock(&ath12k_hw_group_mutex); +@@ -1917,7 +1918,7 @@ int ath12k_core_init(struct ath12k_base *ab) + if (ret) { + mutex_unlock(&ag->mutex); + ath12k_warn(ab, "unable to create hw group\n"); +- goto err; ++ goto err_destroy_hw_group; + } + } + +@@ -1925,9 +1926,12 @@ int ath12k_core_init(struct ath12k_base *ab) + + return 0; + +-err: ++err_destroy_hw_group: + ath12k_core_hw_group_destroy(ab->ag); + ath12k_core_hw_group_unassign(ab); ++err_unregister_notifier: ++ ath12k_core_panic_notifier_unregister(ab); ++ + return ret; + } + +-- +2.39.5 + diff --git a/queue-6.15/wifi-ath12k-refactor-ath12k_hw_regs-structure.patch b/queue-6.15/wifi-ath12k-refactor-ath12k_hw_regs-structure.patch new file mode 100644 index 0000000000..01d60b0209 --- /dev/null +++ b/queue-6.15/wifi-ath12k-refactor-ath12k_hw_regs-structure.patch @@ -0,0 +1,405 @@ +From 4c27b8a451c409657d7f2740006d483cb2fe7685 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Mar 2025 16:22:40 +0530 +Subject: wifi: ath12k: refactor ath12k_hw_regs structure + +From: P Praneesh + +[ 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 +Co-developed-by: Balamurugan S +Signed-off-by: Balamurugan S +Reviewed-by: Vasanthakumar Thiagarajan +Signed-off-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20250321-ath12k-ahb-v12-3-bb389ed76ae5@quicinc.com +Signed-off-by: Jeff Johnson +Stable-dep-of: 7588a893cde5 ("wifi: ath12k: fix GCC_GCC_PCIE_HOT_RST definition for WCN7850") +Signed-off-by: Sasha Levin +--- + 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 178c242a840e3..d00869a33fea0 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 + #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 3156563c77e5b..c8205672cd3dd 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 a106ebed7870d..4c9d6c42fbb92 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 +@@ -619,6 +619,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, +@@ -681,6 +684,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 = { +@@ -695,6 +704,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, +@@ -761,6 +773,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 = { +@@ -775,6 +793,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, +@@ -837,6 +858,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 +