Couple of quick fixes:

- iwlwifi/iwlmld crash on certain error paths
  - iwlwifi/iwlmld regulatory data mixup
  - iwlwifi/iwlmld suspend/resume fix
  - iwlwifi MSI (without -X) fix
  - cfg80211/mac80211 S1G parsing fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmhBaO0ACgkQ10qiO8sP
 aABINw/9ExZdFxO6EDoiNMZbAOjMdNRxt64s7hCjy/CWz5f+qPCmS09mk+LBi+vx
 +1sAIoDIg0YfYjEt+yB7/+dAU66gX85y0wZfGVJPuMfzOvabzCnsNS8++yFIBdLr
 C24I+MRsJU3q+CMlSAkeyCN4jkKTRlVUJtQB1iteK/MYOUxvkRwuZAxfNMHVRq0L
 VWY+8nuzDeYMllnomznsOL4RhcIUXzcEkJA9Vd7ae3KEuw5gicOBiDh+sDl7hYVE
 bW9zDrcXIT2CUrF9ZVErIiUKuCJONTQzGrs1DAFSvnhY3C3IpV4L7UiQwaUChaZv
 THr0Ui4S059mDMZeoX+06RA1/+3nlf8J+yLTBS0JzeyCABxIgEyM55MtnYq6vQk9
 SsHnWLdwMDxVIAveZkP1ukCF7LhY6TybT8AibrmOXvAeNzjTq3D+Yc66BRyBTFq7
 P73wG4gcFd8nz9p5ZiRjqN0VTLi70N0ERUmWEv9LqURD9tZCWqkp6rNX3Dib9ZBV
 knj2PaMdHPbv1ovmqmVGv82mxE1Ke/zF7uaLi6bK/h03ST3cT7wUZCmNL46XorOo
 pQsmSr0E9Z1UlEFVJjDnSiI/m8YaDUKBWUBK72cOy6GmI7KKMQiG0WgZhRdgoi0P
 IdPqg6fl9EFPznY7exghDafV+Op84g+SDqpi4PslXbBVRze7KJk=
 =Ai0E
 -----END PGP SIGNATURE-----

Merge tag 'wireless-2025-06-05' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

Johannes Berg says:

====================
Couple of quick fixes:
 - iwlwifi/iwlmld crash on certain error paths
 - iwlwifi/iwlmld regulatory data mixup
 - iwlwifi/iwlmld suspend/resume fix
 - iwlwifi MSI (without -X) fix
 - cfg80211/mac80211 S1G parsing fixes

* tag 'wireless-2025-06-05' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless:
  wifi: cfg80211/mac80211: correctly parse S1G beacon optional elements
  wifi: iwlwifi: mld: Move regulatory domain initialization
  wifi: iwlwifi: pcie: fix non-MSIX handshake register
  wifi: iwlwifi: mld: avoid panic on init failure
  wifi: iwlwifi: mvm: fix assert on suspend
====================

Link: https://patch.msgid.link/20250605095443.17874-6-johannes@sipsolutions.net
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2025-06-05 15:19:33 +02:00
commit 4d401c5534
8 changed files with 92 additions and 40 deletions

View File

@ -349,10 +349,6 @@ int iwl_mld_load_fw(struct iwl_mld *mld)
if (ret)
goto err;
ret = iwl_mld_init_mcc(mld);
if (ret)
goto err;
mld->fw_status.running = true;
return 0;
@ -546,6 +542,10 @@ int iwl_mld_start_fw(struct iwl_mld *mld)
if (ret)
goto error;
ret = iwl_mld_init_mcc(mld);
if (ret)
goto error;
return 0;
error:

View File

@ -653,7 +653,8 @@ iwl_mld_nic_error(struct iwl_op_mode *op_mode,
* It might not actually be true that we'll restart, but the
* setting doesn't matter if we're going to be unbound either.
*/
if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT)
if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT &&
mld->fw_status.running)
mld->fw_status.in_hw_restart = true;
}

View File

@ -6360,8 +6360,8 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
(struct iwl_mvm_internal_rxq_notif *)cmd->payload;
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD),
.data[0] = &cmd,
.len[0] = sizeof(cmd),
.data[0] = cmd,
.len[0] = __struct_size(cmd),
.data[1] = data,
.len[1] = size,
.flags = CMD_SEND_IN_RFKILL | (sync ? 0 : CMD_ASYNC),

View File

@ -125,7 +125,7 @@ void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
reset_done =
inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE;
} else {
inta_hw = iwl_read32(trans, CSR_INT_MASK);
inta_hw = iwl_read32(trans, CSR_INT);
reset_done = inta_hw & CSR_INT_BIT_RESET_DONE;
}

View File

@ -111,6 +111,8 @@
/* bits unique to S1G beacon */
#define IEEE80211_S1G_BCN_NEXT_TBTT 0x100
#define IEEE80211_S1G_BCN_CSSID 0x200
#define IEEE80211_S1G_BCN_ANO 0x400
/* see 802.11ah-2016 9.9 NDP CMAC frames */
#define IEEE80211_S1G_1MHZ_NDP_BITS 25
@ -153,9 +155,6 @@
#define IEEE80211_ANO_NETTYPE_WILD 15
/* bits unique to S1G beacon */
#define IEEE80211_S1G_BCN_NEXT_TBTT 0x100
/* control extension - for IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTL_EXT */
#define IEEE80211_CTL_EXT_POLL 0x2000
#define IEEE80211_CTL_EXT_SPR 0x3000
@ -627,6 +626,42 @@ static inline bool ieee80211_is_s1g_beacon(__le16 fc)
cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON);
}
/**
* ieee80211_s1g_has_next_tbtt - check if IEEE80211_S1G_BCN_NEXT_TBTT
* @fc: frame control bytes in little-endian byteorder
* Return: whether or not the frame contains the variable-length
* next TBTT field
*/
static inline bool ieee80211_s1g_has_next_tbtt(__le16 fc)
{
return ieee80211_is_s1g_beacon(fc) &&
(fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT));
}
/**
* ieee80211_s1g_has_ano - check if IEEE80211_S1G_BCN_ANO
* @fc: frame control bytes in little-endian byteorder
* Return: whether or not the frame contains the variable-length
* ANO field
*/
static inline bool ieee80211_s1g_has_ano(__le16 fc)
{
return ieee80211_is_s1g_beacon(fc) &&
(fc & cpu_to_le16(IEEE80211_S1G_BCN_ANO));
}
/**
* ieee80211_s1g_has_cssid - check if IEEE80211_S1G_BCN_CSSID
* @fc: frame control bytes in little-endian byteorder
* Return: whether or not the frame contains the variable-length
* compressed SSID field
*/
static inline bool ieee80211_s1g_has_cssid(__le16 fc)
{
return ieee80211_is_s1g_beacon(fc) &&
(fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID));
}
/**
* ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon
* @fc: frame control bytes in little-endian byteorder
@ -1245,16 +1280,40 @@ struct ieee80211_ext {
u8 change_seq;
u8 variable[0];
} __packed s1g_beacon;
struct {
u8 sa[ETH_ALEN];
__le32 timestamp;
u8 change_seq;
u8 next_tbtt[3];
u8 variable[0];
} __packed s1g_short_beacon;
} u;
} __packed __aligned(2);
/**
* ieee80211_s1g_optional_len - determine length of optional S1G beacon fields
* @fc: frame control bytes in little-endian byteorder
* Return: total length in bytes of the optional fixed-length fields
*
* S1G beacons may contain up to three optional fixed-length fields that
* precede the variable-length elements. Whether these fields are present
* is indicated by flags in the frame control field.
*
* From IEEE 802.11-2024 section 9.3.4.3:
* - Next TBTT field may be 0 or 3 bytes
* - Short SSID field may be 0 or 4 bytes
* - Access Network Options (ANO) field may be 0 or 1 byte
*/
static inline size_t
ieee80211_s1g_optional_len(__le16 fc)
{
size_t len = 0;
if (ieee80211_s1g_has_next_tbtt(fc))
len += 3;
if (ieee80211_s1g_has_cssid(fc))
len += 4;
if (ieee80211_s1g_has_ano(fc))
len += 1;
return len;
}
#define IEEE80211_TWT_CONTROL_NDP BIT(0)
#define IEEE80211_TWT_CONTROL_RESP_MODE BIT(1)
#define IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST BIT(3)

View File

@ -7220,11 +7220,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
bssid = ieee80211_get_bssid(hdr, len, sdata->vif.type);
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
struct ieee80211_ext *ext = (void *) mgmt;
if (ieee80211_is_s1g_short_beacon(ext->frame_control))
variable = ext->u.s1g_short_beacon.variable;
else
variable = ext->u.s1g_beacon.variable;
variable = ext->u.s1g_beacon.variable +
ieee80211_s1g_optional_len(ext->frame_control);
}
baselen = (u8 *) variable - (u8 *) mgmt;

View File

@ -276,6 +276,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
struct ieee80211_mgmt *mgmt = (void *)skb->data;
struct ieee80211_bss *bss;
struct ieee80211_channel *channel;
struct ieee80211_ext *ext;
size_t min_hdr_len = offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
@ -285,12 +286,10 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
return;
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
min_hdr_len = offsetof(struct ieee80211_ext,
u.s1g_short_beacon.variable);
else
min_hdr_len = offsetof(struct ieee80211_ext,
u.s1g_beacon);
ext = (struct ieee80211_ext *)mgmt;
min_hdr_len =
offsetof(struct ieee80211_ext, u.s1g_beacon.variable) +
ieee80211_s1g_optional_len(ext->frame_control);
}
if (skb->len < min_hdr_len)

View File

@ -3250,6 +3250,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
const u8 *ie;
size_t ielen;
u64 tsf;
size_t s1g_optional_len;
if (WARN_ON(!mgmt))
return NULL;
@ -3264,12 +3265,11 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
ext = (void *) mgmt;
if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
min_hdr_len = offsetof(struct ieee80211_ext,
u.s1g_short_beacon.variable);
else
min_hdr_len = offsetof(struct ieee80211_ext,
u.s1g_beacon.variable);
s1g_optional_len =
ieee80211_s1g_optional_len(ext->frame_control);
min_hdr_len =
offsetof(struct ieee80211_ext, u.s1g_beacon.variable) +
s1g_optional_len;
} else {
/* same for beacons */
min_hdr_len = offsetof(struct ieee80211_mgmt,
@ -3285,11 +3285,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
const struct ieee80211_s1g_bcn_compat_ie *compat;
const struct element *elem;
if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
ie = ext->u.s1g_short_beacon.variable;
else
ie = ext->u.s1g_beacon.variable;
ie = ext->u.s1g_beacon.variable + s1g_optional_len;
elem = cfg80211_find_elem(WLAN_EID_S1G_BCN_COMPAT, ie, ielen);
if (!elem)
return NULL;