* Re: (subset) [PATCH v9 00/14] firmware: qcom: Add OP-TEE PAS service support
From: Bjorn Andersson @ 2026-07-13 15:06 UTC (permalink / raw)
To: konradybcio, Sumit Garg
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, robh, krzk+dt,
conor+dt, robin.clark, sean, akhilpo, lumag, abhinav.kumar,
jesszhan0024, marijn.suijten, airlied, simona, vikash.garodia,
bod, mchehab, elder, andrew+netdev, davem, edumazet, kuba, pabeni,
jjohnson, mathieu.poirier, trilokkumar.soni, mukesh.ojha,
pavan.kondeti, jorge.ramirez, tonyh, vignesh.viswanathan,
srinivas.kandagatla, amirreza.zarrabi, jenswi, op-tee, apurupa,
skare, linux-kernel, Sumit Garg
In-Reply-To: <20260702115835.167602-1-sumit.garg@kernel.org>
On Thu, 02 Jul 2026 17:28:16 +0530, Sumit Garg wrote:
> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
>
> Qcom platforms has the legacy of using non-standard SCM calls
> splintered over the various kernel drivers. These SCM calls aren't
> compliant with the standard SMC calling conventions which is a
> prerequisite to enable migration to the FF-A specifications from Arm.
>
> [...]
Applied, thanks!
[08/14] drm/msm: Switch to generic PAS TZ APIs
commit: 0be72be03ca7de55f22dd4c0622d81ac98aee38a
Best regards,
--
Bjorn Andersson <andersson@kernel.org>
^ permalink raw reply
* pull-request: ath-current-20260713
From: Jeff Johnson @ 2026-07-13 15:35 UTC (permalink / raw)
To: linux-wireless, Johannes Berg; +Cc: ath10k, ath11k, ath12k, jjohnson
The following changes since commit dc59e4fea9d83f03bad6bddf3fa2e52491777482:
Linux 7.2-rc1 (2026-06-28 12:01:31 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git tags/ath-current-20260713
for you to fetch changes up to a1a21995c2e1cc2ca6b2226cfe4f5f018370182a:
wifi: carl9170: fix buffer overflow in rx_stream failover path (2026-07-13 06:55:20 -0700)
----------------------------------------------------------------
ath.git update for v7.2-rc4
The most significant change is to fix an ath12k regression which led
to low MLO RX throughput on WCN7850.
The remainder are an assortment of minor bug fixes spread across many
of the ath drivers.
----------------------------------------------------------------
Cheng Yongkang (1):
wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming firmware request
Daniel Hodges (1):
wifi: ath6kl: fix use-after-free in aggr_reset_state()
Dmitry Morgun (1):
wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get()
Gaole Zhang (1):
wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin
Jose Ignacio Tornos Martinez (1):
wifi: ath12k: fix NULL pointer dereference in rhash table destroy
Manikanta Pubbisetty (1):
wifi: ath10k: fix skb leak on incomplete msdu during rx pop
Manivannan Sadhasivam (2):
wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
wifi: ath12k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
Tristan Madani (6):
wifi: ath6kl: fix OOB access from firmware ADDBA window size
wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler
wifi: ath6kl: fix OOB read from firmware IE lengths in connect event
wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read
wifi: carl9170: fix OOB read from off-by-two in TX status handler
wifi: carl9170: fix buffer overflow in rx_stream failover path
Wentao Liang (1):
wifi: ath11k: fix refcount leak in ath11k_ahb_fw_resources_init()
Yingying Tang (1):
wifi: ath12k: Fix low MLO RX throughput on WCN7850
drivers/net/wireless/ath/ath10k/htt_rx.c | 2 ++
drivers/net/wireless/ath/ath11k/ahb.c | 1 +
drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++
drivers/net/wireless/ath/ath11k/pci.c | 4 ++++
drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++---
drivers/net/wireless/ath/ath12k/dp_peer.c | 11 +++++++--
drivers/net/wireless/ath/ath12k/dp_peer.h | 1 +
drivers/net/wireless/ath/ath12k/dp_rx.c | 7 +++---
drivers/net/wireless/ath/ath12k/hw.h | 16 +++++++++++++
drivers/net/wireless/ath/ath12k/mac.c | 10 +++++---
drivers/net/wireless/ath/ath12k/pci.c | 4 ++++
drivers/net/wireless/ath/ath12k/peer.c | 3 +++
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 33 +++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 6 +++++
drivers/net/wireless/ath/ath12k/wifi7/hw.c | 3 +++
drivers/net/wireless/ath/ath6kl/txrx.c | 12 ++++++----
drivers/net/wireless/ath/ath6kl/wmi.c | 20 ++++++++++++++++
drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +-----
drivers/net/wireless/ath/carl9170/rx.c | 7 ++++--
drivers/net/wireless/ath/carl9170/tx.c | 2 +-
20 files changed, 137 insertions(+), 26 deletions(-)
^ permalink raw reply
* Re: [PATCH] wifi: mt76: mt7996: fix TX DMA mapping leak for ADDBA-req frames
From: Rory Little @ 2026-07-13 15:38 UTC (permalink / raw)
To: Yang Liu, nbd, lorenzo, ryder.lee
Cc: shayne.chen, sean.wang, linux-wireless, stable
In-Reply-To: <CAMt2zv5c0cYzfe0RQ5AfoUdm+b4bAshgjCs23NjFBhQXDKLniQ@mail.gmail.com>
On 6/28/26 03:11, Yang Liu wrote:
> mt7996 hands the firmware a HW MAC-TXP for ADDBA-req action frames
> (MT_TXD7_MAC_TXD, set in mt7996_mac_write_txwi_80211()), but the chip is a
> FW-TXP device, so on TX completion mt76_connac_txp_skb_unmap() decodes
> the per-frame txp as a struct mt76_connac_fw_txp. For a MAC-TXP the
> fw_txp.nbuf byte aliases the high byte of the TID word
> (MT_TXP1_TID_ADDBA, GENMASK(14, 12)), which is always zero, so the
> unmap loop runs zero times and buf[1] (the skb DMA mapping) is never
> unmapped. mt7996_tx_prepare_skb() also sets buf[1].skip_unmap
> unconditionally, so the generic mt76 DMA-ring cleanup skips it as well.
>
> Each ADDBA req therefore leaks one TX DMA mapping, i.e. roughly one per
> (re)association. When WED is enabled the mt76 DMA device bounces these
> mappings through the WED swiotlb pool, so under continuous client
> reconnect churn the pool is exhausted after ~1-2 days, after which DMA
> mapping fails for WED, the WiFi MCU and other on-SoC consumers.
>
> Only set buf[1].skip_unmap on the FW-TXP path. For MAC-TXD frames
> leave it clear so mt76_dma_tx_cleanup_idx() unmaps buf[1]. The FW
> unmap is a no-op for these frames (nbuf reads 0), so there is no double
> free.
>
> Fixes: cb6ebbdffef2 ("wifi: mt76: mt7996: support writing MAC TXD for
> AddBA Request")
> Cc:stable@vger.kernel.org
> Assisted-by: Claude-Code:claude-opus-4-8
> Signed-off-by: X<50459973+ly4096x@users.noreply.github.com>
> ---
> Tested on a Banana Pi R4 Pro (MT7988A, MT7996/BE14, WED enabled, 6.18.35):
> under a continuous client (re)association reproducer (~51 reassoc/min),
> /sys/kernel/debug/swiotlb/io_tlb_used grew ~25 slots/min before this
> patch (steady leak; pool exhaustion and the resulting DMA failures after
> ~1-2 days) and is flat after it, with no double free.
Hi, this patch worked for me; I am not seeing a DMA mapping leak after
applying it.
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> @@ -1010,6 +1010,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev,
> void *txwi_ptr,
> struct mt76_txwi_cache *t;
> int id, i, pid, nbuf = tx_info->nbuf - 1;
> bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
> + bool mac_txd;
> __le32 *ptr = (__le32 *)txwi_ptr;
> u8 *txwi = (u8 *)txwi_ptr;
> u8 link_id;
> @@ -1096,7 +1097,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev,
> void *txwi_ptr,
> /* MT7996 and MT7992 require driver to provide the MAC TXP for AddBA
> * req
> */
> - if (le32_to_cpu(ptr[7]) & MT_TXD7_MAC_TXD) {
> + mac_txd = le32_to_cpu(ptr[7]) & MT_TXD7_MAC_TXD;
> + if (mac_txd) {
> u32 val, mac_txp_size = sizeof(struct mt76_connac_hw_txp);
>
> ptr = (__le32 *)(txwi + MT_TXD_SIZE);
> @@ -1167,7 +1169,11 @@ int mt7996_tx_prepare_skb(struct mt76_dev
> *mdev, void *txwi_ptr,
>
> /* pass partial skb header to fw */
> tx_info->buf[1].len = MT_CT_PARSE_LEN;
> - tx_info->buf[1].skip_unmap = true;
> + /* MAC-TXD (ADDBA-req) frames use a HW MAC-TXP that the fw-txp
> + * mt76_connac_txp_skb_unmap() path does not unmap; free buf[1] via the
> + * DMA-ring cleanup for them instead.
> + */
> + tx_info->buf[1].skip_unmap = !mac_txd;
> tx_info->nbuf = MT_CT_DMA_BUF_NUM;
>
> return 0;
> -- 2.53.0
>
I am not sure if this is the right way to make the fix, though. Your
unmap occurs during mt76_queue_tx_cleanup, which happens before we
receive the txwi token back from FW. I am concerned that we could unmap
the skb before FW has indicated to us via an explicit tx-free that it
has finished with the frame, which occurs later in mt7996_txwi_free. My
suggestion would be to replace the generic mt76_connac_txp_skb_unmap
call with something mt7996 specific, which inspects the TXD to determine
FW/HW TXP layout in order to unmap the frame.
static void
mt7996_txp_skb_unmap(struct mt7996_dev *dev, struct mt76_txwi_cache *t)
{
struct mt76_connac_txp_common *txp;
struct mt76_connac_txp_ptr *ptr;
__le32 *txwi;
u16 len;
txp = mt76_connac_txwi_to_txp(&dev->mt76, t);
txwi = (__le32 *)mt76_get_txwi_ptr(&dev->mt76, t);
if (le32_to_cpu(txwi[7]) & MT_TXD7_MAC_TXD) {
ptr = &txp->hw.ptr[0];
len = le16_to_cpu(ptr->len0);
dma_unmap_single(dev->mt76.dev, le32_to_cpu(ptr->buf0), len,
DMA_TO_DEVICE);
MT76_COUNT_DMA_UNMAP(&dev->mt76, le32_to_cpu(ptr->buf0));
} else {
mt76_connac_txp_skb_unmap_fw(&dev->mt76, &txp->fw);
}
}
I could be wrong, though, and the early unmap may be safe.
- Rory
^ permalink raw reply
* [PATCH ath-next 0/2] wifi: ath: Correctly copy the hint BSSID in WMI scan request
From: Jeff Johnson @ 2026-07-13 16:15 UTC (permalink / raw)
To: Jeff Johnson
Cc: linux-wireless, ath11k, ath12k, linux-kernel, Baochen Qiang,
Jeff Johnson
Issue was reported in ath12k, but exists in ath11k as well.
---
Jeff Johnson (2):
wifi: ath12k: Correctly copy the hint BSSID in WMI scan request
wifi: ath11k: Correctly copy the hint BSSID in WMI scan request
drivers/net/wireless/ath/ath11k/wmi.c | 4 ++--
drivers/net/wireless/ath/ath12k/wmi.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
---
base-commit: fa1b1469f1c5f0f54ed9dab80106a117e7736bfd
change-id: 20260712-ath12k_wmi_send_scan_start_cmd-bad-hint_bssid-8786dbd8cff9
^ permalink raw reply
* [PATCH ath-next 1/2] wifi: ath12k: Correctly copy the hint BSSID in WMI scan request
From: Jeff Johnson @ 2026-07-13 16:15 UTC (permalink / raw)
To: Jeff Johnson
Cc: linux-wireless, ath11k, ath12k, linux-kernel, Baochen Qiang,
Jeff Johnson
In-Reply-To: <20260713-ath12k_wmi_send_scan_start_cmd-bad-hint_bssid-v1-0-4ffc4a472992@oss.qualcomm.com>
Currently, in ath12k_wmi_send_scan_start_cmd(), the logic to populate
the hint_bssid copies the BSSID in the wrong direction, from the
firmware message to the argument buffer. Swap the parameters so that
the BSSID is correctly populated in the firmware message from the
argument buffer.
Compile tested only.
Reported-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Closes: https://lore.kernel.org/linux-wireless/afbff608-a005-43c4-af76-968a58bf0cc3@oss.qualcomm.com/
Fixes: f40abb4788a2 ("ath12k: New driver for Qualcomm 11be hw family")
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wmi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index ad739bffcf88..fe9394d561f1 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -2796,8 +2796,8 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
for (i = 0; i < arg->num_hint_bssid; ++i) {
hint_bssid->freq_flags =
arg->hint_bssid[i].freq_flags;
- ether_addr_copy(&arg->hint_bssid[i].bssid.addr[0],
- &hint_bssid->bssid.addr[0]);
+ ether_addr_copy(&hint_bssid->bssid.addr[0],
+ &arg->hint_bssid[i].bssid.addr[0]);
hint_bssid++;
}
}
--
2.43.0
^ permalink raw reply related
* [PATCH ath-next 2/2] wifi: ath11k: Correctly copy the hint BSSID in WMI scan request
From: Jeff Johnson @ 2026-07-13 16:15 UTC (permalink / raw)
To: Jeff Johnson
Cc: linux-wireless, ath11k, ath12k, linux-kernel, Baochen Qiang,
Jeff Johnson
In-Reply-To: <20260713-ath12k_wmi_send_scan_start_cmd-bad-hint_bssid-v1-0-4ffc4a472992@oss.qualcomm.com>
Currently, in ath11k_wmi_send_scan_start_cmd(), the logic to populate
the hint_bssid copies the BSSID in the wrong direction, from the
firmware message to the argument buffer. Swap the parameters so that
the BSSID is correctly populated in the firmware message from the
argument buffer.
This issue was reported on ath12k, but exists in ath11k as well.
Compile tested only.
Reported-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Closes: https://lore.kernel.org/linux-wireless/afbff608-a005-43c4-af76-968a58bf0cc3@oss.qualcomm.com/
Fixes: 74601ecfef6e ("ath11k: Add support for 6g scan hint")
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath11k/wmi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index dca6e011cc40..c54f50b98a13 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -2423,8 +2423,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
for (i = 0; i < params->num_hint_bssid; ++i) {
hint_bssid->freq_flags =
params->hint_bssid[i].freq_flags;
- ether_addr_copy(¶ms->hint_bssid[i].bssid.addr[0],
- &hint_bssid->bssid.addr[0]);
+ ether_addr_copy(&hint_bssid->bssid.addr[0],
+ ¶ms->hint_bssid[i].bssid.addr[0]);
hint_bssid++;
}
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 2/2] wifi: ath12k: implement custom wake_tx_queue with flow control
From: Jeff Johnson @ 2026-07-13 16:27 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez, jjohnson
Cc: ath11k, ath12k, linux-wireless, linux-kernel
In-Reply-To: <20260710155443.1761760-3-jtornosm@redhat.com>
On 7/10/2026 8:54 AM, Jose Ignacio Tornos Martinez wrote:
> Under heavy traffic, ath12k can hang and experiences -ENOMEM errors
> ("failed to transmit frame -12") when the hardware TCL ring fills up.
> This issue is more commonly observed in VMs with PCIe passthrough but
> also occurs on bare metal systems.
>
> Implement a custom wake_tx_queue operation that:
>
> 1. Checks hardware ring space before dequeuing packets from mac80211
> 2. Uses per-packet locking to serialize ring access and prevent races
> 3. Syncs with hardware state to get accurate free slot count
> 4. Returns early during firmware crash in the same way as other tx paths
>
> This approach follows the pattern used in the iwlwifi driver, adapted
> for ath12k's hardware ring architecture.
>
> This prevents hangs, eliminates -ENOMEM errors, and improves throughput
> by optimizing resource usage and preventing unnecessary packet drops.
>
> Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Just based upon the description I doubt this will be accepted. The ath12k
datapath team is striving to have a lockless fastpath, so adding new locks is
problematic. I've BCC'ed the internal developers list so that the team knows
to give more constructive feedback.
/jeff
^ permalink raw reply
* Re: [PATCH 2/2] wifi: ath12k: implement custom wake_tx_queue with flow control
From: Tamizh Raja @ 2026-07-13 17:05 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez
Cc: jjohnson, ath11k, ath12k, linux-wireless, linux-kernel
In-Reply-To: <20260710155443.1761760-3-jtornosm@redhat.com>
On Fri, Jul 10, 2026 at 9:25 PM Jose Ignacio Tornos Martinez
<jtornosm@redhat.com> wrote:
>
> Under heavy traffic, ath12k can hang and experiences -ENOMEM errors
> ("failed to transmit frame -12") when the hardware TCL ring fills up.
> This issue is more commonly observed in VMs with PCIe passthrough but
> also occurs on bare metal systems.
>
> Implement a custom wake_tx_queue operation that:
>
> 1. Checks hardware ring space before dequeuing packets from mac80211
> 2. Uses per-packet locking to serialize ring access and prevent races
> 3. Syncs with hardware state to get accurate free slot count
> 4. Returns early during firmware crash in the same way as other tx paths
>
> This approach follows the pattern used in the iwlwifi driver, adapted
> for ath12k's hardware ring architecture.
>
> This prevents hangs, eliminates -ENOMEM errors, and improves throughput
> by optimizing resource usage and preventing unnecessary packet drops.
>
> Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
> ---
> drivers/net/wireless/ath/ath12k/dp.c | 1 +
> drivers/net/wireless/ath/ath12k/dp.h | 2 +
> drivers/net/wireless/ath/ath12k/hal.c | 1 +
> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 50 +++++++++++++++++++++-
> 4 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
> index af5f11fc1d84..3d46cfbf0a1c 100644
> --- a/drivers/net/wireless/ath/ath12k/dp.c
> +++ b/drivers/net/wireless/ath/ath12k/dp.c
> @@ -1539,6 +1539,7 @@ static int ath12k_dp_setup(struct ath12k_base *ab)
> }
>
> for (i = 0; i < ab->hw_params->max_tx_ring; i++) {
> + spin_lock_init(&dp->tx_ring[i].wake_tx_lock);
> dp->tx_ring[i].tcl_data_ring_id = i;
>
> dp->tx_ring[i].tx_status_head = 0;
> diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
> index f8cfc7bb29dd..68d2020be9b8 100644
> --- a/drivers/net/wireless/ath/ath12k/dp.h
> +++ b/drivers/net/wireless/ath/ath12k/dp.h
> @@ -58,6 +58,8 @@ struct dp_tx_ring {
> u8 tcl_data_ring_id;
> struct dp_srng tcl_data_ring;
> struct dp_srng tcl_comp_ring;
> + /* Serializes wake_tx_queue operations for this ring */
> + spinlock_t wake_tx_lock;
> struct hal_wbm_completion_ring_tx *tx_status;
> int tx_status_head;
> int tx_status_tail;
> diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
> index a164563fff28..c1c656e4550b 100644
> --- a/drivers/net/wireless/ath/ath12k/hal.c
> +++ b/drivers/net/wireless/ath/ath12k/hal.c
> @@ -390,6 +390,7 @@ int ath12k_hal_srng_src_num_free(struct ath12k_base *ab, struct hal_srng *srng,
> else
> return ((srng->ring_size - hp + tp) / srng->entry_size) - 1;
> }
> +EXPORT_SYMBOL(ath12k_hal_srng_src_num_free);
>
> void *ath12k_hal_srng_src_next_peek(struct ath12k_base *ab,
> struct hal_srng *srng)
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> index d9fdd2fc8298..e3a6f9cdee24 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> @@ -1100,9 +1100,57 @@ static void ath12k_wifi7_mac_op_tx(struct ieee80211_hw *hw,
> }
> }
>
> +static void ath12k_wifi7_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
> + struct ieee80211_txq *txq)
> +{
> + struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
> + struct ieee80211_tx_control control = {
> + .sta = txq->sta,
> + };
> + struct ath12k *ar = ah->radio;
This assignment is wrong and all traffic is incorrectly steered to
radio[0] as ah->radio is a flexible array, not a pointer
> + struct dp_tx_ring *tx_ring;
> + struct hal_srng *tcl_ring;
> + struct ath12k_dp *dp;
> + struct sk_buff *skb;
> + int num_free;
> +
> + if (!ar)
> + return;
> +
> + if (unlikely(test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)))
> + return;
> +
> + dp = ar->ab->dp;
> + tx_ring = &dp->tx_ring[txq->ac % dp->hw_params->max_tx_ring];
> + tcl_ring = &dp->hal->srng_list[tx_ring->tcl_data_ring.ring_id];
tx_ring/tcl_ring selection should be corrected.
> +
> + while (1) {
> + spin_lock_bh(&tx_ring->wake_tx_lock);
Do we need this spin_lock_bh?
> +
> + spin_lock(&tcl_ring->lock);
> + num_free = ath12k_hal_srng_src_num_free(ar->ab, tcl_ring, true);
> + spin_unlock(&tcl_ring->lock);
> +
Do we need this check and spin_lock here? already ath12k_wifi7_dp_tx()
has this lock and fetches the next entry. Can we check those return
value here and break the loop?
> + if (num_free == 0) {
> + spin_unlock_bh(&tx_ring->wake_tx_lock);
> + break;
> + }
> +
> + skb = ieee80211_tx_dequeue(hw, txq);
> + if (!skb) {
> + spin_unlock_bh(&tx_ring->wake_tx_lock);
> + break;
> + }
> +
> + ath12k_wifi7_mac_op_tx(hw, &control, skb);
> +
> + spin_unlock_bh(&tx_ring->wake_tx_lock);
> + }
> +}
> +
> static const struct ieee80211_ops ath12k_ops_wifi7 = {
> .tx = ath12k_wifi7_mac_op_tx,
> - .wake_tx_queue = ieee80211_handle_wake_tx_queue,
> + .wake_tx_queue = ath12k_wifi7_mac_op_wake_tx_queue,
> .start = ath12k_mac_op_start,
> .stop = ath12k_mac_op_stop,
> .reconfig_complete = ath12k_mac_op_reconfig_complete,
> --
> 2.54.0
>
>
--
- Tamizh.
^ permalink raw reply
* [stable backport request] wifi: mt76: mt7921/mt7925: fix NULL dereference in CSA beacon
From: Ismail Tarim @ 2026-07-13 18:01 UTC (permalink / raw)
To: stable; +Cc: Felix Fietkau, Lorenzo Bianconi, linux-wireless, linux-mediatek
Hi,
Please consider backporting the following mainline commit to the stable
trees:
commit 351dd7d2c80d ("wifi: mt76: mt7921/mt7925: fix NULL dereference in CSA beacon")
The commit carries a Fixes: tag but was not marked Cc: stable, so it has
not been picked up for the stable trees automatically. The tip of
linux-7.1.y still lacks it.
Why it should be applied:
It fixes a NULL pointer dereference in mt7921_channel_switch_rx_beacon()
(and the identical mt7925 path). When an AP sends a Channel Switch
Announcement (CSA) beacon, cfg80211 queues a wiphy work item that later
calls the driver's channel_switch_rx_beacon(); if the station
disconnects or the channel context is torn down in between,
dev->new_ctx has already been cleared to NULL and is then dereferenced
unconditionally. This is triggered by ordinary AP behaviour (channel
switch / DFS), so it is easy to hit in the field, and it hangs the
machine: the crash happens in a workqueue worker that exits with IRQs
disabled, wedging the cfg80211 workqueue and progressively locking up
userspace until a hard reboot. It affects the very common MT7921 /
MT7922 / MT7902 chipsets.
Reproduced on linux-7.1.y (Arch Linux 7.1.3-arch1-1), MT7902
[14c3:7902] driven by mt7921e:
BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: 0010:mt7921_channel_switch_rx_beacon+0x18/0xa0 [mt7921_common]
Call Trace:
ieee80211_sta_process_chanswitch+0x682/0xc30 [mac80211]
ieee80211_rx_mgmt_beacon+0x7ec/0x19c0 [mac80211]
ieee80211_iface_work+0x4c4/0x630 [mac80211]
cfg80211_wiphy_work+0x13f/0x1e0 [cfg80211]
process_one_work+0x19f/0x390
worker_thread+0x1b1/0x310
kthread+0xe4/0x120
note: kworker/u64:15 exited with irqs disabled
The offending code was introduced by
8aa2f59260eb ("wifi: mt76: mt7921: introduce CSA support")
Please apply 351dd7d2c80d to linux-7.1.y and any other supported stable
tree that contains 8aa2f59260eb.
Thanks,
Ismail Tarim
^ permalink raw reply
* Re: [PATCH] wifi: ath6kl: validate assoc info lengths in the WMI connect event
From: Doruk (0sec) @ 2026-07-13 18:18 UTC (permalink / raw)
To: jeff.johnson, linux-wireless
Cc: tristmd, johannes, peddolla.reddy, linux-kernel, stable
In-Reply-To: <779ee099-5132-4752-bdb8-354dfdc53926@oss.qualcomm.com>
On 7/11/2026, Jeff Johnson wrote:
> Some aspects of your patch are already addressed by:
> https://lore.kernel.org/all/20260421135009.348084-3-tristmd@gmail.com
> So you will need to rebase once that lands.
Thanks for the heads up! One thing that looks like it may remain after
Tristan's patch, in case it's useful: the aggregate check bounds the case
where the declared lengths are too large, but ath6kl_cfg80211_connect_event()
still underflows when a length is too small. It does, on u8 values
with no lower bound:
assoc_req_len -= assoc_req_ie_offset; /* -= 4 */
assoc_resp_len -= assoc_resp_ie_offset; /* -= 6 */
so an assoc request/response shorter than the fixed offset wraps to ~250, and
cfg80211_connect_result()/cfg80211_roamed() then treat that as the IE length and
copy that many bytes out of the small assoc_info buffer to user space. That path
is separate from the aggregate over-read Tristan's check covers.
Happy to send a small follow-on clamping those two subtractions on top of
Tristan's series once it lands -- or Tristan, please feel free to fold it into
your series if you'd rather keep it together. Whatever's easiest for you both.
Best
Doruk
DORUK TAN ÖZTÜRK
Co-Founder
0sec
Universitätstrasse 33
8006 Zürich, Switzerland
www.0sec.ai | doruk@0sec.ai | Linkedin
On Sat, 11 Jul 2026 at 16:39, Jeff Johnson
<jeff.johnson@oss.qualcomm.com> wrote:
>
> On 7/11/2026 12:13 AM, Doruk Tan Ozturk wrote:
> > ath6kl_wmi_connect_event_rx() only checks that the received event is at
> > least sizeof(struct wmi_connect_event); it never checks that the trailing
> > beacon_ie_len + assoc_req_len + assoc_resp_len fields fit within the
> > received buffer. Those attacker/AP-influenced lengths then drive two
> > out-of-bounds accesses:
> >
> > - The WMM information-element scan builds
> > peie = assoc_info + beacon_ie_len + assoc_req_len + assoc_resp_len
> > and walks up to it, reading past the end of the event buffer when the
> > declared lengths exceed the buffer. The walk also dereferences
> > pie[1..6] and pie[1] (for the advance) without checking they stay
> > within peie.
> >
> > - ath6kl_cfg80211_connect_event() subtracts fixed offsets from
> > assoc_req_len (-= 4) and assoc_resp_len (-= 6), both u8, with no lower
> > bound. A short assoc request/response underflows the length to ~250,
> > which cfg80211_connect_result() / cfg80211_roamed() then treat as the
> > IE length and copy out of bounds from the small assoc_info buffer,
> > disclosing adjacent slab memory to user space via nl80211.
> >
> > Bound the declared IE lengths against the received buffer, bound the WMM
> > element reads against peie, and clamp the assoc request/response lengths
> > before the subtraction. The sibling wil6210 driver already performs the
> > equivalent length check for the same WMI connect event.
> >
> > Found by 0sec (https://0sec.ai) using automated source analysis; the
> > missing bounds are evident from source and cross-checked against the
> > sibling wil6210 driver. Compile-tested.
> >
> > Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
> > Cc: stable@vger.kernel.org
> > Assisted-by: 0sec:claude-opus-4-8
> > Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
>
> Some aspects of your patch are already addressed by:
> https://lore.kernel.org/all/20260421135009.348084-3-tristmd@gmail.com
>
> So you will need to rebase once that lands.
>
> /jeff
^ permalink raw reply
* Re: [PATCH v9 12/14] wifi: ath12k: Switch to generic PAS TZ APIs
From: Jeff Johnson @ 2026-07-13 18:58 UTC (permalink / raw)
To: Sumit Garg, andersson, konradybcio
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, robh, krzk+dt,
conor+dt, robin.clark, sean, akhilpo, lumag, abhinav.kumar,
jesszhan0024, marijn.suijten, airlied, simona, vikash.garodia,
bod, mchehab, elder, andrew+netdev, davem, edumazet, kuba, pabeni,
jjohnson, mathieu.poirier, trilokkumar.soni, mukesh.ojha,
pavan.kondeti, jorge.ramirez, tonyh, vignesh.viswanathan,
srinivas.kandagatla, amirreza.zarrabi, jenswi, op-tee, apurupa,
skare, linux-kernel, Sumit Garg
In-Reply-To: <20260702115835.167602-13-sumit.garg@kernel.org>
On 7/2/2026 4:58 AM, Sumit Garg wrote:
> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
>
> Switch ath12k client driver over to generic PAS TZ APIs. Generic PAS TZ
> service allows to support multiple TZ implementation backends like QTEE
> based SCM PAS service, OP-TEE based PAS service and any further future TZ
> backend service.
>
> Acked-by: Jeff Johnson <jjohnson@kernel.org>
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/Kconfig | 2 +-
> drivers/net/wireless/ath/ath12k/ahb.c | 10 +++++-----
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/Kconfig b/drivers/net/wireless/ath/ath12k/Kconfig
> index 4a2b240f967a..0d5d1c55bfc1 100644
> --- a/drivers/net/wireless/ath/ath12k/Kconfig
> +++ b/drivers/net/wireless/ath/ath12k/Kconfig
> @@ -18,7 +18,7 @@ config ATH12K_AHB
> bool "Qualcomm ath12k AHB support"
> depends on ATH12K && REMOTEPROC
> select QCOM_MDT_LOADER
> - select QCOM_SCM
> + select QCOM_PAS
> help
> Enable support for Ath12k AHB bus chipsets, example IPQ5332.
>
> diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
> index 30733a244454..69e21214e629 100644
> --- a/drivers/net/wireless/ath/ath12k/ahb.c
> +++ b/drivers/net/wireless/ath/ath12k/ahb.c
> @@ -5,7 +5,7 @@
> */
>
> #include <linux/dma-mapping.h>
> -#include <linux/firmware/qcom/qcom_scm.h>
> +#include <linux/firmware/qcom/qcom_pas.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/platform_device.h>
> @@ -420,7 +420,7 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab)
>
> if (ab_ahb->scm_auth_enabled) {
> /* Authenticate FW image using peripheral ID */
> - ret = qcom_scm_pas_auth_and_reset(pasid);
> + ret = qcom_pas_auth_and_reset(pasid);
> if (ret) {
> ath12k_err(ab, "failed to boot the remote processor %d\n", ret);
> goto err_fw2;
> @@ -485,10 +485,10 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
> pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
> ATH12K_AHB_UPD_SWID;
> /* Release the firmware */
> - ret = qcom_scm_pas_shutdown(pasid);
> + ret = qcom_pas_shutdown(pasid);
> if (ret)
> - ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
> - ab_ahb->userpd_id);
> + ath12k_err(ab, "PAS shutdown failed for userPD%d: %d\n",
> + ab_ahb->userpd_id, ret);
> }
> }
>
My code review agent is flagging:
**Missing probe-defer guard** (`ahb.c:422`) — `qcom_pas_is_available()` is
explicitly documented as mandatory before any PAS call. The OP-TEE backend
registers its ops asynchronously; without an `if (!qcom_pas_is_available())
return -EPROBE_DEFER` in the probe path, firmware auth silently returns
`-ENODEV` with no retry.
Is it an existing deficiency in ath12k that there is no probe deferral?
Or did the qcom_scm_*() calls somehow guarantee something that is no longer
true with the qcom_pas_*() calls?
And also for future cleanup:
**Misleading field name** (`ahb.c:384`) — `scm_auth_enabled` should be
`pas_auth_enabled` to match the backend-agnostic API it now guards.
I plan on taking this patch as-is through the ath tree since it is currently
just simple API changes. Any additional changes can come separately.
/jeff
^ permalink raw reply
* Re: [PATCH] wifi: ath6kl: validate assoc info lengths in the WMI connect event
From: Jeff Johnson @ 2026-07-13 19:21 UTC (permalink / raw)
To: Doruk (0sec), linux-wireless
Cc: tristmd, johannes, peddolla.reddy, linux-kernel, stable
In-Reply-To: <CAPdMp1okStu9UiWn-Kb4xrTEdGj1POT4t+moh77JHpLSzD-pZQ@mail.gmail.com>
On 7/13/2026 11:18 AM, Doruk (0sec) wrote:
> On 7/11/2026, Jeff Johnson wrote:
>> Some aspects of your patch are already addressed by:
>> https://lore.kernel.org/all/20260421135009.348084-3-tristmd@gmail.com
>> So you will need to rebase once that lands.
>
> Thanks for the heads up! One thing that looks like it may remain after
> Tristan's patch, in case it's useful: the aggregate check bounds the case
> where the declared lengths are too large, but ath6kl_cfg80211_connect_event()
> still underflows when a length is too small. It does, on u8 values
> with no lower bound:
>
> assoc_req_len -= assoc_req_ie_offset; /* -= 4 */
> assoc_resp_len -= assoc_resp_ie_offset; /* -= 6 */
>
> so an assoc request/response shorter than the fixed offset wraps to ~250, and
> cfg80211_connect_result()/cfg80211_roamed() then treat that as the IE length and
> copy that many bytes out of the small assoc_info buffer to user space. That path
> is separate from the aggregate over-read Tristan's check covers.
>
> Happy to send a small follow-on clamping those two subtractions on top of
> Tristan's series once it lands -- or Tristan, please feel free to fold it into
> your series if you'd rather keep it together. Whatever's easiest for you both.
I've already landed Tristan's series in ath-current, so you can base a new
patch upon that.
^ permalink raw reply
* [PATCH] wifi: ath6kl: clamp assoc request/response lengths before subtracting IE offsets
From: Doruk Tan Ozturk @ 2026-07-13 21:32 UTC (permalink / raw)
To: Jeff Johnson, linux-wireless
Cc: Johannes Berg, Peddolla Harshavardhan Reddy, linux-kernel, stable
ath6kl_cfg80211_connect_event() subtracts fixed IE offsets from
assoc_req_len (-= 4) and assoc_resp_len (-= 6), both u8, with no lower
bound. The aggregate check recently added to ath6kl_wmi_connect_event_rx()
bounds the declared lengths from above (their sum must fit the received
event), but an assoc request/response shorter than its fixed offset still
underflows here: the u8 wraps to ~250, and cfg80211_connect_result() /
cfg80211_roamed() then treat that wrapped value as the IE length and copy
that many bytes out of the small assoc_info buffer to user space via
nl80211, disclosing adjacent slab memory.
Clamp both lengths to their offsets before subtracting.
Found by 0sec (https://0sec.ai) using automated source analysis; the
missing lower bound is evident from source. Compile-tested.
Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
Cc: stable@vger.kernel.org
Assisted-by: 0sec:claude-opus-4-8
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index cc0f2c45fc3a..62f663c0daa2 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -754,6 +754,11 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
assoc_resp_ie_offset;
+ if (assoc_req_len < assoc_req_ie_offset)
+ assoc_req_len = assoc_req_ie_offset;
+ if (assoc_resp_len < assoc_resp_ie_offset)
+ assoc_resp_len = assoc_resp_ie_offset;
+
assoc_req_len -= assoc_req_ie_offset;
assoc_resp_len -= assoc_resp_ie_offset;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/3] MIPS: BCM47XX: convert buttons to software nodes
From: Dmitry Torokhov @ 2026-07-13 21:58 UTC (permalink / raw)
To: Rafał Miłecki, Michael Buesch, Hauke Mehrtens,
Thomas Bogendoerfer
Cc: Bartosz Golaszewski, Arnd Bergmann, linux-wireless, linux-kernel,
linux-mips, Bartosz Golaszewski
This series converts the legacy gpio-keys platform device on BCM47XX
boards to use software nodes and static properties.
To do this properly without relying on legacy name-based matching
(which is being removed from gpiolib), we introduce and register
software nodes for the underlying GPIO controllers (BCMA and SSB)
and reference them in the button properties.
The first two patches add the software nodes to bcma-gpio and
ssb-gpio respectively. The third patch performs the conversion
for the BCM47XX buttons.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
As Johannes mentioned on v1 this best should go through MIPS tree.
Changes in v2:
- Restrict software node registration to host SoC devices in both ssb
and bcma drivers to avoid conflicts when secondary buses (e.g. PCI
wireless cards) are present
- Fix dangling pointer panic in buttons driver by allocating software
node references on the heap instead of stack
- Link to v1: https://patch.msgid.link/20260704-b4-bcm47xx-swnode-v1-0-730d59340237@gmail.com
---
Dmitry Torokhov (3):
bcma: gpio: Add and register software node for GPIO controller
ssb: gpio: Add and register software node for GPIO controller
MIPS: BCM47XX: Convert buttons to software nodes
arch/mips/bcm47xx/buttons.c | 442 +++++++++++++++++++++++++-------------------
drivers/bcma/driver_gpio.c | 43 ++++-
drivers/ssb/driver_gpio.c | 48 ++++-
include/linux/bcma/bcma.h | 2 +
include/linux/ssb/ssb.h | 2 +
5 files changed, 337 insertions(+), 200 deletions(-)
---
base-commit: 49362394dad7df66c274c867a271394c10ca2bb8
change-id: 20260627-b4-bcm47xx-swnode-99836e552166
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH v2 1/3] bcma: gpio: Add and register software node for GPIO controller
From: Dmitry Torokhov @ 2026-07-13 21:58 UTC (permalink / raw)
To: Rafał Miłecki, Michael Buesch, Hauke Mehrtens,
Thomas Bogendoerfer
Cc: Bartosz Golaszewski, Arnd Bergmann, linux-wireless, linux-kernel,
linux-mips
In-Reply-To: <20260713-b4-bcm47xx-swnode-v2-0-2b879f0c193c@gmail.com>
We want to convert the legacy gpio-keys platform device on BCM47XX
boards to use software nodes. To do this properly and allow
referencing the GPIO controller by address rather than relying on
name-based matching (which is being removed from the gpiolib core),
we need to associate the GPIO controller with a software node.
Introduce bcma_gpio_swnode, register it if the device does not
already have a firmware node, and associate it with the gpio_chip.
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/bcma/driver_gpio.c | 43 +++++++++++++++++++++++++++++++++++++------
include/linux/bcma/bcma.h | 2 ++
2 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 658c7e2ac8bf..ea45222f2fa0 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -19,6 +19,11 @@
#define BCMA_GPIO_MAX_PINS 32
+const struct software_node bcma_gpio_swnode = {
+ .name = "bcma-gpio",
+};
+EXPORT_SYMBOL_GPL(bcma_gpio_swnode);
+
static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
struct bcma_drv_cc *cc = gpiochip_get_data(chip);
@@ -190,7 +195,20 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->direction_input = bcma_gpio_direction_input;
chip->direction_output = bcma_gpio_direction_output;
chip->parent = bus->dev;
- chip->fwnode = dev_fwnode(&cc->core->dev);
+
+ /*
+ * Register software node only for the host SoC bus, unless there is
+ * already a firmware node assigned. There is only one SoC instance
+ * in the system, so there are no concerns with registration conflicts.
+ */
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC && !dev_fwnode(&cc->core->dev)) {
+ err = software_node_register(&bcma_gpio_swnode);
+ if (err)
+ return err;
+ chip->fwnode = software_node_fwnode(&bcma_gpio_swnode);
+ } else {
+ chip->fwnode = dev_fwnode(&cc->core->dev);
+ }
switch (bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM4707:
@@ -219,20 +237,33 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
err = bcma_gpio_irq_init(cc);
if (err)
- return err;
+ goto err_unregister_swnode;
err = gpiochip_add_data(chip, cc);
- if (err) {
- bcma_gpio_irq_exit(cc);
- return err;
- }
+ if (err)
+ goto err_irq_exit;
return 0;
+
+err_irq_exit:
+ bcma_gpio_irq_exit(cc);
+err_unregister_swnode:
+ if (bus->hosttype == BCMA_HOSTTYPE_SOC &&
+ chip->fwnode && is_software_node(chip->fwnode)) {
+ software_node_unregister(&bcma_gpio_swnode);
+ chip->fwnode = NULL;
+ }
+ return err;
}
int bcma_gpio_unregister(struct bcma_drv_cc *cc)
{
bcma_gpio_irq_exit(cc);
gpiochip_remove(&cc->gpio);
+ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC &&
+ cc->gpio.fwnode && is_software_node(cc->gpio.fwnode)) {
+ software_node_unregister(&bcma_gpio_swnode);
+ cc->gpio.fwnode = NULL;
+ }
return 0;
}
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index f02cb3909375..17fc50190014 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -486,4 +486,6 @@ extern u32 bcma_core_dma_translation(struct bcma_device *core);
extern unsigned int bcma_core_irq(struct bcma_device *core, int num);
+extern const struct software_node bcma_gpio_swnode;
+
#endif /* LINUX_BCMA_H_ */
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related
* [PATCH v2 2/3] ssb: gpio: Add and register software node for GPIO controller
From: Dmitry Torokhov @ 2026-07-13 21:58 UTC (permalink / raw)
To: Rafał Miłecki, Michael Buesch, Hauke Mehrtens,
Thomas Bogendoerfer
Cc: Bartosz Golaszewski, Arnd Bergmann, linux-wireless, linux-kernel,
linux-mips
In-Reply-To: <20260713-b4-bcm47xx-swnode-v2-0-2b879f0c193c@gmail.com>
We want to convert the legacy gpio-keys platform device on BCM47XX
boards to use software nodes. To do this properly and allow
referencing the GPIO controller by address rather than relying on
name-based matching (which is being removed from the gpiolib core),
we need to associate the GPIO controller with a software node.
Introduce ssb_gpio_swnode, register it, and associate it with the
gpio_chip.
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/ssb/driver_gpio.c | 48 ++++++++++++++++++++++++++++++++++++++++-------
include/linux/ssb/ssb.h | 2 ++
2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
index 905657c925bc..87922479946c 100644
--- a/drivers/ssb/driver_gpio.c
+++ b/drivers/ssb/driver_gpio.c
@@ -15,8 +15,14 @@
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/export.h>
+#include <linux/property.h>
#include <linux/ssb/ssb.h>
+const struct software_node ssb_gpio_swnode = {
+ .name = "ssb-gpio",
+};
+EXPORT_SYMBOL_GPL(ssb_gpio_swnode);
+
/**************************************************
* Shared
@@ -232,6 +238,8 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus)
chip->to_irq = ssb_gpio_to_irq;
#endif
chip->ngpio = 16;
+ if (bus->bustype == SSB_BUSTYPE_SSB)
+ chip->fwnode = software_node_fwnode(&ssb_gpio_swnode);
/* There is just one SoC in one device and its GPIO addresses should be
* deterministic to address them more easily. The other buses could get
* a random base number.
@@ -433,10 +441,12 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus)
* deterministic to address them more easily. The other buses could get
* a random base number.
*/
- if (bus->bustype == SSB_BUSTYPE_SSB)
- chip->base = 0;
- else
- chip->base = -1;
+ if (bus->bustype == SSB_BUSTYPE_SSB) {
+ chip->base = 0;
+ chip->fwnode = software_node_fwnode(&ssb_gpio_swnode);
+ } else {
+ chip->base = -1;
+ }
err = ssb_gpio_irq_extif_domain_init(bus);
if (err)
@@ -464,11 +474,33 @@ static int ssb_gpio_extif_init(struct ssb_bus *bus)
int ssb_gpio_init(struct ssb_bus *bus)
{
+ int err = 0;
+
+ /*
+ * Register software node only for the host SoC bus. There is only
+ * one SoC instance in the system, so there are no concerns with
+ * registration conflicts.
+ */
+ if (bus->bustype == SSB_BUSTYPE_SSB) {
+ err = software_node_register(&ssb_gpio_swnode);
+ if (err)
+ return err;
+ }
+
if (ssb_chipco_available(&bus->chipco))
- return ssb_gpio_chipco_init(bus);
+ err = ssb_gpio_chipco_init(bus);
else if (ssb_extif_available(&bus->extif))
- return ssb_gpio_extif_init(bus);
- return -1;
+ err = ssb_gpio_extif_init(bus);
+ else
+ err = -ENODEV;
+
+ if (err) {
+ if (bus->bustype == SSB_BUSTYPE_SSB)
+ software_node_unregister(&ssb_gpio_swnode);
+ return err;
+ }
+
+ return 0;
}
int ssb_gpio_unregister(struct ssb_bus *bus)
@@ -476,6 +508,8 @@ int ssb_gpio_unregister(struct ssb_bus *bus)
if (ssb_chipco_available(&bus->chipco) ||
ssb_extif_available(&bus->extif)) {
gpiochip_remove(&bus->gpio);
+ if (bus->bustype == SSB_BUSTYPE_SSB)
+ software_node_unregister(&ssb_gpio_swnode);
return 0;
}
return -1;
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 7fee9afa9458..67cb66f6f5ed 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -671,4 +671,6 @@ int ssb_pcibios_plat_dev_init(struct pci_dev *dev);
int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
#endif /* CONFIG_SSB_EMBEDDED */
+extern const struct software_node ssb_gpio_swnode;
+
#endif /* LINUX_SSB_H_ */
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related
* [PATCH v2 3/3] MIPS: BCM47XX: Convert buttons to software nodes
From: Dmitry Torokhov @ 2026-07-13 21:58 UTC (permalink / raw)
To: Rafał Miłecki, Michael Buesch, Hauke Mehrtens,
Thomas Bogendoerfer
Cc: Bartosz Golaszewski, Arnd Bergmann, linux-wireless, linux-kernel,
linux-mips, Bartosz Golaszewski
In-Reply-To: <20260713-b4-bcm47xx-swnode-v2-0-2b879f0c193c@gmail.com>
Convert the legacy gpio-keys platform device on BCM47XX boards to
use software nodes/properties. This allows us to describe the GPIO
keys and their GPIO bindings using software nodes, so that support
for platform data can eventually be removed from the gpio-keys
driver.
Detect the active bus type (BCMA or SSB) and reference the
corresponding GPIO controller's software node (bcma_gpio_swnode or
ssb_gpio_swnode) in the button properties.
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
arch/mips/bcm47xx/buttons.c | 442 +++++++++++++++++++++++++-------------------
1 file changed, 255 insertions(+), 187 deletions(-)
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
index 46994f9bb821..151a4ee2803f 100644
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -1,9 +1,14 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcm47xx_private.h"
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
+#include "linux/err.h"
+#include <linux/gpio/machine.h>
+#include <linux/gpio/property.h>
+#include <linux/input-event-codes.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
#include <bcm47xx_board.h>
#include <bcm47xx.h>
@@ -11,29 +16,34 @@
* Database
**************************************************/
-#define BCM47XX_GPIO_KEY(_gpio, _code) \
- { \
- .code = _code, \
- .gpio = _gpio, \
- .active_low = 1, \
+struct bcm47xx_gpio_key {
+ u16 code;
+ u8 pin;
+ u8 flags;
+};
+
+#define BCM47XX_GPIO_KEY(_gpio, _code) \
+ { \
+ .code = _code, \
+ .pin = _gpio, \
+ .flags = GPIO_ACTIVE_LOW, \
}
-#define BCM47XX_GPIO_KEY_H(_gpio, _code) \
- { \
- .code = _code, \
- .gpio = _gpio, \
+#define BCM47XX_GPIO_KEY_H(_gpio, _code) \
+ { \
+ .code = _code, \
+ .pin = _gpio, \
+ .flags = GPIO_ACTIVE_HIGH, \
}
/* Asus */
-static const struct gpio_keys_button
-bcm47xx_buttons_asus_rtn10u[] __initconst = {
+static const struct bcm47xx_gpio_key bcm47xx_buttons_asus_rtn10u[] __initconst = {
BCM47XX_GPIO_KEY(20, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(21, KEY_RESTART),
};
-static const struct gpio_keys_button
-bcm47xx_buttons_asus_rtn12[] __initconst = {
+static const struct bcm47xx_gpio_key bcm47xx_buttons_asus_rtn12[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(1, KEY_RESTART),
BCM47XX_GPIO_KEY(4, BTN_0), /* Router mode */
@@ -41,74 +51,73 @@ bcm47xx_buttons_asus_rtn12[] __initconst = {
BCM47XX_GPIO_KEY(6, BTN_2), /* AP mode */
};
-static const struct gpio_keys_button
-bcm47xx_buttons_asus_rtn16[] __initconst = {
+static const struct bcm47xx_gpio_key bcm47xx_buttons_asus_rtn16[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_rtn66u[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(9, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl300g[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl320ge[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl330ge[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl500g[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl500gd[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl500gpv1[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_RESTART),
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl500gpv2[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_RESTART),
BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl500w[] __initconst = {
BCM47XX_GPIO_KEY_H(6, KEY_RESTART),
BCM47XX_GPIO_KEY_H(7, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl520gc[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_RESTART),
BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl520gu[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_RESTART),
BCM47XX_GPIO_KEY(3, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wl700ge[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_POWER), /* Hard disk power switch */
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON), /* EZSetup */
@@ -116,21 +125,21 @@ bcm47xx_buttons_asus_wl700ge[] __initconst = {
BCM47XX_GPIO_KEY(7, KEY_RESTART), /* Hard reset */
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_asus_wlhdd[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
/* Huawei */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_huawei_e970[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
/* Belkin */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_belkin_f7d4301[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
@@ -138,44 +147,44 @@ bcm47xx_buttons_belkin_f7d4301[] __initconst = {
/* Buffalo */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_whr2_a54g54[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_whr_g125[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(4, KEY_RESTART),
BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode switch */
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_whr_g54s[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY_H(4, KEY_RESTART),
BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode switch */
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_whr_hp_g54[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(4, KEY_RESTART),
BCM47XX_GPIO_KEY(5, BTN_0), /* Router / AP mode switch */
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_wzr_g300n[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_wzr_rs_g54[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(4, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_buffalo_wzr_rs_g54hp[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(4, KEY_RESTART),
@@ -183,20 +192,20 @@ bcm47xx_buttons_buffalo_wzr_rs_g54hp[] __initconst = {
/* Dell */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_dell_tm2300[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_RESTART),
};
/* D-Link */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_dlink_dir130[] __initconst = {
BCM47XX_GPIO_KEY(3, KEY_RESTART),
BCM47XX_GPIO_KEY(7, KEY_UNKNOWN),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_dlink_dir330[] __initconst = {
BCM47XX_GPIO_KEY(3, KEY_RESTART),
BCM47XX_GPIO_KEY(7, KEY_UNKNOWN),
@@ -204,127 +213,127 @@ bcm47xx_buttons_dlink_dir330[] __initconst = {
/* Linksys */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e1000v1[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e1000v21[] __initconst = {
BCM47XX_GPIO_KEY(9, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(10, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e2000v1[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e2500v3[] __initconst = {
BCM47XX_GPIO_KEY(9, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(10, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e3000v1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e3200v1[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_RESTART),
BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_e4200v1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt150nv1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt150nv11[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt160nv1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt160nv3[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt300n_v1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt300nv11[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_UNKNOWN),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt310nv1[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
BCM47XX_GPIO_KEY(8, KEY_UNKNOWN),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt310n_v2[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt320n_v1[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_WIMAX),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt610nv1[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
BCM47XX_GPIO_KEY(8, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrt610nv2[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
@@ -332,154 +341,154 @@ bcm47xx_buttons_linksys_wrtsl54gs[] __initconst = {
/* Luxul */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_abr_4400_v1[] = {
BCM47XX_GPIO_KEY(14, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xap_310_v1[] = {
BCM47XX_GPIO_KEY(20, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xap_1210_v1[] = {
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xap_1230_v1[] = {
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xap_1240_v1[] = {
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xap_1500_v1[] = {
BCM47XX_GPIO_KEY(14, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xbr_4400_v1[] = {
BCM47XX_GPIO_KEY(14, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xvw_p30_v1[] = {
BCM47XX_GPIO_KEY(20, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xwr_600_v1[] = {
BCM47XX_GPIO_KEY(8, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_luxul_xwr_1750_v1[] = {
BCM47XX_GPIO_KEY(14, KEY_RESTART),
};
/* Microsoft */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_microsoft_nm700[] __initconst = {
BCM47XX_GPIO_KEY(7, KEY_RESTART),
};
/* Motorola */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_motorola_we800g[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_motorola_wr850gp[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_motorola_wr850gv2v3[] __initconst = {
BCM47XX_GPIO_KEY(5, KEY_RESTART),
};
/* Netgear */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_r6200_v1[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_RFKILL),
BCM47XX_GPIO_KEY(3, KEY_RESTART),
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_r6300_v1[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wn2500rp_v1[] __initconst = {
BCM47XX_GPIO_KEY(12, KEY_RESTART),
BCM47XX_GPIO_KEY(31, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wndr3400v1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_RESTART),
BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(8, KEY_RFKILL),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wndr3400_v3[] __initconst = {
BCM47XX_GPIO_KEY(12, KEY_RESTART),
BCM47XX_GPIO_KEY(23, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wndr3700v3[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_RFKILL),
BCM47XX_GPIO_KEY(3, KEY_RESTART),
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wndr4500v1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(5, KEY_RFKILL),
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wnr1000_v3[] __initconst = {
BCM47XX_GPIO_KEY(2, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(3, KEY_RESTART),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_RESTART),
BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wnr3500lv2[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_RESTART),
BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
BCM47XX_GPIO_KEY(8, KEY_RFKILL),
};
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
BCM47XX_GPIO_KEY(6, KEY_RESTART),
};
/* SimpleTech */
-static const struct gpio_keys_button
+static const struct bcm47xx_gpio_key
bcm47xx_buttons_simpletech_simpleshare[] __initconst = {
BCM47XX_GPIO_KEY(0, KEY_RESTART),
};
@@ -488,31 +497,96 @@ bcm47xx_buttons_simpletech_simpleshare[] __initconst = {
* Init
**************************************************/
-static struct gpio_keys_platform_data bcm47xx_button_pdata;
-
-static struct platform_device bcm47xx_buttons_gpio_keys = {
- .name = "gpio-keys",
- .dev = {
- .platform_data = &bcm47xx_button_pdata,
+static int __init
+bcm47xx_buttons_add(const struct bcm47xx_gpio_key *buttons, int nbuttons)
+{
+ struct platform_device *pdev;
+ const struct software_node *gpio_swnode;
+ struct property_entry *p;
+ int error;
+ int i;
+
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ gpio_swnode = &bcma_gpio_swnode;
+ break;
+#endif
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ gpio_swnode = &ssb_gpio_swnode;
+ break;
+#endif
+ default:
+ return -ENODEV;
}
-};
-/* Copy data from __initconst */
-static int __init bcm47xx_buttons_copy(const struct gpio_keys_button *buttons,
- size_t nbuttons)
-{
- size_t size = nbuttons * sizeof(*buttons);
+ /* 1 node for gpio-keys device, 1 node for each button, 1 terminator */
+ const struct software_node **node_group __free(kfree) =
+ kcalloc(1 + nbuttons + 1, sizeof(*node_group), GFP_KERNEL);
+ if (!node_group)
+ return -ENOMEM;
- bcm47xx_button_pdata.buttons = kmemdup(buttons, size, GFP_KERNEL);
- if (!bcm47xx_button_pdata.buttons)
+ /* 1 code property, 1 gpio property, 1 terminator */
+ struct property_entry *props __free(kfree) =
+ kcalloc(nbuttons * 3, sizeof(*props), GFP_KERNEL);
+ if (!props)
return -ENOMEM;
- bcm47xx_button_pdata.nbuttons = nbuttons;
+ /* 1 node for gpio-keys device, 1 node for each button */
+ struct software_node *nodes __free(kfree) =
+ kcalloc(1 + nbuttons, sizeof(*nodes), GFP_KERNEL);
+ if (!nodes)
+ return -ENOMEM;
+
+ struct software_node_ref_args *ref_args __free(kfree) =
+ kcalloc(nbuttons, sizeof(*ref_args), GFP_KERNEL);
+ if (!ref_args)
+ return -ENOMEM;
+
+ /* gpio-keys node */
+ nodes[0].name = "bcm47xx-gpio-buttons";
+
+ p = props;
+ for (i = 0; i < nbuttons; i++) {
+ const struct bcm47xx_gpio_key *button = &buttons[i];
+ struct software_node *node = &nodes[1 + i];
+ struct software_node_ref_args *ref = &ref_args[i];
+
+ node->parent = &nodes[0];
+ node->properties = p;
+
+ *ref = SOFTWARE_NODE_REFERENCE(gpio_swnode, button->pin, button->flags);
+ *p++ = PROPERTY_ENTRY_REF("gpios", &ref_args[i]);
+ *p++ = PROPERTY_ENTRY_U32("linux,code", button->code);
+ p++;
+ }
+
+ for (i = 0; i < nbuttons + 1; i++)
+ node_group[i] = &nodes[i];
+
+ error = software_node_register_node_group(node_group);
+ if (error)
+ return error;
+
+ pdev = platform_device_register_full(&(struct platform_device_info){
+ .name = "gpio-keys",
+ .swnode = &nodes[0],
+ });
+ error = PTR_ERR_OR_ZERO(pdev);
+ if (error) {
+ software_node_unregister_node_group(node_group);
+ return error;
+ }
+
+ retain_and_null_ptr(props);
+ retain_and_null_ptr(nodes);
+ retain_and_null_ptr(ref_args);
return 0;
}
-#define bcm47xx_copy_bdata(dev_buttons) \
- bcm47xx_buttons_copy(dev_buttons, ARRAY_SIZE(dev_buttons));
+#define bcm47xx_add_bdata(dev_buttons) \
+ bcm47xx_buttons_add(dev_buttons, ARRAY_SIZE(dev_buttons))
int __init bcm47xx_buttons_register(void)
{
@@ -521,52 +595,52 @@ int __init bcm47xx_buttons_register(void)
switch (board) {
case BCM47XX_BOARD_ASUS_RTN10U:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn10u);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn10u);
break;
case BCM47XX_BOARD_ASUS_RTN12:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn12);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn12);
break;
case BCM47XX_BOARD_ASUS_RTN16:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn16);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn16);
break;
case BCM47XX_BOARD_ASUS_RTN66U:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn66u);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_rtn66u);
break;
case BCM47XX_BOARD_ASUS_WL300G:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl300g);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl300g);
break;
case BCM47XX_BOARD_ASUS_WL320GE:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl320ge);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl320ge);
break;
case BCM47XX_BOARD_ASUS_WL330GE:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl330ge);
break;
case BCM47XX_BOARD_ASUS_WL500G:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500g);
break;
case BCM47XX_BOARD_ASUS_WL500GD:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500gd);
break;
case BCM47XX_BOARD_ASUS_WL500GPV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gpv1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500gpv1);
break;
case BCM47XX_BOARD_ASUS_WL500GPV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gpv2);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500gpv2);
break;
case BCM47XX_BOARD_ASUS_WL500W:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500w);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl500w);
break;
case BCM47XX_BOARD_ASUS_WL520GC:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl520gc);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl520gc);
break;
case BCM47XX_BOARD_ASUS_WL520GU:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl520gu);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl520gu);
break;
case BCM47XX_BOARD_ASUS_WL700GE:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl700ge);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wl700ge);
break;
case BCM47XX_BOARD_ASUS_WLHDD:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wlhdd);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_asus_wlhdd);
break;
case BCM47XX_BOARD_BELKIN_F7D3301:
@@ -574,193 +648,193 @@ int __init bcm47xx_buttons_register(void)
case BCM47XX_BOARD_BELKIN_F7D4301:
case BCM47XX_BOARD_BELKIN_F7D4302:
case BCM47XX_BOARD_BELKIN_F7D4401:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_belkin_f7d4301);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_belkin_f7d4301);
break;
case BCM47XX_BOARD_BUFFALO_WHR2_A54G54:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr2_a54g54);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr2_a54g54);
break;
case BCM47XX_BOARD_BUFFALO_WHR_G125:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_g125);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr_g125);
break;
case BCM47XX_BOARD_BUFFALO_WHR_G54S:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_g54s);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr_g54s);
break;
case BCM47XX_BOARD_BUFFALO_WHR_HP_G54:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_whr_hp_g54);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_whr_hp_g54);
break;
case BCM47XX_BOARD_BUFFALO_WZR_G300N:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_g300n);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_wzr_g300n);
break;
case BCM47XX_BOARD_BUFFALO_WZR_RS_G54:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54);
break;
case BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54hp);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_buffalo_wzr_rs_g54hp);
break;
case BCM47XX_BOARD_DELL_TM2300:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_dell_tm2300);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_dell_tm2300);
break;
case BCM47XX_BOARD_DLINK_DIR130:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_dlink_dir130);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_dlink_dir130);
break;
case BCM47XX_BOARD_DLINK_DIR330:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_dlink_dir330);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_dlink_dir330);
break;
case BCM47XX_BOARD_HUAWEI_E970:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_huawei_e970);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_huawei_e970);
break;
case BCM47XX_BOARD_LINKSYS_E1000V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e1000v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e1000v1);
break;
case BCM47XX_BOARD_LINKSYS_E1000V21:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e1000v21);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e1000v21);
break;
case BCM47XX_BOARD_LINKSYS_E2000V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e2000v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e2000v1);
break;
case BCM47XX_BOARD_LINKSYS_E2500V3:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e2500v3);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e2500v3);
break;
case BCM47XX_BOARD_LINKSYS_E3000V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e3000v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e3000v1);
break;
case BCM47XX_BOARD_LINKSYS_E3200V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e3200v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e3200v1);
break;
case BCM47XX_BOARD_LINKSYS_E4200V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_e4200v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_e4200v1);
break;
case BCM47XX_BOARD_LINKSYS_WRT150NV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt150nv1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt150nv1);
break;
case BCM47XX_BOARD_LINKSYS_WRT150NV11:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt150nv11);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt150nv11);
break;
case BCM47XX_BOARD_LINKSYS_WRT160NV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt160nv1);
break;
case BCM47XX_BOARD_LINKSYS_WRT160NV3:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt160nv3);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt160nv3);
break;
case BCM47XX_BOARD_LINKSYS_WRT300N_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt300n_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt300n_v1);
break;
case BCM47XX_BOARD_LINKSYS_WRT300NV11:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt300nv11);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt300nv11);
break;
case BCM47XX_BOARD_LINKSYS_WRT310NV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt310nv1);
break;
case BCM47XX_BOARD_LINKSYS_WRT310NV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310n_v2);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt310n_v2);
break;
case BCM47XX_BOARD_LINKSYS_WRT320N_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt320n_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt320n_v1);
break;
case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
break;
case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
break;
case BCM47XX_BOARD_LINKSYS_WRT610NV1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt610nv1);
break;
case BCM47XX_BOARD_LINKSYS_WRT610NV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv2);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrt610nv2);
break;
case BCM47XX_BOARD_LINKSYS_WRTSL54GS:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
break;
case BCM47XX_BOARD_LUXUL_ABR_4400_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_abr_4400_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_abr_4400_v1);
break;
case BCM47XX_BOARD_LUXUL_XAP_310_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xap_310_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_310_v1);
break;
case BCM47XX_BOARD_LUXUL_XAP_1210_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xap_1210_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1210_v1);
break;
case BCM47XX_BOARD_LUXUL_XAP_1230_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xap_1230_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1230_v1);
break;
case BCM47XX_BOARD_LUXUL_XAP_1240_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xap_1240_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1240_v1);
break;
case BCM47XX_BOARD_LUXUL_XAP_1500_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xap_1500_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xap_1500_v1);
break;
case BCM47XX_BOARD_LUXUL_XBR_4400_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xbr_4400_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xbr_4400_v1);
break;
case BCM47XX_BOARD_LUXUL_XVW_P30_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xvw_p30_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xvw_p30_v1);
break;
case BCM47XX_BOARD_LUXUL_XWR_600_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xwr_600_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xwr_600_v1);
break;
case BCM47XX_BOARD_LUXUL_XWR_1750_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_luxul_xwr_1750_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_luxul_xwr_1750_v1);
break;
case BCM47XX_BOARD_MICROSOFT_MN700:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_microsoft_nm700);
break;
case BCM47XX_BOARD_MOTOROLA_WE800G:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_motorola_we800g);
break;
case BCM47XX_BOARD_MOTOROLA_WR850GP:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gp);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_motorola_wr850gp);
break;
case BCM47XX_BOARD_MOTOROLA_WR850GV2V3:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gv2v3);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_motorola_wr850gv2v3);
break;
case BCM47XX_BOARD_NETGEAR_R6200_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_r6200_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_r6200_v1);
break;
case BCM47XX_BOARD_NETGEAR_R6300_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_r6300_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_r6300_v1);
break;
case BCM47XX_BOARD_NETGEAR_WN2500RP_V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wn2500rp_v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wn2500rp_v1);
break;
case BCM47XX_BOARD_NETGEAR_WNDR3400V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr3400v1);
break;
case BCM47XX_BOARD_NETGEAR_WNDR3400_V3:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400_v3);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr3400_v3);
break;
case BCM47XX_BOARD_NETGEAR_WNDR3700V3:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3700v3);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr3700v3);
break;
case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wndr4500v1);
break;
case BCM47XX_BOARD_NETGEAR_WNR1000_V3:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr1000_v3);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr1000_v3);
break;
case BCM47XX_BOARD_NETGEAR_WNR3500L:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
break;
case BCM47XX_BOARD_NETGEAR_WNR3500L_V2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv2);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr3500lv2);
break;
case BCM47XX_BOARD_NETGEAR_WNR834BV2:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_netgear_wnr834bv2);
break;
case BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE:
- err = bcm47xx_copy_bdata(bcm47xx_buttons_simpletech_simpleshare);
+ err = bcm47xx_add_bdata(bcm47xx_buttons_simpletech_simpleshare);
break;
default:
@@ -769,13 +843,7 @@ int __init bcm47xx_buttons_register(void)
}
if (err)
- return -ENOMEM;
-
- err = platform_device_register(&bcm47xx_buttons_gpio_keys);
- if (err) {
- pr_err("Failed to register platform device: %d\n", err);
return err;
- }
return 0;
}
--
2.55.0.795.g602f6c329a-goog
^ permalink raw reply related
* [PATCH] carl9170: fix out-of-bounds write on bad command response
From: Alexander Bendezu @ 2026-07-13 22:00 UTC (permalink / raw)
To: Christian Lamparter
Cc: linux-wireless, Alexander Bendezu, syzbot+5c1ca6ccaa1215781cac
carl9170_cmd_callback() checks if the response length matches what
was expected (ar->readlen). If it doesn't match, it warns and calls
carl9170_restart(), but the code below still runs anyway and copies
the response into ar->readbuf using the actual (wrong) length.
ar->readbuf is only sized for the expected length, so a bad response
larger than expected overflows it. This showed up as a KASAN
stack-out-of-bounds write, found by syzbot with a fuzzed USB device
sending a 60-byte response when 0 bytes were expected.
Move the memcpy() and complete() into an else branch so they only
run when the length actually matches, instead of falling through
after the mismatch is already detected.
Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend")
Reported-by: syzbot+5c1ca6ccaa1215781cac@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac
Signed-off-by: Alexander Bendezu <alexanderbendezu10@gmail.com>
---
drivers/net/wireless/ath/carl9170/rx.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 6833430130f4..3460b0ca0360 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -145,17 +145,17 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
* and we get a stack trace from there.
*/
carl9170_restart(ar, CARL9170_RR_INVALID_RSP);
- }
-
- spin_lock(&ar->cmd_lock);
- if (ar->readbuf) {
- if (len >= 4)
- memcpy(ar->readbuf, buffer + 4, len - 4);
+ } else {
+ spin_lock(&ar->cmd_lock);
+ if (ar->readbuf) {
+ if (len >= 4)
+ memcpy(ar->readbuf, buffer + 4, len - 4);
- ar->readbuf = NULL;
+ ar->readbuf = NULL;
+ }
+ complete(&ar->cmd_wait);
+ spin_unlock(&ar->cmd_lock);
}
- complete(&ar->cmd_wait);
- spin_unlock(&ar->cmd_lock);
}
void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] wifi: ath10k: Drop redundant NULL check on devm_clk_get()
From: Jeff Johnson @ 2026-07-13 22:31 UTC (permalink / raw)
To: Krzysztof Kozlowski, Jeff Johnson, linux-wireless, ath10k,
linux-kernel
In-Reply-To: <20260705172405.119084-2-krzysztof.kozlowski@oss.qualcomm.com>
On 7/5/2026 10:24 AM, Krzysztof Kozlowski wrote:
> devm_clk_get() does not return NULL (only valid clock or ERR pointer),
> so simplify the code to drop redundant IS_ERR_OR_NULL().
FWIW my AI review agent says:
Under !CONFIG_HAVE_CLK (x86 COMPILE_TEST), devm_clk_get() returns NULL;
IS_ERR(NULL) is false so clock_init() returns 0 with NULL clocks stored
Perhaps the stub function in include/linux/clk.h should be updated to return
an ERR_PTR() instead of NULL?
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath10k/ahb.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
> index eb8b35b6224d..7456f885d2b5 100644
> --- a/drivers/net/wireless/ath/ath10k/ahb.c
> +++ b/drivers/net/wireless/ath/ath10k/ahb.c
> @@ -87,24 +87,24 @@ static int ath10k_ahb_clock_init(struct ath10k *ar)
> dev = &ar_ahb->pdev->dev;
>
> ar_ahb->cmd_clk = devm_clk_get(dev, "wifi_wcss_cmd");
> - if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) {
> + if (IS_ERR(ar_ahb->cmd_clk)) {
> ath10k_err(ar, "failed to get cmd clk: %ld\n",
> PTR_ERR(ar_ahb->cmd_clk));
> - return ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;
> + return PTR_ERR(ar_ahb->cmd_clk);
> }
>
> ar_ahb->ref_clk = devm_clk_get(dev, "wifi_wcss_ref");
> - if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) {
> + if (IS_ERR(ar_ahb->ref_clk)) {
> ath10k_err(ar, "failed to get ref clk: %ld\n",
> PTR_ERR(ar_ahb->ref_clk));
> - return ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;
> + return PTR_ERR(ar_ahb->ref_clk);
> }
>
> ar_ahb->rtc_clk = devm_clk_get(dev, "wifi_wcss_rtc");
> - if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
> + if (IS_ERR(ar_ahb->rtc_clk)) {
> ath10k_err(ar, "failed to get rtc clk: %ld\n",
> PTR_ERR(ar_ahb->rtc_clk));
> - return ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;
> + return PTR_ERR(ar_ahb->rtc_clk);
> }
>
> return 0;
^ permalink raw reply
* iw scan hangs in netlink ENOBUFS loop with kernel 6.6.99+
From: Peter Astrand @ 2026-07-13 22:37 UTC (permalink / raw)
To: linux-wireless
kernel 6.6.y
iw 6.7
libnl-genl-3-200 3.9.0
mac80211_hwsim
With kernel 6.6.99 and later, "iw dev <device> scan" sometimes hangs in
busy loop:
recvmsg(3, {msg_namelen=12}, 0) = -1 ENOBUFS (No buffer space available)
recvmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000},
msg_namelen=12, msg_iov=[{iov_base=[{nlmsg_len=48, nlmsg_type=NLMSG_ERROR,
nlmsg_flags=0, nlmsg_seq=2511084235, nlmsg_pid=-1866444344},
{error=-ENOBUFS, msg=[{nlmsg_len=28, nlmsg_type=0x18 /* NLMSG_??? */,
nlmsg_flags=NLM_F_REQUEST|NLM_F_ACK|0x300, nlmsg_seq=2511084235,
nlmsg_pid=-1866444344},
"\x20\x00\x00\x00\x08\x00\x03\x00\x0e\x00\x00\x00"]}], iov_len=16384}],
msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_PEEK|MSG_TRUNC) = 48
This issue appears with kernel 6.6.99 and later, even latest version
6.6.144.
If I revert these commits:
346c820ef513 netlink: avoid infinite retry looping in netlink_unicast()
c31ee1695b6d netlink: make sure we allow at least one dump skb
ce2ac2e46719 netlink: Fix rmem check in netlink_broadcast_deliver().
55baecb9eb90 netlink: Fix wraparounds of sk->sk_rmem_alloc.
...then 6.6.144 works fine as well. Seems like there is a regression here.
Any ideas?
Br,
Peter Astrand
^ permalink raw reply
* Re: [PATCH ath-current v2] wifi: ath6kl: avoid buffer overreads in WMI event handlers
From: Jeff Johnson @ 2026-07-13 23:39 UTC (permalink / raw)
To: Baochen Qiang, linux-wireless; +Cc: linux-kernel
In-Reply-To: <44c01b93-5538-4a81-ab5e-b25d0d56980d@oss.qualcomm.com>
On 7/12/2026 7:06 PM, Baochen Qiang wrote:
>
>
> On 7/12/2026 2:04 AM, Jeff Johnson wrote:
>> The following WMI event handlers currently read from the event buffer
>> without first verifying that the message was large enough to hold the
>> expected event:
>> ath6kl_wmi_scan_complete_rx()
>> ath6kl_wmi_addba_req_event_rx()
>> ath6kl_wmi_delba_req_event_rx()
>>
>> Add length checks to prevent overread.
>>
>> Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
>> Assisted-by: Claude:claude-sonnet-4-6
>> Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
>> ---
>> Changes in v2:
>> - Added fixes for two more functions: ath6kl_wmi_addba_req_event_rx and ath6kl_wmi_delba_req_event_rx
>> - v1 subject: [PATCH ath-current] wifi: ath6kl: avoid buffer overread in ath6kl_wmi_scan_complete_rx()
>> - Link to v1: https://patch.msgid.link/20260711-ath6kl_wmi_scan_complete_rx-v1-1-7b11e5f8b96c@oss.qualcomm.com
>> ---
>> drivers/net/wireless/ath/ath6kl/wmi.c | 17 +++++++++++++++--
>> 1 file changed, 15 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
>> index 72611a2ceb9d..08030d88c7d3 100644
>> --- a/drivers/net/wireless/ath/ath6kl/wmi.c
>> +++ b/drivers/net/wireless/ath/ath6kl/wmi.c
>> @@ -1276,6 +1276,9 @@ static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len,
>> {
>> struct wmi_scan_complete_event *ev;
>>
>> + if (len < sizeof(*ev))
>> + return -EINVAL;
>> +
>> ev = (struct wmi_scan_complete_event *) datap;
>>
>> ath6kl_scan_complete_evt(vif, a_sle32_to_cpu(ev->status));
>> @@ -3352,7 +3355,12 @@ static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
>> static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len,
>> struct ath6kl_vif *vif)
>> {
>> - struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap;
>> + struct wmi_addba_req_event *cmd;
>> +
>> + if (len < sizeof(*cmd))
>> + return -EINVAL;
>> +
>> + cmd = (struct wmi_addba_req_event *) datap;
>
> Nit: No space is necessary after a cast. This is a preexisting issue, since you are
> touching, better to fix it together.
Yeah, let me make those changes in 'pending'
/jeff
^ permalink raw reply
* Re: [PATCH v2] wifi: mt76: mt7921: Add PCIe AER handler support to prevent system crash
From: Eason Lai (賴易聖) @ 2026-07-14 1:21 UTC (permalink / raw)
To: nbd@nbd.name, lorenzo@kernel.org, johannes@sipsolutions.net,
Mingyen Hsieh (謝明諺)
Cc: Allan Wang (王家偉),
Eric-SY Chang (張書源),
Deren Wu (武德仁), Ryder Lee,
Quan Zhou (周全), Michael.Lo@mediatek.com,
Shayne Chen (陳軒丞), Sean Wang,
Leon Yen (顏良儒),
KM Lin (林昆民),
linux-mediatek@lists.infradead.org,
linux-wireless@vger.kernel.org
In-Reply-To: <d7eb196b01003a1de70456d5a31d9b4a37d555bd.camel@sipsolutions.net>
On Wed, 2025-10-08 at 11:12 +0200, Johannes Berg wrote:
> Hi,
>
> So ... yeah it's your driver, and yes it's already at v2, but ...
> this
> still seems very much papering over a problem?
>
> On Wed, 2025-10-08 at 16:59 +0800, Mingyen Hsieh wrote:
> >
> > Unable to handle kernel paging request at virtual address
> > ffffffc01099eac0
> > pc : mt76_dma_add_buf+0x124/0x188 [mt76]
>
> Why does it even crash there?
>
It's an out-of-range access: the HW returned an unexpected value that
wasn't validated before use.
v3 posted here:
https://lore.kernel.org/linux-wireless/20260506070458.3096180-1-jb.tsai@mediatek.com/
Thanks,
Eason
> > +++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c
> > @@ -96,6 +96,9 @@ mt76_rx_aggr_reorder_work(struct work_struct
> > *work)
> > struct sk_buff_head frames;
> > int nframes;
> >
> > + if (atomic_read(&dev->bus_hung) == 1)
> > + return;
>
> And how does sprinkling this "magic dust" all over even do anything?
>
>
> This sounds a bit like the driver isn't able to deal with surprise
> removal, what happens if you e.g. rmmod it while running traffic? I
> believe the effect of the error recovery would be similar, if you
> don't
> handle it, so are you sure there's not a completely different
> underlying
> bug?
>
> johannes
^ permalink raw reply
* Re: [PATCH] wifi: brcmfmac: set F2 blocksize to 256 for BCM43752
From: LiangCheng Wang @ 2026-07-14 2:28 UTC (permalink / raw)
To: Arend van Spriel, Gokul Sivakumar
Cc: LiangCheng Wang, Kalle Valo, Angus Ainslie, Wig Cheng,
linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel,
stable, wlan-kernel-dev-list
In-Reply-To: <36f4388a-b856-438c-8ef4-795a7b1eda3e@broadcom.com>
Hi Arend,
On 13/07/2026 12:51, Arend van Spriel wrote:
> Looks good to me but the stable instruction looks confusion. What do you
> mean. If there is no 43752 support there is no need for this patch, right?
Thank you for the review, and thanks Gokul for the detailed
explanation - that is exactly what I meant, and sorry the annotation
was not clearer. To summarize: 43752 support has been present since
v5.15 (commit d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and
initialization")), under the SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752 id
name. Commit 74e2ef72bd4b ("wifi: brcmfmac: fix 43752 SDIO FWVID
incorrectly labelled as Cypress (CYW)"), which landed in v6.18,
renamed it to SDIO_DEVICE_ID_BROADCOM_43752.
I also have to correct myself here: the boundary in the annotation
should have been "<= 6.17" rather than "<= 6.16", since the rename
only landed in v6.18. Apologies for the extra confusion.
Gokul's suggestion of cherry-picking the rename patch together with
this one into the stable trees sounds cleaner to me than editing the
id name while backporting, so I would be glad to go with that.
If it helps, I would be happy to send a v2 with the stable annotation
in the prerequisite format from
Documentation/process/stable-kernel-rules.rst:
Cc: <stable@vger.kernel.org> # 74e2ef72bd4b: wifi: brcmfmac: fix 43752 SDIO FWVID incorrectly labelled as Cypress (CYW)
Please let me know if you would prefer that, or if the patch is fine
to take as is.
Best regards,
LiangCheng
^ permalink raw reply
* Re: [PATCH 1/2] wifi: ath11k: implement custom wake_tx_queue with flow control
From: Zhi-Jun You @ 2026-07-14 2:38 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez
Cc: ath11k, ath12k, jjohnson, linux-kernel, linux-wireless
In-Reply-To: <20260713150151.2343583-1-jtornosm@redhat.com>
On Mon, Jul 13, 2026 at 11:02 PM Jose Ignacio Tornos Martinez
<jtornosm@redhat.com> wrote:
>
> Hi Zhi-Jun,
>
> Thank you for the review.
>
> > In wake_tx_queue:
> > ring_id = txq->ac % ar->ab->hw_params.hal_params->num_tx_rings;
> >
> >In ath11k_dp_tx which is called by ath11k_mac_op_tx:
> >ring_selector = ab->hw_params.hw_ops->get_ring_selector(skb);
> > ti.ring_id = ring_selector % num_tx_rings;
> >
> > Are you sure ring_id will be the same?
> You're right — txq->ac % num_tx_rings doesn't match
> get_ring_selector(skb) % num_tx_rings on all platforms.
> In v1 the ring identification was only correct for platforms where the ring
> selector happens to coincide with the AC, but not for platforms.
>
> I will send a v2 trying to solve this globally for all the platforms.
>
> > Also mgmt frames use a different path.
> Correct — management frames go through WMI, not the TCL data rings, so they
> are not affected. The flow control applies to data frames, which are the
> ones causing the problem since they use different TCL rings depending on the
> platform's ring selector.
>
> Best regards,
> Jose Ignacio
>
Hi Jose,
While you are reworking it would you mind looking at the previous attempt?
It tried to follow the behaviour in ath10k but lacks throttling mechanism.
https://lore.kernel.org/linux-wireless/20230501130725.7171-1-quic_tamizhr@quicinc.com/
Best regards,
Zhi-Jun
^ permalink raw reply
* Re: [PATCH ath-next 0/2] wifi: ath: Correctly copy the hint BSSID in WMI scan request
From: Baochen Qiang @ 2026-07-14 2:43 UTC (permalink / raw)
To: Jeff Johnson, Jeff Johnson; +Cc: linux-wireless, ath11k, ath12k, linux-kernel
In-Reply-To: <20260713-ath12k_wmi_send_scan_start_cmd-bad-hint_bssid-v1-0-4ffc4a472992@oss.qualcomm.com>
On 7/14/2026 12:15 AM, Jeff Johnson wrote:
> Issue was reported in ath12k, but exists in ath11k as well.
>
> ---
> Jeff Johnson (2):
> wifi: ath12k: Correctly copy the hint BSSID in WMI scan request
> wifi: ath11k: Correctly copy the hint BSSID in WMI scan request
>
> drivers/net/wireless/ath/ath11k/wmi.c | 4 ++--
> drivers/net/wireless/ath/ath12k/wmi.c | 4 ++--
> 2 files changed, 4 insertions(+), 4 deletions(-)
> ---
> base-commit: fa1b1469f1c5f0f54ed9dab80106a117e7736bfd
> change-id: 20260712-ath12k_wmi_send_scan_start_cmd-bad-hint_bssid-8786dbd8cff9
>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ 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