iwlwifi features, notably:

- unused API cleanups
 - transport layer cleanups
 - new APIs support
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQQM3A3Pv7vbm9vtjWbacY7uyt+OfQUCaL/vOQAKCRDacY7uyt+O
 fToEAPwM+ZkLWMCIJnTRSpll8F9fCnlQRfce/QIGDMGWfXS2iQEA0yPfjqMbQXmI
 aVniE9m6xoOHHcF5V4M1J9mxO+QXQgA=
 =Cr9C
 -----END PGP SIGNATURE-----

Merge tag 'iwlwifi-next-2025-09-09' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

Miri Korenblit says:
====================
iwlwifi features, notably:

- unused API cleanups
- transport layer cleanups
- new APIs support
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2025-09-10 15:08:40 +02:00
commit 6f4f8abad4
35 changed files with 587 additions and 234 deletions

View File

@ -766,7 +766,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
{
int ret;
ret = iwl_finish_nic_init(trans);
ret = iwl_trans_activate_nic(trans);
if (ret)
return ret;

View File

@ -368,7 +368,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
priv->power_data.bus_pm = priv->trans->pm_support;
priv->power_data.bus_pm = iwl_trans_is_pm_supported(priv->trans);
priv->power_data.debug_sleep_level_override = -1;

View File

@ -632,9 +632,64 @@ struct iwl_wowlan_gtk_status_v3 {
struct iwl_wowlan_all_rsc_tsc_v5 sc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */
/**
* enum iwl_wowlan_key_status - Status of security keys in WoWLAN notifications
* @IWL_WOWLAN_NOTIF_NO_KEY: No key is present; this entry should be ignored.
* @IWL_WOWLAN_STATUS_OLD_KEY: old key exists; no rekey occurred, and only
* metadata is available.
* @IWL_WOWLAN_STATUS_NEW_KEY: A new key was created after a rekey; new key
* material is available.
*/
enum iwl_wowlan_key_status {
IWL_WOWLAN_NOTIF_NO_KEY = 0,
IWL_WOWLAN_STATUS_OLD_KEY = 1,
IWL_WOWLAN_STATUS_NEW_KEY = 2
};
/**
* struct iwl_wowlan_gtk_status - GTK status
* @key: GTK material
* @key_len: GTK length, if set to 0, the key is not available
* @key_flags: information about the key:
* bits[0:1]: key index assigned by the AP
* bits[2:6]: GTK index of the key in the internal DB
* bit[7]: Set iff this is the currently used GTK
* @key_status: key status, see &enum iwl_wowlan_key_status
* @reserved: padding
* @tkip_mic_key: TKIP RX MIC key
* @sc: RSC/TSC counters
*/
struct iwl_wowlan_gtk_status {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 key_len;
u8 key_flags;
u8 key_status;
u8 reserved;
u8 tkip_mic_key[IWL_MIC_KEY_SIZE];
struct iwl_wowlan_all_rsc_tsc_v5 sc;
} __packed; /* WOWLAN_GTK_MATERIAL_VER_4 */
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
#define IWL_WOWLAN_IGTK_BIGTK_IDX_MASK (BIT(0))
/**
* struct iwl_wowlan_igtk_status_v1 - IGTK status
* @key: IGTK material
* @ipn: the IGTK packet number (replay counter)
* @key_len: IGTK length, if set to 0, the key is not available
* @key_flags: information about the key:
* bits[0]: key index assigned by the AP (0: index 4, 1: index 5)
* (0: index 6, 1: index 7 with bigtk)
* bits[1:5]: IGTK index of the key in the internal DB
* bit[6]: Set iff this is the currently used IGTK
*/
struct iwl_wowlan_igtk_status_v1 {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 ipn[6];
u8 key_len;
u8 key_flags;
} __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */
/**
* struct iwl_wowlan_igtk_status - IGTK status
* @key: IGTK material
@ -645,13 +700,17 @@ struct iwl_wowlan_gtk_status_v3 {
* (0: index 6, 1: index 7 with bigtk)
* bits[1:5]: IGTK index of the key in the internal DB
* bit[6]: Set iff this is the currently used IGTK
* @key_status: key status, see &enum iwl_wowlan_key_status
* @reserved: padding
*/
struct iwl_wowlan_igtk_status {
u8 key[WOWLAN_KEY_MAX_SIZE];
u8 ipn[6];
u8 key_len;
u8 key_flags;
} __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */
u8 key_status;
u8 reserved[3];
} __packed; /* WOWLAN_IGTK_MATERIAL_VER_2 */
/**
* struct iwl_wowlan_status_v6 - WoWLAN status
@ -701,7 +760,7 @@ struct iwl_wowlan_status_v6 {
*/
struct iwl_wowlan_status_v7 {
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
__le64 replay_ctr;
__le16 pattern_number;
__le16 non_qos_seq_ctr;
@ -736,7 +795,7 @@ struct iwl_wowlan_status_v7 {
*/
struct iwl_wowlan_info_notif_v1 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
__le64 replay_ctr;
__le16 pattern_number;
__le16 reserved1;
@ -818,8 +877,8 @@ struct iwl_wowlan_mlo_gtk {
*/
struct iwl_wowlan_info_notif_v3 {
struct iwl_wowlan_gtk_status_v3 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_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
struct iwl_wowlan_igtk_status_v1 bigtk[WOWLAN_BIGTK_KEYS_NUM];
__le64 replay_ctr;
__le16 pattern_number;
__le16 reserved1;
@ -833,6 +892,45 @@ struct iwl_wowlan_info_notif_v3 {
u8 reserved2[2];
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3 */
/**
* struct iwl_wowlan_info_notif_v5 - 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_v5 {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM];
struct iwl_wowlan_igtk_status_v1 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_5 */
/**
* struct iwl_wowlan_info_notif - WoWLAN information notification
* @gtk: GTK data
@ -855,7 +953,7 @@ struct iwl_wowlan_info_notif_v3 {
* @mlo_gtks: array of GTKs of size num_mlo_link_keys
*/
struct iwl_wowlan_info_notif {
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
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;
@ -870,7 +968,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_5 */
} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */
/**
* struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification

View File

@ -420,6 +420,8 @@ struct iwl_mac_config_cmd {
* eht_support set to true. No longer used since _VER_3 of this command.
* @LINK_CONTEXT_MODIFY_BANDWIDTH: Covers iwl_link_ctx_cfg_cmd::modify_bandwidth.
* Request RX OMI to the AP to modify bandwidth of this link.
* @LINK_CONTEXT_MODIFY_UHR_PARAMS: covers iwl_link_ctx_cfg_cmd::npca_params and
* iwl_link_ctx_cfg_cmd::prio_edca_params. Since _VER_7.
* @LINK_CONTEXT_MODIFY_ALL: set all above flags
*/
enum iwl_link_ctx_modify_flags {
@ -432,6 +434,7 @@ enum iwl_link_ctx_modify_flags {
LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6),
LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7),
LINK_CONTEXT_MODIFY_BANDWIDTH = BIT(8),
LINK_CONTEXT_MODIFY_UHR_PARAMS = BIT(9),
LINK_CONTEXT_MODIFY_ALL = 0xff,
}; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */

View File

@ -20,7 +20,7 @@ enum iwl_prot_offload_subcmd_ids {
/**
* @WOWLAN_INFO_NOTIFICATION: Notification in
* &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3,
* or &struct iwl_wowlan_info_notif
* &struct iwl_wowlan_info_notif_v5 or &struct iwl_wowlan_info_notif
*/
WOWLAN_INFO_NOTIFICATION = 0xFD,

View File

@ -830,7 +830,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
}
/* reading RXF/TXF sizes */
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
if (iwl_trans_is_fw_error(fwrt->trans)) {
fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg);
fifo_len += iwl_fw_txf_len(fwrt, mem_cfg);
@ -3116,7 +3116,7 @@ static void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt,
.len[0] = sizeof(hcmd_data),
};
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
if (iwl_trans_is_fw_error(fwrt->trans))
return;
if (fw_has_capa(&fwrt->fw->ucode_capa,

View File

@ -178,7 +178,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
if (err)
return;
err = iwl_finish_nic_init(trans);
err = iwl_trans_activate_nic(trans);
if (err)
return;
}

View File

@ -59,11 +59,16 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
},
},
{ .ident = "ASUS",
{ .ident = "ASUSTEK",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
},
},
{ .ident = "ASUS",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
},
},
{ .ident = "GOOGLE-HP",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
@ -141,11 +146,16 @@ static const struct dmi_system_id dmi_tas_approved_list[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
},
},
{ .ident = "ASUS",
{ .ident = "ASUSTEK",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
},
},
{ .ident = "ASUS",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
},
},
{ .ident = "GOOGLE-HP",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"),

View File

@ -12,7 +12,6 @@
#include "fw/api/phy.h"
#include "fw/api/config.h"
#include "fw/api/nvm-reg.h"
#include "fw/img.h"
#include "iwl-trans.h"
#define BIOS_SAR_MAX_PROFILE_NUM 4

View File

@ -396,11 +396,11 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
return 0;
}
int iwl_finish_nic_init(struct iwl_trans *trans)
int iwl_trans_activate_nic(struct iwl_trans *trans)
{
return iwl_pcie_gen1_2_finish_nic_init(trans);
return iwl_pcie_gen1_2_activate_nic(trans);
}
IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
IWL_EXPORT_SYMBOL(iwl_trans_activate_nic);
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
u32 sw_err_bit)

View File

@ -57,7 +57,7 @@ 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);
int iwl_finish_nic_init(struct iwl_trans *trans);
int iwl_trans_activate_nic(struct iwl_trans *trans);
/* Error handling */
int iwl_dump_fh(struct iwl_trans *trans, char **buf);

View File

@ -139,50 +139,6 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
#define RATES_52_OFFS 4
#define N_RATES_52 (N_RATES_24 - RATES_52_OFFS)
/**
* enum iwl_nvm_channel_flags - channel flags in NVM
* @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
* @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
* @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and
* AP allowed only in 20 MHz. Valid only
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
* @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
* @NVM_CHANNEL_RADAR: radar detection required
* @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
* @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
* on same channel on 2.4 or same UNII band on 5.2
* @NVM_CHANNEL_UNIFORM: uniform spreading required
* @NVM_CHANNEL_20MHZ: 20 MHz channel okay
* @NVM_CHANNEL_40MHZ: 40 MHz channel okay
* @NVM_CHANNEL_80MHZ: 80 MHz channel okay
* @NVM_CHANNEL_160MHZ: 160 MHz channel okay
* @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
* @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
* @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
* @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed,
* Valid only when %NVM_CHANNEL_VLP is enabled.
*/
enum iwl_nvm_channel_flags {
NVM_CHANNEL_VALID = BIT(0),
NVM_CHANNEL_IBSS = BIT(1),
NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
NVM_CHANNEL_ACTIVE = BIT(3),
NVM_CHANNEL_RADAR = BIT(4),
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
NVM_CHANNEL_UNIFORM = BIT(7),
NVM_CHANNEL_20MHZ = BIT(8),
NVM_CHANNEL_40MHZ = BIT(9),
NVM_CHANNEL_80MHZ = BIT(10),
NVM_CHANNEL_160MHZ = BIT(11),
NVM_CHANNEL_DC_HIGH = BIT(12),
NVM_CHANNEL_VLP = BIT(13),
NVM_CHANNEL_AFC = BIT(14),
NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15),
};
/**
* enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory
* domain.
@ -282,30 +238,6 @@ enum iwl_reg_capa_flags_v4 {
*/
#define REG_CAPA_V4_RESP_VER 8
/**
* struct iwl_reg_capa - struct for global regulatory capabilities, Used for
* handling the different APIs of reg_capa_flags.
*
* @allow_40mhz: 11n channel with a width of 40Mhz is allowed
* for this regulatory domain.
* @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5 and 6 Ghz).
* @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5 and 6 Ghz).
* @allow_320mhz: 11be channel with a width of 320Mhz is allowed
* for this regulatory domain (valid only in 6 Ghz).
* @disable_11ax: 11ax is forbidden for this regulatory domain.
* @disable_11be: 11be is forbidden for this regulatory domain.
*/
struct iwl_reg_capa {
bool allow_40mhz;
bool allow_80mhz;
bool allow_160mhz;
bool allow_320mhz;
bool disable_11ax;
bool disable_11be;
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u32 flags)
{
@ -1596,9 +1528,10 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
}
IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
struct iwl_reg_capa reg_capa)
VISIBLE_IF_IWLWIFI_KUNIT
u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
struct iwl_reg_capa reg_capa)
{
u32 flags = NL80211_RRF_NO_HT40;
@ -1688,6 +1621,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
return flags;
}
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_nvm_get_regdom_bw_flags);
static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver)
{

View File

@ -21,6 +21,80 @@ enum iwl_nvm_sbands_flags {
IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ = BIT(1),
};
/**
* struct iwl_reg_capa - struct for global regulatory capabilities, Used for
* handling the different APIs of reg_capa_flags.
*
* @allow_40mhz: 11n channel with a width of 40Mhz is allowed
* for this regulatory domain.
* @allow_80mhz: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5 and 6 Ghz).
* @allow_160mhz: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5 and 6 Ghz).
* @allow_320mhz: 11be channel with a width of 320Mhz is allowed
* for this regulatory domain (valid only in 6 Ghz).
* @disable_11ax: 11ax is forbidden for this regulatory domain.
* @disable_11be: 11be is forbidden for this regulatory domain.
*/
struct iwl_reg_capa {
bool allow_40mhz;
bool allow_80mhz;
bool allow_160mhz;
bool allow_320mhz;
bool disable_11ax;
bool disable_11be;
};
/**
* enum iwl_nvm_channel_flags - channel flags in NVM
* @NVM_CHANNEL_VALID: channel is usable for this SKU/geo
* @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
* @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and
* AP allowed only in 20 MHz. Valid only
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
* @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS
* when %IWL_NVM_SBANDS_FLAGS_LAR enabled.
* @NVM_CHANNEL_RADAR: radar detection required
* @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed
* @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS
* on same channel on 2.4 or same UNII band on 5.2
* @NVM_CHANNEL_UNIFORM: uniform spreading required
* @NVM_CHANNEL_20MHZ: 20 MHz channel okay
* @NVM_CHANNEL_40MHZ: 40 MHz channel okay
* @NVM_CHANNEL_80MHZ: 80 MHz channel okay
* @NVM_CHANNEL_160MHZ: 160 MHz channel okay
* @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?)
* @NVM_CHANNEL_VLP: client support connection to UHB VLP AP
* @NVM_CHANNEL_AFC: client support connection to UHB AFC AP
* @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed,
* Valid only when %NVM_CHANNEL_VLP is enabled.
*/
enum iwl_nvm_channel_flags {
NVM_CHANNEL_VALID = BIT(0),
NVM_CHANNEL_IBSS = BIT(1),
NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2),
NVM_CHANNEL_ACTIVE = BIT(3),
NVM_CHANNEL_RADAR = BIT(4),
NVM_CHANNEL_INDOOR_ONLY = BIT(5),
NVM_CHANNEL_GO_CONCURRENT = BIT(6),
NVM_CHANNEL_UNIFORM = BIT(7),
NVM_CHANNEL_20MHZ = BIT(8),
NVM_CHANNEL_40MHZ = BIT(9),
NVM_CHANNEL_80MHZ = BIT(10),
NVM_CHANNEL_160MHZ = BIT(11),
NVM_CHANNEL_DC_HIGH = BIT(12),
NVM_CHANNEL_VLP = BIT(13),
NVM_CHANNEL_AFC = BIT(14),
NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15),
};
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
struct iwl_reg_capa reg_capa);
#endif
/*
* iwl_parse_nvm_data - parse NVM data and return values
*

View File

@ -807,3 +807,18 @@ void iwl_trans_set_reduce_power(struct iwl_trans *trans,
{
iwl_trans_pcie_ctx_info_v2_set_reduce_power(trans, capa);
}
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);
}
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);
}
IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);

View File

@ -284,8 +284,6 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
* @STATUS_RFKILL_OPMODE: RF-kill state reported to opmode
* @STATUS_FW_ERROR: the fw is in error state
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
* @STATUS_SUPPRESS_CMD_ERROR_ONCE: suppress "FW error in SYNC CMD" once,
* e.g. for testing
* @STATUS_IN_SW_RESET: device is undergoing reset, cleared by opmode
* via iwl_trans_finish_sw_reset()
* @STATUS_RESET_PENDING: reset worker was scheduled, but didn't dump
@ -302,7 +300,6 @@ enum iwl_trans_status {
STATUS_RFKILL_OPMODE,
STATUS_FW_ERROR,
STATUS_TRANS_DEAD,
STATUS_SUPPRESS_CMD_ERROR_ONCE,
STATUS_IN_SW_RESET,
STATUS_RESET_PENDING,
STATUS_TRANS_RESET_IN_PROGRESS,
@ -847,8 +844,8 @@ struct iwl_trans_info {
* @dev: pointer to struct device * that represents the device
* @info: device information for use by other layers
* @pnvm_loaded: indicates PNVM was loaded
* @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
* @suppress_cmd_error_once: suppress "FW error in SYNC CMD" once,
* e.g. for testing
* @fail_to_parse_pnvm_image: set to true if pnvm parsing failed
* @reduce_power_loaded: indicates reduced power section was loaded
* @failed_to_load_reduce_power_image: set to true if pnvm loading failed
@ -883,9 +880,8 @@ struct iwl_trans {
const struct iwl_trans_info info;
bool reduced_cap_sku;
bool step_urm;
bool suppress_cmd_error_once;
bool pm_support;
bool ltr_enabled;
u8 pnvm_loaded:1;
u8 fail_to_parse_pnvm_image:1;
u8 reduce_power_loaded:1;
@ -1194,11 +1190,6 @@ static inline u16 iwl_trans_get_num_rbds(struct iwl_trans *trans)
return result;
}
static inline void iwl_trans_suppress_cmd_error_once(struct iwl_trans *trans)
{
set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &trans->status);
}
static inline bool iwl_trans_device_enabled(struct iwl_trans *trans)
{
return test_bit(STATUS_DEVICE_ENABLED, &trans->status);
@ -1209,6 +1200,20 @@ static inline bool iwl_trans_is_dead(struct iwl_trans *trans)
return test_bit(STATUS_TRANS_DEAD, &trans->status);
}
static inline bool iwl_trans_is_fw_error(struct iwl_trans *trans)
{
return test_bit(STATUS_FW_ERROR, &trans->status);
}
/*
* This function notifies the transport layer of firmware error, the recovery
* will be handled by the op mode
*/
static inline void iwl_trans_notify_fw_error(struct iwl_trans *trans)
{
trans->state = IWL_TRANS_NO_FW;
set_bit(STATUS_FW_ERROR, &trans->status);
}
/*****************************************************
* PCIe handling
*****************************************************/
@ -1253,4 +1258,8 @@ static inline u16 iwl_trans_get_device_id(struct iwl_trans *trans)
return u32_get_bits(trans->info.hw_id, GENMASK(31, 16));
}
bool iwl_trans_is_pm_supported(struct iwl_trans *trans);
bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans);
#endif /* __iwl_trans_h__ */

View File

@ -300,13 +300,11 @@ enum iwl_sap_msg {
* @type: See &enum iwl_sap_msg.
* @len: The length of the message (header not included).
* @seq_num: For debug.
* @payload: The payload of the message.
*/
struct iwl_sap_hdr {
__le16 type;
__le16 len;
__le32 seq_num;
u8 payload[];
};
/**

View File

@ -281,7 +281,7 @@ iwl_mld_convert_gtk_resume_seq(struct iwl_mld_mcast_key_data *gtk_data,
static void
iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
struct iwl_mld_wowlan_status *wowlan_status,
const struct iwl_wowlan_gtk_status_v3 *gtk_data,
const struct iwl_wowlan_gtk_status *gtk_data,
const struct iwl_wowlan_all_rsc_tsc_v5 *sc)
{
int status_idx = 0;
@ -293,8 +293,9 @@ iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
for (int notif_idx = 0; notif_idx < ARRAY_SIZE(wowlan_status->gtk);
notif_idx++) {
int rsc_idx;
u8 key_status = gtk_data[notif_idx].key_status;
if (!(gtk_data[notif_idx].key_len))
if (!key_status)
continue;
wowlan_status->gtk[status_idx].len =
@ -304,10 +305,6 @@ iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
wowlan_status->gtk[status_idx].id =
wowlan_status->gtk[status_idx].flags &
IWL_WOWLAN_GTK_IDX_MASK;
memcpy(wowlan_status->gtk[status_idx].key,
gtk_data[notif_idx].key,
sizeof(gtk_data[notif_idx].key));
/* The rsc for both gtk keys are stored in gtk[0]->sc->mcast_rsc
* The gtk ids can be any two numbers between 0 and 3,
* the id_map maps between the key id and the index in sc->mcast
@ -317,13 +314,27 @@ iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
iwl_mld_convert_gtk_resume_seq(&wowlan_status->gtk[status_idx],
sc, rsc_idx);
/* if it's as long as the TKIP encryption key, copy MIC key */
if (wowlan_status->gtk[status_idx].len ==
NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
memcpy(wowlan_status->gtk[status_idx].key +
NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
gtk_data[notif_idx].tkip_mic_key,
sizeof(gtk_data[notif_idx].tkip_mic_key));
if (key_status == IWL_WOWLAN_STATUS_NEW_KEY) {
memcpy(wowlan_status->gtk[status_idx].key,
gtk_data[notif_idx].key,
sizeof(gtk_data[notif_idx].key));
/* if it's as long as the TKIP encryption key,
* copy MIC key
*/
if (wowlan_status->gtk[status_idx].len ==
NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
memcpy(wowlan_status->gtk[status_idx].key +
NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
gtk_data[notif_idx].tkip_mic_key,
sizeof(gtk_data[notif_idx].tkip_mic_key));
} else {
/* If the key status is WOWLAN_STATUS_OLD_KEY, it
* indicates that no key material is present, Set the
* key length to 0 as an indication
*/
wowlan_status->gtk[status_idx].len = 0;
}
status_idx++;
}
}
@ -370,11 +381,11 @@ static void
iwl_mld_convert_igtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
const struct iwl_wowlan_igtk_status *igtk)
{
BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key));
if (!igtk->key_len)
if (!igtk->key_status)
return;
BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key));
wowlan_status->igtk.len = igtk->key_len;
wowlan_status->igtk.flags = igtk->key_flags;
wowlan_status->igtk.id =
@ -382,7 +393,15 @@ iwl_mld_convert_igtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
IWL_WOWLAN_IGTK_BIGTK_IDX_MASK) +
WOWLAN_IGTK_MIN_INDEX;
memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key));
if (igtk->key_status == IWL_WOWLAN_STATUS_NEW_KEY)
memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key));
else
/* If the key status is WOWLAN_STATUS_OLD_KEY, it indicates
* that no key material is present. Set the key length to 0
* as an indication.
*/
wowlan_status->igtk.len = 0;
iwl_mld_convert_mcast_ipn(&wowlan_status->igtk, igtk);
}
@ -396,7 +415,7 @@ iwl_mld_convert_bigtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
for (int notif_idx = 0; notif_idx < WOWLAN_BIGTK_KEYS_NUM;
notif_idx++) {
if (!bigtk[notif_idx].key_len)
if (!bigtk[notif_idx].key_status)
continue;
wowlan_status->bigtk[status_idx].len = bigtk[notif_idx].key_len;
@ -409,8 +428,17 @@ iwl_mld_convert_bigtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
BUILD_BUG_ON(sizeof(wowlan_status->bigtk[status_idx].key) <
sizeof(bigtk[notif_idx].key));
memcpy(wowlan_status->bigtk[status_idx].key,
bigtk[notif_idx].key, sizeof(bigtk[notif_idx].key));
if (bigtk[notif_idx].key_status == IWL_WOWLAN_STATUS_NEW_KEY)
memcpy(wowlan_status->bigtk[status_idx].key,
bigtk[notif_idx].key,
sizeof(bigtk[notif_idx].key));
else
/* If the key status is WOWLAN_STATUS_OLD_KEY, it
* indicates that no key material is present. Set the
* key length to 0 as an indication.
*/
wowlan_status->bigtk[status_idx].len = 0;
iwl_mld_convert_mcast_ipn(&wowlan_status->bigtk[status_idx],
&bigtk[notif_idx]);
status_idx++;
@ -453,34 +481,165 @@ iwl_mld_convert_mlo_keys(struct iwl_mld *mld,
}
}
static void
iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5,
struct iwl_wowlan_info_notif *notif)
{
/* Convert GTK from v3 to the new format */
BUILD_BUG_ON(ARRAY_SIZE(notif->gtk) != ARRAY_SIZE(notif_v5->gtk));
for (int i = 0; i < ARRAY_SIZE(notif_v5->gtk); i++) {
const struct iwl_wowlan_gtk_status_v3 *gtk_v3 = &notif_v5->gtk[i];
struct iwl_wowlan_gtk_status *gtk = &notif->gtk[i];
/* Copy key material and metadata */
BUILD_BUG_ON(sizeof(gtk->key) != sizeof(gtk_v3->key));
BUILD_BUG_ON(sizeof(gtk->tkip_mic_key) != sizeof(gtk_v3->tkip_mic_key));
memcpy(gtk->key, gtk_v3->key, sizeof(gtk_v3->key));
gtk->key_len = gtk_v3->key_len;
gtk->key_flags = gtk_v3->key_flags;
memcpy(gtk->tkip_mic_key, gtk_v3->tkip_mic_key,
sizeof(gtk_v3->tkip_mic_key));
gtk->sc = gtk_v3->sc;
/* Set key_status based on whether key material is present.
* in v5, a key is either invalid (should be skipped) or has
* both meta data and the key itself.
*/
if (gtk_v3->key_len)
gtk->key_status = IWL_WOWLAN_STATUS_NEW_KEY;
}
/* Convert IGTK from v1 to the new format, only one IGTK is passed by FW */
BUILD_BUG_ON(offsetof(struct iwl_wowlan_igtk_status, key_status) !=
sizeof(struct iwl_wowlan_igtk_status_v1));
memcpy(&notif->igtk[0], &notif_v5->igtk[0],
offsetof(struct iwl_wowlan_igtk_status, key_status));
/* Set key_status based on whether key material is present.
* in v5, a key is either invalid (should be skipped) or has
* both meta data and the key itself.
*/
if (notif_v5->igtk[0].key_len)
notif->igtk[0].key_status = IWL_WOWLAN_STATUS_NEW_KEY;
/* Convert BIGTK from v1 to the new format */
BUILD_BUG_ON(ARRAY_SIZE(notif->bigtk) != ARRAY_SIZE(notif_v5->bigtk));
for (int i = 0; i < ARRAY_SIZE(notif_v5->bigtk); i++) {
/* Copy everything until key_status */
memcpy(&notif->bigtk[i], &notif_v5->bigtk[i],
offsetof(struct iwl_wowlan_igtk_status, key_status));
/* Set key_status based on whether key material is present.
* in v5, a key is either invalid (should be skipped) or has
* both meta data and the key itself.
*/
if (notif_v5->bigtk[i].key_len)
notif->bigtk[i].key_status = IWL_WOWLAN_STATUS_NEW_KEY;
}
notif->replay_ctr = notif_v5->replay_ctr;
notif->pattern_number = notif_v5->pattern_number;
notif->qos_seq_ctr = notif_v5->qos_seq_ctr;
notif->wakeup_reasons = notif_v5->wakeup_reasons;
notif->num_of_gtk_rekeys = notif_v5->num_of_gtk_rekeys;
notif->transmitted_ndps = notif_v5->transmitted_ndps;
notif->received_beacons = notif_v5->received_beacons;
notif->tid_tear_down = notif_v5->tid_tear_down;
notif->station_id = notif_v5->station_id;
notif->num_mlo_link_keys = notif_v5->num_mlo_link_keys;
notif->tid_offloaded_tx = notif_v5->tid_offloaded_tx;
/* Copy MLO GTK keys */
if (notif_v5->num_mlo_link_keys) {
memcpy(notif->mlo_gtks, notif_v5->mlo_gtks,
notif_v5->num_mlo_link_keys * sizeof(struct iwl_wowlan_mlo_gtk));
}
}
static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld,
u32 len,
u32 expected_len,
u8 num_mlo_keys,
int version)
{
u32 len_with_mlo_keys;
if (IWL_FW_CHECK(mld, len < expected_len,
"Invalid wowlan_info_notif v%d (expected=%u got=%u)\n",
version, expected_len, len))
return false;
len_with_mlo_keys = expected_len +
(num_mlo_keys * sizeof(struct iwl_wowlan_mlo_gtk));
if (IWL_FW_CHECK(mld, len < len_with_mlo_keys,
"Invalid wowlan_info_notif v%d with MLO keys (expected=%u got=%u)\n",
version, len_with_mlo_keys, len))
return false;
return true;
}
static bool
iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
struct iwl_mld_wowlan_status *wowlan_status,
struct iwl_rx_packet *pkt)
{
const struct iwl_wowlan_info_notif *notif = (void *)pkt->data;
const struct iwl_wowlan_info_notif *notif;
struct iwl_wowlan_info_notif *converted_notif __free(kfree) = NULL;
u32 len = iwl_rx_packet_payload_len(pkt);
u32 len_with_mlo_keys;
int wowlan_info_ver = iwl_fw_lookup_notif_ver(mld->fw,
PROT_OFFLOAD_GROUP,
WOWLAN_INFO_NOTIFICATION,
IWL_FW_CMD_VER_UNKNOWN);
if (IWL_FW_CHECK(mld, len < sizeof(*notif),
"Invalid wowlan_info_notif (expected=%zu got=%u)\n",
sizeof(*notif), len))
return true;
/* Now that we know that we have at least sizeof(notif),
* check also the variable length part
*/
len_with_mlo_keys = sizeof(*notif) +
notif->num_mlo_link_keys * sizeof(notif->mlo_gtks[0]);
if (IWL_FW_CHECK(mld, len < len_with_mlo_keys,
"Invalid wowlan_info_notif (expected=%ud got=%u)\n",
len_with_mlo_keys, len))
if (wowlan_info_ver == 5) {
/* v5 format - validate before conversion */
const struct iwl_wowlan_info_notif_v5 *notif_v5 = (void *)pkt->data;
if (!iwl_mld_validate_wowlan_notif_size(mld, len,
sizeof(*notif_v5),
notif_v5->num_mlo_link_keys,
5))
return true;
converted_notif = kzalloc(struct_size(converted_notif,
mlo_gtks,
notif_v5->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_v5(notif_v5,
converted_notif);
notif = converted_notif;
} else if (wowlan_info_ver == 6) {
notif = (void *)pkt->data;
if (!iwl_mld_validate_wowlan_notif_size(mld, len,
sizeof(*notif),
notif->num_mlo_link_keys,
6))
return true;
} else {
/* smaller versions are not supported */
IWL_WARN(mld,
"Unsupported wowlan_info_notif version %d\n",
wowlan_info_ver);
return true;
}
if (IWL_FW_CHECK(mld, notif->tid_offloaded_tx != IWL_WOWLAN_OFFLOAD_TID,
"Invalid tid_offloaded_tx %d\n",
wowlan_status->tid_offloaded_tx))
notif->tid_offloaded_tx))
return true;
iwl_mld_convert_gtk_resume_data(mld, wowlan_status, notif->gtk,
@ -1213,8 +1372,7 @@ static int iwl_mld_wait_d3_notif(struct iwl_mld *mld,
ret = iwl_trans_d3_resume(mld->trans, false);
if (ret) {
/* Avoid sending commands if the FW is dead */
mld->trans->state = IWL_TRANS_NO_FW;
set_bit(STATUS_FW_ERROR, &mld->trans->status);
iwl_trans_notify_fw_error(mld->trans);
iwl_remove_notification(&mld->notif_wait, &wait_d3_notif);
return ret;
}
@ -1267,8 +1425,7 @@ int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld)
if (ret) {
IWL_ERR(mld, "d3 suspend: trans_d3_suspend failed %d\n", ret);
/* We are going to stop the FW. Avoid sending commands in that flow */
mld->trans->state = IWL_TRANS_NO_FW;
set_bit(STATUS_FW_ERROR, &mld->trans->status);
iwl_trans_notify_fw_error(mld->trans);
} else {
/* Async notification might send hcmds, which is not allowed in suspend */
iwl_mld_cancel_async_notifications(mld);

View File

@ -86,7 +86,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mld *mld, char *buf,
if (count == 6 && !strcmp(buf, "nolog\n")) {
mld->fw_status.do_not_dump_once = true;
iwl_trans_suppress_cmd_error_once(mld->trans);
mld->trans->suppress_cmd_error_once = true;
}
/* take the return value to make compiler happy - it will
@ -1001,8 +1001,12 @@ void iwl_mld_add_link_debugfs(struct ieee80211_hw *hw,
* If not, this is a per-link dir of a MLO vif, add in it the iwlmld
* dir.
*/
if (!mld_link_dir)
if (!mld_link_dir) {
mld_link_dir = debugfs_create_dir("iwlmld", dir);
} else {
/* Release the reference from debugfs_lookup */
dput(mld_link_dir);
}
}
static ssize_t _iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,

View File

@ -115,20 +115,12 @@ static bool iwl_mld_is_nic_ack_enabled(struct iwl_mld *mld,
static void iwl_mld_set_he_support(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct iwl_mac_config_cmd *cmd,
int cmd_ver)
struct iwl_mac_config_cmd *cmd)
{
if (vif->type == NL80211_IFTYPE_AP) {
if (cmd_ver == 2)
cmd->wifi_gen_v2.he_ap_support = cpu_to_le16(1);
else
cmd->wifi_gen.he_ap_support = 1;
} else {
if (cmd_ver == 2)
cmd->wifi_gen_v2.he_support = cpu_to_le16(1);
else
cmd->wifi_gen.he_support = 1;
}
if (vif->type == NL80211_IFTYPE_AP)
cmd->wifi_gen.he_ap_support = 1;
else
cmd->wifi_gen.he_support = 1;
}
/* fill the common part for all interface types */
@ -140,9 +132,6 @@ static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
struct ieee80211_bss_conf *link_conf;
unsigned int link_id;
int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw,
WIDE_ID(MAC_CONF_GROUP,
MAC_CONFIG_CMD), 0);
lockdep_assert_wiphy(mld->wiphy);
@ -169,11 +158,8 @@ static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
* and enable both when we have MLO.
*/
if (ieee80211_vif_is_mld(vif)) {
iwl_mld_set_he_support(mld, vif, cmd, cmd_ver);
if (cmd_ver == 2)
cmd->wifi_gen_v2.eht_support = cpu_to_le32(1);
else
cmd->wifi_gen.eht_support = 1;
iwl_mld_set_he_support(mld, vif, cmd);
cmd->wifi_gen.eht_support = 1;
return;
}
@ -181,7 +167,7 @@ static void iwl_mld_mac_cmd_fill_common(struct iwl_mld *mld,
if (!link_conf->he_support)
continue;
iwl_mld_set_he_support(mld, vif, cmd, cmd_ver);
iwl_mld_set_he_support(mld, vif, cmd);
/* EHT, if supported, was already set above */
break;

View File

@ -626,7 +626,7 @@ int iwl_mld_mac80211_add_interface(struct ieee80211_hw *hw,
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
}
if (vif->p2p || iwl_fw_lookup_cmd_ver(mld->fw, PHY_CONTEXT_CMD, 0) < 5)
if (vif->p2p)
vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW;
/*

View File

@ -357,38 +357,26 @@ iwl_mld_vif_iter_emlsr_mode_notif(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
const struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
enum iwl_mvm_fw_esr_recommendation action;
const struct iwl_esr_mode_notif *notif = NULL;
if (iwl_fw_lookup_notif_ver(mld_vif->mld->fw, DATA_PATH_GROUP,
ESR_MODE_NOTIF, 0) > 1) {
notif = (void *)data;
action = le32_to_cpu(notif->action);
} else {
const struct iwl_esr_mode_notif_v1 *notif_v1 = (void *)data;
action = le32_to_cpu(notif_v1->action);
}
const struct iwl_esr_mode_notif *notif = (void *)data;
enum iwl_mvm_fw_esr_recommendation action = le32_to_cpu(notif->action);
if (!iwl_mld_vif_has_emlsr_cap(vif))
return;
switch (action) {
case ESR_RECOMMEND_LEAVE:
if (notif)
IWL_DEBUG_INFO(mld_vif->mld,
"FW recommend leave reason = 0x%x\n",
le32_to_cpu(notif->leave_reason_mask));
IWL_DEBUG_INFO(mld_vif->mld,
"FW recommend leave reason = 0x%x\n",
le32_to_cpu(notif->leave_reason_mask));
iwl_mld_exit_emlsr(mld_vif->mld, vif,
IWL_MLD_EMLSR_EXIT_FW_REQUEST,
iwl_mld_get_primary_link(vif));
break;
case ESR_FORCE_LEAVE:
if (notif)
IWL_DEBUG_INFO(mld_vif->mld,
"FW force leave reason = 0x%x\n",
le32_to_cpu(notif->leave_reason_mask));
IWL_DEBUG_INFO(mld_vif->mld,
"FW force leave reason = 0x%x\n",
le32_to_cpu(notif->leave_reason_mask));
fallthrough;
case ESR_RECOMMEND_ENTER:
default:

View File

@ -333,7 +333,6 @@ CMD_VERSIONS(bt_coex_notif,
CMD_VERSIONS(beacon_notification,
CMD_VER_ENTRY(6, iwl_extended_beacon_notif))
CMD_VERSIONS(emlsr_mode_notif,
CMD_VER_ENTRY(1, iwl_esr_mode_notif_v1)
CMD_VER_ENTRY(2, iwl_esr_mode_notif))
CMD_VERSIONS(emlsr_trans_fail_notif,
CMD_VER_ENTRY(1, iwl_esr_trans_fail_notif))

View File

@ -82,9 +82,6 @@ int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct iwl_roc_req cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
};
u8 ver = iwl_fw_lookup_cmd_ver(mld->fw,
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd);
enum iwl_roc_activity activity;
int ret = 0;
@ -140,7 +137,7 @@ int iwl_mld_start_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
memcpy(cmd.node_addr, vif->addr, ETH_ALEN);
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
&cmd, cmd_len);
&cmd);
if (ret) {
IWL_ERR(mld, "Couldn't send the ROC_CMD\n");
return ret;
@ -190,9 +187,6 @@ int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
struct iwl_roc_req cmd = {
.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
};
u8 ver = iwl_fw_lookup_cmd_ver(mld->fw,
WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0);
u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd);
int ret;
lockdep_assert_wiphy(mld->wiphy);
@ -208,7 +202,7 @@ int iwl_mld_cancel_roc(struct ieee80211_hw *hw,
cmd.activity = cpu_to_le32(mld_vif->roc_activity);
ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD),
&cmd, cmd_len);
&cmd);
if (ret)
IWL_ERR(mld, "Couldn't send the command to cancel the ROC\n");

View File

@ -504,9 +504,7 @@ iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld,
*/
if (scan_status == IWL_MLD_SCAN_REGULAR &&
ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP &&
gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE &&
iwl_fw_lookup_notif_ver(mld->fw, SCAN_GROUP,
CHANNEL_SURVEY_NOTIF, 0) >= 1)
gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE)
flags |= IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS;
return flags;

View File

@ -401,11 +401,9 @@ static u32 iwl_mld_get_htc_flags(struct ieee80211_link_sta *link_sta)
static int iwl_mld_send_sta_cmd(struct iwl_mld *mld,
const struct iwl_sta_cfg_cmd *cmd)
{
u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD);
int cmd_len = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0) > 1 ?
sizeof(*cmd) :
sizeof(struct iwl_sta_cfg_cmd_v1);
int ret = iwl_mld_send_cmd_pdu(mld, cmd_id, cmd, cmd_len);
int ret = iwl_mld_send_cmd_pdu(mld,
WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD),
cmd);
if (ret)
IWL_ERR(mld, "STA_CONFIG_CMD send failed, ret=0x%x\n", ret);
return ret;

View File

@ -2082,7 +2082,7 @@ static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
}
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
struct iwl_wowlan_igtk_status *data)
struct iwl_wowlan_igtk_status_v1 *data)
{
int i;
@ -2106,7 +2106,7 @@ static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
}
static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
const struct iwl_wowlan_igtk_status *data)
const struct iwl_wowlan_igtk_status_v1 *data)
{
int data_idx, status_idx = 0;
@ -2137,7 +2137,7 @@ static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
}
static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,
struct iwl_wowlan_info_notif *data,
struct iwl_wowlan_info_notif_v5 *data,
struct iwl_wowlan_status_data *status,
u32 len)
{
@ -2907,7 +2907,7 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,
iwl_mvm_parse_wowlan_info_notif_v3(mvm, notif,
d3_data->status, len);
} else if (wowlan_info_ver == 5) {
struct iwl_wowlan_info_notif *notif =
struct iwl_wowlan_info_notif_v5 *notif =
(void *)pkt->data;
iwl_mvm_parse_wowlan_info_notif(mvm, notif,
@ -3102,7 +3102,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm)
rt_status = iwl_mvm_check_rt_status(mvm, vif);
if (rt_status != FW_ALIVE) {
set_bit(STATUS_FW_ERROR, &mvm->trans->status);
iwl_trans_notify_fw_error(mvm->trans);
if (rt_status == FW_ERROR) {
IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n");
iwl_mvm_dump_nic_error_log(mvm);
@ -3272,7 +3272,7 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
rt_status = iwl_mvm_check_rt_status(mvm, NULL);
if (rt_status != FW_ALIVE) {
set_bit(STATUS_FW_ERROR, &mvm->trans->status);
iwl_trans_notify_fw_error(mvm->trans);
if (rt_status == FW_ERROR) {
IWL_ERR(mvm,
"iwl_mvm_check_rt_status failed, device is gone during suspend\n");
@ -3284,7 +3284,6 @@ int iwl_mvm_fast_resume(struct iwl_mvm *mvm)
&iwl_dump_desc_assert,
false, 0);
}
mvm->trans->state = IWL_TRANS_NO_FW;
ret = -ENODEV;
goto out;

View File

@ -1134,7 +1134,7 @@ static ssize_t iwl_dbgfs_fw_restart_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_trans_suppress_cmd_error_once(mvm->trans);
mvm->trans->suppress_cmd_error_once = true;
}
/* take the return value to make compiler happy - it will fail anyway */

View File

@ -837,7 +837,7 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
.flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
};
if (!mvm->trans->ltr_enabled)
if (!iwl_trans_is_ltr_enabled(mvm->trans))
return 0;
return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,

View File

@ -1243,7 +1243,7 @@ static int _iwl_pci_resume(struct device *device, bool restore)
* won't really know how to recover.
*/
iwl_pcie_prepare_card_hw(trans);
iwl_finish_nic_init(trans);
iwl_trans_activate_nic(trans);
iwl_op_mode_device_powered_off(trans->op_mode);
}

View File

@ -403,6 +403,8 @@ struct iwl_pcie_txqs {
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
* The user should use iwl_trans_{alloc,free}_tx_cmd.
* @dev_cmd_pool_name: name for the TX command allocation pool
* @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
*/
struct iwl_trans_pcie {
struct iwl_rxq *rxq;
@ -512,6 +514,9 @@ struct iwl_trans_pcie {
struct kmem_cache *dev_cmd_pool;
char dev_cmd_pool_name[50];
bool pm_support;
bool ltr_enabled;
};
static inline struct iwl_trans_pcie *
@ -1131,7 +1136,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_finish_nic_init(struct iwl_trans *trans);
int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans);
/* transport gen 2 exported functions */
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
@ -1151,4 +1156,17 @@ int iwl_trans_pcie_copy_imr(struct iwl_trans *trans,
int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue,
struct iwl_trans_rxq_dma_data *data);
static inline bool iwl_pcie_gen1_is_pm_supported(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
return trans_pcie->pm_support;
}
static inline bool iwl_pcie_gen1_2_is_ltr_enabled(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
return trans_pcie->ltr_enabled;
}
#endif /* __iwl_trans_int_pcie_h__ */

View File

@ -47,7 +47,7 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
iwl_pcie_apm_config(trans);
ret = iwl_finish_nic_init(trans);
ret = iwl_trans_activate_nic(trans);
if (ret)
return ret;

View File

@ -25,7 +25,6 @@
#include "fw/dbg.h"
#include "fw/api/tx.h"
#include "fw/acpi.h"
#include "fw/api/tx.h"
#include "mei/iwl-mei.h"
#include "internal.h"
#include "iwl-fh.h"
@ -215,13 +214,13 @@ void iwl_pcie_apm_config(struct iwl_trans *trans)
iwl_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->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
trans_pcie->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
trans_pcie->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
IWL_DEBUG_POWER(trans, "L1 %sabled - LTR %sabled\n",
(lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
trans->ltr_enabled ? "En" : "Dis");
trans_pcie->ltr_enabled ? "En" : "Dis");
}
/*
@ -268,7 +267,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
if (trans->mac_cfg->base->pll_cfg)
iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
ret = iwl_finish_nic_init(trans);
ret = iwl_trans_activate_nic(trans);
if (ret)
return ret;
@ -341,7 +340,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
ret = iwl_trans_pcie_sw_reset(trans, true);
if (!ret)
ret = iwl_finish_nic_init(trans);
ret = iwl_trans_activate_nic(trans);
if (WARN_ON(ret)) {
/* Release XTAL ON request */
@ -1543,7 +1542,7 @@ int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
ret = iwl_finish_nic_init(trans);
ret = iwl_trans_activate_nic(trans);
if (ret) {
IWL_ERR(trans, "Failed to init nic upon resume. err = %d\n",
ret);
@ -1767,7 +1766,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
{
int ret;
ret = iwl_finish_nic_init(trans);
ret = iwl_trans_activate_nic(trans);
if (ret < 0)
return ret;
@ -3540,7 +3539,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans, u32 dump_mask,
struct iwl_trans_dump_data *dump_data;
u32 len, num_rbs = 0, monitor_len = 0;
int i, ptr;
bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
bool dump_rbs = iwl_trans_is_fw_error(trans) &&
!trans->mac_cfg->mq_rx_supported &&
dump_mask & BIT(IWL_FW_ERROR_DUMP_RB);
@ -4189,7 +4188,7 @@ int iwl_pci_gen1_2_probe(struct pci_dev *pdev,
*/
ret = iwl_pcie_prepare_card_hw(iwl_trans);
if (!ret) {
ret = iwl_finish_nic_init(iwl_trans);
ret = iwl_trans_activate_nic(iwl_trans);
if (ret)
goto out_free_trans;
if (iwl_trans_grab_nic_access(iwl_trans)) {
@ -4309,7 +4308,7 @@ void iwl_pcie_gen1_2_remove(struct iwl_trans *trans)
iwl_trans_pcie_free(trans);
}
int iwl_pcie_gen1_2_finish_nic_init(struct iwl_trans *trans)
int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans)
{
const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg;
u32 poll_ready;

View File

@ -2601,8 +2601,9 @@ static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans,
}
if (test_bit(STATUS_FW_ERROR, &trans->status)) {
if (!test_and_clear_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE,
&trans->status)) {
if (trans->suppress_cmd_error_once) {
trans->suppress_cmd_error_once = false;
} else {
IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str);
dump_stack();
}

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
iwlwifi-tests-y += module.o devinfo.o utils.o
iwlwifi-tests-y += module.o devinfo.o utils.o nvm_parse.o
ccflags-y += -I$(src)/../

View File

@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* KUnit tests for NVM parse
*
* Copyright (C) 2025 Intel Corporation
*/
#include <kunit/static_stub.h>
#include <kunit/test.h>
#include <iwl-nvm-parse.h>
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static const struct nvm_flag_case {
const char *desc;
u16 nvm_flags;
u32 reg_rule_flags;
u32 set_reg_rule_flags;
u32 clear_reg_rule_flags;
} nvm_flag_cases[] = {
{
.desc = "Restricting VLP client and AP access",
.nvm_flags = 0,
.set_reg_rule_flags = NL80211_RRF_NO_6GHZ_VLP_CLIENT,
.clear_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP,
},
{
.desc = "Allow VLP client and AP access",
.nvm_flags = NVM_CHANNEL_VLP,
.set_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP,
.clear_reg_rule_flags = NL80211_RRF_NO_6GHZ_VLP_CLIENT,
},
{
.desc = "Allow VLP client access, while restricting AP access",
.nvm_flags = NVM_CHANNEL_VLP | NVM_CHANNEL_VLP_AP_NOT_ALLOWED,
.set_reg_rule_flags = 0,
.clear_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP |
NL80211_RRF_NO_6GHZ_VLP_CLIENT,
},
};
KUNIT_ARRAY_PARAM_DESC(nvm_flag, nvm_flag_cases, desc)
static void test_nvm_flags(struct kunit *test)
{
const struct nvm_flag_case *params = test->param_value;
struct iwl_reg_capa reg_capa = {};
u32 flags = 0;
flags = iwl_nvm_get_regdom_bw_flags(NULL, 0, params->nvm_flags,
reg_capa);
if ((params->set_reg_rule_flags & flags) != params->set_reg_rule_flags)
KUNIT_FAIL(test, "Expected set bits:0x%08x flags:0x%08x\n",
params->set_reg_rule_flags, flags);
if (params->clear_reg_rule_flags & flags)
KUNIT_FAIL(test, "Expected clear bits:0x%08x flags:0x%08x\n",
params->clear_reg_rule_flags, flags);
}
static struct kunit_case nvm_flags_test_cases[] = {
KUNIT_CASE_PARAM(test_nvm_flags,
nvm_flag_gen_params),
{},
};
static struct kunit_suite nvm_flags_suite = {
.name = "iwlwifi-nvm_flags",
.test_cases = nvm_flags_test_cases,
};
kunit_test_suite(nvm_flags_suite);