Quite a collection of fixes this time, really too many
to list individually. Many stack fixes, even rfkill (found by simulation and the new eevdf scheduler)! Also a bigger maintainers file cleanup, to remove old and redundant information. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmUT/FoACgkQ10qiO8sP aAAeqg/+Iaim4AFPPDeWUvSARyqcMIKqmDtaFqkXE+OY8oahbvvbnGuLM/v/7V3r NG5pzoi0gqFasF+DC1lNWFUnmtWdjzjhhY9FInoWgiNO04V48c3NPI/YF/2Yvy0x biJxSsiaY+buY/p2QOXvlXHetnaftXNikFPZaD1mVGG/GIGZAwqqUO/EkIdliZf5 q/RBt5jzMF/nXTRIGc53kq7tKT97gGnDDYMych0U130PlyyqAZ+iAsR9UbiPa+ww Z1JB8qZO72Hx9iN0WMjXNBX8vxC961Dj+fkttgJqZALTk0UqQitwcsIJgM29JjTG VHsxHMdZAROFGaEHdMs1eHkqHkqyOxA4Jhr5LAci/chzgKkRw2I2LAXndOeg5TLH cWdhNjRW/ZJ64czr5hALQQxK4nj8m7SPFHY/6UuBnNHEXCjr7vUcuhcoK63Kb6Np 6Sg4jtyhakaXemqjhcmIYNF1dG5CDbUmQXFkj9Z9EEyHjAzGJ7ASmdhHwlBQnJuH 39ESEky2zQINAJbisaw9R2zj+V9Ia/mFSbi2q30kX5J4xTHGIURNo9OPkLAQWDdw 6u/d5VZLigliIK+Qj8kVtn41wmUEwB3W5Aq4CI7xB91vKRHCUZQvZ5xBJfHtk2pD 7VIzZscReWCsQP9T0hv38jeaw4m/P+mZO1iOC2qxveJvrQogZMk= =OL/S -----END PGP SIGNATURE----- Merge tag 'wireless-2023-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless Johannes Berg says: ==================== Quite a collection of fixes this time, really too many to list individually. Many stack fixes, even rfkill (found by simulation and the new eevdf scheduler)! Also a bigger maintainers file cleanup, to remove old and redundant information. * tag 'wireless-2023-09-27' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: (32 commits) wifi: iwlwifi: mvm: Fix incorrect usage of scan API wifi: mac80211: Create resources for disabled links wifi: cfg80211: avoid leaking stack data into trace wifi: mac80211: allow transmitting EAPOL frames with tainted key wifi: mac80211: work around Cisco AP 9115 VHT MPDU length wifi: cfg80211: Fix 6GHz scan configuration wifi: mac80211: fix potential key leak wifi: mac80211: fix potential key use-after-free wifi: mt76: mt76x02: fix MT76x0 external LNA gain handling wifi: brcmfmac: Replace 1-element arrays with flexible arrays wifi: mwifiex: Fix oob check condition in mwifiex_process_rx_packet wifi: rtw88: rtw8723d: Fix MAC address offset in EEPROM rfkill: sync before userspace visibility/changes wifi: mac80211: fix mesh id corruption on 32 bit systems wifi: cfg80211: add missing kernel-doc for cqm_rssi_work wifi: cfg80211: fix cqm_config access race wifi: iwlwifi: mvm: Fix a memory corruption issue wifi: iwlwifi: Ensure ack flag is properly cleared. wifi: iwlwifi: dbg_ini: fix structure packing iwlwifi: mvm: handle PS changes in vif_cfg_changed ... ==================== Link: https://lore.kernel.org/r/20230927095835.25803-2-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
72897b2959
10
MAINTAINERS
10
MAINTAINERS
@ -470,7 +470,6 @@ F: drivers/hwmon/adm1029.c
|
||||
ADM8211 WIRELESS DRIVER
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Orphan
|
||||
W: https://wireless.wiki.kernel.org/
|
||||
F: drivers/net/wireless/admtek/adm8211.*
|
||||
|
||||
ADP1653 FLASH CONTROLLER DRIVER
|
||||
@ -9531,10 +9530,8 @@ F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
|
||||
F: drivers/iio/pressure/mprls0025pa.c
|
||||
|
||||
HOST AP DRIVER
|
||||
M: Jouni Malinen <j@w1.fi>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Obsolete
|
||||
W: http://w1.fi/hostap-driver.html
|
||||
F: drivers/net/wireless/intersil/hostap/
|
||||
|
||||
HP BIOSCFG DRIVER
|
||||
@ -17600,6 +17597,7 @@ M: Kalle Valo <kvalo@kernel.org>
|
||||
M: Jeff Johnson <quic_jjohnson@quicinc.com>
|
||||
L: ath12k@lists.infradead.org
|
||||
S: Supported
|
||||
W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
F: drivers/net/wireless/ath/ath12k/
|
||||
|
||||
@ -18130,8 +18128,6 @@ REALTEK WIRELESS DRIVER (rtlwifi family)
|
||||
M: Ping-Ke Shih <pkshih@realtek.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://wireless.wiki.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
F: drivers/net/wireless/realtek/rtlwifi/
|
||||
|
||||
REALTEK WIRELESS DRIVER (rtw88)
|
||||
@ -18659,7 +18655,6 @@ F: drivers/media/dvb-frontends/rtl2832_sdr*
|
||||
RTL8180 WIRELESS DRIVER
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Orphan
|
||||
W: https://wireless.wiki.kernel.org/
|
||||
F: drivers/net/wireless/realtek/rtl818x/rtl8180/
|
||||
|
||||
RTL8187 WIRELESS DRIVER
|
||||
@ -18667,14 +18662,12 @@ M: Hin-Tak Leung <hintak.leung@gmail.com>
|
||||
M: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://wireless.wiki.kernel.org/
|
||||
F: drivers/net/wireless/realtek/rtl818x/rtl8187/
|
||||
|
||||
RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
|
||||
M: Jes Sorensen <Jes.Sorensen@gmail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel
|
||||
F: drivers/net/wireless/realtek/rtl8xxxu/
|
||||
|
||||
RTRS TRANSPORT DRIVERS
|
||||
@ -21656,7 +21649,6 @@ L: linux-wireless@vger.kernel.org
|
||||
S: Orphan
|
||||
W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx
|
||||
W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
|
||||
F: drivers/net/wireless/ti/
|
||||
|
||||
TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
|
||||
|
@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le {
|
||||
* fixed parameter portion is assumed, otherwise
|
||||
* ssid in the fixed portion is ignored
|
||||
*/
|
||||
__le16 channel_list[1]; /* list of chanspecs */
|
||||
union {
|
||||
__le16 padding; /* Reserve space for at least 1 entry for abort
|
||||
* which uses an on stack brcmf_scan_params_v2_le
|
||||
*/
|
||||
DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */
|
||||
};
|
||||
};
|
||||
|
||||
struct brcmf_scan_results {
|
||||
@ -702,7 +707,7 @@ struct brcmf_sta_info_le {
|
||||
|
||||
struct brcmf_chanspec_list {
|
||||
__le32 count; /* # of entries */
|
||||
__le32 element[1]; /* variable length uint32 list */
|
||||
__le32 element[]; /* variable length uint32 list */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -310,9 +310,9 @@ struct iwl_fw_ini_fifo_hdr {
|
||||
struct iwl_fw_ini_error_dump_range {
|
||||
__le32 range_data_size;
|
||||
union {
|
||||
__le32 internal_base_addr;
|
||||
__le64 dram_base_addr;
|
||||
__le32 page_num;
|
||||
__le32 internal_base_addr __packed;
|
||||
__le64 dram_base_addr __packed;
|
||||
__le32 page_num __packed;
|
||||
struct iwl_fw_ini_fifo_hdr fifo_hdr;
|
||||
struct iwl_cmd_header fw_pkt_hdr;
|
||||
};
|
||||
|
@ -802,7 +802,7 @@ out:
|
||||
mvm->nvm_data->bands[0].n_channels = 1;
|
||||
mvm->nvm_data->bands[0].n_bitrates = 1;
|
||||
mvm->nvm_data->bands[0].bitrates =
|
||||
(void *)((u8 *)mvm->nvm_data->channels + 1);
|
||||
(void *)(mvm->nvm_data->channels + 1);
|
||||
mvm->nvm_data->bands[0].bitrates->hw_value = 10;
|
||||
}
|
||||
|
||||
|
@ -731,73 +731,78 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
|
||||
|
||||
mvmvif->associated = vif->cfg.assoc;
|
||||
|
||||
if (!(changes & BSS_CHANGED_ASSOC))
|
||||
return;
|
||||
if (changes & BSS_CHANGED_ASSOC) {
|
||||
if (vif->cfg.assoc) {
|
||||
/* clear statistics to get clean beacon counter */
|
||||
iwl_mvm_request_statistics(mvm, true);
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
iwl_mvm_power_vif_assoc(mvm, vif);
|
||||
|
||||
if (vif->cfg.assoc) {
|
||||
/* clear statistics to get clean beacon counter */
|
||||
iwl_mvm_request_statistics(mvm, true);
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
iwl_mvm_power_vif_assoc(mvm, vif);
|
||||
for_each_mvm_vif_valid_link(mvmvif, i) {
|
||||
memset(&mvmvif->link[i]->beacon_stats, 0,
|
||||
sizeof(mvmvif->link[i]->beacon_stats));
|
||||
|
||||
for_each_mvm_vif_valid_link(mvmvif, i) {
|
||||
memset(&mvmvif->link[i]->beacon_stats, 0,
|
||||
sizeof(mvmvif->link[i]->beacon_stats));
|
||||
if (vif->p2p) {
|
||||
iwl_mvm_update_smps(mvm, vif,
|
||||
IWL_MVM_SMPS_REQ_PROT,
|
||||
IEEE80211_SMPS_DYNAMIC, i);
|
||||
}
|
||||
|
||||
if (vif->p2p) {
|
||||
iwl_mvm_update_smps(mvm, vif,
|
||||
IWL_MVM_SMPS_REQ_PROT,
|
||||
IEEE80211_SMPS_DYNAMIC, i);
|
||||
rcu_read_lock();
|
||||
link_conf = rcu_dereference(vif->link_conf[i]);
|
||||
if (link_conf && !link_conf->dtim_period)
|
||||
protect = true;
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
link_conf = rcu_dereference(vif->link_conf[i]);
|
||||
if (link_conf && !link_conf->dtim_period)
|
||||
protect = true;
|
||||
rcu_read_unlock();
|
||||
}
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
protect) {
|
||||
/* If we're not restarting and still haven't
|
||||
* heard a beacon (dtim period unknown) then
|
||||
* make sure we still have enough minimum time
|
||||
* remaining in the time event, since the auth
|
||||
* might actually have taken quite a while
|
||||
* (especially for SAE) and so the remaining
|
||||
* time could be small without us having heard
|
||||
* a beacon yet.
|
||||
*/
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0);
|
||||
}
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
protect) {
|
||||
/* If we're not restarting and still haven't
|
||||
* heard a beacon (dtim period unknown) then
|
||||
* make sure we still have enough minimum time
|
||||
* remaining in the time event, since the auth
|
||||
* might actually have taken quite a while
|
||||
* (especially for SAE) and so the remaining
|
||||
* time could be small without us having heard
|
||||
* a beacon yet.
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
|
||||
/* FIXME: need to decide about misbehaving AP handling */
|
||||
iwl_mvm_power_vif_assoc(mvm, vif);
|
||||
} else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
|
||||
iwl_mvm_mei_host_disassociated(mvm);
|
||||
|
||||
/* If update fails - SF might be running in associated
|
||||
* mode while disassociated - which is forbidden.
|
||||
*/
|
||||
iwl_mvm_protect_assoc(mvm, vif, 0);
|
||||
ret = iwl_mvm_sf_update(mvm, vif, false);
|
||||
WARN_ONCE(ret &&
|
||||
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
|
||||
&mvm->status),
|
||||
"Failed to update SF upon disassociation\n");
|
||||
|
||||
/* If we get an assert during the connection (after the
|
||||
* station has been added, but before the vif is set
|
||||
* to associated), mac80211 will re-add the station and
|
||||
* then configure the vif. Since the vif is not
|
||||
* associated, we would remove the station here and
|
||||
* this would fail the recovery.
|
||||
*/
|
||||
iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
|
||||
}
|
||||
|
||||
iwl_mvm_sf_update(mvm, vif, false);
|
||||
|
||||
/* FIXME: need to decide about misbehaving AP handling */
|
||||
iwl_mvm_power_vif_assoc(mvm, vif);
|
||||
} else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) {
|
||||
iwl_mvm_mei_host_disassociated(mvm);
|
||||
|
||||
/* If update fails - SF might be running in associated
|
||||
* mode while disassociated - which is forbidden.
|
||||
*/
|
||||
ret = iwl_mvm_sf_update(mvm, vif, false);
|
||||
WARN_ONCE(ret &&
|
||||
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
|
||||
&mvm->status),
|
||||
"Failed to update SF upon disassociation\n");
|
||||
|
||||
/* If we get an assert during the connection (after the
|
||||
* station has been added, but before the vif is set
|
||||
* to associated), mac80211 will re-add the station and
|
||||
* then configure the vif. Since the vif is not
|
||||
* associated, we would remove the station here and
|
||||
* this would fail the recovery.
|
||||
*/
|
||||
iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
|
||||
iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
|
||||
}
|
||||
|
||||
iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
|
||||
if (changes & BSS_CHANGED_PS) {
|
||||
ret = iwl_mvm_power_update_mac(mvm);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to update power mode\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm,
|
||||
if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2)
|
||||
gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS;
|
||||
|
||||
if (version < 12) {
|
||||
if (version < 16) {
|
||||
gp->scan_start_mac_or_link_id = scan_vif->id;
|
||||
} else {
|
||||
struct iwl_mvm_vif_link_info *link_info;
|
||||
|
@ -1612,6 +1612,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]);
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED);
|
||||
|
||||
/* inform mac80211 about what happened with the frame */
|
||||
switch (status & TX_STATUS_MSK) {
|
||||
@ -1964,6 +1965,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
|
||||
*/
|
||||
if (!is_flush)
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
else
|
||||
info->flags &= ~IEEE80211_TX_STAT_ACK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -918,9 +918,17 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
|
||||
|
||||
mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:",
|
||||
event_buf, len);
|
||||
while (tlv_buf_left >= sizeof(*tlv_rxba)) {
|
||||
while (tlv_buf_left > sizeof(*tlv_rxba)) {
|
||||
tlv_type = le16_to_cpu(tlv_rxba->header.type);
|
||||
tlv_len = le16_to_cpu(tlv_rxba->header.len);
|
||||
if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) {
|
||||
mwifiex_dbg(priv->adapter, WARN,
|
||||
"TLV size (%zu) overflows event_buf buf_left=%d\n",
|
||||
size_add(sizeof(tlv_rxba->header), tlv_len),
|
||||
tlv_buf_left);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tlv_type != TLV_TYPE_RXBA_SYNC) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Wrong TLV id=0x%x\n", tlv_type);
|
||||
@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
|
||||
|
||||
tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num);
|
||||
tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len);
|
||||
if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) {
|
||||
mwifiex_dbg(priv->adapter, WARN,
|
||||
"TLV size (%zu) overflows event_buf buf_left=%d\n",
|
||||
size_add(sizeof(*tlv_rxba), tlv_bitmap_len),
|
||||
tlv_buf_left);
|
||||
return;
|
||||
}
|
||||
|
||||
mwifiex_dbg(priv->adapter, INFO,
|
||||
"%pM tid=%d seq_num=%d bitmap_len=%d\n",
|
||||
tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num,
|
||||
@ -965,8 +981,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
|
||||
}
|
||||
}
|
||||
|
||||
tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len);
|
||||
tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba);
|
||||
tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len);
|
||||
tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len;
|
||||
tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp;
|
||||
}
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync {
|
||||
u8 reserved;
|
||||
__le16 seq_num;
|
||||
__le16 bitmap_len;
|
||||
u8 bitmap[1];
|
||||
u8 bitmap[];
|
||||
} __packed;
|
||||
|
||||
struct chan_band_param_set {
|
||||
|
@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
|
||||
rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
|
||||
rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
|
||||
|
||||
if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) {
|
||||
if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) +
|
||||
rx_pkt_off > skb->len) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"wrong rx packet offset: len=%d, rx_pkt_off=%d\n",
|
||||
skb->len, rx_pkt_off);
|
||||
@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
|
||||
sizeof(bridge_tunnel_header))) ||
|
||||
(!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
|
||||
sizeof(rfc1042_header)) &&
|
||||
ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
|
||||
ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
|
||||
if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len &&
|
||||
((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
|
||||
sizeof(bridge_tunnel_header))) ||
|
||||
(!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
|
||||
sizeof(rfc1042_header)) &&
|
||||
ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
|
||||
ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) {
|
||||
/*
|
||||
* Replace the 803 header and rfc1042 header (llc/snap) with an
|
||||
* EthernetII header, keep the src/dst and snap_type
|
||||
|
@ -93,13 +93,13 @@ __mt76_get_rxwi(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *t = NULL;
|
||||
|
||||
spin_lock(&dev->wed_lock);
|
||||
spin_lock_bh(&dev->wed_lock);
|
||||
if (!list_empty(&dev->rxwi_cache)) {
|
||||
t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache,
|
||||
list);
|
||||
list_del(&t->list);
|
||||
}
|
||||
spin_unlock(&dev->wed_lock);
|
||||
spin_unlock_bh(&dev->wed_lock);
|
||||
|
||||
return t;
|
||||
}
|
||||
@ -145,9 +145,9 @@ mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
spin_lock(&dev->wed_lock);
|
||||
spin_lock_bh(&dev->wed_lock);
|
||||
list_add(&t->list, &dev->rxwi_cache);
|
||||
spin_unlock(&dev->wed_lock);
|
||||
spin_unlock_bh(&dev->wed_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_put_rxwi);
|
||||
|
||||
|
@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,
|
||||
s8 *lna_2g, s8 *lna_5g,
|
||||
struct ieee80211_channel *chan)
|
||||
{
|
||||
u16 val;
|
||||
u8 lna;
|
||||
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
|
||||
if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
|
||||
*lna_2g = 0;
|
||||
if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
|
||||
memset(lna_5g, 0, sizeof(s8) * 3);
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ)
|
||||
lna = *lna_2g;
|
||||
else if (chan->hw_value <= 64)
|
||||
|
@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev)
|
||||
struct ieee80211_channel *chan = dev->mphy.chandef.chan;
|
||||
int channel = chan->hw_value;
|
||||
s8 lna_5g[3], lna_2g;
|
||||
u8 lna;
|
||||
bool use_lna;
|
||||
u8 lna = 0;
|
||||
u16 val;
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ)
|
||||
@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev)
|
||||
dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16;
|
||||
dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24;
|
||||
|
||||
lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
|
||||
val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
|
||||
if (chan->band == NL80211_BAND_2GHZ)
|
||||
use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G);
|
||||
else
|
||||
use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G);
|
||||
|
||||
if (use_lna)
|
||||
lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
|
||||
|
||||
dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain);
|
||||
|
@ -46,6 +46,7 @@ struct rtw8723du_efuse {
|
||||
u8 vender_id[2]; /* 0x100 */
|
||||
u8 product_id[2]; /* 0x102 */
|
||||
u8 usb_option; /* 0x104 */
|
||||
u8 res5[2]; /* 0x105 */
|
||||
u8 mac_addr[ETH_ALEN]; /* 0x107 */
|
||||
};
|
||||
|
||||
|
@ -5941,6 +5941,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy,
|
||||
* @event_lock: (private) lock for event list
|
||||
* @owner_nlportid: (private) owner socket port ID
|
||||
* @nl_owner_dead: (private) owner socket went away
|
||||
* @cqm_rssi_work: (private) CQM RSSI reporting work
|
||||
* @cqm_config: (private) nl80211 RSSI monitor state
|
||||
* @pmsr_list: (private) peer measurement requests
|
||||
* @pmsr_lock: (private) peer measurements requests/results lock
|
||||
@ -6013,7 +6014,8 @@ struct wireless_dev {
|
||||
} wext;
|
||||
#endif
|
||||
|
||||
struct cfg80211_cqm_config *cqm_config;
|
||||
struct wiphy_work cqm_rssi_work;
|
||||
struct cfg80211_cqm_config __rcu *cqm_config;
|
||||
|
||||
struct list_head pmsr_list;
|
||||
spinlock_t pmsr_lock;
|
||||
@ -7231,7 +7233,7 @@ struct cfg80211_rx_assoc_resp {
|
||||
int uapsd_queues;
|
||||
const u8 *ap_mld_addr;
|
||||
struct {
|
||||
const u8 *addr;
|
||||
u8 addr[ETH_ALEN] __aligned(2);
|
||||
struct cfg80211_bss *bss;
|
||||
u16 status;
|
||||
} links[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
|
@ -566,6 +566,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
|
||||
}
|
||||
|
||||
err = ieee80211_key_link(key, link, sta);
|
||||
/* KRACK protection, shouldn't happen but just silently accept key */
|
||||
if (err == -EALREADY)
|
||||
err = 0;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
@ -1857,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
|
||||
/* VHT can override some HT caps such as the A-MSDU max length */
|
||||
if (params->vht_capa)
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
params->vht_capa, link_sta);
|
||||
params->vht_capa, NULL,
|
||||
link_sta);
|
||||
|
||||
if (params->he_capa)
|
||||
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
|
||||
|
@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
|
||||
&chandef);
|
||||
memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
&cap_ie,
|
||||
&cap_ie, NULL,
|
||||
&sta->deflink);
|
||||
if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
|
||||
rates_updated |= true;
|
||||
|
@ -676,7 +676,7 @@ struct ieee80211_if_mesh {
|
||||
struct timer_list mesh_path_root_timer;
|
||||
|
||||
unsigned long wrkq_flags;
|
||||
unsigned long mbss_changed;
|
||||
unsigned long mbss_changed[64 / BITS_PER_LONG];
|
||||
|
||||
bool userspace_handles_dfs;
|
||||
|
||||
@ -2141,6 +2141,7 @@ void
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie2,
|
||||
struct link_sta_info *link_sta);
|
||||
enum ieee80211_sta_rx_bandwidth
|
||||
ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta);
|
||||
|
@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key,
|
||||
|
||||
void ieee80211_key_free_unused(struct ieee80211_key *key)
|
||||
{
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
WARN_ON(key->sdata || key->local);
|
||||
ieee80211_key_free_common(key);
|
||||
}
|
||||
@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
* can cause warnings to appear.
|
||||
*/
|
||||
bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
|
||||
int ret = -EOPNOTSUPP;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&sdata->local->key_mtx);
|
||||
|
||||
@ -868,8 +871,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
* the same cipher. Enforce the assumption for pairwise keys.
|
||||
*/
|
||||
if ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
|
||||
(old_key && old_key->conf.cipher != key->conf.cipher))
|
||||
(old_key && old_key->conf.cipher != key->conf.cipher)) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
} else if (sta) {
|
||||
struct link_sta_info *link_sta = &sta->deflink;
|
||||
int link_id = key->conf.link_id;
|
||||
@ -895,8 +900,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
|
||||
/* Non-pairwise keys must also not switch the cipher on rekey */
|
||||
if (!pairwise) {
|
||||
if (old_key && old_key->conf.cipher != key->conf.cipher)
|
||||
if (old_key && old_key->conf.cipher != key->conf.cipher) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
* new version of the key to avoid nonce reuse or replay issues.
|
||||
*/
|
||||
if (ieee80211_key_identical(sdata, old_key, key)) {
|
||||
ieee80211_key_free_unused(key);
|
||||
ret = 0;
|
||||
goto out;
|
||||
ret = -EALREADY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
key->local = sdata->local;
|
||||
@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||
ieee80211_key_free(key, delay_tailroom);
|
||||
}
|
||||
|
||||
key = NULL;
|
||||
|
||||
out:
|
||||
ieee80211_key_free_unused(key);
|
||||
unlock:
|
||||
mutex_unlock(&sdata->local->key_mtx);
|
||||
|
||||
return ret;
|
||||
|
@ -1175,7 +1175,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
/* if we race with running work, worst case this work becomes a noop */
|
||||
for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
|
||||
set_bit(bit, &ifmsh->mbss_changed);
|
||||
set_bit(bit, ifmsh->mbss_changed);
|
||||
set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
|
||||
wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
|
||||
}
|
||||
@ -1257,7 +1257,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
/* clear any mesh work (for next join) we may have accrued */
|
||||
ifmsh->wrkq_flags = 0;
|
||||
ifmsh->mbss_changed = 0;
|
||||
memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed));
|
||||
|
||||
local->fif_other_bss--;
|
||||
atomic_dec(&local->iff_allmultis);
|
||||
@ -1724,9 +1724,9 @@ static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata)
|
||||
u32 bit;
|
||||
u64 changed = 0;
|
||||
|
||||
for_each_set_bit(bit, &ifmsh->mbss_changed,
|
||||
for_each_set_bit(bit, ifmsh->mbss_changed,
|
||||
sizeof(changed) * BITS_PER_BYTE) {
|
||||
clear_bit(bit, &ifmsh->mbss_changed);
|
||||
clear_bit(bit, ifmsh->mbss_changed);
|
||||
changed |= BIT(bit);
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
|
||||
changed |= IEEE80211_RC_BW_CHANGED;
|
||||
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
elems->vht_cap_elem,
|
||||
elems->vht_cap_elem, NULL,
|
||||
&sta->deflink);
|
||||
|
||||
ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
|
||||
|
@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
|
||||
elems->ht_cap_elem,
|
||||
link_sta);
|
||||
|
||||
if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT))
|
||||
if (elems->vht_cap_elem &&
|
||||
!(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) {
|
||||
const struct ieee80211_vht_cap *bss_vht_cap = NULL;
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
|
||||
/*
|
||||
* Cisco AP module 9115 with FW 17.3 has a bug and sends a
|
||||
* too large maximum MPDU length in the association response
|
||||
* (indicating 12k) that it cannot actually process ...
|
||||
* Work around that.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
ies = rcu_dereference(cbss->ies);
|
||||
if (ies) {
|
||||
const struct element *elem;
|
||||
|
||||
elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY,
|
||||
ies->data, ies->len);
|
||||
if (elem && elem->datalen >= sizeof(*bss_vht_cap))
|
||||
bss_vht_cap = (const void *)elem->data;
|
||||
}
|
||||
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
|
||||
elems->vht_cap_elem,
|
||||
link_sta);
|
||||
bss_vht_cap, link_sta);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) &&
|
||||
elems->he_cap) {
|
||||
@ -5107,9 +5130,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
continue;
|
||||
|
||||
valid_links |= BIT(link_id);
|
||||
if (assoc_data->link[link_id].disabled) {
|
||||
if (assoc_data->link[link_id].disabled)
|
||||
dormant_links |= BIT(link_id);
|
||||
} else if (link_id != assoc_data->assoc_link_id) {
|
||||
|
||||
if (link_id != assoc_data->assoc_link_id) {
|
||||
err = ieee80211_sta_allocate_link(sta, link_id);
|
||||
if (err)
|
||||
goto out_err;
|
||||
@ -5124,7 +5148,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_link_data *link;
|
||||
struct link_sta_info *link_sta;
|
||||
|
||||
if (!cbss || assoc_data->link[link_id].disabled)
|
||||
if (!cbss)
|
||||
continue;
|
||||
|
||||
link = sdata_dereference(sdata->link[link_id], sdata);
|
||||
@ -5429,17 +5453,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
|
||||
struct ieee80211_link_data *link;
|
||||
|
||||
link = sdata_dereference(sdata->link[link_id], sdata);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
if (!assoc_data->link[link_id].bss)
|
||||
continue;
|
||||
|
||||
resp.links[link_id].bss = assoc_data->link[link_id].bss;
|
||||
resp.links[link_id].addr = link->conf->addr;
|
||||
ether_addr_copy(resp.links[link_id].addr,
|
||||
assoc_data->link[link_id].addr);
|
||||
resp.links[link_id].status = assoc_data->link[link_id].status;
|
||||
|
||||
link = sdata_dereference(sdata->link[link_id], sdata);
|
||||
if (!link)
|
||||
continue;
|
||||
|
||||
/* get uapsd queues configuration - same for all links */
|
||||
resp.uapsd_queues = 0;
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
|
@ -665,7 +665,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
||||
}
|
||||
|
||||
if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED &&
|
||||
!ieee80211_is_deauth(hdr->frame_control)))
|
||||
!ieee80211_is_deauth(hdr->frame_control)) &&
|
||||
tx->skb->protocol != tx->sdata->control_port_protocol)
|
||||
return TX_DROP;
|
||||
|
||||
if (!skip_hw && tx->key &&
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Portions of this file
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2022 Intel Corporation
|
||||
* Copyright (C) 2018 - 2023 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@ -116,12 +116,14 @@ void
|
||||
ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_supported_band *sband,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie,
|
||||
const struct ieee80211_vht_cap *vht_cap_ie2,
|
||||
struct link_sta_info *link_sta)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap;
|
||||
struct ieee80211_sta_vht_cap own_cap;
|
||||
u32 cap_info, i;
|
||||
bool have_80mhz;
|
||||
u32 mpdu_len;
|
||||
|
||||
memset(vht_cap, 0, sizeof(*vht_cap));
|
||||
|
||||
@ -317,11 +319,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta);
|
||||
|
||||
/*
|
||||
* Work around the Cisco 9115 FW 17.3 bug by taking the min of
|
||||
* both reported MPDU lengths.
|
||||
*/
|
||||
mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK;
|
||||
if (vht_cap_ie2)
|
||||
mpdu_len = min_t(u32, mpdu_len,
|
||||
le32_get_bits(vht_cap_ie2->vht_cap_info,
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_MASK));
|
||||
|
||||
/*
|
||||
* FIXME - should the amsdu len be per link? store per link
|
||||
* and maintain a minimum?
|
||||
*/
|
||||
switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
|
||||
switch (mpdu_len) {
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
|
||||
link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
|
||||
break;
|
||||
|
@ -48,6 +48,7 @@ struct rfkill {
|
||||
bool persistent;
|
||||
bool polling_paused;
|
||||
bool suspended;
|
||||
bool need_sync;
|
||||
|
||||
const struct rfkill_ops *ops;
|
||||
void *data;
|
||||
@ -368,6 +369,17 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
|
||||
rfkill_event(rfkill);
|
||||
}
|
||||
|
||||
static void rfkill_sync(struct rfkill *rfkill)
|
||||
{
|
||||
lockdep_assert_held(&rfkill_global_mutex);
|
||||
|
||||
if (!rfkill->need_sync)
|
||||
return;
|
||||
|
||||
rfkill_set_block(rfkill, rfkill_global_states[rfkill->type].cur);
|
||||
rfkill->need_sync = false;
|
||||
}
|
||||
|
||||
static void rfkill_update_global_state(enum rfkill_type type, bool blocked)
|
||||
{
|
||||
int i;
|
||||
@ -730,6 +742,10 @@ static ssize_t soft_show(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
rfkill_sync(rfkill);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0);
|
||||
}
|
||||
|
||||
@ -751,6 +767,7 @@ static ssize_t soft_store(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
rfkill_sync(rfkill);
|
||||
rfkill_set_block(rfkill, state);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
@ -783,6 +800,10 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
rfkill_sync(rfkill);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state));
|
||||
}
|
||||
|
||||
@ -805,6 +826,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
rfkill_sync(rfkill);
|
||||
rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
@ -1032,14 +1054,10 @@ static void rfkill_uevent_work(struct work_struct *work)
|
||||
|
||||
static void rfkill_sync_work(struct work_struct *work)
|
||||
{
|
||||
struct rfkill *rfkill;
|
||||
bool cur;
|
||||
|
||||
rfkill = container_of(work, struct rfkill, sync_work);
|
||||
struct rfkill *rfkill = container_of(work, struct rfkill, sync_work);
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
cur = rfkill_global_states[rfkill->type].cur;
|
||||
rfkill_set_block(rfkill, cur);
|
||||
rfkill_sync(rfkill);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
|
||||
@ -1087,6 +1105,7 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
round_jiffies_relative(POLL_INTERVAL));
|
||||
|
||||
if (!rfkill->persistent || rfkill_epo_lock_active) {
|
||||
rfkill->need_sync = true;
|
||||
schedule_work(&rfkill->sync_work);
|
||||
} else {
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
@ -1171,6 +1190,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file)
|
||||
ev = kzalloc(sizeof(*ev), GFP_KERNEL);
|
||||
if (!ev)
|
||||
goto free;
|
||||
rfkill_sync(rfkill);
|
||||
rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD);
|
||||
list_add_tail(&ev->list, &data->events);
|
||||
}
|
||||
|
@ -1181,16 +1181,11 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked,
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason);
|
||||
|
||||
void cfg80211_cqm_config_free(struct wireless_dev *wdev)
|
||||
{
|
||||
kfree(wdev->cqm_config);
|
||||
wdev->cqm_config = NULL;
|
||||
}
|
||||
|
||||
static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
|
||||
bool unregister_netdev)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct cfg80211_cqm_config *cqm_config;
|
||||
unsigned int link_id;
|
||||
|
||||
ASSERT_RTNL();
|
||||
@ -1227,7 +1222,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev,
|
||||
kfree_sensitive(wdev->wext.keys);
|
||||
wdev->wext.keys = NULL;
|
||||
#endif
|
||||
cfg80211_cqm_config_free(wdev);
|
||||
wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work);
|
||||
/* deleted from the list, so can't be found from nl80211 any more */
|
||||
cqm_config = rcu_access_pointer(wdev->cqm_config);
|
||||
kfree_rcu(cqm_config, rcu_head);
|
||||
|
||||
/*
|
||||
* Ensure that all events have been processed and
|
||||
@ -1379,6 +1377,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev)
|
||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
#endif
|
||||
|
||||
wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work);
|
||||
|
||||
if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
|
||||
wdev->ps = true;
|
||||
else
|
||||
|
@ -295,12 +295,17 @@ struct cfg80211_beacon_registration {
|
||||
};
|
||||
|
||||
struct cfg80211_cqm_config {
|
||||
struct rcu_head rcu_head;
|
||||
u32 rssi_hyst;
|
||||
s32 last_rssi_event_value;
|
||||
enum nl80211_cqm_rssi_threshold_event last_rssi_event_type;
|
||||
int n_rssi_thresholds;
|
||||
s32 rssi_thresholds[] __counted_by(n_rssi_thresholds);
|
||||
};
|
||||
|
||||
void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy,
|
||||
struct wiphy_work *work);
|
||||
|
||||
void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
|
||||
|
||||
/* free object */
|
||||
@ -566,8 +571,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev,
|
||||
#define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; })
|
||||
#endif
|
||||
|
||||
void cfg80211_cqm_config_free(struct wireless_dev *wdev);
|
||||
|
||||
void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
|
||||
void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
|
||||
void cfg80211_pmsr_free_wk(struct work_struct *work);
|
||||
|
@ -52,7 +52,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
|
||||
cr.links[link_id].bssid = data->links[link_id].bss->bssid;
|
||||
cr.links[link_id].addr = data->links[link_id].addr;
|
||||
/* need to have local link addresses for MLO connections */
|
||||
WARN_ON(cr.ap_mld_addr && !cr.links[link_id].addr);
|
||||
WARN_ON(cr.ap_mld_addr &&
|
||||
!is_valid_ether_addr(cr.links[link_id].addr));
|
||||
|
||||
BUG_ON(!cr.links[link_id].bss->channel);
|
||||
|
||||
|
@ -5909,6 +5909,21 @@ out:
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
|
||||
static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params)
|
||||
{
|
||||
struct ieee80211_channel *channel = params->chandef.chan;
|
||||
|
||||
if ((params->he_cap || params->he_oper) &&
|
||||
(channel->flags & IEEE80211_CHAN_NO_HE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((params->eht_cap || params->eht_oper) &&
|
||||
(channel->flags & IEEE80211_CHAN_NO_EHT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
@ -6178,6 +6193,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
err = nl80211_validate_ap_phy_operation(params);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS])
|
||||
params->flags = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]);
|
||||
@ -8482,7 +8501,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb,
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct mesh_config cfg;
|
||||
struct mesh_config cfg = {};
|
||||
u32 mask;
|
||||
int err;
|
||||
|
||||
@ -12796,7 +12815,8 @@ static int nl80211_set_cqm_txe(struct genl_info *info,
|
||||
}
|
||||
|
||||
static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev)
|
||||
struct net_device *dev,
|
||||
struct cfg80211_cqm_config *cqm_config)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
s32 last, low, high;
|
||||
@ -12805,7 +12825,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
|
||||
int err;
|
||||
|
||||
/* RSSI reporting disabled? */
|
||||
if (!wdev->cqm_config)
|
||||
if (!cqm_config)
|
||||
return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
|
||||
|
||||
/*
|
||||
@ -12814,7 +12834,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
|
||||
* connection is established and enough beacons received to calculate
|
||||
* the average.
|
||||
*/
|
||||
if (!wdev->cqm_config->last_rssi_event_value &&
|
||||
if (!cqm_config->last_rssi_event_value &&
|
||||
wdev->links[0].client.current_bss &&
|
||||
rdev->ops->get_station) {
|
||||
struct station_info sinfo = {};
|
||||
@ -12828,30 +12848,30 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
|
||||
|
||||
cfg80211_sinfo_release_content(&sinfo);
|
||||
if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
|
||||
wdev->cqm_config->last_rssi_event_value =
|
||||
cqm_config->last_rssi_event_value =
|
||||
(s8) sinfo.rx_beacon_signal_avg;
|
||||
}
|
||||
|
||||
last = wdev->cqm_config->last_rssi_event_value;
|
||||
hyst = wdev->cqm_config->rssi_hyst;
|
||||
n = wdev->cqm_config->n_rssi_thresholds;
|
||||
last = cqm_config->last_rssi_event_value;
|
||||
hyst = cqm_config->rssi_hyst;
|
||||
n = cqm_config->n_rssi_thresholds;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
i = array_index_nospec(i, n);
|
||||
if (last < wdev->cqm_config->rssi_thresholds[i])
|
||||
if (last < cqm_config->rssi_thresholds[i])
|
||||
break;
|
||||
}
|
||||
|
||||
low_index = i - 1;
|
||||
if (low_index >= 0) {
|
||||
low_index = array_index_nospec(low_index, n);
|
||||
low = wdev->cqm_config->rssi_thresholds[low_index] - hyst;
|
||||
low = cqm_config->rssi_thresholds[low_index] - hyst;
|
||||
} else {
|
||||
low = S32_MIN;
|
||||
}
|
||||
if (i < n) {
|
||||
i = array_index_nospec(i, n);
|
||||
high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1;
|
||||
high = cqm_config->rssi_thresholds[i] + hyst - 1;
|
||||
} else {
|
||||
high = S32_MAX;
|
||||
}
|
||||
@ -12864,6 +12884,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
|
||||
u32 hysteresis)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct cfg80211_cqm_config *cqm_config = NULL, *old;
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
int i, err;
|
||||
@ -12881,10 +12902,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
|
||||
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
wdev_lock(wdev);
|
||||
cfg80211_cqm_config_free(wdev);
|
||||
wdev_unlock(wdev);
|
||||
|
||||
if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
|
||||
if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
|
||||
return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
|
||||
@ -12901,9 +12918,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
|
||||
n_thresholds = 0;
|
||||
|
||||
wdev_lock(wdev);
|
||||
if (n_thresholds) {
|
||||
struct cfg80211_cqm_config *cqm_config;
|
||||
old = rcu_dereference_protected(wdev->cqm_config,
|
||||
lockdep_is_held(&wdev->mtx));
|
||||
|
||||
if (n_thresholds) {
|
||||
cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
|
||||
n_thresholds),
|
||||
GFP_KERNEL);
|
||||
@ -12918,11 +12936,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
|
||||
flex_array_size(cqm_config, rssi_thresholds,
|
||||
n_thresholds));
|
||||
|
||||
wdev->cqm_config = cqm_config;
|
||||
rcu_assign_pointer(wdev->cqm_config, cqm_config);
|
||||
} else {
|
||||
RCU_INIT_POINTER(wdev->cqm_config, NULL);
|
||||
}
|
||||
|
||||
err = cfg80211_cqm_rssi_update(rdev, dev);
|
||||
|
||||
err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
|
||||
if (err) {
|
||||
rcu_assign_pointer(wdev->cqm_config, old);
|
||||
kfree_rcu(cqm_config, rcu_head);
|
||||
} else {
|
||||
kfree_rcu(old, rcu_head);
|
||||
}
|
||||
unlock:
|
||||
wdev_unlock(wdev);
|
||||
|
||||
@ -19073,9 +19098,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
|
||||
enum nl80211_cqm_rssi_threshold_event rssi_event,
|
||||
s32 rssi_level, gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
struct cfg80211_cqm_config *cqm_config;
|
||||
|
||||
trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level);
|
||||
|
||||
@ -19083,18 +19107,41 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
|
||||
rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
|
||||
return;
|
||||
|
||||
if (wdev->cqm_config) {
|
||||
wdev->cqm_config->last_rssi_event_value = rssi_level;
|
||||
|
||||
cfg80211_cqm_rssi_update(rdev, dev);
|
||||
|
||||
if (rssi_level == 0)
|
||||
rssi_level = wdev->cqm_config->last_rssi_event_value;
|
||||
rcu_read_lock();
|
||||
cqm_config = rcu_dereference(wdev->cqm_config);
|
||||
if (cqm_config) {
|
||||
cqm_config->last_rssi_event_value = rssi_level;
|
||||
cqm_config->last_rssi_event_type = rssi_event;
|
||||
wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
|
||||
|
||||
msg = cfg80211_prepare_cqm(dev, NULL, gfp);
|
||||
void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work)
|
||||
{
|
||||
struct wireless_dev *wdev = container_of(work, struct wireless_dev,
|
||||
cqm_rssi_work);
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
enum nl80211_cqm_rssi_threshold_event rssi_event;
|
||||
struct cfg80211_cqm_config *cqm_config;
|
||||
struct sk_buff *msg;
|
||||
s32 rssi_level;
|
||||
|
||||
wdev_lock(wdev);
|
||||
cqm_config = rcu_dereference_protected(wdev->cqm_config,
|
||||
lockdep_is_held(&wdev->mtx));
|
||||
if (!wdev->cqm_config)
|
||||
goto unlock;
|
||||
|
||||
cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
|
||||
|
||||
rssi_level = cqm_config->last_rssi_event_value;
|
||||
rssi_event = cqm_config->last_rssi_event_type;
|
||||
|
||||
msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
|
||||
rssi_event))
|
||||
@ -19104,14 +19151,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
|
||||
rssi_level))
|
||||
goto nla_put_failure;
|
||||
|
||||
cfg80211_send_cqm(msg, gfp);
|
||||
cfg80211_send_cqm(msg, GFP_KERNEL);
|
||||
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_free(msg);
|
||||
unlock:
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
|
||||
|
||||
void cfg80211_cqm_txe_notify(struct net_device *dev,
|
||||
const u8 *peer, u32 num_packets,
|
||||
|
@ -908,6 +908,10 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev)
|
||||
!cfg80211_find_ssid_match(ap, request))
|
||||
continue;
|
||||
|
||||
if (!is_broadcast_ether_addr(request->bssid) &&
|
||||
!ether_addr_equal(request->bssid, ap->bssid))
|
||||
continue;
|
||||
|
||||
if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid)
|
||||
continue;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user