* Re: [PATCH 13/14] wifi: ath12k: Switch to generic PAS TZ APIs
From: Jeff Johnson @ 2026-03-06 15:52 UTC (permalink / raw)
To: Sumit Garg, linux-arm-msm, devicetree, dri-devel, freedreno,
linux-media, netdev, linux-wireless, ath12k, linux-remoteproc
Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
airlied, simona, vikash.garodia, dikshita.agarwal, 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, jens.wiklander, op-tee, apurupa, skare,
Sumit Garg
In-Reply-To: <20260306105027.290375-14-sumit.garg@kernel.org>
On 3/6/2026 2:50 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.
>
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
Acked-by: Jeff Johnson <jjohnson@kernel.org>
^ permalink raw reply
* Re: [PATCH v3 3/3] wifi: wcn36xx: Add support for WCN3610
From: Kerigan Creighton @ 2026-03-06 18:05 UTC (permalink / raw)
To: Loic Poulain
Cc: linux-wireless, wcn36xx, andersson, mathieu.poirier,
linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
devicetree, linux-kernel
In-Reply-To: <CAFEp6-2MVFXfz4=_Em7YkH_Vx5VcryWMdDnrwe8C0=TnBmknZA@mail.gmail.com>
On Fri, Mar 6, 2026 at 2:41 AM Loic Poulain
<loic.poulain@oss.qualcomm.com> wrote:
>
> > STA_POWERSAVE resulted in BMPS errors and unstable
> > functionality, thus it has been disabled for just this
> > chip.
> >
> > Tested on an Anki Vector 1.0 and 2.0 robot with 3
> > different APs. Support for other WCN36xx chips has not
> > been affected.
> >
> > Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
>
> STA_POWERSAVE is disabled, but the interface still enters BMPS mode as
> controlled by mac80211. If you get the opportunity, It would be useful
> to air-capture the power‑save entry and exit events when this occurs,
> so we can verify that the transitions behave as expected.
>
> Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
[re-sent with full cc list]
I only had the chance to test it with one AP, but wireshark does show
clean power-save entry and exit transitions. Once I do more testing,
I will make a v4 which:
- Adds these power-save findings to the patch 3 commit message
- Amends all commit messages so they are wrapped better
- Amends patch 1 to include a better description of the hardware
Thanks for the review,
- Kerigan
On Fri, Mar 6, 2026 at 2:41 AM Loic Poulain
<loic.poulain@oss.qualcomm.com> wrote:
>
> On Fri, Mar 6, 2026 at 1:44 AM Kerigan Creighton
> <kerigancreighton@gmail.com> wrote:
> >
> > The WCN3610 has a lot in common with the other wcn36xx
> > chips, so much of that code was reused.
> >
> > The WCN3610 requires specific configuration values for
> > stable Wi-Fi. Without these values, there's packet loss.
> > An extra CFG table was made so other chips are not affected.
> >
> > ENABLE_DYNAMIC_RA_START_RATE=0 was discovered from the
> > downstream prima driver. That brought it from 95% to 5%
> > packet loss. The rest of the CFG values came from my own
> > observations and experimentation. The current settings
> > allow for 0% packet loss.
> >
> > STA_POWERSAVE resulted in BMPS errors and unstable
> > functionality, thus it has been disabled for just this
> > chip.
> >
> > Tested on an Anki Vector 1.0 and 2.0 robot with 3
> > different APs. Support for other WCN36xx chips has not
> > been affected.
> >
> > Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
>
> STA_POWERSAVE is disabled, but the interface still enters BMPS mode as
> controlled by mac80211. If you get the opportunity, It would be useful
> to air-capture the power‑save entry and exit events when this occurs,
> so we can verify that the transitions behave as expected.
>
> Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
>
>
>
> > ---
> > Changes in v2:
> > - Move wcn36xx driver changes to the end of the patch set.
> >
> > Changes in v3:
> > - Describe where the CFG values came from in the wcn36xx
> > driver patch [Konrad].
> > ---
> > drivers/net/wireless/ath/wcn36xx/main.c | 4 +-
> > drivers/net/wireless/ath/wcn36xx/smd.c | 61 +++++++++++++++++++++-
> > drivers/net/wireless/ath/wcn36xx/wcn36xx.h | 1 +
> > 3 files changed, 64 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
> > index c3f0860873..6c90c13251 100644
> > --- a/drivers/net/wireless/ath/wcn36xx/main.c
> > +++ b/drivers/net/wireless/ath/wcn36xx/main.c
> > @@ -1438,7 +1438,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
> > BIT(NL80211_IFTYPE_MESH_POINT);
> >
> > wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
> > - if (wcn->rf_id != RF_IRIS_WCN3620)
> > + if (wcn->rf_id != RF_IRIS_WCN3620 && wcn->rf_id != RF_IRIS_WCN3610)
> > wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
> >
> > if (wcn->rf_id == RF_IRIS_WCN3680)
> > @@ -1535,6 +1535,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
> > /* External RF module */
> > iris_node = of_get_child_by_name(mmio_node, "iris");
> > if (iris_node) {
> > + if (of_device_is_compatible(iris_node, "qcom,wcn3610"))
> > + wcn->rf_id = RF_IRIS_WCN3610;
> > if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
> > wcn->rf_id = RF_IRIS_WCN3620;
> > if (of_device_is_compatible(iris_node, "qcom,wcn3660") ||
> > diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
> > index 813553edcb..8d5a746de7 100644
> > --- a/drivers/net/wireless/ath/wcn36xx/smd.c
> > +++ b/drivers/net/wireless/ath/wcn36xx/smd.c
> > @@ -83,6 +83,61 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
> > WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
> > };
> >
> > +static struct wcn36xx_cfg_val wcn3610_cfg_vals[] = {
> > + WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
> > + WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
> > + WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
> > + WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
> > + WCN36XX_CFG_VAL(CAL_PERIOD, 5),
> > + WCN36XX_CFG_VAL(CAL_CONTROL, 1),
> > + WCN36XX_CFG_VAL(PROXIMITY, 0),
> > + WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
> > + WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
> > + WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
> > + WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
> > + WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
> > + WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
> > + WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
> > + WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
> > + WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
> > + WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
> > + WCN36XX_CFG_VAL(FIXED_RATE, 0),
> > + WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
> > + WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 131),
> > + WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 129),
> > + WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
> > + WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
> > + WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
> > + WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
> > + WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 6),
> > + WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
> > + WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
> > + WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
> > + WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
> > + WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
> > + WCN36XX_CFG_VAL(STATS_PERIOD, 10),
> > + WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
> > + WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
> > + WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
> > + WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
> > + WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
> > + WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
> > + WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
> > + WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
> > + WCN36XX_CFG_VAL(BTC_EXECUTION_MODE, 2),
> > + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 90000),
> > + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 60000),
> > + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
> > + WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
> > + WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
> > + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
> > + WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
> > + WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
> > + WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
> > + WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 0),
> > + WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
> > +};
> > +
> > static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
> > WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
> > WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
> > @@ -632,6 +687,9 @@ int wcn36xx_smd_start(struct wcn36xx *wcn)
> > if (wcn->rf_id == RF_IRIS_WCN3680) {
> > cfg_vals = wcn3680_cfg_vals;
> > cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
> > + } else if (wcn->rf_id == RF_IRIS_WCN3610) {
> > + cfg_vals = wcn3610_cfg_vals;
> > + cfg_elements = ARRAY_SIZE(wcn3610_cfg_vals);
> > } else {
> > cfg_vals = wcn36xx_cfg_vals;
> > cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
> > @@ -2380,7 +2438,8 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
> > mutex_lock(&wcn->hal_mutex);
> > INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
> >
> > - wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
> > + if (wcn->rf_id != RF_IRIS_WCN3610)
> > + wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
> > if (wcn->rf_id == RF_IRIS_WCN3680) {
> > wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
> > wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
> > diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> > index 7ee79593cd..cb409d48f7 100644
> > --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> > +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
> > @@ -96,6 +96,7 @@ enum wcn36xx_ampdu_state {
> > #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power)
> >
> > #define RF_UNKNOWN 0x0000
> > +#define RF_IRIS_WCN3610 0x3610
> > #define RF_IRIS_WCN3620 0x3620
> > #define RF_IRIS_WCN3660 0x3660
> > #define RF_IRIS_WCN3680 0x3680
> > --
> > 2.53.0
> >
^ permalink raw reply
* [PATCH] rtw88: add TX power limit support to 114 and 130 channels
From: Thadeu Lima de Souza Cascardo @ 2026-03-06 18:41 UTC (permalink / raw)
To: Ping-Ke Shih, Kalle Valo, Yan-Hsuan Chuang
Cc: linux-wireless, kernel-dev, Thadeu Lima de Souza Cascardo
Though 114 and 130 are not usual channels, they are found in the wild with
setups using 5350MHz as the center frequency of a 80MHz setup.
rtw88 supports that, but issues a WARNING because it cannot find the TX
power limit for those channels.
Fix this by using the lower TX power limit from adjacent 40MHz channels.
After that change, there is no WARNING and the 80MHz bandwidth is still
used.
[ 9.980715] ------------[ cut here ]------------
[ 9.980721] invalid arguments, band=1, bw=2, path=0, rate=44, ch=130
[ 9.980726] WARNING: drivers/net/wireless/realtek/rtw88/phy.c:2213 at rtw_get_tx_power_params+0x541/0x920 [rtw88_core], CPU#0: iwd/1227
[ 9.980755] Modules linked in: ccm algif_aead des3_ede_x86_64 cbc des_generic libdes md4 nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 cmac algif_hash algif_skcipher af_alg ramoops snd_soc_acp5x_mach nf_tables reed_solomon bnep joydev mousedev snd_acp5x_pcm_dma snd_acp5x_i2s amdgpu snd_sof_amd_acp63 rtw88_8822ce amd_atl snd_sof_amd_vangogh intel_rapl_msr rtw88_8822c snd_sof_amd_acp intel_rapl_common snd_sof_pci rtw88_pci amdxcp snd_sof kvm_amd rtw88_core i2c_algo_bit snd_sof_utils snd_hda_codec_atihdmi hid_multitouch drm_ttm_helper snd_hda_codec_hdmi snd_sof_xtensa_dsp snd_soc_cs35l41_spi kvm ttm mac80211 btusb snd_pci_ps snd_soc_cs35l41 snd_hda_intel snd_soc_acpi_amd_match btrtl drm_exec snd_soc_cs35l41_lib drm_panel_backlight_quirks snd_soc_acpi_amd_sdca_quirks btintel gpu_sched snd_hda_codec snd_soc_wm_adsp libarc4 snd_soc_sdca irqbypass drm_suballoc_helper btbcm snd_soc_nau8821 cs_dsp
[ 9.980895] snd_hwdep ghash_clmulni_intel drm_buddy btmtk spd5118 snd_pci_acp6x aesni_intel cfg80211 snd_soc_core snd_hda_core drm_display_helper atkbd rapl snd_pci_acp5x libps2 snd_intel_dspcfg bluetooth snd_compress snd_acp_config hid_steam snd_intel_sdw_acpi cdc_acm hid_generic vivaldi_fmap wdat_wdt snd_pcm pcspkr tpm_crb rfkill snd_soc_acpi snd_timer ccp cec video sp5100_tco ltrf216a wmi opt3001 tpm_tis i2c_hid_acpi snd i2c_hid industrialio tpm_tis_core soundcore 8250_dw k10temp i2c_piix4 i2c_smbus mac_hid pkcs8_key_parser ntsync hid_playstation led_class_multicolor hid_nintendo ff_memless i2c_dev crypto_user loop dm_mod nfnetlink zram tpm libaescfb overlay ext4 crc16 mbcache jbd2 vfat fat usbhid btrfs libblake2b xor raid6_pq sdhci_pci nvme serio_raw sdhci_uhs2 sdhci nvme_core cqhci nvme_keyring mmc_core i8042 nvme_auth hkdf serio spi_amd
[ 9.981052] CPU: 0 UID: 0 PID: 1227 Comm: iwd Not tainted 6.19.0-08324-gf4457a734418 #15 PREEMPT(full) d98827284d7dd170a54c85b32d8344cb5d6741ce
[ 9.981058] Hardware name: Valve Jupiter/Jupiter, BIOS F7A0133 08/05/2024
[ 9.981062] RIP: 0010:rtw_get_tx_power_params+0x553/0x920 [rtw88_core]
[ 9.981079] Code: 5e 41 5f e9 6f 79 b2 e6 44 8b 5c 24 24 44 88 14 24 48 8d 3d 8f 72 40 00 44 8b 44 24 1c 8b 4c 24 18 89 f2 45 0f b6 cb 44 89 fe <67> 48 0f b9 3a 48 8b 43 38 44 0f b6 14 24 0f b6 68 45 41 88 6e 02
[ 9.981083] RSP: 0018:ffffd0cd418f2f10 EFLAGS: 00010246
[ 9.981087] RAX: 0000000000000031 RBX: ffff8f3b1ad72060 RCX: 0000000000000000
[ 9.981090] RDX: 0000000000000002 RSI: 0000000000000001 RDI: ffffffffc13b41d0
[ 9.981093] RBP: 00000000000000fa R08: 000000000000002c R09: 0000000000000082
[ 9.981096] R10: 0000000000000004 R11: 0000000000000082 R12: 000000000000002c
[ 9.981099] R13: 0000000000000000 R14: ffffd0cd418f2f8b R15: 0000000000000001
[ 9.981102] FS: 00007f10c85edb80(0000) GS:ffff8f3e85c8f000(0000) knlGS:0000000000000000
[ 9.981105] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 9.981108] CR2: 00007f8f50200270 CR3: 00000001244cc000 CR4: 0000000000350ef0
[ 9.981111] Call Trace:
[ 9.981116] <TASK>
[ 9.981125] rtw_phy_get_tx_power_index+0x43/0x180 [rtw88_core da6d95ee8f8ea7f3fd6d7370ca8f98e1f6d9c5c7]
[ 9.981147] rtw_phy_set_tx_power_level+0xdc/0x140 [rtw88_core da6d95ee8f8ea7f3fd6d7370ca8f98e1f6d9c5c7]
[ 9.981168] rtw_set_channel+0xb7/0x130 [rtw88_core da6d95ee8f8ea7f3fd6d7370ca8f98e1f6d9c5c7]
[ 9.981188] rtw_ops_config+0x81/0xc0 [rtw88_core da6d95ee8f8ea7f3fd6d7370ca8f98e1f6d9c5c7]
[ 9.981207] drv_config+0x2b/0xd0 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981276] ieee80211_add_chanctx+0x57/0x130 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981352] ieee80211_new_chanctx+0x33/0xc0 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981432] _ieee80211_link_use_channel+0x2da/0x360 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981550] ieee80211_prep_channel+0x2ef/0x550 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981686] ieee80211_prep_connection+0x20a/0x500 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981807] ieee80211_mgd_auth+0x2c5/0x4f0 [mac80211 bbf26b8ca8c7853f2522289e0ff504e0b8b8a571]
[ 9.981904] ? srso_return_thunk+0x5/0x5f
[ 9.981912] ? srso_return_thunk+0x5/0x5f
[ 9.981917] ? __cfg80211_get_bss+0x1e9/0x2d0 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.981986] cfg80211_mlme_auth+0xb7/0x1b0 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982052] cfg80211_conn_do_work+0x449/0x490 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982147] cfg80211_connect+0x3ac/0x7a0 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982209] nl80211_connect+0x624/0x8a0 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982269] ? srso_return_thunk+0x5/0x5f
[ 9.982274] ? _copy_to_iter+0x8d/0x5f0
[ 9.982295] genl_family_rcv_msg_doit+0x103/0x160
[ 9.982309] genl_rcv_msg+0x1b5/0x2c0
[ 9.982315] ? __pfx_nl80211_pre_doit+0x10/0x10 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982372] ? __pfx_nl80211_connect+0x10/0x10 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982426] ? __pfx_nl80211_post_doit+0x10/0x10 [cfg80211 6f7b2df30576ef94720b632aca066e9e39311de2]
[ 9.982482] ? __pfx_genl_rcv_msg+0x10/0x10
[ 9.982488] netlink_rcv_skb+0x52/0x100
[ 9.982499] genl_rcv+0x28/0x40
[ 9.982504] netlink_unicast+0x28a/0x3e0
[ 9.982511] netlink_sendmsg+0x228/0x480
[ 9.982520] __sys_sendto+0x1f1/0x200
[ 9.982535] __x64_sys_sendto+0x24/0x30
[ 9.982539] do_syscall_64+0x11b/0x7e0
[ 9.982546] ? srso_return_thunk+0x5/0x5f
[ 9.982550] ? do_syscall_64+0x11b/0x7e0
[ 9.982556] ? srso_return_thunk+0x5/0x5f
[ 9.982560] ? __sys_sendmsg+0x88/0xf0
[ 9.982564] ? __seccomp_filter+0x42/0x5d0
[ 9.982574] ? srso_return_thunk+0x5/0x5f
[ 9.982578] ? do_syscall_64+0x11b/0x7e0
[ 9.982585] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 9.982591] RIP: 0033:0x7f10c8681006
[ 9.982596] Code: 5d e8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 75 19 83 e2 39 83 fa 08 75 11 e8 26 ff ff ff 66 0f 1f 44 00 00 48 8b 45 10 0f 05 <48> 8b 5d f8 c9 c3 0f 1f 40 00 f3 0f 1e fa 55 48 89 e5 48 83 ec 08
[ 9.982599] RSP: 002b:00007ffdebfc83a0 EFLAGS: 00000202 ORIG_RAX: 000000000000002c
[ 9.982605] RAX: ffffffffffffffda RBX: 00005596e451b8f0 RCX: 00007f10c8681006
[ 9.982608] RDX: 0000000000000068 RSI: 00005596e453cc80 RDI: 0000000000000004
[ 9.982611] RBP: 00007ffdebfc83c0 R08: 0000000000000000 R09: 0000000000000000
[ 9.982613] R10: 0000000000000000 R11: 0000000000000202 R12: 00005596e453cc80
[ 9.982616] R13: 00005596e453d040 R14: 0000000000000001 R15: 0000000000000000
[ 9.982626] </TASK>
[ 9.982629] ---[ end trace 0000000000000000 ]---
Fixes: fa6dfe6bff24 ("rtw88: resolve order of tx power setting routines")
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
---
drivers/net/wireless/realtek/rtw88/main.h | 2 +-
drivers/net/wireless/realtek/rtw88/phy.c | 36 +++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 1ab70214ce36eb1785a6f642b83cc30748d9ec18..652120f7397f5a58ec2e7364fdf4e52f7340e63a 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -47,7 +47,7 @@ extern bool rtw_edcca_enabled;
extern const struct ieee80211_ops rtw_ops;
#define RTW_MAX_CHANNEL_NUM_2G 14
-#define RTW_MAX_CHANNEL_NUM_5G 49
+#define RTW_MAX_CHANNEL_NUM_5G 51
struct rtw_dev;
struct rtw_debugfs;
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
index e2ac5c6fd5002996534e061b6f45dfdd65728525..af9f7f3550890469f9dd58aa7aad8ec30ad596cf 100644
--- a/drivers/net/wireless/realtek/rtw88/phy.c
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
@@ -1602,7 +1602,9 @@ static const u8 rtw_channel_idx_5g[RTW_MAX_CHANNEL_NUM_5G] = {
36, 38, 40, 42, 44, 46, 48, /* Band 1 */
52, 54, 56, 58, 60, 62, 64, /* Band 2 */
100, 102, 104, 106, 108, 110, 112, /* Band 3 */
+ 114, /* Compute from adjacent center frequencies */
116, 118, 120, 122, 124, 126, 128, /* Band 3 */
+ 130, /* Compute from adjacent center frequencies */
132, 134, 136, 138, 140, 142, 144, /* Band 3 */
149, 151, 153, 155, 157, 159, 161, /* Band 4 */
165, 167, 169, 171, 173, 175, 177}; /* Band 4 */
@@ -1732,6 +1734,38 @@ static void rtw_xref_txpwr_lmt(struct rtw_dev *rtwdev)
rtw_xref_txpwr_lmt_by_bw(rtwdev, regd);
}
+static void
+__cfg_txpwr_lmt_extra_channels(struct rtw_hal *hal, u8 regd, u8 bw, u8 rs)
+{
+ u8 channels[] = { 114, 130 };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(channels); i++) {
+ int idx, upper_idx, lower_idx;
+ int upper_limit, lower_limit;
+
+ idx = rtw_channel_to_idx(PHY_BAND_5G, channels[i]);
+ upper_idx = rtw_channel_to_idx(PHY_BAND_5G, channels[i] + 4);
+ lower_idx = rtw_channel_to_idx(PHY_BAND_5G, channels[i] - 4);
+ if (idx < 0 || upper_idx < 0 || lower_idx < 0)
+ WARN(1, "invalid channel index when computing TX power limit for extra channels");
+ upper_limit = hal->tx_pwr_limit_5g[regd][bw][rs][upper_idx];
+ lower_limit = hal->tx_pwr_limit_5g[regd][bw][rs][lower_idx];
+ hal->tx_pwr_limit_5g[regd][bw][rs][idx] = min(lower_limit, upper_limit);
+ }
+}
+
+static void
+rtw_cfg_twpwr_lmt_extra_channels(struct rtw_dev *rtwdev, u8 regd)
+{
+ u8 bw, rs;
+
+ for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++)
+ for (rs = 0; rs < RTW_RATE_SECTION_NUM; rs++)
+ __cfg_txpwr_lmt_extra_channels(&rtwdev->hal, regd,
+ bw, rs);
+}
+
static void
__cfg_txpwr_lmt_by_alt(struct rtw_hal *hal, u8 regd, u8 regd_alt, u8 bw, u8 rs)
{
@@ -1773,6 +1807,8 @@ void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev,
}
for (i = 0; i < RTW_REGD_MAX; i++) {
+ rtw_cfg_twpwr_lmt_extra_channels(rtwdev, i);
+
if (i == RTW_REGD_WW)
continue;
---
base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
change-id: 20260306-rtw88_channel130-3a33ec369249
Best regards,
--
Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
^ permalink raw reply related
* Re: [BUG] wifi: mt76: mt7925u: probe with driver mt7925u failed with error -110
From: Nick @ 2026-03-06 19:23 UTC (permalink / raw)
To: Sean Wang
Cc: linux-wireless, Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
Shayne Chen, Sean Wang, Deren Wu, Leon Yen
In-Reply-To: <CAGp9LzrTMALkJKrGANTCzeG4KUDGwC1YJc8SRKNRriH3a9bnRQ@mail.gmail.com>
> > Reference: https://github.com/morrownr/USB-WiFi/issues/688#issuecomment-3999038526
> >
> > The above thread is rather lengthy as we have been working on this
> > issue since Dec. 25.
> >
> > Testing with a Netgear A9000 USB WiFi adapter (mt7925u driver). Kernel
> > 7.0 rc2 and a x86_64 system. Additional testing with older kernels was
> > also performed with the same results.
> >
> > Problem description:
> >
> > Cold boot shows the adapter coming up and operating normally.
> >
> > Removing the adapter from the USB port and replacing it shows the
> > adapter coming up and operating normally.
> >
> > A warm reboot does not provide a WiFi interface and shows the
> > following in the system log:
> >
> > mt7925u 2-3.2:1.0: probe with driver mt7925u failed with error -110
> >
> > Using the commands rmmod and modeprobe do not provide a WiFi interface.
> >
> > Thoughts: The problem likely is not the module teardown. The problem
> > seems to be that the firmware (or the mt7925u driver) leaves the
> > adapter in a strange state such that a power cycle of the adapter
> > hardware is needed before the mt7925u driver can properly initialize
> > it a second time.
> >
>
> Hi Nick,
>
> Could you enable debug logs and check whether the driver can still
> read the correct chip ID after a warm reboot, and at which step the
> initialization fails before the -110 error? Thanks for continuing to
> test and gather this useful information.
>
> Sean
Hi Sean,
Github user @exct has performed the testing requested and provides the
following report:
mt7925u Probe Failure Debug Report
Adapter: Netgear A9000 (USB ID 0846:9072, MediaTek MT7925)
Kernel: 6.19.6-2-cachyos
Summary
The driver can read the correct chip ID after a warm reload. The
failure occurs before firmware is loaded, inside
mt792xu_wfsys_reset(), which times out waiting for the WiFi subsystem
to reinitialize. -ETIMEDOUT (-110) is returned and the probe aborts.
Findings
Question: Chip ID readable after warm reload?
Answer: Yes — MT_HW_CHIPID = 0x7925, MT_HW_REV = 0x8a00
Question: Which step fails?
Answer: mt792xu_wfsys_reset() — WFSYS_INIT_DONE never asserted
Question: Does it reach mt792xu_mcu_power_on()?
Answer: No
Question: Does it reach mt7925_run_firmware()?
Answer: No
Probe Sequence Trace
mt7925u_probe()
├─ mt76_alloc_device() OK
├─ __mt76u_init() OK
├─ read MT_HW_CHIPID (0x70010200) → 0x00007925 ✓
├─ read MT_HW_REV (0x70010204) → 0x00008a00 ✓
├─ read MT_CONN_ON_MISC (0x7c0600f0) → 0x00000003 ← FW_N9_RDY is SET
├─ enters mt792xu_wfsys_reset() ← triggered because FW_N9_RDY = 1
│ ├─ write MT_CBTOP_RGU_WF_SUBSYS_RST (assert reset)
│ ├─ write MT_CBTOP_RGU_WF_SUBSYS_RST (deassert reset)
│ ├─ poll MT_UDMA_CONN_INFRA_STATUS (0x74000a20) → 0x00000000
│ ├─ poll MT_UDMA_CONN_INFRA_STATUS (0x74000a20) → 0x00000000
│ └─ ... timeout after ~212 ms → return -ETIMEDOUT
└─ goto error: (mt76u_queues_deinit + mt76_free_device)
Root Cause
After rmmod, the firmware leaves FW_N9_RDY asserted in
MT_CONN_ON_MISC. On re-probe, the driver correctly detects this and
calls mt792xu_wfsys_reset() to recover. However, the WiFi subsystem
never signals completion — WFSYS_INIT_DONE in
MT_UDMA_CONN_INFRA_STATUS (reg 0x74000a20) stays 0x00000000 throughout
the retry loop. The subsystem is stuck in a state that the software
reset path cannot recover from. Only a full USB power cycle clears it.
Hope this helps,
Nick
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Trilok Soni @ 2026-03-06 19:47 UTC (permalink / raw)
To: Sumit Garg, linux-arm-msm, devicetree, dri-devel, freedreno,
linux-media, netdev, linux-wireless, ath12k, linux-remoteproc
Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
airlied, simona, vikash.garodia, dikshita.agarwal, bod, mchehab,
elder, andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, mukesh.ojha, pavan.kondeti, jorge.ramirez, tonyh,
vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <20260306105027.290375-3-sumit.garg@kernel.org>
On 3/6/2026 2:50 AM, 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.
You are using multiple conflicting terminologies here. In the first statement
you have used "non-standard" and immediately you have used "aren't complaint".
Which ARM document dictates that "standard" and "compliance" here? Are these
SCM calls are using the vendor space per the spec, and if yes what does
non-standard means here.
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.
>
> OP-TEE as an alternative trusted OS to QTEE can't support these non-
What is QTEE?
> standard SCM calls. And even for newer architectures QTEE won't be able
meaning of architecture please? Are you referring ARMv9.x or SOC architecture
or software architecture? What does "newer" means? Is there
any example available in public or are you ready to share?
> to support SCM calls either with FF-A requirements coming in. And with
> both OP-TEE and QTEE drivers well integrated in the TEE subsystem, it
> makes further sense to reuse the TEE bus client drivers infrastructure.
>
> The added benefit of TEE bus infrastructure is that there is support
> for discoverable/enumerable services. With that client drivers don't
> have to manually invoke a special SCM call to know the service status.
>
> So enable the generic Peripheral Authentication Service (PAS) provided
> by the firmware. It acts as the common layer with different TZ
> backends plugged in whether it's an SCM implementation or a proper
> TEE bus based PAS service implementation.
I haven't checked cover letter in detail, but did you tested these patches
w/ the devices which doesn't support these new facilities?
>
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
> ---
> drivers/firmware/qcom/Kconfig | 8 +
> drivers/firmware/qcom/Makefile | 1 +
> drivers/firmware/qcom/qcom_pas.c | 295 +++++++++++++++++++++++++
> drivers/firmware/qcom/qcom_pas.h | 53 +++++
> include/linux/firmware/qcom/qcom_pas.h | 41 ++++
> 5 files changed, 398 insertions(+)
> create mode 100644 drivers/firmware/qcom/qcom_pas.c
> create mode 100644 drivers/firmware/qcom/qcom_pas.h
> create mode 100644 include/linux/firmware/qcom/qcom_pas.h
>
> diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
> index b477d54b495a..8653639d06db 100644
> --- a/drivers/firmware/qcom/Kconfig
> +++ b/drivers/firmware/qcom/Kconfig
> @@ -6,6 +6,14 @@
>
> menu "Qualcomm firmware drivers"
>
> +config QCOM_PAS
> + tristate
> + help
> + Enable the generic Peripheral Authentication Service (PAS) provided
> + by the firmware. It acts as the common layer with different TZ
> + backends plugged in whether it's an SCM implementation or a proper
> + TEE bus based PAS service implementation.
> +
> config QCOM_SCM
> select QCOM_TZMEM
> tristate
> diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
> index 0be40a1abc13..dc5ab45f906a 100644
> --- a/drivers/firmware/qcom/Makefile
> +++ b/drivers/firmware/qcom/Makefile
> @@ -8,3 +8,4 @@ qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
> obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o
> obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
> obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
> +obj-$(CONFIG_QCOM_PAS) += qcom_pas.o
> diff --git a/drivers/firmware/qcom/qcom_pas.c b/drivers/firmware/qcom/qcom_pas.c
> new file mode 100644
> index 000000000000..dc04ff1b6be0
> --- /dev/null
> +++ b/drivers/firmware/qcom/qcom_pas.c
> @@ -0,0 +1,295 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/device/devres.h>
> +#include <linux/firmware/qcom/qcom_pas.h>
> +#include <linux/of.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
are you sure you are using functionalities from these header files?
I couldn't find slab.h usage quickly and also qcom_scm.h. Can you please confirm?
> +
> +#include "qcom_pas.h"
> +#include "qcom_scm.h"
> +
> +static struct qcom_pas_ops *ops_ptr;
> +
> +/**
> + * devm_qcom_pas_context_alloc() - Allocate peripheral authentication service
> + * context for a given peripheral
> + *
> + * PAS context is device-resource managed, so the caller does not need
> + * to worry about freeing the context memory.
> + *
> + * @dev: PAS firmware device
> + * @pas_id: peripheral authentication service id
> + * @mem_phys: Subsystem reserve memory start address
> + * @mem_size: Subsystem reserve memory size
> + *
> + * Returns: The new PAS context, or ERR_PTR() on failure.
> + */
> +struct qcom_pas_context *devm_qcom_pas_context_alloc(struct device *dev,
> + u32 pas_id,
> + phys_addr_t mem_phys,
> + size_t mem_size)
> +{
> + struct qcom_pas_context *ctx;
> +
> + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> + if (!ctx)
> + return ERR_PTR(-ENOMEM);
> +
> + ctx->dev = dev;
> + ctx->pas_id = pas_id;
> + ctx->mem_phys = mem_phys;
> + ctx->mem_size = mem_size;
> +
> + return ctx;
> +}
> +EXPORT_SYMBOL_GPL(devm_qcom_pas_context_alloc);
> +
> +/**
> + * qcom_pas_init_image() - Initialize peripheral authentication service state
> + * machine for a given peripheral, using the metadata
> + * @pas_id: peripheral authentication service id
> + * @metadata: pointer to memory containing ELF header, program header table
> + * and optional blob of data used for authenticating the metadata
> + * and the rest of the firmware
> + * @size: size of the metadata
> + * @ctx: optional pas context
> + *
> + * Return: 0 on success.
> + *
> + * Upon successful return, the PAS metadata context (@ctx) will be used to
> + * track the metadata allocation, this needs to be released by invoking
> + * qcom_pas_metadata_release() by the caller.
> + */
> +int qcom_pas_init_image(u32 pas_id, const void *metadata, size_t size,
> + struct qcom_pas_context *ctx)
> +{
> + if (ops_ptr)
> + return ops_ptr->init_image(ops_ptr->dev, pas_id,
> + metadata, size, ctx);
> +
> + return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_init_image);
> +
> +/**
> + * qcom_pas_metadata_release() - release metadata context
> + * @ctx: pas context
> + */
> +void qcom_pas_metadata_release(struct qcom_pas_context *ctx)
> +{
> + if (!ctx || !ctx->ptr)
> + return;
> +
> + if (ops_ptr)
> + ops_ptr->metadata_release(ops_ptr->dev, ctx);
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_metadata_release);
> +
> +/**
> + * qcom_pas_mem_setup() - Prepare the memory related to a given peripheral
> + * for firmware loading
> + * @pas_id: peripheral authentication service id
> + * @addr: start address of memory area to prepare
> + * @size: size of the memory area to prepare
> + *
> + * Returns 0 on success.
> + */
> +int qcom_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size)
> +{
> + if (ops_ptr)
> + return ops_ptr->mem_setup(ops_ptr->dev, pas_id, addr, size);
> +
> + return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_mem_setup);
> +
> +/**
> + * qcom_pas_get_rsc_table() - Retrieve the resource table in passed output buffer
> + * for a given peripheral.
> + *
> + * Qualcomm remote processor may rely on both static and dynamic resources for
> + * its functionality. Static resources typically refer to memory-mapped
> + * addresses required by the subsystem and are often embedded within the
> + * firmware binary and dynamic resources, such as shared memory in DDR etc.,
> + * are determined at runtime during the boot process.
> + *
> + * On Qualcomm Technologies devices, it's possible that static resources are
> + * not embedded in the firmware binary and instead are provided by TrustZone.
> + * However, dynamic resources are always expected to come from TrustZone. This
Is it confirmed that it will always come from Trustzone? Is it not possible
that it can come from trusted controller - bypassing the trustzone? Assuming that
such controller is never modified by anyone else including final device makers and
blessed by the trust boundaries.
Is this design going to scale if we put the MCU doing the heavy lifting instead?
> + * indicates that for Qualcomm devices, all resources (static and dynamic) will
> + * be provided by TrustZone PAS service.
> + *
> + * If the remote processor firmware binary does contain static resources, they
> + * should be passed in input_rt. These will be forwarded to TrustZone for
> + * authentication. TrustZone will then append the dynamic resources and return
> + * the complete resource table in output_rt_tzm.
> + *
> + * If the remote processor firmware binary does not include a resource table,
> + * the caller of this function should set input_rt as NULL and input_rt_size
> + * as zero respectively.
> + *
> + * More about documentation on resource table data structures can be found in
> + * include/linux/remoteproc.h
> + *
> + * @ctx: PAS context
> + * @pas_id: peripheral authentication service id
> + * @input_rt: resource table buffer which is present in firmware binary
> + * @input_rt_size: size of the resource table present in firmware binary
> + * @output_rt_size: TrustZone expects caller should pass worst case size for
> + * the output_rt_tzm.
> + *
> + * Return:
> + * On success, returns a pointer to the allocated buffer containing the final
> + * resource table and output_rt_size will have actual resource table size from
> + * TrustZone. The caller is responsible for freeing the buffer. On failure,
> + * returns ERR_PTR(-errno).
> + */
> +struct resource_table *qcom_pas_get_rsc_table(struct qcom_pas_context *ctx,
> + void *input_rt,
> + size_t input_rt_size,
> + size_t *output_rt_size)
> +{
> + if (ops_ptr)
> + return ops_ptr->get_rsc_table(ops_ptr->dev, ctx, input_rt,
> + input_rt_size, output_rt_size);
> +
> + return ERR_PTR(-ENODEV);
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_get_rsc_table);
> +
> +/**
> + * qcom_scm_pas_auth_and_reset() - Authenticate the given peripheral firmware
> + * and reset the remote processor
> + * @pas_id: peripheral authentication service id
> + *
> + * Return 0 on success.
> + */
> +int qcom_pas_auth_and_reset(u32 pas_id)
> +{
> + if (ops_ptr)
> + return ops_ptr->auth_and_reset(ops_ptr->dev, pas_id);
> +
> + return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_auth_and_reset);
> +
> +/**
> + * qcom_pas_prepare_and_auth_reset() - Prepare, authenticate, and reset the
> + * remote processor
> + *
> + * @ctx: Context saved during call to qcom_scm_pas_context_init()
> + *
> + * This function performs the necessary steps to prepare a PAS subsystem,
> + * authenticate it using the provided metadata, and initiate a reset sequence.
> + *
> + * It should be used when Linux is in control setting up the IOMMU hardware
> + * for remote subsystem during secure firmware loading processes. The
> + * preparation step sets up a shmbridge over the firmware memory before
> + * TrustZone accesses the firmware memory region for authentication. The
> + * authentication step verifies the integrity and authenticity of the firmware
> + * or configuration using secure metadata. Finally, the reset step ensures the
> + * subsystem starts in a clean and sane state.
> + *
> + * Return: 0 on success, negative errno on failure.
> + */
> +int qcom_pas_prepare_and_auth_reset(struct qcom_pas_context *ctx)
> +{
> + if (ops_ptr)
> + return ops_ptr->prepare_and_auth_reset(ops_ptr->dev, ctx);
> +
> + return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_prepare_and_auth_reset);
> +
> +/**
> + * qcom_pas_set_remote_state() - Set the remote processor state
> + * @state: peripheral state
> + * @pas_id: peripheral authentication service id
> + *
> + * Returns 0 on success.
> + */
> +int qcom_pas_set_remote_state(u32 state, u32 pas_id)
> +{
> + if (ops_ptr)
> + return ops_ptr->set_remote_state(ops_ptr->dev, state, pas_id);
> +
> + return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_set_remote_state);
> +
> +/**
> + * qcom_pas_shutdown() - Shut down the remote processor
> + * @pas_id: peripheral authentication service id
> + *
> + * Returns 0 on success.
> + */
> +int qcom_pas_shutdown(u32 pas_id)
> +{
> + if (ops_ptr)
> + return ops_ptr->shutdown(ops_ptr->dev, pas_id);
> +
> + return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_shutdown);
> +
> +/**
> + * qcom_pas_supported() - Check if the peripheral authentication service is
> + * available for the given peripheral
> + * @pas_id: peripheral authentication service id
> + *
> + * Returns true if PAS is supported for this peripheral, otherwise false.
> + */
> +bool qcom_pas_supported(u32 pas_id)
> +{
> + if (ops_ptr)
> + return ops_ptr->supported(ops_ptr->dev, pas_id);
> +
> + return false;
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_supported);
> +
> +/**
> + * qcom_pas_is_available() - Check for PAS service
> + *
> + * Returns true on success.
> + */
> +bool qcom_pas_is_available(void)
> +{
> + /* The barrier is needed to synchronize with client drivers. */
> + return !!smp_load_acquire(&ops_ptr);
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_is_available);
> +
> +/**
> + * qcom_pas_ops_register() - Register PAS service ops
> + * @ops: PAS service ops pointer
> + */
> +void qcom_pas_ops_register(struct qcom_pas_ops *ops)
> +{
> + if (!qcom_pas_is_available())
> + /* The barrier is needed to synchronize with client drivers. */
> + smp_store_release(&ops_ptr, ops);
> + else
> + pr_err("qcom_pas: ops already registered\n");
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_ops_register);
> +
> +/**
> + * qcom_pas_ops_unregister() - Unregister PAS service ops
> + */
> +void qcom_pas_ops_unregister(void)
> +{
> + /* The barrier is needed to synchronize with client drivers. */
> + smp_store_release(&ops_ptr, NULL);
> +}
> +EXPORT_SYMBOL_GPL(qcom_pas_ops_unregister);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Sumit Garg <sumit.garg@oss.qualcomm.com>");
What is the convention for Qualcomm authored drivers? In some drivers
I find that Qualcomm doesn't add MODULE_AUTHOR. Can Qualcomm community
clarify it here. I prefer consistency here for the Qualcomm submissions.
> +MODULE_DESCRIPTION("Qualcomm common TZ PAS driver");
> diff --git a/drivers/firmware/qcom/qcom_pas.h b/drivers/firmware/qcom/qcom_pas.h
> new file mode 100644
> index 000000000000..4ebed22178f8
> --- /dev/null
> +++ b/drivers/firmware/qcom/qcom_pas.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#ifndef __QCOM_PAS_INT_H
> +#define __QCOM_PAS_INT_H
> +
> +struct device;
> +
> +/**
> + * struct qcom_pas_ops - Qcom Peripheral Authentication Service (PAS) ops
> + * @drv_name: PAS driver name.
> + * @dev: PAS device pointer.
> + * @supported: Peripheral supported callback.
> + * @init_image: Peripheral image initialization callback.
> + * @mem_setup: Peripheral memory setup callback.
> + * @get_rsc_table: Peripheral get resource table callback.
> + * @prepare_and_auth_reset: Peripheral prepare firmware authentication and
> + * reset callback.
> + * @auth_and_reset: Peripheral firmware authentication and reset
> + * callback.
> + * @set_remote_state: Peripheral set remote state callback.
> + * @shutdown: Peripheral shutdown callback.
> + * @metadata_release: Image metadata release callback.
> + */
> +struct qcom_pas_ops {
> + const char *drv_name;
> + struct device *dev;
> + bool (*supported)(struct device *dev, u32 pas_id);
> + int (*init_image)(struct device *dev, u32 pas_id,
> + const void *metadata, size_t size,
> + struct qcom_pas_context *ctx);
> + int (*mem_setup)(struct device *dev, u32 pas_id,
> + phys_addr_t addr, phys_addr_t size);
> + void *(*get_rsc_table)(struct device *dev,
> + struct qcom_pas_context *ctx,
> + void *input_rt,
> + size_t input_rt_size,
> + size_t *output_rt_size);
void * or resource_table * as return?
> + int (*prepare_and_auth_reset)(struct device *dev,
> + struct qcom_pas_context *ctx);
> + int (*auth_and_reset)(struct device *dev, u32 pas_id);
> + int (*set_remote_state)(struct device *dev, u32 state, u32 pas_id);
> + int (*shutdown)(struct device *dev, u32 pas_id);
> + void (*metadata_release)(struct device *dev,
> + struct qcom_pas_context *ctx);
> +};
> +
> +void qcom_pas_ops_register(struct qcom_pas_ops *ops);
> +void qcom_pas_ops_unregister(void);
> +
> +#endif /* __QCOM_PAS_INT_H */
> diff --git a/include/linux/firmware/qcom/qcom_pas.h b/include/linux/firmware/qcom/qcom_pas.h
> new file mode 100644
> index 000000000000..ef7328ecfa47
> --- /dev/null
> +++ b/include/linux/firmware/qcom/qcom_pas.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#ifndef __QCOM_PAS_H
> +#define __QCOM_PAS_H
> +
> +#include <linux/err.h>
> +#include <linux/types.h>
> +
> +struct qcom_pas_context {
> + struct device *dev;
> + u32 pas_id;
> + phys_addr_t mem_phys;
> + size_t mem_size;
> + void *ptr;
> + dma_addr_t phys;
> + ssize_t size;
> + bool use_tzmem;
> +};
> +
> +bool qcom_pas_is_available(void);
> +struct qcom_pas_context *devm_qcom_pas_context_alloc(struct device *dev,
> + u32 pas_id,
> + phys_addr_t mem_phys,
> + size_t mem_size);
> +int qcom_pas_init_image(u32 pas_id, const void *metadata, size_t size,
> + struct qcom_pas_context *ctx);
> +struct resource_table *qcom_pas_get_rsc_table(struct qcom_pas_context *ctx,
> + void *input_rt, size_t input_rt_size,
> + size_t *output_rt_size);
> +int qcom_pas_mem_setup(u32 pas_id, phys_addr_t addr, phys_addr_t size);
> +int qcom_pas_auth_and_reset(u32 pas_id);
> +int qcom_pas_prepare_and_auth_reset(struct qcom_pas_context *ctx);
> +int qcom_pas_set_remote_state(u32 state, u32 pas_id);
> +int qcom_pas_shutdown(u32 pas_id);
> +bool qcom_pas_supported(u32 pas_id);
> +void qcom_pas_metadata_release(struct qcom_pas_context *ctx);
> +
> +#endif /* __QCOM_PAS_H */
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Trilok Soni @ 2026-03-06 20:00 UTC (permalink / raw)
To: Sumit Garg, linux-arm-msm, devicetree, dri-devel, freedreno,
linux-media, netdev, linux-wireless, ath12k, linux-remoteproc
Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
airlied, simona, vikash.garodia, dikshita.agarwal, bod, mchehab,
elder, andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, mukesh.ojha, pavan.kondeti, jorge.ramirez, tonyh,
vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <e0a86461-c136-4371-99cf-c0b0d31443a3@oss.qualcomm.com>
On 3/6/2026 11:47 AM, Trilok Soni wrote:
>> diff --git a/drivers/firmware/qcom/qcom_pas.c b/drivers/firmware/qcom/qcom_pas.c
>> new file mode 100644
>> index 000000000000..dc04ff1b6be0
>> --- /dev/null
>> +++ b/drivers/firmware/qcom/qcom_pas.c
>> @@ -0,0 +1,295 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/device/devres.h>
>> +#include <linux/firmware/qcom/qcom_pas.h>
>> +#include <linux/of.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
> are you sure you are using functionalities from these header files?
>
> I couldn't find slab.h usage quickly and also qcom_scm.h. Can you please confirm?
I scrolled this patch too fast. I can see slab.h usage, but not sure about qcom_scm.h.
^ permalink raw reply
* [PATCH] wifi: mac80211: fix static key race condition in aql_enable_write()
From: Josh Poimboeuf @ 2026-03-06 20:01 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-kernel, Lorenzo Bianconi, Peter Zijlstra, linux-wireless,
syzbot+feb9ce36a95341bb47a4
If multiple tasks are writing to the 'aql_enable' debugfs file, it may
incorrectly call static_branch_dec() for an already disabled static key,
resulting in the following warning:
val == 0
WARNING: kernel/jump_label.c:311 at __static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311, CPU#0: syz.1.3155/20288
...
Call Trace:
<TASK>
__static_key_slow_dec_cpuslocked kernel/jump_label.c:297 [inline]
__static_key_slow_dec kernel/jump_label.c:321 [inline]
static_key_slow_dec+0x7c/0xc0 kernel/jump_label.c:336
aql_enable_write+0x2b2/0x310 net/mac80211/debugfs.c:343
short_proxy_write+0x133/0x1a0 fs/debugfs/file.c:383
vfs_write+0x2aa/0x1070 fs/read_write.c:684
ksys_pwrite64 fs/read_write.c:793 [inline]
__do_sys_pwrite64 fs/read_write.c:801 [inline]
__se_sys_pwrite64 fs/read_write.c:798 [inline]
__x64_sys_pwrite64+0x1eb/0x250 fs/read_write.c:798
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Fix it by using the atomic static_branch_{enable,disable}() interfaces.
Fixes: e908435e402a ("mac80211: introduce aql_enable node in debugfs")
Reported-by: syzbot+feb9ce36a95341bb47a4@syzkaller.appspotmail.com
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
net/mac80211/debugfs.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index d02f07368c51..687a66cd4943 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -320,7 +320,6 @@ static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
- bool aql_disabled = static_key_false(&aql_disable.key);
char buf[3];
size_t len;
@@ -335,15 +334,12 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = 0;
- if (buf[0] == '0' && buf[1] == '\0') {
- if (!aql_disabled)
- static_branch_inc(&aql_disable);
- } else if (buf[0] == '1' && buf[1] == '\0') {
- if (aql_disabled)
- static_branch_dec(&aql_disable);
- } else {
+ if (buf[0] == '0' && buf[1] == '\0')
+ static_branch_enable(&aql_disable);
+ else if (buf[0] == '1' && buf[1] == '\0')
+ static_branch_disable(&aql_disable);
+ else
return -EINVAL;
- }
return count;
}
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] wifi: mac80211: fix static key race condition in aql_enable_write()
From: Johannes Berg @ 2026-03-06 20:23 UTC (permalink / raw)
To: Josh Poimboeuf
Cc: linux-kernel, Lorenzo Bianconi, Peter Zijlstra, linux-wireless,
syzbot+feb9ce36a95341bb47a4
In-Reply-To: <890b1c1e0eec8f97426c1443745853250dc80737.1772827269.git.jpoimboe@kernel.org>
On Fri, 2026-03-06 at 12:01 -0800, Josh Poimboeuf wrote:
> If multiple tasks are writing to the 'aql_enable' debugfs file, it may
> incorrectly call static_branch_dec() for an already disabled static key,
> resulting in the following warning:
>
> val == 0
> WARNING: kernel/jump_label.c:311 at __static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311, CPU#0: syz.1.3155/20288
> ...
> Call Trace:
> <TASK>
> __static_key_slow_dec_cpuslocked kernel/jump_label.c:297 [inline]
> __static_key_slow_dec kernel/jump_label.c:321 [inline]
> static_key_slow_dec+0x7c/0xc0 kernel/jump_label.c:336
> aql_enable_write+0x2b2/0x310 net/mac80211/debugfs.c:343
> short_proxy_write+0x133/0x1a0 fs/debugfs/file.c:383
> vfs_write+0x2aa/0x1070 fs/read_write.c:684
> ksys_pwrite64 fs/read_write.c:793 [inline]
> __do_sys_pwrite64 fs/read_write.c:801 [inline]
> __se_sys_pwrite64 fs/read_write.c:798 [inline]
> __x64_sys_pwrite64+0x1eb/0x250 fs/read_write.c:798
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> Fix it by using the atomic static_branch_{enable,disable}() interfaces.
Heh, I just applied the same change:
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/commit/?id=b94ae8e0d5fe1bdbbfdc3854ff6ce98f6876a828
johannes
^ permalink raw reply
* Re: [PATCH] wifi: mac80211: fix static key race condition in aql_enable_write()
From: Josh Poimboeuf @ 2026-03-06 20:45 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-kernel, Lorenzo Bianconi, Peter Zijlstra, linux-wireless,
syzbot+feb9ce36a95341bb47a4
In-Reply-To: <c1029770c99b9aa7e9603e666b6626197a5d1c9c.camel@sipsolutions.net>
On Fri, Mar 06, 2026 at 09:23:07PM +0100, Johannes Berg wrote:
> On Fri, 2026-03-06 at 12:01 -0800, Josh Poimboeuf wrote:
> > If multiple tasks are writing to the 'aql_enable' debugfs file, it may
> > incorrectly call static_branch_dec() for an already disabled static key,
> > resulting in the following warning:
> >
> > val == 0
> > WARNING: kernel/jump_label.c:311 at __static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311, CPU#0: syz.1.3155/20288
> > ...
> > Call Trace:
> > <TASK>
> > __static_key_slow_dec_cpuslocked kernel/jump_label.c:297 [inline]
> > __static_key_slow_dec kernel/jump_label.c:321 [inline]
> > static_key_slow_dec+0x7c/0xc0 kernel/jump_label.c:336
> > aql_enable_write+0x2b2/0x310 net/mac80211/debugfs.c:343
> > short_proxy_write+0x133/0x1a0 fs/debugfs/file.c:383
> > vfs_write+0x2aa/0x1070 fs/read_write.c:684
> > ksys_pwrite64 fs/read_write.c:793 [inline]
> > __do_sys_pwrite64 fs/read_write.c:801 [inline]
> > __se_sys_pwrite64 fs/read_write.c:798 [inline]
> > __x64_sys_pwrite64+0x1eb/0x250 fs/read_write.c:798
> > do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> > do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
> > entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >
> > Fix it by using the atomic static_branch_{enable,disable}() interfaces.
>
> Heh, I just applied the same change:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/commit/?id=b94ae8e0d5fe1bdbbfdc3854ff6ce98f6876a828
Ha, and the code looks identical. I approve ;-)
--
Josh
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: account TX stats only when ACK/BA status is present
From: Jeff Johnson @ 2026-03-06 21:18 UTC (permalink / raw)
To: ath12k, Sarika Sharma; +Cc: linux-wireless
In-Reply-To: <20260226051947.1379716-1-sarika.sharma@oss.qualcomm.com>
On Thu, 26 Feb 2026 10:49:47 +0530, Sarika Sharma wrote:
> The fields tx_retry_failed, tx_retry_count, and tx_duration are
> currently updated outside the HTT_PPDU_STATS_TAG_USR_COMPLTN_ACK_BA_STATUS
> flag check. In certain scenarios, firmware delivers multiple PPDU
> statistics for the same PPDU, first without BA/ACK information, and
> later with BA/ACK status once it becomes available. As the same PPDU
> is processed again, these counters are updated a second time,
> resulting in duplicate TX statistics.
>
> [...]
Applied, thanks!
[1/1] wifi: ath12k: account TX stats only when ACK/BA status is present
commit: 1635ecc61a24597f893d057d004051a535c1c643
Best regards,
--
Jeff Johnson <jeff.johnson@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Fix the assignment of logical link index
From: Jeff Johnson @ 2026-03-06 21:18 UTC (permalink / raw)
To: ath12k, Roopni Devanathan; +Cc: linux-wireless, Manish Dharanenthiran
In-Reply-To: <20260226041911.2434999-1-roopni.devanathan@oss.qualcomm.com>
On Thu, 26 Feb 2026 09:49:11 +0530, Roopni Devanathan wrote:
> Per-link logical index is assigned from the global counter,
> ahsta->num_peer. This logical index is sent to firmware during peer
> association. If there is a failure in creating a link station,
> ath12k_mac_free_unassign_link_sta() clears the link, but does not decrement
> the logical link index. This will result in a higher logical link index for
> the next link station created. Also, if there is a leak in logical link
> index as we assign the incremented num_peer, then the index can exceed the
> maximum valid value of 15.
>
> [...]
Applied, thanks!
[1/1] wifi: ath12k: Fix the assignment of logical link index
commit: aecb569d7fb689e3e5b0005ca7bd0a2ef28915e8
Best regards,
--
Jeff Johnson <jeff.johnson@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: Fix legacy rate mapping for monitor mode capture
From: Jeff Johnson @ 2026-03-06 21:18 UTC (permalink / raw)
To: ath12k, Thiraviyam Mariyappan; +Cc: linux-wireless, P Praneesh
In-Reply-To: <20260209054924.2713072-1-thiraviyam.mariyappan@oss.qualcomm.com>
On Mon, 09 Feb 2026 11:19:24 +0530, Thiraviyam Mariyappan wrote:
> The current implementation incorrectly reports legacy CCK and OFDM rates
> in monitor mode radiotap headers. The rate field displays wrong values,
> for example showing 11 Mbps when the actual rate is 1 Mbps. This occurs
> because the HAL layer uses a unified enum for both CCK and OFDM rates
> without distinguishing between long/short preamble variants and proper
> rate mapping to hardware rate indices.
>
> [...]
Applied, thanks!
[1/1] wifi: ath12k: Fix legacy rate mapping for monitor mode capture
commit: 616217a989e09c55398db8555e5ef0c64504cb66
Best regards,
--
Jeff Johnson <jeff.johnson@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v3][next] wifi: ath6kl: wmi: Avoid -Wflex-array-member-not-at-end warning
From: Jeff Johnson @ 2026-03-06 21:18 UTC (permalink / raw)
To: Gustavo A. R. Silva; +Cc: linux-wireless, linux-kernel, linux-hardening
In-Reply-To: <aZ0tGZnmtGckKJzY@kspp>
On Tue, 24 Feb 2026 13:46:17 +0900, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
> getting ready to enable it, globally.
>
> Remove unused structures bss_bias_info and bss_bias, and member
> bss in struct roam_ctrl_cmd.
>
> After these changes, the size of struct roam_ctrl_cmd, along
> with its member's offsets remain the same, hence the memory layout
> doesn't change:
>
> [...]
Applied, thanks!
[1/1] wifi: ath6kl: wmi: Avoid -Wflex-array-member-not-at-end warning
commit: 8e0ab5b9adb7fec3149441621df1cf15325b7215
Best regards,
--
Jeff Johnson <jeff.johnson@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2 00/18] wifi: drop redundant USB device references
From: Jeff Johnson @ 2026-03-06 21:39 UTC (permalink / raw)
To: Johan Hovold, linux-wireless, Johannes Berg
Cc: Jeff Johnson, Toke Høiland-Jørgensen, Brian Norris,
Francesco Dolcini, Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
Shayne Chen, Sean Wang, Jakub Kicinski, Stanislaw Gruszka,
Hin-Tak Leung, Jes Sorensen, Ping-Ke Shih, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea, Matthias Brugger,
AngeloGioacchino Del Regno, Greg Kroah-Hartman, libertas-dev,
linux-kernel
In-Reply-To: <20260306085144.12064-1-johan@kernel.org>
On 3/6/2026 12:51 AM, Johan Hovold wrote:
> Driver core holds a reference to the USB interface and its parent USB
> device while the interface is bound to a driver and there is no need to
> take additional references unless the structures are needed after
> disconnect.
>
> Drop redundant device references to reduce cargo culting, make it easier
> to spot drivers where an extra reference is needed, and reduce the risk
> of memory leaks when drivers fail to release them.
>
> Note that I sent an ath9k patch separately here:
>
> https://lore.kernel.org/all/20260305105803.17011-1-johan@kernel.org/
>
> but I included it here in v2 for completeness.
>
> Also note that Greg had already sent a fix for rtw88 which has been
> picked up by Ping-Ke, but who asked me to send a replacement. If an
> incremental patch is preferred I can instead send a follow up for that
> one later.
>
> Johan
>
>
> Changes in v2:
> - include ath9k, previously submitted separately
> - include ath6kl and ath10k
> - rename the ath6kl and ath10k disconnect callbacks
> - fix a reference leak in rtw88 previously reported (and fixed
> differently) by Greg
>
>
> Johan Hovold (18):
> wifi: ath6kl: drop redundant device reference
> wifi: ath6kl: rename disconnect callback
> wifi: ath9k: drop redundant device reference
> wifi: ath10k: drop redundant device reference
> wifi: ath10k: rename disconnect callback
> wifi: at76c50x: drop redundant device reference
> wifi: libertas: drop redundant device reference
> wifi: libertas_tf: drop redundant device reference
> wifi: mwifiex: drop redundant device reference
> wifi: mt76: drop redundant device reference
> wifi: mt76x0u: drop redundant device reference
> wifi: mt76x2u: drop redundant device reference
> wifi: mt76: mt792xu: drop redundant device reference
> wifi: mt7601u: drop redundant device reference
> wifi: rt2x00: drop redundant device reference
> wifi: rtl818x: drop redundant device reference
> wifi: rtl8xxxu: drop redundant device reference
> wifi: rtw88: fix device leak on probe failure
>
> drivers/net/wireless/ath/ath10k/usb.c | 8 ++------
> drivers/net/wireless/ath/ath6kl/usb.c | 16 ++++------------
> drivers/net/wireless/ath/ath9k/hif_usb.c | 4 ----
> drivers/net/wireless/atmel/at76c50x-usb.c | 12 ++++--------
> drivers/net/wireless/marvell/libertas/if_usb.c | 3 ---
> .../net/wireless/marvell/libertas_tf/if_usb.c | 2 --
> drivers/net/wireless/marvell/mwifiex/usb.c | 4 ----
> drivers/net/wireless/mediatek/mt76/mt7615/usb.c | 3 ---
> drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 3 ---
> drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 4 ----
> drivers/net/wireless/mediatek/mt76/mt7921/usb.c | 2 --
> drivers/net/wireless/mediatek/mt76/mt7925/usb.c | 2 --
> drivers/net/wireless/mediatek/mt76/mt792x_usb.c | 1 -
> drivers/net/wireless/mediatek/mt7601u/usb.c | 3 ---
> drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 12 +-----------
> .../net/wireless/realtek/rtl818x/rtl8187/dev.c | 4 ----
> drivers/net/wireless/realtek/rtl8xxxu/core.c | 11 +++--------
> drivers/net/wireless/realtek/rtw88/usb.c | 3 +--
> 18 files changed, 15 insertions(+), 82 deletions(-)
>
Johannes, will you be taking the entire series via wireless-next?
Or should the individual wireless driver maintainers take their patches
through their individual trees? I'm OK either way.
/jeff
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Jeff Johnson @ 2026-03-06 22:00 UTC (permalink / raw)
To: Trilok Soni, Sumit Garg, linux-arm-msm, devicetree, dri-devel,
freedreno, linux-media, netdev, linux-wireless, ath12k,
linux-remoteproc
Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
airlied, simona, vikash.garodia, dikshita.agarwal, bod, mchehab,
elder, andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, mukesh.ojha, pavan.kondeti, jorge.ramirez, tonyh,
vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <e0a86461-c136-4371-99cf-c0b0d31443a3@oss.qualcomm.com>
On 3/6/2026 11:47 AM, Trilok Soni wrote:
> On 3/6/2026 2:50 AM, Sumit Garg wrote:
>> +MODULE_LICENSE("GPL");
>> +MODULE_AUTHOR("Sumit Garg <sumit.garg@oss.qualcomm.com>");
>
> What is the convention for Qualcomm authored drivers? In some drivers
> I find that Qualcomm doesn't add MODULE_AUTHOR. Can Qualcomm community
> clarify it here. I prefer consistency here for the Qualcomm submissions.
WLAN team was told to not have MODULE_AUTHOR(), so ath10k was the last WLAN
driver that had a MODULE_AUTHOR() -- ath11k and ath12k do not have one.
And in reality it is very rare for a given module, over time, to only have a
single author. The git history contains the real authorship. So just for that
reason I'd drop it.
/jeff
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Trilok Soni @ 2026-03-06 22:16 UTC (permalink / raw)
To: Jeff Johnson, Sumit Garg, linux-arm-msm, devicetree, dri-devel,
freedreno, linux-media, netdev, linux-wireless, ath12k,
linux-remoteproc
Cc: andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
airlied, simona, vikash.garodia, dikshita.agarwal, bod, mchehab,
elder, andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, mukesh.ojha, pavan.kondeti, jorge.ramirez, tonyh,
vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <13091f47-938d-43fb-a8c0-4b081818b557@oss.qualcomm.com>
On 3/6/2026 2:00 PM, Jeff Johnson wrote:
> On 3/6/2026 11:47 AM, Trilok Soni wrote:
>> On 3/6/2026 2:50 AM, Sumit Garg wrote:
>>> +MODULE_LICENSE("GPL");
>>> +MODULE_AUTHOR("Sumit Garg <sumit.garg@oss.qualcomm.com>");
>>
>> What is the convention for Qualcomm authored drivers? In some drivers
>> I find that Qualcomm doesn't add MODULE_AUTHOR. Can Qualcomm community
>> clarify it here. I prefer consistency here for the Qualcomm submissions.
>
> WLAN team was told to not have MODULE_AUTHOR(), so ath10k was the last WLAN
> driver that had a MODULE_AUTHOR() -- ath11k and ath12k do not have one.
>
> And in reality it is very rare for a given module, over time, to only have a
> single author. The git history contains the real authorship. So just for that
> reason I'd drop it.
I agree and that is the same guideline I follow for the drivers we write
downstream. I just want to make sure that we discuss it here. We may not be able
to find one single solution, but I prefer to get consistency for Qualcomm
submissions.
---Trilok Soni
^ permalink raw reply
* [PATCH 00/19] wifi: mt76: mt7925: fix up MLO link lifetime and error handling
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
Hi,
This series fix up MLO link STA lifetime and error handling in mt7925.
The current add path may expose partially initialized links and does
not reliably release host resources when firmware commands fail (e.g.
MCU timeouts). In addition, several helpers internally look up mlink,
creating implicit dependencies on driver state and making the code
harder to reason about and maintain.
Switch link STA handling to RCU lifetime, align WCID publish/teardown
ordering, pass mlink explicitly to helpers, and add host-side unwind
logic to release resources when link add fails.
Sean
Sean Wang (19):
wifi: mt76: mt7925: pass mlink to sta_amsdu_tlv()
wifi: mt76: mt7925: pass WCID indices to bss_basic_tlv()
wifi: mt76: mt7925: pass mlink and mconf to sta_mld_tlv()
wifi: mt76: mt7925: pass mlink to mcu_sta_update()
wifi: mt76: mt7925: resolve primary mlink via def_wcid
wifi: mt76: mt7925: pass mlink to mac_link_sta_remove()
wifi: mt76: mt7925: pass mlink to sta_hdr_trans_tlv()
wifi: mt76: mt7925: validate mlink in sta_hdr_trans_tlv()
wifi: mt76: mt7925: pass mlink to wtbl_update_hdr_trans()
wifi: mt76: mt7925: pass mlink to set_link_key()
wifi: mt76: mt7925: resolve link after acquiring mt76 mutex
wifi: mt76: mt7925: pass mconf and mlink to wtbl_update_hdr_trans()
wifi: mt76: mt7925: make WCID cleanup unconditional in
sta_remove_links()
wifi: mt76: mt7925: unwind WCID setup on link STA add failure
wifi: mt76: mt7925: drop WCID reinit after publish
wifi: mt76: mt7925: move WCID teardown into link_sta_remove()
wifi: mt76: mt7925: switch link STA allocation to RCU lifetime
wifi: mt76: mt7925: publish msta->link after successful link add
wifi: mt76: mt7925: host-only unwind published links on add failure
.../net/wireless/mediatek/mt76/mt7925/mac.c | 3 +-
.../net/wireless/mediatek/mt76/mt7925/main.c | 221 +++++++++++++-----
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 180 +++++++-------
.../net/wireless/mediatek/mt76/mt7925/mcu.h | 7 +
.../wireless/mediatek/mt76/mt7925/mt7925.h | 8 +-
drivers/net/wireless/mediatek/mt76/mt792x.h | 1 +
6 files changed, 280 insertions(+), 140 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH 01/19] wifi: mt76: mt7925: pass mlink to sta_amsdu_tlv()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Drop the mt792x_sta_to_link() lookup in mt7925_mcu_sta_amsdu_tlv() and
pass mlink from the caller instead. The link context is already known
so the lookup is redundant.
This makes link ownership explicit and keeps the helper lookup-free.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index abcdd0e0b3b5..fa5f79004a6e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1726,10 +1726,9 @@ mt7925_mcu_sta_vht_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)
static void
mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta)
+ struct ieee80211_link_sta *link_sta,
+ struct mt792x_link_sta *mlink)
{
- struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
- struct mt792x_link_sta *mlink;
struct sta_rec_amsdu *amsdu;
struct tlv *tlv;
@@ -1745,7 +1744,6 @@ mt7925_mcu_sta_amsdu_tlv(struct sk_buff *skb,
amsdu->max_amsdu_num = 8;
amsdu->amsdu_en = true;
- mlink = mt792x_sta_to_link(msta, link_sta->link_id);
mlink->wcid.amsdu = true;
switch (link_sta->agg.max_amsdu_len) {
@@ -1966,6 +1964,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;
struct mt76_dev *dev = phy->dev;
struct mt792x_bss_conf *mconf;
+ struct mt792x_link_sta *mlink;
struct sk_buff *skb;
int conn_state;
@@ -1980,6 +1979,8 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
CONN_STATE_DISCONNECT;
if (info->enable && info->link_sta) {
+ mlink = container_of(info->wcid, struct mt792x_link_sta, wcid);
+
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
info->link_sta,
conn_state, info->newly);
@@ -1987,7 +1988,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta);
- mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta);
+ mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta, mlink);
mt7925_mcu_sta_he_tlv(skb, info->link_sta);
mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);
mt7925_mcu_sta_eht_tlv(skb, info->link_sta);
--
2.43.0
^ permalink raw reply related
* [PATCH 02/19] wifi: mt76: mt7925: pass WCID indices to bss_basic_tlv()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Drop the mt792x_sta_to_link() lookup in mt7925_mcu_bss_basic_tlv() and
pass the resolved WCID indices from the caller instead. The link
context is already known, so the lookup is redundant.
This makes link ownership explicit and keeps the helper lookup-free.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/main.c | 34 +++++++---
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 68 ++++++++++++-------
.../net/wireless/mediatek/mt76/mt7925/mcu.h | 7 ++
3 files changed, 73 insertions(+), 36 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index afcc0fa4aa35..353461f0e169 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -850,20 +850,22 @@ mt7925_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta)
+ struct ieee80211_link_sta *link_sta,
+ struct mt792x_link_sta *mlink)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct ieee80211_bss_conf *link_conf;
struct mt792x_bss_conf *mconf;
u8 link_id = link_sta->link_id;
- struct mt792x_link_sta *mlink;
struct mt792x_sta *msta;
struct mt76_wcid *wcid;
int ret, idx;
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
- mlink = mt792x_sta_to_link(msta, link_id);
+
+ if (WARN_ON_ONCE(!mlink))
+ return -EINVAL;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);
if (idx < 0)
@@ -898,12 +900,21 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
/* should update bss info before STA add */
if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) {
- if (ieee80211_vif_is_mld(vif))
- mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
- link_conf, link_sta, link_sta != mlink->pri_link);
- else
- mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx,
- link_conf, link_sta, false);
+ struct mt792x_link_sta *mlink_bc;
+
+ mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
+
+ if (ieee80211_vif_is_mld(vif)) {
+ mt7925_mcu_add_bss_info_sta(&dev->phy, mconf->mt76.ctx,
+ link_conf, link_sta,
+ mlink_bc->wcid.idx, mlink->wcid.idx,
+ link_sta != mlink->pri_link);
+ } else {
+ mt7925_mcu_add_bss_info_sta(&dev->phy, mconf->mt76.ctx,
+ link_conf, link_sta,
+ mlink_bc->wcid.idx, mlink->wcid.idx,
+ false);
+ }
}
if (ieee80211_vif_is_mld(vif) &&
@@ -965,7 +976,7 @@ mt7925_mac_sta_add_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
mlink->wcid.def_wcid = &msta->deflink.wcid;
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
- mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta);
+ mt7925_mac_link_sta_add(&dev->mt76, vif, link_sta, mlink);
}
return err;
@@ -989,7 +1000,8 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
err = mt7925_mac_sta_add_links(dev, vif, sta, sta->valid_links);
} else {
- err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink);
+ err = mt7925_mac_link_sta_add(mdev, vif, &sta->deflink,
+ &msta->deflink);
}
return err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index fa5f79004a6e..0d5519e5dc4a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2476,7 +2476,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
struct ieee80211_chanctx_conf *ctx,
- struct mt76_phy *phy, u16 wlan_idx,
+ struct mt76_phy *phy,
+ u16 bmc_tx_wlan_idx,
+ u16 sta_wlan_idx,
bool enable)
{
struct ieee80211_vif *vif = link_conf->vif;
@@ -2485,7 +2487,6 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
&link_conf->chanreq.oper;
enum nl80211_band band = chandef->chan->band;
struct mt76_connac_bss_basic_tlv *basic_req;
- struct mt792x_link_sta *mlink;
struct tlv *tlv;
int conn_type;
u8 idx;
@@ -2509,20 +2510,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, link_sta);
basic_req->bcn_interval = cpu_to_le16(link_conf->beacon_int);
basic_req->dtim_period = link_conf->dtim_period;
- basic_req->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
+ basic_req->bmc_tx_wlan_idx = cpu_to_le16(bmc_tx_wlan_idx);
basic_req->link_idx = mconf->mt76.idx;
-
- if (link_sta) {
- struct mt792x_sta *msta;
-
- msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
- mlink = mt792x_sta_to_link(msta, link_sta->link_id);
-
- } else {
- mlink = &mconf->vif->sta.deflink;
- }
-
- basic_req->sta_idx = cpu_to_le16(mlink->wcid.idx);
+ basic_req->sta_idx = cpu_to_le16(sta_wlan_idx);
basic_req->omac_idx = mconf->mt76.omac_idx;
basic_req->band_idx = mconf->mt76.band_idx;
basic_req->wmm_idx = mconf->mt76.wmm_idx;
@@ -2829,16 +2819,16 @@ void mt7925_mcu_del_dev(struct mt76_dev *mdev,
&dev_req, sizeof(dev_req), true);
}
-int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
- struct ieee80211_chanctx_conf *ctx,
- struct ieee80211_bss_conf *link_conf,
- struct ieee80211_link_sta *link_sta,
- int enable)
+int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
+ struct ieee80211_chanctx_conf *ctx,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_link_sta *link_sta,
+ u16 bmc_tx_wlan_idx,
+ u16 sta_wlan_idx,
+ int enable)
{
- struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
struct mt792x_dev *dev = phy->dev;
- struct mt792x_link_sta *mlink_bc;
struct sk_buff *skb;
skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mconf->mt76,
@@ -2846,11 +2836,9 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
if (IS_ERR(skb))
return PTR_ERR(skb);
- mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
-
/* bss_basic must be first */
mt7925_mcu_bss_basic_tlv(skb, link_conf, link_sta, ctx, phy->mt76,
- mlink_bc->wcid.idx, enable);
+ bmc_tx_wlan_idx, sta_wlan_idx, enable);
mt7925_mcu_bss_sec_tlv(skb, link_conf);
mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, link_conf);
mt7925_mcu_bss_qos_tlv(skb, link_conf);
@@ -2871,6 +2859,36 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
}
+int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
+ struct ieee80211_chanctx_conf *ctx,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_link_sta *link_sta,
+ int enable)
+{
+ struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
+ struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
+ struct mt792x_link_sta *mlink_bc;
+ struct mt792x_link_sta *mlink;
+ u16 sta_wlan_idx;
+
+ sta_wlan_idx = mvif->sta.deflink.wcid.idx;
+
+ mlink_bc = mt792x_sta_to_link(&mvif->sta, mconf->link_id);
+
+ if (link_sta) {
+ struct mt792x_sta *msta = (void *)link_sta->sta->drv_priv;
+
+ mlink = mt792x_sta_to_link(msta, link_sta->link_id);
+ if (WARN_ON(!mlink))
+ return -1;
+ } else {
+ mlink = &mconf->vif->sta.deflink;
+ }
+
+ return mt7925_mcu_add_bss_info_sta(phy, ctx, link_conf, link_sta,
+ mlink_bc->wcid.idx, mlink->wcid.idx, enable);
+}
+
int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
{
struct mt76_dev *mdev = phy->dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
index e09e0600534a..56e2772f3ffe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
@@ -693,6 +693,13 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
int enable);
+int mt7925_mcu_add_bss_info_sta(struct mt792x_phy *phy,
+ struct ieee80211_chanctx_conf *ctx,
+ struct ieee80211_bss_conf *link_conf,
+ struct ieee80211_link_sta *link_sta,
+ u16 bmc_tx_wlan_idx,
+ u16 sta_wlan_idx,
+ int enable);
int mt7925_mcu_set_timing(struct mt792x_phy *phy,
struct ieee80211_bss_conf *link_conf);
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
--
2.43.0
^ permalink raw reply related
* [PATCH 03/19] wifi: mt76: mt7925: pass mlink and mconf to sta_mld_tlv()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Drop the mt792x_sta_to_link() lookup in mt7925_mcu_sta_mld_tlv() and
pass mlink and mconf from the caller instead. The link context is
already known at the call site, making the lookup redundant.
This keeps the helper lookup-free and makes MLD link selection
explicit.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 53 +++++++++++++------
1 file changed, 36 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 0d5519e5dc4a..7582a8c48607 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1914,36 +1914,53 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb,
static void
mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct mt792x_bss_conf *mconf,
+ struct mt792x_link_sta *mlink)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
- unsigned long valid = mvif->valid_links;
- struct mt792x_bss_conf *mconf;
- struct mt792x_link_sta *mlink;
+ struct mt792x_dev *dev = mvif->phy->dev;
+ struct mt792x_bss_conf *mconf_pri;
struct sta_rec_mld *mld;
struct tlv *tlv;
- int i, cnt = 0;
+ u8 cnt = 0;
+
+ /* Primary link always uses driver's deflink WCID. */
+ mconf_pri = (msta->deflink_id != IEEE80211_LINK_UNSPECIFIED) ?
+ mt792x_vif_to_link(mvif, msta->deflink_id) : NULL;
+
+ /* If caller is operating on deflink, reuse its mconf as primary. */
+ if (!mconf_pri && mlink == &msta->deflink)
+ mconf_pri = mconf;
+
+ if (!mconf_pri) {
+ dev_warn_ratelimited(dev->mt76.dev,
+ "mt7925: MLD_TLV_LINK skip (no primary mconf) sta=%pM\n",
+ sta->addr);
+ return;
+ }
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD, sizeof(*mld));
mld = (struct sta_rec_mld *)tlv;
memcpy(mld->mac_addr, sta->addr, ETH_ALEN);
+
mld->primary_id = cpu_to_le16(msta->deflink.wcid.idx);
mld->wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
- mld->link_num = min_t(u8, hweight16(mvif->valid_links), 2);
- for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
- if (cnt == mld->link_num)
- break;
+ /* Always encode primary link first. */
+ mld->link[cnt].wlan_id = cpu_to_le16(msta->deflink.wcid.idx);
+ mld->link[cnt++].bss_idx = mconf_pri->mt76.idx;
- mconf = mt792x_vif_to_link(mvif, i);
- mlink = mt792x_sta_to_link(msta, i);
+ /* Optionally encode the currently-updated secondary link. */
+ if (mlink && mlink != &msta->deflink && mconf) {
+ mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
mld->link[cnt].wlan_id = cpu_to_le16(mlink->wcid.idx);
mld->link[cnt++].bss_idx = mconf->mt76.idx;
-
- if (mlink != &msta->deflink)
- mld->secondary_id = cpu_to_le16(mlink->wcid.idx);
}
+
+ mld->link_num = cnt;
}
static void
@@ -1969,6 +1986,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
int conn_state;
mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
+ mlink = container_of(info->wcid, struct mt792x_link_sta, wcid);
skb = __mt76_connac_mcu_alloc_sta_req(dev, &mconf->mt76, info->wcid,
MT7925_STA_UPDATE_MAX_SIZE);
@@ -1979,8 +1997,6 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
CONN_STATE_DISCONNECT;
if (info->enable && info->link_sta) {
- mlink = container_of(info->wcid, struct mt792x_link_sta, wcid);
-
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
info->link_sta,
conn_state, info->newly);
@@ -1999,7 +2015,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
info->state);
if (info->state != MT76_STA_INFO_STATE_NONE) {
- mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);
+ mt7925_mcu_sta_mld_tlv(skb, info->vif,
+ info->link_sta->sta,
+ mconf, mlink);
+
mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);
}
}
--
2.43.0
^ permalink raw reply related
* [PATCH 04/19] wifi: mt76: mt7925: pass mlink to mcu_sta_update()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Drop the mt792x_sta_to_link() lookup in mt7925_mcu_sta_update() and
pass the resolved mlink from the caller instead. The link context is
already known at the call site, making the lookup redundant.
This keeps the helper lookup-free and makes WCID selection explicit.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/mac.c | 3 ++-
.../net/wireless/mediatek/mt76/mt7925/main.c | 27 +++++++++++++------
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 12 +++------
.../wireless/mediatek/mt76/mt7925/mt7925.h | 4 ++-
4 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 82eedd80f694..139c2a7871fc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -1285,7 +1285,8 @@ mt7925_vif_connect_iter(void *priv, u8 *mac,
if (vif->type == NL80211_IFTYPE_AP) {
mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.deflink.wcid,
true, NULL);
- mt7925_mcu_sta_update(dev, NULL, vif, true,
+ mt7925_mcu_sta_update(dev, NULL, vif,
+ &mvif->sta.deflink, true,
MT76_STA_INFO_STATE_NONE);
mt7925_mcu_uni_add_beacon_offload(dev, hw, vif, true);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 353461f0e169..c65e32a14c01 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -919,23 +919,31 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
if (ieee80211_vif_is_mld(vif) &&
link_sta == mlink->pri_link) {
- ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
+ ret = mt7925_mcu_sta_update(dev, link_sta, vif,
+ mlink, true,
MT76_STA_INFO_STATE_NONE);
if (ret)
return ret;
} else if (ieee80211_vif_is_mld(vif) &&
link_sta != mlink->pri_link) {
+ struct mt792x_link_sta *pri_mlink;
+
+ pri_mlink = mt792x_sta_to_link(msta, mlink->pri_link->link_id);
+
ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,
- true, MT76_STA_INFO_STATE_ASSOC);
+ pri_mlink, true,
+ MT76_STA_INFO_STATE_ASSOC);
if (ret)
return ret;
- ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
+ ret = mt7925_mcu_sta_update(dev, link_sta, vif,
+ mlink, true,
MT76_STA_INFO_STATE_ASSOC);
if (ret)
return ret;
} else {
- ret = mt7925_mcu_sta_update(dev, link_sta, vif, true,
+ ret = mt7925_mcu_sta_update(dev, link_sta, vif,
+ mlink, true,
MT76_STA_INFO_STATE_NONE);
if (ret)
return ret;
@@ -1075,7 +1083,8 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
memset(mlink->airtime_ac, 0, sizeof(mlink->airtime_ac));
- mt7925_mcu_sta_update(dev, link_sta, vif, true, MT76_STA_INFO_STATE_ASSOC);
+ mt7925_mcu_sta_update(dev, link_sta, vif, mlink, true,
+ MT76_STA_INFO_STATE_ASSOC);
mt792x_mutex_release(dev);
}
@@ -1119,7 +1128,7 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid);
mt76_connac_pm_wake(&dev->mphy, &dev->pm);
- mt7925_mcu_sta_update(dev, link_sta, vif, false,
+ mt7925_mcu_sta_update(dev, link_sta, vif, mlink, false,
MT76_STA_INFO_STATE_NONE);
mt7925_mac_wtbl_update(dev, mlink->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -1744,7 +1753,8 @@ mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (err)
goto out;
- err = mt7925_mcu_sta_update(dev, NULL, vif, true,
+ err = mt7925_mcu_sta_update(dev, NULL, vif,
+ &mvif->sta.deflink, true,
MT76_STA_INFO_STATE_NONE);
out:
mt792x_mutex_release(dev);
@@ -1887,7 +1897,8 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,
mt792x_mutex_acquire(dev);
if (changed & BSS_CHANGED_ASSOC) {
- mt7925_mcu_sta_update(dev, NULL, vif, true,
+ mt7925_mcu_sta_update(dev, NULL, vif,
+ &mvif->sta.deflink, true,
MT76_STA_INFO_STATE_ASSOC);
mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 7582a8c48607..fa4915b65fcc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2036,7 +2036,9 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
int mt7925_mcu_sta_update(struct mt792x_dev *dev,
struct ieee80211_link_sta *link_sta,
- struct ieee80211_vif *vif, bool enable,
+ struct ieee80211_vif *vif,
+ struct mt792x_link_sta *mlink,
+ bool enable,
enum mt76_sta_info_state state)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
@@ -2051,14 +2053,8 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,
.offload_fw = true,
.rcpi = to_rcpi(rssi),
};
- struct mt792x_sta *msta;
- struct mt792x_link_sta *mlink;
- if (link_sta) {
- msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
- mlink = mt792x_sta_to_link(msta, link_sta->link_id);
- }
- info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid;
+ info.wcid = &mlink->wcid;
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
return mt7925_mcu_sta_cmd(&dev->mphy, &info);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index 0f0eff748bb7..95f29dae4d9d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -250,7 +250,9 @@ int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev,
bool enable);
int mt7925_mcu_sta_update(struct mt792x_dev *dev,
struct ieee80211_link_sta *link_sta,
- struct ieee80211_vif *vif, bool enable,
+ struct ieee80211_vif *vif,
+ struct mt792x_link_sta *mlink,
+ bool enable,
enum mt76_sta_info_state state);
int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);
int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_bss_conf *bss_conf);
--
2.43.0
^ permalink raw reply related
* [PATCH 05/19] wifi: mt76: mt7925: resolve primary mlink via def_wcid
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Use mlink->wcid.def_wcid to obtain the primary mlink in
mt7925_mac_link_sta_add() instead of calling mt792x_sta_to_link().
The primary link context is already carried by the WCID, so the extra
lookup is redundant. This makes the add path follow the existing WCID
association directly.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index c65e32a14c01..d7a09a0a79fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -927,8 +927,17 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev,
} else if (ieee80211_vif_is_mld(vif) &&
link_sta != mlink->pri_link) {
struct mt792x_link_sta *pri_mlink;
+ struct mt76_wcid *pri_wcid;
- pri_mlink = mt792x_sta_to_link(msta, mlink->pri_link->link_id);
+ /* alternative lookup via def_wcid */
+ pri_wcid = mlink->wcid.def_wcid;
+
+ pri_mlink = pri_wcid ?
+ container_of(pri_wcid, struct mt792x_link_sta, wcid) :
+ NULL;
+
+ if (WARN_ON_ONCE(!pri_mlink))
+ return -EINVAL;
ret = mt7925_mcu_sta_update(dev, mlink->pri_link, vif,
pri_mlink, true,
--
2.43.0
^ permalink raw reply related
* [PATCH 06/19] wifi: mt76: mt7925: pass mlink to mac_link_sta_remove()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Drop the mt792x_sta_to_link() lookup in mt7925_mac_link_sta_remove()
and pass mlink from mt7925_mac_sta_remove_links() instead. The link is
already resolved there, making the extra lookup redundant.
This keeps the remove helper lookup-free and avoids hidden dependence on
msta->link[link_id] during teardown.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index d7a09a0a79fb..ddff6c5ab876 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1121,16 +1121,12 @@ EXPORT_SYMBOL_GPL(mt7925_mac_sta_event);
static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta)
+ struct ieee80211_link_sta *link_sta,
+ struct mt792x_link_sta *mlink)
{
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
struct ieee80211_bss_conf *link_conf;
u8 link_id = link_sta->link_id;
- struct mt792x_link_sta *mlink;
- struct mt792x_sta *msta;
-
- msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
- mlink = mt792x_sta_to_link(msta, link_id);
mt7925_roc_abort_sync(dev);
@@ -1213,7 +1209,7 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
if (!mlink)
continue;
- mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta);
+ mt7925_mac_link_sta_remove(&dev->mt76, vif, link_sta, mlink);
wcid = &mlink->wcid;
rcu_assign_pointer(msta->link[link_id], NULL);
--
2.43.0
^ permalink raw reply related
* [PATCH 07/19] wifi: mt76: mt7925: pass mlink to sta_hdr_trans_tlv()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Drop the mt792x_sta_to_link() lookup in mt7925_mcu_sta_hdr_trans_tlv()
and pass the resolved mlink from the caller instead. The link is
already known at the call site, making the lookup redundant.
This keeps the helper lookup-free and makes WCID selection explicit.
No functional change intended.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 24 +++++++++----------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index fa4915b65fcc..c474dd358650 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1066,9 +1066,9 @@ EXPORT_SYMBOL_GPL(mt7925_run_firmware);
static void
mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta)
+ struct ieee80211_link_sta *link_sta,
+ struct mt792x_link_sta *mlink)
{
- struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct sta_rec_hdr_trans *hdr_trans;
struct mt76_wcid *wcid;
struct tlv *tlv;
@@ -1082,15 +1082,7 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
else
hdr_trans->from_ds = true;
- if (link_sta) {
- struct mt792x_sta *msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
- struct mt792x_link_sta *mlink;
-
- mlink = mt792x_sta_to_link(msta, link_sta->link_id);
- wcid = &mlink->wcid;
- } else {
- wcid = &mvif->sta.deflink.wcid;
- }
+ wcid = &mlink->wcid;
if (!wcid)
return;
@@ -1127,7 +1119,10 @@ int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
return PTR_ERR(skb);
/* starec hdr trans */
- mt7925_mcu_sta_hdr_trans_tlv(skb, vif, link_sta);
+ if (!link_sta)
+ mlink = &mvif->sta.deflink;
+
+ mt7925_mcu_sta_hdr_trans_tlv(skb, vif, link_sta, mlink);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}
@@ -2028,7 +2023,10 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,
sizeof(struct tlv));
} else {
- mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);
+ if (!info->link_sta)
+ mlink = &mvif->sta.deflink;
+
+ mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta, mlink);
}
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
--
2.43.0
^ permalink raw reply related
* [PATCH 08/19] wifi: mt76: mt7925: validate mlink in sta_hdr_trans_tlv()
From: Sean Wang @ 2026-03-06 23:22 UTC (permalink / raw)
To: nbd, lorenzo.bianconi; +Cc: linux-wireless, linux-mediatek, Sean Wang
In-Reply-To: <20260306232238.2039675-1-sean.wang@kernel.org>
From: Sean Wang <sean.wang@mediatek.com>
Replace the dead wcid NULL check in mt7925_mcu_sta_hdr_trans_tlv() with
a WARN_ON_ONCE() guard on mlink before dereferencing mlink->wcid.
wcid is always derived from mlink, so mlink is the only meaningful
object to validate here.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index c474dd358650..03515b891643 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1082,11 +1082,11 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
else
hdr_trans->from_ds = true;
- wcid = &mlink->wcid;
-
- if (!wcid)
+ if (WARN_ON_ONCE(!mlink))
return;
+ wcid = &mlink->wcid;
+
hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
hdr_trans->to_ds = true;
--
2.43.0
^ permalink raw reply related
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