diff options
83 files changed, 1040 insertions, 1353 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/Makefile b/drivers/net/wireless/intel/iwlwifi/Makefile index b82392978b76..941257b811b4 100644 --- a/drivers/net/wireless/intel/iwlwifi/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/Makefile @@ -22,6 +22,7 @@ iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o # MAC configurations iwlwifi-$(CONFIG_IWLMVM) += cfg/9000.o cfg/22000.o iwlwifi-$(CONFIG_IWLMVM) += cfg/ax210.o +iwlwifi-$(CONFIG_IWLMVM) += cfg/bz.o cfg/sc.o iwlwifi-$(CONFIG_IWLMLD) += cfg/bz.o cfg/sc.o cfg/dr.o # RF configurations iwlwifi-$(CONFIG_IWLMVM) += cfg/rf-jf.o cfg/rf-hr.o cfg/rf-gf.o diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 52e0beebf9ce..ca488931a33c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -19,26 +19,8 @@ #define IWL_22000_SMEM_OFFSET 0x400000 #define IWL_22000_SMEM_LEN 0xD0000 -#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" -#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0" -#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0" -#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0" -#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0" -#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0" #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0" -#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \ - IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ - IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \ - IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode" #define IWL_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE "-" __stringify(api) ".ucode" @@ -132,10 +114,4 @@ const char iwl_ax201_killer_1650s_name[] = const char iwl_ax201_killer_1650i_name[] = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)"; -MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_C_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c index 3bf9fdbe01c6..ddf3d313da5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c @@ -13,33 +13,12 @@ #define IWL_AX210_UCODE_API_MAX 89 /* Lowest firmware API version supported */ -#define IWL_AX210_UCODE_API_MIN 77 +#define IWL_AX210_UCODE_API_MIN 89 /* Memory offsets and lengths */ #define IWL_AX210_SMEM_OFFSET 0x400000 #define IWL_AX210_SMEM_LEN 0xD0000 -#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0" -#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" -#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" -#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" -#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" -#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0" -#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" -#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" -#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0" -#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" -#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" - -#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" - static const struct iwl_family_base_params iwl_ax210_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -143,14 +122,3 @@ const struct iwl_mac_cfg iwl_ma_mac_cfg = { .integrated = true, .umac_prph_offset = 0x300000 }; - -MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); -IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); -MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); -IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); -MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX)); -IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_AX210_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_AX210_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 50d454514fe5..9f543946b285 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -19,18 +19,12 @@ #define IWL_BZ_SMEM_OFFSET 0x400000 #define IWL_BZ_SMEM_LEN 0xD0000 -#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0" -#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0" -#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0" #define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0" #define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0" #define IWL_BZ_A_FM4_B_FW_PRE "iwlwifi-bz-a0-fm4-b0" #define IWL_GL_B_FM_B_FW_PRE "iwlwifi-gl-b0-fm-b0" #define IWL_GL_C_FM_C_FW_PRE "iwlwifi-gl-c0-fm-c0" -#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" - static const struct iwl_family_base_params iwl_bz_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -107,9 +101,6 @@ const struct iwl_mac_cfg iwl_gl_mac_cfg = { .low_latency_xtal = true, }; -MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX)); -IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_BZ_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c index f55c286e83be..7ff5170faaa9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c @@ -5,6 +5,24 @@ */ #include "iwl-config.h" +/* Highest firmware API version supported */ +#define IWL_GF_UCODE_API_MAX 100 + +/* Lowest firmware API version supported */ +#define IWL_GF_UCODE_API_MIN 98 + +#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" +#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" +#define IWL_MA_A_GF_A_FW_PRE "iwlwifi-ma-a0-gf-a0" +#define IWL_MA_B_GF_A_FW_PRE "iwlwifi-ma-b0-gf-a0" +#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0" +#define IWL_MA_A_GF4_A_FW_PRE "iwlwifi-ma-a0-gf4-a0" +#define IWL_MA_B_GF4_A_FW_PRE "iwlwifi-ma-b0-gf4-a0" +#define IWL_BZ_A_GF_A_FW_PRE "iwlwifi-bz-a0-gf-a0" +#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0" +#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" +#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" + /* NVM versions */ #define IWL_GF_NVM_VERSION 0x0a1d @@ -22,6 +40,8 @@ const struct iwl_rf_cfg iwl_rf_gf = { .nvm_ver = IWL_GF_NVM_VERSION, .nvm_type = IWL_NVM_EXT, .num_rbds = IWL_NUM_RBDS_HE, + .ucode_api_min = IWL_GF_UCODE_API_MIN, + .ucode_api_max = IWL_GF_UCODE_API_MAX, }; const char iwl_ax210_killer_1675w_name[] = @@ -40,3 +60,14 @@ const char iwl_ax411_killer_1690i_name[] = const char iwl_ax210_name[] = "Intel(R) Wi-Fi 6E AX210 160MHz"; const char iwl_ax211_name[] = "Intel(R) Wi-Fi 6E AX211 160MHz"; const char iwl_ax411_name[] = "Intel(R) Wi-Fi 6E AX411 160MHz"; + +IWL_FW_AND_PNVM(IWL_SO_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_TY_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); +IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c index db02664e3917..9f408d276ce9 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c @@ -5,6 +5,41 @@ */ #include "iwl-config.h" +/* Highest firmware API version supported */ +#define IWL_HR_UCODE_API_MAX 100 + +/* Lowest firmware API version supported */ +#define IWL_HR_UCODE_API_MIN 98 + +#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" +#define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0" +#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0" +#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0" +#define IWL_MA_A_HR_B_FW_PRE "iwlwifi-ma-a0-hr-b0" +#define IWL_MA_B_HR_B_FW_PRE "iwlwifi-ma-b0-hr-b0" +#define IWL_BZ_A_HR_B_FW_PRE "iwlwifi-bz-a0-hr-b0" +#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0" +#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0" + +#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ + IWL_QU_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_QUZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_C_HR_B_MODULE_FIRMWARE(api) \ + IWL_QU_C_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_MA_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_MA_B_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_BZ_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_BZ_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \ + IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" + /* NVM versions */ #define IWL_HR_NVM_VERSION 0x0a1d @@ -20,7 +55,9 @@ }, \ .num_rbds = IWL_NUM_RBDS_HE, \ .nvm_ver = IWL_HR_NVM_VERSION, \ - .nvm_type = IWL_NVM_EXT + .nvm_type = IWL_NVM_EXT, \ + .ucode_api_min = IWL_HR_UCODE_API_MIN, \ + .ucode_api_max = IWL_HR_UCODE_API_MAX const struct iwl_rf_cfg iwl_rf_hr1 = { IWL_DEVICE_HR, @@ -40,3 +77,13 @@ const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101"; const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; const char iwl_ax203_name[] = "Intel(R) Wi-Fi 6 AX203"; + +MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_HR_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c b/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c index 467eaeae6deb..0a074e0a3bc6 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/rf-jf.c @@ -5,6 +5,26 @@ */ #include "iwl-config.h" +/* Highest firmware API version supported */ +#define IWL_JF_UCODE_API_MAX 77 + +/* Lowest firmware API version supported */ +#define IWL_JF_UCODE_API_MIN 77 + +#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0" +#define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0" +#define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0" +#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0" + +#define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_QUZ_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ + IWL_QU_B_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_QU_C_JF_B_MODULE_FIRMWARE(api) \ + IWL_QU_C_JF_B_FW_PRE "-" __stringify(api) ".ucode" +#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_JF_B_FW_PRE "-" __stringify(api) ".ucode" + /* NVM versions */ #define IWL_JF_NVM_VERSION 0x0a1d @@ -56,7 +76,9 @@ static const struct iwl_tt_params iwl_jf_tt_params = { BIT(NL80211_BAND_5GHZ), \ }, \ .nvm_ver = IWL_JF_NVM_VERSION, \ - .nvm_type = IWL_NVM_EXT + .nvm_type = IWL_NVM_EXT, \ + .ucode_api_min = IWL_JF_UCODE_API_MIN, \ + .ucode_api_max = IWL_JF_UCODE_API_MAX const struct iwl_rf_cfg iwl_rf_jf = { IWL_DEVICE_JF, @@ -82,3 +104,8 @@ const char iwl9560_killer_1550i_name[] = "Killer(R) Wireless-AC 1550i Wireless Network Adapter (9560NGW) 160MHz"; const char iwl9560_killer_1550s_name[] = "Killer(R) Wireless-AC 1550s Wireless Network Adapter (9560D2W) 160MHz"; + +MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_C_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_JF_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 97e503a25eae..7b70640abf53 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -24,21 +24,12 @@ #define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0" #define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0" -#define IWL_SC_A_HR_A_FW_PRE "iwlwifi-sc-a0-hr-b0" -#define IWL_SC_A_HR_B_FW_PRE "iwlwifi-sc-a0-hr-b0" -#define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" -#define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" #define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0" #define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0" #define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0" #define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0" #define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0" -#define IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(api) \ - IWL_SC_A_HR_A_FW_PRE "-" __stringify(api) ".ucode" -#define IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(api) \ - IWL_SC_A_HR_B_FW_PRE "-" __stringify(api) ".ucode" - static const struct iwl_family_base_params iwl_sc_base = { .num_of_queues = 512, .max_tfd_queue_size = 65536, @@ -107,10 +98,6 @@ const struct iwl_mac_cfg iwl_sc_mac_cfg = { IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); -MODULE_FIRMWARE(IWL_SC_A_HR_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX)); -IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_SC_UCODE_API_MAX); -IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c index 8087aee03d1c..9f8cdb027839 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c @@ -679,11 +679,11 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) ret = iwl_poll_bits(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_EEPROM_OWN_SEM, IWL_EEPROM_SEM_TIMEOUT); - if (ret >= 0) { + if (!ret) { IWL_DEBUG_EEPROM(trans->dev, "Acquired semaphore after %d tries.\n", count+1); - return ret; + return 0; } } @@ -799,7 +799,7 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, ret = iwl_poll_bits(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); return ret; } @@ -941,14 +941,14 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) return -ENOMEM; ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); goto err_free; } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ ret = iwl_eeprom_acquire_semaphore(trans); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); goto err_free; } @@ -994,7 +994,7 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) ret = iwl_poll_bits(trans, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { + if (ret) { IWL_ERR(trans, "Time out reading EEPROM[%d]\n", addr); goto err_unlock; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h index 3ce477c248ce..ad5b95cad0bf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h @@ -82,21 +82,6 @@ struct iwl_alive_ntf_v3 { struct iwl_umac_alive umac_data; } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */ -struct iwl_alive_ntf_v4 { - __le16 status; - __le16 flags; - struct iwl_lmac_alive lmac_data[2]; - struct iwl_umac_alive umac_data; -} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_4 */ - -struct iwl_alive_ntf_v5 { - __le16 status; - __le16 flags; - struct iwl_lmac_alive lmac_data[2]; - struct iwl_umac_alive umac_data; - struct iwl_sku_id sku_id; -} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */ - struct iwl_imr_alive_info { __le64 base_addr; __le32 size; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 1c86a858aaab..997b0c9ce984 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -573,9 +573,8 @@ enum iwl_legacy_cmds { WOWLAN_KEK_KCK_MATERIAL = 0xe4, /** - * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6, - * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or - * &struct iwl_wowlan_status_v12 + * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6 or + * &struct iwl_wowlan_status_v7 */ WOWLAN_GET_STATUSES = 0xe5, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 99554496300a..53445087e9cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -456,11 +456,6 @@ struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 { union iwl_all_tsc_rsc all_tsc_rsc; } __packed; /* ALL_TSC_RSC_API_S_VER_2 */ -struct iwl_wowlan_rsc_tsc_params_cmd_v4 { - struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 params; - __le32 sta_id; -} __packed; /* ALL_TSC_RSC_API_S_VER_4 */ - struct iwl_wowlan_rsc_tsc_params_cmd { __le64 ucast_rsc[IWL_MAX_TID_COUNT]; __le64 mcast_rsc[WOWLAN_GTK_KEYS_NUM][IWL_MAX_TID_COUNT]; @@ -720,82 +715,6 @@ struct iwl_wowlan_status_v7 { } __packed; /* WOWLAN_STATUSES_API_S_VER_7 */ /** - * struct iwl_wowlan_status_v9 - WoWLAN status (versions 9 and 10) - * @gtk: GTK data - * @igtk: IGTK data - * @replay_ctr: GTK rekey replay counter - * @pattern_number: number of the matched pattern - * @non_qos_seq_ctr: non-QoS sequence counter to use next. - * Reserved if the struct has version >= 10. - * @qos_seq_ctr: QoS sequence counters to use next - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @transmitted_ndps: number of transmitted neighbor discovery packets - * @received_beacons: number of received beacons - * @wake_packet_length: wakeup packet length - * @wake_packet_bufsize: wakeup packet buffer size - * @tid_tear_down: bit mask of tids whose BA sessions were closed - * in suspend state - * @reserved: unused - * @wake_packet: wakeup packet - */ -struct iwl_wowlan_status_v9 { - struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM]; - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; - __le64 replay_ctr; - __le16 pattern_number; - __le16 non_qos_seq_ctr; - __le16 qos_seq_ctr[8]; - __le32 wakeup_reasons; - __le32 num_of_gtk_rekeys; - __le32 transmitted_ndps; - __le32 received_beacons; - __le32 wake_packet_length; - __le32 wake_packet_bufsize; - u8 tid_tear_down; - u8 reserved[3]; - u8 wake_packet[]; /* can be truncated from _length to _bufsize */ -} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */ - -/** - * struct iwl_wowlan_status_v12 - WoWLAN status - * @gtk: GTK data - * @igtk: IGTK data - * @replay_ctr: GTK rekey replay counter - * @pattern_number: number of the matched pattern - * @non_qos_seq_ctr: non-QoS sequence counter to use next. - * Reserved if the struct has version >= 10. - * @qos_seq_ctr: QoS sequence counters to use next - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @transmitted_ndps: number of transmitted neighbor discovery packets - * @received_beacons: number of received beacons - * @wake_packet_length: wakeup packet length - * @wake_packet_bufsize: wakeup packet buffer size - * @tid_tear_down: bit mask of tids whose BA sessions were closed - * in suspend state - * @reserved: unused - * @wake_packet: wakeup packet - */ -struct iwl_wowlan_status_v12 { - struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; - __le64 replay_ctr; - __le16 pattern_number; - __le16 non_qos_seq_ctr; - __le16 qos_seq_ctr[8]; - __le32 wakeup_reasons; - __le32 num_of_gtk_rekeys; - __le32 transmitted_ndps; - __le32 received_beacons; - __le32 wake_packet_length; - __le32 wake_packet_bufsize; - u8 tid_tear_down; - u8 reserved[3]; - u8 wake_packet[]; /* can be truncated from _length to _bufsize */ -} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */ - -/** * struct iwl_wowlan_info_notif_v1 - WoWLAN information notification * @gtk: GTK data * @igtk: IGTK data @@ -832,39 +751,6 @@ struct iwl_wowlan_info_notif_v1 { u8 reserved2[2]; } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */ -/** - * struct iwl_wowlan_info_notif_v2 - WoWLAN information notification - * @gtk: GTK data - * @igtk: IGTK data - * @replay_ctr: GTK rekey replay counter - * @pattern_number: number of the matched patterns - * @reserved1: reserved - * @qos_seq_ctr: QoS sequence counters to use next - * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason - * @num_of_gtk_rekeys: number of GTK rekeys - * @transmitted_ndps: number of transmitted neighbor discovery packets - * @received_beacons: number of received beacons - * @tid_tear_down: bit mask of tids whose BA sessions were closed - * in suspend state - * @station_id: station id - * @reserved2: reserved - */ -struct iwl_wowlan_info_notif_v2 { - struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; - __le64 replay_ctr; - __le16 pattern_number; - __le16 reserved1; - __le16 qos_seq_ctr[8]; - __le32 wakeup_reasons; - __le32 num_of_gtk_rekeys; - __le32 transmitted_ndps; - __le32 received_beacons; - u8 tid_tear_down; - u8 station_id; - u8 reserved2[2]; -} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */ - /* MAX MLO keys of non-active links that can arrive in the notification */ #define WOWLAN_MAX_MLO_KEYS 18 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 9c88bb280609..ee822a87c42c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -125,6 +125,11 @@ enum iwl_data_path_subcmd_ids { TLC_MNG_UPDATE_NOTIF = 0xF7, /** + * @BEACON_FILTER_IN_NOTIF: &struct iwl_beacon_filter_notif + */ + BEACON_FILTER_IN_NOTIF = 0xF8, + + /** * @STA_PM_NOTIF: &struct iwl_mvm_pm_state_notification */ STA_PM_NOTIF = 0xFD, @@ -695,12 +700,23 @@ struct iwl_sec_key_cmd { } __packed; /* SEC_KEY_CMD_API_S_VER_1 */ /** + * struct iwl_omi_send_status_notif_v1 - OMI status notification + * @success: indicates that the OMI was sent successfully + * (currently always set) + */ +struct iwl_omi_send_status_notif_v1 { + __le32 success; +} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_1 */ + +/** * struct iwl_omi_send_status_notif - OMI status notification * @success: indicates that the OMI was sent successfully * (currently always set) + * @sta_id: sta_id to which the OMI was sent */ struct iwl_omi_send_status_notif { __le32 success; -} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_1 */ + __le32 sta_id; +} __packed; /* OMI_SEND_STATUS_NTFY_API_S_VER_2 */ #endif /* __iwl_fw_api_datapath_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 5cdc09d465d4..28ccac7d2142 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -787,6 +787,7 @@ struct iwl_lari_config_change_cmd { /* Activate UNII-1 (5.2GHz) for World Wide */ #define ACTIVATE_5G2_IN_WW_MASK BIT(4) #define CHAN_STATE_ACTIVE_BITMAP_CMD_V11 0x1F +#define CHAN_STATE_ACTIVE_BITMAP_CMD_V12 0x7F /** * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index 9b09b835560b..2a1c2b0f19e4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -3,7 +3,7 @@ * Copyright (C) 2012-2014 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH - * Copyright (C) 2021-2024 Intel Corporation + * Copyright (C) 2021-2025 Intel Corporation */ #ifndef __iwl_fw_api_offload_h__ #define __iwl_fw_api_offload_h__ @@ -19,7 +19,7 @@ enum iwl_prot_offload_subcmd_ids { /** * @WOWLAN_INFO_NOTIFICATION: Notification in - * &struct iwl_wowlan_info_notif_v1, &struct iwl_wowlan_info_notif_v2, + * &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3, * or &struct iwl_wowlan_info_notif */ WOWLAN_INFO_NOTIFICATION = 0xFD, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 23140205ccb9..ab84aac6605d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -255,19 +255,6 @@ struct iwl_uapsd_misbehaving_ap_notif { u8 reserved[3]; } __packed; -/** - * struct iwl_reduce_tx_power_cmd - TX power reduction command - * REDUCE_TX_POWER_CMD = 0x9f - * @flags: (reserved for future implementation) - * @mac_context_id: id of the mac ctx for which we are reducing TX power. - * @pwr_restriction: TX power restriction in dBms. - */ -struct iwl_reduce_tx_power_cmd { - u8 flags; - u8 mac_context_id; - __le16 pwr_restriction; -} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */ - enum iwl_dev_tx_power_cmd_mode { IWL_TX_POWER_MODE_SET_LINK = 0, IWL_TX_POWER_MODE_SET_DEVICE = 1, @@ -342,50 +329,6 @@ struct iwl_dev_tx_power_cmd_v5 { } __packed; /* TX_REDUCED_POWER_API_S_VER_5 */ /** - * struct iwl_dev_tx_power_cmd_v6 - TX power reduction command version 6 - * @per_chain: per chain restrictions - * @enable_ack_reduction: enable or disable close range ack TX power - * reduction. - * @per_chain_restriction_changed: is per_chain_restriction has changed - * from last command. used if set_mode is - * IWL_TX_POWER_MODE_SET_SAR_TIMER. - * note: if not changed, the command is used for keep alive only. - * @reserved: reserved (padding) - * @timer_period: timer in milliseconds. if expires FW will change to default - * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER - */ -struct iwl_dev_tx_power_cmd_v6 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; - u8 enable_ack_reduction; - u8 per_chain_restriction_changed; - u8 reserved[2]; - __le32 timer_period; -} __packed; /* TX_REDUCED_POWER_API_S_VER_6 */ - -/** - * struct iwl_dev_tx_power_cmd_v7 - TX power reduction command version 7 - * @per_chain: per chain restrictions - * @enable_ack_reduction: enable or disable close range ack TX power - * reduction. - * @per_chain_restriction_changed: is per_chain_restriction has changed - * from last command. used if set_mode is - * IWL_TX_POWER_MODE_SET_SAR_TIMER. - * note: if not changed, the command is used for keep alive only. - * @reserved: reserved (padding) - * @timer_period: timer in milliseconds. if expires FW will change to default - * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER - * @flags: reduce power flags. - */ -struct iwl_dev_tx_power_cmd_v7 { - __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; - u8 enable_ack_reduction; - u8 per_chain_restriction_changed; - u8 reserved[2]; - __le32 timer_period; - __le32 flags; -} __packed; /* TX_REDUCED_POWER_API_S_VER_7 */ - -/** * struct iwl_dev_tx_power_cmd_v8 - TX power reduction command version 8 * @per_chain: per chain restrictions * @enable_ack_reduction: enable or disable close range ack TX power @@ -429,8 +372,6 @@ struct iwl_dev_tx_power_cmd_per_band { * @v3: version 3 part of the command * @v4: version 4 part of the command * @v5: version 5 part of the command - * @v6: version 6 part of the command - * @v7: version 7 part of the command * @v8: version 8 part of the command */ struct iwl_dev_tx_power_cmd_v3_v8 { @@ -440,8 +381,6 @@ struct iwl_dev_tx_power_cmd_v3_v8 { struct iwl_dev_tx_power_cmd_v3 v3; struct iwl_dev_tx_power_cmd_v4 v4; struct iwl_dev_tx_power_cmd_v5 v5; - struct iwl_dev_tx_power_cmd_v6 v6; - struct iwl_dev_tx_power_cmd_v7 v7; struct iwl_dev_tx_power_cmd_v8 v8; }; }; @@ -632,8 +571,7 @@ enum iwl_ppag_flags { /** * union iwl_ppag_table_cmd - union for all versions of PPAG command * @v1: command version 1 structure. - * @v2: command version from 2 to 6 are same structure as v2. - * but has a different format of the flags bitmap + * @v2: command version 5 structure. * @v3: command version 7 structure. * @v1.flags: values from &enum iwl_ppag_flags * @v1.gain: table of antenna gain values per chain and sub-band @@ -654,9 +592,7 @@ union iwl_ppag_table_cmd { __le32 flags; s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; s8 reserved[2]; - } __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4, - * VER5, VER6 - */ + } __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_5 */ struct { struct bios_value_u32 ppag_config_info; s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; @@ -664,20 +600,11 @@ union iwl_ppag_table_cmd { } __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ } __packed; -#define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) -#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \ +#define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) +#define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V1_MASK | \ IWL_PPAG_ETSI_LPI_UHB_MASK | \ IWL_PPAG_USA_LPI_UHB_MASK) -#define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \ - IWL_PPAG_ETSI_VLP_UHB_MASK | \ - IWL_PPAG_ETSI_SP_UHB_MASK | \ - IWL_PPAG_USA_VLP_UHB_MASK | \ - IWL_PPAG_USA_SP_UHB_MASK | \ - IWL_PPAG_CANADA_LPI_UHB_MASK | \ - IWL_PPAG_CANADA_VLP_UHB_MASK | \ - IWL_PPAG_CANADA_SP_UHB_MASK) - #define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26 #define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 7cf6d6ac7430..d751789998ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -194,7 +194,9 @@ enum iwl_rx_mpdu_amsdu_info { }; enum iwl_rx_mpdu_mac_phy_band { + /* whether or not this is MAC or LINK depends on the API */ IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK = 0x0f, + IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK = 0x0f, IWL_RX_MPDU_MAC_PHY_BAND_PHY_MASK = 0x30, IWL_RX_MPDU_MAC_PHY_BAND_BAND_MASK = 0xc0, }; @@ -671,7 +673,7 @@ struct iwl_rx_mpdu_desc { */ __le16 phy_info; /** - * @mac_phy_band: MAC ID, PHY ID, band; + * @mac_phy_band: MAC/link ID, PHY ID, band; * see &enum iwl_rx_mpdu_mac_phy_band */ u8 mac_phy_band; @@ -1019,4 +1021,24 @@ struct iwl_rfh_queue_config { struct iwl_rfh_queue_data data[]; } __packed; /* RFH_QUEUE_CONFIG_API_S_VER_1 */ +/** + * struct iwl_beacon_filter_notif_v1 - beacon filter notification + * @average_energy: average energy for the received beacon + * @mac_id: MAC ID the beacon was received for + */ +struct iwl_beacon_filter_notif_v1 { + __le32 average_energy; + __le32 mac_id; +} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_1 */ + +/** + * struct iwl_beacon_filter_notif - beacon filter notification + * @average_energy: average energy for the received beacon + * @link_id: link ID the beacon was received for + */ +struct iwl_beacon_filter_notif { + __le32 average_energy; + __le32 link_id; +} __packed; /* BEACON_FILTER_IN_NTFY_API_S_VER_2 */ + #endif /* __iwl_fw_api_rx_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index fd60a6816150..2879be4b8fcb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2978,7 +2978,7 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc); int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig_type) { - if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) + if (!iwl_trans_device_enabled(fwrt->trans)) return -EIO; if (iwl_trans_dbg_ini_valid(fwrt->trans)) { @@ -3180,13 +3180,13 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) goto out; } - if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) { + if (!iwl_trans_device_enabled(fwrt->trans)) { IWL_ERR(fwrt, "Device is not enabled - cannot dump error\n"); goto out; } /* there's no point in fw dump if the bus is dead */ - if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { + if (iwl_trans_is_dead(fwrt->trans)) { IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); goto out; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 803ba35e7501..3b0e8c43ba4a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -389,6 +389,12 @@ static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v) " %d: %d\n", IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT, has_capa); + has_capa = fw_has_capa(&fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE) ? 1 : 0; + seq_printf(seq, + " %d: %d\n", + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE, + has_capa); seq_puts(seq, "fw_api_ver:\n"); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dump.c b/drivers/net/wireless/intel/iwlwifi/fw/dump.c index 3ec42a4ea801..f633124979ab 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dump.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dump.c @@ -199,7 +199,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu IWL_ERR(trans, "HW error, resetting before reading\n"); /* reset the device */ - err = iwl_trans_sw_reset(trans, true); + err = iwl_trans_sw_reset(trans); if (err) return; @@ -490,7 +490,7 @@ void iwl_fwrt_dump_error_logs(struct iwl_fw_runtime *fwrt) struct iwl_pc_data *pc_data; u8 count; - if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) { + if (!iwl_trans_device_enabled(fwrt->trans)) { IWL_ERR(fwrt, "DEVICE_ENABLED bit is not set. Aborting dump.\n"); return; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index dc1db563c5eb..b7c1ab7a3006 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -407,6 +407,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * for CA from BIOS. * @IWL_UCODE_TLV_CAPA_UHB_CANADA_TAS_SUPPORT: supports %TAS_UHB_ALLOWED_CANADA * @IWL_UCODE_TLV_CAPA_EXT_FSEQ_IMAGE_SUPPORT: external FSEQ image support + * @IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE: Firmware has capability of + * handling raw DSM table data. * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -517,6 +519,7 @@ enum iwl_ucode_tlv_capa { * during assert handling even if the dump isn't split */ IWL_UCODE_TLV_CAPA_RESET_DURING_ASSERT = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 0), + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE = (__force iwl_ucode_tlv_capa_t)(4 * 32 + 1), NUM_IWL_UCODE_TLV_CAPA /* * This construction make both sparse (which cannot increment the previous diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c index 74b90bd92c48..80d8373fccfc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c @@ -344,18 +344,18 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, num_sub_bands = IWL_NUM_SUB_BANDS_V1; gain = cmd->v1.gain[0]; *cmd_size = sizeof(cmd->v1); - cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags); + cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK); if (fwrt->ppag_bios_rev >= 1) { /* in this case FW supports revision 0 */ IWL_DEBUG_RADIO(fwrt, "PPAG table rev is %d, send truncated table\n", fwrt->ppag_bios_rev); } - } else if (cmd_ver >= 2 && cmd_ver <= 6) { + } else if (cmd_ver == 5) { num_sub_bands = IWL_NUM_SUB_BANDS_V2; gain = cmd->v2.gain[0]; *cmd_size = sizeof(cmd->v2); - cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags); + cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK); if (fwrt->ppag_bios_rev == 0) { /* in this case FW supports revisions 1,2 or 3 */ IWL_DEBUG_RADIO(fwrt, @@ -378,17 +378,9 @@ int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, "PPAG MODE bits were read from bios: %d\n", fwrt->ppag_flags); - if (cmd_ver == 6) - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V6_MASK); - else if (cmd_ver == 5) - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK); - else if (cmd_ver < 5) - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK); - - if ((cmd_ver == 1 && - !fw_has_capa(&fwrt->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) || - (cmd_ver == 2 && fwrt->ppag_bios_rev >= 2)) { + if (cmd_ver == 1 && + !fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) { cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n"); } else { @@ -579,6 +571,8 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, { int ret; u32 value; + bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE); u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw, WIDE_ID(REGULATORY_AND_NVM_GROUP, LARI_CONFIG_CHANGE), 1); @@ -593,17 +587,22 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt); ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_11AX_ALLOW_BITMAP; cmd->oem_11ax_allow_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value); if (!ret) { - value &= DSM_UNII4_ALLOW_BITMAP; + if (!has_raw_dsm_capa) + value &= DSM_UNII4_ALLOW_BITMAP; /* Since version 9, bits 4 and 5 are supported - * regardless of this capability. + * regardless of this capability, By pass this masking + * if firmware has capability of accepting raw DSM table. */ - if (cmd_ver < 9 && + if (!has_raw_dsm_capa && cmd_ver < 9 && !fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA)) value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | @@ -614,13 +613,17 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); if (!ret) { - if (cmd_ver < 8) + if (!has_raw_dsm_capa) + value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12; + + if (!has_raw_dsm_capa && cmd_ver < 8) value &= ~ACTIVATE_5G2_IN_WW_MASK; /* Since version 12, bits 5 and 6 are supported - * regardless of this capability. + * regardless of this capability, By pass this masking + * if firmware has capability of accepting raw DSM table. */ - if (cmd_ver < 12 && + if (!has_raw_dsm_capa && cmd_ver < 12 && !fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA)) value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11; @@ -633,13 +636,19 @@ int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, cmd->oem_uhb_allow_bitmap = cpu_to_le32(value); ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP; cmd->force_disable_channels_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_EDT_ALLOWED_BITMAP; cmd->edt_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_wbem(fwrt, &value); if (!ret) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h index 9bed3d573b1e..a07c512b6ed4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.h @@ -159,6 +159,10 @@ enum iwl_dsm_unii4_bitmap { DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK |\ DSM_VALUE_UNII4_CANADA_EN_MSK) +#define DSM_11AX_ALLOW_BITMAP 0xF +#define DSM_EDT_ALLOWED_BITMAP 0x7ffff0 +#define DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP 0x7FF + enum iwl_dsm_values_rfi { DSM_VALUE_RFI_DLVR_DISABLE = BIT(0), DSM_VALUE_RFI_DDR_DISABLE = BIT(1), diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index f62f7c7ee7f3..6d983fe2ee44 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -301,13 +301,17 @@ static void iwl_get_ucode_api_versions(struct iwl_trans *trans, const struct iwl_family_base_params *base = trans->mac_cfg->base; const struct iwl_rf_cfg *cfg = trans->cfg; - if (!base->ucode_api_max) { + /* if the MAC doesn't have range or if its range it higher than the RF's */ + if (!base->ucode_api_max || + (cfg->ucode_api_max && base->ucode_api_min > cfg->ucode_api_max)) { *api_min = cfg->ucode_api_min; *api_max = cfg->ucode_api_max; return; } - if (!cfg->ucode_api_max) { + /* if the RF doesn't have range or if its range it higher than the MAC's */ + if (!cfg->ucode_api_max || + (base->ucode_api_max && cfg->ucode_api_min > base->ucode_api_max)) { *api_min = base->ucode_api_min; *api_max = base->ucode_api_max; return; @@ -1541,7 +1545,7 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) if (!IS_ERR(op_mode)) return op_mode; - if (test_bit(STATUS_TRANS_DEAD, &drv->trans->status)) + if (iwl_trans_is_dead(drv->trans)) break; #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 47ad447b6226..ad857a05d3c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -54,7 +54,7 @@ int iwl_poll_bits_mask(struct iwl_trans *trans, u32 addr, do { if ((iwl_read32(trans, addr) & mask) == (bits & mask)) - return t; + return 0; udelay(IWL_POLL_INTERVAL); t += IWL_POLL_INTERVAL; } while (t < timeout); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 1e4162f1bb44..4424443d2328 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -663,6 +663,8 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { .phy_cap_info[9] = IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB | + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU | (IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED << IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS), .phy_cap_info[10] = @@ -691,44 +693,26 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { .has_eht = true, .eht_cap_elem = { .mac_cap_info[0] = - IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | - IEEE80211_EHT_MAC_CAP0_OM_CONTROL | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 | - IEEE80211_EHT_MAC_CAP0_SCS_TRAFFIC_DESC, - .mac_cap_info[1] = - IEEE80211_EHT_MAC_CAP1_UNSOL_EPCS_PRIO_ACCESS, + IEEE80211_EHT_MAC_CAP0_OM_CONTROL, .phy_cap_info[0] = IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI | - IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE | IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK, .phy_cap_info[1] = IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK | IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK, .phy_cap_info[3] = - IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK, + IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK, .phy_cap_info[4] = - IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | - IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP | IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI, .phy_cap_info[5] = FIELD_PREP_CONST(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK, IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US) | - IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK | IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP | - IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP, - .phy_cap_info[6] = - IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | - IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP, + IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP | + IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF, .phy_cap_info[8] = IEEE80211_EHT_PHY_CAP8_RX_1024QAM_WIDER_BW_DL_OFDMA | IEEE80211_EHT_PHY_CAP8_RX_4096QAM_WIDER_BW_DL_OFDMA, @@ -796,6 +780,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI | IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242, .phy_cap_info[9] = + IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_RESERVED << IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_POS, }, @@ -822,9 +807,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { .has_eht = true, .eht_cap_elem = { .mac_cap_info[0] = - IEEE80211_EHT_MAC_CAP0_OM_CONTROL | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2, + IEEE80211_EHT_MAC_CAP0_OM_CONTROL, .phy_cap_info[0] = IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ | IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI, @@ -1039,48 +1022,17 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << 2); } + /* prior RFs don't have HE, HR RF doesn't have this, later have it */ + if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR1 || + CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_HR2) + iftype_data->he_cap.he_cap_elem.phy_cap_info[9] &= + ~(IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU | + IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU); + if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210 && !is_ap) iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; - switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) { - case IWL_CFG_RF_TYPE_GF: - case IWL_CFG_RF_TYPE_FM: - case IWL_CFG_RF_TYPE_WH: - case IWL_CFG_RF_TYPE_PE: - iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU; - if (!is_ap) - iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |= - IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU; - break; - } - - if (CSR_HW_REV_TYPE(trans->info.hw_rev) == IWL_CFG_MAC_TYPE_GL && - iftype_data->eht_cap.has_eht) { - iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &= - ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | - IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &= - ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | - IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | - IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &= - ~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | - IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] &= - ~IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK; - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[6] &= - ~(IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK | - IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP); - iftype_data->eht_cap.eht_cap_elem.phy_cap_info[5] |= - IEEE80211_EHT_PHY_CAP5_SUPP_EXTRA_EHT_LTF; - } - if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT)) iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_BCAST_TWT; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 9604781dd0b7..810923053053 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -419,7 +419,10 @@ void iwl_trans_op_mode_leave(struct iwl_trans *trans) { might_sleep(); - iwl_trans_pcie_op_mode_leave(trans); + if (trans->mac_cfg->gen2) + iwl_trans_pcie_gen2_op_mode_leave(trans); + else + iwl_trans_pcie_op_mode_leave(trans); cancel_delayed_work_sync(&trans->restart.wk); @@ -495,9 +498,9 @@ void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) } IWL_EXPORT_SYMBOL(iwl_trans_set_pmi); -int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership) +int iwl_trans_sw_reset(struct iwl_trans *trans) { - return iwl_trans_pcie_sw_reset(trans, retake_ownership); + return iwl_trans_pcie_sw_reset(trans, true); } IWL_EXPORT_SYMBOL(iwl_trans_sw_reset); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 103a36d8ee30..d0e658801c2e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -1096,7 +1096,7 @@ static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr, void iwl_trans_set_pmi(struct iwl_trans *trans, bool state); -int iwl_trans_sw_reset(struct iwl_trans *trans, bool retake_ownership); +int iwl_trans_sw_reset(struct iwl_trans *trans); void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); @@ -1230,6 +1230,21 @@ static inline u16 iwl_trans_get_num_rbds(struct iwl_trans *trans) return result; } +static inline void iwl_trans_suppress_cmd_error_once(struct iwl_trans *trans) +{ + set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &trans->status); +} + +static inline bool iwl_trans_device_enabled(struct iwl_trans *trans) +{ + return test_bit(STATUS_DEVICE_ENABLED, &trans->status); +} + +static inline bool iwl_trans_is_dead(struct iwl_trans *trans) +{ + return test_bit(STATUS_TRANS_DEAD, &trans->status); +} + /***************************************************** * PCIe handling *****************************************************/ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/ap.c b/drivers/net/wireless/intel/iwlwifi/mld/ap.c index 26511b49d89a..5c59acc8c4c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/ap.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/ap.c @@ -294,9 +294,20 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, if (ret) return ret; + mld_vif->ap_ibss_active = true; + + if (vif->p2p && mld->p2p_device_vif) { + ret = iwl_mld_mac_fw_action(mld, mld->p2p_device_vif, + FW_CTXT_ACTION_MODIFY); + if (ret) { + mld_vif->ap_ibss_active = false; + goto rm_mcast; + } + } + ret = iwl_mld_add_bcast_sta(mld, vif, link); if (ret) - goto rm_mcast; + goto update_p2p_dev; /* Those keys were configured by the upper layers before starting the * AP. Now that it is started and the bcast and mcast sta were added to @@ -310,12 +321,6 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, iwl_mld_vif_update_low_latency(mld, vif, true, LOW_LATENCY_VIF_TYPE); - mld_vif->ap_ibss_active = true; - - if (vif->p2p && mld->p2p_device_vif) - return iwl_mld_mac_fw_action(mld, mld->p2p_device_vif, - FW_CTXT_ACTION_MODIFY); - /* When the channel context was added, the link is not yet active, so * min_def is always used. Update the PHY again here in case def should * actually be used. @@ -326,6 +331,11 @@ int iwl_mld_start_ap_ibss(struct ieee80211_hw *hw, return 0; rm_bcast: iwl_mld_remove_bcast_sta(mld, vif, link); +update_p2p_dev: + mld_vif->ap_ibss_active = false; + if (vif->p2p && mld->p2p_device_vif) + iwl_mld_mac_fw_action(mld, mld->p2p_device_vif, + FW_CTXT_ACTION_MODIFY); rm_mcast: iwl_mld_remove_mcast_sta(mld, vif, link); return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/coex.c b/drivers/net/wireless/intel/iwlwifi/mld/coex.c index 32c727b3b391..5f262bd43f21 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/coex.c @@ -24,13 +24,17 @@ int iwl_mld_send_bt_init_conf(struct iwl_mld *mld) void iwl_mld_handle_bt_coex_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt) { - const struct iwl_bt_coex_profile_notif *notif = (const void *)pkt->data; + const struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data; const struct iwl_bt_coex_profile_notif zero_notif = {}; /* zeroed structure means that BT is OFF */ bool bt_is_active = memcmp(notif, &zero_notif, sizeof(*notif)); - mld->last_bt_notif = *notif; + if (bt_is_active == mld->bt_is_active) + return; + IWL_DEBUG_INFO(mld, "BT was turned %s\n", bt_is_active ? "ON" : "OFF"); + mld->bt_is_active = bt_is_active; + iwl_mld_emlsr_check_bt(mld); } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/d3.c b/drivers/net/wireless/intel/iwlwifi/mld/d3.c index af12b3d81899..26255246a320 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/d3.c @@ -647,51 +647,6 @@ iwl_mld_set_key_rx_seq(struct ieee80211_key_conf *key, } static void -iwl_mld_d3_update_mcast_key(struct iwl_mld *mld, - struct ieee80211_vif *vif, - struct iwl_mld_wowlan_status *wowlan_status, - struct ieee80211_key_conf *key, - struct iwl_mld_mcast_key_data *key_data) -{ - if (key->keyidx != key_data->id && - (key->keyidx < 4 || key->keyidx > 5)) { - IWL_ERR(mld, - "Unexpected keyId mismatch. Old keyId:%d, New keyId:%d\n", - key->keyidx, key_data->id); - return; - } - - /* All installed keys are sent by the FW, even weren't - * rekeyed during D3. - * We remove an existing key if it has the same index as - * a new key and a rekey has occurred during d3 - */ - if (wowlan_status->num_of_gtk_rekeys && key_data->len) { - if (key->keyidx == 4 || key->keyidx == 5) { - struct iwl_mld_vif *mld_vif = - iwl_mld_vif_from_mac80211(vif); - struct iwl_mld_link *mld_link; - int link_id = vif->active_links ? - __ffs(vif->active_links) : 0; - - mld_link = iwl_mld_link_dereference_check(mld_vif, - link_id); - if (WARN_ON(!mld_link)) - return; - - if (mld_link->igtk == key) - mld_link->igtk = NULL; - mld->num_igtks--; - } - - ieee80211_remove_key(key); - return; - } - - iwl_mld_set_key_rx_seq(key, key_data); -} - -static void iwl_mld_update_ptk_rx_seq(struct iwl_mld *mld, struct iwl_mld_wowlan_status *wowlan_status, struct ieee80211_sta *sta, @@ -759,8 +714,7 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, data->gtk_cipher = key->cipher; status_idx = key->keyidx == wowlan_status->gtk[1].id; - iwl_mld_d3_update_mcast_key(data->mld, vif, wowlan_status, key, - &wowlan_status->gtk[status_idx]); + iwl_mld_set_key_rx_seq(key, &wowlan_status->gtk[status_idx]); break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: @@ -772,9 +726,8 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, return; data->igtk_cipher = key->cipher; - iwl_mld_d3_update_mcast_key(data->mld, vif, - wowlan_status, - key, &wowlan_status->igtk); + if (key->keyidx == wowlan_status->igtk.id) + iwl_mld_set_key_rx_seq(key, &wowlan_status->igtk); } if (key->keyidx == 6 || key->keyidx == 7) { if (WARN_ON(data->bigtk_cipher && @@ -783,9 +736,7 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, data->bigtk_cipher = key->cipher; status_idx = key->keyidx == wowlan_status->bigtk[1].id; - iwl_mld_d3_update_mcast_key(data->mld, vif, - wowlan_status, key, - &wowlan_status->bigtk[status_idx]); + iwl_mld_set_key_rx_seq(key, &wowlan_status->bigtk[status_idx]); } break; default: @@ -795,7 +746,7 @@ iwl_mld_resume_keys_iter(struct ieee80211_hw *hw, data->num_keys++; } -static bool +static void iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, struct iwl_mld *mld, struct iwl_mld_mcast_key_data *key_data, @@ -822,7 +773,7 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key)); if (!key_data->len) - return true; + return; switch (cipher) { case WLAN_CIPHER_SUITE_CCMP: @@ -854,7 +805,7 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, memcpy(conf.conf.key, key_data->key, conf.conf.keylen); key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id); if (IS_ERR(key_config)) - return false; + return; iwl_mld_set_key_rx_seq(key_config, key_data); @@ -862,10 +813,25 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, if (key_config->keyidx == 4 || key_config->keyidx == 5) { struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link_conf); - mld_link->igtk = key_config; - mld->num_igtks++; + + /* If we had more than one rekey, mac80211 will tell us to + * remove the old and add the new so we will update the IGTK in + * drv_set_key + */ + if (mld_link->igtk && mld_link->igtk != key_config) { + /* mark the old IGTK as not in FW */ + mld_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; + mld_link->igtk = key_config; + } + } + + /* Also keep track of the new BIGTK */ + if ((key_config->keyidx == 6 || key_config->keyidx == 7) && + vif->type == NL80211_IFTYPE_STATION) { + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); + + rcu_assign_pointer(mld_vif->bigtks[key_config->keyidx - 6], key_config); } - return true; } static void @@ -877,23 +843,20 @@ iwl_mld_add_all_rekeys(struct ieee80211_vif *vif, int i; for (i = 0; i < ARRAY_SIZE(wowlan_status->gtk); i++) - if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, - &wowlan_status->gtk[i], - link_conf, - key_iter_data->gtk_cipher)) - return; + iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, + &wowlan_status->gtk[i], + link_conf, + key_iter_data->gtk_cipher); - if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, - &wowlan_status->igtk, - link_conf, key_iter_data->igtk_cipher)) - return; + iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, + &wowlan_status->igtk, + link_conf, key_iter_data->igtk_cipher); for (i = 0; i < ARRAY_SIZE(wowlan_status->bigtk); i++) - if (!iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, - &wowlan_status->bigtk[i], - link_conf, - key_iter_data->bigtk_cipher)) - return; + iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, + &wowlan_status->bigtk[i], + link_conf, + key_iter_data->bigtk_cipher); } static bool @@ -1851,6 +1814,7 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld) goto err; } + mld->fw_status.resuming = true; mld->fw_status.in_d3 = false; mld->scan.last_start_time_jiffies = jiffies; @@ -1926,6 +1890,8 @@ int iwl_mld_wowlan_resume(struct iwl_mld *mld) mld->fw_status.in_hw_restart = true; ret = 1; out: + mld->fw_status.resuming = false; + if (resume_data.wowlan_status) { kfree(resume_data.wowlan_status->wake_packet); kfree(resume_data.wowlan_status); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c index 75cc1d8bb90c..cc052b0aa53f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/debugfs.c @@ -86,7 +86,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mld *mld, char *buf, if (count == 6 && !strcmp(buf, "nolog\n")) { mld->fw_status.do_not_dump_once = true; - set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mld->trans->status); + iwl_trans_suppress_cmd_error_once(mld->trans); } /* take the return value to make compiler happy - it will diff --git a/drivers/net/wireless/intel/iwlwifi/mld/key.c b/drivers/net/wireless/intel/iwlwifi/mld/key.c index 0eff13e5ffd5..13462a5ad79a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/key.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/key.c @@ -129,6 +129,12 @@ static int iwl_mld_add_key_to_fw(struct iwl_mld *mld, u32 sta_mask, bool tkip = key->cipher == WLAN_CIPHER_SUITE_TKIP; int max_key_len = sizeof(cmd.u.add.key); +#ifdef CONFIG_PM_SLEEP + /* If there was a rekey in wowlan, FW already has the key */ + if (mld->fw_status.resuming) + return 0; +#endif + if (WARN_ON(!sta_mask)) return -EINVAL; @@ -160,6 +166,12 @@ static void iwl_mld_remove_key_from_fw(struct iwl_mld *mld, u32 sta_mask, .u.remove.key_flags = cpu_to_le32(key_flags), }; +#ifdef CONFIG_PM_SLEEP + /* If there was a rekey in wowlan, FW already removed the key */ + if (mld->fw_status.resuming) + return; +#endif + if (WARN_ON(!sta_mask)) return; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index c65ac6ecbd1d..c48cc3909637 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -649,11 +649,39 @@ void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld, void iwl_mld_handle_omi_status_notif(struct iwl_mld *mld, struct iwl_rx_packet *pkt) { + int ver = iwl_fw_lookup_notif_ver(mld->fw, DATA_PATH_GROUP, + OMI_SEND_STATUS_NOTIF, 1); struct ieee80211_link_sta *link_sta; struct iwl_mld_link *mld_link; struct ieee80211_vif *vif; - vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, &mld_link); + if (ver == 2) { + const struct iwl_omi_send_status_notif *notif = + (const void *)pkt->data; + u32 sta_id = le32_to_cpu(notif->sta_id); + struct iwl_mld_vif *mld_vif; + + if (IWL_FW_CHECK(mld, sta_id >= mld->fw->ucode_capa.num_stations, + "Invalid station %d\n", sta_id)) + return; + + link_sta = wiphy_dereference(mld->wiphy, + mld->fw_id_to_link_sta[sta_id]); + if (IWL_FW_CHECK(mld, !link_sta, "Station does not exist\n")) + return; + + vif = iwl_mld_sta_from_mac80211(link_sta->sta)->vif; + mld_vif = iwl_mld_vif_from_mac80211(vif); + + mld_link = iwl_mld_link_dereference_check(mld_vif, + link_sta->link_id); + if (WARN(!mld_link, "Link %d does not exist\n", + link_sta->link_id)) + return; + } else { + vif = iwl_mld_get_omi_bw_reduction_pointers(mld, &link_sta, + &mld_link); + } if (IWL_FW_CHECK(mld, !vif, "unexpected OMI notification\n")) return; @@ -783,6 +811,7 @@ iwl_mld_init_link(struct iwl_mld *mld, struct ieee80211_bss_conf *link, { mld_link->vif = link->vif; mld_link->link_id = link->link_id; + mld_link->average_beacon_energy = 0; iwl_mld_init_internal_sta(&mld_link->bcast_sta); iwl_mld_init_internal_sta(&mld_link->mcast_sta); @@ -1216,3 +1245,22 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld, return grade; } EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_get_link_grade); + +void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt) +{ + const struct iwl_beacon_filter_notif *notif = (const void *)pkt->data; + u32 link_id = le32_to_cpu(notif->link_id); + struct ieee80211_bss_conf *link_conf = + iwl_mld_fw_id_to_link_conf(mld, link_id); + struct iwl_mld_link *mld_link; + + if (IWL_FW_CHECK(mld, !link_conf, "invalid link ID %d\n", link_id)) + return; + + mld_link = iwl_mld_link_from_mac80211(link_conf); + if (WARN_ON_ONCE(!mld_link)) + return; + + mld_link->average_beacon_energy = le32_to_cpu(notif->average_energy); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h index 39f04aae5579..881823be07ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h @@ -41,6 +41,8 @@ struct iwl_probe_resp_data { * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS. * @mon_sta: station used for TX injection in monitor interface. * @link_id: over the air link ID + * @average_beacon_energy: average beacon energy for beacons received during + * client connections * @ap_early_keys: The firmware cannot install keys before bcast/mcast STAs, * but higher layers work differently, so we store the keys here for * later installation. @@ -85,6 +87,7 @@ struct iwl_mld_link { /* we can only have 2 GTK + 2 IGTK + 2 BIGTK active at a time */ struct ieee80211_key_conf *ap_early_keys[6]; + u32 average_beacon_energy; bool silent_deactivation; struct iwl_probe_resp_data __rcu *probe_resp_data; }; @@ -150,4 +153,7 @@ void iwl_mld_omi_ap_changed_bw(struct iwl_mld *mld, struct ieee80211_bss_conf *link_conf, enum ieee80211_sta_rx_bandwidth bw); +void iwl_mld_handle_beacon_filter_notif(struct iwl_mld *mld, + struct iwl_rx_packet *pkt); + #endif /* __iwl_mld_link_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c index 19cb562e7a73..16bb1b4904f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mcc.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mcc.c @@ -15,7 +15,7 @@ /* It is the caller's responsibility to free the pointer returned here */ static struct iwl_mcc_update_resp_v8 * -iwl_mld_parse_mcc_update_resp_v8(const struct iwl_rx_packet *pkt) +iwl_mld_copy_mcc_resp(const struct iwl_rx_packet *pkt) { const struct iwl_mcc_update_resp_v8 *mcc_resp_v8 = (const void *)pkt->data; int n_channels = __le32_to_cpu(mcc_resp_v8->n_channels); @@ -34,41 +34,9 @@ iwl_mld_parse_mcc_update_resp_v8(const struct iwl_rx_packet *pkt) /* It is the caller's responsibility to free the pointer returned here */ static struct iwl_mcc_update_resp_v8 * -iwl_mld_parse_mcc_update_resp_v5_v6(const struct iwl_rx_packet *pkt) -{ - const struct iwl_mcc_update_resp_v4 *mcc_resp_v4 = (const void *)pkt->data; - struct iwl_mcc_update_resp_v8 *resp_cp; - int n_channels = __le32_to_cpu(mcc_resp_v4->n_channels); - int resp_len; - - if (iwl_rx_packet_payload_len(pkt) != - struct_size(mcc_resp_v4, channels, n_channels)) - return ERR_PTR(-EINVAL); - - resp_len = struct_size(resp_cp, channels, n_channels); - resp_cp = kzalloc(resp_len, GFP_KERNEL); - if (!resp_cp) - return ERR_PTR(-ENOMEM); - - resp_cp->status = mcc_resp_v4->status; - resp_cp->mcc = mcc_resp_v4->mcc; - resp_cp->cap = cpu_to_le32(le16_to_cpu(mcc_resp_v4->cap)); - resp_cp->source_id = mcc_resp_v4->source_id; - resp_cp->geo_info = mcc_resp_v4->geo_info; - resp_cp->n_channels = mcc_resp_v4->n_channels; - memcpy(resp_cp->channels, mcc_resp_v4->channels, - n_channels * sizeof(__le32)); - - return resp_cp; -} - -/* It is the caller's responsibility to free the pointer returned here */ -static struct iwl_mcc_update_resp_v8 * iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2, enum iwl_mcc_source src_id) { - int resp_ver = iwl_fw_lookup_notif_ver(mld->fw, LONG_GROUP, - MCC_UPDATE_CMD, 0); struct iwl_mcc_update_cmd mcc_update_cmd = { .mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]), .source_id = (u8)src_id, @@ -93,23 +61,7 @@ iwl_mld_update_mcc(struct iwl_mld *mld, const char *alpha2, pkt = cmd.resp_pkt; - /* For Wifi-7 radios, we get version 8 - * For Wifi-6E radios, we get version 6 - * For Wifi-6 radios, we get version 5, but 5, 6, and 4 are compatible. - */ - switch (resp_ver) { - case 5: - case 6: - resp_cp = iwl_mld_parse_mcc_update_resp_v5_v6(pkt); - break; - case 8: - resp_cp = iwl_mld_parse_mcc_update_resp_v8(pkt); - break; - default: - IWL_FW_CHECK_FAILED(mld, "Unknown MCC_UPDATE_CMD version %d\n", resp_ver); - resp_cp = ERR_PTR(-EINVAL); - } - + resp_cp = iwl_mld_copy_mcc_resp(pkt); if (IS_ERR(resp_cp)) goto exit; @@ -177,11 +129,15 @@ iwl_mld_get_regdomain(struct iwl_mld *mld, mld->mcc_src = resp->source_id; - if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing, - le16_to_cpu(resp->mcc))) - ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING); - else - __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mld->hw->flags); + /* FM is the earliest supported and later always do puncturing */ + if (CSR_HW_RFID_TYPE(mld->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_FM) { + if (!iwl_puncturing_is_allowed_in_bios(mld->bios_enable_puncturing, + le16_to_cpu(resp->mcc))) + ieee80211_hw_set(mld->hw, DISALLOW_PUNCTURING); + else + __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, + mld->hw->flags); + } out: kfree(resp); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.c b/drivers/net/wireless/intel/iwlwifi/mld/mld.c index 7ade5b714457..e7cbfb9009af 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.c @@ -255,6 +255,7 @@ static const struct iwl_hcmd_names iwl_mld_data_path_names[] = { HCMD_NAME(ESR_MODE_NOTIF), HCMD_NAME(MONITOR_NOTIF), HCMD_NAME(TLC_MNG_UPDATE_NOTIF), + HCMD_NAME(BEACON_FILTER_IN_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), }; @@ -630,7 +631,7 @@ iwl_mld_nic_error(struct iwl_op_mode *op_mode, enum iwl_fw_error_type type) { struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode); - bool trans_dead = test_bit(STATUS_TRANS_DEAD, &mld->trans->status); + bool trans_dead = iwl_trans_is_dead(mld->trans); if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL) IWL_ERR(mld, "Command queue full!\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mld.h b/drivers/net/wireless/intel/iwlwifi/mld/mld.h index 241ab3a00e56..8bc4749599ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mld.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mld.h @@ -127,6 +127,7 @@ * cleanup using iwl_mld_free_internal_sta * @netdetect: indicates the FW is in suspend mode with netdetect configured * @p2p_device_vif: points to the p2p device vif if exists + * @bt_is_active: indicates that BT is active * @dev: pointer to device struct. For printing purposes * @trans: pointer to the transport layer * @cfg: pointer to the device configuration @@ -149,6 +150,7 @@ * @running: true if the firmware is running * @do_not_dump_once: true if firmware dump must be prevented once * @in_d3: indicates FW is in suspend mode and should be resumed + * @resuming: indicates the driver is resuming from wowlan * @in_hw_restart: indicates that we are currently in restart flow. * rather than restarted. Should be unset upon restart. * @radio_kill: bitmap of radio kill status @@ -188,7 +190,6 @@ * @ptp_data: data of the PTP clock * @time_sync: time sync data. * @ftm_initiator: FTM initiator data - * @last_bt_notif: last received BT Coex notif */ struct iwl_mld { /* Add here fields that need clean up on restart */ @@ -213,7 +214,7 @@ struct iwl_mld { bool netdetect; #endif /* CONFIG_PM_SLEEP */ struct ieee80211_vif *p2p_device_vif; - struct iwl_bt_coex_profile_notif last_bt_notif; + bool bt_is_active; ); struct ieee80211_link_sta __rcu *fw_id_to_link_sta[IWL_STATION_COUNT_MAX]; /* And here fields that survive a fw restart */ @@ -237,6 +238,7 @@ struct iwl_mld { do_not_dump_once:1, #ifdef CONFIG_PM_SLEEP in_d3:1, + resuming:1, #endif in_hw_restart:1; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index be66a71a0fd7..e57f5388fe77 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -689,42 +689,6 @@ s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld, #undef RSSI_THRESHOLD } -#define IWL_MLD_BT_COEX_DISABLE_EMLSR_RSSI_THRESH -69 -#define IWL_MLD_BT_COEX_ENABLE_EMLSR_RSSI_THRESH -63 -#define IWL_MLD_BT_COEX_WIFI_LOSS_THRESH 7 - -VISIBLE_IF_IWLWIFI_KUNIT -bool -iwl_mld_bt_allows_emlsr(struct iwl_mld *mld, struct ieee80211_bss_conf *link, - bool check_entry) -{ - int bt_penalty, rssi_thresh; - s32 link_rssi; - - if (WARN_ON_ONCE(!link->bss)) - return false; - - link_rssi = MBM_TO_DBM(link->bss->signal); - rssi_thresh = check_entry ? - IWL_MLD_BT_COEX_ENABLE_EMLSR_RSSI_THRESH : - IWL_MLD_BT_COEX_DISABLE_EMLSR_RSSI_THRESH; - /* No valid RSSI - force to take low rssi */ - if (!link_rssi) - link_rssi = rssi_thresh - 1; - - if (link_rssi > rssi_thresh) - bt_penalty = max(mld->last_bt_notif.wifi_loss_mid_high_rssi[PHY_BAND_24][0], - mld->last_bt_notif.wifi_loss_mid_high_rssi[PHY_BAND_24][1]); - else - bt_penalty = max(mld->last_bt_notif.wifi_loss_low_rssi[PHY_BAND_24][0], - mld->last_bt_notif.wifi_loss_low_rssi[PHY_BAND_24][1]); - - IWL_DEBUG_EHT(mld, "BT penalty for link-id %0X is %d\n", - link->link_id, bt_penalty); - return bt_penalty < IWL_MLD_BT_COEX_WIFI_LOSS_THRESH; -} -EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_bt_allows_emlsr); - static u32 iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld, struct ieee80211_vif *vif, @@ -739,8 +703,7 @@ iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld, if (WARN_ON_ONCE(!conf)) return IWL_MLD_EMLSR_EXIT_INVALID; - if (link->chandef->chan->band == NL80211_BAND_2GHZ && - !iwl_mld_bt_allows_emlsr(mld, conf, true)) + if (link->chandef->chan->band == NL80211_BAND_2GHZ && mld->bt_is_active) ret |= IWL_MLD_EMLSR_EXIT_BT_COEX; if (link->signal < @@ -1078,41 +1041,30 @@ static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); - const struct iwl_bt_coex_profile_notif zero_notif = {}; struct iwl_mld *mld = mld_vif->mld; struct ieee80211_bss_conf *link; unsigned int link_id; - const struct iwl_bt_coex_profile_notif *notif = &mld->last_bt_notif; if (!iwl_mld_vif_has_emlsr_cap(vif)) return; - /* zeroed structure means that BT is OFF */ - if (!memcmp(notif, &zero_notif, sizeof(*notif))) { + if (!mld->bt_is_active) { iwl_mld_retry_emlsr(mld, vif); return; } - for_each_vif_active_link(vif, link, link_id) { - bool emlsr_active, emlsr_allowed; + /* BT is turned ON but we are not in EMLSR, nothing to do */ + if (!iwl_mld_emlsr_active(vif)) + return; - if (WARN_ON(!link->chanreq.oper.chan)) - continue; + /* In EMLSR and BT is turned ON */ - if (link->chanreq.oper.chan->band != NL80211_BAND_2GHZ) + for_each_vif_active_link(vif, link, link_id) { + if (WARN_ON(!link->chanreq.oper.chan)) continue; - emlsr_active = iwl_mld_emlsr_active(vif); - emlsr_allowed = iwl_mld_bt_allows_emlsr(mld, link, - !emlsr_active); - if (emlsr_allowed && !emlsr_active) { - iwl_mld_retry_emlsr(mld, vif); - return; - } - - if (!emlsr_allowed && emlsr_active) { - iwl_mld_exit_emlsr(mld, vif, - IWL_MLD_EMLSR_EXIT_BT_COEX, + if (link->chanreq.oper.chan->band == NL80211_BAND_2GHZ) { + iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BT_COEX, iwl_mld_get_primary_link(vif)); return; } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h index 704f64134798..d936589fe39d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h @@ -163,10 +163,6 @@ void iwl_mld_emlsr_block_tmp_non_bss(struct iwl_mld *mld); u32 iwl_mld_emlsr_pair_state(struct ieee80211_vif *vif, struct iwl_mld_link_sel_data *a, struct iwl_mld_link_sel_data *b); - -bool iwl_mld_bt_allows_emlsr(struct iwl_mld *mld, - struct ieee80211_bss_conf *link, - bool entry_criteria); #endif void iwl_mld_start_ignoring_tpt_updates(struct iwl_mld *mld); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/notif.c b/drivers/net/wireless/intel/iwlwifi/mld/notif.c index c0e62d46aba6..262d8e25e62a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/notif.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/notif.c @@ -349,8 +349,10 @@ CMD_VERSIONS(time_msmt_notif, CMD_VERSIONS(time_sync_confirm_notif, CMD_VER_ENTRY(1, iwl_time_msmt_cfm_notify)) CMD_VERSIONS(omi_status_notif, - CMD_VER_ENTRY(1, iwl_omi_send_status_notif)) -CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(9, iwl_tof_range_rsp_ntfy)) + CMD_VER_ENTRY(1, iwl_omi_send_status_notif_v1) + CMD_VER_ENTRY(2, iwl_omi_send_status_notif)) +CMD_VERSIONS(ftm_resp_notif, CMD_VER_ENTRY(10, iwl_tof_range_rsp_ntfy)) +CMD_VERSIONS(beacon_filter_notif, CMD_VER_ENTRY(2, iwl_beacon_filter_notif)) DEFINE_SIMPLE_CANCELLATION(session_prot, iwl_session_prot_notif, mac_link_id) DEFINE_SIMPLE_CANCELLATION(tlc, iwl_tlc_update_notif, sta_id) @@ -368,6 +370,7 @@ DEFINE_SIMPLE_CANCELLATION(uapsd_misbehaving_ap, iwl_uapsd_misbehaving_ap_notif, mac_id) #define iwl_mld_cancel_omi_status_notif iwl_mld_always_cancel DEFINE_SIMPLE_CANCELLATION(ftm_resp, iwl_tof_range_rsp_ntfy, request_id) +DEFINE_SIMPLE_CANCELLATION(beacon_filter, iwl_beacon_filter_notif, link_id) /** * DOC: Handlers for fw notifications @@ -460,6 +463,8 @@ const struct iwl_rx_handler iwl_mld_rx_handlers[] = { time_sync_confirm_notif, RX_HANDLER_ASYNC) RX_HANDLER_OF_LINK(DATA_PATH_GROUP, OMI_SEND_STATUS_NOTIF, omi_status_notif) + RX_HANDLER_OF_LINK(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF, + beacon_filter_notif) RX_HANDLER_OF_FTM_REQ(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF, ftm_resp_notif) }; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/power.c b/drivers/net/wireless/intel/iwlwifi/mld/power.c index 8cc276041360..f664b277adf7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/power.c @@ -377,23 +377,15 @@ int iwl_mld_set_tx_power(struct iwl_mld *mld, u16 u_tx_power = tx_power == IWL_DEFAULT_MAX_TX_POWER ? IWL_DEV_MAX_TX_POWER : 8 * tx_power; struct iwl_dev_tx_power_cmd cmd = { - /* Those fields sit on the same place for v9 and v10 */ .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_LINK), .common.pwr_restriction = cpu_to_le16(u_tx_power), }; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - int len = sizeof(cmd.common); + int len = sizeof(cmd.common) + sizeof(cmd.v10); if (WARN_ON(!mld_link)) return -ENODEV; cmd.common.link_id = cpu_to_le32(mld_link->fw_id); - if (cmd_ver == 10) - len += sizeof(cmd.v10); - else if (cmd_ver == 9) - len += sizeof(cmd.v9); - return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len); } diff --git a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c index 326c300470ea..75d2f5cb23a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c @@ -71,40 +71,17 @@ void iwl_mld_get_bios_tables(struct iwl_mld *mld) static int iwl_mld_geo_sar_init(struct iwl_mld *mld) { u32 cmd_id = WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD); - union iwl_geo_tx_power_profiles_cmd cmd; - u16 len; - u32 n_bands; - __le32 sk = cpu_to_le32(0); - int ret; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - - BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) != - offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, ops)); - - cmd.v4.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES); - /* Only set to South Korea if the table revision is 1 */ - if (mld->fwrt.geo_rev == 1) - sk = cpu_to_le32(1); - - if (cmd_ver == 5) { - len = sizeof(cmd.v5); - n_bands = ARRAY_SIZE(cmd.v5.table[0]); - cmd.v5.table_revision = sk; - } else if (cmd_ver == 4) { - len = sizeof(cmd.v4); - n_bands = ARRAY_SIZE(cmd.v4.table[0]); - cmd.v4.table_revision = sk; - } else { - return -EOPNOTSUPP; - } + __le32 sk = cpu_to_le32(mld->fwrt.geo_rev == 1 ? 1 : 0); + union iwl_geo_tx_power_profiles_cmd cmd = { + .v5.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES), + .v5.table_revision = sk, + }; + int ret; - BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) != - offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table)); - /* the table is at the same position for all versions, so set use v4 */ - ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v4.table[0][0], - n_bands, BIOS_GEO_MAX_PROFILE_NUM); + ret = iwl_sar_geo_fill_table(&mld->fwrt, &cmd.v5.table[0][0], + ARRAY_SIZE(cmd.v5.table[0]), + BIOS_GEO_MAX_PROFILE_NUM); /* It is a valid scenario to not support SAR, or miss wgds table, * but in that case there is no need to send the command. @@ -112,7 +89,7 @@ static int iwl_mld_geo_sar_init(struct iwl_mld *mld) if (ret) return 0; - return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len); + return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, sizeof(cmd.v5)); } int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) @@ -120,37 +97,20 @@ int iwl_mld_config_sar_profile(struct iwl_mld *mld, int prof_a, int prof_b) u32 cmd_id = REDUCE_TX_POWER_CMD; struct iwl_dev_tx_power_cmd cmd = { .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS), + .v10.flags = cpu_to_le32(mld->fwrt.reduced_power_flags), }; - __le16 *per_chain; int ret; - u16 len = sizeof(cmd.common); - u32 n_subbands; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - - if (cmd_ver == 10) { - len += sizeof(cmd.v10); - n_subbands = IWL_NUM_SUB_BANDS_V2; - per_chain = &cmd.v10.per_chain[0][0][0]; - cmd.v10.flags = - cpu_to_le32(mld->fwrt.reduced_power_flags); - } else if (cmd_ver == 9) { - len += sizeof(cmd.v9); - n_subbands = IWL_NUM_SUB_BANDS_V1; - per_chain = &cmd.v9.per_chain[0][0]; - } else { - return -EOPNOTSUPP; - } /* TODO: CDB - support IWL_NUM_CHAIN_TABLES_V2 */ - ret = iwl_sar_fill_profile(&mld->fwrt, per_chain, - IWL_NUM_CHAIN_TABLES, - n_subbands, prof_a, prof_b); + ret = iwl_sar_fill_profile(&mld->fwrt, &cmd.v10.per_chain[0][0][0], + IWL_NUM_CHAIN_TABLES, IWL_NUM_SUB_BANDS_V2, + prof_a, prof_b); /* return on error or if the profile is disabled (positive number) */ if (ret) return ret; - return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, len); + return iwl_mld_send_cmd_pdu(mld, cmd_id, &cmd, + sizeof(cmd.common) + sizeof(cmd.v10)); } int iwl_mld_init_sar(struct iwl_mld *mld) @@ -238,34 +198,50 @@ void iwl_mld_configure_lari(struct iwl_mld *mld) struct iwl_lari_config_change_cmd cmd = { .config_bitmap = iwl_get_lari_config_bitmap(fwrt), }; + bool has_raw_dsm_capa = fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FW_ACCEPTS_RAW_DSM_TABLE); int ret; u32 value; ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_11AX_ALLOW_BITMAP; cmd.oem_11ax_allow_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value); - if (!ret) - cmd.oem_unii4_allow_bitmap = - cpu_to_le32(value &= DSM_UNII4_ALLOW_BITMAP); + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_UNII4_ALLOW_BITMAP; + cmd.oem_unii4_allow_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12; cmd.chan_state_active_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value); if (!ret) cmd.oem_uhb_allow_bitmap = cpu_to_le32(value); ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_FORCE_DISABLE_CHANNELS_ALLOWED_BITMAP; cmd.force_disable_channels_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD, &value); - if (!ret) + if (!ret) { + if (!has_raw_dsm_capa) + value &= DSM_EDT_ALLOWED_BITMAP; cmd.edt_bitmap = cpu_to_le32(value); + } ret = iwl_bios_get_wbem(fwrt, &value); if (!ret) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/rx.c b/drivers/net/wireless/intel/iwlwifi/mld/rx.c index ce0093d5c638..3d19cec3f696 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/rx.c @@ -143,7 +143,55 @@ void iwl_mld_pass_packet_to_mac80211(struct iwl_mld *mld, } EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_pass_packet_to_mac80211); -static void iwl_mld_fill_signal(struct iwl_mld *mld, +static bool iwl_mld_used_average_energy(struct iwl_mld *mld, int link_id, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_bss_conf *link_conf; + struct iwl_mld_link *mld_link; + + if (unlikely(!hdr || link_id < 0)) + return false; + + if (likely(!ieee80211_is_beacon(hdr->frame_control))) + return false; + + /* + * if link ID is >= valid ones then that means the RX + * was on the AUX link and no correction is needed + */ + if (link_id >= mld->fw->ucode_capa.num_links) + return false; + + /* for the link conf lookup */ + guard(rcu)(); + + link_conf = rcu_dereference(mld->fw_id_to_bss_conf[link_id]); + if (!link_conf) + return false; + + mld_link = iwl_mld_link_from_mac80211(link_conf); + if (!mld_link) + return false; + + /* + * If we know the link by link ID then the frame was + * received for the link, so by filtering it means it + * was from the AP the link is connected to. + */ + + /* skip also in case we don't have it (yet) */ + if (!mld_link->average_beacon_energy) + return false; + + IWL_DEBUG_STATS(mld, "energy override by average %d\n", + mld_link->average_beacon_energy); + rx_status->signal = -mld_link->average_beacon_energy; + return true; +} + +static void iwl_mld_fill_signal(struct iwl_mld *mld, int link_id, + struct ieee80211_hdr *hdr, struct ieee80211_rx_status *rx_status, struct iwl_mld_rx_phy_data *phy_data) { @@ -159,9 +207,11 @@ static void iwl_mld_fill_signal(struct iwl_mld *mld, IWL_DEBUG_STATS(mld, "energy in A %d B %d, and max %d\n", energy_a, energy_b, max_energy); + if (iwl_mld_used_average_energy(mld, link_id, hdr, rx_status)) + return; + rx_status->signal = max_energy; - rx_status->chains = - (rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK); rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; } @@ -1160,7 +1210,10 @@ static void iwl_mld_add_rtap_sniffer_config(struct iwl_mld *mld, } #endif -static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb, +/* Note: hdr can be NULL */ +static void iwl_mld_rx_fill_status(struct iwl_mld *mld, int link_id, + struct ieee80211_hdr *hdr, + struct sk_buff *skb, struct iwl_mld_rx_phy_data *phy_data, int queue) { @@ -1182,7 +1235,7 @@ static void iwl_mld_rx_fill_status(struct iwl_mld *mld, struct sk_buff *skb, phy_data->phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE) rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE; - iwl_mld_fill_signal(mld, rx_status, phy_data); + iwl_mld_fill_signal(mld, link_id, hdr, rx_status, phy_data); /* This may be overridden by iwl_mld_rx_he() to HE_RU */ switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { @@ -1733,7 +1786,7 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi, struct sk_buff *skb; size_t mpdu_desc_size = sizeof(*mpdu_desc); bool drop = false; - u8 crypto_len = 0, band; + u8 crypto_len = 0, band, link_id; u32 pkt_len = iwl_rx_packet_payload_len(pkt); u32 mpdu_len; enum iwl_mld_reorder_result reorder_res; @@ -1822,7 +1875,10 @@ void iwl_mld_rx_mpdu(struct iwl_mld *mld, struct napi_struct *napi, SCHED_SCAN_PASS_ALL_STATE_FOUND; } - iwl_mld_rx_fill_status(mld, skb, &phy_data, queue); + link_id = u8_get_bits(mpdu_desc->mac_phy_band, + IWL_RX_MPDU_MAC_PHY_BAND_LINK_MASK); + + iwl_mld_rx_fill_status(mld, link_id, hdr, skb, &phy_data, queue); if (iwl_mld_rx_crypto(mld, sta, hdr, rx_status, mpdu_desc, queue, le32_to_cpu(pkt->len_n_flags), &crypto_len)) @@ -2035,7 +2091,8 @@ void iwl_mld_rx_monitor_no_data(struct iwl_mld *mld, struct napi_struct *napi, rx_status->freq = ieee80211_channel_to_frequency(channel, rx_status->band); - iwl_mld_rx_fill_status(mld, skb, &phy_data, queue); + /* link ID is ignored for NULL header */ + iwl_mld_rx_fill_status(mld, -1, NULL, skb, &phy_data, queue); /* No more radiotap info should be added after this point. * Mark it as mac header for upper layers to know where diff --git a/drivers/net/wireless/intel/iwlwifi/mld/scan.c b/drivers/net/wireless/intel/iwlwifi/mld/scan.c index 63d5d39bb083..479a76a94aa8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/scan.c @@ -359,7 +359,7 @@ iwl_mld_scan_fits(struct iwl_mld *mld, int n_ssids, struct ieee80211_scan_ies *ies, int n_channels) { return ((n_ssids <= PROBE_OPTION_MAX) && - (n_channels <= mld->fw->ucode_capa.n_scan_channels) & + (n_channels <= mld->fw->ucode_capa.n_scan_channels) && (ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] + ies->len[NL80211_BAND_6GHZ] <= iwl_mld_scan_max_template_size())); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile b/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile index 3e2ae6020613..36317feb923b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -iwlmld-tests-y += module.o hcmd.o utils.o link.o rx.o agg.o link-selection.o emlsr_with_bt.o +iwlmld-tests-y += module.o hcmd.o utils.o link.o rx.o agg.o link-selection.o ccflags-y += -I$(src)/../ obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmld-tests.o diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c deleted file mode 100644 index 91556ee5c142..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/emlsr_with_bt.c +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * KUnit tests for link selection functions - * - * Copyright (C) 2025 Intel Corporation - */ -#include <kunit/static_stub.h> - -#include "utils.h" -#include "mld.h" -#include "mlo.h" - -static const struct emlsr_with_bt_test_case { - const char *desc; - struct { - struct iwl_bt_coex_profile_notif notif; - s32 signal; - bool check_entry; - } input; - bool emlsr_allowed; -} emlsr_with_bt_cases[] = { - { - .desc = "BT penalty(exit) with low rssi 4.5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {7, 9}, - .signal = -69, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(exit) from high rssi 5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {5, 5}, - .signal = -68, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(exit) with low rssi 8: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {4, 5}, - .signal = -69, - .check_entry = false, - }, - .emlsr_allowed = false, - }, - { - .desc = "BT penalty(exit) from high rssi 9: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {9, 9}, - .signal = -68, - .check_entry = false, - }, - .emlsr_allowed = false, - }, - { - .desc = "BT penalty(entry) with low rssi 4.5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {7, 9}, - .signal = -63, - .check_entry = true, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(entry) from high rssi 5: emlsr allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {5, 5}, - .signal = -62, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(entry) with low rssi 8: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {7, 9}, - .notif.wifi_loss_mid_high_rssi[1] = {4, 5}, - .signal = -63, - .check_entry = false, - }, - .emlsr_allowed = true, - }, - { - .desc = "BT penalty(entry) from high rssi 9: emlsr not allowed", - .input = { - .notif.wifi_loss_low_rssi[1] = {4, 5}, - .notif.wifi_loss_mid_high_rssi[1] = {9, 9}, - .signal = -62, - .check_entry = true, - }, - .emlsr_allowed = false, - }, -}; - -KUNIT_ARRAY_PARAM_DESC(emlsr_with_bt, emlsr_with_bt_cases, desc); - -static void test_emlsr_with_bt(struct kunit *test) -{ - struct iwl_mld *mld = test->priv; - const struct emlsr_with_bt_test_case *test_param = - (const void *)(test->param_value); - struct ieee80211_vif *vif = - iwlmld_kunit_add_vif(true, NL80211_IFTYPE_STATION); - struct ieee80211_bss_conf *link = iwlmld_kunit_add_link(vif, 1); - bool actual_value = false; - - KUNIT_ALLOC_AND_ASSERT(test, link->bss); - - /* Extract test case parameters */ - link->bss->signal = DBM_TO_MBM(test_param->input.signal); - memcpy(&mld->last_bt_notif, &test_param->input.notif, - sizeof(struct iwl_bt_coex_profile_notif)); - - actual_value = iwl_mld_bt_allows_emlsr(mld, link, - test_param->input.check_entry); - /* Assert that the returned value matches the expected emlsr_allowed */ - KUNIT_EXPECT_EQ(test, actual_value, test_param->emlsr_allowed); -} - -static struct kunit_case emlsr_with_bt_test_cases[] = { - KUNIT_CASE_PARAM(test_emlsr_with_bt, emlsr_with_bt_gen_params), - {}, -}; - -static struct kunit_suite emlsr_with_bt = { - .name = "iwlmld-emlsr-with-bt-tests", - .test_cases = emlsr_with_bt_test_cases, - .init = iwlmld_kunit_test_init, -}; - -kunit_test_suite(emlsr_with_bt); diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c index 94a037bec1fa..766c24db3613 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c @@ -287,7 +287,6 @@ static void test_iwl_mld_link_pair_allows_emlsr(struct kunit *test) const struct link_pair_case *params = test->param_value; struct iwl_mld *mld = test->priv; struct ieee80211_vif *vif; - struct ieee80211_bss_conf *link; /* link A is the primary and link B is the secondary */ struct iwl_mld_link_sel_data a = { .chandef = params->chandef_a, @@ -311,11 +310,6 @@ static void test_iwl_mld_link_pair_allows_emlsr(struct kunit *test) wiphy_lock(mld->wiphy); - link = wiphy_dereference(mld->wiphy, vif->link_conf[a.link_id]); - KUNIT_ALLOC_AND_ASSERT(test, link->bss); - link = wiphy_dereference(mld->wiphy, vif->link_conf[b.link_id]); - KUNIT_ALLOC_AND_ASSERT(test, link->bss); - /* Simulate channel load */ if (params->primary_link_active) { struct iwl_mld_phy *phy = diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 66749dc38fc5..ef9bab042902 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -211,7 +211,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, } struct wowlan_key_rsc_tsc_data { - struct iwl_wowlan_rsc_tsc_params_cmd_v4 *rsc_tsc; + struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 *rsc_tsc; bool have_rsc_tsc; }; @@ -236,16 +236,16 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw, u64 pn64; tkip_sc = - data->rsc_tsc->params.all_tsc_rsc.tkip.unicast_rsc; + data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc; tkip_tx_sc = - &data->rsc_tsc->params.all_tsc_rsc.tkip.tsc; + &data->rsc_tsc->all_tsc_rsc.tkip.tsc; pn64 = atomic64_read(&key->tx_pn); tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64)); tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64)); } else { tkip_sc = - data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc; + data->rsc_tsc->all_tsc_rsc.tkip.multicast_rsc; } /* @@ -269,15 +269,15 @@ static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw, u64 pn64; aes_sc = - data->rsc_tsc->params.all_tsc_rsc.aes.unicast_rsc; + data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; aes_tx_sc = - &data->rsc_tsc->params.all_tsc_rsc.aes.tsc; + &data->rsc_tsc->all_tsc_rsc.aes.tsc; pn64 = atomic64_read(&key->tx_pn); aes_tx_sc->pn = cpu_to_le64(pn64); } else { aes_sc = - data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc; + data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; } /* @@ -480,30 +480,21 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm, else ret = 0; kfree(data.rsc); - } else if (ver == 4 || ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) { + } else if (ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) { struct wowlan_key_rsc_tsc_data data = {}; - int size; data.rsc_tsc = kzalloc(sizeof(*data.rsc_tsc), GFP_KERNEL); if (!data.rsc_tsc) return -ENOMEM; - if (ver == 4) { - size = sizeof(*data.rsc_tsc); - data.rsc_tsc->sta_id = - cpu_to_le32(mvm_link->ap_sta_id); - } else { - /* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */ - size = sizeof(data.rsc_tsc->params); - } - ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_get_rsc_tsc_data, &data); if (data.have_rsc_tsc) ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM, - CMD_ASYNC, size, + CMD_ASYNC, + sizeof(data.rsc_tsc), data.rsc_tsc); else ret = 0; @@ -1689,7 +1680,7 @@ static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm, } static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status, - union iwl_all_tsc_rsc *sc) + union iwl_all_tsc_rsc *sc, u8 key_idx) { int i; @@ -1704,7 +1695,7 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status, &status->gtk_seq[0].aes.seq[i]); } status->gtk_seq[0].valid = true; - status->gtk_seq[0].key_id = -1; + status->gtk_seq[0].key_id = key_idx; /* PTK TX counter */ status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) | @@ -1795,23 +1786,7 @@ static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key, if (!status->gtk_seq[i].valid) continue; - /* Handle the case where we know the key ID */ - if (status->gtk_seq[i].key_id == key->keyidx) { - s8 new_key_id = -1; - - if (status->num_of_gtk_rekeys) - new_key_id = status->gtk[0].flags & - IWL_WOWLAN_GTK_IDX_MASK; - - /* Don't install a new key's value to an old key */ - if (new_key_id != key->keyidx) - iwl_mvm_set_key_rx_seq_idx(key, status, i); - continue; - } - - /* handle the case where we didn't, last key only */ - if (status->gtk_seq[i].key_id == -1 && - (!status->num_of_gtk_rekeys)) + if (status->gtk_seq[i].key_id == key->keyidx) iwl_mvm_set_key_rx_seq_idx(key, status, i); } } @@ -1901,17 +1876,10 @@ iwl_mvm_d3_update_igtk_bigtk(struct iwl_wowlan_status_data *status, struct ieee80211_key_conf *key, struct iwl_multicast_key_data *key_data) { - if (status->num_of_gtk_rekeys && key_data->len) { - /* remove rekeyed key */ - ieee80211_remove_key(key); - } else { - struct ieee80211_key_seq seq; + struct ieee80211_key_seq seq; - iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, - &seq, - key->cipher); - ieee80211_set_key_rx_seq(key, 0, &seq); - } + iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key->cipher); + ieee80211_set_key_rx_seq(key, 0, &seq); } static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, @@ -1952,18 +1920,13 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw, return; } keyidx = key->keyidx; - /* The current key is always sent by the FW, even if it wasn't - * rekeyed during D3. - * We remove an existing key if it has the same index as - * a new key + /* + * Update the seq even if there was a rekey. If there was a + * rekey, we will update again after replacing the key */ - if (status->num_of_gtk_rekeys && - ((status->gtk[0].len && keyidx == status->gtk[0].id) || - (status->gtk[1].len && keyidx == status->gtk[1].id))) { - ieee80211_remove_key(key); - } else { - iwl_mvm_set_key_rx_seq(key, data->status); - } + if ((status->gtk[0].len && keyidx == status->gtk[0].id) || + (status->gtk[1].len && keyidx == status->gtk[1].id)) + iwl_mvm_set_key_rx_seq(key, status); break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: @@ -2027,8 +1990,12 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, sizeof(status->gtk[i].key)); key = ieee80211_gtk_rekey_add(vif, conf, link_id); - if (IS_ERR(key)) + if (IS_ERR(key)) { + /* FW may send also the old keys */ + if (PTR_ERR(key) == -EALREADY) + continue; return false; + } for (j = 0; j < ARRAY_SIZE(status->gtk_seq); j++) { if (!status->gtk_seq[j].valid || @@ -2048,14 +2015,16 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, struct ieee80211_vif *vif, u32 cipher, struct iwl_multicast_key_data *key_data) { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, WOWLAN_KEY_MAX_SIZE); struct ieee80211_key_conf *key_config; struct ieee80211_key_seq seq; int link_id = vif->active_links ? __ffs(vif->active_links) : -1; + s8 keyidx = key_data->id; conf->cipher = cipher; - conf->keyidx = key_data->id; + conf->keyidx = keyidx; if (!key_data->len) return true; @@ -2082,19 +2051,26 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, memcpy(conf->key, key_data->key, conf->keylen); key_config = ieee80211_gtk_rekey_add(vif, conf, link_id); - if (IS_ERR(key_config)) - return false; + if (IS_ERR(key_config)) { + /* FW may send also the old keys */ + return PTR_ERR(key_config) == -EALREADY; + } ieee80211_set_key_rx_seq(key_config, 0, &seq); - if (key_config->keyidx == 4 || key_config->keyidx == 5) { - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + if (keyidx == 4 || keyidx == 5) { struct iwl_mvm_vif_link_info *mvm_link; link_id = link_id < 0 ? 0 : link_id; mvm_link = mvmvif->link[link_id]; + if (mvm_link->igtk) + mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; mvm_link->igtk = key_config; } + if (vif->type == NL80211_IFTYPE_STATION && (keyidx == 6 || keyidx == 7)) + rcu_assign_pointer(mvmvif->bcn_prot.keys[keyidx - 6], + key_config); + return true; } @@ -2210,6 +2186,7 @@ static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status, status->gtk[0].len = data->key_len; status->gtk[0].flags = data->key_flags; + status->gtk[0].id = status->gtk[0].flags & IWL_WOWLAN_GTK_IDX_MASK; memcpy(status->gtk[0].key, data->key, sizeof(data->key)); @@ -2380,8 +2357,8 @@ iwl_mvm_parse_wowlan_info_notif_v3(struct iwl_mvm *mvm, } static void -iwl_mvm_parse_wowlan_info_notif_v2(struct iwl_mvm *mvm, - struct iwl_wowlan_info_notif_v2 *data, +iwl_mvm_parse_wowlan_info_notif_v1(struct iwl_mvm *mvm, + struct iwl_wowlan_info_notif_v1 *data, struct iwl_wowlan_status_data *status, u32 len) { @@ -2466,8 +2443,6 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \ iwl_mvm_parse_wowlan_status_common(v6) iwl_mvm_parse_wowlan_status_common(v7) -iwl_mvm_parse_wowlan_status_common(v9) -iwl_mvm_parse_wowlan_status_common(v12) static struct iwl_wowlan_status_data * iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) @@ -2523,7 +2498,8 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) v6->gtk.tkip_mic_key, sizeof(v6->gtk.tkip_mic_key)); - iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc); + iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc, + v6->gtk.key_index); /* hardcode the key length to 16 since v6 only supports 16 */ status->gtk[0].len = 16; @@ -2534,6 +2510,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) * currently used key. */ status->gtk[0].flags = v6->gtk.key_index | BIT(7); + status->gtk[0].id = v6->gtk.key_index; } else if (notif_ver == 7) { struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data; @@ -2541,36 +2518,10 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id) if (!status) goto out_free_resp; - iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc); + iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc, + v7->gtk[0].key_flags & IWL_WOWLAN_GTK_IDX_MASK); iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]); iwl_mvm_convert_igtk(status, &v7->igtk[0]); - } else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) { - struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data; - - /* these three command versions have same layout and size, the - * difference is only in a few not used (reserved) fields. - */ - status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len); - if (!status) - goto out_free_resp; - - iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc); - iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]); - iwl_mvm_convert_igtk(status, &v9->igtk[0]); - - status->tid_tear_down = v9->tid_tear_down; - } else if (notif_ver == 12) { - struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data; - - status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len); - if (!status) - goto out_free_resp; - - iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc); - iwl_mvm_convert_gtk_v3(status, v12->gtk); - iwl_mvm_convert_igtk(status, &v12->igtk[0]); - - status->tid_tear_down = v12->tid_tear_down; } else { IWL_ERR(mvm, "Firmware advertises unknown WoWLAN status response %d!\n", @@ -3097,29 +3048,11 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait, break; } - if (wowlan_info_ver < 2) { + if (wowlan_info_ver == 1) { struct iwl_wowlan_info_notif_v1 *notif_v1 = (void *)pkt->data; - struct iwl_wowlan_info_notif_v2 *notif_v2; - - notif_v2 = kmemdup(notif_v1, sizeof(*notif_v2), GFP_ATOMIC); - - if (!notif_v2) - return false; - - notif_v2->tid_tear_down = notif_v1->tid_tear_down; - notif_v2->station_id = notif_v1->station_id; - memset_after(notif_v2, 0, station_id); - iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2, - d3_data->status, - len); - kfree(notif_v2); - - } else if (wowlan_info_ver == 2) { - struct iwl_wowlan_info_notif_v2 *notif_v2 = - (void *)pkt->data; - iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2, + iwl_mvm_parse_wowlan_info_notif_v1(mvm, notif_v1, d3_data->status, len); } else if (wowlan_info_ver == 3) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 86a87ea89916..f0e184c8a81a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1134,7 +1134,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, if (count == 6 && !strcmp(buf, "nolog\n")) { set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status); - set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status); + iwl_trans_suppress_cmd_error_once(mvm->trans); } /* take the return value to make compiler happy - it will fail anyway */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index ab3d78c1e20c..d931c6eaf12f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -121,6 +121,22 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, return false; palive = (void *)pkt->data; + + umac = &palive->umac_data; + lmac1 = &palive->lmac_data[0]; + lmac2 = &palive->lmac_data[1]; + status = le16_to_cpu(palive->status); + + BUILD_BUG_ON(sizeof(palive->sku_id.data) != + sizeof(alive_data->sku_id)); + memcpy(alive_data->sku_id, palive->sku_id.data, + sizeof(palive->sku_id.data)); + + IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n", + le32_to_cpu(alive_data->sku_id[0]), + le32_to_cpu(alive_data->sku_id[1]), + le32_to_cpu(alive_data->sku_id[2])); + mvm->trans->dbg.imr_data.imr_enable = le32_to_cpu(palive->imr.enabled); mvm->trans->dbg.imr_data.imr_size = @@ -168,40 +184,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, IWL_DEBUG_FW(mvm, "platform id: 0x%llx\n", palive_v8->platform_id); } - } - - if (version >= 5) { - struct iwl_alive_ntf_v5 *palive; - - if (pkt_len < sizeof(*palive)) - return false; - - palive = (void *)pkt->data; - umac = &palive->umac_data; - lmac1 = &palive->lmac_data[0]; - lmac2 = &palive->lmac_data[1]; - status = le16_to_cpu(palive->status); - - BUILD_BUG_ON(sizeof(palive->sku_id.data) != - sizeof(alive_data->sku_id)); - memcpy(alive_data->sku_id, palive->sku_id.data, - sizeof(palive->sku_id.data)); - - IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n", - le32_to_cpu(alive_data->sku_id[0]), - le32_to_cpu(alive_data->sku_id[1]), - le32_to_cpu(alive_data->sku_id[2])); - } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) { - struct iwl_alive_ntf_v4 *palive; - - if (pkt_len < sizeof(*palive)) - return false; - - palive = (void *)pkt->data; - umac = &palive->umac_data; - lmac1 = &palive->lmac_data[0]; - lmac2 = &palive->lmac_data[1]; - status = le16_to_cpu(palive->status); } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v3)) { struct iwl_alive_ntf_v3 *palive3; @@ -888,17 +870,11 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) len = sizeof(cmd_v9_v10.v9); n_subbands = IWL_NUM_SUB_BANDS_V1; per_chain = &cmd_v9_v10.v9.per_chain[0][0]; - } else if (cmd_ver >= 7) { - len = sizeof(cmd.v7); - n_subbands = IWL_NUM_SUB_BANDS_V2; - per_chain = cmd.v7.per_chain[0][0]; - cmd.v7.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags); - if (cmd_ver == 8) - len = sizeof(cmd.v8); - } else if (cmd_ver == 6) { - len = sizeof(cmd.v6); + } else if (cmd_ver == 8) { + len = sizeof(cmd.v8); n_subbands = IWL_NUM_SUB_BANDS_V2; - per_chain = cmd.v6.per_chain[0][0]; + per_chain = cmd.v8.per_chain[0][0]; + cmd.v8.flags = cpu_to_le32(mvm->fwrt.reduced_power_flags); } else if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_REDUCE_TX_POWER)) { len = sizeof(cmd.v5); @@ -1462,9 +1438,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm) RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL); } - for (i = 0; i < IWL_FW_MAX_LINK_ID + 1; i++) - RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL); - mvm->tdls_cs.peer.sta_id = IWL_INVALID_STA; /* reset quota debouncing buffer - 0xff will yield invalid data */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 851869c0bd50..2269acc55c0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -18,8 +18,7 @@ HOW(EXIT_COEX) \ HOW(EXIT_BANDWIDTH) \ HOW(EXIT_CSA) \ - HOW(EXIT_LINK_USAGE) \ - HOW(EXIT_FAIL_ENTRY) + HOW(EXIT_LINK_USAGE) static const char *const iwl_mvm_esr_states_names[] = { #define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x, @@ -50,20 +49,6 @@ static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask) #undef NAME_PR } -static u32 iwl_mvm_get_free_fw_link_id(struct iwl_mvm *mvm, - struct iwl_mvm_vif *mvm_vif) -{ - u32 i; - - lockdep_assert_held(&mvm->mutex); - - for (i = 0; i < ARRAY_SIZE(mvm->link_id_to_link_conf); i++) - if (!rcu_access_pointer(mvm->link_id_to_link_conf[i])) - return i; - - return IWL_MVM_FW_LINK_ID_INVALID; -} - static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, struct iwl_link_config_cmd *cmd, enum iwl_ctxt_action action) @@ -80,25 +65,15 @@ static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, return ret; } -int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf) +void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_conf->link_id]; - if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) { - link_info->fw_link_id = iwl_mvm_get_free_fw_link_id(mvm, - mvmvif); - if (link_info->fw_link_id >= - ARRAY_SIZE(mvm->link_id_to_link_conf)) - return -EINVAL; - - rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], - link_conf); - } - - return 0; + if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) + link_info->fw_link_id = mvmvif->id; } int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -110,14 +85,11 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_link_config_cmd cmd = {}; unsigned int cmd_id = WIDE_ID(MAC_CONF_GROUP, LINK_CONFIG_CMD); u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 1); - int ret; if (WARN_ON_ONCE(!link_info)) return -EINVAL; - ret = iwl_mvm_set_link_mapping(mvm, vif, link_conf); - if (ret) - return ret; + iwl_mvm_set_link_fw_id(mvm, vif, link_conf); /* Update SF - Disable if needed. if this fails, SF might still be on * while many macs are bound, which is forbidden - so fail the binding. @@ -374,24 +346,6 @@ send_cmd: return ret; } -int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm_vif_link_info *link_info = - mvmvif->link[link_conf->link_id]; - - /* mac80211 thought we have the link, but it was never configured */ - if (WARN_ON(!link_info || - link_info->fw_link_id >= - ARRAY_SIZE(mvm->link_id_to_link_conf))) - return -EINVAL; - - RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], - NULL); - return 0; -} - int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { @@ -401,10 +355,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_link_config_cmd cmd = {}; int ret; - ret = iwl_mvm_unset_link_mapping(mvm, vif, link_conf); - if (ret) - return 0; - cmd.link_id = cpu_to_le32(link_info->fw_link_id); link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; cmd.spec_link_id = link_conf->link_id; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 9098a36530cc..d9d61e25807a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1586,7 +1586,7 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, u32 id = le32_to_cpu(mb->link_id); union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; u32 mac_type; - int link_id = -1; + int link_id; u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, MISSED_BEACONS_NOTIFICATION, 0); @@ -1602,20 +1602,6 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, if (new_notif_ver) notif_ver = new_notif_ver; - /* before version four the ID in the notification refers to mac ID */ - if (notif_ver < 4) { - vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); - bss_conf = &vif->bss_conf; - } else { - bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, false); - - if (!bss_conf) - return; - - vif = bss_conf->vif; - link_id = bss_conf->link_id; - } - IWL_DEBUG_INFO(mvm, "missed bcn %s_id=%u, consecutive=%u (%u)\n", notif_ver < 4 ? "mac" : "link", @@ -1623,9 +1609,16 @@ iwl_mvm_handle_missed_beacons_notif(struct iwl_mvm *mvm, le32_to_cpu(mb->consec_missed_beacons), le32_to_cpu(mb->consec_missed_beacons_since_last_rx)); + /* + * starting from version 4 the ID is link ID, but driver + * uses link ID == MAC ID, so always treat as MAC ID + */ + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); if (!vif) return; + bss_conf = &vif->bss_conf; + link_id = bss_conf->link_id; mac_type = iwl_mvm_get_mac_type(vif); IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type); @@ -1875,16 +1868,15 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, } else { struct iwl_channel_switch_start_notif *notif = (void *)pkt->data; u32 link_id = le32_to_cpu(notif->link_id); - struct ieee80211_bss_conf *bss_conf = - iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true); - if (!bss_conf) + /* we use link ID == MAC ID */ + vif = iwl_mvm_rcu_dereference_vif_id(mvm, link_id, true); + if (!vif) goto out_unlock; id = link_id; - mac_link_id = bss_conf->link_id; - vif = bss_conf->vif; - csa_active = bss_conf->csa_active; + mac_link_id = vif->bss_conf.link_id; + csa_active = vif->bss_conf.csa_active; } mvmvif = iwl_mvm_vif_from_mac80211(vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index b28c21c20371..fa9d5e0b6609 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -165,12 +165,6 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, mvm->lar_regdom_set = true; mvm->mcc_src = src_id; - if (!iwl_puncturing_is_allowed_in_bios(mvm->bios_enable_puncturing, - le16_to_cpu(resp->mcc))) - ieee80211_hw_set(mvm->hw, DISALLOW_PUNCTURING); - else - __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mvm->hw->flags); - iwl_mei_set_country_code(__le16_to_cpu(resp->mcc)); out: @@ -1521,10 +1515,6 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, len = sizeof(cmd_v9_v10.v9); else if (cmd_ver == 8) len = sizeof(cmd.v8); - else if (cmd_ver == 7) - len = sizeof(cmd.v7); - else if (cmd_ver == 6) - len = sizeof(cmd.v6); else if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_REDUCE_TX_POWER)) len = sizeof(cmd.v5); @@ -1775,6 +1765,8 @@ void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) return; + mvmvif->deflink.average_beacon_energy = 0; + INIT_DELAYED_WORK(&mvmvif->csa_work, iwl_mvm_channel_switch_disconnect_wk); @@ -1812,9 +1804,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, vif->driver_flags = IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC; - ret = iwl_mvm_set_link_mapping(mvm, vif, &vif->bss_conf); - if (ret) - goto out; + iwl_mvm_set_link_fw_id(mvm, vif, &vif->bss_conf); /* * Not much to do here. The stack will not allow interface @@ -2015,7 +2005,6 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvm->monitor_on = false; out: - iwl_mvm_unset_link_mapping(mvm, vif, &vif->bss_conf); if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) { iwl_mvm_dealloc_int_sta(mvm, &mvmvif->deflink.mcast_sta); @@ -4618,6 +4607,10 @@ int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + /* When resuming from wowlan, FW already knows about the newest keys */ + if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) + return 0; + guard(mvm)(mvm); return __iwl_mvm_mac_set_key(hw, cmd, vif, sta, key); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f0d459766365..9e83c671f4e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -304,6 +304,8 @@ struct iwl_probe_resp_data { * @mcast_sta: multicast station * @phy_ctxt: phy context allocated to this link, if any * @bf_data: beacon filtering data + * @average_beacon_energy: average beacon energy for beacons received during + * client connections */ struct iwl_mvm_vif_link_info { u8 bssid[ETH_ALEN]; @@ -342,6 +344,7 @@ struct iwl_mvm_vif_link_info { u16 mgmt_queue; struct iwl_mvm_link_bf_data bf_data; + u32 average_beacon_energy; }; /** @@ -374,7 +377,6 @@ struct iwl_mvm_vif_link_info { * preventing the enablement of EMLSR * @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR * @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link - * @IWL_MVM_ESR_EXIT_FAIL_ENTRY: Exit EMLSR due to entry failure */ enum iwl_mvm_esr_state { IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1, @@ -390,7 +392,6 @@ enum iwl_mvm_esr_state { IWL_MVM_ESR_EXIT_BANDWIDTH = 0x80000, IWL_MVM_ESR_EXIT_CSA = 0x100000, IWL_MVM_ESR_EXIT_LINK_USAGE = 0x200000, - IWL_MVM_ESR_EXIT_FAIL_ENTRY = 0x400000, }; #define IWL_MVM_BLOCK_ESR_REASONS 0xffff @@ -1179,8 +1180,6 @@ struct iwl_mvm { struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; - struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_FW_MAX_LINK_ID + 1]; - u8 *error_recovery_buf; #ifdef CONFIG_IWLWIFI_LEDS @@ -1372,7 +1371,6 @@ struct iwl_mvm { struct iwl_mvm_acs_survey *acs_survey; bool statistics_clear; - u32 bios_enable_puncturing; }; /* Extract MVM priv from op_mode and _hw */ @@ -1488,20 +1486,6 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu) lockdep_is_held(&mvm->mutex)); } -static inline struct ieee80211_bss_conf * -iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu) -{ - if (IWL_FW_CHECK(mvm, link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf), - "erroneous FW link ID: %d\n", link_id)) - return NULL; - - if (rcu) - return rcu_dereference(mvm->link_id_to_link_conf[link_id]); - - return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id], - lockdep_is_held(&mvm->mutex)); -} - static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm) { return fw_has_api(&mvm->fw->ucode_capa, @@ -2093,6 +2077,9 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); + /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); @@ -2100,15 +2087,13 @@ u32 iwl_mvm_get_lmac_id(struct iwl_mvm *mvm, enum nl80211_band band); /* Links */ void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link); -int iwl_mvm_set_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf); +void iwl_mvm_set_link_fw_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf); int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf); int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf, u32 changes, bool active); -int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf); int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf); int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 1c05a3d8e424..c7f08cde1f72 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -161,43 +161,6 @@ static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm, iwl_mvm_get_primary_link(vif)); } -static void iwl_mvm_rx_esr_trans_fail_notif(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_esr_trans_fail_notif *notif = (void *)pkt->data; - struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm); - u8 fw_link_id = le32_to_cpu(notif->link_id); - struct ieee80211_bss_conf *bss_conf; - - if (IS_ERR_OR_NULL(vif)) - return; - - IWL_DEBUG_INFO(mvm, "Failed to %s eSR on link %d, reason %d\n", - le32_to_cpu(notif->activation) ? "enter" : "exit", - le32_to_cpu(notif->link_id), - le32_to_cpu(notif->err_code)); - - /* we couldn't go back to single link, disconnect */ - if (!le32_to_cpu(notif->activation)) { - iwl_mvm_connection_loss(mvm, vif, "emlsr exit failed"); - return; - } - - bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, false); - if (IWL_FW_CHECK(mvm, !bss_conf, - "FW reported failure to activate EMLSR on a non-existing link: %d\n", - fw_link_id)) - return; - - /* - * We failed to activate the second link and enter EMLSR, we need to go - * back to single link. - */ - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_FAIL_ENTRY, - bss_conf->link_id); -} - static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { @@ -526,10 +489,11 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_GRP(SCAN_GROUP, CHANNEL_SURVEY_NOTIF, iwl_mvm_rx_channel_survey_notif, RX_HANDLER_ASYNC_LOCKED, struct iwl_umac_scan_channel_survey_notif), - RX_HANDLER_GRP(MAC_CONF_GROUP, EMLSR_TRANS_FAIL_NOTIF, - iwl_mvm_rx_esr_trans_fail_notif, - RX_HANDLER_ASYNC_LOCKED_WIPHY, - struct iwl_esr_trans_fail_notif), + RX_HANDLER_GRP(DATA_PATH_GROUP, BEACON_FILTER_IN_NOTIF, + iwl_mvm_rx_beacon_filter_notif, + RX_HANDLER_ASYNC_LOCKED, + /* same size as v1 */ + struct iwl_beacon_filter_notif), }; #undef RX_HANDLER #undef RX_HANDLER_GRP @@ -660,7 +624,6 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { HCMD_NAME(STA_REMOVE_CMD), HCMD_NAME(STA_DISABLE_TX_CMD), HCMD_NAME(ROC_CMD), - HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF), HCMD_NAME(ROC_NOTIF), HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF), HCMD_NAME(MISSED_VAP_NOTIF), @@ -701,6 +664,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(ESR_MODE_NOTIF), HCMD_NAME(MONITOR_NOTIF), HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST), + HCMD_NAME(BEACON_FILTER_IN_NOTIF), HCMD_NAME(STA_PM_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), HCMD_NAME(RX_QUEUES_NOTIFICATION), @@ -1397,8 +1361,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, } } - mvm->bios_enable_puncturing = iwl_uefi_get_puncturing(&mvm->fwrt); - if (iwl_mvm_has_new_tx_api(mvm)) { /* * If we have the new TX/queue allocation API initialize them @@ -2055,7 +2017,7 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode, if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL) IWL_ERR(mvm, "Command queue full!\n"); - else if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) && + else if (!iwl_trans_is_dead(mvm->trans) && !test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status)) iwl_mvm_dump_nic_error_log(mvm); @@ -2157,6 +2119,17 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode, iwl_dbg_tlv_time_point(&mvm->fwrt, tp_id, tp_data); } +static void iwl_mvm_dump(struct iwl_op_mode *op_mode) +{ + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + struct iwl_fw_runtime *fwrt = &mvm->fwrt; + + if (!iwl_trans_fw_running(fwrt->trans)) + return; + + iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL); +} + #ifdef CONFIG_PM_SLEEP static void iwl_op_mode_mvm_device_powered_off(struct iwl_op_mode *op_mode) { @@ -2219,4 +2192,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops_mq = { IWL_MVM_COMMON_OPS, .rx = iwl_mvm_rx_mq, .rx_rss = iwl_mvm_rx_mq_rss, + .dump = iwl_mvm_dump, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 8eb0aa448c85..8fae0d41b119 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -877,28 +877,28 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, u32 rx_bytes[MAC_INDEX_AUX] = {}; int fw_link_id; - for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->link_id_to_link_conf); + /* driver uses link ID == MAC ID */ + for (fw_link_id = 0; fw_link_id < ARRAY_SIZE(mvm->vif_id_to_mac); fw_link_id++) { struct iwl_stats_ntfy_per_link *link_stats; - struct ieee80211_bss_conf *bss_conf; - struct iwl_mvm_vif *mvmvif; struct iwl_mvm_vif_link_info *link_info; + struct iwl_mvm_vif *mvmvif; + struct ieee80211_vif *vif; int link_id; int sig; - bss_conf = iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, fw_link_id, - false); - if (!bss_conf) + vif = iwl_mvm_rcu_dereference_vif_id(mvm, fw_link_id, false); + if (!vif) continue; - if (bss_conf->vif->type != NL80211_IFTYPE_STATION) + if (vif->type != NL80211_IFTYPE_STATION) continue; - link_id = bss_conf->link_id; + link_id = vif->bss_conf.link_id; if (link_id >= ARRAY_SIZE(mvmvif->link)) continue; - mvmvif = iwl_mvm_vif_from_mac80211(bss_conf->vif); + mvmvif = iwl_mvm_vif_from_mac80211(vif); link_info = mvmvif->link[link_id]; if (!link_info) continue; @@ -916,8 +916,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, if (link_info->phy_ctxt && link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ) - iwl_mvm_bt_coex_update_link_esr(mvm, bss_conf->vif, - link_id); + iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); /* make sure that beacon statistics don't go backwards with TCM * request to clear statistics @@ -927,8 +926,7 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, mvmvif->link[link_id]->beacon_stats.num_beacons; sig = -le32_to_cpu(link_stats->beacon_filter_average_energy); - iwl_mvm_update_link_sig(bss_conf->vif, sig, link_info, - bss_conf); + iwl_mvm_update_link_sig(vif, sig, link_info, &vif->bss_conf); if (WARN_ONCE(mvmvif->id >= MAC_INDEX_AUX, "invalid mvmvif id: %d", mvmvif->id)) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 077aadbf95db..4b57ca56e1f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -246,13 +246,62 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, ieee80211_rx_napi(mvm->hw, sta, skb, napi); } +static bool iwl_mvm_used_average_energy(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_hdr *hdr, + struct ieee80211_rx_status *rx_status) +{ + struct iwl_mvm_vif *mvm_vif; + struct ieee80211_vif *vif; + u32 id; + + if (unlikely(!hdr || !desc)) + return false; + + if (likely(!ieee80211_is_beacon(hdr->frame_control))) + return false; + + /* for the link conf lookup */ + guard(rcu)(); + + /* MAC or link ID depending on FW, but driver has them equal */ + id = u8_get_bits(desc->mac_phy_band, + IWL_RX_MPDU_MAC_PHY_BAND_MAC_MASK); + + /* >= means AUX MAC/link ID, no energy correction needed then */ + if (id >= ARRAY_SIZE(mvm->vif_id_to_mac)) + return false; + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); + if (!vif) + return false; + + mvm_vif = iwl_mvm_vif_from_mac80211(vif); + + /* + * If we know the MAC by MAC or link ID then the frame was + * received for the link, so by filtering it means it was + * from the AP the link is connected to. + */ + + /* skip also in case we don't have it (yet) */ + if (!mvm_vif->deflink.average_beacon_energy) + return false; + + IWL_DEBUG_STATS(mvm, "energy override by average %d\n", + mvm_vif->deflink.average_beacon_energy); + rx_status->signal = -mvm_vif->deflink.average_beacon_energy; + return true; +} + static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_hdr *hdr, struct ieee80211_rx_status *rx_status, u32 rate_n_flags, int energy_a, int energy_b) { int max_energy; - u32 rate_flags = rate_n_flags; energy_a = energy_a ? -energy_a : S8_MIN; energy_b = energy_b ? -energy_b : S8_MIN; @@ -261,9 +310,11 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n", energy_a, energy_b, max_energy); + if (iwl_mvm_used_average_energy(mvm, desc, hdr, rx_status)) + return; + rx_status->signal = max_energy; - rx_status->chains = - (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS; + rx_status->chains = u32_get_bits(rate_n_flags, RATE_MCS_ANT_AB_MSK); rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; } @@ -1906,8 +1957,11 @@ static void iwl_mvm_rx_get_sta_block_tx(void *data, struct ieee80211_sta *sta) /* * Note: requires also rx_status->band to be prefilled, as well * as phy_data (apart from phy_data->info_type) + * Note: desc/hdr may be NULL */ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm, + struct iwl_rx_mpdu_desc *desc, + struct ieee80211_hdr *hdr, struct sk_buff *skb, struct iwl_mvm_rx_phy_data *phy_data, int queue) @@ -1962,7 +2016,7 @@ static void iwl_mvm_rx_fill_status(struct iwl_mvm *mvm, rx_status->freq = ieee80211_channel_to_frequency(phy_data->channel, rx_status->band); - iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags, + iwl_mvm_get_signal_strength(mvm, desc, hdr, rx_status, rate_n_flags, phy_data->energy_a, phy_data->energy_b); /* using TLV format and must be after all fixed len fields */ @@ -2215,7 +2269,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, goto out; } - iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue); + iwl_mvm_rx_fill_status(mvm, desc, hdr, skb, &phy_data, queue); if (sta) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); @@ -2445,7 +2499,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->band = phy_data.channel > 14 ? NL80211_BAND_5GHZ : NL80211_BAND_2GHZ; - iwl_mvm_rx_fill_status(mvm, skb, &phy_data, queue); + iwl_mvm_rx_fill_status(mvm, NULL, NULL, skb, &phy_data, queue); /* no more radio tap info should be put after this point. * @@ -2548,3 +2602,28 @@ void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, out: rcu_read_unlock(); } + +void iwl_mvm_rx_beacon_filter_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + /* MAC or link ID in v1/v2, but driver has the IDs equal */ + struct iwl_beacon_filter_notif *notif = (void *)pkt->data; + u32 id = le32_to_cpu(notif->link_id); + struct iwl_mvm_vif *mvm_vif; + struct ieee80211_vif *vif; + + /* >= means AUX MAC/link ID, no energy correction needed then */ + if (IWL_FW_CHECK(mvm, id >= ARRAY_SIZE(mvm->vif_id_to_mac), + "invalid link ID %d\n", id)) + return; + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); + if (!vif) + return; + + mvm_vif = iwl_mvm_vif_from_mac80211(vif); + + mvm_vif->deflink.average_beacon_energy = + le32_to_cpu(notif->average_energy); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 5f30109ca18f..9ce1ce0dab34 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -836,7 +836,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids, int n_channels) { return ((n_ssids <= PROBE_OPTION_MAX) && - (n_channels <= mvm->fw->ucode_capa.n_scan_channels) & + (n_channels <= mvm->fw->ucode_capa.n_scan_channels) && (ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] + ies->len[NL80211_BAND_6GHZ] <= @@ -3547,7 +3547,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify) if (!(mvm->scan_status & type)) return 0; - if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) { + if (!iwl_trans_device_enabled(mvm->trans)) { ret = 0; goto out; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 478408f802d9..aa653782d6d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -958,40 +958,19 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_session_prot_notif *notif = (void *)pkt->data; - unsigned int ver = - iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, - SESSION_PROTECTION_NOTIF, 2); int id = le32_to_cpu(notif->mac_link_id); struct ieee80211_vif *vif; struct iwl_mvm_vif *mvmvif; - unsigned int notif_link_id; rcu_read_lock(); - if (ver <= 2) { - vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); - } else { - struct ieee80211_bss_conf *link_conf = - iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true); - - if (!link_conf) - goto out_unlock; - - notif_link_id = link_conf->link_id; - vif = link_conf->vif; - } - + /* note we use link ID == MAC ID */ + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); if (!vif) goto out_unlock; mvmvif = iwl_mvm_vif_from_mac80211(vif); - if (WARN(ver > 2 && mvmvif->time_event_data.link_id >= 0 && - mvmvif->time_event_data.link_id != notif_link_id, - "SESSION_PROTECTION_NOTIF was received for link %u, while the current time event is on link %u\n", - notif_link_id, mvmvif->time_event_data.link_id)) - goto out_unlock; - /* The vif is not a P2P_DEVICE, maintain its time_event_data */ if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { struct iwl_mvm_time_event_data *te_data = diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 0bd9b44d295b..b7add05f7a85 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -501,7 +501,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_mac_cfg)}, {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_mac_cfg)}, #endif /* CONFIG_IWLMVM */ -#if IS_ENABLED(CONFIG_IWLMLD) +#if IS_ENABLED(CONFIG_IWLMVM) || IS_ENABLED(CONFIG_IWLMLD) /* Bz devices */ {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_gl_mac_cfg)}, {IWL_PCI_DEVICE(0xA840, 0x0000, iwl_bz_mac_cfg)}, @@ -546,7 +546,7 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_mac_cfg)}, {IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_mac_cfg)}, {IWL_PCI_DEVICE(0xD240, PCI_ANY_ID, iwl_sc_mac_cfg)}, -#endif /* CONFIG_IWLMLD */ +#endif /* CONFIG_IWLMVM || CONFIG_IWLMLD */ {0} }; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index 7dd11891ccfe..f48aeebb151c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1091,6 +1091,7 @@ int iwl_trans_pcie_start_fw(struct iwl_trans *trans, void iwl_trans_pcie_stop_device(struct iwl_trans *trans); /* common functions that are used by gen2 transport */ +void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans); int iwl_pcie_gen2_apm_init(struct iwl_trans *trans); void iwl_pcie_apm_config(struct iwl_trans *trans); int iwl_pcie_prepare_card_hw(struct iwl_trans *trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c index 0df8522ca410..035048e0e8f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c @@ -630,3 +630,23 @@ out: mutex_unlock(&trans_pcie->mutex); return ret; } + +void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + mutex_lock(&trans_pcie->mutex); + + /* disable interrupts - don't enable HW RF kill interrupt */ + iwl_disable_interrupts(trans); + + iwl_pcie_gen2_apm_stop(trans, true); + + iwl_disable_interrupts(trans); + + iwl_pcie_disable_ict(trans); + + mutex_unlock(&trans_pcie->mutex); + + iwl_pcie_synchronize_irqs(trans); +} diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index 585d845b53fa..327366bf87de 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -392,7 +392,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); } - if (ret < 0) + if (ret) IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); IWL_DEBUG_INFO(trans, "stop master\n"); @@ -495,10 +495,10 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans) CSR_HW_IF_CONFIG_REG_PCI_OWN_SET, HW_READY_TIMEOUT); - if (ret >= 0) + if (!ret) iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE); - IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : ""); + IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret ? " not" : ""); return ret; } @@ -512,7 +512,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) ret = iwl_pcie_set_hw_ready(trans); /* If the card is ready, exit 0 */ - if (ret >= 0) { + if (!ret) { trans->csme_own = false; return 0; } @@ -530,7 +530,7 @@ int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) do { ret = iwl_pcie_set_hw_ready(trans); - if (ret >= 0) { + if (!ret) { trans->csme_own = false; return 0; } @@ -2353,7 +2353,7 @@ bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent) * and do not save/restore SRAM when power cycling. */ ret = iwl_poll_bits_mask(trans, CSR_GP_CNTRL, poll, mask, 15000); - if (unlikely(ret < 0)) { + if (unlikely(ret)) { u32 cntrl = iwl_read32(trans, CSR_GP_CNTRL); if (silent) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c index 3af6e3b3640d..b38ec90f8342 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c @@ -25,6 +25,7 @@ #include "iwl-op-mode.h" #include "internal.h" #include "fw/api/tx.h" +#include "fw/dbg.h" #include "pcie/utils.h" /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** @@ -591,7 +592,7 @@ static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) /* Wait for DMA channels to be idle */ ret = iwl_poll_bits(trans, FH_TSSR_TX_STATUS_REG, mask, 5000); - if (ret < 0) + if (ret) IWL_ERR(trans, "Failing on timeout while stopping DMA channel %d [0x%08x]\n", ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG)); @@ -1638,13 +1639,11 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ - if (WARN(txq_id != trans->conf.cmd_queue, - "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", - txq_id, trans->conf.cmd_queue, sequence, txq->read_ptr, - txq->write_ptr)) { - iwl_print_hex_error(trans, pkt, 32); + if (IWL_FW_CHECK(trans, txq_id != trans->conf.cmd_queue, + "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d pkt=%*phN\n", + txq_id, trans->conf.cmd_queue, sequence, txq->read_ptr, + txq->write_ptr, 32, pkt)) return; - } spin_lock_bh(&txq->lock); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h index 031dfdf4bba4..27437d5e099b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/utils.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/utils.h @@ -6,6 +6,8 @@ #ifndef __iwl_pcie_utils_h__ #define __iwl_pcie_utils_h__ +#include "iwl-io.h" + void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev); static inline void _iwl_trans_set_bits_mask(struct iwl_trans *trans, diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index bc34a025acd6..891e125ad30b 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -1227,6 +1227,10 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) addr = dma_map_single(&priv->pdev->dev, skb->data, MWL8K_RX_MAXSZ, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->pdev->dev, addr)) { + kfree_skb(skb); + break; + } rxq->rxd_count++; rx = rxq->tail++; diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index eefe8da3b14d..3789d46d5614 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -5384,7 +5384,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | NL80211_FEATURE_STATIC_SMPS | NL80211_FEATURE_DYNAMIC_SMPS | - NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | + NL80211_FEATURE_AP_SCAN; wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION); wiphy_ext_feature_set(hw->wiphy, diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.h b/drivers/net/wireless/virtual/mac80211_hwsim.h index f32fc3a492b0..fa157c883f7f 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.h +++ b/drivers/net/wireless/virtual/mac80211_hwsim.h @@ -62,7 +62,7 @@ enum hwsim_tx_control_flags { * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to * kernel, uses: * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, - * %HWSIM_ATTR_TX_INFO, %WSIM_ATTR_TX_INFO_FLAGS, + * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_TX_INFO_FLAGS, * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters, * returns the radio ID (>= 0) or negative on errors, if successful @@ -126,24 +126,24 @@ enum hwsim_commands { * space * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame - * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_CHANNELS: u32 attribute used with the %HWSIM_CMD_NEW_RADIO * command giving the number of channels supported by the new radio * @HWSIM_ATTR_RADIO_ID: u32 attribute used with %HWSIM_CMD_DESTROY_RADIO * only to destroy a radio - * @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatoro driver hint + * @HWSIM_ATTR_REG_HINT_ALPHA2: alpha2 for regulatory driver hint * (nla string, length 2) * @HWSIM_ATTR_REG_CUSTOM_REG: custom regulatory domain index (u32 attribute) * @HWSIM_ATTR_REG_STRICT_REG: request REGULATORY_STRICT_REG (flag attribute) * @HWSIM_ATTR_SUPPORT_P2P_DEVICE: support P2P Device virtual interface (flag) - * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_NEW_RADIO * command to force use of channel contexts even when only a * single channel is supported - * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_NEW_RADIO * command to force radio removal when process that created the radio dies * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666 * @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio. - * @HWSIM_ATTR_PAD: padding attribute for 64-bit values, ignore * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received. + * @HWSIM_ATTR_PAD: padding attribute for 64-bit values, ignore * @HWSIM_ATTR_TX_INFO_FLAGS: additional flags for corresponding * rates of %HWSIM_ATTR_TX_INFO * @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio @@ -151,7 +151,7 @@ enum hwsim_commands { * @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types * @HWSIM_ATTR_MLO_SUPPORT: claim MLO support (exact parameters TBD) for * the new radio - * @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_CREATE_RADIO + * @HWSIM_ATTR_PMSR_SUPPORT: nested attribute used with %HWSIM_CMD_NEW_RADIO * to provide peer measurement capabilities. (nl80211_peer_measurement_attrs) * @HWSIM_ATTR_PMSR_REQUEST: nested attribute used with %HWSIM_CMD_START_PMSR * to provide details about peer measurement request (nl80211_peer_measurement_attrs) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6ec9a8865b8b..77bc17d6e96d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -633,7 +633,7 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband, const struct ieee80211_sband_iftype_data *data; int i; - if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) + if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) return NULL; if (iftype == NL80211_IFTYPE_AP_VLAN) @@ -1526,6 +1526,7 @@ struct cfg80211_ap_update { * @n_counter_offsets_beacon: number of csa counters the beacon (tail) * @n_counter_offsets_presp: number of csa counters in the probe response * @beacon_after: beacon data to be used on the new channel + * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters * @radar_required: whether radar detection is required on the new channel * @block_tx: whether transmissions should be blocked while changing * @count: number of beacons until switch @@ -1540,6 +1541,7 @@ struct cfg80211_csa_settings { unsigned int n_counter_offsets_beacon; unsigned int n_counter_offsets_presp; struct cfg80211_beacon_data beacon_after; + struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; bool radar_required; bool block_tx; u8 count; @@ -1555,6 +1557,7 @@ struct cfg80211_csa_settings { * @counter_offset_beacon: offsets of the counters within the beacon (tail) * @counter_offset_presp: offsets of the counters within the probe response * @beacon_next: beacon data to be used after the color change + * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters * @count: number of beacons until the color change * @color: the color used after the change * @link_id: defines the link on which color change is expected during MLO. @@ -1565,6 +1568,7 @@ struct cfg80211_color_change_settings { u16 counter_offset_beacon; u16 counter_offset_presp; struct cfg80211_beacon_data beacon_next; + struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp; u8 count; u8 color; u8 link_id; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d76643d46150..b99e39cb808b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3841,7 +3841,7 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id) */ struct ieee80211_link_data *iter; - for_each_sdata_link(local, iter) { + for_each_sdata_link_rcu(local, iter) { if (iter->sdata == sdata || rcu_access_pointer(iter->conf->tx_bss_conf) != tx_bss_conf) continue; @@ -4187,6 +4187,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, goto out; } + err = ieee80211_set_unsol_bcast_probe_resp(sdata, + ¶ms->unsol_bcast_probe_resp, + link_data, link_conf, &changed); + if (err) + goto out; + chanctx = container_of(conf, struct ieee80211_chanctx, conf); ch_switch.timestamp = 0; @@ -5128,6 +5134,12 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev, goto out; } + err = ieee80211_set_unsol_bcast_probe_resp(sdata, + ¶ms->unsol_bcast_probe_resp, + link, link_conf, &changed); + if (err) + goto out; + err = ieee80211_set_color_change_beacon(link, params, &changed); if (err) goto out; diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 4bcbcf9d98b5..c9cea0e7ac16 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -910,7 +910,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, conf = rcu_dereference_protected(link->conf->chanctx_conf, lockdep_is_held(&local->hw.wiphy->mtx)); - if (conf) { + if (conf && !local->in_reconfig) { curr_ctx = container_of(conf, struct ieee80211_chanctx, conf); drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx); @@ -930,8 +930,9 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, /* succeeded, so commit it to the data structures */ conf = &new_ctx->conf; - list_add(&link->assigned_chanctx_list, - &new_ctx->assigned_links); + if (!local->in_reconfig) + list_add(&link->assigned_chanctx_list, + &new_ctx->assigned_links); } } else { ret = 0; @@ -1108,7 +1109,7 @@ void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link, __ieee80211_link_copy_chanctx_to_vlans(link, clear); } -int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) +void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) { struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_chanctx *ctx = link->reserved_chanctx; @@ -1116,7 +1117,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) lockdep_assert_wiphy(sdata->local->hw.wiphy); if (WARN_ON(!ctx)) - return -EINVAL; + return; list_del(&link->reserved_chanctx_list); link->reserved_chanctx = NULL; @@ -1124,7 +1125,7 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) { if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) { if (WARN_ON(!ctx->replace_ctx)) - return -EINVAL; + return; WARN_ON(ctx->replace_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED); @@ -1140,8 +1141,6 @@ int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) ieee80211_free_chanctx(sdata->local, ctx, false); } } - - return 0; } static struct ieee80211_chanctx * @@ -1934,7 +1933,8 @@ int _ieee80211_link_use_channel(struct ieee80211_link_data *link, if (ret < 0) goto out; - __ieee80211_link_release_channel(link, false); + if (!local->in_reconfig) + __ieee80211_link_release_channel(link, false); ctx = ieee80211_find_chanctx(local, link, chanreq, mode); /* Note: context is now reserved */ diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index 35349a7f16cb..ba9fba165926 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2015 Intel Deutschland GmbH - * Copyright (C) 2022-2024 Intel Corporation + * Copyright (C) 2022-2025 Intel Corporation */ #include <net/mac80211.h> #include "ieee80211_i.h" @@ -515,6 +515,9 @@ int drv_set_key(struct ieee80211_local *local, !(sdata->vif.active_links & BIT(key->link_id)))) return -ENOLINK; + if (fips_enabled) + return -EOPNOTSUPP; + trace_drv_set_key(local, cmd, sdata, sta, key); ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 8baebb5636ec..181bcb34b795 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -8,6 +8,7 @@ #ifndef __MAC80211_DRIVER_OPS #define __MAC80211_DRIVER_OPS +#include <linux/fips.h> #include <net/mac80211.h> #include "ieee80211_i.h" #include "trace.h" @@ -902,6 +903,9 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return; + if (fips_enabled) + return; + trace_drv_set_rekey_data(local, sdata, data); if (local->ops->set_rekey_data) local->ops->set_rekey_data(&local->hw, &sdata->vif, data); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 32390d8a9d75..1c82a28b03de 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -9,7 +9,7 @@ * Copyright 2007, Michael Wu <flamingice@sourmilk.net> * Copyright 2007-2010, Intel Corporation * Copyright 2017 Intel Deutschland GmbH - * Copyright(c) 2020-2024 Intel Corporation + * Copyright(c) 2020-2025 Intel Corporation */ #include <linux/ieee80211.h> @@ -603,3 +603,41 @@ out: } /* this might change ... don't want non-open drivers using it */ EXPORT_SYMBOL_GPL(ieee80211_request_smps); + +void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct link_sta_info *link_sta, + u8 chanwidth, enum nl80211_band band) +{ + enum ieee80211_sta_rx_bandwidth max_bw, new_bw; + struct ieee80211_supported_band *sband; + struct sta_opmode_info sta_opmode = {}; + + lockdep_assert_wiphy(local->hw.wiphy); + + if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) + max_bw = IEEE80211_STA_RX_BW_20; + else + max_bw = ieee80211_sta_cap_rx_bw(link_sta); + + /* set cur_max_bandwidth and recalc sta bw */ + link_sta->cur_max_bandwidth = max_bw; + new_bw = ieee80211_sta_cur_vht_bw(link_sta); + + if (link_sta->pub->bandwidth == new_bw) + return; + + link_sta->pub->bandwidth = new_bw; + sband = local->hw.wiphy->bands[band]; + sta_opmode.bw = + ieee80211_sta_rx_bw_to_chan_width(link_sta); + sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; + + rate_control_rate_update(local, sband, link_sta, + IEEE80211_RC_BW_CHANGED); + cfg80211_sta_opmode_change_notify(sdata->dev, + sta->addr, + &sta_opmode, + GFP_KERNEL); +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ec68204fddc9..084e2673a27e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1226,6 +1226,21 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) if ((_link = wiphy_dereference((_local)->hw.wiphy, \ ___sdata->link[___link_id]))) +/* + * for_each_sdata_link_rcu() must be used under RCU read lock. + */ +#define for_each_sdata_link_rcu(_local, _link) \ + /* outer loop just to define the variables ... */ \ + for (struct ieee80211_sub_if_data *___sdata = NULL; \ + !___sdata; \ + ___sdata = (void *)~0 /* always stop */) \ + list_for_each_entry_rcu(___sdata, &(_local)->interfaces, list) \ + if (ieee80211_sdata_running(___sdata)) \ + for (int ___link_id = 0; \ + ___link_id < ARRAY_SIZE((___sdata)->link); \ + ___link_id++) \ + if ((_link = rcu_dereference((___sdata)->link[___link_id]))) + #define for_each_link_data(sdata, __link) \ struct ieee80211_sub_if_data *__sdata = sdata; \ for (int __link_id = 0; \ @@ -1403,8 +1418,6 @@ struct ieee80211_local { bool rx_mcast_action_reg; unsigned int filter_flags; /* FIF_* */ - bool wiphy_ciphers_allocated; - struct cfg80211_chan_def dflt_chandef; bool emulate_chanctx; @@ -2206,6 +2219,12 @@ u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs); enum nl80211_smps_mode ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps); +void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta, + struct link_sta_info *link_sta, + u8 chanwidth, enum nl80211_band band); + /* VHT */ void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, @@ -2697,7 +2716,7 @@ ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, bool radar_required); int __must_check ieee80211_link_use_reserved_context(struct ieee80211_link_data *link); -int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link); +void ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link); int __must_check ieee80211_link_change_chanreq(struct ieee80211_link_data *link, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0ba590a68605..07ba68f7cd81 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1557,6 +1557,35 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local, } } } else if (ieee80211_is_action(mgmt->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_HT) { + switch (mgmt->u.action.u.ht_smps.action) { + case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { + u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; + struct ieee80211_rx_status *status; + struct link_sta_info *link_sta; + struct sta_info *sta; + + sta = sta_info_get_bss(sdata, mgmt->sa); + if (!sta) + break; + + status = IEEE80211_SKB_RXCB(skb); + if (!status->link_valid) + link_sta = &sta->deflink; + else + link_sta = rcu_dereference_protected(sta->link[status->link_id], + lockdep_is_held(&local->hw.wiphy->mtx)); + if (link_sta) + ieee80211_ht_handle_chanwidth_notif(local, sdata, sta, + link_sta, chanwidth, + status->band); + break; + } + default: + WARN_ON(1); + break; + } + } else if (ieee80211_is_action(mgmt->frame_control) && mgmt->u.action.category == WLAN_CATEGORY_VHT) { switch (mgmt->u.action.u.vht_group_notif.action_code) { case WLAN_VHT_ACTION_OPMODE_NOTIF: { diff --git a/net/mac80211/key.c b/net/mac80211/key.c index dcf8643a0baa..997892da8886 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -510,7 +510,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, } else { if (!new->local->wowlan) ret = ieee80211_key_enable_hw_accel(new); - else + else if (link_id < 0 || !sdata->vif.active_links || + BIT(link_id) & sdata->vif.active_links) new->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c1c758e76d2e..ec60b82af007 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation */ #include <net/mac80211.h> @@ -1025,12 +1025,9 @@ EXPORT_SYMBOL(ieee80211_alloc_hw_nm); static int ieee80211_init_cipher_suites(struct ieee80211_local *local) { - bool have_wep = !fips_enabled; /* FIPS does not permit the use of RC4 */ bool have_mfp = ieee80211_hw_check(&local->hw, MFP_CAPABLE); - int r = 0, w = 0; - u32 *suites; static const u32 cipher_suites[] = { - /* keep WEP first, it may be removed below */ + /* keep WEP and TKIP first, they may be removed below */ WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, @@ -1046,34 +1043,17 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) WLAN_CIPHER_SUITE_BIP_GMAC_256, }; - if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) || - local->hw.wiphy->cipher_suites) { - /* If the driver advertises, or doesn't support SW crypto, - * we only need to remove WEP if necessary. - */ - if (have_wep) - return 0; - - /* well if it has _no_ ciphers ... fine */ - if (!local->hw.wiphy->n_cipher_suites) - return 0; - - /* Driver provides cipher suites, but we need to exclude WEP */ - suites = kmemdup_array(local->hw.wiphy->cipher_suites, - local->hw.wiphy->n_cipher_suites, - sizeof(u32), GFP_KERNEL); - if (!suites) - return -ENOMEM; - - for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { - u32 suite = local->hw.wiphy->cipher_suites[r]; - - if (suite == WLAN_CIPHER_SUITE_WEP40 || - suite == WLAN_CIPHER_SUITE_WEP104) - continue; - suites[w++] = suite; - } - } else { + if (ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) && fips_enabled) { + dev_err(local->hw.wiphy->dev.parent, + "Drivers with SW_CRYPTO_CONTROL cannot work with FIPS\n"); + return -EINVAL; + } + + if (WARN_ON(ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL) && + !local->hw.wiphy->cipher_suites)) + return -EINVAL; + + if (fips_enabled || !local->hw.wiphy->cipher_suites) { /* assign the (software supported and perhaps offloaded) * cipher suites */ @@ -1083,19 +1063,13 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) if (!have_mfp) local->hw.wiphy->n_cipher_suites -= 4; - if (!have_wep) { - local->hw.wiphy->cipher_suites += 2; - local->hw.wiphy->n_cipher_suites -= 2; + /* FIPS does not permit the use of RC4 */ + if (fips_enabled) { + local->hw.wiphy->cipher_suites += 3; + local->hw.wiphy->n_cipher_suites -= 3; } - - /* not dynamically allocated, so just return */ - return 0; } - local->hw.wiphy->cipher_suites = suites; - local->hw.wiphy->n_cipher_suites = w; - local->wiphy_ciphers_allocated = true; - return 0; } @@ -1651,10 +1625,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ieee80211_led_exit(local); destroy_workqueue(local->workqueue); fail_workqueue: - if (local->wiphy_ciphers_allocated) { - kfree(local->hw.wiphy->cipher_suites); - local->wiphy_ciphers_allocated = false; - } kfree(local->int_scan_req); return result; } @@ -1725,11 +1695,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) mutex_destroy(&local->iflist_mtx); - if (local->wiphy_ciphers_allocated) { - kfree(local->hw.wiphy->cipher_suites); - local->wiphy_ciphers_allocated = false; - } - idr_for_each(&local->ack_status_frames, ieee80211_free_ack_frame, NULL); idr_destroy(&local->ack_status_frames); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 53f8b9bd2bd4..5298dbbb5341 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1214,18 +1214,36 @@ EXPORT_SYMBOL_IF_MAC80211_KUNIT(ieee80211_determine_chan_mode); static int ieee80211_config_bw(struct ieee80211_link_data *link, struct ieee802_11_elems *elems, - bool update, u64 *changed, - const char *frame) + bool update, u64 *changed, u16 stype) { struct ieee80211_channel *channel = link->conf->chanreq.oper.chan; struct ieee80211_sub_if_data *sdata = link->sdata; struct ieee80211_chan_req chanreq = {}; struct cfg80211_chan_def ap_chandef; enum ieee80211_conn_mode ap_mode; + const char *frame; u32 vht_cap_info = 0; u16 ht_opmode; int ret; + switch (stype) { + case IEEE80211_STYPE_BEACON: + frame = "beacon"; + break; + case IEEE80211_STYPE_ASSOC_RESP: + frame = "assoc response"; + break; + case IEEE80211_STYPE_REASSOC_RESP: + frame = "reassoc response"; + break; + case IEEE80211_STYPE_ACTION: + /* the only action frame that gets here */ + frame = "ML reconf response"; + break; + default: + return -EINVAL; + } + /* don't track any bandwidth changes in legacy/S1G modes */ if (link->u.mgd.conn.mode == IEEE80211_CONN_MODE_LEGACY || link->u.mgd.conn.mode == IEEE80211_CONN_MODE_S1G) @@ -1274,7 +1292,9 @@ static int ieee80211_config_bw(struct ieee80211_link_data *link, ieee80211_min_bw_limit_from_chandef(&chanreq.oper)) ieee80211_chandef_downgrade(&chanreq.oper, NULL); - if (ap_chandef.chan->band == NL80211_BAND_6GHZ && + /* TPE element is not present in (re)assoc/ML reconfig response */ + if (stype == IEEE80211_STYPE_BEACON && + ap_chandef.chan->band == NL80211_BAND_6GHZ && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HE) { ieee80211_rearrange_tpe(&elems->tpe, &ap_chandef, &chanreq.oper); @@ -2561,7 +2581,8 @@ ieee80211_sta_abort_chanswitch(struct ieee80211_link_data *link) if (!local->ops->abort_channel_switch) return; - ieee80211_link_unreserve_chanctx(link); + if (rcu_access_pointer(link->conf->chanctx_conf)) + ieee80211_link_unreserve_chanctx(link); ieee80211_vif_unblock_queues_csa(sdata); @@ -5347,7 +5368,9 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, /* check/update if AP changed anything in assoc response vs. scan */ if (ieee80211_config_bw(link, elems, link_id == assoc_data->assoc_link_id, - changed, "assoc response")) { + changed, + le16_to_cpu(mgmt->frame_control) & + IEEE80211_FCTL_STYPE)) { ret = false; goto out; } @@ -7542,7 +7565,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, changed |= ieee80211_recalc_twt_req(sdata, sband, link, link_sta, elems); - if (ieee80211_config_bw(link, elems, true, &changed, "beacon")) { + if (ieee80211_config_bw(link, elems, true, &changed, + IEEE80211_STYPE_BEACON)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DEAUTH_LEAVING, true, deauth_buf); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index caa3e6b3f46e..b414c9e6e61b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3033,7 +3033,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; struct sk_buff_head frame_list; - ieee80211_rx_result res; struct ethhdr ethhdr; const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; @@ -3095,24 +3094,18 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) while (!skb_queue_empty(&frame_list)) { rx->skb = __skb_dequeue(&frame_list); - res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); - switch (res) { + switch (ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb)) { case RX_QUEUED: - continue; - case RX_CONTINUE: break; + case RX_CONTINUE: + if (ieee80211_frame_allowed(rx, fc)) { + ieee80211_deliver_skb(rx); + break; + } + fallthrough; default: - goto free; + dev_kfree_skb(rx->skb); } - - if (!ieee80211_frame_allowed(rx, fc)) - goto free; - - ieee80211_deliver_skb(rx); - continue; - -free: - dev_kfree_skb(rx->skb); } return RX_QUEUED; @@ -3587,41 +3580,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto handled; } case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { - struct ieee80211_supported_band *sband; u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; - enum ieee80211_sta_rx_bandwidth max_bw, new_bw; - struct sta_opmode_info sta_opmode = {}; + + if (chanwidth != IEEE80211_HT_CHANWIDTH_20MHZ && + chanwidth != IEEE80211_HT_CHANWIDTH_ANY) + goto invalid; /* If it doesn't support 40 MHz it can't change ... */ if (!(rx->link_sta->pub->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - goto handled; - - if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) - max_bw = IEEE80211_STA_RX_BW_20; - else - max_bw = ieee80211_sta_cap_rx_bw(rx->link_sta); - - /* set cur_max_bandwidth and recalc sta bw */ - rx->link_sta->cur_max_bandwidth = max_bw; - new_bw = ieee80211_sta_cur_vht_bw(rx->link_sta); - - if (rx->link_sta->pub->bandwidth == new_bw) + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) goto handled; - rx->link_sta->pub->bandwidth = new_bw; - sband = rx->local->hw.wiphy->bands[status->band]; - sta_opmode.bw = - ieee80211_sta_rx_bw_to_chan_width(rx->link_sta); - sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; - - rate_control_rate_update(local, sband, rx->link_sta, - IEEE80211_RC_BW_CHANGED); - cfg80211_sta_opmode_change_notify(sdata->dev, - rx->sta->addr, - &sta_opmode, - GFP_ATOMIC); - goto handled; + goto queue; } default: goto invalid; diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index c5c5d16ed6c8..b099d79e8fbb 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -672,8 +672,9 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED; } } else { - pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d", - link_sta->pub->addr, nss); + sdata_dbg(sdata, + "Ignore NSS change to invalid %d in VHT opmode notif from %pM", + nss, link_sta->pub->addr); } } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4e6c0a4e2a82..63f015ce9ad4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7451,6 +7451,7 @@ static int nl80211_dump_station(struct sk_buff *skb, struct wireless_dev *wdev; u8 mac_addr[ETH_ALEN]; int sta_idx = cb->args[2]; + bool sinfo_alloc = false; int err, i; err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL); @@ -7479,6 +7480,7 @@ static int nl80211_dump_station(struct sk_buff *skb, err = -ENOMEM; goto out_err; } + sinfo_alloc = true; } err = rdev_dump_station(rdev, wdev->netdev, sta_idx, @@ -7491,6 +7493,11 @@ static int nl80211_dump_station(struct sk_buff *skb, if (sinfo.valid_links) cfg80211_sta_set_mld_sinfo(&sinfo); + /* reset the sinfo_alloc flag as nl80211_send_station() + * always releases sinfo + */ + sinfo_alloc = false; + if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, @@ -7505,7 +7512,8 @@ static int nl80211_dump_station(struct sk_buff *skb, cb->args[2] = sta_idx; err = skb->len; out_err: - cfg80211_sinfo_release_content(&sinfo); + if (sinfo_alloc) + cfg80211_sinfo_release_content(&sinfo); wiphy_unlock(&rdev->wiphy); return err; @@ -9761,6 +9769,7 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, { unsigned int link_id; bool all_ok = true; + int radio_idx; lockdep_assert_wiphy(wdev->wiphy); @@ -9770,8 +9779,10 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, if (!cfg80211_beaconing_iface_active(wdev)) return true; + radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, chan); + /* - * FIXME: check if we have a free HW resource/link for chan + * FIXME: check if we have a free radio/link for chan * * This, as well as the FIXME below, requires knowing the link * capabilities of the hardware. @@ -9780,20 +9791,28 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev, /* we cannot leave radar channels */ for_each_valid_link(wdev, link_id) { struct cfg80211_chan_def *chandef; + int link_radio_idx; chandef = wdev_chandef(wdev, link_id); if (!chandef || !chandef->chan) continue; + if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) + continue; + /* - * FIXME: don't require all_ok, but rather check only the - * correct HW resource/link onto which 'chan' falls, - * as only that link leaves the channel for doing - * the off-channel operation. + * chandef->chan is a radar channel. If the radio/link onto + * which this radar channel falls is the same radio/link onto + * which the input 'chan' falls, off-channel operation should + * not be allowed. Hence, set 'all_ok' to false. */ - if (chandef->chan->flags & IEEE80211_CHAN_RADAR) + link_radio_idx = cfg80211_get_radio_idx_by_chan(wdev->wiphy, + chandef->chan); + if (link_radio_idx == radio_idx) { all_ok = false; + break; + } } if (all_ok) @@ -10995,6 +11014,16 @@ skip_beacons: if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) params.block_tx = true; + if ((wdev->iftype == NL80211_IFTYPE_AP || + wdev->iftype == NL80211_IFTYPE_P2P_GO) && + info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) { + err = nl80211_parse_unsol_bcast_probe_resp( + rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], + ¶ms.unsol_bcast_probe_resp); + if (err) + goto free; + } + params.link_id = link_id; err = rdev_channel_switch(rdev, dev, ¶ms); @@ -16797,6 +16826,14 @@ static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info) params.counter_offset_presp = offset; } + if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) { + err = nl80211_parse_unsol_bcast_probe_resp( + rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], + ¶ms.unsol_bcast_probe_resp); + if (err) + goto out; + } + params.link_id = nl80211_link_id(info->attrs); err = rdev_color_change(rdev, dev, ¶ms); |
