* [PATCH v3 3/8] PCI/ASPM: Transition the device to D0 (if required) when enabling ASPM link states
From: Manivannan Sadhasivam @ 2026-07-08 14:30 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Nirmal Patel, Jonathan Derrick, Jeff Johnson
Cc: linux-pci, linux-kernel, linux-arm-msm, linux-wireless, ath12k,
ath11k, ath10k, Krishna Chaitanya Chundru, Qiang Yu, mani,
Ilpo Järvinen, Manivannan Sadhasivam
In-Reply-To: <20260708-pci-aspm-fix-v3-0-6bd72451746e@kernel.org>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Per PCIe spec r6.0, sec 5.5.4:
"If setting either or both of the enable bits for PCI-PM L1 PM Substates,
both ports must be configured as described in this section while in D0."
Currently, the callers of pci_enable_link_state_locked() (vmd, pcie-qcom)
transition the device to D0 themselves before enabling the link state. But
this is easy to get wrong and has to be duplicated by every caller.
Move the D0 transition into the shared __pci_enable_link_state() helper so
that all three APIs pci_enable_link_state(), pci_enable_link_state_locked()
and pci_force_enable_link_state() perform it, and only when the PCI-PM L1
PM Substates are getting enabled.
Now that the helper handles the transition, drop the redundant D0 transition
from the vmd and pcie-qcom callers.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/pci/controller/dwc/pcie-qcom.c | 5 -----
drivers/pci/controller/vmd.c | 5 -----
drivers/pci/pcie/aspm.c | 23 +++++++++++++++++------
3 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index d8eb52857f69..45f4caeb0814 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1085,11 +1085,6 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata)
{
- /*
- * Downstream devices need to be in D0 state before enabling PCI PM
- * substates.
- */
- pci_set_power_state_locked(pdev, PCI_D0);
pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
return 0;
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index d4ae250d4bc6..20597d2cf66e 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -762,11 +762,6 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
pci_info(pdev, "VMD: Default LTR value set by driver\n");
out_state_change:
- /*
- * Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
- * PCIe r6.0, sec 5.5.4.
- */
- pci_set_power_state_locked(pdev, PCI_D0);
pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
return 0;
}
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index c04fb71de91c..6d6862fd2ebb 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1524,6 +1524,17 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked,
return -EPERM;
}
+ /*
+ * Ensure the device is in D0 before enabling PCI-PM L1 PM Substates, per
+ * PCIe r6.0, sec 5.5.4.
+ */
+ if (state & PCIE_LINK_STATE_L1_SS_PCIPM) {
+ if (locked)
+ pci_set_power_state_locked(pdev, PCI_D0);
+ else
+ pci_set_power_state(pdev, PCI_D0);
+ }
+
if (!locked)
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
@@ -1550,8 +1561,8 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked,
* touch the LNKCTL register. Also note that this does not enable states
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
*
- * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
- * PCIe r6.0, sec 5.5.4.
+ * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates
+ * are getting enabled.
*
* @pdev: PCI device
* @state: Mask of ASPM link states to enable
@@ -1569,8 +1580,8 @@ EXPORT_SYMBOL(pci_enable_link_state);
* can't touch the LNKCTL register. Also note that this does not enable states
* disabled by pci_disable_link_state(). Return 0 or a negative errno.
*
- * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
- * PCIe r6.0, sec 5.5.4.
+ * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates
+ * are getting enabled.
*
* @pdev: PCI device
* @state: Mask of ASPM link states to enable
@@ -1600,8 +1611,8 @@ EXPORT_SYMBOL(pci_enable_link_state_locked);
* Note that if the BIOS didn't grant ASPM control to the OS, this does nothing
* because we can't touch the LNKCTL register.
*
- * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
- * PCIe r6.0, sec 5.5.4.
+ * Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates
+ * are getting enabled.
*
* Return: 0 on success, a negative errno otherwise.
*/
--
2.43.0
^ permalink raw reply related
* [PATCH v3 2/8] PCI/ASPM: Add pci_force_enable_link_state() API
From: Manivannan Sadhasivam @ 2026-07-08 14:30 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Nirmal Patel, Jonathan Derrick, Jeff Johnson
Cc: linux-pci, linux-kernel, linux-arm-msm, linux-wireless, ath12k,
ath11k, ath10k, Krishna Chaitanya Chundru, Qiang Yu, mani,
Ilpo Järvinen, Manivannan Sadhasivam
In-Reply-To: <20260708-pci-aspm-fix-v3-0-6bd72451746e@kernel.org>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
pci_enable_link_state() and pci_enable_link_state_locked() APIs only enable
the ASPM states that were not previously disabled via
pci_disable_link_state*() API or blacklisted during init (e.g. the pre-1.1
device blacklist, which is only meant to be overridden with
'pcie_aspm=force'). This is an intentional behavior as these APIs must not
silently re-enable states that were deliberately disabled, since doing so
could enable ASPM on a link where it is known to be unsafe.
However, some drivers (e.g. the atheros WLAN drivers) save the currently
enabled ASPM states, disable all ASPM states before firmware download, and
then try to restore exactly the states that were enabled before. Restoring
those states requires re-enabling states that were just disabled via
pci_disable_link_state() API. But, this cannot be achieved using the
existing APIs.
Hence, add pci_force_enable_link_state() API for such callers. Unlike
pci_enable_link_state(), it re-enables the requested states even if they
were previously disabled via pci_disable_link_state() or disabled during
init. The caller is therefore responsible for only enabling states the
device actually supports, typically the ones previously reported by
pcie_aspm_enabled().
This API is implemented by adding a 'force' parameter to the shared
__pci_enable_link_state() helper. When 'force' is true, the requested
states are cleared from 'link->aspm_disable' before enabling.
Suggested-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/pci/pcie/aspm.c | 37 ++++++++++++++++++++++++++++++++++---
include/linux/pci.h | 3 +++
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 1c15a14718e8..c04fb71de91c 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1506,7 +1506,8 @@ int pci_disable_link_state(struct pci_dev *pdev, int state)
}
EXPORT_SYMBOL(pci_disable_link_state);
-static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
+static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked,
+ bool force)
{
struct pcie_link_state *link = pcie_aspm_get_link(pdev);
@@ -1527,6 +1528,10 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
link->aspm_default = pci_calc_aspm_enable_mask(state);
+
+ /* Force enable states that were previously disabled */
+ if (force)
+ link->aspm_disable &= ~link->aspm_default;
pcie_config_aspm_link(link, policy_to_aspm_state(link));
link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
@@ -1553,7 +1558,7 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
*/
int pci_enable_link_state(struct pci_dev *pdev, int state)
{
- return __pci_enable_link_state(pdev, state, false);
+ return __pci_enable_link_state(pdev, state, false, false);
}
EXPORT_SYMBOL(pci_enable_link_state);
@@ -1576,10 +1581,36 @@ int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
{
lockdep_assert_held_read(&pci_bus_sem);
- return __pci_enable_link_state(pdev, state, true);
+ return __pci_enable_link_state(pdev, state, true, false);
}
EXPORT_SYMBOL(pci_enable_link_state_locked);
+/**
+ * pci_force_enable_link_state - Force enable device link state
+ * @pdev: PCI device
+ * @state: Mask of ASPM link states to enable
+ *
+ * Enable device link state, so the link will enter the specified states.
+ * Unlike pci_enable_link_state(), this also re-enables states previously
+ * disabled by pci_disable_link_state() and overrides the ASPM states disabled
+ * during init (e.g., the pre-1.1 device blacklist). The caller is therefore
+ * responsible for only enabling states the device supports, typically the ones
+ * previously reported by pcie_aspm_enabled().
+ *
+ * Note that if the BIOS didn't grant ASPM control to the OS, this does nothing
+ * because we can't touch the LNKCTL register.
+ *
+ * Note: Ensure devices are in D0 before enabling PCI-PM L1 PM Substates, per
+ * PCIe r6.0, sec 5.5.4.
+ *
+ * Return: 0 on success, a negative errno otherwise.
+ */
+int pci_force_enable_link_state(struct pci_dev *pdev, int state)
+{
+ return __pci_enable_link_state(pdev, state, false, true);
+}
+EXPORT_SYMBOL(pci_force_enable_link_state);
+
void pcie_aspm_remove_cap(struct pci_dev *pdev, u32 lnkcap)
{
if (lnkcap & PCI_EXP_LNKCAP_ASPM_L0S)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ebb5b9d76360..be6719626c8f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1918,6 +1918,7 @@ int pci_disable_link_state(struct pci_dev *pdev, int state);
int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
int pci_enable_link_state(struct pci_dev *pdev, int state);
int pci_enable_link_state_locked(struct pci_dev *pdev, int state);
+int pci_force_enable_link_state(struct pci_dev *pdev, int state);
void pcie_no_aspm(void);
bool pcie_aspm_support_enabled(void);
bool pcie_aspm_enabled(struct pci_dev *pdev);
@@ -1930,6 +1931,8 @@ static inline int pci_enable_link_state(struct pci_dev *pdev, int state)
{ return 0; }
static inline int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
{ return 0; }
+static inline int pci_force_enable_link_state(struct pci_dev *pdev, int state)
+{ return 0; }
static inline void pcie_no_aspm(void) { }
static inline bool pcie_aspm_support_enabled(void) { return false; }
static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
--
2.43.0
^ permalink raw reply related
* [PATCH v3 0/8] PCI/ASPM: Add pci_force_enable_link_state() API and convert Atheros drivers
From: Manivannan Sadhasivam @ 2026-07-08 14:30 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Nirmal Patel, Jonathan Derrick, Jeff Johnson
Cc: linux-pci, linux-kernel, linux-arm-msm, linux-wireless, ath12k,
ath11k, ath10k, Krishna Chaitanya Chundru, Qiang Yu, mani,
Ilpo Järvinen, Manivannan Sadhasivam
Hi,
This series converts the atheros WLAN drivers (ath10k/ath11k/ath12k) to
use the PCI core ASPM APIs for enabling/disabling ASPM instead of writing
to the LNKCTL register directly. Touching LNKCTL behind the PCI core's
back leaves the ASPM service driver's view of the link state out of sync
with the hardware, which is not nice.
The catch is that these drivers save the currently enabled ASPM states,
disable ASPM before firmware download, and restore the saved states
afterwards. pci_enable_link_state() cannot restore states that were
disabled via pci_disable_link_state() or blacklisted during init (like
the pre-1.1 device blacklist, which is only meant to be overridden with
pcie_aspm=force), and that is intentional. So the save/restore sequence
cannot be expressed with the existing APIs.
In v2 I tried to fix this by making pci_enable_link_state*() symmetric
with the disable APIs, but as pointed out during review, that also ends
up overriding the init-time blacklist for every caller (including VMD),
which is not something we want. So instead, this version adds a separate
pci_force_enable_link_state() API (patch 2) that re-enables the requested
states unconditionally. The caller is responsible for only asking for
states the device actually supports, and the ath drivers do this by
restoring exactly what pcie_aspm_enabled() reported earlier.
The first five patches touch the PCI core: patch 1 (from Ilpo) makes
pci_disable_link_state() disable ASPM unconditionally, patch 2 adds the
new API, patch 3 moves the D0 transition needed before enabling PCI-PM
L1 PM Substates (PCIe r6.0, sec 5.5.4) into the shared helper and drops
it from the vmd and pcie-qcom callers, patch 4 cleans up the kernel-doc,
and patch 5 makes pcie_aspm_enabled() return the enabled state mask so it
can be used for save/restore. The last three patches convert the ath
drivers.
Testing
=======
I've tested this series on a Lenovo Thinkpad T14s with WCN7850 (so that's
just the ath12k driver). Rest of the drivers are compile tested only.
Merging Strategy
================
Even though there is no build dependency between the PCI core and atheros
patches, there is a functional dependency. So I'd recommend creating an
immutable branch with the PCI patches and merging that branch into both
the PCI and linux-wireless trees, and finally merging the atheros patches
into the linux-wireless tree.
If the immutable branch seems like a hassle, then the PCI core patches
could get merged first and the atheros patches can wait for the next
cycle.
- Mani
Changes in v3:
* Dropped the change that made pci_enable_link_state*() symmetric with the
disable APIs. Instead added a new pci_force_enable_link_state() API used
only by the ath drivers, so the init-time blacklist stays overridable
only via pcie_aspm=force and existing callers like VMD are left
untouched.
* Fixed the locked path to use pci_set_power_state_locked() for the D0
transition. The previous version called the non-locked variant, which
re-acquires pci_bus_sem.
* ath drivers now disable PCIE_LINK_STATE_ASPM_ALL instead of
PCIE_LINK_STATE_ALL so that CLKPM is preserved and can be restored
(pcie_aspm_enabled() doesn't report CLKPM).
* Reworked the kernel-doc patch to cover both the enable and disable APIs
and reference the new API.
* Rebased on top of v7.2-rc1.
Changes in v2:
* Reworked the pcie_aspm_enabled() API to return the enabled states
instead of bool and used it to save/restore the ASPM states in ath
drivers.
* Added a patch from Ilpo to disable ASPM even if BIOS didn't grant
permission.
* Added the CONFIG_PCIEASPM dependency to ath{10/11/12}k drivers.
* Rebased on top of v6.17-rc1.
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
Ilpo Järvinen (1):
PCI/ASPM: Always disable ASPM when driver requests it
Manivannan Sadhasivam (7):
PCI/ASPM: Add pci_force_enable_link_state() API
PCI/ASPM: Transition the device to D0 (if required) when enabling ASPM link states
PCI/ASPM: Improve the kernel-doc for pci_{enable,disable}_link_state*() APIs
PCI/ASPM: Return enabled ASPM states from pcie_aspm_enabled() API
wifi: ath12k: Use pci_{enable/disable}_link_state() APIs to enable/disable ASPM states
wifi: ath11k: Use pci_{enable/disable}_link_state() APIs to enable/disable ASPM states
wifi: ath10k: Use pci_{enable/disable}_link_state() APIs to enable/disable ASPM states
drivers/net/wireless/ath/ath10k/Kconfig | 2 +-
drivers/net/wireless/ath/ath10k/pci.c | 11 +--
drivers/net/wireless/ath/ath10k/pci.h | 5 +-
drivers/net/wireless/ath/ath11k/Kconfig | 2 +-
drivers/net/wireless/ath/ath11k/pci.c | 19 +----
drivers/net/wireless/ath/ath11k/pci.h | 3 +-
drivers/net/wireless/ath/ath12k/Kconfig | 2 +-
drivers/net/wireless/ath/ath12k/pci.c | 19 +----
drivers/net/wireless/ath/ath12k/pci.h | 4 +-
drivers/pci/controller/dwc/pcie-qcom.c | 5 --
drivers/pci/controller/vmd.c | 5 --
drivers/pci/pcie/aspm.c | 140 ++++++++++++++++++++++++--------
include/linux/pci.h | 7 +-
13 files changed, 129 insertions(+), 95 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260708-pci-aspm-fix-331826a2cb5d
Best regards,
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* [PATCH v3 4/8] PCI/ASPM: Improve the kernel-doc for pci_{enable,disable}_link_state*() APIs
From: Manivannan Sadhasivam @ 2026-07-08 14:30 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Nirmal Patel, Jonathan Derrick, Jeff Johnson
Cc: linux-pci, linux-kernel, linux-arm-msm, linux-wireless, ath12k,
ath11k, ath10k, Krishna Chaitanya Chundru, Qiang Yu, mani,
Ilpo Järvinen, Manivannan Sadhasivam
In-Reply-To: <20260708-pci-aspm-fix-v3-0-6bd72451746e@kernel.org>
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Add kernel-doc for pci_disable_link_state_locked() API and fix the
kernel-doc for pci_disable_link_state() API.
Also convert the kernel-doc of pci_enable_link_state() and
pci_enable_link_state_locked() APIs to the standard format and mention that
pci_force_enable_link_state() should be used to re-enable the states
disabled by pci_disable_link_state().
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/pci/pcie/aspm.c | 47 ++++++++++++++++++++++++++++++++---------------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 6d6862fd2ebb..5e7e199c78d2 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1483,6 +1483,17 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked
return 0;
}
+/**
+ * pci_disable_link_state_locked - Disable device's link state
+ * @pdev: PCI device
+ * @state: ASPM link state to disable
+ *
+ * Disable device's link state so the link will never enter specific states.
+ *
+ * Context: Caller holds pci_bus_sem read lock.
+ *
+ * Return: 0 on success, a negative errno otherwise.
+ */
int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
{
lockdep_assert_held_read(&pci_bus_sem);
@@ -1555,17 +1566,20 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked,
}
/**
- * pci_enable_link_state - Clear and set the default device link state so that
- * the link may be allowed to enter the specified states. Note that if the
- * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
- * touch the LNKCTL register. Also note that this does not enable states
- * disabled by pci_disable_link_state(). Return 0 or a negative errno.
+ * pci_enable_link_state - Enable device's link state
+ * @pdev: PCI device
+ * @state: Mask of ASPM link states to enable
+ *
+ * Enable device's link state, so the link will enter the specified states.
+ * Note that if the BIOS didn't grant ASPM control to the OS, this does
+ * nothing because we can't touch the LNKCTL register. Also note that this
+ * does not enable states disabled by pci_disable_link_state(). Use
+ * pci_force_enable_link_state() for that.
*
* Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates
* are getting enabled.
*
- * @pdev: PCI device
- * @state: Mask of ASPM link states to enable
+ * Return: 0 on success, a negative errno otherwise.
*/
int pci_enable_link_state(struct pci_dev *pdev, int state)
{
@@ -1574,19 +1588,22 @@ int pci_enable_link_state(struct pci_dev *pdev, int state)
EXPORT_SYMBOL(pci_enable_link_state);
/**
- * pci_enable_link_state_locked - Clear and set the default device link state
- * so that the link may be allowed to enter the specified states. Note that if
- * the BIOS didn't grant ASPM control to the OS, this does nothing because we
- * can't touch the LNKCTL register. Also note that this does not enable states
- * disabled by pci_disable_link_state(). Return 0 or a negative errno.
+ * pci_enable_link_state_locked - Enable device's link state
+ * @pdev: PCI device
+ * @state: Mask of ASPM link states to enable
+ *
+ * Enable device's link state, so the link will enter the specified states.
+ * Note that if the BIOS didn't grant ASPM control to the OS, this does
+ * nothing because we can't touch the LNKCTL register. Also note that this
+ * does not enable states disabled by pci_disable_link_state(). Use
+ * pci_force_enable_link_state() for that.
*
* Note: The device will be transitioned to D0 state if the PCI-PM L1 Substates
* are getting enabled.
*
- * @pdev: PCI device
- * @state: Mask of ASPM link states to enable
- *
* Context: Caller holds pci_bus_sem read lock.
+ *
+ * Return: 0 on success, a negative errno otherwise.
*/
int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
{
--
2.43.0
^ permalink raw reply related
* [PATCH v3 1/8] PCI/ASPM: Always disable ASPM when driver requests it
From: Manivannan Sadhasivam @ 2026-07-08 14:30 UTC (permalink / raw)
To: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Nirmal Patel, Jonathan Derrick, Jeff Johnson
Cc: linux-pci, linux-kernel, linux-arm-msm, linux-wireless, ath12k,
ath11k, ath10k, Krishna Chaitanya Chundru, Qiang Yu, mani,
Ilpo Järvinen, Manivannan Sadhasivam
In-Reply-To: <20260708-pci-aspm-fix-v3-0-6bd72451746e@kernel.org>
From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
PCI core/ASPM service driver allows controlling ASPM state through
pci_disable_link_state() API. It was decided earlier (see the Link
below), to not allow ASPM changes when OS does not have control over it
but only log a warning about the problem 'commit 2add0ec14c25 ("PCI/ASPM:
Warn when driver asks to disable ASPM, but we can't do it")'.
A number of drivers have added workarounds to force ASPM off with own
writes into the Link Control Register (some even with comments
explaining why PCI core does not disable it under some circumstances).
According to the comments, some drivers require ASPM to be off for
reliable operation.
Having custom ASPM handling in drivers is problematic because the state
kept in the ASPM service driver is not updated by the changes made
outside the link state management API.
As the first step to address this issue, make pci_disable_link_state()
to unconditionally disable ASPM so the motivation for drivers to come
up with custom ASPM handling code is eliminated.
To fully take advantage of the ASPM handling core provides, the drivers
that need to quirk ASPM have to be altered depend on PCIEASPM and the
custom ASPM code is removed. This is to be done separately. As PCIEASPM
is already behind EXPERT, it should be no problem to limit disabling it
for configurations that do not require touching ASPM.
Make pci_disable_link_state() function comment to comply kerneldoc
formatting while changing the description.
Link: https://lore.kernel.org/all/CANUX_P3F5YhbZX3WGU-j1AGpbXb_T9Bis2ErhvKkFMtDvzatVQ@mail.gmail.com/
Link: https://lore.kernel.org/all/20230511131441.45704-1-ilpo.jarvinen@linux.intel.com/
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
[mani: commit message fixup]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
drivers/pci/pcie/aspm.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 172783e7f519..1c15a14718e8 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1449,16 +1449,23 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool locked
return -EINVAL;
/*
* A driver requested that ASPM be disabled on this device, but
- * if we don't have permission to manage ASPM (e.g., on ACPI
+ * if we might not have permission to manage ASPM (e.g., on ACPI
* systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
- * the _OSC method), we can't honor that request. Windows has
- * a similar mechanism using "PciASPMOptOut", which is also
- * ignored in this situation.
+ * the _OSC method), previously we chose to not honor disable
+ * request in that case. Windows has a similar mechanism using
+ * "PciASPMOptOut", which is also ignored in this situation.
+ *
+ * Not honoring the requests to disable ASPM, however, led to
+ * drivers forcing ASPM off on their own. As such changes of ASPM
+ * state are not tracked by this service driver, the state kept here
+ * became out of sync.
+ *
+ * Therefore, honor ASPM disable requests even when OS does not have
+ * ASPM control. Plain disable for ASPM is assumed to be slightly
+ * safer than fully managing it.
*/
- if (aspm_disabled) {
- pci_warn(pdev, "can't disable ASPM; OS doesn't have ASPM control\n");
- return -EPERM;
- }
+ if (aspm_disabled)
+ pci_warn(pdev, "OS doesn't have ASPM control, disabling ASPM anyway\n");
if (!locked)
down_read(&pci_bus_sem);
@@ -1485,13 +1492,13 @@ int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
EXPORT_SYMBOL(pci_disable_link_state_locked);
/**
- * pci_disable_link_state - Disable device's link state, so the link will
- * never enter specific states. Note that if the BIOS didn't grant ASPM
- * control to the OS, this does nothing because we can't touch the LNKCTL
- * register. Returns 0 or a negative errno.
- *
+ * pci_disable_link_state - Disable device's link state
* @pdev: PCI device
* @state: ASPM link state to disable
+ *
+ * Disable device's link state so the link will never enter specific states.
+ *
+ * Return: 0 or a negative errno
*/
int pci_disable_link_state(struct pci_dev *pdev, int state)
{
--
2.43.0
^ permalink raw reply related
* [linus:master] [wifi] 43ef5856bd: hwsim.nan_stopped_on_iface_removal.fail
From: kernel test robot @ 2026-07-08 13:38 UTC (permalink / raw)
To: Miri Korenblit
Cc: oe-lkp, lkp, linux-kernel, Johannes Berg, linux-wireless,
oliver.sang
Hello,
we reported
"[linux-next:master] [wifi] 43ef5856bd: hwsim.nan_sync_srf_mac_addr_8.fail"
in
https://lore.kernel.org/all/202605112140.63585f81-lkp@intel.com/
when this commit is in linux-next/master
now we noticed the commit merged in mainline and we captured it cause more
hwsim test failures which can pass on parent.
below is just one example FYI.
kernel test robot noticed "hwsim.nan_stopped_on_iface_removal.fail" on:
commit: 43ef5856bdab300acc90ea2c3c437f5535a5f66f ("wifi: mac80211: track the id of the NAN cluster we joined")
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
[test failed on linus/master dc59e4fea9d83f03bad6bddf3fa2e52491777482]
[test failed on linux-next/master 7de6ae9e12207ec146f2f3f1e58d1a99317e88bc]
in testcase: hwsim
version: hwsim-x86_64-890d573a1-1_20260622
with following parameters:
test: group-18
config: x86_64-rhel-9.4-func
compiler: gcc-14
test machine: 8 threads 1 sockets Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz (Haswell) with 8G memory
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202607081635.d6385138-lkp@intel.com
2026-06-30 08:17:46 ./run-tests.py nan_stopped_on_iface_removal
DEV: wlan0: 02:00:00:00:00:00
DEV: wlan1: 02:00:00:00:01:00
DEV: wlan2: 02:00:00:00:02:00
APDEV: wlan3
APDEV: wlan4
START nan_stopped_on_iface_removal 1/1
Test: NAN cluster and discovery followed by radio destruction reports NAN-STOPPED
Starting NAN on publisher
NAN capabilities: USD NAN
NAN device starting on nan0
Setting master_pref to 10 on nan0
Setting dual_band to 0 on nan0
NAN device started on nan0
NAN capabilities: USD NAN
NAN device starting on nan1
Setting master_pref to 10 on nan1
Setting dual_band to 0 on nan1
NAN device started on nan1
Verifying service discovery
Publish ID: 1, Subscribe ID: 1
NAN device stopping on nan1
NAN device stopped on nan1
Exception during test execution: NAN-DISCOVERY-RESULT event not seen
Traceback (most recent call last):
File "/lkp/benchmarks/hwsim/tests/hwsim/./run-tests.py", line 633, in main
t(dev, apdev, params)
~^^^^^^^^^^^^^^^^^^^^
File "/lkp/benchmarks/hwsim/tests/hwsim/test_nan.py", line 2195, in test_nan_stopped_on_iface_removal
nan_sync_discovery(pub, sub, "test_service",
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
pssi="aabbccdd", sssi="ddbbccaa")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/lkp/benchmarks/hwsim/tests/hwsim/test_nan.py", line 396, in nan_sync_discovery
raise Exception("NAN-DISCOVERY-RESULT event not seen")
Exception: NAN-DISCOVERY-RESULT event not seen
FAIL nan_stopped_on_iface_removal 3.09572 2026-06-30 08:17:49.477478
passed 0 test case(s)
skipped 0 test case(s)
failed tests: nan_stopped_on_iface_removal
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20260708/202607081635.d6385138-lkp@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] wifi: ath12k: release QMI handle on late init failures
From: Vasanthakumar Thiagarajan @ 2026-07-08 11:59 UTC (permalink / raw)
To: Guangshuo Li, Jeff Johnson, Baochen Qiang, linux-wireless, ath12k,
linux-kernel
In-Reply-To: <20260708100924.744386-1-lgs201920130244@gmail.com>
On 7/8/2026 3:39 PM, Guangshuo Li wrote:
> The change referenced by the Fixes tag makes hardware group creation
> skip the device whose ath12k_core_soc_create() failed, and only destroys
> devices that were created successfully before it.
>
> That avoids releasing an uninitialized QMI handle when qmi_handle_init()
> fails, but it also means that ath12k_qmi_init_service() must clean up any
> resources it has already acquired before returning an error.
>
> qmi_handle_init() can succeed before later initialization steps fail. If
> the QMI event workqueue allocation fails, or qmi_add_lookup() fails, the
> function returns an error without releasing the already initialized QMI
> handle. Since the failed device is now skipped by the hardware group
> rollback path, that handle is leaked.
>
> Release the QMI handle on those late failure paths and clear ab->qmi.ab
> so the failed device is left in the same state as the qmi_handle_init()
> failure path.
>
> Fixes: 088a099690e4 ("wifi: ath12k: fix error handling in creating hardware group")
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
btw, similar leak may be there in ath11k also, care to fix that as well?
^ permalink raw reply
* [PATCH] wifi: ath12k: release QMI handle on late init failures
From: Guangshuo Li @ 2026-07-08 10:09 UTC (permalink / raw)
To: Jeff Johnson, Baochen Qiang, Vasanthakumar Thiagarajan,
linux-wireless, ath12k, linux-kernel
Cc: Guangshuo Li
The change referenced by the Fixes tag makes hardware group creation
skip the device whose ath12k_core_soc_create() failed, and only destroys
devices that were created successfully before it.
That avoids releasing an uninitialized QMI handle when qmi_handle_init()
fails, but it also means that ath12k_qmi_init_service() must clean up any
resources it has already acquired before returning an error.
qmi_handle_init() can succeed before later initialization steps fail. If
the QMI event workqueue allocation fails, or qmi_add_lookup() fails, the
function returns an error without releasing the already initialized QMI
handle. Since the failed device is now skipped by the hardware group
rollback path, that handle is leaked.
Release the QMI handle on those late failure paths and clear ab->qmi.ab
so the failed device is left in the same state as the qmi_handle_init()
failure path.
Fixes: 088a099690e4 ("wifi: ath12k: fix error handling in creating hardware group")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/net/wireless/ath/ath12k/qmi.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index fd762b5d7bb5..31e9fa9a62be 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -4054,7 +4054,8 @@ int ath12k_qmi_init_service(struct ath12k_base *ab)
ab->qmi.event_wq = alloc_ordered_workqueue("ath12k_qmi_driver_event", 0);
if (!ab->qmi.event_wq) {
ath12k_err(ab, "failed to allocate workqueue\n");
- return -EFAULT;
+ ret = -EFAULT;
+ goto err_release_qmi_handle;
}
INIT_LIST_HEAD(&ab->qmi.event_list);
@@ -4067,9 +4068,15 @@ int ath12k_qmi_init_service(struct ath12k_base *ab)
if (ret < 0) {
ath12k_warn(ab, "failed to add qmi lookup\n");
destroy_workqueue(ab->qmi.event_wq);
- return ret;
+ goto err_release_qmi_handle;
}
+ return ret;
+
+err_release_qmi_handle:
+ qmi_handle_release(&ab->qmi.handle);
+ ab->qmi.ab = NULL;
+
return ret;
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 0/4] drivers/net: replace __get_free_pages() with kmalloc()
From: Johannes Berg @ 2026-07-08 9:09 UTC (permalink / raw)
To: Paolo Abeni
Cc: Brian Norris, Francesco Dolcini, Jakub Kicinski, b43-dev,
libertas-dev, linux-kernel, linux-mm, linux-wireless, netdev,
Mike Rapoport (Microsoft)
In-Reply-To: <3832c190-b5b7-49a2-902d-7f75598b0789@redhat.com>
On Wed, 2026-07-08 at 10:55 +0200, Paolo Abeni wrote:
>
> @Johannes: just an head-up, I assume this series will go via your tree
> (despite the slightly misleading subj)
I assumed the same and already have it in wireless-next (with fixed up
subjects to add wifi: prefixes).
johannes
^ permalink raw reply
* Re: [PATCH 0/4] drivers/net: replace __get_free_pages() with kmalloc()
From: Paolo Abeni @ 2026-07-08 8:55 UTC (permalink / raw)
To: Johannes Berg
Cc: Brian Norris, Francesco Dolcini, Jakub Kicinski, b43-dev,
libertas-dev, linux-kernel, linux-mm, linux-wireless, netdev,
Mike Rapoport (Microsoft)
In-Reply-To: <20260701-b4-drivers-wireless-v1-0-60264cdf2efe@kernel.org>
On 7/1/26 3:59 PM, Mike Rapoport (Microsoft) wrote:
> This is a (small) part of larger work of replacing page allocator calls
> with kmalloc.
>
> My initial intention a few month ago was to remove ugly casts [1], but then
> willy pointed out that Linus objected to something like this [2] and it
> looks like more than a decade old technical debt.
>
> Largely, anything that doesn't need struct page (or a memdesc in the
> future) should just use kmalloc() or kvmalloc() to allocate memory.
> kmalloc() guarantees alignment, physical contiguity and working
> virt_to_phys() and beside nicer API that returns void * on alloc and
> doesn't require to know the allocation size on free, kmalloc() provides
> better debugging capabilities than page allocator.
>
> Another thing is that touching these allocation sites gives the reviewers
> opportunity to see if a PAGE_SIZE buffer is actually needed or maybe
> another size is appropriate.
>
> For larger allocations that don't need physically contiguous memory
> kvmalloc() can be a better option that __get_free_pages() because under
> memory pressure it's is easier to allocate several order-0 pages than a
> physically contiguous chunk with the same number of pages.
>
> And last, but not least, removing needless calls to page allocator should
> help with memdesc (aka project folio) conversion. There will be way less
> places to audit to see if the user was actually using struct page.
>
> Also in git:
> https://git.kernel.org/pub/scm/linux/kernel/git/rppt/linux.git gfp-to-kmalloc/drivers-net-wireless
>
> [1] https://lore.kernel.org/all/20251018093002.3660549-1-rppt@kernel.org/
> [2] https://lore.kernel.org/all/CA+55aFwp4iy4rtX2gE2WjBGFL=NxMVnoFeHqYa2j1dYOMMGqxg@mail.gmail.com/
>
> ---
@Johannes: just an head-up, I assume this series will go via your tree
(despite the slightly misleading subj)
/P
^ permalink raw reply
* [PATCH] wifi: mt76: mt7925: guard link STA in decap offload
From: Guangshuo Li @ 2026-07-08 7:55 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno,
Ming Yen Hsieh, Javier Tia, Leon Yen, Deren Wu, linux-wireless,
linux-kernel, linux-arm-kernel, linux-mediatek
Cc: Guangshuo Li
mt7925_sta_set_decap_offload() iterates over the vif valid_links mask
when updating decap offload state for an MLO station. The station may not
have a link STA for every valid link of the vif, so mt792x_sta_to_link()
can return NULL for a link that belongs to the vif but not to the station.
The function currently dereferences mlink before checking whether the
link WCID is ready. If mlink is NULL, setting or clearing
MT_WCID_FLAG_HDR_TRANS dereferences a NULL pointer.
Skip links without a station link before touching mlink->wcid.
Fixes: b859ad65309a ("wifi: mt76: mt7925: add link handling in mt7925_sta_set_decap_offload")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index a9059866b701..2b6cc8e253c0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1713,6 +1713,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
mconf = mt792x_vif_to_link(mvif, i);
mlink = mt792x_sta_to_link(msta, i);
+ if (!mlink)
+ continue;
+
if (enabled)
set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags);
else
--
2.43.0
^ permalink raw reply related
* [PATCH v4] wifi: brcmfmac: add DPP support
From: Jason Huang @ 2026-07-08 7:12 UTC (permalink / raw)
To: linux-wireless
Cc: brcm80211, brcm80211-dev-list.pdl, linux-kernel, arend.vanspriel,
Jason Huang, Kurt Lee
In-Reply-To: <20260708035843.312554-1-Jason.Huang2@infineon.com>
From: Jason Huang <jason.huang2@infineon.com>
Add DPP AKM handling and RSN parsing support. Map DPP to the
firmware wpa_auth value and recognize DPP public action frames in the
P2P action-frame TX path.
Allow non-P2P public action frames such as DPP to use the primary vif
when a P2P device vif is not present. Guard P2P-device IE access for
the same case.
Gate sup_wpa programming on firmware supplicant capability. Disable it
only when the selected connection mode does not use firmware supplicant.
This keeps pure SAE and 802.1X firmware-supplicant paths intact while
avoiding stale firmware supplicant state for DPP.
Signed-off-by: Kurt Lee <kurt.lee@cypress.com>
Signed-off-by: Jason Huang <jason.huang2@infineon.com>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 151 ++++++++++--------
.../broadcom/brcm80211/brcmfmac/p2p.c | 59 +++++--
.../broadcom/brcm80211/include/brcmu_wifi.h | 2 +
3 files changed, 134 insertions(+), 78 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 4b70845e1a26..d61c3e03a106 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
+#include <linux/unaligned.h>
#include <linux/vmalloc.h>
#include <net/cfg80211.h>
#include <net/netlink.h>
@@ -2154,6 +2155,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
profile->is_ft = true;
break;
+ case WLAN_AKM_SUITE_WFA_DPP:
+ val = WFA_AUTH_DPP;
+ break;
default:
bphy_err(drvr, "invalid akm suite (%d)\n",
sme->crypto.akm_suites[0]);
@@ -2466,43 +2470,50 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
goto done;
}
- if (sme->crypto.psk &&
- profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {
- if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
- err = -EINVAL;
- goto done;
- }
- brcmf_dbg(INFO, "using PSK offload\n");
- profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
- }
-
- if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
- /* enable firmware supplicant for this interface */
- err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
- if (err < 0) {
- bphy_err(drvr, "failed to enable fw supplicant\n");
- goto done;
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {
+ u32 akm = sme->crypto.n_akm_suites ? sme->crypto.akm_suites[0] : 0;
+ bool is_sae_akm = akm == WLAN_AKM_SUITE_SAE ||
+ akm == WLAN_AKM_SUITE_FT_OVER_SAE;
+
+ if (sme->crypto.psk && !is_sae_akm &&
+ profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {
+ if (WARN_ON(profile->use_fwsup !=
+ BRCMF_PROFILE_FWSUP_NONE)) {
+ err = -EINVAL;
+ goto done;
+ }
+ brcmf_dbg(INFO, "using PSK offload\n");
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
}
- }
-
- if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK)
- err = brcmf_set_pmk(ifp, sme->crypto.psk,
- BRCMF_WSEC_MAX_PSK_LEN);
- else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) {
- /* clean up user-space RSNE */
- err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0);
- if (err) {
- bphy_err(drvr, "failed to clean up user-space RSNE\n");
- goto done;
+ if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
+ /* enable firmware supplicant for this interface */
+ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
+ if (err < 0) {
+ bphy_err(drvr, "failed to enable fw supplicant\n");
+ goto done;
+ }
+ } else {
+ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0);
}
- err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto);
- if (!err && sme->crypto.psk)
+ if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK)
err = brcmf_set_pmk(ifp, sme->crypto.psk,
BRCMF_WSEC_MAX_PSK_LEN);
+ else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE &&
+ sme->crypto.sae_pwd &&
+ brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE)) {
+ /* clean up user-space RSNE */
+ if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) {
+ bphy_err(drvr, "failed to clean up user-space RSNE\n");
+ goto done;
+ }
+ err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto);
+ if (!err && sme->crypto.psk)
+ err = brcmf_set_pmk(ifp, sme->crypto.psk,
+ BRCMF_WSEC_MAX_PSK_LEN);
+ }
+ if (err)
+ goto done;
}
- if (err)
- goto done;
-
/* Join with specific BSSID and cached SSID
* If SSID is zero join based on BSSID only
*/
@@ -4519,6 +4530,11 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
}
+static bool brcmf_valid_dpp_suite(u8 *oui)
+{
+ return get_unaligned_be32(oui) == WLAN_AKM_SUITE_WFA_DPP;
+}
+
static s32
brcmf_configure_wpaie(struct brcmf_if *ifp,
const struct brcmf_vs_tlv *wpa_ie,
@@ -4632,42 +4648,47 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
goto exit;
}
for (i = 0; i < count; i++) {
- if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+ if (brcmf_valid_dpp_suite(&data[offset])) {
+ wpa_auth |= WFA_AUTH_DPP;
+ offset += TLV_OUI_LEN;
+ } else if (brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+ offset += TLV_OUI_LEN;
+ switch (data[offset]) {
+ case RSN_AKM_NONE:
+ brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
+ wpa_auth |= WPA_AUTH_NONE;
+ break;
+ case RSN_AKM_UNSPECIFIED:
+ brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
+ is_rsn_ie ?
+ (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
+ (wpa_auth |= WPA_AUTH_UNSPECIFIED);
+ break;
+ case RSN_AKM_PSK:
+ brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
+ is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
+ (wpa_auth |= WPA_AUTH_PSK);
+ break;
+ case RSN_AKM_SHA256_PSK:
+ brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");
+ wpa_auth |= WPA2_AUTH_PSK_SHA256;
+ break;
+ case RSN_AKM_SHA256_1X:
+ brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
+ wpa_auth |= WPA2_AUTH_1X_SHA256;
+ break;
+ case RSN_AKM_SAE:
+ brcmf_dbg(TRACE, "RSN_AKM_SAE\n");
+ wpa_auth |= WPA3_AUTH_SAE_PSK;
+ break;
+ default:
+ bphy_err(drvr, "Invalid key mgmt info\n");
+ }
+ } else {
err = -EINVAL;
bphy_err(drvr, "invalid OUI\n");
goto exit;
}
- offset += TLV_OUI_LEN;
- switch (data[offset]) {
- case RSN_AKM_NONE:
- brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
- wpa_auth |= WPA_AUTH_NONE;
- break;
- case RSN_AKM_UNSPECIFIED:
- brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
- is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
- (wpa_auth |= WPA_AUTH_UNSPECIFIED);
- break;
- case RSN_AKM_PSK:
- brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
- is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
- (wpa_auth |= WPA_AUTH_PSK);
- break;
- case RSN_AKM_SHA256_PSK:
- brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");
- wpa_auth |= WPA2_AUTH_PSK_SHA256;
- break;
- case RSN_AKM_SHA256_1X:
- brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
- wpa_auth |= WPA2_AUTH_1X_SHA256;
- break;
- case RSN_AKM_SAE:
- brcmf_dbg(TRACE, "RSN_AKM_SAE\n");
- wpa_auth |= WPA3_AUTH_SAE_PSK;
- break;
- default:
- bphy_err(drvr, "Invalid key mgmt info\n");
- }
offset++;
}
@@ -4687,10 +4708,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
*/
if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 |
WPA2_AUTH_1X_SHA256 |
+ WFA_AUTH_DPP |
WPA3_AUTH_SAE_PSK))) {
err = -EINVAL;
goto exit;
}
+
/* Firmware has requirement that WPA2_AUTH_PSK/
* WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI
* is to be included in the rsn ie.
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 6e0c90f4718b..2c1f52ed5138 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -6,6 +6,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
+#include <linux/unaligned.h>
#include <net/cfg80211.h>
#include <brcmu_wifi.h>
@@ -44,9 +45,6 @@
#define BRCMF_SCB_TIMEOUT_VALUE 20
-#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */
-#define P2P_PUB_AF_CATEGORY 0x04
-#define P2P_PUB_AF_ACTION 0x09
#define P2P_AF_CATEGORY 0x7f
#define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */
#define P2P_OUI_LEN 3 /* P2P OUI length */
@@ -143,10 +141,10 @@ struct brcmf_p2p_scan_le {
/**
* struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame
*
- * @category: P2P_PUB_AF_CATEGORY
- * @action: P2P_PUB_AF_ACTION
+ * @category: WLAN_CATEGORY_PUBLIC
+ * @action: WLAN_PUB_ACTION_VENDOR_SPECIFIC
* @oui: P2P_OUI
- * @oui_type: OUI type - P2P_VER
+ * @oui_type: OUI type - WLAN_OUI_TYPE_WFA_P2P
* @subtype: OUI subtype - P2P_TYPE_*
* @dialog_token: nonzero, identifies req/rsp transaction
* @elts: Variable length information elements.
@@ -166,7 +164,7 @@ struct brcmf_p2p_pub_act_frame {
*
* @category: P2P_AF_CATEGORY
* @oui: OUI - P2P_OUI
- * @type: OUI Type - P2P_VER
+ * @type: OUI Type - WLAN_OUI_TYPE_WFA_P2P
* @subtype: OUI Subtype - P2P_AF_*
* @dialog_token: nonzero, identifies req/resp tranaction
* @elts: Variable length information elements.
@@ -228,10 +226,38 @@ static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len)
if (frame_len < sizeof(*pact_frm))
return false;
- if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
- pact_frm->action == P2P_PUB_AF_ACTION &&
- pact_frm->oui_type == P2P_VER &&
- memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
+ if (pact_frm->category == WLAN_CATEGORY_PUBLIC &&
+ pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC &&
+ pact_frm->oui_type == WLAN_OUI_TYPE_WFA_P2P &&
+ get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA)
+ return true;
+
+ return false;
+}
+
+/**
+ * brcmf_p2p_is_dpp_pub_action() - true if dpp public type frame.
+ *
+ * @frame: action frame data.
+ * @frame_len: length of action frame data.
+ *
+ * Determine if action frame is dpp public action type
+ */
+static bool brcmf_p2p_is_dpp_pub_action(void *frame, u32 frame_len)
+{
+ struct brcmf_p2p_pub_act_frame *pact_frm;
+
+ if (!frame)
+ return false;
+
+ pact_frm = (struct brcmf_p2p_pub_act_frame *)frame;
+ if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1)
+ return false;
+
+ if (pact_frm->category == WLAN_CATEGORY_PUBLIC &&
+ pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC &&
+ pact_frm->oui_type == WLAN_OUI_TYPE_WFA_DPP &&
+ get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA)
return true;
return false;
@@ -257,7 +283,7 @@ static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len)
return false;
if (act_frm->category == P2P_AF_CATEGORY &&
- act_frm->type == P2P_VER &&
+ act_frm->type == WLAN_OUI_TYPE_WFA_P2P &&
memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
return true;
@@ -1281,6 +1307,9 @@ static s32 brcmf_p2p_abort_action_frame(struct brcmf_cfg80211_info *cfg)
brcmf_dbg(TRACE, "Enter\n");
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+ if (!vif)
+ vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+
err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val,
sizeof(s32));
if (err)
@@ -1789,7 +1818,9 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
goto exit;
}
} else if (brcmf_p2p_is_p2p_action(action_frame->data,
- action_frame_len)) {
+ action_frame_len) ||
+ brcmf_p2p_is_dpp_pub_action(action_frame->data,
+ action_frame_len)) {
/* do not configure anything. it will be */
/* sent with a default configuration */
} else {
@@ -1826,6 +1857,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
/* validate channel and p2p ies */
if (config_af_params.search_channel &&
IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) &&
+ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif &&
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) {
afx_hdl = &p2p->afx_hdl;
afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel);
@@ -2543,4 +2575,3 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
/* just set it all to zero */
memset(p2p, 0, sizeof(*p2p));
}
-
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
index 7552bdb91991..c465208c4331 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
@@ -233,6 +233,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
#define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */
+#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */
+
#define DOT11_DEFAULT_RTS_LEN 2347
#define DOT11_DEFAULT_FRAG_LEN 2346
base-commit: 3737936e2be920977aea7d9f7eb8cb4468d700d7
--
2.25.1
^ permalink raw reply related
* [PATCH] wifi: brcmfmac: guard P2P device vif in action frame search
From: Guangshuo Li @ 2026-07-08 6:39 UTC (permalink / raw)
To: Arend van Spriel, Johannes Berg, Peddolla Harshavardhan Reddy,
Bjorn Helgaas, Gokul Sivakumar, Guangshuo Li,
Pieter-Paul Giesberts, Hante Meuleman, John W. Linville,
Piotr Haber, linux-wireless, brcm80211, brcm80211-dev-list.pdl,
linux-kernel
brcmf_p2p_send_action_frame() checks the P2P device vif saved probe
request IE when deciding whether to perform a peer channel search. The
P2P device vif is not guaranteed to exist, for example in standalone AP
mode where no P2P device interface has been created.
If a search-channel action frame is sent on a social channel in that
mode, the validation condition can dereference the NULL P2P device vif
before the frame is transmitted through the caller's vif.
Guard the P2P device vif before checking its saved probe request IE.
Fixes: 6eda4e2c5425 ("brcmfmac: Add tx p2p off-channel support.")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 92c16a317328..bbdebf4c2010 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -1819,6 +1819,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_if *ifp,
/* validate channel and p2p ies */
if (config_af_params.search_channel &&
IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) &&
+ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif &&
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) {
afx_hdl = &p2p->afx_hdl;
afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v1 07/12] nfc: Drop __maybe_unused from of_device_id tables
From: Uwe Kleine-König (The Capable Hub) @ 2026-07-08 5:05 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: David Heidelberg, Mark Greer, Simon Horman, Tomasz Unger,
oe-linux-nfc, linux-kernel, linux-wireless
In-Reply-To: <c5b1dec1-de39-4359-9cee-86cfac87b358@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 1975 bytes --]
On Tue, Jul 07, 2026 at 07:28:57PM +0200, Krzysztof Kozlowski wrote:
> On 03/07/2026 17:46, Uwe Kleine-König (The Capable Hub) wrote:
> > Referencing these arrays in MODULE_DEVICE_TABLE() is enough to convince
> > the compiler that they are used even if the drivers are built-in (since
> > 5ab23c7923a1 ("modpost: Create modalias for builtin modules"). So the
> > __maybe_unused marking can be removed without introducing a compiler
> > warning.
> >
> > Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> > ---
> > drivers/nfc/nfcmrvl/i2c.c | 2 +-
> > drivers/nfc/nfcmrvl/spi.c | 2 +-
> > drivers/nfc/pn533/i2c.c | 2 +-
> > drivers/nfc/pn544/i2c.c | 2 +-
> > drivers/nfc/s3fwrn5/i2c.c | 2 +-
> > drivers/nfc/st-nci/i2c.c | 2 +-
> > drivers/nfc/st-nci/spi.c | 2 +-
> > drivers/nfc/st21nfca/i2c.c | 2 +-
> > drivers/nfc/st95hf/core.c | 2 +-
> > drivers/nfc/trf7970a.c | 2 +-
> > 10 files changed, 10 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
> > index 66877a7d03f2..687d2979b881 100644
> > --- a/drivers/nfc/nfcmrvl/i2c.c
> > +++ b/drivers/nfc/nfcmrvl/i2c.c
> > @@ -245,7 +245,7 @@ static void nfcmrvl_i2c_remove(struct i2c_client *client)
> > }
> >
> >
> > -static const struct of_device_id of_nfcmrvl_i2c_match[] __maybe_unused = {
> > +static const struct of_device_id of_nfcmrvl_i2c_match[] = {
> > { .compatible = "marvell,nfc-i2c", },
> > {},
>
> This (and probably others) should re-introduce warnings on !MODULE and
> !OF builds (and other cases).
With an x86_64 allnoconfig and just the things enabled to make this
driver build (i.e. I2C and a few NFC related switches, but neither OF
nor MODULES) the driver builds fine even with W=1. If I drop
MODULE_DEVICE_TABLE() the warning appears. So unless proven otherwise I
claim the commit log and the patch are correct.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [wireless:for-next] BUILD SUCCESS cb8afea4655ff004fa7feee825d5c79783525383
From: kernel test robot @ 2026-07-08 4:16 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git for-next
branch HEAD: cb8afea4655ff004fa7feee825d5c79783525383 wifi: cfg80211: bound element ID read when checking non-inheritance
elapsed time: 956m
configs tested: 186
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-16.1.0
alpha allyesconfig gcc-16.1.0
alpha defconfig gcc-16.1.0
arc alldefconfig gcc-16.1.0
arc allmodconfig clang-23
arc allmodconfig gcc-16.1.0
arc allnoconfig gcc-16.1.0
arc allyesconfig clang-23
arc allyesconfig gcc-16.1.0
arc defconfig gcc-16.1.0
arc randconfig-001-20260708 gcc-13.4.0
arc randconfig-002-20260708 gcc-13.4.0
arm allnoconfig clang-17
arm allnoconfig gcc-16.1.0
arm allyesconfig clang-23
arm allyesconfig gcc-16.1.0
arm defconfig gcc-16.1.0
arm randconfig-001-20260708 gcc-13.4.0
arm randconfig-002-20260708 gcc-13.4.0
arm randconfig-003-20260708 gcc-13.4.0
arm randconfig-004-20260708 gcc-13.4.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
arm64 defconfig gcc-16.1.0
arm64 randconfig-001-20260708 gcc-9.5.0
arm64 randconfig-002-20260708 gcc-9.5.0
arm64 randconfig-003-20260708 gcc-9.5.0
arm64 randconfig-004-20260708 gcc-9.5.0
csky allmodconfig gcc-16.1.0
csky allnoconfig gcc-16.1.0
csky defconfig gcc-16.1.0
csky randconfig-001-20260708 gcc-9.5.0
csky randconfig-002-20260708 gcc-9.5.0
hexagon allmodconfig clang-23
hexagon allmodconfig gcc-16.1.0
hexagon allnoconfig clang-23
hexagon allnoconfig gcc-16.1.0
hexagon defconfig gcc-16.1.0
hexagon randconfig-001-20260708 gcc-13.4.0
hexagon randconfig-002-20260708 gcc-13.4.0
i386 allmodconfig clang-22
i386 allnoconfig gcc-14
i386 allnoconfig gcc-16.1.0
i386 allyesconfig clang-22
i386 buildonly-randconfig-001-20260708 clang-22
i386 buildonly-randconfig-002-20260708 clang-22
i386 buildonly-randconfig-003-20260708 clang-22
i386 buildonly-randconfig-004-20260708 clang-22
i386 buildonly-randconfig-005-20260708 clang-22
i386 buildonly-randconfig-006-20260708 clang-22
i386 defconfig gcc-16.1.0
i386 randconfig-001-20260708 clang-22
i386 randconfig-002-20260708 clang-22
i386 randconfig-003-20260708 clang-22
i386 randconfig-004-20260708 clang-22
i386 randconfig-005-20260708 clang-22
i386 randconfig-006-20260708 clang-22
i386 randconfig-007-20260708 clang-22
i386 randconfig-011-20260708 gcc-14
i386 randconfig-012-20260708 gcc-14
i386 randconfig-013-20260708 gcc-14
i386 randconfig-014-20260708 gcc-14
i386 randconfig-015-20260708 gcc-14
i386 randconfig-016-20260708 gcc-14
i386 randconfig-017-20260708 gcc-14
loongarch allmodconfig clang-19
loongarch allmodconfig clang-23
loongarch allnoconfig clang-20
loongarch allnoconfig gcc-16.1.0
loongarch defconfig clang-23
loongarch randconfig-001-20260708 gcc-13.4.0
loongarch randconfig-002-20260708 gcc-13.4.0
m68k allmodconfig gcc-16.1.0
m68k allnoconfig gcc-16.1.0
m68k allyesconfig clang-23
m68k allyesconfig gcc-16.1.0
m68k defconfig clang-23
microblaze allnoconfig gcc-16.1.0
microblaze allyesconfig gcc-16.1.0
microblaze defconfig clang-23
mips allmodconfig gcc-16.1.0
mips allnoconfig gcc-16.1.0
mips allyesconfig gcc-16.1.0
nios2 allmodconfig clang-20
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig clang-23
nios2 defconfig clang-23
nios2 randconfig-001-20260708 gcc-13.4.0
nios2 randconfig-002-20260708 gcc-13.4.0
openrisc allmodconfig clang-20
openrisc allmodconfig gcc-16.1.0
openrisc allnoconfig clang-23
openrisc defconfig gcc-16.1.0
parisc allmodconfig gcc-16.1.0
parisc allnoconfig clang-23
parisc allyesconfig clang-17
parisc allyesconfig gcc-16.1.0
parisc defconfig gcc-16.1.0
parisc randconfig-001-20260708 clang-22
parisc randconfig-002-20260708 clang-22
parisc64 defconfig clang-23
powerpc allmodconfig gcc-16.1.0
powerpc allnoconfig clang-23
powerpc randconfig-001-20260708 clang-22
powerpc randconfig-002-20260708 clang-22
powerpc64 randconfig-001-20260708 clang-22
powerpc64 randconfig-002-20260708 clang-22
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allyesconfig clang-23
riscv defconfig gcc-16.1.0
riscv randconfig-001-20260708 clang-23
riscv randconfig-002-20260708 clang-23
s390 allmodconfig clang-17
s390 allmodconfig clang-23
s390 allnoconfig clang-23
s390 allyesconfig gcc-16.1.0
s390 defconfig gcc-16.1.0
s390 randconfig-001-20260708 clang-23
s390 randconfig-002-20260708 clang-23
sh allmodconfig gcc-16.1.0
sh allnoconfig clang-23
sh allyesconfig clang-17
sh allyesconfig gcc-16.1.0
sh defconfig gcc-14
sh randconfig-001-20260708 clang-23
sh randconfig-002-20260708 clang-23
sh se7206_defconfig gcc-16.1.0
sparc allnoconfig clang-23
sparc defconfig gcc-16.1.0
sparc randconfig-001-20260708 gcc-8.5.0
sparc randconfig-002-20260708 gcc-8.5.0
sparc64 allmodconfig clang-20
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260708 gcc-8.5.0
sparc64 randconfig-002-20260708 gcc-8.5.0
um allmodconfig clang-17
um allnoconfig clang-23
um allyesconfig gcc-14
um allyesconfig gcc-16.1.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260708 gcc-8.5.0
um randconfig-002-20260708 gcc-8.5.0
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-22
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-22
x86_64 buildonly-randconfig-001-20260708 gcc-12
x86_64 buildonly-randconfig-002-20260708 gcc-12
x86_64 buildonly-randconfig-003-20260708 gcc-12
x86_64 buildonly-randconfig-004-20260708 gcc-12
x86_64 buildonly-randconfig-005-20260708 gcc-12
x86_64 buildonly-randconfig-006-20260708 gcc-12
x86_64 defconfig gcc-14
x86_64 kexec clang-22
x86_64 randconfig-001-20260708 gcc-14
x86_64 randconfig-002-20260708 gcc-14
x86_64 randconfig-003-20260708 gcc-14
x86_64 randconfig-004-20260708 gcc-14
x86_64 randconfig-005-20260708 gcc-14
x86_64 randconfig-006-20260708 gcc-14
x86_64 randconfig-011-20260708 clang-22
x86_64 randconfig-012-20260708 clang-22
x86_64 randconfig-013-20260708 clang-22
x86_64 randconfig-014-20260708 clang-22
x86_64 randconfig-015-20260708 clang-22
x86_64 randconfig-016-20260708 clang-22
x86_64 randconfig-071-20260708 clang-22
x86_64 randconfig-072-20260708 clang-22
x86_64 randconfig-073-20260708 clang-22
x86_64 randconfig-074-20260708 clang-22
x86_64 randconfig-075-20260708 clang-22
x86_64 randconfig-076-20260708 clang-22
x86_64 rhel-9.4 clang-22
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-22
x86_64 rhel-9.4-kselftests clang-22
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-22
xtensa allnoconfig clang-23
xtensa allyesconfig clang-20
xtensa allyesconfig gcc-16.1.0
xtensa randconfig-001-20260708 gcc-8.5.0
xtensa randconfig-002-20260708 gcc-8.5.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH v3] wifi: brcmfmac: add DPP support
From: Jason Huang @ 2026-07-08 3:58 UTC (permalink / raw)
To: linux-wireless
Cc: brcm80211, brcm80211-dev-list.pdl, linux-kernel, arend.vanspriel,
Jason Huang, Kurt Lee, Copilot
In-Reply-To: <20260604034227.590951-1-Jason.Huang2@infineon.com>
From: Jason Huang <jason.huang2@infineon.com>
Add DPP AKM handling and RSN parsing support. Map DPP to the
firmware wpa_auth value and recognize DPP public action frames in the
P2P action-frame TX path.
Allow non-P2P public action frames such as DPP to use the primary vif
when a P2P device vif is not present. Guard P2P-device IE access for
the same case.
Gate sup_wpa programming on firmware supplicant capability. Disable it
only when the selected connection mode does not use firmware supplicant.
This keeps pure SAE and 802.1X firmware-supplicant paths intact while
avoiding stale firmware supplicant state for DPP.
Signed-off-by: Kurt Lee <kurt.lee@cypress.com>
Signed-off-by: Jason Huang <jason.huang2@infineon.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 151 ++++++++++--------
.../broadcom/brcm80211/brcmfmac/p2p.c | 59 +++++--
.../broadcom/brcm80211/include/brcmu_wifi.h | 2 +
3 files changed, 134 insertions(+), 78 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 4b70845e1a26..d61c3e03a106 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
+#include <linux/unaligned.h>
#include <linux/vmalloc.h>
#include <net/cfg80211.h>
#include <net/netlink.h>
@@ -2154,6 +2155,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
profile->is_ft = true;
break;
+ case WLAN_AKM_SUITE_WFA_DPP:
+ val = WFA_AUTH_DPP;
+ break;
default:
bphy_err(drvr, "invalid akm suite (%d)\n",
sme->crypto.akm_suites[0]);
@@ -2466,43 +2470,50 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
goto done;
}
- if (sme->crypto.psk &&
- profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {
- if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
- err = -EINVAL;
- goto done;
- }
- brcmf_dbg(INFO, "using PSK offload\n");
- profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
- }
-
- if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
- /* enable firmware supplicant for this interface */
- err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
- if (err < 0) {
- bphy_err(drvr, "failed to enable fw supplicant\n");
- goto done;
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {
+ u32 akm = sme->crypto.n_akm_suites ? sme->crypto.akm_suites[0] : 0;
+ bool is_sae_akm = akm == WLAN_AKM_SUITE_SAE ||
+ akm == WLAN_AKM_SUITE_FT_OVER_SAE;
+
+ if (sme->crypto.psk && !is_sae_akm &&
+ profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {
+ if (WARN_ON(profile->use_fwsup !=
+ BRCMF_PROFILE_FWSUP_NONE)) {
+ err = -EINVAL;
+ goto done;
+ }
+ brcmf_dbg(INFO, "using PSK offload\n");
+ profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
}
- }
-
- if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK)
- err = brcmf_set_pmk(ifp, sme->crypto.psk,
- BRCMF_WSEC_MAX_PSK_LEN);
- else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) {
- /* clean up user-space RSNE */
- err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0);
- if (err) {
- bphy_err(drvr, "failed to clean up user-space RSNE\n");
- goto done;
+ if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
+ /* enable firmware supplicant for this interface */
+ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
+ if (err < 0) {
+ bphy_err(drvr, "failed to enable fw supplicant\n");
+ goto done;
+ }
+ } else {
+ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0);
}
- err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto);
- if (!err && sme->crypto.psk)
+ if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK)
err = brcmf_set_pmk(ifp, sme->crypto.psk,
BRCMF_WSEC_MAX_PSK_LEN);
+ else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE &&
+ sme->crypto.sae_pwd &&
+ brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE)) {
+ /* clean up user-space RSNE */
+ if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) {
+ bphy_err(drvr, "failed to clean up user-space RSNE\n");
+ goto done;
+ }
+ err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto);
+ if (!err && sme->crypto.psk)
+ err = brcmf_set_pmk(ifp, sme->crypto.psk,
+ BRCMF_WSEC_MAX_PSK_LEN);
+ }
+ if (err)
+ goto done;
}
- if (err)
- goto done;
-
/* Join with specific BSSID and cached SSID
* If SSID is zero join based on BSSID only
*/
@@ -4519,6 +4530,11 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
}
+static bool brcmf_valid_dpp_suite(u8 *oui)
+{
+ return get_unaligned_be32(oui) == WLAN_AKM_SUITE_WFA_DPP;
+}
+
static s32
brcmf_configure_wpaie(struct brcmf_if *ifp,
const struct brcmf_vs_tlv *wpa_ie,
@@ -4632,42 +4648,47 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
goto exit;
}
for (i = 0; i < count; i++) {
- if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+ if (brcmf_valid_dpp_suite(&data[offset])) {
+ wpa_auth |= WFA_AUTH_DPP;
+ offset += TLV_OUI_LEN;
+ } else if (brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+ offset += TLV_OUI_LEN;
+ switch (data[offset]) {
+ case RSN_AKM_NONE:
+ brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
+ wpa_auth |= WPA_AUTH_NONE;
+ break;
+ case RSN_AKM_UNSPECIFIED:
+ brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
+ is_rsn_ie ?
+ (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
+ (wpa_auth |= WPA_AUTH_UNSPECIFIED);
+ break;
+ case RSN_AKM_PSK:
+ brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
+ is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
+ (wpa_auth |= WPA_AUTH_PSK);
+ break;
+ case RSN_AKM_SHA256_PSK:
+ brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");
+ wpa_auth |= WPA2_AUTH_PSK_SHA256;
+ break;
+ case RSN_AKM_SHA256_1X:
+ brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
+ wpa_auth |= WPA2_AUTH_1X_SHA256;
+ break;
+ case RSN_AKM_SAE:
+ brcmf_dbg(TRACE, "RSN_AKM_SAE\n");
+ wpa_auth |= WPA3_AUTH_SAE_PSK;
+ break;
+ default:
+ bphy_err(drvr, "Invalid key mgmt info\n");
+ }
+ } else {
err = -EINVAL;
bphy_err(drvr, "invalid OUI\n");
goto exit;
}
- offset += TLV_OUI_LEN;
- switch (data[offset]) {
- case RSN_AKM_NONE:
- brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
- wpa_auth |= WPA_AUTH_NONE;
- break;
- case RSN_AKM_UNSPECIFIED:
- brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
- is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
- (wpa_auth |= WPA_AUTH_UNSPECIFIED);
- break;
- case RSN_AKM_PSK:
- brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
- is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
- (wpa_auth |= WPA_AUTH_PSK);
- break;
- case RSN_AKM_SHA256_PSK:
- brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");
- wpa_auth |= WPA2_AUTH_PSK_SHA256;
- break;
- case RSN_AKM_SHA256_1X:
- brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
- wpa_auth |= WPA2_AUTH_1X_SHA256;
- break;
- case RSN_AKM_SAE:
- brcmf_dbg(TRACE, "RSN_AKM_SAE\n");
- wpa_auth |= WPA3_AUTH_SAE_PSK;
- break;
- default:
- bphy_err(drvr, "Invalid key mgmt info\n");
- }
offset++;
}
@@ -4687,10 +4708,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp,
*/
if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 |
WPA2_AUTH_1X_SHA256 |
+ WFA_AUTH_DPP |
WPA3_AUTH_SAE_PSK))) {
err = -EINVAL;
goto exit;
}
+
/* Firmware has requirement that WPA2_AUTH_PSK/
* WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI
* is to be included in the rsn ie.
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 6e0c90f4718b..2c1f52ed5138 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -6,6 +6,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
+#include <linux/unaligned.h>
#include <net/cfg80211.h>
#include <brcmu_wifi.h>
@@ -44,9 +45,6 @@
#define BRCMF_SCB_TIMEOUT_VALUE 20
-#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */
-#define P2P_PUB_AF_CATEGORY 0x04
-#define P2P_PUB_AF_ACTION 0x09
#define P2P_AF_CATEGORY 0x7f
#define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */
#define P2P_OUI_LEN 3 /* P2P OUI length */
@@ -143,10 +141,10 @@ struct brcmf_p2p_scan_le {
/**
* struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame
*
- * @category: P2P_PUB_AF_CATEGORY
- * @action: P2P_PUB_AF_ACTION
+ * @category: WLAN_CATEGORY_PUBLIC
+ * @action: WLAN_PUB_ACTION_VENDOR_SPECIFIC
* @oui: P2P_OUI
- * @oui_type: OUI type - P2P_VER
+ * @oui_type: OUI type - WLAN_OUI_TYPE_WFA_P2P
* @subtype: OUI subtype - P2P_TYPE_*
* @dialog_token: nonzero, identifies req/rsp transaction
* @elts: Variable length information elements.
@@ -166,7 +164,7 @@ struct brcmf_p2p_pub_act_frame {
*
* @category: P2P_AF_CATEGORY
* @oui: OUI - P2P_OUI
- * @type: OUI Type - P2P_VER
+ * @type: OUI Type - WLAN_OUI_TYPE_WFA_P2P
* @subtype: OUI Subtype - P2P_AF_*
* @dialog_token: nonzero, identifies req/resp tranaction
* @elts: Variable length information elements.
@@ -228,10 +226,38 @@ static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len)
if (frame_len < sizeof(*pact_frm))
return false;
- if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
- pact_frm->action == P2P_PUB_AF_ACTION &&
- pact_frm->oui_type == P2P_VER &&
- memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
+ if (pact_frm->category == WLAN_CATEGORY_PUBLIC &&
+ pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC &&
+ pact_frm->oui_type == WLAN_OUI_TYPE_WFA_P2P &&
+ get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA)
+ return true;
+
+ return false;
+}
+
+/**
+ * brcmf_p2p_is_dpp_pub_action() - true if dpp public type frame.
+ *
+ * @frame: action frame data.
+ * @frame_len: length of action frame data.
+ *
+ * Determine if action frame is dpp public action type
+ */
+static bool brcmf_p2p_is_dpp_pub_action(void *frame, u32 frame_len)
+{
+ struct brcmf_p2p_pub_act_frame *pact_frm;
+
+ if (!frame)
+ return false;
+
+ pact_frm = (struct brcmf_p2p_pub_act_frame *)frame;
+ if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1)
+ return false;
+
+ if (pact_frm->category == WLAN_CATEGORY_PUBLIC &&
+ pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC &&
+ pact_frm->oui_type == WLAN_OUI_TYPE_WFA_DPP &&
+ get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA)
return true;
return false;
@@ -257,7 +283,7 @@ static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len)
return false;
if (act_frm->category == P2P_AF_CATEGORY &&
- act_frm->type == P2P_VER &&
+ act_frm->type == WLAN_OUI_TYPE_WFA_P2P &&
memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
return true;
@@ -1281,6 +1307,9 @@ static s32 brcmf_p2p_abort_action_frame(struct brcmf_cfg80211_info *cfg)
brcmf_dbg(TRACE, "Enter\n");
vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+ if (!vif)
+ vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+
err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val,
sizeof(s32));
if (err)
@@ -1789,7 +1818,9 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
goto exit;
}
} else if (brcmf_p2p_is_p2p_action(action_frame->data,
- action_frame_len)) {
+ action_frame_len) ||
+ brcmf_p2p_is_dpp_pub_action(action_frame->data,
+ action_frame_len)) {
/* do not configure anything. it will be */
/* sent with a default configuration */
} else {
@@ -1826,6 +1857,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
/* validate channel and p2p ies */
if (config_af_params.search_channel &&
IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) &&
+ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif &&
p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) {
afx_hdl = &p2p->afx_hdl;
afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel);
@@ -2543,4 +2575,3 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
/* just set it all to zero */
memset(p2p, 0, sizeof(*p2p));
}
-
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
index 7552bdb91991..c465208c4331 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
@@ -233,6 +233,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
#define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */
+#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */
+
#define DOT11_DEFAULT_RTS_LEN 2347
#define DOT11_DEFAULT_FRAG_LEN 2346
base-commit: 3737936e2be920977aea7d9f7eb8cb4468d700d7
--
2.25.1
^ permalink raw reply related
* [PATCH v2] wifi: cfg80211: BUG on runaway wiphy work drains
From: Cen Zhang @ 2026-07-08 3:14 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, baijiaju1990, zzzccc427
cfg80211_process_wiphy_works() currently tries to recover from a
runaway drain by reinitializing rdev->wiphy_work_list. That avoids
walking the list any further, but it can strand valid owner-embedded work
entries with stale list links. Trying to fix that by walking the
remaining list is not safe either, because the guard may have fired after
list corruption or accidental work reinitialization.
Stop trying to recover from this state. Raise the limit to 30000
iterations so ordinary long drains have much more headroom, and BUG() if
the guard still fires. At that point the code cannot reliably tell a
self-requeueing work loop from a corrupted list, and continuing risks
either silently losing work or touching corrupted links.
Fixes: a3ee4dc84c4e ("wifi: cfg80211: add a work abstraction with special semantics")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
v2:
- Raise the runaway limit to 30000 and BUG() if it is still hit.
- Drop the per-entry drain so the fallback does not walk a possibly
corrupted list.
net/wireless/core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 3dcf63b04c41..9a4d022f8838 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1256,7 +1256,7 @@ EXPORT_SYMBOL(wiphy_rfkill_start_polling);
void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev,
struct wiphy_work *end)
{
- unsigned int runaway_limit = 100;
+ unsigned int runaway_limit = 30000;
unsigned long flags;
lockdep_assert_held(&rdev->wiphy.mtx);
@@ -1278,8 +1278,8 @@ void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev,
if (wk == end)
break;
- if (WARN_ON(--runaway_limit == 0))
- INIT_LIST_HEAD(&rdev->wiphy_work_list);
+ if (--runaway_limit == 0)
+ BUG();
}
spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags);
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] wifi: cfg80211: reinit wiphy work entries on runaway drain
From: Cen Zhang @ 2026-07-08 3:04 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, baijiaju1990
In-Reply-To: <bf10372fba8d1ce8503d01106a7adf2313f48381.camel@sipsolutions.net>
Hi Johannes,
Thanks for your review and explanation.
> Yeah ... that's not ideal, but also maybe part of the point. IIRC we've
> seen cases where works are accidentally re-initialised and we get into
> infinite loops iterating the list, or so.
>
> So if everything else goes according to plan, your fix is certainly
> correct. If we get some kind of list corruption in the first place, then
> it's potentially going to make it worse.
Fair enough, thanks.
> Maybe at this point it's just worth bumping it to a few tens of thousand
> iterations and doing BUG()? I don't think loop detection is simple here.
I'll respin v2 with a much higher limit and BUG() if it is still hit.
Best regards,
Cen Zhang
^ permalink raw reply
* pull request: mm81x-driver-08-07-2026
From: Lachlan Hodges @ 2026-07-08 2:30 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, arien.judge, ayman.grais, dan.callaghan
The following changes since commit ac798f757d6475dc6fee2ec899980d6740714596:
wifi: mac80211: Route (Re)association req/response to per-STA queue (2026-07-07 10:16:31 +0200)
are available in the Git repository at:
https://github.com/MorseMicro/linux.git tags/mm81x-driver-08-07-2026
for you to fetch changes up to b1906cea00b021acea22460225401d5b27bc7c36:
wifi: mm81x: add mm81x Wi-Fi HaLow driver (2026-07-08 12:03:50 +1000)
----------------------------------------------------------------
Introduce mm81x driver for mm81x based chipsets plus associated
SDIO ids.
----------------------------------------------------------------
Lachlan Hodges (2):
mmc: sdio: add Morse Micro vendor ids
wifi: mm81x: add mm81x Wi-Fi HaLow driver
MAINTAINERS | 8 +
drivers/net/wireless/Kconfig | 1 +
drivers/net/wireless/Makefile | 1 +
drivers/net/wireless/morsemicro/Kconfig | 15 +
drivers/net/wireless/morsemicro/Makefile | 2 +
drivers/net/wireless/morsemicro/mm81x/Kconfig | 24 +
drivers/net/wireless/morsemicro/mm81x/Makefile | 21 +
drivers/net/wireless/morsemicro/mm81x/bus.h | 99 +
drivers/net/wireless/morsemicro/mm81x/command.c | 563 +++++
drivers/net/wireless/morsemicro/mm81x/command.h | 85 +
.../net/wireless/morsemicro/mm81x/command_defs.h | 1658 +++++++++++++
drivers/net/wireless/morsemicro/mm81x/core.c | 138 ++
drivers/net/wireless/morsemicro/mm81x/core.h | 456 ++++
drivers/net/wireless/morsemicro/mm81x/fw.c | 752 ++++++
drivers/net/wireless/morsemicro/mm81x/fw.h | 143 ++
drivers/net/wireless/morsemicro/mm81x/hif.h | 117 +
drivers/net/wireless/morsemicro/mm81x/hw.c | 367 +++
drivers/net/wireless/morsemicro/mm81x/hw.h | 159 ++
drivers/net/wireless/morsemicro/mm81x/mac.c | 2443 ++++++++++++++++++++
drivers/net/wireless/morsemicro/mm81x/mac.h | 63 +
drivers/net/wireless/morsemicro/mm81x/mmrc.c | 1354 +++++++++++
drivers/net/wireless/morsemicro/mm81x/mmrc.h | 193 ++
drivers/net/wireless/morsemicro/mm81x/ps.c | 120 +
drivers/net/wireless/morsemicro/mm81x/ps.h | 22 +
drivers/net/wireless/morsemicro/mm81x/rate_code.h | 177 ++
drivers/net/wireless/morsemicro/mm81x/rc.c | 494 ++++
drivers/net/wireless/morsemicro/mm81x/rc.h | 51 +
drivers/net/wireless/morsemicro/mm81x/sdio.c | 613 +++++
drivers/net/wireless/morsemicro/mm81x/skbq.c | 1064 +++++++++
drivers/net/wireless/morsemicro/mm81x/skbq.h | 218 ++
drivers/net/wireless/morsemicro/mm81x/usb.c | 943 ++++++++
drivers/net/wireless/morsemicro/mm81x/yaps.c | 704 ++++++
drivers/net/wireless/morsemicro/mm81x/yaps.h | 77 +
drivers/net/wireless/morsemicro/mm81x/yaps_hw.c | 702 ++++++
drivers/net/wireless/morsemicro/mm81x/yaps_hw.h | 52 +
include/linux/mmc/sdio_ids.h | 3 +
36 files changed, 13902 insertions(+)
create mode 100644 drivers/net/wireless/morsemicro/Kconfig
create mode 100644 drivers/net/wireless/morsemicro/Makefile
create mode 100644 drivers/net/wireless/morsemicro/mm81x/Kconfig
create mode 100644 drivers/net/wireless/morsemicro/mm81x/Makefile
create mode 100644 drivers/net/wireless/morsemicro/mm81x/bus.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/command.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/command.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/command_defs.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/core.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/core.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/fw.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/fw.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/hif.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/hw.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/hw.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/mac.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/mac.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/mmrc.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/mmrc.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/ps.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/ps.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/rate_code.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/rc.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/rc.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/sdio.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/skbq.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/skbq.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/usb.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/yaps.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/yaps.h
create mode 100644 drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
create mode 100644 drivers/net/wireless/morsemicro/mm81x/yaps_hw.h
^ permalink raw reply
* RE: [BUG] rtw89: RTL8852CE RX_DCK timeout + Bluetooth A2DP coexistence failures (fw-2.bin 0.27.129.4)
From: Ping-Ke Shih @ 2026-07-08 0:54 UTC (permalink / raw)
To: or1k, linux-wireless@vger.kernel.org, kvalo@kernel.org
In-Reply-To: <OduUSxVfSVayC9OVEeIrxw@gmail.com>
or1k <tixzit@gmail.com> wrote:
> Hi,
>
> Reporting a Wi-Fi/Bluetooth coexistence issue on RTL8852CE that also has an
> open Fedora/Red Hat tracker (bugzilla.redhat.com #2349675), but that report
> was filed against an older firmware (rtw8852c_fw-1.bin, 0.27.97.0). I'm
> seeing what looks like the same class of failure on the newer
> rtw8852c_fw-2.bin, firmware version 0.27.129.4 (3f1a5302), so it may not be
> fully fixed by whatever changed between those firmware revisions.
We are working on driver to support the new firmware (0.27.129.4), and
I expected to land the patches on 7.3.
I'd clarify that does 0.27.97.0 work to you?
>
> Hardware:
> Wi-Fi: Realtek RTL8852CE [10ec:c852] rev 01, Lenovo subsystem
> [17aa:5852]
> PCI 0000:02:00.0, driver rtw89_8852ce
> Bluetooth: same combo chip, USB 0bda:5852 "Realtek Bluetooth Radio",
> driver btusb/btrtl, BT firmware rtl8852cu_fw_v2.bin (0x040d7225)
> Platform: Lenovo laptop, AMD Ryzen APU (unrelated to this bug, just for
> context — ruled out as a factor)
>
> Software:
> Kernel 7.1.3-200.fc44.x86_64 (Fedora 44), linux-firmware-20260622-1.fc44
>
> Symptom: intermittent Wi-Fi disconnects/reauth together with Bluetooth A2DP
> audio transport failures, both traced to the same physical combo chip.
>
> dmesg (Wi-Fi side), recurring several times/day in short clusters:
>
> rtw89_8852ce 0000:02:00.0: [RX_DCK] S1 RXDCK timeout
> rtw89_8852ce 0000:02:00.0: timed out to flush queues
>
> journalctl (Bluetooth side), same time frame, device 85:42:36:51:B1:D1
> (Bluetooth headphones, A2DP sink):
>
> wireplumber: spa.bluez5.sink.media: Misscket
> (0 suppressed): Bluetooth adapter firm
> bluetoothd: src/profile.c:ext_io_disconn for
> Hands-Free Voice gateway: getpeername:
> connected (107)
> wireplumber: spa.bluez5: Failure in Bluetooth audio transport
> /org/bluez/hci0/dev_85_42_36_51_B1_D1/
>
> Direct correlation captured with mtr: a WireGuard-tunneled ping test
> (ultimately routed over wlp2s0) showed 5.9 the
> same ~60s window as 8 consecutive "Missingines
> for the same device (00:12:51) and an HFP 1).
> Both radios degraded together, which pointmware
> fault rather than two unrelated bugs.
>
> Workarounds tried, partial effect only:
> - USB autosuspend disabled for the BT ad
> - rtw89_core.disable_ps_mode=1, rtw89_pc
> - A2DP codec forced to SBC instead of AA
>
> Is this expected to be covered by the same fix path as RH#2349675, or is it
> worth tracking separately since it reprodu?
Can you explain what RH#2349675 is?
> Happy to test candidate firmware/patches o
I will share the patches when they get ready (I suppose it will be
in one or two weeks).
Ping-Ke
^ permalink raw reply
* [wireless-next:main] BUILD SUCCESS ac798f757d6475dc6fee2ec899980d6740714596
From: kernel test robot @ 2026-07-07 23:10 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
branch HEAD: ac798f757d6475dc6fee2ec899980d6740714596 wifi: mac80211: Route (Re)association req/response to per-STA queue
elapsed time: 874m
configs tested: 224
configs skipped: 59
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-16.1.0
alpha allyesconfig gcc-16.1.0
alpha defconfig gcc-16.1.0
arc alldefconfig gcc-16.1.0
arc allmodconfig clang-23
arc allmodconfig gcc-16.1.0
arc allnoconfig gcc-16.1.0
arc allyesconfig clang-23
arc allyesconfig gcc-16.1.0
arc defconfig gcc-16.1.0
arc randconfig-001-20260708 gcc-13.4.0
arc randconfig-002-20260708 gcc-13.4.0
arm allnoconfig clang-17
arm allnoconfig gcc-16.1.0
arm allyesconfig clang-23
arm allyesconfig gcc-16.1.0
arm defconfig gcc-16.1.0
arm randconfig-001-20260708 gcc-13.4.0
arm randconfig-002-20260708 gcc-13.4.0
arm randconfig-003-20260708 gcc-13.4.0
arm randconfig-004-20260708 gcc-13.4.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
arm64 defconfig gcc-16.1.0
arm64 randconfig-001-20260708 clang-23
arm64 randconfig-001-20260708 gcc-9.5.0
arm64 randconfig-002-20260708 clang-23
arm64 randconfig-002-20260708 gcc-9.5.0
arm64 randconfig-003-20260708 gcc-9.5.0
arm64 randconfig-004-20260708 gcc-15.2.0
arm64 randconfig-004-20260708 gcc-9.5.0
csky allmodconfig gcc-16.1.0
csky allnoconfig gcc-16.1.0
csky defconfig gcc-16.1.0
csky randconfig-001-20260708 gcc-9.5.0
csky randconfig-002-20260708 gcc-9.5.0
hexagon allmodconfig clang-23
hexagon allmodconfig gcc-16.1.0
hexagon allnoconfig gcc-16.1.0
hexagon defconfig gcc-16.1.0
hexagon randconfig-001-20260707 clang-18
hexagon randconfig-001-20260708 gcc-13.4.0
hexagon randconfig-002-20260707 clang-18
hexagon randconfig-002-20260708 gcc-13.4.0
i386 allmodconfig clang-22
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allnoconfig gcc-16.1.0
i386 allyesconfig clang-22
i386 allyesconfig gcc-14
i386 buildonly-randconfig-001-20260707 clang-22
i386 buildonly-randconfig-001-20260708 clang-22
i386 buildonly-randconfig-002-20260707 clang-22
i386 buildonly-randconfig-002-20260708 clang-22
i386 buildonly-randconfig-003-20260707 clang-22
i386 buildonly-randconfig-003-20260708 clang-22
i386 buildonly-randconfig-004-20260707 clang-22
i386 buildonly-randconfig-004-20260708 clang-22
i386 buildonly-randconfig-005-20260707 clang-22
i386 buildonly-randconfig-005-20260708 clang-22
i386 buildonly-randconfig-006-20260707 clang-22
i386 buildonly-randconfig-006-20260708 clang-22
i386 defconfig gcc-16.1.0
i386 randconfig-001-20260708 clang-22
i386 randconfig-002-20260708 clang-22
i386 randconfig-003-20260708 clang-22
i386 randconfig-004-20260708 clang-22
i386 randconfig-005-20260708 clang-22
i386 randconfig-006-20260708 clang-22
i386 randconfig-007-20260708 clang-22
i386 randconfig-011 gcc-14
i386 randconfig-011-20260707 gcc-14
i386 randconfig-012 gcc-14
i386 randconfig-012-20260707 gcc-14
i386 randconfig-013 gcc-14
i386 randconfig-013-20260707 gcc-14
i386 randconfig-014 gcc-14
i386 randconfig-014-20260707 gcc-14
i386 randconfig-015 gcc-14
i386 randconfig-015-20260707 gcc-14
i386 randconfig-016 gcc-14
i386 randconfig-016-20260707 gcc-14
i386 randconfig-017 gcc-14
i386 randconfig-017-20260707 gcc-14
loongarch allmodconfig clang-19
loongarch allmodconfig clang-23
loongarch allnoconfig gcc-16.1.0
loongarch defconfig clang-23
loongarch randconfig-001-20260707 clang-18
loongarch randconfig-001-20260708 gcc-13.4.0
loongarch randconfig-002-20260707 clang-18
loongarch randconfig-002-20260708 gcc-13.4.0
m68k allmodconfig gcc-16.1.0
m68k allnoconfig gcc-16.1.0
m68k allyesconfig clang-23
m68k allyesconfig gcc-16.1.0
m68k defconfig clang-23
microblaze allnoconfig gcc-16.1.0
microblaze allyesconfig gcc-16.1.0
microblaze defconfig clang-23
mips allmodconfig gcc-16.1.0
mips allnoconfig gcc-16.1.0
mips allyesconfig gcc-16.1.0
nios2 allmodconfig clang-20
nios2 allnoconfig clang-23
nios2 allnoconfig gcc-11.5.0
nios2 defconfig clang-23
nios2 randconfig-001-20260707 clang-18
nios2 randconfig-001-20260708 gcc-13.4.0
nios2 randconfig-002-20260707 clang-18
nios2 randconfig-002-20260708 gcc-13.4.0
openrisc allmodconfig clang-20
openrisc allnoconfig clang-23
openrisc allnoconfig gcc-16.1.0
openrisc defconfig gcc-16.1.0
parisc allmodconfig gcc-16.1.0
parisc allnoconfig clang-23
parisc allnoconfig gcc-16.1.0
parisc allyesconfig clang-17
parisc allyesconfig gcc-16.1.0
parisc defconfig gcc-16.1.0
parisc randconfig-001-20260707 clang-22
parisc randconfig-001-20260708 clang-22
parisc randconfig-002-20260707 clang-22
parisc randconfig-002-20260708 clang-22
parisc64 defconfig clang-23
powerpc allmodconfig gcc-16.1.0
powerpc allnoconfig clang-23
powerpc allnoconfig gcc-16.1.0
powerpc bamboo_defconfig clang-21
powerpc randconfig-001-20260707 clang-22
powerpc randconfig-001-20260708 clang-22
powerpc randconfig-002-20260707 clang-22
powerpc randconfig-002-20260708 clang-22
powerpc64 randconfig-001-20260707 clang-22
powerpc64 randconfig-001-20260708 clang-22
powerpc64 randconfig-002-20260707 clang-22
powerpc64 randconfig-002-20260708 clang-22
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allnoconfig gcc-16.1.0
riscv allyesconfig clang-23
riscv defconfig gcc-16.1.0
riscv randconfig-001-20260708 clang-23
riscv randconfig-002-20260708 clang-23
s390 allmodconfig clang-17
s390 allmodconfig clang-23
s390 allnoconfig clang-23
s390 allyesconfig gcc-16.1.0
s390 defconfig gcc-16.1.0
s390 randconfig-001-20260708 clang-23
s390 randconfig-002-20260708 clang-23
sh allmodconfig gcc-16.1.0
sh allnoconfig clang-23
sh allnoconfig gcc-16.1.0
sh allyesconfig clang-17
sh allyesconfig gcc-16.1.0
sh defconfig gcc-14
sh randconfig-001-20260708 clang-23
sh randconfig-002-20260708 clang-23
sparc allnoconfig clang-23
sparc allnoconfig gcc-16.1.0
sparc defconfig gcc-16.1.0
sparc randconfig-001-20260708 gcc-8.5.0
sparc randconfig-002-20260708 gcc-8.5.0
sparc64 allmodconfig clang-20
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260708 gcc-8.5.0
sparc64 randconfig-002-20260708 gcc-8.5.0
um allmodconfig clang-17
um allnoconfig clang-17
um allnoconfig clang-23
um allyesconfig gcc-14
um allyesconfig gcc-16.1.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260708 gcc-8.5.0
um randconfig-002-20260708 gcc-8.5.0
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-22
x86_64 allnoconfig clang-22
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-22
x86_64 buildonly-randconfig-001-20260708 gcc-12
x86_64 buildonly-randconfig-002-20260708 gcc-12
x86_64 buildonly-randconfig-003-20260708 gcc-12
x86_64 buildonly-randconfig-004-20260708 gcc-12
x86_64 buildonly-randconfig-005-20260708 gcc-12
x86_64 buildonly-randconfig-006-20260708 gcc-12
x86_64 defconfig gcc-14
x86_64 randconfig-001-20260708 gcc-14
x86_64 randconfig-002-20260708 gcc-14
x86_64 randconfig-003-20260708 gcc-14
x86_64 randconfig-004-20260708 gcc-14
x86_64 randconfig-005-20260708 gcc-14
x86_64 randconfig-006-20260708 gcc-14
x86_64 randconfig-011-20260707 clang-22
x86_64 randconfig-011-20260708 clang-22
x86_64 randconfig-012-20260707 clang-22
x86_64 randconfig-012-20260708 clang-22
x86_64 randconfig-013-20260707 clang-22
x86_64 randconfig-013-20260708 clang-22
x86_64 randconfig-014-20260707 clang-22
x86_64 randconfig-014-20260708 clang-22
x86_64 randconfig-015-20260707 clang-22
x86_64 randconfig-015-20260708 clang-22
x86_64 randconfig-016-20260707 clang-22
x86_64 randconfig-016-20260708 clang-22
x86_64 randconfig-071-20260708 clang-22
x86_64 randconfig-072-20260708 clang-22
x86_64 randconfig-073-20260708 clang-22
x86_64 randconfig-074-20260708 clang-22
x86_64 randconfig-075-20260708 clang-22
x86_64 randconfig-076-20260708 clang-22
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-22
xtensa allnoconfig clang-23
xtensa allnoconfig gcc-16.1.0
xtensa allyesconfig clang-20
xtensa iss_defconfig gcc-16.1.0
xtensa randconfig-001-20260708 gcc-8.5.0
xtensa randconfig-002-20260708 gcc-8.5.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [BUG] rtw89: RTL8852CE RX_DCK timeout + Bluetooth A2DP coexistence failures (fw-2.bin 0.27.129.4)
From: or1k @ 2026-07-07 21:59 UTC (permalink / raw)
To: linux-wireless, pkshih, kvalo
Hi,
Reporting a Wi-Fi/Bluetooth coexistence issue on RTL8852CE that also has an
open Fedora/Red Hat tracker (bugzilla.redhat.com #2349675), but that report
was filed against an older firmware (rtw8852c_fw-1.bin, 0.27.97.0). I'm
seeing what looks like the same class of failure on the newer
rtw8852c_fw-2.bin, firmware version 0.27.129.4 (3f1a5302), so it may not be
fully fixed by whatever changed between those firmware revisions.
Hardware:
Wi-Fi: Realtek RTL8852CE [10ec:c852] rev 01, Lenovo subsystem
[17aa:5852]
PCI 0000:02:00.0, driver rtw89_8852ce
Bluetooth: same combo chip, USB 0bda:5852 "Realtek Bluetooth Radio",
driver btusb/btrtl, BT firmware rtl8852cu_fw_v2.bin (0x040d7225)
Platform: Lenovo laptop, AMD Ryzen APU (unrelated to this bug, just for
context — ruled out as a factor)
Software:
Kernel 7.1.3-200.fc44.x86_64 (Fedora 44), linux-firmware-20260622-1.fc44
Symptom: intermittent Wi-Fi disconnects/reauth together with Bluetooth A2DP
audio transport failures, both traced to the same physical combo chip.
dmesg (Wi-Fi side), recurring several times/day in short clusters:
rtw89_8852ce 0000:02:00.0: [RX_DCK] S1 RXDCK timeout
rtw89_8852ce 0000:02:00.0: timed out to flush queues
journalctl (Bluetooth side), same time frame, device 85:42:36:51:B1:D1
(Bluetooth headphones, A2DP sink):
wireplumber: spa.bluez5.sink.media: Misscket
(0 suppressed): Bluetooth adapter firm
bluetoothd: src/profile.c:ext_io_disconn for
Hands-Free Voice gateway: getpeername:
connected (107)
wireplumber: spa.bluez5: Failure in Bluetooth audio transport
/org/bluez/hci0/dev_85_42_36_51_B1_D1/
Direct correlation captured with mtr: a WireGuard-tunneled ping test
(ultimately routed over wlp2s0) showed 5.9 the
same ~60s window as 8 consecutive "Missingines
for the same device (00:12:51) and an HFP 1).
Both radios degraded together, which pointmware
fault rather than two unrelated bugs.
Workarounds tried, partial effect only:
- USB autosuspend disabled for the BT ad
- rtw89_core.disable_ps_mode=1, rtw89_pc
- A2DP codec forced to SBC instead of AA
Is this expected to be covered by the same fix path as RH#2349675, or is it
worth tracking separately since it reprodu?
Happy to test candidate firmware/patches o
Thanks,
Oleh
^ permalink raw reply
* Re: [PATCH] wifi: cfg80211: reinit wiphy work entries on runaway drain
From: Johannes Berg @ 2026-07-07 17:31 UTC (permalink / raw)
To: Cen Zhang; +Cc: linux-wireless, baijiaju1990
In-Reply-To: <20260707134925.106972-1-zzzccc427@gmail.com>
On Tue, 2026-07-07 at 21:49 +0800, Cen Zhang wrote:
> cfg80211_process_wiphy_works() has a runaway guard for the process-all
> case. When the guard fires, it drops the remaining queued work by
> reinitializing rdev->wiphy_work_list.
>
> That only resets the list head. The queued struct wiphy_work entries are
> embedded in their owners, and their entry fields still point at the old
> list neighbors. Later queue or cancel checks can then see a work item as
> listed even though the rdev list has been cleared.
Yeah ... that's not ideal, but also maybe part of the point. IIRC we've
seen cases where works are accidentally re-initialised and we get into
infinite loops iterating the list, or so.
So if everything else goes according to plan, your fix is certainly
correct. If we get some kind of list corruption in the first place, then
it's potentially going to make it worse.
Maybe at this point it's just worth bumping it to a few tens of thousand
iterations and doing BUG()? I don't think loop detection is simple here.
johannes
^ permalink raw reply
* Re: [PATCH v1 07/12] nfc: Drop __maybe_unused from of_device_id tables
From: Krzysztof Kozlowski @ 2026-07-07 17:28 UTC (permalink / raw)
To: Uwe Kleine-König (The Capable Hub), David Heidelberg,
Mark Greer, Simon Horman, Tomasz Unger
Cc: oe-linux-nfc, linux-kernel, linux-wireless
In-Reply-To: <031ea0ae38838df3261f844eb13e9841769b49a7.1783091699.git.u.kleine-koenig@baylibre.com>
On 03/07/2026 17:46, Uwe Kleine-König (The Capable Hub) wrote:
> Referencing these arrays in MODULE_DEVICE_TABLE() is enough to convince
> the compiler that they are used even if the drivers are built-in (since
> 5ab23c7923a1 ("modpost: Create modalias for builtin modules"). So the
> __maybe_unused marking can be removed without introducing a compiler
> warning.
>
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> ---
> drivers/nfc/nfcmrvl/i2c.c | 2 +-
> drivers/nfc/nfcmrvl/spi.c | 2 +-
> drivers/nfc/pn533/i2c.c | 2 +-
> drivers/nfc/pn544/i2c.c | 2 +-
> drivers/nfc/s3fwrn5/i2c.c | 2 +-
> drivers/nfc/st-nci/i2c.c | 2 +-
> drivers/nfc/st-nci/spi.c | 2 +-
> drivers/nfc/st21nfca/i2c.c | 2 +-
> drivers/nfc/st95hf/core.c | 2 +-
> drivers/nfc/trf7970a.c | 2 +-
> 10 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
> index 66877a7d03f2..687d2979b881 100644
> --- a/drivers/nfc/nfcmrvl/i2c.c
> +++ b/drivers/nfc/nfcmrvl/i2c.c
> @@ -245,7 +245,7 @@ static void nfcmrvl_i2c_remove(struct i2c_client *client)
> }
>
>
> -static const struct of_device_id of_nfcmrvl_i2c_match[] __maybe_unused = {
> +static const struct of_device_id of_nfcmrvl_i2c_match[] = {
> { .compatible = "marvell,nfc-i2c", },
> {},
This (and probably others) should re-introduce warnings on !MODULE and
!OF builds (and other cases).
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v1 08/12] nfc: Unify style of of_device_id arrays
From: Ian Ray @ 2026-07-07 17:13 UTC (permalink / raw)
To: Uwe Kleine-König (The Capable Hub)
Cc: David Heidelberg, Krzysztof Kozlowski, Mark Greer, Carl Lee,
Jakub Kicinski, Paolo Abeni, Pengpeng Hou, Kees Cook,
Simon Horman, Tomasz Unger, oe-linux-nfc, linux-kernel,
linux-wireless
In-Reply-To: <583375dcd834f5edf6241b09cdd75ad4f32af668.1783091699.git.u.kleine-koenig@baylibre.com>
On Fri, Jul 03, 2026 at 05:46:22PM +0200, Uwe Kleine-König (The Capable Hub) wrote:
> The most common style treewide is:
>
> - A single space in the list terminator and no trailing ,
> - No comma after a named initializers iff the closing } is on the same
> line
>
> Adapt the of_device_id arrays accordingly.
>
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
Reviewed-by: Ian Ray <ian.ray@gehealthcare.com>
> ---
> drivers/nfc/nfcmrvl/i2c.c | 4 ++--
> drivers/nfc/nfcmrvl/spi.c | 4 ++--
> drivers/nfc/nxp-nci/i2c.c | 4 ++--
> drivers/nfc/pn533/i2c.c | 8 ++++----
> drivers/nfc/pn533/uart.c | 4 ++--
> drivers/nfc/pn544/i2c.c | 4 ++--
> drivers/nfc/s3fwrn5/i2c.c | 4 ++--
> drivers/nfc/s3fwrn5/uart.c | 4 ++--
> drivers/nfc/st-nci/i2c.c | 8 ++++----
> drivers/nfc/st-nci/spi.c | 4 ++--
> drivers/nfc/st21nfca/i2c.c | 6 +++---
> drivers/nfc/st95hf/core.c | 2 +-
> drivers/nfc/trf7970a.c | 5 ++---
> 13 files changed, 30 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
> index 687d2979b881..068c5d278a35 100644
> --- a/drivers/nfc/nfcmrvl/i2c.c
> +++ b/drivers/nfc/nfcmrvl/i2c.c
> @@ -246,8 +246,8 @@ static void nfcmrvl_i2c_remove(struct i2c_client *client)
>
>
> static const struct of_device_id of_nfcmrvl_i2c_match[] = {
> - { .compatible = "marvell,nfc-i2c", },
> - {},
> + { .compatible = "marvell,nfc-i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_nfcmrvl_i2c_match);
>
> diff --git a/drivers/nfc/nfcmrvl/spi.c b/drivers/nfc/nfcmrvl/spi.c
> index 8dd71fed8493..34842ecc4a05 100644
> --- a/drivers/nfc/nfcmrvl/spi.c
> +++ b/drivers/nfc/nfcmrvl/spi.c
> @@ -182,8 +182,8 @@ static void nfcmrvl_spi_remove(struct spi_device *spi)
> }
>
> static const struct of_device_id of_nfcmrvl_spi_match[] = {
> - { .compatible = "marvell,nfc-spi", },
> - {},
> + { .compatible = "marvell,nfc-spi" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_nfcmrvl_spi_match);
>
> diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
> index 39b43f8f3bf0..d424452934ec 100644
> --- a/drivers/nfc/nxp-nci/i2c.c
> +++ b/drivers/nfc/nxp-nci/i2c.c
> @@ -355,8 +355,8 @@ static const struct i2c_device_id nxp_nci_i2c_id_table[] = {
> MODULE_DEVICE_TABLE(i2c, nxp_nci_i2c_id_table);
>
> static const struct of_device_id of_nxp_nci_i2c_match[] = {
> - { .compatible = "nxp,nxp-nci-i2c", },
> - {}
> + { .compatible = "nxp,nxp-nci-i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match);
>
> diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c
> index 2128083f0297..66d201c14a40 100644
> --- a/drivers/nfc/pn533/i2c.c
> +++ b/drivers/nfc/pn533/i2c.c
> @@ -237,14 +237,14 @@ static void pn533_i2c_remove(struct i2c_client *client)
> }
>
> static const struct of_device_id of_pn533_i2c_match[] = {
> - { .compatible = "nxp,pn532", },
> + { .compatible = "nxp,pn532" },
> /*
> * NOTE: The use of the compatibles with the trailing "...-i2c" is
> * deprecated and will be removed.
> */
> - { .compatible = "nxp,pn533-i2c", },
> - { .compatible = "nxp,pn532-i2c", },
> - {},
> + { .compatible = "nxp,pn533-i2c" },
> + { .compatible = "nxp,pn532-i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_pn533_i2c_match);
>
> diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c
> index e0d67cd2ac9b..83c1ccda0af6 100644
> --- a/drivers/nfc/pn533/uart.c
> +++ b/drivers/nfc/pn533/uart.c
> @@ -238,8 +238,8 @@ static const struct serdev_device_ops pn532_serdev_ops = {
> };
>
> static const struct of_device_id pn532_uart_of_match[] = {
> - { .compatible = "nxp,pn532", },
> - {},
> + { .compatible = "nxp,pn532" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, pn532_uart_of_match);
>
> diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
> index 50907a1974cd..7fde3aefae70 100644
> --- a/drivers/nfc/pn544/i2c.c
> +++ b/drivers/nfc/pn544/i2c.c
> @@ -938,8 +938,8 @@ static void pn544_hci_i2c_remove(struct i2c_client *client)
> }
>
> static const struct of_device_id of_pn544_i2c_match[] = {
> - { .compatible = "nxp,pn544-i2c", },
> - {},
> + { .compatible = "nxp,pn544-i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_pn544_i2c_match);
>
> diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
> index 499301a6fa3f..4ba762611711 100644
> --- a/drivers/nfc/s3fwrn5/i2c.c
> +++ b/drivers/nfc/s3fwrn5/i2c.c
> @@ -211,8 +211,8 @@ static const struct i2c_device_id s3fwrn5_i2c_id_table[] = {
> MODULE_DEVICE_TABLE(i2c, s3fwrn5_i2c_id_table);
>
> static const struct of_device_id of_s3fwrn5_i2c_match[] = {
> - { .compatible = "samsung,s3fwrn5-i2c", },
> - {}
> + { .compatible = "samsung,s3fwrn5-i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_s3fwrn5_i2c_match);
>
> diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
> index e17c599a2da5..8f142a255101 100644
> --- a/drivers/nfc/s3fwrn5/uart.c
> +++ b/drivers/nfc/s3fwrn5/uart.c
> @@ -85,8 +85,8 @@ static const struct serdev_device_ops s3fwrn82_serdev_ops = {
> };
>
> static const struct of_device_id s3fwrn82_uart_of_match[] = {
> - { .compatible = "samsung,s3fwrn82", },
> - {},
> + { .compatible = "samsung,s3fwrn82" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
>
> diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c
> index ceb7d7450e47..152c20b6bb01 100644
> --- a/drivers/nfc/st-nci/i2c.c
> +++ b/drivers/nfc/st-nci/i2c.c
> @@ -270,10 +270,10 @@ static const struct acpi_device_id st_nci_i2c_acpi_match[] = {
> MODULE_DEVICE_TABLE(acpi, st_nci_i2c_acpi_match);
>
> static const struct of_device_id of_st_nci_i2c_match[] = {
> - { .compatible = "st,st21nfcb-i2c", },
> - { .compatible = "st,st21nfcb_i2c", },
> - { .compatible = "st,st21nfcc-i2c", },
> - {}
> + { .compatible = "st,st21nfcb-i2c" },
> + { .compatible = "st,st21nfcb_i2c" },
> + { .compatible = "st,st21nfcc-i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match);
>
> diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
> index 8632cc0cb305..5e0b94050f90 100644
> --- a/drivers/nfc/st-nci/spi.c
> +++ b/drivers/nfc/st-nci/spi.c
> @@ -284,8 +284,8 @@ static const struct acpi_device_id st_nci_spi_acpi_match[] = {
> MODULE_DEVICE_TABLE(acpi, st_nci_spi_acpi_match);
>
> static const struct of_device_id of_st_nci_spi_match[] = {
> - { .compatible = "st,st21nfcb-spi", },
> - {}
> + { .compatible = "st,st21nfcb-spi" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
>
> diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
> index 4e70f591af55..a4c93ff7c5b0 100644
> --- a/drivers/nfc/st21nfca/i2c.c
> +++ b/drivers/nfc/st21nfca/i2c.c
> @@ -584,9 +584,9 @@ static const struct acpi_device_id st21nfca_hci_i2c_acpi_match[] = {
> MODULE_DEVICE_TABLE(acpi, st21nfca_hci_i2c_acpi_match);
>
> static const struct of_device_id of_st21nfca_i2c_match[] = {
> - { .compatible = "st,st21nfca-i2c", },
> - { .compatible = "st,st21nfca_i2c", },
> - {}
> + { .compatible = "st,st21nfca-i2c" },
> + { .compatible = "st,st21nfca_i2c" },
> + { }
> };
> MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
>
> diff --git a/drivers/nfc/st95hf/core.c b/drivers/nfc/st95hf/core.c
> index 1ecd47c6518e..265ab10bbb61 100644
> --- a/drivers/nfc/st95hf/core.c
> +++ b/drivers/nfc/st95hf/core.c
> @@ -1056,7 +1056,7 @@ MODULE_DEVICE_TABLE(spi, st95hf_id);
>
> static const struct of_device_id st95hf_spi_of_match[] = {
> { .compatible = "st,st95hf" },
> - {},
> + { }
> };
> MODULE_DEVICE_TABLE(of, st95hf_spi_of_match);
>
> diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
> index bc01b46f461c..3802081fb8ee 100644
> --- a/drivers/nfc/trf7970a.c
> +++ b/drivers/nfc/trf7970a.c
> @@ -2304,10 +2304,9 @@ static const struct dev_pm_ops trf7970a_pm_ops = {
> };
>
> static const struct of_device_id trf7970a_of_match[] = {
> - {.compatible = "ti,trf7970a",},
> - {},
> + { .compatible = "ti,trf7970a" },
> + { }
> };
> -
> MODULE_DEVICE_TABLE(of, trf7970a_of_match);
>
> static const struct spi_device_id trf7970a_id_table[] = {
> --
> 2.55.0.11.g153666a7d9bb
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox