mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
Merge tag 'wireless-2025-11-12' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless
Johannes Berg says: ==================== Couple more fixes: - mwl8k: work around FW expecting a DSSS element in beacons - ath11k: report correct TX status - iwlwifi: avoid toggling links due to wrong element use - iwlwifi: fix beacon template rate on older devices - iwlwifi: fix loop iterator being used after loop - mac80211: disallow address changes while using the address - mac80211: avoid bad rate warning in monitor/sniffer mode - hwsim: fix potential NULL deref (on monitor injection) * tag 'wireless-2025-11-12' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: iwlwifi: mld: always take beacon ies in link grading wifi: iwlwifi: mvm: fix beacon template/fixed rate wifi: iwlwifi: fix aux ROC time event iterator usage wifi: mwl8k: inject DSSS Parameter Set element into beacons if missing wifi: mac80211_hwsim: Fix possible NULL dereference wifi: mac80211: skip rate verification for not captured PSDUs wifi: mac80211: reject address change while connecting wifi: ath11k: zero init info->status in wmi_process_mgmt_tx_comp() ==================== Link: https://patch.msgid.link/20251112114621.15716-5-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -5961,6 +5961,9 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
|
||||
dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->status.rates[0].idx = -1;
|
||||
|
||||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) &&
|
||||
!tx_compl_param->status) {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
@@ -708,18 +708,13 @@ static int
|
||||
iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
|
||||
struct ieee80211_bss_conf *link_conf)
|
||||
{
|
||||
struct ieee80211_vif *vif = link_conf->vif;
|
||||
const struct cfg80211_bss_ies *ies;
|
||||
const struct element *bss_load_elem = NULL;
|
||||
const struct ieee80211_bss_load_elem *bss_load;
|
||||
|
||||
guard(rcu)();
|
||||
|
||||
if (ieee80211_vif_link_active(vif, link_conf->link_id))
|
||||
ies = rcu_dereference(link_conf->bss->beacon_ies);
|
||||
else
|
||||
ies = rcu_dereference(link_conf->bss->ies);
|
||||
|
||||
ies = rcu_dereference(link_conf->bss->beacon_ies);
|
||||
if (ies)
|
||||
bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD,
|
||||
ies->data, ies->len);
|
||||
|
||||
@@ -938,19 +938,12 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
|
||||
|
||||
u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
|
||||
{
|
||||
u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
|
||||
bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
|
||||
u16 flags, cck_flag;
|
||||
|
||||
if (is_new_rate) {
|
||||
flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
|
||||
cck_flag = IWL_MAC_BEACON_CCK;
|
||||
} else {
|
||||
cck_flag = IWL_MAC_BEACON_CCK_V1;
|
||||
flags = iwl_fw_rate_idx_to_plcp(rate_idx);
|
||||
}
|
||||
|
||||
if (rate_idx <= IWL_LAST_CCK_RATE)
|
||||
flags |= cck_flag;
|
||||
flags |= is_new_rate ? IWL_MAC_BEACON_CCK
|
||||
: IWL_MAC_BEACON_CCK_V1;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
|
||||
if (!aux_roc_te) /* Not a Aux ROC time event */
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_te_check_trigger(mvm, notif, te_data);
|
||||
iwl_mvm_te_check_trigger(mvm, notif, aux_roc_te);
|
||||
|
||||
IWL_DEBUG_TE(mvm,
|
||||
"Aux ROC time event notification - UID = 0x%x action %d (error = %d)\n",
|
||||
@@ -475,14 +475,14 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
|
||||
/* End TE, notify mac80211 */
|
||||
ieee80211_remain_on_channel_expired(mvm->hw);
|
||||
iwl_mvm_roc_finished(mvm); /* flush aux queue */
|
||||
list_del(&te_data->list); /* remove from list */
|
||||
te_data->running = false;
|
||||
te_data->vif = NULL;
|
||||
te_data->uid = 0;
|
||||
te_data->id = TE_MAX;
|
||||
list_del(&aux_roc_te->list); /* remove from list */
|
||||
aux_roc_te->running = false;
|
||||
aux_roc_te->vif = NULL;
|
||||
aux_roc_te->uid = 0;
|
||||
aux_roc_te->id = TE_MAX;
|
||||
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
|
||||
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
|
||||
te_data->running = true;
|
||||
aux_roc_te->running = true;
|
||||
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
|
||||
} else {
|
||||
IWL_DEBUG_TE(mvm,
|
||||
|
||||
@@ -159,9 +159,15 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
||||
|
||||
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
|
||||
{
|
||||
return (rate_idx >= IWL_FIRST_OFDM_RATE ?
|
||||
rate_idx - IWL_FIRST_OFDM_RATE :
|
||||
rate_idx);
|
||||
if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
|
||||
/* In the new rate legacy rates are indexed:
|
||||
* 0 - 3 for CCK and 0 - 7 for OFDM.
|
||||
*/
|
||||
return (rate_idx >= IWL_FIRST_OFDM_RATE ?
|
||||
rate_idx - IWL_FIRST_OFDM_RATE :
|
||||
rate_idx);
|
||||
|
||||
return iwl_fw_rate_idx_to_plcp(rate_idx);
|
||||
}
|
||||
|
||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
|
||||
|
||||
@@ -2966,6 +2966,51 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
|
||||
/*
|
||||
* CMD_SET_BEACON.
|
||||
*/
|
||||
|
||||
static bool mwl8k_beacon_has_ds_params(const u8 *buf, int len)
|
||||
{
|
||||
const struct ieee80211_mgmt *mgmt = (const void *)buf;
|
||||
int ies_len;
|
||||
|
||||
if (len <= offsetof(struct ieee80211_mgmt, u.beacon.variable))
|
||||
return false;
|
||||
|
||||
ies_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||
|
||||
return cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
|
||||
ies_len) != NULL;
|
||||
}
|
||||
|
||||
static void mwl8k_beacon_copy_inject_ds_params(struct ieee80211_hw *hw,
|
||||
u8 *buf_dst, const u8 *buf_src,
|
||||
int src_len)
|
||||
{
|
||||
const struct ieee80211_mgmt *mgmt = (const void *)buf_src;
|
||||
static const u8 before_ds_params[] = {
|
||||
WLAN_EID_SSID,
|
||||
WLAN_EID_SUPP_RATES,
|
||||
};
|
||||
const u8 *ies;
|
||||
int hdr_len, left, offs, pos;
|
||||
|
||||
ies = mgmt->u.beacon.variable;
|
||||
hdr_len = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||
|
||||
offs = ieee80211_ie_split(ies, src_len - hdr_len, before_ds_params,
|
||||
ARRAY_SIZE(before_ds_params), 0);
|
||||
|
||||
pos = hdr_len + offs;
|
||||
left = src_len - pos;
|
||||
|
||||
memcpy(buf_dst, buf_src, pos);
|
||||
|
||||
/* Inject a DSSS Parameter Set after SSID + Supp Rates */
|
||||
buf_dst[pos + 0] = WLAN_EID_DS_PARAMS;
|
||||
buf_dst[pos + 1] = 1;
|
||||
buf_dst[pos + 2] = hw->conf.chandef.chan->hw_value;
|
||||
|
||||
memcpy(buf_dst + pos + 3, buf_src + pos, left);
|
||||
}
|
||||
struct mwl8k_cmd_set_beacon {
|
||||
struct mwl8k_cmd_pkt_hdr header;
|
||||
__le16 beacon_len;
|
||||
@@ -2975,17 +3020,33 @@ struct mwl8k_cmd_set_beacon {
|
||||
static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u8 *beacon, int len)
|
||||
{
|
||||
bool ds_params_present = mwl8k_beacon_has_ds_params(beacon, len);
|
||||
struct mwl8k_cmd_set_beacon *cmd;
|
||||
int rc;
|
||||
int rc, final_len = len;
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
|
||||
if (!ds_params_present) {
|
||||
/*
|
||||
* mwl8k firmware requires a DS Params IE with the current
|
||||
* channel in AP beacons. If mac80211/hostapd does not
|
||||
* include it, inject one here. IE ID + length + channel
|
||||
* number = 3 bytes.
|
||||
*/
|
||||
final_len += 3;
|
||||
}
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd) + final_len, GFP_KERNEL);
|
||||
if (cmd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
|
||||
cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
|
||||
cmd->beacon_len = cpu_to_le16(len);
|
||||
memcpy(cmd->beacon, beacon, len);
|
||||
cmd->header.length = cpu_to_le16(sizeof(*cmd) + final_len);
|
||||
cmd->beacon_len = cpu_to_le16(final_len);
|
||||
|
||||
if (ds_params_present)
|
||||
memcpy(cmd->beacon, beacon, len);
|
||||
else
|
||||
mwl8k_beacon_copy_inject_ds_params(hw, cmd->beacon, beacon,
|
||||
len);
|
||||
|
||||
rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
|
||||
kfree(cmd);
|
||||
|
||||
@@ -2003,8 +2003,14 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta = control->sta;
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
|
||||
/* This can happen in case of monitor injection */
|
||||
if (!vif) {
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (link != IEEE80211_LINK_UNSPECIFIED) {
|
||||
bss_conf = rcu_dereference(txi->control.vif->link_conf[link]);
|
||||
bss_conf = rcu_dereference(vif->link_conf[link]);
|
||||
if (sta)
|
||||
link_sta = rcu_dereference(sta->link[link]);
|
||||
} else {
|
||||
@@ -2065,13 +2071,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
||||
return;
|
||||
}
|
||||
|
||||
if (txi->control.vif)
|
||||
hwsim_check_magic(txi->control.vif);
|
||||
if (vif)
|
||||
hwsim_check_magic(vif);
|
||||
if (control->sta)
|
||||
hwsim_check_sta_magic(control->sta);
|
||||
|
||||
if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE))
|
||||
ieee80211_get_tx_rates(txi->control.vif, control->sta, skb,
|
||||
ieee80211_get_tx_rates(vif, control->sta, skb,
|
||||
txi->control.rates,
|
||||
ARRAY_SIZE(txi->control.rates));
|
||||
|
||||
|
||||
@@ -223,6 +223,10 @@ static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata
|
||||
if (netif_carrier_ok(sdata->dev))
|
||||
return -EBUSY;
|
||||
|
||||
/* if any stations are set known (so they know this vif too), reject */
|
||||
if (sta_info_get_by_idx(sdata, 0))
|
||||
return -EBUSY;
|
||||
|
||||
/* First check no ROC work is happening on this iface */
|
||||
list_for_each_entry(roc, &local->roc_list, list) {
|
||||
if (roc->sdata != sdata)
|
||||
@@ -242,12 +246,16 @@ static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* More interface types could be added here but changing the
|
||||
* address while powered makes the most sense in client modes.
|
||||
*/
|
||||
switch (sdata->vif.type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
/* More interface types could be added here but changing the
|
||||
* address while powered makes the most sense in client modes.
|
||||
*/
|
||||
/* refuse while connecting */
|
||||
if (sdata->u.mgd.auth_data || sdata->u.mgd.assoc_data)
|
||||
return -EBUSY;
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
|
||||
@@ -5360,10 +5360,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
|
||||
if (WARN_ON(!local->started))
|
||||
goto drop;
|
||||
|
||||
if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) {
|
||||
if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) &&
|
||||
!(status->flag & RX_FLAG_NO_PSDU &&
|
||||
status->zero_length_psdu_type ==
|
||||
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) {
|
||||
/*
|
||||
* Validate the rate, unless a PLCP error means that
|
||||
* we probably can't have a valid rate here anyway.
|
||||
* Validate the rate, unless there was a PLCP error which may
|
||||
* have an invalid rate or the PSDU was not capture and may be
|
||||
* missing rate information.
|
||||
*/
|
||||
|
||||
switch (status->encoding) {
|
||||
|
||||
Reference in New Issue
Block a user