Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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

- more cleanups of d3 code
- cleanups of the transport layer
====================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+885 -3394
+9 -9
drivers/net/wireless/intel/iwlwifi/cfg/bz.c
··· 9 9 #include "iwl-prph.h" 10 10 #include "fw/api/txq.h" 11 11 12 - /* Highest firmware API version supported */ 13 - #define IWL_BZ_UCODE_API_MAX 102 12 + /* Highest firmware core release supported */ 13 + #define IWL_BZ_UCODE_CORE_MAX 99 14 14 15 15 /* Lowest firmware API version supported */ 16 - #define IWL_BZ_UCODE_API_MIN 98 16 + #define IWL_BZ_UCODE_API_MIN 100 17 17 18 18 /* Memory offsets and lengths */ 19 19 #define IWL_BZ_SMEM_OFFSET 0x400000 ··· 75 75 }, 76 76 }, 77 77 .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, 78 - .ucode_api_max = IWL_BZ_UCODE_API_MAX, 78 + .ucode_api_max = ENCODE_CORE_AS_API(IWL_BZ_UCODE_CORE_MAX), 79 79 .ucode_api_min = IWL_BZ_UCODE_API_MIN, 80 80 }; 81 81 ··· 101 101 .low_latency_xtal = true, 102 102 }; 103 103 104 - IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX); 105 - IWL_FW_AND_PNVM(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX); 106 - IWL_FW_AND_PNVM(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_API_MAX); 107 - IWL_FW_AND_PNVM(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX); 108 - IWL_FW_AND_PNVM(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX); 104 + IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 105 + IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 106 + IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 107 + IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 108 + IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+5 -8
drivers/net/wireless/intel/iwlwifi/cfg/dr.c
··· 8 8 #include "iwl-prph.h" 9 9 #include "fw/api/txq.h" 10 10 11 - /* Highest firmware API version supported */ 12 - #define IWL_DR_UCODE_API_MAX 102 11 + /* Highest firmware core release supported */ 12 + #define IWL_DR_UCODE_CORE_MAX 99 13 13 14 14 /* Lowest firmware API version supported */ 15 - #define IWL_DR_UCODE_API_MIN 98 15 + #define IWL_DR_UCODE_API_MIN 100 16 16 17 17 /* Memory offsets and lengths */ 18 18 #define IWL_DR_SMEM_OFFSET 0x400000 19 19 #define IWL_DR_SMEM_LEN 0xD0000 20 20 21 21 #define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0" 22 - 23 - #define IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(api) \ 24 - IWL_DR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode" 25 22 26 23 static const struct iwl_family_base_params iwl_dr_base = { 27 24 .num_of_queues = 512, ··· 70 73 }, 71 74 }, 72 75 .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, 73 - .ucode_api_max = IWL_DR_UCODE_API_MAX, 76 + .ucode_api_max = ENCODE_CORE_AS_API(IWL_DR_UCODE_CORE_MAX), 74 77 .ucode_api_min = IWL_DR_UCODE_API_MIN, 75 78 }; 76 79 ··· 86 89 .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, 87 90 }; 88 91 89 - MODULE_FIRMWARE(IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX)); 92 + IWL_CORE_FW(IWL_DR_A_PE_A_FW_PRE, IWL_DR_UCODE_CORE_MAX); 90 93
+17 -5
drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c
··· 9 9 #define IWL_GF_UCODE_API_MAX 100 10 10 11 11 /* Lowest firmware API version supported */ 12 - #define IWL_GF_UCODE_API_MIN 98 12 + #define IWL_GF_UCODE_API_MIN 100 13 13 14 14 #define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" 15 15 #define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" ··· 22 22 #define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0" 23 23 #define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" 24 24 #define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" 25 + 26 + #define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \ 27 + IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" 28 + 29 + #define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \ 30 + IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" 31 + 32 + #define IWL_SC_A_GF_A_MODULE_FIRMWARE(api) \ 33 + IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" 34 + 35 + #define IWL_SC_A_GF4_A_MODULE_FIRMWARE(api) \ 36 + IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" 25 37 26 38 /* NVM versions */ 27 39 #define IWL_GF_NVM_VERSION 0x0a1d ··· 79 67 IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); 80 68 IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 81 69 IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 82 - IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); 83 - IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 84 - IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); 85 - IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 70 + MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); 71 + MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); 72 + MODULE_FIRMWARE(IWL_SC_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); 73 + MODULE_FIRMWARE(IWL_SC_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX));
+1 -1
drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c
··· 9 9 #define IWL_HR_UCODE_API_MAX 100 10 10 11 11 /* Lowest firmware API version supported */ 12 - #define IWL_HR_UCODE_API_MIN 98 12 + #define IWL_HR_UCODE_API_MIN 100 13 13 14 14 #define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" 15 15 #define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
+9 -9
drivers/net/wireless/intel/iwlwifi/cfg/sc.c
··· 9 9 #include "iwl-prph.h" 10 10 #include "fw/api/txq.h" 11 11 12 - /* Highest firmware API version supported */ 13 - #define IWL_SC_UCODE_API_MAX 102 12 + /* Highest firmware core release supported */ 13 + #define IWL_SC_UCODE_CORE_MAX 99 14 14 15 15 /* Lowest firmware API version supported */ 16 - #define IWL_SC_UCODE_API_MIN 98 16 + #define IWL_SC_UCODE_API_MIN 100 17 17 18 18 /* NVM versions */ 19 19 #define IWL_SC_NVM_VERSION 0x0a1d ··· 78 78 }, 79 79 }, 80 80 .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, 81 - .ucode_api_max = IWL_SC_UCODE_API_MAX, 81 + .ucode_api_max = ENCODE_CORE_AS_API(IWL_SC_UCODE_CORE_MAX), 82 82 .ucode_api_min = IWL_SC_UCODE_API_MIN, 83 83 }; 84 84 ··· 94 94 .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, 95 95 }; 96 96 97 - IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX); 98 - IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); 99 - IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); 100 - IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); 101 - IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); 97 + IWL_CORE_FW(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_CORE_MAX); 98 + IWL_CORE_FW(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_CORE_MAX); 99 + IWL_CORE_FW(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_CORE_MAX); 100 + IWL_CORE_FW(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_CORE_MAX); 101 + IWL_CORE_FW(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_CORE_MAX);
+2 -8
drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
··· 378 378 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, 379 379 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); 380 380 381 - iwl_trans_d3_suspend(priv->trans, false, true); 381 + iwl_trans_d3_suspend(priv->trans, true); 382 382 383 383 goto out; 384 384 ··· 422 422 struct ieee80211_vif *vif; 423 423 u32 base; 424 424 int ret; 425 - enum iwl_d3_status d3_status; 426 425 struct error_table_start { 427 426 /* cf. struct iwl_error_event_table */ 428 427 u32 valid; ··· 450 451 /* we'll clear ctx->vif during iwlagn_prepare_restart() */ 451 452 vif = ctx->vif; 452 453 453 - ret = iwl_trans_d3_resume(priv->trans, &d3_status, false, true); 454 + ret = iwl_trans_d3_resume(priv->trans, true); 454 455 if (ret) 455 456 goto out_unlock; 456 - 457 - if (d3_status != IWL_D3_STATUS_ALIVE) { 458 - IWL_INFO(priv, "Device was reset during suspend\n"); 459 - goto out_unlock; 460 - } 461 457 462 458 /* uCode is no longer operating by itself */ 463 459 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
+3 -3
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
··· 9 9 #include "acpi.h" 10 10 #include "fw/runtime.h" 11 11 12 - const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6, 13 - 0xA5, 0xB3, 0x1F, 0x73, 14 - 0x8E, 0x28, 0x5A, 0xDE); 12 + static const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6, 13 + 0xA5, 0xB3, 0x1F, 0x73, 14 + 0x8E, 0x28, 0x5A, 0xDE); 15 15 16 16 static const size_t acpi_dsm_size[DSM_FUNC_NUM_FUNCS] = { 17 17 [DSM_FUNC_QUERY] = sizeof(u32),
-2
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
··· 140 140 141 141 struct iwl_fw_runtime; 142 142 143 - extern const guid_t iwl_guid; 144 - 145 143 union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev, 146 144 int func, union acpi_object *args, 147 145 const guid_t *guid);
+1
drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
··· 367 367 ENABLE_NBNS_FILTERING = BIT(2), 368 368 ENABLE_DHCP_FILTERING = BIT(3), 369 369 ENABLE_STORE_BEACON = BIT(4), 370 + HAS_BEACON_PROTECTION = BIT(5), 370 371 }; 371 372 372 373 /**
+11 -23
drivers/net/wireless/intel/iwlwifi/fw/api/power.h
··· 571 571 /** 572 572 * union iwl_ppag_table_cmd - union for all versions of PPAG command 573 573 * @v1: command version 1 structure. 574 - * @v2: command version from 2 to 6 are same structure as v2. 575 - * but has a different format of the flags bitmap 576 - * @v3: command version 7 structure. 574 + * @v5: command version 5 structure. 575 + * @v7: command version 7 structure. 577 576 * @v1.flags: values from &enum iwl_ppag_flags 578 577 * @v1.gain: table of antenna gain values per chain and sub-band 579 578 * @v1.reserved: reserved 580 - * @v2.flags: values from &enum iwl_ppag_flags 581 - * @v2.gain: table of antenna gain values per chain and sub-band 582 - * @v3.ppag_config_info: see @struct bios_value_u32 583 - * @v3.gain: table of antenna gain values per chain and sub-band 584 - * @v3.reserved: reserved 579 + * @v5.flags: values from &enum iwl_ppag_flags 580 + * @v5.gain: table of antenna gain values per chain and sub-band 581 + * @v7.ppag_config_info: see @struct bios_value_u32 582 + * @v7.gain: table of antenna gain values per chain and sub-band 583 + * @v7.reserved: reserved 585 584 */ 586 585 union iwl_ppag_table_cmd { 587 586 struct { ··· 592 593 __le32 flags; 593 594 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; 594 595 s8 reserved[2]; 595 - } __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4, 596 - * VER5, VER6 597 - */ 596 + } __packed v5; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_5 */ 598 597 struct { 599 598 struct bios_value_u32 ppag_config_info; 600 599 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; 601 600 s8 reserved[2]; 602 - } __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ 601 + } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ 603 602 } __packed; 604 603 605 - #define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) 606 - #define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \ 604 + #define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) 605 + #define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V1_MASK | \ 607 606 IWL_PPAG_ETSI_LPI_UHB_MASK | \ 608 607 IWL_PPAG_USA_LPI_UHB_MASK) 609 - 610 - #define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \ 611 - IWL_PPAG_ETSI_VLP_UHB_MASK | \ 612 - IWL_PPAG_ETSI_SP_UHB_MASK | \ 613 - IWL_PPAG_USA_VLP_UHB_MASK | \ 614 - IWL_PPAG_USA_SP_UHB_MASK | \ 615 - IWL_PPAG_CANADA_LPI_UHB_MASK | \ 616 - IWL_PPAG_CANADA_VLP_UHB_MASK | \ 617 - IWL_PPAG_CANADA_SP_UHB_MASK) 618 608 619 609 #define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26 620 610 #define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13
+35
drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
··· 24 24 * for BPSK (MCS 0) with 2 spatial 25 25 * streams 26 26 * @IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK: enable support for EHT extra LTF 27 + * @IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK: support ELR 1.5 Mbps 28 + * @IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK: support ELR 3 Mbps 27 29 */ 28 30 enum iwl_tlc_mng_cfg_flags { 29 31 IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0), ··· 34 32 IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3), 35 33 IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4), 36 34 IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK = BIT(6), 35 + IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK = BIT(7), 36 + IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK = BIT(8), 37 37 }; 38 38 39 39 /** ··· 203 199 __le16 max_mpdu_len; 204 200 __le16 max_tx_op; 205 201 } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */ 202 + 203 + /** 204 + * struct iwl_tlc_config_cmd - TLC configuration 205 + * @sta_id: station id 206 + * @reserved1: reserved 207 + * @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw 208 + * @mode: &enum iwl_tlc_mng_cfg_mode 209 + * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains 210 + * @sgi_ch_width_supp: bitmap of SGI support per channel width 211 + * use BIT(&enum iwl_tlc_mng_cfg_cw) 212 + * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags 213 + * @non_ht_rates: bitmap of supported legacy rates 214 + * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width> 215 + * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz). 216 + * @max_mpdu_len: max MPDU length, in bytes 217 + * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI), 218 + * set zero for no limit. 219 + */ 220 + struct iwl_tlc_config_cmd { 221 + u8 sta_id; 222 + u8 reserved1[3]; 223 + u8 max_ch_width; 224 + u8 mode; 225 + u8 chains; 226 + u8 sgi_ch_width_supp; 227 + __le16 flags; 228 + __le16 non_ht_rates; 229 + __le32 ht_rates[IWL_TLC_NSS_MAX][IWL_TLC_MCS_PER_BW_NUM_V4]; 230 + __le16 max_mpdu_len; 231 + __le16 max_tx_op; 232 + } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_5 */ 206 233 207 234 /** 208 235 * enum iwl_tlc_update_flags - updated fields
+2 -37
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
··· 2393 2393 struct iwl_fw_ini_dump_cfg_name *cfg_name; 2394 2394 u32 size = sizeof(*tlv) + sizeof(*dump); 2395 2395 u32 num_of_cfg_names = 0; 2396 - u32 hw_type, is_cdb, is_jacket; 2396 + u32 hw_type, is_cdb; 2397 2397 2398 2398 list_for_each_entry(node, &fwrt->trans->dbg.debug_info_tlv_list, list) { 2399 2399 size += sizeof(*cfg_name); ··· 2426 2426 hw_type = CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev); 2427 2427 2428 2428 is_cdb = CSR_HW_RFID_IS_CDB(fwrt->trans->info.hw_rf_id); 2429 - is_jacket = !!(iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR) & 2430 - WFPM_OTP_CFG1_IS_JACKET_BIT); 2431 - 2432 - /* Use bits 12 and 13 to indicate jacket/CDB, respectively */ 2433 - hw_type |= (is_jacket | (is_cdb << 1)) << IWL_JACKET_CDB_SHIFT; 2429 + hw_type |= IWL_CDB_MASK(is_cdb); 2434 2430 2435 2431 dump->hw_type = cpu_to_le32(hw_type); 2436 2432 ··· 2470 2474 * the first TLV in the dump 2471 2475 */ 2472 2476 list_add(&entry->list, list); 2473 - 2474 - return entry->size; 2475 - } 2476 - 2477 - static u32 iwl_dump_ini_file_name_info(struct iwl_fw_runtime *fwrt, 2478 - struct list_head *list) 2479 - { 2480 - struct iwl_fw_ini_dump_entry *entry; 2481 - struct iwl_dump_file_name_info *tlv; 2482 - u32 len = strnlen(fwrt->trans->dbg.dump_file_name_ext, 2483 - IWL_FW_INI_MAX_NAME); 2484 - 2485 - if (!fwrt->trans->dbg.dump_file_name_ext_valid) 2486 - return 0; 2487 - 2488 - entry = vzalloc(sizeof(*entry) + sizeof(*tlv) + len); 2489 - if (!entry) 2490 - return 0; 2491 - 2492 - entry->size = sizeof(*tlv) + len; 2493 - 2494 - tlv = (void *)entry->data; 2495 - tlv->type = cpu_to_le32(IWL_INI_DUMP_NAME_TYPE); 2496 - tlv->len = cpu_to_le32(len); 2497 - memcpy(tlv->data, fwrt->trans->dbg.dump_file_name_ext, len); 2498 - 2499 - /* add the dump file name extension tlv to the list */ 2500 - list_add_tail(&entry->list, list); 2501 - 2502 - fwrt->trans->dbg.dump_file_name_ext_valid = false; 2503 2477 2504 2478 return entry->size; 2505 2479 } ··· 2730 2764 &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]); 2731 2765 2732 2766 if (size) { 2733 - size += iwl_dump_ini_file_name_info(fwrt, list); 2734 2767 size += iwl_dump_ini_info(fwrt, trigger, list); 2735 2768 } 2736 2769
-52
drivers/net/wireless/intel/iwlwifi/fw/dump.c
··· 14 14 #include "iwl-csr.h" 15 15 #include "pnvm.h" 16 16 17 - #define FW_ASSERT_LMAC_FATAL 0x70 18 - #define FW_ASSERT_LMAC2_FATAL 0x72 19 - #define FW_ASSERT_UMAC_FATAL 0x71 20 - #define UMAC_RT_NMI_LMAC2_FATAL 0x72 21 - #define RT_NMI_INTERRUPT_OTHER_LMAC_FATAL 0x73 22 - #define FW_ASSERT_NMI_UNKNOWN 0x84 23 - 24 17 /* 25 18 * Note: This structure is read from the device with IO accesses, 26 19 * and the reading already does the endian conversion. As it is ··· 96 103 #define ERROR_START_OFFSET (1 * sizeof(u32)) 97 104 #define ERROR_ELEM_SIZE (7 * sizeof(u32)) 98 105 99 - static bool iwl_fwrt_if_errorid_other_cpu(u32 err_id) 100 - { 101 - err_id &= 0xFF; 102 - 103 - if ((err_id >= FW_ASSERT_LMAC_FATAL && 104 - err_id <= RT_NMI_INTERRUPT_OTHER_LMAC_FATAL) || 105 - err_id == FW_ASSERT_NMI_UNKNOWN) 106 - return true; 107 - return false; 108 - } 109 - 110 106 static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt) 111 107 { 112 108 struct iwl_trans *trans = fwrt->trans; ··· 112 130 113 131 if (table.valid) 114 132 fwrt->dump.umac_err_id = table.error_id; 115 - 116 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.umac_err_id) && 117 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 118 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 119 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 120 - "0x%x", fwrt->dump.umac_err_id); 121 - } 122 133 123 134 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 124 135 IWL_ERR(trans, "Start IWL Error Log Dump:\n"); ··· 187 212 188 213 if (table.valid) 189 214 fwrt->dump.lmac_err_id[lmac_num] = table.error_id; 190 - 191 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.lmac_err_id[lmac_num]) && 192 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 193 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 194 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 195 - "0x%x", fwrt->dump.lmac_err_id[lmac_num]); 196 - } 197 215 198 216 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 199 217 IWL_ERR(trans, "Start IWL Error Log Dump:\n"); ··· 273 305 274 306 iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); 275 307 276 - if (table.valid) 277 - fwrt->dump.tcm_err_id[idx] = table.error_id; 278 - 279 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.tcm_err_id[idx]) && 280 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 281 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 282 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 283 - "0x%x", fwrt->dump.tcm_err_id[idx]); 284 - } 285 - 286 308 IWL_ERR(fwrt, "TCM%d status:\n", idx + 1); 287 309 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id); 288 310 IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2); ··· 335 377 return; 336 378 337 379 iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); 338 - 339 - if (table.valid) 340 - fwrt->dump.rcm_err_id[idx] = table.error_id; 341 - 342 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.rcm_err_id[idx]) && 343 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 344 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 345 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 346 - "0x%x", fwrt->dump.rcm_err_id[idx]); 347 - } 348 380 349 381 IWL_ERR(fwrt, "RCM%d status:\n", idx + 1); 350 382 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
+2 -1
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
··· 372 372 u8 cfg_name[IWL_FW_INI_MAX_CFG_NAME]; 373 373 } __packed; 374 374 375 - #define IWL_JACKET_CDB_SHIFT 12 375 + #define IWL_CDB_MASK(val) val << 13 376 + 376 377 377 378 /* struct iwl_fw_ini_dump_info - ini dump information 378 379 * @version: dump version
+67 -14
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
··· 237 237 return -ENOENT; 238 238 } 239 239 240 - static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len) 240 + static u8 *iwl_pnvm_get_from_fs(struct iwl_trans *trans, size_t *len) 241 241 { 242 242 const struct firmware *pnvm; 243 243 char pnvm_name[MAX_PNVM_NAME]; 244 244 size_t new_len; 245 + u8 *data; 245 246 int ret; 246 247 247 248 iwl_pnvm_get_fs_name(trans, pnvm_name, sizeof(pnvm_name)); ··· 251 250 if (ret) { 252 251 IWL_DEBUG_FW(trans, "PNVM file %s not found %d\n", 253 252 pnvm_name, ret); 254 - return ret; 253 + return NULL; 255 254 } 256 255 257 256 new_len = pnvm->size; 258 - *data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL); 257 + data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL); 259 258 release_firmware(pnvm); 260 259 261 - if (!*data) 262 - return -ENOMEM; 260 + if (!data) 261 + return NULL; 263 262 264 263 *len = new_len; 265 264 266 - return 0; 265 + return data; 266 + } 267 + 268 + /** 269 + * enum iwl_pnvm_source - different PNVM possible sources 270 + * 271 + * @IWL_PNVM_SOURCE_NONE: No PNVM. 272 + * @IWL_PNVM_SOURCE_BIOS: PNVM should be read from BIOS. 273 + * @IWL_PNVM_SOURCE_EXTERNAL: read .pnvm external file 274 + * @IWL_PNVM_SOURCE_EMBEDDED: PNVM is embedded in the .ucode file. 275 + */ 276 + enum iwl_pnvm_source { 277 + IWL_PNVM_SOURCE_NONE, 278 + IWL_PNVM_SOURCE_BIOS, 279 + IWL_PNVM_SOURCE_EXTERNAL, 280 + IWL_PNVM_SOURCE_EMBEDDED 281 + }; 282 + 283 + static enum iwl_pnvm_source iwl_select_pnvm_source(struct iwl_trans *trans, 284 + bool intel_sku) 285 + { 286 + 287 + /* Get PNVM from BIOS for non-Intel SKU */ 288 + if (!intel_sku) 289 + return IWL_PNVM_SOURCE_BIOS; 290 + 291 + /* Before those devices, PNVM didn't exist at all */ 292 + if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) 293 + return IWL_PNVM_SOURCE_NONE; 294 + 295 + /* After those devices, we moved to embedded PNVM */ 296 + if (trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_AX210) 297 + return IWL_PNVM_SOURCE_EMBEDDED; 298 + 299 + /* For IWL_DEVICE_FAMILY_AX210, depends on the CRF */ 300 + if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_GF) 301 + return IWL_PNVM_SOURCE_EXTERNAL; 302 + 303 + return IWL_PNVM_SOURCE_NONE; 267 304 } 268 305 269 306 static const u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len, 270 307 __le32 sku_id[3], const struct iwl_fw *fw) 271 308 { 272 309 struct pnvm_sku_package *package; 310 + enum iwl_pnvm_source pnvm_src = 311 + iwl_select_pnvm_source(trans_p, sku_id[2] == 0); 273 312 u8 *image = NULL; 274 313 275 - /* Get PNVM from BIOS for non-Intel SKU */ 276 - if (sku_id[2]) { 314 + IWL_DEBUG_FW(trans_p, "PNVM source %d\n", pnvm_src); 315 + 316 + if (pnvm_src == IWL_PNVM_SOURCE_NONE) 317 + return NULL; 318 + 319 + if (pnvm_src == IWL_PNVM_SOURCE_BIOS) { 277 320 package = iwl_uefi_get_pnvm(trans_p, len); 278 321 if (!IS_ERR_OR_NULL(package)) { 279 322 if (*len >= sizeof(*package)) { ··· 334 289 if (image) 335 290 return image; 336 291 } 292 + 293 + /* PNVM doesn't exist in BIOS. Find the fallback source */ 294 + pnvm_src = iwl_select_pnvm_source(trans_p, true); 295 + IWL_DEBUG_FW(trans_p, "PNVM in BIOS doesn't exist, try %d\n", 296 + pnvm_src); 337 297 } 338 298 339 - if (fw->pnvm_data) { 340 - *len = fw->pnvm_size; 299 + if (pnvm_src == IWL_PNVM_SOURCE_EXTERNAL) { 300 + image = iwl_pnvm_get_from_fs(trans_p, len); 301 + if (image) 302 + return image; 303 + } 341 304 305 + if (pnvm_src == IWL_PNVM_SOURCE_EMBEDDED && fw->pnvm_data) { 306 + *len = fw->pnvm_size; 342 307 return fw->pnvm_data; 343 308 } 344 309 345 - /* If it's not available, or for Intel SKU, try from the filesystem */ 346 - if (iwl_pnvm_get_from_fs(trans_p, &image, len)) 347 - return NULL; 348 - return image; 310 + IWL_ERR(trans_p, "Couldn't get PNVM from required source: %d\n", pnvm_src); 311 + return NULL; 349 312 } 350 313 351 314 static void
+16 -23
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
··· 305 305 return true; 306 306 } 307 307 308 + /* Utility function for iwlmvm and iwlxvt */ 308 309 int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, 309 310 union iwl_ppag_table_cmd *cmd, int *cmd_size) 310 311 { ··· 345 344 num_sub_bands = IWL_NUM_SUB_BANDS_V1; 346 345 gain = cmd->v1.gain[0]; 347 346 *cmd_size = sizeof(cmd->v1); 348 - cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags); 347 + cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK); 349 348 if (fwrt->ppag_bios_rev >= 1) { 350 349 /* in this case FW supports revision 0 */ 351 350 IWL_DEBUG_RADIO(fwrt, 352 351 "PPAG table rev is %d, send truncated table\n", 353 352 fwrt->ppag_bios_rev); 354 353 } 355 - } else if (cmd_ver >= 2 && cmd_ver <= 6) { 354 + } else if (cmd_ver == 5) { 356 355 num_sub_bands = IWL_NUM_SUB_BANDS_V2; 357 - gain = cmd->v2.gain[0]; 358 - *cmd_size = sizeof(cmd->v2); 359 - cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags); 356 + gain = cmd->v5.gain[0]; 357 + *cmd_size = sizeof(cmd->v5); 358 + cmd->v5.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK); 360 359 if (fwrt->ppag_bios_rev == 0) { 361 360 /* in this case FW supports revisions 1,2 or 3 */ 362 361 IWL_DEBUG_RADIO(fwrt, ··· 364 363 } 365 364 } else if (cmd_ver == 7) { 366 365 num_sub_bands = IWL_NUM_SUB_BANDS_V2; 367 - gain = cmd->v3.gain[0]; 368 - *cmd_size = sizeof(cmd->v3); 369 - cmd->v3.ppag_config_info.table_source = fwrt->ppag_bios_source; 370 - cmd->v3.ppag_config_info.table_revision = fwrt->ppag_bios_rev; 371 - cmd->v3.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags); 366 + gain = cmd->v7.gain[0]; 367 + *cmd_size = sizeof(cmd->v7); 368 + cmd->v7.ppag_config_info.table_source = fwrt->ppag_bios_source; 369 + cmd->v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev; 370 + cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags); 372 371 } else { 373 372 IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n"); 374 373 return -EINVAL; ··· 379 378 "PPAG MODE bits were read from bios: %d\n", 380 379 fwrt->ppag_flags); 381 380 382 - if (cmd_ver == 6) 383 - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V6_MASK); 384 - else if (cmd_ver == 5) 385 - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK); 386 - else if (cmd_ver < 5) 387 - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK); 388 - 389 - if ((cmd_ver == 1 && 390 - !fw_has_capa(&fwrt->fw->ucode_capa, 391 - IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) || 392 - (cmd_ver == 2 && fwrt->ppag_bios_rev >= 2)) { 381 + if (cmd_ver == 1 && 382 + !fw_has_capa(&fwrt->fw->ucode_capa, 383 + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) { 393 384 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); 394 385 IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n"); 395 386 } else { 396 387 IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n"); 397 388 } 398 389 399 - /* The 'flags' field is the same in v1 and v2 so we can just 390 + /* The 'flags' field is the same in v1 and v5 so we can just 400 391 * use v1 to access it. 401 392 */ 402 393 IWL_DEBUG_RADIO(fwrt, 403 394 "PPAG MODE bits going to be sent: %d\n", 404 395 (cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) : 405 - le32_to_cpu(cmd->v3.ppag_config_info.value)); 396 + le32_to_cpu(cmd->v7.ppag_config_info.value)); 406 397 407 398 for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) { 408 399 for (j = 0; j < num_sub_bands; j++) {
-2
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
··· 146 146 unsigned long non_collect_ts_start[IWL_FW_INI_TIME_POINT_NUM]; 147 147 u32 *d3_debug_data; 148 148 u32 lmac_err_id[MAX_NUM_LMAC]; 149 - u32 tcm_err_id[MAX_NUM_TCM]; 150 - u32 rcm_err_id[MAX_NUM_RCM]; 151 149 u32 umac_err_id; 152 150 153 151 struct iwl_txf_iter_data txf_iter_data;
+2 -5
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
··· 727 727 struct uefi_cnv_var_general_cfg *data; 728 728 int ret = -EINVAL; 729 729 730 + BUILD_BUG_ON(ARRAY_SIZE(data->functions) < DSM_FUNC_NUM_FUNCS); 731 + 730 732 /* Not supported function index */ 731 733 if (func >= DSM_FUNC_NUM_FUNCS || func == 5) 732 734 return -EOPNOTSUPP; ··· 741 739 if (data->revision != IWL_UEFI_DSM_REVISION) { 742 740 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI DSM revision:%d\n", 743 741 data->revision); 744 - goto out; 745 - } 746 - 747 - if (ARRAY_SIZE(data->functions) != UEFI_MAX_DSM_FUNCS) { 748 - IWL_DEBUG_RADIO(fwrt, "Invalid size of DSM functions array\n"); 749 742 goto out; 750 743 } 751 744
+36 -4
drivers/net/wireless/intel/iwlwifi/iwl-config.h
··· 11 11 #include <linux/netdevice.h> 12 12 #include <linux/ieee80211.h> 13 13 #include <linux/nl80211.h> 14 + #include <linux/module.h> 14 15 #include <linux/mod_devicetable.h> 15 16 #include "iwl-csr.h" 16 17 #include "iwl-drv.h" ··· 108 107 MODULE_FIRMWARE(pfx "-" __stringify(api) ".ucode"); \ 109 108 MODULE_FIRMWARE(pfx ".pnvm") 110 109 110 + #define IWL_CORE_FW(pfx, core) \ 111 + MODULE_FIRMWARE(pfx "-c" __stringify(core) ".ucode") 112 + 111 113 static inline u8 num_of_ant(u8 mask) 112 114 { 113 115 return !!((mask) & ANT_A) + ··· 196 192 197 193 u8 max_ll_items; 198 194 u8 led_compensation; 199 - u8 ucode_api_max; 200 - u8 ucode_api_min; 195 + u16 ucode_api_max; 196 + u16 ucode_api_min; 201 197 u32 mac_addr_from_csr:10; 202 198 u8 nvm_hw_section_num; 203 199 netdev_features_t features; ··· 213 209 const struct iwl_fw_mon_regs mon_smem_regs; 214 210 const struct iwl_fw_mon_regs mon_dbgi_regs; 215 211 }; 212 + 213 + /* 214 + * FW is released as "core N release", and we used to have a 215 + * gap of 3 between the API version and core number. Now the 216 + * reported API version will be 1000 + core and we encode it 217 + * in the filename as "c<core>". 218 + */ 219 + #define API_IS_CORE_START 1000 220 + #define API_TO_CORE_OFFS 3 221 + #define ENCODE_CORE_AS_API(core) (API_IS_CORE_START + (core)) 222 + 223 + static inline bool iwl_api_is_core_number(int api) 224 + { 225 + return api >= API_IS_CORE_START; 226 + } 227 + 228 + static inline int iwl_api_to_core(int api) 229 + { 230 + if (iwl_api_is_core_number(api)) 231 + return api - API_IS_CORE_START; 232 + 233 + return api - API_TO_CORE_OFFS; 234 + } 235 + 236 + #define FW_API_FMT "%s%d" 237 + #define FW_API_ARG(n) \ 238 + iwl_api_is_core_number(n) ? "c" : "", \ 239 + iwl_api_is_core_number(n) ? (n) - API_IS_CORE_START : (n) 216 240 217 241 /* 218 242 * @stbc: support Tx STBC and 1*SS Rx STBC ··· 454 422 u8 valid_tx_ant; 455 423 u8 valid_rx_ant; 456 424 u8 non_shared_ant; 457 - u8 ucode_api_max; 458 - u8 ucode_api_min; 425 + u16 ucode_api_max; 426 + u16 ucode_api_min; 459 427 u16 num_rbds; 460 428 }; 461 429
+36 -11
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
··· 337 337 return -EINVAL; 338 338 } 339 339 340 + if (CSR_HW_RFID_TYPE(drv->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_WH && 341 + CSR_HW_RFID_STEP(drv->trans->info.hw_rf_id) == SILICON_A_STEP) { 342 + IWL_ERR(drv, "WH A step is not supported\n"); 343 + return -EINVAL; 344 + } 345 + 340 346 fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre); 341 347 342 348 if (first) 343 349 drv->fw_index = ucode_api_max; 350 + else if (drv->fw_index == ENCODE_CORE_AS_API(99)) 351 + drv->fw_index = 101; /* last API-scheme number below core 99 */ 344 352 else 345 353 drv->fw_index--; 346 354 ··· 356 348 IWL_ERR(drv, "no suitable firmware found!\n"); 357 349 358 350 if (ucode_api_min == ucode_api_max) { 359 - IWL_ERR(drv, "%s-%d is required\n", fw_name_pre, 360 - ucode_api_max); 351 + IWL_ERR(drv, "%s-" FW_API_FMT " is required\n", 352 + fw_name_pre, FW_API_ARG(ucode_api_max)); 361 353 } else { 362 - IWL_ERR(drv, "minimum version required: %s-%d\n", 363 - fw_name_pre, ucode_api_min); 364 - IWL_ERR(drv, "maximum version supported: %s-%d\n", 365 - fw_name_pre, ucode_api_max); 354 + IWL_ERR(drv, 355 + "minimum version required: %s-" FW_API_FMT "\n", 356 + fw_name_pre, FW_API_ARG(ucode_api_min)); 357 + IWL_ERR(drv, 358 + "maximum version supported: %s-" FW_API_FMT "\n", 359 + fw_name_pre, FW_API_ARG(ucode_api_max)); 366 360 } 367 361 368 362 IWL_ERR(drv, ··· 372 362 return -ENOENT; 373 363 } 374 364 375 - snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s-%d.ucode", 376 - fw_name_pre, drv->fw_index); 365 + snprintf(drv->firmware_name, sizeof(drv->firmware_name), 366 + "%s-" FW_API_FMT ".ucode", 367 + fw_name_pre, FW_API_ARG(drv->fw_index)); 377 368 378 369 IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n", 379 370 drv->firmware_name); ··· 1599 1588 */ 1600 1589 static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) 1601 1590 { 1591 + unsigned int min_core, max_core, loaded_core; 1602 1592 struct iwl_drv *drv = context; 1603 1593 struct iwl_fw *fw = &drv->fw; 1604 1594 const struct iwl_ucode_header *ucode; ··· 1662 1650 * firmware filename ... but we don't check for that and only rely 1663 1651 * on the API version read from firmware header from here on forward 1664 1652 */ 1665 - if (api_ver < api_min || api_ver > api_max) { 1653 + 1654 + /* 1655 + * if -cN.ucode file was loaded, core version == file version, 1656 + * otherwise core version == file version (API version) - 3 1657 + */ 1658 + if (iwl_api_is_core_number(drv->fw_index)) 1659 + loaded_core = api_ver; 1660 + else 1661 + loaded_core = api_ver - API_TO_CORE_OFFS; 1662 + 1663 + min_core = iwl_api_to_core(api_min); 1664 + max_core = iwl_api_to_core(api_max); 1665 + 1666 + if (loaded_core < min_core || loaded_core > max_core) { 1666 1667 IWL_ERR(drv, 1667 1668 "Driver unable to support your firmware API. " 1668 - "Driver supports v%u, firmware is v%u.\n", 1669 - api_max, api_ver); 1669 + "Driver supports FW core %u..%u, firmware is %u.\n", 1670 + min_core, max_core, loaded_core); 1670 1671 goto try_again; 1671 1672 } 1672 1673
+3 -88
drivers/net/wireless/intel/iwlwifi/iwl-io.c
··· 3 3 * Copyright (C) 2003-2014, 2018-2022, 2024-2025 Intel Corporation 4 4 * Copyright (C) 2015-2016 Intel Deutschland GmbH 5 5 */ 6 - #include <linux/delay.h> 7 6 #include <linux/device.h> 8 7 #include <linux/export.h> 9 8 ··· 12 13 #include "iwl-debug.h" 13 14 #include "iwl-prph.h" 14 15 #include "iwl-fh.h" 16 + #include "pcie/gen1_2/internal.h" 15 17 16 18 void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) 17 19 { ··· 160 160 161 161 do { 162 162 if ((iwl_read_prph(trans, addr) & mask) == (bits & mask)) 163 - return t; 163 + return 0; 164 164 udelay(IWL_POLL_INTERVAL); 165 165 t += IWL_POLL_INTERVAL; 166 166 } while (t < timeout); ··· 396 396 return 0; 397 397 } 398 398 399 - #define IWL_HOST_MON_BLOCK_PEMON 0x00 400 - #define IWL_HOST_MON_BLOCK_HIPM 0x22 401 - 402 - #define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00 403 - #define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01 404 - #define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06 405 - 406 - static void iwl_dump_host_monitor_block(struct iwl_trans *trans, 407 - u32 block, u32 vec, u32 iter) 408 - { 409 - int i; 410 - 411 - IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec); 412 - iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); 413 - for (i = 0; i < iter; i++) 414 - IWL_ERR(trans, " value [iter %d]: 0x%08x\n", 415 - i, iwl_read32(trans, CSR_MONITOR_STATUS_REG)); 416 - } 417 - 418 - static void iwl_dump_host_monitor(struct iwl_trans *trans) 419 - { 420 - switch (trans->mac_cfg->device_family) { 421 - case IWL_DEVICE_FAMILY_22000: 422 - case IWL_DEVICE_FAMILY_AX210: 423 - IWL_ERR(trans, "CSR_RESET = 0x%x\n", 424 - iwl_read32(trans, CSR_RESET)); 425 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 426 - IWL_HOST_MON_BLOCK_PEMON_VEC0, 15); 427 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 428 - IWL_HOST_MON_BLOCK_PEMON_VEC1, 15); 429 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 430 - IWL_HOST_MON_BLOCK_PEMON_WFPM, 15); 431 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM, 432 - IWL_HOST_MON_BLOCK_PEMON_VEC0, 1); 433 - break; 434 - default: 435 - /* not supported yet */ 436 - return; 437 - } 438 - } 439 - 440 399 int iwl_finish_nic_init(struct iwl_trans *trans) 441 400 { 442 - const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg; 443 - u32 poll_ready; 444 - int err; 445 - 446 - if (mac_cfg->bisr_workaround) { 447 - /* ensure the TOP FSM isn't still in previous reset */ 448 - mdelay(2); 449 - } 450 - 451 - /* 452 - * Set "initialization complete" bit to move adapter from 453 - * D0U* --> D0A* (powered-up active) state. 454 - */ 455 - if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { 456 - iwl_set_bit(trans, CSR_GP_CNTRL, 457 - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ | 458 - CSR_GP_CNTRL_REG_FLAG_MAC_INIT); 459 - poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS; 460 - } else { 461 - iwl_set_bit(trans, CSR_GP_CNTRL, 462 - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 463 - poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY; 464 - } 465 - 466 - if (mac_cfg->device_family == IWL_DEVICE_FAMILY_8000) 467 - udelay(2); 468 - 469 - /* 470 - * Wait for clock stabilization; once stabilized, access to 471 - * device-internal resources is supported, e.g. iwl_write_prph() 472 - * and accesses to uCode SRAM. 473 - */ 474 - err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000); 475 - if (err < 0) { 476 - IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); 477 - 478 - iwl_dump_host_monitor(trans); 479 - } 480 - 481 - if (mac_cfg->bisr_workaround) { 482 - /* ensure BISR shift has finished */ 483 - udelay(200); 484 - } 485 - 486 - return err < 0 ? err : 0; 401 + return iwl_pcie_gen1_2_finish_nic_init(trans); 487 402 } 488 403 IWL_EXPORT_SYMBOL(iwl_finish_nic_init); 489 404
-4
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
··· 1042 1042 iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |= 1043 1043 IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; 1044 1044 1045 - if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT)) 1046 - iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |= 1047 - IEEE80211_HE_MAC_CAP2_BCAST_TWT; 1048 - 1049 1045 if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000 && 1050 1046 !is_ap) { 1051 1047 iftype_data->vendor_elems.data = iwl_vendor_caps;
+19 -37
drivers/net/wireless/intel/iwlwifi/iwl-trans.c
··· 268 268 269 269 struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, 270 270 struct device *dev, 271 - const struct iwl_mac_cfg *mac_cfg, 272 - unsigned int txcmd_size, 273 - unsigned int txcmd_align) 271 + const struct iwl_mac_cfg *mac_cfg) 274 272 { 275 273 struct iwl_trans *trans; 276 274 #ifdef CONFIG_LOCKDEP ··· 290 292 291 293 INIT_DELAYED_WORK(&trans->restart.wk, iwl_trans_restart_wk); 292 294 293 - snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), 294 - "iwl_cmd_pool:%s", dev_name(trans->dev)); 295 - trans->dev_cmd_pool = 296 - kmem_cache_create(trans->dev_cmd_pool_name, 297 - txcmd_size, txcmd_align, 298 - SLAB_HWCACHE_ALIGN, NULL); 299 - if (!trans->dev_cmd_pool) 300 - return NULL; 301 - 302 295 return trans; 303 296 } 304 297 305 298 void iwl_trans_free(struct iwl_trans *trans) 306 299 { 307 300 cancel_delayed_work_sync(&trans->restart.wk); 308 - kmem_cache_destroy(trans->dev_cmd_pool); 309 301 } 310 302 311 303 int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) ··· 305 317 if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) && 306 318 test_bit(STATUS_RFKILL_OPMODE, &trans->status))) 307 319 return -ERFKILL; 308 - 309 - if (unlikely(test_bit(STATUS_SUSPENDED, &trans->status))) 310 - return -EHOSTDOWN; 311 320 312 321 if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) 313 322 return -EIO; ··· 332 347 return ret; 333 348 } 334 349 IWL_EXPORT_SYMBOL(iwl_trans_send_cmd); 350 + 351 + struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) 352 + { 353 + return iwl_pcie_gen1_2_alloc_tx_cmd(trans); 354 + } 355 + IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd); 356 + 357 + void iwl_trans_free_tx_cmd(struct iwl_trans *trans, 358 + struct iwl_device_tx_cmd *dev_cmd) 359 + { 360 + iwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd); 361 + } 362 + IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd); 335 363 336 364 /* Comparator for struct iwl_hcmd_names. 337 365 * Used in the binary search over a list of host commands. ··· 397 399 398 400 WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd); 399 401 400 - iwl_trans_pcie_op_mode_enter(trans); 402 + iwl_pcie_gen1_2_op_mode_enter(trans); 401 403 } 402 404 IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter); 403 405 ··· 406 408 might_sleep(); 407 409 408 410 clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status); 409 - /* opmode may not resume if it detects errors */ 410 - clear_bit(STATUS_SUSPENDED, &trans->status); 411 411 412 412 return iwl_trans_pcie_start_hw(trans); 413 413 } ··· 503 507 sanitize_ops, sanitize_ctx); 504 508 } 505 509 506 - int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset) 510 + int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset) 507 511 { 508 - int err; 509 - 510 512 might_sleep(); 511 513 512 - err = iwl_trans_pcie_d3_suspend(trans, test, reset); 513 - 514 - if (!err) 515 - set_bit(STATUS_SUSPENDED, &trans->status); 516 - 517 - return err; 514 + return iwl_trans_pcie_d3_suspend(trans, reset); 518 515 } 519 516 IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend); 520 517 521 - int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, 522 - bool test, bool reset) 518 + int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset) 523 519 { 524 - int err; 525 - 526 520 might_sleep(); 527 521 528 - err = iwl_trans_pcie_d3_resume(trans, status, test, reset); 529 - 530 - clear_bit(STATUS_SUSPENDED, &trans->status); 531 - 532 - return err; 522 + return iwl_trans_pcie_d3_resume(trans, reset); 533 523 } 534 524 IWL_EXPORT_SYMBOL(iwl_trans_d3_resume); 535 525
+6 -42
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
··· 275 275 #define IWL_9000_MAX_RX_HW_QUEUES 1 276 276 277 277 /** 278 - * enum iwl_d3_status - WoWLAN image/device status 279 - * @IWL_D3_STATUS_ALIVE: firmware is still running after resume 280 - * @IWL_D3_STATUS_RESET: device was reset while suspended 281 - */ 282 - enum iwl_d3_status { 283 - IWL_D3_STATUS_ALIVE, 284 - IWL_D3_STATUS_RESET, 285 - }; 286 - 287 - /** 288 278 * enum iwl_trans_status: transport status flags 289 279 * @STATUS_SYNC_HCMD_ACTIVE: a SYNC command is being processed 290 280 * @STATUS_DEVICE_ENABLED: APM is enabled ··· 292 302 * the firmware state yet 293 303 * @STATUS_TRANS_RESET_IN_PROGRESS: reset is still in progress, don't 294 304 * attempt another reset yet 295 - * @STATUS_SUSPENDED: device is suspended, don't send commands that 296 - * aren't marked accordingly 297 305 */ 298 306 enum iwl_trans_status { 299 307 STATUS_SYNC_HCMD_ACTIVE, ··· 306 318 STATUS_IN_SW_RESET, 307 319 STATUS_RESET_PENDING, 308 320 STATUS_TRANS_RESET_IN_PROGRESS, 309 - STATUS_SUSPENDED, 310 321 }; 311 322 312 323 static inline int ··· 645 658 * @restart_required: indicates debug restart is required 646 659 * @last_tp_resetfw: last handling of reset during debug timepoint 647 660 * @imr_data: IMR debug data allocation 648 - * @dump_file_name_ext: dump file name extension 649 - * @dump_file_name_ext_valid: dump file name extension if valid or not 650 661 * @num_pc: number of program counter for cpu 651 662 * @pc_data: details of the program counter 652 663 * @yoyo_bin_loaded: tells if a yoyo debug file has been loaded ··· 683 698 bool restart_required; 684 699 u32 last_tp_resetfw; 685 700 struct iwl_imr_data imr_data; 686 - u8 dump_file_name_ext[IWL_FW_INI_MAX_NAME]; 687 - bool dump_file_name_ext_valid; 688 701 u32 num_pc; 689 702 struct iwl_pc_data *pc_data; 690 703 bool yoyo_bin_loaded; ··· 813 830 * @hw_rf_id: the device RF ID 814 831 * @hw_cnv_id: the device CNV ID 815 832 * @hw_crf_id: the device CRF ID 816 - * @hw_wfpm_id: the device wfpm ID 817 833 * @hw_id: the ID of the device / sub-device 818 834 * Bits 0:15 represent the sub-device ID 819 835 * Bits 16:31 represent the device ID. ··· 828 846 u32 hw_rf_id; 829 847 u32 hw_crf_id; 830 848 u32 hw_cnv_id; 831 - u32 hw_wfpm_id; 832 849 u32 hw_id; 833 850 u8 pcie_link_speed; 834 851 u8 num_rxqs; ··· 852 871 * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed 853 872 * @reduce_power_loaded: indicates reduced power section was loaded 854 873 * @failed_to_load_reduce_power_image: set to true if pnvm loading failed 855 - * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. 856 - * The user should use iwl_trans_{alloc,free}_tx_cmd. 857 - * @dev_cmd_pool_name: name for the TX command allocation pool 858 874 * @dbgfs_dir: iwlwifi debugfs base dir for this device 859 875 * @sync_cmd_lockdep_map: lockdep map for checking sync commands 860 876 * @dbg: additional debug data, see &struct iwl_trans_debug ··· 890 912 u8 fail_to_parse_pnvm_image:1; 891 913 u8 reduce_power_loaded:1; 892 914 u8 failed_to_load_reduce_power_image:1; 893 - 894 - /* The following fields are internal only */ 895 - struct kmem_cache *dev_cmd_pool; 896 - char dev_cmd_pool_name[50]; 897 915 898 916 struct dentry *dbgfs_dir; 899 917 ··· 930 956 931 957 void iwl_trans_stop_device(struct iwl_trans *trans); 932 958 933 - int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset); 959 + int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset); 934 960 935 - int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, 936 - bool test, bool reset); 961 + int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset); 937 962 938 963 struct iwl_trans_dump_data * 939 964 iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask, 940 965 const struct iwl_dump_sanitize_ops *sanitize_ops, 941 966 void *sanitize_ctx); 942 967 943 - static inline struct iwl_device_tx_cmd * 944 - iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) 945 - { 946 - return kmem_cache_zalloc(trans->dev_cmd_pool, GFP_ATOMIC); 947 - } 968 + struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans); 948 969 949 970 int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); 950 971 951 - static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, 952 - struct iwl_device_tx_cmd *dev_cmd) 953 - { 954 - kmem_cache_free(trans->dev_cmd_pool, dev_cmd); 955 - } 972 + void iwl_trans_free_tx_cmd(struct iwl_trans *trans, 973 + struct iwl_device_tx_cmd *dev_cmd); 956 974 957 975 int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, 958 976 struct iwl_device_tx_cmd *dev_cmd, int queue); ··· 1171 1205 *****************************************************/ 1172 1206 struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, 1173 1207 struct device *dev, 1174 - const struct iwl_mac_cfg *mac_cfg, 1175 - unsigned int txcmd_size, 1176 - unsigned int txcmd_align); 1208 + const struct iwl_mac_cfg *mac_cfg); 1177 1209 void iwl_trans_free(struct iwl_trans *trans); 1178 1210 1179 1211 static inline bool iwl_trans_is_hw_error_value(u32 val)
+176 -178
drivers/net/wireless/intel/iwlwifi/mld/d3.c
··· 11 11 #include "mcc.h" 12 12 #include "sta.h" 13 13 #include "mlo.h" 14 + #include "key.h" 14 15 15 16 #include "fw/api/d3.h" 16 17 #include "fw/api/offload.h" ··· 41 40 struct iwl_mld_resume_key_iter_data { 42 41 struct iwl_mld *mld; 43 42 struct iwl_mld_wowlan_status *wowlan_status; 44 - u32 num_keys, gtk_cipher, igtk_cipher, bigtk_cipher; 45 - bool unhandled_cipher; 46 43 }; 47 44 48 45 struct iwl_mld_suspend_key_iter_data { ··· 70 71 71 72 }; 72 73 74 + struct iwl_mld_wowlan_mlo_key { 75 + u8 key[WOWLAN_KEY_MAX_SIZE]; 76 + u8 idx, type, link_id; 77 + u8 pn[6]; 78 + }; 79 + 73 80 /** 74 81 * struct iwl_mld_wowlan_status - contains wowlan status data from 75 82 * all wowlan notifications ··· 94 89 * @bigtk: data of the last two used gtk's by the FW upon resume 95 90 * @ptk: last seq numbers per tid passed by the FW, 96 91 * holds both in tkip and aes formats 92 + * @num_mlo_keys: number of &struct iwl_mld_wowlan_mlo_key structs 93 + * @mlo_keys: array of MLO keys 97 94 */ 98 95 struct iwl_mld_wowlan_status { 99 96 u32 wakeup_reasons; ··· 115 108 struct ieee80211_key_seq tkip_seq[IWL_MAX_TID_COUNT]; 116 109 117 110 } ptk; 111 + 112 + int num_mlo_keys; 113 + struct iwl_mld_wowlan_mlo_key mlo_keys[WOWLAN_MAX_MLO_KEYS]; 118 114 }; 119 115 120 116 #define NETDETECT_QUERY_BUF_LEN \ ··· 417 407 } 418 408 } 419 409 410 + static void 411 + iwl_mld_convert_mlo_keys(struct iwl_mld *mld, 412 + const struct iwl_wowlan_info_notif *notif, 413 + struct iwl_mld_wowlan_status *wowlan_status) 414 + { 415 + if (!notif->num_mlo_link_keys) 416 + return; 417 + 418 + wowlan_status->num_mlo_keys = notif->num_mlo_link_keys; 419 + 420 + if (IWL_FW_CHECK(mld, wowlan_status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS, 421 + "Too many MLO keys: %d, max %d\n", 422 + wowlan_status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS)) 423 + wowlan_status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS; 424 + 425 + for (int i = 0; i < wowlan_status->num_mlo_keys; i++) { 426 + const struct iwl_wowlan_mlo_gtk *fw_mlo_key = &notif->mlo_gtks[i]; 427 + struct iwl_mld_wowlan_mlo_key *driver_mlo_key = 428 + &wowlan_status->mlo_keys[i]; 429 + u16 flags = le16_to_cpu(fw_mlo_key->flags); 430 + 431 + driver_mlo_key->link_id = 432 + u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK); 433 + driver_mlo_key->type = 434 + u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK); 435 + driver_mlo_key->idx = 436 + u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK); 437 + 438 + BUILD_BUG_ON(sizeof(driver_mlo_key->key) != sizeof(fw_mlo_key->key)); 439 + BUILD_BUG_ON(sizeof(driver_mlo_key->pn) != sizeof(fw_mlo_key->pn)); 440 + 441 + memcpy(driver_mlo_key->key, fw_mlo_key->key, sizeof(fw_mlo_key->key)); 442 + memcpy(driver_mlo_key->pn, fw_mlo_key->pn, sizeof(fw_mlo_key->pn)); 443 + } 444 + } 445 + 420 446 static bool 421 447 iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld, 422 448 struct iwl_mld_wowlan_status *wowlan_status, 423 449 struct iwl_rx_packet *pkt) 424 450 { 425 451 const struct iwl_wowlan_info_notif *notif = (void *)pkt->data; 426 - u32 expected_len, len = iwl_rx_packet_payload_len(pkt); 452 + u32 len = iwl_rx_packet_payload_len(pkt); 453 + u32 len_with_mlo_keys; 427 454 428 - expected_len = sizeof(*notif); 455 + if (IWL_FW_CHECK(mld, len < sizeof(*notif), 456 + "Invalid wowlan_info_notif (expected=%zu got=%u)\n", 457 + sizeof(*notif), len)) 458 + return true; 429 459 430 - if (IWL_FW_CHECK(mld, len < expected_len, 431 - "Invalid wowlan_info_notif (expected=%ud got=%ud)\n", 432 - expected_len, len)) 460 + /* Now that we know that we have at least sizeof(notif), 461 + * check also the variable length part 462 + */ 463 + len_with_mlo_keys = sizeof(*notif) + 464 + notif->num_mlo_link_keys * sizeof(notif->mlo_gtks[0]); 465 + 466 + if (IWL_FW_CHECK(mld, len < len_with_mlo_keys, 467 + "Invalid wowlan_info_notif (expected=%ud got=%u)\n", 468 + len_with_mlo_keys, len)) 433 469 return true; 434 470 435 471 if (IWL_FW_CHECK(mld, notif->tid_offloaded_tx != IWL_WOWLAN_OFFLOAD_TID, ··· 498 442 wowlan_status->num_of_gtk_rekeys = 499 443 le32_to_cpu(notif->num_of_gtk_rekeys); 500 444 wowlan_status->wakeup_reasons = le32_to_cpu(notif->wakeup_reasons); 445 + 446 + iwl_mld_convert_mlo_keys(mld, notif, wowlan_status); 447 + 501 448 return false; 502 - /* TODO: mlo_links (task=MLO)*/ 503 449 } 504 450 505 451 static bool ··· 677 619 } 678 620 679 621 static void 680 - iwl_mld_set_key_rx_seq(struct ieee80211_key_conf *key, 681 - struct iwl_mld_mcast_key_data *key_data) 622 + iwl_mld_update_mcast_rx_seq(struct ieee80211_key_conf *key, 623 + struct iwl_mld_mcast_key_data *key_data) 682 624 { 683 625 switch (key->cipher) { 684 626 case WLAN_CIPHER_SUITE_CCMP: ··· 745 687 struct iwl_mld_wowlan_status *wowlan_status = data->wowlan_status; 746 688 u8 status_idx; 747 689 748 - /* TODO: check key link id (task=MLO) */ 749 - if (data->unhandled_cipher) 750 - return; 751 - 752 - switch (key->cipher) { 753 - case WLAN_CIPHER_SUITE_WEP40: 754 - case WLAN_CIPHER_SUITE_WEP104: 755 - /* ignore WEP completely, nothing to do */ 756 - return; 757 - case WLAN_CIPHER_SUITE_CCMP: 758 - case WLAN_CIPHER_SUITE_GCMP: 759 - case WLAN_CIPHER_SUITE_GCMP_256: 760 - case WLAN_CIPHER_SUITE_TKIP: 690 + if (key->keyidx >= 0 && key->keyidx <= 3) { 691 + /* PTK */ 761 692 if (sta) { 762 693 iwl_mld_update_ptk_rx_seq(data->mld, wowlan_status, 763 694 sta, key, 764 695 key->cipher == 765 696 WLAN_CIPHER_SUITE_TKIP); 766 - return; 697 + /* GTK */ 698 + } else { 699 + status_idx = key->keyidx == wowlan_status->gtk[1].id; 700 + iwl_mld_update_mcast_rx_seq(key, 701 + &wowlan_status->gtk[status_idx]); 767 702 } 768 - 769 - if (WARN_ON(data->gtk_cipher && 770 - data->gtk_cipher != key->cipher)) 771 - return; 772 - 773 - data->gtk_cipher = key->cipher; 774 - status_idx = key->keyidx == wowlan_status->gtk[1].id; 775 - iwl_mld_set_key_rx_seq(key, &wowlan_status->gtk[status_idx]); 776 - break; 777 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 778 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 779 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 780 - case WLAN_CIPHER_SUITE_AES_CMAC: 781 - if (key->keyidx == 4 || key->keyidx == 5) { 782 - if (WARN_ON(data->igtk_cipher && 783 - data->igtk_cipher != key->cipher)) 784 - return; 785 - 786 - data->igtk_cipher = key->cipher; 787 - if (key->keyidx == wowlan_status->igtk.id) 788 - iwl_mld_set_key_rx_seq(key, &wowlan_status->igtk); 789 - } 790 - if (key->keyidx == 6 || key->keyidx == 7) { 791 - if (WARN_ON(data->bigtk_cipher && 792 - data->bigtk_cipher != key->cipher)) 793 - return; 794 - 795 - data->bigtk_cipher = key->cipher; 796 - status_idx = key->keyidx == wowlan_status->bigtk[1].id; 797 - iwl_mld_set_key_rx_seq(key, &wowlan_status->bigtk[status_idx]); 798 - } 799 - break; 800 - default: 801 - data->unhandled_cipher = true; 802 - return; 803 703 } 804 - data->num_keys++; 704 + 705 + /* IGTK */ 706 + if (key->keyidx == 4 || key->keyidx == 5) { 707 + if (key->keyidx == wowlan_status->igtk.id) 708 + iwl_mld_update_mcast_rx_seq(key, &wowlan_status->igtk); 709 + } 710 + 711 + /* BIGTK */ 712 + if (key->keyidx == 6 || key->keyidx == 7) { 713 + status_idx = key->keyidx == wowlan_status->bigtk[1].id; 714 + iwl_mld_update_mcast_rx_seq(key, 715 + &wowlan_status->bigtk[status_idx]); 716 + } 805 717 } 806 718 807 719 static void 808 720 iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, 809 721 struct iwl_mld *mld, 810 722 struct iwl_mld_mcast_key_data *key_data, 811 - struct ieee80211_bss_conf *link_conf, 812 - u32 cipher) 723 + struct ieee80211_bss_conf *link_conf) 813 724 { 814 725 struct ieee80211_key_conf *key_config; 815 - struct { 816 - struct ieee80211_key_conf conf; 817 - u8 key[WOWLAN_KEY_MAX_SIZE]; 818 - } conf = { 819 - .conf.cipher = cipher, 820 - .conf.keyidx = key_data->id, 821 - }; 822 726 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 823 - u8 key[WOWLAN_KEY_MAX_SIZE]; 824 - 825 - BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); 826 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP); 827 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256); 828 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP); 829 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_BIP_GMAC_128); 830 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_BIP_GMAC_256); 831 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_AES_CMAC); 832 - BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key)); 833 727 834 728 if (!key_data->len) 835 729 return; 836 730 837 - switch (cipher) { 838 - case WLAN_CIPHER_SUITE_CCMP: 839 - case WLAN_CIPHER_SUITE_GCMP: 840 - conf.conf.keylen = WLAN_KEY_LEN_CCMP; 841 - break; 842 - case WLAN_CIPHER_SUITE_GCMP_256: 843 - conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; 844 - break; 845 - case WLAN_CIPHER_SUITE_TKIP: 846 - conf.conf.keylen = WLAN_KEY_LEN_TKIP; 847 - break; 848 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 849 - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128; 850 - break; 851 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 852 - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256; 853 - break; 854 - case WLAN_CIPHER_SUITE_AES_CMAC: 855 - conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC; 856 - break; 857 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 858 - conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256; 859 - break; 860 - default: 861 - WARN_ON(1); 862 - } 863 - 864 - memcpy(conf.conf.key, key_data->key, conf.conf.keylen); 865 - 866 - memcpy(key, key_data->key, sizeof(key_data->key)); 867 - 868 - key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key, 869 - sizeof(key), link_id); 731 + key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key_data->key, 732 + sizeof(key_data->key), link_id); 870 733 if (IS_ERR(key_config)) 871 734 return; 872 735 873 - iwl_mld_set_key_rx_seq(key_config, key_data); 736 + iwl_mld_update_mcast_rx_seq(key_config, key_data); 874 737 875 738 /* The FW holds only one igtk so we keep track of the valid one */ 876 739 if (key_config->keyidx == 4 || key_config->keyidx == 5) { ··· 810 831 } 811 832 812 833 /* Also keep track of the new BIGTK */ 813 - if ((key_config->keyidx == 6 || key_config->keyidx == 7) && 814 - vif->type == NL80211_IFTYPE_STATION) { 815 - struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 816 - 817 - rcu_assign_pointer(mld_vif->bigtks[key_config->keyidx - 6], key_config); 818 - } 834 + if (key_config->keyidx == 6 || key_config->keyidx == 7) 835 + iwl_mld_track_bigtk(mld, vif, key_config, true); 819 836 } 820 837 821 838 static void 822 - iwl_mld_add_all_rekeys(struct ieee80211_vif *vif, 839 + iwl_mld_add_all_rekeys(struct iwl_mld *mld, 840 + struct ieee80211_vif *vif, 823 841 struct iwl_mld_wowlan_status *wowlan_status, 824 - struct iwl_mld_resume_key_iter_data *key_iter_data, 825 842 struct ieee80211_bss_conf *link_conf) 826 843 { 827 844 int i; 828 845 829 846 for (i = 0; i < ARRAY_SIZE(wowlan_status->gtk); i++) 830 - iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, 831 - &wowlan_status->gtk[i], 832 - link_conf, 833 - key_iter_data->gtk_cipher); 847 + iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->gtk[i], 848 + link_conf); 834 849 835 - iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, 836 - &wowlan_status->igtk, 837 - link_conf, key_iter_data->igtk_cipher); 850 + iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->igtk, link_conf); 838 851 839 852 for (i = 0; i < ARRAY_SIZE(wowlan_status->bigtk); i++) 840 - iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, 841 - &wowlan_status->bigtk[i], 842 - link_conf, 843 - key_iter_data->bigtk_cipher); 853 + iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->bigtk[i], 854 + link_conf); 855 + } 856 + 857 + static void iwl_mld_mlo_rekey(struct iwl_mld *mld, 858 + struct iwl_mld_wowlan_status *wowlan_status, 859 + struct ieee80211_vif *vif) 860 + { 861 + struct iwl_mld_old_mlo_keys *old_keys __free(kfree) = NULL; 862 + 863 + IWL_DEBUG_WOWLAN(mld, "Num of MLO Keys: %d\n", wowlan_status->num_mlo_keys); 864 + 865 + if (!wowlan_status->num_mlo_keys) 866 + return; 867 + 868 + for (int i = 0; i < wowlan_status->num_mlo_keys; i++) { 869 + struct iwl_mld_wowlan_mlo_key *mlo_key = &wowlan_status->mlo_keys[i]; 870 + struct ieee80211_key_conf *key; 871 + struct ieee80211_key_seq seq; 872 + u8 link_id = mlo_key->link_id; 873 + 874 + if (IWL_FW_CHECK(mld, mlo_key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS || 875 + mlo_key->idx >= 8 || 876 + mlo_key->type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES, 877 + "Invalid MLO key link_id %d, idx %d, type %d\n", 878 + mlo_key->link_id, mlo_key->idx, mlo_key->type)) 879 + continue; 880 + 881 + if (!(vif->valid_links & BIT(link_id)) || 882 + (vif->active_links & BIT(link_id))) 883 + continue; 884 + 885 + IWL_DEBUG_WOWLAN(mld, "Add MLO key id %d, link id %d\n", 886 + mlo_key->idx, link_id); 887 + 888 + key = ieee80211_gtk_rekey_add(vif, mlo_key->idx, mlo_key->key, 889 + sizeof(mlo_key->key), link_id); 890 + 891 + if (IS_ERR(key)) 892 + continue; 893 + 894 + /* 895 + * mac80211 expects the PN in big-endian 896 + * also note that seq is a union of all cipher types 897 + * (ccmp, gcmp, cmac, gmac), and they all have the same 898 + * pn field (of length 6) so just copy it to ccmp.pn. 899 + */ 900 + for (int j = 5; j >= 0; j--) 901 + seq.ccmp.pn[5 - j] = mlo_key->pn[j]; 902 + 903 + /* group keys are non-QoS and use TID 0 */ 904 + ieee80211_set_key_rx_seq(key, 0, &seq); 905 + } 844 906 } 845 907 846 908 static bool ··· 904 884 ieee80211_iter_keys(mld->hw, vif, iwl_mld_resume_keys_iter, 905 885 &key_iter_data); 906 886 907 - if (key_iter_data.unhandled_cipher) 908 - return false; 909 - 910 - IWL_DEBUG_WOWLAN(mld, 911 - "Number of installed keys: %d, Number of rekeys: %d\n", 912 - key_iter_data.num_keys, 887 + IWL_DEBUG_WOWLAN(mld, "Number of rekeys: %d\n", 913 888 wowlan_status->num_of_gtk_rekeys); 914 889 915 - if (!key_iter_data.num_keys || !wowlan_status->num_of_gtk_rekeys) 890 + if (!wowlan_status->num_of_gtk_rekeys) 916 891 return true; 917 892 918 - iwl_mld_add_all_rekeys(vif, wowlan_status, &key_iter_data, 893 + iwl_mld_add_all_rekeys(mld, vif, wowlan_status, 919 894 link_conf); 895 + 896 + iwl_mld_mlo_rekey(mld, wowlan_status, vif); 920 897 921 898 ieee80211_gtk_rekey_notify(vif, link_conf->bssid, 922 899 (void *)&replay_ctr, GFP_KERNEL); 923 - /* TODO: MLO rekey (task=MLO) */ 924 900 return true; 925 901 } 926 902 ··· 1195 1179 WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION) 1196 1180 }; 1197 1181 struct iwl_notification_wait wait_d3_notif; 1198 - enum iwl_d3_status d3_status; 1199 1182 int ret; 1200 1183 1201 1184 if (with_wowlan) ··· 1210 1195 iwl_mld_handle_d3_notif, 1211 1196 resume_data); 1212 1197 1213 - ret = iwl_trans_d3_resume(mld->trans, &d3_status, false, false); 1214 - if (ret || d3_status != IWL_D3_STATUS_ALIVE) { 1215 - if (d3_status != IWL_D3_STATUS_ALIVE) { 1216 - IWL_INFO(mld, "Device was reset during suspend\n"); 1217 - ret = -ENOENT; 1218 - } else { 1219 - IWL_ERR(mld, "Transport resume failed\n"); 1220 - } 1198 + ret = iwl_trans_d3_resume(mld->trans, false); 1199 + if (ret) { 1200 + /* Avoid sending commands if the FW is dead */ 1201 + mld->trans->state = IWL_TRANS_NO_FW; 1202 + set_bit(STATUS_FW_ERROR, &mld->trans->status); 1221 1203 iwl_remove_notification(&mld->notif_wait, &wait_d3_notif); 1222 1204 return ret; 1223 1205 } ··· 1248 1236 1249 1237 iwl_mld_low_latency_stop(mld); 1250 1238 1251 - /* This will happen if iwl_mld_supsend failed with FW error */ 1252 - if (mld->trans->state == IWL_TRANS_NO_FW && 1253 - test_bit(STATUS_FW_ERROR, &mld->trans->status)) 1254 - return -ENODEV; 1255 - 1256 1239 ret = iwl_mld_update_device_power(mld, true); 1257 1240 if (ret) { 1258 1241 IWL_ERR(mld, 1259 1242 "d3 suspend: couldn't send power_device %d\n", ret); 1260 - goto out; 1243 + return ret; 1261 1244 } 1262 1245 1263 1246 ret = iwl_mld_send_cmd_pdu(mld, D3_CONFIG_CMD, ··· 1260 1253 if (ret) { 1261 1254 IWL_ERR(mld, 1262 1255 "d3 suspend: couldn't send D3_CONFIG_CMD %d\n", ret); 1263 - goto out; 1256 + return ret; 1264 1257 } 1265 1258 1266 - ret = iwl_trans_d3_suspend(mld->trans, false, false); 1259 + ret = iwl_trans_d3_suspend(mld->trans, false); 1267 1260 if (ret) { 1268 1261 IWL_ERR(mld, "d3 suspend: trans_d3_suspend failed %d\n", ret); 1262 + /* We are going to stop the FW. Avoid sending commands in that flow */ 1263 + mld->trans->state = IWL_TRANS_NO_FW; 1264 + set_bit(STATUS_FW_ERROR, &mld->trans->status); 1269 1265 } else { 1270 1266 /* Async notification might send hcmds, which is not allowed in suspend */ 1271 1267 iwl_mld_cancel_async_notifications(mld); 1272 1268 mld->fw_status.in_d3 = true; 1273 - } 1274 - 1275 - out: 1276 - if (ret) { 1277 - mld->trans->state = IWL_TRANS_NO_FW; 1278 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1279 1269 } 1280 1270 1281 1271 return ret; ··· 1294 1290 iwl_fw_dbg_read_d3_debug_data(&mld->fwrt); 1295 1291 1296 1292 ret = iwl_mld_wait_d3_notif(mld, &resume_data, false); 1293 + if (ret) 1294 + return ret; 1297 1295 1298 1296 if (!ret && (resume_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE)) 1299 1297 return -ENODEV; 1300 1298 1301 - if (ret) { 1302 - mld->trans->state = IWL_TRANS_NO_FW; 1303 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1304 - return ret; 1305 - } 1306 1299 iwl_mld_low_latency_restart(mld); 1307 1300 1308 1301 return iwl_mld_update_device_power(mld, false); ··· 1531 1530 iwl_mld_set_wowlan_config_cmd(struct iwl_mld *mld, 1532 1531 struct cfg80211_wowlan *wowlan, 1533 1532 struct iwl_wowlan_config_cmd *wowlan_config_cmd, 1534 - struct ieee80211_sta *ap_sta) 1533 + struct ieee80211_sta *ap_sta, 1534 + struct ieee80211_bss_conf *link) 1535 1535 { 1536 1536 wowlan_config_cmd->is_11n_connection = 1537 1537 ap_sta->deflink.ht_cap.ht_supported; ··· 1541 1539 1542 1540 if (ap_sta->mfp) 1543 1541 wowlan_config_cmd->flags |= IS_11W_ASSOC; 1542 + 1543 + if (iwl_mld_beacon_protection_enabled(mld, link)) 1544 + wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION; 1544 1545 1545 1546 if (wowlan->disconnect) 1546 1547 wowlan_config_cmd->wakeup_filter |= ··· 1742 1737 return ret; 1743 1738 1744 1739 iwl_mld_set_wowlan_config_cmd(mld, wowlan, 1745 - &wowlan_config_cmd, ap_sta); 1740 + &wowlan_config_cmd, ap_sta, link_conf); 1746 1741 ret = iwl_mld_send_cmd_pdu(mld, WOWLAN_CONFIGURATION, 1747 1742 &wowlan_config_cmd); 1748 1743 if (ret) ··· 1812 1807 }; 1813 1808 int link_id; 1814 1809 int ret; 1815 - bool fw_err = false; 1816 1810 1817 1811 lockdep_assert_wiphy(mld->wiphy); 1818 1812 ··· 1854 1850 ret = iwl_mld_wait_d3_notif(mld, &resume_data, true); 1855 1851 if (ret) { 1856 1852 IWL_ERR(mld, "Couldn't get the d3 notifs %d\n", ret); 1857 - fw_err = true; 1858 1853 goto err; 1859 1854 } 1860 1855 ··· 1890 1887 goto out; 1891 1888 1892 1889 err: 1893 - if (fw_err) { 1894 - mld->trans->state = IWL_TRANS_NO_FW; 1895 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1896 - } 1897 - 1898 1890 mld->fw_status.in_hw_restart = true; 1899 1891 ret = 1; 1900 1892 out:
+3 -6
drivers/net/wireless/intel/iwlwifi/mld/iface.c
··· 451 451 return ret; 452 452 } 453 453 454 - int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) 454 + void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) 455 455 { 456 456 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 457 - int ret; 458 457 459 458 lockdep_assert_wiphy(mld->wiphy); 460 459 461 - ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE); 460 + iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE); 462 461 463 462 if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif))) 464 - return -EINVAL; 463 + return; 465 464 466 465 RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL); 467 466 468 467 iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_VIF, 469 468 mld_vif->fw_id); 470 - 471 - return ret; 472 469 } 473 470 474 471 void iwl_mld_set_vif_associated(struct iwl_mld *mld,
+1 -4
drivers/net/wireless/intel/iwlwifi/mld/iface.h
··· 125 125 * @ap_sta: pointer to AP sta, for easier access to it. 126 126 * Relevant only for STA vifs. 127 127 * @authorized: indicates the AP station was set to authorized 128 - * @bigtks: BIGTKs of the AP, for beacon protection. 129 - * Only valid for STA. (FIXME: needs to be per link) 130 128 * @num_associated_stas: number of associated STAs. Relevant only for AP mode. 131 129 * @ap_ibss_active: whether the AP/IBSS was started 132 130 * @cca_40mhz_workaround: When we are connected in 2.4 GHz and 40 MHz, and the ··· 156 158 struct iwl_mld_session_protect session_protect; 157 159 struct ieee80211_sta *ap_sta; 158 160 bool authorized; 159 - struct ieee80211_key_conf __rcu *bigtks[2]; 160 161 u8 num_associated_stas; 161 162 bool ap_ibss_active; 162 163 enum iwl_mld_cca_40mhz_wa_status cca_40mhz_workaround; ··· 224 227 int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif, 225 228 u32 action); 226 229 int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif); 227 - int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif); 230 + void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif); 228 231 void iwl_mld_set_vif_associated(struct iwl_mld *mld, 229 232 struct ieee80211_vif *vif); 230 233 u8 iwl_mld_get_fw_bss_vifs_ids(struct iwl_mld *mld);
+38
drivers/net/wireless/intel/iwlwifi/mld/key.c
··· 368 368 &data); 369 369 return data.err; 370 370 } 371 + 372 + void iwl_mld_track_bigtk(struct iwl_mld *mld, 373 + struct ieee80211_vif *vif, 374 + struct ieee80211_key_conf *key, bool add) 375 + { 376 + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 377 + struct iwl_mld_link *link; 378 + 379 + if (vif->type != NL80211_IFTYPE_STATION) 380 + return; 381 + 382 + if (WARN_ON(key->keyidx < 6 || key->keyidx > 7)) 383 + return; 384 + 385 + if (WARN_ON(key->link_id < 0)) 386 + return; 387 + 388 + link = iwl_mld_link_dereference_check(mld_vif, key->link_id); 389 + if (WARN_ON(!link)) 390 + return; 391 + 392 + if (add) 393 + rcu_assign_pointer(link->bigtks[key->keyidx - 6], key); 394 + else 395 + RCU_INIT_POINTER(link->bigtks[key->keyidx - 6], NULL); 396 + } 397 + 398 + bool iwl_mld_beacon_protection_enabled(struct iwl_mld *mld, 399 + struct ieee80211_bss_conf *link) 400 + { 401 + struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link); 402 + 403 + if (WARN_ON(!mld_link)) 404 + return false; 405 + 406 + return rcu_access_pointer(mld_link->bigtks[0]) || 407 + rcu_access_pointer(mld_link->bigtks[1]); 408 + }
+7
drivers/net/wireless/intel/iwlwifi/mld/key.h
··· 36 36 key->hw_key_idx = STA_KEY_IDX_INVALID; 37 37 } 38 38 39 + void iwl_mld_track_bigtk(struct iwl_mld *mld, 40 + struct ieee80211_vif *vif, 41 + struct ieee80211_key_conf *key, bool add); 42 + 43 + bool iwl_mld_beacon_protection_enabled(struct iwl_mld *mld, 44 + struct ieee80211_bss_conf *link); 45 + 39 46 #endif /* __iwl_mld_key_h__ */
+18 -8
drivers/net/wireless/intel/iwlwifi/mld/link.c
··· 532 532 le32_to_cpu(notif->consec_missed_beacons_other_link); 533 533 struct ieee80211_bss_conf *link_conf = 534 534 iwl_mld_fw_id_to_link_conf(mld, fw_link_id); 535 - u32 bss_param_ch_cnt_link_id; 535 + struct ieee80211_bss_conf *other_link; 536 + u32 bss_param_ch_cnt_link_id, other_link_fw_id; 536 537 struct ieee80211_vif *vif; 537 538 u8 link_id; 538 539 ··· 550 549 551 550 if (WARN_ON(!vif)) 552 551 return; 553 - 554 - mld->trans->dbg.dump_file_name_ext_valid = true; 555 - snprintf(mld->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 556 - "LinkId_%d_MacType_%d", fw_link_id, 557 - iwl_mld_mac80211_iftype_to_fw(vif)); 558 552 559 553 iwl_dbg_tlv_time_point(&mld->fwrt, 560 554 IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data); ··· 568 572 if (missed_bcon_since_rx > IWL_MLD_MISSED_BEACONS_THRESHOLD) { 569 573 ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC); 570 574 571 - /* try to switch links, no-op if we don't have MLO */ 572 - iwl_mld_int_mlo_scan(mld, vif); 575 + /* Not in EMLSR and we can't hear the link. 576 + * Try to switch to a better link. EMLSR case is handled below. 577 + */ 578 + if (!iwl_mld_emlsr_active(vif)) 579 + iwl_mld_int_mlo_scan(mld, vif); 573 580 } 574 581 575 582 /* no more logic if we're not in EMLSR */ ··· 582 583 /* We are processing a notification before link activation */ 583 584 if (le32_to_cpu(notif->other_link_id) == FW_CTXT_ID_INVALID) 584 585 return; 586 + 587 + other_link_fw_id = le32_to_cpu(notif->other_link_id); 588 + other_link = iwl_mld_fw_id_to_link_conf(mld, other_link_fw_id); 589 + 590 + if (IWL_FW_CHECK(mld, !other_link, "link doesn't exist for: %d\n", 591 + other_link_fw_id)) 592 + return; 593 + 594 + IWL_DEBUG_EHT(mld, 595 + "missed bcn on the other link (link_id=%u): %u\n", 596 + other_link->link_id, scnd_lnk_bcn_lost); 585 597 586 598 /* Exit EMLSR if we lost more than 587 599 * IWL_MLD_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
+2
drivers/net/wireless/intel/iwlwifi/mld/link.h
··· 36 36 * @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked. 37 37 * @igtk: fw can only have one IGTK at a time, whereas mac80211 can have two. 38 38 * This tracks the one IGTK that currently exists in FW. 39 + * @bigtks: BIGTKs of the AP. Only valid for STA mode. 39 40 * @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS. 40 41 * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS. 41 42 * @mon_sta: station used for TX injection in monitor interface. ··· 60 59 struct ieee80211_chanctx_conf __rcu *chan_ctx; 61 60 bool he_ru_2mhz_block; 62 61 struct ieee80211_key_conf *igtk; 62 + struct ieee80211_key_conf __rcu *bigtks[2]; 63 63 ); 64 64 /* And here fields that survive a fw restart */ 65 65 struct iwl_mld_int_sta bcast_sta;
+5 -12
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
··· 1966 1966 iwl_fw_runtime_suspend(&mld->fwrt); 1967 1967 1968 1968 ret = iwl_mld_wowlan_suspend(mld, wowlan); 1969 - if (ret) { 1970 - if (ret < 0) { 1971 - mld->trans->state = IWL_TRANS_NO_FW; 1972 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1973 - } 1969 + if (ret) 1974 1970 return 1; 1975 - } 1976 1971 1977 1972 if (iwl_mld_no_wowlan_suspend(mld)) 1978 1973 return 1; ··· 2060 2065 return -EOPNOTSUPP; 2061 2066 } 2062 2067 2063 - if (vif->type == NL80211_IFTYPE_STATION && 2064 - (keyidx == 6 || keyidx == 7)) 2065 - rcu_assign_pointer(mld_vif->bigtks[keyidx - 6], key); 2068 + if (keyidx == 6 || keyidx == 7) 2069 + iwl_mld_track_bigtk(mld, vif, key, true); 2066 2070 2067 2071 /* After exiting from RFKILL, hostapd configures GTK/ITGK before the 2068 2072 * AP is started, but those keys can't be sent to the FW before the ··· 2110 2116 sta ? iwl_mld_sta_from_mac80211(sta) : NULL; 2111 2117 int keyidx = key->keyidx; 2112 2118 2113 - if (vif->type == NL80211_IFTYPE_STATION && 2114 - (keyidx == 6 || keyidx == 7)) 2115 - RCU_INIT_POINTER(mld_vif->bigtks[keyidx - 6], NULL); 2119 + if (keyidx == 6 || keyidx == 7) 2120 + iwl_mld_track_bigtk(mld, vif, key, false); 2116 2121 2117 2122 if (mld_sta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE && 2118 2123 (key->cipher == WLAN_CIPHER_SUITE_CCMP ||
+4
drivers/net/wireless/intel/iwlwifi/mld/mld.c
··· 147 147 */ 148 148 static const struct iwl_hcmd_names iwl_mld_legacy_names[] = { 149 149 HCMD_NAME(UCODE_ALIVE_NTFY), 150 + HCMD_NAME(REPLY_ERROR), 150 151 HCMD_NAME(INIT_COMPLETE_NOTIF), 151 152 HCMD_NAME(PHY_CONTEXT_CMD), 152 153 HCMD_NAME(SCAN_CFG_CMD), ··· 159 158 HCMD_NAME(LEDS_CMD), 160 159 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION), 161 160 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION), 161 + HCMD_NAME(PHY_CONFIGURATION_CMD), 162 162 HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), 163 163 HCMD_NAME(POWER_TABLE_CMD), 164 164 HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), 165 165 HCMD_NAME(BEACON_NOTIFICATION), 166 166 HCMD_NAME(BEACON_TEMPLATE_CMD), 167 167 HCMD_NAME(TX_ANT_CONFIGURATION_CMD), 168 + HCMD_NAME(BT_CONFIG), 168 169 HCMD_NAME(REDUCE_TX_POWER_CMD), 169 170 HCMD_NAME(MISSED_BEACONS_NOTIFICATION), 170 171 HCMD_NAME(MAC_PM_POWER_TABLE), ··· 254 251 HCMD_NAME(TLC_MNG_CONFIG_CMD), 255 252 HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD), 256 253 HCMD_NAME(SCD_QUEUE_CONFIG_CMD), 254 + HCMD_NAME(SEC_KEY_CMD), 257 255 HCMD_NAME(ESR_MODE_NOTIF), 258 256 HCMD_NAME(MONITOR_NOTIF), 259 257 HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
-6
drivers/net/wireless/intel/iwlwifi/mld/mlo.c
··· 735 735 u16 max_grade = 0; 736 736 unsigned long link_id; 737 737 738 - /* 739 - * TODO: don't select links that weren't discovered in the last scan 740 - * This requires mac80211 (or cfg80211) changes to forward/track when 741 - * a BSS was last updated. cfg80211 already tracks this information but 742 - * it is not exposed within the kernel. 743 - */ 744 738 for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 745 739 struct ieee80211_bss_conf *link_conf = 746 740 link_conf_dereference_protected(vif, link_id);
+21 -7
drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
··· 163 163 164 164 static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld) 165 165 { 166 - union iwl_ppag_table_cmd cmd = {}; 167 - int ret, len; 166 + struct iwl_fw_runtime *fwrt = &mld->fwrt; 167 + union iwl_ppag_table_cmd cmd = { 168 + .v7.ppag_config_info.table_source = fwrt->ppag_bios_source, 169 + .v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev, 170 + .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags), 171 + }; 172 + int ret; 168 173 169 - ret = iwl_fill_ppag_table(&mld->fwrt, &cmd, &len); 170 - /* Not supporting PPAG table is a valid scenario */ 171 - if (ret < 0) 172 - return 0; 174 + IWL_DEBUG_RADIO(fwrt, 175 + "PPAG MODE bits going to be sent: %d\n", 176 + fwrt->ppag_flags); 177 + 178 + for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) { 179 + for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) { 180 + cmd.v7.gain[chain][subband] = 181 + fwrt->ppag_chains[chain].subbands[subband]; 182 + IWL_DEBUG_RADIO(fwrt, 183 + "PPAG table: chain[%d] band[%d]: gain = %d\n", 184 + chain, subband, cmd.v7.gain[chain][subband]); 185 + } 186 + } 173 187 174 188 IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n"); 175 189 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP, 176 190 PER_PLATFORM_ANT_GAIN_CMD), 177 - &cmd, len); 191 + &cmd, sizeof(cmd.v7)); 178 192 if (ret < 0) 179 193 IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n", 180 194 ret);
+18 -8
drivers/net/wireless/intel/iwlwifi/mld/rx.c
··· 1611 1611 return sta; 1612 1612 } 1613 1613 1614 - #define KEY_IDX_LEN 2 1615 - 1616 1614 static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta, 1617 1615 struct ieee80211_hdr *hdr, 1618 1616 struct ieee80211_rx_status *rx_status, 1619 1617 u32 mpdu_status, 1620 1618 u32 mpdu_len) 1621 1619 { 1620 + struct iwl_mld_link *link; 1622 1621 struct wireless_dev *wdev; 1623 1622 struct iwl_mld_sta *mld_sta; 1624 1623 struct iwl_mld_vif *mld_vif; 1625 1624 u8 keyidx; 1626 1625 struct ieee80211_key_conf *key; 1627 1626 const u8 *frame = (void *)hdr; 1627 + const u8 *mmie; 1628 + u8 link_id; 1628 1629 1629 1630 if ((mpdu_status & IWL_RX_MPDU_STATUS_SEC_MASK) == 1630 1631 IWL_RX_MPDU_STATUS_SEC_NONE) ··· 1658 1657 return 0; 1659 1658 } 1660 1659 1660 + link_id = rx_status->link_valid ? rx_status->link_id : 0; 1661 + link = rcu_dereference(mld_vif->link[link_id]); 1662 + if (WARN_ON_ONCE(!link)) 1663 + return -1; 1664 + 1661 1665 /* both keys will have the same cipher and MIC length, use 1662 1666 * whichever one is available 1663 1667 */ 1664 - key = rcu_dereference(mld_vif->bigtks[0]); 1668 + key = rcu_dereference(link->bigtks[0]); 1665 1669 if (!key) { 1666 - key = rcu_dereference(mld_vif->bigtks[1]); 1670 + key = rcu_dereference(link->bigtks[1]); 1667 1671 if (!key) 1668 1672 goto report; 1669 1673 } 1670 1674 1671 - if (mpdu_len < key->icv_len + IEEE80211_GMAC_PN_LEN + KEY_IDX_LEN) 1675 + /* get the real key ID */ 1676 + if (mpdu_len < key->icv_len) 1672 1677 goto report; 1673 1678 1674 - /* get the real key ID */ 1675 - keyidx = frame[mpdu_len - key->icv_len - IEEE80211_GMAC_PN_LEN - KEY_IDX_LEN]; 1679 + mmie = frame + (mpdu_len - key->icv_len); 1680 + 1681 + /* the position of the key_id in ieee80211_mmie_16 is the same */ 1682 + keyidx = le16_to_cpu(((const struct ieee80211_mmie *) mmie)->key_id); 1683 + 1676 1684 /* and if that's the other key, look it up */ 1677 1685 if (keyidx != key->keyidx) { 1678 1686 /* shouldn't happen since firmware checked, but be safe ··· 1690 1680 if (keyidx != 6 && keyidx != 7) 1691 1681 return -1; 1692 1682 1693 - key = rcu_dereference(mld_vif->bigtks[keyidx - 6]); 1683 + key = rcu_dereference(link->bigtks[keyidx - 6]); 1694 1684 if (!key) 1695 1685 goto report; 1696 1686 }
+7 -4
drivers/net/wireless/intel/iwlwifi/mld/stats.c
··· 379 379 380 380 /* TODO: task=statistics handle CQM notifications */ 381 381 382 - if (sig < IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH) 383 - iwl_mld_int_mlo_scan(mld, vif); 384 - 385 - if (!iwl_mld_emlsr_active(vif)) 382 + if (!iwl_mld_emlsr_active(vif)) { 383 + /* We're not in EMLSR and our signal is bad, 384 + * try to switch link maybe. EMLSR will be handled below. 385 + */ 386 + if (sig < IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH) 387 + iwl_mld_int_mlo_scan(mld, vif); 386 388 return; 389 + } 387 390 388 391 /* We are in EMLSR, check if we need to exit */ 389 392 exit_emlsr_thresh =
+56 -19
drivers/net/wireless/intel/iwlwifi/mld/tlc.c
··· 157 157 static void 158 158 iwl_mld_fill_vht_rates(const struct ieee80211_link_sta *link_sta, 159 159 const struct ieee80211_sta_vht_cap *vht_cap, 160 - struct iwl_tlc_config_cmd_v4 *cmd) 160 + struct iwl_tlc_config_cmd *cmd) 161 161 { 162 - u16 supp; 162 + u32 supp; 163 163 int i, highest_mcs; 164 164 u8 max_nss = link_sta->rx_nss; 165 165 struct ieee80211_vht_cap ieee_vht_cap = { ··· 182 182 if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) 183 183 supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9); 184 184 185 - cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le16(supp); 185 + cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le32(supp); 186 186 /* Check if VHT extended NSS indicates that the bandwidth/NSS 187 187 * configuration is supported - only for MCS 0 since we already 188 188 * decoded the MCS bits anyway ourselves. ··· 196 196 } 197 197 } 198 198 199 - static u16 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs) 199 + static u32 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs) 200 200 { 201 201 switch (mcs) { 202 202 case IEEE80211_HE_MCS_SUPPORT_0_7: ··· 216 216 static void 217 217 iwl_mld_fill_he_rates(const struct ieee80211_link_sta *link_sta, 218 218 const struct ieee80211_sta_he_cap *own_he_cap, 219 - struct iwl_tlc_config_cmd_v4 *cmd) 219 + struct iwl_tlc_config_cmd *cmd) 220 220 { 221 221 const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; 222 222 u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); ··· 245 245 if (_mcs_80 > _tx_mcs_80) 246 246 _mcs_80 = _tx_mcs_80; 247 247 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = 248 - cpu_to_le16(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80)); 248 + cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80)); 249 249 250 250 /* If one side doesn't support - mark both as not supporting */ 251 251 if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED || ··· 256 256 if (_mcs_160 > _tx_mcs_160) 257 257 _mcs_160 = _tx_mcs_160; 258 258 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] = 259 - cpu_to_le16(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160)); 259 + cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160)); 260 260 } 261 261 } 262 262 263 - static void iwl_mld_set_eht_mcs(__le16 ht_rates[][3], 263 + static void iwl_mld_set_eht_mcs(__le32 ht_rates[][3], 264 264 enum IWL_TLC_MCS_PER_BW bw, 265 - u8 max_nss, u16 mcs_msk) 265 + u8 max_nss, u32 mcs_msk) 266 266 { 267 267 if (max_nss >= 2) 268 - ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le16(mcs_msk); 268 + ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le32(mcs_msk); 269 269 270 270 if (max_nss >= 1) 271 - ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le16(mcs_msk); 271 + ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le32(mcs_msk); 272 272 } 273 273 274 274 static const ··· 307 307 const struct ieee80211_link_sta *link_sta, 308 308 const struct ieee80211_sta_he_cap *own_he_cap, 309 309 const struct ieee80211_sta_eht_cap *own_eht_cap, 310 - struct iwl_tlc_config_cmd_v4 *cmd) 310 + struct iwl_tlc_config_cmd *cmd) 311 311 { 312 312 /* peer RX mcs capa */ 313 313 const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs = ··· 405 405 struct ieee80211_supported_band *sband, 406 406 const struct ieee80211_sta_he_cap *own_he_cap, 407 407 const struct ieee80211_sta_eht_cap *own_eht_cap, 408 - struct iwl_tlc_config_cmd_v4 *cmd) 408 + struct iwl_tlc_config_cmd *cmd) 409 409 { 410 410 int i; 411 411 u16 non_ht_rates = 0; ··· 435 435 } else if (ht_cap->ht_supported) { 436 436 cmd->mode = IWL_TLC_MNG_MODE_HT; 437 437 cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] = 438 - cpu_to_le16(ht_cap->mcs.rx_mask[0]); 438 + cpu_to_le32(ht_cap->mcs.rx_mask[0]); 439 439 440 440 /* the station support only a single receive chain */ 441 441 if (link_sta->smps_mode == IEEE80211_SMPS_STATIC) ··· 443 443 0; 444 444 else 445 445 cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] = 446 - cpu_to_le16(ht_cap->mcs.rx_mask[1]); 446 + cpu_to_le32(ht_cap->mcs.rx_mask[1]); 447 447 } 448 + } 449 + 450 + static void iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd, 451 + struct iwl_tlc_config_cmd_v4 *cmd_v4) 452 + { 453 + /* Copy everything until ht_rates */ 454 + memcpy(cmd_v4, cmd, offsetof(struct iwl_tlc_config_cmd, ht_rates)); 455 + 456 + /* Convert ht_rates from __le32 to __le16 */ 457 + BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates) != ARRAY_SIZE(cmd->ht_rates)); 458 + BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates[0]) != ARRAY_SIZE(cmd->ht_rates[0])); 459 + 460 + for (int nss = 0; nss < ARRAY_SIZE(cmd->ht_rates); nss++) 461 + for (int bw = 0; bw < ARRAY_SIZE(cmd->ht_rates[nss]); bw++) 462 + cmd_v4->ht_rates[nss][bw] = 463 + cpu_to_le16(le32_to_cpu(cmd->ht_rates[nss][bw])); 464 + 465 + /* Copy the rest */ 466 + cmd_v4->max_mpdu_len = cmd->max_mpdu_len; 467 + cmd_v4->max_tx_op = cmd->max_tx_op; 448 468 } 449 469 450 470 static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, ··· 478 458 ieee80211_get_he_iftype_cap_vif(sband, vif); 479 459 const struct ieee80211_sta_eht_cap *own_eht_cap = 480 460 ieee80211_get_eht_iftype_cap_vif(sband, vif); 481 - struct iwl_tlc_config_cmd_v4 cmd = { 461 + struct iwl_tlc_config_cmd cmd = { 482 462 /* For AP mode, use 20 MHz until the STA is authorized */ 483 463 .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ? 484 464 iwl_mld_fw_bw_from_sta_bw(link_sta) : ··· 490 470 .max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len), 491 471 }; 492 472 int fw_sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta); 473 + u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD); 474 + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0); 475 + struct iwl_tlc_config_cmd_v4 cmd_v4; 476 + void *cmd_ptr; 477 + u8 cmd_size; 493 478 int ret; 494 479 495 480 if (fw_sta_id < 0) ··· 506 481 own_he_cap, own_eht_cap, 507 482 &cmd); 508 483 484 + if (cmd_ver == 5) { 485 + cmd_ptr = &cmd; 486 + cmd_size = sizeof(cmd); 487 + } else if (cmd_ver == 4) { 488 + iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4); 489 + cmd_ptr = &cmd_v4; 490 + cmd_size = sizeof(cmd_v4); 491 + } else { 492 + IWL_ERR(mld, "Unsupported TLC config cmd version %d\n", 493 + cmd_ver); 494 + return; 495 + } 496 + 509 497 IWL_DEBUG_RATE(mld, 510 498 "TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n", 511 499 cmd.sta_id, cmd.max_ch_width, cmd.mode); 512 500 513 501 /* Send async since this can be called within a RCU-read section */ 514 - ret = iwl_mld_send_cmd_with_flags_pdu(mld, WIDE_ID(DATA_PATH_GROUP, 515 - TLC_MNG_CONFIG_CMD), 516 - CMD_ASYNC, &cmd); 502 + ret = iwl_mld_send_cmd_with_flags_pdu(mld, cmd_id, CMD_ASYNC, cmd_ptr, 503 + cmd_size); 517 504 if (ret) 518 505 IWL_ERR(mld, "Failed to send TLC cmd (%d)\n", ret); 519 506 }
-131
drivers/net/wireless/intel/iwlwifi/mvm/coex.c
··· 253 253 swap(data->primary, data->secondary); 254 254 } 255 255 256 - /* 257 - * This function receives the LB link id and checks if eSR should be 258 - * enabled or disabled (due to BT coex) 259 - */ 260 - bool 261 - iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, 262 - struct ieee80211_vif *vif, 263 - s32 link_rssi, 264 - bool primary) 265 - { 266 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 267 - bool have_wifi_loss_rate = 268 - iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, 269 - BT_PROFILE_NOTIFICATION, 0) > 4 || 270 - iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP, 271 - PROFILE_NOTIF, 0) >= 1; 272 - u8 wifi_loss_mid_high_rssi; 273 - u8 wifi_loss_low_rssi; 274 - u8 wifi_loss_rate; 275 - 276 - if (iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP, 277 - PROFILE_NOTIF, 0) >= 1) { 278 - /* For now, we consider 2.4 GHz band / ANT_A only */ 279 - wifi_loss_mid_high_rssi = 280 - mvm->last_bt_wifi_loss.wifi_loss_mid_high_rssi[PHY_BAND_24][0]; 281 - wifi_loss_low_rssi = 282 - mvm->last_bt_wifi_loss.wifi_loss_low_rssi[PHY_BAND_24][0]; 283 - } else { 284 - wifi_loss_mid_high_rssi = mvm->last_bt_notif.wifi_loss_mid_high_rssi; 285 - wifi_loss_low_rssi = mvm->last_bt_notif.wifi_loss_low_rssi; 286 - } 287 - 288 - if (wifi_loss_low_rssi == BT_OFF) 289 - return true; 290 - 291 - if (primary) 292 - return false; 293 - 294 - /* The feature is not supported */ 295 - if (!have_wifi_loss_rate) 296 - return true; 297 - 298 - 299 - /* 300 - * In case we don't know the RSSI - take the lower wifi loss, 301 - * so we will more likely enter eSR, and if RSSI is low - 302 - * we will get an update on this and exit eSR. 303 - */ 304 - if (!link_rssi) 305 - wifi_loss_rate = wifi_loss_mid_high_rssi; 306 - 307 - else if (mvmvif->esr_active) 308 - /* RSSI needs to get really low to disable eSR... */ 309 - wifi_loss_rate = 310 - link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ? 311 - wifi_loss_low_rssi : 312 - wifi_loss_mid_high_rssi; 313 - else 314 - /* ...And really high before we enable it back */ 315 - wifi_loss_rate = 316 - link_rssi <= -IWL_MVM_BT_COEX_ENABLE_ESR_THRESH ? 317 - wifi_loss_low_rssi : 318 - wifi_loss_mid_high_rssi; 319 - 320 - return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH; 321 - } 322 - 323 - void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, 324 - struct ieee80211_vif *vif, 325 - int link_id) 326 - { 327 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 328 - struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id]; 329 - 330 - if (!ieee80211_vif_is_mld(vif) || 331 - !iwl_mvm_vif_from_mac80211(vif)->authorized || 332 - WARN_ON(!link)) 333 - return; 334 - 335 - if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, 336 - (s8)link->beacon_stats.avg_signal, 337 - link_id == iwl_mvm_get_primary_link(vif))) 338 - /* In case we decided to exit eSR - stay with the primary */ 339 - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX, 340 - iwl_mvm_get_primary_link(vif)); 341 - } 342 - 343 256 static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm, 344 257 struct ieee80211_vif *vif, 345 258 struct iwl_bt_iterator_data *data, ··· 297 384 } 298 385 return; 299 386 } 300 - 301 - iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); 302 387 303 388 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2)) 304 389 min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC; ··· 436 525 iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id); 437 526 } 438 527 439 - /* must be called under rcu_read_lock */ 440 - static void iwl_mvm_bt_coex_notif_iterator(void *_data, u8 *mac, 441 - struct ieee80211_vif *vif) 442 - { 443 - struct iwl_mvm *mvm = _data; 444 - struct ieee80211_bss_conf *link_conf; 445 - unsigned int link_id; 446 - 447 - lockdep_assert_held(&mvm->mutex); 448 - 449 - if (vif->type != NL80211_IFTYPE_STATION) 450 - return; 451 - 452 - for_each_vif_active_link(vif, link_conf, link_id) { 453 - struct ieee80211_chanctx_conf *chanctx_conf = 454 - rcu_dereference_check(link_conf->chanctx_conf, 455 - lockdep_is_held(&mvm->mutex)); 456 - 457 - if ((!chanctx_conf || 458 - chanctx_conf->def.chan->band != NL80211_BAND_2GHZ)) 459 - continue; 460 - 461 - iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); 462 - } 463 - } 464 - 465 528 static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) 466 529 { 467 530 struct iwl_bt_iterator_data data = { ··· 537 652 memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); 538 653 539 654 iwl_mvm_bt_coex_notif_handle(mvm); 540 - } 541 - 542 - void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, 543 - struct iwl_rx_cmd_buffer *rxb) 544 - { 545 - const struct iwl_rx_packet *pkt = rxb_addr(rxb); 546 - const struct iwl_bt_coex_profile_notif *notif = (const void *)pkt->data; 547 - 548 - lockdep_assert_held(&mvm->mutex); 549 - 550 - mvm->last_bt_wifi_loss = *notif; 551 - 552 - ieee80211_iterate_active_interfaces(mvm->hw, 553 - IEEE80211_IFACE_ITER_NORMAL, 554 - iwl_mvm_bt_coex_notif_iterator, 555 - mvm); 556 655 } 557 656 558 657 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+1 -19
drivers/net/wireless/intel/iwlwifi/mvm/constants.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 2 2 /* 3 3 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH 4 - * Copyright (C) 2013-2014, 2018-2024 Intel Corporation 4 + * Copyright (C) 2013-2014, 2018-2025 Intel Corporation 5 5 * Copyright (C) 2015 Intel Deutschland GmbH 6 6 */ 7 7 #ifndef __MVM_CONSTANTS_H ··· 11 11 #include "fw-api.h" 12 12 13 13 #define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20 14 - #define IWL_MVM_BT_COEX_DISABLE_ESR_THRESH 69 15 - #define IWL_MVM_BT_COEX_ENABLE_ESR_THRESH 63 16 - #define IWL_MVM_BT_COEX_WIFI_LOSS_THRESH 0 17 14 #define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30 18 - #define IWL_MVM_TPT_COUNT_WINDOW_SEC 5 19 - #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5 20 - #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 15 21 - #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11 22 - #define IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH -72 23 15 24 16 #define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC) 25 17 #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) ··· 121 129 #define IWL_MVM_MIN_BEACON_INTERVAL_TU 16 122 130 #define IWL_MVM_AUTO_EML_ENABLE true 123 131 124 - #define IWL_MVM_HIGH_RSSI_THRESH_20MHZ -67 125 - #define IWL_MVM_LOW_RSSI_THRESH_20MHZ -71 126 - #define IWL_MVM_HIGH_RSSI_THRESH_40MHZ -64 127 - #define IWL_MVM_LOW_RSSI_THRESH_40MHZ -67 128 - #define IWL_MVM_HIGH_RSSI_THRESH_80MHZ -61 129 - #define IWL_MVM_LOW_RSSI_THRESH_80MHZ -74 130 - #define IWL_MVM_HIGH_RSSI_THRESH_160MHZ -58 131 - #define IWL_MVM_LOW_RSSI_THRESH_160MHZ -61 132 - 133 - #define IWL_MVM_ENTER_ESR_TPT_THRESH 400 134 132 #endif /* __MVM_CONSTANTS_H */
+38 -331
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
··· 928 928 if (ap_sta->mfp) 929 929 wowlan_config_cmd->flags |= IS_11W_ASSOC; 930 930 931 + if (rcu_access_pointer(mvmvif->bcn_prot.keys[0]) || 932 + rcu_access_pointer(mvmvif->bcn_prot.keys[1])) 933 + wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION; 934 + 931 935 if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) < 6) { 932 936 /* Query the last used seqno and set it */ 933 937 int ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); ··· 1242 1238 } 1243 1239 1244 1240 static int __iwl_mvm_suspend(struct ieee80211_hw *hw, 1245 - struct cfg80211_wowlan *wowlan, 1246 - bool test) 1241 + struct cfg80211_wowlan *wowlan) 1247 1242 { 1248 1243 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1249 1244 struct ieee80211_vif *vif = NULL; 1250 1245 struct iwl_mvm_vif *mvmvif = NULL; 1251 1246 struct ieee80211_sta *ap_sta = NULL; 1252 1247 struct iwl_mvm_vif_link_info *mvm_link; 1253 - struct iwl_d3_manager_config d3_cfg_cmd_data = { 1248 + struct iwl_d3_manager_config d3_cfg_cmd = { 1254 1249 /* 1255 1250 * Program the minimum sleep time to 10 seconds, as many 1256 1251 * platforms have issues processing a wakeup signal while ··· 1257 1254 */ 1258 1255 .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), 1259 1256 }; 1260 - struct iwl_host_cmd d3_cfg_cmd = { 1261 - .id = D3_CONFIG_CMD, 1262 - .flags = CMD_WANT_SKB, 1263 - .data[0] = &d3_cfg_cmd_data, 1264 - .len[0] = sizeof(d3_cfg_cmd_data), 1265 - }; 1266 1257 int ret; 1267 1258 int len __maybe_unused; 1268 1259 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, 1269 1260 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); 1270 1261 1271 1262 if (!wowlan) { 1272 - /* 1273 - * mac80211 shouldn't get here, but for D3 test 1274 - * it doesn't warrant a warning 1275 - */ 1276 - WARN_ON(!test); 1263 + /* mac80211 shouldn't get here */ 1264 + WARN_ON(1); 1277 1265 return -EINVAL; 1278 1266 } 1279 1267 1280 1268 vif = iwl_mvm_get_bss_vif(mvm); 1281 1269 if (IS_ERR_OR_NULL(vif)) 1282 1270 return 1; 1283 - 1284 - ret = iwl_mvm_block_esr_sync(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN); 1285 - if (ret) 1286 - return ret; 1287 1271 1288 1272 mutex_lock(&mvm->mutex); 1289 1273 ··· 1341 1351 1342 1352 #ifdef CONFIG_IWLWIFI_DEBUGFS 1343 1353 if (mvm->d3_wake_sysassert) 1344 - d3_cfg_cmd_data.wakeup_flags |= 1354 + d3_cfg_cmd.wakeup_flags |= 1345 1355 cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR); 1346 1356 #endif 1347 1357 ··· 1354 1364 iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true); 1355 1365 1356 1366 /* must be last -- this switches firmware state */ 1357 - ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); 1367 + ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, 0, sizeof(d3_cfg_cmd), 1368 + &d3_cfg_cmd); 1358 1369 if (ret) 1359 1370 goto out; 1360 - #ifdef CONFIG_IWLWIFI_DEBUGFS 1361 - len = iwl_rx_packet_payload_len(d3_cfg_cmd.resp_pkt); 1362 - if (len >= sizeof(u32)) { 1363 - mvm->d3_test_pme_ptr = 1364 - le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); 1365 - } 1366 - #endif 1367 - iwl_free_resp(&d3_cfg_cmd); 1368 1371 1369 1372 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); 1370 1373 1371 - ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image); 1374 + ret = iwl_trans_d3_suspend(mvm->trans, !unified_image); 1372 1375 out: 1373 1376 if (ret < 0) { 1374 1377 iwl_mvm_free_nd(mvm); ··· 1384 1401 iwl_fw_runtime_suspend(&mvm->fwrt); 1385 1402 mutex_unlock(&mvm->mutex); 1386 1403 1387 - return __iwl_mvm_suspend(hw, wowlan, false); 1404 + return __iwl_mvm_suspend(hw, wowlan); 1388 1405 } 1389 1406 1390 1407 struct iwl_multicast_key_data { ··· 1777 1794 struct iwl_mvm_d3_gtk_iter_data { 1778 1795 struct iwl_mvm *mvm; 1779 1796 struct iwl_wowlan_status_data *status; 1780 - u32 gtk_cipher, igtk_cipher, bigtk_cipher; 1781 - bool unhandled_cipher, igtk_support, bigtk_support; 1782 - int num_keys; 1783 1797 }; 1784 - 1785 - static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw, 1786 - struct ieee80211_vif *vif, 1787 - struct ieee80211_sta *sta, 1788 - struct ieee80211_key_conf *key, 1789 - void *_data) 1790 - { 1791 - struct iwl_mvm_d3_gtk_iter_data *data = _data; 1792 - int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1793 - 1794 - if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id) 1795 - return; 1796 - 1797 - if (data->unhandled_cipher) 1798 - return; 1799 - 1800 - switch (key->cipher) { 1801 - case WLAN_CIPHER_SUITE_WEP40: 1802 - case WLAN_CIPHER_SUITE_WEP104: 1803 - /* ignore WEP completely, nothing to do */ 1804 - return; 1805 - case WLAN_CIPHER_SUITE_CCMP: 1806 - case WLAN_CIPHER_SUITE_GCMP: 1807 - case WLAN_CIPHER_SUITE_GCMP_256: 1808 - case WLAN_CIPHER_SUITE_TKIP: 1809 - /* we support these */ 1810 - data->gtk_cipher = key->cipher; 1811 - break; 1812 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1813 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1814 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1815 - case WLAN_CIPHER_SUITE_AES_CMAC: 1816 - /* we support these */ 1817 - if (data->igtk_support && 1818 - (key->keyidx == 4 || key->keyidx == 5)) { 1819 - data->igtk_cipher = key->cipher; 1820 - } else if (data->bigtk_support && 1821 - (key->keyidx == 6 || key->keyidx == 7)) { 1822 - data->bigtk_cipher = key->cipher; 1823 - } else { 1824 - data->unhandled_cipher = true; 1825 - return; 1826 - } 1827 - break; 1828 - default: 1829 - /* everything else - disconnect from AP */ 1830 - data->unhandled_cipher = true; 1831 - return; 1832 - } 1833 - 1834 - data->num_keys++; 1835 - } 1836 1798 1837 1799 static void 1838 1800 iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key, ··· 1822 1894 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1823 1895 1824 1896 if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id) 1825 - return; 1826 - 1827 - if (data->unhandled_cipher) 1828 1897 return; 1829 1898 1830 1899 switch (key->cipher) { ··· 1872 1947 1873 1948 static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, 1874 1949 struct ieee80211_vif *vif, 1875 - struct iwl_mvm *mvm, u32 gtk_cipher) 1950 + struct iwl_mvm *mvm) 1876 1951 { 1877 1952 int i, j; 1878 1953 struct ieee80211_key_conf *key; 1879 - DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, 1880 - WOWLAN_KEY_MAX_SIZE); 1881 1954 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1882 - u8 key_data[WOWLAN_KEY_MAX_SIZE]; 1883 - 1884 - conf->cipher = gtk_cipher; 1885 - 1886 - BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); 1887 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_CCMP); 1888 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_GCMP_256); 1889 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_TKIP); 1890 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(status->gtk[0].key)); 1891 - 1892 - switch (gtk_cipher) { 1893 - case WLAN_CIPHER_SUITE_CCMP: 1894 - case WLAN_CIPHER_SUITE_GCMP: 1895 - conf->keylen = WLAN_KEY_LEN_CCMP; 1896 - break; 1897 - case WLAN_CIPHER_SUITE_GCMP_256: 1898 - conf->keylen = WLAN_KEY_LEN_GCMP_256; 1899 - break; 1900 - case WLAN_CIPHER_SUITE_TKIP: 1901 - conf->keylen = WLAN_KEY_LEN_TKIP; 1902 - break; 1903 - default: 1904 - WARN_ON(1); 1905 - } 1906 1955 1907 1956 for (i = 0; i < ARRAY_SIZE(status->gtk); i++) { 1908 1957 if (!status->gtk[i].len) 1909 1958 continue; 1910 1959 1911 - conf->keyidx = status->gtk[i].id; 1912 1960 IWL_DEBUG_WOWLAN(mvm, 1913 - "Received from FW GTK cipher %d, key index %d\n", 1914 - conf->cipher, conf->keyidx); 1915 - memcpy(conf->key, status->gtk[i].key, 1916 - sizeof(status->gtk[i].key)); 1917 - memcpy(key_data, status->gtk[i].key, sizeof(status->gtk[i].key)); 1961 + "Received from FW GTK: key index %d\n", 1962 + status->gtk[i].id); 1918 1963 1919 - key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id, key_data, 1920 - sizeof(key_data), link_id); 1964 + key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id, 1965 + status->gtk[i].key, 1966 + sizeof(status->gtk[i].key), 1967 + link_id); 1921 1968 if (IS_ERR(key)) { 1922 1969 /* FW may send also the old keys */ 1923 1970 if (PTR_ERR(key) == -EALREADY) ··· 1912 2015 1913 2016 static bool 1914 2017 iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, 1915 - struct ieee80211_vif *vif, u32 cipher, 2018 + struct ieee80211_vif *vif, 1916 2019 struct iwl_multicast_key_data *key_data) 1917 2020 { 1918 2021 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1919 - DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, 1920 - WOWLAN_KEY_MAX_SIZE); 1921 2022 struct ieee80211_key_conf *key_config; 1922 2023 struct ieee80211_key_seq seq; 1923 2024 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1924 - u8 key[WOWLAN_KEY_MAX_SIZE]; 1925 2025 s8 keyidx = key_data->id; 1926 - 1927 - conf->cipher = cipher; 1928 - conf->keyidx = keyidx; 1929 2026 1930 2027 if (!key_data->len) 1931 2028 return true; 1932 2029 1933 - iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf->cipher); 1934 - 1935 - switch (cipher) { 1936 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1937 - conf->keylen = WLAN_KEY_LEN_BIP_GMAC_128; 1938 - break; 1939 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1940 - conf->keylen = WLAN_KEY_LEN_BIP_GMAC_256; 1941 - break; 1942 - case WLAN_CIPHER_SUITE_AES_CMAC: 1943 - conf->keylen = WLAN_KEY_LEN_AES_CMAC; 1944 - break; 1945 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1946 - conf->keylen = WLAN_KEY_LEN_BIP_CMAC_256; 1947 - break; 1948 - default: 1949 - WARN_ON(1); 1950 - } 1951 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(key_data->key)); 1952 - memcpy(conf->key, key_data->key, conf->keylen); 1953 - 1954 - memcpy(key, key_data->key, sizeof(key_data->key)); 1955 - 1956 - key_config = ieee80211_gtk_rekey_add(vif, keyidx, key, sizeof(key), 1957 - link_id); 2030 + key_config = ieee80211_gtk_rekey_add(vif, keyidx, key_data->key, 2031 + sizeof(key_data->key), link_id); 1958 2032 if (IS_ERR(key_config)) { 1959 2033 /* FW may send also the old keys */ 1960 2034 return PTR_ERR(key_config) == -EALREADY; 1961 2035 } 2036 + 2037 + iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key_config->cipher); 1962 2038 ieee80211_set_key_rx_seq(key_config, 0, &seq); 1963 2039 1964 2040 if (keyidx == 4 || keyidx == 5) { ··· 1985 2115 1986 2116 if (!status || !vif->bss_conf.bssid) 1987 2117 return false; 1988 - 1989 - if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 || 1990 - iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP, 1991 - WOWLAN_INFO_NOTIFICATION, 1992 - 0)) 1993 - gtkdata.igtk_support = true; 1994 - 1995 - if (iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP, 1996 - WOWLAN_INFO_NOTIFICATION, 1997 - 0) >= 3) 1998 - gtkdata.bigtk_support = true; 1999 - 2000 - /* find last GTK that we used initially, if any */ 2001 - ieee80211_iter_keys(mvm->hw, vif, 2002 - iwl_mvm_d3_find_last_keys, &gtkdata); 2003 - /* not trying to keep connections with MFP/unhandled ciphers */ 2004 - if (gtkdata.unhandled_cipher) 2005 - return false; 2006 - if (!gtkdata.num_keys) 2007 - goto out; 2008 - 2009 2118 /* 2010 2119 * invalidate all other GTKs that might still exist and update 2011 2120 * the one that we used ··· 1998 2149 IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n", 1999 2150 status->num_of_gtk_rekeys); 2000 2151 2001 - if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher)) 2152 + if (!iwl_mvm_gtk_rekey(status, vif, mvm)) 2002 2153 return false; 2003 2154 2004 2155 if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif, 2005 - gtkdata.igtk_cipher, 2006 2156 &status->igtk)) 2007 2157 return false; 2008 2158 2009 2159 for (i = 0; i < ARRAY_SIZE(status->bigtk); i++) { 2010 2160 if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif, 2011 - gtkdata.bigtk_cipher, 2012 2161 &status->bigtk[i])) 2013 2162 return false; 2014 2163 } ··· 2015 2168 (void *)&replay_ctr, GFP_KERNEL); 2016 2169 } 2017 2170 2018 - out: 2019 2171 if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, 2020 2172 WOWLAN_GET_STATUSES, 2021 2173 IWL_FW_CMD_VER_UNKNOWN) < 10) { ··· 2573 2727 /* manage d3 resume data */ 2574 2728 struct iwl_d3_data { 2575 2729 struct iwl_wowlan_status_data *status; 2576 - bool test; 2577 2730 u32 d3_end_flags; 2578 2731 u32 notif_expected; /* bitmap - see &enum iwl_d3_notif */ 2579 2732 u32 notif_received; /* bitmap - see &enum iwl_d3_notif */ ··· 2764 2919 2765 2920 if (mvm->net_detect) { 2766 2921 iwl_mvm_query_netdetect_reasons(mvm, vif, d3_data); 2767 - } else { 2768 - bool keep = iwl_mvm_query_wakeup_reasons(mvm, vif, 2769 - d3_data->status); 2770 - 2771 - #ifdef CONFIG_IWLWIFI_DEBUGFS 2772 - if (keep) 2773 - mvm->keep_vif = vif; 2774 - #endif 2775 - 2776 - return keep; 2922 + return false; 2777 2923 } 2778 - return false; 2924 + 2925 + return iwl_mvm_query_wakeup_reasons(mvm, vif, 2926 + d3_data->status); 2779 2927 } 2780 2928 2781 2929 #define IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT (IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET | \ ··· 2981 3143 return d3_data->notif_received == d3_data->notif_expected; 2982 3144 } 2983 3145 2984 - static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm, bool test) 3146 + static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm) 2985 3147 { 2986 3148 int ret; 2987 - enum iwl_d3_status d3_status; 2988 3149 struct iwl_host_cmd cmd = { 2989 3150 .id = D0I3_END_CMD, 2990 3151 .flags = CMD_WANT_SKB, ··· 2991 3154 bool reset = fw_has_capa(&mvm->fw->ucode_capa, 2992 3155 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); 2993 3156 2994 - ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !reset); 3157 + ret = iwl_trans_d3_resume(mvm->trans, !reset); 2995 3158 if (ret) 2996 3159 return ret; 2997 - 2998 - if (d3_status != IWL_D3_STATUS_ALIVE) { 2999 - IWL_INFO(mvm, "Device was reset during suspend\n"); 3000 - return -ENOENT; 3001 - } 3002 3160 3003 3161 /* 3004 3162 * We should trigger resume flow using command only for 22000 family ··· 3039 3207 ARRAY_SIZE(d3_resume_notif), 3040 3208 iwl_mvm_wait_d3_notif, d3_data); 3041 3209 3042 - ret = iwl_mvm_resume_firmware(mvm, d3_data->test); 3210 + ret = iwl_mvm_resume_firmware(mvm); 3043 3211 if (ret) { 3044 3212 iwl_remove_notification(&mvm->notif_wait, &wait_d3_notif); 3045 3213 return ret; ··· 3059 3227 D3_END_NOTIFICATION, 0); 3060 3228 } 3061 3229 3062 - static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) 3230 + static int __iwl_mvm_resume(struct iwl_mvm *mvm) 3063 3231 { 3064 3232 struct ieee80211_vif *vif = NULL; 3065 3233 int ret = 1; 3066 3234 struct iwl_mvm_nd_results results = {}; 3067 3235 struct iwl_d3_data d3_data = { 3068 - .test = test, 3069 3236 .notif_expected = 3070 3237 IWL_D3_NOTIF_WOWLAN_INFO | 3071 3238 IWL_D3_NOTIF_D3_END_NOTIF, ··· 3129 3298 if (ret) 3130 3299 goto err; 3131 3300 } else { 3132 - ret = iwl_mvm_resume_firmware(mvm, test); 3301 + ret = iwl_mvm_resume_firmware(mvm); 3133 3302 if (ret < 0) 3134 3303 goto err; 3135 3304 } 3136 - 3137 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN); 3138 3305 3139 3306 /* when reset is required we can't send these following commands */ 3140 3307 if (d3_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE) ··· 3175 3346 kfree(d3_data.status); 3176 3347 iwl_mvm_free_nd(mvm); 3177 3348 3178 - if (!d3_data.test && !mvm->net_detect) 3349 + if (!mvm->net_detect) 3179 3350 ieee80211_iterate_active_interfaces_mtx(mvm->hw, 3180 3351 IEEE80211_IFACE_ITER_NORMAL, 3181 3352 iwl_mvm_d3_disconnect_iter, ··· 3214 3385 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 3215 3386 int ret; 3216 3387 3217 - ret = __iwl_mvm_resume(mvm, false); 3388 + ret = __iwl_mvm_resume(mvm); 3218 3389 3219 3390 iwl_mvm_resume_tcm(mvm); 3220 3391 ··· 3249 3420 IWL_ERR(mvm, 3250 3421 "fast suspend: couldn't send D3_CONFIG_CMD %d\n", ret); 3251 3422 3252 - ret = iwl_trans_d3_suspend(mvm->trans, false, false); 3423 + ret = iwl_trans_d3_suspend(mvm->trans, false); 3253 3424 if (ret) 3254 3425 IWL_ERR(mvm, "fast suspend: trans_d3_suspend failed %d\n", ret); 3255 3426 } ··· 3302 3473 3303 3474 return ret; 3304 3475 } 3305 - 3306 - #ifdef CONFIG_IWLWIFI_DEBUGFS 3307 - static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) 3308 - { 3309 - struct iwl_mvm *mvm = inode->i_private; 3310 - int err; 3311 - 3312 - if (mvm->d3_test_active) 3313 - return -EBUSY; 3314 - 3315 - file->private_data = inode->i_private; 3316 - 3317 - iwl_mvm_pause_tcm(mvm, true); 3318 - 3319 - iwl_fw_runtime_suspend(&mvm->fwrt); 3320 - 3321 - /* start pseudo D3 */ 3322 - rtnl_lock(); 3323 - wiphy_lock(mvm->hw->wiphy); 3324 - err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); 3325 - wiphy_unlock(mvm->hw->wiphy); 3326 - rtnl_unlock(); 3327 - if (err > 0) 3328 - err = -EINVAL; 3329 - if (err) 3330 - return err; 3331 - 3332 - mvm->d3_test_active = true; 3333 - mvm->keep_vif = NULL; 3334 - return 0; 3335 - } 3336 - 3337 - static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, 3338 - size_t count, loff_t *ppos) 3339 - { 3340 - struct iwl_mvm *mvm = file->private_data; 3341 - unsigned long end = jiffies + 60 * HZ; 3342 - u32 pme_asserted; 3343 - 3344 - while (true) { 3345 - /* read pme_ptr if available */ 3346 - if (mvm->d3_test_pme_ptr) { 3347 - pme_asserted = iwl_trans_read_mem32(mvm->trans, 3348 - mvm->d3_test_pme_ptr); 3349 - if (pme_asserted) 3350 - break; 3351 - } 3352 - 3353 - if (msleep_interruptible(100)) 3354 - break; 3355 - 3356 - if (time_is_before_jiffies(end)) { 3357 - IWL_ERR(mvm, 3358 - "ending pseudo-D3 with timeout after ~60 seconds\n"); 3359 - return -ETIMEDOUT; 3360 - } 3361 - } 3362 - 3363 - return 0; 3364 - } 3365 - 3366 - static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac, 3367 - struct ieee80211_vif *vif) 3368 - { 3369 - /* skip the one we keep connection on */ 3370 - if (_data == vif) 3371 - return; 3372 - 3373 - if (vif->type == NL80211_IFTYPE_STATION) 3374 - ieee80211_connection_loss(vif); 3375 - } 3376 - 3377 - static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) 3378 - { 3379 - struct iwl_mvm *mvm = inode->i_private; 3380 - bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, 3381 - IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); 3382 - 3383 - mvm->d3_test_active = false; 3384 - 3385 - iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt); 3386 - 3387 - rtnl_lock(); 3388 - wiphy_lock(mvm->hw->wiphy); 3389 - __iwl_mvm_resume(mvm, true); 3390 - wiphy_unlock(mvm->hw->wiphy); 3391 - rtnl_unlock(); 3392 - 3393 - iwl_mvm_resume_tcm(mvm); 3394 - 3395 - iwl_fw_runtime_resume(&mvm->fwrt); 3396 - 3397 - iwl_abort_notification_waits(&mvm->notif_wait); 3398 - if (!unified_image) { 3399 - int remaining_time = 10; 3400 - 3401 - ieee80211_restart_hw(mvm->hw); 3402 - 3403 - /* wait for restart and disconnect all interfaces */ 3404 - while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && 3405 - remaining_time > 0) { 3406 - remaining_time--; 3407 - msleep(1000); 3408 - } 3409 - 3410 - if (remaining_time == 0) 3411 - IWL_ERR(mvm, "Timed out waiting for HW restart!\n"); 3412 - } 3413 - 3414 - ieee80211_iterate_active_interfaces_atomic( 3415 - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 3416 - iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif); 3417 - 3418 - return 0; 3419 - } 3420 - 3421 - const struct file_operations iwl_dbgfs_d3_test_ops = { 3422 - .open = iwl_mvm_d3_test_open, 3423 - .read = iwl_mvm_d3_test_read, 3424 - .release = iwl_mvm_d3_test_release, 3425 - }; 3426 - #endif
-94
drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
··· 762 762 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 763 763 } 764 764 765 - static ssize_t iwl_dbgfs_int_mlo_scan_write(struct ieee80211_vif *vif, 766 - char *buf, size_t count, 767 - loff_t *ppos) 768 - { 769 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 770 - struct iwl_mvm *mvm = mvmvif->mvm; 771 - u32 action; 772 - int ret; 773 - 774 - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif)) 775 - return -EINVAL; 776 - 777 - if (kstrtou32(buf, 0, &action)) 778 - return -EINVAL; 779 - 780 - mutex_lock(&mvm->mutex); 781 - 782 - if (!action) { 783 - ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false); 784 - } else if (action == 1) { 785 - ret = iwl_mvm_int_mlo_scan(mvm, vif); 786 - } else { 787 - ret = -EINVAL; 788 - } 789 - 790 - mutex_unlock(&mvm->mutex); 791 - 792 - return ret ?: count; 793 - } 794 - 795 - static ssize_t iwl_dbgfs_esr_disable_reason_read(struct file *file, 796 - char __user *user_buf, 797 - size_t count, loff_t *ppos) 798 - { 799 - struct ieee80211_vif *vif = file->private_data; 800 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 801 - struct iwl_mvm *mvm = mvmvif->mvm; 802 - unsigned long esr_mask; 803 - char *buf; 804 - int bufsz, pos, i; 805 - ssize_t rv; 806 - 807 - mutex_lock(&mvm->mutex); 808 - esr_mask = mvmvif->esr_disable_reason; 809 - mutex_unlock(&mvm->mutex); 810 - 811 - bufsz = hweight32(esr_mask) * 32 + 40; 812 - buf = kmalloc(bufsz, GFP_KERNEL); 813 - if (!buf) 814 - return -ENOMEM; 815 - 816 - pos = scnprintf(buf, bufsz, "EMLSR state: '0x%lx'\nreasons:\n", 817 - esr_mask); 818 - for_each_set_bit(i, &esr_mask, BITS_PER_LONG) 819 - pos += scnprintf(buf + pos, bufsz - pos, " - %s\n", 820 - iwl_get_esr_state_string(BIT(i))); 821 - 822 - rv = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 823 - kfree(buf); 824 - return rv; 825 - } 826 - 827 - static ssize_t iwl_dbgfs_esr_disable_reason_write(struct ieee80211_vif *vif, 828 - char *buf, size_t count, 829 - loff_t *ppos) 830 - { 831 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 832 - struct iwl_mvm *mvm = mvmvif->mvm; 833 - u32 reason; 834 - u8 block; 835 - int ret; 836 - 837 - ret = sscanf(buf, "%u %hhu", &reason, &block); 838 - if (ret < 0) 839 - return ret; 840 - 841 - if (hweight16(reason) != 1 || !(reason & IWL_MVM_BLOCK_ESR_REASONS)) 842 - return -EINVAL; 843 - 844 - mutex_lock(&mvm->mutex); 845 - if (block) 846 - iwl_mvm_block_esr(mvm, vif, reason, 847 - iwl_mvm_get_primary_link(vif)); 848 - else 849 - iwl_mvm_unblock_esr(mvm, vif, reason); 850 - mutex_unlock(&mvm->mutex); 851 - 852 - return count; 853 - } 854 - 855 765 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ 856 766 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) 857 767 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ ··· 794 884 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32); 795 885 MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff); 796 886 MVM_DEBUGFS_READ_WRITE_FILE_OPS(max_tx_op, 10); 797 - MVM_DEBUGFS_WRITE_FILE_OPS(int_mlo_scan, 32); 798 - MVM_DEBUGFS_READ_WRITE_FILE_OPS(esr_disable_reason, 32); 799 887 800 888 void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 801 889 { ··· 824 916 MVM_DEBUGFS_ADD_FILE_VIF(max_tx_op, mvmvif->dbgfs_dir, 0600); 825 917 debugfs_create_bool("ftm_unprotected", 0200, mvmvif->dbgfs_dir, 826 918 &mvmvif->ftm_unprotected); 827 - MVM_DEBUGFS_ADD_FILE_VIF(int_mlo_scan, mvmvif->dbgfs_dir, 0200); 828 - MVM_DEBUGFS_ADD_FILE_VIF(esr_disable_reason, mvmvif->dbgfs_dir, 0600); 829 919 830 920 if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && 831 921 mvmvif == mvm->bf_allowed_vif)
-1
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
··· 2159 2159 MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR); 2160 2160 2161 2161 #ifdef CONFIG_PM_SLEEP 2162 - MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400); 2163 2162 debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir, 2164 2163 &mvm->d3_wake_sysassert); 2165 2164 debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
-809
drivers/net/wireless/intel/iwlwifi/mvm/link.c
··· 5 5 #include "mvm.h" 6 6 #include "time-event.h" 7 7 8 - #define HANDLE_ESR_REASONS(HOW) \ 9 - HOW(BLOCKED_PREVENTION) \ 10 - HOW(BLOCKED_WOWLAN) \ 11 - HOW(BLOCKED_TPT) \ 12 - HOW(BLOCKED_FW) \ 13 - HOW(BLOCKED_NON_BSS) \ 14 - HOW(BLOCKED_ROC) \ 15 - HOW(BLOCKED_TMP_NON_BSS) \ 16 - HOW(EXIT_MISSED_BEACON) \ 17 - HOW(EXIT_LOW_RSSI) \ 18 - HOW(EXIT_COEX) \ 19 - HOW(EXIT_BANDWIDTH) \ 20 - HOW(EXIT_CSA) \ 21 - HOW(EXIT_LINK_USAGE) 22 - 23 - static const char *const iwl_mvm_esr_states_names[] = { 24 - #define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x, 25 - HANDLE_ESR_REASONS(NAME_ENTRY) 26 - }; 27 - 28 - const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state) 29 - { 30 - int offs = ilog2(state); 31 - 32 - if (offs >= ARRAY_SIZE(iwl_mvm_esr_states_names) || 33 - !iwl_mvm_esr_states_names[offs]) 34 - return "UNKNOWN"; 35 - 36 - return iwl_mvm_esr_states_names[offs]; 37 - } 38 - 39 - static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask) 40 - { 41 - #define NAME_FMT(x) "%s" 42 - #define NAME_PR(x) (mask & IWL_MVM_ESR_##x) ? "[" #x "]" : "", 43 - IWL_DEBUG_INFO(mvm, 44 - "EMLSR state = " HANDLE_ESR_REASONS(NAME_FMT) 45 - " (0x%x)\n", 46 - HANDLE_ESR_REASONS(NAME_PR) 47 - mask); 48 - #undef NAME_FMT 49 - #undef NAME_PR 50 - } 51 - 52 8 static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, 53 9 struct iwl_link_config_cmd *cmd, 54 10 enum iwl_ctxt_action action) ··· 68 112 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); 69 113 70 114 return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD); 71 - } 72 - 73 - struct iwl_mvm_esr_iter_data { 74 - struct ieee80211_vif *vif; 75 - unsigned int link_id; 76 - bool lift_block; 77 - }; 78 - 79 - static void iwl_mvm_esr_vif_iterator(void *_data, u8 *mac, 80 - struct ieee80211_vif *vif) 81 - { 82 - struct iwl_mvm_esr_iter_data *data = _data; 83 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 84 - int link_id; 85 - 86 - if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) 87 - return; 88 - 89 - for_each_mvm_vif_valid_link(mvmvif, link_id) { 90 - struct iwl_mvm_vif_link_info *link_info = 91 - mvmvif->link[link_id]; 92 - if (vif == data->vif && link_id == data->link_id) 93 - continue; 94 - if (link_info->active) 95 - data->lift_block = false; 96 - } 97 - } 98 - 99 - int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 100 - unsigned int link_id, bool active) 101 - { 102 - /* An active link of a non-station vif blocks EMLSR. Upon activation 103 - * block EMLSR on the bss vif. Upon deactivation, check if this link 104 - * was the last non-station link active, and if so unblock the bss vif 105 - */ 106 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 107 - struct iwl_mvm_esr_iter_data data = { 108 - .vif = vif, 109 - .link_id = link_id, 110 - .lift_block = true, 111 - }; 112 - 113 - if (IS_ERR_OR_NULL(bss_vif)) 114 - return 0; 115 - 116 - if (active) 117 - return iwl_mvm_block_esr_sync(mvm, bss_vif, 118 - IWL_MVM_ESR_BLOCKED_NON_BSS); 119 - 120 - ieee80211_iterate_active_interfaces(mvm->hw, 121 - IEEE80211_IFACE_ITER_NORMAL, 122 - iwl_mvm_esr_vif_iterator, &data); 123 - if (data.lift_block) { 124 - mutex_lock(&mvm->mutex); 125 - iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_NON_BSS); 126 - mutex_unlock(&mvm->mutex); 127 - } 128 - 129 - return 0; 130 115 } 131 116 132 117 int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ··· 285 388 return ret; 286 389 } 287 390 288 - struct iwl_mvm_rssi_to_grade { 289 - s8 rssi[2]; 290 - u16 grade; 291 - }; 292 - 293 - #define RSSI_TO_GRADE_LINE(_lb, _hb_uhb, _grade) \ 294 - { \ 295 - .rssi = {_lb, _hb_uhb}, \ 296 - .grade = _grade \ 297 - } 298 - 299 - /* 300 - * This array must be sorted by increasing RSSI for proper functionality. 301 - * The grades are actually estimated throughput, represented as fixed-point 302 - * with a scale factor of 1/10. 303 - */ 304 - static const struct iwl_mvm_rssi_to_grade rssi_to_grade_map[] = { 305 - RSSI_TO_GRADE_LINE(-85, -89, 177), 306 - RSSI_TO_GRADE_LINE(-83, -86, 344), 307 - RSSI_TO_GRADE_LINE(-82, -85, 516), 308 - RSSI_TO_GRADE_LINE(-80, -83, 688), 309 - RSSI_TO_GRADE_LINE(-77, -79, 1032), 310 - RSSI_TO_GRADE_LINE(-73, -76, 1376), 311 - RSSI_TO_GRADE_LINE(-70, -74, 1548), 312 - RSSI_TO_GRADE_LINE(-69, -72, 1750), 313 - RSSI_TO_GRADE_LINE(-65, -68, 2064), 314 - RSSI_TO_GRADE_LINE(-61, -66, 2294), 315 - RSSI_TO_GRADE_LINE(-58, -61, 2580), 316 - RSSI_TO_GRADE_LINE(-55, -58, 2868), 317 - RSSI_TO_GRADE_LINE(-46, -55, 3098), 318 - RSSI_TO_GRADE_LINE(-43, -54, 3442) 319 - }; 320 - 321 - #define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade) 322 - 323 - #define DEFAULT_CHAN_LOAD_LB 30 324 - #define DEFAULT_CHAN_LOAD_HB 15 325 - #define DEFAULT_CHAN_LOAD_UHB 0 326 - 327 - /* Factors calculation is done with fixed-point with a scaling factor of 1/256 */ 328 - #define SCALE_FACTOR 256 329 - 330 - /* Convert a percentage from [0,100] to [0,255] */ 331 - #define NORMALIZE_PERCENT_TO_255(percentage) ((percentage) * SCALE_FACTOR / 100) 332 - 333 - static unsigned int 334 - iwl_mvm_get_puncturing_factor(const struct ieee80211_bss_conf *link_conf) 335 - { 336 - enum nl80211_chan_width chan_width = 337 - link_conf->chanreq.oper.width; 338 - int mhz = nl80211_chan_width_to_mhz(chan_width); 339 - unsigned int n_subchannels, n_punctured, puncturing_penalty; 340 - 341 - if (WARN_ONCE(mhz < 20 || mhz > 320, 342 - "Invalid channel width : (%d)\n", mhz)) 343 - return SCALE_FACTOR; 344 - 345 - /* No puncturing, no penalty */ 346 - if (mhz < 80) 347 - return SCALE_FACTOR; 348 - 349 - /* total number of subchannels */ 350 - n_subchannels = mhz / 20; 351 - /* how many of these are punctured */ 352 - n_punctured = hweight16(link_conf->chanreq.oper.punctured); 353 - 354 - puncturing_penalty = n_punctured * SCALE_FACTOR / n_subchannels; 355 - return SCALE_FACTOR - puncturing_penalty; 356 - } 357 - 358 - static unsigned int 359 - iwl_mvm_get_chan_load(struct ieee80211_bss_conf *link_conf) 360 - { 361 - struct ieee80211_vif *vif = link_conf->vif; 362 - struct iwl_mvm_vif_link_info *mvm_link = 363 - iwl_mvm_vif_from_mac80211(link_conf->vif)->link[link_conf->link_id]; 364 - const struct element *bss_load_elem; 365 - const struct ieee80211_bss_load_elem *bss_load; 366 - enum nl80211_band band = link_conf->chanreq.oper.chan->band; 367 - const struct cfg80211_bss_ies *ies; 368 - unsigned int chan_load; 369 - u32 chan_load_by_us; 370 - 371 - rcu_read_lock(); 372 - if (ieee80211_vif_link_active(vif, link_conf->link_id)) 373 - ies = rcu_dereference(link_conf->bss->beacon_ies); 374 - else 375 - ies = rcu_dereference(link_conf->bss->ies); 376 - 377 - if (ies) 378 - bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD, 379 - ies->data, ies->len); 380 - else 381 - bss_load_elem = NULL; 382 - 383 - /* If there isn't BSS Load element, take the defaults */ 384 - if (!bss_load_elem || 385 - bss_load_elem->datalen != sizeof(*bss_load)) { 386 - rcu_read_unlock(); 387 - switch (band) { 388 - case NL80211_BAND_2GHZ: 389 - chan_load = DEFAULT_CHAN_LOAD_LB; 390 - break; 391 - case NL80211_BAND_5GHZ: 392 - chan_load = DEFAULT_CHAN_LOAD_HB; 393 - break; 394 - case NL80211_BAND_6GHZ: 395 - chan_load = DEFAULT_CHAN_LOAD_UHB; 396 - break; 397 - default: 398 - chan_load = 0; 399 - break; 400 - } 401 - /* The defaults are given in percentage */ 402 - return NORMALIZE_PERCENT_TO_255(chan_load); 403 - } 404 - 405 - bss_load = (const void *)bss_load_elem->data; 406 - /* Channel util is in range 0-255 */ 407 - chan_load = bss_load->channel_util; 408 - rcu_read_unlock(); 409 - 410 - if (!mvm_link || !mvm_link->active) 411 - return chan_load; 412 - 413 - if (WARN_ONCE(!mvm_link->phy_ctxt, 414 - "Active link (%u) without phy ctxt assigned!\n", 415 - link_conf->link_id)) 416 - return chan_load; 417 - 418 - /* channel load by us is given in percentage */ 419 - chan_load_by_us = 420 - NORMALIZE_PERCENT_TO_255(mvm_link->phy_ctxt->channel_load_by_us); 421 - 422 - /* Use only values that firmware sends that can possibly be valid */ 423 - if (chan_load_by_us <= chan_load) 424 - chan_load -= chan_load_by_us; 425 - 426 - return chan_load; 427 - } 428 - 429 - static unsigned int 430 - iwl_mvm_get_chan_load_factor(struct ieee80211_bss_conf *link_conf) 431 - { 432 - return SCALE_FACTOR - iwl_mvm_get_chan_load(link_conf); 433 - } 434 - 435 - /* This function calculates the grade of a link. Returns 0 in error case */ 436 - VISIBLE_IF_IWLWIFI_KUNIT 437 - unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf) 438 - { 439 - enum nl80211_band band; 440 - int i, rssi_idx; 441 - s32 link_rssi; 442 - unsigned int grade = MAX_GRADE; 443 - 444 - if (WARN_ON_ONCE(!link_conf)) 445 - return 0; 446 - 447 - band = link_conf->chanreq.oper.chan->band; 448 - if (WARN_ONCE(band != NL80211_BAND_2GHZ && 449 - band != NL80211_BAND_5GHZ && 450 - band != NL80211_BAND_6GHZ, 451 - "Invalid band (%u)\n", band)) 452 - return 0; 453 - 454 - link_rssi = MBM_TO_DBM(link_conf->bss->signal); 455 - /* 456 - * For 6 GHz the RSSI of the beacons is lower than 457 - * the RSSI of the data. 458 - */ 459 - if (band == NL80211_BAND_6GHZ) 460 - link_rssi += 4; 461 - 462 - rssi_idx = band == NL80211_BAND_2GHZ ? 0 : 1; 463 - 464 - /* No valid RSSI - take the lowest grade */ 465 - if (!link_rssi) 466 - link_rssi = rssi_to_grade_map[0].rssi[rssi_idx]; 467 - 468 - /* Get grade based on RSSI */ 469 - for (i = 0; i < ARRAY_SIZE(rssi_to_grade_map); i++) { 470 - const struct iwl_mvm_rssi_to_grade *line = 471 - &rssi_to_grade_map[i]; 472 - 473 - if (link_rssi > line->rssi[rssi_idx]) 474 - continue; 475 - grade = line->grade; 476 - break; 477 - } 478 - 479 - /* apply the channel load and puncturing factors */ 480 - grade = grade * iwl_mvm_get_chan_load_factor(link_conf) / SCALE_FACTOR; 481 - grade = grade * iwl_mvm_get_puncturing_factor(link_conf) / SCALE_FACTOR; 482 - return grade; 483 - } 484 - EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_get_link_grade); 485 - 486 - static 487 - u8 iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif, 488 - struct iwl_mvm_link_sel_data *data, 489 - unsigned long usable_links, 490 - u8 *best_link_idx) 491 - { 492 - u8 n_data = 0; 493 - u16 max_grade = 0; 494 - unsigned long link_id; 495 - 496 - /* TODO: don't select links that weren't discovered in the last scan */ 497 - for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 498 - struct ieee80211_bss_conf *link_conf = 499 - link_conf_dereference_protected(vif, link_id); 500 - 501 - if (WARN_ON_ONCE(!link_conf)) 502 - continue; 503 - 504 - data[n_data].link_id = link_id; 505 - data[n_data].chandef = &link_conf->chanreq.oper; 506 - data[n_data].signal = link_conf->bss->signal / 100; 507 - data[n_data].grade = iwl_mvm_get_link_grade(link_conf); 508 - 509 - if (data[n_data].grade > max_grade) { 510 - max_grade = data[n_data].grade; 511 - *best_link_idx = n_data; 512 - } 513 - n_data++; 514 - } 515 - 516 - return n_data; 517 - } 518 - 519 - struct iwl_mvm_bw_to_rssi_threshs { 520 - s8 low; 521 - s8 high; 522 - }; 523 - 524 - #define BW_TO_RSSI_THRESHOLDS(_bw) \ 525 - [IWL_PHY_CHANNEL_MODE ## _bw] = { \ 526 - .low = IWL_MVM_LOW_RSSI_THRESH_##_bw##MHZ, \ 527 - .high = IWL_MVM_HIGH_RSSI_THRESH_##_bw##MHZ \ 528 - } 529 - 530 - s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, 531 - const struct cfg80211_chan_def *chandef, 532 - bool low) 533 - { 534 - const struct iwl_mvm_bw_to_rssi_threshs bw_to_rssi_threshs_map[] = { 535 - BW_TO_RSSI_THRESHOLDS(20), 536 - BW_TO_RSSI_THRESHOLDS(40), 537 - BW_TO_RSSI_THRESHOLDS(80), 538 - BW_TO_RSSI_THRESHOLDS(160) 539 - /* 320 MHz has the same thresholds as 20 MHz */ 540 - }; 541 - const struct iwl_mvm_bw_to_rssi_threshs *threshs; 542 - u8 chan_width = iwl_mvm_get_channel_width(chandef); 543 - 544 - if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && 545 - chandef->chan->band != NL80211_BAND_5GHZ && 546 - chandef->chan->band != NL80211_BAND_6GHZ)) 547 - return S8_MAX; 548 - 549 - /* 6 GHz will always use 20 MHz thresholds, regardless of the BW */ 550 - if (chan_width == IWL_PHY_CHANNEL_MODE320) 551 - chan_width = IWL_PHY_CHANNEL_MODE20; 552 - 553 - threshs = &bw_to_rssi_threshs_map[chan_width]; 554 - 555 - return low ? threshs->low : threshs->high; 556 - } 557 - 558 - static u32 559 - iwl_mvm_esr_disallowed_with_link(struct iwl_mvm *mvm, 560 - struct ieee80211_vif *vif, 561 - const struct iwl_mvm_link_sel_data *link, 562 - bool primary) 563 - { 564 - struct wiphy *wiphy = mvm->hw->wiphy; 565 - struct ieee80211_bss_conf *conf; 566 - enum iwl_mvm_esr_state ret = 0; 567 - s8 thresh; 568 - 569 - conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); 570 - if (WARN_ON_ONCE(!conf)) 571 - return false; 572 - 573 - /* BT Coex effects eSR mode only if one of the links is on LB */ 574 - if (link->chandef->chan->band == NL80211_BAND_2GHZ && 575 - (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal, 576 - primary))) 577 - ret |= IWL_MVM_ESR_EXIT_COEX; 578 - 579 - thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef, 580 - false); 581 - 582 - if (link->signal < thresh) 583 - ret |= IWL_MVM_ESR_EXIT_LOW_RSSI; 584 - 585 - if (conf->csa_active) 586 - ret |= IWL_MVM_ESR_EXIT_CSA; 587 - 588 - if (ret) { 589 - IWL_DEBUG_INFO(mvm, 590 - "Link %d is not allowed for esr\n", 591 - link->link_id); 592 - iwl_mvm_print_esr_state(mvm, ret); 593 - } 594 - return ret; 595 - } 596 - 597 - VISIBLE_IF_IWLWIFI_KUNIT 598 - bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, 599 - const struct iwl_mvm_link_sel_data *a, 600 - const struct iwl_mvm_link_sel_data *b) 601 - { 602 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 603 - struct iwl_mvm *mvm = mvmvif->mvm; 604 - enum iwl_mvm_esr_state ret = 0; 605 - 606 - /* Per-link considerations */ 607 - if (iwl_mvm_esr_disallowed_with_link(mvm, vif, a, true) || 608 - iwl_mvm_esr_disallowed_with_link(mvm, vif, b, false)) 609 - return false; 610 - 611 - if (a->chandef->chan->band == b->chandef->chan->band || 612 - a->chandef->width != b->chandef->width) 613 - ret |= IWL_MVM_ESR_EXIT_BANDWIDTH; 614 - 615 - if (ret) { 616 - IWL_DEBUG_INFO(mvm, 617 - "Links %d and %d are not a valid pair for EMLSR\n", 618 - a->link_id, b->link_id); 619 - iwl_mvm_print_esr_state(mvm, ret); 620 - return false; 621 - } 622 - 623 - return true; 624 - 625 - } 626 - EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_mld_valid_link_pair); 627 - 628 - /* 629 - * Returns the combined eSR grade of two given links. 630 - * Returns 0 if eSR is not allowed with these 2 links. 631 - */ 632 - static 633 - unsigned int iwl_mvm_get_esr_grade(struct ieee80211_vif *vif, 634 - const struct iwl_mvm_link_sel_data *a, 635 - const struct iwl_mvm_link_sel_data *b, 636 - u8 *primary_id) 637 - { 638 - struct ieee80211_bss_conf *primary_conf; 639 - struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy; 640 - unsigned int primary_load; 641 - 642 - lockdep_assert_wiphy(wiphy); 643 - 644 - /* a is always primary, b is always secondary */ 645 - if (b->grade > a->grade) 646 - swap(a, b); 647 - 648 - *primary_id = a->link_id; 649 - 650 - if (!iwl_mvm_mld_valid_link_pair(vif, a, b)) 651 - return 0; 652 - 653 - primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]); 654 - 655 - if (WARN_ON_ONCE(!primary_conf)) 656 - return 0; 657 - 658 - primary_load = iwl_mvm_get_chan_load(primary_conf); 659 - 660 - return a->grade + 661 - ((b->grade * primary_load) / SCALE_FACTOR); 662 - } 663 - 664 - void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 665 - { 666 - struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS]; 667 - struct iwl_mvm_link_sel_data *best_link; 668 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 669 - u32 max_active_links = iwl_mvm_max_active_links(mvm, vif); 670 - u16 usable_links = ieee80211_vif_usable_links(vif); 671 - u8 best, primary_link, best_in_pair, n_data; 672 - u16 max_esr_grade = 0, new_active_links; 673 - 674 - lockdep_assert_wiphy(mvm->hw->wiphy); 675 - 676 - if (!mvmvif->authorized || !ieee80211_vif_is_mld(vif)) 677 - return; 678 - 679 - if (!IWL_MVM_AUTO_EML_ENABLE) 680 - return; 681 - 682 - /* The logic below is a simple version that doesn't suit more than 2 683 - * links 684 - */ 685 - WARN_ON_ONCE(max_active_links > 2); 686 - 687 - n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links, 688 - &best); 689 - 690 - if (WARN(!n_data, "Couldn't find a valid grade for any link!\n")) 691 - return; 692 - 693 - best_link = &data[best]; 694 - primary_link = best_link->link_id; 695 - new_active_links = BIT(best_link->link_id); 696 - 697 - /* eSR is not supported/blocked, or only one usable link */ 698 - if (max_active_links == 1 || !iwl_mvm_vif_has_esr_cap(mvm, vif) || 699 - mvmvif->esr_disable_reason || n_data == 1) 700 - goto set_active; 701 - 702 - for (u8 a = 0; a < n_data; a++) 703 - for (u8 b = a + 1; b < n_data; b++) { 704 - u16 esr_grade = iwl_mvm_get_esr_grade(vif, &data[a], 705 - &data[b], 706 - &best_in_pair); 707 - 708 - if (esr_grade <= max_esr_grade) 709 - continue; 710 - 711 - max_esr_grade = esr_grade; 712 - primary_link = best_in_pair; 713 - new_active_links = BIT(data[a].link_id) | 714 - BIT(data[b].link_id); 715 - } 716 - 717 - /* No valid pair was found, go with the best link */ 718 - if (hweight16(new_active_links) <= 1) 719 - goto set_active; 720 - 721 - /* For equal grade - prefer EMLSR */ 722 - if (best_link->grade > max_esr_grade) { 723 - primary_link = best_link->link_id; 724 - new_active_links = BIT(best_link->link_id); 725 - } 726 - set_active: 727 - IWL_DEBUG_INFO(mvm, "Link selection result: 0x%x. Primary = %d\n", 728 - new_active_links, primary_link); 729 - ieee80211_set_active_links_async(vif, new_active_links); 730 - mvmvif->link_selection_res = new_active_links; 731 - mvmvif->link_selection_primary = primary_link; 732 - } 733 - 734 391 u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif) 735 392 { 736 393 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ··· 305 854 return mvmvif->primary_link; 306 855 307 856 return __ffs(vif->active_links); 308 - } 309 - 310 - /* 311 - * For non-MLO/single link, this will return the deflink/single active link, 312 - * respectively 313 - */ 314 - u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id) 315 - { 316 - switch (hweight16(vif->active_links)) { 317 - case 0: 318 - return 0; 319 - default: 320 - WARN_ON(1); 321 - fallthrough; 322 - case 1: 323 - return __ffs(vif->active_links); 324 - case 2: 325 - return __ffs(vif->active_links & ~BIT(link_id)); 326 - } 327 - } 328 - 329 - /* Reasons that can cause esr prevention */ 330 - #define IWL_MVM_ESR_PREVENT_REASONS IWL_MVM_ESR_EXIT_MISSED_BEACON 331 - #define IWL_MVM_PREVENT_ESR_TIMEOUT (HZ * 400) 332 - #define IWL_MVM_ESR_PREVENT_SHORT (HZ * 300) 333 - #define IWL_MVM_ESR_PREVENT_LONG (HZ * 600) 334 - 335 - static bool iwl_mvm_check_esr_prevention(struct iwl_mvm *mvm, 336 - struct iwl_mvm_vif *mvmvif, 337 - enum iwl_mvm_esr_state reason) 338 - { 339 - bool timeout_expired = time_after(jiffies, 340 - mvmvif->last_esr_exit.ts + 341 - IWL_MVM_PREVENT_ESR_TIMEOUT); 342 - unsigned long delay; 343 - 344 - lockdep_assert_held(&mvm->mutex); 345 - 346 - /* Only handle reasons that can cause prevention */ 347 - if (!(reason & IWL_MVM_ESR_PREVENT_REASONS)) 348 - return false; 349 - 350 - /* 351 - * Reset the counter if more than 400 seconds have passed between one 352 - * exit and the other, or if we exited due to a different reason. 353 - * Will also reset the counter after the long prevention is done. 354 - */ 355 - if (timeout_expired || mvmvif->last_esr_exit.reason != reason) { 356 - mvmvif->exit_same_reason_count = 1; 357 - return false; 358 - } 359 - 360 - mvmvif->exit_same_reason_count++; 361 - if (WARN_ON(mvmvif->exit_same_reason_count < 2 || 362 - mvmvif->exit_same_reason_count > 3)) 363 - return false; 364 - 365 - mvmvif->esr_disable_reason |= IWL_MVM_ESR_BLOCKED_PREVENTION; 366 - 367 - /* 368 - * For the second exit, use a short prevention, and for the third one, 369 - * use a long prevention. 370 - */ 371 - delay = mvmvif->exit_same_reason_count == 2 ? 372 - IWL_MVM_ESR_PREVENT_SHORT : 373 - IWL_MVM_ESR_PREVENT_LONG; 374 - 375 - IWL_DEBUG_INFO(mvm, 376 - "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n", 377 - delay / HZ, mvmvif->exit_same_reason_count, 378 - iwl_get_esr_state_string(reason), reason); 379 - 380 - wiphy_delayed_work_queue(mvm->hw->wiphy, 381 - &mvmvif->prevent_esr_done_wk, delay); 382 - return true; 383 - } 384 - 385 - #define IWL_MVM_TRIGGER_LINK_SEL_TIME (IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC * HZ) 386 - 387 - /* API to exit eSR mode */ 388 - void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 389 - enum iwl_mvm_esr_state reason, 390 - u8 link_to_keep) 391 - { 392 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 393 - u16 new_active_links; 394 - bool prevented; 395 - 396 - lockdep_assert_held(&mvm->mutex); 397 - 398 - if (!IWL_MVM_AUTO_EML_ENABLE) 399 - return; 400 - 401 - /* Nothing to do */ 402 - if (!mvmvif->esr_active) 403 - return; 404 - 405 - if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized)) 406 - return; 407 - 408 - if (WARN_ON(!(vif->active_links & BIT(link_to_keep)))) 409 - link_to_keep = __ffs(vif->active_links); 410 - 411 - new_active_links = BIT(link_to_keep); 412 - IWL_DEBUG_INFO(mvm, 413 - "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n", 414 - iwl_get_esr_state_string(reason), reason, 415 - vif->active_links, new_active_links); 416 - 417 - ieee80211_set_active_links_async(vif, new_active_links); 418 - 419 - /* Prevent EMLSR if needed */ 420 - prevented = iwl_mvm_check_esr_prevention(mvm, mvmvif, reason); 421 - 422 - /* Remember why and when we exited EMLSR */ 423 - mvmvif->last_esr_exit.ts = jiffies; 424 - mvmvif->last_esr_exit.reason = reason; 425 - 426 - /* 427 - * If EMLSR is prevented now - don't try to get back to EMLSR. 428 - * If we exited due to a blocking event, we will try to get back to 429 - * EMLSR when the corresponding unblocking event will happen. 430 - */ 431 - if (prevented || reason & IWL_MVM_BLOCK_ESR_REASONS) 432 - return; 433 - 434 - /* If EMLSR is not blocked - try enabling it again in 30 seconds */ 435 - wiphy_delayed_work_queue(mvm->hw->wiphy, 436 - &mvmvif->mlo_int_scan_wk, 437 - round_jiffies_relative(IWL_MVM_TRIGGER_LINK_SEL_TIME)); 438 - } 439 - 440 - void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 441 - enum iwl_mvm_esr_state reason, 442 - u8 link_to_keep) 443 - { 444 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 445 - 446 - lockdep_assert_held(&mvm->mutex); 447 - 448 - if (!IWL_MVM_AUTO_EML_ENABLE) 449 - return; 450 - 451 - /* This should be called only with disable reasons */ 452 - if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 453 - return; 454 - 455 - if (mvmvif->esr_disable_reason & reason) 456 - return; 457 - 458 - IWL_DEBUG_INFO(mvm, 459 - "Blocking EMLSR mode. reason = %s (0x%x)\n", 460 - iwl_get_esr_state_string(reason), reason); 461 - 462 - mvmvif->esr_disable_reason |= reason; 463 - 464 - iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); 465 - 466 - iwl_mvm_exit_esr(mvm, vif, reason, link_to_keep); 467 - } 468 - 469 - int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 470 - enum iwl_mvm_esr_state reason) 471 - { 472 - int primary_link = iwl_mvm_get_primary_link(vif); 473 - int ret; 474 - 475 - if (!IWL_MVM_AUTO_EML_ENABLE || !ieee80211_vif_is_mld(vif)) 476 - return 0; 477 - 478 - /* This should be called only with blocking reasons */ 479 - if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 480 - return 0; 481 - 482 - /* leave ESR immediately, not only async with iwl_mvm_block_esr() */ 483 - ret = ieee80211_set_active_links(vif, BIT(primary_link)); 484 - if (ret) 485 - return ret; 486 - 487 - mutex_lock(&mvm->mutex); 488 - /* only additionally block for consistency and to avoid concurrency */ 489 - iwl_mvm_block_esr(mvm, vif, reason, primary_link); 490 - mutex_unlock(&mvm->mutex); 491 - 492 - return 0; 493 - } 494 - 495 - static void iwl_mvm_esr_unblocked(struct iwl_mvm *mvm, 496 - struct ieee80211_vif *vif) 497 - { 498 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 499 - bool need_new_sel = time_after(jiffies, mvmvif->last_esr_exit.ts + 500 - IWL_MVM_TRIGGER_LINK_SEL_TIME); 501 - 502 - lockdep_assert_held(&mvm->mutex); 503 - 504 - if (!ieee80211_vif_is_mld(vif) || !mvmvif->authorized || 505 - mvmvif->esr_active) 506 - return; 507 - 508 - IWL_DEBUG_INFO(mvm, "EMLSR is unblocked\n"); 509 - 510 - /* If we exited due to an EXIT reason, and the exit was in less than 511 - * 30 seconds, then a MLO scan was scheduled already. 512 - */ 513 - if (!need_new_sel && 514 - !(mvmvif->last_esr_exit.reason & IWL_MVM_BLOCK_ESR_REASONS)) { 515 - IWL_DEBUG_INFO(mvm, "Wait for MLO scan\n"); 516 - return; 517 - } 518 - 519 - /* 520 - * If EMLSR was blocked for more than 30 seconds, or the last link 521 - * selection decided to not enter EMLSR, trigger a new scan. 522 - */ 523 - if (need_new_sel || hweight16(mvmvif->link_selection_res) < 2) { 524 - IWL_DEBUG_INFO(mvm, "Trigger MLO scan\n"); 525 - wiphy_delayed_work_queue(mvm->hw->wiphy, 526 - &mvmvif->mlo_int_scan_wk, 0); 527 - /* 528 - * If EMLSR was blocked for less than 30 seconds, and the last link 529 - * selection decided to use EMLSR, activate EMLSR using the previous 530 - * link selection result. 531 - */ 532 - } else { 533 - IWL_DEBUG_INFO(mvm, 534 - "Use the latest link selection result: 0x%x\n", 535 - mvmvif->link_selection_res); 536 - ieee80211_set_active_links_async(vif, 537 - mvmvif->link_selection_res); 538 - } 539 - } 540 - 541 - void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 542 - enum iwl_mvm_esr_state reason) 543 - { 544 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 545 - 546 - lockdep_assert_held(&mvm->mutex); 547 - 548 - if (!IWL_MVM_AUTO_EML_ENABLE) 549 - return; 550 - 551 - /* This should be called only with disable reasons */ 552 - if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 553 - return; 554 - 555 - /* No Change */ 556 - if (!(mvmvif->esr_disable_reason & reason)) 557 - return; 558 - 559 - mvmvif->esr_disable_reason &= ~reason; 560 - 561 - IWL_DEBUG_INFO(mvm, 562 - "Unblocking EMLSR mode. reason = %s (0x%x)\n", 563 - iwl_get_esr_state_string(reason), reason); 564 - iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); 565 - 566 - if (!mvmvif->esr_disable_reason) 567 - iwl_mvm_esr_unblocked(mvm, vif); 568 857 } 569 858 570 859 void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link)
-38
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
··· 1586 1586 u32 id = le32_to_cpu(mb->link_id); 1587 1587 union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; 1588 1588 u32 mac_type; 1589 - int link_id; 1590 1589 u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, 1591 1590 MISSED_BEACONS_NOTIFICATION, 1592 1591 0); 1593 1592 u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, 1594 1593 MISSED_BEACONS_NOTIF, 0); 1595 - struct ieee80211_bss_conf *bss_conf; 1596 1594 1597 1595 /* If the firmware uses the new notification (from MAC_CONF_GROUP), 1598 1596 * refer to that notification's version. ··· 1615 1617 if (!vif) 1616 1618 return; 1617 1619 1618 - bss_conf = &vif->bss_conf; 1619 - link_id = bss_conf->link_id; 1620 1620 mac_type = iwl_mvm_get_mac_type(vif); 1621 1621 1622 1622 IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type); 1623 - 1624 - mvm->trans->dbg.dump_file_name_ext_valid = true; 1625 - snprintf(mvm->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 1626 - "MacId_%d_MacType_%d", id, mac_type); 1627 1623 1628 1624 rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons); 1629 1625 rx_missed_bcon_since_rx = ··· 1636 1644 "missed_beacons:%d, missed_beacons_since_rx:%d\n", 1637 1645 rx_missed_bcon, rx_missed_bcon_since_rx); 1638 1646 } 1639 - } else if (link_id >= 0 && hweight16(vif->active_links) > 1) { 1640 - u32 bss_param_ch_cnt_link_id = 1641 - bss_conf->bss_param_ch_cnt_link_id; 1642 - u32 scnd_lnk_bcn_lost = 0; 1643 - 1644 - if (notif_ver >= 5 && 1645 - !IWL_FW_CHECK(mvm, 1646 - le32_to_cpu(mb->other_link_id) == IWL_MVM_FW_LINK_ID_INVALID, 1647 - "No data for other link id but we are in EMLSR active_links: 0x%x\n", 1648 - vif->active_links)) 1649 - scnd_lnk_bcn_lost = 1650 - le32_to_cpu(mb->consec_missed_beacons_other_link); 1651 - 1652 - /* Exit EMLSR if we lost more than 1653 - * IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links 1654 - * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link. 1655 - * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 1656 - * and the link's bss_param_ch_count has changed. 1657 - */ 1658 - if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS && 1659 - scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) || 1660 - rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH || 1661 - (bss_param_ch_cnt_link_id != link_id && 1662 - rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED)) 1663 - iwl_mvm_exit_esr(mvm, vif, 1664 - IWL_MVM_ESR_EXIT_MISSED_BEACON, 1665 - iwl_mvm_get_primary_link(vif)); 1666 1647 } else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) { 1667 1648 if (!iwl_mvm_has_new_tx_api(mvm)) 1668 1649 ieee80211_beacon_loss(vif); 1669 1650 else 1670 1651 ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC); 1671 - 1672 - /* try to switch links, no-op if we don't have MLO */ 1673 - iwl_mvm_int_mlo_scan(mvm, vif); 1674 1652 } 1675 1653 1676 1654 iwl_dbg_tlv_time_point(&mvm->fwrt,
+6 -118
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
··· 1425 1425 { 1426 1426 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1427 1427 1428 - /* Stop internal MLO scan, if running */ 1429 - mutex_lock(&mvm->mutex); 1430 - iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false); 1431 - mutex_unlock(&mvm->mutex); 1432 - 1433 - wiphy_work_cancel(mvm->hw->wiphy, &mvm->trig_link_selection_wk); 1434 1428 wiphy_work_flush(mvm->hw->wiphy, &mvm->async_handlers_wiphy_wk); 1435 1429 flush_work(&mvm->async_handlers_wk); 1436 1430 flush_work(&mvm->add_stream_wk); ··· 1709 1715 IWL_STA_MULTICAST); 1710 1716 } 1711 1717 1712 - static void iwl_mvm_prevent_esr_done_wk(struct wiphy *wiphy, 1713 - struct wiphy_work *wk) 1714 - { 1715 - struct iwl_mvm_vif *mvmvif = 1716 - container_of(wk, struct iwl_mvm_vif, prevent_esr_done_wk.work); 1717 - struct iwl_mvm *mvm = mvmvif->mvm; 1718 - struct ieee80211_vif *vif = 1719 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1720 - 1721 - guard(mvm)(mvm); 1722 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_PREVENTION); 1723 - } 1724 - 1725 - static void iwl_mvm_mlo_int_scan_wk(struct wiphy *wiphy, struct wiphy_work *wk) 1726 - { 1727 - struct iwl_mvm_vif *mvmvif = container_of(wk, struct iwl_mvm_vif, 1728 - mlo_int_scan_wk.work); 1729 - struct ieee80211_vif *vif = 1730 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1731 - 1732 - guard(mvm)(mvmvif->mvm); 1733 - iwl_mvm_int_mlo_scan(mvmvif->mvm, vif); 1734 - } 1735 - 1736 - static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk) 1737 - { 1738 - struct iwl_mvm_vif *mvmvif = 1739 - container_of(wk, struct iwl_mvm_vif, unblock_esr_tpt_wk); 1740 - struct iwl_mvm *mvm = mvmvif->mvm; 1741 - struct ieee80211_vif *vif = 1742 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1743 - 1744 - guard(mvm)(mvm); 1745 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT); 1746 - } 1747 - 1748 - static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy, 1749 - struct wiphy_work *wk) 1750 - { 1751 - struct iwl_mvm_vif *mvmvif = 1752 - container_of(wk, struct iwl_mvm_vif, 1753 - unblock_esr_tmp_non_bss_wk.work); 1754 - struct iwl_mvm *mvm = mvmvif->mvm; 1755 - struct ieee80211_vif *vif = 1756 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1757 - 1758 - mutex_lock(&mvm->mutex); 1759 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS); 1760 - mutex_unlock(&mvm->mutex); 1761 - } 1762 - 1763 1718 void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) 1764 1719 { 1765 1720 lockdep_assert_held(&mvm->mutex); ··· 1720 1777 1721 1778 INIT_DELAYED_WORK(&mvmvif->csa_work, 1722 1779 iwl_mvm_channel_switch_disconnect_wk); 1723 - 1724 - wiphy_delayed_work_init(&mvmvif->prevent_esr_done_wk, 1725 - iwl_mvm_prevent_esr_done_wk); 1726 - 1727 - wiphy_delayed_work_init(&mvmvif->mlo_int_scan_wk, 1728 - iwl_mvm_mlo_int_scan_wk); 1729 - 1730 - wiphy_work_init(&mvmvif->unblock_esr_tpt_wk, 1731 - iwl_mvm_unblock_esr_tpt); 1732 - 1733 - wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk, 1734 - iwl_mvm_unblock_esr_tmp_non_bss); 1735 1780 } 1736 1781 1737 1782 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ··· 1856 1925 */ 1857 1926 flush_work(&mvm->roc_done_wk); 1858 1927 } 1859 - 1860 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 1861 - &mvmvif->prevent_esr_done_wk); 1862 - 1863 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 1864 - &mvmvif->mlo_int_scan_wk); 1865 - 1866 - wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk); 1867 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 1868 - &mvmvif->unblock_esr_tmp_non_bss_wk); 1869 1928 1870 1929 cancel_delayed_work_sync(&mvmvif->csa_work); 1871 1930 } ··· 3929 4008 3930 4009 callbacks->mac_ctxt_changed(mvm, vif, false); 3931 4010 iwl_mvm_mei_host_associated(mvm, vif, mvm_sta); 3932 - 3933 - memset(&mvmvif->last_esr_exit, 0, 3934 - sizeof(mvmvif->last_esr_exit)); 3935 - 3936 - iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT, 0); 3937 - 3938 - /* Block until FW notif will arrive */ 3939 - iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW, 0); 3940 - 3941 - /* when client is authorized (AP station marked as such), 3942 - * try to enable the best link(s). 3943 - */ 3944 - if (vif->type == NL80211_IFTYPE_STATION && 3945 - !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) 3946 - iwl_mvm_select_links(mvm, vif); 3947 4011 } 3948 4012 3949 4013 mvm_sta->authorized = true; ··· 3976 4070 3977 4071 /* disable beacon filtering */ 3978 4072 iwl_mvm_disable_beacon_filter(mvm, vif); 3979 - 3980 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 3981 - &mvmvif->prevent_esr_done_wk); 3982 - 3983 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 3984 - &mvmvif->mlo_int_scan_wk); 3985 - 3986 - wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk); 3987 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 3988 - &mvmvif->unblock_esr_tmp_non_bss_wk); 3989 4073 } 3990 4074 3991 4075 return 0; ··· 4816 4920 const struct iwl_mvm_roc_ops *ops) 4817 4921 { 4818 4922 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 4819 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 4820 4923 u32 lmac_id; 4821 4924 int ret; 4822 4925 ··· 4827 4932 * the work it does can complete and we can accept new frames. 4828 4933 */ 4829 4934 flush_work(&mvm->roc_done_wk); 4830 - 4831 - if (!IS_ERR_OR_NULL(bss_vif)) { 4832 - ret = iwl_mvm_block_esr_sync(mvm, bss_vif, 4833 - IWL_MVM_ESR_BLOCKED_ROC); 4834 - if (ret) 4835 - return ret; 4836 - } 4837 4935 4838 4936 guard(mvm)(mvm); 4839 4937 ··· 5492 5604 } 5493 5605 5494 5606 #define IWL_MAX_CSA_BLOCK_TX 1500 5495 - int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm, 5496 - struct ieee80211_vif *vif, 5497 - struct ieee80211_channel_switch *chsw) 5607 + static int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm, 5608 + struct ieee80211_vif *vif, 5609 + struct ieee80211_channel_switch *chsw) 5498 5610 { 5499 5611 struct ieee80211_vif *csa_vif; 5500 5612 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ··· 5612 5724 return ret; 5613 5725 } 5614 5726 5615 - static int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, 5616 - struct ieee80211_vif *vif, 5617 - struct ieee80211_channel_switch *chsw) 5727 + int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, 5728 + struct ieee80211_vif *vif, 5729 + struct ieee80211_channel_switch *chsw) 5618 5730 { 5619 5731 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 5620 5732
+1 -137
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
··· 340 340 { 341 341 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 342 342 343 - /* update EMLSR mode */ 344 - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) { 345 - int ret; 346 - 347 - ret = iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id, 348 - true); 349 - /* 350 - * Don't activate this link if failed to exit EMLSR in 351 - * the BSS interface 352 - */ 353 - if (ret) 354 - return ret; 355 - } 356 - 357 343 guard(mvm)(mvm); 358 344 return __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false); 359 345 } ··· 458 472 iwl_mvm_add_link(mvm, vif, link_conf); 459 473 } 460 474 mutex_unlock(&mvm->mutex); 461 - 462 - /* update EMLSR mode */ 463 - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) 464 - iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id, false); 465 475 } 466 476 467 477 static void ··· 666 684 &callbacks); 667 685 } 668 686 669 - static bool iwl_mvm_esr_bw_criteria(struct iwl_mvm *mvm, 670 - struct ieee80211_vif *vif, 671 - struct ieee80211_bss_conf *link_conf) 672 - { 673 - struct ieee80211_bss_conf *other_link; 674 - int link_id; 675 - 676 - /* Exit EMLSR if links don't have equal bandwidths */ 677 - for_each_vif_active_link(vif, other_link, link_id) { 678 - if (link_id == link_conf->link_id) 679 - continue; 680 - if (link_conf->chanreq.oper.width == 681 - other_link->chanreq.oper.width) 682 - return true; 683 - } 684 - 685 - return false; 686 - } 687 - 688 687 static void 689 688 iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm, 690 689 struct ieee80211_vif *vif, ··· 699 736 IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n"); 700 737 link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS; 701 738 } 702 - 703 - if ((changes & BSS_CHANGED_BANDWIDTH) && 704 - ieee80211_vif_link_active(vif, link_conf->link_id) && 705 - mvmvif->esr_active && 706 - !iwl_mvm_esr_bw_criteria(mvm, vif, link_conf)) 707 - iwl_mvm_exit_esr(mvm, vif, 708 - IWL_MVM_ESR_EXIT_BANDWIDTH, 709 - iwl_mvm_get_primary_link(vif)); 710 739 711 740 /* if associated, maybe puncturing changed - we'll check later */ 712 741 if (vif->cfg.assoc) ··· 834 879 if (ret) 835 880 IWL_ERR(mvm, "failed to update power mode\n"); 836 881 } 837 - 838 - if (changes & (BSS_CHANGED_MLD_VALID_LINKS | BSS_CHANGED_MLD_TTLM) && 839 - ieee80211_vif_is_mld(vif) && mvmvif->authorized) 840 - wiphy_delayed_work_queue(mvm->hw->wiphy, 841 - &mvmvif->mlo_int_scan_wk, 0); 842 882 } 843 883 844 884 static void ··· 1189 1239 return NEG_TTLM_RES_ACCEPT; 1190 1240 } 1191 1241 1192 - static int 1193 - iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw, 1194 - struct ieee80211_vif *vif, 1195 - struct ieee80211_channel_switch *chsw) 1196 - { 1197 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1198 - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1199 - int ret; 1200 - 1201 - mutex_lock(&mvm->mutex); 1202 - if (mvmvif->esr_active) { 1203 - u8 primary = iwl_mvm_get_primary_link(vif); 1204 - int selected; 1205 - 1206 - /* prefer primary unless quiet CSA on it */ 1207 - if (chsw->link_id == primary && chsw->block_tx) 1208 - selected = iwl_mvm_get_other_link(vif, primary); 1209 - else 1210 - selected = primary; 1211 - 1212 - /* 1213 - * remembers to tell the firmware that this link can't tx 1214 - * Note that this logic seems to be unrelated to esr, but it 1215 - * really is needed only when esr is active. When we have a 1216 - * single link, the firmware will handle all this on its own. 1217 - * In multi-link scenarios, we can learn about the CSA from 1218 - * another link and this logic is too complex for the firmware 1219 - * to track. 1220 - * Since we want to de-activate the link that got a CSA, we 1221 - * need to tell the firmware not to send any frame on that link 1222 - * as the firmware may not be aware that link is under a CSA 1223 - * with mode=1 (no Tx allowed). 1224 - */ 1225 - if (chsw->block_tx && mvmvif->link[chsw->link_id]) 1226 - mvmvif->link[chsw->link_id]->csa_block_tx = true; 1227 - 1228 - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_CSA, selected); 1229 - mutex_unlock(&mvm->mutex); 1230 - 1231 - /* 1232 - * If we've not kept the link active that's doing the CSA 1233 - * then we don't need to do anything else, just return. 1234 - */ 1235 - if (selected != chsw->link_id) 1236 - return 0; 1237 - 1238 - mutex_lock(&mvm->mutex); 1239 - } 1240 - 1241 - ret = iwl_mvm_pre_channel_switch(mvm, vif, chsw); 1242 - mutex_unlock(&mvm->mutex); 1243 - 1244 - return ret; 1245 - } 1246 - 1247 - #define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ) 1248 - 1249 - static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw, 1250 - enum nl80211_iftype type) 1251 - { 1252 - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1253 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 1254 - struct iwl_mvm_vif *mvmvif; 1255 - int ret; 1256 - 1257 - IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n", 1258 - type); 1259 - 1260 - if (IS_ERR_OR_NULL(bss_vif) || 1261 - !(type == NL80211_IFTYPE_AP || 1262 - type == NL80211_IFTYPE_P2P_GO || 1263 - type == NL80211_IFTYPE_P2P_CLIENT)) 1264 - return; 1265 - 1266 - mvmvif = iwl_mvm_vif_from_mac80211(bss_vif); 1267 - ret = iwl_mvm_block_esr_sync(mvm, bss_vif, 1268 - IWL_MVM_ESR_BLOCKED_TMP_NON_BSS); 1269 - if (ret) 1270 - return; 1271 - 1272 - wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy, 1273 - &mvmvif->unblock_esr_tmp_non_bss_wk, 1274 - IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT); 1275 - } 1276 - 1277 1242 const struct ieee80211_ops iwl_mvm_mld_hw_ops = { 1278 1243 .tx = iwl_mvm_mac_tx, 1279 1244 .wake_tx_queue = iwl_mvm_mac_wake_tx_queue, ··· 1242 1377 .tx_last_beacon = iwl_mvm_tx_last_beacon, 1243 1378 1244 1379 .channel_switch = iwl_mvm_channel_switch, 1245 - .pre_channel_switch = iwl_mvm_mld_mac_pre_channel_switch, 1380 + .pre_channel_switch = iwl_mvm_mac_pre_channel_switch, 1246 1381 .post_channel_switch = iwl_mvm_post_channel_switch, 1247 1382 .abort_channel_switch = iwl_mvm_abort_channel_switch, 1248 1383 .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon, ··· 1283 1418 .change_sta_links = iwl_mvm_mld_change_sta_links, 1284 1419 .can_activate_links = iwl_mvm_mld_can_activate_links, 1285 1420 .can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm, 1286 - .prep_add_interface = iwl_mvm_mld_prep_add_interface, 1287 1421 };
-2
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
··· 852 852 853 853 iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta, link_id); 854 854 } 855 - kfree(mvm_sta->mpdu_counters); 856 - mvm_sta->mpdu_counters = NULL; 857 855 858 856 return ret; 859 857 }
+5 -131
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
··· 348 348 }; 349 349 350 350 /** 351 - * enum iwl_mvm_esr_state - defines reasons for which the EMLSR is exited or 352 - * blocked. 353 - * The low 16 bits are used for blocking reasons, and the 16 higher bits 354 - * are used for exit reasons. 355 - * For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit 356 - * reasons - use iwl_mvm_exit_esr(). 357 - * 358 - * Note: new reasons shall be added to HANDLE_ESR_REASONS as well (for logs) 359 - * 360 - * @IWL_MVM_ESR_BLOCKED_PREVENTION: Prevent EMLSR to avoid entering and exiting 361 - * in a loop. 362 - * @IWL_MVM_ESR_BLOCKED_WOWLAN: WOWLAN is preventing the enablement of EMLSR 363 - * @IWL_MVM_ESR_BLOCKED_TPT: block EMLSR when there is not enough traffic 364 - * @IWL_MVM_ESR_BLOCKED_FW: FW didn't recommended/forced exit from EMLSR 365 - * @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is 366 - * preventing EMLSR 367 - * @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR 368 - * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link 369 - * is preventing EMLSR. This is a temporary blocking that is set when there 370 - * is an indication that a non-BSS interface is to be added. 371 - * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons 372 - * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR 373 - * due to low RSSI. 374 - * @IWL_MVM_ESR_EXIT_COEX: link is deactivated/not allowed for EMLSR 375 - * due to BT Coex. 376 - * @IWL_MVM_ESR_EXIT_BANDWIDTH: Bandwidths of primary and secondry links 377 - * preventing the enablement of EMLSR 378 - * @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR 379 - * @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link 380 - */ 381 - enum iwl_mvm_esr_state { 382 - IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1, 383 - IWL_MVM_ESR_BLOCKED_WOWLAN = 0x2, 384 - IWL_MVM_ESR_BLOCKED_TPT = 0x4, 385 - IWL_MVM_ESR_BLOCKED_FW = 0x8, 386 - IWL_MVM_ESR_BLOCKED_NON_BSS = 0x10, 387 - IWL_MVM_ESR_BLOCKED_ROC = 0x20, 388 - IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40, 389 - IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000, 390 - IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000, 391 - IWL_MVM_ESR_EXIT_COEX = 0x40000, 392 - IWL_MVM_ESR_EXIT_BANDWIDTH = 0x80000, 393 - IWL_MVM_ESR_EXIT_CSA = 0x100000, 394 - IWL_MVM_ESR_EXIT_LINK_USAGE = 0x200000, 395 - }; 396 - 397 - #define IWL_MVM_BLOCK_ESR_REASONS 0xffff 398 - 399 - const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state); 400 - 401 - /** 402 - * struct iwl_mvm_esr_exit - details of the last exit from EMLSR mode. 403 - * @reason: The reason for the last exit from EMLSR. 404 - * &iwl_mvm_prevent_esr_reasons. Will be 0 before exiting EMLSR. 405 - * @ts: the time stamp of the last time we existed EMLSR. 406 - */ 407 - struct iwl_mvm_esr_exit { 408 - unsigned long ts; 409 - enum iwl_mvm_esr_state reason; 410 - }; 411 - 412 - /** 413 351 * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context 414 352 * @mvm: pointer back to the mvm struct 415 353 * @id: between 0 and 3 ··· 381 443 * @deflink: default link data for use in non-MLO 382 444 * @link: link data for each link in MLO 383 445 * @esr_active: indicates eSR mode is active 384 - * @esr_disable_reason: a bitmap of &enum iwl_mvm_esr_state 385 446 * @pm_enabled: indicates powersave is enabled 386 447 * @link_selection_res: bitmap of active links as it was decided in the last 387 448 * link selection. Valid only for a MLO vif after assoc. 0 if there wasn't ··· 388 451 * @link_selection_primary: primary link selected by link selection 389 452 * @primary_link: primary link in eSR. Valid only for an associated MLD vif, 390 453 * and in eSR mode. Valid only for a STA. 391 - * @last_esr_exit: Details of the last exit from EMLSR. 392 - * @exit_same_reason_count: The number of times we exited due to the specified 393 - * @last_esr_exit::reason, only counting exits due to 394 - * &IWL_MVM_ESR_PREVENT_REASONS. 395 - * @prevent_esr_done_wk: work that should be done when esr prevention ends. 396 - * @mlo_int_scan_wk: work for the internal MLO scan. 397 - * @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough. 398 - * @unblock_esr_tmp_non_bss_wk: work for removing the 399 - * IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR. 400 454 * @roc_activity: currently running ROC activity for this vif (or 401 455 * ROC_NUM_ACTIVITIES if no activity is running). 402 456 * @session_prot_connection_loss: the connection was lost due to session ··· 443 515 u8 authorized:1; 444 516 bool ps_disabled; 445 517 446 - u32 esr_disable_reason; 447 518 u32 ap_beacon_time; 448 519 bool bf_enabled; 449 520 bool ba_enabled; ··· 518 591 u16 link_selection_res; 519 592 u8 link_selection_primary; 520 593 u8 primary_link; 521 - struct iwl_mvm_esr_exit last_esr_exit; 522 - u8 exit_same_reason_count; 523 - struct wiphy_delayed_work prevent_esr_done_wk; 524 - struct wiphy_delayed_work mlo_int_scan_wk; 525 - struct wiphy_work unblock_esr_tpt_wk; 526 - struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk; 527 594 528 595 struct iwl_mvm_vif_link_info deflink; 529 596 struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS]; ··· 543 622 IWL_MVM_SCAN_REGULAR = BIT(0), 544 623 IWL_MVM_SCAN_SCHED = BIT(1), 545 624 IWL_MVM_SCAN_NETDETECT = BIT(2), 546 - IWL_MVM_SCAN_INT_MLO = BIT(3), 547 625 548 626 IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8), 549 627 IWL_MVM_SCAN_STOPPING_SCHED = BIT(9), ··· 555 635 IWL_MVM_SCAN_STOPPING_SCHED, 556 636 IWL_MVM_SCAN_NETDETECT_MASK = IWL_MVM_SCAN_NETDETECT | 557 637 IWL_MVM_SCAN_STOPPING_NETDETECT, 558 - IWL_MVM_SCAN_INT_MLO_MASK = IWL_MVM_SCAN_INT_MLO | 559 - IWL_MVM_SCAN_STOPPING_INT_MLO, 560 638 561 639 IWL_MVM_SCAN_STOPPING_MASK = 0xff << IWL_MVM_SCAN_STOPPING_SHIFT, 562 640 IWL_MVM_SCAN_MASK = 0xff, ··· 935 1017 /* For async rx handlers that require the wiphy lock */ 936 1018 struct wiphy_work async_handlers_wiphy_wk; 937 1019 938 - struct wiphy_work trig_link_selection_wk; 939 - 940 1020 struct work_struct roc_done_wk; 941 1021 942 1022 unsigned long init_status; ··· 1119 1203 u8 offload_tid; 1120 1204 #ifdef CONFIG_IWLWIFI_DEBUGFS 1121 1205 bool d3_wake_sysassert; 1122 - bool d3_test_active; 1123 - u32 d3_test_pme_ptr; 1124 - struct ieee80211_vif *keep_vif; 1125 1206 u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */ 1126 1207 #endif 1127 1208 #endif 1128 1209 1129 1210 wait_queue_head_t rx_sync_waitq; 1130 1211 1131 - /* BT-Coex - only one of those will be used */ 1132 - union { 1133 - struct iwl_bt_coex_prof_old_notif last_bt_notif; 1134 - struct iwl_bt_coex_profile_notif last_bt_wifi_loss; 1135 - }; 1212 + struct iwl_bt_coex_prof_old_notif last_bt_notif; 1136 1213 struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; 1137 1214 1138 1215 u8 bt_tx_prio; ··· 2008 2099 int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2009 2100 struct ieee80211_bss_conf *link_conf); 2010 2101 2011 - void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 2012 2102 u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif); 2013 - u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id); 2014 2103 2015 2104 struct iwl_mvm_link_sel_data { 2016 2105 u8 link_id; ··· 2018 2111 }; 2019 2112 2020 2113 #if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) 2021 - unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf); 2022 - bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, 2023 - const struct iwl_mvm_link_sel_data *a, 2024 - const struct iwl_mvm_link_sel_data *b); 2025 - 2026 - s8 iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif); 2027 - 2028 2114 extern const struct iwl_hcmd_arr iwl_mvm_groups[]; 2029 2115 extern const unsigned int iwl_mvm_groups_size; 2030 2116 #endif ··· 2101 2201 int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm); 2102 2202 void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm); 2103 2203 void iwl_mvm_scan_timeout_wk(struct work_struct *work); 2104 - int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 2105 2204 void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm, 2106 2205 struct iwl_rx_cmd_buffer *rxb); 2107 2206 ··· 2226 2327 int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm); 2227 2328 void iwl_mvm_rx_bt_coex_old_notif(struct iwl_mvm *mvm, 2228 2329 struct iwl_rx_cmd_buffer *rxb); 2229 - void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, 2230 - struct iwl_rx_cmd_buffer *rxb); 2231 2330 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2232 2331 enum ieee80211_rssi_event_data); 2233 2332 void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); ··· 2826 2929 int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw); 2827 2930 void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2828 2931 struct ieee80211_channel_switch *chsw); 2829 - int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm, 2830 - struct ieee80211_vif *vif, 2831 - struct ieee80211_channel_switch *chsw); 2932 + int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, 2933 + struct ieee80211_vif *vif, 2934 + struct ieee80211_channel_switch *chsw); 2935 + 2832 2936 void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw, 2833 2937 struct ieee80211_vif *vif, 2834 2938 struct ieee80211_bss_conf *link_conf); ··· 2886 2988 2887 2989 /* EMLSR */ 2888 2990 bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 2889 - void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2890 - enum iwl_mvm_esr_state reason, 2891 - u8 link_to_keep); 2892 - int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2893 - enum iwl_mvm_esr_state reason); 2894 - void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2895 - enum iwl_mvm_esr_state reason); 2896 - void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2897 - enum iwl_mvm_esr_state reason, 2898 - u8 link_to_keep); 2899 - s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, 2900 - const struct cfg80211_chan_def *chandef, 2901 - bool low); 2902 - void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, 2903 - struct ieee80211_vif *vif, 2904 - int link_id); 2905 - bool 2906 - iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, 2907 - struct ieee80211_vif *vif, 2908 - s32 link_rssi, 2909 - bool primary); 2910 - int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2911 - unsigned int link_id, bool active); 2912 - 2913 2991 void 2914 2992 iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm, 2915 2993 struct ieee80211_vif *vif,
-53
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
··· 143 143 ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); 144 144 } 145 145 146 - static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm, 147 - struct iwl_rx_cmd_buffer *rxb) 148 - { 149 - struct iwl_rx_packet *pkt = rxb_addr(rxb); 150 - struct iwl_esr_mode_notif *notif = (void *)pkt->data; 151 - struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm); 152 - 153 - /* FW recommendations is only for entering EMLSR */ 154 - if (IS_ERR_OR_NULL(vif) || iwl_mvm_vif_from_mac80211(vif)->esr_active) 155 - return; 156 - 157 - if (le32_to_cpu(notif->action) == ESR_RECOMMEND_ENTER) 158 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW); 159 - else 160 - iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW, 161 - iwl_mvm_get_primary_link(vif)); 162 - } 163 - 164 146 static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, 165 147 struct iwl_rx_cmd_buffer *rxb) 166 148 { ··· 327 345 RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_old_notif, 328 346 RX_HANDLER_ASYNC_LOCKED_WIPHY, 329 347 struct iwl_bt_coex_prof_old_notif), 330 - RX_HANDLER_GRP(BT_COEX_GROUP, PROFILE_NOTIF, iwl_mvm_rx_bt_coex_notif, 331 - RX_HANDLER_ASYNC_LOCKED_WIPHY, 332 - struct iwl_bt_coex_profile_notif), 333 348 RX_HANDLER_NO_SIZE(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, 334 349 RX_HANDLER_ASYNC_LOCKED), 335 350 RX_HANDLER_NO_SIZE(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, ··· 435 456 iwl_mvm_channel_switch_error_notif, 436 457 RX_HANDLER_ASYNC_UNLOCKED, 437 458 struct iwl_channel_switch_error_notif), 438 - 439 - RX_HANDLER_GRP(DATA_PATH_GROUP, ESR_MODE_NOTIF, 440 - iwl_mvm_rx_esr_mode_notif, 441 - RX_HANDLER_ASYNC_LOCKED_WIPHY, 442 - struct iwl_esr_mode_notif), 443 459 444 460 RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF, 445 461 iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED, ··· 635 661 HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), 636 662 HCMD_NAME(SCD_QUEUE_CONFIG_CMD), 637 663 HCMD_NAME(SEC_KEY_CMD), 638 - HCMD_NAME(ESR_MODE_NOTIF), 639 664 HCMD_NAME(MONITOR_NOTIF), 640 665 HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST), 641 666 HCMD_NAME(BEACON_FILTER_IN_NOTIF), ··· 1193 1220 .nic_stolen = iwl_mvm_mei_nic_stolen, 1194 1221 }; 1195 1222 1196 - static void iwl_mvm_find_link_selection_vif(void *_data, u8 *mac, 1197 - struct ieee80211_vif *vif) 1198 - { 1199 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1200 - 1201 - if (ieee80211_vif_is_mld(vif) && mvmvif->authorized) 1202 - iwl_mvm_select_links(mvmvif->mvm, vif); 1203 - } 1204 - 1205 - static void iwl_mvm_trig_link_selection(struct wiphy *wiphy, 1206 - struct wiphy_work *wk) 1207 - { 1208 - struct iwl_mvm *mvm = 1209 - container_of(wk, struct iwl_mvm, trig_link_selection_wk); 1210 - 1211 - mutex_lock(&mvm->mutex); 1212 - ieee80211_iterate_active_interfaces(mvm->hw, 1213 - IEEE80211_IFACE_ITER_NORMAL, 1214 - iwl_mvm_find_link_selection_vif, 1215 - NULL); 1216 - mutex_unlock(&mvm->mutex); 1217 - } 1218 - 1219 1223 static struct iwl_op_mode * 1220 1224 iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, 1221 1225 const struct iwl_fw *fw, struct dentry *dbgfs_dir) ··· 1360 1410 1361 1411 wiphy_work_init(&mvm->async_handlers_wiphy_wk, 1362 1412 iwl_mvm_async_handlers_wiphy_wk); 1363 - 1364 - wiphy_work_init(&mvm->trig_link_selection_wk, 1365 - iwl_mvm_trig_link_selection); 1366 1413 1367 1414 init_waitqueue_head(&mvm->rx_sync_waitq); 1368 1415
-133
drivers/net/wireless/intel/iwlwifi/mvm/rx.c
··· 563 563 int thold = bss_conf->cqm_rssi_thold; 564 564 int hyst = bss_conf->cqm_rssi_hyst; 565 565 int last_event; 566 - s8 exit_esr_thresh; 567 566 568 567 if (sig == 0) { 569 568 IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n"); ··· 618 619 sig, 619 620 GFP_KERNEL); 620 621 } 621 - 622 - /* ESR recalculation */ 623 - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif)) 624 - return; 625 - 626 - /* We're not in EMLSR and our signal is bad, try to switch link maybe */ 627 - if (sig < IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH && !mvmvif->esr_active) { 628 - iwl_mvm_int_mlo_scan(mvm, vif); 629 - return; 630 - } 631 - 632 - /* We are in EMLSR, check if we need to exit */ 633 - exit_esr_thresh = 634 - iwl_mvm_get_esr_rssi_thresh(mvm, 635 - &bss_conf->chanreq.oper, 636 - true); 637 - 638 - if (sig < exit_esr_thresh) 639 - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_LOW_RSSI, 640 - iwl_mvm_get_other_link(vif, 641 - bss_conf->link_id)); 642 622 } 643 623 644 624 static void iwl_mvm_stat_iterator(void *_data, u8 *mac, ··· 892 914 link_info->beacon_stats.avg_signal = 893 915 -le32_to_cpu(link_stats->beacon_average_energy); 894 916 895 - if (link_info->phy_ctxt && 896 - link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ) 897 - iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); 898 - 899 917 /* make sure that beacon statistics don't go backwards with TCM 900 918 * request to clear statistics 901 919 */ ··· 930 956 } 931 957 } 932 958 933 - #define SEC_LINK_MIN_PERC 10 934 - #define SEC_LINK_MIN_TX 3000 935 - #define SEC_LINK_MIN_RX 400 936 - 937 - /* Accept a ~20% short window to avoid issues due to jitter */ 938 - #define IWL_MVM_TPT_MIN_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ * 4 / 5) 939 - 940 - static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm) 941 - { 942 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 943 - struct iwl_mvm_vif *mvmvif; 944 - struct iwl_mvm_sta *mvmsta; 945 - unsigned long total_tx = 0, total_rx = 0; 946 - unsigned long sec_link_tx = 0, sec_link_rx = 0; 947 - u8 sec_link_tx_perc, sec_link_rx_perc; 948 - u8 sec_link; 949 - bool skip = false; 950 - 951 - lockdep_assert_held(&mvm->mutex); 952 - 953 - if (IS_ERR_OR_NULL(bss_vif)) 954 - return; 955 - 956 - mvmvif = iwl_mvm_vif_from_mac80211(bss_vif); 957 - 958 - if (!mvmvif->esr_active || !mvmvif->ap_sta) 959 - return; 960 - 961 - mvmsta = iwl_mvm_sta_from_mac80211(mvmvif->ap_sta); 962 - /* We only count for the AP sta in a MLO connection */ 963 - if (!mvmsta->mpdu_counters) 964 - return; 965 - 966 - /* Get the FW ID of the secondary link */ 967 - sec_link = iwl_mvm_get_other_link(bss_vif, 968 - iwl_mvm_get_primary_link(bss_vif)); 969 - if (WARN_ON(!mvmvif->link[sec_link])) 970 - return; 971 - sec_link = mvmvif->link[sec_link]->fw_link_id; 972 - 973 - /* Sum up RX and TX MPDUs from the different queues/links */ 974 - for (int q = 0; q < mvm->trans->info.num_rxqs; q++) { 975 - spin_lock_bh(&mvmsta->mpdu_counters[q].lock); 976 - 977 - /* The link IDs that doesn't exist will contain 0 */ 978 - for (int link = 0; link < IWL_FW_MAX_LINK_ID; link++) { 979 - total_tx += mvmsta->mpdu_counters[q].per_link[link].tx; 980 - total_rx += mvmsta->mpdu_counters[q].per_link[link].rx; 981 - } 982 - 983 - sec_link_tx += mvmsta->mpdu_counters[q].per_link[sec_link].tx; 984 - sec_link_rx += mvmsta->mpdu_counters[q].per_link[sec_link].rx; 985 - 986 - /* 987 - * In EMLSR we have statistics every 5 seconds, so we can reset 988 - * the counters upon every statistics notification. 989 - * The FW sends the notification regularly, but it will be 990 - * misaligned at the start. Skipping the measurement if it is 991 - * short will synchronize us. 992 - */ 993 - if (jiffies - mvmsta->mpdu_counters[q].window_start < 994 - IWL_MVM_TPT_MIN_COUNT_WINDOW) 995 - skip = true; 996 - mvmsta->mpdu_counters[q].window_start = jiffies; 997 - memset(mvmsta->mpdu_counters[q].per_link, 0, 998 - sizeof(mvmsta->mpdu_counters[q].per_link)); 999 - 1000 - spin_unlock_bh(&mvmsta->mpdu_counters[q].lock); 1001 - } 1002 - 1003 - if (skip) { 1004 - IWL_DEBUG_INFO(mvm, "MPDU statistics window was short\n"); 1005 - return; 1006 - } 1007 - 1008 - IWL_DEBUG_INFO(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n", 1009 - total_tx, total_rx); 1010 - 1011 - /* If we don't have enough MPDUs - exit EMLSR */ 1012 - if (total_tx < IWL_MVM_ENTER_ESR_TPT_THRESH && 1013 - total_rx < IWL_MVM_ENTER_ESR_TPT_THRESH) { 1014 - iwl_mvm_block_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_TPT, 1015 - iwl_mvm_get_primary_link(bss_vif)); 1016 - return; 1017 - } 1018 - 1019 - IWL_DEBUG_INFO(mvm, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n", 1020 - sec_link, sec_link_tx, sec_link_rx); 1021 - 1022 - /* Calculate the percentage of the secondary link TX/RX */ 1023 - sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0; 1024 - sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0; 1025 - 1026 - /* 1027 - * The TX/RX percentage is checked only if it exceeds the required 1028 - * minimum. In addition, RX is checked only if the TX check failed. 1029 - */ 1030 - if ((total_tx > SEC_LINK_MIN_TX && 1031 - sec_link_tx_perc < SEC_LINK_MIN_PERC) || 1032 - (total_rx > SEC_LINK_MIN_RX && 1033 - sec_link_rx_perc < SEC_LINK_MIN_PERC)) 1034 - iwl_mvm_exit_esr(mvm, bss_vif, IWL_MVM_ESR_EXIT_LINK_USAGE, 1035 - iwl_mvm_get_primary_link(bss_vif)); 1036 - } 1037 - 1038 959 void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm, 1039 960 struct iwl_rx_cmd_buffer *rxb) 1040 961 { ··· 957 1088 ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter, 958 1089 average_energy); 959 1090 iwl_mvm_handle_per_phy_stats(mvm, stats->per_phy); 960 - 961 - iwl_mvm_update_esr_mode_tpt(mvm); 962 1091 } 963 1092 964 1093 void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
+10 -13
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
··· 332 332 struct ieee80211_key_conf *key; 333 333 u32 len = le16_to_cpu(desc->mpdu_len); 334 334 const u8 *frame = (void *)hdr; 335 + const u8 *mmie; 335 336 336 337 if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE) 337 338 return 0; ··· 376 375 goto report; 377 376 } 378 377 379 - if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2) 378 + if (len < key->icv_len) 380 379 goto report; 381 380 382 381 /* get the real key ID */ 383 - keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2]; 382 + mmie = frame + (len - key->icv_len); 383 + 384 + /* the position of the key_id in ieee80211_mmie_16 is the same */ 385 + keyid = le16_to_cpu(((const struct ieee80211_mmie *) mmie)->key_id); 386 + 384 387 /* and if that's the other key, look it up */ 385 388 if (keyid != key->keyidx) { 386 389 /* ··· 2104 2099 struct ieee80211_sta *sta = NULL; 2105 2100 struct sk_buff *skb; 2106 2101 u8 crypt_len = 0; 2107 - u8 sta_id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID); 2108 2102 size_t desc_size; 2109 2103 struct iwl_mvm_rx_phy_data phy_data = {}; 2110 2104 u32 format; ··· 2250 2246 rcu_read_lock(); 2251 2247 2252 2248 if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) { 2249 + u8 sta_id = le32_get_bits(desc->status, 2250 + IWL_RX_MPDU_STATUS_STA_ID); 2251 + 2253 2252 if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) { 2254 2253 struct ieee80211_link_sta *link_sta; 2255 2254 ··· 2379 2372 u32 reorder_data = le32_to_cpu(desc->reorder_data); 2380 2373 2381 2374 iwl_mvm_agg_rx_received(mvm, reorder_data, baid); 2382 - } 2383 - 2384 - if (ieee80211_is_data(hdr->frame_control)) { 2385 - u8 sub_frame_idx = desc->amsdu_info & 2386 - IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK; 2387 - 2388 - /* 0 means not an A-MSDU, and 1 means a new A-MSDU */ 2389 - if (!sub_frame_idx || sub_frame_idx == 1) 2390 - iwl_mvm_count_mpdu(mvmsta, sta_id, 1, false, 2391 - queue); 2392 2375 } 2393 2376 } 2394 2377
-101
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
··· 1392 1392 { 1393 1393 if (type == IWL_MVM_SCAN_REGULAR) 1394 1394 return IWL_SCAN_PRIORITY_EXT_6; 1395 - if (type == IWL_MVM_SCAN_INT_MLO) 1396 - return IWL_SCAN_PRIORITY_EXT_4; 1397 1395 1398 1396 return IWL_SCAN_PRIORITY_EXT_2; 1399 1397 } ··· 3218 3220 struct iwl_umac_scan_complete *notif = (void *)pkt->data; 3219 3221 u32 uid = __le32_to_cpu(notif->uid); 3220 3222 bool aborted = (notif->status == IWL_SCAN_OFFLOAD_ABORTED); 3221 - bool select_links = false; 3222 3223 3223 3224 mvm->mei_scan_filter.is_mei_limited_scan = false; 3224 3225 ··· 3264 3267 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { 3265 3268 ieee80211_sched_scan_stopped(mvm->hw); 3266 3269 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 3267 - } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_INT_MLO) { 3268 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan completed\n"); 3269 - /* 3270 - * Other scan types won't necessarily scan for the MLD links channels. 3271 - * Therefore, only select links after successful internal scan. 3272 - */ 3273 - select_links = notif->status == IWL_SCAN_OFFLOAD_COMPLETED; 3274 3270 } 3275 3271 3276 3272 mvm->scan_status &= ~mvm->scan_uid_status[uid]; ··· 3276 3286 mvm->last_ebs_successful = false; 3277 3287 3278 3288 mvm->scan_uid_status[uid] = 0; 3279 - 3280 - if (select_links) 3281 - wiphy_work_queue(mvm->hw->wiphy, &mvm->trig_link_selection_wk); 3282 3289 } 3283 3290 3284 3291 void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, ··· 3470 3483 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 3471 3484 mvm->scan_uid_status[uid] = 0; 3472 3485 } 3473 - uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_INT_MLO); 3474 - if (uid >= 0) { 3475 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan aborted\n"); 3476 - mvm->scan_uid_status[uid] = 0; 3477 - } 3478 3486 3479 3487 uid = iwl_mvm_scan_uid_by_status(mvm, 3480 3488 IWL_MVM_SCAN_STOPPING_REGULAR); ··· 3563 3581 } 3564 3582 3565 3583 return ret; 3566 - } 3567 - 3568 - static int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm, 3569 - struct ieee80211_vif *vif, 3570 - struct ieee80211_channel **channels, 3571 - size_t n_channels) 3572 - { 3573 - struct cfg80211_scan_request *req = NULL; 3574 - struct ieee80211_scan_ies ies = {}; 3575 - size_t size, i; 3576 - int ret; 3577 - 3578 - lockdep_assert_held(&mvm->mutex); 3579 - 3580 - IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n", 3581 - n_channels); 3582 - 3583 - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) || 3584 - hweight16(vif->valid_links) == 1) 3585 - return -EINVAL; 3586 - 3587 - size = struct_size(req, channels, n_channels); 3588 - req = kzalloc(size, GFP_KERNEL); 3589 - if (!req) 3590 - return -ENOMEM; 3591 - 3592 - /* set the requested channels */ 3593 - for (i = 0; i < n_channels; i++) 3594 - req->channels[i] = channels[i]; 3595 - 3596 - req->n_channels = n_channels; 3597 - 3598 - /* set the rates */ 3599 - for (i = 0; i < NUM_NL80211_BANDS; i++) 3600 - if (mvm->hw->wiphy->bands[i]) 3601 - req->rates[i] = 3602 - (1 << mvm->hw->wiphy->bands[i]->n_bitrates) - 1; 3603 - 3604 - req->wdev = ieee80211_vif_to_wdev(vif); 3605 - req->wiphy = mvm->hw->wiphy; 3606 - req->scan_start = jiffies; 3607 - req->tsf_report_link_id = -1; 3608 - 3609 - ret = _iwl_mvm_single_scan_start(mvm, vif, req, &ies, 3610 - IWL_MVM_SCAN_INT_MLO); 3611 - kfree(req); 3612 - 3613 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan: ret=%d\n", ret); 3614 - return ret; 3615 - } 3616 - 3617 - int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 3618 - { 3619 - struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS]; 3620 - unsigned long usable_links = ieee80211_vif_usable_links(vif); 3621 - size_t n_channels = 0; 3622 - u8 link_id; 3623 - 3624 - lockdep_assert_held(&mvm->mutex); 3625 - 3626 - if (mvm->scan_status & IWL_MVM_SCAN_INT_MLO) { 3627 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan is already running\n"); 3628 - return -EBUSY; 3629 - } 3630 - 3631 - rcu_read_lock(); 3632 - 3633 - for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 3634 - struct ieee80211_bss_conf *link_conf = 3635 - rcu_dereference(vif->link_conf[link_id]); 3636 - 3637 - if (WARN_ON_ONCE(!link_conf)) 3638 - continue; 3639 - 3640 - channels[n_channels++] = link_conf->chanreq.oper.chan; 3641 - } 3642 - 3643 - rcu_read_unlock(); 3644 - 3645 - if (!n_channels) 3646 - return -EINVAL; 3647 - 3648 - return iwl_mvm_int_mlo_scan_start(mvm, vif, channels, n_channels); 3649 3584 } 3650 3585 3651 3586 static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm,
-89
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
··· 1835 1835 1836 1836 iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant); 1837 1837 1838 - /* MPDUs are counted only when EMLSR is possible */ 1839 - if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && 1840 - !sta->tdls && ieee80211_vif_is_mld(vif)) { 1841 - mvm_sta->mpdu_counters = 1842 - kcalloc(mvm->trans->info.num_rxqs, 1843 - sizeof(*mvm_sta->mpdu_counters), 1844 - GFP_KERNEL); 1845 - if (mvm_sta->mpdu_counters) 1846 - for (int q = 0; q < mvm->trans->info.num_rxqs; q++) 1847 - spin_lock_init(&mvm_sta->mpdu_counters[q].lock); 1848 - } 1849 - 1850 1838 return 0; 1851 1839 } 1852 1840 ··· 4315 4327 &cancel_channel_switch_cmd); 4316 4328 if (ret) 4317 4329 IWL_ERR(mvm, "Failed to cancel the channel switch\n"); 4318 - } 4319 - 4320 - static int iwl_mvm_fw_sta_id_to_fw_link_id(struct iwl_mvm_vif *mvmvif, 4321 - u8 fw_sta_id) 4322 - { 4323 - struct ieee80211_link_sta *link_sta = 4324 - rcu_dereference(mvmvif->mvm->fw_id_to_link_sta[fw_sta_id]); 4325 - struct iwl_mvm_vif_link_info *link; 4326 - 4327 - if (WARN_ON_ONCE(!link_sta)) 4328 - return -EINVAL; 4329 - 4330 - link = mvmvif->link[link_sta->link_id]; 4331 - 4332 - if (WARN_ON_ONCE(!link)) 4333 - return -EINVAL; 4334 - 4335 - return link->fw_link_id; 4336 - } 4337 - 4338 - #define IWL_MVM_TPT_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ) 4339 - 4340 - void iwl_mvm_count_mpdu(struct iwl_mvm_sta *mvm_sta, u8 fw_sta_id, u32 count, 4341 - bool tx, int queue) 4342 - { 4343 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvm_sta->vif); 4344 - struct iwl_mvm *mvm = mvmvif->mvm; 4345 - struct iwl_mvm_tpt_counter *queue_counter; 4346 - struct iwl_mvm_mpdu_counter *link_counter; 4347 - u32 total_mpdus = 0; 4348 - int fw_link_id; 4349 - 4350 - /* Count only for a BSS sta, and only when EMLSR is possible */ 4351 - if (!mvm_sta->mpdu_counters) 4352 - return; 4353 - 4354 - /* Map sta id to link id */ 4355 - fw_link_id = iwl_mvm_fw_sta_id_to_fw_link_id(mvmvif, fw_sta_id); 4356 - if (fw_link_id < 0) 4357 - return; 4358 - 4359 - queue_counter = &mvm_sta->mpdu_counters[queue]; 4360 - link_counter = &queue_counter->per_link[fw_link_id]; 4361 - 4362 - spin_lock_bh(&queue_counter->lock); 4363 - 4364 - if (tx) 4365 - link_counter->tx += count; 4366 - else 4367 - link_counter->rx += count; 4368 - 4369 - /* 4370 - * When not in EMLSR, the window and the decision to enter EMLSR are 4371 - * handled during counting, when in EMLSR - in the statistics flow 4372 - */ 4373 - if (mvmvif->esr_active) 4374 - goto out; 4375 - 4376 - if (time_is_before_jiffies(queue_counter->window_start + 4377 - IWL_MVM_TPT_COUNT_WINDOW)) { 4378 - memset(queue_counter->per_link, 0, 4379 - sizeof(queue_counter->per_link)); 4380 - queue_counter->window_start = jiffies; 4381 - 4382 - IWL_DEBUG_INFO(mvm, "MPDU counters are cleared\n"); 4383 - } 4384 - 4385 - for (int i = 0; i < IWL_FW_MAX_LINK_ID; i++) 4386 - total_mpdus += tx ? queue_counter->per_link[i].tx : 4387 - queue_counter->per_link[i].rx; 4388 - 4389 - if (total_mpdus > IWL_MVM_ENTER_ESR_TPT_THRESH) 4390 - wiphy_work_queue(mvmvif->mvm->hw->wiphy, 4391 - &mvmvif->unblock_esr_tpt_wk); 4392 - 4393 - out: 4394 - spin_unlock_bh(&queue_counter->lock); 4395 4330 }
-24
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
··· 344 344 u8 avg_energy; 345 345 }; 346 346 347 - struct iwl_mvm_mpdu_counter { 348 - u32 tx; 349 - u32 rx; 350 - }; 351 - 352 - /** 353 - * struct iwl_mvm_tpt_counter - per-queue MPDU counter 354 - * 355 - * @lock: Needed to protect the counters when modified from statistics. 356 - * @per_link: per-link counters. 357 - * @window_start: timestamp of the counting-window start 358 - */ 359 - struct iwl_mvm_tpt_counter { 360 - spinlock_t lock; 361 - struct iwl_mvm_mpdu_counter per_link[IWL_FW_MAX_LINK_ID]; 362 - unsigned long window_start; 363 - } ____cacheline_aligned_in_smp; 364 - 365 347 /** 366 348 * struct iwl_mvm_sta - representation of a station in the driver 367 349 * @vif: the interface the station belongs to ··· 391 409 * @link: per link sta entries. For non-MLO only link[0] holds data. For MLO, 392 410 * link[0] points to deflink and link[link_id] is allocated when new link 393 411 * sta is added. 394 - * @mpdu_counters: RX/TX MPDUs counters for each queue. 395 412 * 396 413 * When mac80211 creates a station it reserves some space (hw->sta_data_size) 397 414 * in the structure for use by driver. This structure is placed in that ··· 430 449 431 450 struct iwl_mvm_link_sta deflink; 432 451 struct iwl_mvm_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; 433 - 434 - struct iwl_mvm_tpt_counter *mpdu_counters; 435 452 }; 436 453 437 454 u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data); ··· 511 532 512 533 void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm, 513 534 struct iwl_rx_cmd_buffer *rxb); 514 - 515 - void iwl_mvm_count_mpdu(struct iwl_mvm_sta *mvm_sta, u8 fw_sta_id, u32 count, 516 - bool tx, int queue); 517 535 518 536 /* AMPDU */ 519 537 int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
··· 1 - iwlmvm-tests-y += module.o links.o hcmd.o 1 + iwlmvm-tests-y += module.o hcmd.o 2 2 3 3 obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmvm-tests.o
-433
drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * KUnit tests for channel helper functions 4 - * 5 - * Copyright (C) 2024 Intel Corporation 6 - */ 7 - #include <net/mac80211.h> 8 - #include "../mvm.h" 9 - #include <kunit/test.h> 10 - 11 - MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 12 - 13 - static struct wiphy wiphy = { 14 - .mtx = __MUTEX_INITIALIZER(wiphy.mtx), 15 - }; 16 - 17 - static struct ieee80211_hw hw = { 18 - .wiphy = &wiphy, 19 - }; 20 - 21 - static struct ieee80211_channel chan_5ghz = { 22 - .band = NL80211_BAND_5GHZ, 23 - }; 24 - 25 - static struct ieee80211_channel chan_6ghz = { 26 - .band = NL80211_BAND_6GHZ, 27 - }; 28 - 29 - static struct ieee80211_channel chan_2ghz = { 30 - .band = NL80211_BAND_2GHZ, 31 - }; 32 - 33 - static struct cfg80211_chan_def chandef_a = {}; 34 - 35 - static struct cfg80211_chan_def chandef_b = {}; 36 - 37 - static struct iwl_mvm_phy_ctxt ctx = {}; 38 - 39 - static struct iwl_mvm_vif_link_info mvm_link = { 40 - .phy_ctxt = &ctx, 41 - .active = true 42 - }; 43 - 44 - static struct cfg80211_bss bss = {}; 45 - 46 - static struct ieee80211_bss_conf link_conf = {.bss = &bss}; 47 - 48 - static const struct iwl_fw_cmd_version entry = { 49 - .group = LEGACY_GROUP, 50 - .cmd = BT_PROFILE_NOTIFICATION, 51 - .notif_ver = 4 52 - }; 53 - 54 - static struct iwl_fw fw = { 55 - .ucode_capa = { 56 - .n_cmd_versions = 1, 57 - .cmd_versions = &entry, 58 - }, 59 - }; 60 - 61 - static struct iwl_mvm mvm = { 62 - .hw = &hw, 63 - .fw = &fw, 64 - }; 65 - 66 - static const struct link_grading_case { 67 - const char *desc; 68 - const struct cfg80211_chan_def chandef; 69 - s32 signal; 70 - s16 channel_util; 71 - int chan_load_by_us; 72 - unsigned int grade; 73 - } link_grading_cases[] = { 74 - { 75 - .desc = "UHB, RSSI below range, no factors", 76 - .chandef = { 77 - .chan = &chan_6ghz, 78 - .width = NL80211_CHAN_WIDTH_20, 79 - }, 80 - .signal = -100, 81 - .grade = 177, 82 - }, 83 - { 84 - .desc = "LB, RSSI in range, no factors", 85 - .chandef = { 86 - .chan = &chan_2ghz, 87 - .width = NL80211_CHAN_WIDTH_20, 88 - }, 89 - .signal = -84, 90 - .grade = 344, 91 - }, 92 - { 93 - .desc = "HB, RSSI above range, no factors", 94 - .chandef = { 95 - .chan = &chan_5ghz, 96 - .width = NL80211_CHAN_WIDTH_20, 97 - }, 98 - .signal = -50, 99 - .grade = 3442, 100 - }, 101 - { 102 - .desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor", 103 - .chandef = { 104 - .chan = &chan_5ghz, 105 - .width = NL80211_CHAN_WIDTH_20, 106 - }, 107 - .signal = -66, 108 - .channel_util = 51, 109 - .grade = 1836, 110 - }, 111 - { 112 - .desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor", 113 - .chandef = { 114 - .chan = &chan_2ghz, 115 - .width = NL80211_CHAN_WIDTH_20, 116 - }, 117 - .signal = -61, 118 - .channel_util = 51, 119 - .chan_load_by_us = 10, 120 - .grade = 2061, 121 - }, 122 - { 123 - .desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor", 124 - .chandef = { 125 - .chan = &chan_6ghz, 126 - .width = NL80211_CHAN_WIDTH_20, 127 - }, 128 - .signal = -66, 129 - .channel_util = 102, 130 - .chan_load_by_us = 50, 131 - .grade = 1552, 132 - }, 133 - { .desc = "HB, 80 MHz, no channel load factor, punctured percentage 0", 134 - .chandef = { 135 - .chan = &chan_5ghz, 136 - .width = NL80211_CHAN_WIDTH_80, 137 - .punctured = 0x0000 138 - }, 139 - .signal = -72, 140 - .grade = 1750, 141 - }, 142 - { .desc = "HB, 160 MHz, no channel load factor, punctured percentage 25", 143 - .chandef = { 144 - .chan = &chan_5ghz, 145 - .width = NL80211_CHAN_WIDTH_160, 146 - .punctured = 0x3 147 - }, 148 - .signal = -72, 149 - .grade = 1312, 150 - }, 151 - { .desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)", 152 - .chandef = { 153 - .chan = &chan_6ghz, 154 - .width = NL80211_CHAN_WIDTH_320, 155 - .punctured = 0x3 156 - }, 157 - .signal = -72, 158 - .grade = 1806, 159 - }, 160 - { .desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25", 161 - .chandef = { 162 - .chan = &chan_5ghz, 163 - .width = NL80211_CHAN_WIDTH_160, 164 - .punctured = 0x3 165 - }, 166 - .channel_util = 51, 167 - .chan_load_by_us = 10, 168 - .signal = -72, 169 - .grade = 1179, 170 - }, 171 - }; 172 - 173 - KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc) 174 - 175 - static void setup_link_conf(struct kunit *test) 176 - { 177 - const struct link_grading_case *params = test->param_value; 178 - size_t vif_size = sizeof(struct ieee80211_vif) + 179 - sizeof(struct iwl_mvm_vif); 180 - struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL); 181 - struct ieee80211_bss_load_elem *bss_load; 182 - struct element *element; 183 - size_t ies_size = sizeof(struct cfg80211_bss_ies) + sizeof(*bss_load) + sizeof(element); 184 - struct cfg80211_bss_ies *ies; 185 - struct iwl_mvm_vif *mvmvif; 186 - 187 - KUNIT_ASSERT_NOT_NULL(test, vif); 188 - 189 - mvmvif = iwl_mvm_vif_from_mac80211(vif); 190 - if (params->chan_load_by_us > 0) { 191 - ctx.channel_load_by_us = params->chan_load_by_us; 192 - mvmvif->link[0] = &mvm_link; 193 - } 194 - 195 - link_conf.vif = vif; 196 - link_conf.chanreq.oper = params->chandef; 197 - bss.signal = DBM_TO_MBM(params->signal); 198 - 199 - ies = kunit_kzalloc(test, ies_size, GFP_KERNEL); 200 - KUNIT_ASSERT_NOT_NULL(test, ies); 201 - ies->len = sizeof(*bss_load) + sizeof(struct element); 202 - 203 - element = (void *)ies->data; 204 - element->datalen = sizeof(*bss_load); 205 - element->id = 11; 206 - 207 - bss_load = (void *)element->data; 208 - bss_load->channel_util = params->channel_util; 209 - 210 - rcu_assign_pointer(bss.ies, ies); 211 - rcu_assign_pointer(bss.beacon_ies, ies); 212 - } 213 - 214 - static void test_link_grading(struct kunit *test) 215 - { 216 - const struct link_grading_case *params = test->param_value; 217 - unsigned int ret; 218 - 219 - setup_link_conf(test); 220 - 221 - rcu_read_lock(); 222 - ret = iwl_mvm_get_link_grade(&link_conf); 223 - rcu_read_unlock(); 224 - 225 - KUNIT_EXPECT_EQ(test, ret, params->grade); 226 - 227 - kunit_kfree(test, link_conf.vif); 228 - RCU_INIT_POINTER(bss.ies, NULL); 229 - } 230 - 231 - static struct kunit_case link_grading_test_cases[] = { 232 - KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params), 233 - {} 234 - }; 235 - 236 - static struct kunit_suite link_grading = { 237 - .name = "iwlmvm-link-grading", 238 - .test_cases = link_grading_test_cases, 239 - }; 240 - 241 - kunit_test_suite(link_grading); 242 - 243 - static const struct valid_link_pair_case { 244 - const char *desc; 245 - bool bt; 246 - struct ieee80211_channel *chan_a; 247 - struct ieee80211_channel *chan_b; 248 - enum nl80211_chan_width cw_a; 249 - enum nl80211_chan_width cw_b; 250 - s32 sig_a; 251 - s32 sig_b; 252 - bool csa_a; 253 - bool valid; 254 - } valid_link_pair_cases[] = { 255 - { 256 - .desc = "HB + UHB, valid.", 257 - .chan_a = &chan_6ghz, 258 - .chan_b = &chan_5ghz, 259 - .valid = true, 260 - }, 261 - { 262 - .desc = "LB + HB, no BT.", 263 - .chan_a = &chan_2ghz, 264 - .chan_b = &chan_5ghz, 265 - .valid = true, 266 - }, 267 - { 268 - .desc = "LB + HB, with BT.", 269 - .bt = true, 270 - .chan_a = &chan_2ghz, 271 - .chan_b = &chan_5ghz, 272 - .valid = false, 273 - }, 274 - { 275 - .desc = "Same band", 276 - .chan_a = &chan_2ghz, 277 - .chan_b = &chan_2ghz, 278 - .valid = false, 279 - }, 280 - { 281 - .desc = "RSSI: LB, 20 MHz, low", 282 - .chan_a = &chan_2ghz, 283 - .cw_a = NL80211_CHAN_WIDTH_20, 284 - .sig_a = -68, 285 - .chan_b = &chan_5ghz, 286 - .valid = false, 287 - }, 288 - { 289 - .desc = "RSSI: UHB, 20 MHz, high", 290 - .chan_a = &chan_6ghz, 291 - .cw_a = NL80211_CHAN_WIDTH_20, 292 - .sig_a = -66, 293 - .chan_b = &chan_5ghz, 294 - .cw_b = NL80211_CHAN_WIDTH_20, 295 - .valid = true, 296 - }, 297 - { 298 - .desc = "RSSI: UHB, 40 MHz, low", 299 - .chan_a = &chan_6ghz, 300 - .cw_a = NL80211_CHAN_WIDTH_40, 301 - .sig_a = -65, 302 - .chan_b = &chan_5ghz, 303 - .cw_b = NL80211_CHAN_WIDTH_40, 304 - .valid = false, 305 - }, 306 - { 307 - .desc = "RSSI: UHB, 40 MHz, high", 308 - .chan_a = &chan_6ghz, 309 - .cw_a = NL80211_CHAN_WIDTH_40, 310 - .sig_a = -63, 311 - .chan_b = &chan_5ghz, 312 - .cw_b = NL80211_CHAN_WIDTH_40, 313 - .valid = true, 314 - }, 315 - { 316 - .desc = "RSSI: UHB, 80 MHz, low", 317 - .chan_a = &chan_6ghz, 318 - .cw_a = NL80211_CHAN_WIDTH_80, 319 - .sig_a = -62, 320 - .chan_b = &chan_5ghz, 321 - .cw_b = NL80211_CHAN_WIDTH_80, 322 - .valid = false, 323 - }, 324 - { 325 - .desc = "RSSI: UHB, 80 MHz, high", 326 - .chan_a = &chan_6ghz, 327 - .cw_a = NL80211_CHAN_WIDTH_80, 328 - .sig_a = -60, 329 - .chan_b = &chan_5ghz, 330 - .cw_b = NL80211_CHAN_WIDTH_80, 331 - .valid = true, 332 - }, 333 - { 334 - .desc = "RSSI: UHB, 160 MHz, low", 335 - .chan_a = &chan_6ghz, 336 - .cw_a = NL80211_CHAN_WIDTH_160, 337 - .sig_a = -59, 338 - .chan_b = &chan_5ghz, 339 - .cw_b = NL80211_CHAN_WIDTH_160, 340 - .valid = false, 341 - }, 342 - { 343 - .desc = "RSSI: HB, 160 MHz, high", 344 - .chan_a = &chan_6ghz, 345 - .cw_a = NL80211_CHAN_WIDTH_160, 346 - .sig_a = -5, 347 - .chan_b = &chan_5ghz, 348 - .cw_b = NL80211_CHAN_WIDTH_160, 349 - .valid = true, 350 - }, 351 - { 352 - .desc = "CSA active", 353 - .chan_a = &chan_6ghz, 354 - .cw_a = NL80211_CHAN_WIDTH_160, 355 - .sig_a = -5, 356 - .chan_b = &chan_5ghz, 357 - .cw_b = NL80211_CHAN_WIDTH_160, 358 - .valid = false, 359 - /* same as previous entry with valid=true except for CSA */ 360 - .csa_a = true, 361 - }, 362 - }; 363 - 364 - KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc) 365 - 366 - static void test_valid_link_pair(struct kunit *test) 367 - { 368 - const struct valid_link_pair_case *params = test->param_value; 369 - size_t vif_size = sizeof(struct ieee80211_vif) + 370 - sizeof(struct iwl_mvm_vif); 371 - struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL); 372 - struct iwl_trans *trans = kunit_kzalloc(test, sizeof(struct iwl_trans), 373 - GFP_KERNEL); 374 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 375 - struct iwl_mvm_link_sel_data link_a = { 376 - .chandef = &chandef_a, 377 - .link_id = 1, 378 - .signal = params->sig_a, 379 - }; 380 - struct iwl_mvm_link_sel_data link_b = { 381 - .chandef = &chandef_b, 382 - .link_id = 5, 383 - .signal = params->sig_b, 384 - }; 385 - struct ieee80211_bss_conf *conf; 386 - bool result; 387 - 388 - KUNIT_ASSERT_NOT_NULL(test, vif); 389 - KUNIT_ASSERT_NOT_NULL(test, trans); 390 - 391 - chandef_a.chan = params->chan_a; 392 - chandef_b.chan = params->chan_b; 393 - 394 - chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20; 395 - chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20; 396 - 397 - mvm.trans = trans; 398 - 399 - mvm.last_bt_notif.wifi_loss_low_rssi = params->bt; 400 - mvmvif->mvm = &mvm; 401 - 402 - conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL); 403 - KUNIT_ASSERT_NOT_NULL(test, conf); 404 - conf->chanreq.oper = chandef_a; 405 - conf->csa_active = params->csa_a; 406 - vif->link_conf[link_a.link_id] = (void __rcu *)conf; 407 - 408 - conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL); 409 - KUNIT_ASSERT_NOT_NULL(test, conf); 410 - conf->chanreq.oper = chandef_b; 411 - vif->link_conf[link_b.link_id] = (void __rcu *)conf; 412 - 413 - wiphy_lock(&wiphy); 414 - result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b); 415 - wiphy_unlock(&wiphy); 416 - 417 - KUNIT_EXPECT_EQ(test, result, params->valid); 418 - 419 - kunit_kfree(test, vif); 420 - kunit_kfree(test, trans); 421 - } 422 - 423 - static struct kunit_case valid_link_pair_test_cases[] = { 424 - KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params), 425 - {}, 426 - }; 427 - 428 - static struct kunit_suite valid_link_pair = { 429 - .name = "iwlmvm-valid-link-pair", 430 - .test_cases = valid_link_pair_test_cases, 431 - }; 432 - 433 - kunit_test_suite(valid_link_pair);
-3
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
··· 47 47 48 48 static void iwl_mvm_cleanup_roc(struct iwl_mvm *mvm) 49 49 { 50 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 51 50 struct ieee80211_vif *vif = mvm->p2p_device_vif; 52 51 53 52 lockdep_assert_held(&mvm->mutex); ··· 124 125 iwl_mvm_rm_aux_sta(mvm); 125 126 } 126 127 127 - if (!IS_ERR_OR_NULL(bss_vif)) 128 - iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_ROC); 129 128 mutex_unlock(&mvm->mutex); 130 129 } 131 130
+1 -7
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
··· 1769 1769 IWL_DEBUG_TX_REPLY(mvm, 1770 1770 "Next reclaimed packet:%d\n", 1771 1771 next_reclaimed); 1772 - if (tid < IWL_MAX_TID_COUNT) 1773 - iwl_mvm_count_mpdu(mvmsta, sta_id, 1, 1774 - true, 0); 1775 1772 } else { 1776 1773 IWL_DEBUG_TX_REPLY(mvm, 1777 1774 "NDP - don't update next_reclaimed\n"); ··· 2147 2150 ba_res->tx_rate, false); 2148 2151 } 2149 2152 2150 - if (mvmsta) { 2153 + if (mvmsta) 2151 2154 iwl_mvm_tx_airtime(mvm, mvmsta, 2152 2155 le32_to_cpu(ba_res->wireless_time)); 2153 2156 2154 - iwl_mvm_count_mpdu(mvmsta, sta_id, 2155 - le16_to_cpu(ba_res->txed), true, 0); 2156 - } 2157 2157 rcu_read_unlock(); 2158 2158 return; 2159 2159 }
-10
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
··· 22 22 { 23 23 int ret; 24 24 25 - #if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) 26 - if (WARN_ON(mvm->d3_test_active)) 27 - return -EIO; 28 - #endif 29 - 30 25 /* 31 26 * Synchronous commands from this op-mode must hold 32 27 * the mutex, this ensures we don't try to send two ··· 73 78 int ret, resp_len; 74 79 75 80 lockdep_assert_held(&mvm->mutex); 76 - 77 - #if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) 78 - if (WARN_ON(mvm->d3_test_active)) 79 - return -EIO; 80 - #endif 81 81 82 82 /* 83 83 * Only synchronous commands can wait for status,
+1 -6
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
··· 1171 1171 static void iwl_pci_remove(struct pci_dev *pdev) 1172 1172 { 1173 1173 struct iwl_trans *trans = pci_get_drvdata(pdev); 1174 - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1175 1174 1176 1175 if (!trans) 1177 1176 return; 1178 1177 1179 - cancel_delayed_work_sync(&trans_pcie->me_recheck_wk); 1180 - 1181 - iwl_drv_stop(trans->drv); 1182 - 1183 - iwl_trans_pcie_free(trans); 1178 + iwl_pcie_gen1_2_remove(trans); 1184 1179 } 1185 1180 1186 1181 #ifdef CONFIG_PM_SLEEP
+31 -4
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
··· 400 400 * @me_recheck_wk: worker to recheck WiAMT/CSME presence 401 401 * @invalid_tx_cmd: invalid TX command buffer 402 402 * @wait_command_queue: wait queue for sync commands 403 + * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. 404 + * The user should use iwl_trans_{alloc,free}_tx_cmd. 405 + * @dev_cmd_pool_name: name for the TX command allocation pool 403 406 */ 404 407 struct iwl_trans_pcie { 405 408 struct iwl_rxq *rxq; ··· 509 506 struct iwl_dma_ptr invalid_tx_cmd; 510 507 511 508 wait_queue_head_t wait_command_queue; 509 + 510 + struct kmem_cache *dev_cmd_pool; 511 + char dev_cmd_pool_name[50]; 512 512 }; 513 513 514 514 static inline struct iwl_trans_pcie * ··· 789 783 return le16_to_cpu(tb->hi_n_len) >> 4; 790 784 } 791 785 786 + static inline struct iwl_device_tx_cmd * 787 + iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans) 788 + { 789 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 790 + 791 + return kmem_cache_zalloc(trans_pcie->dev_cmd_pool, GFP_ATOMIC); 792 + } 793 + 794 + static inline void 795 + iwl_pcie_gen1_2_free_tx_cmd(struct iwl_trans *trans, 796 + struct iwl_device_tx_cmd *dev_cmd) 797 + { 798 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 799 + 800 + kmem_cache_free(trans_pcie->dev_cmd_pool, dev_cmd); 801 + } 802 + 792 803 void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, 793 804 struct sk_buff_head *skbs, bool is_flush); 794 805 void iwl_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr); ··· 841 818 trans_pcie->fh_init_mask); 842 819 iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, 843 820 trans_pcie->hw_init_mask); 821 + trans_pcie->fh_mask = 0; 822 + trans_pcie->hw_mask = 0; 844 823 } 845 824 IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); 846 825 } ··· 1025 1000 } else { 1026 1001 iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, 1027 1002 trans_pcie->fh_init_mask); 1003 + trans_pcie->fh_mask = 0; 1028 1004 iwl_enable_hw_int_msk_msix(trans, 1029 1005 MSIX_HW_INT_CAUSES_REG_RF_KILL); 1030 1006 } ··· 1073 1047 void iwl_pcie_rx_allocator_work(struct work_struct *data); 1074 1048 1075 1049 /* common trans ops for all generations transports */ 1076 - void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans); 1050 + void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans); 1077 1051 int _iwl_trans_pcie_start_hw(struct iwl_trans *trans); 1078 1052 int iwl_trans_pcie_start_hw(struct iwl_trans *trans); 1079 1053 void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans); ··· 1090 1064 const struct iwl_dump_sanitize_ops *sanitize_ops, 1091 1065 void *sanitize_ctx); 1092 1066 int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, 1093 - enum iwl_d3_status *status, 1094 - bool test, bool reset); 1095 - int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset); 1067 + bool reset); 1068 + int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset); 1096 1069 void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable); 1097 1070 void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans); 1098 1071 void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, ··· 1106 1081 const struct pci_device_id *ent, 1107 1082 const struct iwl_mac_cfg *mac_cfg, 1108 1083 u8 __iomem *hw_base, u32 hw_rev); 1084 + void iwl_pcie_gen1_2_remove(struct iwl_trans *trans); 1109 1085 1110 1086 /* transport gen 1 exported functions */ 1111 1087 void iwl_trans_pcie_fw_alive(struct iwl_trans *trans); ··· 1131 1105 struct iwl_dma_ptr *ptr, size_t size); 1132 1106 void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr); 1133 1107 void iwl_pcie_apply_destination(struct iwl_trans *trans); 1108 + int iwl_pcie_gen1_2_finish_nic_init(struct iwl_trans *trans); 1134 1109 1135 1110 /* transport gen 2 exported functions */ 1136 1111 int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
+152 -66
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
··· 32 32 #include "pcie/iwl-context-info-v2.h" 33 33 #include "pcie/utils.h" 34 34 35 + #define IWL_HOST_MON_BLOCK_PEMON 0x00 36 + #define IWL_HOST_MON_BLOCK_HIPM 0x22 37 + 38 + #define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00 39 + #define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01 40 + #define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06 41 + 42 + static void iwl_dump_host_monitor_block(struct iwl_trans *trans, 43 + u32 block, u32 vec, u32 iter) 44 + { 45 + int i; 46 + 47 + IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec); 48 + iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); 49 + for (i = 0; i < iter; i++) 50 + IWL_ERR(trans, " value [iter %d]: 0x%08x\n", 51 + i, iwl_read32(trans, CSR_MONITOR_STATUS_REG)); 52 + } 53 + 54 + static void iwl_pcie_dump_host_monitor(struct iwl_trans *trans) 55 + { 56 + switch (trans->mac_cfg->device_family) { 57 + case IWL_DEVICE_FAMILY_22000: 58 + case IWL_DEVICE_FAMILY_AX210: 59 + IWL_ERR(trans, "CSR_RESET = 0x%x\n", 60 + iwl_read32(trans, CSR_RESET)); 61 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 62 + IWL_HOST_MON_BLOCK_PEMON_VEC0, 15); 63 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 64 + IWL_HOST_MON_BLOCK_PEMON_VEC1, 15); 65 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 66 + IWL_HOST_MON_BLOCK_PEMON_WFPM, 15); 67 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM, 68 + IWL_HOST_MON_BLOCK_PEMON_VEC0, 1); 69 + break; 70 + default: 71 + return; 72 + } 73 + } 74 + 35 75 /* extended range in FW SRAM */ 36 76 #define IWL_FW_MEM_EXTENDED_START 0x40000 37 77 #define IWL_FW_MEM_EXTENDED_END 0x57FFF ··· 1437 1397 } 1438 1398 1439 1399 static void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans, 1440 - bool test, bool reset) 1400 + bool reset) 1441 1401 { 1442 1402 iwl_disable_interrupts(trans); 1443 - 1444 - /* 1445 - * in testing mode, the host stays awake and the 1446 - * hardware won't be reset (not even partially) 1447 - */ 1448 - if (test) 1449 - return; 1450 1403 1451 1404 iwl_pcie_disable_ict(trans); 1452 1405 ··· 1511 1478 return ret; 1512 1479 } 1513 1480 1514 - int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset) 1481 + int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset) 1515 1482 { 1516 1483 int ret; 1517 1484 ··· 1524 1491 if (ret) 1525 1492 return ret; 1526 1493 1527 - iwl_pcie_d3_complete_suspend(trans, test, reset); 1494 + iwl_pcie_d3_complete_suspend(trans, reset); 1528 1495 1529 1496 return 0; 1530 1497 } 1531 1498 1532 1499 int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, 1533 - enum iwl_d3_status *status, 1534 - bool test, bool reset) 1500 + bool reset) 1535 1501 { 1536 1502 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1537 1503 u32 val; 1538 1504 int ret; 1539 - 1540 - if (test) { 1541 - iwl_enable_interrupts(trans); 1542 - *status = IWL_D3_STATUS_ALIVE; 1543 - ret = 0; 1544 - goto out; 1545 - } 1546 1505 1547 1506 if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) 1548 1507 iwl_set_bit(trans, CSR_GP_CNTRL, ··· 1544 1519 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1545 1520 1546 1521 ret = iwl_finish_nic_init(trans); 1547 - if (ret) 1522 + if (ret) { 1523 + IWL_ERR(trans, "Failed to init nic upon resume. err = %d\n", 1524 + ret); 1548 1525 return ret; 1526 + } 1549 1527 1550 1528 /* 1551 1529 * Reconfigure IVAR table in case of MSIX or reset ict table in ··· 1582 1554 iwl_read_umac_prph(trans, WFPM_GP2)); 1583 1555 1584 1556 val = iwl_read32(trans, CSR_RESET); 1585 - if (val & CSR_RESET_REG_FLAG_NEVO_RESET) 1586 - *status = IWL_D3_STATUS_RESET; 1587 - else 1588 - *status = IWL_D3_STATUS_ALIVE; 1589 - 1590 - out: 1591 - if (*status == IWL_D3_STATUS_ALIVE) 1592 - ret = iwl_pcie_d3_handshake(trans, false); 1593 - else 1557 + if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { 1558 + IWL_INFO(trans, "Device was reset during suspend\n"); 1594 1559 trans->state = IWL_TRANS_NO_FW; 1560 + return -ENOENT; 1561 + } 1595 1562 1596 - return ret; 1563 + return iwl_pcie_d3_handshake(trans, false); 1597 1564 } 1598 1565 1599 1566 static void ··· 1905 1882 iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); 1906 1883 } 1907 1884 1908 - void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans) 1885 + void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans) 1909 1886 { 1910 1887 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1911 1888 ··· 2023 2000 free_percpu(trans_pcie->txqs.tso_hdr_page); 2024 2001 } 2025 2002 2003 + kmem_cache_destroy(trans_pcie->dev_cmd_pool); 2026 2004 iwl_trans_free(trans); 2027 2005 } 2028 2006 ··· 3708 3684 iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit); 3709 3685 } 3710 3686 3711 - static int iwl_trans_pcie_set_txcmd_info(const struct iwl_mac_cfg *mac_cfg, 3712 - unsigned int *txcmd_size, 3713 - unsigned int *txcmd_align) 3687 + static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans) 3714 3688 { 3715 - if (!mac_cfg->gen2) { 3716 - *txcmd_size = sizeof(struct iwl_tx_cmd_v6); 3717 - *txcmd_align = sizeof(void *); 3718 - } else if (mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { 3719 - *txcmd_size = sizeof(struct iwl_tx_cmd_v9); 3720 - *txcmd_align = 64; 3689 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 3690 + unsigned int txcmd_size, txcmd_align; 3691 + 3692 + if (!trans->mac_cfg->gen2) { 3693 + txcmd_size = sizeof(struct iwl_tx_cmd_v6); 3694 + txcmd_align = sizeof(void *); 3695 + } else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { 3696 + txcmd_size = sizeof(struct iwl_tx_cmd_v9); 3697 + txcmd_align = 64; 3721 3698 } else { 3722 - *txcmd_size = sizeof(struct iwl_tx_cmd); 3723 - *txcmd_align = 128; 3699 + txcmd_size = sizeof(struct iwl_tx_cmd); 3700 + txcmd_align = 128; 3724 3701 } 3725 3702 3726 - *txcmd_size += sizeof(struct iwl_cmd_header); 3727 - *txcmd_size += 36; /* biggest possible 802.11 header */ 3703 + txcmd_size += sizeof(struct iwl_cmd_header); 3704 + txcmd_size += 36; /* biggest possible 802.11 header */ 3728 3705 3729 3706 /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ 3730 - if (WARN_ON((mac_cfg->gen2 && *txcmd_size >= *txcmd_align))) 3707 + if (WARN_ON((trans->mac_cfg->gen2 && txcmd_size >= txcmd_align))) 3731 3708 return -EINVAL; 3709 + 3710 + snprintf(trans_pcie->dev_cmd_pool_name, 3711 + sizeof(trans_pcie->dev_cmd_pool_name), 3712 + "iwl_cmd_pool:%s", dev_name(trans->dev)); 3713 + 3714 + trans_pcie->dev_cmd_pool = 3715 + kmem_cache_create(trans_pcie->dev_cmd_pool_name, 3716 + txcmd_size, txcmd_align, 3717 + SLAB_HWCACHE_ALIGN, NULL); 3718 + if (!trans_pcie->dev_cmd_pool) 3719 + return -ENOMEM; 3732 3720 3733 3721 return 0; 3734 3722 } ··· 3751 3715 struct iwl_trans_info *info, u8 __iomem *hw_base) 3752 3716 { 3753 3717 struct iwl_trans_pcie *trans_pcie, **priv; 3754 - unsigned int txcmd_size, txcmd_align; 3755 3718 struct iwl_trans *trans; 3756 3719 unsigned int bc_tbl_n_entries; 3757 3720 int ret, addr_size; 3758 3721 3759 - ret = iwl_trans_pcie_set_txcmd_info(mac_cfg, &txcmd_size, 3760 - &txcmd_align); 3761 - if (ret) 3762 - return ERR_PTR(ret); 3763 - 3764 3722 trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, 3765 - mac_cfg, txcmd_size, txcmd_align); 3723 + mac_cfg); 3766 3724 if (!trans) 3767 3725 return ERR_PTR(-ENOMEM); 3768 3726 ··· 3766 3736 3767 3737 /* Initialize the wait queue for commands */ 3768 3738 init_waitqueue_head(&trans_pcie->wait_command_queue); 3739 + 3740 + ret = iwl_trans_pcie_alloc_txcmd_pool(trans); 3741 + if (ret) 3742 + goto out_free_trans; 3769 3743 3770 3744 if (trans->mac_cfg->gen2) { 3771 3745 trans_pcie->txqs.tfd.addr_size = 64; ··· 3790 3756 trans_pcie->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); 3791 3757 if (!trans_pcie->txqs.tso_hdr_page) { 3792 3758 ret = -ENOMEM; 3793 - goto out_free_trans; 3759 + goto out_free_txcmd_pool; 3794 3760 } 3795 3761 3796 3762 if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) ··· 3940 3906 free_netdev(trans_pcie->napi_dev); 3941 3907 out_free_tso: 3942 3908 free_percpu(trans_pcie->txqs.tso_hdr_page); 3909 + out_free_txcmd_pool: 3910 + kmem_cache_destroy(trans_pcie->dev_cmd_pool); 3943 3911 out_free_trans: 3944 3912 iwl_trans_free(trans); 3945 3913 return ERR_PTR(ret); ··· 4035 3999 4036 4000 /* Read cdb info (also contains the jacket info if needed in the future */ 4037 4001 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR); 4002 + 4038 4003 IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n", 4039 4004 info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id); 4040 4005 } ··· 4051 4014 u32 val = info->hw_crf_id; 4052 4015 u32 step_id = REG_CRF_ID_STEP(val); 4053 4016 u32 slave_id = REG_CRF_ID_SLAVE(val); 4054 - u32 jacket_id_cnv = REG_CRF_ID_SLAVE(info->hw_cnv_id); 4055 4017 u32 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, 4056 4018 WFPM_OTP_CFG1_ADDR); 4057 - u32 jacket_id_wfpm = WFPM_OTP_CFG1_IS_JACKET(hw_wfpm_id); 4058 4019 u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id); 4059 4020 4060 4021 /* Map between crf id to rf id */ ··· 4101 4066 IWL_INFO(iwl_trans, "Adding cdb to rf id\n"); 4102 4067 } 4103 4068 4104 - /* Set Jacket capabilities */ 4105 - if (jacket_id_wfpm || jacket_id_cnv) { 4106 - info->hw_rf_id += BIT(29); 4107 - IWL_INFO(iwl_trans, "Adding jacket to rf id\n"); 4108 - } 4109 - 4110 4069 IWL_INFO(iwl_trans, 4111 4070 "Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n", 4112 4071 REG_CRF_ID_TYPE(val), step_id, slave_id, info->hw_rf_id); 4113 4072 IWL_INFO(iwl_trans, 4114 - "Detected cdb-id 0x%x jacket-id 0x%x from wfpm id 0x%x\n", 4115 - cdb_id_wfpm, jacket_id_wfpm, hw_wfpm_id); 4116 - IWL_INFO(iwl_trans, "Detected jacket-id 0x%x from cnvi id 0x%x\n", 4117 - jacket_id_cnv, info->hw_cnv_id); 4118 - 4073 + "Detected cdb-id 0x%x from wfpm id 0x%x\n", 4074 + cdb_id_wfpm, hw_wfpm_id); 4119 4075 out: 4120 4076 return ret; 4121 4077 } ··· 4296 4270 out_free_trans: 4297 4271 iwl_trans_pcie_free(iwl_trans); 4298 4272 return ret; 4273 + } 4274 + 4275 + void iwl_pcie_gen1_2_remove(struct iwl_trans *trans) 4276 + { 4277 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 4278 + 4279 + cancel_delayed_work_sync(&trans_pcie->me_recheck_wk); 4280 + 4281 + iwl_drv_stop(trans->drv); 4282 + 4283 + iwl_trans_pcie_free(trans); 4284 + } 4285 + 4286 + int iwl_pcie_gen1_2_finish_nic_init(struct iwl_trans *trans) 4287 + { 4288 + const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg; 4289 + u32 poll_ready; 4290 + int err; 4291 + 4292 + if (mac_cfg->bisr_workaround) { 4293 + /* ensure the TOP FSM isn't still in previous reset */ 4294 + mdelay(2); 4295 + } 4296 + 4297 + /* 4298 + * Set "initialization complete" bit to move adapter from 4299 + * D0U* --> D0A* (powered-up active) state. 4300 + */ 4301 + if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { 4302 + iwl_set_bit(trans, CSR_GP_CNTRL, 4303 + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ | 4304 + CSR_GP_CNTRL_REG_FLAG_MAC_INIT); 4305 + poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS; 4306 + } else { 4307 + iwl_set_bit(trans, CSR_GP_CNTRL, 4308 + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 4309 + poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY; 4310 + } 4311 + 4312 + if (mac_cfg->device_family == IWL_DEVICE_FAMILY_8000) 4313 + udelay(2); 4314 + 4315 + /* 4316 + * Wait for clock stabilization; once stabilized, access to 4317 + * device-internal resources is supported, e.g. iwl_write_prph() 4318 + * and accesses to uCode SRAM. 4319 + */ 4320 + err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000); 4321 + if (err < 0) { 4322 + IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); 4323 + 4324 + iwl_pcie_dump_host_monitor(trans); 4325 + } 4326 + 4327 + if (mac_cfg->bisr_workaround) { 4328 + /* ensure BISR shift has finished */ 4329 + udelay(200); 4330 + } 4331 + 4332 + return err; 4299 4333 }