From 9c0c2ae7d9f4a627942c9703085943b56fbdec76 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 21 Sep 2026 23:41:11 +0300 Subject: [PATCH 001/104] wifi: iwlwifi: mld: Add support for (Re)association req/resp encryption Introduce support for (re)association request/response encryption if supported by the firmware. Signed-off-by: Ilan Peer Link: https://patch.msgid.link/20260921233730.25ccedf95d32.Ie2834534bd644593b61a063d4ec5f7e323be4370@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h | 2 ++ drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mld/key.c | 6 ++++++ drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index c8eb016e1a7e..b17babef71c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -643,6 +643,7 @@ struct iwl_scd_queue_cfg_cmd { * @IWL_SEC_KEY_FLAG_MFP: MFP is in used for this key * @IWL_SEC_KEY_FLAG_MCAST_KEY: this is a multicast key * @IWL_SEC_KEY_FLAG_SPP_AMSDU: SPP A-MSDU should be used + * @IWL_SEC_KEY_FLAG_ASSOC_ENC: use this key for (Re)Assoc Req/Resp encryption */ enum iwl_sec_key_flags { IWL_SEC_KEY_FLAG_CIPHER_MASK = 0x07, @@ -655,6 +656,7 @@ enum iwl_sec_key_flags { IWL_SEC_KEY_FLAG_MFP = 0x20, IWL_SEC_KEY_FLAG_MCAST_KEY = 0x40, IWL_SEC_KEY_FLAG_SPP_AMSDU = 0x80, + IWL_SEC_KEY_FLAG_ASSOC_ENC = 0x200, }; #define IWL_SEC_WEP_KEY_OFFSET 3 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 664ac25754e9..3a986b394dd8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -452,6 +452,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * table data. For LARI_CONFIG_CHANGE command version 13 and above, this * capability is obsolete since raw DSM values are accepted by default. * @IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT: Supports NAN synchronization + * @IWL_UCODE_TLV_CAPA_ASSOC_ENC_SUPPORT: firmware supports association frame encryption * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -556,6 +557,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0), IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1), IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 2), + IWL_UCODE_TLV_CAPA_ASSOC_ENC_SUPPORT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 4), NUM_IWL_UCODE_TLV_CAPA /* * This construction make both sparse (which cannot increment the previous diff --git a/drivers/net/wireless/intel/iwlwifi/mld/key.c b/drivers/net/wireless/intel/iwlwifi/mld/key.c index bf80b4770b5a..f2c87f830ba3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/key.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/key.c @@ -37,6 +37,12 @@ static u32 iwl_mld_get_key_flags(struct iwl_mld *mld, break; } + /* Note that sta->mfp might not be set yet, as it is set only + * after association. + */ + if (sta && pairwise && sta->epp_peer) + flags |= IWL_SEC_KEY_FLAG_ASSOC_ENC | IWL_SEC_KEY_FLAG_MFP; + /* If we are installing an iGTK (in AP or STA mode), we need to tell * the firmware this key will en/decrypt MGMT frames. * Same goes if we are installing a pairwise key for an MFP station. diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 3a4c8fda68d0..0b121114d47c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -395,6 +395,10 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld) if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_PROTECTED_TWT)) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_PROTECTED_TWT); + if (fw_has_capa(ucode_capa, IWL_UCODE_TLV_CAPA_ASSOC_ENC_SUPPORT)) + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_ASSOC_FRAME_ENCRYPTION); + if (iwlmld_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; else From 787f6368914c47457b7c2b95c9cecbde9cb63a4a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 21 Sep 2026 23:41:12 +0300 Subject: [PATCH 002/104] wifi: iwlwifi: mvm: wait for 6 missed beacons before disconnection In case we keep getting data from the AP, wait for 6 missed beacons since last Rx before disconnecting. This will give the firmware a chance to send NDPs to the AP and avoid disconnecting if the AP is still there. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233730.025f2655b3b1.Ieceece6d8f660399e844ea4dadac414243e35d07@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index c64e4ed00986..fb1fc9c42280 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -42,7 +42,7 @@ #define IWL_MVM_MAX_ADDRESSES 5 /* RSSI offset for WkP */ #define IWL_RSSI_OFFSET 50 -#define IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD 4 +#define IWL_MVM_MISSED_BEACONS_SINCE_RX_THOLD 6 #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 #define IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG 19 From 0a0e3d4923e03f0acb058b8839835f316265c09d Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 21 Sep 2026 23:41:13 +0300 Subject: [PATCH 003/104] wifi: iwlwifi: mld: config TLC only after attaching station to a link When a NAN link is activated, the TLC config command was sent for all the NAN stations. The TLC config was sent on all phys used by NAN. However, when a new NAN channel is added when there is already a NAN station (e.g. during schedule update), the station is not yet attached to the link of this phy (until the new schedule is applied by firmware). Sending a TLC command for the station on the new phy at this stage results in an assert because in firmware the station is not yet attached with the phy of this channel. Fix it by sending the TLC command only after configuring the station for the new phy. Signed-off-by: Avraham Stern Link: https://patch.msgid.link/20260921233730.24cefdd72e7d.Ib32c29716c805531f881c61d13931f5b3d7084a9@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/nan.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c index dbe7a54a38b7..8853fcb2b4ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c @@ -576,21 +576,11 @@ static int iwl_mld_nan_link_set_active(struct iwl_mld *mld, bool active) { struct iwl_link_config_cmd cmd; - struct ieee80211_sta *sta; int ret; if (nan_link->active == active) return 0; - if (active) { - for_each_station(sta, mld->hw) { - struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta); - - if (mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI) - iwl_mld_config_tlc(mld, mld_sta->vif, sta); - } - } - nan_link->active = active; iwl_mld_nan_link_prep_cmd(mld, nan_link, &cmd, @@ -602,10 +592,8 @@ static int iwl_mld_nan_link_set_active(struct iwl_mld *mld, return ret; } - if (!active) { + if (!active) nan_link->chanctx = NULL; - /* TODO: when FW is ready, Update phy in TLC to invalid after */ - } return 0; } @@ -847,6 +835,10 @@ void iwl_mld_nan_vif_cfg_changed(struct iwl_mld *mld, if (mld_sta->sta_type == STATION_TYPE_NAN_PEER_NMI || mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI) iwl_mld_add_modify_sta_cmd(mld, &sta->deflink); + + if (added_links && + mld_sta->sta_type == STATION_TYPE_NAN_PEER_NDI) + iwl_mld_config_tlc(mld, mld_sta->vif, sta); } /* From 96588f292d8d99bae25919c86a27a23b896ca7b3 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 21 Sep 2026 23:41:14 +0300 Subject: [PATCH 004/104] wifi: iwlwifi: document MIC delay resolution This delay is given in the same format as in the CIP capabilities. Update the comment to make it clear that the resolution is 4 us. Signed-off-by: Benjamin Berg Link: https://patch.msgid.link/20260921233730.0947a2665f17.Ic994dae3eddf50955eac4cf79cb6388887c75b67@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 09b2cddc4ad2..01db6765855c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -868,8 +868,8 @@ struct iwl_sta_cfg_cmd_v1 { * @dps_pad_time: DPS (Dynamic Power Save) padding delay resolution to ensure * proper timing alignment * @dps_trans_delay: DPS minimal time that takes the peer to return to low power - * @mic_prep_pad_delay: MIC prep time padding - * @mic_compute_pad_delay: MIC compute time padding + * @mic_prep_pad_delay: MIC prep time padding (4 us resolution) + * @mic_compute_pad_delay: MIC compute time padding (4 us resolution) * @reserved: Reserved for alignment */ struct iwl_sta_cfg_cmd_v2 { @@ -942,8 +942,8 @@ struct iwl_sta_cfg_cmd_v2 { * proper timing alignment * @dps_trans_delay: DPS minimal time that takes the peer to return to low power * @dps_enabled: flag indicating whether or not DPS is enabled - * @mic_prep_pad_delay: MIC prep time padding - * @mic_compute_pad_delay: MIC compute time padding + * @mic_prep_pad_delay: MIC prep time padding (4 us resolution) + * @mic_compute_pad_delay: MIC compute time padding (4 us resolution) * @nmi_sta_id: for an NDI peer STA, the NMI peer STA ID it relates to * @ndi_local_addr: for an NDI peer STA or NAN multicast data station, * the local NDI interface MAC address From c4286559de5af81ada13d948e3cdc567f764b255 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 21 Sep 2026 23:41:15 +0300 Subject: [PATCH 005/104] wifi: iwlwifi: mld: don't use bss_conf in NAN When we receive the TLC notif, we try to fetch the band from the vif link. However, in NAN we don't have the bss_conf (link_conf[0] is technically pointing to vif::bss_conf, but it doesn't point to a channel). For now we don't have a way to fetch the channel used by this TLC instance (a NAN station can have multiple), but in the future we will have a TLC object in the driver and then we will have a phy id in it. For now, just take either the minimum between both lmacs or the only existing one. Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260921233730.18fefde9f26d.I8bc0c16de230f3bd45b80101db0936f1e4aea516@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c index b6c2fa3664cb..1f5994f8be26 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c @@ -824,8 +824,13 @@ iwl_mld_get_amsdu_size_of_tid(struct iwl_mld *mld, txf = iwl_mld_mac80211_ac_to_fw_tx_fifo(ac); - /* Only one link: take the lmac according to the band */ - if (hweight16(sta->valid_links) <= 1) { + /* + * Only one link: take the lmac according to the band + * In NAN, we don't have a link_conf. + * TODO: once we have a TLC object, we can know better the band. + */ + if (hweight16(sta->valid_links) <= 1 && + vif->type != NL80211_IFTYPE_NAN_DATA) { enum nl80211_band band; struct ieee80211_bss_conf *link = wiphy_dereference(mld->wiphy, From 56fe437aef2dc9bd37ad2b0abd9404a65d69e102 Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Mon, 21 Sep 2026 23:41:16 +0300 Subject: [PATCH 006/104] wifi: iwlwifi: fw: fix integer overflow in INI dump size calc The INI debug dump get_size handlers compute the region size as hdr_size + ranges * (size + sizeof(range)) using u32 arithmetic. Both the per-range size and the number of ranges originate from debug TLVs with no upper bound, so the multiplication and additions can overflow u32. A small value passes the size < sizeof(*header) check in iwl_dump_ini_mem_prep(). Add the size computation in each handler using check_add_overflow()/check_mul_overflow() and return 0 when the result would overflow. For the block handler the variable per-pair sizes are summed with check_add_overflow() before computing size, since that accumulation can overflow on its own. Signed-off-by: Shahar Tzarfati Assisted-by: GitHub-Copilot:claude-opus-4-8 Link: https://patch.msgid.link/20260921233730.0644f76cd8af.Id0d26b11fcdb33a5eff7824343caa6dc23385fd5@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 37 +++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 6621ef9358bc..a314fabbf06d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1016,8 +1016,16 @@ static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, if (!size || !ranges) return 0; - return sizeof(struct iwl_fw_ini_error_dump) + ranges * - (size + sizeof(struct iwl_fw_ini_error_dump_range)); + if (check_add_overflow(size, + (u32)sizeof(struct iwl_fw_ini_error_dump_range), + &size) || + check_mul_overflow(ranges, size, &size) || + check_add_overflow(size, + (u32)sizeof(struct iwl_fw_ini_error_dump), + &size)) + return 0; + + return size; } static u32 @@ -1028,15 +1036,24 @@ iwl_dump_ini_mem_block_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_addr_size *pairs = (void *)reg->addrs; u32 ranges = iwl_dump_ini_mem_block_ranges(fwrt, reg_data); u32 size = sizeof(struct iwl_fw_ini_error_dump); + u32 range_hdrs; int range; if (!ranges) return 0; for (range = 0; range < ranges; range++) - size += le32_to_cpu(pairs[range].size); + if (check_add_overflow(size, le32_to_cpu(pairs[range].size), + &size)) + return 0; - return size + ranges * sizeof(struct iwl_fw_ini_error_dump_range); + if (check_mul_overflow(ranges, + (u32)sizeof(struct iwl_fw_ini_error_dump_range), + &range_hdrs) || + check_add_overflow(size, range_hdrs, &size)) + return 0; + + return size; } static u32 @@ -1112,8 +1129,16 @@ static u32 iwl_dump_ini_mon_dbgi_get_size(struct iwl_fw_runtime *fwrt, if (!size || !ranges) return 0; - return sizeof(struct iwl_fw_ini_monitor_dump) + ranges * - (size + sizeof(struct iwl_fw_ini_error_dump_range)); + if (check_add_overflow(size, + (u32)sizeof(struct iwl_fw_ini_error_dump_range), + &size) || + check_mul_overflow(ranges, size, &size) || + check_add_overflow(size, + (u32)sizeof(struct iwl_fw_ini_monitor_dump), + &size)) + return 0; + + return size; } static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, From ef292778d590e9db4a4620175221786f84d6c34c Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Mon, 21 Sep 2026 23:41:17 +0300 Subject: [PATCH 007/104] wifi: iwlwifi: validate TLV length before reading fields The INI/Yoyo debug TLVs are parsed from an untrusted firmware-debug file. The dispatcher only guarantees that the TLV length covers the 8-byte common header, yet several per-type handlers dereferenced fields located beyond that header before checking the TLV length. Add the missing minimum-length check in iwl_dbg_tlv_config_set() so the short TLV is rejected before it is stored, and move the field reads in the other handlers to after their existing length checks so no field is dereferenced before the buffer is known to be large enough. Signed-off-by: Shahar Tzarfati Assisted-by: GitHub-Copilot:claude-opus-4-8 Link: https://patch.msgid.link/20260921233730.6127e849e40a.If963f766dbe29cbb8c226e163ab678be97240730@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 11763dec77ec..bd2a9e4b4b5f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -167,11 +167,13 @@ static int iwl_dbg_tlv_alloc_hcmd(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv) { const struct iwl_fw_ini_hcmd_tlv *hcmd = (const void *)tlv->data; - u32 tp = le32_to_cpu(hcmd->time_point); + u32 tp; if (le32_to_cpu(tlv->length) <= sizeof(*hcmd)) return -EINVAL; + tp = le32_to_cpu(hcmd->time_point); + /* Host commands can not be sent in early time point since the FW * is not ready */ @@ -194,9 +196,14 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans, { const struct iwl_fw_ini_region_tlv *reg = (const void *)tlv->data; struct iwl_ucode_tlv **active_reg; - u32 id = le32_to_cpu(reg->id); - u8 type = reg->type; u32 tlv_len = sizeof(*tlv) + le32_to_cpu(tlv->length); + u32 id; + u8 type; + + if (le32_to_cpu(tlv->length) < sizeof(*reg)) + return -EINVAL; + + id = le32_to_cpu(reg->id); /* * The higher part of the ID from version 2 is debug policy. @@ -205,9 +212,6 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans, if (le32_to_cpu(reg->hdr.version) >= 2) id &= IWL_FW_INI_REGION_ID_MASK; - if (le32_to_cpu(tlv->length) < sizeof(*reg)) - return -EINVAL; - /* for safe use of a string from FW, limit it to IWL_FW_INI_MAX_NAME */ IWL_DEBUG_FW(trans, "WRT: parsing region: %.*s\n", IWL_FW_INI_MAX_NAME, reg->name); @@ -217,6 +221,8 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans, return -EINVAL; } + type = reg->type; + if (type <= IWL_FW_INI_REGION_INVALID || type >= IWL_FW_INI_REGION_NUM) { IWL_ERR(trans, "WRT: Invalid region type %u\n", type); @@ -251,13 +257,14 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv) { const struct iwl_fw_ini_trigger_tlv *trig = (const void *)tlv->data; - u32 tp = le32_to_cpu(trig->time_point); - u32 rf = le32_to_cpu(trig->reset_fw); + u32 tp, rf; struct iwl_ucode_tlv *new_tlv; if (le32_to_cpu(tlv->length) < sizeof(*trig)) return -EINVAL; + tp = le32_to_cpu(trig->time_point); + if (tp <= IWL_FW_INI_TIME_POINT_INVALID || tp >= IWL_FW_INI_TIME_POINT_NUM) { IWL_ERR(trans, @@ -266,6 +273,8 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans, return -EINVAL; } + rf = le32_to_cpu(trig->reset_fw); + IWL_DEBUG_FW(trans, "WRT: time point %u for trigger TLV with reset_fw %u\n", tp, rf); @@ -288,8 +297,13 @@ static int iwl_dbg_tlv_config_set(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv) { const struct iwl_fw_ini_conf_set_tlv *conf_set = (const void *)tlv->data; - u32 tp = le32_to_cpu(conf_set->time_point); - u32 type = le32_to_cpu(conf_set->set_type); + u32 tp, type; + + if (le32_to_cpu(tlv->length) < sizeof(*conf_set)) + return -EINVAL; + + tp = le32_to_cpu(conf_set->time_point); + type = le32_to_cpu(conf_set->set_type); if (tp <= IWL_FW_INI_TIME_POINT_INVALID || tp >= IWL_FW_INI_TIME_POINT_NUM) { From 90f99edd7169723d13aa67c3cc8e0baabd60f2e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 21 Sep 2026 23:41:18 +0300 Subject: [PATCH 008/104] wifi: iwlwifi: pcie: validate txq_id in txq_disable iwl_trans_pcie_txq_disable() computed SCD_TX_STTS_QUEUE_OFFSET(txq_id) and dereferenced trans_pcie->txqs.txq[txq_id] before checking that txq_id is within range or that the queue was allocated. Bail out with a WARN_ON when txq_id is out of range or the queue is not allocated, and only compute the status address after the checks pass. We don't really want to disable the command queue either, so check that as well. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233730.c96ee7e007bc.Ie593dfd5451be69a5e6deca248a4b443e168ac88@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c index dc2fe0c4f68c..060074c2871b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -1276,9 +1276,17 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, bool configure_scd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u32 stts_addr = trans_pcie->scd_base_addr + - SCD_TX_STTS_QUEUE_OFFSET(txq_id); static const u32 zero_val[4] = {}; + u32 stts_addr; + + if (WARN_ON(txq_id < 0 || + txq_id >= trans->mac_cfg->base->num_of_queues || + txq_id == trans->conf.cmd_queue || + !trans_pcie->txqs.txq[txq_id])) + return; + + stts_addr = trans_pcie->scd_base_addr + + SCD_TX_STTS_QUEUE_OFFSET(txq_id); trans_pcie->txqs.txq[txq_id]->frozen_expiry_remainder = 0; trans_pcie->txqs.txq[txq_id]->frozen = false; From 8794e8501d0f2a08dc09f9f3d676c55138d2b6d0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 21 Sep 2026 23:41:19 +0300 Subject: [PATCH 009/104] wifi: iwlwifi: mvm: remove SRAM access through debugfs This is not really secure and we won't really need on old devices (driven by iwlmvm) anyway. Just remove the code. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233730.60f5274c7116.Ieec87672d84763b599e2d322525f68acff63e701@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 68 ------------------- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 - 2 files changed, 69 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index e6b9896dc4ac..b7315598d522 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -153,72 +153,6 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, return ret; } -static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm *mvm = file->private_data; - const struct fw_img *img; - unsigned int ofs, len; - size_t ret; - u8 *ptr; - - if (!iwl_mvm_firmware_running(mvm)) - return -EINVAL; - - /* default is to dump the entire data segment */ - img = &mvm->fw->img[mvm->fwrt.cur_fw_img]; - ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; - len = img->sec[IWL_UCODE_SECTION_DATA].len; - - if (mvm->dbgfs_sram_len) { - ofs = mvm->dbgfs_sram_offset; - len = mvm->dbgfs_sram_len; - } - - ptr = kzalloc(len, GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len); - - ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len); - - kfree(ptr); - - return ret; -} - -static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf, - size_t count, loff_t *ppos) -{ - const struct fw_img *img; - u32 offset, len; - u32 img_offset, img_len; - - if (!iwl_mvm_firmware_running(mvm)) - return -EINVAL; - - img = &mvm->fw->img[mvm->fwrt.cur_fw_img]; - img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset; - img_len = img->sec[IWL_UCODE_SECTION_DATA].len; - - if (sscanf(buf, "%x,%x", &offset, &len) == 2) { - if ((offset & 0x3) || (len & 0x3)) - return -EINVAL; - - if (offset + len > img_offset + img_len) - return -EINVAL; - - mvm->dbgfs_sram_offset = offset; - mvm->dbgfs_sram_len = len; - } else { - mvm->dbgfs_sram_offset = 0; - mvm->dbgfs_sram_len = 0; - } - - return count; -} - static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1916,7 +1850,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(start_ctdp, 8); MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8); MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); MVM_DEBUGFS_READ_FILE_OPS(nic_temp); MVM_DEBUGFS_READ_FILE_OPS(stations); @@ -2114,7 +2047,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) spin_lock_init(&mvm->drv_stats_lock); MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200); - MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400); MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index fb1fc9c42280..ae2ee8771f16 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1053,7 +1053,6 @@ struct iwl_mvm { */ struct dentry *debugfs_dir; #ifdef CONFIG_IWLWIFI_DEBUGFS - u32 dbgfs_sram_offset, dbgfs_sram_len; u32 dbgfs_prph_reg_addr; bool disable_power_off; bool disable_power_off_d3; From 5450e8b28cb4bae56dbf6027541668c2312608bf Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 21 Sep 2026 23:41:20 +0300 Subject: [PATCH 010/104] wifi: iwlwifi: dbg: validate dram_alloc_id from debug TLV iwl_dbg_tlv_alloc_region() did not validate reg->dram_alloc_id for IWL_FW_INI_REGION_DRAM_BUFFER regions, and the DRAM monitor dump consumers in fw/dbg.c used it directly to index the fw_mon_ini array. Check that dram_alloc_id is in range at TLV parse time, and add bounds checks in iwl_dump_ini_mon_dram_iter(), iwl_dump_ini_mon_dram_ranges() and iwl_dump_ini_mon_dram_get_size() before accessing the array. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233730.4c896fab0bb7.I3296a5523ce58df085ea0867694ea157c00945bd@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 9 +++++++++ drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index a314fabbf06d..8c8d15ac71ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -344,6 +344,9 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, struct iwl_dram_data *frag; u32 alloc_id = le32_to_cpu(reg->dram_alloc_id); + if (WARN_ON_ONCE(alloc_id >= ARRAY_SIZE(fwrt->trans->dbg.fw_mon_ini))) + return -EINVAL; + frag = &fwrt->trans->dbg.fw_mon_ini[alloc_id].frags[idx]; range->dram_base_addr = cpu_to_le64(frag->physical); @@ -957,6 +960,9 @@ iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt, u32 ranges = 0, alloc_id = le32_to_cpu(reg->dram_alloc_id); int i; + if (WARN_ON_ONCE(alloc_id >= ARRAY_SIZE(fwrt->trans->dbg.fw_mon_ini))) + return 0; + fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id]; for (i = 0; i < fw_mon->num_frags; i++) { @@ -1085,6 +1091,9 @@ iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, u32 size = 0, alloc_id = le32_to_cpu(reg->dram_alloc_id); int i; + if (WARN_ON_ONCE(alloc_id >= ARRAY_SIZE(fwrt->trans->dbg.fw_mon_ini))) + return 0; + fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id]; for (i = 0; i < fw_mon->num_frags; i++) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index bd2a9e4b4b5f..5576598cc6e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -229,6 +229,18 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans, return -EINVAL; } + if (type == IWL_FW_INI_REGION_DRAM_BUFFER) { + u32 alloc_id = le32_to_cpu(reg->dram_alloc_id); + + if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID || + alloc_id >= ARRAY_SIZE(trans->dbg.fw_mon_ini)) { + IWL_ERR(trans, + "WRT: Invalid dram_alloc_id %u for region %u\n", + alloc_id, id); + return -EINVAL; + } + } + if (type == IWL_FW_INI_REGION_INTERNAL_BUFFER) { trans->dbg.imr_data.sram_addr = le32_to_cpu(reg->internal_buffer.base_addr); From 1f602dd4678abd74e2fdc12d9fe966b5bd620ae8 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 21 Sep 2026 23:41:21 +0300 Subject: [PATCH 011/104] wifi: iwlwifi: Don't allocate a DRAM buffer with an invalid ID A DRAM buffer allocation shouldn't have an ID of 0. If a broken TLV contained such an id, this buffer will be allocated and a command will be sent to the FW. regardless of the FW asserting on that or not, this buffer will never be freed, since in the free path we do check for INVALID... Link: https://patch.msgid.link/20260921233731.ebd907861742.Ib74687a84e65d2e5295d338600283978a7018375@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 5576598cc6e7..4372a171172b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -619,7 +619,7 @@ static int iwl_dbg_tlv_alloc_fragments(struct iwl_fw_runtime *fwrt, u32 num_frags, remain_pages, frag_pages; int i; - if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID || + if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID || alloc_id >= IWL_FW_INI_ALLOCATION_NUM) return -EIO; @@ -702,7 +702,7 @@ static int iwl_dbg_tlv_apply_buffer(struct iwl_fw_runtime *fwrt, IWL_UCODE_TLV_CAPA_DBG_BUF_ALLOC_CMD_SUPP)) return 0; - if (alloc_id < IWL_FW_INI_ALLOCATION_INVALID || + if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID || alloc_id >= IWL_FW_INI_ALLOCATION_NUM) return -EIO; From 10348bcfae0798ef0735d764ae666e9ee71de938 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 21 Sep 2026 23:41:22 +0300 Subject: [PATCH 012/104] wifi: iwlwifi: mld: explicitly include mld.h in hcmd.h hcmd.h relies on mld.h. Make this dependency explicit. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233731.252cd5ae36b1.I5ea033fff1dcabd46e7d66f15c140dce2c5c9a1f@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/hcmd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/hcmd.h b/drivers/net/wireless/intel/iwlwifi/mld/hcmd.h index 19e1c9e509cf..761ef73dd9a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/hcmd.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/hcmd.h @@ -5,6 +5,8 @@ #ifndef __iwl_mld_hcmd_h__ #define __iwl_mld_hcmd_h__ +#include "mld.h" + static inline int iwl_mld_send_cmd(struct iwl_mld *mld, struct iwl_host_cmd *cmd) { /* No commands, including the d3 related commands, should be sent From d8867b883f6732be1b6e1b5916aeb4cc41b814a9 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 21 Sep 2026 23:41:23 +0300 Subject: [PATCH 013/104] wifi: iwlwifi: mld: explicitly include ieee80211-p2p.h in mac-cfg.h Make this dependency explicit. We use the ieee80211_p2p_noa_desc structure in the FW API file. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233731.13c9033a18cf.I2d3f3b8e2d4c7af0961726219974db2485e8312e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 01db6765855c..4a494563aa8c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -7,6 +7,8 @@ #ifndef __iwl_fw_api_mac_cfg_h__ #define __iwl_fw_api_mac_cfg_h__ +#include + #include "mac.h" #include "phy-ctxt.h" From db96b53de2e04c67d8f28ab1c6fc67d53d1ea9cf Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Mon, 21 Sep 2026 23:41:24 +0300 Subject: [PATCH 014/104] wifi: iwlwifi: fw: add Google-ASUS TAS approved DMI match Some Google devices with ASUS board vendor need to be included in the TAS approved DMI list so TAS policy is applied for this platform combination. Add a new GOOGLE-ASUS match entry using DMI_SYS_VENDOR=Google and DMI_BOARD_VENDOR=ASUS in the approved list. This change only extends platform coverage and does not alter existing matching behavior. Signed-off-by: Pagadala Yesu Anjaneyulu Assisted-by: GitHubCopilot:GPT-5.3-Codex Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233731.43ea7ba69e05.Ib2ec495e6dea3db1db783d43171505bd03d24cf6@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/regulatory.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 1d6d38ee55b4..3ab383b569bc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -167,6 +167,12 @@ static const struct dmi_system_id dmi_tas_approved_list[] = { DMI_MATCH(DMI_BOARD_VENDOR, "HP"), }, }, + { .ident = "GOOGLE-ASUS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "ASUS"), + }, + }, { .ident = "MSI", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), From 1fd7d929549476c6190b9a0d0a7057fd33a4277a Mon Sep 17 00:00:00 2001 From: Ayala Beker Date: Mon, 21 Sep 2026 23:41:25 +0300 Subject: [PATCH 015/104] wifi: iwlwifi: mld: remove NAN keys before removing internal stations FW expects all keys to be removed before removing a station. On NAN teardown, iwl_mld_stop_nan() removed the NAN internal stations while their IGTK/BIGTK were still in FW. mac80211 frees NAN keys only after drv_stop_nan() returns, so they are available while NAN is still up. Remove the NAN group keys before deleting the NAN internal stations. Signed-off-by: Ayala Beker Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260921233731.6d541e506ee4.Idaed08b15314b26abb4dc9f4a8a41e61a021597e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/nan.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c index 8853fcb2b4ec..10df33a238d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c @@ -5,6 +5,7 @@ #include "mld.h" #include "iface.h" +#include "key.h" #include "link.h" #include "mlo.h" #include "tlc.h" @@ -107,6 +108,20 @@ static void iwl_mld_nan_flush(struct iwl_mld *mld, struct ieee80211_vif *vif) iwl_mld_flush_link_sta_txqs(mld, sta->sta_id); } +static void iwl_mld_remove_nan_keys_iter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key, + void *data) +{ + struct iwl_mld *mld = data; + + if (sta || key->hw_key_idx == STA_KEY_IDX_INVALID) + return; + + iwl_mld_remove_key(mld, vif, NULL, key); +} + static void iwl_mld_nan_remove_stations(struct iwl_mld *mld, struct ieee80211_vif *vif) { @@ -296,6 +311,8 @@ int iwl_mld_stop_nan(struct ieee80211_hw *hw, if (ret) IWL_ERR(mld, "NAN: Failed to stop NAN. ret=%d\n", ret); + ieee80211_iter_keys(mld->hw, vif, iwl_mld_remove_nan_keys_iter, mld); + /* assume that higher layer guarantees that no additional frames are * added before calling this callback */ From 11ba2770d3bcac41ac174df9c6589a9593d6a906 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:48 +0300 Subject: [PATCH 016/104] wifi: iwlwifi: mld: support operational statistics notif ver 5 Add STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_5, which uses a new per-PHY struct (VER_3) that appends the NPCA channel load fields. Assisted-by: GitHubCopilot:claude-opus-4.8 Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260922144819.971d1a747698.I0792723d62dca7cf68056f13c8f733084ce6445f@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/stats.h | 60 +++++++++++++++++-- .../net/wireless/intel/iwlwifi/mld/notif.c | 3 +- .../net/wireless/intel/iwlwifi/mld/stats.c | 35 +++++++++-- 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h index 8d16782a129c..e3bf5d08c7e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h @@ -616,7 +616,7 @@ struct iwl_stats_ntfy_coex { } __packed; /* STATISTICS_FW_NTFY_COEX_TELEMETRY_API_S_VER_1 */ /** - * struct iwl_stats_ntfy_per_phy - per PHY statistics + * struct iwl_stats_ntfy_per_phy_v2 - per PHY statistics * @channel_load: channel load * @channel_load_by_us: device contribution to MCLM * @channel_load_not_by_us: other devices' contribution to MCLM @@ -632,7 +632,7 @@ struct iwl_stats_ntfy_coex { * @last_tx_ch_width_indx: last txed frame channel width index * @coex: coex related data */ -struct iwl_stats_ntfy_per_phy { +struct iwl_stats_ntfy_per_phy_v2 { __le32 channel_load; __le32 channel_load_by_us; __le32 channel_load_not_by_us; @@ -646,6 +646,43 @@ struct iwl_stats_ntfy_per_phy { struct iwl_stats_ntfy_coex coex; } __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_2 */ +/** + * struct iwl_stats_ntfy_per_phy - per PHY statistics + * @channel_load: channel load + * @channel_load_by_us: device contribution to MCLM + * @channel_load_not_by_us: other devices' contribution to MCLM + * @clt: CLT HW timer (TIM_CH_LOAD2) + * @act: active accumulator SW + * @elp: elapsed time accumulator SW + * @rx_detected_per_ch_width: number of deferred TX per channel width, + * 0 - 20, 1/2/3 - 40/80/160 + * @success_per_ch_width: number of frames that got ACK/BACK/CTS + * per channel BW. note, BACK counted as 1 + * @fail_per_ch_width: number of frames that didn't get ACK/BACK/CTS + * per channel BW. note BACK counted as 1 + * @last_tx_ch_width_indx: last txed frame channel width index + * @coex: coex related data + * @channel_load_npca_by_us: device NPCA contribution to MCLM + * @channel_load_npca_obss: the time FW identified for NPCA, not necessarily + * entered to NPCA state, but can be used as an indication for NPCA + * opportunities in the environment + */ +struct iwl_stats_ntfy_per_phy { + __le32 channel_load; + __le32 channel_load_by_us; + __le32 channel_load_not_by_us; + __le32 clt; + __le32 act; + __le32 elp; + __le32 rx_detected_per_ch_width[IWL_STATS_MAX_BW_INDEX]; + __le32 success_per_ch_width[IWL_STATS_MAX_BW_INDEX]; + __le32 fail_per_ch_width[IWL_STATS_MAX_BW_INDEX]; + __le32 last_tx_ch_width_indx; + struct iwl_stats_ntfy_coex coex; + __le32 channel_load_npca_by_us; + __le32 channel_load_npca_obss; +} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_3 */ + /* unknown channel load (due to not being active on channel) */ #define IWL_STATS_UNKNOWN_CHANNEL_LOAD 0xffffffff @@ -675,12 +712,27 @@ struct iwl_system_statistics_notif_oper_v3 { struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX]; } __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_3 */ +/** + * struct iwl_system_statistics_notif_oper_v4 - statistics notification + * + * @time_stamp: time when the notification is sent from firmware + * @per_link: per link statistics, &struct iwl_stats_ntfy_per_link + * @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy_v2 + * @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta + */ +struct iwl_system_statistics_notif_oper_v4 { + __le32 time_stamp; + struct iwl_stats_ntfy_per_link per_link[IWL_FW_MAX_LINKS]; + struct iwl_stats_ntfy_per_phy_v2 per_phy[IWL_STATS_MAX_PHY_OPERATIONAL]; + struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX]; +} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_4 */ + /** * struct iwl_system_statistics_notif_oper - statistics notification * * @time_stamp: time when the notification is sent from firmware * @per_link: per link statistics, &struct iwl_stats_ntfy_per_link - * @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy_v1 + * @per_phy: per phy statistics, &struct iwl_stats_ntfy_per_phy * @per_sta: per sta statistics, &struct iwl_stats_ntfy_per_sta */ struct iwl_system_statistics_notif_oper { @@ -688,7 +740,7 @@ struct iwl_system_statistics_notif_oper { struct iwl_stats_ntfy_per_link per_link[IWL_FW_MAX_LINKS]; struct iwl_stats_ntfy_per_phy per_phy[IWL_STATS_MAX_PHY_OPERATIONAL]; struct iwl_stats_ntfy_per_sta per_sta[IWL_STATION_COUNT_MAX]; -} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_4 */ +} __packed; /* STATISTICS_FW_NTFY_OPERATIONAL_API_S_VER_5 */ /** * struct iwl_system_statistics_part1_notif_oper - part1 stats notification diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index 90733bbaf733..d0b85adf7417 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -329,7 +329,8 @@ CMD_VERSIONS(datapath_monitor_notif, CMD_VER_ENTRY(1, iwl_datapath_monitor_notif)) CMD_VERSIONS(stats_oper_notif, CMD_VER_ENTRY(3, iwl_system_statistics_notif_oper_v3) - CMD_VER_ENTRY(4, iwl_system_statistics_notif_oper)) + CMD_VER_ENTRY(4, iwl_system_statistics_notif_oper_v4) + CMD_VER_ENTRY(5, iwl_system_statistics_notif_oper)) CMD_VERSIONS(stats_oper_part1_notif, CMD_VER_ENTRY(4, iwl_system_statistics_part1_notif_oper)) CMD_VERSIONS(bt_coex_notif, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/stats.c b/drivers/net/wireless/intel/iwlwifi/mld/stats.c index e7b283cbe199..3b6cd4f382f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/stats.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/stats.c @@ -43,12 +43,17 @@ iwl_mld_fill_stats_from_oper_notif(struct iwl_mld *mld, const struct iwl_stats_ntfy_per_sta *per_sta; struct ieee80211_link_sta *link_sta; struct iwl_mld_link_sta *mld_link_sta; + u8 notif_ver = iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP, + STATISTICS_OPER_NOTIF, 3); - if (iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP, - STATISTICS_OPER_NOTIF, 3) >= 4) { + if (notif_ver >= 5) { const struct iwl_system_statistics_notif_oper *notif = (void *)&pkt->data; per_sta = ¬if->per_sta[fw_sta_id]; + } else if (notif_ver == 4) { + const struct iwl_system_statistics_notif_oper_v4 *notif = + (void *)&pkt->data; + per_sta = ¬if->per_sta[fw_sta_id]; } else { const struct iwl_system_statistics_notif_oper_v3 *notif = (void *)&pkt->data; @@ -581,17 +586,39 @@ void iwl_mld_handle_stats_oper_notif(struct iwl_mld *mld, struct iwl_system_statistics_notif_oper *_notif __free(kfree) = NULL; const struct iwl_system_statistics_notif_oper *notif = (void *)&pkt->data; + u8 notif_ver = iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP, + STATISTICS_OPER_NOTIF, 3); BUILD_BUG_ON(ARRAY_SIZE(notif->per_sta) != IWL_STATION_COUNT_MAX); BUILD_BUG_ON(ARRAY_SIZE(notif->per_link) < ARRAY_SIZE(mld->fw_id_to_bss_conf)); - if (iwl_fw_lookup_notif_ver(mld->fw, STATISTICS_GROUP, - STATISTICS_OPER_NOTIF, 3) == 3) { + if (notif_ver == 3) { const struct iwl_system_statistics_notif_oper_v3 *stats = (void *)&pkt->data; _notif = kzalloc_obj(*_notif); + if (!_notif) + return; + + _notif->time_stamp = stats->time_stamp; + for (int i = 0; i < ARRAY_SIZE(_notif->per_link); i++) + _notif->per_link[i] = stats->per_link[i]; + + BUILD_BUG_ON(sizeof(_notif->per_phy[0]) < + sizeof(stats->per_phy[0])); + for (int i = 0; i < ARRAY_SIZE(_notif->per_phy); i++) + memcpy(&_notif->per_phy[i], &stats->per_phy[i], + sizeof(stats->per_phy[i])); + for (int i = 0; i < ARRAY_SIZE(_notif->per_sta); i++) + _notif->per_sta[i] = stats->per_sta[i]; + + notif = _notif; + } else if (notif_ver == 4) { + const struct iwl_system_statistics_notif_oper_v4 *stats = + (void *)&pkt->data; + _notif = kzalloc_obj(*_notif); + if (!_notif) return; From a552da3e4fd01672c4f72754f0d2ca21d943302b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:49 +0300 Subject: [PATCH 017/104] wifi: iwlwifi: poke the config space in case of command timeout There is a race between the PCI link power save flow and the notification flow from the firmware. The firmware prepares the notification in DRAM and then sends an MSI-X message to interrupt the CPU and let it know it can handle the notification. In case the PCI link goes L1.2 between the access to the DRAM to copy the notification and the MSI-X interrupt, the host won't be interrupted. Add a work-around to cope with this situation. If the command response was not received after 200ms, read the config space of the device just to wake up the link. This will allow the MSI-X interrupt to go through and the CPU will get the interrupt. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221501 Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.ef433f3da32b.I017c1c7a1dd3ac6f111d4640966968b82f37e291@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c index 060074c2871b..fae5beed2ecb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -2560,6 +2560,7 @@ void iwl_pcie_freeze_txq_timer(struct iwl_trans *trans, } } +#define HOST_COMPLETE_QUICK_TIMEOUT msecs_to_jiffies(200) #define HOST_COMPLETE_TIMEOUT (2 * HZ) static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans, @@ -2593,10 +2594,32 @@ static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans, return ret; } - ret = wait_event_timeout(trans_pcie->wait_command_queue, - !test_bit(STATUS_SYNC_HCMD_ACTIVE, - &trans->status), - HOST_COMPLETE_TIMEOUT); + /* + * There is a race between the PCI link power save flows and the + * notification / MSI-X interrupt in the firmware. + * If we didn't get a response after 200ms, poke the config space + * to force a wake-up of the PCI link. + */ + for (int i = 0; i < 2; i++) { + ret = wait_event_timeout(trans_pcie->wait_command_queue, + !test_bit(STATUS_SYNC_HCMD_ACTIVE, + &trans->status), + i == 0 ? HOST_COMPLETE_QUICK_TIMEOUT : + HOST_COMPLETE_TIMEOUT); + if (ret) + break; + + if (i == 0) { + u32 val; + + pci_read_config_dword(trans_pcie->pci_dev, + PCI_VENDOR_ID, &val); + IWL_DEBUG_HC(trans, + "write_ptr: %d: no response after %ums poking config space\n", + txq->write_ptr, + jiffies_to_msecs(HOST_COMPLETE_QUICK_TIMEOUT)); + } + } if (!ret) { IWL_ERR(trans, "Error sending %s: time out after %dms.\n", cmd_str, jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); From 4e7c4a59a5336a501ac31e32b5ca76dd1c44b9e2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:50 +0300 Subject: [PATCH 018/104] wifi: iwlwifi: pcie: remove monitor_data debugfs file The monitor_data debugfs file exposed the DRAM firmware monitor buffer to userspace. Remove it along with all the code and data that only existed to support it: the read/open/release handlers and the iwl_write_to_user_buf() helper, the cont_rec state tracking structure and iwl_fw_mon_dbgfs_state enum, the fw_mon_data field and its initialization, and the now-unused debugfs cleanup path (iwl_trans_pcie_debugfs_cleanup() and iwl_trans_debugfs_cleanup()). This relied on old firmware monitor format. Assisted-By: GitHubCopilot:Claude Opus 4.8 Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.9e5d30a9caa4.Idf62277c82970daf49d3d4d7b7a021595672eeed@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 - .../net/wireless/intel/iwlwifi/iwl-trans.c | 7 - .../net/wireless/intel/iwlwifi/iwl-trans.h | 4 - .../intel/iwlwifi/pcie/gen1_2/internal.h | 43 ----- .../intel/iwlwifi/pcie/gen1_2/trans.c | 153 ------------------ 5 files changed, 209 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 7f1515dfc5bf..ef9d50ee3704 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -2039,8 +2039,6 @@ void iwl_drv_stop(struct iwl_drv *drv) mutex_unlock(&iwlwifi_opmode_table_mtx); #ifdef CONFIG_IWLWIFI_DEBUGFS - iwl_trans_debugfs_cleanup(drv->trans); - debugfs_remove_recursive(drv->dbgfs_drv); #endif diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 73aae1125042..a1545e9d2cd8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -746,13 +746,6 @@ void iwl_trans_txq_set_shared_mode(struct iwl_trans *trans, } IWL_EXPORT_SYMBOL(iwl_trans_txq_set_shared_mode); -#ifdef CONFIG_IWLWIFI_DEBUGFS -void iwl_trans_debugfs_cleanup(struct iwl_trans *trans) -{ - iwl_trans_pcie_debugfs_cleanup(trans); -} -#endif - void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, int ptr) { if (WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index c581cc8f5bcb..dfad839dd2e6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -934,10 +934,6 @@ int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr, int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs, u32 *val); -#ifdef CONFIG_IWLWIFI_DEBUGFS -void iwl_trans_debugfs_cleanup(struct iwl_trans *trans); -#endif - #define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \ ({ \ if (__builtin_constant_p(bufsize)) \ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index d84c7c1efee1..f0e70b0fedfe 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -206,23 +206,6 @@ static inline u16 iwl_get_closed_rb_stts(struct iwl_trans *trans, } } -#ifdef CONFIG_IWLWIFI_DEBUGFS -/** - * enum iwl_fw_mon_dbgfs_state - the different states of the monitor_data - * debugfs file - * - * @IWL_FW_MON_DBGFS_STATE_CLOSED: the file is closed. - * @IWL_FW_MON_DBGFS_STATE_OPEN: the file is open. - * @IWL_FW_MON_DBGFS_STATE_DISABLED: the file is disabled, once this state is - * set the file can no longer be used. - */ -enum iwl_fw_mon_dbgfs_state { - IWL_FW_MON_DBGFS_STATE_CLOSED, - IWL_FW_MON_DBGFS_STATE_OPEN, - IWL_FW_MON_DBGFS_STATE_DISABLED, -}; -#endif - /** * enum iwl_shared_irq_flags - level of sharing for irq * @IWL_SHARED_IRQ_NON_RX: interrupt vector serves non rx causes. @@ -245,26 +228,6 @@ enum iwl_image_response_code { IWL_IMAGE_RESP_FAIL = 2, }; -#ifdef CONFIG_IWLWIFI_DEBUGFS -/** - * struct cont_rec: continuous recording data structure - * @prev_wr_ptr: the last address that was read in monitor_data - * debugfs file - * @prev_wrap_cnt: the wrap count that was used during the last read in - * monitor_data debugfs file - * @state: the state of monitor_data debugfs file as described - * in &iwl_fw_mon_dbgfs_state enum - * @mutex: locked while reading from monitor_data debugfs file - */ -struct cont_rec { - u32 prev_wr_ptr; - u32 prev_wrap_cnt; - u8 state; - /* Used to sync monitor_data debugfs file with driver unload flow */ - struct mutex mutex; -}; -#endif - enum iwl_pcie_fw_reset_state { FW_RESET_IDLE, FW_RESET_REQUESTED, @@ -451,7 +414,6 @@ struct iwl_pcie_txqs { * @rx_buf_bytes: RX buffer (RB) size in bytes * @reg_lock: protect hw register access * @mutex: to protect stop_device / start_fw / start_hw - * @fw_mon_data: fw continuous recording data * @cmd_hold_nic_awake: indicates NIC is held awake for APMG workaround * during commands in flight * @msix_entries: array of MSI-X entries @@ -577,10 +539,6 @@ struct iwl_trans_pcie { spinlock_t reg_lock; bool cmd_hold_nic_awake; -#ifdef CONFIG_IWLWIFI_DEBUGFS - struct cont_rec fw_mon_data; -#endif - struct msix_entry msix_entries[IWL_MAX_RX_HW_QUEUES]; bool msix_enabled; u8 shared_vec_mask; @@ -1167,7 +1125,6 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state, bool from_irq); #ifdef CONFIG_IWLWIFI_DEBUGFS void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); -void iwl_trans_pcie_debugfs_cleanup(struct iwl_trans *trans); #else static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { } #endif diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index 28b276c65952..71c4746c61a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -3073,137 +3073,6 @@ static ssize_t iwl_dbgfs_rfkill_write(struct file *file, return count; } -static int iwl_dbgfs_monitor_data_open(struct inode *inode, - struct file *file) -{ - struct iwl_trans *trans = inode->i_private; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - if (!trans->dbg.dest_tlv || - trans->dbg.dest_tlv->monitor_mode != EXTERNAL_MODE) { - IWL_ERR(trans, "Debug destination is not set to DRAM\n"); - return -ENOENT; - } - - if (trans_pcie->fw_mon_data.state != IWL_FW_MON_DBGFS_STATE_CLOSED) - return -EBUSY; - - trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_OPEN; - return simple_open(inode, file); -} - -static int iwl_dbgfs_monitor_data_release(struct inode *inode, - struct file *file) -{ - struct iwl_trans_pcie *trans_pcie = - IWL_TRANS_GET_PCIE_TRANS(inode->i_private); - - if (trans_pcie->fw_mon_data.state == IWL_FW_MON_DBGFS_STATE_OPEN) - trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED; - return 0; -} - -static bool iwl_write_to_user_buf(char __user *user_buf, ssize_t count, - void *buf, ssize_t *size, - ssize_t *bytes_copied) -{ - ssize_t buf_size_left = count - *bytes_copied; - - buf_size_left = buf_size_left - (buf_size_left % sizeof(u32)); - if (*size > buf_size_left) - *size = buf_size_left; - - *size -= copy_to_user(user_buf, buf, *size); - *bytes_copied += *size; - - if (buf_size_left == *size) - return true; - return false; -} - -static ssize_t iwl_dbgfs_monitor_data_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u8 *cpu_addr = (void *)trans->dbg.fw_mon.block, *curr_buf; - struct cont_rec *data = &trans_pcie->fw_mon_data; - u32 write_ptr_addr, wrap_cnt_addr, write_ptr, wrap_cnt; - ssize_t size, bytes_copied = 0; - bool b_full; - - if (trans->dbg.dest_tlv) { - write_ptr_addr = - le32_to_cpu(trans->dbg.dest_tlv->write_ptr_reg); - wrap_cnt_addr = le32_to_cpu(trans->dbg.dest_tlv->wrap_count); - } else { - write_ptr_addr = MON_BUFF_WRPTR; - wrap_cnt_addr = MON_BUFF_CYCLE_CNT; - } - - if (unlikely(!trans->dbg.rec_on)) - return 0; - - mutex_lock(&data->mutex); - if (data->state == - IWL_FW_MON_DBGFS_STATE_DISABLED) { - mutex_unlock(&data->mutex); - return 0; - } - - /* write_ptr position in bytes rather then DW */ - write_ptr = iwl_read_prph(trans, write_ptr_addr) * sizeof(u32); - wrap_cnt = iwl_read_prph(trans, wrap_cnt_addr); - - if (data->prev_wrap_cnt == wrap_cnt) { - size = write_ptr - data->prev_wr_ptr; - curr_buf = cpu_addr + data->prev_wr_ptr; - b_full = iwl_write_to_user_buf(user_buf, count, - curr_buf, &size, - &bytes_copied); - data->prev_wr_ptr += size; - - } else if (data->prev_wrap_cnt == wrap_cnt - 1 && - write_ptr < data->prev_wr_ptr) { - size = trans->dbg.fw_mon.size - data->prev_wr_ptr; - curr_buf = cpu_addr + data->prev_wr_ptr; - b_full = iwl_write_to_user_buf(user_buf, count, - curr_buf, &size, - &bytes_copied); - data->prev_wr_ptr += size; - - if (!b_full) { - size = write_ptr; - b_full = iwl_write_to_user_buf(user_buf, count, - cpu_addr, &size, - &bytes_copied); - data->prev_wr_ptr = size; - data->prev_wrap_cnt++; - } - } else { - if (data->prev_wrap_cnt == wrap_cnt - 1 && - write_ptr > data->prev_wr_ptr) - IWL_WARN(trans, - "write pointer passed previous write pointer, start copying from the beginning\n"); - else if (!unlikely(data->prev_wrap_cnt == 0 && - data->prev_wr_ptr == 0)) - IWL_WARN(trans, - "monitor data is out of sync, start copying from the beginning\n"); - - size = write_ptr; - b_full = iwl_write_to_user_buf(user_buf, count, - cpu_addr, &size, - &bytes_copied); - data->prev_wr_ptr = size; - data->prev_wrap_cnt = wrap_cnt; - } - - mutex_unlock(&data->mutex); - - return bytes_copied; -} - static ssize_t iwl_dbgfs_rf_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -3279,12 +3148,6 @@ static const struct file_operations iwl_dbgfs_tx_queue_ops = { .release = seq_release_private, }; -static const struct file_operations iwl_dbgfs_monitor_data_ops = { - .read = iwl_dbgfs_monitor_data_read, - .open = iwl_dbgfs_monitor_data_open, - .release = iwl_dbgfs_monitor_data_release, -}; - /* Create the debugfs files and directories */ void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { @@ -3296,20 +3159,9 @@ void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) DEBUGFS_ADD_FILE(csr, dir, 0200); DEBUGFS_ADD_FILE(fh_reg, dir, 0400); DEBUGFS_ADD_FILE(rfkill, dir, 0600); - DEBUGFS_ADD_FILE(monitor_data, dir, 0400); DEBUGFS_ADD_FILE(rf, dir, 0400); DEBUGFS_ADD_FILE(reset, dir, 0200); } - -void iwl_trans_pcie_debugfs_cleanup(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct cont_rec *data = &trans_pcie->fw_mon_data; - - mutex_lock(&data->mutex); - data->state = IWL_FW_MON_DBGFS_STATE_DISABLED; - mutex_unlock(&data->mutex); -} #endif /*CONFIG_IWLWIFI_DEBUGFS */ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_trans *trans, void *tfd) @@ -3974,11 +3826,6 @@ iwl_trans_pcie_alloc(struct pci_dev *pdev, } } -#ifdef CONFIG_IWLWIFI_DEBUGFS - trans_pcie->fw_mon_data.state = IWL_FW_MON_DBGFS_STATE_CLOSED; - mutex_init(&trans_pcie->fw_mon_data.mutex); -#endif - iwl_dbg_tlv_init(trans); return trans; From ded9ad2d04d2d23aaf88e99313fa2a5b961a57ef Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Tue, 22 Sep 2026 14:49:51 +0300 Subject: [PATCH 019/104] wifi: iwlwifi: mvm: validate NVM read response length Treat firmware-provided NVM response length as untrusted before copying data into the host buffer. Reject responses that are shorter than the fixed response header, where reported bytes exceed the requested chunk length, or where payload size does not contain the reported number of bytes. This prevents heap overwrite and RX payload over-read in malformed or malicious NVM_ACCESS responses. Signed-off-by: Pagadala Yesu Anjaneyulu Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.a9d384de40a0.Id6028e4753a2af5638bed0279bbf55842845df3b@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index f76e57399c1f..54006d5e15a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -86,6 +86,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, .data = { &nvm_access_cmd, }, }; int ret, bytes_read, offset_read; + unsigned int pkt_len; u8 *resp_data; cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); @@ -95,6 +96,12 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, return ret; pkt = cmd.resp_pkt; + pkt_len = iwl_rx_packet_payload_len(pkt); + if (pkt_len < sizeof(*nvm_resp)) { + IWL_ERR(mvm, "NVM ACCESS response too short: %u\n", pkt_len); + ret = -EINVAL; + goto exit; + } /* Extract NVM response */ nvm_resp = (void *)pkt->data; @@ -133,6 +140,14 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, goto exit; } + if (bytes_read > length || + pkt_len < struct_size(nvm_resp, data, bytes_read)) { + IWL_ERR(mvm, "NVM ACCESS response with invalid length %d\n", + bytes_read); + ret = -EINVAL; + goto exit; + } + /* Write data to NVM */ memcpy(data + offset, resp_data, bytes_read); ret = bytes_read; From fbd25abf05b1465bacbacf78066902fe028e63af Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:52 +0300 Subject: [PATCH 020/104] wifi: iwlwifi: mld: stop filling link fields unused by the firmware The htc_trig_based_pkt_ext, rand_alloc_ecwmin, rand_alloc_ecwmax and frame_time_rts_th fields of the LINK context config command are not used by the firmware. Stop filling them. Assisted-by: GithubCopilot:claude-opus-4.8 Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.887695af3d15.Ie0f0804a28ec4e1e8e41d0eb11615ed2a0f2823e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/link.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 96e06940b34c..65eddbd63016 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -361,13 +361,6 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link, flags |= LINK_FLG_MLPM; } - cmd.htc_trig_based_pkt_ext = link->htc_trig_based_pkt_ext; - - if (link->uora_exists) { - cmd.rand_alloc_ecwmin = link->uora_ocw_range & 0x7; - cmd.rand_alloc_ecwmax = (link->uora_ocw_range >> 3) & 0x7; - } - if (iwl_mld_fill_mu_edca(mld, mld_link, cmd.trig_based_txf)) flags |= LINK_FLG_MU_EDCA_CW; @@ -376,8 +369,6 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link, if (!link->he_bss_color.enabled) flags |= LINK_FLG_BSS_COLOR_DIS; - cmd.frame_time_rts_th = cpu_to_le16(link->frame_time_rts_th); - /* Block 26-tone RU OFDMA transmissions */ if (mld_link->he_ru_2mhz_block) flags |= LINK_FLG_RU_2MHZ_BLOCK; From e54f06b4d5cc95b0528dac76456b27387cbd669b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:53 +0300 Subject: [PATCH 021/104] wifi: iwlwifi: add multi-BSS/EMCCA max BSSID indicator to LINK cmd Add support for version 9 of the LINK context config command, which carries the max BSSID indicator N, where 2**N is the maximal number of BSSIDs the physical AP can support. The firmware uses this to mask N bits of the transmitter address for NPCA OBSS and inter/intra BSS NAV decisions. N=0 disables the feature. Assisted-by: GithubCopilot:claude-opus-4.8 Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.fafac4d1052d.I91be3bcfcd25d23b5c10c043d6cd639de4efa214@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/mac-cfg.h | 28 ++++++++++++++----- drivers/net/wireless/intel/iwlwifi/mld/link.c | 5 ++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 4a494563aa8c..9579e691cc87 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -665,7 +665,13 @@ struct iwl_npca_params { * @puncture_mask: puncture mask for EHT (removed in VER_3) * @frame_time_rts_th: HE duration RTS threshold, in units of 32us * @flags: a combination from &enum iwl_link_ctx_flags - * @flags_mask: what of %flags have changed. Also &enum iwl_link_ctx_flags + * @flags_mask: what of %flags have changed. Also &enum iwl_link_ctx_flags. + * Removed in _VER_6, reused as @reserved4 / @max_bssid_indicator + * in _VER_9. + * @reserved4: reserved + * @max_bssid_indicator: N where 2**N is the max number of BSSIDs the physical + * AP can support (multi-BSS or EMCCA set). 0 disables the feature. + * Since _VER_9. * Below fields are for multi-bssid: * @ref_bssid_addr: reference BSSID used by the AP * @reserved_for_ref_bssid_addr: reserved @@ -706,17 +712,23 @@ struct iwl_link_config_cmd { /* MAC_QOS_PARAM_API_S_VER_1 */ __le32 qos_flags; struct iwl_ac_qos ac[AC_NUM + 1]; - u8 htc_trig_based_pkt_ext; - u8 rand_alloc_ecwmin; - u8 rand_alloc_ecwmax; + u8 htc_trig_based_pkt_ext; /* removed in _VER_9 */ + u8 rand_alloc_ecwmin; /* removed in _VER_9 */ + u8 rand_alloc_ecwmax; /* removed in _VER_9 */ u8 ndp_fdbk_buff_th_exp; struct iwl_he_backoff_conf trig_based_txf[AC_NUM]; __le32 bi; __le32 dtim_interval; __le16 puncture_mask; /* removed in _VER_3 */ - __le16 frame_time_rts_th; + __le16 frame_time_rts_th; /* removed in _VER_9 */ __le32 flags; - __le32 flags_mask; /* removed in _VER_6 */ + union { + __le32 flags_mask; /* removed in _VER_6 */ + struct { + u8 reserved4[3]; + u8 max_bssid_indicator; /* since _VER_9 */ + }; + }; /* The below fields are for multi-bssid */ u8 ref_bssid_addr[6]; __le16 reserved_for_ref_bssid_addr; @@ -730,7 +742,9 @@ struct iwl_link_config_cmd { struct iwl_ac_qos prio_edca_params; /* since _VER_7 */ __le32 reserved3[4]; } __packed; /* LINK_CONTEXT_CONFIG_CMD_API_S_VER_1, _VER_2, _VER_3, _VER_4, - * _VER_5, _VER_6, _VER_7, _VER_8 */ + * _VER_5, _VER_6, _VER_7, _VER_8, + * _VER_9 + */ /* Currently FW supports link ids in the range 0-3 and can have * at most two active links for each vif. diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index 65eddbd63016..c7d50ba30b36 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -378,6 +378,11 @@ iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link, cmd.bssid_index = link->bssid_index; } + if (iwl_fw_lookup_cmd_ver(mld->fw, + WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD), + 0) >= 9) + cmd.max_bssid_indicator = link->bssid_indicator; + /* The only EHT parameter is puncturing, and starting from PHY cmd * version 6 - it is sent there. For older versions of the PHY cmd, * puncturing is not needed at all. From e9531438f55097aa9f5f37e495b799803afe71b1 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:54 +0300 Subject: [PATCH 022/104] wifi: iwlwifi: pcie: fix TSO page leak in iwl_pcie_prep_tso() iwl_pcie_prep_tso() obtains a TSO header page via iwl_pcie_get_page_hdr(), which stores the page in skb->cb and increments its internal reference count. If skb_to_sgvec() or dma_map_sgtable() then fails, the function returns NULL without calling iwl_pcie_free_tso_pages() or otherwise dropping the page reference and/or DMA mapping. Fix this page leak. Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.9f5a0b76e75e.Ic7d2303cb85a6de5158a713f57d4366c7b0d93b0@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c index fae5beed2ecb..26d1530cfa37 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -1902,18 +1902,27 @@ struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, /* Only map the data, not the header (it is copied to the TSO page) */ orig_nents = skb_to_sgvec(skb, sgt->sgl, offset, skb->len - offset); if (WARN_ON_ONCE(orig_nents <= 0)) - return NULL; + goto err_cleanup; sgt->orig_nents = orig_nents; /* And map the entire SKB */ if (dma_map_sgtable(trans->dev, sgt, DMA_TO_DEVICE, 0) < 0) - return NULL; + goto err_cleanup; /* Store non-zero (i.e. valid) offset for unmapping */ cmd_meta->sg_offset = (unsigned long) sgt & ~PAGE_MASK; return sgt; + +err_cleanup: + /* + * Since cmd_meta->sg_offset is not set yet, iwl_pcie_free_tso_pages + * will only free the page without unmapping the SG table (which hasn't + * been successfully mapped yet anyway). + */ + iwl_pcie_free_tso_pages(trans, skb, cmd_meta); + return NULL; } static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, From 7ca419fa4475443983e39bf62820c564f101a068 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 22 Sep 2026 14:49:55 +0300 Subject: [PATCH 023/104] wifi: iwlwifi: fix ctxt-info-v2 unwind UAF A failed ctxt-info-v2 allocation can free prph_scratch/prph_info without clearing the stored transport pointers. Clear stale DMA address/pointer fields during unwind. Also add an alloc-entry WARN_ON_ONCE/-EBUSY invariant to reject re-entry when ctxt/prph/iml state is already populated. Also, assign iml_len only the allocation. Assisted-by: GitHubCopilot:gpt-5.3-codex Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260922144819.be2c3cf96a4e.I207172d76a22c0302575f3383a044700f97a9980@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/pcie/ctxt-info-v2.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index 06be929a3ca5..1ea23d297713 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2025 Intel Corporation + * Copyright (C) 2018-2026 Intel Corporation */ #include #include "iwl-trans.h" @@ -112,6 +112,14 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans, int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE, trans->mac_cfg->base->min_txq_size); + if (WARN_ON_ONCE(trans_pcie->ctxt_info_v2 || trans_pcie->prph_info || + trans_pcie->prph_scratch || trans_pcie->iml || + trans_pcie->ctxt_info_dma_addr || + trans_pcie->prph_info_dma_addr || + trans_pcie->prph_scratch_dma_addr || + trans_pcie->iml_dma_addr || trans_pcie->iml_len)) + return -EBUSY; + switch (trans->conf.rx_buf_size) { case IWL_AMSDU_DEF: return -EINVAL; @@ -263,7 +271,6 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans, trans_pcie->prph_scratch = prph_scratch; /* Allocate IML */ - trans_pcie->iml_len = fw->iml_len; trans_pcie->iml = dma_alloc_coherent(trans->dev, fw->iml_len, &trans_pcie->iml_dma_addr, GFP_KERNEL); @@ -271,6 +278,7 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans, ret = -ENOMEM; goto err_free_ctxt_info; } + trans_pcie->iml_len = fw->iml_len; memcpy(trans_pcie->iml, fw->iml, fw->iml_len); @@ -280,16 +288,21 @@ int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans, dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_v2), trans_pcie->ctxt_info_v2, trans_pcie->ctxt_info_dma_addr); + trans_pcie->ctxt_info_dma_addr = 0; trans_pcie->ctxt_info_v2 = NULL; err_free_prph_info: dma_free_coherent(trans->dev, PAGE_SIZE, prph_info, trans_pcie->prph_info_dma_addr); + trans_pcie->prph_info_dma_addr = 0; + trans_pcie->prph_info = NULL; err_free_prph_scratch: dma_free_coherent(trans->dev, sizeof(*prph_scratch), prph_scratch, trans_pcie->prph_scratch_dma_addr); + trans_pcie->prph_scratch_dma_addr = 0; + trans_pcie->prph_scratch = NULL; return ret; } From a5d2d2e169634701756e2df6ab0fafd46fc622dd Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 22 Sep 2026 14:49:56 +0300 Subject: [PATCH 024/104] wifi: iwlwifi: mld: pass phy status explicitly for sniffer In some cases the frame status is changed to AID_NOT_FOR_US if no data is received. Pass the status explicitly so that the PHY data remains intact as that simplifies debugging. Signed-off-by: Benjamin Berg Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260922144819.86c1201ae2f6.I4b10b530325df711c7d229f1c487285a4dfcd294@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 02bdf6ccbcdc..82da642146a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -2281,7 +2281,7 @@ void iwl_mld_handle_rsc_notif(struct iwl_mld *mld, #endif /* CONFIG_PM_SLEEP */ static void iwl_mld_no_data_rx(struct iwl_mld *mld, - struct napi_struct *napi, + struct napi_struct *napi, u8 status, struct iwl_rx_phy_air_sniffer_ntfy *ntfy) { struct ieee80211_rx_status *rx_status; @@ -2306,7 +2306,7 @@ static void iwl_mld_no_data_rx(struct iwl_mld *mld, /* 0-length PSDU */ rx_status->flag |= RX_FLAG_NO_PSDU; - switch (ntfy->status) { + switch (status) { case IWL_SNIF_STAT_PLCP_RX_OK: /* we only get here with sounding PPDUs */ rx_status->zero_length_psdu_type = @@ -2365,11 +2365,9 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld, return; /* check if there's an old one to release as errored */ - if (mld->monitor.phy.valid && !mld->monitor.phy.used) { - /* didn't capture data, so override status */ - mld->monitor.phy.data.status = IWL_SNIF_STAT_AID_NOT_FOR_US; - iwl_mld_no_data_rx(mld, napi, &mld->monitor.phy.data); - } + if (mld->monitor.phy.valid && !mld->monitor.phy.used) + iwl_mld_no_data_rx(mld, napi, IWL_SNIF_STAT_AID_NOT_FOR_US, + &mld->monitor.phy.data); /* old data is no longer valid now */ mld->monitor.phy.valid = false; @@ -2406,7 +2404,7 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld, } if (ntfy->status != IWL_SNIF_STAT_PLCP_RX_OK || is_ndp) { - iwl_mld_no_data_rx(mld, napi, ntfy); + iwl_mld_no_data_rx(mld, napi, ntfy->status, ntfy); return; } From 7dd06e9263ce7fd96eff3d24514e8decafdd9de8 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Tue, 22 Sep 2026 14:49:57 +0300 Subject: [PATCH 025/104] wifi: iwlwifi: mld: Add support for scan iteration complete notification v3 Add support for scan iteration complete notification v3. This version is a superset of the previous version and adds information about the EBS corresponding with this scan iteration. Assisted-by: GitHub-Copilot:claude-opus-5 Signed-off-by: Ilan Peer Link: https://patch.msgid.link/20260922144819.daf57b66d8a9.I1ff60b070464ea5cc1f402293c2342157d29ea79@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/scan.h | 40 ++++++++++++++++++- .../net/wireless/intel/iwlwifi/mld/notif.c | 3 +- drivers/net/wireless/intel/iwlwifi/mld/scan.c | 15 ++++++- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index ee78371082b0..cb6217763bd1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -987,6 +987,8 @@ struct iwl_scan_probe_params_v4 { #define SCAN_MAX_NUM_CHANS_V3 67 #define SCAN_MAX_NUM_CHANS_V4 68 +#define SCAN_MAX_NUM_NOTIF_RESULTS 112 + /** * struct iwl_scan_channel_params_v4 - channel params * @flags: channel flags &enum iwl_scan_channel_flags @@ -1325,7 +1327,8 @@ struct iwl_scan_offload_match_info { */ /** - * struct iwl_umac_scan_iter_complete_notif - notifies end of scanning iteration + * struct iwl_umac_scan_iter_complete_notif_v2 - notifies end of scanning + * iteration * @uid: scan id, &enum iwl_umac_scan_uid_offsets * @scanned_channels: number of channels scanned and number of valid elements in * results array @@ -1336,7 +1339,7 @@ struct iwl_scan_offload_match_info { * in &struct iwl_scan_req_umac. * @results: array of scan results, length in @scanned_channels */ -struct iwl_umac_scan_iter_complete_notif { +struct iwl_umac_scan_iter_complete_notif_v2 { __le32 uid; u8 scanned_channels; u8 status; @@ -1346,6 +1349,39 @@ struct iwl_umac_scan_iter_complete_notif { struct iwl_scan_results_notif results[]; } __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_2 */ +/** + * struct iwl_umac_scan_iter_complete_notif - notifies end of scanning + * iteration + * @uid: scan id, &enum iwl_umac_scan_uid_offsets + * @scanned_channels: number of channels scanned and number of valid elements in + * results array + * @status: one of SCAN_COMP_STATUS_* + * @bt_status: BT on/off status + * @last_channel: last channel that was scanned + * @start_tsf: TSF timer in usecs of the scan start time for the mac specified + * in &struct iwl_scan_req_umac. + * @results: array of scan results, only @scanned_channels of them are valid + * @ebs_status: EBS completion status, &enum iwl_scan_ebs_status + * @reserved: reserved for alignment + * @ebs_channel_status: only valid when @ebs_status is %IWL_SCAN_EBS_SUCCESS. + * Bitmap of the 5 GHz channels on which EBS found energy: + * bit i in [0..27]: channel = 36 + 4 * i (channels 36 - 144) + * bit i in [28..35]: channel = 37 + 4 * i (channels 149 - 177) + * bit 36: channel 181 (reserved, not currently covered by EBS) + */ +struct iwl_umac_scan_iter_complete_notif { + __le32 uid; + u8 scanned_channels; + u8 status; + u8 bt_status; + u8 last_channel; + __le64 start_tsf; + struct iwl_scan_results_notif results[SCAN_MAX_NUM_NOTIF_RESULTS]; + u8 ebs_status; + u8 reserved[3]; + __le64 ebs_channel_status; +} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_3 */ + /** * struct iwl_umac_scan_channel_survey_notif - data for survey * @channel: the channel scanned diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index d0b85adf7417..570b0011fd9e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -292,7 +292,8 @@ CMD_VERSIONS(scan_start_notif, CMD_VERSIONS(scan_complete_notif, CMD_VER_ENTRY(1, iwl_umac_scan_complete)) CMD_VERSIONS(scan_iter_complete_notif, - CMD_VER_ENTRY(2, iwl_umac_scan_iter_complete_notif)) + CMD_VER_ENTRY(2, iwl_umac_scan_iter_complete_notif_v2) + CMD_VER_ENTRY(3, iwl_umac_scan_iter_complete_notif)) CMD_VERSIONS(channel_survey_notif, CMD_VER_ENTRY(1, iwl_umac_scan_channel_survey_notif)) CMD_VERSIONS(mfuart_notif, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index 0faca402bc14..e44b24904c19 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -1992,7 +1992,14 @@ void iwl_mld_int_mlo_scan(struct iwl_mld *mld, struct ieee80211_vif *vif) void iwl_mld_handle_scan_iter_complete_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt) { - struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data; + /* + * The v3 notification is a superset of v2, so the fields that are + * common to both versions can always be read from the v3 layout. + */ + const struct iwl_umac_scan_iter_complete_notif *notif = + (const void *)pkt->data; + u8 notif_ver = iwl_fw_lookup_notif_ver(mld->fw, LEGACY_GROUP, + SCAN_ITERATION_COMPLETE_UMAC, 2); u32 uid = __le32_to_cpu(notif->uid); if (IWL_FW_CHECK(mld, uid >= ARRAY_SIZE(mld->scan.uid_status), @@ -2006,6 +2013,12 @@ void iwl_mld_handle_scan_iter_complete_notif(struct iwl_mld *mld, "UMAC Scan iteration complete: status=0x%x scanned_channels=%d\n", notif->status, notif->scanned_channels); + if (notif_ver >= 3) + IWL_DEBUG_SCAN(mld, + "UMAC Scan iteration complete: EBS=%s, EBS channel status=0x%llx\n", + iwl_mld_scan_ebs_status_str(notif->ebs_status), + le64_to_cpu(notif->ebs_channel_status)); + if (mld->scan.pass_all_sched_res == SCHED_SCAN_PASS_ALL_STATE_FOUND) { IWL_DEBUG_SCAN(mld, "Pass all scheduled scan results found\n"); ieee80211_sched_scan_results(mld->hw); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 1dd27292af9b..93d5cab87f64 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -374,7 +374,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { struct iwl_umac_scan_complete), RX_HANDLER(SCAN_ITERATION_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_iter_complete_notif, RX_HANDLER_SYNC, - struct iwl_umac_scan_iter_complete_notif), + struct iwl_umac_scan_iter_complete_notif_v2), RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif_legacy, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 3831b3c27e0f..817c6dacfacc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -3282,7 +3282,7 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data; + struct iwl_umac_scan_iter_complete_notif_v2 *notif = (void *)pkt->data; mvm->scan_start = le64_to_cpu(notif->start_tsf); From c5dda1236138b637195dd053e045eda5179cf17d Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Tue, 22 Sep 2026 14:49:58 +0300 Subject: [PATCH 026/104] wifi: iwlwifi: mld: log error when missing a recovery buffer If we are recovering from FW error but we don't have a reocvery buffer (for example due to a driver bug), it means that the FW might not have all the data it needs and we can therefore have bugs after the recovery. Those bugs can be difficult to debug. Log a clear error in such case. Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260922144819.afd6c953d680.Ibbf29ef47b99a9037a56b3342883376e9f7749dd@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/fw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/fw.c b/drivers/net/wireless/intel/iwlwifi/mld/fw.c index 7b1fb84a641c..e5866d89176d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/fw.c @@ -396,8 +396,10 @@ void iwl_mld_send_recovery_cmd(struct iwl_mld *mld, u32 flags) if (flags & ERROR_RECOVERY_UPDATE_DB) { /* no buf was allocated upon NIC error */ - if (!mld->error_recovery_buf) + if (!mld->error_recovery_buf) { + IWL_ERR(mld, "Recovering without recovery buffer. Expect bugs\n"); return; + } cmd.data[1] = mld->error_recovery_buf; cmd.len[1] = error_log_size; From d9504926b43d721659db69c81eae534b09c63d32 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Tue, 22 Sep 2026 14:49:59 +0300 Subject: [PATCH 027/104] wifi: iwlwifi: mld: avoid leaking error recovery buffer If we allocated a recovery buffer, but didn't eventually send the recovery command (for example because we failed to load the FW), We won't free the buffer until the module is unloaded. If in between another FW error occured, we will override the pointer with a new allocated buffer without freeing the previous one. Fix this by freeing a previous buffer before allocating a new one. Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260922144819.36e637b8162a.Ida6e834d7f5d1e69d46c47e2e46db1e87a57ac71@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/mld.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 6e991fb99ff3..b7b1e3686336 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -621,6 +621,13 @@ static void iwl_mld_read_error_recovery_buffer(struct iwl_mld *mld) if (!src_size) return; + /* + * If we have a the recovery buffer from a previous (failing) recovery - + * free it here + */ + kfree(mld->error_recovery_buf); + mld->error_recovery_buf = NULL; + recovery_buf = kzalloc(src_size, GFP_ATOMIC); if (!recovery_buf) return; From 567d62c9eadb5e4d1a46e02819a807564d9cda11 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Tue, 22 Sep 2026 14:50:00 +0300 Subject: [PATCH 028/104] wifi: iwlwifi: fw: reject empty UEFI DSM query bitmap Some platforms expose a UEFI DSM table with the expected revision but with an empty QUERY bitmap, which means no DSM function is advertised as valid. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260922144819.fe9c61c887e1.I735e6a67f7fb4903ddeca84f0a2ca5cd062ba1df@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index bf6a31e6f149..7c290b526383 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -915,6 +915,12 @@ static int iwl_uefi_load_dsm_values(struct iwl_fw_runtime *fwrt) data->revision); goto out; } + if (!data->functions[DSM_FUNC_QUERY]) { + IWL_DEBUG_RADIO(fwrt, + "UEFI DSM query bitmap is empty, revision:%d\n", + data->revision); + goto out; + } fwrt->dsm_revision = data->revision; fwrt->dsm_source = BIOS_SOURCE_UEFI; From b6b944fe45cbb30e4a9ddbd30b0f86290f3db5da Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Tue, 22 Sep 2026 14:50:01 +0300 Subject: [PATCH 029/104] wifi: iwlwifi: fw: fix dbg dest TLV size check by version Validate FW_DBG_DEST TLV size before using it: Validate the version byte first, then check the length of each version of the payload. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260922144819.7eb8d71ff962.I81295f046c785da613331c6a619897ccf66007d6@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index ef9d50ee3704..0982e60842b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1103,10 +1103,17 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, const struct iwl_fw_dbg_dest_tlv_v1 *dest_v1 = NULL; u8 mon_mode; + if (tlv_len < sizeof(*pieces->dbg_dest_ver)) + goto invalid_tlv_len; + pieces->dbg_dest_ver = (const u8 *)tlv_data; if (*pieces->dbg_dest_ver == 1) { + if (tlv_len < sizeof(*dest)) + goto invalid_tlv_len; dest = (const void *)tlv_data; } else if (*pieces->dbg_dest_ver == 0) { + if (tlv_len < sizeof(*dest_v1)) + goto invalid_tlv_len; dest_v1 = (const void *)tlv_data; } else { IWL_ERR(drv, From d7193a172370772aba312c2189429128d03da9e7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 22 Sep 2026 14:50:02 +0300 Subject: [PATCH 030/104] wifi: iwlwifi: mld: separate HT/VHT/HE/EHT LDPC/STBC capabilities It appears that there are some APs that advertise STBC for HT and VHT, but don't actually support it for HE. Since the FW TLC will only use the mode we set (or fall back to legacy rates), we can set the bits according to the mode for STBC and LDPC. For EHT, there's no STBC at all, but LDPC support is more complex to determine. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20260922144819.cf235dddcbb3.I315c8089e341c6f7b2108276a32560595a8571fd@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 175 +++++++++++++------ 1 file changed, 121 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c index 1f5994f8be26..0e448b24a6a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c @@ -49,9 +49,60 @@ struct iwl_mld_tlc_sta_capa { const struct ieee80211_sta_uhr_cap *own_uhr_cap; }; +static bool iwl_mld_eht_ldpc_support(const struct ieee80211_sta_he_cap *he_cap, + const struct ieee80211_sta_eht_cap *eht_cap, + bool from_ap) +{ + u8 nss; + + /* higher bandwidth implies LDPC */ + if (he_cap->he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) + return true; + if (he_cap->he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) + return true; + if (he_cap->he_cap_elem.phy_cap_info[0] & + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G) + return true; + if (eht_cap->eht_cap_elem.phy_cap_info[0] & + IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ) + return true; + + /* MCS 10-14 imply LDPC support, we only check 10-13 here */ + if (!from_ap) { + const struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss; + + mcs_nss = &eht_cap->eht_mcs_nss_supp.only_20mhz; + + if (mcs_nss->rx_tx_mcs11_max_nss || + mcs_nss->rx_tx_mcs13_max_nss) + return true; + + nss = mcs_nss->rx_tx_mcs7_max_nss; + } else { + const struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; + + mcs_nss = &eht_cap->eht_mcs_nss_supp.bw._80; + + if (mcs_nss->rx_tx_mcs11_max_nss || + mcs_nss->rx_tx_mcs13_max_nss) + return true; + + nss = mcs_nss->rx_tx_mcs9_max_nss; + } + + /* NSS > 4 implies LDPC support */ + return u8_get_bits(nss, IEEE80211_EHT_MCS_NSS_RX) > 4 || + u8_get_bits(nss, IEEE80211_EHT_MCS_NSS_TX) > 4; +} + static __le16 iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld, - struct iwl_mld_tlc_sta_capa *capa) + struct ieee80211_vif *vif, + struct iwl_mld_tlc_sta_capa *capa, + enum iwl_tlc_mng_cfg_mode mode, + enum iwl_tlc_mng_cfg_cw max_bw) { const struct ieee80211_sta_ht_cap *ht_cap = capa->ht_cap; const struct ieee80211_sta_vht_cap *vht_cap = capa->vht_cap; @@ -61,64 +112,79 @@ iwl_mld_get_tlc_cmd_flags(struct iwl_mld *mld, const struct ieee80211_sta_he_cap *own_he_cap = capa->own_he_cap; const struct ieee80211_sta_eht_cap *own_eht_cap = capa->own_eht_cap; const struct ieee80211_sta_uhr_cap *own_uhr_cap = capa->own_uhr_cap; - bool has_vht = vht_cap && vht_cap->vht_supported; + bool stbc_possible = mld->cfg->ht_params.stbc && + hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1; u16 flags = 0; - /* STBC flags */ - if (mld->cfg->ht_params.stbc && - (hweight8(iwl_mld_get_valid_tx_ant(mld)) > 1)) { - if (he_cap && he_cap->has_he && + switch (mode) { + case IWL_TLC_MNG_MODE_NON_HT: + break; + case IWL_TLC_MNG_MODE_HT: + if (WARN_ON(!ht_cap || !ht_cap->ht_supported)) + return 0; + if (stbc_possible && + ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) + flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; + if (mld->cfg->ht_params.ldpc && + ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) + flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + break; + case IWL_TLC_MNG_MODE_VHT: + if (WARN_ON(!vht_cap || !vht_cap->vht_supported)) + return 0; + if (stbc_possible && + vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) + flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; + if (mld->cfg->ht_params.ldpc && + vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC) + flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + break; + case IWL_TLC_MNG_MODE_HE: + if (WARN_ON(!he_cap || !he_cap->has_he || !own_he_cap)) + return 0; + if (stbc_possible && he_cap->he_cap_elem.phy_cap_info[2] & - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ) - flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; - else if (vht_cap && - vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) - flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; - else if (ht_cap && ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) + IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ && + (max_bw <= IWL_TLC_MNG_CH_WIDTH_80MHZ || + he_cap->he_cap_elem.phy_cap_info[7] & + IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)) flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK; + if (he_cap->he_cap_elem.phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD && + own_he_cap->he_cap_elem.phy_cap_info[1] & + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD) + flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + if (he_cap->he_cap_elem.phy_cap_info[3] & + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK && + own_he_cap->he_cap_elem.phy_cap_info[3] & + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK) + flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK; + break; + case IWL_TLC_MNG_MODE_UHR: + if (WARN_ON(!uhr_cap || !uhr_cap->has_uhr || !own_uhr_cap)) + return 0; + if (uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX) && + own_uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_TX)) + flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK | + IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK; + /* uses most config from EHT */ + fallthrough; + case IWL_TLC_MNG_MODE_EHT: + if (WARN_ON(!own_he_cap || !he_cap || !he_cap->has_he || + !own_eht_cap || !eht_cap || !eht_cap->has_eht)) + return 0; + if (own_eht_cap->eht_cap_elem.phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF && + eht_cap->eht_cap_elem.phy_cap_info[5] & + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) + flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK; + /* no STBC in EHT */ + if (iwl_mld_eht_ldpc_support(he_cap, eht_cap, + vif->type == NL80211_IFTYPE_STATION)) + flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; + break; } - /* LDPC */ - if (mld->cfg->ht_params.ldpc && - ((ht_cap && ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) || - (has_vht && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)))) - flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; - - if (he_cap && he_cap->has_he && - (he_cap->he_cap_elem.phy_cap_info[1] & - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) - flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; - - if (own_he_cap && - !(own_he_cap->he_cap_elem.phy_cap_info[1] & - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) - flags &= ~IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK; - - /* DCM */ - if (he_cap && he_cap->has_he && - (he_cap->he_cap_elem.phy_cap_info[3] & - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK && - own_he_cap && - own_he_cap->he_cap_elem.phy_cap_info[3] & - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK)) - flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK; - - /* Extra EHT LTF */ - if (own_eht_cap && - own_eht_cap->eht_cap_elem.phy_cap_info[5] & - IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF && - eht_cap && eht_cap->has_eht && - eht_cap->eht_cap_elem.phy_cap_info[5] & - IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF) { - flags |= IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK; - } - - if (uhr_cap && uhr_cap->has_uhr && own_uhr_cap && - uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX) && - own_uhr_cap->phy.cap & cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_TX)) - flags |= IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK | - IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK; - return cpu_to_le16(flags); } @@ -478,7 +544,6 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ? iwl_mld_fw_bw_from_sta_bw(capa->bandwidth) : IWL_TLC_MNG_CH_WIDTH_20MHZ, - .flags = iwl_mld_get_tlc_cmd_flags(mld, capa), .chains = iwl_mld_get_fw_chains(mld), .sgi_ch_width_supp = iwl_mld_get_fw_sgi(capa), .max_mpdu_len = cpu_to_le16(capa->max_amsdu_len), @@ -493,6 +558,8 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, cmd.phy_id = cpu_to_le32(phy_id); iwl_mld_fill_supp_rates(mld, vif, capa, &cmd); + cmd.flags = iwl_mld_get_tlc_cmd_flags(mld, vif, capa, cmd.mode, + cmd.max_ch_width); if (cmd_ver == 6) { cmd_ptr = &cmd; From b154c5bdb728491765f7b6cb24a3f989b962865a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 23 Sep 2026 16:04:44 +0300 Subject: [PATCH 031/104] wifi: iwlwifi: mvm: remove indirection_tbl debugfs entry The RSS indirection table debugfs knob is not used, and its pattern repetition logic triggered a static analysis out-of-bounds report on the trailing copy that forms a one-past-the-end pointer. Rather than reworking unused code, drop the entry entirely. Assisted-by: GitHub-Copilot:claude-opus-5 Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260923160318.bc19cf5a20b9.I04cbf6a929070775a7e0cb04c7330421e6777f4e@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 50 ------------------- 1 file changed, 50 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index b7315598d522..99fb149b8543 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1145,53 +1145,6 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, return count; } -static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, - char *buf, size_t count, - loff_t *ppos) -{ - struct iwl_rss_config_cmd cmd = { - .flags = cpu_to_le32(IWL_RSS_ENABLE), - .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | - IWL_RSS_HASH_TYPE_IPV4_UDP | - IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | - IWL_RSS_HASH_TYPE_IPV6_TCP | - IWL_RSS_HASH_TYPE_IPV6_UDP | - IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, - }; - int ret, i, num_repeats, nbytes = count / 2; - - ret = hex2bin(cmd.indirection_table, buf, nbytes); - if (ret) - return ret; - - /* - * The input is the redirection table, partial or full. - * Repeat the pattern if needed. - * For example, input of 01020F will be repeated 42 times, - * indirecting RSS hash results to queues 1, 2, 15 (skipping - * queues 3 - 14). - */ - num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes; - for (i = 1; i < num_repeats; i++) - memcpy(&cmd.indirection_table[i * nbytes], - cmd.indirection_table, nbytes); - /* handle cut in the middle pattern for the last places */ - memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, - ARRAY_SIZE(cmd.indirection_table) % nbytes); - - netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key)); - - mutex_lock(&mvm->mutex); - if (iwl_mvm_firmware_running(mvm)) - ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, - sizeof(cmd), &cmd); - else - ret = 0; - mutex_unlock(&mvm->mutex); - - return ret ?: count; -} - static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) @@ -1866,8 +1819,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_clear, 64); MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64); -MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, - (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512); MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512); MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512); @@ -2066,7 +2017,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) MVM_DEBUGFS_ADD_FILE(fw_dbg_clear, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); - MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200); From e8fa92f169ff569e323be5073c4358e5bc91ddd4 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Wed, 23 Sep 2026 16:04:45 +0300 Subject: [PATCH 032/104] wifi: iwlwifi: mvm: debugfs: validate TAS response and loop bounds iwl_dbgfs_tas_get_status_read() trusted the FW response layout and iterated with rsp->in_dual_radio + 1 without capping to the tas_status_mac array size. A malformed or inconsistent response could lead to out-of-bounds access while printing TAS status. Validate the GET_TAS_STATUS payload length before dereferencing rsp, free the response on early allocation failure, and cap both TAS loops with array size. This keeps the existing behavior for valid responses and hardens the debugfs path against invalid firmware data. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260923160318.f03b511b938e.Ib5069ecf15340506498a28d965c49387cab609b1@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 99fb149b8543..4db0f29dd21a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -525,16 +525,24 @@ static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file, if (ret < 0) return ret; + if (iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp)) { + iwl_free_resp(&hcmd); + return -EIO; + } + buff = kzalloc(bufsz, GFP_KERNEL); - if (!buff) + if (!buff) { + iwl_free_resp(&hcmd); return -ENOMEM; + } pos = buff; endpos = pos + bufsz; rsp = (void *)hcmd.resp_pkt->data; pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n"); - for (i = 0; i < rsp->in_dual_radio + 1; i++) { + for (i = 0; i < min_t(int, rsp->in_dual_radio + 1, + ARRAY_SIZE(rsp->tas_status_mac)); i++) { if (rsp->tas_status_mac[i].dynamic_status & BIT(TAS_DYNA_ACTIVE)) { pos += scnprintf(pos, endpos - pos, "\tON for "); @@ -589,7 +597,8 @@ static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file, "\tDo TAS Support Dual Radio?: %s\n", rsp->in_dual_radio ? "TRUE" : "FALSE"); - for (i = 0; i < rsp->in_dual_radio + 1; i++) { + for (i = 0; i < min_t(int, rsp->in_dual_radio + 1, + ARRAY_SIZE(rsp->tas_status_mac)); i++) { if (rsp->tas_status_mac[i].static_status == 0) { pos += scnprintf(pos, endpos - pos, "Static status: disabled\n"); From cfd58870fe51b3ae441af40b438604486792b67c Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Wed, 23 Sep 2026 16:04:46 +0300 Subject: [PATCH 033/104] wifi: iwlwifi: mvm: fix LARI_CONFIG_EXTENSION version check The version guard used `< 1` instead of `!= 1`. With `< 1` the command would be sent for any firmware version >= 1, including future versions that may have a different structure, which could trigger a firmware assert due to a size/format mismatch. Fix the check to `!= 1` so the command is only sent when the firmware supports exactly version 1. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260923160318.27693f88a8d7.Id6a4b91938cd7758c2be3b98379f1057e574cdad@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 43a7230f1ab4..06f3b065914b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1526,7 +1526,7 @@ static void iwl_mvm_send_lari_cfg_extension(struct iwl_mvm *mvm) u32 value; int ret; - if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) < 1) + if (iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 0) != 1) return; ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG, &value); From e1f10daf7cbdb08606cbf186e0d641ad7bad6c5f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Sep 2026 16:04:47 +0300 Subject: [PATCH 034/104] wifi: iwlwifi: advertise 2xLDPC RX support for UHR In UHR, currently supported devices have 2x LDPC support. Enable the bit. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20260923160318.9771e88dbc3b.I22693891ed85fd0449ae17106e2502ec4ee2e086@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 863d5e358152..6bb27d7f1166 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -710,7 +710,8 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { .has_uhr = true, /* Note: asymmetry is fixed later */ .phy.cap = cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX | - IEEE80211_UHR_PHY_CAP_ELR_TX), + IEEE80211_UHR_PHY_CAP_ELR_TX | + IEEE80211_UHR_PHY_CAP_2XLDPC_RX), .mac.mac_cap = { [0] = IEEE80211_UHR_MAC_CAP0_NPCA_SUPP | IEEE80211_UHR_MAC_CAP0_DPS_SUPP, @@ -820,7 +821,8 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { .has_uhr = true, /* Note: asymmetry is fixed later */ .phy.cap = cpu_to_le32(IEEE80211_UHR_PHY_CAP_ELR_RX | - IEEE80211_UHR_PHY_CAP_ELR_TX), + IEEE80211_UHR_PHY_CAP_ELR_TX | + IEEE80211_UHR_PHY_CAP_2XLDPC_RX), }, }, }; From 5e45403e60e17c971c97ce6f432960852c3d5f1a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Sep 2026 16:04:48 +0300 Subject: [PATCH 035/104] wifi: iwlwifi: mld: fix some UHR ELR bits These were wrong in the driver based on the hardware definitions, fix them. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20260923160318.3fa552b3d795.I8098855c931e1f9df16951e2d527bb079eca0549@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/rx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 699343cf0279..a8f1edf19bbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -1347,7 +1347,7 @@ struct iwl_uhr_elr_sigs { #define OFDM_RX_VECTOR_UHR_ELR_PPDU_TYPE 0x00000003 #define OFDM_RX_VECTOR_UHR_ELR_USIG_STA_ID 0x00001ffc #define OFDM_RX_VECTOR_UHR_ELR_VALIDATE 0x0000e000 -#define OFDM_RX_VECTOR_UHR_ELR_CRC_OK 0x00010000 +#define OFDM_RX_VECTOR_UHR_ELR_CRC_OK 0x40000000 __le32 usig_a2_uhr_elr; #define OFDM_RX_VECTOR_UHR_ELR_VER_ID 0x00000007 #define OFDM_RX_VECTOR_UHR_ELR_UPLINK_FLAG 0x00000008 @@ -1363,7 +1363,7 @@ struct iwl_uhr_elr_sigs { #define OFDM_RX_VECTOR_UHR_ELR_SIG_ID_INDX 0x00000e00 #define OFDM_RX_VECTOR_UHR_ELR_STA_RU 0x000ff000 #define OFDM_RX_VECTOR_UHR_ELR_STA_RU_PS160 0x00100000 -#define OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK 0x00200000 +#define OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK 0x40000000 __le32 uhr_sig_elr2; }; From ff5bddd1bcf6b3f3a60e8a415d3ab97a82dbd3f1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Sep 2026 16:04:49 +0300 Subject: [PATCH 036/104] wifi: iwlwifi: mld: correct EHT U-SIG-1 B20:25 report This needs to be combined from two places, fix that. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20260923160318.e65cdac4424f.I23b05c26fc788081ad8aa2673e104e2215697416@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 82da642146a7..5f18aa551af5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -818,7 +818,8 @@ static void iwl_mld_decode_eht_usig_tb(struct iwl_mld_rx_phy_data *phy_data, __le32 usig_a2 = phy_data->ntfy->sigs.eht_tb.usig_a2_eht; IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1, - OFDM_RX_FRAME_EHT_USIG1_DISREGARD, + OFDM_RX_FRAME_EHT_USIG1_DISREGARD | + OFDM_RX_FRAME_EHT_USIG1_VALIDATE, IEEE80211_RADIOTAP_EHT_USIG1_TB_B20_B25_DISREGARD); IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, OFDM_RX_FRAME_EHT_PPDU_TYPE, From 74f2ced8acb48cea939a13732e472a2e344ab7f9 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 23 Sep 2026 16:04:50 +0300 Subject: [PATCH 037/104] wifi: iwlwifi: support net detect match info version 3 Since API 77, firmware reports scan offload profile matches using SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_3, which has more channels (16 byte instead of 7). Somehow we missed this change, and the driver only handles the 5- and 7-byte layouts, so on such firmware it misparsed the match (reading band as energy) and could not recover matches beyond the first 56 channels. Add the version 3 match structure and select it based on the SCAN_OFFLOAD_PROFILES_QUERY_CMD notification version (in MVM, in MLD, this is the only version supported). In MVM, while walking the matched-channels bitmap, bound the channel index with IWL_FW_CHECK so firmware that sets a bit beyond n_nd_channels can no longer trigger an out-of-bounds read of nd_channels[]. Reviewed-by: Ilan Peer Link: https://patch.msgid.link/20260923160318.07738ca44b54.I58162891250af9f46220fd01db667460e6dd621b@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/scan.h | 28 +++++- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 89 ++++++++++++++----- 2 files changed, 93 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index cb6217763bd1..8994a7b840ef 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -1234,7 +1234,8 @@ struct iwl_umac_scan_complete { } __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */ #define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 5 -#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 7 +#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V2 7 +#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 16 /** * struct iwl_scan_offload_profile_match_v1 - match information @@ -1280,11 +1281,31 @@ struct iwl_scan_offload_profiles_query_v1 { struct iwl_scan_offload_profile_match_v1 matches[]; } __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */ +/** + * struct iwl_scan_offload_profile_match_v2 - match information + * @bssid: matched bssid + * @reserved: reserved + * @channel: channel where the match occurred + * @energy: energy + * @matching_feature: feature matches + * @matching_channels: bitmap of channels that matched, referencing + * the channels passed in the scan offload request. + */ +struct iwl_scan_offload_profile_match_v2 { + u8 bssid[ETH_ALEN]; + __le16 reserved; + u8 channel; + u8 energy; + u8 matching_feature; + u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V2]; +} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */ + /** * struct iwl_scan_offload_profile_match - match information * @bssid: matched bssid * @reserved: reserved * @channel: channel where the match occurred + * @band: band where the match occurred * @energy: energy * @matching_feature: feature matches * @matching_channels: bitmap of channels that matched, referencing @@ -1294,10 +1315,11 @@ struct iwl_scan_offload_profile_match { u8 bssid[ETH_ALEN]; __le16 reserved; u8 channel; + u8 band; u8 energy; u8 matching_feature; u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN]; -} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_2 */ +} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_3 */ /** * struct iwl_scan_offload_match_info - match results information @@ -1322,7 +1344,7 @@ struct iwl_scan_offload_match_info { u8 self_recovery; __le16 reserved; struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES_V2]; -} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_3 and +} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_5 and * SCAN_OFFLOAD_MATCH_INFO_NOTIFICATION_S_VER_1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index bd52f2ebd3ba..2abc4bc3eb34 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2440,6 +2440,12 @@ struct iwl_mvm_nd_results { u8 matches[ND_QUERY_BUF_LEN]; }; +static bool iwl_mvm_nd_match_info_v3(struct iwl_mvm *mvm) +{ + return iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, + SCAN_OFFLOAD_PROFILES_QUERY_CMD, 0) >= 4; +} + static int iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, struct iwl_mvm_nd_results *results) @@ -2459,12 +2465,17 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm, return ret; } - if (fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + if (iwl_mvm_nd_match_info_v3(mvm)) { matches_len = sizeof(struct iwl_scan_offload_profile_match) * max_profiles; query_len = offsetof(struct iwl_scan_offload_match_info, matches) + matches_len; + } else if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + matches_len = sizeof(struct iwl_scan_offload_profile_match_v2) * + max_profiles; + query_len = offsetof(struct iwl_scan_offload_match_info, + matches) + matches_len; } else { matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) * max_profiles; @@ -2499,13 +2510,19 @@ static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm, { int n_chans = 0, i; - if (fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + if (iwl_mvm_nd_match_info_v3(mvm)) { struct iwl_scan_offload_profile_match *matches = (void *)results->matches; for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++) n_chans += hweight8(matches[idx].matching_channels[i]); + } else if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + struct iwl_scan_offload_profile_match_v2 *matches = + (void *)results->matches; + + for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V2; i++) + n_chans += hweight8(matches[idx].matching_channels[i]); } else { struct iwl_scan_offload_profile_match_v1 *matches = (void *)results->matches; @@ -2517,34 +2534,58 @@ static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm, return n_chans; } +static void iwl_mvm_set_matching_freqs(struct iwl_mvm *mvm, + const u8 *matching_channels, + size_t num_bytes, + struct cfg80211_wowlan_nd_match *match) +{ + int n_channels = 0; + + for (int i = 0; i < num_bytes * 8; i++) { + if (!(matching_channels[i / 8] & BIT(i % 8))) + continue; + if (IWL_FW_CHECK(mvm, i >= mvm->n_nd_channels, + "FW matched channel bit %d beyond n_nd_channels %d\n", + i, mvm->n_nd_channels)) + break; + match->channels[n_channels++] = + mvm->nd_channels[i]->center_freq; + } + /* We may have ended up with fewer channels than we allocated. */ + match->n_channels = n_channels; +} + static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm, struct iwl_mvm_nd_results *results, struct cfg80211_wowlan_nd_match *match, int idx) { - int i; - int n_channels = 0; - - if (fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + if (iwl_mvm_nd_match_info_v3(mvm)) { struct iwl_scan_offload_profile_match *matches = (void *)results->matches; - for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++) - if (matches[idx].matching_channels[i / 8] & (BIT(i % 8))) - match->channels[n_channels++] = - mvm->nd_channels[i]->center_freq; + iwl_mvm_set_matching_freqs(mvm, + matches[idx].matching_channels, + sizeof(matches[idx].matching_channels), + match); + } else if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) { + struct iwl_scan_offload_profile_match_v2 *matches = + (void *)results->matches; + + iwl_mvm_set_matching_freqs(mvm, + matches[idx].matching_channels, + sizeof(matches[idx].matching_channels), + match); } else { struct iwl_scan_offload_profile_match_v1 *matches = (void *)results->matches; - for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++) - if (matches[idx].matching_channels[i / 8] & (BIT(i % 8))) - match->channels[n_channels++] = - mvm->nd_channels[i]->center_freq; + iwl_mvm_set_matching_freqs(mvm, + matches[idx].matching_channels, + sizeof(matches[idx].matching_channels), + match); } - /* We may have ended up with fewer channels than we allocated. */ - match->n_channels = n_channels; } /** @@ -2817,8 +2858,14 @@ static void iwl_mvm_nd_match_info_handler(struct iwl_mvm *mvm, struct iwl_wowlan_status_data *status = d3_data->status; struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm); struct iwl_mvm_nd_results *results = d3_data->nd_results; - size_t i, matches_len = sizeof(struct iwl_scan_offload_profile_match) * - iwl_umac_scan_get_max_profiles(mvm->fw); + size_t i, matches_len; + + if (iwl_mvm_nd_match_info_v3(mvm)) + matches_len = sizeof(struct iwl_scan_offload_profile_match) * + iwl_umac_scan_get_max_profiles(mvm->fw); + else + matches_len = sizeof(struct iwl_scan_offload_profile_match_v2) * + iwl_umac_scan_get_max_profiles(mvm->fw); if (IS_ERR_OR_NULL(vif)) return; From 6ec296ca4dc89fea5fde5fd3f1dc33536e3bdf30 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 23 Sep 2026 16:04:51 +0300 Subject: [PATCH 038/104] wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 108 Start supporting Core 108 FW on these devices. The BZ/FM combination is frozen on Core107 (while each of BZ, FM is not yet frozen and is still supported in other combinations). Indicate this in the relevant FW file mames, for modinfo. While at it, remove names that are no longer needed. Link: https://patch.msgid.link/20260923160318.61c292103e38.I0e2918e21f8a20d200d371c1861ed2c5deac829d@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 8 +------- drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c | 4 ++++ drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 1099d8cfe6aa..3cc3ffd0aa1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -10,14 +10,11 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_BZ_UCODE_CORE_MAX 107 +#define IWL_BZ_UCODE_CORE_MAX 108 /* Lowest firmware core release supported */ #define IWL_BZ_UCODE_CORE_MIN 102 -#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0" -#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0" -#define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0" #define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0" #define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0" @@ -92,8 +89,5 @@ const struct iwl_mac_cfg iwl_gl_mac_cfg = { .low_latency_xtal = true, }; -IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); -IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX); -IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index a89a2c75687f..f6dd1f9733fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -9,7 +9,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_DR_UCODE_CORE_MAX 107 +#define IWL_DR_UCODE_CORE_MAX 108 /* Lowest firmware core release supported */ #define IWL_DR_UCODE_CORE_MIN 102 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c index 35b1618f3474..a7770cd61213 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c @@ -5,6 +5,8 @@ */ #include "iwl-config.h" +#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0" + #define IWL_DEVICE_FM \ .ht_params = { \ .stbc = true, \ @@ -48,3 +50,5 @@ const char iwl_be201_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz"; const char iwl_be200_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz"; const char iwl_be202_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz"; const char iwl_be401_name[] = "Intel(R) Wi-Fi 7 BE401 320MHz"; + +IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, 107); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 16abf0147fe4..467888c8d2cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_SC_UCODE_CORE_MAX 107 +#define IWL_SC_UCODE_CORE_MAX 108 /* Lowest firmware core release supported */ #define IWL_SC_UCODE_CORE_MIN 102 From ce9a74d575297ec9d937194bd63a16548ce1892c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 23 Sep 2026 16:04:52 +0300 Subject: [PATCH 039/104] wifi: iwlwifi: mvm: validate mpdu len before relying on it iwl_mvm_rx_mpdu_mq path only checks that the mpdu_len fits into the pkt len, but it doesn't validate len itself before dereferencing parts of the mpdu: the header, the padding, and the mic_crc_len. Check that the mpdu len covers the hdrlen, the padding (if exists) and the mic_crc_len. Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260923160318.fbf29ec27bc0.I4bb0dbd739ff1ddf969e51bbd68c42ca9e4e0634@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 8c4009d3a00c..c01c704929ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -99,10 +99,14 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb, u8 mic_crc_len = u8_get_bits(desc->mac_flags1, IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK) << 1; - if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) { - len -= 2; - pad_len = 2; - } + pad_len = desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD ? 2 : 0; + + if (IWL_FW_CHECK(mvm, len < hdrlen + crypt_len + pad_len + mic_crc_len, + "invalid len (%d): hdrlen=%u, crypt_len=%u, pad_len=%u, mic_crc_len=%u\n", + len, hdrlen, crypt_len, pad_len, mic_crc_len)) + return -EINVAL; + + len -= pad_len; /* * For non monitor interface strip the bytes the RADA might not have @@ -110,7 +114,7 @@ static int iwl_mvm_create_skb(struct iwl_mvm *mvm, struct sk_buff *skb, * interface cannot exist with other interfaces, this removal is safe * and sufficient, in monitor mode there's no decryption being done. */ - if (len > mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS)) + if (!ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS)) len -= mic_crc_len; /* If frame is small enough to fit in skb->head, pull it completely. @@ -2164,7 +2168,17 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, phy_data.phy_info = le16_to_cpu(desc->phy_info); phy_data.d4 = desc->phy_data4; + if (IWL_FW_CHECK(mvm, len < sizeof(hdr->frame_control), + "MPDU len (%u) is smaller than frame control\n", + len)) + return; + hdr = (void *)(pkt->data + desc_size); + if (IWL_FW_CHECK(mvm, len < ieee80211_hdrlen(hdr->frame_control), + "MPDU len (%u) is smaller than header length (%u)\n", + len, ieee80211_hdrlen(hdr->frame_control))) + return; + /* Dont use dev_alloc_skb(), we'll have enough headroom once * ieee80211_hdr pulled. */ @@ -2285,7 +2299,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_fw_dbg_trigger_tlv *trig; struct ieee80211_vif *vif = mvmsta->vif; - if (!mvm->tcm.paused && len >= sizeof(*hdr) && + if (!mvm->tcm.paused && !is_multicast_ether_addr(hdr->addr1) && ieee80211_is_data(hdr->frame_control) && time_after(jiffies, mvm->tcm.ts + MVM_TCM_PERIOD)) From b7dc5aec39f29f97171797fb0bdbac38dd1e0d85 Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Wed, 23 Sep 2026 16:04:53 +0300 Subject: [PATCH 040/104] wifi: iwlwifi: uefi: add UEFI GUID Lock Indicator (GLUI) definitions The platform provides a root-of-trust mechanism for connectivity UEFI variables via a dedicated UEFI GUID Lock Indicator (GLUI) variable. The GLUI may remain locked in both production and testing modes. A UEFI indicator is used rather than relying on the ACPI GLAI alone, so the mechanism also works on platforms that do not expose ACPI. Add the building blocks for consuming this variable and iwl_uefi_get_guid_lock_status() to read its value and store it, so the driver can use its lock state to decide whether the connectivity UEFI variables are trusted. Signed-off-by: Shahar Tzarfati Assisted-by: GitHub-Copilot:claude-opus-4-8 Link: https://patch.msgid.link/20260923160318.55d7dc9c9531.If4c9949de70fe78951464b983caf2c9d974061b3@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 3 +- drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 4 --- .../wireless/intel/iwlwifi/fw/regulatory.c | 2 +- .../wireless/intel/iwlwifi/fw/regulatory.h | 13 +++++++ .../net/wireless/intel/iwlwifi/fw/runtime.h | 4 +-- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 34 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 12 +++++++ 7 files changed, 64 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 71e0950d0193..f53cb531cf88 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -1153,7 +1153,8 @@ void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt) } if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || - wifi_pkg->package.elements[1].integer.value > ACPI_GLAI_MAX_STATUS) + wifi_pkg->package.elements[1].integer.value > + UEFI_CNV_GUID_TEST_MODE) goto out_free; fwrt->uefi_tables_lock_status = diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 45eb35ffb637..426b0c51abec 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -89,7 +89,6 @@ * and one for the status */ #define ACPI_GLAI_WIFI_DATA_SIZE 2 -#define ACPI_GLAI_MAX_STATUS 2 /* * TAS size: 1 elelment for type, * 1 element for enabled field, @@ -111,9 +110,6 @@ #define ACPI_PPAG_WIFI_DATA_SIZE_V3 ((ACPI_PPAG_NUM_CHAINS * \ ACPI_PPAG_NUM_BANDS_V3) + 2) -/* The Inidcator whether UEFI WIFI GUID tables are locked is read from ACPI */ -#define UEFI_WIFI_GUID_UNLOCKED 0 - #define ACPI_DSM_REV 0 #define DSM_INTERNAL_FUNC_GET_PLAT_INFO 1 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 3ab383b569bc..8dff97b8e0f1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -12,7 +12,7 @@ #define GET_BIOS_TABLE(__name, ...) \ do { \ int ret = -ENOENT; \ - if (fwrt->uefi_tables_lock_status > UEFI_WIFI_GUID_UNLOCKED) \ + if (fwrt->uefi_tables_lock_status > UEFI_CNV_GUID_UNLOCKED) \ ret = iwl_uefi_get_ ## __name(__VA_ARGS__); \ if (ret < 0) \ ret = iwl_acpi_get_ ## __name(__VA_ARGS__); \ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index 22c97c75b83c..08fd11adf905 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -47,6 +47,19 @@ #define IWL_WTAS_CANADA_UHB_MSK BIT(15) #define IWL_WTAS_USA_UHB_MSK BIT(16) +/** + * enum iwl_uefi_cnv_guid_status - lock status of the connectivity + * UEFI tables + * @UEFI_CNV_GUID_UNLOCKED: the tables are unlocked + * @UEFI_CNV_GUID_LOCKED: the tables are locked + * @UEFI_CNV_GUID_TEST_MODE: the tables are locked in test mode + */ +enum iwl_uefi_cnv_guid_status { + UEFI_CNV_GUID_UNLOCKED = 0, + UEFI_CNV_GUID_LOCKED = 1, + UEFI_CNV_GUID_TEST_MODE = 2, +}; + struct iwl_tas_selection_data { u8 override_tas_iec:1, enable_tas_iec:1, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index ac01ac0092ee..12a1cf6b16f1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -108,8 +108,8 @@ struct iwl_txf_iter_data { * @dump: debug dump data * @ap_type_cmd: AP type tables (for enablement on 6 GHz) * @ap_type_cmd_valid: if &ap_type_cmd is valid - * @uefi_tables_lock_status: The status of the WIFI GUID UEFI variables lock: - * 0: Unlocked, 1 and 2: Locked. + * @uefi_tables_lock_status: the status of the WIFI GUID UEFI variables lock, + * see &enum iwl_uefi_cnv_guid_status. * Only read the UEFI variables if locked. * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables * @geo_profiles: geographic profiles as read from WGDS BIOS table diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 7c290b526383..7df0e5ea4a1d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -20,6 +20,10 @@ 0x8d, 0x03, 0x77, 0x2e, \ 0xcc, 0x3d, 0xa5, 0x31) +#define IWL_EFI_GLUI_GUID EFI_GUID(0x6c5bed75, 0x0ee8, 0x4d45, \ + 0x98, 0x0b, 0x4d, 0x81, \ + 0x31, 0xba, 0x84, 0xb5) + struct iwl_uefi_pnvm_mem_desc { __le32 addr; __le32 size; @@ -1063,3 +1067,33 @@ int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt) IWL_DEBUG_RADIO(fwrt, "Loaded WPFC config from UEFI\n"); return 0; } + +void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt) +{ + struct uefi_cnv_var_glui *data __free(kfree) = + iwl_uefi_get_verified_variable_guid(fwrt->trans, + &IWL_EFI_GLUI_GUID, + IWL_UEFI_GLUI_NAME, "GLUI", + sizeof(*data), NULL); + + if (IS_ERR(data)) + return; + + if (data->revision != IWL_UEFI_GLUI_REVISION) { + IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI GLUI revision:%d\n", + data->revision); + return; + } + + /* UEFI_CNV_GUID_TEST_MODE is the max value */ + if (data->guid_lock_status > UEFI_CNV_GUID_TEST_MODE) { + IWL_DEBUG_RADIO(fwrt, "Invalid UEFI GUID lock status:%d\n", + data->guid_lock_status); + return; + } + + fwrt->uefi_tables_lock_status = data->guid_lock_status; + + IWL_DEBUG_RADIO(fwrt, "Loaded UEFI WIFI GUID lock status: %d\n", + fwrt->uefi_tables_lock_status); +} diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 386ca3744408..64fa1a78aacf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -13,6 +13,7 @@ #define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP" #define IWL_UEFI_UATS_NAME L"CnvUefiWlanUATS" #define IWL_UEFI_WRDS_NAME L"UefiCnvWlanWRDS" +#define IWL_UEFI_GLUI_NAME L"UefiCnvCommonGLUI" #define IWL_UEFI_EWRD_NAME L"UefiCnvWlanEWRD" #define IWL_UEFI_WGDS_NAME L"UefiCnvWlanWGDS" #define IWL_UEFI_PPAG_NAME L"UefiCnvWlanPPAG" @@ -40,6 +41,7 @@ #define IWL_UEFI_DSM_REVISION 4 #define IWL_UEFI_PUNCTURING_REVISION 0 #define IWL_UEFI_DSBR_REVISION 1 +#define IWL_UEFI_GLUI_REVISION 0 struct pnvm_sku_package { u8 rev; @@ -54,6 +56,11 @@ struct uefi_cnv_wlan_sgom_data { u8 offset_map[IWL_SGOM_MAP_SIZE - 1]; } __packed; +struct uefi_cnv_var_glui { + u8 revision; + u8 guid_lock_status; +} __packed; + struct uefi_cnv_wlan_uats_data { u8 revision; u8 mcc_to_ap_type_map[IWL_UATS_MAP_SIZE - 1]; @@ -349,6 +356,7 @@ void iwl_uefi_get_uneb_table(struct iwl_trans *trans, int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt); int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value); int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt); +void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt); #else /* CONFIG_EFI */ static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { @@ -466,5 +474,9 @@ static inline int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt) { return -ENOENT; } + +static inline void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt) +{ +} #endif /* CONFIG_EFI */ #endif /* __iwl_fw_uefi__ */ From d96966a8aa10028a97ff9db6aa078eec8dce5da0 Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Wed, 23 Sep 2026 16:04:54 +0300 Subject: [PATCH 041/104] wifi: iwlwifi: uefi: add a way to probe connectivity UEFI variables The connectivity UEFI variables are only trusted when the platform attests they are locked. When the lock status is unknown, the trust of each variable has to be discovered on its own by checking whether it is write protected. Probing depends on trying to rewrite UEFI variables and it is only attempted on non-x86 platforms. If the write is rejected the variable is considered locked and therefore trusted, otherwise it is treated as not trusted. Separate reading such a variable into two steps: iwl_uefi_get_variable_guid() only fetches and validates the variable, while iwl_uefi_get_verified_variable_guid() layers the trust decision on top of it. The latter now takes an iwl_fw_runtime so it can consult the lock status. Rename its WiFi-GUID wrapper from iwl_uefi_get_verified_variable() to iwl_uefi_get_verified_wifi_var(). With the trust check now performed by every iwl_uefi_get_*() reached through the GET_BIOS_TABLE() macro, the per-table lock-status gate in that macro is redundant, so drop it here. This move, and the new unknown-status handling, affect only the tables reached through GET_BIOS_TABLE(), i.e. those that have both a UEFI and an ACPI source. Assisted-by: GitHub-Copilot:claude-opus-4-8 Signed-off-by: Shahar Tzarfati Link: https://patch.msgid.link/20260923160318.6caa9ca17ffe.I877c0d6ab5126edb3e4f1f187ca1e20e563b2ec4@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/init.c | 4 +- .../wireless/intel/iwlwifi/fw/regulatory.c | 4 +- .../wireless/intel/iwlwifi/fw/regulatory.h | 3 + .../net/wireless/intel/iwlwifi/fw/runtime.h | 2 +- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 198 +++++++++++++----- 5 files changed, 148 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index d1d8058ad29f..d69757b0149d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2019-2021, 2024-2025 Intel Corporation + * Copyright (C) 2019-2021, 2024-2026 Intel Corporation */ #include "iwl-drv.h" #include "runtime.h" @@ -31,6 +31,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, fwrt->sanitize_ops = sanitize_ops; fwrt->sanitize_ctx = sanitize_ctx; fwrt->ops_ctx = ops_ctx; + /* default until the connectivity GUID lock status is resolved */ + fwrt->uefi_tables_lock_status = UEFI_CNV_GUID_UNKNOWN; for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) { fwrt->dump.wks[i].idx = i; INIT_DELAYED_WORK(&fwrt->dump.wks[i].wk, iwl_fw_error_dump_wk); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 8dff97b8e0f1..c62f7f53323a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -11,9 +11,7 @@ #define GET_BIOS_TABLE(__name, ...) \ do { \ - int ret = -ENOENT; \ - if (fwrt->uefi_tables_lock_status > UEFI_CNV_GUID_UNLOCKED) \ - ret = iwl_uefi_get_ ## __name(__VA_ARGS__); \ + int ret = iwl_uefi_get_ ## __name(__VA_ARGS__); \ if (ret < 0) \ ret = iwl_acpi_get_ ## __name(__VA_ARGS__); \ return ret; \ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index 08fd11adf905..cd6218e3a740 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -53,11 +53,14 @@ * @UEFI_CNV_GUID_UNLOCKED: the tables are unlocked * @UEFI_CNV_GUID_LOCKED: the tables are locked * @UEFI_CNV_GUID_TEST_MODE: the tables are locked in test mode + * @UEFI_CNV_GUID_UNKNOWN: the lock status could not be determined. + * This value is a driver internal, not a possible BIOS reported one */ enum iwl_uefi_cnv_guid_status { UEFI_CNV_GUID_UNLOCKED = 0, UEFI_CNV_GUID_LOCKED = 1, UEFI_CNV_GUID_TEST_MODE = 2, + UEFI_CNV_GUID_UNKNOWN = 3, }; struct iwl_tas_selection_data { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 12a1cf6b16f1..d0709ab2f593 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -110,7 +110,7 @@ struct iwl_txf_iter_data { * @ap_type_cmd_valid: if &ap_type_cmd is valid * @uefi_tables_lock_status: the status of the WIFI GUID UEFI variables lock, * see &enum iwl_uefi_cnv_guid_status. - * Only read the UEFI variables if locked. + * Trust the UEFI variables if locked or in test mode. * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables * @geo_profiles: geographic profiles as read from WGDS BIOS table * @geo_bios_source: see &enum bios_source diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 7df0e5ea4a1d..871d8f5db9c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -31,9 +31,10 @@ struct iwl_uefi_pnvm_mem_desc { } __packed; static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, - unsigned long *data_size) + u32 *attributes, unsigned long *data_size) { efi_status_t status; + u32 attr = 0; void *data; if (!data_size) @@ -52,15 +53,28 @@ static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, if (!data) return ERR_PTR(-ENOMEM); - status = efi.get_variable(name, guid, NULL, data_size, data); + status = efi.get_variable(name, guid, &attr, data_size, data); if (status != EFI_SUCCESS) { kfree(data); return ERR_PTR(-ENOENT); } + if (attributes) + *attributes = attr; + return data; } +static efi_status_t iwl_uefi_set_variable(efi_char16_t *name, efi_guid_t *guid, + u32 attributes, void *data, + unsigned long data_size) +{ + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE)) + return EFI_UNSUPPORTED; + + return efi.set_variable(name, guid, attributes, data_size, data); +} + void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { unsigned long package_size; @@ -69,7 +83,7 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) *len = 0; data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_WIFI_GUID, - &package_size); + NULL, &package_size); if (IS_ERR(data)) { IWL_DEBUG_FW(trans, "PNVM UEFI variable not found 0x%lx (len %lu)\n", @@ -84,17 +98,18 @@ void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) } static void * -iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans, - efi_guid_t *guid, - efi_char16_t *uefi_var_name, - char *var_name, - unsigned int expected_size, - unsigned long *size) +iwl_uefi_get_variable_guid(struct iwl_trans *trans, + efi_guid_t *guid, + efi_char16_t *uefi_var_name, + char *var_name, + unsigned int expected_size, + unsigned long *size, + u32 *attributes) { void *var; unsigned long var_size; - var = iwl_uefi_get_variable(uefi_var_name, guid, &var_size); + var = iwl_uefi_get_variable(uefi_var_name, guid, attributes, &var_size); if (IS_ERR(var)) { IWL_DEBUG_RADIO(trans, @@ -120,13 +135,72 @@ iwl_uefi_get_verified_variable_guid(struct iwl_trans *trans, } static void * -iwl_uefi_get_verified_variable(struct iwl_trans *trans, +iwl_uefi_get_verified_variable_guid(struct iwl_fw_runtime *fwrt, + efi_guid_t *guid, + efi_char16_t *uefi_var_name, + char *var_name, + unsigned int expected_size, + unsigned long *size) +{ + unsigned long var_size; + u32 attributes = 0; + void *var; + + if (fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_UNLOCKED) + return ERR_PTR(-EINVAL); + + /* In x86 either GLUI or GLAI should exist */ + if ((IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) || + IS_ENABLED(CONFIG_X86_32)) && + fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_UNKNOWN) + return ERR_PTR(-EINVAL); + + var = iwl_uefi_get_variable_guid(fwrt->trans, + guid, + uefi_var_name, var_name, + expected_size, &var_size, + &attributes); + if (IS_ERR(var)) + return var; + + if (fwrt->uefi_tables_lock_status != UEFI_CNV_GUID_UNKNOWN) + goto out; + + /* + * The lock status is unknown, so probe it: rewrite the variable + * with the data just read and trust it only if the firmware + * refuses the write. Treat a zero attributes value as untrusted, + * since a SetVariable() with no attributes would delete it. + */ + if (attributes) { + efi_status_t status; + + status = iwl_uefi_set_variable(uefi_var_name, guid, attributes, + var, var_size); + if (status == EFI_WRITE_PROTECTED || + status == EFI_SECURITY_VIOLATION || + status == EFI_ACCESS_DENIED) + goto out; + } + + /* unprobeable (e.g. EFI_UNSUPPORTED) or writable: not trusted */ + kfree(var); + return ERR_PTR(-EINVAL); + +out: + if (size) + *size = var_size; + return var; +} + +static void * +iwl_uefi_get_verified_wifi_var(struct iwl_fw_runtime *fwrt, efi_char16_t *uefi_var_name, char *var_name, unsigned int expected_size, unsigned long *size) { - return iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_GUID, + return iwl_uefi_get_verified_variable_guid(fwrt, &IWL_EFI_WIFI_GUID, uefi_var_name, var_name, expected_size, size); } @@ -292,11 +366,12 @@ u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) unsigned long package_size; u8 *data; - package = iwl_uefi_get_verified_variable(trans, - IWL_UEFI_REDUCED_POWER_NAME, - "Reduced Power", - sizeof(*package), - &package_size); + package = + iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID, + IWL_UEFI_REDUCED_POWER_NAME, + "Reduced Power", + sizeof(*package), + &package_size, NULL); if (IS_ERR(package)) return ERR_CAST(package); @@ -338,9 +413,9 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return; - data = iwl_uefi_get_verified_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID, - IWL_UEFI_STEP_NAME, - "STEP", sizeof(*data), NULL); + data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_BT_GUID, + IWL_UEFI_STEP_NAME, "STEP", + sizeof(*data), NULL, NULL); if (IS_ERR(data)) return; @@ -393,8 +468,9 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, if (!fwrt->geo_enabled) return; - data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_SGOM_NAME, - "SGOM", sizeof(*data), NULL); + data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID, + IWL_UEFI_SGOM_NAME, "SGOM", + sizeof(*data), NULL, NULL); if (IS_ERR(data)) return; @@ -427,8 +503,9 @@ void iwl_uefi_get_uats_table(struct iwl_trans *trans, struct uefi_cnv_wlan_uats_data *data; int ret; - data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UATS_NAME, - "UATS", sizeof(*data), NULL); + data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID, + IWL_UEFI_UATS_NAME, "UATS", + sizeof(*data), NULL, NULL); if (IS_ERR(data)) return; @@ -444,8 +521,9 @@ void iwl_uefi_get_uneb_table(struct iwl_trans *trans, { struct uefi_cnv_wlan_uneb_data *data; - data = iwl_uefi_get_verified_variable(trans, IWL_UEFI_UNEB_NAME, - "UNEB", sizeof(*data), NULL); + data = iwl_uefi_get_variable_guid(trans, &IWL_EFI_WIFI_GUID, + IWL_UEFI_UNEB_NAME, "UNEB", + sizeof(*data), NULL, NULL); if (IS_ERR(data)) return; @@ -506,8 +584,8 @@ int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt) int num_subbands; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDS_NAME, - "WRDS", + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WRDS_NAME, "WRDS", UEFI_SAR_WRDS_TABLE_SIZE_REV2, &size); @@ -555,8 +633,8 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt) int num_subbands; int profile_size; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_EWRD_NAME, - "EWRD", + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_EWRD_NAME, "EWRD", UEFI_SAR_EWRD_TABLE_SIZE_REV2, &size); if (IS_ERR(data)) @@ -609,9 +687,9 @@ int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt) int n_subbands; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WGDS_NAME, - "WGDS", UEFI_WGDS_TABLE_SIZE_REV3, - &size); + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WGDS_NAME, "WGDS", + UEFI_WGDS_TABLE_SIZE_REV3, &size); if (IS_ERR(data)) return -EINVAL; @@ -684,9 +762,9 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt) u32 valid_rev; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_PPAG_NAME, - "PPAG", UEFI_PPAG_DATA_SIZE_V5, - NULL); + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_PPAG_NAME, "PPAG", + UEFI_PPAG_DATA_SIZE_V5, NULL); if (!IS_ERR(data)) { n_subbands = UEFI_PPAG_SUB_BANDS_NUM_REV5; valid_rev = BIT(5); @@ -694,7 +772,7 @@ int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt) goto parse_table; } - data = iwl_uefi_get_verified_variable(fwrt->trans, + data = iwl_uefi_get_verified_wifi_var(fwrt, IWL_UEFI_PPAG_NAME, "PPAG", UEFI_PPAG_DATA_SIZE_V4, @@ -752,8 +830,9 @@ int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt, struct uefi_cnv_var_wtas *uefi_tas; int ret, enabled; - uefi_tas = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WTAS_NAME, - "WTAS", sizeof(*uefi_tas), NULL); + uefi_tas = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WTAS_NAME, "WTAS", + sizeof(*uefi_tas), NULL); if (IS_ERR(uefi_tas)) return -EINVAL; @@ -805,7 +884,7 @@ int iwl_uefi_get_pwr_limit(struct iwl_fw_runtime *fwrt, struct uefi_cnv_var_splc *data; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_SPLC_NAME, + data = iwl_uefi_get_verified_wifi_var(fwrt, IWL_UEFI_SPLC_NAME, "SPLC", sizeof(*data), NULL); if (IS_ERR(data)) return -EINVAL; @@ -827,8 +906,9 @@ int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc) struct uefi_cnv_var_wrdd *data; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WRDD_NAME, - "WRDD", sizeof(*data), NULL); + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WRDD_NAME, "WRDD", + sizeof(*data), NULL); if (IS_ERR(data)) return -EINVAL; @@ -858,7 +938,7 @@ int iwl_uefi_get_eckv(struct iwl_fw_runtime *fwrt, u32 *extl_clk) struct uefi_cnv_var_eckv *data; int ret = 0; - data = iwl_uefi_get_verified_variable_guid(fwrt->trans, + data = iwl_uefi_get_verified_variable_guid(fwrt, &IWL_EFI_WIFI_BT_GUID, IWL_UEFI_ECKV_NAME, "ECKV", sizeof(*data), NULL); @@ -882,8 +962,9 @@ int iwl_uefi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value) struct uefi_cnv_wlan_wbem_data *data; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WBEM_NAME, - "WBEM", sizeof(*data), NULL); + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WBEM_NAME, "WBEM", + sizeof(*data), NULL); if (IS_ERR(data)) return -EINVAL; @@ -909,7 +990,7 @@ static int iwl_uefi_load_dsm_values(struct iwl_fw_runtime *fwrt) BUILD_BUG_ON(ARRAY_SIZE(data->functions) < ARRAY_SIZE(fwrt->dsm_values)); - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_DSM_NAME, + data = iwl_uefi_get_verified_wifi_var(fwrt, IWL_UEFI_DSM_NAME, "DSM", sizeof(*data), NULL); if (IS_ERR(data)) return -EINVAL; @@ -990,10 +1071,10 @@ int iwl_uefi_get_puncturing(struct iwl_fw_runtime *fwrt) struct uefi_cnv_var_puncturing_data *data; int ret = 0; - data = iwl_uefi_get_verified_variable(fwrt->trans, - IWL_UEFI_PUNCTURING_NAME, - "UefiCnvWlanPuncturing", - sizeof(*data), NULL); + data = iwl_uefi_get_variable_guid(fwrt->trans, &IWL_EFI_WIFI_GUID, + IWL_UEFI_PUNCTURING_NAME, + "UefiCnvWlanPuncturing", + sizeof(*data), NULL, NULL); if (IS_ERR(data)) return -EINVAL; @@ -1019,7 +1100,7 @@ int iwl_uefi_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value) struct uefi_cnv_wlan_dsbr_data *data; int ret = 0; - data = iwl_uefi_get_verified_variable_guid(fwrt->trans, + data = iwl_uefi_get_verified_variable_guid(fwrt, &IWL_EFI_WIFI_BT_GUID, IWL_UEFI_DSBR_NAME, "DSBR", sizeof(*data), NULL); @@ -1045,8 +1126,9 @@ int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt) struct uefi_cnv_wpfc_data *data __free(kfree); struct iwl_phy_specific_cfg *filters = &fwrt->phy_filters; - data = iwl_uefi_get_verified_variable(fwrt->trans, IWL_UEFI_WPFC_NAME, - "WPFC", sizeof(*data), NULL); + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WPFC_NAME, "WPFC", + sizeof(*data), NULL); if (IS_ERR(data)) return -EINVAL; @@ -1071,10 +1153,10 @@ int iwl_uefi_get_phy_filters(struct iwl_fw_runtime *fwrt) void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt) { struct uefi_cnv_var_glui *data __free(kfree) = - iwl_uefi_get_verified_variable_guid(fwrt->trans, - &IWL_EFI_GLUI_GUID, - IWL_UEFI_GLUI_NAME, "GLUI", - sizeof(*data), NULL); + iwl_uefi_get_variable_guid(fwrt->trans, + &IWL_EFI_GLUI_GUID, + IWL_UEFI_GLUI_NAME, "GLUI", + sizeof(*data), NULL, NULL); if (IS_ERR(data)) return; @@ -1085,7 +1167,7 @@ void iwl_uefi_get_guid_lock_status(struct iwl_fw_runtime *fwrt) return; } - /* UEFI_CNV_GUID_TEST_MODE is the max value */ + /* UEFI_CNV_GUID_TEST_MODE is the max value the BIOS can report */ if (data->guid_lock_status > UEFI_CNV_GUID_TEST_MODE) { IWL_DEBUG_RADIO(fwrt, "Invalid UEFI GUID lock status:%d\n", data->guid_lock_status); From 7bec311676af0aa93f8999bec7eb2b35da35589f Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Wed, 23 Sep 2026 16:04:55 +0300 Subject: [PATCH 042/104] wifi: iwlwifi: regulatory: use GLUI as root-of-trust for connectivity variables The BIOS tables can be sourced from either UEFI or ACPI. The UEFI copies are writable, so they may be trusted only when the platform attests they are locked. Resolve this trust from a single source, preferring the UEFI GUID Lock Indicator (GLUI) and consulting the ACPI GLAI whenever GLUI does not attest the tables as locked or in test mode. Add iwl_bios_get_guid_lock_status() as that entry point and have the mvm and mld op-modes use it instead of the ACPI-only helper, so trust is resolved consistently regardless of whether a platform ships GLUI or GLAI. Signed-off-by: Shahar Tzarfati Assisted-by: GitHub-Copilot:claude-opus-4-8 Link: https://patch.msgid.link/20260923160318.c6a2252dafb9.I46f8c4d55bd22d98a7200cce8f528c5e182f443c@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 1 - .../wireless/intel/iwlwifi/fw/regulatory.c | 24 +++++++++++++++++++ .../wireless/intel/iwlwifi/fw/regulatory.h | 1 + .../wireless/intel/iwlwifi/mld/regulatory.c | 3 +-- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index f53cb531cf88..21470b8ae8e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -1166,7 +1166,6 @@ void iwl_acpi_get_guid_lock_status(struct iwl_fw_runtime *fwrt) out_free: kfree(data); } -IWL_EXPORT_SYMBOL(iwl_acpi_get_guid_lock_status); int iwl_acpi_get_wbem(struct iwl_fw_runtime *fwrt, u32 *value) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index c62f7f53323a..5dbb3cdb9916 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -451,3 +451,27 @@ bool iwl_rfi_is_enabled_in_bios(struct iwl_fw_runtime *fwrt) return false; } IWL_EXPORT_SYMBOL(iwl_rfi_is_enabled_in_bios); + +/** + * iwl_bios_get_guid_lock_status - resolve connectivity variables lock status + * @fwrt: the firmware runtime context + * + * Determine the root-of-trust for the connectivity UEFI variables. The UEFI + * GUID Lock Indicator (GLUI) is preferred: if it attests the tables as locked + * or in test mode, that result is used. Otherwise (GLUI is missing, invalid or + * reports unlocked) the ACPI GUID Lock Indicator is consulted and can override + * the GLUI result. + * + * This only caches the result in &fwrt->uefi_tables_lock_status + * (see &enum iwl_uefi_cnv_guid_status). + */ +void iwl_bios_get_guid_lock_status(struct iwl_fw_runtime *fwrt) +{ + iwl_uefi_get_guid_lock_status(fwrt); + if (fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_LOCKED || + fwrt->uefi_tables_lock_status == UEFI_CNV_GUID_TEST_MODE) + return; + + iwl_acpi_get_guid_lock_status(fwrt); +} +IWL_EXPORT_SYMBOL(iwl_bios_get_guid_lock_status); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index cd6218e3a740..f7bd09195ab4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -258,6 +258,7 @@ bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc); int iwl_bios_get_dsbr(struct iwl_fw_runtime *fwrt, u32 *value); int iwl_bios_get_phy_filters(struct iwl_fw_runtime *fwrt); +void iwl_bios_get_guid_lock_status(struct iwl_fw_runtime *fwrt); static inline void iwl_bios_setup_step(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index 6db84c2117f2..9f395a1fd12a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -6,7 +6,6 @@ #include #include "fw/regulatory.h" -#include "fw/acpi.h" #include "fw/uefi.h" #include "regulatory.h" @@ -37,7 +36,7 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld) { int ret; - iwl_acpi_get_guid_lock_status(&mld->fwrt); + iwl_bios_get_guid_lock_status(&mld->fwrt); ret = iwl_bios_get_ppag_table(&mld->fwrt); if (ret < 0) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 06f3b065914b..0b5b41223a8a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1576,7 +1576,7 @@ void iwl_mvm_get_bios_tables(struct iwl_mvm *mvm) { int ret; - iwl_acpi_get_guid_lock_status(&mvm->fwrt); + iwl_bios_get_guid_lock_status(&mvm->fwrt); /* read PPAG table */ ret = iwl_bios_get_ppag_table(&mvm->fwrt); From 80b4900412e06a7b28a196c850f522915aad5836 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 23 Sep 2026 16:04:56 +0300 Subject: [PATCH 043/104] wifi: iwlwifi: support for another device ID Add support of another flavor of AX231. Link: https://patch.msgid.link/20260923160318.af9e8f9c1548.I1fd3aa97da28065966952c36edcdb99acd5313cb@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index a3e6c9e09a3b..a117c378b1f1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1018,6 +1018,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = { /* GF RF */ IWL_DEV_INFO(iwl_rf_gf, iwl_ax211_name, RF_TYPE(GF)), IWL_DEV_INFO(iwl_rf_ot, iwl_ax231_name, RF_TYPE(GF), SUBDEV(0x0294)), + IWL_DEV_INFO(iwl_rf_ot, iwl_ax231_name, RF_TYPE(GF), SUBDEV(0x4294)), IWL_DEV_INFO(iwl_rf_gf, iwl_ax411_name, RF_TYPE(GF), CDB), IWL_DEV_INFO(iwl_rf_gf, iwl_ax210_name, DEVICE(0x2725)), From 5c0c0c189bc74c599cb6ed4a7ad8651c75994ecc Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Wed, 23 Sep 2026 16:04:57 +0300 Subject: [PATCH 044/104] wifi: iwlwifi: mvm: validate BAID from FW The BAID from the ADD_STA response is used to access mvm->baid_map[] without an upper bound check. Check and reject an invalid value. Signed-off-by: Shahar Tzarfati Link: https://patch.msgid.link/20260923160318.22624c6dfa10.I9a99a140ab72cb1790a03a130ae7c8aa93cfac01@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 2d0811be7346..a66128a62546 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2015, 2018-2025 Intel Corporation + * Copyright (C) 2012-2015, 2018-2026 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -2792,7 +2792,11 @@ static int iwl_mvm_fw_baid_op_sta(struct iwl_mvm *mvm, if (WARN_ON(start && iwl_mvm_has_new_rx_api(mvm) && !(status & IWL_ADD_STA_BAID_VALID_MASK))) return -EINVAL; - return u32_get_bits(status, IWL_ADD_STA_BAID_MASK); + ret = u32_get_bits(status, IWL_ADD_STA_BAID_MASK); + if (IWL_FW_CHECK(mvm, start && ret >= ARRAY_SIZE(mvm->baid_map), + "invalid BAID %d from FW\n", ret)) + return -EINVAL; + return ret; case ADD_STA_IMMEDIATE_BA_FAILURE: IWL_WARN(mvm, "RX BA Session refused by fw\n"); return -ENOSPC; From dc651c43a9d12e3e7cb4104fd62f07498ea6b332 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Wed, 23 Sep 2026 16:04:58 +0300 Subject: [PATCH 045/104] wifi: iwlwifi: add standalone WRSS/EWSS BIOS table loading Add support for reading WRSS and EWSS standalone SAR tables from the BIOS in the ACPI and UEFI paths. WRDS/EWRD tables describe SAR limits for concurrent Wi-Fi and Bluetooth operation. When Bluetooth is not active, those limits can unnecessarily restrict Wi-Fi transmit power. WRSS/EWSS provide separate standalone SAR profiles for Wi-Fi-only operation, allowing the firmware to select the appropriate higher-power limits while still respecting the platform-specific regulatory constraints. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260923160318.9a8eb3ff9512.Id79836e772136e1e38f107b578007faf39b13b4e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 302 +++++++++++++----- drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 16 + drivers/net/wireless/intel/iwlwifi/fw/init.c | 2 + .../wireless/intel/iwlwifi/fw/regulatory.c | 2 + .../wireless/intel/iwlwifi/fw/regulatory.h | 5 + .../net/wireless/intel/iwlwifi/fw/runtime.h | 7 + drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 133 +++++++- drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 14 + 8 files changed, 392 insertions(+), 89 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 21470b8ae8e9..7b11316a3062 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -525,6 +525,83 @@ iwl_acpi_parse_chains_table(union acpi_object *table, return 0; } +static int +iwl_acpi_parse_extended_sar_profiles(union acpi_object *wifi_pkg, + struct iwl_sar_profile *sar_profiles, + u8 num_sub_bands, bool has_cdb) +{ + int n_profiles, pos, ret; + bool enabled; + + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || + wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) + return -EINVAL; + + if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands > + ARRAY_SIZE(sar_profiles[0].chains) * + ARRAY_SIZE(sar_profiles[0].chains[0].subbands))) + return -EINVAL; + + enabled = !!(wifi_pkg->package.elements[1].integer.value); + n_profiles = wifi_pkg->package.elements[2].integer.value; + + if (n_profiles >= BIOS_SAR_MAX_PROFILE_NUM) + return -EINVAL; + + /* the tables start at element 3 */ + pos = 3; + + BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1); + BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0); + + /* parse non-cdb chains for all profiles */ + for (int i = 0; i < n_profiles; i++) { + union acpi_object *table = &wifi_pkg->package.elements[pos]; + + ret = iwl_acpi_parse_chains_table(table, + sar_profiles[i + 1].chains, + ACPI_SAR_NUM_CHAINS_REV0, + num_sub_bands); + if (ret < 0) + return ret; + + /* go to the next table */ + pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands; + } + + if (!has_cdb) + goto set_enabled; + + if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * 2 * num_sub_bands > + ARRAY_SIZE(sar_profiles[0].chains) * + ARRAY_SIZE(sar_profiles[0].chains[0].subbands))) + return -EINVAL; + + /* parse cdb chains for all profiles */ + for (int i = 0; i < n_profiles; i++) { + struct iwl_sar_profile_chain *chains; + union acpi_object *table; + + table = &wifi_pkg->package.elements[pos]; + chains = &sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0]; + ret = iwl_acpi_parse_chains_table(table, + chains, + ACPI_SAR_NUM_CHAINS_REV0, + num_sub_bands); + if (ret < 0) + return ret; + + /* go to the next table */ + pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands; + } + +set_enabled: + for (int i = 0; i < n_profiles; i++) + sar_profiles[i + 1].enabled = enabled; + + return 0; +} + int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt) { union acpi_object *wifi_pkg, *table, *data; @@ -629,8 +706,12 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt) */ ret = iwl_acpi_parse_chains_table(table, fwrt->sar_profiles[0].chains, num_chains, num_sub_bands); - if (!ret && flags & IWL_SAR_ENABLE_MSK) + if (ret) + goto out_free; + + if (flags & IWL_SAR_ENABLE_MSK) fwrt->sar_profiles[0].enabled = true; + fwrt->wrds_table_revision = tbl_rev; out_free: kfree(data); @@ -640,8 +721,7 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt) int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) { union acpi_object *wifi_pkg, *data; - bool enabled; - int i, n_profiles, tbl_rev, pos; + int tbl_rev; int ret = 0; u8 num_sub_bands; @@ -713,95 +793,149 @@ int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) goto out_free; read_table: - if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || - wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) { - ret = -EINVAL; + ret = iwl_acpi_parse_extended_sar_profiles(wifi_pkg, + fwrt->sar_profiles, + num_sub_bands, + tbl_rev >= 2); + if (ret) goto out_free; - } - if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands > - ARRAY_SIZE(fwrt->sar_profiles[0].chains) * - ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) { - ret = -EINVAL; - goto out_free; - } - - enabled = !!(wifi_pkg->package.elements[1].integer.value); - n_profiles = wifi_pkg->package.elements[2].integer.value; - - /* - * Check the validity of n_profiles. The EWRD profiles start - * from index 1, so the maximum value allowed here is - * ACPI_SAR_PROFILES_NUM - 1. - */ - if (n_profiles >= BIOS_SAR_MAX_PROFILE_NUM) { - ret = -EINVAL; - goto out_free; - } - - /* the tables start at element 3 */ - pos = 3; - - BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV0 != ACPI_SAR_NUM_CHAINS_REV1); - BUILD_BUG_ON(ACPI_SAR_NUM_CHAINS_REV2 != 2 * ACPI_SAR_NUM_CHAINS_REV0); - - /* parse non-cdb chains for all profiles */ - for (i = 0; i < n_profiles; i++) { - union acpi_object *table = &wifi_pkg->package.elements[pos]; - - /* The EWRD profiles officially go from 2 to 4, but we - * save them in sar_profiles[1-3] (because we don't - * have profile 0). So in the array we start from 1. - */ - ret = iwl_acpi_parse_chains_table(table, - fwrt->sar_profiles[i + 1].chains, - ACPI_SAR_NUM_CHAINS_REV0, - num_sub_bands); - if (ret < 0) - goto out_free; - - /* go to the next table */ - pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands; - } - - /* non-cdb table revisions */ - if (tbl_rev < 2) - goto set_enabled; - - if (WARN_ON(ACPI_SAR_NUM_CHAINS_REV0 * 2 * num_sub_bands > - ARRAY_SIZE(fwrt->sar_profiles[0].chains) * - ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) { - ret = -EINVAL; - goto out_free; - } - - /* parse cdb chains for all profiles */ - for (i = 0; i < n_profiles; i++) { - struct iwl_sar_profile_chain *chains; - union acpi_object *table; - - table = &wifi_pkg->package.elements[pos]; - chains = &fwrt->sar_profiles[i + 1].chains[ACPI_SAR_NUM_CHAINS_REV0]; - ret = iwl_acpi_parse_chains_table(table, - chains, - ACPI_SAR_NUM_CHAINS_REV0, - num_sub_bands); - if (ret < 0) - goto out_free; - - /* go to the next table */ - pos += ACPI_SAR_NUM_CHAINS_REV0 * num_sub_bands; - } - -set_enabled: - for (i = 0; i < n_profiles; i++) - fwrt->sar_profiles[i + 1].enabled = enabled; + fwrt->ewrd_table_revision = tbl_rev; out_free: kfree(data); return ret; } +int iwl_acpi_get_wsss_table(struct iwl_fw_runtime *fwrt) +{ + union acpi_object *data __free(kfree) = NULL; + union acpi_object *wifi_pkg, *table; + u8 num_chains, num_sub_bands; + int ret, tbl_rev; + u32 flags; + + if (fwrt->wrds_table_revision == IWL_BIOS_REVISION_UNSET) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: WRDS table was not read\n"); + return -EINVAL; + } + + data = iwl_acpi_get_object(fwrt->dev, ACPI_WSSS_METHOD); + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (fwrt->wrds_table_revision) { + case 3: + wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, + ACPI_WRDS_WIFI_DATA_SIZE_REV3, + &tbl_rev); + num_chains = ACPI_SAR_NUM_CHAINS_REV2; + num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3; + break; + case 2: + wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, + ACPI_WRDS_WIFI_DATA_SIZE_REV2, + &tbl_rev); + num_chains = ACPI_SAR_NUM_CHAINS_REV2; + num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2; + break; + default: + return -EINVAL; + } + + if (IS_ERR(wifi_pkg)) + return PTR_ERR(wifi_pkg); + + if (fwrt->wrds_table_revision != tbl_rev) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: WRDS/WSSS revision mismatch (WRDS rev %d, WSSS rev %d)\n", + fwrt->wrds_table_revision, + tbl_rev); + return -EINVAL; + } + + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) + return -EINVAL; + + if (WARN_ON(num_chains * num_sub_bands > + ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains) * + ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains[0].subbands))) + return -EINVAL; + + IWL_DEBUG_RADIO(fwrt, "Reading WSSS (WRDS Standalone) tbl_rev=%d\n", + tbl_rev); + + flags = wifi_pkg->package.elements[1].integer.value; + + /* position of the actual table */ + table = &wifi_pkg->package.elements[2]; + + ret = iwl_acpi_parse_chains_table(table, + fwrt->sar_standalone_profiles[0].chains, + num_chains, num_sub_bands); + if (ret) + return ret; + + if (flags & IWL_SAR_ENABLE_MSK) + fwrt->sar_standalone_profiles[0].enabled = true; + + return ret; +} + +int iwl_acpi_get_ewss_table(struct iwl_fw_runtime *fwrt) +{ + union acpi_object *data __free(kfree) = NULL; + union acpi_object *wifi_pkg; + u8 num_sub_bands; + int tbl_rev; + + if (fwrt->ewrd_table_revision == IWL_BIOS_REVISION_UNSET) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: EWRD table was not read\n"); + return -EINVAL; + } + + data = iwl_acpi_get_object(fwrt->dev, ACPI_EWSS_METHOD); + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (fwrt->ewrd_table_revision) { + case 3: + wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, + ACPI_EWRD_WIFI_DATA_SIZE_REV3, + &tbl_rev); + num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV3; + break; + case 2: + wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, + ACPI_EWRD_WIFI_DATA_SIZE_REV2, + &tbl_rev); + num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2; + break; + default: + return -EINVAL; + } + + if (IS_ERR(wifi_pkg)) + return PTR_ERR(wifi_pkg); + + if (fwrt->ewrd_table_revision != tbl_rev) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: EWRD/EWSS revision mismatch (EWRD rev %d, EWSS rev %d)\n", + fwrt->ewrd_table_revision, tbl_rev); + return -EINVAL; + } + + IWL_DEBUG_RADIO(fwrt, "Reading EWSS (EWRD Standalone) tbl_rev=%d\n", + tbl_rev); + + return iwl_acpi_parse_extended_sar_profiles(wifi_pkg, + fwrt->sar_standalone_profiles, + num_sub_bands, + fwrt->ewrd_table_revision >= 2); +} + int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) { union acpi_object *wifi_pkg, *data; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 426b0c51abec..b722beae2f00 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -14,6 +14,8 @@ #define ACPI_WRDS_METHOD "WRDS" #define ACPI_EWRD_METHOD "EWRD" +#define ACPI_WSSS_METHOD "WSSS" +#define ACPI_EWSS_METHOD "EWSS" #define ACPI_WGDS_METHOD "WGDS" #define ACPI_WRDD_METHOD "WRDD" #define ACPI_SPLC_METHOD "SPLC" @@ -175,6 +177,10 @@ int iwl_acpi_get_wrds_table(struct iwl_fw_runtime *fwrt); int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt); +int iwl_acpi_get_wsss_table(struct iwl_fw_runtime *fwrt); + +int iwl_acpi_get_ewss_table(struct iwl_fw_runtime *fwrt); + int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt); int iwl_acpi_get_tas_table(struct iwl_fw_runtime *fwrt, @@ -229,6 +235,16 @@ static inline int iwl_acpi_get_ewrd_table(struct iwl_fw_runtime *fwrt) return -ENOENT; } +static inline int iwl_acpi_get_wsss_table(struct iwl_fw_runtime *fwrt) +{ + return -ENOENT; +} + +static inline int iwl_acpi_get_ewss_table(struct iwl_fw_runtime *fwrt) +{ + return -ENOENT; +} + static inline int iwl_acpi_get_wgds_table(struct iwl_fw_runtime *fwrt) { return 1; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index d69757b0149d..f62c6a69f0dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -23,6 +23,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, int i; memset(fwrt, 0, sizeof(*fwrt)); + fwrt->wrds_table_revision = IWL_BIOS_REVISION_UNSET; + fwrt->ewrd_table_revision = IWL_BIOS_REVISION_UNSET; fwrt->trans = trans; fwrt->fw = fw; fwrt->dev = trans->dev; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 5dbb3cdb9916..137303e4a29b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -30,6 +30,8 @@ IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name) IWL_BIOS_TABLE_LOADER(wrds_table); IWL_BIOS_TABLE_LOADER(ewrd_table); +IWL_BIOS_TABLE_LOADER(wsss_table); +IWL_BIOS_TABLE_LOADER(ewss_table); IWL_BIOS_TABLE_LOADER(wgds_table); IWL_BIOS_TABLE_LOADER(ppag_table); IWL_BIOS_TABLE_LOADER(phy_filters); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index f7bd09195ab4..bd7ea0ff3d19 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -31,6 +31,7 @@ #define IWL_SAR_ENABLE_MSK BIT(0) #define IWL_REDUCE_POWER_FLAGS_POS 1 +#define IWL_BIOS_REVISION_UNSET 0xFF /* PPAG gain value bounds in 1/8 dBm */ #define IWL_PPAG_MIN_LB -16 @@ -223,6 +224,10 @@ int iwl_bios_get_wrds_table(struct iwl_fw_runtime *fwrt); int iwl_bios_get_ewrd_table(struct iwl_fw_runtime *fwrt); +int iwl_bios_get_wsss_table(struct iwl_fw_runtime *fwrt); + +int iwl_bios_get_ewss_table(struct iwl_fw_runtime *fwrt); + int iwl_bios_get_wgds_table(struct iwl_fw_runtime *fwrt); int iwl_bios_get_ppag_table(struct iwl_fw_runtime *fwrt); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index d0709ab2f593..33ce06f1a60a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -112,6 +112,10 @@ struct iwl_txf_iter_data { * see &enum iwl_uefi_cnv_guid_status. * Trust the UEFI variables if locked or in test mode. * @sar_profiles: sar profiles as read from WRDS/EWRD BIOS tables + * @sar_standalone_profiles: standalone sar profiles as read from + * WSSS/EWSS BIOS tables (for Wi-Fi HB/UHB without concurrent BT) + * @wrds_table_revision: revision of WRDS BIOS table + * @ewrd_table_revision: revision of EWRD BIOS table * @geo_profiles: geographic profiles as read from WGDS BIOS table * @geo_bios_source: see &enum bios_source * @phy_filters: specific phy filters as read from WPFC BIOS table @@ -206,6 +210,9 @@ struct iwl_fw_runtime { bool tpc_enabled; #endif /* CONFIG_IWLWIFI_DEBUGFS */ struct iwl_sar_profile sar_profiles[BIOS_SAR_MAX_PROFILE_NUM]; + struct iwl_sar_profile sar_standalone_profiles[BIOS_SAR_MAX_PROFILE_NUM]; + u8 wrds_table_revision; + u8 ewrd_table_revision; u8 sar_chain_a_profile; u8 sar_chain_b_profile; u8 reduced_power_flags; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 871d8f5db9c3..79fd95d08732 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -547,11 +547,11 @@ void iwl_uefi_get_uneb_table(struct iwl_trans *trans, } IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table); -static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt, +static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles, const u8 *vals, u8 prof_index, u8 num_subbands, bool enabled) { - struct iwl_sar_profile *sar_prof = &fwrt->sar_profiles[prof_index]; + struct iwl_sar_profile *sar_prof = &profiles[prof_index]; /* * Make sure fwrt has enough room to hold the data @@ -573,7 +573,7 @@ static void iwl_uefi_set_sar_profile(struct iwl_fw_runtime *fwrt, vals[chain * num_subbands + subband]; } - fwrt->sar_profiles[prof_index].enabled = enabled & IWL_SAR_ENABLE_MSK; + sar_prof->enabled = enabled & IWL_SAR_ENABLE_MSK; } int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt) @@ -617,8 +617,9 @@ int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt) /* The profile from WRDS is officially profile 1, but goes * into sar_profiles[0] (because we don't have a profile 0). */ - iwl_uefi_set_sar_profile(fwrt, data->vals, 0, + iwl_uefi_set_sar_profile(fwrt->sar_profiles, data->vals, 0, num_subbands, data->mode); + fwrt->wrds_table_revision = data->revision; out: kfree(data); return ret; @@ -670,14 +671,136 @@ int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt) * save them in sar_profiles[1-3] (because we don't * have profile 0). So in the array we start from 1. */ - iwl_uefi_set_sar_profile(fwrt, &data->vals[i * profile_size], + iwl_uefi_set_sar_profile(fwrt->sar_profiles, + &data->vals[i * profile_size], i + 1, num_subbands, data->mode); + fwrt->ewrd_table_revision = data->revision; + out: kfree(data); return ret; } +int iwl_uefi_get_wsss_table(struct iwl_fw_runtime *fwrt) +{ + struct uefi_cnv_var_wrds *data __free(kfree) = NULL; + unsigned long expected_size; + unsigned long size; + int num_subbands; + + if (fwrt->wrds_table_revision == IWL_BIOS_REVISION_UNSET) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: WRDS table was not read\n"); + return -EINVAL; + } + + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_WSSS_NAME, + "WSSS", + UEFI_SAR_WRDS_TABLE_SIZE_REV2, + &size); + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (data->revision) { + case 2: + expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV2; + num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2; + break; + case 3: + expected_size = UEFI_SAR_WRDS_TABLE_SIZE_REV3; + num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3; + break; + default: + IWL_DEBUG_RADIO(fwrt, + "Unsupported UEFI WSSS revision:%d\n", + data->revision); + return -EINVAL; + } + + if (size != expected_size) + return -EINVAL; + + if (fwrt->wrds_table_revision != data->revision) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: WRDS/WSSS revision mismatch (WRDS rev %d, WSSS rev %d)\n", + fwrt->wrds_table_revision, + data->revision); + return -EINVAL; + } + + IWL_DEBUG_RADIO(fwrt, "Reading WSSS (WRDS Standalone) tbl_rev=%d\n", + data->revision); + iwl_uefi_set_sar_profile(fwrt->sar_standalone_profiles, + data->vals, 0, + num_subbands, + data->mode); + return 0; +} + +int iwl_uefi_get_ewss_table(struct iwl_fw_runtime *fwrt) +{ + struct uefi_cnv_var_ewrd *data __free(kfree) = NULL; + unsigned long expected_size; + unsigned long size; + int num_subbands; + int profile_size; + int i; + + if (fwrt->ewrd_table_revision == IWL_BIOS_REVISION_UNSET) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: EWRD table was not read\n"); + return -EINVAL; + } + + data = iwl_uefi_get_verified_wifi_var(fwrt, + IWL_UEFI_EWSS_NAME, + "EWSS", + UEFI_SAR_EWRD_TABLE_SIZE_REV2, + &size); + if (IS_ERR(data)) + return PTR_ERR(data); + + switch (data->revision) { + case 3: + expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV3; + num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV3; + profile_size = UEFI_SAR_PROFILE_SIZE_REV3; + break; + case 2: + expected_size = UEFI_SAR_EWRD_TABLE_SIZE_REV2; + num_subbands = UEFI_SAR_SUB_BANDS_NUM_REV2; + profile_size = UEFI_SAR_PROFILE_SIZE_REV2; + break; + default: + IWL_DEBUG_RADIO(fwrt, + "Unsupported UEFI EWSS revision:%d\n", + data->revision); + return -EINVAL; + } + + if (size != expected_size || + data->num_profiles >= BIOS_SAR_MAX_PROFILE_NUM) + return -EINVAL; + + if (fwrt->ewrd_table_revision != data->revision) { + IWL_DEBUG_RADIO(fwrt, + "Skipping standalone SAR: EWRD/EWSS revision mismatch (EWRD rev %d, EWSS rev %d)\n", + fwrt->ewrd_table_revision, + data->revision); + return -EINVAL; + } + + for (i = 0; i < data->num_profiles; i++) + iwl_uefi_set_sar_profile(fwrt->sar_standalone_profiles, + &data->vals[i * profile_size], + i + 1, num_subbands, + data->mode); + + return 0; +} + int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt) { struct uefi_cnv_var_wgds *data; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 64fa1a78aacf..f4f7a447e528 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -15,6 +15,8 @@ #define IWL_UEFI_WRDS_NAME L"UefiCnvWlanWRDS" #define IWL_UEFI_GLUI_NAME L"UefiCnvCommonGLUI" #define IWL_UEFI_EWRD_NAME L"UefiCnvWlanEWRD" +#define IWL_UEFI_WSSS_NAME L"UefiCnvWlanWSSS" +#define IWL_UEFI_EWSS_NAME L"UefiCnvWlanEWSS" #define IWL_UEFI_WGDS_NAME L"UefiCnvWlanWGDS" #define IWL_UEFI_PPAG_NAME L"UefiCnvWlanPPAG" #define IWL_UEFI_WTAS_NAME L"UefiCnvWlanWTAS" @@ -337,6 +339,8 @@ int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, u32 tlv_len, struct iwl_pnvm_image *pnvm_data); int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt); int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt); +int iwl_uefi_get_wsss_table(struct iwl_fw_runtime *fwrt); +int iwl_uefi_get_ewss_table(struct iwl_fw_runtime *fwrt); int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt); int iwl_uefi_get_ppag_table(struct iwl_fw_runtime *fwrt); int iwl_uefi_get_tas_table(struct iwl_fw_runtime *fwrt, @@ -399,6 +403,16 @@ static inline int iwl_uefi_get_ewrd_table(struct iwl_fw_runtime *fwrt) return -ENOENT; } +static inline int iwl_uefi_get_wsss_table(struct iwl_fw_runtime *fwrt) +{ + return -ENOENT; +} + +static inline int iwl_uefi_get_ewss_table(struct iwl_fw_runtime *fwrt) +{ + return -ENOENT; +} + static inline int iwl_uefi_get_wgds_table(struct iwl_fw_runtime *fwrt) { return -ENOENT; From 915b6e9ffb0586d389b47821ce6deeab9ea5ec83 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:20 +0300 Subject: [PATCH 046/104] wifi: iwlwifi: pcie: drop gen1_2 prefix from several functions As a preparation of a future pcie-transport, we added a gen1_2 prefix to some functions to distinguish them from the new implementation. Since the new pcie-transport will not happen eventaully, remove this prefix from those functions. Link: https://patch.msgid.link/20260926201527.dc1a22771b0e.I20e77f228e1536c6eb327dc077b030dbea889ac2@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/iwl-trans.c | 10 +++++----- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +- .../intel/iwlwifi/pcie/gen1_2/internal.h | 19 +++++++++---------- .../intel/iwlwifi/pcie/gen1_2/trans.c | 11 +++++------ 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index a1545e9d2cd8..8cc8f6c4e934 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -333,14 +333,14 @@ IWL_EXPORT_SYMBOL(iwl_trans_send_cmd); struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) { - return iwl_pcie_gen1_2_alloc_tx_cmd(trans); + return iwl_pcie_alloc_tx_cmd(trans); } IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd); void iwl_trans_free_tx_cmd(struct iwl_trans *trans, struct iwl_device_tx_cmd *dev_cmd) { - iwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd); + iwl_pcie_free_tx_cmd(trans, dev_cmd); } IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd); @@ -395,7 +395,7 @@ void iwl_trans_op_mode_enter(struct iwl_trans *trans, WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd); - iwl_pcie_gen1_2_op_mode_enter(trans); + iwl_trans_pcie_op_mode_enter(trans); } IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter); @@ -821,13 +821,13 @@ IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported); bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans) { - return iwl_pcie_gen1_2_is_ltr_enabled(trans); + return iwl_pcie_is_ltr_enabled(trans); } IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled); int iwl_trans_activate_nic(struct iwl_trans *trans) { - return iwl_pcie_gen1_2_activate_nic(trans); + return iwl_pcie_activate_nic(trans); } IWL_EXPORT_SYMBOL(iwl_trans_activate_nic); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index a117c378b1f1..04a4fa8ddb79 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1188,7 +1188,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -EIO; } - return iwl_pci_gen1_2_probe(pdev, ent, mac_cfg, hw_base, hw_rev); + return _iwl_pci_probe(pdev, ent, mac_cfg, hw_base, hw_rev); } static void iwl_pci_remove(struct pci_dev *pdev) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index f0e70b0fedfe..ee3825954f65 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -850,7 +850,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans, } static inline struct iwl_device_tx_cmd * -iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans) +iwl_pcie_alloc_tx_cmd(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -858,8 +858,8 @@ iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans) } static inline void -iwl_pcie_gen1_2_free_tx_cmd(struct iwl_trans *trans, - struct iwl_device_tx_cmd *dev_cmd) +iwl_pcie_free_tx_cmd(struct iwl_trans *trans, + struct iwl_device_tx_cmd *dev_cmd) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -1132,7 +1132,7 @@ static inline void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) { } void iwl_pcie_rx_allocator_work(struct work_struct *data); /* common trans ops for all generations transports */ -void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans); +void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans); int _iwl_trans_pcie_start_hw(struct iwl_trans *trans); int iwl_trans_pcie_start_hw(struct iwl_trans *trans); void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans); @@ -1164,10 +1164,9 @@ void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans); void __releases(nic_access_nobh) iwl_trans_pcie_release_nic_access(struct iwl_trans *trans); void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power); -int iwl_pci_gen1_2_probe(struct pci_dev *pdev, - const struct pci_device_id *ent, - const struct iwl_mac_cfg *mac_cfg, - u8 __iomem *hw_base, u32 hw_rev); +int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, + const struct iwl_mac_cfg *mac_cfg, + u8 __iomem *hw_base, u32 hw_rev); void iwl_pcie_gen1_2_remove(struct iwl_trans *trans); /* transport gen 1 exported functions */ @@ -1193,7 +1192,7 @@ int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr, size_t size); void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr); void iwl_pcie_apply_destination(struct iwl_trans *trans); -int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans); +int iwl_pcie_activate_nic(struct iwl_trans *trans); /* transport gen 2 exported functions */ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, @@ -1223,7 +1222,7 @@ static inline bool iwl_pcie_gen1_is_pm_supported(struct iwl_trans *trans) return trans_pcie->pm_support; } -static inline bool iwl_pcie_gen1_2_is_ltr_enabled(struct iwl_trans *trans) +static inline bool iwl_pcie_is_ltr_enabled(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index 71c4746c61a6..0b46431ce68f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -1903,7 +1903,7 @@ void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val) iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); } -void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans) +void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -4076,10 +4076,9 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans) schedule_delayed_work(&trans_pcie->me_recheck_wk, HZ); } -int iwl_pci_gen1_2_probe(struct pci_dev *pdev, - const struct pci_device_id *ent, - const struct iwl_mac_cfg *mac_cfg, - u8 __iomem *hw_base, u32 hw_rev) +int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, + const struct iwl_mac_cfg *mac_cfg, + u8 __iomem *hw_base, u32 hw_rev) { const struct iwl_dev_info *dev_info; struct iwl_trans_info info = { @@ -4240,7 +4239,7 @@ void iwl_pcie_gen1_2_remove(struct iwl_trans *trans) iwl_trans_pcie_free(trans); } -int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans) +int iwl_pcie_activate_nic(struct iwl_trans *trans) { const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg; u32 poll_ready; From ac7f248012abc87b000d236a240df3431932daa1 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:21 +0300 Subject: [PATCH 047/104] wifi: iwlwifi: Revert "wifi: iwlwifi: gen1_2: move gen specific code to a function" This reverts commit df70a9a86eee ("wifi: iwlwifi: gen1_2: move gen specific code to a function"). The remove flow body was factored out into into a new function to prepare for a new pcie-transport, which will not happen eventually. Inline the code back. Link: https://patch.msgid.link/20260926201527.44edf3234ede.Ic19d96486253518e2107d91e512654596689a426@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 7 ++++++- .../net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h | 1 - .../net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 11 ----------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 04a4fa8ddb79..4fa514ba9975 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1194,11 +1194,16 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static void iwl_pci_remove(struct pci_dev *pdev) { struct iwl_trans *trans = pci_get_drvdata(pdev); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); if (!trans) return; - iwl_pcie_gen1_2_remove(trans); + cancel_delayed_work_sync(&trans_pcie->me_recheck_wk); + + iwl_drv_stop(trans->drv); + + iwl_trans_pcie_free(trans); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index ee3825954f65..cff02afa4e26 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1167,7 +1167,6 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power); int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, const struct iwl_mac_cfg *mac_cfg, u8 __iomem *hw_base, u32 hw_rev); -void iwl_pcie_gen1_2_remove(struct iwl_trans *trans); /* transport gen 1 exported functions */ void iwl_trans_pcie_fw_alive(struct iwl_trans *trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index 0b46431ce68f..db92c5c954e6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -4228,17 +4228,6 @@ int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, return ret; } -void iwl_pcie_gen1_2_remove(struct iwl_trans *trans) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - - cancel_delayed_work_sync(&trans_pcie->me_recheck_wk); - - iwl_drv_stop(trans->drv); - - iwl_trans_pcie_free(trans); -} - int iwl_pcie_activate_nic(struct iwl_trans *trans) { const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg; From fb15d5e1141511f93fc730fd8c721c501c2b420c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:22 +0300 Subject: [PATCH 048/104] wifi: iwlwifi: Revert "wifi: iwlwifi: pcie: move generation specific files to a folder" This reverts commit a6fafaedb5d6 ("wifi: iwlwifi: pcie: move generation specific files to a folder"). The pcie/gen1_2/ subfolder was introduced to prepare for a future pcie-transport, which will not happen eventually. Move all the files back to the pcie folder and remove the gen1_2 folder. Link: https://patch.msgid.link/20260926201527.91ac209ad70d.I25521996309a25ac779cb31f2c93477b25be9ac3@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/Makefile | 6 +++--- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/internal.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/rx.c | 2 +- .../wireless/intel/iwlwifi/pcie/{gen1_2 => }/trans-gen2.c | 4 ++-- .../net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/trans.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/tx-gen2.c | 0 drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/tx.c | 0 11 files changed, 12 insertions(+), 12 deletions(-) rename drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/internal.h (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/rx.c (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/trans-gen2.c (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/trans.c (99%) rename drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/tx-gen2.c (100%) rename drivers/net/wireless/intel/iwlwifi/pcie/{gen1_2 => }/tx.c (100%) diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index 2a74efe09cf0..6746281350e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -9,9 +9,9 @@ iwlwifi-objs += iwl-utils.o iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o # Bus -iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/drv.o pcie/utils.o -iwlwifi-objs += pcie/gen1_2/rx.o pcie/gen1_2/tx.o pcie/gen1_2/trans.o -iwlwifi-objs += pcie/gen1_2/trans-gen2.o pcie/gen1_2/tx-gen2.o +iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o +iwlwifi-objs += pcie/ctxt-info.o pcie/ctxt-info-v2.o pcie/trans-gen2.o pcie/tx-gen2.o +iwlwifi-objs += pcie/utils.o CFLAGS_pcie/drv.o += -Wno-override-init diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 8cc8f6c4e934..24bf45f06746 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -12,7 +12,7 @@ #include "iwl-drv.h" #include #include "fw/api/commands.h" -#include "pcie/gen1_2/internal.h" +#include "pcie/internal.h" #include "pcie/iwl-context-info-v2.h" struct iwl_trans_dev_restart_data { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index 1ea23d297713..c75210829ec9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -6,7 +6,7 @@ #include "iwl-trans.h" #include "iwl-fh.h" #include "iwl-context-info-v2.h" -#include "gen1_2/internal.h" +#include "internal.h" #include "iwl-prph.h" static const struct dmi_system_id dmi_force_scu_active_approved_list[] = { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 7f886200d693..23ec968577bd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -6,7 +6,7 @@ #include "iwl-trans.h" #include "iwl-fh.h" #include "iwl-context-info.h" -#include "gen1_2/internal.h" +#include "internal.h" #include "iwl-prph.h" static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 4fa514ba9975..905482419a9a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -15,7 +15,7 @@ #include "iwl-trans.h" #include "iwl-drv.h" #include "iwl-prph.h" -#include "gen1_2/internal.h" +#include "internal.h" #define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \ struct _struct) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h rename to drivers/net/wireless/intel/iwlwifi/pcie/internal.h index cff02afa4e26..e10aa8e7e061 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -22,7 +22,7 @@ #include "iwl-io.h" #include "iwl-op-mode.h" #include "iwl-drv.h" -#include "pcie/iwl-context-info.h" +#include "iwl-context-info.h" /* * RX related structures and functions diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c rename to drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 4631e11f2a96..eb70922cf516 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -12,7 +12,7 @@ #include "iwl-io.h" #include "internal.h" #include "iwl-op-mode.h" -#include "pcie/iwl-context-info-v2.h" +#include "iwl-context-info-v2.h" #include "fw/dbg.h" /****************************************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c rename to drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index f41cbe62e7aa..39dd963920b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -5,8 +5,8 @@ */ #include "iwl-trans.h" #include "iwl-prph.h" -#include "pcie/iwl-context-info.h" -#include "pcie/iwl-context-info-v2.h" +#include "iwl-context-info.h" +#include "iwl-context-info-v2.h" #include "internal.h" #include "fw/dbg.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c similarity index 99% rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c rename to drivers/net/wireless/intel/iwlwifi/pcie/trans.c index db92c5c954e6..4771cf3b3e11 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -28,7 +28,7 @@ #include "mei/iwl-mei.h" #include "internal.h" #include "iwl-fh.h" -#include "pcie/iwl-context-info-v2.h" +#include "iwl-context-info-v2.h" #include "pcie/utils.h" #define IWL_HOST_MON_BLOCK_PEMON 0x00 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c similarity index 100% rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx-gen2.c rename to drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c similarity index 100% rename from drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c rename to drivers/net/wireless/intel/iwlwifi/pcie/tx.c From 2395f2a298eec2abdb148d51fe2e0ccac431237f Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Sat, 26 Sep 2026 20:17:23 +0300 Subject: [PATCH 049/104] wifi: iwlwifi: send standalone SAR to firmware Plumb the standalone WRSS/EWSS SAR data and send the standalone profile to firmware. Add REDUCE_TX_POWER_CMD version 12 support with the IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS set_mode, and rename iwl_dev_tx_power_cmd_v11 to iwl_dev_tx_power_cmd_v12 to match the updated command layout. This enables higher transmit power limits for standalone firmware operation while preserving the existing concurrent SAR handling. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260926201527.d5315e93c1ce.Ic02190e91e795dcfe660710721b47de71f2b2c86@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/power.h | 14 ++-- .../wireless/intel/iwlwifi/fw/regulatory.c | 26 ++++-- .../wireless/intel/iwlwifi/fw/regulatory.h | 4 +- .../net/wireless/intel/iwlwifi/mld/power.c | 2 +- .../wireless/intel/iwlwifi/mld/regulatory.c | 80 +++++++++++++++++-- .../wireless/intel/iwlwifi/mld/regulatory.h | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 3 +- 7 files changed, 107 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 115e65ba19f8..4d54a95b98ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -300,7 +300,8 @@ enum iwl_dev_tx_power_cmd_mode { IWL_TX_POWER_MODE_SET_ACK = 3, IWL_TX_POWER_MODE_SET_SAR_TIMER = 4, IWL_TX_POWER_MODE_SET_SAR_TIMER_DEFAULT_TABLE = 5, -}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_5 */; + IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS = 8, /* cmd ver 12+ */ +}; /* TX_POWER_REDUCED_FLAGS_TYPE_API_E_VER_2 */; #define IWL_NUM_CHAIN_TABLES 1 #define IWL_NUM_CHAIN_TABLES_V2 2 @@ -464,31 +465,34 @@ struct iwl_dev_tx_power_cmd_v10 { __le32 flags; } __packed; /* TX_REDUCED_POWER_API_S_VER_10 */ -struct iwl_dev_tx_power_cmd_v11 { +struct iwl_dev_tx_power_cmd_v12 { __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V3]; u8 per_chain_restriction_changed; u8 reserved; __le32 timer_period; __le32 flags; -} __packed; /* TX_REDUCED_POWER_API_S_VER_11 */ +} __packed; /* TX_REDUCED_POWER_API_S_VER_11 + * TX_REDUCED_POWER_API_S_VER_12 + */ /* * struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion) * @common: common part of the command * @v9: version 9 part of the command * @v10: version 10 part of the command - * @v11: version 11 part of the command + * @v12: version 12 part of the command (also covers v11) */ struct iwl_dev_tx_power_cmd { struct iwl_dev_tx_power_common common; union { struct iwl_dev_tx_power_cmd_v9 v9; struct iwl_dev_tx_power_cmd_v10 v10; - struct iwl_dev_tx_power_cmd_v11 v11; + struct iwl_dev_tx_power_cmd_v12 v12; }; } __packed; /* TX_REDUCED_POWER_API_S_VER_9 * TX_REDUCED_POWER_API_S_VER_10 * TX_REDUCED_POWER_API_S_VER_11 + * TX_REDUCED_POWER_API_S_VER_12 */ #define IWL_NUM_GEO_PROFILES 3 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 137303e4a29b..27a5804dbd73 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -247,17 +247,22 @@ IWL_EXPORT_SYMBOL(iwl_sar_geo_fill_table); static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, __le16 *per_chain, u32 n_subbands, - int prof_a, int prof_b) + int prof_a, int prof_b, + const struct iwl_sar_profile *profiles, + bool is_standalone) { int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b }; int i, j; + BUILD_BUG_ON(ARRAY_SIZE(fwrt->sar_standalone_profiles[0].chains[0].subbands) != + ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands)); + if (WARN_ON_ONCE(n_subbands > ARRAY_SIZE(fwrt->sar_profiles[0].chains[0].subbands))) return -EINVAL; for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) { - struct iwl_sar_profile *prof; + const struct iwl_sar_profile *prof; /* don't allow SAR to be disabled (profile 0 means disable) */ if (profs[i] == 0) @@ -268,11 +273,13 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, return -EINVAL; /* profiles go from 1 to 4, so decrement to access the array */ - prof = &fwrt->sar_profiles[profs[i] - 1]; + prof = &profiles[profs[i] - 1]; /* if the profile is disabled, do nothing */ if (!prof->enabled) { - IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n", + IWL_DEBUG_RADIO(fwrt, + "SAR %sprofile %d is disabled.\n", + is_standalone ? "standalone " : "", profs[i]); /* * if one of the profiles is disabled, we @@ -282,8 +289,8 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, return 1; } - IWL_DEBUG_INFO(fwrt, - "SAR EWRD: chain %d profile index %d\n", + IWL_DEBUG_INFO(fwrt, "SAR %s: chain %d profile index %d\n", + is_standalone ? "standalone" : "EWRD", i, profs[i]); IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i); for (j = 0; j < n_subbands; j++) { @@ -299,14 +306,17 @@ static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt, __le16 *per_chain, u32 n_tables, u32 n_subbands, - int prof_a, int prof_b) + int prof_a, int prof_b, + const struct iwl_sar_profile *profiles, + bool is_standalone) { int i, ret = 0; for (i = 0; i < n_tables; i++) { ret = iwl_sar_fill_table(fwrt, &per_chain[i * n_subbands * BIOS_SAR_NUM_CHAINS], - n_subbands, prof_a, prof_b); + n_subbands, prof_a, prof_b, profiles, + is_standalone); if (ret) break; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index bd7ea0ff3d19..e32e107812b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -210,7 +210,9 @@ int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt, int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt, __le16 *per_chain, u32 n_tables, u32 n_subbands, - int prof_a, int prof_b); + int prof_a, int prof_b, + const struct iwl_sar_profile *profiles, + bool is_standalone); bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c index 2387f3da5185..6fcbb1a2e8a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c @@ -525,7 +525,7 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld, .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK), .common.pwr_restriction = cpu_to_le16(u_tx_power), }; - int len = sizeof(cmd.common) + sizeof(cmd.v11); + int len = sizeof(cmd.common) + sizeof(cmd.v12); if (iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 10) == 10) len = sizeof(cmd.common) + sizeof(cmd.v10); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index 9f395a1fd12a..8a20d7622329 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -74,6 +74,21 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld) "EWRD SAR BIOS table invalid or unavailable. (%d)\n", ret); + ret = iwl_bios_get_wsss_table(&mld->fwrt); + if (ret < 0) + IWL_DEBUG_RADIO(mld, + "WSSS (WRDS Standalone) SAR BIOS table invalid or unavailable. (%d)\n", + ret); + + if (!ret) { + /* EWSS only extends the standalone SAR profiles from WSSS. */ + ret = iwl_bios_get_ewss_table(&mld->fwrt); + if (ret < 0) + IWL_DEBUG_RADIO(mld, + "EWSS (EWRD Standalone) SAR BIOS table invalid or unavailable. (%d)\n", + ret); + } + ret = iwl_bios_get_wgds_table(&mld->fwrt); if (ret < 0) IWL_DEBUG_RADIO(mld, @@ -135,7 +150,9 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld) return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, cmd_size); } -int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) +static int +iwl_mld_config_sar_concurrent_profile(struct iwl_mld *mld, int prof_a, + int prof_b) { struct iwl_dev_tx_power_cmd cmd = { .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS), @@ -152,8 +169,9 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) num_subbands = IWL_NUM_SUB_BANDS_V2; break; case 11: - cmd.v11.flags = cpu_to_le32(mld->fwrt.reduced_power_flags); - cmd_size = sizeof(cmd.common) + sizeof(cmd.v11); + case 12: + cmd.v12.flags = cpu_to_le32(mld->fwrt.reduced_power_flags); + cmd_size = sizeof(cmd.common) + sizeof(cmd.v12); num_subbands = IWL_NUM_SUB_BANDS_V3; break; default: @@ -163,12 +181,13 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) } /* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */ - /* v10 and v11 have the same position for per_chain */ - BUILD_BUG_ON(offsetof(typeof(cmd), v11.per_chain) != + /* v10 and v12 have the same position for per_chain */ + BUILD_BUG_ON(offsetof(typeof(cmd), v12.per_chain) != offsetof(typeof(cmd), v10.per_chain)); - ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v11.per_chain[0][0][0], + ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v12.per_chain[0][0][0], IWL_NUM_CHAIN_TABLES, num_subbands, - prof_a, prof_b); + prof_a, prof_b, + mld->fwrt.sar_profiles, false); /* return on error or if the profile is disabled (positive number) */ if (ret) return ret; @@ -176,6 +195,51 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd, cmd_size); } +static int iwl_mld_config_sar_standalone_profile(struct iwl_mld *mld, + int prof_a, int prof_b) +{ + struct iwl_dev_tx_power_cmd cmd = { + .common.set_mode = + cpu_to_le32(IWL_TX_POWER_MODE_SET_STANDALONE_CHAINS), + }; + int ret; + + /* standalone per-chain SAR limits require cmd version 12 */ + if (iwl_fw_lookup_cmd_ver(mld->fw, REDUCE_TX_POWER_CMD, 10) != 12) + return 0; + + ret = iwl_sar_fill_profile(&mld->fwrt, + &cmd.v12.per_chain[0][0][0], + IWL_NUM_CHAIN_TABLES, + IWL_NUM_SUB_BANDS_V3, + prof_a, prof_b, + mld->fwrt.sar_standalone_profiles, + true); + /* return on error or if the standalone profile is disabled */ + if (ret) + return ret; + + return iwl_mld_send_cmd_pdu(mld, REDUCE_TX_POWER_CMD, &cmd, + sizeof(cmd.common) + sizeof(cmd.v12)); +} + +int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b) +{ + int ret; + + ret = iwl_mld_config_sar_concurrent_profile(mld, prof_a, prof_b); + /* return on error or if the profile is disabled (positive number) */ + if (ret) + return ret; + + ret = iwl_mld_config_sar_standalone_profile(mld, prof_a, prof_b); + /* standalone profile is optional and may be disabled (positive number) */ + if (ret < 0) + return ret; + + return 0; +} + int iwl_mld_init_sar(struct iwl_mld *mld) { int chain_a_prof = 1; @@ -190,7 +254,7 @@ int iwl_mld_init_sar(struct iwl_mld *mld) chain_b_prof = mld->fwrt.sar_chain_b_profile; } - ret = iwl_mld_config_sar_profile(mld, chain_a_prof, chain_b_prof); + ret = iwl_mld_config_sar_profiles(mld, chain_a_prof, chain_b_prof); if (ret < 0) return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h index 5498c19789f4..0877b951f2e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #ifndef __iwl_mld_regulatory_h__ #define __iwl_mld_regulatory_h__ @@ -18,6 +18,6 @@ int iwl_mld_init_sgom(struct iwl_mld *mld); int iwl_mld_init_sar(struct iwl_mld *mld); -int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b); +int iwl_mld_config_sar_profiles(struct iwl_mld *mld, int prof_a, int prof_b); #endif /* __iwl_mld_regulatory_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 0b5b41223a8a..c3402f5e47a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -911,7 +911,8 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) ret = iwl_sar_fill_profile(&mvm->fwrt, per_chain, IWL_NUM_CHAIN_TABLES, - n_subbands, prof_a, prof_b); + n_subbands, prof_a, prof_b, + mvm->fwrt.sar_profiles, false); /* return on error or if the profile is disabled (positive number) */ if (ret) From c27b72f04d00697ea8452cc7585ef1a6f7353db6 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Sat, 26 Sep 2026 20:17:24 +0300 Subject: [PATCH 050/104] wifi: iwlwifi: uefi: Fix SAR enable check to use mode parameter correctly The iwl_uefi_set_sar_profile() function was receiving a bool parameter, which would treat any non-zero value as enabled. This is incorrect because the SAR mode value contains additional bits beyond the enable flag. Change the parameter from bool enabled to u32 mode and properly extract the enable bit using IWL_SAR_ENABLE_MSK bitmask. This ensures that only the designated enable bit determines whether SAR is enabled, not arbitrary non-zero values. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260926201527.60160602581b.Ib184c201e677cb6d95f64e725a1e39148234fa41@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 79fd95d08732..86825318c543 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -549,7 +549,7 @@ IWL_EXPORT_SYMBOL(iwl_uefi_get_uneb_table); static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles, const u8 *vals, u8 prof_index, - u8 num_subbands, bool enabled) + u8 num_subbands, u32 mode) { struct iwl_sar_profile *sar_prof = &profiles[prof_index]; @@ -573,7 +573,7 @@ static void iwl_uefi_set_sar_profile(struct iwl_sar_profile *profiles, vals[chain * num_subbands + subband]; } - sar_prof->enabled = enabled & IWL_SAR_ENABLE_MSK; + sar_prof->enabled = mode & IWL_SAR_ENABLE_MSK; } int iwl_uefi_get_wrds_table(struct iwl_fw_runtime *fwrt) From c9e7a64a7376700f712642cf8b4a122faad47069 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Sat, 26 Sep 2026 20:17:25 +0300 Subject: [PATCH 051/104] wifi: iwlwifi: fw: harden UEFI reduced-power TLV parsing UEFI reduced-power parsing advanced by ALIGN(tlv_len, 4) but validated only tlv_len. When remaining bytes were between these values, len could underflow and parsing could continue past the buffer boundary. Validate remaining bytes against the aligned length before advancing in both TLV walkers. Signed-off-by: Pagadala Yesu Anjaneyulu Assisted-by: GitHubCopilot:GPT-5.3-Codex Link: https://patch.msgid.link/20260926201527.2552432e98e8.I570750f27d9530d4c76922d2699a272d9c60a0ab@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 47 ++++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 86825318c543..872df8f6c375 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -251,15 +251,24 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, memset(pnvm_data, 0, sizeof(*pnvm_data)); while (len >= sizeof(*tlv)) { - u32 tlv_len, tlv_type; + u32 tlv_len, tlv_type, tlv_len_aligned; len -= sizeof(*tlv); tlv = (const void *)data; tlv_len = le32_to_cpu(tlv->length); tlv_type = le32_to_cpu(tlv->type); + tlv_len_aligned = ALIGN(tlv_len, 4); - if (len < tlv_len) { + /* Make sure ALIGN() did not overflow for a malformed TLV length. */ + if (tlv_len_aligned < tlv_len) { + IWL_ERR(trans, + "TLV len overflows on alignment: %u\n", + tlv_len); + return -EINVAL; + } + + if (len < tlv_len_aligned) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); return -EINVAL; @@ -278,13 +287,13 @@ static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, "New REDUCE_POWER section started, stop parsing.\n"); goto done; default: - IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %d\n", + IWL_DEBUG_FW(trans, "Found TLV 0x%0x, len %u\n", tlv_type, tlv_len); break; } - len -= ALIGN(tlv_len, 4); - data += ALIGN(tlv_len, 4); + len -= tlv_len_aligned; + data += tlv_len_aligned; } done: @@ -305,15 +314,24 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n"); while (len >= sizeof(*tlv)) { - u32 tlv_len, tlv_type; + u32 tlv_len, tlv_type, tlv_len_aligned; len -= sizeof(*tlv); tlv = (const void *)data; tlv_len = le32_to_cpu(tlv->length); tlv_type = le32_to_cpu(tlv->type); + tlv_len_aligned = ALIGN(tlv_len, 4); - if (len < tlv_len) { + /* Make sure ALIGN() did not overflow for a malformed TLV length. */ + if (tlv_len_aligned < tlv_len) { + IWL_ERR(trans, + "TLV len overflows on alignment: %u\n", + tlv_len); + return -EINVAL; + } + + if (len < tlv_len_aligned) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); return -EINVAL; @@ -323,22 +341,23 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, const struct iwl_sku_id *tlv_sku_id = (const void *)(data + sizeof(*tlv)); - IWL_DEBUG_FW(trans, - "Got IWL_UCODE_TLV_PNVM_SKU len %d\n", - tlv_len); if (tlv_len < sizeof(*tlv_sku_id)) { IWL_ERR(trans, "invalid PNVM SKU TLV len: %u\n", tlv_len); return -EINVAL; } + IWL_DEBUG_FW(trans, + "Got IWL_UCODE_TLV_PNVM_SKU len %u\n", + tlv_len); + IWL_DEBUG_FW(trans, "sku_id 0x%0x 0x%0x 0x%0x\n", le32_to_cpu(tlv_sku_id->data[0]), le32_to_cpu(tlv_sku_id->data[1]), le32_to_cpu(tlv_sku_id->data[2])); - data += sizeof(*tlv) + ALIGN(tlv_len, 4); - len -= ALIGN(tlv_len, 4); + data += sizeof(*tlv) + tlv_len_aligned; + len -= tlv_len_aligned; if (sku_id[0] == tlv_sku_id->data[0] && sku_id[1] == tlv_sku_id->data[1] && @@ -352,8 +371,8 @@ int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, IWL_DEBUG_FW(trans, "SKU ID didn't match!\n"); } } else { - data += sizeof(*tlv) + ALIGN(tlv_len, 4); - len -= ALIGN(tlv_len, 4); + data += sizeof(*tlv) + tlv_len_aligned; + len -= tlv_len_aligned; } } From d57bd34a6d4ee7ced4c2f115396e20b2348d1076 Mon Sep 17 00:00:00 2001 From: Pagadala Yesu Anjaneyulu Date: Sat, 26 Sep 2026 20:17:26 +0300 Subject: [PATCH 052/104] wifi: iwlwifi: fw: add Samsung to TAS and PPAG allow lists Allow platforms reporting the exact manufacturer string "Samsung" to use TAS and PPAG, while retaining the existing Samsung Electronics entry. Signed-off-by: Pagadala Yesu Anjaneyulu Link: https://patch.msgid.link/20260926201527.e2e2e1f720af.I18a7292b5a8bd878d074b114b45ce99e1309897e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/regulatory.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 27a5804dbd73..c7de45323935 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -49,11 +49,16 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), }, }, - { .ident = "SAMSUNG", + { .ident = "SAMSUNG_ELECTRONICS", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), }, }, + { .ident = "SAMSUNG", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Samsung"), + }, + }, { .ident = "MSFT", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), @@ -126,10 +131,15 @@ static const struct dmi_system_id dmi_tas_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), }, }, - { .ident = "SAMSUNG", + { .ident = "SAMSUNG_ELECTRONICS", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), }, + }, + { .ident = "SAMSUNG", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Samsung"), + }, }, { .ident = "LENOVO", .matches = { From cc014b0cb9b65e0dff8febee69265d4273b1f5b7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 26 Sep 2026 20:17:27 +0300 Subject: [PATCH 053/104] wifi: iwlwifi: pcie: order RX reads after the write pointer iwl_pcie_rx_handle() reads the last closed RB index from rb_stts and then reads the completion descriptor and the RB contents that this index makes visible. Nothing orders those two reads: there is no barrier, the descriptor address derives from rxq->read rather than from the index just read, so there is no address dependency, and the "while (i != r)" test is only a control dependency, which does not order loads on arm64. The CPU can therefore speculate past the loop test, perform the completion descriptor load early and sample the value from before the device's DMA, then resolve the rb_stts load to the value from after it. On arm64 (Jetson AGX Orin) this showed up as recurring "Invalid rxb from HW " naming an in-range rbid the driver still owned, and "frame on invalid queue" for an RB tagged with the queue that used it before the wrap. Both force an NMI and a firmware restart. x86 never shows it because loads are not reordered with loads there. Add a dma_rmb() after reading the write pointer, as other NIC drivers do when consuming a DMA descriptor ring. It is a no-op on x86 and a dmb on arm64. Verified to stop the warnings on Orin. Signed-off-by: Emmanuel Grumbach Assisted-by: GitHub-Copilot:claude-opus-5 Link: https://patch.msgid.link/20260926201527.1bff8cebef69.I24dec81516e37a33674e87ed3359c41e59d12e5e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index eb70922cf516..d1ef0365b932 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1519,6 +1519,11 @@ static int iwl_pcie_rx_handle(struct iwl_trans *trans, int queue, int budget) r = iwl_get_closed_rb_stts(trans, rxq); i = rxq->read; + /* Order the read of the write pointer before any read of the + * completion descriptors and of the RB contents it makes visible. + */ + dma_rmb(); + /* W/A 9000 device step A0 wrap-around bug */ r &= (rxq->queue_size - 1); From 950b3e44cae72b687ba91f37ee67860c35a065bd Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:28 +0300 Subject: [PATCH 054/104] wifi: iwlwifi: pcie: remove iwl_dbgfs_fh_reg_read This is no longer needed, and adds lots of parsing code Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260926201527.3e2f229ac9f6.I122eaf364743ffc42bd18a84a766d7920ec5700d@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 177 ------------------ drivers/net/wireless/intel/iwlwifi/iwl-io.h | 3 - .../net/wireless/intel/iwlwifi/pcie/trans.c | 20 -- 3 files changed, 200 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index bb746112ddad..544b8e686dfe 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -11,7 +11,6 @@ #include "iwl-csr.h" #include "iwl-debug.h" #include "iwl-prph.h" -#include "iwl-fh.h" void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) { @@ -235,182 +234,6 @@ void iwl_force_nmi(struct iwl_trans *trans) } IWL_EXPORT_SYMBOL(iwl_force_nmi); -static const char *get_rfh_string(int cmd) -{ -#define IWL_CMD(x) case x: return #x -#define IWL_CMD_MQ(arg, reg, q) { if (arg == reg(q)) return #reg; } - - int i; - - for (i = 0; i < IWL_MAX_RX_HW_QUEUES; i++) { - IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_BA_LSB, i); - IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_WIDX, i); - IWL_CMD_MQ(cmd, RFH_Q_FRBDCB_RIDX, i); - IWL_CMD_MQ(cmd, RFH_Q_URBD_STTS_WPTR_LSB, i); - } - - switch (cmd) { - IWL_CMD(RFH_RXF_DMA_CFG); - IWL_CMD(RFH_GEN_CFG); - IWL_CMD(RFH_GEN_STATUS); - IWL_CMD(FH_TSSR_TX_STATUS_REG); - IWL_CMD(FH_TSSR_TX_ERROR_REG); - default: - return "UNKNOWN"; - } -#undef IWL_CMD_MQ -} - -struct reg { - u32 addr; - bool is64; -}; - -static int iwl_dump_rfh(struct iwl_trans *trans, char **buf) -{ - int i, q; - int num_q = trans->info.num_rxqs; - static const u32 rfh_tbl[] = { - RFH_RXF_DMA_CFG, - RFH_GEN_CFG, - RFH_GEN_STATUS, - FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_ERROR_REG, - }; - static const struct reg rfh_mq_tbl[] = { - { RFH_Q0_FRBDCB_BA_LSB, true }, - { RFH_Q0_FRBDCB_WIDX, false }, - { RFH_Q0_FRBDCB_RIDX, false }, - { RFH_Q0_URBD_STTS_WPTR_LSB, true }, - }; - -#ifdef CONFIG_IWLWIFI_DEBUGFS - if (buf) { - int pos = 0; - /* - * Register (up to 34 for name + 8 blank/q for MQ): 40 chars - * Colon + space: 2 characters - * 0X%08x: 10 characters - * New line: 1 character - * Total of 53 characters - */ - size_t bufsz = ARRAY_SIZE(rfh_tbl) * 53 + - ARRAY_SIZE(rfh_mq_tbl) * 53 * num_q + 40; - - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - - pos += scnprintf(*buf + pos, bufsz - pos, - "RFH register values:\n"); - - for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++) - pos += scnprintf(*buf + pos, bufsz - pos, - "%40s: 0X%08x\n", - get_rfh_string(rfh_tbl[i]), - iwl_read_prph(trans, rfh_tbl[i])); - - for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++) - for (q = 0; q < num_q; q++) { - u32 addr = rfh_mq_tbl[i].addr; - - addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4); - pos += scnprintf(*buf + pos, bufsz - pos, - "%34s(q %2d): 0X%08x\n", - get_rfh_string(addr), q, - iwl_read_prph(trans, addr)); - } - - return pos; - } -#endif - - IWL_ERR(trans, "RFH register values:\n"); - for (i = 0; i < ARRAY_SIZE(rfh_tbl); i++) - IWL_ERR(trans, " %34s: 0X%08x\n", - get_rfh_string(rfh_tbl[i]), - iwl_read_prph(trans, rfh_tbl[i])); - - for (i = 0; i < ARRAY_SIZE(rfh_mq_tbl); i++) - for (q = 0; q < num_q; q++) { - u32 addr = rfh_mq_tbl[i].addr; - - addr += q * (rfh_mq_tbl[i].is64 ? 8 : 4); - IWL_ERR(trans, " %34s(q %d): 0X%08x\n", - get_rfh_string(addr), q, - iwl_read_prph(trans, addr)); - } - - return 0; -} - -static const char *get_fh_string(int cmd) -{ - switch (cmd) { - IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); - IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); - IWL_CMD(FH_RSCSR_CHNL0_WPTR); - IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); - IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); - IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); - IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); - IWL_CMD(FH_TSSR_TX_STATUS_REG); - IWL_CMD(FH_TSSR_TX_ERROR_REG); - default: - return "UNKNOWN"; - } -#undef IWL_CMD -} - -int iwl_dump_fh(struct iwl_trans *trans, char **buf) -{ - int i; - static const u32 fh_tbl[] = { - FH_RSCSR_CHNL0_STTS_WPTR_REG, - FH_RSCSR_CHNL0_RBDCB_BASE_REG, - FH_RSCSR_CHNL0_WPTR, - FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_MEM_RSSR_SHARED_CTRL_REG, - FH_MEM_RSSR_RX_STATUS_REG, - FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, - FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_ERROR_REG - }; - - if (trans->mac_cfg->mq_rx_supported) - return iwl_dump_rfh(trans, buf); - -#ifdef CONFIG_IWLWIFI_DEBUGFS - if (buf) { - int pos = 0; - size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; - - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - - pos += scnprintf(*buf + pos, bufsz - pos, - "FH register values:\n"); - - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) - pos += scnprintf(*buf + pos, bufsz - pos, - " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(trans, fh_tbl[i])); - - return pos; - } -#endif - - IWL_ERR(trans, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) - IWL_ERR(trans, " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(trans, fh_tbl[i])); - - return 0; -} - void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, u32 sw_err_bit) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index 6dce2e5267a6..e66b0c2a0467 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -59,9 +59,6 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); void iwl_force_nmi(struct iwl_trans *trans); -/* Error handling */ -int iwl_dump_fh(struct iwl_trans *trans, char **buf); - /* * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from * device family AX200. So peripheries used in families above and below AX200 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 4771cf3b3e11..97bbc3faa98c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3016,24 +3016,6 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, return count; } -static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_trans *trans = file->private_data; - char *buf = NULL; - ssize_t ret; - - ret = iwl_dump_fh(trans, &buf); - if (ret < 0) - return ret; - if (!buf) - return -EINVAL; - ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); - kfree(buf); - return ret; -} - static ssize_t iwl_dbgfs_rfkill_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -3133,7 +3115,6 @@ static ssize_t iwl_dbgfs_reset_write(struct file *file, } DEBUGFS_READ_WRITE_FILE_OPS(interrupt); -DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_FILE_OPS(rx_queue); DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(rfkill); @@ -3157,7 +3138,6 @@ void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) DEBUGFS_ADD_FILE(tx_queue, dir, 0400); DEBUGFS_ADD_FILE(interrupt, dir, 0600); DEBUGFS_ADD_FILE(csr, dir, 0200); - DEBUGFS_ADD_FILE(fh_reg, dir, 0400); DEBUGFS_ADD_FILE(rfkill, dir, 0600); DEBUGFS_ADD_FILE(rf, dir, 0400); DEBUGFS_ADD_FILE(reset, dir, 0200); From b6f39b3c8f0fd9d7864b197b77f0b29fc013ce82 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:29 +0300 Subject: [PATCH 055/104] wifi: iwlwifi: open code iwl_trans_sync_nmi_with_addr() iwl_trans_sync_nmi_with_addr() had a single caller, iwl_trans_pcie_sync_nmi(). There is no reason to keep it as a separate exported function in iwl-io.c, so embed its body directly in the caller and drop the now-unused declaration. Link: https://patch.msgid.link/20260926201527.a2048732f45f.I23611eb40d875c6a69df0c08add3834f6f7d8528@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 36 ------------------- .../net/wireless/intel/iwlwifi/iwl-trans.c | 5 --- .../net/wireless/intel/iwlwifi/iwl-trans.h | 5 --- .../net/wireless/intel/iwlwifi/pcie/trans.c | 33 +++++++++++++++-- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 544b8e686dfe..ef4d97ef0b1b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -233,39 +233,3 @@ void iwl_force_nmi(struct iwl_trans *trans) UREG_DOORBELL_TO_ISR6_NMI_BIT); } IWL_EXPORT_SYMBOL(iwl_force_nmi); - -void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, - u32 sw_err_bit) -{ - unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT; - bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status); - - /* if the interrupts were already disabled, there is no point in - * calling iwl_disable_interrupts - */ - if (interrupts_enabled) - iwl_trans_interrupts(trans, false); - - iwl_force_nmi(trans); - while (time_after(timeout, jiffies)) { - u32 inta_hw = iwl_read32(trans, inta_addr); - - /* Error detected by uCode */ - if (inta_hw & sw_err_bit) { - /* Clear causes register */ - iwl_write32(trans, inta_addr, inta_hw & sw_err_bit); - break; - } - - mdelay(1); - } - - /* enable interrupts only if there were already enabled before this - * function to avoid a case were the driver enable interrupts before - * proper configurations were made - */ - if (interrupts_enabled) - iwl_trans_interrupts(trans, true); - - iwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED); -} diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 24bf45f06746..ad43cf53e8c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -523,11 +523,6 @@ int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset) } IWL_EXPORT_SYMBOL(iwl_trans_d3_resume); -void iwl_trans_interrupts(struct iwl_trans *trans, bool enable) -{ - iwl_trans_pci_interrupts(trans, enable); -} - void iwl_trans_sync_nmi(struct iwl_trans *trans) { iwl_trans_pcie_sync_nmi(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index dfad839dd2e6..f933cba7eee8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1055,9 +1055,6 @@ static inline bool iwl_trans_fw_running(struct iwl_trans *trans) void iwl_trans_sync_nmi(struct iwl_trans *trans); -void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, - u32 sw_err_bit); - int iwl_trans_load_pnvm(struct iwl_trans *trans, const struct iwl_pnvm_image *pnvm_data, const struct iwl_ucode_capabilities *capa); @@ -1078,8 +1075,6 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans) trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED; } -void iwl_trans_interrupts(struct iwl_trans *trans, bool enable); - int iwl_trans_activate_nic(struct iwl_trans *trans); static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 97bbc3faa98c..48ae2440cfe1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3574,8 +3574,10 @@ void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable) void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans) { - u32 inta_addr, sw_err_bit; + bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT; + u32 inta_addr, sw_err_bit; if (trans_pcie->msix_enabled) { inta_addr = CSR_MSIX_HW_INT_CAUSES_AD; @@ -3588,7 +3590,34 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans) sw_err_bit = CSR_INT_BIT_SW_ERR; } - iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit); + /* if the interrupts were already disabled, there is no point in + * calling iwl_disable_interrupts + */ + if (interrupts_enabled) + iwl_trans_pci_interrupts(trans, false); + + iwl_force_nmi(trans); + while (time_after(timeout, jiffies)) { + u32 inta_hw = iwl_read32(trans, inta_addr); + + /* Error detected by uCode */ + if (inta_hw & sw_err_bit) { + /* Clear causes register */ + iwl_write32(trans, inta_addr, inta_hw & sw_err_bit); + break; + } + + mdelay(1); + } + + /* enable interrupts only if there were already enabled before this + * function to avoid a case were the driver enable interrupts before + * proper configurations were made + */ + if (interrupts_enabled) + iwl_trans_pci_interrupts(trans, true); + + iwl_trans_fw_error(trans, IWL_ERR_TYPE_NMI_FORCED); } static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans) From a1cbc81c1278dac51fddc938bfbb4e5e724d59bd Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:30 +0300 Subject: [PATCH 056/104] wifi: iwlwifi: move iwl_force_nmi() to where it belongs iwl_force_nmi() forces a firmware NMI and has nothing to do with the register I/O helpers in iwl-io.c. Move it to iwl-trans.c and rename it to iwl_trans_force_nmi() to match the transport API naming. Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260926201527.c3312fb2f2cc.Ie0d3ea9b23e35d7ff4b67e129c7b97ccb7c6c453@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 5 +++-- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 18 ------------------ drivers/net/wireless/intel/iwlwifi/iwl-io.h | 1 - drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 18 ++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 ++ .../net/wireless/intel/iwlwifi/mld/debugfs.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/trans.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 4 ++-- 12 files changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 8c8d15ac71ac..897538066b7d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2055,7 +2055,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, if (trigger->flags & IWL_FW_DBG_FORCE_RESTART) { IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", trig); - iwl_force_nmi(fwrt->trans); + iwl_trans_force_nmi(fwrt->trans); return 0; } @@ -2233,7 +2233,8 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) } if (fwrt->trans->dbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY) - iwl_force_nmi(fwrt->trans); + iwl_trans_force_nmi(fwrt->trans); + out: if (iwl_trans_dbg_ini_valid(fwrt->trans)) { iwl_fw_error_dump_data_free(dump_data); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index ef4d97ef0b1b..cc6bf4ea5055 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -10,7 +10,6 @@ #include "iwl-io.h" #include "iwl-csr.h" #include "iwl-debug.h" -#include "iwl-prph.h" void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) { @@ -216,20 +215,3 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) } } IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); - -void iwl_force_nmi(struct iwl_trans *trans) -{ - if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000) - iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG, - DEVICE_SET_NMI_VAL_DRV, 1); - else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, - UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER); - else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ) - iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, - UREG_DOORBELL_TO_ISR6_NMI_BIT); - else - iwl_write32(trans, CSR_DOORBELL_VECTOR, - UREG_DOORBELL_TO_ISR6_NMI_BIT); -} -IWL_EXPORT_SYMBOL(iwl_force_nmi); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index e66b0c2a0467..e4a9f2ba0de9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -57,7 +57,6 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, u32 bits, u32 mask); void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); -void iwl_force_nmi(struct iwl_trans *trans); /* * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index ad43cf53e8c5..efe657857772 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -10,6 +10,7 @@ #include "iwl-trans.h" #include "iwl-drv.h" +#include "iwl-prph.h" #include #include "fw/api/commands.h" #include "pcie/internal.h" @@ -452,6 +453,23 @@ void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) return iwl_trans_pcie_write_prph(trans, ofs, val); } +void iwl_trans_force_nmi(struct iwl_trans *trans) +{ + if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000) + iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG, + DEVICE_SET_NMI_VAL_DRV, 1); + else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, + UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER); + else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ) + iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, + UREG_DOORBELL_TO_ISR6_NMI_BIT); + else + iwl_write32(trans, CSR_DOORBELL_VECTOR, + UREG_DOORBELL_TO_ISR6_NMI_BIT); +} +IWL_EXPORT_SYMBOL(iwl_trans_force_nmi); + int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index f933cba7eee8..a7bb6cee8188 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1055,6 +1055,8 @@ static inline bool iwl_trans_fw_running(struct iwl_trans *trans) void iwl_trans_sync_nmi(struct iwl_trans *trans); +void iwl_trans_force_nmi(struct iwl_trans *trans); + int iwl_trans_load_pnvm(struct iwl_trans *trans, const struct iwl_pnvm_image *pnvm_data, const struct iwl_ucode_capabilities *capa); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c index 351a4f177e92..dd4bf7cb6a79 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c @@ -69,7 +69,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mld *mld, char *buf, if (count == 6 && !strcmp(buf, "nolog\n")) mld->fw_status.do_not_dump_once = true; - iwl_force_nmi(mld->trans); + iwl_trans_force_nmi(mld->trans); return count; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 4db0f29dd21a..06502f57e823 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1102,7 +1102,7 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf, if (count == 6 && !strcmp(buf, "nolog\n")) set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status); - iwl_force_nmi(mvm->trans); + iwl_trans_force_nmi(mvm->trans); return count; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 5bd246e37943..a4f3d3c2bd35 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -5258,7 +5258,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, out_restart: /* things keep failing, better restart the hw */ - iwl_force_nmi(mvm->trans); + iwl_trans_force_nmi(mvm->trans); return ret; } @@ -5294,7 +5294,7 @@ iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm, out_restart: /* things keep failing, better restart the hw */ - iwl_force_nmi(mvm->trans); + iwl_trans_force_nmi(mvm->trans); return ret; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 817c6dacfacc..a94eaca0b3ed 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -2703,7 +2703,7 @@ void iwl_mvm_scan_timeout_wk(struct work_struct *work) IWL_ERR(mvm, "regular scan timed out\n"); - iwl_force_nmi(mvm->trans); + iwl_trans_force_nmi(mvm->trans); } static void iwl_mvm_fill_scan_type(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index d1ef0365b932..db3933b0d197 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1493,7 +1493,7 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, out_err: WARN(1, "Invalid rxb from HW %u\n", (u32)vid); - iwl_force_nmi(trans); + iwl_trans_force_nmi(trans); return NULL; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 48ae2440cfe1..1304d8916424 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3596,7 +3596,7 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans) if (interrupts_enabled) iwl_trans_pci_interrupts(trans, false); - iwl_force_nmi(trans); + iwl_trans_force_nmi(trans); while (time_after(timeout, jiffies)) { u32 inta_hw = iwl_read32(trans, inta_addr); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 26d1530cfa37..496435ea93ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -715,7 +715,7 @@ static void iwl_txq_stuck_timer(struct timer_list *t) iwl_txq_log_scd_error(trans, txq); - iwl_force_nmi(trans); + iwl_trans_force_nmi(trans); } int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, @@ -1105,7 +1105,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) if (nfreed++ > 0) { IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx, txq->write_ptr, r); - iwl_force_nmi(trans); + iwl_trans_force_nmi(trans); } } From 38e3a2e9936f7967643f6ef328ebb3ceb2807877 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 26 Sep 2026 20:17:31 +0300 Subject: [PATCH 057/104] wifi: iwlwifi: add support for the new MPDU descriptor The firmware now reports in DW-12 bits 31:24 the RU/MRU/DRU that was used for the received frame, in trigger-like format. The MAC context byte moved to bits 31:24 of DW-10. It isn't used by the driver, so just follow the new layout. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260926201527.cf236c23d1aa.Ie2d919c884f7db8cd76b4cb6a9f4584eb285eea5@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/rx.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index a8f1edf19bbe..20460534fc99 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -583,7 +583,11 @@ struct iwl_rx_mpdu_desc_v3 { /** * @reserved_xsum: reserved high bits in the raw checksum */ - __le16 reserved_xsum; + u8 reserved_xsum; + /** + * @mac_context: MAC context mask, in this DW only from API version 10 + */ + u8 mac_context; /* DW11 */ /** * @rate_n_flags: RX rate/flags encoding @@ -603,9 +607,10 @@ struct iwl_rx_mpdu_desc_v3 { */ u8 channel; /** - * @mac_context: MAC context mask + * @ru: RU/MRU/DRU used for the frame, in trigger-like format; + * only from API version 10, this byte held @mac_context before */ - u8 mac_context; + u8 ru; /* DW13 */ /** * @gp2_on_air_rise: GP2 timer value on air rise (INA) @@ -647,7 +652,11 @@ struct iwl_rx_mpdu_desc_v3 { __le32 reserved[1]; } __packed; /* RX_MPDU_RES_START_API_S_VER_3, * RX_MPDU_RES_START_API_S_VER_5, - * RX_MPDU_RES_START_API_S_VER_6 + * RX_MPDU_RES_START_API_S_VER_6, + * RX_MPDU_RES_START_API_S_VER_7, + * RX_MPDU_RES_START_API_S_VER_8, + * RX_MPDU_RES_START_API_S_VER_9, + * RX_MPDU_RES_START_API_S_VER_10 */ /** @@ -737,6 +746,8 @@ struct iwl_rx_mpdu_desc { * RX_MPDU_RES_START_API_S_VER_6 * RX_MPDU_RES_START_API_S_VER_7 * RX_MPDU_RES_START_API_S_VER_8 + * RX_MPDU_RES_START_API_S_VER_9 + * RX_MPDU_RES_START_API_S_VER_10 */ #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1) From 60cce59decdaff868484a5f91b0d71f8e630131b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sat, 26 Sep 2026 20:17:32 +0300 Subject: [PATCH 058/104] wifi: iwlwifi: support RX BAID modify command version 3 Version 3 of the RX BAID allocation modify command shrinks the tid field to a u8 and adds a window size field, so that the window size can be updated while moving a BAID to a new AP. A window size of 0 tells the firmware to keep the current one, which is what we need for now. Add the new layout and pick it based on the command version. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260926201527.46c77de75c0b.Ie41b1d43f945a0c5e2bb68981a0cec0c62111233@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/datapath.h | 29 +++++++++++++++---- drivers/net/wireless/intel/iwlwifi/mld/agg.c | 7 ++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index b17babef71c0..3fbcb2e4bfe0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -522,17 +522,34 @@ struct iwl_rx_baid_cfg_cmd_alloc { } __packed; /* RX_BAID_ALLOCATION_ADD_CMD_API_S_VER_1 */ /** - * struct iwl_rx_baid_cfg_cmd_modify - BAID modification data + * struct iwl_rx_baid_cfg_cmd_modify_v2 - BAID modification data * @old_sta_id_mask: old station ID mask * @new_sta_id_mask: new station ID mask * @tid: TID of the BAID */ -struct iwl_rx_baid_cfg_cmd_modify { +struct iwl_rx_baid_cfg_cmd_modify_v2 { __le32 old_sta_id_mask; __le32 new_sta_id_mask; __le32 tid; } __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_2 */ +/** + * struct iwl_rx_baid_cfg_cmd_modify - BAID modification data + * @old_sta_id_mask: old station ID mask + * @new_sta_id_mask: new station ID mask + * @tid: TID of the BAID + * @reserved: reserved + * @win_size: RX BA session window size to apply to the modified BAID, + * 0 means keep the current one + */ +struct iwl_rx_baid_cfg_cmd_modify { + __le32 old_sta_id_mask; + __le32 new_sta_id_mask; + u8 tid; + u8 reserved; + __le16 win_size; +} __packed; /* RX_BAID_ALLOCATION_MODIFY_CMD_API_S_VER_3 */ + /** * struct iwl_rx_baid_cfg_cmd_remove_v1 - BAID removal data * @baid: the BAID to remove @@ -555,7 +572,8 @@ struct iwl_rx_baid_cfg_cmd_remove { * struct iwl_rx_baid_cfg_cmd - BAID allocation/config command * @action: the action, from &enum iwl_rx_baid_action * @alloc: allocation data - * @modify: modify data + * @modify_v2: modify data (version 2) + * @modify: modify data (version 3) * @remove_v1: remove data (version 1) * @remove: remove data */ @@ -563,11 +581,12 @@ struct iwl_rx_baid_cfg_cmd { __le32 action; union { struct iwl_rx_baid_cfg_cmd_alloc alloc; + struct iwl_rx_baid_cfg_cmd_modify_v2 modify_v2; struct iwl_rx_baid_cfg_cmd_modify modify; struct iwl_rx_baid_cfg_cmd_remove_v1 remove_v1; struct iwl_rx_baid_cfg_cmd_remove remove; - }; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_2 */ -} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_2 */ + }; /* RX_BAID_ALLOCATION_OPERATION_API_U_VER_3 */ +} __packed; /* RX_BAID_ALLOCATION_CONFIG_CMD_API_S_VER_3 */ /** * struct iwl_rx_baid_cfg_resp - BAID allocation response diff --git a/drivers/net/wireless/intel/iwlwifi/mld/agg.c b/drivers/net/wireless/intel/iwlwifi/mld/agg.c index c45c47337509..ea1f02380ad4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/agg.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/agg.c @@ -660,6 +660,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld, .modify.new_sta_id_mask = cpu_to_le32(new_sta_mask), }; u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, RX_BAID_ALLOCATION_CONFIG_CMD); + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 2); int baid; /* mac80211 will remove sessions later, but we ignore all that */ @@ -667,6 +668,7 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld, return 0; BUILD_BUG_ON(sizeof(struct iwl_rx_baid_cfg_resp) != sizeof(baid)); + BUILD_BUG_ON(sizeof(cmd.modify) != sizeof(cmd.modify_v2)); for (baid = 0; baid < ARRAY_SIZE(mld->fw_id_to_ba); baid++) { struct iwl_mld_baid_data *data; @@ -683,7 +685,10 @@ int iwl_mld_update_sta_baids(struct iwl_mld *mld, "BAID data for %d corrupted - expected 0x%x found 0x%x\n", baid, old_sta_mask, data->sta_mask); - cmd.modify.tid = cpu_to_le32(data->tid); + if (cmd_ver >= 3) + cmd.modify.tid = data->tid; + else + cmd.modify_v2.tid = cpu_to_le32(data->tid); ret = iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd); if (ret) From f7357ab44fe8f001705a604db48a2843dd8f12f7 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sat, 26 Sep 2026 20:17:33 +0300 Subject: [PATCH 059/104] wifi: iwlwifi: drop the orphaned nic_access annotations commit 5b63d0ae94cc ("compiler-context-analysis: Remove Sparse support") deleted the Sparse implementation of the lock annotations. __acquires()/__releases()/__acquire()/__release() are gone; the macros now only map onto clang's context analysis and expand to nothing for gcc. The nic_access annotations describe nothing anymore: - Every one of them is a __releases() with no matching __acquires(). The acquire side was the __cond_lock() wrapper around _iwl_trans_grab_nic_access(), which went away together with __cond_lock() itself. The names don't even agree - PCIe releases nic_access_nobh while the generic wrapper calling it claims nic_access. - The __acquire()/__release(reg_lock) pairs only existed to silence Sparse Use lockdep_assert_held() instead, which unlike the annotations actually runs, and add the missing assertion to iwl_trans_pcie_resched_with_nic_access(). Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260926201527.f818a7e09def.Iccecaabe0f37525430377ae1c0db6fd7bbf7625a@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 3 +-- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 3 +-- .../net/wireless/intel/iwlwifi/pcie/internal.h | 3 +-- .../net/wireless/intel/iwlwifi/pcie/trans.c | 18 ++++++------------ 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index efe657857772..0a6b7b264aa2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -576,8 +576,7 @@ void iwl_trans_resched_with_nic_access(struct iwl_trans *trans) iwl_trans_pcie_resched_with_nic_access(trans); } -void __releases(nic_access) -iwl_trans_release_nic_access(struct iwl_trans *trans) +void iwl_trans_release_nic_access(struct iwl_trans *trans) { iwl_trans_pcie_release_nic_access(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index a7bb6cee8188..56c5e61b614a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -992,8 +992,7 @@ bool iwl_trans_grab_nic_access(struct iwl_trans *trans); */ void iwl_trans_resched_with_nic_access(struct iwl_trans *trans); -void __releases(nic_access) -iwl_trans_release_nic_access(struct iwl_trans *trans); +void iwl_trans_release_nic_access(struct iwl_trans *trans); static inline void iwl_trans_schedule_reset(struct iwl_trans *trans, enum iwl_fw_error_type type) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index e10aa8e7e061..e6b1cb559a0a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1161,8 +1161,7 @@ int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs, u32 *val); bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans); -void __releases(nic_access_nobh) -iwl_trans_pcie_release_nic_access(struct iwl_trans *trans); +void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans); void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power); int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, const struct iwl_mac_cfg *mac_cfg, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 1304d8916424..bda069a6f7eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2402,10 +2402,10 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) out: /* - * Fool sparse by faking we release the lock - sparse will - * track nic_access anyway. + * Deliberately return with reg_lock held; the caller must drop it via + * iwl_trans_pcie_release_nic_access(), or explicitly if it wants to + * keep the NIC awake past the critical section (cmd_hold_nic_awake). */ - __release(&trans_pcie->reg_lock); return true; } @@ -2427,24 +2427,19 @@ void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + lockdep_assert_held(&trans_pcie->reg_lock); + spin_unlock_bh(&trans_pcie->reg_lock); cond_resched(); spin_lock_bh(&trans_pcie->reg_lock); } -void __releases(nic_access_nobh) -iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) +void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); lockdep_assert_held(&trans_pcie->reg_lock); - /* - * Fool sparse by faking we acquiring the lock - sparse will - * track nic_access anyway. - */ - __acquire(&trans_pcie->reg_lock); - if (trans_pcie->cmd_hold_nic_awake) goto out; if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) @@ -2460,7 +2455,6 @@ iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) * scheduled on different CPUs (after we drop reg_lock). */ out: - __release(nic_access_nobh); spin_unlock_bh(&trans_pcie->reg_lock); } From 7964121c8691f3b0f890c9f3d6be35fb77998bc0 Mon Sep 17 00:00:00 2001 From: Shahar Tzarfati Date: Sat, 26 Sep 2026 20:17:34 +0300 Subject: [PATCH 060/104] wifi: iwlwifi: disable HE ER mode HE ER mode (~3 Mbps) provides marginal range benefit over legacy rates, while effective coverage remains constrained by beacon reception. In addition, ~3 Mbps is insufficient for laptop connectivity. Furthermore, any range benefit in 5 and 6 GHz is more easily achieved by roaming to 2.4 GHz, while avoiding degrading 5 and 6 GHz aggregate network capacity with low-rate links. Therefore, disable HE ER mode. Signed-off-by: Shahar Tzarfati Link: https://patch.msgid.link/20260926201527.aac48f46b60e.I5dcf9ed88b2b73bc09c81c0d9c841dc624447faf@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 6bb27d7f1166..413dd55115f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -612,7 +612,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP | IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI, .phy_cap_info[8] = - IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI | IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | @@ -747,7 +746,6 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { .phy_cap_info[7] = IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI, .phy_cap_info[8] = - IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI | IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242, .phy_cap_info[9] = IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | From 80f864fa6fa793d60a5a930bd3830243cb6d6e2e Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:38 +0300 Subject: [PATCH 061/104] wifi: iwlwifi: add _no_grab postfix to some functions A function that accesses the nic memory without grabbing nic access first, needs to have a _no_grab postfix. It makes it clear to the caller that he is responsible for grabbing it. Add it to iwl_trans_write_prph and iwl_trans_pcie_write_prph as well. Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.68337f23f322.I38ed9c92bf6358158974b0af025d8bf8fdd7e4f5@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/dbg-old.c | 32 +++++++++---------- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 20 ++++++------ .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 2 +- .../net/wireless/intel/iwlwifi/iwl-trans.c | 4 +-- .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- .../wireless/intel/iwlwifi/pcie/internal.h | 2 +- .../net/wireless/intel/iwlwifi/pcie/trans.c | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c index 19b1bfd0abee..a4e1f82c8bd1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c @@ -47,7 +47,7 @@ static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt, u32 rd_cmd = RADIO_RSP_RD_CMD; rd_cmd |= i << RADIO_RSP_ADDR_POS; - iwl_trans_write_prph(fwrt->trans, RSP_RADIO_CMD, rd_cmd); + iwl_trans_write_prph_no_grab(fwrt->trans, RSP_RADIO_CMD, rd_cmd); *pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT); pos++; @@ -97,12 +97,12 @@ static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt, RXF_SET_FENCE_MODE + offset)); /* Lock fence */ - iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1); + iwl_trans_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1); /* Set fence pointer to the same place like WR pointer */ - iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1); + iwl_trans_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offset, 0x1); /* Set fence offset */ - iwl_trans_write_prph(fwrt->trans, - RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0); + iwl_trans_write_prph_no_grab(fwrt->trans, + RXF_LD_FENCE_OFFSET_ADDR + offset, 0x0); /* Read FIFO */ fifo_len /= sizeof(u32); /* Size in DWORDS */ @@ -152,8 +152,8 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt, TXF_LOCK_FENCE + offset)); /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */ - iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offset, - TXF_WR_PTR + offset); + iwl_trans_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offset, + TXF_WR_PTR + offset); /* Dummy-read to advance the read pointer to the head */ iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset); @@ -217,7 +217,7 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, /* Pull TXF data from LMAC1 */ for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) { /* Mark the number of TXF we're pulling now */ - iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i); + iwl_trans_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM, i); iwl_fwrt_dump_txf(fwrt, dump_data, cfg->lmac[0].txfifo_size[i], 0, i); } @@ -227,9 +227,9 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) { /* Mark the number of TXF we're pulling now */ - iwl_trans_write_prph(fwrt->trans, - TXF_LARC_NUM + - LMAC2_PRPH_OFFSET, i); + iwl_trans_write_prph_no_grab(fwrt->trans, + TXF_LARC_NUM + + LMAC2_PRPH_OFFSET, i); iwl_fwrt_dump_txf(fwrt, dump_data, cfg->lmac[1].txfifo_size[i], LMAC2_PRPH_OFFSET, @@ -262,8 +262,8 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, fifo_hdr->fifo_num = cpu_to_le32(i); /* Mark the number of TXF we're pulling now */ - iwl_trans_write_prph(fwrt->trans, TXF_CPU2_NUM, i + - fwrt->smem_cfg.num_txfifo_entries); + iwl_trans_write_prph_no_grab(fwrt->trans, TXF_CPU2_NUM, i + + fwrt->smem_cfg.num_txfifo_entries); fifo_hdr->available_bytes = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, @@ -282,9 +282,9 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, TXF_CPU2_LOCK_FENCE)); /* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */ - iwl_trans_write_prph(fwrt->trans, - TXF_CPU2_READ_MODIFY_ADDR, - TXF_CPU2_WR_PTR); + iwl_trans_write_prph_no_grab(fwrt->trans, + TXF_CPU2_READ_MODIFY_ADDR, + TXF_CPU2_WR_PTR); /* Dummy-read to advance the read pointer to head */ iwl_trans_read_prph(fwrt->trans, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 897538066b7d..8d08ce7db3b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -169,8 +169,8 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, continue; } - iwl_trans_write_prph(fwrt->trans, indirect_wr_addr, - WMAL_INDRCT_CMD(addr + i)); + iwl_trans_write_prph_no_grab(fwrt->trans, indirect_wr_addr, + WMAL_INDRCT_CMD(addr + i)); if (fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF1 && fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_JF2 && @@ -446,7 +446,7 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, range->fifo_hdr.num_of_registers = cpu_to_le32(registers_num); range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size); - iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo); + iwl_trans_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo); /* * read txf registers. for each register, write to the dump the @@ -468,8 +468,8 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, } /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */ - iwl_trans_write_prph(fwrt->trans, TXF_READ_MODIFY_ADDR + offs, - TXF_WR_PTR + offs); + iwl_trans_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offs, + TXF_WR_PTR + offs); /* Dummy-read to advance the read pointer to the head */ iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offs); @@ -518,8 +518,8 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt, continue; } - iwl_trans_write_prph(fwrt->trans, indirect_rd_wr_addr, - addr + i); + iwl_trans_write_prph_no_grab(fwrt->trans, indirect_rd_wr_addr, + addr + i); /* wait a bit for value to be ready in register */ udelay(1); prph_val = iwl_trans_read_prph(fwrt->trans, @@ -642,11 +642,11 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, offs = rxf_data.offset; /* Lock fence */ - iwl_trans_write_prph(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1); + iwl_trans_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1); /* Set fence pointer to the same place like WR pointer */ - iwl_trans_write_prph(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1); + iwl_trans_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1); /* Set fence offset */ - iwl_trans_write_prph(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, 0x0); + iwl_trans_write_prph_no_grab(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, 0x0); /* Read FIFO */ addr = RXF_FIFO_RD_FENCE_INC + offs; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 4372a171172b..5aca343372d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -912,7 +912,7 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt, for (count = 0; count < len; count++) { address = le32_to_cpu(config_list->addr_val[count].address); value = le32_to_cpu(config_list->addr_val[count].value); - iwl_trans_write_prph(fwrt->trans, address + offset, value); + iwl_trans_write_prph_no_grab(fwrt->trans, address + offset, value); } iwl_trans_release_nic_access(fwrt->trans); break; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index cc6bf4ea5055..5ce046e3fa5c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -115,7 +115,7 @@ u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) { trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val); - iwl_trans_write_prph(trans, ofs, val); + iwl_trans_write_prph_no_grab(trans, ofs, val); } void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 0a6b7b264aa2..1c593fd29d02 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -448,9 +448,9 @@ u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs) return iwl_trans_pcie_read_prph(trans, ofs); } -void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) +void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) { - return iwl_trans_pcie_write_prph(trans, ofs, val); + return iwl_pcie_write_prph_no_grab(trans, ofs, val); } void iwl_trans_force_nmi(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 56c5e61b614a..c59b935ce4bf 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -918,7 +918,7 @@ u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs); u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs); -void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val); +void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val); int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index e6b1cb559a0a..550c5c23a52e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1140,7 +1140,7 @@ void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val); void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val); u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs); u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg); -void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val); +void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val); int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords); int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index bda069a6f7eb..3d1cc49effb4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1894,7 +1894,7 @@ u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg) return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); } -void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, u32 val) +void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val) { u32 mask = iwl_trans_pcie_prph_msk(trans); From b4f714ea8feba4948e39c72610b2b185651a1144 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:39 +0300 Subject: [PATCH 062/104] wifi: iwlwifi: move pcie-only functions to pcie There are several helpers that exported to the opmodes but are really only called from the pcie transport. Define those functions there. No functional change intended. Assisted-by: GitHubCopilot:claude-opus-4.8 Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.480246f9b623.I88de3ad2bbd8a8444ff2a154f7eb1f08ecb7b7ea@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 3 +- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 89 ------------------- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 26 ------ .../net/wireless/intel/iwlwifi/iwl-trans.c | 5 -- .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 - .../intel/iwlwifi/pcie/ctxt-info-v2.c | 5 +- .../wireless/intel/iwlwifi/pcie/ctxt-info.c | 3 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 47 +++++----- .../net/wireless/intel/iwlwifi/pcie/trans.c | 33 +++---- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 10 +-- .../net/wireless/intel/iwlwifi/pcie/utils.c | 87 +++++++++++++++++- .../net/wireless/intel/iwlwifi/pcie/utils.h | 28 +++++- 12 files changed, 166 insertions(+), 172 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index d2fa80a3dd04..ba14e583a4ad 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -501,7 +501,8 @@ enum { * to indirectly access device's internal memory or registers that * may be powered-down. * - * Use iwl_write_direct32()/iwl_read_direct32() family for these registers; + * Use iwl_write_direct32() family for writing to these registers; + * A read operation doesn't exist, can be added if needed. * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ * to make sure the MAC (uCode processor, etc.) is powered up for accessing * internal resources. diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 5ce046e3fa5c..297f4550ae72 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -11,13 +11,6 @@ #include "iwl-csr.h" #include "iwl-debug.h" -void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) -{ - trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); - iwl_trans_write8(trans, ofs, val); -} -IWL_EXPORT_SYMBOL(iwl_write8); - void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) { trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); @@ -25,14 +18,6 @@ void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) } IWL_EXPORT_SYMBOL(iwl_write32); -void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val) -{ - trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val); - iwl_trans_write32(trans, ofs, lower_32_bits(val)); - iwl_trans_write32(trans, ofs + 4, upper_32_bits(val)); -} -IWL_EXPORT_SYMBOL(iwl_write64); - u32 iwl_read32(struct iwl_trans *trans, u32 ofs) { u32 val = iwl_trans_read32(trans, ofs); @@ -60,19 +45,6 @@ int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, } IWL_EXPORT_SYMBOL(iwl_poll_bits_mask); -u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg) -{ - if (iwl_trans_grab_nic_access(trans)) { - u32 value = iwl_read32(trans, reg); - - iwl_trans_release_nic_access(trans); - return value; - } - - /* return as if we have a HW timeout/failure */ - return 0x5a5a5a5a; -} - void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) { if (iwl_trans_grab_nic_access(trans)) { @@ -82,29 +54,6 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) } IWL_EXPORT_SYMBOL(iwl_write_direct32); -void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value) -{ - if (iwl_trans_grab_nic_access(trans)) { - iwl_write64(trans, reg, value); - iwl_trans_release_nic_access(trans); - } -} - -int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, - int timeout) -{ - int t = 0; - - do { - if ((iwl_read_direct32(trans, addr) & mask) == mask) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) { u32 val = iwl_trans_read_prph(trans, ofs); @@ -118,13 +67,6 @@ void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) iwl_trans_write_prph_no_grab(trans, ofs, val); } -void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val) -{ - trace_iwlwifi_dev_iowrite_prph64(trans->dev, ofs, val); - iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff); - iwl_write_prph_no_grab(trans, ofs + 4, val >> 32); -} - u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) { if (iwl_trans_grab_nic_access(trans)) { @@ -150,37 +92,6 @@ void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_m } IWL_EXPORT_SYMBOL(iwl_write_prph_delay); -int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int t = 0; - - do { - if ((iwl_read_prph(trans, addr) & mask) == (bits & mask)) - return 0; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - -int iwl_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int t = 0; - - do { - if ((iwl_read_umac_prph_no_grab(trans, addr) & mask) == - (bits & mask)) - return 0; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) { if (iwl_trans_grab_nic_access(trans)) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index e4a9f2ba0de9..b24c5eeca206 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -8,9 +8,7 @@ #include "iwl-devtrace.h" #include "iwl-trans.h" -void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val); void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val); -void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val); u32 iwl_read32(struct iwl_trans *trans, u32 ofs); static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) @@ -30,18 +28,13 @@ static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits, { return iwl_poll_bits_mask(trans, addr, bits, bits, timeout); } -int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, - int timeout); -u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); -void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value); u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs); u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val); -void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val); void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms); static inline void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) @@ -49,10 +42,6 @@ static inline void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) iwl_write_prph_delay(trans, ofs, val, 0); } -int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout); -int iwl_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout); void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, u32 bits, u32 mask); @@ -79,25 +68,10 @@ static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) return iwl_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset); } -static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs, - u32 val) -{ - iwl_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset, - val); -} - static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs, u32 val) { iwl_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val); } -static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout) -{ - return iwl_poll_prph_bit(trans, addr + - trans->mac_cfg->umac_prph_offset, - bits, mask, timeout); -} - #endif diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 1c593fd29d02..b3e39f0bbea4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -428,11 +428,6 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans) } IWL_EXPORT_SYMBOL(iwl_trans_op_mode_leave); -void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val) -{ - iwl_trans_pcie_write8(trans, ofs, val); -} - void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val) { iwl_trans_pcie_write32(trans, ofs, val); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index c59b935ce4bf..c882313eaceb 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -910,8 +910,6 @@ int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, u32 txqs); int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue); -void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val); - void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val); u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index c75210829ec9..c57b17133772 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -7,6 +7,7 @@ #include "iwl-fh.h" #include "iwl-context-info-v2.h" #include "internal.h" +#include "pcie/utils.h" #include "iwl-prph.h" static const struct dmi_system_id dmi_force_scu_active_approved_list[] = { @@ -314,8 +315,8 @@ void iwl_pcie_ctxt_info_v2_kick(struct iwl_trans *trans) iwl_enable_fw_load_int_ctx_info(trans, trans->do_top_reset); /* kick FW self load */ - iwl_write64(trans, CSR_CTXT_INFO_ADDR, trans_pcie->ctxt_info_dma_addr); - iwl_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr); + iwl_pcie_write64(trans, CSR_CTXT_INFO_ADDR, trans_pcie->ctxt_info_dma_addr); + iwl_pcie_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr); iwl_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len); iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 23ec968577bd..bc90a2714251 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -7,6 +7,7 @@ #include "iwl-fh.h" #include "iwl-context-info.h" #include "internal.h" +#include "utils.h" #include "iwl-prph.h" static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, @@ -245,7 +246,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, iwl_pcie_apply_destination(trans); /* kick FW self load */ - iwl_write64(trans, CSR_CTXT_INFO_BA, trans_pcie->ctxt_info_dma_addr); + iwl_pcie_write64(trans, CSR_CTXT_INFO_BA, trans_pcie->ctxt_info_dma_addr); /* Context info will be released upon alive or failure to get one */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index db3933b0d197..fec3d6e0b146 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -11,6 +11,7 @@ #include "iwl-prph.h" #include "iwl-io.h" #include "internal.h" +#include "pcie/utils.h" #include "iwl-op-mode.h" #include "iwl-context-info-v2.h" #include "fw/dbg.h" @@ -147,17 +148,17 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { /* TODO: remove this once fw does it */ iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_AX210, 0); - return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_AX210, - RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); + return iwl_pcie_poll_umac_prph_bit(trans, RFH_GEN_STATUS_AX210, + RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); } else if (trans->mac_cfg->mq_rx_supported) { iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); - return iwl_poll_prph_bit(trans, RFH_GEN_STATUS, - RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); + return iwl_pcie_poll_prph_bit(trans, RFH_GEN_STATUS, + RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); } else { iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - return iwl_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, - FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, - 1000); + return iwl_pcie_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, + FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, + 1000); } } @@ -890,7 +891,7 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_trans_release_nic_access(trans); /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_trans_pcie_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); /* W/A for interrupt coalescing bug in 7260 and 3160 */ if (trans->cfg->host_interrupt_operation_mode) @@ -931,17 +932,17 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) for (i = 0; i < trans->info.num_rxqs; i++) { /* Tell device where to find RBD free table in DRAM */ - iwl_write_prph64_no_grab(trans, - RFH_Q_FRBDCB_BA_LSB(i), - trans_pcie->rxq[i].bd_dma); + iwl_pcie_write_prph64_no_grab(trans, + RFH_Q_FRBDCB_BA_LSB(i), + trans_pcie->rxq[i].bd_dma); /* Tell device where to find RBD used table in DRAM */ - iwl_write_prph64_no_grab(trans, - RFH_Q_URBDCB_BA_LSB(i), - trans_pcie->rxq[i].used_bd_dma); + iwl_pcie_write_prph64_no_grab(trans, + RFH_Q_URBDCB_BA_LSB(i), + trans_pcie->rxq[i].used_bd_dma); /* Tell device where in DRAM to update its Rx status */ - iwl_write_prph64_no_grab(trans, - RFH_Q_URBD_STTS_WPTR_LSB(i), - trans_pcie->rxq[i].rb_stts_dma); + iwl_pcie_write_prph64_no_grab(trans, + RFH_Q_URBD_STTS_WPTR_LSB(i), + trans_pcie->rxq[i].rb_stts_dma); /* Reset device indice tables */ iwl_write_prph_no_grab(trans, RFH_Q_FRBDCB_WIDX(i), 0); iwl_write_prph_no_grab(trans, RFH_Q_FRBDCB_RIDX(i), 0); @@ -982,7 +983,7 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) iwl_trans_release_nic_access(trans); /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_trans_pcie_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) @@ -1189,7 +1190,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) int iwl_pcie_gen2_rx_init(struct iwl_trans *trans) { /* Set interrupt coalescing timer to default (2048 usecs) */ - iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); + iwl_trans_pcie_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); /* * We don't configure the RFH. @@ -2090,8 +2091,8 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) */ /* Disable periodic interrupt; we use it as just a one-shot. */ - iwl_write8(trans, CSR_INT_PERIODIC_REG, - CSR_INT_PERIODIC_DIS); + iwl_trans_pcie_write8(trans, CSR_INT_PERIODIC_REG, + CSR_INT_PERIODIC_DIS); /* * Enable periodic interrupt in 8 msec only if we received @@ -2101,8 +2102,8 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) * to extend the periodic interrupt; one-shot is enough. */ if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write8(trans, CSR_INT_PERIODIC_REG, - CSR_INT_PERIODIC_ENA); + iwl_trans_pcie_write8(trans, CSR_INT_PERIODIC_REG, + CSR_INT_PERIODIC_ENA); isr_stats->rx++; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 3d1cc49effb4..b81dd7daca6c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -751,7 +751,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans, return ret; /* Notify ucode of loaded section number and status */ - val = iwl_read_direct32(trans, FH_UCODE_LOAD_STATUS); + val = iwl_pcie_read_direct32(trans, FH_UCODE_LOAD_STATUS); val = val | (sec_num << shift_param); iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, val); @@ -1079,7 +1079,7 @@ static void iwl_pcie_map_list(struct iwl_trans *trans, int i; for (i = 0; i < arr_size; i++) { - iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); + iwl_trans_pcie_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); iwl_clear_bit(trans, causes[i].mask_reg, BIT(causes[i].bit)); } @@ -1119,8 +1119,8 @@ static void iwl_pcie_map_rx_causes(struct iwl_trans *trans) */ val = BIT(MSIX_FH_INT_CAUSES_Q(0)); for (idx = 1; idx < trans->info.num_rxqs; idx++) { - iwl_write8(trans, CSR_MSIX_RX_IVAR(idx), - MSIX_FH_INT_CAUSES_Q(idx - offset)); + iwl_trans_pcie_write8(trans, CSR_MSIX_RX_IVAR(idx), + MSIX_FH_INT_CAUSES_Q(idx - offset)); val |= BIT(MSIX_FH_INT_CAUSES_Q(idx)); } iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~val); @@ -1128,10 +1128,10 @@ static void iwl_pcie_map_rx_causes(struct iwl_trans *trans) val = MSIX_FH_INT_CAUSES_Q(0); if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX) val |= MSIX_NON_AUTO_CLEAR_CAUSE; - iwl_write8(trans, CSR_MSIX_RX_IVAR(0), val); + iwl_trans_pcie_write8(trans, CSR_MSIX_RX_IVAR(0), val); if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_FIRST_RSS) - iwl_write8(trans, CSR_MSIX_RX_IVAR(1), val); + iwl_trans_pcie_write8(trans, CSR_MSIX_RX_IVAR(1), val); } void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) @@ -1754,8 +1754,8 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans) "Error, can not clear persistence bit\n"); return -EPERM; } - iwl_write_umac_prph_no_grab(trans, HPM_DEBUG, - hpm & ~PERSISTENCE_BIT); + iwl_pcie_write_umac_prph_no_grab(trans, HPM_DEBUG, + hpm & ~PERSISTENCE_BIT); } return 0; @@ -1864,6 +1864,7 @@ void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) { + trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); } @@ -3253,11 +3254,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans, if (!iwl_trans_grab_nic_access(trans)) return 0; - iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); + iwl_pcie_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); for (i = 0; i < buf_size_in_dwords; i++) buffer[i] = iwl_read_umac_prph_no_grab(trans, MON_DMARB_RD_DATA_ADDR); - iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); + iwl_pcie_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); iwl_trans_release_nic_access(trans); @@ -3916,11 +3917,11 @@ static void get_crf_id(struct iwl_trans *iwl_trans, return; } - ret = iwl_poll_umac_prph_bits_no_grab(iwl_trans, - WFPM_RSRCS_4PHS_ACK_STTS, - RSRC_ACK_CNVR_TOP, - RSRC_ACK_CNVR_TOP, - 50 * 1000); + ret = iwl_pcie_poll_umac_prph_bits_no_grab(iwl_trans, + WFPM_RSRCS_4PHS_ACK_STTS, + RSRC_ACK_CNVR_TOP, + RSRC_ACK_CNVR_TOP, + 50 * 1000); if (ret < 0) IWL_ERR(iwl_trans, "WFPM_RSRCS_4PHS_ACK_STTS bit 6 is clear\n"); @@ -3929,7 +3930,7 @@ static void get_crf_id(struct iwl_trans *iwl_trans, /* Enable access to peripheral registers */ val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG); val |= WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK; - iwl_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val); + iwl_pcie_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val); /* Read crf info */ info->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 496435ea93ee..bdd330280689 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -523,7 +523,7 @@ void iwl_pcie_tx_start(struct iwl_trans *trans) FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); /* Update FH chicken bits */ - reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); + reg_val = iwl_pcie_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); @@ -549,9 +549,9 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) txq_id++) { struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; if (trans->mac_cfg->gen2) - iwl_write_direct64(trans, - FH_MEM_CBBC_QUEUE(trans, txq_id), - txq->dma_addr); + iwl_pcie_write_direct64(trans, + FH_MEM_CBBC_QUEUE(trans, txq_id), + txq->dma_addr); else iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id), @@ -697,7 +697,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq) (trans->mac_cfg->base->max_tfd_queue_size - 1), iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) & (trans->mac_cfg->base->max_tfd_queue_size - 1), - iwl_read_direct32(trans, FH_TX_TRB_REG(fifo))); + iwl_pcie_read_direct32(trans, FH_TX_TRB_REG(fifo))); } static void iwl_txq_stuck_timer(struct timer_list *t) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c index 1bb274d8390c..bace3e21989c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2025 Intel Corporation + * Copyright (C) 2025-2026 Intel Corporation */ #include @@ -102,3 +102,88 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev) pcie_dbg_dumped_once = 1; kfree(buf); } + +u32 iwl_pcie_read_direct32(struct iwl_trans *trans, u32 reg) +{ + if (iwl_trans_grab_nic_access(trans)) { + u32 value = iwl_read32(trans, reg); + + iwl_trans_release_nic_access(trans); + return value; + } + + /* return as if we have a HW timeout/failure */ + return 0x5a5a5a5a; +} + +#define IWL_PCIE_POLL_INTERVAL 10 /* microseconds */ + +int iwl_pcie_poll_direct_bit(struct iwl_trans *trans, + u32 addr, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_pcie_read_direct32(trans, addr) & mask) == mask) + return t; + udelay(IWL_PCIE_POLL_INTERVAL); + t += IWL_PCIE_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + +int iwl_pcie_poll_prph_bit(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_read_prph(trans, addr) & mask) == (bits & mask)) + return 0; + udelay(IWL_PCIE_POLL_INTERVAL); + t += IWL_PCIE_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + +int iwl_pcie_poll_umac_prph_bit(struct iwl_trans *trans, + u32 addr, u32 bits, u32 mask, + int timeout) +{ + return iwl_pcie_poll_prph_bit(trans, addr + + trans->mac_cfg->umac_prph_offset, + bits, mask, timeout); +} + +int iwl_pcie_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_read_umac_prph_no_grab(trans, addr) & mask) == + (bits & mask)) + return 0; + udelay(IWL_PCIE_POLL_INTERVAL); + t += IWL_PCIE_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + +void iwl_pcie_write_prph64_no_grab(struct iwl_trans *trans, u32 ofs, u64 val) +{ + trace_iwlwifi_dev_iowrite_prph64(trans->dev, ofs, val); + iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff); + iwl_write_prph_no_grab(trans, ofs + 4, val >> 32); +} + +void iwl_pcie_write_direct64(struct iwl_trans *trans, u64 reg, u64 value) +{ + if (iwl_trans_grab_nic_access(trans)) { + iwl_pcie_write64(trans, reg, value); + iwl_trans_release_nic_access(trans); + } +} diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index 27437d5e099b..341928cdb64b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2025 Intel Corporation + * Copyright (C) 2025-2026 Intel Corporation */ #ifndef __iwl_pcie_utils_h__ @@ -10,6 +10,32 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev); +u32 iwl_pcie_read_direct32(struct iwl_trans *trans, u32 reg); +int iwl_pcie_poll_direct_bit(struct iwl_trans *trans, + u32 addr, u32 mask, int timeout); +int iwl_pcie_poll_prph_bit(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout); +int iwl_pcie_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout); +int iwl_pcie_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout); +void iwl_pcie_write_prph64_no_grab(struct iwl_trans *trans, u32 ofs, u64 val); +void iwl_pcie_write_direct64(struct iwl_trans *trans, u64 reg, u64 value); + +static inline void iwl_pcie_write64(struct iwl_trans *trans, u64 ofs, u64 val) +{ + trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val); + iwl_trans_write32(trans, ofs, lower_32_bits(val)); + iwl_trans_write32(trans, ofs + 4, upper_32_bits(val)); +} + +static inline void iwl_pcie_write_umac_prph_no_grab(struct iwl_trans *trans, + u32 ofs, u32 val) +{ + iwl_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset, + val); +} + static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) { From c56b0989065999bb99d331d9fb35f50f1da1cc71 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 30 Sep 2026 12:19:40 +0300 Subject: [PATCH 063/104] wifi: iwlwifi: mld: fake a valid NSS field when needed We hit a WARNING in mac80211 in sniffer that complains that rx_status->nss is 0. This happens on frames that the firmware doesn't really understand and when that happens, somehow the STBC bit is set. The driver divides the number of antennas by 2 to get the NSS with STBC set because each stream requires 2 antennas. Since NSTS=1, NSS end up being 0. Since we don't have devices with more than 2 antennas, just consider that when we receive STBC traffic, we have one spatial stream. Since this problem has been seen on HE traffic only, don't apply this logic on VHT / HT code paths. Signed-off-by: Emmanuel Grumbach Reviewed-by: Johannes Berg Link: https://patch.msgid.link/20260930121740.2589668e377b.Ib41003bd4e10f0fe6d7f4aa1038291be330c3175@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 5f18aa551af5..8fa438fd7815 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -553,7 +553,10 @@ iwl_mld_decode_he_tb_phy_data(struct iwl_mld_rx_phy_data *phy_data, nsts = le32_get_bits(phy_data->ntfy->sigs.he_tb.tb_rx1, OFDM_UCODE_TRIG_BASE_RX_NSTS) + 1; - rx_status->nss = nsts >> !!(rate_n_flags & RATE_MCS_STBC_MSK); + + rx_status->nss = nsts; + if (rate_n_flags & RATE_MCS_STBC_MSK) + rx_status->nss = 1; } static void @@ -589,7 +592,9 @@ iwl_mld_decode_he_phy_data(struct iwl_mld_rx_phy_data *phy_data, break; } - rx_status->nss = nsts >> !!(rate_n_flags & RATE_MCS_STBC_MSK); + rx_status->nss = nsts; + if (rate_n_flags & RATE_MCS_STBC_MSK) + rx_status->nss = 1; he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN); From 594c359b00422f1cb1afc3713595fc7e56828869 Mon Sep 17 00:00:00 2001 From: Daniel Gabay Date: Wed, 30 Sep 2026 12:19:41 +0300 Subject: [PATCH 064/104] wifi: iwlwifi: mld: add gp2 timestamps to TX commands TX command v12 adds a driver timestamp in the gp2 clock domain. Firmware uses it to age out frames deferred by CCA for more than four seconds. Without it, a blocked queue can stall until the datapath monitor fires LMAC assert 0x4433. Reading the gp2 register per frame is too expensive for the TX path. Instead, use a worker to measure its offset from host boottime and publish the offset and validity deadline using atomic stores. TX then estimates gp2 without allocation or locking for timestamp reads. TX requests a refresh after five seconds, while the estimate remains valid for ten seconds to tolerate worker delays and bound clock drift. Successful refreshes require no periodic work while traffic is idle. A failed read invalidates the estimate and schedules a retry after roughly one second, rounded for timer coalescing, even without traffic. Invalidate the estimate before D3 entry and firmware shutdown, and refresh it on resume or reload because gp2 restarts with firmware. Frames without a valid estimate carry a zero timestamp, which firmware ignores. Signed-off-by: Daniel Gabay Assisted-by: LLM Link: https://patch.msgid.link/20260930121740.a5016741a467.Ie4d4af8d7100a656a8469edc0c38ec81b0b58860@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/tx.h | 11 +- .../wireless/intel/iwlwifi/mld/constants.h | 4 + drivers/net/wireless/intel/iwlwifi/mld/d3.c | 5 + drivers/net/wireless/intel/iwlwifi/mld/fw.c | 7 +- .../net/wireless/intel/iwlwifi/mld/mac80211.c | 2 + drivers/net/wireless/intel/iwlwifi/mld/mld.c | 13 ++ drivers/net/wireless/intel/iwlwifi/mld/mld.h | 6 + drivers/net/wireless/intel/iwlwifi/mld/ptp.c | 12 +- drivers/net/wireless/intel/iwlwifi/mld/tx.c | 130 ++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mld/tx.h | 36 ++++- 10 files changed, 209 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 31d3336726b4..9d9eb320db7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2025 Intel Corporation + * Copyright (C) 2012-2014, 2018-2026 Intel Corporation * Copyright (C) 2016-2017 Intel Deutschland GmbH */ #ifndef __iwl_fw_api_tx_h__ @@ -292,6 +292,9 @@ struct iwl_tx_cmd_v9 { * @dram_info: FW internal DRAM storage * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is * cleared. Combination of RATE_MCS_*; format depends on version + * @driver_timestamp: gp2 time, in microseconds, assigned before queueing the + * MPDU. Firmware uses it to detect frames blocked for too long. + * Zero means no timestamp. Used from TX_CMD_API_S_VER_12. * @reserved: reserved * @hdr: 802.11 header */ @@ -301,10 +304,12 @@ struct iwl_tx_cmd { __le32 offload_assist; struct iwl_dram_sec_info dram_info; __le32 rate_n_flags; - u8 reserved[8]; + __le32 driver_timestamp; + u8 reserved[4]; struct ieee80211_hdr hdr[]; } __packed; /* TX_CMD_API_S_VER_10, - * TX_CMD_API_S_VER_11 + * TX_CMD_API_S_VER_11, + * TX_CMD_API_S_VER_12 */ /* diff --git a/drivers/net/wireless/intel/iwlwifi/mld/constants.h b/drivers/net/wireless/intel/iwlwifi/mld/constants.h index 890abcab3837..bfd5398510ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/constants.h @@ -39,6 +39,10 @@ #define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ) +#define IWL_MLD_TX_GP2_VALID_PERIOD (10 * HZ) +#define IWL_MLD_TX_GP2_REFRESH_MARGIN (5 * HZ) +#define IWL_MLD_TX_GP2_RETRY_PERIOD HZ + #define IWL_MLD_DIS_RANDOM_FW_ID false #define IWL_MLD_D3_DEBUG false #define IWL_MLD_NON_TRANSMITTING_AP false diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index 6d8ede336d59..7a7d07a7914d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -5,6 +5,7 @@ #include "mld.h" #include "d3.h" +#include "tx.h" #include "power.h" #include "hcmd.h" #include "iface.h" @@ -1610,6 +1611,8 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld) iwl_mld_low_latency_stop(mld); + iwl_mld_tx_gp2_stop(mld); + ret = iwl_mld_update_device_power(mld, true); if (ret) { IWL_ERR(mld, @@ -1663,6 +1666,8 @@ int iwl_mld_no_wowlan_resume(struct iwl_mld *mld) iwl_mld_low_latency_restart(mld); + iwl_mld_tx_gp2_start(mld); + return iwl_mld_update_device_power(mld, false); } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/fw.c b/drivers/net/wireless/intel/iwlwifi/mld/fw.c index e5866d89176d..7891afd556a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/fw.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #include "mld.h" +#include "tx.h" #include "fw/api/alive.h" #include "fw/api/scan.h" @@ -355,6 +356,8 @@ void iwl_mld_stop_fw(struct iwl_mld *mld) { lockdep_assert_wiphy(mld->wiphy); + iwl_mld_tx_gp2_stop(mld); + iwl_abort_notification_waits(&mld->notif_wait); iwl_fw_dbg_stop_sync(&mld->fwrt); @@ -542,6 +545,8 @@ int iwl_mld_start_fw(struct iwl_mld *mld) if (ret) goto error; + iwl_mld_tx_gp2_start(mld); + return 0; error: diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 0b121114d47c..e05bdbd3e1a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -2168,6 +2168,8 @@ static int iwl_mld_resume(struct ieee80211_hw *hw) iwl_mld_low_latency_restart(mld); + iwl_mld_tx_gp2_start(mld); + return 0; } #endif diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index b7b1e3686336..95d6f36b9fd9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -35,6 +35,17 @@ MODULE_IMPORT_NS("IWLWIFI"); static const struct iwl_op_mode_ops iwl_mld_ops; +int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2) +{ + *gp2 = iwl_read_prph(mld->trans, + mld->trans->mac_cfg->base->gp2_reg_addr); + + if (*gp2 == 0x5a5a5a5a) + return -EINVAL; + + return 0; +} + static int __init iwl_mld_init(void) { int ret = iwl_opmode_register("iwlmld", &iwl_mld_ops); @@ -425,6 +436,8 @@ iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, /* Configure transport layer with the opmode specific params */ iwl_mld_configure_trans(op_mode); + iwl_mld_tx_gp2_init(mld); + /* needed for regulatory init */ rtnl_lock(); /* Needed for sending commands */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h index 37f41b504b54..a9e65b216fd3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h @@ -29,6 +29,7 @@ #include "notif.h" #include "scan.h" #include "rx.h" +#include "tx.h" #include "thermal.h" #include "low_latency.h" #include "constants.h" @@ -196,6 +197,7 @@ * being IBSS manager for that time and needing to respond to probe * requests * @ptp_data: data of the PTP clock + * @tx_gp2: gp2 timestamping state for TX commands * @time_sync: time sync data. * @ftm_initiator: FTM initiator data * @nan_device_vif: points to the NAN device vif if exists @@ -306,6 +308,8 @@ struct iwl_mld { struct ptp_data ptp_data; + struct iwl_mld_tx_gp2 tx_gp2; + struct iwl_mld_time_sync_data __rcu *time_sync; struct ftm_initiator_data ftm_initiator; @@ -572,6 +576,8 @@ iwl_mld_fw_id_to_link_conf(struct iwl_mld *mld, u8 fw_link_id) #define MSEC_TO_TU(_msec) ((_msec) * 1000 / 1024) +int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2); + void iwl_mld_add_vif_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mld_add_link_debugfs(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c index 1ac85d6ce1d7..9f7d17dbdee1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/ptp.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/ptp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2025 Intel Corporation + * Copyright (C) 2025 - 2026 Intel Corporation */ #include "mld.h" @@ -19,16 +19,6 @@ #define IWL_PTP_WRAP_TIME (3600 * HZ) #define IWL_PTP_WRAP_THRESHOLD_USEC (5000) -static int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2) -{ - *gp2 = iwl_read_prph(mld->trans, mld->trans->mac_cfg->base->gp2_reg_addr); - - if (*gp2 == 0x5a5a5a5a) - return -EINVAL; - - return 0; -} - static void iwl_mld_ptp_update_new_read(struct iwl_mld *mld, u32 gp2) { IWL_DEBUG_PTP(mld, "PTP: last_gp2=%u, new gp2 read=%u\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c index 2df6643a5aa8..aac7d43bffd1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c @@ -2,6 +2,7 @@ /* * Copyright (C) 2024 - 2026 Intel Corporation */ +#include #include #include "tx.h" @@ -20,6 +21,132 @@ #define MAX_ANT_NUM 2 +static u32 iwl_mld_tx_gp2_host_us(void) +{ + return div_u64(ktime_get_boottime_ns(), NSEC_PER_USEC); +} + +/* Returns the gp2 for the TX command, or 0 to leave the frame unstamped. + * Sets @refresh when the estimate expired or is about to. + */ +static u32 +iwl_mld_tx_gp2_from_est(u32 delta_us, unsigned long valid_until, u32 host_us, + unsigned long now, bool *refresh) +{ + u32 gp2; + + *refresh = time_after_eq(now, valid_until - + IWL_MLD_TX_GP2_REFRESH_MARGIN); + + if (time_after_eq(now, valid_until)) + return 0; + + gp2 = host_us + delta_us; + + /* 0 means no timestamp; use 1 for a valid wrapped value. */ + return gp2 ?: 1; +} + +static u32 +iwl_mld_tx_gp2_timestamp(struct iwl_mld *mld) +{ + unsigned long valid_until = + atomic_long_read_acquire(&mld->tx_gp2.valid_until); + bool refresh = false; + u32 gp2; + + if (!valid_until) + return 0; + + gp2 = iwl_mld_tx_gp2_from_est(atomic_read(&mld->tx_gp2.delta_us), + valid_until, iwl_mld_tx_gp2_host_us(), + jiffies, &refresh); + + if (refresh) + wiphy_delayed_work_queue(mld->wiphy, &mld->tx_gp2.wk, 0); + + return gp2; +} + +static void iwl_mld_tx_gp2_refresh(struct iwl_mld *mld) +{ + unsigned long valid_until, delay; + u32 gp2, host_us; + + lockdep_assert_wiphy(mld->wiphy); + + if (!mld->fw_status.running) + return; + +#ifdef CONFIG_PM_SLEEP + if (mld->fw_status.in_d3) + return; +#endif + + if (iwl_mld_get_systime(mld, &gp2)) + goto retry; + + host_us = iwl_mld_tx_gp2_host_us(); + valid_until = jiffies + IWL_MLD_TX_GP2_VALID_PERIOD; + + /* Keep arithmetic in u32 to match firmware wraparound semantics. */ + atomic_set(&mld->tx_gp2.delta_us, gp2 - host_us); + atomic_long_set_release(&mld->tx_gp2.valid_until, valid_until ?: 1); + + IWL_DEBUG_TX(mld, "gp2 sync: gp2=%u host_us=%u delta_us=%u\n", + gp2, host_us, gp2 - host_us); + return; + +retry: + /* Stop new TX readers from requesting immediate retries. */ + atomic_long_set(&mld->tx_gp2.valid_until, 0); + delay = round_jiffies_relative(IWL_MLD_TX_GP2_RETRY_PERIOD); + wiphy_delayed_work_queue(mld->wiphy, &mld->tx_gp2.wk, delay); +} + +static void iwl_mld_tx_gp2_wk(struct wiphy *wiphy, struct wiphy_work *wk) +{ + struct iwl_mld *mld = container_of(wk, struct iwl_mld, tx_gp2.wk.work); + unsigned long valid_until = atomic_long_read(&mld->tx_gp2.valid_until); + + /* TX may have queued this work using an older estimate. */ + if (valid_until && + time_before(jiffies, valid_until - IWL_MLD_TX_GP2_REFRESH_MARGIN)) + return; + + iwl_mld_tx_gp2_refresh(mld); +} + +void iwl_mld_tx_gp2_init(struct iwl_mld *mld) +{ + atomic_set(&mld->tx_gp2.delta_us, 0); + atomic_long_set(&mld->tx_gp2.valid_until, 0); + wiphy_delayed_work_init(&mld->tx_gp2.wk, iwl_mld_tx_gp2_wk); +} + +void iwl_mld_tx_gp2_start(struct iwl_mld *mld) +{ + lockdep_assert_wiphy(mld->wiphy); + + if (iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) < 12) + return; + + iwl_mld_tx_gp2_refresh(mld); +} + +/* TX is quiesced before stopping the refresh work. */ +void iwl_mld_tx_gp2_stop(struct iwl_mld *mld) +{ + lockdep_assert_wiphy(mld->wiphy); + + if (iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) < 12) + return; + + wiphy_delayed_work_cancel(mld->wiphy, &mld->tx_gp2.wk); + + atomic_long_set(&mld->tx_gp2.valid_until, 0); +} + /* Toggles between TX antennas. Receives the bitmask of valid TX antennas and * the *index* used for the last TX, and returns the next valid *index* to use. * In order to set it in the tx_cmd, must do BIT(idx). @@ -588,6 +715,9 @@ iwl_mld_fill_tx_cmd(struct iwl_mld *mld, struct sk_buff *skb, tx_cmd->flags = cpu_to_le16(flags); tx_cmd->rate_n_flags = rate_n_flags; + + tx_cmd->driver_timestamp = + cpu_to_le32(iwl_mld_tx_gp2_timestamp(mld)); } /* Caller of this need to check that info->control.vif is not NULL */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.h b/drivers/net/wireless/intel/iwlwifi/mld/tx.h index 520f15f9d33c..0a9a2e4abcab 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.h @@ -1,11 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024, 2026 Intel Corporation */ #ifndef __iwl_mld_tx_h__ #define __iwl_mld_tx_h__ -#include "mld.h" +#include +#include + +struct iwl_mld; +struct iwl_rx_packet; #define IWL_MLD_INVALID_QUEUE 0xFFFF #define IWL_MLD_INVALID_DROP_TX 0xFFFE @@ -74,4 +78,32 @@ u8 iwl_mld_get_lowest_rate(struct iwl_mld *mld, void iwl_mld_tx_skb(struct iwl_mld *mld, struct sk_buff *skb, struct ieee80211_txq *txq); +/** + * struct iwl_mld_tx_gp2 - gp2 timestamping state for TX commands + * + * Reading gp2 directly in the TX path is too costly. Instead, TX lazily + * schedules @wk to refresh gp2 in process context and adds @delta_us to the + * host clock to timestamp queued frames. + * + * A zero @valid_until leaves frames unstamped, including on older firmware + * without TX_CMD v12. A deadline that wraps to zero is published as one. + * Failed refreshes clear @valid_until, leaving @delta_us for old readers, and + * schedule a retry with %IWL_MLD_TX_GP2_RETRY_PERIOD rounded for timer + * coalescing, even without further TX traffic. Old readers may retry sooner. + * + * @delta_us: gp2 minus host time, in microseconds, modulo 2^32; + * valid while @valid_until is nonzero and has not expired + * @valid_until: jiffies deadline for the offset, or zero when disabled + * @wk: worker that refreshes the offset and retries failures + */ +struct iwl_mld_tx_gp2 { + atomic_t delta_us; + atomic_long_t valid_until; + struct wiphy_delayed_work wk; +}; + +void iwl_mld_tx_gp2_init(struct iwl_mld *mld); +void iwl_mld_tx_gp2_start(struct iwl_mld *mld); +void iwl_mld_tx_gp2_stop(struct iwl_mld *mld); + #endif /* __iwl_mld_tx_h__ */ From c9ebbfdba19d44ae1022b75290f5e48d170be815 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 30 Sep 2026 12:19:42 +0300 Subject: [PATCH 065/104] wifi: iwlwifi: mld: report RX time from channel survey Newer firmware versions will start reporting a separate RX time value that represents for how long the channel was busy with Wi-Fi frames. Previously the reported value for RX time was equal to the busy time. As such, report the information as it will be useful in the future. Signed-off-by: Benjamin Berg Link: https://patch.msgid.link/20260930121740.727c05ab3c58.I9509587622fa7c6493b6baee53372c548bf60ed8@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/scan.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/mld/scan.h | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index e44b24904c19..b942ac1e7ccc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -2273,6 +2273,7 @@ void iwl_mld_handle_channel_survey_notif(struct iwl_mld *mld, /* Times are all in ms */ info->time = le32_to_cpu(notif->active_time); info->time_busy = le32_to_cpu(notif->busy_time); + info->time_rx = le32_to_cpu(notif->rx_time); info->noise = iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise)); } @@ -2321,9 +2322,11 @@ int iwl_mld_mac80211_get_survey(struct ieee80211_hw *hw, int idx, /* Found (the next) channel to report */ survey->channel = &sband->channels[per_band_idx]; survey->filled = SURVEY_INFO_TIME | - SURVEY_INFO_TIME_BUSY; + SURVEY_INFO_TIME_BUSY | + SURVEY_INFO_TIME_RX; survey->time = info->time; survey->time_busy = info->time_busy; + survey->time_rx = info->time_rx; survey->noise = info->noise; if (survey->noise < 0) survey->filled |= SURVEY_INFO_NOISE_DBM; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.h b/drivers/net/wireless/intel/iwlwifi/mld/scan.h index dc299fe2f999..74ebe8296693 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #ifndef __iwl_mld_scan_h__ #define __iwl_mld_scan_h__ @@ -151,11 +151,13 @@ struct iwl_mld_scan { * * @time: time in ms the radio was on the channel * @time_busy: time in ms the channel was sensed busy + * @time_rx: time in ms the channel was sensed to carry Wi-Fi frames * @noise: channel noise in dBm */ struct iwl_mld_survey_channel { u32 time; u32 time_busy; + u32 time_rx; s8 noise; }; From 27a4816f37ce99d4e78332072306d9a8401cc362 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:43 +0300 Subject: [PATCH 066/104] wifi: iwlwifi: avoid unnecessary indirection Some helpers in iwl-io are no more than thin wrappers that do tracing and call the underlying iwl_trans_* function, which in turn calls the bus specific implementation. This forces an unneeded indirection for calls from within pcie, and in general makes the code harder to follow. Move the tracing to the pcie implementation and get rid of those wrappers: change the pcie callers to call the pcie implementation directly, and the callers outside the transport - to call the iwl_trans_* API. This also improves the current callers of the pcie specific implementations to include tracing, which they didn't have before this commit. Assisted-by: GitHubCopilot:claude-opus-4.8 Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.8a85afed9cd7.If4806e645949ec73b8c734486605d7d4ea8ada4e@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/dvm/debugfs.c | 4 +- .../net/wireless/intel/iwlwifi/dvm/devices.c | 6 +- .../net/wireless/intel/iwlwifi/dvm/eeprom.c | 30 ++--- drivers/net/wireless/intel/iwlwifi/dvm/led.c | 10 +- .../net/wireless/intel/iwlwifi/dvm/mac80211.c | 10 +- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 22 +-- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 10 +- drivers/net/wireless/intel/iwlwifi/dvm/tt.c | 12 +- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 8 +- .../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 2 +- .../wireless/intel/iwlwifi/iwl-devtrace-io.h | 18 +-- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 42 ++---- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 4 - .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 12 +- .../net/wireless/intel/iwlwifi/iwl-trans.c | 12 +- drivers/net/wireless/intel/iwlwifi/mvm/led.c | 6 +- .../intel/iwlwifi/pcie/ctxt-info-v2.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +- .../wireless/intel/iwlwifi/pcie/internal.h | 58 ++++---- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 124 ++++++++--------- .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 34 ++--- .../net/wireless/intel/iwlwifi/pcie/trans.c | 127 +++++++++--------- .../net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 4 +- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 14 +- .../net/wireless/intel/iwlwifi/pcie/utils.c | 8 +- .../net/wireless/intel/iwlwifi/pcie/utils.h | 14 +- 27 files changed, 282 insertions(+), 315 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index ec94c43ba28c..ed041710c74f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2018, 2025 Intel Corporation + * Copyright (C) 2018, 2025-2026 Intel Corporation *****************************************************************************/ #include @@ -1788,7 +1788,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, const size_t bufsz = sizeof(buf); u32 pwrsave_status; - pwrsave_status = iwl_read32(priv->trans, CSR_GP_CNTRL) & + pwrsave_status = iwl_trans_read32(priv->trans, CSR_GP_CNTRL) & CSR_GP_REG_POWER_SAVE_STATUS_MSK; pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index 7f83f1bbdaad..b40a769f8e2d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2019, 2025 Intel Corporation + * Copyright (C) 2019, 2025-2026 Intel Corporation *****************************************************************************/ #include @@ -490,8 +490,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv) break; case IWL_DEVICE_FAMILY_6000i: /* 2x2 IPA phy type */ - iwl_write32(priv->trans, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); + iwl_trans_write32(priv->trans, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); break; case IWL_DEVICE_FAMILY_6050: /* Indicate calibration version to uCode. */ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c index 6de2517188f7..d20691f7d82f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2019, 2021, 2024-2025 Intel Corporation + * Copyright (C) 2005-2014, 2018-2019, 2021, 2024-2026 Intel Corporation */ #include #include @@ -698,7 +698,7 @@ static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) { - u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; + u32 gp = iwl_trans_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp); @@ -734,7 +734,7 @@ static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) static void iwl_set_otp_access_absolute(struct iwl_trans *trans) { - iwl_read32(trans, CSR_OTP_GP_REG); + iwl_trans_read32(trans, CSR_OTP_GP_REG); iwl_clear_bit(trans, CSR_OTP_GP_REG, CSR_OTP_GP_REG_OTP_ACCESS_MODE); @@ -755,7 +755,7 @@ static int iwl_nvm_is_otp(struct iwl_trans *trans) case CSR_HW_REV_TYPE_5150: return 0; default: - otpgp = iwl_read32(trans, CSR_OTP_GP_REG); + otpgp = iwl_trans_read32(trans, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) return 1; return 0; @@ -794,8 +794,8 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, u32 r; u32 otpgp; - iwl_write32(trans, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + iwl_trans_write32(trans, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bits(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); @@ -803,9 +803,9 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); return ret; } - r = iwl_read32(trans, CSR_EEPROM_REG); + r = iwl_trans_read32(trans, CSR_EEPROM_REG); /* check for ECC errors: */ - otpgp = iwl_read32(trans, CSR_OTP_GP_REG); + otpgp = iwl_trans_read32(trans, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { /* stop in this case */ /* set the uncorrectable OTP ECC bit for acknowledgment */ @@ -918,7 +918,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans, int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) { __le16 *e; - u32 gp = iwl_read32(trans, CSR_EEPROM_GP); + u32 gp = iwl_trans_read32(trans, CSR_EEPROM_GP); int sz; int ret; u16 addr; @@ -960,9 +960,9 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) goto err_unlock; } - iwl_write32(trans, CSR_EEPROM_GP, - iwl_read32(trans, CSR_EEPROM_GP) & - ~CSR_EEPROM_GP_IF_OWNER_MSK); + iwl_trans_write32(trans, CSR_EEPROM_GP, + iwl_trans_read32(trans, CSR_EEPROM_GP) & + ~CSR_EEPROM_GP_IF_OWNER_MSK); iwl_set_bit(trans, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | @@ -988,8 +988,8 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - iwl_write32(trans, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + iwl_trans_write32(trans, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bits(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, @@ -999,7 +999,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) "Time out reading EEPROM[%d]\n", addr); goto err_unlock; } - r = iwl_read32(trans, CSR_EEPROM_REG); + r = iwl_trans_read32(trans, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index cec2ebdfd651..6fa02cd0ab04 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2019, 2025 Intel Corporation + * Copyright (C) 2019, 2025-2026 Intel Corporation *****************************************************************************/ @@ -49,7 +49,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = { /* Set led register off */ void iwlagn_led_enable(struct iwl_priv *priv) { - iwl_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON); + iwl_trans_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON); } /* @@ -85,10 +85,10 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) }; u32 reg; - reg = iwl_read32(priv->trans, CSR_LED_REG); + reg = iwl_trans_read32(priv->trans, CSR_LED_REG); if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(priv->trans, CSR_LED_REG, - reg & CSR_LED_BSM_CTRL_MSK); + iwl_trans_write32(priv->trans, CSR_LED_REG, + reg & CSR_LED_BSM_CTRL_MSK); return iwl_dvm_send_cmd(priv, &cmd); } diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index a0a26ef482a5..1da59e724054 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(C) 2018 - 2019, 2022 - 2025 Intel Corporation + * Copyright(C) 2018 - 2019, 2022 - 2026 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -375,8 +375,8 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, goto error; /* let the ucode operate on its own */ - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); iwl_trans_d3_suspend(priv->trans, true); @@ -455,8 +455,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) goto out_unlock; /* uCode is no longer operating by itself */ - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); base = priv->device_pointers.error_event_table; if (!iwlagn_hw_valid_rtc_data_addr(base)) { diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 6bd5b6d84b2a..9bf16950ebf0 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014, 2018 - 2022 Intel Corporation. All rights reserved. - * Copyright(c) 2024-2025 Intel Corporation. All rights reserved. + * Copyright(c) 2024-2026 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well @@ -413,7 +413,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, return; /* Set starting address; reads will auto-increment */ - iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr); + iwl_trans_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr); /* * Refuse to read more than would have fit into the log from @@ -429,13 +429,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); - time = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); + ev = iwl_trans_read32(priv->trans, HBUS_TARG_MEM_RDAT); + time = iwl_trans_read32(priv->trans, HBUS_TARG_MEM_RDAT); if (mode == 0) { trace_iwlwifi_dev_ucode_cont_event( priv->trans->dev, 0, time, ev); } else { - data = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT); + data = iwl_trans_read32(priv->trans, HBUS_TARG_MEM_RDAT); trace_iwlwifi_dev_ucode_cont_event( priv->trans->dev, time, data, ev); } @@ -661,8 +661,8 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) struct iwl_ct_kill_throttling_config adv_cmd; int ret = 0; - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = false; @@ -1731,13 +1731,13 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, return pos; /* Set starting address; reads will auto-increment */ - iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); + iwl_trans_write32(trans, HBUS_TARG_MEM_RADDR, ptr); /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT); - time = iwl_read32(trans, HBUS_TARG_MEM_RDAT); + ev = iwl_trans_read32(trans, HBUS_TARG_MEM_RDAT); + time = iwl_trans_read32(trans, HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ if (bufsz) { @@ -1751,7 +1751,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, time, ev); } } else { - data = iwl_read32(trans, HBUS_TARG_MEM_RDAT); + data = iwl_trans_read32(trans, HBUS_TARG_MEM_RDAT); if (bufsz) { pos += scnprintf(*buf + pos, bufsz - pos, "EVT_LOGT:%010u:0x%08x:%04u\n", diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 088302a238de..79ee4fb239b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -3,7 +3,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH - * Copyright(c) 2018, 2020-2021, 2025 Intel Corporation + * Copyright(c) 2018, 2020-2021, 2025-2026 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portionhelp of the ieee80211 subsystem header files. @@ -482,15 +482,15 @@ static void iwlagn_rx_card_state_notif(struct iwl_priv *priv, if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | CT_CARD_DISABLED)) { - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); iwl_write_direct32(priv->trans, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); iwl_write_direct32(priv->trans, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c index fc9cf0531024..c4ee22876f77 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2018, 2020 Intel Corporation + * Copyright (C) 2018, 2020, 2026 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -146,15 +146,15 @@ static void iwl_tt_check_exit_ct_kill(struct timer_list *t) if (tt->state == IWL_TI_CT_KILL) { if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = false; } else { - iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); + iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); priv->thermal_throttle.ct_kill_toggle = true; } - iwl_read32(priv->trans, CSR_UCODE_DRV_GP1); + iwl_trans_read32(priv->trans, CSR_UCODE_DRV_GP1); if (iwl_trans_grab_nic_access(priv->trans)) iwl_trans_release_nic_access(priv->trans); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index bbbf3669a555..eef89c141564 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -404,7 +404,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt) } if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - u32 scratch = iwl_read32(fwrt->trans, CSR_FUNC_SCRATCH); + u32 scratch = iwl_trans_read32(fwrt->trans, CSR_FUNC_SCRATCH); IWL_ERR(fwrt, "Function Scratch status:\n"); IWL_ERR(fwrt, "0x%08X | Func Scratch\n", scratch); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index ba14e583a4ad..b9f7e791dd37 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -14,7 +14,7 @@ * low power states due to driver-invoked device resets * (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes. * - * Use iwl_write32() and iwl_read32() family to access these registers; + * Use iwl_trans_write32() and iwl_trans_read32() family to access these registers; * these provide simple PCI bus access, without waking up the MAC. * Do not use iwl_write_direct32() family for these registers; * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ. @@ -36,7 +36,7 @@ #define CSR_GP_CNTRL (CSR_BASE+0x024) #define CSR_FUNC_SCRATCH (CSR_BASE+0x02c) /* Scratch register - used for FW dbg */ -/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */ +/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_trans_write32()! */ #define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) /* @@ -474,7 +474,7 @@ enum { * indirect read/write via HEEP_CTRL_WRD_PCIEX_CTRL (0xEC) and * HEEP_CTRL_WRD_PCIEX_DATA (0xF4) registers. * - * Use iwl_write32()/iwl_read32() family to access these registers. The MAC HW + * Use iwl_trans_write32()/iwl_trans_read32() family to access these registers. The MAC HW * need not be powered up so no "grab inc access" is required. */ @@ -507,7 +507,7 @@ enum { * to make sure the MAC (uCode processor, etc.) is powered up for accessing * internal resources. * - * Do not use iwl_write32()/iwl_read32() family to access these registers; + * Do not use iwl_trans_write32()/iwl_trans_read32() family to access these registers; * these provide only simple PCI bus access, without waking up the MAC. */ #define HBUS_BASE (0x400) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 5aca343372d5..cc6044222b5c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -931,7 +931,7 @@ static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt, for (count = 0; count < len; count++) { address = le32_to_cpu(config_list->addr_val[count].address); value = le32_to_cpu(config_list->addr_val[count].value); - iwl_write32(fwrt->trans, address + offset, value); + iwl_trans_write32(fwrt->trans, address + offset, value); IWL_DEBUG_FW(fwrt, "WRT: CSR: count %u, add: %u val: %u\n", count, address, value); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h index 0af9d8362c5b..a0cc40119890 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h @@ -3,6 +3,7 @@ * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2016-2017 Intel Deutschland GmbH + * Copyright (C) 2026 Intel Corporation *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ) @@ -65,23 +66,6 @@ TRACE_EVENT(iwlwifi_dev_iowrite32, __get_str(dev), __entry->offs, __entry->val) ); -TRACE_EVENT(iwlwifi_dev_iowrite64, - TP_PROTO(const struct device *dev, u64 offs, u64 val), - TP_ARGS(dev, offs, val), - TP_STRUCT__entry( - DEV_ENTRY - __field(u64, offs) - __field(u64, val) - ), - TP_fast_assign( - DEV_ASSIGN; - __entry->offs = offs; - __entry->val = val; - ), - TP_printk("[%s] write io[%llu] = %llu)", - __get_str(dev), __entry->offs, __entry->val) -); - TRACE_EVENT(iwlwifi_dev_iowrite_prph32, TP_PROTO(const struct device *dev, u32 offs, u32 val), TP_ARGS(dev, offs, val), diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 297f4550ae72..085074be2549 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -11,22 +11,6 @@ #include "iwl-csr.h" #include "iwl-debug.h" -void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) -{ - trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); - iwl_trans_write32(trans, ofs, val); -} -IWL_EXPORT_SYMBOL(iwl_write32); - -u32 iwl_read32(struct iwl_trans *trans, u32 ofs) -{ - u32 val = iwl_trans_read32(trans, ofs); - - trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); - return val; -} -IWL_EXPORT_SYMBOL(iwl_read32); - #define IWL_POLL_INTERVAL 10 /* microseconds */ int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, @@ -35,7 +19,7 @@ int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, int t = 0; do { - if ((iwl_read32(trans, addr) & mask) == (bits & mask)) + if ((iwl_trans_read32(trans, addr) & mask) == (bits & mask)) return 0; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; @@ -48,7 +32,7 @@ IWL_EXPORT_SYMBOL(iwl_poll_bits_mask); void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) { if (iwl_trans_grab_nic_access(trans)) { - iwl_write32(trans, reg, value); + iwl_trans_write32(trans, reg, value); iwl_trans_release_nic_access(trans); } } @@ -61,12 +45,6 @@ u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) return val; } -void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) -{ - trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val); - iwl_trans_write_prph_no_grab(trans, ofs, val); -} - u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) { if (iwl_trans_grab_nic_access(trans)) { @@ -86,7 +64,7 @@ void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_m { if (iwl_trans_grab_nic_access(trans)) { mdelay(delay_ms); - iwl_write_prph_no_grab(trans, ofs, val); + iwl_trans_write_prph_no_grab(trans, ofs, val); iwl_trans_release_nic_access(trans); } } @@ -95,9 +73,9 @@ IWL_EXPORT_SYMBOL(iwl_write_prph_delay); void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) { if (iwl_trans_grab_nic_access(trans)) { - iwl_write_prph_no_grab(trans, ofs, - iwl_read_prph_no_grab(trans, ofs) | - mask); + iwl_trans_write_prph_no_grab(trans, ofs, + iwl_read_prph_no_grab(trans, ofs) | + mask); iwl_trans_release_nic_access(trans); } } @@ -107,9 +85,9 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, u32 bits, u32 mask) { if (iwl_trans_grab_nic_access(trans)) { - iwl_write_prph_no_grab(trans, ofs, - (iwl_read_prph_no_grab(trans, ofs) & - mask) | bits); + iwl_trans_write_prph_no_grab(trans, ofs, + (iwl_read_prph_no_grab(trans, ofs) & + mask) | bits); iwl_trans_release_nic_access(trans); } } @@ -121,7 +99,7 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) if (iwl_trans_grab_nic_access(trans)) { val = iwl_read_prph_no_grab(trans, ofs); - iwl_write_prph_no_grab(trans, ofs, (val & ~mask)); + iwl_trans_write_prph_no_grab(trans, ofs, (val & ~mask)); iwl_trans_release_nic_access(trans); } } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index b24c5eeca206..b33bc4822e5c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -8,9 +8,6 @@ #include "iwl-devtrace.h" #include "iwl-trans.h" -void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val); -u32 iwl_read32(struct iwl_trans *trans, u32 ofs); - static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { iwl_trans_set_bits_mask(trans, reg, mask, mask); @@ -34,7 +31,6 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs); u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); -void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val); void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms); static inline void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 413dd55115f8..76cba6ac0c8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1312,10 +1312,10 @@ static void iwl_flip_hw_address(__le32 mac_addr0, __le32 mac_addr1, u8 *dest) static void iwl_set_hw_address_from_csr(struct iwl_trans *trans, struct iwl_nvm_data *data) { - __le32 mac_addr0 = cpu_to_le32(iwl_read32(trans, - CSR_MAC_ADDR0_STRAP(trans))); - __le32 mac_addr1 = cpu_to_le32(iwl_read32(trans, - CSR_MAC_ADDR1_STRAP(trans))); + __le32 mac_addr0 = cpu_to_le32(iwl_trans_read32(trans, + CSR_MAC_ADDR0_STRAP(trans))); + __le32 mac_addr1 = cpu_to_le32(iwl_trans_read32(trans, + CSR_MAC_ADDR1_STRAP(trans))); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); /* @@ -1325,8 +1325,8 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans, if (is_valid_ether_addr(data->hw_addr)) return; - mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP(trans))); - mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP(trans))); + mac_addr0 = cpu_to_le32(iwl_trans_read32(trans, CSR_MAC_ADDR0_OTP(trans))); + mac_addr1 = cpu_to_le32(iwl_trans_read32(trans, CSR_MAC_ADDR1_OTP(trans))); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index b3e39f0bbea4..2d0bb3de7df5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -432,11 +432,13 @@ void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val) { iwl_trans_pcie_write32(trans, ofs, val); } +IWL_EXPORT_SYMBOL(iwl_trans_write32); u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) { return iwl_trans_pcie_read32(trans, ofs); } +IWL_EXPORT_SYMBOL(iwl_trans_read32); u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs) { @@ -460,8 +462,8 @@ void iwl_trans_force_nmi(struct iwl_trans *trans) iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, UREG_DOORBELL_TO_ISR6_NMI_BIT); else - iwl_write32(trans, CSR_DOORBELL_VECTOR, - UREG_DOORBELL_TO_ISR6_NMI_BIT); + iwl_trans_write32(trans, CSR_DOORBELL_VECTOR, + UREG_DOORBELL_TO_ISR6_NMI_BIT); } IWL_EXPORT_SYMBOL(iwl_trans_force_nmi); @@ -485,10 +487,10 @@ int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, const u32 *vals = buf; if (iwl_trans_grab_nic_access(trans)) { - iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); + iwl_trans_write32(trans, HBUS_TARG_MEM_WADDR, addr); for (offs = 0; offs < dwords; offs++) - iwl_write32(trans, HBUS_TARG_MEM_WDAT, - vals ? vals[offs] : 0); + iwl_trans_write32(trans, HBUS_TARG_MEM_WDAT, + vals ? vals[offs] : 0); iwl_trans_release_nic_access(trans); } else { ret = -EBUSY; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c index c3cc1ea3ccc9..264423943b60 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2019, 2025 Intel Corporation + * Copyright (C) 2012-2014, 2018-2019, 2025-2026 Intel Corporation * Copyright (C) 2017 Intel Deutschland GmbH */ #include @@ -38,8 +38,8 @@ static void iwl_mvm_led_set(struct iwl_mvm *mvm, bool on) return; } - iwl_write32(mvm->trans, CSR_LED_REG, - on ? CSR_LED_REG_TURN_ON : CSR_LED_REG_TURN_OFF); + iwl_trans_write32(mvm->trans, CSR_LED_REG, + on ? CSR_LED_REG_TURN_ON : CSR_LED_REG_TURN_OFF); } static void iwl_led_brightness_set(struct led_classdev *led_cdev, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index c57b17133772..917010a7d8ef 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -317,7 +317,7 @@ void iwl_pcie_ctxt_info_v2_kick(struct iwl_trans *trans) /* kick FW self load */ iwl_pcie_write64(trans, CSR_CTXT_INFO_ADDR, trans_pcie->ctxt_info_dma_addr); iwl_pcie_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr); - iwl_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len); + iwl_trans_pcie_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len); iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 905482419a9a..24012005ccb8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1252,7 +1252,7 @@ static int _iwl_pci_resume(struct device *device, bool restore) * For older devices, just try silently to grab the NIC. */ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH); + u32 scratch = iwl_trans_pcie_read32(trans, CSR_FUNC_SCRATCH); if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) || scratch == ~0U) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 550c5c23a52e..96821850298f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -24,6 +24,13 @@ #include "iwl-drv.h" #include "iwl-context-info.h" +/* transport-specific register accessors (bus implementation) */ +void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val); +void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val); +u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs); +u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg); +void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val); + /* * RX related structures and functions */ @@ -593,7 +600,7 @@ static inline void iwl_pcie_clear_irq(struct iwl_trans *trans, int queue) * write 1 clear (W1C) register, meaning that it's being clear * by writing 1 to the bit. */ - iwl_write32(trans, CSR_MSIX_AUTOMASK_ST_AD, BIT(queue)); + iwl_trans_pcie_write32(trans, CSR_MSIX_AUTOMASK_ST_AD, BIT(queue)); } static inline struct iwl_trans * @@ -889,18 +896,18 @@ static inline void _iwl_disable_interrupts(struct iwl_trans *trans) clear_bit(STATUS_INT_ENABLED, &trans->status); if (!trans_pcie->msix_enabled) { /* disable interrupts from uCode/NIC to host */ - iwl_write32(trans, CSR_INT_MASK, 0x00000000); + iwl_trans_pcie_write32(trans, CSR_INT_MASK, 0x00000000); /* acknowledge/clear/reset any interrupts still pending * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(trans, CSR_INT, 0xffffffff); - iwl_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); + iwl_trans_pcie_write32(trans, CSR_INT, 0xffffffff); + iwl_trans_pcie_write32(trans, CSR_FH_INT_STATUS, 0xffffffff); } else { /* disable all the interrupt we might use */ - iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, - trans_pcie->fh_init_mask); - iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, - trans_pcie->hw_init_mask); + iwl_trans_pcie_write32(trans, CSR_MSIX_FH_INT_MASK_AD, + trans_pcie->fh_init_mask); + iwl_trans_pcie_write32(trans, CSR_MSIX_HW_INT_MASK_AD, + trans_pcie->hw_init_mask); trans_pcie->fh_mask = 0; trans_pcie->hw_mask = 0; } @@ -958,7 +965,7 @@ static inline void _iwl_enable_interrupts(struct iwl_trans *trans) set_bit(STATUS_INT_ENABLED, &trans->status); if (!trans_pcie->msix_enabled) { trans_pcie->inta_mask = CSR_INI_SET_MASK; - iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); + iwl_trans_pcie_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } else { /* * fh/hw_mask keeps all the unmasked causes. @@ -966,10 +973,10 @@ static inline void _iwl_enable_interrupts(struct iwl_trans *trans) */ trans_pcie->hw_mask = trans_pcie->hw_init_mask; trans_pcie->fh_mask = trans_pcie->fh_init_mask; - iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, - ~trans_pcie->fh_mask); - iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, - ~trans_pcie->hw_mask); + iwl_trans_pcie_write32(trans, CSR_MSIX_FH_INT_MASK_AD, + ~trans_pcie->fh_mask); + iwl_trans_pcie_write32(trans, CSR_MSIX_HW_INT_MASK_AD, + ~trans_pcie->hw_mask); } } @@ -985,7 +992,7 @@ static inline void iwl_enable_hw_int_msk_msix(struct iwl_trans *trans, u32 msk) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, ~msk); + iwl_trans_pcie_write32(trans, CSR_MSIX_HW_INT_MASK_AD, ~msk); trans_pcie->hw_mask = msk; } @@ -993,7 +1000,7 @@ static inline void iwl_enable_fh_int_msk_msix(struct iwl_trans *trans, u32 msk) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~msk); + iwl_trans_pcie_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~msk); trans_pcie->fh_mask = msk; } @@ -1004,10 +1011,10 @@ static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n"); if (!trans_pcie->msix_enabled) { trans_pcie->inta_mask = CSR_INT_BIT_FH_TX; - iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); + iwl_trans_pcie_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } else { - iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, - trans_pcie->hw_init_mask); + iwl_trans_pcie_write32(trans, CSR_MSIX_HW_INT_MASK_AD, + trans_pcie->hw_init_mask); iwl_enable_fh_int_msk_msix(trans, MSIX_FH_INT_CAUSES_D2S_CH0_NUM); } @@ -1034,7 +1041,7 @@ static inline void iwl_enable_fw_load_int_ctx_info(struct iwl_trans *trans, else trans_pcie->inta_mask = CSR_INT_BIT_ALIVE | CSR_INT_BIT_FH_RX; - iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); + iwl_trans_pcie_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } else { u32 val = top_reset ? MSIX_HW_INT_CAUSES_REG_RESET_DONE : MSIX_HW_INT_CAUSES_REG_ALIVE; @@ -1081,10 +1088,10 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n"); if (!trans_pcie->msix_enabled) { trans_pcie->inta_mask = CSR_INT_BIT_RF_KILL; - iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); + iwl_trans_pcie_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); } else { - iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, - trans_pcie->fh_init_mask); + iwl_trans_pcie_write32(trans, CSR_MSIX_FH_INT_MASK_AD, + trans_pcie->fh_init_mask); trans_pcie->fh_mask = 0; iwl_enable_hw_int_msk_msix(trans, MSIX_HW_INT_CAUSES_REG_RF_KILL); @@ -1112,7 +1119,7 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) if (trans_pcie->debug_rfkill == 1) return true; - return !(iwl_read32(trans, CSR_GP_CNTRL) & + return !(iwl_trans_pcie_read32(trans, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); } @@ -1136,11 +1143,6 @@ void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans); int _iwl_trans_pcie_start_hw(struct iwl_trans *trans); int iwl_trans_pcie_start_hw(struct iwl_trans *trans); void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans); -void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val); -void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val); -u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs); -u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg); -void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val); int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords); int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index fec3d6e0b146..cf6beba6041f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -179,7 +179,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, */ if (!trans->mac_cfg->base->shadow_reg_enable && test_bit(STATUS_TPOWER_PMI, &trans->status)) { - reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); + reg = iwl_trans_pcie_read32(trans, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n", @@ -193,13 +193,13 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, rxq->write_actual = round_down(rxq->write, 8); if (!trans->mac_cfg->mq_rx_supported) - iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); + iwl_trans_pcie_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - iwl_write32(trans, HBUS_TARG_WRPTR, rxq->write_actual | - HBUS_TARG_WRPTR_RX_Q(rxq->id)); + iwl_trans_pcie_write32(trans, HBUS_TARG_WRPTR, rxq->write_actual | + HBUS_TARG_WRPTR_RX_Q(rxq->id)); else - iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id), - rxq->write_actual); + iwl_trans_pcie_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id), + rxq->write_actual); } static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) @@ -855,22 +855,22 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) return; /* Stop Rx DMA */ - iwl_write32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_trans_pcie_write32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); /* reset and flush pointers */ - iwl_write32(trans, FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0); - iwl_write32(trans, FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0); - iwl_write32(trans, FH_RSCSR_CHNL0_RDPTR, 0); + iwl_trans_pcie_write32(trans, FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0); + iwl_trans_pcie_write32(trans, FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0); + iwl_trans_pcie_write32(trans, FH_RSCSR_CHNL0_RDPTR, 0); /* Reset driver's Rx queue write index */ - iwl_write32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + iwl_trans_pcie_write32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - (u32)(rxq->bd_dma >> 8)); + iwl_trans_pcie_write32(trans, FH_RSCSR_CHNL0_RBDCB_BASE_REG, + (u32)(rxq->bd_dma >> 8)); /* Tell device where in DRAM to update its Rx status */ - iwl_write32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, - rxq->rb_stts_dma >> 4); + iwl_trans_pcie_write32(trans, FH_RSCSR_CHNL0_STTS_WPTR_REG, + rxq->rb_stts_dma >> 4); /* Enable Rx DMA * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in @@ -880,13 +880,13 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) * RB timeout 0x10 * 256 RBDs */ - iwl_write32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - rb_size | - (RX_RB_TIMEOUT << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) | - (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); + iwl_trans_pcie_write32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | + FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | + rb_size | + (RX_RB_TIMEOUT << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS) | + (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); iwl_trans_release_nic_access(trans); @@ -926,9 +926,9 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) return; /* Stop Rx DMA */ - iwl_write_prph_no_grab(trans, RFH_RXF_DMA_CFG, 0); + iwl_pcie_write_prph_no_grab(trans, RFH_RXF_DMA_CFG, 0); /* disable free amd used rx queue operation */ - iwl_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, 0); + iwl_pcie_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, 0); for (i = 0; i < trans->info.num_rxqs; i++) { /* Tell device where to find RBD free table in DRAM */ @@ -944,9 +944,9 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) RFH_Q_URBD_STTS_WPTR_LSB(i), trans_pcie->rxq[i].rb_stts_dma); /* Reset device indice tables */ - iwl_write_prph_no_grab(trans, RFH_Q_FRBDCB_WIDX(i), 0); - iwl_write_prph_no_grab(trans, RFH_Q_FRBDCB_RIDX(i), 0); - iwl_write_prph_no_grab(trans, RFH_Q_URBDCB_WIDX(i), 0); + iwl_pcie_write_prph_no_grab(trans, RFH_Q_FRBDCB_WIDX(i), 0); + iwl_pcie_write_prph_no_grab(trans, RFH_Q_FRBDCB_RIDX(i), 0); + iwl_pcie_write_prph_no_grab(trans, RFH_Q_URBDCB_WIDX(i), 0); enabled |= BIT(i) | BIT(i + 16); } @@ -958,27 +958,27 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) * Drop frames that exceed RB size * 512 RBDs */ - iwl_write_prph_no_grab(trans, RFH_RXF_DMA_CFG, - RFH_DMA_EN_ENABLE_VAL | rb_size | - RFH_RXF_DMA_MIN_RB_4_8 | - RFH_RXF_DMA_DROP_TOO_LARGE_MASK | - RFH_RXF_DMA_RBDCB_SIZE_512); + iwl_pcie_write_prph_no_grab(trans, RFH_RXF_DMA_CFG, + RFH_DMA_EN_ENABLE_VAL | rb_size | + RFH_RXF_DMA_MIN_RB_4_8 | + RFH_RXF_DMA_DROP_TOO_LARGE_MASK | + RFH_RXF_DMA_RBDCB_SIZE_512); /* * Activate DMA snooping. * Set RX DMA chunk size to 64B for IOSF and 128B for PCIe * Default queue is 0 */ - iwl_write_prph_no_grab(trans, RFH_GEN_CFG, - RFH_GEN_CFG_RFH_DMA_SNOOP | - RFH_GEN_CFG_VAL(DEFAULT_RXQ_NUM, 0) | - RFH_GEN_CFG_SERVICE_DMA_SNOOP | - RFH_GEN_CFG_VAL(RB_CHUNK_SIZE, - trans->mac_cfg->integrated ? - RFH_GEN_CFG_RB_CHUNK_SIZE_64 : - RFH_GEN_CFG_RB_CHUNK_SIZE_128)); + iwl_pcie_write_prph_no_grab(trans, RFH_GEN_CFG, + RFH_GEN_CFG_RFH_DMA_SNOOP | + RFH_GEN_CFG_VAL(DEFAULT_RXQ_NUM, 0) | + RFH_GEN_CFG_SERVICE_DMA_SNOOP | + RFH_GEN_CFG_VAL(RB_CHUNK_SIZE, + trans->mac_cfg->integrated ? + RFH_GEN_CFG_RB_CHUNK_SIZE_64 : + RFH_GEN_CFG_RB_CHUNK_SIZE_128)); /* Enable the relevant rx queues */ - iwl_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, enabled); + iwl_pcie_write_prph_no_grab(trans, RFH_RXF_RXQ_ACTIVE, enabled); iwl_trans_release_nic_access(trans); @@ -1709,7 +1709,7 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) } if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) { - u32 val = iwl_read32(trans, CSR_IPC_STATE); + u32 val = iwl_trans_pcie_read32(trans, CSR_IPC_STATE); if (val & CSR_IPC_STATE_TOP_RESET_REQ) { IWL_ERR(trans, "FW requested TOP reset for FSEQ\n"); @@ -1734,7 +1734,7 @@ static u32 iwl_pcie_int_cause_non_ict(struct iwl_trans *trans) trace_iwlwifi_dev_irq(trans->dev); /* Discover which interrupts are active/pending */ - inta = iwl_read32(trans, CSR_INT); + inta = iwl_trans_pcie_read32(trans, CSR_INT); /* the thread will service interrupts and re-enable them */ return inta; @@ -1851,7 +1851,7 @@ static void iwl_trans_pcie_handle_reset_interrupt(struct iwl_trans *trans) u32 state; if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC) { - u32 val = iwl_read32(trans, CSR_IPC_STATE); + u32 val = iwl_trans_pcie_read32(trans, CSR_IPC_STATE); state = u32_get_bits(val, CSR_IPC_STATE_RESET); IWL_DEBUG_ISR(trans, "IPC state = 0x%x/%d\n", val, state); @@ -1923,8 +1923,8 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x(sw), enabled(hw) 0x%08x, fh 0x%08x\n", inta, trans_pcie->inta_mask, - iwl_read32(trans, CSR_INT_MASK), - iwl_read32(trans, CSR_FH_INT_STATUS)); + iwl_trans_pcie_read32(trans, CSR_INT_MASK), + iwl_trans_pcie_read32(trans, CSR_FH_INT_STATUS)); if (inta & (~trans_pcie->inta_mask)) IWL_DEBUG_ISR(trans, "We got a masked interrupt (0x%08x)\n", @@ -1972,11 +1972,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) * hardware bugs here by ACKing all the possible interrupts so that * interrupt coalescing can still be achieved. */ - iwl_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask); + iwl_trans_pcie_write32(trans, CSR_INT, inta | ~trans_pcie->inta_mask); if (iwl_have_debug_level(IWL_DL_ISR)) IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", - inta, iwl_read32(trans, CSR_INT_MASK)); + inta, iwl_trans_pcie_read32(trans, CSR_INT_MASK)); spin_unlock_bh(&trans_pcie->irq_lock); @@ -2071,13 +2071,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) IWL_DEBUG_ISR(trans, "Rx interrupt\n"); if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(trans, CSR_FH_INT_STATUS, - CSR_FH_INT_RX_MASK); + iwl_trans_pcie_write32(trans, CSR_FH_INT_STATUS, + CSR_FH_INT_RX_MASK); } if (inta & CSR_INT_BIT_RX_PERIODIC) { handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(trans, - CSR_INT, CSR_INT_BIT_RX_PERIODIC); + iwl_trans_pcie_write32(trans, + CSR_INT, CSR_INT_BIT_RX_PERIODIC); } /* Sending RX interrupt require many steps to be done in the * device: @@ -2117,7 +2117,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) /* This "Tx" DMA channel is used only for loading uCode */ if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(trans, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); + iwl_trans_pcie_write32(trans, CSR_FH_INT_STATUS, CSR_FH_INT_TX_MASK); IWL_DEBUG_ISR(trans, "uCode load interrupt\n"); isr_stats->tx++; handled |= CSR_INT_BIT_FH_TX; @@ -2231,10 +2231,10 @@ void iwl_pcie_reset_ict(struct iwl_trans *trans) IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); - iwl_write32(trans, CSR_DRAM_INT_TBL_REG, val); + iwl_trans_pcie_write32(trans, CSR_DRAM_INT_TBL_REG, val); trans_pcie->use_ict = true; trans_pcie->ict_index = 0; - iwl_write32(trans, CSR_INT, trans_pcie->inta_mask); + iwl_trans_pcie_write32(trans, CSR_INT, trans_pcie->inta_mask); _iwl_enable_interrupts(trans); spin_unlock_bh(&trans_pcie->irq_lock); } @@ -2261,7 +2261,7 @@ irqreturn_t iwl_pcie_isr(int irq, void *data) * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - iwl_write32(trans, CSR_INT_MASK, 0x00000000); + iwl_trans_pcie_write32(trans, CSR_INT_MASK, 0x00000000); return IRQ_WAKE_THREAD; } @@ -2291,13 +2291,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) lock_map_acquire(&trans->sync_cmd_lockdep_map); spin_lock_bh(&trans_pcie->irq_lock); - inta_fh = iwl_read32(trans, CSR_MSIX_FH_INT_CAUSES_AD); - inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD); + inta_fh = iwl_trans_pcie_read32(trans, CSR_MSIX_FH_INT_CAUSES_AD); + inta_hw = iwl_trans_pcie_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD); /* * Clear causes registers to avoid being handling the same cause. */ - iwl_write32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh & inta_fh_msk); - iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, inta_hw); + iwl_trans_pcie_write32(trans, CSR_MSIX_FH_INT_CAUSES_AD, inta_fh & inta_fh_msk); + iwl_trans_pcie_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, inta_hw); spin_unlock_bh(&trans_pcie->irq_lock); trace_iwlwifi_dev_irq_msix(trans->dev, entry, true, inta_fh, inta_hw); @@ -2312,7 +2312,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) IWL_DEBUG_ISR(trans, "ISR[%d] inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n", entry->entry, inta_fh, trans_pcie->fh_mask, - iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD)); + iwl_trans_pcie_read32(trans, CSR_MSIX_FH_INT_MASK_AD)); if (inta_fh & ~trans_pcie->fh_mask) IWL_DEBUG_ISR(trans, "We got a masked interrupt (0x%08x)\n", @@ -2414,7 +2414,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) IWL_DEBUG_ISR(trans, "ISR[%d] inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n", entry->entry, inta_hw, trans_pcie->hw_mask, - iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD)); + iwl_trans_pcie_read32(trans, CSR_MSIX_HW_INT_MASK_AD)); if (inta_hw & ~trans_pcie->hw_mask) IWL_DEBUG_ISR(trans, "We got a masked interrupt 0x%08x\n", diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 39dd963920b3..91d0b935fca6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -111,8 +111,8 @@ _iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans, iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE); else - iwl_write32(trans, CSR_DOORBELL_VECTOR, - UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE); + iwl_trans_pcie_write32(trans, CSR_DOORBELL_VECTOR, + UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE); /* wait 200ms */ ret = wait_event_timeout(trans_pcie->fw_reset_waitq, @@ -123,11 +123,11 @@ _iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans, u32 inta_hw; if (trans_pcie->msix_enabled) { - inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD); + inta_hw = iwl_trans_pcie_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD); reset_done = inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE; } else { - inta_hw = iwl_read32(trans, CSR_INT); + inta_hw = iwl_trans_pcie_read32(trans, CSR_INT); reset_done = inta_hw & CSR_INT_BIT_RESET_DONE; } @@ -434,7 +434,7 @@ static bool iwl_pcie_set_ltr(struct iwl_trans *trans) if ((trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210 || trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000) && !trans->mac_cfg->integrated) { - iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); + iwl_trans_pcie_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); return true; } @@ -447,8 +447,8 @@ static bool iwl_pcie_set_ltr(struct iwl_trans *trans) if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) { /* First clear the interrupt, just in case */ - iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, - MSIX_HW_INT_CAUSES_REG_IML); + iwl_trans_pcie_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, + MSIX_HW_INT_CAUSES_REG_IML); /* In this case, unfortunately the same ROM bug exists in the * device (not setting LTR correctly), but we don't have control * over the settings from the host due to some hardware security @@ -475,18 +475,18 @@ static void iwl_pcie_spin_for_iml(struct iwl_trans *trans) if (WARN_ON(!trans_pcie->iml)) return; - value = iwl_read32(trans, CSR_LTR_LAST_MSG); + value = iwl_trans_pcie_read32(trans, CSR_LTR_LAST_MSG); IWL_DEBUG_INFO(trans, "Polling for IML load - CSR_LTR_LAST_MSG=0x%x\n", value); while (time_before(jiffies, end_time)) { - if (iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD) & + if (iwl_trans_pcie_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD) & MSIX_HW_INT_CAUSES_REG_IML) { irq = true; break; } /* Keep the CPU and device busy. */ - value = iwl_read32(trans, CSR_LTR_LAST_MSG); + value = iwl_trans_pcie_read32(trans, CSR_LTR_LAST_MSG); loops++; } @@ -522,7 +522,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, iwl_enable_rfkill_int(trans); - iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + iwl_trans_pcie_write32(trans, CSR_INT, 0xFFFFFFFF); /* * We enabled the RF-Kill interrupt and the handler may very @@ -550,12 +550,12 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, } /* make sure rfkill handshake bits are cleared */ - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + iwl_trans_pcie_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_trans_pcie_write32(trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + iwl_trans_pcie_write32(trans, CSR_INT, 0xFFFFFFFF); ret = iwl_pcie_gen2_nic_init(trans); if (ret) { @@ -591,8 +591,8 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { IWL_DEBUG_POWER(trans, "function scratch register value is 0x%08x\n", - iwl_read32(trans, CSR_FUNC_SCRATCH)); - iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE); + iwl_trans_pcie_read32(trans, CSR_FUNC_SCRATCH)); + iwl_trans_pcie_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE); iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_ROM_START); } else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b81dd7daca6c..8dc8924564e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -44,10 +44,10 @@ static void iwl_dump_host_monitor_block(struct iwl_trans *trans, int i; IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec); - iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); + iwl_trans_pcie_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); for (i = 0; i < iter; i++) IWL_ERR(trans, " value [iter %d]: 0x%08x\n", - i, iwl_read32(trans, CSR_MONITOR_STATUS_REG)); + i, iwl_trans_pcie_read32(trans, CSR_MONITOR_STATUS_REG)); } static void iwl_pcie_dump_host_monitor(struct iwl_trans *trans) @@ -56,7 +56,7 @@ static void iwl_pcie_dump_host_monitor(struct iwl_trans *trans) case IWL_DEVICE_FAMILY_22000: case IWL_DEVICE_FAMILY_AX210: IWL_ERR(trans, "CSR_RESET = 0x%x\n", - iwl_read32(trans, CSR_RESET)); + iwl_trans_pcie_read32(trans, CSR_RESET)); iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, IWL_HOST_MON_BLOCK_PEMON_VEC0, 15); iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, @@ -170,16 +170,16 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power) static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) { - iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, - ((reg & 0x0000ffff) | (2 << 28))); - return iwl_read32(trans, HEEP_CTRL_WRD_PCIEX_DATA_REG); + iwl_trans_pcie_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, + ((reg & 0x0000ffff) | (2 << 28))); + return iwl_trans_pcie_read32(trans, HEEP_CTRL_WRD_PCIEX_DATA_REG); } static void iwl_trans_pcie_write_shr(struct iwl_trans *trans, u32 reg, u32 val) { - iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_DATA_REG, val); - iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, - ((reg & 0x0000ffff) | (3 << 28))); + iwl_trans_pcie_write32(trans, HEEP_CTRL_WRD_PCIEX_DATA_REG, val); + iwl_trans_pcie_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, + ((reg & 0x0000ffff) | (3 << 28))); } static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) @@ -603,28 +603,28 @@ static void iwl_pcie_load_firmware_chunk_fh(struct iwl_trans *trans, u32 dst_addr, dma_addr_t phy_addr, u32 byte_cnt) { - iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); + iwl_trans_pcie_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - iwl_write32(trans, FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), - dst_addr); + iwl_trans_pcie_write32(trans, FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), + dst_addr); - iwl_write32(trans, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), - phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); + iwl_trans_pcie_write32(trans, FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), + phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - iwl_write32(trans, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), - (iwl_get_dma_hi_addr(phy_addr) - << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); + iwl_trans_pcie_write32(trans, FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), + (iwl_get_dma_hi_addr(phy_addr) + << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - iwl_write32(trans, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), - BIT(FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) | - BIT(FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) | - FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); + iwl_trans_pcie_write32(trans, FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), + BIT(FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) | + BIT(FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) | + FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | - FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); + iwl_trans_pcie_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | + FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); } static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans, @@ -884,7 +884,7 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) switch (dest->reg_ops[i].op) { case CSR_ASSIGN: - iwl_write32(trans, addr, val); + iwl_trans_pcie_write32(trans, addr, val); break; case CSR_SETBIT: iwl_set_bit(trans, addr, BIT(val)); @@ -964,7 +964,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, iwl_enable_interrupts(trans); /* release CPU reset */ - iwl_write32(trans, CSR_RESET, 0); + iwl_trans_pcie_write32(trans, CSR_RESET, 0); return 0; } @@ -1123,7 +1123,7 @@ static void iwl_pcie_map_rx_causes(struct iwl_trans *trans) MSIX_FH_INT_CAUSES_Q(idx - offset)); val |= BIT(MSIX_FH_INT_CAUSES_Q(idx)); } - iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~val); + iwl_trans_pcie_write32(trans, CSR_MSIX_FH_INT_MASK_AD, ~val); val = MSIX_FH_INT_CAUSES_Q(0); if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX) @@ -1174,9 +1174,9 @@ static void iwl_pcie_init_msix(struct iwl_trans_pcie *trans_pcie) if (!trans_pcie->msix_enabled) return; - trans_pcie->fh_init_mask = ~iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD); + trans_pcie->fh_init_mask = ~iwl_trans_pcie_read32(trans, CSR_MSIX_FH_INT_MASK_AD); trans_pcie->fh_mask = trans_pcie->fh_init_mask; - trans_pcie->hw_init_mask = ~iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD); + trans_pcie->hw_init_mask = ~iwl_trans_pcie_read32(trans, CSR_MSIX_HW_INT_MASK_AD); trans_pcie->hw_mask = trans_pcie->hw_init_mask; } @@ -1296,7 +1296,7 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_enable_rfkill_int(trans); - iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + iwl_trans_pcie_write32(trans, CSR_INT, 0xFFFFFFFF); /* * We enabled the RF-Kill interrupt and the handler may very @@ -1326,12 +1326,12 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, } /* make sure rfkill handshake bits are cleared */ - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); + iwl_trans_pcie_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_trans_pcie_write32(trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl_write32(trans, CSR_INT, 0xFFFFFFFF); + iwl_trans_pcie_write32(trans, CSR_INT, 0xFFFFFFFF); ret = iwl_pcie_nic_init(trans); if (ret) { @@ -1349,8 +1349,8 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_enable_fw_load_int(trans); /* really make sure rfkill handshake bits are cleared */ - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_trans_pcie_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_trans_pcie_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); /* Load the given image to the HW */ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000) @@ -1482,9 +1482,9 @@ static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend) suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND : UREG_DOORBELL_TO_ISR6_RESUME); else - iwl_write32(trans, CSR_IPC_SLEEP_CONTROL, - suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND : - CSR_IPC_SLEEP_CONTROL_RESUME); + iwl_trans_pcie_write32(trans, CSR_IPC_SLEEP_CONTROL, + suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND : + CSR_IPC_SLEEP_CONTROL_RESUME); ret = wait_event_timeout(trans_pcie->sx_waitq, trans_pcie->sx_state != IWL_SX_WAITING, @@ -1579,7 +1579,7 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n", iwl_read_umac_prph(trans, WFPM_GP2)); - val = iwl_read32(trans, CSR_RESET); + val = iwl_trans_pcie_read32(trans, CSR_RESET); if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { IWL_INFO(trans, "Device was reset during suspend\n"); trans->state = IWL_TRANS_NO_FW; @@ -1870,12 +1870,16 @@ void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val) { + trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); writel(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); } u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) { - return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); + u32 val = readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs); + + trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); + return val; } static u32 iwl_trans_pcie_prph_msk(struct iwl_trans *trans) @@ -1899,6 +1903,7 @@ void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val) { u32 mask = iwl_trans_pcie_prph_msk(trans); + trace_iwlwifi_dev_iowrite_prph32(trans->dev, addr, val); iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR, ((addr & mask) | (3 << 24))); iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); @@ -2377,7 +2382,7 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) */ ret = iwl_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000); if (unlikely(ret)) { - u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL); + u32 cntrl = iwl_trans_pcie_read32(trans, CSR_GP_CNTRL); if (silent) { spin_unlock(&trans_pcie->reg_lock); @@ -2394,8 +2399,8 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) iwl_trans_pcie_reset(trans, IWL_RESET_MODE_REMOVE_ONLY); else - iwl_write32(trans, CSR_RESET, - CSR_RESET_REG_FLAG_FORCE_NMI); + iwl_trans_pcie_write32(trans, CSR_RESET, + CSR_RESET_REG_FLAG_FORCE_NMI); spin_unlock(&trans_pcie->reg_lock); return false; @@ -2473,12 +2478,12 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, bool resched = false; if (iwl_trans_grab_nic_access(trans)) { - iwl_write32(trans, HBUS_TARG_MEM_RADDR, - addr + 4 * offs); + iwl_trans_pcie_write32(trans, HBUS_TARG_MEM_RADDR, + addr + 4 * offs); while (offs < dwords) { - vals[offs] = iwl_read32(trans, - HBUS_TARG_MEM_RDAT); + vals[offs] = iwl_trans_pcie_read32(trans, + HBUS_TARG_MEM_RDAT); if (iwl_trans_is_hw_error_value(vals[offs])) num_consec_hw_errors++; @@ -2525,11 +2530,11 @@ int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr, unsigned long end = jiffies + HZ / 2; bool resched = false; - iwl_write32(trans, HBUS_TARG_MEM_RADDR, - addr + 4 * offs); + iwl_trans_pcie_write32(trans, HBUS_TARG_MEM_RADDR, + addr + 4 * offs); while (offs < dwords) { - vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); + vals[offs] = iwl_trans_pcie_read32(trans, HBUS_TARG_MEM_RDAT); if (iwl_trans_is_hw_error_value(vals[offs])) num_consec_hw_errors++; @@ -2746,7 +2751,7 @@ void iwl_pcie_dump_csr(struct iwl_trans *trans) for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { IWL_ERR(trans, " %25s: 0X%08x\n", get_csr_string(csr_tbl[i]), - iwl_read32(trans, csr_tbl[i])); + iwl_trans_pcie_read32(trans, csr_tbl[i])); } } @@ -3022,7 +3027,7 @@ static ssize_t iwl_dbgfs_rfkill_read(struct file *file, pos = scnprintf(buf, sizeof(buf), "debug: %d\nhw: %d\n", trans_pcie->debug_rfkill, - !(iwl_read32(trans, CSR_GP_CNTRL) & + !(iwl_trans_pcie_read32(trans, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -3593,12 +3598,12 @@ void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans) iwl_trans_force_nmi(trans); while (time_after(timeout, jiffies)) { - u32 inta_hw = iwl_read32(trans, inta_addr); + u32 inta_hw = iwl_trans_pcie_read32(trans, inta_addr); /* Error detected by uCode */ if (inta_hw & sw_err_bit) { /* Clear causes register */ - iwl_write32(trans, inta_addr, inta_hw & sw_err_bit); + iwl_trans_pcie_write32(trans, inta_addr, inta_hw & sw_err_bit); break; } @@ -4044,7 +4049,7 @@ static void iwl_pcie_recheck_me_status(struct work_struct *wk) me_recheck_wk.work); u32 val; - val = iwl_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG); + val = iwl_trans_pcie_read32(trans_pcie->trans, CSR_HW_IF_CONFIG_REG); trans_pcie->me_present = !!(val & CSR_HW_IF_CONFIG_REG_IAMT_UP); } @@ -4062,14 +4067,14 @@ static void iwl_pcie_check_me_status(struct iwl_trans *trans) if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ) return; - val = iwl_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1); + val = iwl_trans_pcie_read_prph(trans, CNVI_SCU_REG_FOR_ECO_1); if (val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_KNOWN) { trans_pcie->me_present = !!(val & CNVI_SCU_REG_FOR_ECO_1_WIAMT_PRESENT); return; } - val = iwl_read32(trans, CSR_HW_IF_CONFIG_REG); + val = iwl_trans_pcie_read32(trans, CSR_HW_IF_CONFIG_REG); if (val & (CSR_HW_IF_CONFIG_REG_ME_OWN | CSR_HW_IF_CONFIG_REG_IAMT_UP)) { trans_pcie->me_present = 1; @@ -4127,7 +4132,7 @@ int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, } } - info.hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID); + info.hw_rf_id = iwl_trans_pcie_read32(iwl_trans, CSR_HW_RF_ID); /* * The RF_ID is set to zero in blank OTP so read version to diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 27f4973791d0..abdb2548827f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020, 2023-2025 Intel Corporation + * Copyright (C) 2018-2020, 2023-2026 Intel Corporation */ #include #include @@ -711,7 +711,7 @@ static void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) * if not in power-save mode, uCode will never sleep when we're * trying to tx (during RFKILL, we're not trying to tx). */ - iwl_write32(trans, HBUS_TARG_WRPTR, txq->write_ptr | (txq->id << 16)); + iwl_trans_pcie_write32(trans, HBUS_TARG_WRPTR, txq->write_ptr | (txq->id << 16)); } int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index bdd330280689..f5aa456180d8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -99,7 +99,7 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); + reg = iwl_trans_pcie_read32(trans, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", @@ -117,8 +117,8 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, */ IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->write_ptr); if (!txq->block) - iwl_write32(trans, HBUS_TARG_WRPTR, - txq->write_ptr | (txq_id << 8)); + iwl_trans_pcie_write32(trans, HBUS_TARG_WRPTR, + txq->write_ptr | (txq_id << 8)); } void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) @@ -586,7 +586,7 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) /* Stop each Tx DMA channel */ for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { - iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + iwl_trans_pcie_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); mask |= FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch); } @@ -595,7 +595,7 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) if (ret) IWL_ERR(trans, "Failing on timeout while stopping DMA channel %d [0x%08x]\n", - ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG)); + ch, iwl_trans_pcie_read32(trans, FH_TSSR_TX_STATUS_REG)); iwl_trans_release_nic_access(trans); @@ -1335,8 +1335,8 @@ static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block) if (!block && !(WARN_ON_ONCE(!txq->block))) { txq->block--; if (!txq->block) { - iwl_write32(trans, HBUS_TARG_WRPTR, - txq->write_ptr | (i << 8)); + iwl_trans_pcie_write32(trans, HBUS_TARG_WRPTR, + txq->write_ptr | (i << 8)); } } else if (block) { txq->block++; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c index bace3e21989c..4365ffb0fd37 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c @@ -51,7 +51,7 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev) IWL_ERR(trans, "iwlwifi device memory mapped registers:\n"); for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++) - *ptr = iwl_read32(trans, i); + *ptr = iwl_trans_pcie_read32(trans, i); print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0); pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); @@ -106,7 +106,7 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev) u32 iwl_pcie_read_direct32(struct iwl_trans *trans, u32 reg) { if (iwl_trans_grab_nic_access(trans)) { - u32 value = iwl_read32(trans, reg); + u32 value = iwl_trans_pcie_read32(trans, reg); iwl_trans_release_nic_access(trans); return value; @@ -176,8 +176,8 @@ int iwl_pcie_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr, void iwl_pcie_write_prph64_no_grab(struct iwl_trans *trans, u32 ofs, u64 val) { trace_iwlwifi_dev_iowrite_prph64(trans->dev, ofs, val); - iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff); - iwl_write_prph_no_grab(trans, ofs + 4, val >> 32); + iwl_pcie_write_prph_no_grab(trans, ofs, val & 0xffffffff); + iwl_pcie_write_prph_no_grab(trans, ofs + 4, val >> 32); } void iwl_pcie_write_direct64(struct iwl_trans *trans, u64 reg, u64 value) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index 341928cdb64b..2d92bff513df 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -7,6 +7,7 @@ #define __iwl_pcie_utils_h__ #include "iwl-io.h" +#include "internal.h" void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev); @@ -24,16 +25,15 @@ void iwl_pcie_write_direct64(struct iwl_trans *trans, u64 reg, u64 value); static inline void iwl_pcie_write64(struct iwl_trans *trans, u64 ofs, u64 val) { - trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val); - iwl_trans_write32(trans, ofs, lower_32_bits(val)); - iwl_trans_write32(trans, ofs + 4, upper_32_bits(val)); + iwl_trans_pcie_write32(trans, ofs, lower_32_bits(val)); + iwl_trans_pcie_write32(trans, ofs + 4, upper_32_bits(val)); } static inline void iwl_pcie_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) { - iwl_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset, - val); + iwl_pcie_write_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset, + val); } static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, @@ -45,10 +45,10 @@ static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, WARN_ON_ONCE(value & ~mask); #endif - v = iwl_read32(trans, reg); + v = iwl_trans_pcie_read32(trans, reg); v &= ~mask; v |= value; - iwl_write32(trans, reg, v); + iwl_trans_pcie_write32(trans, reg, v); } static inline void iwl_trans_clear_bit(struct iwl_trans *trans, From a35d782c25f5d8f5fe0e90a7af7099973e115cba Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:44 +0300 Subject: [PATCH 067/104] wifi: iwlwifi: rename iwl_trans_read_prph Functions that assume that nic access was acquired should have a _no_grab postfix, so the caller will know that he is responsible to have access when calling it. Add the postfix. Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.3441b513bd7f.If88dcac92f705918b550fd3e524196be1f8d92d0@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/dbg-old.c | 86 +++++++++---------- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 38 ++++---- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 2 +- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 8 +- .../net/wireless/intel/iwlwifi/iwl-trans.c | 2 +- .../net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- 6 files changed, 69 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c index a4e1f82c8bd1..320e891b3b03 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c @@ -48,7 +48,7 @@ static void iwl_read_radio_regs(struct iwl_fw_runtime *fwrt, rd_cmd |= i << RADIO_RSP_ADDR_POS; iwl_trans_write_prph_no_grab(fwrt->trans, RSP_RADIO_CMD, rd_cmd); - *pos = (u8)iwl_trans_read_prph(fwrt->trans, RSP_RADIO_RDDAT); + *pos = (u8)iwl_trans_read_prph_no_grab(fwrt->trans, RSP_RADIO_RDDAT); pos++; } @@ -81,20 +81,20 @@ static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt, fifo_hdr->fifo_num = cpu_to_le32(fifo_num); fifo_hdr->available_bytes = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - RXF_RD_D_SPACE + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + RXF_RD_D_SPACE + offset)); fifo_hdr->wr_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - RXF_RD_WR_PTR + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + RXF_RD_WR_PTR + offset)); fifo_hdr->rd_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - RXF_RD_RD_PTR + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + RXF_RD_RD_PTR + offset)); fifo_hdr->fence_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - RXF_RD_FENCE_PTR + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + RXF_RD_FENCE_PTR + offset)); fifo_hdr->fence_mode = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - RXF_SET_FENCE_MODE + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + RXF_SET_FENCE_MODE + offset)); /* Lock fence */ iwl_trans_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offset, 0x1); @@ -107,9 +107,9 @@ static void iwl_fwrt_dump_rxf(struct iwl_fw_runtime *fwrt, /* Read FIFO */ fifo_len /= sizeof(u32); /* Size in DWORDS */ for (i = 0; i < fifo_len; i++) - fifo_data[i] = iwl_trans_read_prph(fwrt->trans, - RXF_FIFO_RD_FENCE_INC + - offset); + fifo_data[i] = iwl_trans_read_prph_no_grab(fwrt->trans, + RXF_FIFO_RD_FENCE_INC + + offset); *dump_data = iwl_fw_error_next_data(*dump_data); } @@ -136,33 +136,33 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt, fifo_hdr->fifo_num = cpu_to_le32(fifo_num); fifo_hdr->available_bytes = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_FIFO_ITEM_CNT + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_FIFO_ITEM_CNT + offset)); fifo_hdr->wr_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_WR_PTR + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_WR_PTR + offset)); fifo_hdr->rd_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_RD_PTR + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_RD_PTR + offset)); fifo_hdr->fence_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_FENCE_PTR + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_FENCE_PTR + offset)); fifo_hdr->fence_mode = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_LOCK_FENCE + offset)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_LOCK_FENCE + offset)); /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */ iwl_trans_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offset, TXF_WR_PTR + offset); /* Dummy-read to advance the read pointer to the head */ - iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset); + iwl_trans_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offset); /* Read FIFO */ for (i = 0; i < fifo_len / sizeof(u32); i++) - fifo_data[i] = iwl_trans_read_prph(fwrt->trans, - TXF_READ_MODIFY_DATA + - offset); + fifo_data[i] = iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_READ_MODIFY_DATA + + offset); if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, @@ -266,20 +266,20 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, fwrt->smem_cfg.num_txfifo_entries); fifo_hdr->available_bytes = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_FIFO_ITEM_CNT)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_FIFO_ITEM_CNT)); fifo_hdr->wr_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_WR_PTR)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_WR_PTR)); fifo_hdr->rd_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_RD_PTR)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_RD_PTR)); fifo_hdr->fence_ptr = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_FENCE_PTR)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_FENCE_PTR)); fifo_hdr->fence_mode = - cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_LOCK_FENCE)); + cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_LOCK_FENCE)); /* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */ iwl_trans_write_prph_no_grab(fwrt->trans, @@ -287,15 +287,15 @@ static void iwl_fw_dump_txf(struct iwl_fw_runtime *fwrt, TXF_CPU2_WR_PTR); /* Dummy-read to advance the read pointer to head */ - iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_READ_MODIFY_DATA); + iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_READ_MODIFY_DATA); /* Read FIFO */ fifo_len /= sizeof(u32); /* Size in DWORDS */ for (j = 0; j < fifo_len; j++) fifo_data[j] = - iwl_trans_read_prph(fwrt->trans, - TXF_CPU2_READ_MODIFY_DATA); + iwl_trans_read_prph_no_grab(fwrt->trans, + TXF_CPU2_READ_MODIFY_DATA); *dump_data = iwl_fw_error_next_data(*dump_data); } } @@ -514,7 +514,7 @@ static void iwl_read_prph_block(struct iwl_trans *trans, u32 start, u32 i; for (i = 0; i < len_bytes; i += 4) - *data++ = cpu_to_le32(iwl_trans_read_prph(trans, start + i)); + *data++ = cpu_to_le32(iwl_trans_read_prph_no_grab(trans, start + i)); } static void iwl_dump_prph(struct iwl_fw_runtime *fwrt, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 8d08ce7db3b9..3a0318070bfb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -103,7 +103,7 @@ static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = size; for (i = 0; i < le32_to_cpu(size); i += 4) - *val++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr + i)); + *val++ = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, addr + i)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -177,8 +177,8 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR1 && fwrt->trans->info.hw_rf_id != IWL_CFG_RF_TYPE_HR2) { udelay(2); - prph_stts = iwl_trans_read_prph(fwrt->trans, - WMAL_MRSPF_STTS); + prph_stts = iwl_trans_read_prph_no_grab(fwrt->trans, + WMAL_MRSPF_STTS); /* Abort dump if status is 0xA5A5A5A2 or FIFO1 empty */ if (prph_stts == WMAL_TIMEOUT_VAL || @@ -186,8 +186,8 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, break; } - prph_val = iwl_trans_read_prph(fwrt->trans, - indirect_rd_addr); + prph_val = iwl_trans_read_prph_no_grab(fwrt->trans, + indirect_rd_addr); *val++ = cpu_to_le32(prph_val); } @@ -456,8 +456,8 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, addr = le32_to_cpu(reg->addrs[i]) + offs; reg_dump->addr = cpu_to_le32(addr); - reg_dump->data = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - addr)); + reg_dump->data = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + addr)); reg_dump++; } @@ -472,13 +472,13 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, TXF_WR_PTR + offs); /* Dummy-read to advance the read pointer to the head */ - iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offs); + iwl_trans_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offs); /* Read FIFO */ addr = TXF_READ_MODIFY_DATA + offs; data = (void *)reg_dump; for (i = 0; i < iter->fifo_size; i += sizeof(*data)) - *data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr)); + *data++ = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, addr)); if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx, @@ -522,8 +522,8 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt, addr + i); /* wait a bit for value to be ready in register */ udelay(1); - prph_val = iwl_trans_read_prph(fwrt->trans, - indirect_rd_wr_addr); + prph_val = iwl_trans_read_prph_no_grab(fwrt->trans, + indirect_rd_wr_addr); *val++ = cpu_to_le32((prph_val & DPHYIP_INDIRECT_RD_MSK) >> DPHYIP_INDIRECT_RD_SHIFT); } @@ -628,8 +628,8 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, addr = le32_to_cpu(reg->addrs[i]) + offs; reg_dump->addr = cpu_to_le32(addr); - reg_dump->data = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, - addr)); + reg_dump->data = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, + addr)); reg_dump++; } @@ -652,7 +652,7 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, addr = RXF_FIFO_RD_FENCE_INC + offs; data = (void *)reg_dump; for (i = 0; i < rxf_data.size; i += sizeof(*data)) - *data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr)); + *data++ = cpu_to_le32(iwl_trans_read_prph_no_grab(fwrt->trans, addr)); out: return sizeof(*range) + le32_to_cpu(range->range_data_size); @@ -712,10 +712,10 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt, range->range_data_size = reg->dev_addr.size; for (i = 0; i < (le32_to_cpu(reg->dev_addr.size) / 4); i++) { prph_data = - iwl_trans_read_prph(fwrt->trans, - (i % 2) ? - DBGI_SRAM_TARGET_ACCESS_RDATA_MSB : - DBGI_SRAM_TARGET_ACCESS_RDATA_LSB); + iwl_trans_read_prph_no_grab(fwrt->trans, + (i % 2) ? + DBGI_SRAM_TARGET_ACCESS_RDATA_MSB : + DBGI_SRAM_TARGET_ACCESS_RDATA_LSB); if (iwl_trans_is_hw_error_value(prph_data)) return -EBUSY; *val++ = cpu_to_le32(prph_data); @@ -812,7 +812,7 @@ static __le32 iwl_get_mon_reg(struct iwl_fw_runtime *fwrt, u32 alloc_id, if (!reg_info || !reg_info->addr || !reg_info->mask) return 0; - val = iwl_trans_read_prph(fwrt->trans, reg_info->addr + offs); + val = iwl_trans_read_prph_no_grab(fwrt->trans, reg_info->addr + offs); return cpu_to_le32(mask_apply_and_normalize(val, reg_info->mask)); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 085074be2549..bc3ef107c4eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -40,7 +40,7 @@ IWL_EXPORT_SYMBOL(iwl_write_direct32); u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) { - u32 val = iwl_trans_read_prph(trans, ofs); + u32 val = iwl_trans_read_prph_no_grab(trans, ofs); trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val); return val; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 76cba6ac0c8b..9e02a498b5f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1367,10 +1367,10 @@ static void iwl_set_hw_address_family_8000(struct iwl_trans *trans, if (nvm_hw) { /* read the mac address from WFMP registers */ - __le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph(trans, - WFMP_MAC_ADDR_0)); - __le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph(trans, - WFMP_MAC_ADDR_1)); + __le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph_no_grab(trans, + WFMP_MAC_ADDR_0)); + __le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph_no_grab(trans, + WFMP_MAC_ADDR_1)); iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 2d0bb3de7df5..123eca3f5d0a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -440,7 +440,7 @@ u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) } IWL_EXPORT_SYMBOL(iwl_trans_read32); -u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs) +u32 iwl_trans_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) { return iwl_trans_pcie_read_prph(trans, ofs); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index c882313eaceb..18c1c46c11ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -914,7 +914,7 @@ void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val); u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs); -u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs); +u32 iwl_trans_read_prph_no_grab(struct iwl_trans *trans, u32 ofs); void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val); From e8733ea9818b00244e9277ad8b828e92ac90b13c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:45 +0300 Subject: [PATCH 068/104] wifi: iwlwifi: collapse iwl_read_prph_no_grab() into the transport API iwl_read_prph_no_grab() was a thin wrapper that read via iwl_trans_read_prph_no_grab() and emitted the ioread_prph32 tracepoint. Fold the tracepoint into the bus-specific implementation (iwl_trans_pcie_read_prph()) and remove the wrapper, so callers use the transport API (or the pcie primitive from within pcie) directly. No functional change intended. Assisted-by: GitHubCopilot:claude-opus-4.8 Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.592c74d42694.I329ccec5de9d0a6ec87538aceabce17149258841@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 6 +++--- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 15 ++++----------- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 5 ++--- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 9 ++++++--- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index eef89c141564..7b9e98a21704 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -360,7 +360,7 @@ static void iwl_fwrt_dump_fseq_regs(struct iwl_fw_runtime *fwrt) for (i = 0; i < ARRAY_SIZE(fseq_regs); i++) IWL_ERR(fwrt, "0x%08X | %s\n", - iwl_read_prph_no_grab(trans, fseq_regs[i].addr), + iwl_trans_read_prph_no_grab(trans, fseq_regs[i].addr), fseq_regs[i].str); iwl_trans_release_nic_access(trans); @@ -398,8 +398,8 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt) count++, pc_data++) IWL_ERR(fwrt, "%s: 0x%x\n", pc_data->pc_name, - iwl_read_prph_no_grab(fwrt->trans, - pc_data->pc_address)); + iwl_trans_read_prph_no_grab(fwrt->trans, + pc_data->pc_address)); iwl_trans_release_nic_access(fwrt->trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index bc3ef107c4eb..515d6b2becc9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -38,17 +38,10 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) } IWL_EXPORT_SYMBOL(iwl_write_direct32); -u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) -{ - u32 val = iwl_trans_read_prph_no_grab(trans, ofs); - trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val); - return val; -} - u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) { if (iwl_trans_grab_nic_access(trans)) { - u32 val = iwl_read_prph_no_grab(trans, ofs); + u32 val = iwl_trans_read_prph_no_grab(trans, ofs); iwl_trans_release_nic_access(trans); @@ -74,7 +67,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) { if (iwl_trans_grab_nic_access(trans)) { iwl_trans_write_prph_no_grab(trans, ofs, - iwl_read_prph_no_grab(trans, ofs) | + iwl_trans_read_prph_no_grab(trans, ofs) | mask); iwl_trans_release_nic_access(trans); } @@ -86,7 +79,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, { if (iwl_trans_grab_nic_access(trans)) { iwl_trans_write_prph_no_grab(trans, ofs, - (iwl_read_prph_no_grab(trans, ofs) & + (iwl_trans_read_prph_no_grab(trans, ofs) & mask) | bits); iwl_trans_release_nic_access(trans); } @@ -98,7 +91,7 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) u32 val; if (iwl_trans_grab_nic_access(trans)) { - val = iwl_read_prph_no_grab(trans, ofs); + val = iwl_trans_read_prph_no_grab(trans, ofs); iwl_trans_write_prph_no_grab(trans, ofs, (val & ~mask)); iwl_trans_release_nic_access(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index b33bc4822e5c..a26c6525ec40 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -29,7 +29,6 @@ static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits, void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); -u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs); u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms); @@ -55,8 +54,8 @@ static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs) static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) { - return iwl_read_prph_no_grab(trans, ofs + - trans->mac_cfg->umac_prph_offset); + return iwl_trans_read_prph_no_grab(trans, ofs + + trans->mac_cfg->umac_prph_offset); } static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 8dc8924564e5..709c2499ffc8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1893,10 +1893,13 @@ static u32 iwl_trans_pcie_prph_msk(struct iwl_trans *trans) u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg) { u32 mask = iwl_trans_pcie_prph_msk(trans); + u32 val; iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, ((reg & mask) | (3 << 24))); - return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); + val = iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT); + trace_iwlwifi_dev_ioread_prph32(trans->dev, reg, val); + return val; } void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val) @@ -3938,10 +3941,10 @@ static void get_crf_id(struct iwl_trans *iwl_trans, iwl_pcie_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val); /* Read crf info */ - info->hw_crf_id = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr); + info->hw_crf_id = iwl_trans_pcie_read_prph(iwl_trans, sd_reg_ver_addr); /* Read cnv info */ - info->hw_cnv_id = iwl_read_prph_no_grab(iwl_trans, CNVI_AUX_MISC_CHIP); + info->hw_cnv_id = iwl_trans_pcie_read_prph(iwl_trans, CNVI_AUX_MISC_CHIP); /* For BZ-W, take B step also when A step is indicated */ if (CSR_HW_REV_TYPE(info->hw_rev) == IWL_CFG_MAC_TYPE_BZ_W) From cc5782ad2ed4e07364ebea93ef5b968c92d1e5bd Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:46 +0300 Subject: [PATCH 069/104] wifi: iwlwifi: pcie: rename pcie-internal functions Functions that are in pcie level should have the pcie prefix. In particular, the functions renamed in this commit are easy to be confused with the generic trans ones. Rename those functions to have a pcie prefix. Assisted-by: GitHubCopilot:claude-opus-4.8 Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.09af8a4d712b.I5867c6f937d569349e1950733361bf83a5e49fbb@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/pcie/trans.c | 28 +++++++++---------- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 4 +-- .../net/wireless/intel/iwlwifi/pcie/utils.h | 12 ++++---- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 709c2499ffc8..ce7d01a36688 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -334,8 +334,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) u32 dl_cfg_reg; /* Force XTAL ON */ - iwl_trans_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_XTAL_ON); + iwl_pcie_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_XTAL_ON); ret = iwl_trans_pcie_sw_reset(trans, true); @@ -344,8 +344,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) if (WARN_ON(ret)) { /* Release XTAL ON request */ - iwl_trans_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_XTAL_ON); + iwl_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_XTAL_ON); return; } @@ -396,12 +396,12 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* Activates XTAL resources monitor */ - iwl_trans_set_bit(trans, CSR_MONITOR_CFG_REG, - CSR_MONITOR_XTAL_RESOURCES); + iwl_pcie_set_bit(trans, CSR_MONITOR_CFG_REG, + CSR_MONITOR_XTAL_RESOURCES); /* Release XTAL ON request */ - iwl_trans_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_XTAL_ON); + iwl_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_XTAL_ON); udelay(10); /* Release APMG XTAL */ @@ -2359,7 +2359,7 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) } /* this bit wakes up the NIC */ - iwl_trans_set_bit(trans, CSR_GP_CNTRL, write); + iwl_pcie_set_bit(trans, CSR_GP_CNTRL, write); if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000) udelay(2); @@ -2452,11 +2452,11 @@ void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans) if (trans_pcie->cmd_hold_nic_awake) goto out; if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - iwl_trans_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + iwl_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); else - iwl_trans_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* * Above we read the CSR_GP_CNTRL register, which will flush * any previous writes, but we need the write that clears the @@ -2681,7 +2681,7 @@ void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); spin_lock_bh(&trans_pcie->reg_lock); - _iwl_trans_set_bits_mask(trans, reg, mask, value); + iwl_pcie_set_bits_mask(trans, reg, mask, value); spin_unlock_bh(&trans_pcie->reg_lock); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index f5aa456180d8..cd744f7002b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -205,8 +205,8 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) } trans_pcie->cmd_hold_nic_awake = false; - iwl_trans_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_pcie_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); spin_unlock(&trans_pcie->reg_lock); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index 2d92bff513df..74c23ec199e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -36,8 +36,8 @@ static inline void iwl_pcie_write_umac_prph_no_grab(struct iwl_trans *trans, val); } -static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, - u32 reg, u32 mask, u32 value) +static inline void iwl_pcie_set_bits_mask(struct iwl_trans *trans, + u32 reg, u32 mask, u32 value) { u32 v; @@ -51,16 +51,16 @@ static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, iwl_trans_pcie_write32(trans, reg, v); } -static inline void iwl_trans_clear_bit(struct iwl_trans *trans, +static inline void iwl_pcie_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) { - _iwl_trans_set_bits_mask(trans, reg, mask, 0); + iwl_pcie_set_bits_mask(trans, reg, mask, 0); } -static inline void iwl_trans_set_bit(struct iwl_trans *trans, +static inline void iwl_pcie_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { - _iwl_trans_set_bits_mask(trans, reg, mask, mask); + iwl_pcie_set_bits_mask(trans, reg, mask, mask); } #endif /* __iwl_pcie_utils_h__ */ From e46ac2e5fa10e1f7c9157ebccb5df018954aa863 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:47 +0300 Subject: [PATCH 070/104] wifi: iwlwifi: rename io helpers to iwl_trans_ prefix The iwl-io is a wrapper layer for all the device memory access operations. But all it really does is either a combination of other operations, or tracing and calling the trans function, which calls the bus-specific implementation. This makes the code hard to follow. Those helpers are really part of the transports functionality, so there is no reason to keep this complexity. This and the following commit will remove iwl-io.c/h: this renames the functions to have the trans prefix, and a next one will move them to iwl-trans. No functional change. Assisted-by: GitHubCopilot:claude-opus-4.8 Link: https://patch.msgid.link/20260930121740.96f5fe1d78b9.Ie580d7156b6b0175bf45e24c93dd4cce1da065ea@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/dvm/devices.c | 24 +- .../net/wireless/intel/iwlwifi/dvm/eeprom.c | 56 +-- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 12 +- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 8 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 32 +- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 6 +- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 32 +- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 50 +-- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-scd.h | 21 +- .../net/wireless/intel/iwlwifi/iwl-trans.c | 12 +- drivers/net/wireless/intel/iwlwifi/mld/fw.c | 8 +- drivers/net/wireless/intel/iwlwifi/mld/mld.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 34 +- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 +- .../net/wireless/intel/iwlwifi/mvm/utils.c | 2 +- .../intel/iwlwifi/pcie/ctxt-info-v2.c | 4 +- .../wireless/intel/iwlwifi/pcie/internal.h | 4 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 16 +- .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 58 +-- .../net/wireless/intel/iwlwifi/pcie/trans.c | 372 +++++++++--------- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 74 ++-- .../net/wireless/intel/iwlwifi/pcie/utils.c | 4 +- 26 files changed, 426 insertions(+), 425 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index b40a769f8e2d..c22f68db3e83 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -45,10 +45,10 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) static void iwl1000_nic_config(struct iwl_priv *priv) { /* Setting digital SVR for 1000 card to 1.32V */ - /* locking is acquired in iwl_set_bits_mask_prph() function */ - iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, - APMG_SVR_DIGITAL_VOLTAGE_1_32, - ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); + /* locking is acquired in iwl_trans_set_bits_mask_prph() function */ + iwl_trans_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, + APMG_SVR_DIGITAL_VOLTAGE_1_32, + ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } /** @@ -184,8 +184,8 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) /* NIC configuration for 2000 series */ static void iwl2000_nic_config(struct iwl_priv *priv) { - iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); + iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); } static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { @@ -496,16 +496,16 @@ static void iwl6000_nic_config(struct iwl_priv *priv) case IWL_DEVICE_FAMILY_6050: /* Indicate calibration version to uCode. */ if (priv->nvm_data->calib_version >= 6) - iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); + iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); break; case IWL_DEVICE_FAMILY_6150: /* Indicate calibration version to uCode. */ if (priv->nvm_data->calib_version >= 6) - iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); - iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_6050_1x2); + iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); + iwl_trans_set_bit(priv->trans, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_6050_1x2); break; default: WARN_ON(1); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c index d20691f7d82f..aa532635e414 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c @@ -672,13 +672,13 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) for (count = 0; count < IWL_EEPROM_SEM_RETRY_LIMIT; count++) { /* Request semaphore */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM); /* See if we got it */ - ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM, - IWL_EEPROM_SEM_TIMEOUT); + ret = iwl_trans_poll_bits(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM, + IWL_EEPROM_SEM_TIMEOUT); if (!ret) { IWL_DEBUG_EEPROM(trans->dev, "Acquired semaphore after %d tries.\n", @@ -692,8 +692,8 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) { - iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM); + iwl_trans_clear_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM); } static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) @@ -736,8 +736,8 @@ static void iwl_set_otp_access_absolute(struct iwl_trans *trans) { iwl_trans_read32(trans, CSR_OTP_GP_REG); - iwl_clear_bit(trans, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); + iwl_trans_clear_bit(trans, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_OTP_ACCESS_MODE); } static int iwl_nvm_is_otp(struct iwl_trans *trans) @@ -770,19 +770,19 @@ static int iwl_init_otp_access(struct iwl_trans *trans) if (ret) return ret; - iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); + iwl_trans_set_bits_prph(trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); + iwl_trans_clear_bits_prph(trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_RESET_REQ); /* * CSR auto clock gate disable bit - * this is only applicable for HW with OTP shadow RAM */ if (trans->mac_cfg->base->shadow_ram_support) - iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); + iwl_trans_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); return 0; } @@ -796,9 +796,9 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, iwl_trans_write32(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bits(trans, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); + ret = iwl_trans_poll_bits(trans, CSR_EEPROM_REG, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); if (ret) { IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); return ret; @@ -809,16 +809,16 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { /* stop in this case */ /* set the uncorrectable OTP ECC bit for acknowledgment */ - iwl_set_bit(trans, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); + iwl_trans_set_bit(trans, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); return -EINVAL; } if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { /* continue in this case */ /* set the correctable OTP ECC bit for acknowledgment */ - iwl_set_bit(trans, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); + iwl_trans_set_bit(trans, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); } *eeprom_data = cpu_to_le16(r >> 16); @@ -964,9 +964,9 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) iwl_trans_read32(trans, CSR_EEPROM_GP) & ~CSR_EEPROM_GP_IF_OWNER_MSK); - iwl_set_bit(trans, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | - CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); + iwl_trans_set_bit(trans, CSR_OTP_GP_REG, + CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | + CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); /* traversing the linked list if no shadow ram supported */ if (!trans->mac_cfg->base->shadow_ram_support) { ret = iwl_find_otp_image(trans, &validblockaddr); @@ -991,9 +991,9 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) iwl_trans_write32(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_bits(trans, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); + ret = iwl_trans_poll_bits(trans, CSR_EEPROM_REG, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); if (ret) { IWL_ERR(trans, "Time out reading EEPROM[%d]\n", addr); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 9bf16950ebf0..b3f73c773abe 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -2028,17 +2028,17 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode) } /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | - CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); + iwl_trans_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | + CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); /* W/A : NIC is stuck in a reset state after Early PCIe power off * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, - ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); + iwl_trans_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, + ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); if (priv->lib->nic_config) priv->lib->nic_config(priv); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 79ee4fb239b2..77aa7e04854f 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -485,14 +485,14 @@ static void iwlagn_rx_card_state_notif(struct iwl_priv *priv, iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(priv->trans, HBUS_TARG_MBX_C, - HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); + iwl_trans_write_direct32(priv->trans, HBUS_TARG_MBX_C, + HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); if (!(flags & RXON_CARD_DISABLED)) { iwl_trans_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(priv->trans, HBUS_TARG_MBX_C, - HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); + iwl_trans_write_direct32(priv->trans, HBUS_TARG_MBX_C, + HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } if (flags & CT_CARD_DISABLED) iwl_tt_enter_ct_kill(priv); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 3a0318070bfb..8827e4f317f1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -159,7 +159,7 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, indirect_rd_addr += le32_to_cpu(offset); dphy_addr = (offset) ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW; - dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr); + dphy_state = iwl_trans_read_umac_prph_no_grab(fwrt->trans, dphy_addr); for (i = 0; i < le32_to_cpu(size); i += 4) { if (dphy_state == HBUS_TIMEOUT || @@ -508,7 +508,7 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt, indirect_rd_wr_addr += le32_to_cpu(offset); dphy_addr = offset ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW; - dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr); + dphy_state = iwl_trans_read_umac_prph_no_grab(fwrt->trans, dphy_addr); for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) { if (dphy_state == HBUS_TIMEOUT || @@ -586,13 +586,13 @@ static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt, switch (fifo_idx) { case 0: data->size = fwrt->smem_cfg.rxfifo2_size; - data->offset = iwl_umac_prph(fwrt->trans, - RXF_DIFF_FROM_PREV); + data->offset = iwl_trans_umac_prph(fwrt->trans, + RXF_DIFF_FROM_PREV); break; case 1: data->size = fwrt->smem_cfg.rxfifo2_control_size; - data->offset = iwl_umac_prph(fwrt->trans, - RXF2C_DIFF_FROM_PREV); + data->offset = iwl_trans_umac_prph(fwrt->trans, + RXF2C_DIFF_FROM_PREV); break; } } @@ -2381,21 +2381,21 @@ static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans, struct iwl_fw_dbg_params *params) { if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) { - iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); + iwl_trans_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); return; } if (params) { - params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE); - params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL); + params->in_sample = iwl_trans_read_umac_prph(trans, DBGC_IN_SAMPLE); + params->out_ctrl = iwl_trans_read_umac_prph(trans, DBGC_OUT_CTRL); } - iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0); + iwl_trans_write_umac_prph(trans, DBGC_IN_SAMPLE, 0); /* wait for the DBGC to finish writing the internal buffer to DRAM to * avoid halting the HW while writing */ usleep_range(700, 1000); - iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0); + iwl_trans_write_umac_prph(trans, DBGC_OUT_CTRL, 0); } static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans, @@ -2405,12 +2405,12 @@ static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans, return -EIO; if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) { - iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); - iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); - iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); + iwl_trans_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); + iwl_trans_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); + iwl_trans_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); } else { - iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample); - iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); + iwl_trans_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample); + iwl_trans_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); } return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 7b9e98a21704..deb7af465746 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -309,7 +309,7 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt) return; } - error = iwl_read_umac_prph(trans, error); + error = iwl_trans_read_umac_prph(trans, error); IWL_ERR(trans, "IML/ROM dump:\n"); @@ -318,11 +318,11 @@ static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt) IWL_ERR(fwrt, "0x%08X | IML/ROM error/state\n", error); IWL_ERR(fwrt, "0x%08X | IML/ROM data1\n", - iwl_read_umac_prph(trans, data1)); + iwl_trans_read_umac_prph(trans, data1)); if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_22000) IWL_ERR(fwrt, "0x%08X | IML/ROM WFPM_AUTH_KEY_0\n", - iwl_read_umac_prph(trans, SB_MODIFY_CFG_FLAG)); + iwl_trans_read_umac_prph(trans, SB_MODIFY_CFG_FLAG)); } #define FSEQ_REG(x) { .addr = (x), .str = #x, } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 545a213df71d..6e863059ffa7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -485,8 +485,8 @@ int iwl_pnvm_load(struct iwl_trans *trans, iwl_pnvm_complete_fn, trans); /* kick the doorbell */ - iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, - UREG_DOORBELL_TO_ISR6_PNVM); + iwl_trans_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, + UREG_DOORBELL_TO_ISR6_PNVM); return iwl_wait_notification(notif_wait, &pnvm_wait, MVM_UCODE_PNVM_TIMEOUT); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index b9f7e791dd37..11f2b31f6df7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -16,7 +16,7 @@ * * Use iwl_trans_write32() and iwl_trans_read32() family to access these registers; * these provide simple PCI bus access, without waking up the MAC. - * Do not use iwl_write_direct32() family for these registers; + * Do not use iwl_trans_write_direct32() family for these registers; * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ. * The MAC (uCode processor, etc.) does not need to be powered up for accessing * the CSR registers. @@ -501,7 +501,7 @@ enum { * to indirectly access device's internal memory or registers that * may be powered-down. * - * Use iwl_write_direct32() family for writing to these registers; + * Use iwl_trans_write_direct32() family for writing to these registers; * A read operation doesn't exist, can be added if needed. * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ * to make sure the MAC (uCode processor, etc.) is powered up for accessing diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 515d6b2becc9..09965fb39fb6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -13,8 +13,8 @@ #define IWL_POLL_INTERVAL 10 /* microseconds */ -int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout) +int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout) { int t = 0; @@ -27,18 +27,18 @@ int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, return -ETIMEDOUT; } -IWL_EXPORT_SYMBOL(iwl_poll_bits_mask); +IWL_EXPORT_SYMBOL(iwl_trans_poll_bits_mask); -void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) +void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) { if (iwl_trans_grab_nic_access(trans)) { iwl_trans_write32(trans, reg, value); iwl_trans_release_nic_access(trans); } } -IWL_EXPORT_SYMBOL(iwl_write_direct32); +IWL_EXPORT_SYMBOL(iwl_trans_write_direct32); -u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) +u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs) { if (iwl_trans_grab_nic_access(trans)) { u32 val = iwl_trans_read_prph_no_grab(trans, ofs); @@ -51,9 +51,9 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) /* return as if we have a HW timeout/failure */ return 0x5a5a5a5a; } -IWL_EXPORT_SYMBOL(iwl_read_prph); +IWL_EXPORT_SYMBOL(iwl_trans_read_prph); -void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms) +void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms) { if (iwl_trans_grab_nic_access(trans)) { mdelay(delay_ms); @@ -61,9 +61,9 @@ void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_m iwl_trans_release_nic_access(trans); } } -IWL_EXPORT_SYMBOL(iwl_write_prph_delay); +IWL_EXPORT_SYMBOL(iwl_trans_write_prph_delay); -void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) +void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) { if (iwl_trans_grab_nic_access(trans)) { iwl_trans_write_prph_no_grab(trans, ofs, @@ -72,10 +72,10 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) iwl_trans_release_nic_access(trans); } } -IWL_EXPORT_SYMBOL(iwl_set_bits_prph); +IWL_EXPORT_SYMBOL(iwl_trans_set_bits_prph); -void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, - u32 bits, u32 mask) +void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, + u32 bits, u32 mask) { if (iwl_trans_grab_nic_access(trans)) { iwl_trans_write_prph_no_grab(trans, ofs, @@ -84,9 +84,9 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, iwl_trans_release_nic_access(trans); } } -IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph); +IWL_EXPORT_SYMBOL(iwl_trans_set_bits_mask_prph); -void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) +void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) { u32 val; @@ -96,4 +96,4 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) iwl_trans_release_nic_access(trans); } } -IWL_EXPORT_SYMBOL(iwl_clear_bits_prph); +IWL_EXPORT_SYMBOL(iwl_trans_clear_bits_prph); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index a26c6525ec40..5cb422a4d9de 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -8,65 +8,65 @@ #include "iwl-devtrace.h" #include "iwl-trans.h" -static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) +static inline void iwl_trans_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { iwl_trans_set_bits_mask(trans, reg, mask, mask); } -static inline void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) +static inline void iwl_trans_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) { iwl_trans_set_bits_mask(trans, reg, mask, 0); } -int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout); -static inline int iwl_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits, - int timeout) +int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout); +static inline int iwl_trans_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits, + int timeout) { - return iwl_poll_bits_mask(trans, addr, bits, bits, timeout); + return iwl_trans_poll_bits_mask(trans, addr, bits, bits, timeout); } -void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); +void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); -u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); -void iwl_write_prph_delay(struct iwl_trans *trans, u32 ofs, - u32 val, u32 delay_ms); -static inline void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) +u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs); +void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, + u32 val, u32 delay_ms); +static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) { - iwl_write_prph_delay(trans, ofs, val, 0); + iwl_trans_write_prph_delay(trans, ofs, val, 0); } -void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); -void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, - u32 bits, u32 mask); -void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); +void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); +void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, + u32 bits, u32 mask); +void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); /* * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from * device family AX200. So peripheries used in families above and below AX200 - * should go through iwl_..._umac_..._prph. + * should go through iwl_trans_..._umac_..._prph. */ -static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs) +static inline u32 iwl_trans_umac_prph(struct iwl_trans *trans, u32 ofs) { return ofs + trans->mac_cfg->umac_prph_offset; } -static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) +static inline u32 iwl_trans_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) { return iwl_trans_read_prph_no_grab(trans, ofs + trans->mac_cfg->umac_prph_offset); } -static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) +static inline u32 iwl_trans_read_umac_prph(struct iwl_trans *trans, u32 ofs) { - return iwl_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset); + return iwl_trans_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset); } -static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs, - u32 val) +static inline void iwl_trans_write_umac_prph(struct iwl_trans *trans, u32 ofs, + u32 val) { - iwl_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val); + iwl_trans_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val); } #endif diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 9e02a498b5f9..9a8355514c4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1410,7 +1410,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans, if (!trans->csme_own) IWL_INFO(trans, "base HW address: %pM, OTP minor version: 0x%x\n", - data->hw_addr, iwl_read_prph(trans, REG_OTP_MINOR)); + data->hw_addr, iwl_trans_read_prph(trans, REG_OTP_MINOR)); return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-scd.h b/drivers/net/wireless/intel/iwlwifi/iwl-scd.h index 1eaff898ca3c..22a7da73a918 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-scd.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-scd.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2014 Intel Mobile Communications GmbH + * Copyright (C) 2026 Intel Corporation */ #ifndef __iwl_scd_h__ #define __iwl_scd_h__ @@ -13,40 +14,40 @@ static inline void iwl_scd_txq_set_chain(struct iwl_trans *trans, u16 txq_id) { - iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); + iwl_trans_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); } static inline void iwl_scd_txq_enable_agg(struct iwl_trans *trans, u16 txq_id) { - iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); + iwl_trans_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); } static inline void iwl_scd_txq_disable_agg(struct iwl_trans *trans, u16 txq_id) { - iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); + iwl_trans_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); } static inline void iwl_scd_disable_agg(struct iwl_trans *trans) { - iwl_set_bits_prph(trans, SCD_AGGR_SEL, 0); + iwl_trans_set_bits_prph(trans, SCD_AGGR_SEL, 0); } static inline void iwl_scd_activate_fifos(struct iwl_trans *trans) { - iwl_write_prph(trans, SCD_TXFACT, IWL_MASK(0, 7)); + iwl_trans_write_prph(trans, SCD_TXFACT, IWL_MASK(0, 7)); } static inline void iwl_scd_deactivate_fifos(struct iwl_trans *trans) { - iwl_write_prph(trans, SCD_TXFACT, 0); + iwl_trans_write_prph(trans, SCD_TXFACT, 0); } static inline void iwl_scd_enable_set_active(struct iwl_trans *trans, u32 value) { - iwl_write_prph(trans, SCD_EN_CTRL, value); + iwl_trans_write_prph(trans, SCD_EN_CTRL, value); } static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl) @@ -76,9 +77,9 @@ static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl) static inline void iwl_scd_txq_set_inactive(struct iwl_trans *trans, u16 txq_id) { - iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), - (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); + iwl_trans_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), + (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } #endif diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 123eca3f5d0a..59b4e180825f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -453,14 +453,14 @@ void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) void iwl_trans_force_nmi(struct iwl_trans *trans) { if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000) - iwl_write_prph_delay(trans, DEVICE_SET_NMI_REG, - DEVICE_SET_NMI_VAL_DRV, 1); + iwl_trans_write_prph_delay(trans, DEVICE_SET_NMI_REG, + DEVICE_SET_NMI_VAL_DRV, 1); else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, - UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER); + iwl_trans_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, + UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER); else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_BZ) - iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, - UREG_DOORBELL_TO_ISR6_NMI_BIT); + iwl_trans_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, + UREG_DOORBELL_TO_ISR6_NMI_BIT); else iwl_trans_write32(trans, CSR_DOORBELL_VECTOR, UREG_DOORBELL_TO_ISR6_NMI_BIT); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/fw.c b/drivers/net/wireless/intel/iwlwifi/mld/fw.c index 7891afd556a8..3b9f412cdff2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/fw.c @@ -207,11 +207,11 @@ static void iwl_mld_print_alive_notif_timeout(struct iwl_mld *mld) IWL_ERR(mld, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", - iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), - iwl_read_umac_prph(trans, - UMAG_SB_CPU_2_STATUS)); + iwl_trans_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), + iwl_trans_read_umac_prph(trans, + UMAG_SB_CPU_2_STATUS)); #define IWL_FW_PRINT_REG_INFO(reg_name) \ - IWL_ERR(mld, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name)) + IWL_ERR(mld, #reg_name ": 0x%x\n", iwl_trans_read_umac_prph(trans, reg_name)) IWL_FW_PRINT_REG_INFO(WFPM_LMAC1_PD_NOTIFICATION); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 95d6f36b9fd9..71832d92024d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -37,7 +37,7 @@ static const struct iwl_op_mode_ops iwl_mld_ops; int iwl_mld_get_systime(struct iwl_mld *mld, u32 *gp2) { - *gp2 = iwl_read_prph(mld->trans, + *gp2 = iwl_trans_read_prph(mld->trans, mld->trans->mac_cfg->base->gp2_reg_addr); if (*gp2 == 0x5a5a5a5a) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 06502f57e823..48f8bab4dc85 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1548,7 +1548,7 @@ iwl_dbgfs_prph_reg_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", mvm->dbgfs_prph_reg_addr, - iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); + iwl_trans_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -1569,7 +1569,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf, if (args != 2) return -EINVAL; - iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); + iwl_trans_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); out: return count; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index c3402f5e47a0..9b4637a3d1ef 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -263,7 +263,7 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait, static void iwl_mvm_print_pd_notification(struct iwl_mvm *mvm) { #define IWL_FW_PRINT_REG_INFO(reg_name) \ - IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_read_umac_prph(trans, reg_name)) + IWL_ERR(mvm, #reg_name ": 0x%x\n", iwl_trans_read_umac_prph(trans, reg_name)) struct iwl_trans *trans = mvm->trans; enum iwl_device_family device_family = trans->mac_cfg->device_family; @@ -332,13 +332,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, IWL_DEVICE_FAMILY_AX210) { /* print these registers regardless of alive fail/success */ IWL_INFO(mvm, "WFPM_UMAC_PD_NOTIFICATION: 0x%x\n", - iwl_read_umac_prph(mvm->trans, WFPM_ARC1_PD_NOTIFICATION)); + iwl_trans_read_umac_prph(mvm->trans, WFPM_ARC1_PD_NOTIFICATION)); IWL_INFO(mvm, "WFPM_LMAC2_PD_NOTIFICATION: 0x%x\n", - iwl_read_umac_prph(mvm->trans, WFPM_LMAC2_PD_NOTIFICATION)); + iwl_trans_read_umac_prph(mvm->trans, WFPM_LMAC2_PD_NOTIFICATION)); IWL_INFO(mvm, "WFPM_AUTH_KEY_0: 0x%x\n", - iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG)); + iwl_trans_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG)); IWL_INFO(mvm, "CNVI_SCU_SEQ_DATA_DW9: 0x%x\n", - iwl_read_prph(mvm->trans, CNVI_SCU_SEQ_DATA_DW9)); + iwl_trans_read_prph(mvm->trans, CNVI_SCU_SEQ_DATA_DW9)); } if (ret) { @@ -349,15 +349,15 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, IWL_DEVICE_FAMILY_22000) { IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", - iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), - iwl_read_umac_prph(trans, - UMAG_SB_CPU_2_STATUS)); + iwl_trans_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), + iwl_trans_read_umac_prph(trans, + UMAG_SB_CPU_2_STATUS)); } else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000) { IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", - iwl_read_prph(trans, SB_CPU_1_STATUS), - iwl_read_prph(trans, SB_CPU_2_STATUS)); + iwl_trans_read_prph(trans, SB_CPU_1_STATUS), + iwl_trans_read_prph(trans, SB_CPU_2_STATUS)); } iwl_mvm_print_pd_notification(mvm); @@ -374,15 +374,15 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, } else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000) { IWL_ERR(mvm, "UMAC PC: 0x%x\n", - iwl_read_umac_prph(trans, - UREG_UMAC_CURRENT_PC)); + iwl_trans_read_umac_prph(trans, + UREG_UMAC_CURRENT_PC)); IWL_ERR(mvm, "LMAC PC: 0x%x\n", - iwl_read_umac_prph(trans, - UREG_LMAC1_CURRENT_PC)); + iwl_trans_read_umac_prph(trans, + UREG_LMAC1_CURRENT_PC)); if (iwl_mvm_is_cdb_supported(mvm)) IWL_ERR(mvm, "LMAC2 PC: 0x%x\n", - iwl_read_umac_prph(trans, - UREG_LMAC2_CURRENT_PC)); + iwl_trans_read_umac_prph(trans, + UREG_LMAC2_CURRENT_PC)); } if (ret == -ETIMEDOUT && !mvm->fw_product_reset) @@ -616,7 +616,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm) mvm->rfkill_safe_init_done = false; if (mvm->trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) { - sb_cfg = iwl_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG); + sb_cfg = iwl_trans_read_umac_prph(mvm->trans, SB_MODIFY_CFG_FLAG); /* if needed, we'll reset this on our way out later */ mvm->fw_product_reset = sb_cfg == SB_CFG_RESIDES_IN_ROM; if (mvm->fw_product_reset && iwl_mei_pldr_req()) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 93d5cab87f64..653c620361d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -138,9 +138,9 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) * to lose ownership and not being able to obtain it back. */ if (!mvm->trans->mac_cfg->base->apmg_not_supported) - iwl_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, - ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); + iwl_trans_set_bits_mask_prph(mvm->trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, + ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); } static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 2fd4a9961145..cd0d89feecea 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1159,7 +1159,7 @@ u32 iwl_mvm_get_systime(struct iwl_mvm *mvm) mvm->trans->mac_cfg->base->gp2_reg_addr) reg_addr = mvm->trans->mac_cfg->base->gp2_reg_addr; - return iwl_read_prph(mvm->trans, reg_addr); + return iwl_trans_read_prph(mvm->trans, reg_addr); } void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, int clock_type, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c index 917010a7d8ef..0009a05511af 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-v2.c @@ -319,8 +319,8 @@ void iwl_pcie_ctxt_info_v2_kick(struct iwl_trans *trans) iwl_pcie_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr); iwl_trans_pcie_write32(trans, CSR_IML_SIZE_ADDR, trans_pcie->iml_len); - iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, - CSR_AUTO_FUNC_BOOT_ENA); + iwl_trans_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, + CSR_AUTO_FUNC_BOOT_ENA); } void iwl_pcie_ctxt_info_v2_free(struct iwl_trans *trans, bool alive) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 96821850298f..d74742df2fe5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1103,8 +1103,8 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) * when we power down the device we need set the bit to allow it * to wake up the PCI-E bus for RF-kill interrupts. */ - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_RFKILL_WAKE_L1A_EN); } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index cf6beba6041f..e3fe5a912a8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -147,15 +147,15 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) { if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { /* TODO: remove this once fw does it */ - iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_AX210, 0); + iwl_trans_write_umac_prph(trans, RFH_RXF_DMA_CFG_AX210, 0); return iwl_pcie_poll_umac_prph_bit(trans, RFH_GEN_STATUS_AX210, RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); } else if (trans->mac_cfg->mq_rx_supported) { - iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); + iwl_trans_write_prph(trans, RFH_RXF_DMA_CFG, 0); return iwl_pcie_poll_prph_bit(trans, RFH_GEN_STATUS, RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); } else { - iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_trans_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); return iwl_pcie_poll_direct_bit(trans, FH_MEM_RSSR_RX_STATUS_REG, FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); @@ -184,8 +184,8 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n", reg); - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); rxq->need_update = true; return; } @@ -895,7 +895,7 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) /* W/A for interrupt coalescing bug in 7260 and 3160 */ if (trans->cfg->host_interrupt_operation_mode) - iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); + iwl_trans_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) @@ -1692,9 +1692,9 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) /* W/A for WiFi/WiMAX coex and WiMAX own the RF */ if (trans->cfg->internal_wimax_coex && !trans->mac_cfg->base->apmg_not_supported && - (!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) & + (!(iwl_trans_read_prph(trans, APMG_CLK_CTRL_REG) & APMS_CLK_VAL_MRB_FUNC_MODE) || - (iwl_read_prph(trans, APMG_PS_CTRL_REG) & + (iwl_trans_read_prph(trans, APMG_PS_CTRL_REG) & APMG_PS_CTRL_VAL_RESET_REQ))) { clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); iwl_op_mode_wimax_active(trans->op_mode); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 91d0b935fca6..dce6043fe962 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -32,18 +32,18 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) * Disable L0s without affecting L1; * don't wait for ICH L0s (ICH bug W/A) */ - iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + iwl_trans_set_bit(trans, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + iwl_trans_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_HAP_WAKE); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_HAP_WAKE); iwl_pcie_apm_config(trans); @@ -65,14 +65,14 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave) iwl_pcie_gen2_apm_init(trans); /* inform ME that we are leaving */ - iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_WAKE_ME | - CSR_HW_IF_CONFIG_REG_WAKE_ME_PCIE_OWNER_EN); + iwl_trans_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_WAKE_ME | + CSR_HW_IF_CONFIG_REG_WAKE_ME_PCIE_OWNER_EN); mdelay(1); - iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); + iwl_trans_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); mdelay(5); } @@ -88,11 +88,11 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave) * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_INIT); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_INIT); else - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } static void @@ -105,11 +105,11 @@ _iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans, trans_pcie->fw_reset_state = FW_RESET_REQUESTED; if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, - UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE); + iwl_trans_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, + UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE); else if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) - iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, - UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE); + iwl_trans_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, + UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE); else iwl_trans_pcie_write32(trans, CSR_DOORBELL_VECTOR, UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE); @@ -281,7 +281,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) return -ENOMEM; /* enable shadow regs in HW */ - iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); + iwl_trans_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n"); return 0; @@ -342,7 +342,7 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans) case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR): case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR1): case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HRCDB): - version = iwl_read_prph(trans, CNVI_MBOX_C); + version = iwl_trans_read_prph(trans, CNVI_MBOX_C); switch (version) { case 0x20000: pos += scnprintf(buf + pos, buflen - pos, " B3"); @@ -410,7 +410,7 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans) step_reg = trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_SC ? CNVI_PMU_STEP_FLOW_SC : CNVI_PMU_STEP_FLOW_BZ; - trans->step_urm = !!(iwl_read_prph(trans, step_reg) & + trans->step_urm = !!(iwl_trans_read_prph(trans, step_reg) & CNVI_PMU_STEP_FLOW_FORCE_URM); } @@ -440,8 +440,8 @@ static bool iwl_pcie_set_ltr(struct iwl_trans *trans) if (trans->mac_cfg->integrated && trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000) { - iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); - iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val); + iwl_trans_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); + iwl_trans_write_prph(trans, HPM_UMAC_LTR, ltr_val); return true; } @@ -593,12 +593,12 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, IWL_DEBUG_POWER(trans, "function scratch register value is 0x%08x\n", iwl_trans_pcie_read32(trans, CSR_FUNC_SCRATCH)); iwl_trans_pcie_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE); - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_ROM_START); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_ROM_START); } else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { - iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); + iwl_trans_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); } else { - iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); + iwl_trans_write_prph(trans, UREG_CPU_INIT_RUN, 1); } if (keep_ram_busy) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index ce7d01a36688..8da0cc603070 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -79,12 +79,12 @@ int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership) { /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_SW_RESET); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_SW_RESET); usleep_range(10000, 20000); } else { - iwl_set_bit(trans, CSR_RESET, - CSR_RESET_REG_FLAG_SW_RESET); + iwl_trans_set_bit(trans, CSR_RESET, + CSR_RESET_REG_FLAG_SW_RESET); usleep_range(5000, 6000); } @@ -188,13 +188,13 @@ static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux) return; if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold)) - iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); + iwl_trans_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VAUX, + ~APMG_PS_CTRL_MSK_PWR_SRC); else - iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); + iwl_trans_set_bits_mask_prph(trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); } /* PCI registers */ @@ -211,7 +211,7 @@ void iwl_pcie_apm_config(struct iwl_trans *trans) * and in newer hardware they are not officially supported at * all, so we must always set the L0S_DISABLED bit. */ - iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_DISABLED); + iwl_trans_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_DISABLED); pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); trans_pcie->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); @@ -241,31 +241,31 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) /* Disable L0S exit timer (platform NMI Work/Around) */ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000) - iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); + iwl_trans_set_bit(trans, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); /* * Disable L0s without affecting L1; * don't wait for ICH L0s (ICH bug W/A) */ - iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + iwl_trans_set_bit(trans, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + iwl_trans_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); /* * Enable HAP INTA (interrupt from management bus) to * wake device's PCI Express link L1a -> L0s */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_HAP_WAKE); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_HAP_WAKE); iwl_pcie_apm_config(trans); /* Configure analog phase-lock-loop before activating to D0A */ if (trans->mac_cfg->base->pll_cfg) - iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); + iwl_trans_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); ret = iwl_trans_activate_nic(trans); if (ret) @@ -286,11 +286,11 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) * just to discard the value. But that's the way the hardware * seems to like it. */ - iwl_read_prph(trans, OSC_CLK); - iwl_read_prph(trans, OSC_CLK); - iwl_set_bits_prph(trans, OSC_CLK, OSC_CLK_FORCE_CONTROL); - iwl_read_prph(trans, OSC_CLK); - iwl_read_prph(trans, OSC_CLK); + iwl_trans_read_prph(trans, OSC_CLK); + iwl_trans_read_prph(trans, OSC_CLK); + iwl_trans_set_bits_prph(trans, OSC_CLK, OSC_CLK_FORCE_CONTROL); + iwl_trans_read_prph(trans, OSC_CLK); + iwl_trans_read_prph(trans, OSC_CLK); } /* @@ -301,17 +301,17 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) * bits already set by default in "CLK_CTRL_REG" after reset. */ if (!trans->mac_cfg->base->apmg_not_supported) { - iwl_write_prph(trans, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT); + iwl_trans_write_prph(trans, APMG_CLK_EN_REG, + APMG_CLK_VAL_DMA_CLK_RQT); udelay(20); /* Disable L1-Active */ - iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + iwl_trans_set_bits_prph(trans, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); /* Clear the interrupt in APMG if the NIC is in RFKILL */ - iwl_write_prph(trans, APMG_RTC_INT_STT_REG, - APMG_RTC_INT_STT_RFKILL); + iwl_trans_write_prph(trans, APMG_RTC_INT_STT_REG, + APMG_RTC_INT_STT_RFKILL); } set_bit(STATUS_DEVICE_ENABLED, &trans->status); @@ -353,8 +353,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) * Clear "disable persistence" to avoid LP XTAL resetting when * SHRD_HW_RST is applied in S3. */ - iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_PERSIST_DIS); + iwl_trans_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_PERSIST_DIS); /* * Force APMG XTAL to be active to prevent its disabling by HW @@ -386,14 +386,14 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) * Enable persistence mode to avoid LP XTAL resetting when * SHRD_HW_RST is applied in S3. */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PERSISTENCE); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PERSISTENCE); /* * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* Activates XTAL resources monitor */ iwl_pcie_set_bit(trans, CSR_MONITOR_CFG_REG, @@ -417,18 +417,18 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) /* stop device's busmaster DMA activity */ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ); - ret = iwl_poll_bits(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, - 100); + ret = iwl_trans_poll_bits(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, + 100); usleep_range(10000, 20000); } else { - iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_trans_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - ret = iwl_poll_bits(trans, CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); + ret = iwl_trans_poll_bits(trans, CSR_RESET, + CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); } if (ret) @@ -447,18 +447,18 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave) /* inform ME that we are leaving */ if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_7000) - iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_WAKE_ME); + iwl_trans_set_bits_prph(trans, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_WAKE_ME); else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000) { - iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_WAKE_ME | - CSR_HW_IF_CONFIG_REG_WAKE_ME_PCIE_OWNER_EN); + iwl_trans_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_WAKE_ME | + CSR_HW_IF_CONFIG_REG_WAKE_ME_PCIE_OWNER_EN); mdelay(1); - iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); + iwl_trans_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); } mdelay(5); } @@ -479,7 +479,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } static int iwl_pcie_nic_init(struct iwl_trans *trans) @@ -512,7 +512,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans) if (trans->mac_cfg->base->shadow_reg_enable) { /* enable shadow regs in HW */ - iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); + iwl_trans_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF); IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n"); } @@ -525,16 +525,16 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans) { int ret; - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PCI_OWN_SET); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PCI_OWN_SET); /* See if we got it */ - ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PCI_OWN_SET, - HW_READY_TIMEOUT); + ret = iwl_trans_poll_bits(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PCI_OWN_SET, + HW_READY_TIMEOUT); if (!ret) - iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE); + iwl_trans_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE); IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret ? " not" : ""); return ret; @@ -555,16 +555,16 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) return 0; } - iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); + iwl_trans_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); usleep_range(1000, 2000); for (iter = 0; iter < 10; iter++) { int t = 0; /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_WAKE_ME); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_WAKE_ME); do { ret = iwl_pcie_set_hw_ready(trans); @@ -688,16 +688,16 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, extended_addr = true; if (extended_addr) - iwl_set_bits_prph(trans, LMPM_CHICK, - LMPM_CHICK_EXTENDED_ADDR_SPACE); + iwl_trans_set_bits_prph(trans, LMPM_CHICK, + LMPM_CHICK_EXTENDED_ADDR_SPACE); memcpy(v_addr, (const u8 *)section->data + offset, copy_size); ret = iwl_pcie_load_firmware_chunk(trans, dst_addr, p_addr, copy_size); if (extended_addr) - iwl_clear_bits_prph(trans, LMPM_CHICK, - LMPM_CHICK_EXTENDED_ADDR_SPACE); + iwl_trans_clear_bits_prph(trans, LMPM_CHICK, + LMPM_CHICK_EXTENDED_ADDR_SPACE); if (ret) { IWL_ERR(trans, @@ -753,7 +753,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans, /* Notify ucode of loaded section number and status */ val = iwl_pcie_read_direct32(trans, FH_UCODE_LOAD_STATUS); val = val | (sec_num << shift_param); - iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, val); + iwl_trans_write_direct32(trans, FH_UCODE_LOAD_STATUS, val); sec_num = (sec_num << 1) | 0x1; } @@ -764,18 +764,18 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans, if (trans->mac_cfg->gen2) { if (cpu == 1) - iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS, - 0xFFFF); + iwl_trans_write_prph(trans, UREG_UCODE_LOAD_STATUS, + 0xFFFF); else - iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS, - 0xFFFFFFFF); + iwl_trans_write_prph(trans, UREG_UCODE_LOAD_STATUS, + 0xFFFFFFFF); } else { if (cpu == 1) - iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, - 0xFFFF); + iwl_trans_write_direct32(trans, FH_UCODE_LOAD_STATUS, + 0xFFFF); else - iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, - 0xFFFFFFFF); + iwl_trans_write_direct32(trans, FH_UCODE_LOAD_STATUS, + 0xFFFFFFFF); } return 0; @@ -836,8 +836,8 @@ static void iwl_pcie_apply_destination_ini(struct iwl_trans *trans) IWL_FW_INI_LOCATION_SRAM_PATH) { IWL_DEBUG_FW(trans, "WRT: Applying SMEM buffer destination\n"); /* set sram monitor by enabling bit 7 */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM); return; } @@ -852,11 +852,11 @@ static void iwl_pcie_apply_destination_ini(struct iwl_trans *trans) IWL_DEBUG_FW(trans, "WRT: Applying DRAM destination (alloc_id=%u)\n", alloc_id); - iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, - frag->physical >> MON_BUFF_SHIFT_VER2); - iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2, - (frag->physical + frag->size - 256) >> - MON_BUFF_SHIFT_VER2); + iwl_trans_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, + frag->physical >> MON_BUFF_SHIFT_VER2); + iwl_trans_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2, + (frag->physical + frag->size - 256) >> + MON_BUFF_SHIFT_VER2); } void iwl_pcie_apply_destination(struct iwl_trans *trans) @@ -887,22 +887,22 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) iwl_trans_pcie_write32(trans, addr, val); break; case CSR_SETBIT: - iwl_set_bit(trans, addr, BIT(val)); + iwl_trans_set_bit(trans, addr, BIT(val)); break; case CSR_CLEARBIT: - iwl_clear_bit(trans, addr, BIT(val)); + iwl_trans_clear_bit(trans, addr, BIT(val)); break; case PRPH_ASSIGN: - iwl_write_prph(trans, addr, val); + iwl_trans_write_prph(trans, addr, val); break; case PRPH_SETBIT: - iwl_set_bits_prph(trans, addr, BIT(val)); + iwl_trans_set_bits_prph(trans, addr, BIT(val)); break; case PRPH_CLEARBIT: - iwl_clear_bits_prph(trans, addr, BIT(val)); + iwl_trans_clear_bits_prph(trans, addr, BIT(val)); break; case PRPH_BLOCKBIT: - if (iwl_read_prph(trans, addr) & BIT(val)) { + if (iwl_trans_read_prph(trans, addr) & BIT(val)) { IWL_ERR(trans, "BIT(%u) in address 0x%x is 1, stopping FW configuration\n", val, addr); @@ -918,16 +918,16 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) monitor: if (dest->monitor_mode == EXTERNAL_MODE && fw_mon->size) { - iwl_write_prph(trans, le32_to_cpu(dest->base_reg), - fw_mon->physical >> dest->base_shift); + iwl_trans_write_prph(trans, le32_to_cpu(dest->base_reg), + fw_mon->physical >> dest->base_shift); if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_8000) - iwl_write_prph(trans, le32_to_cpu(dest->end_reg), - (fw_mon->physical + fw_mon->size - - 256) >> dest->end_shift); + iwl_trans_write_prph(trans, le32_to_cpu(dest->end_reg), + (fw_mon->physical + fw_mon->size - + 256) >> dest->end_shift); else - iwl_write_prph(trans, le32_to_cpu(dest->end_reg), - (fw_mon->physical + fw_mon->size) >> - dest->end_shift); + iwl_trans_write_prph(trans, le32_to_cpu(dest->end_reg), + (fw_mon->physical + fw_mon->size) >> + dest->end_shift); } } @@ -947,9 +947,9 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, if (image->is_dual_cpus) { /* set CPU2 header address */ - iwl_write_prph(trans, - LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR, - LMPM_SECURE_CPU2_HDR_MEM_SPACE); + iwl_trans_write_prph(trans, + LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR, + LMPM_SECURE_CPU2_HDR_MEM_SPACE); /* load to FW the binary sections of CPU2 */ ret = iwl_pcie_load_cpu_sections(trans, image, 2, @@ -982,18 +982,18 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans, iwl_pcie_apply_destination(trans); IWL_DEBUG_POWER(trans, "Original WFPM value = 0x%08X\n", - iwl_read_prph(trans, WFPM_GP2)); + iwl_trans_read_prph(trans, WFPM_GP2)); /* * Set default value. On resume reading the values that were * zeored can provide debug data on the resume flow. * This is for debugging only and has no functional impact. */ - iwl_write_prph(trans, WFPM_GP2, 0x01010101); + iwl_trans_write_prph(trans, WFPM_GP2, 0x01010101); /* configure the ucode to be ready to get the secured image */ /* release CPU reset */ - iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT); + iwl_trans_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT); /* load to FW the binary Secured sections of CPU1 */ ret = iwl_pcie_load_cpu_sections_8000(trans, image, 1, @@ -1080,8 +1080,8 @@ static void iwl_pcie_map_list(struct iwl_trans *trans, for (i = 0; i < arr_size; i++) { iwl_trans_pcie_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); - iwl_clear_bit(trans, causes[i].mask_reg, - BIT(causes[i].bit)); + iwl_trans_clear_bit(trans, causes[i].mask_reg, + BIT(causes[i].bit)); } } @@ -1141,8 +1141,8 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) if (!trans_pcie->msix_enabled) { if (trans->mac_cfg->mq_rx_supported && test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - iwl_write_umac_prph(trans, UREG_CHICK, - UREG_CHICK_MSI_ENABLE); + iwl_trans_write_umac_prph(trans, UREG_CHICK, + UREG_CHICK_MSI_ENABLE); return; } /* @@ -1151,7 +1151,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) * prph. */ if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - iwl_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); + iwl_trans_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); /* * Each cause from the causes list above and the RX causes is @@ -1215,19 +1215,19 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool from_irq) /* Power-down device's busmaster DMA clocks */ if (!trans->mac_cfg->base->apmg_not_supported) { - iwl_write_prph(trans, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); + iwl_trans_write_prph(trans, APMG_CLK_DIS_REG, + APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); } } /* Make sure (redundant) we've released our request to stay awake */ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); else - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ iwl_pcie_apm_stop(trans, false); @@ -1444,15 +1444,15 @@ static void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans, iwl_pcie_synchronize_irqs(trans); if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_INIT); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_INIT); } else { - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } if (reset) { @@ -1478,9 +1478,9 @@ static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend) trans_pcie->sx_state = IWL_SX_WAITING; if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) - iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, - suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND : - UREG_DOORBELL_TO_ISR6_RESUME); + iwl_trans_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, + suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND : + UREG_DOORBELL_TO_ISR6_RESUME); else iwl_trans_pcie_write32(trans, CSR_IPC_SLEEP_CONTROL, suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND : @@ -1515,8 +1515,8 @@ int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset) if (!reset) /* Enable persistence mode to avoid reset */ - iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PERSISTENCE); + iwl_trans_set_bit(trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_PERSISTENCE); ret = iwl_pcie_d3_handshake(trans, true); if (ret) @@ -1535,11 +1535,11 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, int ret; if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ); else - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); ret = iwl_trans_activate_nic(trans); if (ret) { @@ -1563,8 +1563,8 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, iwl_pcie_set_pwr(trans, false); if (!reset) { - iwl_clear_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_clear_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } else { iwl_trans_pcie_tx_reset(trans); @@ -1577,7 +1577,7 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, } IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n", - iwl_read_umac_prph(trans, WFPM_GP2)); + iwl_trans_read_umac_prph(trans, WFPM_GP2)); val = iwl_trans_pcie_read32(trans, CSR_RESET); if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { @@ -1745,9 +1745,9 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans) return 0; } - hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG); + hpm = iwl_trans_read_umac_prph_no_grab(trans, HPM_DEBUG); if (!iwl_trans_is_hw_error_value(hpm) && (hpm & PERSISTENCE_BIT)) { - u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot); + u32 wprot_val = iwl_trans_read_umac_prph_no_grab(trans, wprot); if (wprot_val & PREG_WFPM_ACCESS) { IWL_ERR(trans, @@ -1769,15 +1769,15 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans) if (ret < 0) return ret; - iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG, - HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); + iwl_trans_set_bits_prph(trans, HPM_HIPM_GEN_CFG, + HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); udelay(20); - iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG, - HPM_HIPM_GEN_CFG_CR_PG_EN | - HPM_HIPM_GEN_CFG_CR_SLP_EN); + iwl_trans_set_bits_prph(trans, HPM_HIPM_GEN_CFG, + HPM_HIPM_GEN_CFG_CR_PG_EN | + HPM_HIPM_GEN_CFG_CR_SLP_EN); udelay(20); - iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG, - HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); + iwl_trans_clear_bits_prph(trans, HPM_HIPM_GEN_CFG, + HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); return iwl_trans_pcie_sw_reset(trans, true); } @@ -2383,7 +2383,7 @@ bool _iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) * 5000 series and later (including 1000 series) have non-volatile SRAM, * and do not save/restore SRAM when power cycling. */ - ret = iwl_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000); + ret = iwl_trans_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000); if (unlikely(ret)) { u32 cntrl = iwl_trans_pcie_read32(trans, CSR_GP_CNTRL); @@ -3237,8 +3237,8 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans, i += sizeof(u32)) *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); else - for (i = iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2); - i < iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2); + for (i = iwl_trans_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2); + i < iwl_trans_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2); i += sizeof(u32)) *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans, i)); @@ -3264,8 +3264,8 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans, iwl_pcie_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); for (i = 0; i < buf_size_in_dwords; i++) - buffer[i] = iwl_read_umac_prph_no_grab(trans, - MON_DMARB_RD_DATA_ADDR); + buffer[i] = iwl_trans_read_umac_prph_no_grab(trans, + MON_DMARB_RD_DATA_ADDR); iwl_pcie_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); iwl_trans_release_nic_access(trans); @@ -3294,14 +3294,14 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, wrap_cnt = MON_BUFF_CYCLE_CNT; } - write_ptr_val = iwl_read_prph(trans, write_ptr); + write_ptr_val = iwl_trans_read_prph(trans, write_ptr); fw_mon_data->fw_mon_cycle_cnt = - cpu_to_le32(iwl_read_prph(trans, wrap_cnt)); + cpu_to_le32(iwl_trans_read_prph(trans, wrap_cnt)); fw_mon_data->fw_mon_base_ptr = - cpu_to_le32(iwl_read_prph(trans, base)); + cpu_to_le32(iwl_trans_read_prph(trans, base)); if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { fw_mon_data->fw_mon_base_high_ptr = - cpu_to_le32(iwl_read_prph(trans, base_high)); + cpu_to_le32(iwl_trans_read_prph(trans, base_high)); write_ptr_val &= DBGC_CUR_DBGBUF_STATUS_OFFSET_MSK; /* convert wrtPtr to DWs, to align with all HWs */ write_ptr_val >>= 2; @@ -3339,13 +3339,13 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans, * shifting */ if (trans->dbg.dest_tlv->version) { - base = (iwl_read_prph(trans, base) & + base = (iwl_trans_read_prph(trans, base) & IWL_LDBG_M2S_BUF_BA_MSK) << trans->dbg.dest_tlv->base_shift; base *= IWL_M2S_UNIT_SIZE; base += trans->mac_cfg->base->smem_offset; } else { - base = iwl_read_prph(trans, base) << + base = iwl_trans_read_prph(trans, base) << trans->dbg.dest_tlv->base_shift; } @@ -3380,7 +3380,7 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len) if (trans->dbg.dest_tlv->version == 1) { cfg_reg = le32_to_cpu(trans->dbg.dest_tlv->base_reg); - cfg_reg = iwl_read_prph(trans, cfg_reg); + cfg_reg = iwl_trans_read_prph(trans, cfg_reg); base = (cfg_reg & IWL_LDBG_M2S_BUF_BA_MSK) << trans->dbg.dest_tlv->base_shift; base *= IWL_M2S_UNIT_SIZE; @@ -3394,9 +3394,9 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len) base = le32_to_cpu(trans->dbg.dest_tlv->base_reg); end = le32_to_cpu(trans->dbg.dest_tlv->end_reg); - base = iwl_read_prph(trans, base) << + base = iwl_trans_read_prph(trans, base) << trans->dbg.dest_tlv->base_shift; - end = iwl_read_prph(trans, end) << + end = iwl_trans_read_prph(trans, end) << trans->dbg.dest_tlv->end_shift; /* Make "end" point to the actual end */ @@ -3454,8 +3454,8 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask, if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { if (trans->mac_cfg->gen2) len += sizeof(*data) + - (iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) - - iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2)); + (iwl_trans_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) - + iwl_trans_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2)); else len += sizeof(*data) + (FH_MEM_UPPER_BOUND - @@ -3860,19 +3860,19 @@ iwl_trans_pcie_alloc(struct pci_dev *pdev, void iwl_trans_pcie_copy_imr_fh(struct iwl_trans *trans, u32 dst_addr, u64 src_addr, u32 byte_cnt) { - iwl_write_prph(trans, IMR_UREG_CHICK, - iwl_read_prph(trans, IMR_UREG_CHICK) | - IMR_UREG_CHICK_HALT_UMAC_PERMANENTLY_MSK); - iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_SRAM_ADDR, dst_addr); - iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_DRAM_ADDR_LSB, - (u32)(src_addr & 0xFFFFFFFF)); - iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_DRAM_ADDR_MSB, - iwl_get_dma_hi_addr(src_addr)); - iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_BC, byte_cnt); - iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_CTRL, - IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_IRQ_TARGET_POS | - IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_DMA_EN_POS | - IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_RS_MSK); + iwl_trans_write_prph(trans, IMR_UREG_CHICK, + iwl_trans_read_prph(trans, IMR_UREG_CHICK) | + IMR_UREG_CHICK_HALT_UMAC_PERMANENTLY_MSK); + iwl_trans_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_SRAM_ADDR, dst_addr); + iwl_trans_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_DRAM_ADDR_LSB, + (u32)(src_addr & 0xFFFFFFFF)); + iwl_trans_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_DRAM_ADDR_MSB, + iwl_get_dma_hi_addr(src_addr)); + iwl_trans_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_BC, byte_cnt); + iwl_trans_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_CTRL, + IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_IRQ_TARGET_POS | + IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_DMA_EN_POS | + IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_RS_MSK); } int iwl_trans_pcie_copy_imr(struct iwl_trans *trans, @@ -3914,8 +3914,8 @@ static void get_crf_id(struct iwl_trans *iwl_trans, /* wait until the device is ready to access the prph registers */ if (iwl_trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_DR || iwl_trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_SC) { - u32 req = iwl_read_umac_prph_no_grab(iwl_trans, - WFPM_RSRCS_4PHS_REQ_STTS); + u32 req = iwl_trans_read_umac_prph_no_grab(iwl_trans, + WFPM_RSRCS_4PHS_REQ_STTS); int ret; if (!(req & RSRC_REQ_CNVR_TOP)) { @@ -3936,7 +3936,7 @@ static void get_crf_id(struct iwl_trans *iwl_trans, } /* Enable access to peripheral registers */ - val = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG); + val = iwl_trans_read_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG); val |= WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK; iwl_pcie_write_umac_prph_no_grab(iwl_trans, WFPM_CTRL_REG, val); @@ -3968,7 +3968,7 @@ static void get_crf_id(struct iwl_trans *iwl_trans, } /* Read cdb info (also contains the jacket info if needed in the future */ - hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR); + hw_wfpm_id = iwl_trans_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR); IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n", info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id); @@ -3985,8 +3985,8 @@ static int map_crf_id(struct iwl_trans *iwl_trans, u32 val = info->hw_crf_id; u32 step_id = REG_CRF_ID_STEP(val); u32 slave_id = REG_CRF_ID_SLAVE(val); - u32 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, - WFPM_OTP_CFG1_ADDR); + u32 hw_wfpm_id = iwl_trans_read_umac_prph_no_grab(iwl_trans, + WFPM_OTP_CFG1_ADDR); u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id); /* Map between crf id to rf id */ @@ -4256,13 +4256,13 @@ int iwl_pcie_activate_nic(struct iwl_trans *trans) * D0U* --> D0A* (powered-up active) state. */ if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ | - CSR_GP_CNTRL_REG_FLAG_MAC_INIT); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ | + CSR_GP_CNTRL_REG_FLAG_MAC_INIT); poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS; } else { - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY; } @@ -4271,10 +4271,10 @@ int iwl_pcie_activate_nic(struct iwl_trans *trans) /* * Wait for clock stabilization; once stabilized, access to - * device-internal resources is supported, e.g. iwl_write_prph() + * device-internal resources is supported, e.g. iwl_trans_write_prph() * and accesses to uCode SRAM. */ - err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000); + err = iwl_trans_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000); if (err < 0) { IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index cd744f7002b6..c217e5189df4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -104,8 +104,8 @@ static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", txq_id, reg); - iwl_set_bit(trans, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + iwl_trans_set_bit(trans, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); txq->need_update = true; return; } @@ -493,21 +493,21 @@ void iwl_pcie_tx_start(struct iwl_trans *trans) sizeof(trans_pcie->txqs.queue_used)); trans_pcie->scd_base_addr = - iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); + iwl_trans_read_prph(trans, SCD_SRAM_BASE_ADDR); /* reset context data, TX status and translation data */ iwl_trans_write_mem(trans, trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND, NULL, clear_dwords); - iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, - trans_pcie->txqs.scd_bc_tbls.dma >> 10); + iwl_trans_write_prph(trans, SCD_DRAM_BASE_ADDR, + trans_pcie->txqs.scd_bc_tbls.dma >> 10); /* The chain extension of the SCD doesn't work well. This feature is * enabled by default by the HW, so we need to disable it manually. */ if (trans->mac_cfg->base->scd_chain_ext_wa) - iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); + iwl_trans_write_prph(trans, SCD_CHAINEXT_EN, 0); iwl_trans_ac_txq_enable(trans, trans->conf.cmd_queue, trans->conf.cmd_fifo, @@ -518,19 +518,19 @@ void iwl_pcie_tx_start(struct iwl_trans *trans) /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM; chan++) - iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); + iwl_trans_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | + FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); /* Update FH chicken bits */ reg_val = iwl_pcie_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); + iwl_trans_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, + reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); /* Enable L1-Active */ if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_8000) - iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + iwl_trans_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); } void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) @@ -553,17 +553,17 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) FH_MEM_CBBC_QUEUE(trans, txq_id), txq->dma_addr); else - iwl_write_direct32(trans, - FH_MEM_CBBC_QUEUE(trans, txq_id), - txq->dma_addr >> 8); + iwl_trans_write_direct32(trans, + FH_MEM_CBBC_QUEUE(trans, txq_id), + txq->dma_addr >> 8); iwl_pcie_txq_unmap(trans, txq_id); txq->read_ptr = 0; txq->write_ptr = 0; } /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, - trans_pcie->kw.dma >> 4); + iwl_trans_write_direct32(trans, FH_KW_MEM_ADDR_REG, + trans_pcie->kw.dma >> 4); /* * Send 0 as the scd_base_addr since the device may have be reset @@ -591,7 +591,7 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) } /* Wait for DMA channels to be idle */ - ret = iwl_poll_bits(trans, FH_TSSR_TX_STATUS_REG, mask, 5000); + ret = iwl_trans_poll_bits(trans, FH_TSSR_TX_STATUS_REG, mask, 5000); if (ret) IWL_ERR(trans, "Failing on timeout while stopping DMA channel %d [0x%08x]\n", @@ -684,7 +684,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq) return; } - status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id)); + status = iwl_trans_read_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id)); fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); @@ -693,9 +693,9 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq) txq_id, active ? "" : "in", fifo, jiffies_to_msecs(txq->wd_timeout), txq->read_ptr, txq->write_ptr, - iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & + iwl_trans_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (trans->mac_cfg->base->max_tfd_queue_size - 1), - iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) & + iwl_trans_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) & (trans->mac_cfg->base->max_tfd_queue_size - 1), iwl_pcie_read_direct32(trans, FH_TX_TRB_REG(fifo))); } @@ -955,8 +955,8 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) iwl_scd_deactivate_fifos(trans); /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, - trans_pcie->kw.dma >> 4); + iwl_trans_write_direct32(trans, FH_KW_MEM_ADDR_REG, + trans_pcie->kw.dma >> 4); spin_unlock_bh(&trans_pcie->irq_lock); @@ -984,14 +984,14 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) * queue. * Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id), - trans_pcie->txqs.txq[txq_id]->dma_addr >> 8); + iwl_trans_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id), + trans_pcie->txqs.txq[txq_id]->dma_addr >> 8); } - iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE); + iwl_trans_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE); if (trans->mac_cfg->base->num_of_queues > 20) - iwl_set_bits_prph(trans, SCD_GP_CTRL, - SCD_GP_CTRL_ENABLE_31_QUEUES); + iwl_trans_set_bits_prph(trans, SCD_GP_CTRL, + SCD_GP_CTRL_ENABLE_31_QUEUES); return 0; error: @@ -1222,13 +1222,13 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, * Assumes that ssn_idx is valid (!= 0xFFF) */ txq->read_ptr = (ssn & 0xff); txq->write_ptr = (ssn & 0xff); - iwl_write_direct32(trans, HBUS_TARG_WRPTR, - (ssn & 0xff) | (txq_id << 8)); + iwl_trans_write_direct32(trans, HBUS_TARG_WRPTR, + (ssn & 0xff) | (txq_id << 8)); if (cfg) { u8 frame_limit = cfg->frame_limit; - iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); + iwl_trans_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); /* Set up Tx window size and frame limit for this queue */ iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + @@ -1240,11 +1240,11 @@ bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, SCD_QUEUE_CTX_REG2_VAL(FRAME_LIMIT, frame_limit)); /* Set up status area in SRAM, map to Tx DMA/FIFO, activate */ - iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), - (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (cfg->fifo << SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << SCD_QUEUE_STTS_REG_POS_WSL) | - SCD_QUEUE_STTS_REG_MSK); + iwl_trans_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), + (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) | + (cfg->fifo << SCD_QUEUE_STTS_REG_POS_TXF) | + (1 << SCD_QUEUE_STTS_REG_POS_WSL) | + SCD_QUEUE_STTS_REG_MSK); /* enable the scheduler for this queue (only) */ if (txq_id == trans->conf.cmd_queue && diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c index 4365ffb0fd37..eb54b5da1d25 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c @@ -139,7 +139,7 @@ int iwl_pcie_poll_prph_bit(struct iwl_trans *trans, u32 addr, int t = 0; do { - if ((iwl_read_prph(trans, addr) & mask) == (bits & mask)) + if ((iwl_trans_read_prph(trans, addr) & mask) == (bits & mask)) return 0; udelay(IWL_PCIE_POLL_INTERVAL); t += IWL_PCIE_POLL_INTERVAL; @@ -163,7 +163,7 @@ int iwl_pcie_poll_umac_prph_bits_no_grab(struct iwl_trans *trans, u32 addr, int t = 0; do { - if ((iwl_read_umac_prph_no_grab(trans, addr) & mask) == + if ((iwl_trans_read_umac_prph_no_grab(trans, addr) & mask) == (bits & mask)) return 0; udelay(IWL_PCIE_POLL_INTERVAL); From 2874e58196eff1fae8bb07903ca72fb16c1a2c4c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:48 +0300 Subject: [PATCH 071/104] wifi: iwlwifi: move iwl-io functions to iwl-trans This commit completes the removal of iwl-io. Now that all io helpers use the iwl_trans_ prefix, move them to iwl-trans.h/c. Includers are updated to pull in iwl-trans.h No functional change. Assisted-by: GitHubCopilot:claude-opus-4.8 Link: https://patch.msgid.link/20260930121740.28c8b1af4303.I93a06977d9f5affa16c699d32e0e0577e49a534e@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/Makefile | 1 - .../net/wireless/intel/iwlwifi/dvm/debugfs.c | 1 - .../net/wireless/intel/iwlwifi/dvm/devices.c | 2 +- .../net/wireless/intel/iwlwifi/dvm/eeprom.c | 2 +- drivers/net/wireless/intel/iwlwifi/dvm/led.c | 1 - drivers/net/wireless/intel/iwlwifi/dvm/lib.c | 2 +- .../net/wireless/intel/iwlwifi/dvm/mac80211.c | 1 - drivers/net/wireless/intel/iwlwifi/dvm/main.c | 2 +- .../net/wireless/intel/iwlwifi/dvm/power.c | 3 +- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 1 - drivers/net/wireless/intel/iwlwifi/dvm/tt.c | 2 +- drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 3 +- .../net/wireless/intel/iwlwifi/dvm/ucode.c | 3 +- .../net/wireless/intel/iwlwifi/fw/dbg-old.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 2 +- drivers/net/wireless/intel/iwlwifi/fw/dump.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 99 ------------------- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 72 -------------- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-scd.h | 1 - .../net/wireless/intel/iwlwifi/iwl-trans.c | 89 +++++++++++++++++ .../net/wireless/intel/iwlwifi/iwl-trans.h | 60 +++++++++++ .../net/wireless/intel/iwlwifi/mld/debugfs.c | 2 +- .../intel/iwlwifi/mld/ftm-initiator.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +- .../intel/iwlwifi/mvm/ftm-initiator.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/led.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 +- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 - drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/tdls.c | 4 +- .../wireless/intel/iwlwifi/mvm/time-event.c | 1 - .../net/wireless/intel/iwlwifi/mvm/utils.c | 2 +- .../wireless/intel/iwlwifi/pcie/internal.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/utils.c | 2 +- .../net/wireless/intel/iwlwifi/pcie/utils.h | 2 +- 43 files changed, 181 insertions(+), 214 deletions(-) delete mode 100644 drivers/net/wireless/intel/iwlwifi/iwl-io.c delete mode 100644 drivers/net/wireless/intel/iwlwifi/iwl-io.h diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index 6746281350e0..504381b4aac7 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # common obj-$(CONFIG_IWLWIFI) += iwlwifi.o -iwlwifi-objs += iwl-io.o iwlwifi-objs += iwl-drv.o iwlwifi-objs += iwl-debug.o iwlwifi-objs += iwl-nvm-utils.o diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index ed041710c74f..799599efdd06 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -14,7 +14,6 @@ #include "iwl-debug.h" #include "iwl-trans.h" -#include "iwl-io.h" #include "dev.h" #include "agn.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c index c22f68db3e83..b7bd5e6deb5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/devices.c @@ -10,7 +10,7 @@ /* * DVM device-specific data & functions */ -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "iwl-nvm-utils.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c index aa532635e414..190e482849ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c @@ -8,7 +8,7 @@ #include "iwl-drv.h" #include "iwl-debug.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "iwl-csr.h" #include "agn.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index 6fa02cd0ab04..17b045ddb910 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -14,7 +14,6 @@ #include #include #include -#include "iwl-io.h" #include "iwl-trans.h" #include "iwl-modparams.h" #include "dev.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c index 2e16799818e4..37d6f2cf7efb 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c @@ -2,6 +2,7 @@ /****************************************************************************** * * Copyright(c) 2008 - 2014, 2022 Intel Corporation. All rights reserved. + * Copyright (C) 2026 Intel Corporation *****************************************************************************/ #include #include @@ -9,7 +10,6 @@ #include #include -#include "iwl-io.h" #include "iwl-agn-hw.h" #include "iwl-trans.h" #include "iwl-modparams.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 1da59e724054..e83bf615c161 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -23,7 +23,6 @@ #include -#include "iwl-io.h" #include "iwl-trans.h" #include "iwl-op-mode.h" #include "iwl-modparams.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index b3f73c773abe..4bf69f7a35a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -27,8 +27,8 @@ #include #include "iwl-nvm-utils.h" -#include "iwl-io.h" #include "iwl-trans.h" +#include "iwl-devtrace.h" #include "iwl-op-mode.h" #include "iwl-drv.h" #include "iwl-modparams.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/power.c b/drivers/net/wireless/intel/iwlwifi/dvm/power.c index e7dbba7134f7..4e19799d15d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/power.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2019, 2025 Intel Corporation + * Copyright (C) 2019, 2025-2026 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -13,7 +13,6 @@ #include #include #include -#include "iwl-io.h" #include "iwl-debug.h" #include "iwl-trans.h" #include "iwl-modparams.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 77aa7e04854f..fa2aff5bea6c 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -16,7 +16,6 @@ #include #include "iwl-trans.h" -#include "iwl-io.h" #include "dev.h" #include "calib.h" #include "agn.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c index c4ee22876f77..a414eb7c2446 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c @@ -13,7 +13,7 @@ #include #include #include -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-modparams.h" #include "iwl-debug.h" #include "agn.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c index 1a0167f67c7b..8dbc52971e7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -3,14 +3,13 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2019 Intel Corporation - * Copyright (C) 2023, 2025 Intel Corporation + * Copyright (C) 2023, 2025-2026 Intel Corporation *****************************************************************************/ #include #include #include #include -#include "iwl-io.h" #include "iwl-trans.h" #include "iwl-agn-hw.h" #include "dev.h" diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c index ac90191a3973..2ab1a32d774e 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c @@ -3,12 +3,11 @@ * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH - * Copyright (C) 2025 Intel Corporation + * Copyright (C) 2025-2026 Intel Corporation *****************************************************************************/ #include -#include "iwl-io.h" #include "iwl-agn-hw.h" #include "iwl-trans.h" #include "iwl-fh.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c index 320e891b3b03..09c798d2eba3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg-old.c @@ -9,7 +9,7 @@ #include "runtime.h" #include "dbg.h" #include "debugfs.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "iwl-csr.h" #include "iwl-fh.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 8827e4f317f1..8be5202dba94 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -9,7 +9,7 @@ #include "runtime.h" #include "dbg.h" #include "debugfs.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "iwl-csr.h" #include "iwl-fh.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index fc962a320583..70134d8f03c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -10,7 +10,7 @@ #include #include "runtime.h" #include "iwl-prph.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "file.h" #include "error-dump.h" #include "api/commands.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index deb7af465746..b76abc77f495 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -9,7 +9,7 @@ #include "runtime.h" #include "dbg.h" #include "debugfs.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "iwl-csr.h" #include "pnvm.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index 6e863059ffa7..ccd190ab8a55 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -6,7 +6,7 @@ #include "iwl-drv.h" #include "pnvm.h" #include "iwl-prph.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "fw/api/commands.h" #include "fw/api/nvm-reg.h" #include "fw/api/alive.h" diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 872df8f6c375..a654ab29ee42 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -6,7 +6,7 @@ #include "iwl-drv.h" #include "pnvm.h" #include "iwl-prph.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "fw/uefi.h" #include "fw/api/alive.h" diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c deleted file mode 100644 index 09965fb39fb6..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * Copyright (C) 2003-2014, 2018-2022, 2024-2026 Intel Corporation - * Copyright (C) 2015-2016 Intel Deutschland GmbH - */ -#include -#include - -#include "iwl-drv.h" -#include "iwl-io.h" -#include "iwl-csr.h" -#include "iwl-debug.h" - -#define IWL_POLL_INTERVAL 10 /* microseconds */ - -int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int t = 0; - - do { - if ((iwl_trans_read32(trans, addr) & mask) == (bits & mask)) - return 0; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} -IWL_EXPORT_SYMBOL(iwl_trans_poll_bits_mask); - -void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) -{ - if (iwl_trans_grab_nic_access(trans)) { - iwl_trans_write32(trans, reg, value); - iwl_trans_release_nic_access(trans); - } -} -IWL_EXPORT_SYMBOL(iwl_trans_write_direct32); - -u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs) -{ - if (iwl_trans_grab_nic_access(trans)) { - u32 val = iwl_trans_read_prph_no_grab(trans, ofs); - - iwl_trans_release_nic_access(trans); - - return val; - } - - /* return as if we have a HW timeout/failure */ - return 0x5a5a5a5a; -} -IWL_EXPORT_SYMBOL(iwl_trans_read_prph); - -void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, u32 delay_ms) -{ - if (iwl_trans_grab_nic_access(trans)) { - mdelay(delay_ms); - iwl_trans_write_prph_no_grab(trans, ofs, val); - iwl_trans_release_nic_access(trans); - } -} -IWL_EXPORT_SYMBOL(iwl_trans_write_prph_delay); - -void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) -{ - if (iwl_trans_grab_nic_access(trans)) { - iwl_trans_write_prph_no_grab(trans, ofs, - iwl_trans_read_prph_no_grab(trans, ofs) | - mask); - iwl_trans_release_nic_access(trans); - } -} -IWL_EXPORT_SYMBOL(iwl_trans_set_bits_prph); - -void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, - u32 bits, u32 mask) -{ - if (iwl_trans_grab_nic_access(trans)) { - iwl_trans_write_prph_no_grab(trans, ofs, - (iwl_trans_read_prph_no_grab(trans, ofs) & - mask) | bits); - iwl_trans_release_nic_access(trans); - } -} -IWL_EXPORT_SYMBOL(iwl_trans_set_bits_mask_prph); - -void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) -{ - u32 val; - - if (iwl_trans_grab_nic_access(trans)) { - val = iwl_trans_read_prph_no_grab(trans, ofs); - iwl_trans_write_prph_no_grab(trans, ofs, (val & ~mask)); - iwl_trans_release_nic_access(trans); - } -} -IWL_EXPORT_SYMBOL(iwl_trans_clear_bits_prph); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h deleted file mode 100644 index 5cb422a4d9de..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* - * Copyright (C) 2018-2021, 2025-2026 Intel Corporation - */ -#ifndef __iwl_io_h__ -#define __iwl_io_h__ - -#include "iwl-devtrace.h" -#include "iwl-trans.h" - -static inline void iwl_trans_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) -{ - iwl_trans_set_bits_mask(trans, reg, mask, mask); -} - -static inline void iwl_trans_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) -{ - iwl_trans_set_bits_mask(trans, reg, mask, 0); -} - -int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, - u32 bits, u32 mask, int timeout); -static inline int iwl_trans_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits, - int timeout) -{ - return iwl_trans_poll_bits_mask(trans, addr, bits, bits, timeout); -} - -void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); - - -u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs); -void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, - u32 val, u32 delay_ms); -static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) -{ - iwl_trans_write_prph_delay(trans, ofs, val, 0); -} - -void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); -void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, - u32 bits, u32 mask); -void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); - -/* - * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from - * device family AX200. So peripheries used in families above and below AX200 - * should go through iwl_trans_..._umac_..._prph. - */ -static inline u32 iwl_trans_umac_prph(struct iwl_trans *trans, u32 ofs) -{ - return ofs + trans->mac_cfg->umac_prph_offset; -} - -static inline u32 iwl_trans_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) -{ - return iwl_trans_read_prph_no_grab(trans, ofs + - trans->mac_cfg->umac_prph_offset); -} - -static inline u32 iwl_trans_read_umac_prph(struct iwl_trans *trans, u32 ofs) -{ - return iwl_trans_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset); -} - -static inline void iwl_trans_write_umac_prph(struct iwl_trans *trans, u32 ofs, - u32 val) -{ - iwl_trans_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val); -} - -#endif diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 9a8355514c4f..ed2b094c1ad7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -16,7 +16,7 @@ #include "iwl-modparams.h" #include "iwl-nvm-parse.h" #include "iwl-prph.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-csr.h" #include "fw/api/nvm-reg.h" #include "fw/api/commands.h" diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-scd.h b/drivers/net/wireless/intel/iwlwifi/iwl-scd.h index 22a7da73a918..f13568d3094b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-scd.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-scd.h @@ -7,7 +7,6 @@ #define __iwl_scd_h__ #include "iwl-trans.h" -#include "iwl-io.h" #include "iwl-prph.h" diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 59b4e180825f..09e5b606df26 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -6,6 +6,7 @@ */ #include #include +#include #include #include "iwl-trans.h" @@ -450,6 +451,94 @@ void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) return iwl_pcie_write_prph_no_grab(trans, ofs, val); } +#define IWL_POLL_INTERVAL 10 /* microseconds */ + +int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_trans_read32(trans, addr) & mask) == (bits & mask)) + return 0; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} +IWL_EXPORT_SYMBOL(iwl_trans_poll_bits_mask); + +void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value) +{ + if (iwl_trans_grab_nic_access(trans)) { + iwl_trans_write32(trans, reg, value); + iwl_trans_release_nic_access(trans); + } +} +IWL_EXPORT_SYMBOL(iwl_trans_write_direct32); + +u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs) +{ + if (iwl_trans_grab_nic_access(trans)) { + u32 val = iwl_trans_read_prph_no_grab(trans, ofs); + + iwl_trans_release_nic_access(trans); + + return val; + } + + /* return as if we have a HW timeout/failure */ + return 0x5a5a5a5a; +} +IWL_EXPORT_SYMBOL(iwl_trans_read_prph); + +void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, u32 val, + u32 delay_ms) +{ + if (iwl_trans_grab_nic_access(trans)) { + mdelay(delay_ms); + iwl_trans_write_prph_no_grab(trans, ofs, val); + iwl_trans_release_nic_access(trans); + } +} +IWL_EXPORT_SYMBOL(iwl_trans_write_prph_delay); + +void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) +{ + if (iwl_trans_grab_nic_access(trans)) { + iwl_trans_write_prph_no_grab(trans, ofs, + iwl_trans_read_prph_no_grab(trans, ofs) | + mask); + iwl_trans_release_nic_access(trans); + } +} +IWL_EXPORT_SYMBOL(iwl_trans_set_bits_prph); + +void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, + u32 bits, u32 mask) +{ + if (iwl_trans_grab_nic_access(trans)) { + iwl_trans_write_prph_no_grab(trans, ofs, + (iwl_trans_read_prph_no_grab(trans, ofs) & + mask) | bits); + iwl_trans_release_nic_access(trans); + } +} +IWL_EXPORT_SYMBOL(iwl_trans_set_bits_mask_prph); + +void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask) +{ + u32 val; + + if (iwl_trans_grab_nic_access(trans)) { + val = iwl_trans_read_prph_no_grab(trans, ofs); + iwl_trans_write_prph_no_grab(trans, ofs, (val & ~mask)); + iwl_trans_release_nic_access(trans); + } +} +IWL_EXPORT_SYMBOL(iwl_trans_clear_bits_prph); + void iwl_trans_force_nmi(struct iwl_trans *trans) { if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_9000) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 18c1c46c11ce..a32b03f19c3f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -977,6 +977,66 @@ int iwl_trans_sw_reset(struct iwl_trans *trans); void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); +static inline void iwl_trans_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) +{ + iwl_trans_set_bits_mask(trans, reg, mask, mask); +} + +static inline void iwl_trans_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) +{ + iwl_trans_set_bits_mask(trans, reg, mask, 0); +} + +int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout); +static inline int iwl_trans_poll_bits(struct iwl_trans *trans, u32 addr, u32 bits, + int timeout) +{ + return iwl_trans_poll_bits_mask(trans, addr, bits, bits, timeout); +} + +void iwl_trans_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); + +u32 iwl_trans_read_prph(struct iwl_trans *trans, u32 ofs); +void iwl_trans_write_prph_delay(struct iwl_trans *trans, u32 ofs, + u32 val, u32 delay_ms); +static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) +{ + iwl_trans_write_prph_delay(trans, ofs, val, 0); +} + +void iwl_trans_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); +void iwl_trans_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, + u32 bits, u32 mask); +void iwl_trans_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); + +/* + * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from + * device family AX200. So peripheries used in families above and below AX200 + * should go through iwl_trans_..._umac_..._prph. + */ +static inline u32 iwl_trans_umac_prph(struct iwl_trans *trans, u32 ofs) +{ + return ofs + trans->mac_cfg->umac_prph_offset; +} + +static inline u32 iwl_trans_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) +{ + return iwl_trans_read_prph_no_grab(trans, ofs + + trans->mac_cfg->umac_prph_offset); +} + +static inline u32 iwl_trans_read_umac_prph(struct iwl_trans *trans, u32 ofs) +{ + return iwl_trans_read_prph(trans, ofs + trans->mac_cfg->umac_prph_offset); +} + +static inline void iwl_trans_write_umac_prph(struct iwl_trans *trans, u32 ofs, + u32 val) +{ + iwl_trans_write_prph(trans, ofs + trans->mac_cfg->umac_prph_offset, val); +} + bool iwl_trans_grab_nic_access(struct iwl_trans *trans); /** diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c index dd4bf7cb6a79..b8793b71494d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c @@ -5,7 +5,7 @@ #include "mld.h" #include "debugfs.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "hcmd.h" #include "iface.h" #include "sta.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c index a4b8037b5c76..a6a4f9672e4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/ftm-initiator.c @@ -8,7 +8,7 @@ #include "mld.h" #include "iface.h" #include "phy.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "constants.h" #include "fw/api/location.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 48f8bab4dc85..90175307a7db 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -13,7 +13,7 @@ #include "mvm.h" #include "sta.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "debugfs.h" #include "iwl-modparams.h" #include "iwl-drv.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 8d7f60dcd027..4c39a452564d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -7,7 +7,7 @@ #include #include #include "mvm.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "constants.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c index 264423943b60..ac238c963855 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c @@ -4,7 +4,7 @@ * Copyright (C) 2017 Intel Deutschland GmbH */ #include -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-csr.h" #include "mvm.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index b41b4bbf0049..58a77056e607 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -7,7 +7,7 @@ #include #include #include -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "fw-api.h" #include "mvm.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index a4f3d3c2bd35..daa05339e3fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -19,7 +19,7 @@ #include "iwl-drv.h" #include "iwl-op-mode.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "mvm.h" #include "sta.h" #include "time-event.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 653c620361d5..183251457361 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -20,7 +20,6 @@ #include "iwl-phy-db.h" #include "iwl-nvm-utils.h" #include "iwl-csr.h" -#include "iwl-io.h" #include "iwl-prph.h" #include "rs.h" #include "fw/api/scan.h" diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index a94eaca0b3ed..c12eda75317d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -10,7 +10,7 @@ #include "mvm.h" #include "fw/api/scan.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-utils.h" #define IWL_DENSE_EBS_SCAN_RATIO 5 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c index a7cd2e4ba1ae..6aac71cfccb3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c @@ -2,12 +2,12 @@ /* * Copyright (C) 2014 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020, 2022-2025 Intel Corporation + * Copyright (C) 2018-2020, 2022-2026 Intel Corporation */ #include #include "mvm.h" #include "time-event.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #define TU_TO_US(x) (x * 1024) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 93b46c9e2333..5a800d3f2a98 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -12,7 +12,6 @@ #include "fw-api.h" #include "time-event.h" #include "mvm.h" -#include "iwl-io.h" #include "iwl-prph.h" /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index cd0d89feecea..e97ab2c9e5ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -7,7 +7,7 @@ #include #include "iwl-debug.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-prph.h" #include "iwl-csr.h" #include "mvm.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index d74742df2fe5..e0ac9f2e6526 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -18,8 +18,8 @@ #include "iwl-fh.h" #include "iwl-csr.h" #include "iwl-trans.h" +#include "iwl-devtrace.h" #include "iwl-debug.h" -#include "iwl-io.h" #include "iwl-op-mode.h" #include "iwl-drv.h" #include "iwl-context-info.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index e3fe5a912a8b..f033bb51dcca 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -9,7 +9,7 @@ #include #include "iwl-prph.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "internal.h" #include "pcie/utils.h" #include "iwl-op-mode.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index abdb2548827f..e6bebd37417f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -8,7 +8,7 @@ #include "iwl-debug.h" #include "iwl-csr.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "internal.h" #include "fw/api/tx.h" #include "fw/api/commands.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index c217e5189df4..d612678ae122 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -20,7 +20,7 @@ #include "iwl-debug.h" #include "iwl-csr.h" #include "iwl-prph.h" -#include "iwl-io.h" +#include "iwl-trans.h" #include "iwl-scd.h" #include "iwl-op-mode.h" #include "internal.h" diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c index eb54b5da1d25..8aa43e5ac0e1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.c @@ -6,7 +6,7 @@ #include #include -#include "iwl-io.h" +#include "iwl-trans.h" #include "pcie/utils.h" void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index 74c23ec199e2..ece1caaa4948 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -6,7 +6,7 @@ #ifndef __iwl_pcie_utils_h__ #define __iwl_pcie_utils_h__ -#include "iwl-io.h" +#include "iwl-trans.h" #include "internal.h" void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev); From a95d336d91c0bd7108735fe0db75b06b0bfad7f3 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:49 +0300 Subject: [PATCH 072/104] wifi: iwlwifi: call generic trans API and not pcie one iwl_trans_pcie_reset is currently called from outside of pcie, like in mvm opmode. This is wrong and contradicts the architecture. Add a generic trans API which will call the PCIE implementation. Link: https://patch.msgid.link/20260930121740.444e257d5a49.I4c4892ca6bcae0095639341f3c2aba76bcd1ee86@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 9 ++++++++- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 3 +-- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 1 - 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 09e5b606df26..b0eb3deba23d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -261,7 +261,7 @@ static void iwl_trans_restart_wk(struct work_struct *wk) iwl_trans_schedule_reprobe(trans, 0); break; default: - iwl_trans_pcie_reset(trans, mode); + iwl_trans_reset(trans, mode); break; } } @@ -929,3 +929,10 @@ int iwl_trans_activate_nic(struct iwl_trans *trans) } IWL_EXPORT_SYMBOL(iwl_trans_activate_nic); + +void iwl_trans_reset(struct iwl_trans *trans, enum iwl_reset_mode mode) +{ + iwl_trans_pcie_reset(trans, mode); +} +IWL_EXPORT_SYMBOL(iwl_trans_reset); + diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index a32b03f19c3f..719b6c9ba360 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1216,7 +1216,7 @@ enum iwl_reset_mode { IWL_RESET_MODE_BACKOFF, }; -void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode); +void iwl_trans_reset(struct iwl_trans *trans, enum iwl_reset_mode mode); void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans); /* Internal helper */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 9b4637a3d1ef..ae109e3ea141 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -640,8 +640,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm) /* if we needed reset then fail here, but notify and remove */ if (mvm->fw_product_reset) { iwl_mei_alive_notif(false); - iwl_trans_pcie_reset(mvm->trans, - IWL_RESET_MODE_RESCAN); + iwl_trans_reset(mvm->trans, IWL_RESET_MODE_RESCAN); } goto error; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index e0ac9f2e6526..fab73693e683 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1148,6 +1148,7 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr, void *buf, u32 dwords); int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership); +void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode); struct iwl_trans_dump_data * iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask, const struct iwl_dump_sanitize_ops *sanitize_ops, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 8da0cc603070..59e9ef0d6b51 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2329,7 +2329,6 @@ void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode) pci_dev_get(removal->pdev); schedule_work(&removal->work); } -EXPORT_SYMBOL(iwl_trans_pcie_reset); /* * This version doesn't disable BHs but rather assumes they're From a24618b2e22b91d3932df48e160744d8a9d2780d Mon Sep 17 00:00:00 2001 From: Daniel Gabay Date: Wed, 30 Sep 2026 12:19:50 +0300 Subject: [PATCH 073/104] wifi: iwlwifi: mld: test TX gp2 timestamps Add KUnit tests for the gp2 estimate: timestamp arithmetic and u32 wraparounds, zero offsets, zero timestamp handling, and the expiry and refresh thresholds driven by valid_until. Exercise the thresholds with jiffies near wraparound. Signed-off-by: Daniel Gabay Assisted-by: LLM Link: https://patch.msgid.link/20260930121740.16628072486e.Ia0ead71cdc521a3c5db80bfd2e11a718692b3ab2@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/mld/tests/Makefile | 2 +- .../wireless/intel/iwlwifi/mld/tests/tx-gp2.c | 154 ++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mld/tx.c | 3 +- drivers/net/wireless/intel/iwlwifi/mld/tx.h | 5 + 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wireless/intel/iwlwifi/mld/tests/tx-gp2.c diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile index efa61638b8ee..730185be3fa8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause iwlmld-tests-y += module.o hcmd.o utils.o link.o rx.o agg.o link-selection.o -iwlmld-tests-y += chan_load_thresh.o +iwlmld-tests-y += chan_load_thresh.o tx-gp2.o ccflags-y += -I$(src)/../ obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmld-tests.o diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/tx-gp2.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/tx-gp2.c new file mode 100644 index 000000000000..535140eb17c4 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/tx-gp2.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * KUnit tests for TX gp2 timestamp handling + * + * Copyright (C) 2026 Intel Corporation + */ +#include + +#include "mld.h" +#include "tx.h" + +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); + +static const struct tx_gp2_case { + const char *desc; + u32 est_gp2_us; + u32 est_host_us; + u32 tx_host_us; + long valid_for; + u32 expected_gp2_us; + bool expected_refresh; +} tx_gp2_cases[] = { + { + .desc = "zero offset is valid", + .est_gp2_us = 2000, + .est_host_us = 2000, + .tx_host_us = 3500, + .valid_for = IWL_MLD_TX_GP2_VALID_PERIOD, + .expected_gp2_us = 3500, + }, + { + .desc = "gp2 behind host", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = IWL_MLD_TX_GP2_VALID_PERIOD, + .expected_gp2_us = 3500, + }, + { + .desc = "gp2 ahead of host", + .est_gp2_us = 10000, + .est_host_us = 2000, + .tx_host_us = 3500, + .valid_for = IWL_MLD_TX_GP2_VALID_PERIOD, + .expected_gp2_us = 11500, + }, + { + .desc = "gp2 wraps after the estimate", + .est_gp2_us = U32_MAX - 999, + .est_host_us = 1000, + .tx_host_us = 2500, + .valid_for = IWL_MLD_TX_GP2_VALID_PERIOD, + .expected_gp2_us = 500, + }, + { + .desc = "host time wraps after the estimate", + .est_gp2_us = 5000, + .est_host_us = U32_MAX - 999, + .tx_host_us = 500, + .valid_for = IWL_MLD_TX_GP2_VALID_PERIOD, + .expected_gp2_us = 6500, + }, + { + .desc = "gp2 landing on 0 is reported as 1", + .est_gp2_us = U32_MAX - 1499, + .est_host_us = 1000, + .tx_host_us = 2500, + .valid_for = IWL_MLD_TX_GP2_VALID_PERIOD, + .expected_gp2_us = 1, + }, + { + .desc = "within the refresh margin: still timestamped", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = IWL_MLD_TX_GP2_REFRESH_MARGIN - 1, + .expected_gp2_us = 3500, + .expected_refresh = true, + }, + { + .desc = "outside the refresh margin: no refresh", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = IWL_MLD_TX_GP2_REFRESH_MARGIN + 1, + .expected_gp2_us = 3500, + }, + { + .desc = "at the refresh threshold", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = IWL_MLD_TX_GP2_REFRESH_MARGIN, + .expected_gp2_us = 3500, + .expected_refresh = true, + }, + { + .desc = "last valid tick", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = 1, + .expected_gp2_us = 3500, + .expected_refresh = true, + }, + { + .desc = "validity reached: leave the frame unstamped", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = 0, + .expected_refresh = true, + }, + { + .desc = "validity passed: leave the frame unstamped", + .est_gp2_us = 2000, + .est_host_us = 10000, + .tx_host_us = 11500, + .valid_for = -1, + .expected_refresh = true, + }, +}; + +KUNIT_ARRAY_PARAM_DESC(tx_gp2, tx_gp2_cases, desc); + +static void test_tx_gp2(struct kunit *test) +{ + /* Pin time near wraparound to exercise wrapped validity deadlines. */ + const unsigned long now = + ULONG_MAX - IWL_MLD_TX_GP2_REFRESH_MARGIN - 1; + const struct tx_gp2_case *test_case = test->param_value; + u32 delta_us = test_case->est_gp2_us - test_case->est_host_us; + unsigned long valid_until = now + test_case->valid_for; + bool refresh = !test_case->expected_refresh; + u32 timestamp; + + timestamp = iwl_mld_tx_gp2_from_est(delta_us, valid_until, + test_case->tx_host_us, now, + &refresh); + KUNIT_EXPECT_EQ(test, timestamp, test_case->expected_gp2_us); + KUNIT_EXPECT_EQ(test, refresh, test_case->expected_refresh); +} + +static struct kunit_case tx_gp2_test_cases[] = { + KUNIT_CASE_PARAM(test_tx_gp2, tx_gp2_gen_params), + {} +}; + +static struct kunit_suite tx_gp2_test_suite = { + .name = "iwl_mld_tx_gp2", + .test_cases = tx_gp2_test_cases, +}; + +kunit_test_suite(tx_gp2_test_suite); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c index aac7d43bffd1..fc501ac0c1f2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c @@ -29,7 +29,7 @@ static u32 iwl_mld_tx_gp2_host_us(void) /* Returns the gp2 for the TX command, or 0 to leave the frame unstamped. * Sets @refresh when the estimate expired or is about to. */ -static u32 +VISIBLE_IF_IWLWIFI_KUNIT u32 iwl_mld_tx_gp2_from_est(u32 delta_us, unsigned long valid_until, u32 host_us, unsigned long now, bool *refresh) { @@ -46,6 +46,7 @@ iwl_mld_tx_gp2_from_est(u32 delta_us, unsigned long valid_until, u32 host_us, /* 0 means no timestamp; use 1 for a valid wrapped value. */ return gp2 ?: 1; } +EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_tx_gp2_from_est); static u32 iwl_mld_tx_gp2_timestamp(struct iwl_mld *mld) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.h b/drivers/net/wireless/intel/iwlwifi/mld/tx.h index 0a9a2e4abcab..a376e8c9c500 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.h @@ -106,4 +106,9 @@ void iwl_mld_tx_gp2_init(struct iwl_mld *mld); void iwl_mld_tx_gp2_start(struct iwl_mld *mld); void iwl_mld_tx_gp2_stop(struct iwl_mld *mld); +#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) +u32 iwl_mld_tx_gp2_from_est(u32 delta_us, unsigned long valid_until, + u32 host_us, unsigned long now, bool *refresh); +#endif + #endif /* __iwl_mld_tx_h__ */ From 5567873198b2eea8e22a12a104ae870e8c318e3f Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Wed, 30 Sep 2026 12:19:51 +0300 Subject: [PATCH 074/104] wifi: iwlwifi: trans: bring virtualization back We removed virtualization because PCIe is the only bus. The problem with the if-else approach is that it causes a dual dependency: the generic trans needs to include the bus specific, and vice-versa. Besides being a bad design, it also has pratical problems: 1. small functions that could be static inline ones - can't, because only iwl-trans.c has the bus specific include. 2. while in pcie we have one giant header file, ironically called internal.h, that has all the declarations needed by the generic trans, in USB there will be several ones, and including them means including all the USB internal logic, which should not be exposed. This commit brings back the virtualization. Since gen1 and gen2 were never split properly, and since they share almost all the callbacks, pcie registers with a single ops struct. This also fixed the debug code to call a generic API for fw reset handshake, instead of calling the pcie directly. Assisted-by: GitHubCopilot:claude-opus-4.8 Reviewed-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.c0dde34db029.I0b53f83df3faad21c0c39b3e709896e7dde6ac35@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 +- .../net/wireless/intel/iwlwifi/iwl-trans.c | 230 ++++++++++++------ .../net/wireless/intel/iwlwifi/iwl-trans.h | 150 +++++++++++- .../wireless/intel/iwlwifi/pcie/internal.h | 5 +- .../net/wireless/intel/iwlwifi/pcie/trans.c | 101 +++++++- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 3 + 6 files changed, 407 insertions(+), 86 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 8be5202dba94..1d34ad59bb71 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1820,14 +1820,14 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt, cpu_to_le32(IWL_FW_INI_APPLY_POLICY_SPLIT_DUMP_RESET)) { size += iwl_dump_ini_dump_entries(fwrt, list, IWL_INI_DUMP_EARLY_REGIONS); - iwl_trans_pcie_fw_reset_handshake(fwrt->trans); + iwl_trans_fw_reset_handshake(fwrt->trans); size += iwl_dump_ini_dump_entries(fwrt, list, IWL_INI_DUMP_LATE_REGIONS); } else { if (fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT) && iwl_dump_due_to_error(tp_id)) - iwl_trans_pcie_fw_reset_handshake(fwrt->trans); + iwl_trans_fw_reset_handshake(fwrt->trans); size += iwl_dump_ini_dump_entries(fwrt, list, IWL_INI_DUMP_ALL_REGIONS); } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index b0eb3deba23d..6ddf4945ed1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -14,8 +14,6 @@ #include "iwl-prph.h" #include #include "fw/api/commands.h" -#include "pcie/internal.h" -#include "pcie/iwl-context-info-v2.h" struct iwl_trans_dev_restart_data { struct list_head list; @@ -268,6 +266,7 @@ static void iwl_trans_restart_wk(struct work_struct *wk) struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct device *dev, + const struct iwl_trans_ops *ops, const struct iwl_mac_cfg *mac_cfg) { struct iwl_trans *trans; @@ -279,6 +278,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, if (!trans) return NULL; + trans->ops = ops; trans->mac_cfg = mac_cfg; #ifdef CONFIG_LOCKDEP @@ -302,6 +302,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { int ret; + if (WARN_ON_ONCE(!trans->ops->send_cmd)) + return -EOPNOTSUPP; + if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) && test_bit(STATUS_RFKILL_OPMODE, &trans->status))) return -ERFKILL; @@ -321,7 +324,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) cmd->id = DEF_ID(cmd->id); } - ret = iwl_trans_pcie_send_hcmd(trans, cmd); + ret = trans->ops->send_cmd(trans, cmd); if (!(cmd->flags & CMD_ASYNC)) lock_map_release(&trans->sync_cmd_lockdep_map); @@ -335,14 +338,18 @@ IWL_EXPORT_SYMBOL(iwl_trans_send_cmd); struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) { - return iwl_pcie_alloc_tx_cmd(trans); + if (WARN_ON_ONCE(!trans->ops->alloc_tx_cmd)) + return ERR_PTR(-EOPNOTSUPP); + return trans->ops->alloc_tx_cmd(trans); } IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd); void iwl_trans_free_tx_cmd(struct iwl_trans *trans, struct iwl_device_tx_cmd *dev_cmd) { - iwl_pcie_free_tx_cmd(trans, dev_cmd); + if (WARN_ON_ONCE(!trans->ops->free_tx_cmd)) + return; + trans->ops->free_tx_cmd(trans, dev_cmd); } IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd); @@ -397,7 +404,9 @@ void iwl_trans_op_mode_enter(struct iwl_trans *trans, WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd); - iwl_trans_pcie_op_mode_enter(trans); + if (WARN_ON_ONCE(!trans->ops->op_mode_enter)) + return; + trans->ops->op_mode_enter(trans); } IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter); @@ -407,7 +416,9 @@ int iwl_trans_start_hw(struct iwl_trans *trans) clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status); - return iwl_trans_pcie_start_hw(trans); + if (WARN_ON_ONCE(!trans->ops->start_hw)) + return -EOPNOTSUPP; + return trans->ops->start_hw(trans); } IWL_EXPORT_SYMBOL(iwl_trans_start_hw); @@ -415,10 +426,8 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans) { might_sleep(); - if (trans->mac_cfg->gen2) - iwl_trans_pcie_gen2_op_mode_leave(trans); - else - iwl_trans_pcie_op_mode_leave(trans); + if (!WARN_ON_ONCE(!trans->ops->op_mode_leave)) + trans->ops->op_mode_leave(trans); cancel_delayed_work_sync(&trans->restart.wk); @@ -431,41 +440,40 @@ IWL_EXPORT_SYMBOL(iwl_trans_op_mode_leave); void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val) { - iwl_trans_pcie_write32(trans, ofs, val); + if (WARN_ON_ONCE(!trans->ops->write32)) + return; + trans->ops->write32(trans, ofs, val); } IWL_EXPORT_SYMBOL(iwl_trans_write32); u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) { - return iwl_trans_pcie_read32(trans, ofs); + if (WARN_ON_ONCE(!trans->ops->read32)) + return 0; + return trans->ops->read32(trans, ofs); } IWL_EXPORT_SYMBOL(iwl_trans_read32); u32 iwl_trans_read_prph_no_grab(struct iwl_trans *trans, u32 ofs) { - return iwl_trans_pcie_read_prph(trans, ofs); + if (WARN_ON_ONCE(!trans->ops->read_prph)) + return 0; + return trans->ops->read_prph(trans, ofs); } void iwl_trans_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val) { - return iwl_pcie_write_prph_no_grab(trans, ofs, val); + if (WARN_ON_ONCE(!trans->ops->write_prph)) + return; + trans->ops->write_prph(trans, ofs, val); } -#define IWL_POLL_INTERVAL 10 /* microseconds */ - int iwl_trans_poll_bits_mask(struct iwl_trans *trans, u32 addr, u32 bits, u32 mask, int timeout) { - int t = 0; - - do { - if ((iwl_trans_read32(trans, addr) & mask) == (bits & mask)) - return 0; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; + if (WARN_ON_ONCE(!trans->ops->poll_bits_mask)) + return -EOPNOTSUPP; + return trans->ops->poll_bits_mask(trans, addr, bits, mask, timeout); } IWL_EXPORT_SYMBOL(iwl_trans_poll_bits_mask); @@ -559,14 +567,18 @@ IWL_EXPORT_SYMBOL(iwl_trans_force_nmi); int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords) { - return iwl_trans_pcie_read_mem(trans, addr, buf, dwords); + if (WARN_ON_ONCE(!trans->ops->read_mem)) + return -EOPNOTSUPP; + return trans->ops->read_mem(trans, addr, buf, dwords); } IWL_EXPORT_SYMBOL(iwl_trans_read_mem); int iwl_trans_read_mem_no_grab(struct iwl_trans *trans, u32 addr, void *buf, u32 dwords) { - return iwl_trans_pcie_read_mem_no_grab(trans, addr, buf, dwords); + if (WARN_ON_ONCE(!trans->ops->read_mem_no_grab)) + return -EOPNOTSUPP; + return trans->ops->read_mem_no_grab(trans, addr, buf, dwords); } int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, @@ -599,7 +611,9 @@ IWL_EXPORT_SYMBOL(iwl_trans_set_pmi); int iwl_trans_sw_reset(struct iwl_trans *trans) { - return iwl_trans_pcie_sw_reset(trans, true); + if (WARN_ON_ONCE(!trans->ops->sw_reset)) + return -EOPNOTSUPP; + return trans->ops->sw_reset(trans, true); } struct iwl_trans_dump_data * @@ -607,15 +621,19 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask, const struct iwl_dump_sanitize_ops *sanitize_ops, void *sanitize_ctx) { - return iwl_trans_pcie_dump_data(trans, dump_mask, - sanitize_ops, sanitize_ctx); + if (WARN_ON_ONCE(!trans->ops->dump_data)) + return NULL; + return trans->ops->dump_data(trans, dump_mask, + sanitize_ops, sanitize_ctx); } int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset) { might_sleep(); - return iwl_trans_pcie_d3_suspend(trans, reset); + if (WARN_ON_ONCE(!trans->ops->d3_suspend)) + return -EOPNOTSUPP; + return trans->ops->d3_suspend(trans, reset); } IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend); @@ -623,48 +641,64 @@ int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset) { might_sleep(); - return iwl_trans_pcie_d3_resume(trans, reset); + if (WARN_ON_ONCE(!trans->ops->d3_resume)) + return -EOPNOTSUPP; + return trans->ops->d3_resume(trans, reset); } IWL_EXPORT_SYMBOL(iwl_trans_d3_resume); void iwl_trans_sync_nmi(struct iwl_trans *trans) { - iwl_trans_pcie_sync_nmi(trans); + if (WARN_ON_ONCE(!trans->ops->sync_nmi)) + return; + trans->ops->sync_nmi(trans); } int iwl_trans_write_imr_mem(struct iwl_trans *trans, u32 dst_addr, u64 src_addr, u32 byte_cnt) { - return iwl_trans_pcie_copy_imr(trans, dst_addr, src_addr, byte_cnt); + if (WARN_ON_ONCE(!trans->ops->write_imr_mem)) + return -EOPNOTSUPP; + return trans->ops->write_imr_mem(trans, dst_addr, src_addr, byte_cnt); } void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) { - iwl_trans_pcie_set_bits_mask(trans, reg, mask, value); + if (WARN_ON_ONCE(!trans->ops->set_bits_mask)) + return; + trans->ops->set_bits_mask(trans, reg, mask, value); } IWL_EXPORT_SYMBOL(iwl_trans_set_bits_mask); int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs, u32 *val) { - return iwl_trans_pcie_read_config32(trans, ofs, val); + if (WARN_ON_ONCE(!trans->ops->read_config32)) + return -EOPNOTSUPP; + return trans->ops->read_config32(trans, ofs, val); } bool iwl_trans_grab_nic_access(struct iwl_trans *trans) { - return iwl_trans_pcie_grab_nic_access(trans); + if (WARN_ON_ONCE(!trans->ops->grab_nic_access)) + return false; + return trans->ops->grab_nic_access(trans); } IWL_EXPORT_SYMBOL(iwl_trans_grab_nic_access); void iwl_trans_resched_with_nic_access(struct iwl_trans *trans) { - iwl_trans_pcie_resched_with_nic_access(trans); + if (WARN_ON_ONCE(!trans->ops->resched_with_nic_access)) + return; + trans->ops->resched_with_nic_access(trans); } void iwl_trans_release_nic_access(struct iwl_trans *trans) { - iwl_trans_pcie_release_nic_access(trans); + if (WARN_ON_ONCE(!trans->ops->release_nic_access)) + return; + trans->ops->release_nic_access(trans); } IWL_EXPORT_SYMBOL(iwl_trans_release_nic_access); @@ -674,10 +708,8 @@ void iwl_trans_fw_alive(struct iwl_trans *trans) trans->state = IWL_TRANS_FW_ALIVE; - if (trans->mac_cfg->gen2) - iwl_trans_pcie_gen2_fw_alive(trans); - else - iwl_trans_pcie_fw_alive(trans); + if (!WARN_ON_ONCE(!trans->ops->fw_alive)) + trans->ops->fw_alive(trans); } IWL_EXPORT_SYMBOL(iwl_trans_fw_alive); @@ -695,12 +727,10 @@ int iwl_trans_start_fw(struct iwl_trans *trans, const struct iwl_fw *fw, clear_bit(STATUS_FW_ERROR, &trans->status); - if (trans->mac_cfg->gen2) - ret = iwl_trans_pcie_gen2_start_fw(trans, fw, img, - run_in_rfkill); - else - ret = iwl_trans_pcie_start_fw(trans, fw, img, - run_in_rfkill); + if (WARN_ON_ONCE(!trans->ops->start_fw)) + return -EOPNOTSUPP; + + ret = trans->ops->start_fw(trans, fw, img, run_in_rfkill); if (ret == 0) trans->state = IWL_TRANS_FW_STARTED; @@ -741,10 +771,8 @@ void iwl_trans_stop_device(struct iwl_trans *trans) iwl_op_mode_dump_error(trans->op_mode, &mode); } - if (trans->mac_cfg->gen2) - iwl_trans_pcie_gen2_stop_device(trans); - else - iwl_trans_pcie_stop_device(trans); + if (!WARN_ON_ONCE(!trans->ops->stop_device)) + trans->ops->stop_device(trans); trans->state = IWL_TRANS_NO_FW; } @@ -760,10 +788,10 @@ int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, "bad state = %d\n", trans->state)) return -EIO; - if (trans->mac_cfg->gen2) - return iwl_txq_gen2_tx(trans, skb, dev_cmd, queue); + if (WARN_ON_ONCE(!trans->ops->tx)) + return -EOPNOTSUPP; - return iwl_trans_pcie_tx(trans, skb, dev_cmd, queue); + return trans->ops->tx(trans, skb, dev_cmd, queue); } IWL_EXPORT_SYMBOL(iwl_trans_tx); @@ -777,14 +805,18 @@ void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn, "bad state = %d\n", trans->state)) return; - iwl_pcie_reclaim(trans, queue, ssn, skbs, is_flush); + if (WARN_ON_ONCE(!trans->ops->reclaim)) + return; + trans->ops->reclaim(trans, queue, ssn, skbs, is_flush); } IWL_EXPORT_SYMBOL(iwl_trans_reclaim); void iwl_trans_txq_disable(struct iwl_trans *trans, int queue, bool configure_scd) { - iwl_trans_pcie_txq_disable(trans, queue, configure_scd); + if (WARN_ON_ONCE(!trans->ops->txq_disable)) + return; + trans->ops->txq_disable(trans, queue, configure_scd); } IWL_EXPORT_SYMBOL(iwl_trans_txq_disable); @@ -798,8 +830,10 @@ bool iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn, "bad state = %d\n", trans->state)) return false; - return iwl_trans_pcie_txq_enable(trans, queue, ssn, - cfg, queue_wdg_timeout); + if (WARN_ON_ONCE(!trans->ops->txq_enable)) + return false; + return trans->ops->txq_enable(trans, queue, ssn, + cfg, queue_wdg_timeout); } IWL_EXPORT_SYMBOL(iwl_trans_txq_enable_cfg); @@ -812,7 +846,9 @@ int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue) "bad state = %d\n", trans->state)) return -EIO; - return iwl_trans_pcie_wait_txq_empty(trans, queue); + if (WARN_ON_ONCE(!trans->ops->wait_txq_empty)) + return -EOPNOTSUPP; + return trans->ops->wait_txq_empty(trans, queue); } IWL_EXPORT_SYMBOL(iwl_trans_wait_txq_empty); @@ -822,7 +858,9 @@ int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, u32 txqs) "bad state = %d\n", trans->state)) return -EIO; - return iwl_trans_pcie_wait_txqs_empty(trans, txqs); + if (WARN_ON_ONCE(!trans->ops->wait_txqs_empty)) + return -EOPNOTSUPP; + return trans->ops->wait_txqs_empty(trans, txqs); } IWL_EXPORT_SYMBOL(iwl_trans_wait_tx_queues_empty); @@ -833,14 +871,18 @@ void iwl_trans_freeze_txq_timer(struct iwl_trans *trans, "bad state = %d\n", trans->state)) return; - iwl_pcie_freeze_txq_timer(trans, txqs, freeze); + if (WARN_ON_ONCE(!trans->ops->freeze_txq_timer)) + return; + trans->ops->freeze_txq_timer(trans, txqs, freeze); } IWL_EXPORT_SYMBOL(iwl_trans_freeze_txq_timer); void iwl_trans_txq_set_shared_mode(struct iwl_trans *trans, int txq_id, bool shared_mode) { - iwl_trans_pcie_txq_set_shared_mode(trans, txq_id, shared_mode); + if (WARN_ON_ONCE(!trans->ops->txq_set_shared_mode)) + return; + trans->ops->txq_set_shared_mode(trans, txq_id, shared_mode); } IWL_EXPORT_SYMBOL(iwl_trans_txq_set_shared_mode); @@ -850,7 +892,9 @@ void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, int ptr) "bad state = %d\n", trans->state)) return; - iwl_pcie_set_q_ptrs(trans, queue, ptr); + if (WARN_ON_ONCE(!trans->ops->set_q_ptrs)) + return; + trans->ops->set_q_ptrs(trans, queue, ptr); } IWL_EXPORT_SYMBOL(iwl_trans_set_q_ptrs); @@ -863,49 +907,62 @@ int iwl_trans_txq_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask, "bad state = %d\n", trans->state)) return -EIO; - return iwl_txq_dyn_alloc(trans, flags, sta_mask, tid, - size, wdg_timeout); + if (WARN_ON_ONCE(!trans->ops->txq_alloc)) + return -EOPNOTSUPP; + return trans->ops->txq_alloc(trans, flags, sta_mask, tid, + size, wdg_timeout); } IWL_EXPORT_SYMBOL(iwl_trans_txq_alloc); void iwl_trans_txq_free(struct iwl_trans *trans, int queue) { - iwl_txq_dyn_free(trans, queue); + if (WARN_ON_ONCE(!trans->ops->txq_free)) + return; + trans->ops->txq_free(trans, queue); } IWL_EXPORT_SYMBOL(iwl_trans_txq_free); int iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue, struct iwl_trans_rxq_dma_data *data) { - return iwl_trans_pcie_rxq_dma_data(trans, queue, data); + if (WARN_ON_ONCE(!trans->ops->rxq_dma_data)) + return -EOPNOTSUPP; + return trans->ops->rxq_dma_data(trans, queue, data); } int iwl_trans_load_pnvm(struct iwl_trans *trans, const struct iwl_pnvm_image *pnvm_data, const struct iwl_ucode_capabilities *capa) { - return iwl_trans_pcie_ctx_info_v2_load_pnvm(trans, pnvm_data, capa); + if (WARN_ON_ONCE(!trans->ops->load_pnvm)) + return -EOPNOTSUPP; + return trans->ops->load_pnvm(trans, pnvm_data, capa); } IWL_EXPORT_SYMBOL(iwl_trans_load_pnvm); void iwl_trans_set_pnvm(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa) { - iwl_trans_pcie_ctx_info_v2_set_pnvm(trans, capa); + if (WARN_ON_ONCE(!trans->ops->set_pnvm)) + return; + trans->ops->set_pnvm(trans, capa); } int iwl_trans_load_reduce_power(struct iwl_trans *trans, const struct iwl_pnvm_image *payloads, const struct iwl_ucode_capabilities *capa) { - return iwl_trans_pcie_ctx_info_v2_load_reduce_power(trans, payloads, - capa); + if (WARN_ON_ONCE(!trans->ops->load_reduce_power)) + return -EOPNOTSUPP; + return trans->ops->load_reduce_power(trans, payloads, capa); } void iwl_trans_set_reduce_power(struct iwl_trans *trans, const struct iwl_ucode_capabilities *capa) { - iwl_trans_pcie_ctx_info_v2_set_reduce_power(trans, capa); + if (WARN_ON_ONCE(!trans->ops->set_reduce_power)) + return; + trans->ops->set_reduce_power(trans, capa); } bool iwl_trans_is_pm_supported(struct iwl_trans *trans) @@ -913,26 +970,39 @@ bool iwl_trans_is_pm_supported(struct iwl_trans *trans) if (WARN_ON(trans->mac_cfg->gen2)) return false; - return iwl_pcie_gen1_is_pm_supported(trans); + if (WARN_ON_ONCE(!trans->ops->is_pm_supported)) + return false; + return trans->ops->is_pm_supported(trans); } IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported); bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans) { - return iwl_pcie_is_ltr_enabled(trans); + if (WARN_ON_ONCE(!trans->ops->is_ltr_enabled)) + return false; + return trans->ops->is_ltr_enabled(trans); } IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled); int iwl_trans_activate_nic(struct iwl_trans *trans) { - return iwl_pcie_activate_nic(trans); + if (WARN_ON_ONCE(!trans->ops->activate_nic)) + return -EOPNOTSUPP; + return trans->ops->activate_nic(trans); } IWL_EXPORT_SYMBOL(iwl_trans_activate_nic); void iwl_trans_reset(struct iwl_trans *trans, enum iwl_reset_mode mode) { - iwl_trans_pcie_reset(trans, mode); + if (!WARN_ON_ONCE(!trans->ops->reset)) + trans->ops->reset(trans, mode); } IWL_EXPORT_SYMBOL(iwl_trans_reset); +void iwl_trans_fw_reset_handshake(struct iwl_trans *trans) +{ + if (!WARN_ON_ONCE(!trans->ops->fw_reset_handshake)) + trans->ops->fw_reset_handshake(trans); +} + diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 719b6c9ba360..5db07f1eab56 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -734,12 +734,15 @@ struct iwl_trans_info { u8 num_rxqs; }; +struct iwl_trans_ops; + /** * struct iwl_trans - transport common data * * @csme_own: true if we couldn't get ownership on the device * @op_mode: pointer to the op_mode * @mac_cfg: the trans-specific configuration part + * @ops: bus-specific transport operations, see &struct iwl_trans_ops * @cfg: pointer to the configuration * @drv: pointer to iwl_drv * @conf: configuration set by the opmode before enter @@ -773,6 +776,7 @@ struct iwl_trans { bool csme_own; struct iwl_op_mode *op_mode; const struct iwl_mac_cfg *mac_cfg; + const struct iwl_trans_ops *ops; const struct iwl_rf_cfg *cfg; struct iwl_drv *drv; struct iwl_trans_config conf; @@ -1146,6 +1150,7 @@ static inline void iwl_trans_finish_sw_reset(struct iwl_trans *trans) *****************************************************/ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, struct device *dev, + const struct iwl_trans_ops *ops, const struct iwl_mac_cfg *mac_cfg); void iwl_trans_free(struct iwl_trans *trans); @@ -1217,7 +1222,150 @@ enum iwl_reset_mode { }; void iwl_trans_reset(struct iwl_trans *trans, enum iwl_reset_mode mode); -void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans); +void iwl_trans_fw_reset_handshake(struct iwl_trans *trans); + +/** + * struct iwl_trans_ops - bus-specific transport operations + * + * Function-pointer table filled in by the bus implementation. Unless noted + * otherwise, each callback implements the identically named iwl_trans_*() + * API, see its documentation. + * + * @op_mode_enter: the op_mode took ownership of the transport + * @start_hw: start the hardware + * @op_mode_leave: the op_mode released the transport + * @send_cmd: send a host command to the firmware + * @alloc_tx_cmd: allocate a device TX command + * @free_tx_cmd: free a device TX command + * @write8: write a byte to a device register + * @write32: write a dword to a device register + * @read32: read a dword from a device register + * @read_prph: read a peripheral register + * @write_prph: write a peripheral register + * @read_mem: read device memory, taking NIC access + * @read_mem_no_grab: read device memory, NIC access already taken + * @set_bits_mask: read-modify-write a device register + * @poll_bits_mask: poll a device register until the masked bits match + * @read_config32: read a dword from the bus configuration space + * @grab_nic_access: keep the NIC awake for register access + * @release_nic_access: release the NIC access taken by @grab_nic_access + * @resched_with_nic_access: reschedule while holding NIC access + * @sw_reset: perform a software reset of the device + * @reset: reset the device, see &enum iwl_reset_mode + * @fw_reset_handshake: do a firmware reset handshake. + * @dump_data: collect a firmware error dump + * @d3_suspend: prepare the device for D3 (WoWLAN) + * @d3_resume: resume the device from D3 (WoWLAN) + * @sync_nmi: trigger an NMI and wait for it to be handled + * @write_imr_mem: write to the IMR memory region + * @fw_alive: Notify trans that the firmware sent the ALIVE notification + * @start_fw: download firmware code to the device and and start the firmware + * @stop_device: stop the device and the firmware + * @tx: transmit an MPDU + * @reclaim: free TX MPDUs up to the given sequence number + * @txq_disable: disable a TX queue (gen1) + * @txq_enable: enable a TX queue (gen1) + * @wait_txq_empty: wait for a single TX queue to become empty + * @wait_txqs_empty: wait for the given TX queues to become empty + * @freeze_txq_timer: freeze/unfreeze the watchdog of the given TX queues + * @txq_set_shared_mode: mark a TX queue as shared between TIDs + * @set_q_ptrs: set the write pointer of a TX queue + * @txq_alloc: allocate a TX queue (gen2) + * @txq_free: free a TX queue allocated by @txq_alloc + * @rxq_dma_data: get the DMA addresses of an RX queue + * @load_pnvm: load the PNVM image + * @set_pnvm: tell the firmware to use the loaded PNVM + * @load_reduce_power: load the reduced power table + * @set_reduce_power: tell the firmware to use the reduced power table + * @is_pm_supported: whether bus power management is supported + * @is_ltr_enabled: whether LTR is enabled on the bus + * @activate_nic: bring the NIC out of low power and make it accessible + */ +struct iwl_trans_ops { + void (*op_mode_enter)(struct iwl_trans *trans); + int (*start_hw)(struct iwl_trans *trans); + void (*op_mode_leave)(struct iwl_trans *trans); + + int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); + struct iwl_device_tx_cmd *(*alloc_tx_cmd)(struct iwl_trans *trans); + void (*free_tx_cmd)(struct iwl_trans *trans, + struct iwl_device_tx_cmd *dev_cmd); + + void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); + void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); + u32 (*read32)(struct iwl_trans *trans, u32 ofs); + u32 (*read_prph)(struct iwl_trans *trans, u32 ofs); + void (*write_prph)(struct iwl_trans *trans, u32 ofs, u32 val); + int (*read_mem)(struct iwl_trans *trans, u32 addr, + void *buf, int dwords); + int (*read_mem_no_grab)(struct iwl_trans *trans, u32 addr, + void *buf, u32 dwords); + void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, + u32 mask, u32 value); + int (*poll_bits_mask)(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout); + int (*read_config32)(struct iwl_trans *trans, u32 ofs, u32 *val); + bool (*grab_nic_access)(struct iwl_trans *trans); + void (*release_nic_access)(struct iwl_trans *trans); + void (*resched_with_nic_access)(struct iwl_trans *trans); + + int (*sw_reset)(struct iwl_trans *trans, bool retake_ownership); + void (*reset)(struct iwl_trans *trans, enum iwl_reset_mode mode); + void (*fw_reset_handshake)(struct iwl_trans *trans); + + struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans, + u32 dump_mask, + const struct iwl_dump_sanitize_ops *sanitize_ops, + void *sanitize_ctx); + int (*d3_suspend)(struct iwl_trans *trans, bool reset); + int (*d3_resume)(struct iwl_trans *trans, bool reset); + + void (*sync_nmi)(struct iwl_trans *trans); + int (*write_imr_mem)(struct iwl_trans *trans, u32 dst_addr, + u64 src_addr, u32 byte_cnt); + + void (*fw_alive)(struct iwl_trans *trans); + int (*start_fw)(struct iwl_trans *trans, const struct iwl_fw *fw, + const struct fw_img *img, bool run_in_rfkill); + void (*stop_device)(struct iwl_trans *trans); + + int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, + struct iwl_device_tx_cmd *dev_cmd, int queue); + void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, + struct sk_buff_head *skbs, bool is_flush); + void (*txq_disable)(struct iwl_trans *trans, int queue, + bool configure_scd); + bool (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, + const struct iwl_trans_txq_scd_cfg *cfg, + unsigned int queue_wdg_timeout); + int (*wait_txq_empty)(struct iwl_trans *trans, int queue); + int (*wait_txqs_empty)(struct iwl_trans *trans, u32 txqs); + void (*freeze_txq_timer)(struct iwl_trans *trans, + unsigned long txqs, bool freeze); + void (*txq_set_shared_mode)(struct iwl_trans *trans, u32 txq_id, + bool shared_mode); + void (*set_q_ptrs)(struct iwl_trans *trans, int queue, int ptr); + int (*txq_alloc)(struct iwl_trans *trans, u32 flags, u32 sta_mask, + u8 tid, int size, unsigned int wdg_timeout); + void (*txq_free)(struct iwl_trans *trans, int queue); + int (*rxq_dma_data)(struct iwl_trans *trans, int queue, + struct iwl_trans_rxq_dma_data *data); + + int (*load_pnvm)(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data, + const struct iwl_ucode_capabilities *capa); + void (*set_pnvm)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); + int (*load_reduce_power)(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_reduce_power)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); + + bool (*is_pm_supported)(struct iwl_trans *trans); + bool (*is_ltr_enabled)(struct iwl_trans *trans); + int (*activate_nic)(struct iwl_trans *trans); +}; /* Internal helper */ static inline void iwl_trans_set_info(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index fab73693e683..01bfc1492c84 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -31,6 +31,9 @@ u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs); u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg); void iwl_pcie_write_prph_no_grab(struct iwl_trans *trans, u32 addr, u32 val); +/* bus-specific transport operations table */ +extern const struct iwl_trans_ops iwl_trans_pcie_ops; + /* * RX related structures and functions */ @@ -1148,7 +1151,7 @@ int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, int iwl_trans_pcie_read_mem_no_grab(struct iwl_trans *trans, u32 addr, void *buf, u32 dwords); int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership); -void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode); +void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans); struct iwl_trans_dump_data * iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask, const struct iwl_dump_sanitize_ops *sanitize_ops, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 59e9ef0d6b51..c905b6d5db3d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1288,6 +1288,10 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, bool hw_rfkill; int ret; + if (trans->mac_cfg->gen2) + return iwl_trans_pcie_gen2_start_fw(trans, fw, img, + run_in_rfkill); + /* This may fail if AMT took ownership of the device */ if (iwl_pcie_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); @@ -1370,6 +1374,11 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, void iwl_trans_pcie_fw_alive(struct iwl_trans *trans) { + if (trans->mac_cfg->gen2) { + iwl_trans_pcie_gen2_fw_alive(trans); + return; + } + iwl_pcie_reset_ict(trans); iwl_pcie_tx_start(trans); } @@ -1408,6 +1417,11 @@ void iwl_trans_pcie_stop_device(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); bool was_in_rfkill; + if (trans->mac_cfg->gen2) { + iwl_trans_pcie_gen2_stop_device(trans); + return; + } + iwl_op_mode_time_point(trans->op_mode, IWL_FW_INI_TIME_POINT_HOST_DEVICE_DISABLE, NULL); @@ -1846,6 +1860,11 @@ void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + if (trans->mac_cfg->gen2) { + iwl_trans_pcie_gen2_op_mode_leave(trans); + return; + } + mutex_lock(&trans_pcie->mutex); /* disable interrupts - don't enable HW RF kill interrupt */ @@ -2274,7 +2293,7 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk) module_put(THIS_MODULE); } -void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode) +static void iwl_trans_pcie_reset(struct iwl_trans *trans, enum iwl_reset_mode mode) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie_removal *removal; @@ -2684,6 +2703,23 @@ void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, spin_unlock_bh(&trans_pcie->reg_lock); } +#define IWL_POLL_INTERVAL 10 /* microseconds */ + +static int iwl_trans_pcie_poll_bits_mask(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int t = 0; + + do { + if ((iwl_trans_pcie_read32(trans, addr) & mask) == (bits & mask)) + return 0; + udelay(IWL_POLL_INTERVAL); + t += IWL_POLL_INTERVAL; + } while (t < timeout); + + return -ETIMEDOUT; +} + static const char *get_csr_string(int cmd) { #define IWL_CMD(x) case x: return #x @@ -3659,6 +3695,67 @@ static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans) return 0; } +const struct iwl_trans_ops iwl_trans_pcie_ops = { + .op_mode_enter = iwl_trans_pcie_op_mode_enter, + .start_hw = iwl_trans_pcie_start_hw, + .op_mode_leave = iwl_trans_pcie_op_mode_leave, + + .send_cmd = iwl_trans_pcie_send_hcmd, + .alloc_tx_cmd = iwl_pcie_alloc_tx_cmd, + .free_tx_cmd = iwl_pcie_free_tx_cmd, + + .write8 = iwl_trans_pcie_write8, + .write32 = iwl_trans_pcie_write32, + .read32 = iwl_trans_pcie_read32, + .read_prph = iwl_trans_pcie_read_prph, + .write_prph = iwl_pcie_write_prph_no_grab, + .read_mem = iwl_trans_pcie_read_mem, + .read_mem_no_grab = iwl_trans_pcie_read_mem_no_grab, + .set_bits_mask = iwl_trans_pcie_set_bits_mask, + .poll_bits_mask = iwl_trans_pcie_poll_bits_mask, + .read_config32 = iwl_trans_pcie_read_config32, + .grab_nic_access = iwl_trans_pcie_grab_nic_access, + .release_nic_access = iwl_trans_pcie_release_nic_access, + .resched_with_nic_access = iwl_trans_pcie_resched_with_nic_access, + + .sw_reset = iwl_trans_pcie_sw_reset, + .reset = iwl_trans_pcie_reset, + .fw_reset_handshake = iwl_trans_pcie_fw_reset_handshake, + + .dump_data = iwl_trans_pcie_dump_data, + .d3_suspend = iwl_trans_pcie_d3_suspend, + .d3_resume = iwl_trans_pcie_d3_resume, + + .sync_nmi = iwl_trans_pcie_sync_nmi, + .write_imr_mem = iwl_trans_pcie_copy_imr, + + .fw_alive = iwl_trans_pcie_fw_alive, + .start_fw = iwl_trans_pcie_start_fw, + .stop_device = iwl_trans_pcie_stop_device, + + .tx = iwl_trans_pcie_tx, + .reclaim = iwl_pcie_reclaim, + .txq_disable = iwl_trans_pcie_txq_disable, + .txq_enable = iwl_trans_pcie_txq_enable, + .wait_txq_empty = iwl_trans_pcie_wait_txq_empty, + .wait_txqs_empty = iwl_trans_pcie_wait_txqs_empty, + .freeze_txq_timer = iwl_pcie_freeze_txq_timer, + .txq_set_shared_mode = iwl_trans_pcie_txq_set_shared_mode, + .set_q_ptrs = iwl_pcie_set_q_ptrs, + .txq_alloc = iwl_txq_dyn_alloc, + .txq_free = iwl_txq_dyn_free, + .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, + + .load_pnvm = iwl_trans_pcie_ctx_info_v2_load_pnvm, + .set_pnvm = iwl_trans_pcie_ctx_info_v2_set_pnvm, + .load_reduce_power = iwl_trans_pcie_ctx_info_v2_load_reduce_power, + .set_reduce_power = iwl_trans_pcie_ctx_info_v2_set_reduce_power, + + .is_pm_supported = iwl_pcie_gen1_is_pm_supported, + .is_ltr_enabled = iwl_pcie_is_ltr_enabled, + .activate_nic = iwl_pcie_activate_nic, +}; + static struct iwl_trans * iwl_trans_pcie_alloc(struct pci_dev *pdev, const struct iwl_mac_cfg *mac_cfg, @@ -3670,7 +3767,7 @@ iwl_trans_pcie_alloc(struct pci_dev *pdev, int ret, addr_size; trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, - mac_cfg); + &iwl_trans_pcie_ops, mac_cfg); if (!trans) return ERR_PTR(-ENOMEM); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index d612678ae122..0c29fb6b9ca7 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -2147,6 +2147,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, u16 wifi_seq; bool amsdu; + if (trans->mac_cfg->gen2) + return iwl_txq_gen2_tx(trans, skb, dev_cmd, txq_id); + txq = trans_pcie->txqs.txq[txq_id]; if (WARN_ONCE(!test_bit(txq_id, trans_pcie->txqs.queue_used), From 6a972f26b7ddb8ddeac3b2f20db1c30d1f8c027b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 30 Sep 2026 12:19:52 +0300 Subject: [PATCH 075/104] wifi: iwlwifi: mld: remove unused fields from the firmware API ENABLE_STORE_BEACON is not defined in the firmware API and is never set by the driver. STA_CONFIG_CMD's trig_rnd_alloc was never used by the firmware either. Remove both. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260930121740.157e71ac8641.Iac2bd1f57b2c4bbdfe33efab31111a7de02bdf16@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/d3.h | 3 +-- drivers/net/wireless/intel/iwlwifi/mld/sta.c | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index d3bed0216df4..9f7407c4f980 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2025 Intel Corporation + * Copyright (C) 2012-2014, 2018-2026 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH */ @@ -366,7 +366,6 @@ enum iwl_wowlan_flags { ENABLE_L3_FILTERING = BIT(1), ENABLE_NBNS_FILTERING = BIT(2), ENABLE_DHCP_FILTERING = BIT(3), - ENABLE_STORE_BEACON = BIT(4), HAS_BEACON_PROTECTION = BIT(5), }; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/sta.c b/drivers/net/wireless/intel/iwlwifi/mld/sta.c index 7957ac11b0cd..97f013330f06 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/sta.c @@ -465,8 +465,8 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta); struct iwl_sta_cfg_cmd cmd = {}; int fw_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta); - bool is_6ghz, uora_exists; u32 link_mask; + bool is_6ghz; lockdep_assert_wiphy(mld->wiphy); @@ -479,7 +479,6 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, return -EINVAL; is_6ghz = false; - uora_exists = false; link_mask = iwl_mld_get_nan_link_mask(mld); } else { @@ -495,7 +494,6 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, link_mask = BIT(mld_link->fw_id); is_6ghz = link->chanreq.oper.chan->band == NL80211_BAND_6GHZ; - uora_exists = link->uora_exists; } cmd.sta_id = cpu_to_le32(fw_id); @@ -554,9 +552,6 @@ int iwl_mld_add_modify_sta_cmd(struct iwl_mld *mld, } if (link_sta->he_cap.has_he) { - cmd.trig_rnd_alloc = - cpu_to_le32(uora_exists ? 1 : 0); - /* PPE Thresholds */ iwl_mld_fill_pkt_ext(mld, link_sta, &cmd.pkt_ext); From 0dc7a804a45828503e3707d7f2c3a298ef7a4647 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 1 Oct 2026 16:20:14 +0300 Subject: [PATCH 076/104] wifi: iwlwifi: mld: add STA_CONFIG_CMD version 4 Version 4 replaces the unused trig_rnd_alloc field with cip_defer and epp_robust: - cip_defer tells the firmware to delay the usage of the unicast control frame protection key until after association. - epp_robust tells the firmware that EPP robust individually addressed management frame support was negotiated, so that the protected action categories are used for specific unicast action frames. Add the matching EPP_ROBUST_CONNECTION flag to the WoWLAN config command flags for the D3 path. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20261001161715.b62474b1ccef.I51756391283ec42a40dd38a3586ad89759fb82d1@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/api/d3.h | 1 + .../net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 9f7407c4f980..a0379aca99d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -366,6 +366,7 @@ enum iwl_wowlan_flags { ENABLE_L3_FILTERING = BIT(1), ENABLE_NBNS_FILTERING = BIT(2), ENABLE_DHCP_FILTERING = BIT(3), + EPP_ROBUST_CONNECTION = BIT(4), HAS_BEACON_PROTECTION = BIT(5), }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 9579e691cc87..6e536f48acdb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -940,8 +940,13 @@ struct iwl_sta_cfg_cmd_v2 { * @mimo_protection: indicates whether the sta uses mimo protection or not * @ack_enabled: indicates that the AP supports receiving ACK- * enabled AGG, i.e. both BACK and non-BACK frames in a single AGG - * @trig_rnd_alloc: indicates that trigger based random allocation - * is enabled according to UORA element existence + * @cip_defer: delay the usage of the unicast control frame protection until + * after association. + * Only supported from command version 4, must be left cleared otherwise. + * @epp_robust: indicates that EPP robust individually addressed management + * frame support was negotiated during association. + * Only supported from command version 4, must be left cleared otherwise. + * @reserved1: Reserved for alignment * @tx_ampdu_spacing: minimum A-MPDU spacing: * 4 - 2us density, 5 - 4us density, 6 - 8us density, 7 - 16us density * @tx_ampdu_max_size: maximum A-MPDU length: 0 - 8K, 1 - 16K, 2 - 32K, @@ -979,7 +984,9 @@ struct iwl_sta_cfg_cmd { __le32 mimo; __le32 mimo_protection; __le32 ack_enabled; - __le32 trig_rnd_alloc; + u8 cip_defer; + u8 epp_robust; + __le16 reserved1; __le32 tx_ampdu_spacing; __le32 tx_ampdu_max_size; __le32 sp_length; @@ -996,7 +1003,7 @@ struct iwl_sta_cfg_cmd { u8 nmi_sta_id; u8 ndi_local_addr[ETH_ALEN]; u8 reserved[2]; -} __packed; /* STA_CMD_API_S_VER_3 */ +} __packed; /* STA_CMD_API_S_VER_3, STA_CMD_API_S_VER_4 */ /** * struct iwl_aux_sta_cmd - command for AUX STA configuration From 0b5f2164ceaad36b68c868fc9d079b4b0475b006 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:15 +0300 Subject: [PATCH 077/104] wifi: iwlwifi: mld: add UHR sniffer support Add UHR sniffer support as supported by the hardware. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.a1e1090ec775.I47fb568ddcd9d6aca634400b2d4850c1fef035ca@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 593 +++++++++++++++++++- 1 file changed, 573 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 8fa438fd7815..1362e3ad97b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -944,8 +944,8 @@ static void iwl_mld_decode_eht_usig(struct iwl_mld_rx_phy_data *phy_data, } static void -iwl_mld_eht_set_ru_alloc(struct ieee80211_rx_status *rx_status, - u32 ru_with_p80) +iwl_mld_eht_uhr_set_ru_alloc(struct ieee80211_rx_status *rx_status, + u32 ru_with_p80, bool uhr) { enum nl80211_eht_ru_alloc nl_ru; u32 ru = ru_with_p80 >> 1; @@ -1011,7 +1011,15 @@ iwl_mld_eht_set_ru_alloc(struct ieee80211_rx_status *rx_status, } rx_status->bw = RATE_INFO_BW_EHT_RU; - rx_status->eht.ru = nl_ru; + + /* + * This should get optimised away, but since it's bitfields, + * we can't ensure uhr.ru and eht.ru overlap in the union. + */ + if (uhr) + rx_status->uhr.ru = nl_ru; + else + rx_status->eht.ru = nl_ru; } static void iwl_mld_decode_eht_tb(struct iwl_mld_rx_phy_data *phy_data, @@ -1051,9 +1059,10 @@ static void iwl_mld_decode_eht_tb(struct iwl_mld_rx_phy_data *phy_data, OFDM_UCODE_TRIG_BASE_RX_RU_P80, IEEE80211_RADIOTAP_EHT_DATA1_PRIMARY_80); - iwl_mld_eht_set_ru_alloc(rx_status, - le32_get_bits(phy_data->ntfy->sigs.eht_tb.tb_rx1, - OFDM_UCODE_TRIG_BASE_RX_RU)); + iwl_mld_eht_uhr_set_ru_alloc(rx_status, + le32_get_bits(phy_data->ntfy->sigs.eht_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_RU), + false); } static void iwl_mld_eht_decode_user_ru(struct iwl_mld_rx_phy_data *phy_data, @@ -1209,9 +1218,10 @@ static void iwl_mld_decode_eht_non_tb(struct iwl_mld_rx_phy_data *phy_data, iwl_mld_eht_decode_user_ru(phy_data, eht); - iwl_mld_eht_set_ru_alloc(rx_status, - le32_get_bits(phy_data->ntfy->sigs.eht.b2, - OFDM_RX_FRAME_EHT_STA_RU)); + iwl_mld_eht_uhr_set_ru_alloc(rx_status, + le32_get_bits(phy_data->ntfy->sigs.eht.b2, + OFDM_RX_FRAME_EHT_STA_RU), + false); if (phy_data->with_data) eht->user_info[0] |= @@ -1317,7 +1327,7 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, eht->user_info[0] |= le32_encode_bits(u32_get_bits(rate_n_flags, - RATE_VHT_MCS_RATE_CODE_MSK), + RATE_MCS_CODE_MSK), IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) | le32_encode_bits(u32_get_bits(rate_n_flags, RATE_MCS_NSS_MSK), @@ -1331,6 +1341,526 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, iwl_mld_decode_eht_phy_data(phy_data, rx_status, eht); } +static void iwl_mld_decode_uhr_usig_tb(struct iwl_mld_rx_phy_data *phy_data, + struct ieee80211_radiotap_eht_usig *usig) +{ + __le32 usig_a1 = phy_data->ntfy->sigs.uhr_tb.usig_a1; + __le32 usig_a2 = phy_data->ntfy->sigs.uhr_tb.usig_a2_uhr; + + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1, + OFDM_RX_FRAME_EHT_USIG1_DISREGARD | + OFDM_RX_FRAME_EHT_USIG1_VALIDATE, + IEEE80211_RADIOTAP_UHR_USIG1_TB_B20_B25_DISREGARD); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_PPDU_TYPE, + IEEE80211_RADIOTAP_UHR_USIG2_TB_B0_B1_PPDU_TYPE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B2_COBF_COSR, + IEEE80211_RADIOTAP_UHR_USIG2_TB_B2_VALIDATE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_1, + IEEE80211_RADIOTAP_UHR_USIG2_TB_B3_B6_SPATIAL_REUSE_1); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_2, + IEEE80211_RADIOTAP_UHR_USIG2_TB_B7_B10_SPATIAL_REUSE_2); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_TRIG_USIG2_DISREGARD, + IEEE80211_RADIOTAP_UHR_USIG2_TB_B11_B15_DISREGARD); + + if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) && + le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8)) + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK); + + if (!le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG_CRC_OK)) + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC); +} + +static void iwl_mld_decode_uhr_usig_elr(struct iwl_mld_rx_phy_data *phy_data, + struct ieee80211_radiotap_eht_usig *usig) +{ + __le32 usig_a1 = phy_data->ntfy->sigs.uhr_elr.usig_a1; + __le32 usig_a2 = phy_data->ntfy->sigs.uhr_elr.usig_a2_uhr_elr; + + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1, + OFDM_RX_FRAME_EHT_USIG1_DISREGARD, + IEEE80211_RADIOTAP_UHR_USIG1_ELR_B20_B24_DISREGARD); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1, + OFDM_RX_FRAME_EHT_USIG1_VALIDATE, + IEEE80211_RADIOTAP_UHR_USIG1_ELR_B25_VALIDATE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_VECTOR_UHR_ELR_PPDU_TYPE, + IEEE80211_RADIOTAP_UHR_USIG2_ELR_B0_B1_PPDU_TYPE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_VECTOR_UHR_ELR_USIG_STA_ID, + IEEE80211_RADIOTAP_UHR_USIG2_ELR_B2_B12_STA_ID); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_VECTOR_UHR_ELR_VALIDATE, + IEEE80211_RADIOTAP_UHR_USIG2_ELR_B13_B15_VALIDATE); + + if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) && + le32_get_bits(usig_a2, OFDM_RX_VECTOR_UHR_ELR_VALIDATE) == 0xe) + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK); + + if (!le32_get_bits(usig_a2, OFDM_RX_VECTOR_UHR_ELR_CRC_OK)) + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC); +} + +static void iwl_mld_decode_uhr_usig_non_tb(struct iwl_mld_rx_phy_data *phy_data, + struct ieee80211_radiotap_eht_usig *usig) +{ + __le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1; + __le32 usig_a2 = phy_data->ntfy->sigs.uhr.usig_a2_uhr; + + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1, + OFDM_RX_FRAME_EHT_USIG1_DISREGARD, + IEEE80211_RADIOTAP_UHR_USIG1_MU_B20_B24_DISREGARD); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a1, + OFDM_RX_FRAME_EHT_USIG1_VALIDATE, + IEEE80211_RADIOTAP_UHR_USIG1_MU_B25_VALIDATE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_PPDU_TYPE, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B0_B1_PPDU_TYPE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_COBF_CSR_DISABLE, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B2_COBF_COSR); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_PUNC_CHANNEL, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B3_B7_PUNCTURED_INFO); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B8_VALIDATE); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_SIG_MCS, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B9_B10_SIG_MCS); + IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, + OFDM_RX_FRAME_UHR_SIG_SYM_NUM, + IEEE80211_RADIOTAP_UHR_USIG2_MU_B11_B15_UHR_SIG_SYMBOLS); + + if (le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_USIG1_VALIDATE) && + le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG2_VALIDATE_B8)) + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_OK); + + if (!le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_USIG_CRC_OK)) + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC); +} + +static void iwl_mld_decode_uhr_usig(struct iwl_mld_rx_phy_data *phy_data, + struct sk_buff *skb) +{ + u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK; + struct ieee80211_radiotap_eht_usig *usig; + __le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1; + u32 bw; + + usig = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG, + sizeof(*usig)); + + BUILD_BUG_ON(offsetof(typeof(phy_data->ntfy->sigs.uhr), usig_a1) != + offsetof(typeof(phy_data->ntfy->sigs.uhr_elr), usig_a1)); + BUILD_BUG_ON(offsetof(typeof(phy_data->ntfy->sigs.uhr), usig_a1) != + offsetof(typeof(phy_data->ntfy->sigs.uhr_tb), usig_a1)); + + usig->common |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL_KNOWN | + IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR_KNOWN | + IEEE80211_RADIOTAP_EHT_USIG_COMMON_VALIDATE_BITS_CHECKED | + IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_KNOWN | + IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP_KNOWN | + IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER_KNOWN); + +#define CHECK_BW(bw) \ + BUILD_BUG_ON(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_ ## bw ## MHZ != \ + RATE_MCS_CHAN_WIDTH_ ## bw ## _VAL) + CHECK_BW(20); + CHECK_BW(40); + CHECK_BW(80); + CHECK_BW(160); +#undef CHECK_BW + BUILD_BUG_ON(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW_320MHZ_1 != + RATE_MCS_CHAN_WIDTH_320_VAL); + bw = u32_get_bits(phy_data->rate_n_flags, RATE_MCS_CHAN_WIDTH_MSK); + /* specific handling for 320MHz-1/320MHz-2 */ + if (bw == RATE_MCS_CHAN_WIDTH_320_VAL) + bw += le32_get_bits(usig_a1, OFDM_RX_FRAME_EHT_BW320_SLOT); + usig->common |= le32_encode_bits(bw, + IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW); + + usig->common |= LE32_DEC_ENC(usig_a1, OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG, + IEEE80211_RADIOTAP_EHT_USIG_COMMON_UL_DL); + usig->common |= LE32_DEC_ENC(usig_a1, OFDM_RX_FRAME_ENHANCED_WIFI_BSS_COLOR, + IEEE80211_RADIOTAP_EHT_USIG_COMMON_BSS_COLOR); + usig->common |= LE32_DEC_ENC(usig_a1, + OFDM_RX_FRAME_ENHANCED_WIFI_TXOP_DURATION, + IEEE80211_RADIOTAP_EHT_USIG_COMMON_TXOP); + usig->common |= LE32_DEC_ENC(usig_a1, + OFDM_RX_FRAME_ENHANCED_WIFI_VER_ID, + IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER); + + switch (he_type) { + case RATE_MCS_HE_TYPE_TRIG: + iwl_mld_decode_uhr_usig_tb(phy_data, usig); + break; + case RATE_MCS_HE_TYPE_UHR_ELR: + iwl_mld_decode_uhr_usig_elr(phy_data, usig); + break; + default: + iwl_mld_decode_uhr_usig_non_tb(phy_data, usig); + break; + } +} + +static void iwl_mld_decode_uhr_tb(struct iwl_mld_rx_phy_data *phy_data, + struct ieee80211_rx_status *rx_status, + struct ieee80211_radiotap_uhr *uhr) +{ + if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_TB_RX)) + return; + + uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT | + IEEE80211_RADIOTAP_UHR_KNOWN_LDPC_EXTRA_SYMBOL_SEGMENT | + IEEE80211_RADIOTAP_UHR_KNOWN_PRE_FEC_PADDING_FACTOR | + IEEE80211_RADIOTAP_UHR_KNOWN_PE_DISAMBIGUITY | + IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_UHR_LTF_SYMBOLS | + IEEE80211_RADIOTAP_UHR_KNOWN_PRI80_CHAN_POS); + + uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx0, + OFDM_UCODE_TRIG_BASE_PS160, + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160); + uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_RU, + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B0 | + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B7_B1); + uhr->data[8] |= le32_encode_bits(!le32_get_bits(phy_data->ntfy->sigs.uhr_tb.tb_rx0, + OFDM_UCODE_RX_IS_DRU), + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_INDICATION); + + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_CODING_EXTRA_SYM, + IEEE80211_RADIOTAP_UHR_DATA0_LDPC_EXTRA_SYMBOL_SEGMENT); + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_PRE_FEC_PAD_FACTOR, + IEEE80211_RADIOTAP_UHR_DATA0_PRE_FEC_PADDING_FACTOR); + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_PE_DISAMBIG, + IEEE80211_RADIOTAP_UHR_DATA0_PE_DISAMBIGUITY); + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_NUM_OF_LTF_SYM, + IEEE80211_RADIOTAP_UHR_DATA0_NUMBER_OF_LTF_SYMBOLS); + uhr->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr_tb.tb_rx0, + OFDM_UCODE_TRIG_BASE_RX_RU_P80, + IEEE80211_RADIOTAP_UHR_DATA1_PRI80_CHAN_POS); + + iwl_mld_eht_uhr_set_ru_alloc(rx_status, + le32_get_bits(phy_data->ntfy->sigs.uhr_tb.tb_rx1, + OFDM_UCODE_TRIG_BASE_RX_RU), + true); +} + +static void iwl_mld_uhr_decode_user_ru(struct iwl_mld_rx_phy_data *phy_data, + struct ieee80211_radiotap_uhr *uhr) +{ + u32 phy_bw = phy_data->rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK; + + if (!(phy_data->ntfy->flags & IWL_SNIF_FLAG_VALID_RU)) + return; + +#define __IWL_MLD_ENC_UHR_RU(rt_data, rt_ru, fw_data, fw_ru) \ + uhr->data[(rt_data)] |= \ + (cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru ## _KNOWN) | \ + LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.cmn[fw_data], \ + OFDM_RX_FRAME_EHT_RU_ALLOC_ ## fw_data ## _ ## fw_ru, \ + IEEE80211_RADIOTAP_UHR_DATA ## rt_data ## _RU_ALLOC_CC_ ## rt_ru)) + +#define _IWL_MLD_ENC_UHR_RU(rt_data, rt_ru, fw_data, fw_ru) \ + __IWL_MLD_ENC_UHR_RU(rt_data, rt_ru, fw_data, fw_ru) + +#define IEEE80211_RADIOTAP_RU_DATA_1_1_1 1 +#define IEEE80211_RADIOTAP_RU_DATA_2_1_1 2 +#define IEEE80211_RADIOTAP_RU_DATA_1_1_2 2 +#define IEEE80211_RADIOTAP_RU_DATA_2_1_2 2 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_1 3 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_1 3 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_2 3 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_2 4 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_3 4 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_3 4 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_4 5 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_4 5 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_5 5 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_5 6 +#define IEEE80211_RADIOTAP_RU_DATA_1_2_6 6 +#define IEEE80211_RADIOTAP_RU_DATA_2_2_6 6 + +#define IWL_RX_RU_DATA_A1 0 +#define IWL_RX_RU_DATA_A2 0 +#define IWL_RX_RU_DATA_A3 0 +#define IWL_RX_RU_DATA_A4 4 +#define IWL_RX_RU_DATA_B1 1 +#define IWL_RX_RU_DATA_B2 1 +#define IWL_RX_RU_DATA_B3 1 +#define IWL_RX_RU_DATA_B4 4 +#define IWL_RX_RU_DATA_C1 2 +#define IWL_RX_RU_DATA_C2 2 +#define IWL_RX_RU_DATA_C3 2 +#define IWL_RX_RU_DATA_C4 5 +#define IWL_RX_RU_DATA_D1 3 +#define IWL_RX_RU_DATA_D2 3 +#define IWL_RX_RU_DATA_D3 3 +#define IWL_RX_RU_DATA_D4 5 + +#define IWL_MLD_ENC_UHR_RU(rt_ru, fw_ru) \ + _IWL_MLD_ENC_UHR_RU(IEEE80211_RADIOTAP_RU_DATA_ ## rt_ru, \ + rt_ru, \ + IWL_RX_RU_DATA_ ## fw_ru, \ + fw_ru) + + /* + * Hardware labels the content channels/RU allocation values + * as follows: + * + * Content Channel 1 Content Channel 2 + * 20 MHz: A1 + * 40 MHz: A1 B1 + * 80 MHz: A1 C1 B1 D1 + * 160 MHz: A1 C1 A2 C2 B1 D1 B2 D2 + * 320 MHz: A1 C1 A2 C2 A3 C3 A4 C4 B1 D1 B2 D2 B3 D3 B4 D4 + */ + + switch (phy_bw) { + case RATE_MCS_CHAN_WIDTH_320: + /* content channel 1 */ + IWL_MLD_ENC_UHR_RU(1_2_3, A3); + IWL_MLD_ENC_UHR_RU(1_2_4, C3); + IWL_MLD_ENC_UHR_RU(1_2_5, A4); + IWL_MLD_ENC_UHR_RU(1_2_6, C4); + /* content channel 2 */ + IWL_MLD_ENC_UHR_RU(2_2_3, B3); + IWL_MLD_ENC_UHR_RU(2_2_4, D3); + IWL_MLD_ENC_UHR_RU(2_2_5, B4); + IWL_MLD_ENC_UHR_RU(2_2_6, D4); + fallthrough; + case RATE_MCS_CHAN_WIDTH_160: + /* content channel 1 */ + IWL_MLD_ENC_UHR_RU(1_2_1, A2); + IWL_MLD_ENC_UHR_RU(1_2_2, C2); + /* content channel 2 */ + IWL_MLD_ENC_UHR_RU(2_2_1, B2); + IWL_MLD_ENC_UHR_RU(2_2_2, D2); + fallthrough; + case RATE_MCS_CHAN_WIDTH_80: + /* content channel 1 */ + IWL_MLD_ENC_UHR_RU(1_1_2, C1); + /* content channel 2 */ + IWL_MLD_ENC_UHR_RU(2_1_2, D1); + fallthrough; + case RATE_MCS_CHAN_WIDTH_40: + /* content channel 2 */ + IWL_MLD_ENC_UHR_RU(2_1_1, B1); + fallthrough; + case RATE_MCS_CHAN_WIDTH_20: + /* content channel 1 */ + IWL_MLD_ENC_UHR_RU(1_1_1, A1); + break; + } +} + +static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data, + struct ieee80211_rx_status *rx_status, + struct ieee80211_radiotap_uhr *uhr) +{ + __le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1; + __le32 usig_a2 = phy_data->ntfy->sigs.uhr.usig_a2_uhr; + + uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_SPATIAL_REUSE | + /* All RU allocating size/index is in TB format */ + IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT | + IEEE80211_RADIOTAP_UHR_KNOWN_LDPC_EXTRA_SYMBOL_SEGMENT | + IEEE80211_RADIOTAP_UHR_KNOWN_PRE_FEC_PADDING_FACTOR | + IEEE80211_RADIOTAP_UHR_KNOWN_PE_DISAMBIGUITY | + IEEE80211_RADIOTAP_UHR_KNOWN_PRI80_CHAN_POS | + IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_NON_OFDMA_USERS | + IEEE80211_RADIOTAP_UHR_KNOWN_INTERFERENCE_MITIGATION); + + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_SPATIAL_REUSE, + IEEE80211_RADIOTAP_UHR_DATA0_SPATIAL_REUSE); + uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_STA_RU_PS160, + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160); + uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_STA_RU, + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B0 | + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B7_B1); + /* downlink is never DRU */ + uhr->data[8] |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_INDICATION); + + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_CODING_EXTRA_SYM, + IEEE80211_RADIOTAP_UHR_DATA0_LDPC_EXTRA_SYMBOL_SEGMENT); + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_PE_A_FACTOR, + IEEE80211_RADIOTAP_UHR_DATA0_PRE_FEC_PADDING_FACTOR); + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_PE_DISAMBIGUITY, + IEEE80211_RADIOTAP_UHR_DATA0_PE_DISAMBIGUITY); + uhr->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_STA_RU_P80, + IEEE80211_RADIOTAP_UHR_DATA1_PRI80_CHAN_POS); + uhr->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_NUM_OF_USERS, + IEEE80211_RADIOTAP_UHR_DATA7_NUMBER_OF_NON_OFDMA_USERS); + + uhr->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_IM_DISABLE, + IEEE80211_RADIOTAP_UHR_DATA7_INTERFERENCE_MITIGATION); + + iwl_mld_uhr_decode_user_ru(phy_data, uhr); + + iwl_mld_eht_uhr_set_ru_alloc(rx_status, + le32_get_bits(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_STA_RU), + true); + + if (!phy_data->with_data) + return; + + uhr->user[0].known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_STA_ID); + uhr->user[0].info |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.user_id, + OFDM_RX_FRAME_UHR_USER_FIELD_ID, + IEEE80211_RADIOTAP_UHR_USER_INFO_STA_ID); + + /* don't report UEQM for downlink non-OFDMA MU-MIMO allocations */ + if (!(usig_a1 & cpu_to_le32(OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG)) && + le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_PPDU_TYPE) == 2) + return; + + uhr->user[0].known |= + cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_UEQM); + uhr->user[0].info |= + LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_UEQM, + IEEE80211_RADIOTAP_UHR_USER_INFO_UEQM); + + if (uhr->user[0].info & cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_UEQM)) { + uhr->user[0].known |= + cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_UEQM_PATTERN); + uhr->user[0].info |= + LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_UEQM_PATTERN, + IEEE80211_RADIOTAP_UHR_USER_INFO_UEQM_PATTERN); + } +} + +static void +iwl_mld_decode_uhr_elr_phy_data(struct iwl_mld_rx_phy_data *phy_data, + struct sk_buff *skb, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_radiotap_uhr_elr *elr; + __le32 elr1 = phy_data->ntfy->sigs.uhr_elr.uhr_sig_elr1; + __le32 elr2 = phy_data->ntfy->sigs.uhr_elr.uhr_sig_elr2; + + elr = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_UHR_ELR, + sizeof(*elr)); + + elr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_ELR_KNOWN_VERSION_ID | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_UL_DL | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_MCS | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_CODING | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_LENGTH | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_LDPC_EXTRA_OFDM_SYM | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_STA_ID | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_DISREGARD | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_SIG_1_CRC_CHECKED | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_SIG_2_CRC_CHECKED | + IEEE80211_RADIOTAP_UHR_ELR_KNOWN_MARK_BSS_COLOR); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_VER_ID, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_VERSION_ID); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_UPLINK_FLAG, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_UL_DL); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_MCS, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_MCS); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_CODING, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_CODING); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_LENGTH_IN_SYM, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_LENGTH); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_CODING_EXTRA_SYM, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_LDPC_EXTRA_OFDM_SYM); + elr->sig1 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_SIG1_CRC_OK, + IEEE80211_RADIOTAP_UHR_ELR_SIG1_CRC_VALID); + + elr->sig2 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_STA_ID, + IEEE80211_RADIOTAP_UHR_ELR_SIG2_STA_ID); + elr->sig2 |= LE32_DEC_ENC(elr1, OFDM_RX_VECTOR_UHR_ELR_DISREGARD, + IEEE80211_RADIOTAP_UHR_ELR_SIG2_DISREGARD); + + elr->sig2 |= LE32_DEC_ENC(elr2, OFDM_RX_VECTOR_UHR_ELR_SIG2_CRC_OK, + IEEE80211_RADIOTAP_UHR_ELR_SIG2_CRC_VALID); + + elr->mark |= LE32_DEC_ENC(elr2, OFDM_RX_VECTOR_UHR_ELR_MARK_BSS_COLOR, + IEEE80211_RADIOTAP_UHR_ELR_MARK_BSS_COLOR); +} + +static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data, + struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + u32 rate_n_flags = phy_data->rate_n_flags; + u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; + struct ieee80211_radiotap_uhr *uhr; + size_t uhr_len; + + if (he_type == RATE_MCS_HE_TYPE_UHR_ELR) { + iwl_mld_decode_uhr_elr_phy_data(phy_data, skb, rx_status); + return; + } + + /* space for one user_info if we captured data */ + uhr_len = struct_size(uhr, user, (phy_data->with_data ? 1 : 0)); + + uhr = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_UHR, uhr_len); + + uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_GI_LTF_SIZE); + uhr->data[0] |= le32_encode_bits(u32_get_bits(rate_n_flags, + RATE_MCS_HE_GI_LTF_MSK), + IEEE80211_RADIOTAP_UHR_DATA0_GI_LTF_SIZE); + + if (phy_data->with_data) { + uhr->user[0].known |= + cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_MCS | + IEEE80211_RADIOTAP_UHR_USER_KNOWN_2X_LDPC | + IEEE80211_RADIOTAP_UHR_USER_KNOWN_CODING | + IEEE80211_RADIOTAP_UHR_USER_KNOWN_USER_CAPTURED); + + uhr->user[0].info |= + le32_encode_bits(u32_get_bits(rate_n_flags, + RATE_MCS_CODE_MSK), + IEEE80211_RADIOTAP_UHR_USER_INFO_MCS); + + if (phy_data->phy_info & IWL_RX_MPDU_PHY_2X_LDPC) + uhr->user[0].info |= + cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_2X_LDPC); + + if (rate_n_flags & RATE_MCS_LDPC_MSK) + uhr->user[0].info |= + cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_CODING); + } + + if (he_type == RATE_MCS_HE_TYPE_TRIG) + iwl_mld_decode_uhr_tb(phy_data, rx_status, uhr); + else + iwl_mld_decode_uhr_non_tb(phy_data, rx_status, uhr); +} + +static void iwl_mld_rx_uhr(struct iwl_mld *mld, struct sk_buff *skb, + struct iwl_mld_rx_phy_data *phy_data) +{ + if (likely(!phy_data->ntfy)) + return; + + iwl_mld_decode_uhr_usig(phy_data, skb); + iwl_mld_decode_uhr_phy_data(phy_data, skb); +} + #ifdef CONFIG_IWLWIFI_DEBUGFS static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld, struct sk_buff *skb) @@ -1512,19 +2042,42 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id, iwl_mld_set_rx_rate(mld, phy_data, rx_status); - /* must be before HE data (radiotap field order) */ - if (format == RATE_MCS_MOD_TYPE_VHT) + switch (format) { + case RATE_MCS_MOD_TYPE_CCK: + /* nothing to see here, see note below */ + break; + case RATE_MCS_MOD_TYPE_LEGACY_OFDM: + /* + * Technically legacy CCK/OFDM frames don't have an L-SIG + * since that's the compat format for HT (non-greenfield) + * and up. However, it's meant to be compatible with the + * LENGTH and RATE fields in Clause 17 and 18 OFDM frames + * so include the field for any non-CCK frame. For CCK it + * cannot work, since the LENGTH field for them is 16-bit + * and the radiotap field only has 12 bits. + */ + iwl_mld_decode_lsig(skb, phy_data); + break; + case RATE_MCS_MOD_TYPE_HT: + iwl_mld_decode_lsig(skb, phy_data); + break; + case RATE_MCS_MOD_TYPE_VHT: iwl_mld_rx_vht(skb, phy_data); - - /* must be before L-SIG data (radiotap field order) */ - if (format == RATE_MCS_MOD_TYPE_HE) + iwl_mld_decode_lsig(skb, phy_data); + break; + case RATE_MCS_MOD_TYPE_HE: iwl_mld_rx_he(skb, phy_data); - - iwl_mld_decode_lsig(skb, phy_data); - - /* TLVs - must be after radiotap fixed fields */ - if (format == RATE_MCS_MOD_TYPE_EHT) + iwl_mld_decode_lsig(skb, phy_data); + break; + case RATE_MCS_MOD_TYPE_EHT: + iwl_mld_decode_lsig(skb, phy_data); iwl_mld_rx_eht(mld, skb, phy_data); + break; + case RATE_MCS_MOD_TYPE_UHR: + iwl_mld_decode_lsig(skb, phy_data); + iwl_mld_rx_uhr(mld, skb, phy_data); + break; + } #ifdef CONFIG_IWLWIFI_DEBUGFS if (unlikely(mld->monitor.on)) { From f1969100392792abe0e1649961ce0eeb9d43a709 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:16 +0300 Subject: [PATCH 078/104] wifi: iwlwifi: mld: report UHR LTF symbols for non-TB PPDUs For TB (trigger-based) PPDUs we were already reporting this, but I missed it in the non-TB PPDU case. Add it now. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.a8228ab59708.I6c58f3e4f30bb0fb7e57a6c49782bf79d280371d@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 1362e3ad97b2..5866999c2abd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -1671,6 +1671,7 @@ static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data, __le32 usig_a2 = phy_data->ntfy->sigs.uhr.usig_a2_uhr; uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_SPATIAL_REUSE | + IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_UHR_LTF_SYMBOLS | /* All RU allocating size/index is in TB format */ IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT | IEEE80211_RADIOTAP_UHR_KNOWN_LDPC_EXTRA_SYMBOL_SEGMENT | @@ -1683,6 +1684,9 @@ static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data, uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, OFDM_RX_FRAME_UHR_SPATIAL_REUSE, IEEE80211_RADIOTAP_UHR_DATA0_SPATIAL_REUSE); + uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_NUM_OF_LTF_SYM, + IEEE80211_RADIOTAP_UHR_DATA0_NUMBER_OF_LTF_SYMBOLS); uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, OFDM_RX_FRAME_UHR_STA_RU_PS160, IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160); From 1e516621dc0bd35718852a5df52de2b11fa3e76f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:17 +0300 Subject: [PATCH 079/104] wifi: iwlwifi: mld: fix some radiotap field reports For non-trigger-based UHR frames, the RU/DRU allocation is only valid for OFDMA PPDUs, and the non-OFDMA users and interference mitigation (IM) is only valid for non-OFDMA. Fix the reporting accordingly. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.1c9e8d8a9176.I4f67f80fc962187dbe488506a7d90ffaf78585c4@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 52 ++++++++++++--------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 5866999c2abd..cb3872cb9e56 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -1669,17 +1669,43 @@ static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data, { __le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1; __le32 usig_a2 = phy_data->ntfy->sigs.uhr.usig_a2_uhr; + bool ofdma; uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_SPATIAL_REUSE | IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_UHR_LTF_SYMBOLS | - /* All RU allocating size/index is in TB format */ - IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT | IEEE80211_RADIOTAP_UHR_KNOWN_LDPC_EXTRA_SYMBOL_SEGMENT | IEEE80211_RADIOTAP_UHR_KNOWN_PRE_FEC_PADDING_FACTOR | IEEE80211_RADIOTAP_UHR_KNOWN_PE_DISAMBIGUITY | - IEEE80211_RADIOTAP_UHR_KNOWN_PRI80_CHAN_POS | - IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_NON_OFDMA_USERS | - IEEE80211_RADIOTAP_UHR_KNOWN_INTERFERENCE_MITIGATION); + IEEE80211_RADIOTAP_UHR_KNOWN_PRI80_CHAN_POS); + + /* + * TB isn't handled here, so uplink can't be OFDMA. + * Downlink OFDMA is PPDU type 0. + */ + ofdma = !(usig_a1 & cpu_to_le32(OFDM_RX_FRAME_ENHANCED_WIFI_UL_FLAG)) && + le32_get_bits(usig_a2, OFDM_RX_FRAME_UHR_PPDU_TYPE) == 0; + + if (ofdma) { + /* All RU allocation size/index is in TB format */ + uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_DRU_RRU_ALLOC_TB_FMT); + /* downlink is never DRU */ + uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_STA_RU_PS160, + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160); + uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, + OFDM_RX_FRAME_UHR_STA_RU, + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B0 | + IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B7_B1); + uhr->data[8] |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_INDICATION); + } else { + uhr->known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_KNOWN_NUMBER_OF_NON_OFDMA_USERS | + IEEE80211_RADIOTAP_UHR_KNOWN_INTERFERENCE_MITIGATION); + uhr->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, + OFDM_RX_FRAME_UHR_NUM_OF_USERS, + IEEE80211_RADIOTAP_UHR_DATA7_NUMBER_OF_NON_OFDMA_USERS); + if (!(phy_data->ntfy->sigs.uhr.b1 & cpu_to_le32(OFDM_RX_FRAME_UHR_IM_DISABLE))) + uhr->data[7] |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA7_INTERFERENCE_MITIGATION); + } uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, OFDM_RX_FRAME_UHR_SPATIAL_REUSE, @@ -1687,15 +1713,6 @@ static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data, uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, OFDM_RX_FRAME_UHR_NUM_OF_LTF_SYM, IEEE80211_RADIOTAP_UHR_DATA0_NUMBER_OF_LTF_SYMBOLS); - uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, - OFDM_RX_FRAME_UHR_STA_RU_PS160, - IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_PS_160); - uhr->data[8] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, - OFDM_RX_FRAME_UHR_STA_RU, - IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B0 | - IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_ALLOC_TB_FMT_B7_B1); - /* downlink is never DRU */ - uhr->data[8] |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_DATA8_DRU_RRU_INDICATION); uhr->data[0] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, OFDM_RX_FRAME_UHR_CODING_EXTRA_SYM, @@ -1709,13 +1726,6 @@ static void iwl_mld_decode_uhr_non_tb(struct iwl_mld_rx_phy_data *phy_data, uhr->data[1] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b2, OFDM_RX_FRAME_UHR_STA_RU_P80, IEEE80211_RADIOTAP_UHR_DATA1_PRI80_CHAN_POS); - uhr->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, - OFDM_RX_FRAME_UHR_NUM_OF_USERS, - IEEE80211_RADIOTAP_UHR_DATA7_NUMBER_OF_NON_OFDMA_USERS); - - uhr->data[7] |= LE32_DEC_ENC(phy_data->ntfy->sigs.uhr.b1, - OFDM_RX_FRAME_UHR_IM_DISABLE, - IEEE80211_RADIOTAP_UHR_DATA7_INTERFERENCE_MITIGATION); iwl_mld_uhr_decode_user_ru(phy_data, uhr); From 97a0cde5d8105cc96e6fd3c01f14c21ced0e3010 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:18 +0300 Subject: [PATCH 080/104] wifi: iwlwifi: mld: report UHR per-user NSS Given that the sniffer only receives a single user's data and only reports such in radiotap, simply add the NSS value. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.72614c2740f4.I34ad1e61e97e410eae7aa36018876277440da12f@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index cb3872cb9e56..e59f33c39a57 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -1841,6 +1841,7 @@ static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data, if (phy_data->with_data) { uhr->user[0].known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_MCS | + IEEE80211_RADIOTAP_UHR_USER_KNOWN_NSS | IEEE80211_RADIOTAP_UHR_USER_KNOWN_2X_LDPC | IEEE80211_RADIOTAP_UHR_USER_KNOWN_CODING | IEEE80211_RADIOTAP_UHR_USER_KNOWN_USER_CAPTURED); @@ -1849,6 +1850,10 @@ static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data, le32_encode_bits(u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK), IEEE80211_RADIOTAP_UHR_USER_INFO_MCS); + uhr->user[0].info |= + le32_encode_bits(u32_get_bits(rate_n_flags, + RATE_MCS_NSS_MSK), + IEEE80211_RADIOTAP_UHR_USER_INFO_NSS); if (phy_data->phy_info & IWL_RX_MPDU_PHY_2X_LDPC) uhr->user[0].info |= From 023202af5e927c41523ed9cc6fa280687a4d87dc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:19 +0300 Subject: [PATCH 081/104] wifi: iwlwifi: mld: report beamforming in UHR sniffer In per-user information for UHR sniffer, report whether or not beamforming was used, according to rate_n_flags. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.3f8de2b3592b.Ie21d26e1a25a117515907e9577a51de3bc29692b@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index e59f33c39a57..738b6fb9770f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -1842,6 +1842,7 @@ static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data, uhr->user[0].known |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_KNOWN_MCS | IEEE80211_RADIOTAP_UHR_USER_KNOWN_NSS | + IEEE80211_RADIOTAP_UHR_USER_KNOWN_BF | IEEE80211_RADIOTAP_UHR_USER_KNOWN_2X_LDPC | IEEE80211_RADIOTAP_UHR_USER_KNOWN_CODING | IEEE80211_RADIOTAP_UHR_USER_KNOWN_USER_CAPTURED); @@ -1859,6 +1860,10 @@ static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data, uhr->user[0].info |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_2X_LDPC); + if (rate_n_flags & RATE_MCS_BF_MSK) + uhr->user[0].info |= + cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_BF); + if (rate_n_flags & RATE_MCS_LDPC_MSK) uhr->user[0].info |= cpu_to_le32(IEEE80211_RADIOTAP_UHR_USER_INFO_CODING); From db2bca92bdc7184266d84b57f9ae5528e085e73b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:20 +0300 Subject: [PATCH 082/104] wifi: iwlwifi: correctly report TB sounding PPDUs in sniffer Sounding PPDUs are currently reported as "not for us" in the sniffer, since PHY reports that aren't detected as sounding immediately by a zero-length indication (which doesn't exist for trigger-based) are released only on the next PHY sniffer notification, when no MPDU was received. The "not for us" indication is, however, wrong in both cases: for TB sounding PPDUs it should be sounding, for others it should be some unspecified (DSP?) error. Fix both cases. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.f8f6a08851a8.I8689a2a1599578aea53dda62cffc7f012d1d10f7@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 33 +++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 738b6fb9770f..60d653b5b755 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -2864,7 +2864,7 @@ void iwl_mld_handle_rsc_notif(struct iwl_mld *mld, #endif /* CONFIG_PM_SLEEP */ static void iwl_mld_no_data_rx(struct iwl_mld *mld, - struct napi_struct *napi, u8 status, + struct napi_struct *napi, bool no_mpdu, struct iwl_rx_phy_air_sniffer_ntfy *ntfy) { struct ieee80211_rx_status *rx_status; @@ -2889,11 +2889,26 @@ static void iwl_mld_no_data_rx(struct iwl_mld *mld, /* 0-length PSDU */ rx_status->flag |= RX_FLAG_NO_PSDU; - switch (status) { + switch (ntfy->status) { case IWL_SNIF_STAT_PLCP_RX_OK: - /* we only get here with sounding PPDUs */ - rx_status->zero_length_psdu_type = - IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING; + /* + * For trigger-based PPDUs, the firmware decodes the PHY header + * and releases with a good status only if the frame was for the + * configured AID (the bad status depends on the version), and + * also only sets IWL_SNIF_FLAG_VALID_TB_RX if receiving for the + * configured AID. + * + * So trigger-based PHY notifications without MPDU are sounding + * PPDUs, while other releases without MPDU are some kind of + * error after a good PHY header - don't flag failed PLCP in + * this case, but release as unspecified zero-len reason. + */ + if (no_mpdu && !(ntfy->flags & IWL_SNIF_FLAG_VALID_TB_RX)) + rx_status->zero_length_psdu_type = + IEEE80211_RADIOTAP_ZERO_LEN_PSDU_VENDOR; + else + rx_status->zero_length_psdu_type = + IEEE80211_RADIOTAP_ZERO_LEN_PSDU_SOUNDING; break; case IWL_SNIF_STAT_AID_NOT_FOR_US: rx_status->zero_length_psdu_type = @@ -2904,6 +2919,7 @@ static void iwl_mld_no_data_rx(struct iwl_mld *mld, case IWL_SNIF_STAT_PLCP_RX_SIGB_ERR: case IWL_SNIF_STAT_UNKNOWN_ERROR: default: + /* some kind of PLCP error - no details from FW */ rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC; fallthrough; case IWL_SNIF_STAT_UNEXPECTED_TB: @@ -2947,10 +2963,9 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld, "invalid air sniffer notification size\n")) return; - /* check if there's an old one to release as errored */ + /* check if there's an old one to release */ if (mld->monitor.phy.valid && !mld->monitor.phy.used) - iwl_mld_no_data_rx(mld, napi, IWL_SNIF_STAT_AID_NOT_FOR_US, - &mld->monitor.phy.data); + iwl_mld_no_data_rx(mld, napi, true, &mld->monitor.phy.data); /* old data is no longer valid now */ mld->monitor.phy.valid = false; @@ -2987,7 +3002,7 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld, } if (ntfy->status != IWL_SNIF_STAT_PLCP_RX_OK || is_ndp) { - iwl_mld_no_data_rx(mld, napi, ntfy->status, ntfy); + iwl_mld_no_data_rx(mld, napi, false, ntfy); return; } From 6f177130233c64a01949f309d90cfdb0bf573f3d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:21 +0300 Subject: [PATCH 083/104] wifi: iwlwifi: mld: remove UHR TB U-SIG2 B2 validate bit Clearly the existing code is wrong. Since it's not clear that the value is reported by hardware, and we probably won't need it, remove it for now. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.56c9dd83eb39.I4482c69e48aa4661d11aecc23aab03fb9fef5ead@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 60d653b5b755..076c4fd6f37c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -1354,9 +1354,6 @@ static void iwl_mld_decode_uhr_usig_tb(struct iwl_mld_rx_phy_data *phy_data, IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, OFDM_RX_FRAME_UHR_PPDU_TYPE, IEEE80211_RADIOTAP_UHR_USIG2_TB_B0_B1_PPDU_TYPE); - IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, - IEEE80211_RADIOTAP_UHR_USIG2_MU_B2_COBF_COSR, - IEEE80211_RADIOTAP_UHR_USIG2_TB_B2_VALIDATE); IWL_MLD_ENC_USIG_VALUE_MASK(usig, usig_a2, OFDM_RX_FRAME_UHR_TRIG_SPATIAL_REUSE_1, IEEE80211_RADIOTAP_UHR_USIG2_TB_B3_B6_SPATIAL_REUSE_1); From cfa74632ec5f74af5c9b2c4c25873438a0a245a8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:22 +0300 Subject: [PATCH 084/104] wifi: iwlwifi: mld: detect UHR sounding packets Detect UHR sounding packets by checking their data length just like for EHT and reporting them to the sniffer immediately. Signed-off-by: Johannes Berg Reviewed-by: Benjamin Berg Link: https://patch.msgid.link/20261001161715.1c6817d2205b.Icc0cb8f2ef738bba6105f7b909c47d6d0cf12491@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 076c4fd6f37c..c0203e74fff6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -2996,6 +2996,13 @@ void iwl_mld_handle_phy_air_sniffer_notif(struct iwl_mld *mld, !le32_get_bits(ntfy->sigs.eht.sig2, OFDM_RX_FRAME_EHT_NUM_OF_DATA_SYM); break; + case RATE_MCS_MOD_TYPE_UHR: + if (he_type == RATE_MCS_HE_TYPE_TRIG || + he_type == RATE_MCS_HE_TYPE_UHR_ELR) + break; + is_ndp = !le32_get_bits(ntfy->sigs.uhr.sig2, + OFDM_RX_UHR_NUM_OF_DATA_SYM); + break; } if (ntfy->status != IWL_SNIF_STAT_PLCP_RX_OK || is_ndp) { From 7f2793237f68a52d4d78e8223b84ba96a3acdf7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:23 +0300 Subject: [PATCH 085/104] wifi: iwlwifi: mld: report the guard interval for UHR We didn't report the guard interval for UHR to mac80211, fix that by refactoring the EHT function and using it. The LTF is reported only in radiotap (differently), so the code for UHR doesn't need it. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.9f728be36075.Ic46d2234d03fdf3b098a8b25f607bd3559e6a2db@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 70 ++++++++++++--------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index c0203e74fff6..9ba68564bf98 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -1243,48 +1243,30 @@ static void iwl_mld_decode_eht_phy_data(struct iwl_mld_rx_phy_data *phy_data, iwl_mld_decode_eht_non_tb(phy_data, rx_status, eht); } -static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, - struct iwl_mld_rx_phy_data *phy_data) +static u8 iwl_mld_decode_eht_uhr_gi_ltf(u32 rate_n_flags, u8 *gi) { - struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); - struct ieee80211_radiotap_eht *eht; - size_t eht_len = sizeof(*eht); - u32 rate_n_flags = phy_data->rate_n_flags; u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; - /* EHT and HE have the same values for LTF */ - u8 ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN; - /* u32 for 1 user_info */ - if (phy_data->with_data) - eht_len += sizeof(u32); - - eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len); + *gi = NL80211_RATE_INFO_EHT_GI_0_8; switch (u32_get_bits(rate_n_flags, RATE_MCS_HE_GI_LTF_MSK)) { case 0: if (he_type == RATE_MCS_HE_TYPE_TRIG) { - rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6; - ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X; - } else { - rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8; - ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; + *gi = NL80211_RATE_INFO_EHT_GI_1_6; + return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X; } - break; + return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; case 1: - rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_1_6; - ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; - break; + *gi = NL80211_RATE_INFO_EHT_GI_1_6; + return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X; case 2: - ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; if (he_type == RATE_MCS_HE_TYPE_TRIG) - rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2; - else - rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_0_8; - break; + *gi = NL80211_RATE_INFO_EHT_GI_3_2; + return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; case 3: if (he_type != RATE_MCS_HE_TYPE_TRIG) { - ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; - rx_status->eht.gi = NL80211_RATE_INFO_EHT_GI_3_2; + *gi = NL80211_RATE_INFO_EHT_GI_3_2; + return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X; } break; default: @@ -1292,7 +1274,29 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, break; } + return IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN; +} + +static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb, + struct iwl_mld_rx_phy_data *phy_data) +{ + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_radiotap_eht *eht; + size_t eht_len = sizeof(*eht); + u32 rate_n_flags = phy_data->rate_n_flags; + u8 gi, ltf; + + /* u32 for 1 user_info */ + if (phy_data->with_data) + eht_len += sizeof(u32); + + eht = iwl_mld_radiotap_put_tlv(skb, IEEE80211_RADIOTAP_EHT, eht_len); + + ltf = iwl_mld_decode_eht_uhr_gi_ltf(rate_n_flags, &gi); + if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) { + rx_status->eht.gi = gi; + eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_GI); eht->data[0] |= le32_encode_bits(ltf, IEEE80211_RADIOTAP_EHT_DATA0_LTF) | @@ -1875,6 +1879,14 @@ static void iwl_mld_decode_uhr_phy_data(struct iwl_mld_rx_phy_data *phy_data, static void iwl_mld_rx_uhr(struct iwl_mld *mld, struct sk_buff *skb, struct iwl_mld_rx_phy_data *phy_data) { + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + u8 gi, ltf; + + /* the LTF size is reported from the PHY data, only the GI is needed */ + ltf = iwl_mld_decode_eht_uhr_gi_ltf(phy_data->rate_n_flags, &gi); + if (ltf != IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN) + rx_status->uhr.gi = gi; + if (likely(!phy_data->ntfy)) return; From 946f44ef759cedf70cb6ea1136b5e9806877ca57 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:24 +0300 Subject: [PATCH 086/104] wifi: iwlwifi: mld: set RX_FLAG_FAILED_PLCP_CRC for bad U-SIG CRC There are a number of places checking for the U-SIG CRC and then reporting if it failed, but we should set the failed PLCP CRC top-level radiotap flag for easier discarding of such packets in users such as wireshark. Do that with a new helper function, to avoid doing it in so many places. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.cda01742eff8.I824c410fefd4022973403c1cf18f47459e34c4b2@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/rx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index 9ba68564bf98..e1964e570012 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -816,6 +816,14 @@ iwl_mld_radiotap_put_tlv(struct sk_buff *skb, u16 type, u16 len) (_usig)->value |= LE32_DEC_ENC(in_value, dec_bits, _enc_bits); \ } while (0) +static void +iwl_mld_check_bad_usig_crc(struct ieee80211_rx_status *rx_status, + struct ieee80211_radiotap_eht_usig *usig) +{ + if (usig->common & cpu_to_le32(IEEE80211_RADIOTAP_EHT_USIG_COMMON_BAD_USIG_CRC)) + rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC; +} + static void iwl_mld_decode_eht_usig_tb(struct iwl_mld_rx_phy_data *phy_data, struct ieee80211_radiotap_eht_usig *usig) { @@ -878,6 +886,7 @@ static void iwl_mld_decode_eht_usig_non_tb(struct iwl_mld_rx_phy_data *phy_data, static void iwl_mld_decode_eht_usig(struct iwl_mld_rx_phy_data *phy_data, struct sk_buff *skb) { + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK; __le32 usig_a1 = phy_data->ntfy->sigs.eht.usig_a1; __le32 usig_a2 = phy_data->ntfy->sigs.eht.usig_a2_eht; @@ -941,6 +950,8 @@ static void iwl_mld_decode_eht_usig(struct iwl_mld_rx_phy_data *phy_data, iwl_mld_decode_eht_usig_tb(phy_data, usig); else iwl_mld_decode_eht_usig_non_tb(phy_data, usig); + + iwl_mld_check_bad_usig_crc(rx_status, usig); } static void @@ -1448,6 +1459,7 @@ static void iwl_mld_decode_uhr_usig_non_tb(struct iwl_mld_rx_phy_data *phy_data, static void iwl_mld_decode_uhr_usig(struct iwl_mld_rx_phy_data *phy_data, struct sk_buff *skb) { + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); u32 he_type = phy_data->rate_n_flags & RATE_MCS_HE_TYPE_MSK; struct ieee80211_radiotap_eht_usig *usig; __le32 usig_a1 = phy_data->ntfy->sigs.uhr.usig_a1; @@ -1507,6 +1519,8 @@ static void iwl_mld_decode_uhr_usig(struct iwl_mld_rx_phy_data *phy_data, iwl_mld_decode_uhr_usig_non_tb(phy_data, usig); break; } + + iwl_mld_check_bad_usig_crc(rx_status, usig); } static void iwl_mld_decode_uhr_tb(struct iwl_mld_rx_phy_data *phy_data, From db3bf5d67b3c4433b1b864adc30efa1026cb0ad5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:25 +0300 Subject: [PATCH 087/104] wifi: iwlwifi: advertise UHR Co-BF support This is supported by hardware, advertise it. We'll have to separately work on enabling it in firmware if the AP supports it. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.6c5fc579f2d8.I0cdf7516e95181e31c33fde374216fb6bc8f4aa1@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index ed2b094c1ad7..31badfa35f97 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -716,6 +716,7 @@ static const struct ieee80211_sband_iftype_data iwl_iftype_cap[] = { IEEE80211_UHR_MAC_CAP0_DPS_SUPP, [1] = IEEE80211_UHR_MAC_CAP1_DUO_SUPP | IEEE80211_UHR_MAC_CAP1_DBE_SUPP, + [4] = IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP, }, }, }, From ec02ebd4d7099e3827c3b3476b1814c7fa666dbc Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 1 Oct 2026 16:20:26 +0300 Subject: [PATCH 088/104] wifi: iwlwifi: mld: add support for WoWLAN CIGTK API The firmware added CIGTK rekey support for D3: - KEK_KCK_MATERIAL_CMD version 5 has a new cigtk_cipher field. - WOWLAN_INFO_NOTIFICATION version 7 reports the CIGTK material of the active link, and MLO keys can now be of type CIGTK. The CIGTK material itself is not used yet, this is done in a separate patch. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20261001161715.45aa7d3f2421.I1c53d0b8f1a1f1b3a4e35a86b5a6a5c04ff5f1a2@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/commands.h | 5 +- .../net/wireless/intel/iwlwifi/fw/api/d3.h | 62 +++++++++++++++- .../wireless/intel/iwlwifi/fw/api/offload.h | 5 +- drivers/net/wireless/intel/iwlwifi/mld/d3.c | 71 +++++++++++++++++-- 4 files changed, 133 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index f76f76e54c4e..dbb0e7c194df 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -569,8 +569,9 @@ enum iwl_legacy_cmds { /** * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd_v2, - * &struct iwl_wowlan_kek_kck_material_cmd_v3 or - * &struct iwl_wowlan_kek_kck_material_cmd_v4 + * &struct iwl_wowlan_kek_kck_material_cmd_v3, + * &struct iwl_wowlan_kek_kck_material_cmd_v4 or + * &struct iwl_wowlan_kek_kck_material_cmd */ WOWLAN_KEK_KCK_MATERIAL = 0xe4, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index a0379aca99d7..c469ea965157 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -422,6 +422,7 @@ struct iwl_wowlan_config_cmd { #define WOWLAN_IGTK_MIN_INDEX 4 #define WOWLAN_BIGTK_KEYS_NUM 2 #define WOWLAN_BIGTK_MIN_INDEX 6 +#define WOWLAN_CIGTK_KEYS_NUM 2 /* * WOWLAN_TSC_RSC_PARAMS @@ -531,6 +532,20 @@ struct iwl_wowlan_kek_kck_material_cmd_v4 { __le32 bigtk_cipher; } __packed; /* KEK_KCK_MATERIAL_API_S_VER_4 */ +struct iwl_wowlan_kek_kck_material_cmd { + __le32 sta_id; + u8 kck[IWL_KCK_MAX_SIZE]; + u8 kek[IWL_KEK_MAX_SIZE]; + __le16 kck_len; + __le16 kek_len; + __le64 replay_ctr; + __le32 akm; + __le32 gtk_cipher; + __le32 igtk_cipher; + __le32 bigtk_cipher; + __le32 cigtk_cipher; +} __packed; /* KEK_KCK_MATERIAL_API_S_VER_5 */ + struct iwl_wowlan_get_status_cmd { __le32 sta_id; } __packed; /* WOWLAN_GET_STATUSES_CMD_API_S_VER_1 */ @@ -812,19 +827,21 @@ struct iwl_wowlan_info_notif_v1 { } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */ /* MAX MLO keys of non-active links that can arrive in the notification */ -#define WOWLAN_MAX_MLO_KEYS 18 +#define WOWLAN_MAX_MLO_KEYS 24 /** * enum iwl_wowlan_mlo_gtk_type - GTK types * @WOWLAN_MLO_GTK_KEY_TYPE_GTK: GTK * @WOWLAN_MLO_GTK_KEY_TYPE_IGTK: IGTK * @WOWLAN_MLO_GTK_KEY_TYPE_BIGTK: BIGTK + * @WOWLAN_MLO_GTK_KEY_TYPE_CIGTK: CIGTK * @WOWLAN_MLO_GTK_KEY_NUM_TYPES: number of key types */ enum iwl_wowlan_mlo_gtk_type { WOWLAN_MLO_GTK_KEY_TYPE_GTK, WOWLAN_MLO_GTK_KEY_TYPE_IGTK, WOWLAN_MLO_GTK_KEY_TYPE_BIGTK, + WOWLAN_MLO_GTK_KEY_TYPE_CIGTK, WOWLAN_MLO_GTK_KEY_NUM_TYPES }; /* WOWLAN_MLO_GTK_KEY_TYPE_API_E_VER_1 */ @@ -931,11 +948,51 @@ struct iwl_wowlan_info_notif_v5 { struct iwl_wowlan_mlo_gtk mlo_gtks[]; } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */ +/** + * struct iwl_wowlan_info_notif_v6 - WoWLAN information notification + * @gtk: GTK data + * @igtk: IGTK data + * @bigtk: BIGTK data + * @replay_ctr: GTK rekey replay counter + * @pattern_number: number of the matched patterns + * @qos_seq_ctr: QoS sequence counters to use next + * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason + * @num_of_gtk_rekeys: number of GTK rekeys + * @transmitted_ndps: number of transmitted neighbor discovery packets + * @received_beacons: number of received beacons + * @tid_tear_down: bit mask of tids whose BA sessions were closed + * in suspend state + * @station_id: station id + * @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs + * following this notif + * @tid_offloaded_tx: tid used by the firmware to transmit data packets + * while in wowlan + * @mlo_gtks: array of GTKs of size num_mlo_link_keys + */ +struct iwl_wowlan_info_notif_v6 { + struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM]; + struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; + struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM]; + __le64 replay_ctr; + __le16 pattern_number; + __le16 qos_seq_ctr; + __le32 wakeup_reasons; + __le32 num_of_gtk_rekeys; + __le32 transmitted_ndps; + __le32 received_beacons; + u8 tid_tear_down; + u8 station_id; + u8 num_mlo_link_keys; + u8 tid_offloaded_tx; + struct iwl_wowlan_mlo_gtk mlo_gtks[]; +} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */ + /** * struct iwl_wowlan_info_notif - WoWLAN information notification * @gtk: GTK data * @igtk: IGTK data * @bigtk: BIGTK data + * @cigtk: CIGTK data * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched patterns * @qos_seq_ctr: QoS sequence counters to use next @@ -956,6 +1013,7 @@ struct iwl_wowlan_info_notif { struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM]; struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM]; + struct iwl_wowlan_igtk_status cigtk[WOWLAN_CIGTK_KEYS_NUM]; __le64 replay_ctr; __le16 pattern_number; __le16 qos_seq_ctr; @@ -968,7 +1026,7 @@ struct iwl_wowlan_info_notif { u8 num_mlo_link_keys; u8 tid_offloaded_tx; struct iwl_wowlan_mlo_gtk mlo_gtks[]; -} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */ +} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_7 */ /** * struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index bb801650a565..078116fab054 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -3,7 +3,7 @@ * Copyright (C) 2012-2014 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2021-2025 Intel Corporation + * Copyright (C) 2021-2026 Intel Corporation */ #ifndef __iwl_fw_api_offload_h__ #define __iwl_fw_api_offload_h__ @@ -20,7 +20,8 @@ enum iwl_prot_offload_subcmd_ids { /** * @WOWLAN_INFO_NOTIFICATION: Notification in * &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3, - * &struct iwl_wowlan_info_notif_v5 or &struct iwl_wowlan_info_notif + * &struct iwl_wowlan_info_notif_v5, &struct iwl_wowlan_info_notif_v6 + * or &struct iwl_wowlan_info_notif */ WOWLAN_INFO_NOTIFICATION = 0xFD, diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index 7a7d07a7914d..ce959363f62c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -598,6 +598,37 @@ iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5, } } +static void +iwl_mld_convert_wowlan_notif_v6(const struct iwl_wowlan_info_notif_v6 *notif_v6, + struct iwl_wowlan_info_notif *notif) +{ + /* v6 is identical to the new format, except that it has no CIGTK */ + BUILD_BUG_ON(sizeof(notif->gtk) != sizeof(notif_v6->gtk)); + BUILD_BUG_ON(sizeof(notif->igtk) != sizeof(notif_v6->igtk)); + BUILD_BUG_ON(sizeof(notif->bigtk) != sizeof(notif_v6->bigtk)); + + memcpy(notif->gtk, notif_v6->gtk, sizeof(notif_v6->gtk)); + memcpy(notif->igtk, notif_v6->igtk, sizeof(notif_v6->igtk)); + memcpy(notif->bigtk, notif_v6->bigtk, sizeof(notif_v6->bigtk)); + + notif->replay_ctr = notif_v6->replay_ctr; + notif->pattern_number = notif_v6->pattern_number; + notif->qos_seq_ctr = notif_v6->qos_seq_ctr; + notif->wakeup_reasons = notif_v6->wakeup_reasons; + notif->num_of_gtk_rekeys = notif_v6->num_of_gtk_rekeys; + notif->transmitted_ndps = notif_v6->transmitted_ndps; + notif->received_beacons = notif_v6->received_beacons; + notif->tid_tear_down = notif_v6->tid_tear_down; + notif->station_id = notif_v6->station_id; + notif->num_mlo_link_keys = notif_v6->num_mlo_link_keys; + notif->tid_offloaded_tx = notif_v6->tid_offloaded_tx; + + if (notif_v6->num_mlo_link_keys) + memcpy(notif->mlo_gtks, notif_v6->mlo_gtks, + notif_v6->num_mlo_link_keys * + sizeof(struct iwl_wowlan_mlo_gtk)); +} + static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld, u32 len, const void *notif_data, int version) @@ -619,12 +650,23 @@ static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld, u32 len, num_mlo_keys = notif_v5->num_mlo_link_keys; } else if (version == 6) { + const struct iwl_wowlan_info_notif_v6 *notif_v6 = notif_data; + + expected_len = sizeof(*notif_v6); + + if (IWL_FW_CHECK(mld, len < expected_len, + "Invalid wowlan_info_notif v6 (expected=%u got=%u)\n", + expected_len, len)) + return false; + + num_mlo_keys = notif_v6->num_mlo_link_keys; + } else if (version == 7) { const struct iwl_wowlan_info_notif *notif = notif_data; expected_len = sizeof(*notif); if (IWL_FW_CHECK(mld, len < expected_len, - "Invalid wowlan_info_notif v6 (expected=%u got=%u)\n", + "Invalid wowlan_info_notif v7 (expected=%u got=%u)\n", expected_len, len)) return false; @@ -683,9 +725,27 @@ iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld, iwl_mld_convert_wowlan_notif_v5(_notif, converted_notif); notif = converted_notif; } else if (wowlan_info_ver == 6) { + const struct iwl_wowlan_info_notif_v6 *_notif = + (void *)pkt->data; + + if (!iwl_mld_validate_wowlan_notif_size(mld, len, _notif, 6)) + return true; + + converted_notif = kzalloc_flex(*converted_notif, mlo_gtks, + _notif->num_mlo_link_keys, + GFP_ATOMIC); + if (!converted_notif) { + IWL_ERR(mld, + "Failed to allocate memory for converted wowlan_info_notif\n"); + return true; + } + + iwl_mld_convert_wowlan_notif_v6(_notif, converted_notif); + notif = converted_notif; + } else if (wowlan_info_ver == 7) { notif = (void *)pkt->data; - if (!iwl_mld_validate_wowlan_notif_size(mld, len, notif, 6)) + if (!iwl_mld_validate_wowlan_notif_size(mld, len, notif, 7)) return true; } else { /* smaller versions are not supported */ @@ -1834,9 +1894,12 @@ iwl_mld_send_kek_kck_cmd(struct iwl_mld *mld, struct iwl_mld_suspend_key_iter_data data, int ap_sta_id) { - struct iwl_wowlan_kek_kck_material_cmd_v4 kek_kck_cmd = {}; + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, WOWLAN_KEK_KCK_MATERIAL, 4); + struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_mld_rekey_data *rekey_data = &mld_vif->wowlan_data.rekey_data; + u32 cmd_size = cmd_ver == 5 ? sizeof(kek_kck_cmd) : + sizeof(struct iwl_wowlan_kek_kck_material_cmd_v4); memcpy(kek_kck_cmd.kck, rekey_data->kck, rekey_data->kck_len); @@ -1855,7 +1918,7 @@ iwl_mld_send_kek_kck_cmd(struct iwl_mld *mld, rekey_data->akm); return iwl_mld_send_cmd_pdu(mld, WOWLAN_KEK_KCK_MATERIAL, - &kek_kck_cmd); + &kek_kck_cmd, cmd_size); } static int From 0d91e1d069fa5740d23e9a1f47d36279f50b699b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 1 Oct 2026 16:20:27 +0300 Subject: [PATCH 089/104] wifi: iwlwifi: don't mask ucode_ver in iwl_sar_geo_support() All the firmwares used by iwlmvm and iwlmld set IWL_UCODE_TLV_API_NEW_VERSION. Since iwl_sar_geo_support is not called by iwldvm, simplify the ucode_ver check. No functional change intended. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20261001161715.5e290d456f51.Ic33c983411e93201e5e05a9d3df5af524de09b9a@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/regulatory.c | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index c7de45323935..b6707312c188 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -199,21 +199,22 @@ static const struct dmi_system_id dmi_tas_approved_list[] = { bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) { + u32 ucode_ver = fwrt->fw->ucode_ver; + /* * The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on * earlier firmware versions. Unfortunately, we don't have a - * TLV API flag to rely on, so rely on the major version which - * is in the first byte of ucode_ver. This was implemented - * initially on version 38 and then backported to 17. It was - * also backported to 29, but only for 7265D devices. The - * intention was to have it in 36 as well, but not all 8000 - * family got this feature enabled. The 8000 family is the - * only one using version 36, so skip this version entirely. + * TLV API flag to rely on, so rely on the ucode version. This + * was implemented initially on version 38 and then backported + * to 17. It was also backported to 29, but only for 7265D + * devices. The intention was to have it in 36 as well, but not + * all 8000 family got this feature enabled. The 8000 family is + * the only one using version 36, so skip this version entirely. */ - return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 || - (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 && + return ucode_ver >= 38 || + (ucode_ver == 17 && fwrt->trans->info.hw_rev != CSR_HW_REV_TYPE_3160) || - (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 && + (ucode_ver == 29 && ((fwrt->trans->info.hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)); } From c20947271de1ed5d62b8c62429eaaf1fb1cc71f0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 1 Oct 2026 16:20:28 +0300 Subject: [PATCH 090/104] wifi: iwlwifi: dbg: validate the index before accessing an array If the worker index is bad, then the pointer to the containing array cannot be determined. Avoid it, and just make it a WARN_ONCE() since it should never happen. Signed-off-by: Johannes Berg Link: https://patch.msgid.link/20261001161715.dd857cfe0d6b.I8162af7b34d03b1b30be5914cde6248ad84b6a9f@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 1d34ad59bb71..e29c58575859 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2304,8 +2304,13 @@ void iwl_fw_error_dump_wk(struct work_struct *work) { struct iwl_fwrt_wk_data *wks = container_of(work, typeof(*wks), wk.work); - struct iwl_fw_runtime *fwrt = - container_of(wks, typeof(*fwrt), dump.wks[wks->idx]); + struct iwl_fw_runtime *fwrt; + + if (WARN_ONCE(wks->idx >= IWL_FW_RUNTIME_DUMP_WK_NUM, + "invalid worker index %d\n", wks->idx)) + return; + + fwrt = container_of(wks, typeof(*fwrt), dump.wks[wks->idx]); /* assumes the op mode mutex is locked in dump_start since * iwl_fw_dbg_collect_sync can't run in parallel From f4cc1930a78ff5d106ffa30f81898c13300057c3 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 11 Oct 2026 14:07:02 +0300 Subject: [PATCH 091/104] wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 109 Start supporting Core 109 FW on these devices. Reviewed-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.603d3010fb29.I53bc9bf1f5931e573fd55b62eef8be16270e6a92@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 3cc3ffd0aa1c..f6e0f0c8a82e 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_BZ_UCODE_CORE_MAX 108 +#define IWL_BZ_UCODE_CORE_MAX 109 /* Lowest firmware core release supported */ #define IWL_BZ_UCODE_CORE_MIN 102 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c index f6dd1f9733fb..f62a0bf29754 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c @@ -9,7 +9,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_DR_UCODE_CORE_MAX 108 +#define IWL_DR_UCODE_CORE_MAX 109 /* Lowest firmware core release supported */ #define IWL_DR_UCODE_CORE_MIN 102 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 467888c8d2cb..220b0d181f42 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware core release supported */ -#define IWL_SC_UCODE_CORE_MAX 108 +#define IWL_SC_UCODE_CORE_MAX 109 /* Lowest firmware core release supported */ #define IWL_SC_UCODE_CORE_MIN 102 From a2f60db1c1514c7d083b5c0c8b9510b1adf0cc2c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 11 Oct 2026 14:07:03 +0300 Subject: [PATCH 092/104] wifi: iwlwifi: mvm: fix the VHT MCS sent to a v1 firmware When converting a v3 rate to the v1 format, the MCS index was read from the mask of the NSS field and written into the mask of the MCS field. This is obviously wrong, we must not mix the NSS and the MCS. Fixes: 3592c0083fb2 ("wifi: iwlwifi: mvm: fix beacon template/fixed rate") Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.dfca0c8b560a.I7a3e1f0e91f0d0c6f4c5f1e6a33dc7c0c5e9ad11@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index e97ab2c9e5ba..b2f34d1f2c48 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1356,8 +1356,8 @@ __le32 iwl_mvm_v3_rate_to_fw(u32 rate, u8 rate_ver) case RATE_MCS_MOD_TYPE_VHT: result = RATE_MCS_VHT_MSK_V1; result |= u32_encode_bits(u32_get_bits(rate, - RATE_VHT_MCS_NSS_MSK), - RATE_MCS_CODE_MSK); + RATE_MCS_CODE_MSK), + RATE_VHT_MCS_RATE_CODE_MSK); result |= u32_encode_bits(u32_get_bits(rate, RATE_MCS_NSS_MSK), RATE_VHT_MCS_NSS_MSK); break; From 40a0b9f3ac2c28eb85bcb4e6433c879d3a3e14b3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:04 +0300 Subject: [PATCH 093/104] wifi: iwlwifi: fw: api: fix D3 sequence counter docs Most sequence counters in WoWLAN are documented as "to use next", but in reality firmware treats them as "last used". Fix the docs accordingly, while at it noting that for newer versions it only applies to the offload TID. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.5d17b80be44c.Ia3ec5e1f714029561b08ab659b116bc20a60beb3@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/fw/api/d3.h | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index c469ea965157..327a8c05f4db 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -373,9 +373,9 @@ enum iwl_wowlan_flags { /** * struct iwl_wowlan_config_cmd_v6 - WoWLAN configuration (versions 5 and 6) * @wakeup_filter: filter from &enum iwl_wowlan_wakeup_filters - * @non_qos_seq: non-QoS sequence counter to use next. + * @non_qos_seq: last used non-QoS sequence counter. * Reserved if the struct has version >= 6. - * @qos_seq: QoS sequence counters to use next + * @qos_seq: last used QoS sequence counters * @wowlan_ba_teardown_tids: bitmap of BA sessions to tear down * @is_11n_connection: indicates HT connection * @offloading_tid: TID reserved for firmware use @@ -732,8 +732,8 @@ struct iwl_wowlan_igtk_status { * @gtk: GTK data * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched pattern - * @non_qos_seq_ctr: non-QoS sequence counter to use next - * @qos_seq_ctr: QoS sequence counters to use next + * @non_qos_seq_ctr: last used non-QoS sequence counter + * @qos_seq_ctr: last used QoS sequence counters * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets @@ -763,8 +763,8 @@ struct iwl_wowlan_status_v6 { * @igtk: IGTK data * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched pattern - * @non_qos_seq_ctr: non-QoS sequence counter to use next - * @qos_seq_ctr: QoS sequence counters to use next + * @non_qos_seq_ctr: last used non-QoS sequence counter + * @qos_seq_ctr: last used QoS sequence counters * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets @@ -796,7 +796,7 @@ struct iwl_wowlan_status_v7 { * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched patterns * @reserved1: reserved - * @qos_seq_ctr: QoS sequence counters to use next + * @qos_seq_ctr: last used QoS sequence counters * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets @@ -882,7 +882,7 @@ struct iwl_wowlan_mlo_gtk { * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched patterns * @reserved1: reserved - * @qos_seq_ctr: QoS sequence counters to use next + * @qos_seq_ctr: last used QoS sequence counters * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets @@ -916,7 +916,7 @@ struct iwl_wowlan_info_notif_v3 { * @bigtk: BIGTK data * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched patterns - * @qos_seq_ctr: QoS sequence counters to use next + * @qos_seq_ctr: last used QoS sequence counter for @tid_offloaded_tx * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets @@ -955,7 +955,7 @@ struct iwl_wowlan_info_notif_v5 { * @bigtk: BIGTK data * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched patterns - * @qos_seq_ctr: QoS sequence counters to use next + * @qos_seq_ctr: last used QoS sequence counter for @tid_offloaded_tx * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets @@ -995,7 +995,7 @@ struct iwl_wowlan_info_notif_v6 { * @cigtk: CIGTK data * @replay_ctr: GTK rekey replay counter * @pattern_number: number of the matched patterns - * @qos_seq_ctr: QoS sequence counters to use next + * @qos_seq_ctr: last used QoS sequence counter for @tid_offloaded_tx * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason * @num_of_gtk_rekeys: number of GTK rekeys * @transmitted_ndps: number of transmitted neighbor discovery packets From 4f823509afa84ae785d9f7440ef01f496bd36345 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 11 Oct 2026 14:07:05 +0300 Subject: [PATCH 094/104] wifi: iwlwifi: move context info APIs to a separate file Context info structures and enums are APIs. While they have only been used in pcie bus until now, part of those will be used for future bus types as well. Extract the APIs from pcie/iwl-context-info*.h to fw/api/context-info*.h. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.87b73a7de1e5.I5e526d01b560a277bc363b3f1b42dcb63d51c574@changeid Signed-off-by: Miri Korenblit --- .../intel/iwlwifi/fw/api/ctxt-info-v2.h | 328 ++++++++++++++++++ .../wireless/intel/iwlwifi/fw/api/ctxt-info.h | 185 ++++++++++ .../intel/iwlwifi/pcie/iwl-context-info-v2.h | 320 +---------------- .../intel/iwlwifi/pcie/iwl-context-info.h | 177 +--------- 4 files changed, 517 insertions(+), 493 deletions(-) create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info-v2.h create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info.h diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info-v2.h b/drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info-v2.h new file mode 100644 index 000000000000..dd2ca1949735 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info-v2.h @@ -0,0 +1,328 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright (C) 2026 Intel Corporation + */ +#ifndef __iwl_fw_api_context_info_v2_h__ +#define __iwl_fw_api_context_info_v2_h__ + +#include +#include +#include "ctxt-info.h" + +/* CSR addresses used by context info v2 */ +#define CSR_CTXT_INFO_BOOT_CTRL 0x0 +#define CSR_CTXT_INFO_ADDR 0x118 +#define CSR_IML_DATA_ADDR 0x120 +#define CSR_IML_SIZE_ADDR 0x128 +#define CSR_IML_RESP_ADDR 0x12c + +#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2 + +/* Set bit for enabling automatic function boot */ +#define CSR_AUTO_FUNC_BOOT_ENA BIT(1) +/* Set bit for initiating function boot */ +#define CSR_AUTO_FUNC_INIT BIT(7) + +/** + * enum iwl_prph_scratch_mtr_format - tfd size configuration + * @IWL_PRPH_MTR_FORMAT_16B: 16 bit tfd + * @IWL_PRPH_MTR_FORMAT_32B: 32 bit tfd + * @IWL_PRPH_MTR_FORMAT_64B: 64 bit tfd + * @IWL_PRPH_MTR_FORMAT_256B: 256 bit tfd + */ +enum iwl_prph_scratch_mtr_format { + IWL_PRPH_MTR_FORMAT_16B = 0x0, + IWL_PRPH_MTR_FORMAT_32B = 0x40000, + IWL_PRPH_MTR_FORMAT_64B = 0x80000, + IWL_PRPH_MTR_FORMAT_256B = 0xC0000, +}; + +/** + * enum iwl_prph_scratch_flags - PRPH scratch control flags + * @IWL_PRPH_SCRATCH_IMR_DEBUG_EN: IMR support for debug + * @IWL_PRPH_SCRATCH_EARLY_DEBUG_EN: enable early debug conf + * @IWL_PRPH_SCRATCH_EDBG_DEST_DRAM: use DRAM, with size allocated + * in hwm config. + * @IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL: use buffer on SRAM + * @IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER: use st arbiter, mainly for + * multicomm. + * @IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF: route debug data to SoC HW + * @IWL_PRPH_SCRATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K) + * @IWL_PRPH_SCRATCH_MTR_MODE: format used for completion - 0: for + * completion descriptor, 1 for responses (legacy) + * @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd. + * There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit, + * 3: 256 bit. + * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK: RB size full information, ignored + * by older firmware versions, so set IWL_PRPH_SCRATCH_RB_SIZE_4K + * appropriately; use the below values for this. + * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K: 8kB RB size + * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K: 12kB RB size + * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K: 16kB RB size + * @IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE: Indicate fw to set SCU_FORCE_ACTIVE + * upon reset. + * @IWL_PRPH_SCRATCH_TOP_RESET: request TOP reset + */ +enum iwl_prph_scratch_flags { + IWL_PRPH_SCRATCH_IMR_DEBUG_EN = BIT(1), + IWL_PRPH_SCRATCH_EARLY_DEBUG_EN = BIT(4), + IWL_PRPH_SCRATCH_EDBG_DEST_DRAM = BIT(8), + IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL = BIT(9), + IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER = BIT(10), + IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF = BIT(11), + IWL_PRPH_SCRATCH_RB_SIZE_4K = BIT(16), + IWL_PRPH_SCRATCH_MTR_MODE = BIT(17), + IWL_PRPH_SCRATCH_MTR_FORMAT = BIT(18) | BIT(19), + IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK = 0xf << 20, + IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K = 8 << 20, + IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K = 9 << 20, + IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K = 10 << 20, + IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE = BIT(29), + IWL_PRPH_SCRATCH_TOP_RESET = BIT(30), +}; + +/** + * enum iwl_prph_scratch_ext_flags - PRPH scratch control ext flags + * @IWL_PRPH_SCRATCH_EXT_EXT_FSEQ: external FSEQ image provided + * @IWL_PRPH_SCRATCH_EXT_URM_FW: switch to URM mode based on fw setting + * @IWL_PRPH_SCRATCH_EXT_URM_PERM: switch to permanent URM mode + * @IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID: use external 32 KHz clock + */ +enum iwl_prph_scratch_ext_flags { + IWL_PRPH_SCRATCH_EXT_EXT_FSEQ = BIT(0), + IWL_PRPH_SCRATCH_EXT_URM_FW = BIT(4), + IWL_PRPH_SCRATCH_EXT_URM_PERM = BIT(5), + IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID = BIT(8), +}; + +/** + * struct iwl_prph_scratch_version - version structure + * @mac_id: SKU and revision id + * @version: prph scratch information version id + * @size: the size of the context information in DWs + * @reserved: reserved + */ +struct iwl_prph_scratch_version { + __le16 mac_id; + __le16 version; + __le16 size; + __le16 reserved; +} __packed; /* PERIPH_SCRATCH_VERSION_S */ + +/** + * struct iwl_prph_scratch_control - control structure + * @control_flags: context information flags see &enum iwl_prph_scratch_flags + * @control_flags_ext: context information for extended flags, + * see &enum iwl_prph_scratch_ext_flags + */ +struct iwl_prph_scratch_control { + __le32 control_flags; + __le32 control_flags_ext; +} __packed; /* PERIPH_SCRATCH_CONTROL_S */ + +/** + * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch + * @pnvm_base_addr: PNVM start address + * @pnvm_size: the size of the PNVM image in bytes + * @reserved: reserved + */ +struct iwl_prph_scratch_pnvm_cfg { + __le64 pnvm_base_addr; + __le32 pnvm_size; + __le32 reserved; +} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */ + +/** + * struct iwl_prph_scratch_mem_desc_addr_array - DRAM + * @mem_descs: array of dram addresses. + * Each address is the beginning of a PNVM payload. + */ +struct iwl_prph_scratch_mem_desc_addr_array { + __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX]; +} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */ + +/** + * struct iwl_prph_scratch_hwm_cfg - hwm config + * @hwm_base_addr: hwm start address + * @hwm_size: hwm size in DWs + * @debug_token_config: debug preset + */ +struct iwl_prph_scratch_hwm_cfg { + __le64 hwm_base_addr; + __le32 hwm_size; + __le32 debug_token_config; +} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */ + +/** + * struct iwl_prph_scratch_rbd_cfg - RBDs configuration + * @free_rbd_addr: default queue free RB CB base address + * @reserved: reserved + */ +struct iwl_prph_scratch_rbd_cfg { + __le64 free_rbd_addr; + __le32 reserved; +} __packed; /* PERIPH_SCRATCH_RBD_CFG_S */ + +/** + * struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table + * @base_addr: reduce power table address + * @size: the size of the entire power table image + * @reserved: (reserved) + */ +struct iwl_prph_scratch_uefi_cfg { + __le64 base_addr; + __le32 size; + __le32 reserved; +} __packed; /* PERIPH_SCRATCH_UEFI_CFG_S */ + +/** + * struct iwl_prph_scratch_step_cfg - prph scratch step configuration + * @mbx_addr_0: [0:7] revision, + * [8:15] cnvi_to_cnvr length, + * [16:23] cnvr_to_cnvi channel length, + * [24:31] radio1 reserved + * @mbx_addr_1: [0:7] radio2 reserved + */ +struct iwl_prph_scratch_step_cfg { + __le32 mbx_addr_0; + __le32 mbx_addr_1; +} __packed; + +/** + * struct iwl_prph_scratch_ctrl_cfg - prph scratch ctrl and config + * @version: version information of context info and HW + * @control: control flags of FH configurations + * @pnvm_cfg: ror configuration + * @hwm_cfg: hwm configuration + * @rbd_cfg: default RX queue configuration + * @reduce_power_cfg: UEFI power reduction table + * @step_cfg: step configuration + */ +struct iwl_prph_scratch_ctrl_cfg { + struct iwl_prph_scratch_version version; + struct iwl_prph_scratch_control control; + struct iwl_prph_scratch_pnvm_cfg pnvm_cfg; + struct iwl_prph_scratch_hwm_cfg hwm_cfg; + struct iwl_prph_scratch_rbd_cfg rbd_cfg; + struct iwl_prph_scratch_uefi_cfg reduce_power_cfg; + struct iwl_prph_scratch_step_cfg step_cfg; +} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */ + +/** + * struct iwl_context_info_v2 - device INIT configuration + * @version: version of the context information + * @size: size of context information in DWs + * @config: context in which the peripheral would execute - a subset of + * capability csr register published by the peripheral + * @prph_info_base_addr: the peripheral information structure start address + * @cr_head_idx_arr_base_addr: the completion ring head index array + * start address + * @tr_tail_idx_arr_base_addr: the transfer ring tail index array + * start address + * @cr_tail_idx_arr_base_addr: the completion ring tail index array + * start address + * @tr_head_idx_arr_base_addr: the transfer ring head index array + * start address + * @cr_idx_arr_size: number of entries in the completion ring index array + * @tr_idx_arr_size: number of entries in the transfer ring index array + * @mtr_base_addr: the message transfer ring start address + * @mcr_base_addr: the message completion ring start address + * @mtr_size: number of entries which the message transfer ring can hold + * @mcr_size: number of entries which the message completion ring can hold + * @mtr_doorbell_vec: the doorbell vector associated with the message + * transfer ring + * @mcr_doorbell_vec: the doorbell vector associated with the message + * completion ring + * @mtr_msi_vec: the MSI which shall be generated by the peripheral after + * completing a transfer descriptor in the message transfer ring + * @mcr_msi_vec: the MSI which shall be generated by the peripheral after + * completing a completion descriptor in the message completion ring + * @mtr_opt_header_size: the size of the optional header in the transfer + * descriptor associated with the message transfer ring in DWs + * @mtr_opt_footer_size: the size of the optional footer in the transfer + * descriptor associated with the message transfer ring in DWs + * @mcr_opt_header_size: the size of the optional header in the completion + * descriptor associated with the message completion ring in DWs + * @mcr_opt_footer_size: the size of the optional footer in the completion + * descriptor associated with the message completion ring in DWs + * @msg_rings_ctrl_flags: message rings control flags + * @prph_info_msi_vec: the MSI which shall be generated by the peripheral + * after updating the Peripheral Information structure + * @prph_scratch_base_addr: the peripheral scratch structure start address + * @prph_scratch_size: the size of the peripheral scratch structure in DWs + * @reserved: reserved + */ +struct iwl_context_info_v2 { + __le16 version; + __le16 size; + __le32 config; + __le64 prph_info_base_addr; + __le64 cr_head_idx_arr_base_addr; + __le64 tr_tail_idx_arr_base_addr; + __le64 cr_tail_idx_arr_base_addr; + __le64 tr_head_idx_arr_base_addr; + __le16 cr_idx_arr_size; + __le16 tr_idx_arr_size; + __le64 mtr_base_addr; + __le64 mcr_base_addr; + __le16 mtr_size; + __le16 mcr_size; + __le16 mtr_doorbell_vec; + __le16 mcr_doorbell_vec; + __le16 mtr_msi_vec; + __le16 mcr_msi_vec; + u8 mtr_opt_header_size; + u8 mtr_opt_footer_size; + u8 mcr_opt_header_size; + u8 mcr_opt_footer_size; + __le16 msg_rings_ctrl_flags; + __le16 prph_info_msi_vec; + __le64 prph_scratch_base_addr; + __le32 prph_scratch_size; + __le32 reserved; +} __packed; /* IPC_CONTEXT_INFO_S */ + +#define IWL_NUM_DRAM_FSEQ_ENTRIES 8 + +/** + * struct iwl_context_info_dram_fseq - images DRAM map (with fseq) + * each entry in the map represents a DRAM chunk of up to 32 KB + * @common: UMAC/LMAC/virtual images + * @fseq_img: FSEQ image DRAM map + */ +struct iwl_context_info_dram_fseq { + struct iwl_context_info_dram_nonfseq common; + __le64 fseq_img[IWL_NUM_DRAM_FSEQ_ENTRIES]; +} __packed; /* PERIPH_SCRATCH_DRAM_MAP_S */ + +/** + * struct iwl_prph_scratch - peripheral scratch mapping + * @ctrl_cfg: control and configuration of prph scratch + * @dram: firmware images addresses in DRAM + * @fseq_override: FSEQ override parameters + * @step_analog_params: STEP analog calibration values + * @reserved: reserved + */ +struct iwl_prph_scratch { + struct iwl_prph_scratch_ctrl_cfg ctrl_cfg; + __le32 fseq_override; + __le32 step_analog_params; + __le32 reserved[8]; + struct iwl_context_info_dram_fseq dram; +} __packed; /* PERIPH_SCRATCH_S */ + +/** + * struct iwl_prph_info - peripheral information + * @boot_stage_mirror: reflects the value in the Boot Stage CSR register + * @ipc_status_mirror: reflects the value in the IPC Status CSR register + * @sleep_notif: indicates the peripheral sleep status + * @reserved: reserved + */ +struct iwl_prph_info { + __le32 boot_stage_mirror; + __le32 ipc_status_mirror; + __le32 sleep_notif; + __le32 reserved; +} __packed; /* PERIPH_INFO_S */ + +#endif /* __iwl_fw_api_context_info_v2_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info.h b/drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info.h new file mode 100644 index 000000000000..40a087b22150 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/ctxt-info.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* + * Copyright (C) 2026 Intel Corporation + */ +#ifndef __iwl_fw_api_context_info_h__ +#define __iwl_fw_api_context_info_h__ + +#include + +/* maximum number of DRAM map entries supported by FW */ +#define IWL_MAX_DRAM_ENTRY 64 +#define CSR_CTXT_INFO_BA 0x40 + +/** + * enum iwl_context_info_flags - Context information control flags + * @IWL_CTXT_INFO_AUTO_FUNC_INIT: If set, FW will not wait before interrupting + * the init done for driver command that configures several system modes + * @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug + * @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump + * @IWL_CTXT_INFO_RB_CB_SIZE: mask of the RBD Cyclic Buffer Size + * exponent, the actual size is 2**value, valid sizes are 8-2048. + * The value is four bits long. Maximum valid exponent is 12 + * @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the + * default is short format - not supported by the driver) + * @IWL_CTXT_INFO_RB_SIZE: RB size mask + * (values are IWL_CTXT_INFO_RB_SIZE_*K) + * @IWL_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size + * @IWL_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size + * @IWL_CTXT_INFO_RB_SIZE_4K: Value for 4K RB size + * @IWL_CTXT_INFO_RB_SIZE_8K: Value for 8K RB size + * @IWL_CTXT_INFO_RB_SIZE_12K: Value for 12K RB size + * @IWL_CTXT_INFO_RB_SIZE_16K: Value for 16K RB size + * @IWL_CTXT_INFO_RB_SIZE_20K: Value for 20K RB size + * @IWL_CTXT_INFO_RB_SIZE_24K: Value for 24K RB size + * @IWL_CTXT_INFO_RB_SIZE_28K: Value for 28K RB size + * @IWL_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size + */ +enum iwl_context_info_flags { + IWL_CTXT_INFO_AUTO_FUNC_INIT = 0x0001, + IWL_CTXT_INFO_EARLY_DEBUG = 0x0002, + IWL_CTXT_INFO_ENABLE_CDMP = 0x0004, + IWL_CTXT_INFO_RB_CB_SIZE = 0x00f0, + IWL_CTXT_INFO_TFD_FORMAT_LONG = 0x0100, + IWL_CTXT_INFO_RB_SIZE = 0x1e00, + IWL_CTXT_INFO_RB_SIZE_1K = 0x1, + IWL_CTXT_INFO_RB_SIZE_2K = 0x2, + IWL_CTXT_INFO_RB_SIZE_4K = 0x4, + IWL_CTXT_INFO_RB_SIZE_8K = 0x8, + IWL_CTXT_INFO_RB_SIZE_12K = 0x9, + IWL_CTXT_INFO_RB_SIZE_16K = 0xa, + IWL_CTXT_INFO_RB_SIZE_20K = 0xb, + IWL_CTXT_INFO_RB_SIZE_24K = 0xc, + IWL_CTXT_INFO_RB_SIZE_28K = 0xd, + IWL_CTXT_INFO_RB_SIZE_32K = 0xe, +}; + +/** + * struct iwl_context_info_version - version structure + * @mac_id: SKU and revision id + * @version: context information version id + * @size: the size of the context information in DWs + * @reserved: (reserved) + */ +struct iwl_context_info_version { + __le16 mac_id; + __le16 version; + __le16 size; + __le16 reserved; +} __packed; + +/** + * struct iwl_context_info_control - version structure + * @control_flags: context information flags see &enum iwl_context_info_flags + * @reserved: (reserved) + */ +struct iwl_context_info_control { + __le32 control_flags; + __le32 reserved; +} __packed; + +/** + * struct iwl_context_info_dram_nonfseq - images DRAM map + * each entry in the map represents a DRAM chunk of up to 32 KB + * @umac_img: UMAC image DRAM map + * @lmac_img: LMAC image DRAM map + * @virtual_img: paged image DRAM map + */ +struct iwl_context_info_dram_nonfseq { + __le64 umac_img[IWL_MAX_DRAM_ENTRY]; + __le64 lmac_img[IWL_MAX_DRAM_ENTRY]; + __le64 virtual_img[IWL_MAX_DRAM_ENTRY]; +} __packed; + +/** + * struct iwl_context_info_rbd_cfg - RBDs configuration + * @free_rbd_addr: default queue free RB CB base address + * @used_rbd_addr: default queue used RB CB base address + * @status_wr_ptr: default queue used RB status write pointer + */ +struct iwl_context_info_rbd_cfg { + __le64 free_rbd_addr; + __le64 used_rbd_addr; + __le64 status_wr_ptr; +} __packed; + +/** + * struct iwl_context_info_hcmd_cfg - command queue configuration + * @cmd_queue_addr: address of command queue + * @cmd_queue_size: number of entries + * @reserved: (reserved) + */ +struct iwl_context_info_hcmd_cfg { + __le64 cmd_queue_addr; + u8 cmd_queue_size; + u8 reserved[7]; +} __packed; + +/** + * struct iwl_context_info_dump_cfg - Core Dump configuration + * @core_dump_addr: core dump (debug DRAM address) start address + * @core_dump_size: size, in DWs + * @reserved: (reserved) + */ +struct iwl_context_info_dump_cfg { + __le64 core_dump_addr; + __le32 core_dump_size; + __le32 reserved; +} __packed; + +/** + * struct iwl_context_info_pnvm_cfg - platform NVM data configuration + * @platform_nvm_addr: Platform NVM data start address + * @platform_nvm_size: size in DWs + * @reserved: (reserved) + */ +struct iwl_context_info_pnvm_cfg { + __le64 platform_nvm_addr; + __le32 platform_nvm_size; + __le32 reserved; +} __packed; + +/** + * struct iwl_context_info_early_dbg_cfg - early debug configuration for + * dumping DRAM addresses + * @early_debug_addr: early debug start address + * @early_debug_size: size in DWs + * @reserved: (reserved) + */ +struct iwl_context_info_early_dbg_cfg { + __le64 early_debug_addr; + __le32 early_debug_size; + __le32 reserved; +} __packed; + +/** + * struct iwl_context_info - device INIT configuration + * @version: version information of context info and HW + * @control: control flags of FH configurations + * @reserved0: (reserved) + * @rbd_cfg: default RX queue configuration + * @hcmd_cfg: command queue configuration + * @reserved1: (reserved) + * @dump_cfg: core dump data + * @edbg_cfg: early debug configuration + * @pnvm_cfg: platform nvm configuration + * @reserved2: (reserved) + * @dram: firmware image addresses in DRAM + * @reserved3: (reserved) + */ +struct iwl_context_info { + struct iwl_context_info_version version; + struct iwl_context_info_control control; + __le64 reserved0; + struct iwl_context_info_rbd_cfg rbd_cfg; + struct iwl_context_info_hcmd_cfg hcmd_cfg; + __le32 reserved1[4]; + struct iwl_context_info_dump_cfg dump_cfg; + struct iwl_context_info_early_dbg_cfg edbg_cfg; + struct iwl_context_info_pnvm_cfg pnvm_cfg; + __le32 reserved2[16]; + struct iwl_context_info_dram_nonfseq dram; + __le32 reserved3[16]; +} __packed; /* BOOT_LOADER_CONTEXT_INFO_S */ + +#endif /* __iwl_fw_api_context_info_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h index 416baadc5017..a50e80cccadb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info-v2.h @@ -1,327 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2018, 2020-2025 Intel Corporation + * Copyright (C) 2018, 2020-2026 Intel Corporation */ #ifndef __iwl_context_info_file_v2_h__ #define __iwl_context_info_file_v2_h__ -#include "iwl-context-info.h" - -#define CSR_CTXT_INFO_BOOT_CTRL 0x0 -#define CSR_CTXT_INFO_ADDR 0x118 -#define CSR_IML_DATA_ADDR 0x120 -#define CSR_IML_SIZE_ADDR 0x128 -#define CSR_IML_RESP_ADDR 0x12c - -#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2 - -/* Set bit for enabling automatic function boot */ -#define CSR_AUTO_FUNC_BOOT_ENA BIT(1) -/* Set bit for initiating function boot */ -#define CSR_AUTO_FUNC_INIT BIT(7) - -/** - * enum iwl_prph_scratch_mtr_format - tfd size configuration - * @IWL_PRPH_MTR_FORMAT_16B: 16 bit tfd - * @IWL_PRPH_MTR_FORMAT_32B: 32 bit tfd - * @IWL_PRPH_MTR_FORMAT_64B: 64 bit tfd - * @IWL_PRPH_MTR_FORMAT_256B: 256 bit tfd - */ -enum iwl_prph_scratch_mtr_format { - IWL_PRPH_MTR_FORMAT_16B = 0x0, - IWL_PRPH_MTR_FORMAT_32B = 0x40000, - IWL_PRPH_MTR_FORMAT_64B = 0x80000, - IWL_PRPH_MTR_FORMAT_256B = 0xC0000, -}; - -/** - * enum iwl_prph_scratch_flags - PRPH scratch control flags - * @IWL_PRPH_SCRATCH_IMR_DEBUG_EN: IMR support for debug - * @IWL_PRPH_SCRATCH_EARLY_DEBUG_EN: enable early debug conf - * @IWL_PRPH_SCRATCH_EDBG_DEST_DRAM: use DRAM, with size allocated - * in hwm config. - * @IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL: use buffer on SRAM - * @IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER: use st arbiter, mainly for - * multicomm. - * @IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF: route debug data to SoC HW - * @IWL_PRPH_SCRATCH_RB_SIZE_4K: Use 4K RB size (the default is 2K) - * @IWL_PRPH_SCRATCH_MTR_MODE: format used for completion - 0: for - * completion descriptor, 1 for responses (legacy) - * @IWL_PRPH_SCRATCH_MTR_FORMAT: a mask for the size of the tfd. - * There are 4 optional values: 0: 16 bit, 1: 32 bit, 2: 64 bit, - * 3: 256 bit. - * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK: RB size full information, ignored - * by older firmware versions, so set IWL_PRPH_SCRATCH_RB_SIZE_4K - * appropriately; use the below values for this. - * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K: 8kB RB size - * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K: 12kB RB size - * @IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K: 16kB RB size - * @IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE: Indicate fw to set SCU_FORCE_ACTIVE - * upon reset. - * @IWL_PRPH_SCRATCH_TOP_RESET: request TOP reset - */ -enum iwl_prph_scratch_flags { - IWL_PRPH_SCRATCH_IMR_DEBUG_EN = BIT(1), - IWL_PRPH_SCRATCH_EARLY_DEBUG_EN = BIT(4), - IWL_PRPH_SCRATCH_EDBG_DEST_DRAM = BIT(8), - IWL_PRPH_SCRATCH_EDBG_DEST_INTERNAL = BIT(9), - IWL_PRPH_SCRATCH_EDBG_DEST_ST_ARBITER = BIT(10), - IWL_PRPH_SCRATCH_EDBG_DEST_TB22DTF = BIT(11), - IWL_PRPH_SCRATCH_RB_SIZE_4K = BIT(16), - IWL_PRPH_SCRATCH_MTR_MODE = BIT(17), - IWL_PRPH_SCRATCH_MTR_FORMAT = BIT(18) | BIT(19), - IWL_PRPH_SCRATCH_RB_SIZE_EXT_MASK = 0xf << 20, - IWL_PRPH_SCRATCH_RB_SIZE_EXT_8K = 8 << 20, - IWL_PRPH_SCRATCH_RB_SIZE_EXT_12K = 9 << 20, - IWL_PRPH_SCRATCH_RB_SIZE_EXT_16K = 10 << 20, - IWL_PRPH_SCRATCH_SCU_FORCE_ACTIVE = BIT(29), - IWL_PRPH_SCRATCH_TOP_RESET = BIT(30), -}; - -/** - * enum iwl_prph_scratch_ext_flags - PRPH scratch control ext flags - * @IWL_PRPH_SCRATCH_EXT_EXT_FSEQ: external FSEQ image provided - * @IWL_PRPH_SCRATCH_EXT_URM_FW: switch to URM mode based on fw setting - * @IWL_PRPH_SCRATCH_EXT_URM_PERM: switch to permanent URM mode - * @IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID: use external 32 KHz clock - */ -enum iwl_prph_scratch_ext_flags { - IWL_PRPH_SCRATCH_EXT_EXT_FSEQ = BIT(0), - IWL_PRPH_SCRATCH_EXT_URM_FW = BIT(4), - IWL_PRPH_SCRATCH_EXT_URM_PERM = BIT(5), - IWL_PRPH_SCRATCH_EXT_32KHZ_CLK_VALID = BIT(8), -}; - -/** - * struct iwl_prph_scratch_version - version structure - * @mac_id: SKU and revision id - * @version: prph scratch information version id - * @size: the size of the context information in DWs - * @reserved: reserved - */ -struct iwl_prph_scratch_version { - __le16 mac_id; - __le16 version; - __le16 size; - __le16 reserved; -} __packed; /* PERIPH_SCRATCH_VERSION_S */ - -/** - * struct iwl_prph_scratch_control - control structure - * @control_flags: context information flags see &enum iwl_prph_scratch_flags - * @control_flags_ext: context information for extended flags, - * see &enum iwl_prph_scratch_ext_flags - */ -struct iwl_prph_scratch_control { - __le32 control_flags; - __le32 control_flags_ext; -} __packed; /* PERIPH_SCRATCH_CONTROL_S */ - -/** - * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch - * @pnvm_base_addr: PNVM start address - * @pnvm_size: the size of the PNVM image in bytes - * @reserved: reserved - */ -struct iwl_prph_scratch_pnvm_cfg { - __le64 pnvm_base_addr; - __le32 pnvm_size; - __le32 reserved; -} __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */ - -/** - * struct iwl_prph_scratch_mem_desc_addr_array - DRAM - * @mem_descs: array of dram addresses. - * Each address is the beginning of a PNVM payload. - */ -struct iwl_prph_scratch_mem_desc_addr_array { - __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX]; -} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */ - -/** - * struct iwl_prph_scratch_hwm_cfg - hwm config - * @hwm_base_addr: hwm start address - * @hwm_size: hwm size in DWs - * @debug_token_config: debug preset - */ -struct iwl_prph_scratch_hwm_cfg { - __le64 hwm_base_addr; - __le32 hwm_size; - __le32 debug_token_config; -} __packed; /* PERIPH_SCRATCH_HWM_CFG_S */ - -/** - * struct iwl_prph_scratch_rbd_cfg - RBDs configuration - * @free_rbd_addr: default queue free RB CB base address - * @reserved: reserved - */ -struct iwl_prph_scratch_rbd_cfg { - __le64 free_rbd_addr; - __le32 reserved; -} __packed; /* PERIPH_SCRATCH_RBD_CFG_S */ - -/** - * struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table - * @base_addr: reduce power table address - * @size: the size of the entire power table image - * @reserved: (reserved) - */ -struct iwl_prph_scratch_uefi_cfg { - __le64 base_addr; - __le32 size; - __le32 reserved; -} __packed; /* PERIPH_SCRATCH_UEFI_CFG_S */ - -/** - * struct iwl_prph_scratch_step_cfg - prph scratch step configuration - * @mbx_addr_0: [0:7] revision, - * [8:15] cnvi_to_cnvr length, - * [16:23] cnvr_to_cnvi channel length, - * [24:31] radio1 reserved - * @mbx_addr_1: [0:7] radio2 reserved - */ - -struct iwl_prph_scratch_step_cfg { - __le32 mbx_addr_0; - __le32 mbx_addr_1; -} __packed; - -/** - * struct iwl_prph_scratch_ctrl_cfg - prph scratch ctrl and config - * @version: version information of context info and HW - * @control: control flags of FH configurations - * @pnvm_cfg: ror configuration - * @hwm_cfg: hwm configuration - * @rbd_cfg: default RX queue configuration - * @reduce_power_cfg: UEFI power reduction table - * @step_cfg: step configuration - */ -struct iwl_prph_scratch_ctrl_cfg { - struct iwl_prph_scratch_version version; - struct iwl_prph_scratch_control control; - struct iwl_prph_scratch_pnvm_cfg pnvm_cfg; - struct iwl_prph_scratch_hwm_cfg hwm_cfg; - struct iwl_prph_scratch_rbd_cfg rbd_cfg; - struct iwl_prph_scratch_uefi_cfg reduce_power_cfg; - struct iwl_prph_scratch_step_cfg step_cfg; -} __packed; /* PERIPH_SCRATCH_CTRL_CFG_S */ - -#define IWL_NUM_DRAM_FSEQ_ENTRIES 8 - -/** - * struct iwl_context_info_dram_fseq - images DRAM map (with fseq) - * each entry in the map represents a DRAM chunk of up to 32 KB - * @common: UMAC/LMAC/virtual images - * @fseq_img: FSEQ image DRAM map - */ -struct iwl_context_info_dram_fseq { - struct iwl_context_info_dram_nonfseq common; - __le64 fseq_img[IWL_NUM_DRAM_FSEQ_ENTRIES]; -} __packed; /* PERIPH_SCRATCH_DRAM_MAP_S */ - -/** - * struct iwl_prph_scratch - peripheral scratch mapping - * @ctrl_cfg: control and configuration of prph scratch - * @dram: firmware images addresses in DRAM - * @fseq_override: FSEQ override parameters - * @step_analog_params: STEP analog calibration values - * @reserved: reserved - */ -struct iwl_prph_scratch { - struct iwl_prph_scratch_ctrl_cfg ctrl_cfg; - __le32 fseq_override; - __le32 step_analog_params; - __le32 reserved[8]; - struct iwl_context_info_dram_fseq dram; -} __packed; /* PERIPH_SCRATCH_S */ - -/** - * struct iwl_prph_info - peripheral information - * @boot_stage_mirror: reflects the value in the Boot Stage CSR register - * @ipc_status_mirror: reflects the value in the IPC Status CSR register - * @sleep_notif: indicates the peripheral sleep status - * @reserved: reserved - */ -struct iwl_prph_info { - __le32 boot_stage_mirror; - __le32 ipc_status_mirror; - __le32 sleep_notif; - __le32 reserved; -} __packed; /* PERIPH_INFO_S */ - -/** - * struct iwl_context_info_v2 - device INIT configuration - * @version: version of the context information - * @size: size of context information in DWs - * @config: context in which the peripheral would execute - a subset of - * capability csr register published by the peripheral - * @prph_info_base_addr: the peripheral information structure start address - * @cr_head_idx_arr_base_addr: the completion ring head index array - * start address - * @tr_tail_idx_arr_base_addr: the transfer ring tail index array - * start address - * @cr_tail_idx_arr_base_addr: the completion ring tail index array - * start address - * @tr_head_idx_arr_base_addr: the transfer ring head index array - * start address - * @cr_idx_arr_size: number of entries in the completion ring index array - * @tr_idx_arr_size: number of entries in the transfer ring index array - * @mtr_base_addr: the message transfer ring start address - * @mcr_base_addr: the message completion ring start address - * @mtr_size: number of entries which the message transfer ring can hold - * @mcr_size: number of entries which the message completion ring can hold - * @mtr_doorbell_vec: the doorbell vector associated with the message - * transfer ring - * @mcr_doorbell_vec: the doorbell vector associated with the message - * completion ring - * @mtr_msi_vec: the MSI which shall be generated by the peripheral after - * completing a transfer descriptor in the message transfer ring - * @mcr_msi_vec: the MSI which shall be generated by the peripheral after - * completing a completion descriptor in the message completion ring - * @mtr_opt_header_size: the size of the optional header in the transfer - * descriptor associated with the message transfer ring in DWs - * @mtr_opt_footer_size: the size of the optional footer in the transfer - * descriptor associated with the message transfer ring in DWs - * @mcr_opt_header_size: the size of the optional header in the completion - * descriptor associated with the message completion ring in DWs - * @mcr_opt_footer_size: the size of the optional footer in the completion - * descriptor associated with the message completion ring in DWs - * @msg_rings_ctrl_flags: message rings control flags - * @prph_info_msi_vec: the MSI which shall be generated by the peripheral - * after updating the Peripheral Information structure - * @prph_scratch_base_addr: the peripheral scratch structure start address - * @prph_scratch_size: the size of the peripheral scratch structure in DWs - * @reserved: reserved - */ -struct iwl_context_info_v2 { - __le16 version; - __le16 size; - __le32 config; - __le64 prph_info_base_addr; - __le64 cr_head_idx_arr_base_addr; - __le64 tr_tail_idx_arr_base_addr; - __le64 cr_tail_idx_arr_base_addr; - __le64 tr_head_idx_arr_base_addr; - __le16 cr_idx_arr_size; - __le16 tr_idx_arr_size; - __le64 mtr_base_addr; - __le64 mcr_base_addr; - __le16 mtr_size; - __le16 mcr_size; - __le16 mtr_doorbell_vec; - __le16 mcr_doorbell_vec; - __le16 mtr_msi_vec; - __le16 mcr_msi_vec; - u8 mtr_opt_header_size; - u8 mtr_opt_footer_size; - u8 mcr_opt_header_size; - u8 mcr_opt_footer_size; - __le16 msg_rings_ctrl_flags; - __le16 prph_info_msi_vec; - __le64 prph_scratch_base_addr; - __le32 prph_scratch_size; - __le32 reserved; -} __packed; /* IPC_CONTEXT_INFO_S */ +#include "fw/api/ctxt-info-v2.h" int iwl_pcie_ctxt_info_v2_alloc(struct iwl_trans *trans, const struct iwl_fw *fw, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h index 7ae0fbdef208..562c023cbf2c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/iwl-context-info.h @@ -1,185 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020, 2022, 2024-2025 Intel Corporation + * Copyright (C) 2018-2020, 2022, 2024-2026 Intel Corporation */ #ifndef __iwl_context_info_file_h__ #define __iwl_context_info_file_h__ -/* maximum number of DRAM map entries supported by FW */ -#define IWL_MAX_DRAM_ENTRY 64 -#define CSR_CTXT_INFO_BA 0x40 - -/** - * enum iwl_context_info_flags - Context information control flags - * @IWL_CTXT_INFO_AUTO_FUNC_INIT: If set, FW will not wait before interrupting - * the init done for driver command that configures several system modes - * @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug - * @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump - * @IWL_CTXT_INFO_RB_CB_SIZE: mask of the RBD Cyclic Buffer Size - * exponent, the actual size is 2**value, valid sizes are 8-2048. - * The value is four bits long. Maximum valid exponent is 12 - * @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the - * default is short format - not supported by the driver) - * @IWL_CTXT_INFO_RB_SIZE: RB size mask - * (values are IWL_CTXT_INFO_RB_SIZE_*K) - * @IWL_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size - * @IWL_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size - * @IWL_CTXT_INFO_RB_SIZE_4K: Value for 4K RB size - * @IWL_CTXT_INFO_RB_SIZE_8K: Value for 8K RB size - * @IWL_CTXT_INFO_RB_SIZE_12K: Value for 12K RB size - * @IWL_CTXT_INFO_RB_SIZE_16K: Value for 16K RB size - * @IWL_CTXT_INFO_RB_SIZE_20K: Value for 20K RB size - * @IWL_CTXT_INFO_RB_SIZE_24K: Value for 24K RB size - * @IWL_CTXT_INFO_RB_SIZE_28K: Value for 28K RB size - * @IWL_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size - */ -enum iwl_context_info_flags { - IWL_CTXT_INFO_AUTO_FUNC_INIT = 0x0001, - IWL_CTXT_INFO_EARLY_DEBUG = 0x0002, - IWL_CTXT_INFO_ENABLE_CDMP = 0x0004, - IWL_CTXT_INFO_RB_CB_SIZE = 0x00f0, - IWL_CTXT_INFO_TFD_FORMAT_LONG = 0x0100, - IWL_CTXT_INFO_RB_SIZE = 0x1e00, - IWL_CTXT_INFO_RB_SIZE_1K = 0x1, - IWL_CTXT_INFO_RB_SIZE_2K = 0x2, - IWL_CTXT_INFO_RB_SIZE_4K = 0x4, - IWL_CTXT_INFO_RB_SIZE_8K = 0x8, - IWL_CTXT_INFO_RB_SIZE_12K = 0x9, - IWL_CTXT_INFO_RB_SIZE_16K = 0xa, - IWL_CTXT_INFO_RB_SIZE_20K = 0xb, - IWL_CTXT_INFO_RB_SIZE_24K = 0xc, - IWL_CTXT_INFO_RB_SIZE_28K = 0xd, - IWL_CTXT_INFO_RB_SIZE_32K = 0xe, -}; - -/** - * struct iwl_context_info_version - version structure - * @mac_id: SKU and revision id - * @version: context information version id - * @size: the size of the context information in DWs - * @reserved: (reserved) - */ -struct iwl_context_info_version { - __le16 mac_id; - __le16 version; - __le16 size; - __le16 reserved; -} __packed; - -/** - * struct iwl_context_info_control - version structure - * @control_flags: context information flags see &enum iwl_context_info_flags - * @reserved: (reserved) - */ -struct iwl_context_info_control { - __le32 control_flags; - __le32 reserved; -} __packed; - -/** - * struct iwl_context_info_dram_nonfseq - images DRAM map - * each entry in the map represents a DRAM chunk of up to 32 KB - * @umac_img: UMAC image DRAM map - * @lmac_img: LMAC image DRAM map - * @virtual_img: paged image DRAM map - */ -struct iwl_context_info_dram_nonfseq { - __le64 umac_img[IWL_MAX_DRAM_ENTRY]; - __le64 lmac_img[IWL_MAX_DRAM_ENTRY]; - __le64 virtual_img[IWL_MAX_DRAM_ENTRY]; -} __packed; - -/** - * struct iwl_context_info_rbd_cfg - RBDs configuration - * @free_rbd_addr: default queue free RB CB base address - * @used_rbd_addr: default queue used RB CB base address - * @status_wr_ptr: default queue used RB status write pointer - */ -struct iwl_context_info_rbd_cfg { - __le64 free_rbd_addr; - __le64 used_rbd_addr; - __le64 status_wr_ptr; -} __packed; - -/** - * struct iwl_context_info_hcmd_cfg - command queue configuration - * @cmd_queue_addr: address of command queue - * @cmd_queue_size: number of entries - * @reserved: (reserved) - */ -struct iwl_context_info_hcmd_cfg { - __le64 cmd_queue_addr; - u8 cmd_queue_size; - u8 reserved[7]; -} __packed; - -/** - * struct iwl_context_info_dump_cfg - Core Dump configuration - * @core_dump_addr: core dump (debug DRAM address) start address - * @core_dump_size: size, in DWs - * @reserved: (reserved) - */ -struct iwl_context_info_dump_cfg { - __le64 core_dump_addr; - __le32 core_dump_size; - __le32 reserved; -} __packed; - -/** - * struct iwl_context_info_pnvm_cfg - platform NVM data configuration - * @platform_nvm_addr: Platform NVM data start address - * @platform_nvm_size: size in DWs - * @reserved: (reserved) - */ -struct iwl_context_info_pnvm_cfg { - __le64 platform_nvm_addr; - __le32 platform_nvm_size; - __le32 reserved; -} __packed; - -/** - * struct iwl_context_info_early_dbg_cfg - early debug configuration for - * dumping DRAM addresses - * @early_debug_addr: early debug start address - * @early_debug_size: size in DWs - * @reserved: (reserved) - */ -struct iwl_context_info_early_dbg_cfg { - __le64 early_debug_addr; - __le32 early_debug_size; - __le32 reserved; -} __packed; - -/** - * struct iwl_context_info - device INIT configuration - * @version: version information of context info and HW - * @control: control flags of FH configurations - * @reserved0: (reserved) - * @rbd_cfg: default RX queue configuration - * @hcmd_cfg: command queue configuration - * @reserved1: (reserved) - * @dump_cfg: core dump data - * @edbg_cfg: early debug configuration - * @pnvm_cfg: platform nvm configuration - * @reserved2: (reserved) - * @dram: firmware image addresses in DRAM - * @reserved3: (reserved) - */ -struct iwl_context_info { - struct iwl_context_info_version version; - struct iwl_context_info_control control; - __le64 reserved0; - struct iwl_context_info_rbd_cfg rbd_cfg; - struct iwl_context_info_hcmd_cfg hcmd_cfg; - __le32 reserved1[4]; - struct iwl_context_info_dump_cfg dump_cfg; - struct iwl_context_info_early_dbg_cfg edbg_cfg; - struct iwl_context_info_pnvm_cfg pnvm_cfg; - __le32 reserved2[16]; - struct iwl_context_info_dram_nonfseq dram; - __le32 reserved3[16]; -} __packed; /* BOOT_LOADER_CONTEXT_INFO_S */ +#include "fw/api/ctxt-info.h" int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, const struct fw_img *img); void iwl_pcie_ctxt_info_free(struct iwl_trans *trans); From 96c80e5f1a7e77ac1e6d2fd044185fadb0f25292 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 11 Oct 2026 14:07:06 +0300 Subject: [PATCH 095/104] wifi: iwlwifi: mld: don't enable RSS if there is one queue. There is no point in RSS when we have only one rxq. Don't send the command in this case - RSS will be disabled by default. Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.dbeea799293f.I1c37945a248f101e0bca2cd723ce6551871926ab@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/fw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/fw.c b/drivers/net/wireless/intel/iwlwifi/mld/fw.c index 3b9f412cdff2..c33a553488ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/fw.c @@ -47,6 +47,9 @@ static int iwl_mld_send_rss_cfg_cmd(struct iwl_mld *mld) lockdep_assert_wiphy(mld->wiphy); + if (mld->trans->info.num_rxqs == 1) + return 0; + /* Do not direct RSS traffic to Q 0 which is our fallback queue */ for (int i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++) cmd.indirection_table[i] = From ea8d93d704dfae2f056fa2daf254aead2226e161 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 11 Oct 2026 14:07:07 +0300 Subject: [PATCH 096/104] wifi: iwlwifi: mvm: remove dead sta check in rx_monitor_no_data sta is never assigned in iwl_mvm_rx_monitor_no_data(), so the sta ? &sta->deflink : NULL expression is dead code. Drop the variable and pass NULL directly. Drop the unneeded RCU read lock, ieee80211_rx_napi() takes the RCU read lock on its own. Spotted by Coverity. Assisted-by: LLM Signed-off-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.2d0a56daefed.I2bd50c74f1f50e0fd87996333b804d2731dbd0fa@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index c01c704929ba..77a3d8dcab57 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -2427,7 +2427,6 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_no_data_ver_3 *desc = (void *)pkt->data; u32 rssi; - struct ieee80211_sta *sta = NULL; struct sk_buff *skb; struct iwl_mvm_rx_phy_data phy_data; u32 format; @@ -2541,9 +2540,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, RX_NO_DATA_RX_VEC2_EHT_NSTS_MSK) + 1; } - rcu_read_lock(); - ieee80211_rx_napi(mvm->hw, sta ? &sta->deflink : NULL, skb, napi); - rcu_read_unlock(); + ieee80211_rx_napi(mvm->hw, NULL, skb, napi); } void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, From aacf9ec032980ca75017e968fb9e125f7779556c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:08 +0300 Subject: [PATCH 097/104] wifi: iwlwifi: pcie: correctly read WFPM_OTP_CFG1_ADDR We shouldn't read this without having NIC access, which I had broken in the past. Enabling clang's context analysis now surfaced this bug. Luckily, it only applies to blank OTP devices, which aren't really common/shipping at all. Keep the value from earlier, and use zero (as in the past before I broke it) if it can't be read at all. Fixes: 0b205d0f0f50 ("wifi: iwlwifi: trans: remove hw_wfpm_id") Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.74912aba718d.I9568d08c280c0ca148c3918439c6beb8c4647a40@changeid Signed-off-by: Miri Korenblit --- .../net/wireless/intel/iwlwifi/pcie/trans.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index c905b6d5db3d..bd6e38d5f631 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3995,10 +3995,10 @@ int iwl_trans_pcie_copy_imr(struct iwl_trans *trans, * Read rf id and cdb info from prph register and store it */ static void get_crf_id(struct iwl_trans *iwl_trans, - struct iwl_trans_info *info) + struct iwl_trans_info *info, + u32 *hw_wfpm_id) { u32 sd_reg_ver_addr; - u32 hw_wfpm_id; u32 val = 0; u8 step; @@ -4064,10 +4064,10 @@ static void get_crf_id(struct iwl_trans *iwl_trans, } /* Read cdb info (also contains the jacket info if needed in the future */ - hw_wfpm_id = iwl_trans_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR); + *hw_wfpm_id = iwl_trans_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR); IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n", - info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id); + info->hw_crf_id, info->hw_cnv_id, *hw_wfpm_id); } /* @@ -4075,14 +4075,13 @@ static void get_crf_id(struct iwl_trans *iwl_trans, * from the prph registers. */ static int map_crf_id(struct iwl_trans *iwl_trans, - struct iwl_trans_info *info) + struct iwl_trans_info *info, + u32 hw_wfpm_id) { int ret = 0; u32 val = info->hw_crf_id; u32 step_id = REG_CRF_ID_STEP(val); u32 slave_id = REG_CRF_ID_SLAVE(val); - u32 hw_wfpm_id = iwl_trans_read_umac_prph_no_grab(iwl_trans, - WFPM_OTP_CFG1_ADDR); u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id); /* Map between crf id to rf id */ @@ -4195,6 +4194,7 @@ int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, }; struct iwl_trans *iwl_trans; struct iwl_trans_pcie *trans_pcie; + u32 hw_wfpm_id = 0; int ret; iwl_trans = iwl_trans_pcie_alloc(pdev, mac_cfg, &info, hw_base); @@ -4222,7 +4222,7 @@ int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, if (ret) goto out_free_trans; if (iwl_trans_grab_nic_access(iwl_trans)) { - get_crf_id(iwl_trans, &info); + get_crf_id(iwl_trans, &info, &hw_wfpm_id); /* all good */ iwl_trans_release_nic_access(iwl_trans); } else { @@ -4239,7 +4239,8 @@ int _iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent, * This is relevant only for family 9000 and up. */ if (iwl_trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 && - !CSR_HW_RFID_TYPE(info.hw_rf_id) && map_crf_id(iwl_trans, &info)) { + !CSR_HW_RFID_TYPE(info.hw_rf_id) && + map_crf_id(iwl_trans, &info, hw_wfpm_id)) { ret = -EINVAL; goto out_free_trans; } From 3bc32cd63c2072ef634d923c31cffa92dfe468a2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:09 +0300 Subject: [PATCH 098/104] wifi: iwlwifi: mld: avoid const in iwl_mld_chan_load_update_iter() The phy pointer here isn't really const, and if it were we'd need container_of_const() (which can do both), but as it's just non-const anyway drop the const. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.ccd4dbfffb5f.Id15631e4372d9495282634f89bd73e7f526ce2ce@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index a2f8a6957535..34273d4731ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -1076,9 +1076,9 @@ static void iwl_mld_chan_load_update_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { struct iwl_mld_chan_load_data *data = _data; - const struct iwl_mld_phy *phy = data->phy; + struct iwl_mld_phy *phy = data->phy; struct ieee80211_chanctx_conf *chanctx = - container_of((const void *)phy, struct ieee80211_chanctx_conf, + container_of((void *)phy, struct ieee80211_chanctx_conf, drv_priv); struct iwl_mld *mld = iwl_mld_vif_from_mac80211(vif)->mld; u32 new_chan_load = phy->avg_channel_load_not_by_us; From 3a0429065f62ed24fc51ef24c0d7a3f7def118e6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:10 +0300 Subject: [PATCH 099/104] wifi: iwlwifi: mld: fix const in iwl_mld_mu_mimo_iface_iterator ieee80211_update_mu_groups() takes const u8 * pointers, and we have const values, but remove the const which can lead to some warnings with clang. Leave it const throughout. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.6acceb79b0ef.Ia22765206364220b115dd84eb1a16b5a979d9340@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/notif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index 570b0011fd9e..7d9416ecbf92 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -159,8 +159,8 @@ static void iwl_mld_mu_mimo_iface_iterator(void *_data, u8 *mac, * action frame, so no conversion is needed. */ ieee80211_update_mu_groups(vif, link_id, - (u8 *)¬if->membership_status, - (u8 *)¬if->user_position); + (const u8 *)¬if->membership_status, + (const u8 *)¬if->user_position); } } From b750e75cb9267be3d98b44b1f3c76e4698ff3016 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:11 +0300 Subject: [PATCH 100/104] wifi: iwlwifi: mvm: fix beacon flags compiler warning With clang we can hit warnings here due to different enum types on the different sides of the ternary, but we don't really need to care because they're plain integer variables. Cast them to avoid the warnings. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.6ea24eaa784d.I91bab31db441f9e230228c3893ff13fd7fc3e7bf@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 58a77056e607..18372ddcc0e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -932,8 +932,8 @@ u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx) u16 flags = 0; if (rate_idx <= IWL_LAST_CCK_RATE) - flags |= is_new_rate ? IWL_MAC_BEACON_CCK - : IWL_MAC_BEACON_CCK_V1; + flags |= is_new_rate ? (u16)IWL_MAC_BEACON_CCK + : (u16)IWL_MAC_BEACON_CCK_V1; if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8) flags |= iwl_mvm_rate_idx_to_fw_idx(fw, rate_idx); @@ -1109,8 +1109,8 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, if (iwl_mvm_enable_fils(mvm, vif, ctx)) { flags |= iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 10 ? - IWL_MAC_BEACON_FILS : - IWL_MAC_BEACON_FILS_V1; + (u16)IWL_MAC_BEACON_FILS : + (u16)IWL_MAC_BEACON_FILS_V1; beacon_cmd.short_ssid = cpu_to_le32(~crc32_le(~0, vif->cfg.ssid, vif->cfg.ssid_len)); From 9811953945bceebf3e3362ee55227df0617d8ae0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:12 +0300 Subject: [PATCH 101/104] wifi: iwlwifi: mvm: uninline iwl_mvm_ftm_start versions This is not a performance-critical path, and with clang and KASAN it can use a lot of stack space. Uninline the various versions to avoid that. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.97f5c8503204.Ib88f908b0638889e84753ae334525c4c52064838@changeid Signed-off-by: Miri Korenblit --- .../intel/iwlwifi/mvm/ftm-initiator.c | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 4c39a452564d..dd1b80561f8c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -519,8 +519,9 @@ static int iwl_mvm_ftm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *hcmd) return err; } -static int iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v5 cmd_v5; struct iwl_host_cmd hcmd = { @@ -545,8 +546,9 @@ static int iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return iwl_mvm_ftm_send_cmd(mvm, &hcmd); } -static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v7 cmd_v7; struct iwl_host_cmd hcmd = { @@ -575,8 +577,9 @@ static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return iwl_mvm_ftm_send_cmd(mvm, &hcmd); } -static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v8 cmd; struct iwl_host_cmd hcmd = { @@ -601,8 +604,10 @@ static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return iwl_mvm_ftm_send_cmd(mvm, &hcmd); } -static int iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) + +static int noinline_for_stack +iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v9 cmd; struct iwl_host_cmd hcmd = { @@ -735,9 +740,10 @@ iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, &target->initiator_ap_flags); } -static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v11 cmd; struct iwl_host_cmd hcmd = { @@ -807,9 +813,10 @@ iwl_mvm_ftm_put_target_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return 0; } -static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v12 cmd; struct iwl_host_cmd hcmd = { @@ -835,9 +842,10 @@ static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm, return iwl_mvm_ftm_send_cmd(mvm, &hcmd); } -static int iwl_mvm_ftm_start_v13(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v13(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd_v13 cmd; struct iwl_host_cmd hcmd = { @@ -951,9 +959,10 @@ iwl_mvm_ftm_put_target_v10(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return 0; } -static int iwl_mvm_ftm_start_v14(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct cfg80211_pmsr_request *req) +static int noinline_for_stack +iwl_mvm_ftm_start_v14(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) { struct iwl_tof_range_req_cmd cmd; struct iwl_host_cmd hcmd = { From b359cbb421490e1221710665859bebe70fc614ad Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2026 14:07:13 +0300 Subject: [PATCH 102/104] wifi: iwlwifi: support SCD_QUEUE_CONFIG_CMD version 4 This version has a new flags field that must be set to indicate which other fields are valid, in preparation for moving queue pointers during SMD transition. Only set the IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK flag on the existing users of the command for now. Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.534cc32f2ac6.I394c38c58ad6619e3e52b52c3bc686acbbd2e4f1@changeid Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/fw/api/datapath.h | 20 ++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/mld/tx.c | 4 ++++ .../net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 3 ++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 3fbcb2e4bfe0..eddf13325df9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -608,6 +608,16 @@ enum iwl_scd_queue_cfg_operation { IWL_SCD_QUEUE_MODIFY = 2, }; +/** + * enum iwl_scd_queue_modify_flags - scheduler queue modify flags + * @IWL_SCD_QUEUE_MODIFY_FLAG_RD_PTR: update the read pointer + * @IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK: update the station mask + */ +enum iwl_scd_queue_modify_flags { + IWL_SCD_QUEUE_MODIFY_FLAG_RD_PTR = BIT(0), + IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK = BIT(1), +}; + /** * struct iwl_scd_queue_cfg_cmd - scheduler queue allocation command * @operation: the operation, see &enum iwl_scd_queue_cfg_operation @@ -625,6 +635,8 @@ enum iwl_scd_queue_cfg_operation { * @u.modify.old_sta_mask: old station mask for modify * @u.modify.tid: TID of queue to modify * @u.modify.new_sta_mask: new station mask for modify + * @u.modify.rd_ptr: new read pointer to set for the queue (version 4) + * @u.modify.flags: &enum iwl_scd_queue_modify_flags (version 4) */ struct iwl_scd_queue_cfg_cmd { __le32 operation; @@ -646,9 +658,11 @@ struct iwl_scd_queue_cfg_cmd { __le32 old_sta_mask; __le32 tid; __le32 new_sta_mask; - } __packed modify; /* TX_QUEUE_CFG_CMD_MODIFY_API_S_VER_1 */ - } __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1 */ -} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3 */ + __le16 rd_ptr; + __le16 flags; + } __packed modify; /* TX_QUEUE_CFG_CMD_MODIFY_API_S_VER_1, _VER_2 */ + } __packed u; /* TX_QUEUE_CFG_CMD_OPERATION_API_U_VER_1, _VER_2 */ +} __packed; /* TX_QUEUE_CFG_CMD_API_S_VER_3, _VER_4 */ /** * enum iwl_sec_key_flags - security key command key flags diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c index fc501ac0c1f2..44aa317b8e7d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c @@ -1484,6 +1484,10 @@ int iwl_mld_update_sta_txqs(struct iwl_mld *mld, lockdep_assert_wiphy(mld->wiphy); + if (mld->trans->conf.queue_alloc_cmd_ver >= 4) + cmd.u.modify.flags = + cpu_to_le16(IWL_SCD_QUEUE_MODIFY_FLAG_STA_MSK); + for (int tid = 0; tid <= IWL_MAX_TID_COUNT; tid++) { struct ieee80211_txq *txq = sta->txq[tid != IWL_MAX_TID_COUNT ? diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index e6bebd37417f..b235a4539d7c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -1075,7 +1075,8 @@ int iwl_txq_dyn_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask, hcmd.id = SCD_QUEUE_CFG; hcmd.len[0] = sizeof(cmd.old); hcmd.data[0] = &cmd.old; - } else if (trans->conf.queue_alloc_cmd_ver == 3) { + } else if (trans->conf.queue_alloc_cmd_ver == 3 || + trans->conf.queue_alloc_cmd_ver == 4) { memset(&cmd.new, 0, sizeof(cmd.new)); cmd.new.operation = cpu_to_le32(IWL_SCD_QUEUE_ADD); cmd.new.u.add.tfdq_dram_addr = cpu_to_le64(txq->dma_addr); From afbb3c6bd7010fa47844626540ce84c85dd65656 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 11 Oct 2026 14:07:14 +0300 Subject: [PATCH 103/104] wifi: iwlwifi: trans: remove the unused write8 operation Unlike the other bus operations, write8 has no generic wrapper and is never dispatched through trans->ops: all the callers are in the pcie code and call iwl_trans_pcie_write8() directly. Remove it. Assisted-by: LLM Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20261011140453.fecac6ba37d1.Icf8e741c8ccc6eff1abd046223b575c07f69aff5@changeid Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 -- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 5db07f1eab56..7a358daab584 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1237,7 +1237,6 @@ void iwl_trans_fw_reset_handshake(struct iwl_trans *trans); * @send_cmd: send a host command to the firmware * @alloc_tx_cmd: allocate a device TX command * @free_tx_cmd: free a device TX command - * @write8: write a byte to a device register * @write32: write a dword to a device register * @read32: read a dword from a device register * @read_prph: read a peripheral register @@ -1291,7 +1290,6 @@ struct iwl_trans_ops { void (*free_tx_cmd)(struct iwl_trans *trans, struct iwl_device_tx_cmd *dev_cmd); - void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); u32 (*read32)(struct iwl_trans *trans, u32 ofs); u32 (*read_prph)(struct iwl_trans *trans, u32 ofs); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index bd6e38d5f631..0f4e309fe32b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3704,7 +3704,6 @@ const struct iwl_trans_ops iwl_trans_pcie_ops = { .alloc_tx_cmd = iwl_pcie_alloc_tx_cmd, .free_tx_cmd = iwl_pcie_free_tx_cmd, - .write8 = iwl_trans_pcie_write8, .write32 = iwl_trans_pcie_write32, .read32 = iwl_trans_pcie_read32, .read_prph = iwl_trans_pcie_read_prph, From 3627924ed81fd7783394fb2555ea179c6606a231 Mon Sep 17 00:00:00 2001 From: Endrik Einberg Date: Mon, 5 Oct 2026 17:42:25 +0300 Subject: [PATCH 104/104] wifi: iwlwifi: mld: include VI packets in low latency detection iwl_mld_is_vo_vi_pkt() checks whether the mapped access category is less than IEEE80211_AC_VI. Since mac80211 defines IEEE80211_AC_VO as 0 and IEEE80211_AC_VI as 1, this only matches voice traffic and excludes video traffic. Synthetic video-priority UDP traffic does not automatically activate low-latency mode, whereas voice-priority traffic does Include IEEE80211_AC_VI as intended. Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver") Signed-off-by: Endrik Einberg Link: https://patch.msgid.link/20261005144225.170280-1-git@endrik.dev Signed-off-by: Miri Korenblit --- drivers/net/wireless/intel/iwlwifi/mld/low_latency.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c b/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c index a4ddc32e2860..e7482623111c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c @@ -257,7 +257,8 @@ static bool iwl_mld_is_vo_vi_pkt(struct ieee80211_hdr *hdr) if (tid >= IWL_MAX_TID_COUNT) return false; - return tid_to_mac80211_ac[tid] < IEEE80211_AC_VI; + return tid_to_mac80211_ac[tid] == IEEE80211_AC_VI || + tid_to_mac80211_ac[tid] == IEEE80211_AC_VO; } void iwl_mld_low_latency_update_counters(struct iwl_mld *mld,