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

- disable features in fips
- remove RX OMI feature code
- A few fixes and cleanups
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg
2025-07-23 14:13:15 +02:00
34 changed files with 443 additions and 678 deletions

View File

@@ -27,8 +27,6 @@
#define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
#define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0"
#define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0"
#define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0"
#define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0"
static const struct iwl_family_base_params iwl_sc_base = {
.num_of_queues = 512,
@@ -101,5 +99,3 @@ IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_SC2F_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX);
IWL_FW_AND_PNVM(IWL_SC2F_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX);

View File

@@ -388,7 +388,7 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state)
/**
* iwl_parse_eeprom_data - parse EEPROM data and return values
*
* @trans: ransport we're parsing for, for debug only
* @trans: transport we're parsing for, for debug only
* @cfg: device configuration for parsing and overrides
* @eeprom: the EEPROM data
* @eeprom_size: length of the EEPROM data

View File

@@ -90,12 +90,6 @@ enum iwl_data_path_subcmd_ids {
*/
SEC_KEY_CMD = 0x18,
/**
* @OMI_SEND_STATUS_NOTIF: notification after OMI was sent
* uses &struct iwl_omi_send_status_notif
*/
OMI_SEND_STATUS_NOTIF = 0xF2,
/**
* @ESR_MODE_NOTIF: notification to recommend/force a wanted esr mode,
* uses &struct iwl_esr_mode_notif or &struct iwl_esr_mode_notif_v1
@@ -699,24 +693,4 @@ struct iwl_sec_key_cmd {
} __packed u; /* SEC_KEY_OPERATION_API_U_VER_1 */
} __packed; /* SEC_KEY_CMD_API_S_VER_1 */
/**
* struct iwl_omi_send_status_notif_v1 - OMI status notification
* @success: indicates that the OMI was sent successfully
* (currently always set)
*/
struct iwl_omi_send_status_notif_v1 {
__le32 success;
} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_1 */
/**
* struct iwl_omi_send_status_notif - OMI status notification
* @success: indicates that the OMI was sent successfully
* (currently always set)
* @sta_id: sta_id to which the OMI was sent
*/
struct iwl_omi_send_status_notif {
__le32 success;
__le32 sta_id;
} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_2 */
#endif /* __iwl_fw_api_datapath_h__ */

View File

@@ -571,7 +571,8 @@ enum iwl_ppag_flags {
/**
* union iwl_ppag_table_cmd - union for all versions of PPAG command
* @v1: command version 1 structure.
* @v2: command version 5 structure.
* @v2: command version from 2 to 6 are same structure as v2.
* but has a different format of the flags bitmap
* @v3: command version 7 structure.
* @v1.flags: values from &enum iwl_ppag_flags
* @v1.gain: table of antenna gain values per chain and sub-band
@@ -592,7 +593,9 @@ union iwl_ppag_table_cmd {
__le32 flags;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_5 */
} __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4,
* VER5, VER6
*/
struct {
struct bios_value_u32 ppag_config_info;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
@@ -600,11 +603,20 @@ union iwl_ppag_table_cmd {
} __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */
} __packed;
#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V1_MASK | \
#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK)
#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \
IWL_PPAG_ETSI_LPI_UHB_MASK | \
IWL_PPAG_USA_LPI_UHB_MASK)
#define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \
IWL_PPAG_ETSI_VLP_UHB_MASK | \
IWL_PPAG_ETSI_SP_UHB_MASK | \
IWL_PPAG_USA_VLP_UHB_MASK | \
IWL_PPAG_USA_SP_UHB_MASK | \
IWL_PPAG_CANADA_LPI_UHB_MASK | \
IWL_PPAG_CANADA_VLP_UHB_MASK | \
IWL_PPAG_CANADA_SP_UHB_MASK)
#define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26
#define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13

View File

@@ -50,7 +50,7 @@ struct iwl_tdls_channel_switch_timing {
*/
struct iwl_tdls_channel_switch_frame {
__le32 switch_time_offset;
struct iwl_tx_cmd_v6 tx_cmd;
struct iwl_tx_cmd_v6_params tx_cmd;
u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
@@ -131,7 +131,7 @@ struct iwl_tdls_config_cmd {
struct iwl_tdls_sta_info sta_info[IWL_TDLS_STA_COUNT];
__le32 pti_req_data_offset;
struct iwl_tx_cmd_v6 pti_req_tx_cmd;
struct iwl_tx_cmd_v6_params pti_req_tx_cmd;
u8 pti_req_template[];
} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */

View File

@@ -181,8 +181,8 @@ enum iwl_tx_offload_assist_flags_pos {
/* TODO: complete documentation for try_cnt and btkill_cnt */
/**
* struct iwl_tx_cmd_v6 - TX command struct to FW
* ( TX_CMD = 0x1c )
* struct iwl_tx_cmd_v6_params - parameters of the TX
*
* @len: in bytes of the payload, see below for details
* @offload_assist: TX offload configuration
* @tx_flags: combination of TX_CMD_FLG_*, see &enum iwl_tx_flags
@@ -205,8 +205,6 @@ enum iwl_tx_offload_assist_flags_pos {
* @tid_tspec: TID/tspec
* @pm_frame_timeout: PM TX frame timeout
* @reserved4: reserved
* @payload: payload (same as @hdr)
* @hdr: 802.11 header (same as @payload)
*
* The byte count (both len and next_frame_len) includes MAC header
* (24/26/30/32 bytes)
@@ -217,11 +215,8 @@ enum iwl_tx_offload_assist_flags_pos {
* It does not include post-MAC padding, i.e.,
* MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.
* Range of len: 14-2342 bytes.
*
* After the struct fields the MAC header is placed, plus any padding,
* and then the actial payload.
*/
struct iwl_tx_cmd_v6 {
struct iwl_tx_cmd_v6_params {
__le16 len;
__le16 offload_assist;
__le32 tx_flags;
@@ -245,10 +240,20 @@ struct iwl_tx_cmd_v6 {
u8 tid_tspec;
__le16 pm_frame_timeout;
__le16 reserved4;
union {
DECLARE_FLEX_ARRAY(u8, payload);
DECLARE_FLEX_ARRAY(struct ieee80211_hdr, hdr);
};
} __packed; /* TX_CMD_API_S_VER_6 */
/**
* struct iwl_tx_cmd_v6 - TX command struct to FW
* ( TX_CMD = 0x1c )
* @params: parameters of the TX, see &struct iwl_tx_cmd_v6_tx_params
* @hdr: 802.11 header
*
* After &params, the MAC header is placed, plus any padding,
* and then the actual payload.
*/
struct iwl_tx_cmd_v6 {
struct iwl_tx_cmd_v6_params params;
struct ieee80211_hdr hdr[];
} __packed; /* TX_CMD_API_S_VER_6 */
struct iwl_dram_sec_info {
@@ -748,7 +753,7 @@ struct iwl_compressed_ba_notif {
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v6 {
struct iwl_tx_cmd_v6 tx;
struct iwl_tx_cmd_v6_params tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;
@@ -767,7 +772,7 @@ struct iwl_mac_beacon_cmd_v6 {
* @frame: the template of the beacon frame
*/
struct iwl_mac_beacon_cmd_v7 {
struct iwl_tx_cmd_v6 tx;
struct iwl_tx_cmd_v6_params tx;
__le32 template_id;
__le32 tim_idx;
__le32 tim_size;

View File

@@ -344,18 +344,18 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
num_sub_bands = IWL_NUM_SUB_BANDS_V1;
gain = cmd->v1.gain[0];
*cmd_size = sizeof(cmd->v1);
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK);
cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags);
if (fwrt->ppag_bios_rev >= 1) {
/* in this case FW supports revision 0 */
IWL_DEBUG_RADIO(fwrt,
"PPAG table rev is %d, send truncated table\n",
fwrt->ppag_bios_rev);
}
} else if (cmd_ver == 5) {
} else if (cmd_ver >= 2 && cmd_ver <= 6) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = cmd->v2.gain[0];
*cmd_size = sizeof(cmd->v2);
cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK);
cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags);
if (fwrt->ppag_bios_rev == 0) {
/* in this case FW supports revisions 1,2 or 3 */
IWL_DEBUG_RADIO(fwrt,
@@ -378,9 +378,17 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt,
"PPAG MODE bits were read from bios: %d\n",
fwrt->ppag_flags);
if (cmd_ver == 1 &&
!fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) {
if (cmd_ver == 6)
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V6_MASK);
else if (cmd_ver == 5)
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK);
else if (cmd_ver < 5)
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK);
if ((cmd_ver == 1 &&
!fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) ||
(cmd_ver == 2 && fwrt->ppag_bios_rev >= 2)) {
cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK);
IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n");
} else {

View File

@@ -236,10 +236,9 @@ const char *iwl_drv_get_fwname_pre(struct iwl_trans *trans, char *buf)
mac = "sc";
break;
case IWL_CFG_MAC_TYPE_SC2:
mac = "sc2";
break;
/* Uses the same firmware as SC2 */
case IWL_CFG_MAC_TYPE_SC2F:
mac = "sc2f";
mac = "sc2";
break;
case IWL_CFG_MAC_TYPE_BR:
mac = "br";

View File

@@ -75,7 +75,6 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
/* return as if we have a HW timeout/failure */
return 0x5a5a5a5a;
}
IWL_EXPORT_SYMBOL(iwl_read_direct32);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
{
@@ -93,7 +92,6 @@ void iwl_write_direct64(struct iwl_trans *trans, u64 reg, u64 value)
iwl_trans_release_nic_access(trans);
}
}
IWL_EXPORT_SYMBOL(iwl_write_direct64);
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout)
@@ -109,7 +107,6 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
return -ETIMEDOUT;
}
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
{
@@ -117,14 +114,12 @@ u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
return val;
}
IWL_EXPORT_SYMBOL(iwl_read_prph_no_grab);
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_EXPORT_SYMBOL(iwl_write_prph_no_grab);
void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
{
@@ -132,7 +127,6 @@ void iwl_write_prph64_no_grab(struct iwl_trans *trans, u64 ofs, u64 val)
iwl_write_prph_no_grab(trans, ofs, val & 0xffffffff);
iwl_write_prph_no_grab(trans, ofs + 4, val >> 32);
}
IWL_EXPORT_SYMBOL(iwl_write_prph64_no_grab);
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
{

View File

@@ -5,6 +5,7 @@
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/types.h>
#include <linux/fips.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/etherdevice.h>
@@ -543,16 +544,22 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
else
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
/*
* With fips_enabled crypto is done by software, so the HW cannot
* split up A-MSDUs and the real limit that was set applies.
* Note that EHT doesn't honour this (HE copies the VHT value),
* but EHT is also entirely disabled for fips_enabled.
*/
switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_DEF:
if (trans->mac_cfg->mq_rx_supported)
if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
else
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
break;
case IWL_AMSDU_2K:
if (trans->mac_cfg->mq_rx_supported)
if (trans->mac_cfg->mq_rx_supported && !fips_enabled)
vht_cap->cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
else
@@ -909,7 +916,9 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
bool slow_pcie = (!trans->mac_cfg->integrated &&
trans->info.pcie_link_speed < PCI_EXP_LNKSTA_CLS_8_0GB);
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be)
/* EHT needs WPA3/MFP so cannot do it for fips_enabled */
if (!data->sku_cap_11be_enable || iwlwifi_mod_params.disable_11be ||
fips_enabled)
iftype_data->eht_cap.has_eht = false;
/* Advertise an A-MPDU exponent extension based on
@@ -1197,11 +1206,19 @@ static void iwl_init_sbands(struct iwl_trans *trans,
n_used += iwl_init_sband_channels(data, sband, n_channels,
NL80211_BAND_6GHZ);
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax)
/*
* 6 GHz requires WPA3 which requires MFP, which FW cannot do
* when fips_enabled, so don't advertise any 6 GHz channels to
* avoid spending time on scanning those channels and perhaps
* even finding APs there that cannot be used.
*/
if (!fips_enabled && data->sku_cap_11ax_enable &&
!iwlwifi_mod_params.disable_11ax)
iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains,
fw);
else
sband->n_channels = 0;
if (n_channels != n_used)
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
n_used, n_channels);

View File

@@ -437,31 +437,26 @@ void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{
iwl_trans_pcie_write8(trans, ofs, val);
}
IWL_EXPORT_SYMBOL(iwl_trans_write8);
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)
{
return iwl_trans_pcie_read_prph(trans, ofs);
}
IWL_EXPORT_SYMBOL(iwl_trans_read_prph);
void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{
return iwl_trans_pcie_write_prph(trans, ofs, val);
}
IWL_EXPORT_SYMBOL(iwl_trans_write_prph);
int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
void *buf, int dwords)
@@ -502,7 +497,6 @@ int iwl_trans_sw_reset(struct iwl_trans *trans)
{
return iwl_trans_pcie_sw_reset(trans, true);
}
IWL_EXPORT_SYMBOL(iwl_trans_sw_reset);
struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
@@ -512,7 +506,6 @@ iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
return iwl_trans_pcie_dump_data(trans, dump_mask,
sanitize_ops, sanitize_ctx);
}
IWL_EXPORT_SYMBOL(iwl_trans_dump_data);
int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset)
{
@@ -548,20 +541,17 @@ void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
{
iwl_trans_pci_interrupts(trans, enable);
}
IWL_EXPORT_SYMBOL(iwl_trans_interrupts);
void iwl_trans_sync_nmi(struct iwl_trans *trans)
{
iwl_trans_pcie_sync_nmi(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_sync_nmi);
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);
}
IWL_EXPORT_SYMBOL(iwl_trans_write_imr_mem);
void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg,
u32 mask, u32 value)
@@ -575,7 +565,6 @@ int iwl_trans_read_config32(struct iwl_trans *trans, u32 ofs,
{
return iwl_trans_pcie_read_config32(trans, ofs, val);
}
IWL_EXPORT_SYMBOL(iwl_trans_read_config32);
bool _iwl_trans_grab_nic_access(struct iwl_trans *trans)
{
@@ -771,7 +760,6 @@ void iwl_trans_debugfs_cleanup(struct iwl_trans *trans)
{
iwl_trans_pcie_debugfs_cleanup(trans);
}
IWL_EXPORT_SYMBOL(iwl_trans_debugfs_cleanup);
#endif
void iwl_trans_set_q_ptrs(struct iwl_trans *trans, int queue, int ptr)
@@ -809,7 +797,6 @@ int iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue,
{
return iwl_trans_pcie_rxq_dma_data(trans, queue, data);
}
IWL_EXPORT_SYMBOL(iwl_trans_get_rxq_dma_data);
int iwl_trans_load_pnvm(struct iwl_trans *trans,
const struct iwl_pnvm_image *pnvm_data,
@@ -824,7 +811,6 @@ void iwl_trans_set_pnvm(struct iwl_trans *trans,
{
iwl_trans_pcie_ctx_info_v2_set_pnvm(trans, capa);
}
IWL_EXPORT_SYMBOL(iwl_trans_set_pnvm);
int iwl_trans_load_reduce_power(struct iwl_trans *trans,
const struct iwl_pnvm_image *payloads,
@@ -833,11 +819,9 @@ int iwl_trans_load_reduce_power(struct iwl_trans *trans,
return iwl_trans_pcie_ctx_info_v2_load_reduce_power(trans, payloads,
capa);
}
IWL_EXPORT_SYMBOL(iwl_trans_load_reduce_power);
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);
}
IWL_EXPORT_SYMBOL(iwl_trans_set_reduce_power);

View File

@@ -305,10 +305,15 @@ iwl_mld_reorder(struct iwl_mld *mld, struct napi_struct *napi,
* already ahead and it will be dropped.
* If the last sub-frame is not on this queue - we will get frame
* release notification with up to date NSSN.
* If this is the first frame that is stored in the buffer, the head_sn
* may be outdated. Update it based on the last NSSN to make sure it
* will be released when the frame release notification arrives.
*/
if (!amsdu || last_subframe)
iwl_mld_reorder_release_frames(mld, sta, napi, baid_data,
buffer, nssn);
else if (buffer->num_stored == 1)
buffer->head_sn = nssn;
return IWL_MLD_BUFFERED_SKB;
}

View File

@@ -40,15 +40,6 @@
#define IWL_MLD_TPT_COUNT_WINDOW (5 * HZ)
/* OMI reduced BW thresholds (channel load percentage) */
#define IWL_MLD_OMI_ENTER_CHAN_LOAD 10
#define IWL_MLD_OMI_EXIT_CHAN_LOAD_160 20
#define IWL_MLD_OMI_EXIT_CHAN_LOAD_320 30
/* time (in milliseconds) to let AP "settle" the OMI */
#define IWL_MLD_OMI_AP_SETTLE_DELAY 27
/* time (in milliseconds) to not enter OMI reduced BW after leaving */
#define IWL_MLD_OMI_EXIT_PROTECTION 5000
#define IWL_MLD_DIS_RANDOM_FW_ID false
#define IWL_MLD_D3_DEBUG false
#define IWL_MLD_NON_TRANSMITTING_AP false

View File

@@ -242,27 +242,9 @@ static bool iwl_mld_fill_mu_edca(struct iwl_mld *mld,
return true;
}
static u8 iwl_mld_sta_rx_bw_to_fw(enum ieee80211_sta_rx_bandwidth bw)
{
switch (bw) {
default: /* potential future values not supported by this hw/driver */
case IEEE80211_STA_RX_BW_20:
return IWL_LINK_MODIFY_BW_20;
case IEEE80211_STA_RX_BW_40:
return IWL_LINK_MODIFY_BW_40;
case IEEE80211_STA_RX_BW_80:
return IWL_LINK_MODIFY_BW_80;
case IEEE80211_STA_RX_BW_160:
return IWL_LINK_MODIFY_BW_160;
case IEEE80211_STA_RX_BW_320:
return IWL_LINK_MODIFY_BW_320;
}
}
static int _iwl_mld_change_link_in_fw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link,
enum ieee80211_sta_rx_bandwidth bw,
u32 changes)
int
iwl_mld_change_link_in_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
u32 changes)
{
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
struct ieee80211_vif *vif = link->vif;
@@ -318,9 +300,6 @@ static int _iwl_mld_change_link_in_fw(struct iwl_mld *mld,
cmd.bi = cpu_to_le32(link->beacon_int);
cmd.dtim_interval = cpu_to_le32(link->beacon_int * link->dtim_period);
if (changes & LINK_CONTEXT_MODIFY_BANDWIDTH)
cmd.modify_bandwidth = iwl_mld_sta_rx_bw_to_fw(bw);
/* Configure HE parameters only if HE is supported, and only after
* the parameters are set in mac80211 (meaning after assoc)
*/
@@ -382,29 +361,11 @@ static int _iwl_mld_change_link_in_fw(struct iwl_mld *mld,
return iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_MODIFY);
}
int iwl_mld_change_link_in_fw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link,
u32 changes)
{
if (WARN_ON(changes & LINK_CONTEXT_MODIFY_BANDWIDTH))
changes &= ~LINK_CONTEXT_MODIFY_BANDWIDTH;
return _iwl_mld_change_link_in_fw(mld, link, 0, changes);
}
int iwl_mld_change_link_omi_bw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link,
enum ieee80211_sta_rx_bandwidth bw)
{
return _iwl_mld_change_link_in_fw(mld, link, bw,
LINK_CONTEXT_MODIFY_BANDWIDTH);
}
int iwl_mld_activate_link(struct iwl_mld *mld,
struct ieee80211_bss_conf *link)
{
struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link);
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(mld_link->vif);
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(link->vif);
int ret;
lockdep_assert_wiphy(mld->wiphy);
@@ -412,7 +373,6 @@ int iwl_mld_activate_link(struct iwl_mld *mld,
if (WARN_ON(!mld_link || mld_link->active))
return -EINVAL;
mld_link->rx_omi.exit_ts = jiffies;
mld_link->active = true;
ret = iwl_mld_change_link_in_fw(mld, link,
@@ -477,331 +437,6 @@ iwl_mld_rm_link_from_fw(struct iwl_mld *mld, struct ieee80211_bss_conf *link)
iwl_mld_send_link_cmd(mld, &cmd, FW_CTXT_ACTION_REMOVE);
}
static void iwl_mld_omi_bw_update(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf,
struct iwl_mld_link *mld_link,
struct ieee80211_link_sta *link_sta,
enum ieee80211_sta_rx_bandwidth bw,
bool ap_update)
{
enum ieee80211_sta_rx_bandwidth apply_bw;
mld_link->rx_omi.desired_bw = bw;
/* Can't update OMI while already in progress, desired_bw was
* set so on FW notification the worker will see the change
* and apply new the new desired bw.
*/
if (mld_link->rx_omi.bw_in_progress)
return;
if (bw == IEEE80211_STA_RX_BW_MAX)
apply_bw = ieee80211_chan_width_to_rx_bw(link_conf->chanreq.oper.width);
else
apply_bw = bw;
if (!ap_update) {
/* The update isn't due to AP tracking after leaving OMI,
* where the AP could increase BW and then we must tell
* it that we can do the increased BW as well, if we did
* update the chandef.
* In this case, if we want MAX, then we will need to send
* a new OMI to the AP if it increases its own bandwidth as
* we can (due to internal and FW limitations, and being
* worried the AP might break) only send to what we're doing
* at the moment. In this case, set last_max_bw; otherwise
* if we really want to decrease our bandwidth set it to 0
* to indicate no updates are needed if the AP changes.
*/
if (bw != IEEE80211_STA_RX_BW_MAX)
mld_link->rx_omi.last_max_bw = apply_bw;
else
mld_link->rx_omi.last_max_bw = 0;
} else {
/* Otherwise, if we're already trying to do maximum and
* the AP is changing, set last_max_bw to the new max the
* AP is using, we'll only get to this code path if the
* new bandwidth of the AP is bigger than what we sent it
* previously. This avoids repeatedly sending updates if
* it changes bandwidth, only doing it once on an increase.
*/
mld_link->rx_omi.last_max_bw = apply_bw;
}
if (ieee80211_prepare_rx_omi_bw(link_sta, bw)) {
mld_link->rx_omi.bw_in_progress = apply_bw;
iwl_mld_change_link_omi_bw(mld, link_conf, apply_bw);
}
}
static void iwl_mld_omi_bw_finished_work(struct wiphy *wiphy,
struct wiphy_work *work)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
struct iwl_mld_link *mld_link =
container_of(work, typeof(*mld_link), rx_omi.finished_work.work);
enum ieee80211_sta_rx_bandwidth desired_bw, switched_to_bw;
struct ieee80211_vif *vif = mld_link->vif;
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
if (!mld_vif->ap_sta)
return;
link_sta = wiphy_dereference(mld->wiphy,
mld_vif->ap_sta->link[mld_link->link_id]);
if (WARN_ON_ONCE(!link_sta))
return;
link_conf = link_conf_dereference_protected(vif, link_sta->link_id);
if (WARN_ON_ONCE(!link_conf))
return;
if (WARN_ON(!mld_link->rx_omi.bw_in_progress))
return;
desired_bw = mld_link->rx_omi.desired_bw;
switched_to_bw = mld_link->rx_omi.bw_in_progress;
ieee80211_finalize_rx_omi_bw(link_sta);
mld_link->rx_omi.bw_in_progress = 0;
if (desired_bw != switched_to_bw)
iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta,
desired_bw, false);
}
static struct ieee80211_vif *
iwl_mld_get_omi_bw_reduction_pointers(struct iwl_mld *mld,
struct ieee80211_link_sta **link_sta,
struct iwl_mld_link **mld_link)
{
struct iwl_mld_vif *mld_vif;
struct ieee80211_vif *vif;
int n_link_stas = 0;
*link_sta = NULL;
if (mld->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)
return NULL;
vif = iwl_mld_get_bss_vif(mld);
if (!vif)
return NULL;
for (int i = 0; i < ARRAY_SIZE(mld->fw_id_to_link_sta); i++) {
struct ieee80211_link_sta *tmp;
tmp = wiphy_dereference(mld->wiphy, mld->fw_id_to_link_sta[i]);
if (IS_ERR_OR_NULL(tmp))
continue;
n_link_stas++;
*link_sta = tmp;
}
/* can't do anything if we have TDLS peers or EMLSR */
if (n_link_stas != 1)
return NULL;
mld_vif = iwl_mld_vif_from_mac80211(vif);
*mld_link = iwl_mld_link_dereference_check(mld_vif,
(*link_sta)->link_id);
if (WARN_ON(!*mld_link))
return NULL;
return vif;
}
void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf,
enum ieee80211_sta_rx_bandwidth bw)
{
struct ieee80211_link_sta *link_sta;
struct iwl_mld_link *mld_link;
struct ieee80211_vif *vif;
vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
if (!vif)
return;
if (WARN_ON(link_conf->vif != vif))
return;
/* This is 0 if we requested an OMI BW reduction and don't want to
* be sending an OMI when the AP's bandwidth changes.
*/
if (!mld_link->rx_omi.last_max_bw)
return;
/* We only need to tell the AP if it increases BW over what we last
* told it we were using, if it reduces then our last OMI to it will
* not get used anyway (e.g. we said we want 160 but it's doing 80.)
*/
if (bw < mld_link->rx_omi.last_max_bw)
return;
iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta, bw, true);
}
void iwl_mld_handle_omi_status_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt)
{
int ver = iwl_fw_lookup_notif_ver(mld->fw, DATA_PATH_GROUP,
OMI_SEND_STATUS_NOTIF, 1);
struct ieee80211_link_sta *link_sta;
struct iwl_mld_link *mld_link;
struct ieee80211_vif *vif;
if (ver == 2) {
const struct iwl_omi_send_status_notif *notif =
(const void *)pkt->data;
u32 sta_id = le32_to_cpu(notif->sta_id);
struct iwl_mld_vif *mld_vif;
if (IWL_FW_CHECK(mld, sta_id >= mld->fw->ucode_capa.num_stations,
"Invalid station %d\n", sta_id))
return;
link_sta = wiphy_dereference(mld->wiphy,
mld->fw_id_to_link_sta[sta_id]);
if (IWL_FW_CHECK(mld, !link_sta, "Station does not exist\n"))
return;
vif = iwl_mld_sta_from_mac80211(link_sta->sta)->vif;
mld_vif = iwl_mld_vif_from_mac80211(vif);
mld_link = iwl_mld_link_dereference_check(mld_vif,
link_sta->link_id);
if (WARN(!mld_link, "Link %d does not exist\n",
link_sta->link_id))
return;
} else {
vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta,
&mld_link);
}
if (IWL_FW_CHECK(mld, !vif, "unexpected OMI notification\n"))
return;
if (IWL_FW_CHECK(mld, !mld_link->rx_omi.bw_in_progress,
"OMI notification when not requested\n"))
return;
wiphy_delayed_work_queue(mld->hw->wiphy,
&mld_link->rx_omi.finished_work,
msecs_to_jiffies(IWL_MLD_OMI_AP_SETTLE_DELAY));
}
void iwl_mld_leave_omi_bw_reduction(struct iwl_mld *mld)
{
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
struct iwl_mld_link *mld_link;
struct ieee80211_vif *vif;
vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
if (!vif)
return;
link_conf = link_conf_dereference_protected(vif, link_sta->link_id);
if (WARN_ON_ONCE(!link_conf))
return;
if (!link_conf->he_support)
return;
mld_link->rx_omi.exit_ts = jiffies;
iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta,
IEEE80211_STA_RX_BW_MAX, false);
}
void iwl_mld_check_omi_bw_reduction(struct iwl_mld *mld)
{
enum ieee80211_sta_rx_bandwidth bw = IEEE80211_STA_RX_BW_MAX;
struct ieee80211_chanctx_conf *chanctx;
struct ieee80211_bss_conf *link_conf;
struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def chandef;
struct iwl_mld_link *mld_link;
struct iwl_mld_vif *mld_vif;
struct ieee80211_vif *vif;
struct iwl_mld_phy *phy;
u16 punctured;
int exit_thr;
/* not allowed in CAM mode */
if (iwlmld_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
return;
/* must have one BSS connection (no P2P), no TDLS, nor EMLSR */
vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link);
if (!vif)
return;
link_conf = link_conf_dereference_protected(vif, link_sta->link_id);
if (WARN_ON_ONCE(!link_conf))
return;
if (!link_conf->he_support)
return;
chanctx = wiphy_dereference(mld->wiphy, mld_link->chan_ctx);
if (WARN_ON(!chanctx))
return;
mld_vif = iwl_mld_vif_from_mac80211(vif);
if (!mld_vif->authorized)
goto apply;
/* must not be in low-latency mode */
if (iwl_mld_vif_low_latency(mld_vif))
goto apply;
chandef = link_conf->chanreq.oper;
switch (chandef.width) {
case NL80211_CHAN_WIDTH_320:
exit_thr = IWL_MLD_OMI_EXIT_CHAN_LOAD_320;
break;
case NL80211_CHAN_WIDTH_160:
exit_thr = IWL_MLD_OMI_EXIT_CHAN_LOAD_160;
break;
default:
/* since we reduce to 80 MHz, must have more to start with */
goto apply;
}
/* not to be done if primary 80 MHz is punctured */
if (cfg80211_chandef_primary(&chandef, NL80211_CHAN_WIDTH_80,
&punctured) < 0 ||
punctured != 0)
goto apply;
phy = iwl_mld_phy_from_mac80211(chanctx);
if (phy->channel_load_by_us > exit_thr) {
/* send OMI for max bandwidth */
goto apply;
}
if (phy->channel_load_by_us > IWL_MLD_OMI_ENTER_CHAN_LOAD) {
/* no changes between enter/exit thresholds */
return;
}
if (time_is_after_jiffies(mld_link->rx_omi.exit_ts +
msecs_to_jiffies(IWL_MLD_OMI_EXIT_PROTECTION)))
return;
/* reduce bandwidth to 80 MHz to save power */
bw = IEEE80211_STA_RX_BW_80;
apply:
iwl_mld_omi_bw_update(mld, link_conf, mld_link, link_sta, bw, false);
}
IWL_MLD_ALLOC_FN(link, bss_conf)
/* Constructor function for struct iwl_mld_link */
@@ -809,18 +444,12 @@ static int
iwl_mld_init_link(struct iwl_mld *mld, struct ieee80211_bss_conf *link,
struct iwl_mld_link *mld_link)
{
mld_link->vif = link->vif;
mld_link->link_id = link->link_id;
mld_link->average_beacon_energy = 0;
iwl_mld_init_internal_sta(&mld_link->bcast_sta);
iwl_mld_init_internal_sta(&mld_link->mcast_sta);
iwl_mld_init_internal_sta(&mld_link->mon_sta);
if (!mld->fw_status.in_hw_restart)
wiphy_delayed_work_init(&mld_link->rx_omi.finished_work,
iwl_mld_omi_bw_finished_work);
return iwl_mld_allocate_link_fw_id(mld, &mld_link->fw_id, link);
}
@@ -884,8 +513,6 @@ void iwl_mld_remove_link(struct iwl_mld *mld,
RCU_INIT_POINTER(mld_vif->link[bss_conf->link_id], NULL);
wiphy_delayed_work_cancel(mld->wiphy, &link->rx_omi.finished_work);
if (WARN_ON(link->fw_id >= mld->fw->ucode_capa.num_links))
return;
@@ -897,21 +524,23 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
{
const struct iwl_missed_beacons_notif *notif = (const void *)pkt->data;
union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
u32 link_id = le32_to_cpu(notif->link_id);
u32 fw_link_id = le32_to_cpu(notif->link_id);
u32 missed_bcon = le32_to_cpu(notif->consec_missed_beacons);
u32 missed_bcon_since_rx =
le32_to_cpu(notif->consec_missed_beacons_since_last_rx);
u32 scnd_lnk_bcn_lost =
le32_to_cpu(notif->consec_missed_beacons_other_link);
struct ieee80211_bss_conf *link_conf =
iwl_mld_fw_id_to_link_conf(mld, link_id);
iwl_mld_fw_id_to_link_conf(mld, fw_link_id);
u32 bss_param_ch_cnt_link_id;
struct ieee80211_vif *vif;
u8 link_id;
if (WARN_ON(!link_conf))
return;
vif = link_conf->vif;
link_id = link_conf->link_id;
bss_param_ch_cnt_link_id = link_conf->bss_param_ch_cnt_link_id;
IWL_DEBUG_INFO(mld,
@@ -923,7 +552,7 @@ void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
mld->trans->dbg.dump_file_name_ext_valid = true;
snprintf(mld->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME,
"LinkId_%d_MacType_%d", link_id,
"LinkId_%d_MacType_%d", fw_link_id,
iwl_mld_mac80211_iftype_to_fw(vif));
iwl_dbg_tlv_time_point(&mld->fwrt,

View File

@@ -36,11 +36,9 @@ struct iwl_probe_resp_data {
* @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked.
* @igtk: fw can only have one IGTK at a time, whereas mac80211 can have two.
* This tracks the one IGTK that currently exists in FW.
* @vif: the vif this link belongs to
* @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS.
* @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS.
* @mon_sta: station used for TX injection in monitor interface.
* @link_id: over the air link ID
* @average_beacon_energy: average beacon energy for beacons received during
* client connections
* @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs,
@@ -49,14 +47,6 @@ struct iwl_probe_resp_data {
* @silent_deactivation: next deactivation needs to be silent.
* @probe_resp_data: data from FW notification to store NOA related data to be
* inserted into probe response.
* @rx_omi: data for BW reduction with OMI
* @rx_omi.bw_in_progress: update is in progress (indicates target BW)
* @rx_omi.exit_ts: timestamp of last exit
* @rx_omi.finished_work: work for the delayed reaction to the firmware saying
* the change was applied, and for then applying a new mode if it was
* updated while waiting for firmware/AP settle delay.
* @rx_omi.desired_bw: desired bandwidth
* @rx_omi.last_max_bw: last maximum BW used by firmware, for AP BW changes
*/
struct iwl_mld_link {
struct rcu_head rcu_head;
@@ -71,19 +61,9 @@ struct iwl_mld_link {
struct ieee80211_key_conf *igtk;
);
/* And here fields that survive a fw restart */
struct ieee80211_vif *vif;
struct iwl_mld_int_sta bcast_sta;
struct iwl_mld_int_sta mcast_sta;
struct iwl_mld_int_sta mon_sta;
u8 link_id;
struct {
struct wiphy_delayed_work finished_work;
unsigned long exit_ts;
enum ieee80211_sta_rx_bandwidth bw_in_progress,
desired_bw,
last_max_bw;
} rx_omi;
/* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */
struct ieee80211_key_conf *ap_early_keys[6];
@@ -123,9 +103,6 @@ int iwl_mld_activate_link(struct iwl_mld *mld,
struct ieee80211_bss_conf *link);
void iwl_mld_deactivate_link(struct iwl_mld *mld,
struct ieee80211_bss_conf *link);
int iwl_mld_change_link_omi_bw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link,
enum ieee80211_sta_rx_bandwidth bw);
int iwl_mld_change_link_in_fw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link, u32 changes);
void iwl_mld_handle_missed_beacon_notif(struct iwl_mld *mld,
@@ -145,13 +122,6 @@ unsigned int iwl_mld_get_chan_load(struct iwl_mld *mld,
int iwl_mld_get_chan_load_by_others(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf,
bool expect_active_link);
void iwl_mld_handle_omi_status_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt);
void iwl_mld_leave_omi_bw_reduction(struct iwl_mld *mld);
void iwl_mld_check_omi_bw_reduction(struct iwl_mld *mld);
void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf,
enum ieee80211_sta_rx_bandwidth bw);
void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt);

View File

@@ -224,9 +224,6 @@ void iwl_mld_vif_update_low_latency(struct iwl_mld *mld,
return;
}
if (low_latency)
iwl_mld_leave_omi_bw_reduction(mld);
if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_P2P_CLIENT)
return;

View File

@@ -4,6 +4,7 @@
*/
#include <net/mac80211.h>
#include <linux/fips.h>
#include <linux/ip.h>
#include "mld.h"
@@ -156,6 +157,9 @@ static void iwl_mld_hw_set_security(struct iwl_mld *mld)
WLAN_CIPHER_SUITE_BIP_GMAC_256
};
if (fips_enabled)
return;
hw->wiphy->n_cipher_suites = ARRAY_SIZE(mld_ciphers);
hw->wiphy->cipher_suites = mld_ciphers;
@@ -180,6 +184,9 @@ static void iwl_mld_hw_set_pm(struct iwl_mld *mld)
if (!device_can_wakeup(mld->trans->dev))
return;
if (fips_enabled)
return;
mld->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
@@ -284,9 +291,11 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld)
WIPHY_FLAG_SUPPORTS_TDLS |
WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
/* For fips_enabled, don't support WiFi7 due to WPA3/MFP requirements */
if (mld->nvm_data->sku_cap_11be_enable &&
!iwlwifi_mod_params.disable_11ax &&
!iwlwifi_mod_params.disable_11be)
!iwlwifi_mod_params.disable_11be &&
!fips_enabled)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
/* the firmware uses u8 for num of iterations, but 0xff is saved for
@@ -1006,8 +1015,6 @@ int iwl_mld_assign_vif_chanctx(struct ieee80211_hw *hw,
if (n_active > 1) {
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
iwl_mld_leave_omi_bw_reduction(mld);
/* Indicate to mac80211 that EML is enabled */
vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE;
mld_vif->emlsr.last_entry_ts = jiffies;
@@ -1203,20 +1210,6 @@ iwl_mld_mac80211_link_info_changed_sta(struct iwl_mld *mld,
if (changes & (BSS_CHANGED_CQM | BSS_CHANGED_BEACON_INFO))
iwl_mld_enable_beacon_filter(mld, link_conf, false);
/* If we have used OMI before to reduce bandwidth to 80 MHz and then
* increased to 160 MHz again, and then the AP changes to 320 MHz, it
* will think that we're limited to 160 MHz right now. Update it by
* requesting a new OMI bandwidth.
*/
if (changes & BSS_CHANGED_BANDWIDTH) {
enum ieee80211_sta_rx_bandwidth bw;
bw = ieee80211_chan_width_to_rx_bw(link_conf->chanreq.oper.width);
iwl_mld_omi_ap_changed_bw(mld, link_conf, bw);
}
if (changes & BSS_CHANGED_BANDWIDTH)
iwl_mld_retry_emlsr(mld, vif);
}
@@ -1419,30 +1412,6 @@ iwl_mld_mac80211_sched_scan_stop(struct ieee80211_hw *hw,
return iwl_mld_scan_stop(mld, IWL_MLD_SCAN_SCHED, false);
}
static void
iwl_mld_restart_complete_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
struct ieee80211_bss_conf *link_conf;
struct iwl_mld *mld = data;
int link_id;
for_each_vif_active_link(vif, link_conf, link_id) {
enum ieee80211_sta_rx_bandwidth bw;
struct iwl_mld_link *mld_link;
mld_link = wiphy_dereference(mld->wiphy,
mld_vif->link[link_id]);
if (WARN_ON_ONCE(!mld_link))
continue;
bw = mld_link->rx_omi.bw_in_progress;
if (bw)
iwl_mld_change_link_omi_bw(mld, link_conf, bw);
}
}
static void
iwl_mld_mac80211_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
@@ -1453,11 +1422,6 @@ iwl_mld_mac80211_reconfig_complete(struct ieee80211_hw *hw,
case IEEE80211_RECONFIG_TYPE_RESTART:
mld->fw_status.in_hw_restart = false;
iwl_mld_send_recovery_cmd(mld, ERROR_RECOVERY_END_OF_RECOVERY);
ieee80211_iterate_interfaces(mld->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mld_restart_complete_vif, mld);
iwl_trans_finish_sw_reset(mld->trans);
/* no need to lock, adding in parallel would schedule too */
if (!list_empty(&mld->txqs_to_add))
@@ -1681,18 +1645,6 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld,
return -EBUSY;
}
/*
* If this is the first STA (i.e. the AP) it won't do
* anything, otherwise must leave for any new STA on
* any other interface, or for TDLS, etc.
* Need to call this _before_ adding the STA so it can
* look up the one STA to use to ask mac80211 to leave
* OMI; in the unlikely event that adding the new STA
* then fails we'll just re-enter OMI later (via the
* statistics notification handling.)
*/
iwl_mld_leave_omi_bw_reduction(mld);
ret = iwl_mld_add_sta(mld, sta, vif, STATION_TYPE_PEER);
if (ret)
return ret;
@@ -1918,6 +1870,10 @@ iwl_mld_mac80211_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
if (!iwl_enable_rx_ampdu()) {
ret = -EINVAL;
break;
}
ret = iwl_mld_ampdu_rx_start(mld, sta, tid, ssn, buf_size,
timeout);
break;
@@ -2671,6 +2627,7 @@ const struct ieee80211_ops iwl_mld_hw_ops = {
.mgd_complete_tx = iwl_mld_mac_mgd_complete_tx,
.sta_state = iwl_mld_mac80211_sta_state,
.sta_statistics = iwl_mld_mac80211_sta_statistics,
.get_survey = iwl_mld_mac80211_get_survey,
.flush = iwl_mld_mac80211_flush,
.flush_sta = iwl_mld_mac80211_flush_sta,
.ampdu_action = iwl_mld_mac80211_ampdu_action,

View File

@@ -251,7 +251,6 @@ static const struct iwl_hcmd_names iwl_mld_data_path_names[] = {
HCMD_NAME(TLC_MNG_CONFIG_CMD),
HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD),
HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
HCMD_NAME(OMI_SEND_STATUS_NOTIF),
HCMD_NAME(ESR_MODE_NOTIF),
HCMD_NAME(MONITOR_NOTIF),
HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
@@ -259,6 +258,13 @@ static const struct iwl_hcmd_names iwl_mld_data_path_names[] = {
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
};
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mld_scan_names[] = {
HCMD_NAME(CHANNEL_SURVEY_NOTIF),
};
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search
*/
@@ -310,6 +316,7 @@ const struct iwl_hcmd_arr iwl_mld_groups[] = {
[SYSTEM_GROUP] = HCMD_ARR(iwl_mld_system_names),
[MAC_CONF_GROUP] = HCMD_ARR(iwl_mld_mac_conf_names),
[DATA_PATH_GROUP] = HCMD_ARR(iwl_mld_data_path_names),
[SCAN_GROUP] = HCMD_ARR(iwl_mld_scan_names),
[LOCATION_GROUP] = HCMD_ARR(iwl_mld_location_names),
[REGULATORY_AND_NVM_GROUP] = HCMD_ARR(iwl_mld_reg_and_nvm_names),
[DEBUG_GROUP] = HCMD_ARR(iwl_mld_debug_names),
@@ -507,6 +514,7 @@ iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode)
kfree(mld->nvm_data);
kfree(mld->scan.cmd);
kfree(mld->channel_survey);
kfree(mld->error_recovery_buf);
kfree(mld->mcast_filter_cmd);

View File

@@ -160,6 +160,7 @@
* device
* @addresses: device MAC addresses.
* @scan: instance of the scan object
* @channel_survey: channel survey information collected during scan
* @wowlan: WoWLAN support data.
* @debug_max_sleep: maximum sleep time in D3 (for debug purposes)
* @led: the led device
@@ -253,6 +254,7 @@ struct iwl_mld {
struct mac_address addresses[IWL_MLD_MAX_ADDRESSES];
struct iwl_mld_scan scan;
struct iwl_mld_survey *channel_survey;
#ifdef CONFIG_PM_SLEEP
struct wiphy_wowlan_support wowlan;
u32 debug_max_sleep;

View File

@@ -78,13 +78,6 @@ static bool iwl_mld_cancel_##name##_notif(struct iwl_mld *mld, \
u8: (notif)->id_member); \
}
static bool iwl_mld_always_cancel(struct iwl_mld *mld,
struct iwl_rx_packet *pkt,
u32 obj_id)
{
return true;
}
/* Currently only defined for the RX_HANDLER_SIZES options. Use this for
* notifications that belong to a specific object, and that should be
* canceled when the object is removed
@@ -295,6 +288,8 @@ 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_VERSIONS(channel_survey_notif,
CMD_VER_ENTRY(1, iwl_umac_scan_channel_survey_notif))
CMD_VERSIONS(mfuart_notif,
CMD_VER_ENTRY(2, iwl_mfuart_load_notif))
CMD_VERSIONS(update_mcc,
@@ -348,9 +343,6 @@ CMD_VERSIONS(time_msmt_notif,
CMD_VER_ENTRY(1, iwl_time_msmt_notify))
CMD_VERSIONS(time_sync_confirm_notif,
CMD_VER_ENTRY(1, iwl_time_msmt_cfm_notify))
CMD_VERSIONS(omi_status_notif,
CMD_VER_ENTRY(1, iwl_omi_send_status_notif_v1)
CMD_VER_ENTRY(2, iwl_omi_send_status_notif))
CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy))
CMD_VERSIONS(beacon_filter_notif, CMD_VER_ENTRY(2, iwl_beacon_filter_notif))
@@ -368,7 +360,6 @@ DEFINE_SIMPLE_CANCELLATION(probe_resp_data, iwl_probe_resp_data_notif,
mac_id)
DEFINE_SIMPLE_CANCELLATION(uapsd_misbehaving_ap, iwl_uapsd_misbehaving_ap_notif,
mac_id)
#define iwl_mld_cancel_omi_status_notif iwl_mld_always_cancel
DEFINE_SIMPLE_CANCELLATION(ftm_resp, iwl_tof_range_rsp_ntfy, request_id)
DEFINE_SIMPLE_CANCELLATION(beacon_filter, iwl_beacon_filter_notif, link_id)
@@ -415,6 +406,10 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
RX_HANDLER_NO_VAL(LEGACY_GROUP, MATCH_FOUND_NOTIFICATION,
match_found_notif, RX_HANDLER_SYNC)
RX_HANDLER_NO_OBJECT(SCAN_GROUP, CHANNEL_SURVEY_NOTIF,
channel_survey_notif,
RX_HANDLER_ASYNC)
RX_HANDLER_NO_OBJECT(STATISTICS_GROUP, STATISTICS_OPER_NOTIF,
stats_oper_notif, RX_HANDLER_ASYNC)
RX_HANDLER_NO_OBJECT(STATISTICS_GROUP, STATISTICS_OPER_PART1_NOTIF,
@@ -461,8 +456,6 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = {
RX_HANDLER_NO_OBJECT(LEGACY_GROUP,
WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION,
time_sync_confirm_notif, RX_HANDLER_ASYNC)
RX_HANDLER_OF_LINK(DATA_PATH_GROUP, OMI_SEND_STATUS_NOTIF,
omi_status_notif)
RX_HANDLER_OF_LINK(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF,
beacon_filter_notif)
RX_HANDLER_OF_FTM_REQ(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF,

View File

@@ -1089,6 +1089,15 @@ static void iwl_mld_rx_eht(struct iwl_mld *mld, struct sk_buff *skb,
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
/* update aggregation data for monitor sake on default queue */
if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) &&
(phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) {
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
if (phy_data->data0 &
cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF))
rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
}
if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD)
iwl_mld_decode_eht_phy_data(mld, phy_data, rx_status, eht, usig);

View File

@@ -4,6 +4,8 @@
*/
#include <linux/crc32.h>
#include "iwl-utils.h"
#include "mld.h"
#include "scan.h"
#include "hcmd.h"
@@ -482,7 +484,9 @@ iwl_mld_scan_get_cmd_gen_flags(struct iwl_mld *mld,
static u8
iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld,
struct iwl_mld_scan_params *params,
struct ieee80211_vif *vif, u16 gen_flags)
struct ieee80211_vif *vif,
enum iwl_mld_scan_status scan_status,
u16 gen_flags)
{
u8 flags = 0;
@@ -494,6 +498,17 @@ iwl_mld_scan_get_cmd_gen_flags2(struct iwl_mld *mld,
if (params->scan_6ghz)
flags |= IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_DONT_TOGGLE_ANT;
/* For AP interfaces, request survey data for regular scans and if
* it is supported. For non-AP interfaces, EBS will be enabled and
* the results may be missing information for some channels.
*/
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)
flags |= IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS;
return flags;
}
@@ -544,6 +559,7 @@ iwl_mld_scan_cmd_set_gen_params(struct iwl_mld *mld,
u16 gen_flags = iwl_mld_scan_get_cmd_gen_flags(mld, params, vif,
scan_status);
u8 gen_flags2 = iwl_mld_scan_get_cmd_gen_flags2(mld, params, vif,
scan_status,
gen_flags);
IWL_DEBUG_SCAN(mld, "General: flags=0x%x, flags2=0x%x\n",
@@ -1752,6 +1768,11 @@ int iwl_mld_regular_scan_start(struct iwl_mld *mld, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies)
{
/* Clear survey data when starting the first part of a regular scan */
if (req->first_part && mld->channel_survey)
memset(mld->channel_survey->channels, 0,
sizeof(mld->channel_survey->channels[0]) *
mld->channel_survey->n_channels);
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
iwl_mld_emlsr_block_tmp_non_bss(mld);
@@ -2025,3 +2046,136 @@ int iwl_mld_alloc_scan_cmd(struct iwl_mld *mld)
return 0;
}
static int iwl_mld_chanidx_from_phy(struct iwl_mld *mld,
enum nl80211_band band,
u16 phy_chan_num)
{
struct ieee80211_supported_band *sband = mld->wiphy->bands[band];
if (WARN_ON_ONCE(!sband))
return -EINVAL;
for (int chan_idx = 0; chan_idx < sband->n_channels; chan_idx++) {
struct ieee80211_channel *channel = &sband->channels[chan_idx];
if (channel->hw_value == phy_chan_num)
return chan_idx;
}
return -EINVAL;
}
void iwl_mld_handle_channel_survey_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt)
{
const struct iwl_umac_scan_channel_survey_notif *notif =
(void *)pkt->data;
struct iwl_mld_survey_channel *info;
enum nl80211_band band;
int chan_idx;
if (!mld->channel_survey) {
size_t n_channels = 0;
for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!mld->wiphy->bands[band])
continue;
n_channels += mld->wiphy->bands[band]->n_channels;
}
mld->channel_survey = kzalloc(struct_size(mld->channel_survey,
channels, n_channels),
GFP_KERNEL);
if (!mld->channel_survey)
return;
mld->channel_survey->n_channels = n_channels;
n_channels = 0;
for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!mld->wiphy->bands[band])
continue;
mld->channel_survey->bands[band] =
&mld->channel_survey->channels[n_channels];
n_channels += mld->wiphy->bands[band]->n_channels;
}
}
band = iwl_mld_phy_band_to_nl80211(le32_to_cpu(notif->band));
chan_idx = iwl_mld_chanidx_from_phy(mld, band,
le32_to_cpu(notif->channel));
if (WARN_ON_ONCE(chan_idx < 0))
return;
IWL_DEBUG_SCAN(mld, "channel survey received for freq %d\n",
mld->wiphy->bands[band]->channels[chan_idx].center_freq);
info = &mld->channel_survey->bands[band][chan_idx];
/* Times are all in ms */
info->time = le32_to_cpu(notif->active_time);
info->time_busy = le32_to_cpu(notif->busy_time);
info->noise =
iwl_average_neg_dbm(notif->noise, ARRAY_SIZE(notif->noise));
}
int iwl_mld_mac80211_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
int curr_idx = 0;
if (!mld->channel_survey)
return -ENOENT;
/* Iterate bands/channels to find the requested index.
* Logically this returns the entry with index "idx" from a flattened
* survey result array that only contains channels with information.
* The current index into this flattened array is tracked in curr_idx.
*/
for (enum nl80211_band band = 0; band < NUM_NL80211_BANDS; band++) {
struct ieee80211_supported_band *sband =
mld->wiphy->bands[band];
if (!sband)
continue;
for (int per_band_idx = 0;
per_band_idx < sband->n_channels;
per_band_idx++) {
struct iwl_mld_survey_channel *info =
&mld->channel_survey->bands[band][per_band_idx];
/* Skip entry entirely, it was not reported/scanned,
* do not increase curr_idx for this entry.
*/
if (!info->time)
continue;
/* Search did not reach the requested entry yet,
* increment curr_idx and continue.
*/
if (idx != curr_idx) {
curr_idx++;
continue;
}
/* Found (the next) channel to report */
survey->channel = &sband->channels[per_band_idx];
survey->filled = SURVEY_INFO_TIME |
SURVEY_INFO_TIME_BUSY;
survey->time = info->time;
survey->time_busy = info->time_busy;
survey->noise = info->noise;
if (survey->noise < 0)
survey->filled |= SURVEY_INFO_NOISE_DBM;
return 0;
}
}
return -ENOENT;
}

View File

@@ -30,6 +30,12 @@ void iwl_mld_handle_match_found_notif(struct iwl_mld *mld,
void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt);
int iwl_mld_mac80211_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
void iwl_mld_handle_channel_survey_notif(struct iwl_mld *mld,
struct iwl_rx_packet *pkt);
#define WFA_TPC_IE_LEN 9
static inline int iwl_mld_scan_max_template_size(void)
@@ -133,4 +139,35 @@ struct iwl_mld_scan {
u64 last_mlo_scan_time;
};
/**
* struct iwl_mld_survey_channel - per-channel survey information
*
* Driver version of &struct survey_info with just the data we want to report.
*
* @time: time in ms the radio was on the channel
* @time_busy: time in ms the channel was sensed busy
* @noise: channel noise in dBm
*/
struct iwl_mld_survey_channel {
u32 time;
u32 time_busy;
s8 noise;
};
/**
* struct iwl_mld_survey - survey information
*
* Survey information for all available channels.
*
* @bands: per-band array for per-channel survey data, points into @channels
* @n_channels: Number of @channels entries that are allocated
* @channels: per-channel information
*/
struct iwl_mld_survey {
struct iwl_mld_survey_channel *bands[NUM_NL80211_BANDS];
int n_channels;
struct iwl_mld_survey_channel channels[] __counted_by(n_channels);
};
#endif /* __iwl_mld_scan_h__ */

View File

@@ -508,8 +508,6 @@ void iwl_mld_handle_stats_oper_notif(struct iwl_mld *mld,
iwl_mld_process_per_link_stats(mld, stats->per_link, curr_ts_usec);
iwl_mld_process_per_sta_stats(mld, stats->per_sta);
iwl_mld_process_per_phy_stats(mld, stats->per_phy);
iwl_mld_check_omi_bw_reduction(mld);
}
void iwl_mld_handle_stats_oper_part1_notif(struct iwl_mld *mld,

View File

@@ -494,7 +494,7 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
if (data.have_rsc_tsc)
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,
CMD_ASYNC,
sizeof(data.rsc_tsc),
sizeof(*data.rsc_tsc),
data.rsc_tsc);
else
ret = 0;

View File

@@ -301,7 +301,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_init_link(&mvmvif->deflink);
/* No need to allocate data queues to P2P Device MAC and NAN.*/
/* No need to allocate data queues to P2P Device MAC */
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
return 0;
@@ -976,7 +976,7 @@ u8 iwl_mvm_mac_ctxt_get_beacon_rate(struct iwl_mvm *mvm,
static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct sk_buff *beacon,
struct iwl_tx_cmd_v6 *tx)
struct iwl_tx_cmd_v6_params *tx_params)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_tx_info *info;
@@ -986,30 +986,30 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
info = IEEE80211_SKB_CB(beacon);
/* Set up TX command fields */
tx->len = cpu_to_le16((u16)beacon->len);
tx->sta_id = mvmvif->deflink.bcast_sta.sta_id;
tx->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_params->len = cpu_to_le16((u16)beacon->len);
tx_params->sta_id = mvmvif->deflink.bcast_sta.sta_id;
tx_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF;
tx_flags |=
iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) <<
TX_CMD_FLG_BT_PRIO_POS;
tx->tx_flags = cpu_to_le32(tx_flags);
tx_params->tx_flags = cpu_to_le32(tx_flags);
if (!fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION)) {
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
tx->rate_n_flags =
tx_params->rate_n_flags =
cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) <<
RATE_MCS_ANT_POS);
}
rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
tx->rate_n_flags |=
tx_params->rate_n_flags |=
cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
if (rate == IWL_FIRST_CCK_RATE)
tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
tx_params->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
}

View File

@@ -5,6 +5,7 @@
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#include <linux/kernel.h>
#include <linux/fips.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -461,7 +462,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IWL_ERR(mvm,
"iwlmvm doesn't allow to disable BT Coex, check bt_coex_active module parameter\n");
ieee80211_hw_set(hw, MFP_CAPABLE);
if (!fips_enabled)
ieee80211_hw_set(hw, MFP_CAPABLE);
mvm->ciphers[hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC;
hw->wiphy->n_cipher_suites++;
if (iwl_mvm_has_new_rx_api(mvm)) {
@@ -485,12 +488,17 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa;
}
if (sec_key_ver &&
/*
* beacon protection must be handled by firmware,
* so cannot be done with fips_enabled
*/
if (!fips_enabled && sec_key_ver &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT))
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION);
else if (fw_has_capa(&mvm->fw->ucode_capa,
else if (!fips_enabled &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT))
wiphy_ext_feature_set(hw->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT);
@@ -730,7 +738,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
#ifdef CONFIG_PM_SLEEP
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
device_can_wakeup(mvm->trans->dev)) {
device_can_wakeup(mvm->trans->dev) && !fips_enabled) {
mvm->wowlan.flags |= WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
@@ -1825,12 +1833,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif);
/* Currently not much to do for NAN */
if (vif->type == NL80211_IFTYPE_NAN) {
ret = 0;
goto out;
}
/*
* The AP binding flow can be done only after the beacon
* template is configured (which happens only in the mac80211

View File

@@ -282,9 +282,6 @@ int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
return -EOPNOTSUPP;
if (WARN_ONCE(mvmvif->uploaded, "Adding active MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
@@ -307,9 +304,6 @@ int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm,
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
return -EOPNOTSUPP;
if (WARN_ONCE(!mvmvif->uploaded, "Changing inactive MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
@@ -327,9 +321,6 @@ int iwl_mvm_mld_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
};
int ret;
if (WARN_ON_ONCE(vif->type == NL80211_IFTYPE_NAN))
return -EOPNOTSUPP;
if (WARN_ONCE(!mvmvif->uploaded, "Removing inactive MAC %pM/%d\n",
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;

View File

@@ -1325,7 +1325,6 @@ struct iwl_mvm {
u8 range_resp;
} cmd_ver;
struct ieee80211_vif *nan_vif;
struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID];
/*
@@ -1821,11 +1820,12 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta);
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_tx_cmd_v6 *tx_cmd,
struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info, u8 sta_id);
void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd_v6 *tx_cmd,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc);
void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc);
void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
@@ -1854,12 +1854,12 @@ int iwl_mvm_set_sta_pkt_ext(struct iwl_mvm *mvm,
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
struct iwl_tx_cmd_v6 *tx_cmd)
struct iwl_tx_cmd_v6_params *tx_cmd_params)
{
struct ieee80211_key_conf *keyconf = info->control.hw_key;
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
tx_cmd_params->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd_params->key, keyconf->key, keyconf->keylen);
}
static inline void iwl_mvm_wait_for_async_handlers(struct iwl_mvm *mvm)

View File

@@ -231,7 +231,6 @@ static void iwl_mvm_allow_uapsd_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_NAN:
data->allow_uapsd = false;
break;
case NL80211_IFTYPE_STATION:

View File

@@ -905,10 +905,15 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
* already ahead and it will be dropped.
* If the last sub-frame is not on this queue - we will get frame
* release notification with up to date NSSN.
* If this is the first frame that is stored in the buffer, the head_sn
* may be outdated. Update it based on the last NSSN to make sure it
* will be released when the frame release notification arrives.
*/
if (!amsdu || last_subframe)
iwl_mvm_release_frames(mvm, sta, napi, baid_data,
buffer, nssn);
else if (buffer->num_stored == 1)
buffer->head_sn = nssn;
spin_unlock_bh(&buffer->lock);
return true;

View File

@@ -148,12 +148,12 @@ static u32 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
* Sets most of the Tx cmd's fields
*/
void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_tx_cmd_v6 *tx_cmd,
struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info, u8 sta_id)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
u32 tx_flags = le32_to_cpu(tx_cmd_params->tx_flags);
u32 len = skb->len + FCS_LEN;
bool amsdu = false;
u8 ac;
@@ -173,7 +173,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ieee80211_is_data_qos(fc)) {
u8 *qc = ieee80211_get_qos_ctl(hdr);
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_cmd_params->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
amsdu = *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT;
} else if (ieee80211_is_back_req(fc)) {
@@ -182,17 +182,17 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
u16 ssn = le16_to_cpu(bar->start_seq_num);
tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;
tx_cmd->tid_tspec = (control &
tx_cmd_params->tid_tspec = (control &
IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
WARN_ON_ONCE(tx_cmd->tid_tspec >= IWL_MAX_TID_COUNT);
iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd->tid_tspec,
WARN_ON_ONCE(tx_cmd_params->tid_tspec >= IWL_MAX_TID_COUNT);
iwl_mvm_bar_check_trigger(mvm, bar->ra, tx_cmd_params->tid_tspec,
ssn);
} else {
if (ieee80211_is_data(fc))
tx_cmd->tid_tspec = IWL_TID_NON_QOS;
tx_cmd_params->tid_tspec = IWL_TID_NON_QOS;
else
tx_cmd->tid_tspec = IWL_MAX_TID_COUNT;
tx_cmd_params->tid_tspec = IWL_MAX_TID_COUNT;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
tx_flags |= TX_CMD_FLG_SEQ_CTL;
@@ -201,8 +201,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
}
/* Default to 0 (BE) when tid_spec is set to IWL_MAX_TID_COUNT */
if (tx_cmd->tid_tspec < IWL_MAX_TID_COUNT)
ac = tid_to_mac80211_ac[tx_cmd->tid_tspec];
if (tx_cmd_params->tid_tspec < IWL_MAX_TID_COUNT)
ac = tid_to_mac80211_ac[tx_cmd_params->tid_tspec];
else
ac = tid_to_mac80211_ac[0];
@@ -211,20 +211,20 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
if (ieee80211_is_mgmt(fc)) {
if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_ASSOC);
tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_ASSOC);
else if (ieee80211_is_action(fc))
tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
else
tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
/* The spec allows Action frames in A-MPDU, we don't support
* it
*/
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
} else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_MGMT);
} else {
tx_cmd->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
tx_cmd_params->pm_frame_timeout = cpu_to_le16(PM_FRAME_NONE);
}
if (ieee80211_is_data(fc) && len > mvm->rts_threshold &&
@@ -236,13 +236,13 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
ieee80211_action_contains_tpc(skb))
tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
tx_cmd->tx_flags = cpu_to_le32(tx_flags);
tx_cmd_params->tx_flags = cpu_to_le32(tx_flags);
/* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
tx_cmd->len = cpu_to_le16((u16)skb->len);
tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_cmd->sta_id = sta_id;
tx_cmd_params->len = cpu_to_le16((u16)skb->len);
tx_cmd_params->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_cmd_params->sta_id = sta_id;
tx_cmd->offload_assist =
tx_cmd_params->offload_assist =
cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, info, amsdu));
}
@@ -395,22 +395,23 @@ static __le32 iwl_mvm_get_tx_rate_n_flags(struct iwl_mvm *mvm,
/*
* Sets the fields in the Tx cmd that are rate related
*/
void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd_v6 *tx_cmd,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc)
void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc)
{
/* Set retry limit on RTS packets */
tx_cmd->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
tx_cmd_params->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
/* Set retry limit on DATA packets and Probe Responses*/
if (ieee80211_is_probe_resp(fc)) {
tx_cmd->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
tx_cmd->rts_retry_limit =
min(tx_cmd->data_retry_limit, tx_cmd->rts_retry_limit);
tx_cmd_params->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
tx_cmd_params->rts_retry_limit =
min(tx_cmd_params->data_retry_limit, tx_cmd_params->rts_retry_limit);
} else if (ieee80211_is_back_req(fc)) {
tx_cmd->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
tx_cmd_params->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
} else {
tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
tx_cmd_params->data_retry_limit = IWL_DEFAULT_TX_RETRY;
}
/*
@@ -423,17 +424,17 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd_v6 *tx_cmd,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
tx_cmd_params->initial_rate_index = 0;
tx_cmd_params->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
return;
}
} else if (ieee80211_is_back_req(fc)) {
tx_cmd->tx_flags |=
tx_cmd_params->tx_flags |=
cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
}
/* Set the rate in the TX cmd */
tx_cmd->rate_n_flags = iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc);
tx_cmd_params->rate_n_flags = iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc);
}
static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
@@ -458,7 +459,7 @@ static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,
*/
static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
struct iwl_tx_cmd_v6 *tx_cmd,
struct iwl_tx_cmd_v6_params *tx_cmd_params,
struct sk_buff *skb_frag,
int hdrlen)
{
@@ -469,26 +470,26 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd);
iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd_params);
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break;
case WLAN_CIPHER_SUITE_TKIP:
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
tx_cmd_params->sec_ctl = TX_CMD_SEC_TKIP;
pn = atomic64_inc_return(&keyconf->tx_pn);
ieee80211_tkip_add_iv(crypto_hdr, keyconf, pn);
ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd_params->key);
break;
case WLAN_CIPHER_SUITE_WEP104:
tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
tx_cmd_params->sec_ctl |= TX_CMD_SEC_KEY128;
fallthrough;
case WLAN_CIPHER_SUITE_WEP40:
tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
tx_cmd_params->sec_ctl |= TX_CMD_SEC_WEP |
((keyconf->keyidx << TX_CMD_SEC_WEP_KEY_IDX_POS) &
TX_CMD_SEC_WEP_KEY_IDX_MSK);
memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
memcpy(&tx_cmd_params->key[3], keyconf->key, keyconf->keylen);
break;
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
@@ -501,12 +502,12 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
* one.
* Need to handle this.
*/
tx_cmd->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
tx_cmd->key[0] = keyconf->hw_key_idx;
tx_cmd_params->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
tx_cmd_params->key[0] = keyconf->hw_key_idx;
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break;
default:
tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
tx_cmd_params->sec_ctl |= TX_CMD_SEC_EXT;
}
}
@@ -636,11 +637,11 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd = (struct iwl_tx_cmd_v6 *)dev_cmd->payload;
if (info->control.hw_key)
iwl_mvm_set_tx_cmd_crypto(mvm, info, tx_cmd, skb, hdrlen);
iwl_mvm_set_tx_cmd_crypto(mvm, info, &tx_cmd->params, skb, hdrlen);
iwl_mvm_set_tx_cmd(mvm, skb, tx_cmd, info, sta_id);
iwl_mvm_set_tx_cmd(mvm, skb, &tx_cmd->params, info, sta_id);
iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
iwl_mvm_set_tx_cmd_rate(mvm, &tx_cmd->params, info, sta, hdr->frame_control);
/* Copy MAC header from skb into command buffer */
iwl_mvm_copy_hdr(tx_cmd->hdr, hdr, hdrlen, addr3_override);

View File

@@ -1963,7 +1963,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
* have in the MPDU by themselves, but that we duplicate into
* all the different MSDUs inside the A-MSDU.
*/
le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
le16_add_cpu(&tx_cmd->params.len, -snap_ip_tcp_hdrlen);
tso_start(skb, &tso);
@@ -2006,7 +2006,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr,
hdr_tb_phys, hdr_tb_len);
/* add this subframe's headers' length to the tx_cmd */
le16_add_cpu(&tx_cmd->len, pos_hdr - subf_hdrs_start);
le16_add_cpu(&tx_cmd->params.len, pos_hdr - subf_hdrs_start);
/* prepare the start_hdr for the next subframe */
start_hdr = pos_hdr;
@@ -2074,11 +2074,11 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans,
__le16 bc_ent;
struct iwl_device_tx_cmd *dev_cmd = txq->entries[txq->write_ptr].cmd;
struct iwl_tx_cmd_v6 *tx_cmd = (void *)dev_cmd->payload;
u8 sta_id = tx_cmd->sta_id;
u8 sta_id = tx_cmd->params.sta_id;
scd_bc_tbl = trans_pcie->txqs.scd_bc_tbls.addr;
sec_ctl = tx_cmd->sec_ctl;
sec_ctl = tx_cmd->params.sec_ctl;
switch (sec_ctl & TX_CMD_SEC_MSK) {
case TX_CMD_SEC_CCM:
@@ -2185,10 +2185,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tb0_phys = iwl_txq_get_first_tb_dma(txq, txq->write_ptr);
scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
offsetof(struct iwl_tx_cmd_v6, scratch);
offsetof(struct iwl_tx_cmd_v6_params, scratch);
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
tx_cmd->params.dram_lsb_ptr = cpu_to_le32(scratch_phys);
tx_cmd->params.dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_meta = &txq->entries[txq->write_ptr].meta;
@@ -2210,7 +2210,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tb1_len = ALIGN(len, 4);
/* Tell NIC about any 2-byte padding after MAC header */
if (tb1_len != len)
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_MH_PAD);
tx_cmd->params.tx_flags |= cpu_to_le32(TX_CMD_FLG_MH_PAD);
} else {
tb1_len = len;
}
@@ -2225,7 +2225,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
/* there must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_v6) < IWL_FIRST_TB_SIZE);
BUILD_BUG_ON(sizeof(struct iwl_cmd_header) +
offsetofend(struct iwl_tx_cmd_v6, scratch) >
offsetofend(struct iwl_tx_cmd_v6_params, scratch) >
IWL_FIRST_TB_SIZE);
/* map the data for TB1 */
@@ -2271,7 +2271,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tfd = iwl_txq_get_tfd(trans, txq, txq->write_ptr);
/* Set up entry for this TFD in Tx byte-count array */
iwl_txq_gen1_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),
iwl_txq_gen1_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->params.len),
iwl_txq_gen1_tfd_get_num_tbs(tfd));
wait_write_ptr = ieee80211_has_morefrags(fc);
@@ -2323,7 +2323,7 @@ static void iwl_txq_gen1_inval_byte_cnt_tbl(struct iwl_trans *trans,
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
if (txq_id != trans->conf.cmd_queue)
sta_id = tx_cmd->sta_id;
sta_id = tx_cmd->params.sta_id;
bc_ent = cpu_to_le16(1 | (sta_id << 12));

View File

@@ -238,6 +238,33 @@ static void devinfo_no_mac_cfg_dups(struct kunit *test)
}
}
static void devinfo_api_range(struct kunit *test)
{
/* Check that all iwl_mac_cfg's have either both min and max set, or neither */
for (int i = 0; iwl_hw_card_ids[i].vendor; i++) {
const struct iwl_mac_cfg *mac_cfg =
(void *)iwl_hw_card_ids[i].driver_data;
const struct iwl_family_base_params *base = mac_cfg->base;
KUNIT_EXPECT_EQ_MSG(test, !!base->ucode_api_min,
!!base->ucode_api_max,
"%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n",
base, base->ucode_api_min,
base->ucode_api_max);
}
/* Check the same for the iwl_rf_cfg's */
for (int i = 0; i < iwl_dev_info_table_size; i++) {
const struct iwl_rf_cfg *rf_cfg = iwl_dev_info_table[i].cfg;
KUNIT_EXPECT_EQ_MSG(test, !!rf_cfg->ucode_api_min,
!!rf_cfg->ucode_api_max,
"%ps: ucode_api_min (%u) and ucode_api_min (%u) should be both set or neither.\n",
rf_cfg, rf_cfg->ucode_api_min,
rf_cfg->ucode_api_max);
}
}
static struct kunit_case devinfo_test_cases[] = {
KUNIT_CASE(devinfo_table_order),
KUNIT_CASE(devinfo_discrete_match),
@@ -248,6 +275,7 @@ static struct kunit_case devinfo_test_cases[] = {
KUNIT_CASE(devinfo_check_killer_subdev),
KUNIT_CASE(devinfo_pci_ids),
KUNIT_CASE(devinfo_no_mac_cfg_dups),
KUNIT_CASE(devinfo_api_range),
{}
};