mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
Some fixes for the current cycle:
- mt76: MLO regressions, offchannel handling, list corruption - mac80211: scan allocation size, no 40 MHz EHT, signed type - rt2x00: (randconfig) build - cfg80211: use-after-free - iwlwifi: config/old devices, BIOS compatibility - mwifiex: vmalloc content leak -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmiwSqwACgkQ10qiO8sP aAACdg//cgUHFzPKIqkNRPiv6ThWWzun4//iRUFyDI7Y5c35p61qxiUnQVsLmDnW BcHfHd4mEspNHWwvsHS/P+DBhJT+LWzG6nkSZukmVP56wCROB+Rtv0I8SzbLYVId tiFnL4gwzrpjWVb/K7FwwY8Co4eX4bA+Hef5CKnU6/RqmtaTj+7QzFyqz6pckHkK 9tZiwBWueUWcBIhYWV46Qw7HF/Eoex70w0nK1t1asBOXSdyXBmKJh5LfinqbLBEi pbCHuzDDD37l0y+/BgY/ROp1io5AIzS+0YpbAVj20YUXkFCZ5fGAXc3tSGDztJU6 /M5i4fA93iHiD90sUb4ThvZWf8KBgc0Umnb5bRKS0RnbAHtH0FzZlyLhoVdY46UR UyOCsXWdsaNA4YSNdlHQePPS8lPJCeVkrLLLnYIo37DsBaDUBmGh1fmNPzOzMLtU lpjVOsMveYd2XADDTgFer0UYoG1Vok9I/5piE0UjrGbzg4G7KRVJWOHZg5hgQMWa siZ9xOpXf7gjkOERrbiUb8vA60v9FGn1sKCUu59c80/uL+9cxg8k5H7IeecrSwc5 yXaoJ6gMutRauQ7jh8lwlxLA2aySMjG0Z+jel76SGyOA0mmuOh4NqWiSVLchA1PP J3WORpk4zA5U8ySk/TU47+XSR4x70gZr3bUC5ajOkZhRk7Aahio= =fAPG -----END PGP SIGNATURE----- Merge tag 'wireless-2025-08-28' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless Johannes Berg says: ==================== Some fixes for the current cycle: - mt76: MLO regressions, offchannel handling, list corruption - mac80211: scan allocation size, no 40 MHz EHT, signed type - rt2x00: (randconfig) build - cfg80211: use-after-free - iwlwifi: config/old devices, BIOS compatibility - mwifiex: vmalloc content leak * tag 'wireless-2025-08-28' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: (29 commits) wifi: iwlwifi: cfg: add back more lost PCI IDs wifi: iwlwifi: fix byte count table for old devices wifi: iwlwifi: cfg: restore some 1000 series configs wifi: mwifiex: Initialize the chan_stats array to zero wifi: mac80211: do not permit 40 MHz EHT operation on 5/6 GHz wifi: iwlwifi: uefi: check DSM item validity wifi: iwlwifi: acpi: check DSM func validity wifi: iwlwifi: if scratch is ~0U, consider it a failure wifi: mt76: fix linked list corruption wifi: mt76: free pending offchannel tx frames on wcid cleanup wifi: mt76: mt7915: fix list corruption after hardware restart wifi: mt76: mt7996: add missing check for rx wcid entries wifi: mt76: do not add non-sta wcid entries to the poll list wifi: mt76: mt7996: fix crash on some tx status reports wifi: mt76: mt7996: use the correct vif link for scanning/roc wifi: mt76: mt7996: disable beacons when going offchannel wifi: mt76: prevent non-offchannel mgmt tx during scan/roc wifi: mt76: mt7925: skip EHT MLD TLV on non-MLD and pass conn_state for sta_cmd wifi: mt76: mt7925u: use connac3 tx aggr check in tx complete wifi: mt76: mt7925: fix the wrong bss cleanup for SAP ... ==================== Link: https://patch.msgid.link/20250828122654.1167754-8-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
629840e208
|
|
@ -393,10 +393,8 @@ void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
|
|||
if (!cfg->btcoex)
|
||||
return;
|
||||
|
||||
if (cfg->btcoex->timer_on) {
|
||||
cfg->btcoex->timer_on = false;
|
||||
timer_shutdown_sync(&cfg->btcoex->timer);
|
||||
}
|
||||
timer_shutdown_sync(&cfg->btcoex->timer);
|
||||
cfg->btcoex->timer_on = false;
|
||||
|
||||
cancel_work_sync(&cfg->btcoex->work);
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS);
|
||||
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size)))
|
||||
if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func))
|
||||
return -EINVAL;
|
||||
|
||||
expected_size = acpi_dsm_size[func];
|
||||
|
|
@ -178,6 +178,29 @@ int iwl_acpi_get_dsm(struct iwl_fw_runtime *fwrt,
|
|||
if (expected_size != sizeof(u8) && expected_size != sizeof(u32))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fwrt->acpi_dsm_funcs_valid) {
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV,
|
||||
DSM_FUNC_QUERY,
|
||||
&iwl_guid, &tmp,
|
||||
acpi_dsm_size[DSM_FUNC_QUERY]);
|
||||
if (ret) {
|
||||
/* always indicate BIT(0) to avoid re-reading */
|
||||
fwrt->acpi_dsm_funcs_valid = BIT(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n",
|
||||
(u32)tmp);
|
||||
/* always indicate BIT(0) to avoid re-reading */
|
||||
fwrt->acpi_dsm_funcs_valid = tmp | BIT(0);
|
||||
}
|
||||
|
||||
if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n",
|
||||
func);
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func,
|
||||
&iwl_guid, &tmp, expected_size);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ struct iwl_txf_iter_data {
|
|||
* @phy_filters: specific phy filters as read from WPFC BIOS table
|
||||
* @ppag_bios_rev: PPAG BIOS revision
|
||||
* @ppag_bios_source: see &enum bios_source
|
||||
* @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid,
|
||||
* zero (default initialization) means it hasn't been read yet,
|
||||
* and BIT(0) is set when it has since function 0 also has this
|
||||
* bitmap and is always supported
|
||||
*/
|
||||
struct iwl_fw_runtime {
|
||||
struct iwl_trans *trans;
|
||||
|
|
@ -189,6 +193,10 @@ struct iwl_fw_runtime {
|
|||
bool uats_valid;
|
||||
u8 uefi_tables_lock_status;
|
||||
struct iwl_phy_specific_cfg phy_filters;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
u32 acpi_dsm_funcs_valid;
|
||||
#endif
|
||||
};
|
||||
|
||||
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
||||
|
|
|
|||
|
|
@ -747,6 +747,12 @@ int iwl_uefi_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!(data->functions[DSM_FUNC_QUERY] & BIT(func))) {
|
||||
IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n",
|
||||
func, data->functions[DSM_FUNC_QUERY]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*value = data->functions[func];
|
||||
|
||||
IWL_DEBUG_RADIO(fwrt,
|
||||
|
|
|
|||
|
|
@ -673,6 +673,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name,
|
||||
DEVICE(0x0082), SUBDEV_MASKED(0xC000, 0xF000)),
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name,
|
||||
DEVICE(0x0085), SUBDEV_MASKED(0xC000, 0xF000)),
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_d_name,
|
||||
DEVICE(0x0082), SUBDEV(0x4820)),
|
||||
IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_mow1_name,
|
||||
|
|
@ -729,10 +731,10 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
DEVICE(0x0083), SUBDEV_MASKED(0x5, 0xF)),
|
||||
IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
|
||||
DEVICE(0x0083), SUBDEV_MASKED(0x6, 0xF)),
|
||||
IWL_DEV_INFO(iwl1000_bgn_cfg, iwl1000_bgn_name,
|
||||
DEVICE(0x0084), SUBDEV_MASKED(0x5, 0xF)),
|
||||
IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
|
||||
DEVICE(0x0084), SUBDEV(0x1216)),
|
||||
IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name,
|
||||
DEVICE(0x0084), SUBDEV(0x1316)),
|
||||
DEVICE(0x0084), SUBDEV_MASKED(0x6, 0xF)),
|
||||
|
||||
/* 100 Series WiFi */
|
||||
IWL_DEV_INFO(iwl100_bgn_cfg, iwl100_bgn_name,
|
||||
|
|
@ -964,6 +966,12 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
|
|||
DEVICE(0x24F3), SUBDEV(0x0004)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl8260_2n_name,
|
||||
DEVICE(0x24F3), SUBDEV(0x0044)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl8260_2ac_name,
|
||||
DEVICE(0x24F4)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name,
|
||||
DEVICE(0x24F5)),
|
||||
IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name,
|
||||
DEVICE(0x24F6)),
|
||||
IWL_DEV_INFO(iwl8265_cfg, iwl8265_2ac_name,
|
||||
DEVICE(0x24FD)),
|
||||
IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name,
|
||||
|
|
@ -1222,11 +1230,15 @@ static int _iwl_pci_resume(struct device *device, bool restore)
|
|||
* Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan,
|
||||
* but not bits [15:8]. So if we have bits set in lower word, assume
|
||||
* the device is alive.
|
||||
* Alternatively, if the scratch value is 0xFFFFFFFF, then we no longer
|
||||
* have access to the device and consider it powered off.
|
||||
* For older devices, just try silently to grab the NIC.
|
||||
*/
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
if (!(iwl_read32(trans, CSR_FUNC_SCRATCH) &
|
||||
CSR_FUNC_SCRATCH_POWER_OFF_MASK))
|
||||
u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
|
||||
|
||||
if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) ||
|
||||
scratch == ~0U)
|
||||
device_was_powered_off = true;
|
||||
} else {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2092,7 +2092,8 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
|
|||
break;
|
||||
}
|
||||
|
||||
if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
|
||||
trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
len = DIV_ROUND_UP(len, 4);
|
||||
|
||||
if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX))
|
||||
|
|
|
|||
|
|
@ -4673,8 +4673,9 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
|
|||
* additional active scan request for hidden SSIDs on passive channels.
|
||||
*/
|
||||
adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a);
|
||||
adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats),
|
||||
adapter->num_in_chan_stats));
|
||||
adapter->chan_stats = kcalloc(adapter->num_in_chan_stats,
|
||||
sizeof(*adapter->chan_stats),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!adapter->chan_stats)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context)
|
|||
goto done;
|
||||
|
||||
err_add_intf:
|
||||
vfree(adapter->chan_stats);
|
||||
kfree(adapter->chan_stats);
|
||||
err_init_chan_scan:
|
||||
wiphy_unregister(adapter->wiphy);
|
||||
wiphy_free(adapter->wiphy);
|
||||
|
|
@ -1485,7 +1485,7 @@ static void mwifiex_uninit_sw(struct mwifiex_adapter *adapter)
|
|||
wiphy_free(adapter->wiphy);
|
||||
adapter->wiphy = NULL;
|
||||
|
||||
vfree(adapter->chan_stats);
|
||||
kfree(adapter->chan_stats);
|
||||
mwifiex_free_cmd_buffers(adapter);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -818,6 +818,43 @@ void mt76_free_device(struct mt76_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
|
||||
static void mt76_reset_phy(struct mt76_phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
INIT_LIST_HEAD(&phy->tx_list);
|
||||
}
|
||||
|
||||
void mt76_reset_device(struct mt76_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[i]);
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
wcid->sta = 0;
|
||||
mt76_wcid_cleanup(dev, wcid);
|
||||
rcu_assign_pointer(dev->wcid[i], NULL);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
INIT_LIST_HEAD(&dev->wcid_list);
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
dev->vif_mask = 0;
|
||||
memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask));
|
||||
|
||||
mt76_reset_phy(&dev->phy);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++)
|
||||
mt76_reset_phy(dev->phys[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_reset_device);
|
||||
|
||||
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -1679,6 +1716,10 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
|||
skb_queue_splice_tail_init(&wcid->tx_pending, &list);
|
||||
spin_unlock(&wcid->tx_pending.lock);
|
||||
|
||||
spin_lock(&wcid->tx_offchannel.lock);
|
||||
skb_queue_splice_tail_init(&wcid->tx_offchannel, &list);
|
||||
spin_unlock(&wcid->tx_offchannel.lock);
|
||||
|
||||
spin_unlock_bh(&phy->tx_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&list)) != NULL) {
|
||||
|
|
@ -1690,7 +1731,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
|
|||
|
||||
void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
{
|
||||
if (test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
if (test_bit(MT76_MCU_RESET, &dev->phy.state) || !wcid->sta)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
|||
struct ieee80211_rate *rates, int n_rates);
|
||||
void mt76_unregister_device(struct mt76_dev *dev);
|
||||
void mt76_free_device(struct mt76_dev *dev);
|
||||
void mt76_reset_device(struct mt76_dev *dev);
|
||||
void mt76_unregister_phy(struct mt76_phy *phy);
|
||||
|
||||
struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size,
|
||||
|
|
|
|||
|
|
@ -1460,17 +1460,15 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
|
|||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip full reset failed\n");
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
while (!list_empty(&dev->mt76.sta_poll_list))
|
||||
list_del_init(dev->mt76.sta_poll_list.next);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask));
|
||||
dev->mt76.vif_mask = 0;
|
||||
dev->phy.omac_mask = 0;
|
||||
if (phy2)
|
||||
phy2->omac_mask = 0;
|
||||
|
||||
mt76_reset_device(&dev->mt76);
|
||||
|
||||
INIT_LIST_HEAD(&dev->sta_rc_list);
|
||||
INIT_LIST_HEAD(&dev->twt_list);
|
||||
|
||||
i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
|
||||
dev->mt76.global_wcid.idx = i;
|
||||
dev->recovery.hw_full_reset = false;
|
||||
|
|
|
|||
|
|
@ -1459,11 +1459,8 @@ static int mt7921_pre_channel_switch(struct ieee80211_hw *hw,
|
|||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Avoid beacon loss due to the CAC(Channel Availability Check) time
|
||||
* of the AP.
|
||||
*/
|
||||
if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef,
|
||||
IEEE80211_CHAN_RADAR))
|
||||
IEEE80211_CHAN_DISABLED))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1449,7 +1449,7 @@ void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
|||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt76_connac2_tx_check_aggr(sta, txwi);
|
||||
mt7925_tx_check_aggr(sta, e->skb, wcid);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
|
|
|
|||
|
|
@ -1191,6 +1191,9 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
|||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
break;
|
||||
|
||||
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
|
||||
if (!link_sta)
|
||||
continue;
|
||||
|
|
@ -2069,8 +2072,10 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
GFP_KERNEL);
|
||||
mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink),
|
||||
GFP_KERNEL);
|
||||
if (!mconf || !mlink)
|
||||
if (!mconf || !mlink) {
|
||||
mt792x_mutex_release(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
mconfs[link_id] = mconf;
|
||||
|
|
|
|||
|
|
@ -1834,13 +1834,13 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb,
|
|||
struct tlv *tlv;
|
||||
u16 eml_cap;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));
|
||||
eht_mld = (struct sta_rec_eht_mld *)tlv;
|
||||
eht_mld->mld_type = 0xff;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
ext_capa = cfg80211_get_iftype_ext_capa(wiphy,
|
||||
ieee80211_vif_type_p2p(vif));
|
||||
if (!ext_capa)
|
||||
|
|
@ -1912,6 +1912,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
|||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct sk_buff *skb;
|
||||
int conn_state;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
|
||||
|
||||
|
|
@ -1920,10 +1921,13 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
|||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
conn_state = info->enable ? CONN_STATE_PORT_SECURE :
|
||||
CONN_STATE_DISCONNECT;
|
||||
|
||||
if (info->enable && info->link_sta) {
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
info->enable, info->newly);
|
||||
conn_state, info->newly);
|
||||
mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);
|
||||
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
|||
int i;
|
||||
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (!wcid)
|
||||
if (!wcid || !wcid->sta)
|
||||
return NULL;
|
||||
|
||||
if (!mt7996_band_valid(dev, band_idx))
|
||||
|
|
@ -903,8 +903,12 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
|
||||
if (mvif)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
if (mvif) {
|
||||
if (wcid->offchannel)
|
||||
mlink = rcu_dereference(mvif->mt76.offchannel_link);
|
||||
if (!mlink)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
}
|
||||
|
||||
if (mlink) {
|
||||
omac_idx = mlink->omac_idx;
|
||||
|
|
@ -1243,8 +1247,10 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
|||
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta)
|
||||
if (!sta) {
|
||||
link_sta = NULL;
|
||||
goto next;
|
||||
}
|
||||
|
||||
link_sta = rcu_dereference(sta->link[wcid->link_id]);
|
||||
if (!link_sta)
|
||||
|
|
@ -1694,17 +1700,37 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
|
|||
static void
|
||||
mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt7996_phy *phy = priv;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
unsigned int link_id;
|
||||
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link || link->phy != phy)
|
||||
continue;
|
||||
|
||||
mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf);
|
||||
}
|
||||
}
|
||||
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces(phy->mt76->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1712,25 +1738,15 @@ mt7996_update_beacons(struct mt7996_dev *dev)
|
|||
{
|
||||
struct mt76_phy *phy2, *phy3;
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, dev->mt76.hw);
|
||||
mt7996_mac_update_beacons(&dev->phy);
|
||||
|
||||
phy2 = dev->mt76.phys[MT_BAND1];
|
||||
if (!phy2)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(phy2->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy2->hw);
|
||||
if (phy2)
|
||||
mt7996_mac_update_beacons(phy2->priv);
|
||||
|
||||
phy3 = dev->mt76.phys[MT_BAND2];
|
||||
if (!phy3)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(phy3->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy3->hw);
|
||||
if (phy3)
|
||||
mt7996_mac_update_beacons(phy3->priv);
|
||||
}
|
||||
|
||||
void mt7996_tx_token_put(struct mt7996_dev *dev)
|
||||
|
|
|
|||
|
|
@ -516,6 +516,9 @@ int mt7996_set_channel(struct mt76_phy *mphy)
|
|||
struct mt7996_phy *phy = mphy->priv;
|
||||
int ret;
|
||||
|
||||
if (mphy->offchannel)
|
||||
mt7996_mac_update_beacons(phy);
|
||||
|
||||
ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -533,6 +536,8 @@ int mt7996_set_channel(struct mt76_phy *mphy)
|
|||
|
||||
mt7996_mac_reset_counters(phy);
|
||||
phy->noise = 0;
|
||||
if (!mphy->offchannel)
|
||||
mt7996_mac_update_beacons(phy);
|
||||
|
||||
out:
|
||||
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
|
||||
|
|
|
|||
|
|
@ -1879,8 +1879,8 @@ mt7996_mcu_get_mmps_mode(enum ieee80211_smps_mode smps)
|
|||
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
void *data, u16 version)
|
||||
{
|
||||
struct uni_header hdr = {};
|
||||
struct ra_fixed_rate *req;
|
||||
struct uni_header hdr;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
int len;
|
||||
|
|
@ -2755,13 +2755,15 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
struct mt76_vif_link *mlink = mt76_vif_conf_link(&dev->mt76, vif, link_conf);
|
||||
struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf);
|
||||
struct mt76_vif_link *mlink = link ? &link->mt76 : NULL;
|
||||
struct ieee80211_mutable_offsets offs;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb, *rskb;
|
||||
struct tlv *tlv;
|
||||
struct bss_bcn_content_tlv *bcn;
|
||||
int len, extra_len = 0;
|
||||
bool enabled = link_conf->enable_beacon;
|
||||
|
||||
if (link_conf->nontransmitted)
|
||||
return 0;
|
||||
|
|
@ -2769,13 +2771,16 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
if (!mlink)
|
||||
return -EINVAL;
|
||||
|
||||
if (link->phy && link->phy->mt76->offchannel)
|
||||
enabled = false;
|
||||
|
||||
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink,
|
||||
MT7996_MAX_BSS_OFFLOAD_SIZE);
|
||||
if (IS_ERR(rskb))
|
||||
return PTR_ERR(rskb);
|
||||
|
||||
skb = ieee80211_beacon_get_template(hw, vif, &offs, link_conf->link_id);
|
||||
if (link_conf->enable_beacon && !skb) {
|
||||
if (enabled && !skb) {
|
||||
dev_kfree_skb(rskb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -2794,7 +2799,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + extra_len, 4);
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len);
|
||||
bcn = (struct bss_bcn_content_tlv *)tlv;
|
||||
bcn->enable = link_conf->enable_beacon;
|
||||
bcn->enable = enabled;
|
||||
if (!bcn->enable)
|
||||
goto out;
|
||||
|
||||
|
|
@ -3372,7 +3377,7 @@ int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans)
|
|||
{
|
||||
struct {
|
||||
u8 __rsv[4];
|
||||
} __packed hdr;
|
||||
} __packed hdr = {};
|
||||
struct hdr_trans_blacklist *req_blacklist;
|
||||
struct hdr_trans_en *req_en;
|
||||
struct sk_buff *skb;
|
||||
|
|
|
|||
|
|
@ -732,6 +732,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
|||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy);
|
||||
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
|
||||
void mt7996_mac_work(struct work_struct *work);
|
||||
void mt7996_mac_reset_work(struct work_struct *work);
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
|||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct sk_buff_head *head;
|
||||
|
||||
if (mt76_testmode_enabled(phy)) {
|
||||
|
|
@ -349,7 +350,8 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
|||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
|
||||
(info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK))
|
||||
((info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK) &&
|
||||
ieee80211_is_probe_req(hdr->frame_control)))
|
||||
head = &wcid->tx_offchannel;
|
||||
else
|
||||
head = &wcid->tx_pending;
|
||||
|
|
@ -644,6 +646,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
|||
static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
{
|
||||
LIST_HEAD(tx_list);
|
||||
int ret = 0;
|
||||
|
||||
if (list_empty(&phy->tx_list))
|
||||
return;
|
||||
|
|
@ -655,13 +658,13 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
|||
list_splice_init(&phy->tx_list, &tx_list);
|
||||
while (!list_empty(&tx_list)) {
|
||||
struct mt76_wcid *wcid;
|
||||
int ret;
|
||||
|
||||
wcid = list_first_entry(&tx_list, struct mt76_wcid, tx_list);
|
||||
list_del_init(&wcid->tx_list);
|
||||
|
||||
spin_unlock(&phy->tx_lock);
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel);
|
||||
if (ret >= 0)
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel);
|
||||
if (ret >= 0 && !phy->offchannel)
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_pending);
|
||||
spin_lock(&phy->tx_lock);
|
||||
|
|
@ -670,9 +673,6 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
|||
!skb_queue_empty(&wcid->tx_offchannel) &&
|
||||
list_empty(&wcid->tx_list))
|
||||
list_add_tail(&wcid->tx_list, &phy->tx_list);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&phy->tx_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ config RT2800PCI
|
|||
select RT2X00_LIB_PCI
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select CRC_CCITT
|
||||
select EEPROM_93CX6
|
||||
help
|
||||
This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
|
||||
|
|
@ -142,7 +141,6 @@ config RT2800USB
|
|||
select RT2X00_LIB_USB
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select CRC_CCITT
|
||||
help
|
||||
This adds support for rt27xx/rt28xx/rt30xx wireless chipset family.
|
||||
Supported chips: RT2770, RT2870 & RT3070, RT3071 & RT3072
|
||||
|
|
@ -217,6 +215,7 @@ config RT2800SOC
|
|||
|
||||
config RT2800_LIB
|
||||
tristate
|
||||
select CRC_CCITT
|
||||
|
||||
config RT2800_LIB_MMIO
|
||||
tristate
|
||||
|
|
@ -225,6 +224,7 @@ config RT2800_LIB_MMIO
|
|||
|
||||
config RT2X00_LIB_MMIO
|
||||
tristate
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_PCI
|
||||
tristate
|
||||
|
|
|
|||
|
|
@ -1416,7 +1416,7 @@ drv_get_ftm_responder_stats(struct ieee80211_local *local,
|
|||
struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_ftm_responder_stats *ftm_stats)
|
||||
{
|
||||
u32 ret = -EOPNOTSUPP;
|
||||
int ret = -EOPNOTSUPP;
|
||||
|
||||
might_sleep();
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
|
|
|||
|
|
@ -1111,7 +1111,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
int result, i;
|
||||
enum nl80211_band band;
|
||||
int channels, max_bitrates;
|
||||
bool supp_ht, supp_vht, supp_he, supp_eht;
|
||||
bool supp_ht, supp_vht, supp_he, supp_eht, supp_s1g;
|
||||
struct cfg80211_chan_def dflt_chandef = {};
|
||||
|
||||
if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
|
||||
|
|
@ -1227,6 +1227,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
supp_vht = false;
|
||||
supp_he = false;
|
||||
supp_eht = false;
|
||||
supp_s1g = false;
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
const struct ieee80211_sband_iftype_data *iftd;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
|
@ -1274,6 +1275,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
max_bitrates = sband->n_bitrates;
|
||||
supp_ht = supp_ht || sband->ht_cap.ht_supported;
|
||||
supp_vht = supp_vht || sband->vht_cap.vht_supported;
|
||||
supp_s1g = supp_s1g || sband->s1g_cap.s1g;
|
||||
|
||||
for_each_sband_iftype_data(sband, i, iftd) {
|
||||
u8 he_40_mhz_cap;
|
||||
|
|
@ -1406,6 +1408,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
local->scan_ies_len +=
|
||||
2 + sizeof(struct ieee80211_vht_cap);
|
||||
|
||||
if (supp_s1g)
|
||||
local->scan_ies_len += 2 + sizeof(struct ieee80211_s1g_cap);
|
||||
|
||||
/*
|
||||
* HE cap element is variable in size - set len to allow max size */
|
||||
if (supp_he) {
|
||||
|
|
|
|||
|
|
@ -1189,6 +1189,14 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata,
|
|||
"required MCSes not supported, disabling EHT\n");
|
||||
}
|
||||
|
||||
if (conn->mode >= IEEE80211_CONN_MODE_EHT &&
|
||||
channel->band != NL80211_BAND_2GHZ &&
|
||||
conn->bw_limit == IEEE80211_CONN_BW_LIMIT_40) {
|
||||
conn->mode = IEEE80211_CONN_MODE_HE;
|
||||
link_id_info(sdata, link_id,
|
||||
"required bandwidth not supported, disabling EHT\n");
|
||||
}
|
||||
|
||||
/* the mode can only decrease, so this must terminate */
|
||||
if (ap_mode != conn->mode) {
|
||||
kfree(elems);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* KUnit tests for channel mode functions
|
||||
*
|
||||
* Copyright (C) 2024 Intel Corporation
|
||||
* Copyright (C) 2024-2025 Intel Corporation
|
||||
*/
|
||||
#include <net/cfg80211.h>
|
||||
#include <kunit/test.h>
|
||||
|
|
@ -28,6 +28,10 @@ static const struct determine_chan_mode_case {
|
|||
u8 vht_basic_mcs_1_4, vht_basic_mcs_5_8;
|
||||
u8 he_basic_mcs_1_4, he_basic_mcs_5_8;
|
||||
u8 eht_mcs7_min_nss;
|
||||
u16 eht_disabled_subchannels;
|
||||
u8 eht_bw;
|
||||
enum ieee80211_conn_bw_limit conn_bw_limit;
|
||||
enum ieee80211_conn_bw_limit expected_bw_limit;
|
||||
int error;
|
||||
} determine_chan_mode_cases[] = {
|
||||
{
|
||||
|
|
@ -128,6 +132,14 @@ static const struct determine_chan_mode_case {
|
|||
.conn_mode = IEEE80211_CONN_MODE_EHT,
|
||||
.eht_mcs7_min_nss = 0x15,
|
||||
.error = EINVAL,
|
||||
}, {
|
||||
.desc = "80 MHz EHT is downgraded to 40 MHz HE due to puncturing",
|
||||
.conn_mode = IEEE80211_CONN_MODE_EHT,
|
||||
.expected_mode = IEEE80211_CONN_MODE_HE,
|
||||
.conn_bw_limit = IEEE80211_CONN_BW_LIMIT_80,
|
||||
.expected_bw_limit = IEEE80211_CONN_BW_LIMIT_40,
|
||||
.eht_disabled_subchannels = 0x08,
|
||||
.eht_bw = IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ,
|
||||
}
|
||||
};
|
||||
KUNIT_ARRAY_PARAM_DESC(determine_chan_mode, determine_chan_mode_cases, desc)
|
||||
|
|
@ -138,7 +150,7 @@ static void test_determine_chan_mode(struct kunit *test)
|
|||
struct t_sdata *t_sdata = T_SDATA(test);
|
||||
struct ieee80211_conn_settings conn = {
|
||||
.mode = params->conn_mode,
|
||||
.bw_limit = IEEE80211_CONN_BW_LIMIT_20,
|
||||
.bw_limit = params->conn_bw_limit,
|
||||
};
|
||||
struct cfg80211_bss cbss = {
|
||||
.channel = &t_sdata->band_5ghz.channels[0],
|
||||
|
|
@ -191,14 +203,21 @@ static void test_determine_chan_mode(struct kunit *test)
|
|||
0x7f, 0x01, 0x00, 0x88, 0x88, 0x88, 0x00, 0x00,
|
||||
0x00,
|
||||
/* EHT Operation */
|
||||
WLAN_EID_EXTENSION, 0x09, WLAN_EID_EXT_EHT_OPERATION,
|
||||
0x01, params->eht_mcs7_min_nss ? params->eht_mcs7_min_nss : 0x11,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x00,
|
||||
WLAN_EID_EXTENSION, 0x0b, WLAN_EID_EXT_EHT_OPERATION,
|
||||
0x03, params->eht_mcs7_min_nss ? params->eht_mcs7_min_nss : 0x11,
|
||||
0x00, 0x00, 0x00, params->eht_bw,
|
||||
params->eht_bw == IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ ? 42 : 36,
|
||||
0x00,
|
||||
u16_get_bits(params->eht_disabled_subchannels, 0xff),
|
||||
u16_get_bits(params->eht_disabled_subchannels, 0xff00),
|
||||
};
|
||||
struct ieee80211_chan_req chanreq = {};
|
||||
struct cfg80211_chan_def ap_chandef = {};
|
||||
struct ieee802_11_elems *elems;
|
||||
|
||||
/* To force EHT downgrade to HE on punctured 80 MHz downgraded to 40 MHz */
|
||||
set_bit(IEEE80211_HW_DISALLOW_PUNCTURING, t_sdata->local.hw.flags);
|
||||
|
||||
if (params->strict)
|
||||
set_bit(IEEE80211_HW_STRICT, t_sdata->local.hw.flags);
|
||||
else
|
||||
|
|
@ -237,6 +256,7 @@ static void test_determine_chan_mode(struct kunit *test)
|
|||
} else {
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elems);
|
||||
KUNIT_ASSERT_EQ(test, conn.mode, params->expected_mode);
|
||||
KUNIT_ASSERT_EQ(test, conn.bw_limit, params->expected_bw_limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1916,7 +1916,8 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,
|
|||
*/
|
||||
|
||||
f = rcu_access_pointer(new->pub.beacon_ies);
|
||||
kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
|
||||
if (!new->pub.hidden_beacon_bss)
|
||||
kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user