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

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

Johannes Berg says:

====================
Plenty of things going on, notably:
- iwlwifi: major cleanups/rework
- brcmfmac: gets AP isolation support
- mac80211: gets more S1G support

* tag 'wireless-next-2025-09-11' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (94 commits)
wifi: mwifiex: fix endianness handling in mwifiex_send_rgpower_table
wifi: cfg80211: Remove the redundant wiphy_dev
wifi: mac80211: fix incorrect comment
wifi: cfg80211: update the time stamps in hidden ssid
wifi: mac80211: Fix HE capabilities element check
wifi: mac80211: add tx_handlers_drop statistics to ethtool
wifi: mac80211: fix reporting of all valid links in sta_set_sinfo()
wifi: iwlwifi: mld: CHANNEL_SURVEY_NOTIF is always supported
wifi: iwlwifi: mld: remove support of iwl_esr_mode_notif version 1
wifi: iwlwifi: mld: remove support from of sta cmd version 1
wifi: iwlwifi: mld: remove support of roc cmd version 5
wifi: iwlwifi: mld: remove support of mac cmd ver 2
wifi: iwlwifi: mld: don't consider phy cmd version 5
wifi: iwlwifi: implement wowlan status notification API update
wifi: iwlwifi: fw: Add ASUS to PPAG and TAS list
wifi: iwlwifi: add kunit tests for nvm parse
wifi: iwlwifi: api: add a flag to iwl_link_ctx_modify_flags
wifi: iwlwifi: pcie: move ltr_enabled to the specific transport
wifi: iwlwifi: pcie: move pm_support to the specific transport
wifi: iwlwifi: rename iwl_finish_nic_init
...
====================

Link: https://patch.msgid.link/20250911100854.20445-3-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+2915 -3863
+1 -1
drivers/net/wireless/ath/carl9170/rx.c
··· 555 555 /* Check whenever the PHY can be turned off again. */ 556 556 557 557 /* 1. What about buffered unicast traffic for our AID? */ 558 - cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid); 558 + cam = ieee80211_check_tim(tim_ie, tim_len, ar->common.curaid, false); 559 559 560 560 /* 2. Maybe the AP wants to send multicast/broadcast data? */ 561 561 cam |= !!(tim_ie->bitmap_ctrl & 0x01);
+1
drivers/net/wireless/ath/wil6210/cfg80211.c
··· 2708 2708 wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); 2709 2709 wiphy->mgmt_stypes = wil_mgmt_stypes; 2710 2710 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS; 2711 + wiphy->bss_param_support = WIPHY_BSS_PARAM_AP_ISOLATE; 2711 2712 2712 2713 wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands); 2713 2714 wiphy->vendor_commands = wil_nl80211_vendor_commands;
+1 -1
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
··· 997 997 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356, WCC), 998 998 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359, WCC), 999 999 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43751, WCC), 1000 + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43752, WCC), 1000 1001 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373, CYW), 1001 1002 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012, CYW), 1002 - BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW), 1003 1003 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW), 1004 1004 CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW), 1005 1005 { /* end: all zeroes */ }
+23
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
··· 5958 5958 return brcmf_set_pmk(ifp, NULL, 0); 5959 5959 } 5960 5960 5961 + static int brcmf_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, 5962 + struct bss_parameters *params) 5963 + { 5964 + struct brcmf_if *ifp = netdev_priv(dev); 5965 + int ret = 0; 5966 + 5967 + /* In AP mode, the "ap_isolate" value represents 5968 + * 0 = allow low-level bridging of frames between associated stations 5969 + * 1 = restrict low-level bridging of frames to isolate associated stations 5970 + * -1 = do not change existing setting 5971 + */ 5972 + if (params->ap_isolate >= 0) { 5973 + ret = brcmf_fil_iovar_int_set(ifp, "ap_isolate", params->ap_isolate); 5974 + if (ret < 0) 5975 + brcmf_err("ap_isolate iovar failed: ret=%d\n", ret); 5976 + } 5977 + 5978 + return ret; 5979 + } 5980 + 5961 5981 static struct cfg80211_ops brcmf_cfg80211_ops = { 5962 5982 .add_virtual_intf = brcmf_cfg80211_add_iface, 5963 5983 .del_virtual_intf = brcmf_cfg80211_del_iface, ··· 6025 6005 .update_connect_params = brcmf_cfg80211_update_conn_params, 6026 6006 .set_pmk = brcmf_cfg80211_set_pmk, 6027 6007 .del_pmk = brcmf_cfg80211_del_pmk, 6008 + .change_bss = brcmf_cfg80211_change_bss, 6028 6009 }; 6029 6010 6030 6011 struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings) ··· 7679 7658 wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) | 7680 7659 BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) | 7681 7660 BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST); 7661 + 7662 + wiphy->bss_param_support = WIPHY_BSS_PARAM_AP_ISOLATE; 7682 7663 7683 7664 wiphy->flags |= WIPHY_FLAG_NETNS_OK | 7684 7665 WIPHY_FLAG_PS_ON_BY_DEFAULT |
+2 -2
drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
··· 738 738 case BRCM_CC_4364_CHIP_ID: 739 739 case CY_CC_4373_CHIP_ID: 740 740 return 0x160000; 741 - case CY_CC_43752_CHIP_ID: 742 741 case BRCM_CC_43751_CHIP_ID: 742 + case BRCM_CC_43752_CHIP_ID: 743 743 case BRCM_CC_4377_CHIP_ID: 744 744 return 0x170000; 745 745 case BRCM_CC_4378_CHIP_ID: ··· 1452 1452 return (reg & CC_SR_CTL0_ENABLE_MASK) != 0; 1453 1453 case BRCM_CC_4359_CHIP_ID: 1454 1454 case BRCM_CC_43751_CHIP_ID: 1455 - case CY_CC_43752_CHIP_ID: 1455 + case BRCM_CC_43752_CHIP_ID: 1456 1456 case CY_CC_43012_CHIP_ID: 1457 1457 addr = CORE_CC_REG(pmu->base, retention_ctl); 1458 1458 reg = chip->ops->read32(chip->ctx, addr);
+9 -5
drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
··· 554 554 data = (u8 *)fw->data; 555 555 data_len = fw->size; 556 556 } else { 557 - if ((data = bcm47xx_nvram_get_contents(&data_len))) 557 + data = bcm47xx_nvram_get_contents(&data_len); 558 + if (data) { 558 559 free_bcm47xx_nvram = true; 559 - else if ((data = brcmf_fw_nvram_from_efi(&data_len))) 560 - kfree_nvram = true; 561 - else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) 562 - goto fail; 560 + } else { 561 + data = brcmf_fw_nvram_from_efi(&data_len); 562 + if (data) 563 + kfree_nvram = true; 564 + else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) 565 + goto fail; 566 + } 563 567 } 564 568 565 569 if (data)
+4 -4
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
··· 655 655 BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), 656 656 BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), 657 657 BRCMF_FW_ENTRY(BRCM_CC_43751_CHIP_ID, 0xFFFFFFFF, 43752), 658 + BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752), 658 659 BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373), 659 660 BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012), 660 661 BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439), 661 - BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752) 662 662 }; 663 663 664 664 #define TXCTL_CREDITS 2 ··· 3426 3426 static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus) 3427 3427 { 3428 3428 if (bus->ci->chip == BRCM_CC_43751_CHIP_ID || 3429 - bus->ci->chip == CY_CC_43012_CHIP_ID || 3430 - bus->ci->chip == CY_CC_43752_CHIP_ID) 3429 + bus->ci->chip == BRCM_CC_43752_CHIP_ID || 3430 + bus->ci->chip == CY_CC_43012_CHIP_ID) 3431 3431 return true; 3432 3432 else 3433 3433 return false; ··· 4278 4278 4279 4279 switch (sdiod->func1->device) { 4280 4280 case SDIO_DEVICE_ID_BROADCOM_43751: 4281 + case SDIO_DEVICE_ID_BROADCOM_43752: 4281 4282 case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373: 4282 - case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752: 4283 4283 brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n", 4284 4284 CY_4373_F2_WATERMARK); 4285 4285 brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK,
-1
drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
··· 60 60 #define CY_CC_4373_CHIP_ID 0x4373 61 61 #define CY_CC_43012_CHIP_ID 43012 62 62 #define CY_CC_43439_CHIP_ID 43439 63 - #define CY_CC_43752_CHIP_ID 43752 64 63 65 64 /* USB Device IDs */ 66 65 #define BRCM_USB_43143_DEVICE_ID 0xbd1e
-24
drivers/net/wireless/intel/iwlegacy/iwl-spectrum.h
··· 50 50 __le16 duration; 51 51 } __packed; 52 52 53 - struct ieee80211_info_element { 54 - u8 id; 55 - u8 len; 56 - u8 data[]; 57 - } __packed; 58 - 59 - struct ieee80211_measurement_request { 60 - struct ieee80211_info_element ie; 61 - u8 token; 62 - u8 mode; 63 - u8 type; 64 - struct ieee80211_measurement_params params[]; 65 - } __packed; 66 - 67 - struct ieee80211_measurement_report { 68 - struct ieee80211_info_element ie; 69 - u8 token; 70 - u8 mode; 71 - u8 type; 72 - union { 73 - struct ieee80211_basic_report basic[0]; 74 - } u; 75 - } __packed; 76 - 77 53 #endif
+9 -9
drivers/net/wireless/intel/iwlwifi/cfg/bz.c
··· 9 9 #include "iwl-prph.h" 10 10 #include "fw/api/txq.h" 11 11 12 - /* Highest firmware API version supported */ 13 - #define IWL_BZ_UCODE_API_MAX 102 12 + /* Highest firmware core release supported */ 13 + #define IWL_BZ_UCODE_CORE_MAX 99 14 14 15 15 /* Lowest firmware API version supported */ 16 - #define IWL_BZ_UCODE_API_MIN 98 16 + #define IWL_BZ_UCODE_API_MIN 100 17 17 18 18 /* Memory offsets and lengths */ 19 19 #define IWL_BZ_SMEM_OFFSET 0x400000 ··· 75 75 }, 76 76 }, 77 77 .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, 78 - .ucode_api_max = IWL_BZ_UCODE_API_MAX, 78 + .ucode_api_max = ENCODE_CORE_AS_API(IWL_BZ_UCODE_CORE_MAX), 79 79 .ucode_api_min = IWL_BZ_UCODE_API_MIN, 80 80 }; 81 81 ··· 101 101 .low_latency_xtal = true, 102 102 }; 103 103 104 - IWL_FW_AND_PNVM(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX); 105 - IWL_FW_AND_PNVM(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX); 106 - IWL_FW_AND_PNVM(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_API_MAX); 107 - IWL_FW_AND_PNVM(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_API_MAX); 108 - IWL_FW_AND_PNVM(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_API_MAX); 104 + IWL_CORE_FW(IWL_BZ_A_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 105 + IWL_CORE_FW(IWL_BZ_A_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 106 + IWL_CORE_FW(IWL_BZ_A_FM4_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 107 + IWL_CORE_FW(IWL_GL_B_FM_B_FW_PRE, IWL_BZ_UCODE_CORE_MAX); 108 + IWL_CORE_FW(IWL_GL_C_FM_C_FW_PRE, IWL_BZ_UCODE_CORE_MAX);
+5 -8
drivers/net/wireless/intel/iwlwifi/cfg/dr.c
··· 8 8 #include "iwl-prph.h" 9 9 #include "fw/api/txq.h" 10 10 11 - /* Highest firmware API version supported */ 12 - #define IWL_DR_UCODE_API_MAX 102 11 + /* Highest firmware core release supported */ 12 + #define IWL_DR_UCODE_CORE_MAX 99 13 13 14 14 /* Lowest firmware API version supported */ 15 - #define IWL_DR_UCODE_API_MIN 98 15 + #define IWL_DR_UCODE_API_MIN 100 16 16 17 17 /* Memory offsets and lengths */ 18 18 #define IWL_DR_SMEM_OFFSET 0x400000 19 19 #define IWL_DR_SMEM_LEN 0xD0000 20 20 21 21 #define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0" 22 - 23 - #define IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(api) \ 24 - IWL_DR_A_PE_A_FW_PRE "-" __stringify(api) ".ucode" 25 22 26 23 static const struct iwl_family_base_params iwl_dr_base = { 27 24 .num_of_queues = 512, ··· 70 73 }, 71 74 }, 72 75 .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, 73 - .ucode_api_max = IWL_DR_UCODE_API_MAX, 76 + .ucode_api_max = ENCODE_CORE_AS_API(IWL_DR_UCODE_CORE_MAX), 74 77 .ucode_api_min = IWL_DR_UCODE_API_MIN, 75 78 }; 76 79 ··· 86 89 .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, 87 90 }; 88 91 89 - MODULE_FIRMWARE(IWL_DR_A_PE_A_FW_MODULE_FIRMWARE(IWL_DR_UCODE_API_MAX)); 92 + IWL_CORE_FW(IWL_DR_A_PE_A_FW_PRE, IWL_DR_UCODE_CORE_MAX); 90 93
+17 -5
drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c
··· 9 9 #define IWL_GF_UCODE_API_MAX 100 10 10 11 11 /* Lowest firmware API version supported */ 12 - #define IWL_GF_UCODE_API_MIN 98 12 + #define IWL_GF_UCODE_API_MIN 100 13 13 14 14 #define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0" 15 15 #define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0" ··· 22 22 #define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0" 23 23 #define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0" 24 24 #define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0" 25 + 26 + #define IWL_BZ_A_GF_A_MODULE_FIRMWARE(api) \ 27 + IWL_BZ_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" 28 + 29 + #define IWL_BZ_A_GF4_A_MODULE_FIRMWARE(api) \ 30 + IWL_BZ_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" 31 + 32 + #define IWL_SC_A_GF_A_MODULE_FIRMWARE(api) \ 33 + IWL_SC_A_GF_A_FW_PRE "-" __stringify(api) ".ucode" 34 + 35 + #define IWL_SC_A_GF4_A_MODULE_FIRMWARE(api) \ 36 + IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode" 25 37 26 38 /* NVM versions */ 27 39 #define IWL_GF_NVM_VERSION 0x0a1d ··· 79 67 IWL_FW_AND_PNVM(IWL_MA_B_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); 80 68 IWL_FW_AND_PNVM(IWL_MA_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 81 69 IWL_FW_AND_PNVM(IWL_MA_B_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 82 - IWL_FW_AND_PNVM(IWL_BZ_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); 83 - IWL_FW_AND_PNVM(IWL_BZ_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 84 - IWL_FW_AND_PNVM(IWL_SC_A_GF_A_FW_PRE, IWL_GF_UCODE_API_MAX); 85 - IWL_FW_AND_PNVM(IWL_SC_A_GF4_A_FW_PRE, IWL_GF_UCODE_API_MAX); 70 + MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); 71 + MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); 72 + MODULE_FIRMWARE(IWL_SC_A_GF_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX)); 73 + MODULE_FIRMWARE(IWL_SC_A_GF4_A_MODULE_FIRMWARE(IWL_GF_UCODE_API_MAX));
+1 -1
drivers/net/wireless/intel/iwlwifi/cfg/rf-hr.c
··· 9 9 #define IWL_HR_UCODE_API_MAX 100 10 10 11 11 /* Lowest firmware API version supported */ 12 - #define IWL_HR_UCODE_API_MIN 98 12 + #define IWL_HR_UCODE_API_MIN 100 13 13 14 14 #define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0" 15 15 #define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0"
+9 -9
drivers/net/wireless/intel/iwlwifi/cfg/sc.c
··· 9 9 #include "iwl-prph.h" 10 10 #include "fw/api/txq.h" 11 11 12 - /* Highest firmware API version supported */ 13 - #define IWL_SC_UCODE_API_MAX 102 12 + /* Highest firmware core release supported */ 13 + #define IWL_SC_UCODE_CORE_MAX 99 14 14 15 15 /* Lowest firmware API version supported */ 16 - #define IWL_SC_UCODE_API_MIN 98 16 + #define IWL_SC_UCODE_API_MIN 100 17 17 18 18 /* NVM versions */ 19 19 #define IWL_SC_NVM_VERSION 0x0a1d ··· 78 78 }, 79 79 }, 80 80 .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, 81 - .ucode_api_max = IWL_SC_UCODE_API_MAX, 81 + .ucode_api_max = ENCODE_CORE_AS_API(IWL_SC_UCODE_CORE_MAX), 82 82 .ucode_api_min = IWL_SC_UCODE_API_MIN, 83 83 }; 84 84 ··· 94 94 .ltr_delay = IWL_CFG_TRANS_LTR_DELAY_2500US, 95 95 }; 96 96 97 - IWL_FW_AND_PNVM(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_API_MAX); 98 - IWL_FW_AND_PNVM(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); 99 - IWL_FW_AND_PNVM(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); 100 - IWL_FW_AND_PNVM(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_API_MAX); 101 - IWL_FW_AND_PNVM(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_API_MAX); 97 + IWL_CORE_FW(IWL_SC_A_FM_B_FW_PRE, IWL_SC_UCODE_CORE_MAX); 98 + IWL_CORE_FW(IWL_SC_A_FM_C_FW_PRE, IWL_SC_UCODE_CORE_MAX); 99 + IWL_CORE_FW(IWL_SC_A_WH_A_FW_PRE, IWL_SC_UCODE_CORE_MAX); 100 + IWL_CORE_FW(IWL_SC2_A_FM_C_FW_PRE, IWL_SC_UCODE_CORE_MAX); 101 + IWL_CORE_FW(IWL_SC2_A_WH_A_FW_PRE, IWL_SC_UCODE_CORE_MAX);
+1 -1
drivers/net/wireless/intel/iwlwifi/dvm/eeprom.c
··· 766 766 { 767 767 int ret; 768 768 769 - ret = iwl_finish_nic_init(trans); 769 + ret = iwl_trans_activate_nic(trans); 770 770 if (ret) 771 771 return ret; 772 772
+2 -8
drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
··· 378 378 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, 379 379 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); 380 380 381 - iwl_trans_d3_suspend(priv->trans, false, true); 381 + iwl_trans_d3_suspend(priv->trans, true); 382 382 383 383 goto out; 384 384 ··· 422 422 struct ieee80211_vif *vif; 423 423 u32 base; 424 424 int ret; 425 - enum iwl_d3_status d3_status; 426 425 struct error_table_start { 427 426 /* cf. struct iwl_error_event_table */ 428 427 u32 valid; ··· 450 451 /* we'll clear ctx->vif during iwlagn_prepare_restart() */ 451 452 vif = ctx->vif; 452 453 453 - ret = iwl_trans_d3_resume(priv->trans, &d3_status, false, true); 454 + ret = iwl_trans_d3_resume(priv->trans, true); 454 455 if (ret) 455 456 goto out_unlock; 456 - 457 - if (d3_status != IWL_D3_STATUS_ALIVE) { 458 - IWL_INFO(priv, "Device was reset during suspend\n"); 459 - goto out_unlock; 460 - } 461 457 462 458 /* uCode is no longer operating by itself */ 463 459 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
+1 -1
drivers/net/wireless/intel/iwlwifi/dvm/power.c
··· 368 368 /* initialize to default */ 369 369 void iwl_power_initialize(struct iwl_priv *priv) 370 370 { 371 - priv->power_data.bus_pm = priv->trans->pm_support; 371 + priv->power_data.bus_pm = iwl_trans_is_pm_supported(priv->trans); 372 372 373 373 priv->power_data.debug_sleep_level_override = -1; 374 374
+3 -3
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
··· 9 9 #include "acpi.h" 10 10 #include "fw/runtime.h" 11 11 12 - const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6, 13 - 0xA5, 0xB3, 0x1F, 0x73, 14 - 0x8E, 0x28, 0x5A, 0xDE); 12 + static const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6, 13 + 0xA5, 0xB3, 0x1F, 0x73, 14 + 0x8E, 0x28, 0x5A, 0xDE); 15 15 16 16 static const size_t acpi_dsm_size[DSM_FUNC_NUM_FUNCS] = { 17 17 [DSM_FUNC_QUERY] = sizeof(u32),
-2
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
··· 140 140 141 141 struct iwl_fw_runtime; 142 142 143 - extern const guid_t iwl_guid; 144 - 145 143 union acpi_object *iwl_acpi_get_dsm_object(struct device *dev, int rev, 146 144 int func, union acpi_object *args, 147 145 const guid_t *guid);
+106 -7
drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
··· 367 367 ENABLE_NBNS_FILTERING = BIT(2), 368 368 ENABLE_DHCP_FILTERING = BIT(3), 369 369 ENABLE_STORE_BEACON = BIT(4), 370 + HAS_BEACON_PROTECTION = BIT(5), 370 371 }; 371 372 372 373 /** ··· 632 631 struct iwl_wowlan_all_rsc_tsc_v5 sc; 633 632 } __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */ 634 633 634 + /** 635 + * enum iwl_wowlan_key_status - Status of security keys in WoWLAN notifications 636 + * @IWL_WOWLAN_NOTIF_NO_KEY: No key is present; this entry should be ignored. 637 + * @IWL_WOWLAN_STATUS_OLD_KEY: old key exists; no rekey occurred, and only 638 + * metadata is available. 639 + * @IWL_WOWLAN_STATUS_NEW_KEY: A new key was created after a rekey; new key 640 + * material is available. 641 + */ 642 + enum iwl_wowlan_key_status { 643 + IWL_WOWLAN_NOTIF_NO_KEY = 0, 644 + IWL_WOWLAN_STATUS_OLD_KEY = 1, 645 + IWL_WOWLAN_STATUS_NEW_KEY = 2 646 + }; 647 + 648 + /** 649 + * struct iwl_wowlan_gtk_status - GTK status 650 + * @key: GTK material 651 + * @key_len: GTK length, if set to 0, the key is not available 652 + * @key_flags: information about the key: 653 + * bits[0:1]: key index assigned by the AP 654 + * bits[2:6]: GTK index of the key in the internal DB 655 + * bit[7]: Set iff this is the currently used GTK 656 + * @key_status: key status, see &enum iwl_wowlan_key_status 657 + * @reserved: padding 658 + * @tkip_mic_key: TKIP RX MIC key 659 + * @sc: RSC/TSC counters 660 + */ 661 + struct iwl_wowlan_gtk_status { 662 + u8 key[WOWLAN_KEY_MAX_SIZE]; 663 + u8 key_len; 664 + u8 key_flags; 665 + u8 key_status; 666 + u8 reserved; 667 + u8 tkip_mic_key[IWL_MIC_KEY_SIZE]; 668 + struct iwl_wowlan_all_rsc_tsc_v5 sc; 669 + } __packed; /* WOWLAN_GTK_MATERIAL_VER_4 */ 670 + 635 671 #define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1)) 636 672 #define IWL_WOWLAN_IGTK_BIGTK_IDX_MASK (BIT(0)) 673 + 674 + /** 675 + * struct iwl_wowlan_igtk_status_v1 - IGTK status 676 + * @key: IGTK material 677 + * @ipn: the IGTK packet number (replay counter) 678 + * @key_len: IGTK length, if set to 0, the key is not available 679 + * @key_flags: information about the key: 680 + * bits[0]: key index assigned by the AP (0: index 4, 1: index 5) 681 + * (0: index 6, 1: index 7 with bigtk) 682 + * bits[1:5]: IGTK index of the key in the internal DB 683 + * bit[6]: Set iff this is the currently used IGTK 684 + */ 685 + struct iwl_wowlan_igtk_status_v1 { 686 + u8 key[WOWLAN_KEY_MAX_SIZE]; 687 + u8 ipn[6]; 688 + u8 key_len; 689 + u8 key_flags; 690 + } __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */ 637 691 638 692 /** 639 693 * struct iwl_wowlan_igtk_status - IGTK status ··· 700 644 * (0: index 6, 1: index 7 with bigtk) 701 645 * bits[1:5]: IGTK index of the key in the internal DB 702 646 * bit[6]: Set iff this is the currently used IGTK 647 + * @key_status: key status, see &enum iwl_wowlan_key_status 648 + * @reserved: padding 703 649 */ 704 650 struct iwl_wowlan_igtk_status { 705 651 u8 key[WOWLAN_KEY_MAX_SIZE]; 706 652 u8 ipn[6]; 707 653 u8 key_len; 708 654 u8 key_flags; 709 - } __packed; /* WOWLAN_IGTK_MATERIAL_VER_1 */ 655 + u8 key_status; 656 + u8 reserved[3]; 657 + } __packed; /* WOWLAN_IGTK_MATERIAL_VER_2 */ 710 658 711 659 /** 712 660 * struct iwl_wowlan_status_v6 - WoWLAN status ··· 760 700 */ 761 701 struct iwl_wowlan_status_v7 { 762 702 struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM]; 763 - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; 703 + struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM]; 764 704 __le64 replay_ctr; 765 705 __le16 pattern_number; 766 706 __le16 non_qos_seq_ctr; ··· 795 735 */ 796 736 struct iwl_wowlan_info_notif_v1 { 797 737 struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; 798 - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; 738 + struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM]; 799 739 __le64 replay_ctr; 800 740 __le16 pattern_number; 801 741 __le16 reserved1; ··· 877 817 */ 878 818 struct iwl_wowlan_info_notif_v3 { 879 819 struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; 880 - struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; 881 - struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM]; 820 + struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM]; 821 + struct iwl_wowlan_igtk_status_v1 bigtk[WOWLAN_BIGTK_KEYS_NUM]; 882 822 __le64 replay_ctr; 883 823 __le16 pattern_number; 884 824 __le16 reserved1; ··· 891 831 u8 station_id; 892 832 u8 reserved2[2]; 893 833 } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_3 */ 834 + 835 + /** 836 + * struct iwl_wowlan_info_notif_v5 - WoWLAN information notification 837 + * @gtk: GTK data 838 + * @igtk: IGTK data 839 + * @bigtk: BIGTK data 840 + * @replay_ctr: GTK rekey replay counter 841 + * @pattern_number: number of the matched patterns 842 + * @qos_seq_ctr: QoS sequence counters to use next 843 + * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason 844 + * @num_of_gtk_rekeys: number of GTK rekeys 845 + * @transmitted_ndps: number of transmitted neighbor discovery packets 846 + * @received_beacons: number of received beacons 847 + * @tid_tear_down: bit mask of tids whose BA sessions were closed 848 + * in suspend state 849 + * @station_id: station id 850 + * @num_mlo_link_keys: number of &struct iwl_wowlan_mlo_gtk structs 851 + * following this notif 852 + * @tid_offloaded_tx: tid used by the firmware to transmit data packets 853 + * while in wowlan 854 + * @mlo_gtks: array of GTKs of size num_mlo_link_keys 855 + */ 856 + struct iwl_wowlan_info_notif_v5 { 857 + struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; 858 + struct iwl_wowlan_igtk_status_v1 igtk[WOWLAN_IGTK_KEYS_NUM]; 859 + struct iwl_wowlan_igtk_status_v1 bigtk[WOWLAN_BIGTK_KEYS_NUM]; 860 + __le64 replay_ctr; 861 + __le16 pattern_number; 862 + __le16 qos_seq_ctr; 863 + __le32 wakeup_reasons; 864 + __le32 num_of_gtk_rekeys; 865 + __le32 transmitted_ndps; 866 + __le32 received_beacons; 867 + u8 tid_tear_down; 868 + u8 station_id; 869 + u8 num_mlo_link_keys; 870 + u8 tid_offloaded_tx; 871 + struct iwl_wowlan_mlo_gtk mlo_gtks[]; 872 + } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */ 894 873 895 874 /** 896 875 * struct iwl_wowlan_info_notif - WoWLAN information notification ··· 953 854 * @mlo_gtks: array of GTKs of size num_mlo_link_keys 954 855 */ 955 856 struct iwl_wowlan_info_notif { 956 - struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; 857 + struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM]; 957 858 struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; 958 859 struct iwl_wowlan_igtk_status bigtk[WOWLAN_BIGTK_KEYS_NUM]; 959 860 __le64 replay_ctr; ··· 968 869 u8 num_mlo_link_keys; 969 870 u8 tid_offloaded_tx; 970 871 struct iwl_wowlan_mlo_gtk mlo_gtks[]; 971 - } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_5 */ 872 + } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_6 */ 972 873 973 874 /** 974 875 * struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification
+3
drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
··· 420 420 * eht_support set to true. No longer used since _VER_3 of this command. 421 421 * @LINK_CONTEXT_MODIFY_BANDWIDTH: Covers iwl_link_ctx_cfg_cmd::modify_bandwidth. 422 422 * Request RX OMI to the AP to modify bandwidth of this link. 423 + * @LINK_CONTEXT_MODIFY_UHR_PARAMS: covers iwl_link_ctx_cfg_cmd::npca_params and 424 + * iwl_link_ctx_cfg_cmd::prio_edca_params. Since _VER_7. 423 425 * @LINK_CONTEXT_MODIFY_ALL: set all above flags 424 426 */ 425 427 enum iwl_link_ctx_modify_flags { ··· 434 432 LINK_CONTEXT_MODIFY_BSS_COLOR_DISABLE = BIT(6), 435 433 LINK_CONTEXT_MODIFY_EHT_PARAMS = BIT(7), 436 434 LINK_CONTEXT_MODIFY_BANDWIDTH = BIT(8), 435 + LINK_CONTEXT_MODIFY_UHR_PARAMS = BIT(9), 437 436 LINK_CONTEXT_MODIFY_ALL = 0xff, 438 437 }; /* LINK_CONTEXT_MODIFY_MASK_E_VER_1 */ 439 438
+1 -1
drivers/net/wireless/intel/iwlwifi/fw/api/offload.h
··· 20 20 /** 21 21 * @WOWLAN_INFO_NOTIFICATION: Notification in 22 22 * &struct iwl_wowlan_info_notif_v1, iwl_wowlan_info_notif_v3, 23 - * or &struct iwl_wowlan_info_notif 23 + * &struct iwl_wowlan_info_notif_v5 or &struct iwl_wowlan_info_notif 24 24 */ 25 25 WOWLAN_INFO_NOTIFICATION = 0xFD, 26 26
+11 -23
drivers/net/wireless/intel/iwlwifi/fw/api/power.h
··· 571 571 /** 572 572 * union iwl_ppag_table_cmd - union for all versions of PPAG command 573 573 * @v1: command version 1 structure. 574 - * @v2: command version from 2 to 6 are same structure as v2. 575 - * but has a different format of the flags bitmap 576 - * @v3: command version 7 structure. 574 + * @v5: command version 5 structure. 575 + * @v7: command version 7 structure. 577 576 * @v1.flags: values from &enum iwl_ppag_flags 578 577 * @v1.gain: table of antenna gain values per chain and sub-band 579 578 * @v1.reserved: reserved 580 - * @v2.flags: values from &enum iwl_ppag_flags 581 - * @v2.gain: table of antenna gain values per chain and sub-band 582 - * @v3.ppag_config_info: see @struct bios_value_u32 583 - * @v3.gain: table of antenna gain values per chain and sub-band 584 - * @v3.reserved: reserved 579 + * @v5.flags: values from &enum iwl_ppag_flags 580 + * @v5.gain: table of antenna gain values per chain and sub-band 581 + * @v7.ppag_config_info: see @struct bios_value_u32 582 + * @v7.gain: table of antenna gain values per chain and sub-band 583 + * @v7.reserved: reserved 585 584 */ 586 585 union iwl_ppag_table_cmd { 587 586 struct { ··· 592 593 __le32 flags; 593 594 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; 594 595 s8 reserved[2]; 595 - } __packed v2; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_2, VER3, VER4, 596 - * VER5, VER6 597 - */ 596 + } __packed v5; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_5 */ 598 597 struct { 599 598 struct bios_value_u32 ppag_config_info; 600 599 s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; 601 600 s8 reserved[2]; 602 - } __packed v3; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ 601 + } __packed v7; /* PER_PLAT_ANTENNA_GAIN_CMD_API_S_VER_7 */ 603 602 } __packed; 604 603 605 - #define IWL_PPAG_CMD_V4_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) 606 - #define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V4_MASK | \ 604 + #define IWL_PPAG_CMD_V1_MASK (IWL_PPAG_ETSI_MASK | IWL_PPAG_CHINA_MASK) 605 + #define IWL_PPAG_CMD_V5_MASK (IWL_PPAG_CMD_V1_MASK | \ 607 606 IWL_PPAG_ETSI_LPI_UHB_MASK | \ 608 607 IWL_PPAG_USA_LPI_UHB_MASK) 609 - 610 - #define IWL_PPAG_CMD_V6_MASK (IWL_PPAG_CMD_V5_MASK | \ 611 - IWL_PPAG_ETSI_VLP_UHB_MASK | \ 612 - IWL_PPAG_ETSI_SP_UHB_MASK | \ 613 - IWL_PPAG_USA_VLP_UHB_MASK | \ 614 - IWL_PPAG_USA_SP_UHB_MASK | \ 615 - IWL_PPAG_CANADA_LPI_UHB_MASK | \ 616 - IWL_PPAG_CANADA_VLP_UHB_MASK | \ 617 - IWL_PPAG_CANADA_SP_UHB_MASK) 618 608 619 609 #define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26 620 610 #define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13
+35
drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
··· 24 24 * for BPSK (MCS 0) with 2 spatial 25 25 * streams 26 26 * @IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK: enable support for EHT extra LTF 27 + * @IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK: support ELR 1.5 Mbps 28 + * @IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK: support ELR 3 Mbps 27 29 */ 28 30 enum iwl_tlc_mng_cfg_flags { 29 31 IWL_TLC_MNG_CFG_FLAGS_STBC_MSK = BIT(0), ··· 34 32 IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK = BIT(3), 35 33 IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK = BIT(4), 36 34 IWL_TLC_MNG_CFG_FLAGS_EHT_EXTRA_LTF_MSK = BIT(6), 35 + IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_1_5_MBPS_MSK = BIT(7), 36 + IWL_TLC_MNG_CFG_FLAGS_UHR_ELR_3_MBPS_MSK = BIT(8), 37 37 }; 38 38 39 39 /** ··· 203 199 __le16 max_mpdu_len; 204 200 __le16 max_tx_op; 205 201 } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */ 202 + 203 + /** 204 + * struct iwl_tlc_config_cmd - TLC configuration 205 + * @sta_id: station id 206 + * @reserved1: reserved 207 + * @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw 208 + * @mode: &enum iwl_tlc_mng_cfg_mode 209 + * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains 210 + * @sgi_ch_width_supp: bitmap of SGI support per channel width 211 + * use BIT(&enum iwl_tlc_mng_cfg_cw) 212 + * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags 213 + * @non_ht_rates: bitmap of supported legacy rates 214 + * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width> 215 + * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz). 216 + * @max_mpdu_len: max MPDU length, in bytes 217 + * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI), 218 + * set zero for no limit. 219 + */ 220 + struct iwl_tlc_config_cmd { 221 + u8 sta_id; 222 + u8 reserved1[3]; 223 + u8 max_ch_width; 224 + u8 mode; 225 + u8 chains; 226 + u8 sgi_ch_width_supp; 227 + __le16 flags; 228 + __le16 non_ht_rates; 229 + __le32 ht_rates[IWL_TLC_NSS_MAX][IWL_TLC_MCS_PER_BW_NUM_V4]; 230 + __le16 max_mpdu_len; 231 + __le16 max_tx_op; 232 + } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_5 */ 206 233 207 234 /** 208 235 * enum iwl_tlc_update_flags - updated fields
+4 -39
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
··· 830 830 } 831 831 832 832 /* reading RXF/TXF sizes */ 833 - if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) { 833 + if (iwl_trans_is_fw_error(fwrt->trans)) { 834 834 fifo_len = iwl_fw_rxf_len(fwrt, mem_cfg); 835 835 fifo_len += iwl_fw_txf_len(fwrt, mem_cfg); 836 836 ··· 2393 2393 struct iwl_fw_ini_dump_cfg_name *cfg_name; 2394 2394 u32 size = sizeof(*tlv) + sizeof(*dump); 2395 2395 u32 num_of_cfg_names = 0; 2396 - u32 hw_type, is_cdb, is_jacket; 2396 + u32 hw_type, is_cdb; 2397 2397 2398 2398 list_for_each_entry(node, &fwrt->trans->dbg.debug_info_tlv_list, list) { 2399 2399 size += sizeof(*cfg_name); ··· 2426 2426 hw_type = CSR_HW_REV_TYPE(fwrt->trans->info.hw_rev); 2427 2427 2428 2428 is_cdb = CSR_HW_RFID_IS_CDB(fwrt->trans->info.hw_rf_id); 2429 - is_jacket = !!(iwl_read_umac_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR) & 2430 - WFPM_OTP_CFG1_IS_JACKET_BIT); 2431 - 2432 - /* Use bits 12 and 13 to indicate jacket/CDB, respectively */ 2433 - hw_type |= (is_jacket | (is_cdb << 1)) << IWL_JACKET_CDB_SHIFT; 2429 + hw_type |= IWL_CDB_MASK(is_cdb); 2434 2430 2435 2431 dump->hw_type = cpu_to_le32(hw_type); 2436 2432 ··· 2470 2474 * the first TLV in the dump 2471 2475 */ 2472 2476 list_add(&entry->list, list); 2473 - 2474 - return entry->size; 2475 - } 2476 - 2477 - static u32 iwl_dump_ini_file_name_info(struct iwl_fw_runtime *fwrt, 2478 - struct list_head *list) 2479 - { 2480 - struct iwl_fw_ini_dump_entry *entry; 2481 - struct iwl_dump_file_name_info *tlv; 2482 - u32 len = strnlen(fwrt->trans->dbg.dump_file_name_ext, 2483 - IWL_FW_INI_MAX_NAME); 2484 - 2485 - if (!fwrt->trans->dbg.dump_file_name_ext_valid) 2486 - return 0; 2487 - 2488 - entry = vzalloc(sizeof(*entry) + sizeof(*tlv) + len); 2489 - if (!entry) 2490 - return 0; 2491 - 2492 - entry->size = sizeof(*tlv) + len; 2493 - 2494 - tlv = (void *)entry->data; 2495 - tlv->type = cpu_to_le32(IWL_INI_DUMP_NAME_TYPE); 2496 - tlv->len = cpu_to_le32(len); 2497 - memcpy(tlv->data, fwrt->trans->dbg.dump_file_name_ext, len); 2498 - 2499 - /* add the dump file name extension tlv to the list */ 2500 - list_add_tail(&entry->list, list); 2501 - 2502 - fwrt->trans->dbg.dump_file_name_ext_valid = false; 2503 2477 2504 2478 return entry->size; 2505 2479 } ··· 2730 2764 &iwl_dump_ini_region_ops[IWL_FW_INI_REGION_DRAM_IMR]); 2731 2765 2732 2766 if (size) { 2733 - size += iwl_dump_ini_file_name_info(fwrt, list); 2734 2767 size += iwl_dump_ini_info(fwrt, trigger, list); 2735 2768 } 2736 2769 ··· 3116 3151 .len[0] = sizeof(hcmd_data), 3117 3152 }; 3118 3153 3119 - if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) 3154 + if (iwl_trans_is_fw_error(fwrt->trans)) 3120 3155 return; 3121 3156 3122 3157 if (fw_has_capa(&fwrt->fw->ucode_capa,
+1 -53
drivers/net/wireless/intel/iwlwifi/fw/dump.c
··· 14 14 #include "iwl-csr.h" 15 15 #include "pnvm.h" 16 16 17 - #define FW_ASSERT_LMAC_FATAL 0x70 18 - #define FW_ASSERT_LMAC2_FATAL 0x72 19 - #define FW_ASSERT_UMAC_FATAL 0x71 20 - #define UMAC_RT_NMI_LMAC2_FATAL 0x72 21 - #define RT_NMI_INTERRUPT_OTHER_LMAC_FATAL 0x73 22 - #define FW_ASSERT_NMI_UNKNOWN 0x84 23 - 24 17 /* 25 18 * Note: This structure is read from the device with IO accesses, 26 19 * and the reading already does the endian conversion. As it is ··· 96 103 #define ERROR_START_OFFSET (1 * sizeof(u32)) 97 104 #define ERROR_ELEM_SIZE (7 * sizeof(u32)) 98 105 99 - static bool iwl_fwrt_if_errorid_other_cpu(u32 err_id) 100 - { 101 - err_id &= 0xFF; 102 - 103 - if ((err_id >= FW_ASSERT_LMAC_FATAL && 104 - err_id <= RT_NMI_INTERRUPT_OTHER_LMAC_FATAL) || 105 - err_id == FW_ASSERT_NMI_UNKNOWN) 106 - return true; 107 - return false; 108 - } 109 - 110 106 static void iwl_fwrt_dump_umac_error_log(struct iwl_fw_runtime *fwrt) 111 107 { 112 108 struct iwl_trans *trans = fwrt->trans; ··· 112 130 113 131 if (table.valid) 114 132 fwrt->dump.umac_err_id = table.error_id; 115 - 116 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.umac_err_id) && 117 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 118 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 119 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 120 - "0x%x", fwrt->dump.umac_err_id); 121 - } 122 133 123 134 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 124 135 IWL_ERR(trans, "Start IWL Error Log Dump:\n"); ··· 178 203 if (err) 179 204 return; 180 205 181 - err = iwl_finish_nic_init(trans); 206 + err = iwl_trans_activate_nic(trans); 182 207 if (err) 183 208 return; 184 209 } ··· 187 212 188 213 if (table.valid) 189 214 fwrt->dump.lmac_err_id[lmac_num] = table.error_id; 190 - 191 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.lmac_err_id[lmac_num]) && 192 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 193 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 194 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 195 - "0x%x", fwrt->dump.lmac_err_id[lmac_num]); 196 - } 197 215 198 216 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { 199 217 IWL_ERR(trans, "Start IWL Error Log Dump:\n"); ··· 273 305 274 306 iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); 275 307 276 - if (table.valid) 277 - fwrt->dump.tcm_err_id[idx] = table.error_id; 278 - 279 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.tcm_err_id[idx]) && 280 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 281 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 282 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 283 - "0x%x", fwrt->dump.tcm_err_id[idx]); 284 - } 285 - 286 308 IWL_ERR(fwrt, "TCM%d status:\n", idx + 1); 287 309 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id); 288 310 IWL_ERR(fwrt, "0x%08X | tcm branchlink2\n", table.blink2); ··· 335 377 return; 336 378 337 379 iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); 338 - 339 - if (table.valid) 340 - fwrt->dump.rcm_err_id[idx] = table.error_id; 341 - 342 - if (!iwl_fwrt_if_errorid_other_cpu(fwrt->dump.rcm_err_id[idx]) && 343 - !fwrt->trans->dbg.dump_file_name_ext_valid) { 344 - fwrt->trans->dbg.dump_file_name_ext_valid = true; 345 - snprintf(fwrt->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 346 - "0x%x", fwrt->dump.rcm_err_id[idx]); 347 - } 348 380 349 381 IWL_ERR(fwrt, "RCM%d status:\n", idx + 1); 350 382 IWL_ERR(fwrt, "0x%08X | error ID\n", table.error_id);
+2 -1
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
··· 372 372 u8 cfg_name[IWL_FW_INI_MAX_CFG_NAME]; 373 373 } __packed; 374 374 375 - #define IWL_JACKET_CDB_SHIFT 12 375 + #define IWL_CDB_MASK(val) val << 13 376 + 376 377 377 378 /* struct iwl_fw_ini_dump_info - ini dump information 378 379 * @version: dump version
+67 -14
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
··· 237 237 return -ENOENT; 238 238 } 239 239 240 - static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len) 240 + static u8 *iwl_pnvm_get_from_fs(struct iwl_trans *trans, size_t *len) 241 241 { 242 242 const struct firmware *pnvm; 243 243 char pnvm_name[MAX_PNVM_NAME]; 244 244 size_t new_len; 245 + u8 *data; 245 246 int ret; 246 247 247 248 iwl_pnvm_get_fs_name(trans, pnvm_name, sizeof(pnvm_name)); ··· 251 250 if (ret) { 252 251 IWL_DEBUG_FW(trans, "PNVM file %s not found %d\n", 253 252 pnvm_name, ret); 254 - return ret; 253 + return NULL; 255 254 } 256 255 257 256 new_len = pnvm->size; 258 - *data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL); 257 + data = kvmemdup(pnvm->data, pnvm->size, GFP_KERNEL); 259 258 release_firmware(pnvm); 260 259 261 - if (!*data) 262 - return -ENOMEM; 260 + if (!data) 261 + return NULL; 263 262 264 263 *len = new_len; 265 264 266 - return 0; 265 + return data; 266 + } 267 + 268 + /** 269 + * enum iwl_pnvm_source - different PNVM possible sources 270 + * 271 + * @IWL_PNVM_SOURCE_NONE: No PNVM. 272 + * @IWL_PNVM_SOURCE_BIOS: PNVM should be read from BIOS. 273 + * @IWL_PNVM_SOURCE_EXTERNAL: read .pnvm external file 274 + * @IWL_PNVM_SOURCE_EMBEDDED: PNVM is embedded in the .ucode file. 275 + */ 276 + enum iwl_pnvm_source { 277 + IWL_PNVM_SOURCE_NONE, 278 + IWL_PNVM_SOURCE_BIOS, 279 + IWL_PNVM_SOURCE_EXTERNAL, 280 + IWL_PNVM_SOURCE_EMBEDDED 281 + }; 282 + 283 + static enum iwl_pnvm_source iwl_select_pnvm_source(struct iwl_trans *trans, 284 + bool intel_sku) 285 + { 286 + 287 + /* Get PNVM from BIOS for non-Intel SKU */ 288 + if (!intel_sku) 289 + return IWL_PNVM_SOURCE_BIOS; 290 + 291 + /* Before those devices, PNVM didn't exist at all */ 292 + if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) 293 + return IWL_PNVM_SOURCE_NONE; 294 + 295 + /* After those devices, we moved to embedded PNVM */ 296 + if (trans->mac_cfg->device_family > IWL_DEVICE_FAMILY_AX210) 297 + return IWL_PNVM_SOURCE_EMBEDDED; 298 + 299 + /* For IWL_DEVICE_FAMILY_AX210, depends on the CRF */ 300 + if (CSR_HW_RFID_TYPE(trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_GF) 301 + return IWL_PNVM_SOURCE_EXTERNAL; 302 + 303 + return IWL_PNVM_SOURCE_NONE; 267 304 } 268 305 269 306 static const u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len, 270 307 __le32 sku_id[3], const struct iwl_fw *fw) 271 308 { 272 309 struct pnvm_sku_package *package; 310 + enum iwl_pnvm_source pnvm_src = 311 + iwl_select_pnvm_source(trans_p, sku_id[2] == 0); 273 312 u8 *image = NULL; 274 313 275 - /* Get PNVM from BIOS for non-Intel SKU */ 276 - if (sku_id[2]) { 314 + IWL_DEBUG_FW(trans_p, "PNVM source %d\n", pnvm_src); 315 + 316 + if (pnvm_src == IWL_PNVM_SOURCE_NONE) 317 + return NULL; 318 + 319 + if (pnvm_src == IWL_PNVM_SOURCE_BIOS) { 277 320 package = iwl_uefi_get_pnvm(trans_p, len); 278 321 if (!IS_ERR_OR_NULL(package)) { 279 322 if (*len >= sizeof(*package)) { ··· 334 289 if (image) 335 290 return image; 336 291 } 292 + 293 + /* PNVM doesn't exist in BIOS. Find the fallback source */ 294 + pnvm_src = iwl_select_pnvm_source(trans_p, true); 295 + IWL_DEBUG_FW(trans_p, "PNVM in BIOS doesn't exist, try %d\n", 296 + pnvm_src); 337 297 } 338 298 339 - if (fw->pnvm_data) { 340 - *len = fw->pnvm_size; 299 + if (pnvm_src == IWL_PNVM_SOURCE_EXTERNAL) { 300 + image = iwl_pnvm_get_from_fs(trans_p, len); 301 + if (image) 302 + return image; 303 + } 341 304 305 + if (pnvm_src == IWL_PNVM_SOURCE_EMBEDDED && fw->pnvm_data) { 306 + *len = fw->pnvm_size; 342 307 return fw->pnvm_data; 343 308 } 344 309 345 - /* If it's not available, or for Intel SKU, try from the filesystem */ 346 - if (iwl_pnvm_get_from_fs(trans_p, &image, len)) 347 - return NULL; 348 - return image; 310 + IWL_ERR(trans_p, "Couldn't get PNVM from required source: %d\n", pnvm_src); 311 + return NULL; 349 312 } 350 313 351 314 static void
+28 -25
drivers/net/wireless/intel/iwlwifi/fw/regulatory.c
··· 59 59 DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), 60 60 }, 61 61 }, 62 - { .ident = "ASUS", 62 + { .ident = "ASUSTEK", 63 63 .matches = { 64 64 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 65 + }, 66 + }, 67 + { .ident = "ASUS", 68 + .matches = { 69 + DMI_MATCH(DMI_SYS_VENDOR, "ASUS"), 65 70 }, 66 71 }, 67 72 { .ident = "GOOGLE-HP", ··· 146 141 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 147 142 }, 148 143 }, 149 - { .ident = "ASUS", 144 + { .ident = "ASUSTEK", 150 145 .matches = { 151 146 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 147 + }, 148 + }, 149 + { .ident = "ASUS", 150 + .matches = { 151 + DMI_MATCH(DMI_SYS_VENDOR, "ASUS"), 152 152 }, 153 153 }, 154 154 { .ident = "GOOGLE-HP", ··· 315 305 return true; 316 306 } 317 307 308 + /* Utility function for iwlmvm and iwlxvt */ 318 309 int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, 319 310 union iwl_ppag_table_cmd *cmd, int *cmd_size) 320 311 { ··· 355 344 num_sub_bands = IWL_NUM_SUB_BANDS_V1; 356 345 gain = cmd->v1.gain[0]; 357 346 *cmd_size = sizeof(cmd->v1); 358 - cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags); 347 + cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V1_MASK); 359 348 if (fwrt->ppag_bios_rev >= 1) { 360 349 /* in this case FW supports revision 0 */ 361 350 IWL_DEBUG_RADIO(fwrt, 362 351 "PPAG table rev is %d, send truncated table\n", 363 352 fwrt->ppag_bios_rev); 364 353 } 365 - } else if (cmd_ver >= 2 && cmd_ver <= 6) { 354 + } else if (cmd_ver == 5) { 366 355 num_sub_bands = IWL_NUM_SUB_BANDS_V2; 367 - gain = cmd->v2.gain[0]; 368 - *cmd_size = sizeof(cmd->v2); 369 - cmd->v2.flags = cpu_to_le32(fwrt->ppag_flags); 356 + gain = cmd->v5.gain[0]; 357 + *cmd_size = sizeof(cmd->v5); 358 + cmd->v5.flags = cpu_to_le32(fwrt->ppag_flags & IWL_PPAG_CMD_V5_MASK); 370 359 if (fwrt->ppag_bios_rev == 0) { 371 360 /* in this case FW supports revisions 1,2 or 3 */ 372 361 IWL_DEBUG_RADIO(fwrt, ··· 374 363 } 375 364 } else if (cmd_ver == 7) { 376 365 num_sub_bands = IWL_NUM_SUB_BANDS_V2; 377 - gain = cmd->v3.gain[0]; 378 - *cmd_size = sizeof(cmd->v3); 379 - cmd->v3.ppag_config_info.table_source = fwrt->ppag_bios_source; 380 - cmd->v3.ppag_config_info.table_revision = fwrt->ppag_bios_rev; 381 - cmd->v3.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags); 366 + gain = cmd->v7.gain[0]; 367 + *cmd_size = sizeof(cmd->v7); 368 + cmd->v7.ppag_config_info.table_source = fwrt->ppag_bios_source; 369 + cmd->v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev; 370 + cmd->v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags); 382 371 } else { 383 372 IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n"); 384 373 return -EINVAL; ··· 389 378 "PPAG MODE bits were read from bios: %d\n", 390 379 fwrt->ppag_flags); 391 380 392 - if (cmd_ver == 6) 393 - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V6_MASK); 394 - else if (cmd_ver == 5) 395 - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK); 396 - else if (cmd_ver < 5) 397 - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK); 398 - 399 - if ((cmd_ver == 1 && 400 - !fw_has_capa(&fwrt->fw->ucode_capa, 401 - IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) || 402 - (cmd_ver == 2 && fwrt->ppag_bios_rev >= 2)) { 381 + if (cmd_ver == 1 && 382 + !fw_has_capa(&fwrt->fw->ucode_capa, 383 + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) { 403 384 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); 404 385 IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n"); 405 386 } else { 406 387 IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n"); 407 388 } 408 389 409 - /* The 'flags' field is the same in v1 and v2 so we can just 390 + /* The 'flags' field is the same in v1 and v5 so we can just 410 391 * use v1 to access it. 411 392 */ 412 393 IWL_DEBUG_RADIO(fwrt, 413 394 "PPAG MODE bits going to be sent: %d\n", 414 395 (cmd_ver < 7) ? le32_to_cpu(cmd->v1.flags) : 415 - le32_to_cpu(cmd->v3.ppag_config_info.value)); 396 + le32_to_cpu(cmd->v7.ppag_config_info.value)); 416 397 417 398 for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) { 418 399 for (j = 0; j < num_sub_bands; j++) {
-1
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h
··· 12 12 #include "fw/api/phy.h" 13 13 #include "fw/api/config.h" 14 14 #include "fw/api/nvm-reg.h" 15 - #include "fw/img.h" 16 15 #include "iwl-trans.h" 17 16 18 17 #define BIOS_SAR_MAX_PROFILE_NUM 4
-2
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
··· 150 150 unsigned long non_collect_ts_start[IWL_FW_INI_TIME_POINT_NUM]; 151 151 u32 *d3_debug_data; 152 152 u32 lmac_err_id[MAX_NUM_LMAC]; 153 - u32 tcm_err_id[MAX_NUM_TCM]; 154 - u32 rcm_err_id[MAX_NUM_RCM]; 155 153 u32 umac_err_id; 156 154 157 155 struct iwl_txf_iter_data txf_iter_data;
+2 -5
drivers/net/wireless/intel/iwlwifi/fw/uefi.c
··· 727 727 struct uefi_cnv_var_general_cfg *data; 728 728 int ret = -EINVAL; 729 729 730 + BUILD_BUG_ON(ARRAY_SIZE(data->functions) < DSM_FUNC_NUM_FUNCS); 731 + 730 732 /* Not supported function index */ 731 733 if (func >= DSM_FUNC_NUM_FUNCS || func == 5) 732 734 return -EOPNOTSUPP; ··· 741 739 if (data->revision != IWL_UEFI_DSM_REVISION) { 742 740 IWL_DEBUG_RADIO(fwrt, "Unsupported UEFI DSM revision:%d\n", 743 741 data->revision); 744 - goto out; 745 - } 746 - 747 - if (ARRAY_SIZE(data->functions) != UEFI_MAX_DSM_FUNCS) { 748 - IWL_DEBUG_RADIO(fwrt, "Invalid size of DSM functions array\n"); 749 742 goto out; 750 743 } 751 744
+36 -4
drivers/net/wireless/intel/iwlwifi/iwl-config.h
··· 11 11 #include <linux/netdevice.h> 12 12 #include <linux/ieee80211.h> 13 13 #include <linux/nl80211.h> 14 + #include <linux/module.h> 14 15 #include <linux/mod_devicetable.h> 15 16 #include "iwl-csr.h" 16 17 #include "iwl-drv.h" ··· 108 107 MODULE_FIRMWARE(pfx "-" __stringify(api) ".ucode"); \ 109 108 MODULE_FIRMWARE(pfx ".pnvm") 110 109 110 + #define IWL_CORE_FW(pfx, core) \ 111 + MODULE_FIRMWARE(pfx "-c" __stringify(core) ".ucode") 112 + 111 113 static inline u8 num_of_ant(u8 mask) 112 114 { 113 115 return !!((mask) & ANT_A) + ··· 196 192 197 193 u8 max_ll_items; 198 194 u8 led_compensation; 199 - u8 ucode_api_max; 200 - u8 ucode_api_min; 195 + u16 ucode_api_max; 196 + u16 ucode_api_min; 201 197 u32 mac_addr_from_csr:10; 202 198 u8 nvm_hw_section_num; 203 199 netdev_features_t features; ··· 213 209 const struct iwl_fw_mon_regs mon_smem_regs; 214 210 const struct iwl_fw_mon_regs mon_dbgi_regs; 215 211 }; 212 + 213 + /* 214 + * FW is released as "core N release", and we used to have a 215 + * gap of 3 between the API version and core number. Now the 216 + * reported API version will be 1000 + core and we encode it 217 + * in the filename as "c<core>". 218 + */ 219 + #define API_IS_CORE_START 1000 220 + #define API_TO_CORE_OFFS 3 221 + #define ENCODE_CORE_AS_API(core) (API_IS_CORE_START + (core)) 222 + 223 + static inline bool iwl_api_is_core_number(int api) 224 + { 225 + return api >= API_IS_CORE_START; 226 + } 227 + 228 + static inline int iwl_api_to_core(int api) 229 + { 230 + if (iwl_api_is_core_number(api)) 231 + return api - API_IS_CORE_START; 232 + 233 + return api - API_TO_CORE_OFFS; 234 + } 235 + 236 + #define FW_API_FMT "%s%d" 237 + #define FW_API_ARG(n) \ 238 + iwl_api_is_core_number(n) ? "c" : "", \ 239 + iwl_api_is_core_number(n) ? (n) - API_IS_CORE_START : (n) 216 240 217 241 /* 218 242 * @stbc: support Tx STBC and 1*SS Rx STBC ··· 454 422 u8 valid_tx_ant; 455 423 u8 valid_rx_ant; 456 424 u8 non_shared_ant; 457 - u8 ucode_api_max; 458 - u8 ucode_api_min; 425 + u16 ucode_api_max; 426 + u16 ucode_api_min; 459 427 u16 num_rbds; 460 428 }; 461 429
+36 -11
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
··· 337 337 return -EINVAL; 338 338 } 339 339 340 + if (CSR_HW_RFID_TYPE(drv->trans->info.hw_rf_id) == IWL_CFG_RF_TYPE_WH && 341 + CSR_HW_RFID_STEP(drv->trans->info.hw_rf_id) == SILICON_A_STEP) { 342 + IWL_ERR(drv, "WH A step is not supported\n"); 343 + return -EINVAL; 344 + } 345 + 340 346 fw_name_pre = iwl_drv_get_fwname_pre(drv->trans, _fw_name_pre); 341 347 342 348 if (first) 343 349 drv->fw_index = ucode_api_max; 350 + else if (drv->fw_index == ENCODE_CORE_AS_API(99)) 351 + drv->fw_index = 101; /* last API-scheme number below core 99 */ 344 352 else 345 353 drv->fw_index--; 346 354 ··· 356 348 IWL_ERR(drv, "no suitable firmware found!\n"); 357 349 358 350 if (ucode_api_min == ucode_api_max) { 359 - IWL_ERR(drv, "%s-%d is required\n", fw_name_pre, 360 - ucode_api_max); 351 + IWL_ERR(drv, "%s-" FW_API_FMT " is required\n", 352 + fw_name_pre, FW_API_ARG(ucode_api_max)); 361 353 } else { 362 - IWL_ERR(drv, "minimum version required: %s-%d\n", 363 - fw_name_pre, ucode_api_min); 364 - IWL_ERR(drv, "maximum version supported: %s-%d\n", 365 - fw_name_pre, ucode_api_max); 354 + IWL_ERR(drv, 355 + "minimum version required: %s-" FW_API_FMT "\n", 356 + fw_name_pre, FW_API_ARG(ucode_api_min)); 357 + IWL_ERR(drv, 358 + "maximum version supported: %s-" FW_API_FMT "\n", 359 + fw_name_pre, FW_API_ARG(ucode_api_max)); 366 360 } 367 361 368 362 IWL_ERR(drv, ··· 372 362 return -ENOENT; 373 363 } 374 364 375 - snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s-%d.ucode", 376 - fw_name_pre, drv->fw_index); 365 + snprintf(drv->firmware_name, sizeof(drv->firmware_name), 366 + "%s-" FW_API_FMT ".ucode", 367 + fw_name_pre, FW_API_ARG(drv->fw_index)); 377 368 378 369 IWL_DEBUG_FW_INFO(drv, "attempting to load firmware '%s'\n", 379 370 drv->firmware_name); ··· 1599 1588 */ 1600 1589 static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) 1601 1590 { 1591 + unsigned int min_core, max_core, loaded_core; 1602 1592 struct iwl_drv *drv = context; 1603 1593 struct iwl_fw *fw = &drv->fw; 1604 1594 const struct iwl_ucode_header *ucode; ··· 1662 1650 * firmware filename ... but we don't check for that and only rely 1663 1651 * on the API version read from firmware header from here on forward 1664 1652 */ 1665 - if (api_ver < api_min || api_ver > api_max) { 1653 + 1654 + /* 1655 + * if -cN.ucode file was loaded, core version == file version, 1656 + * otherwise core version == file version (API version) - 3 1657 + */ 1658 + if (iwl_api_is_core_number(drv->fw_index)) 1659 + loaded_core = api_ver; 1660 + else 1661 + loaded_core = api_ver - API_TO_CORE_OFFS; 1662 + 1663 + min_core = iwl_api_to_core(api_min); 1664 + max_core = iwl_api_to_core(api_max); 1665 + 1666 + if (loaded_core < min_core || loaded_core > max_core) { 1666 1667 IWL_ERR(drv, 1667 1668 "Driver unable to support your firmware API. " 1668 - "Driver supports v%u, firmware is v%u.\n", 1669 - api_max, api_ver); 1669 + "Driver supports FW core %u..%u, firmware is %u.\n", 1670 + min_core, max_core, loaded_core); 1670 1671 goto try_again; 1671 1672 } 1672 1673
+5 -90
drivers/net/wireless/intel/iwlwifi/iwl-io.c
··· 3 3 * Copyright (C) 2003-2014, 2018-2022, 2024-2025 Intel Corporation 4 4 * Copyright (C) 2015-2016 Intel Deutschland GmbH 5 5 */ 6 - #include <linux/delay.h> 7 6 #include <linux/device.h> 8 7 #include <linux/export.h> 9 8 ··· 12 13 #include "iwl-debug.h" 13 14 #include "iwl-prph.h" 14 15 #include "iwl-fh.h" 16 + #include "pcie/gen1_2/internal.h" 15 17 16 18 void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) 17 19 { ··· 160 160 161 161 do { 162 162 if ((iwl_read_prph(trans, addr) & mask) == (bits & mask)) 163 - return t; 163 + return 0; 164 164 udelay(IWL_POLL_INTERVAL); 165 165 t += IWL_POLL_INTERVAL; 166 166 } while (t < timeout); ··· 396 396 return 0; 397 397 } 398 398 399 - #define IWL_HOST_MON_BLOCK_PEMON 0x00 400 - #define IWL_HOST_MON_BLOCK_HIPM 0x22 401 - 402 - #define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00 403 - #define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01 404 - #define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06 405 - 406 - static void iwl_dump_host_monitor_block(struct iwl_trans *trans, 407 - u32 block, u32 vec, u32 iter) 399 + int iwl_trans_activate_nic(struct iwl_trans *trans) 408 400 { 409 - int i; 410 - 411 - IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec); 412 - iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); 413 - for (i = 0; i < iter; i++) 414 - IWL_ERR(trans, " value [iter %d]: 0x%08x\n", 415 - i, iwl_read32(trans, CSR_MONITOR_STATUS_REG)); 401 + return iwl_pcie_gen1_2_activate_nic(trans); 416 402 } 417 - 418 - static void iwl_dump_host_monitor(struct iwl_trans *trans) 419 - { 420 - switch (trans->mac_cfg->device_family) { 421 - case IWL_DEVICE_FAMILY_22000: 422 - case IWL_DEVICE_FAMILY_AX210: 423 - IWL_ERR(trans, "CSR_RESET = 0x%x\n", 424 - iwl_read32(trans, CSR_RESET)); 425 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 426 - IWL_HOST_MON_BLOCK_PEMON_VEC0, 15); 427 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 428 - IWL_HOST_MON_BLOCK_PEMON_VEC1, 15); 429 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 430 - IWL_HOST_MON_BLOCK_PEMON_WFPM, 15); 431 - iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM, 432 - IWL_HOST_MON_BLOCK_PEMON_VEC0, 1); 433 - break; 434 - default: 435 - /* not supported yet */ 436 - return; 437 - } 438 - } 439 - 440 - int iwl_finish_nic_init(struct iwl_trans *trans) 441 - { 442 - const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg; 443 - u32 poll_ready; 444 - int err; 445 - 446 - if (mac_cfg->bisr_workaround) { 447 - /* ensure the TOP FSM isn't still in previous reset */ 448 - mdelay(2); 449 - } 450 - 451 - /* 452 - * Set "initialization complete" bit to move adapter from 453 - * D0U* --> D0A* (powered-up active) state. 454 - */ 455 - if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { 456 - iwl_set_bit(trans, CSR_GP_CNTRL, 457 - CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ | 458 - CSR_GP_CNTRL_REG_FLAG_MAC_INIT); 459 - poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS; 460 - } else { 461 - iwl_set_bit(trans, CSR_GP_CNTRL, 462 - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 463 - poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY; 464 - } 465 - 466 - if (mac_cfg->device_family == IWL_DEVICE_FAMILY_8000) 467 - udelay(2); 468 - 469 - /* 470 - * Wait for clock stabilization; once stabilized, access to 471 - * device-internal resources is supported, e.g. iwl_write_prph() 472 - * and accesses to uCode SRAM. 473 - */ 474 - err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000); 475 - if (err < 0) { 476 - IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); 477 - 478 - iwl_dump_host_monitor(trans); 479 - } 480 - 481 - if (mac_cfg->bisr_workaround) { 482 - /* ensure BISR shift has finished */ 483 - udelay(200); 484 - } 485 - 486 - return err < 0 ? err : 0; 487 - } 488 - IWL_EXPORT_SYMBOL(iwl_finish_nic_init); 403 + IWL_EXPORT_SYMBOL(iwl_trans_activate_nic); 489 404 490 405 void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, 491 406 u32 sw_err_bit)
+1 -1
drivers/net/wireless/intel/iwlwifi/iwl-io.h
··· 57 57 void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); 58 58 void iwl_force_nmi(struct iwl_trans *trans); 59 59 60 - int iwl_finish_nic_init(struct iwl_trans *trans); 60 + int iwl_trans_activate_nic(struct iwl_trans *trans); 61 61 62 62 /* Error handling */ 63 63 int iwl_dump_fh(struct iwl_trans *trans, char **buf);
+5 -75
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
··· 140 140 #define N_RATES_52 (N_RATES_24 - RATES_52_OFFS) 141 141 142 142 /** 143 - * enum iwl_nvm_channel_flags - channel flags in NVM 144 - * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo 145 - * @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated 146 - * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. 147 - * @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and 148 - * AP allowed only in 20 MHz. Valid only 149 - * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. 150 - * @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS 151 - * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. 152 - * @NVM_CHANNEL_RADAR: radar detection required 153 - * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed 154 - * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS 155 - * on same channel on 2.4 or same UNII band on 5.2 156 - * @NVM_CHANNEL_UNIFORM: uniform spreading required 157 - * @NVM_CHANNEL_20MHZ: 20 MHz channel okay 158 - * @NVM_CHANNEL_40MHZ: 40 MHz channel okay 159 - * @NVM_CHANNEL_80MHZ: 80 MHz channel okay 160 - * @NVM_CHANNEL_160MHZ: 160 MHz channel okay 161 - * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?) 162 - * @NVM_CHANNEL_VLP: client support connection to UHB VLP AP 163 - * @NVM_CHANNEL_AFC: client support connection to UHB AFC AP 164 - * @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed, 165 - * Valid only when %NVM_CHANNEL_VLP is enabled. 166 - */ 167 - enum iwl_nvm_channel_flags { 168 - NVM_CHANNEL_VALID = BIT(0), 169 - NVM_CHANNEL_IBSS = BIT(1), 170 - NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2), 171 - NVM_CHANNEL_ACTIVE = BIT(3), 172 - NVM_CHANNEL_RADAR = BIT(4), 173 - NVM_CHANNEL_INDOOR_ONLY = BIT(5), 174 - NVM_CHANNEL_GO_CONCURRENT = BIT(6), 175 - NVM_CHANNEL_UNIFORM = BIT(7), 176 - NVM_CHANNEL_20MHZ = BIT(8), 177 - NVM_CHANNEL_40MHZ = BIT(9), 178 - NVM_CHANNEL_80MHZ = BIT(10), 179 - NVM_CHANNEL_160MHZ = BIT(11), 180 - NVM_CHANNEL_DC_HIGH = BIT(12), 181 - NVM_CHANNEL_VLP = BIT(13), 182 - NVM_CHANNEL_AFC = BIT(14), 183 - NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15), 184 - }; 185 - 186 - /** 187 143 * enum iwl_reg_capa_flags_v1 - global flags applied for the whole regulatory 188 144 * domain. 189 145 * @REG_CAPA_V1_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the ··· 237 281 * MCC update command response. 238 282 */ 239 283 #define REG_CAPA_V4_RESP_VER 8 240 - 241 - /** 242 - * struct iwl_reg_capa - struct for global regulatory capabilities, Used for 243 - * handling the different APIs of reg_capa_flags. 244 - * 245 - * @allow_40mhz: 11n channel with a width of 40Mhz is allowed 246 - * for this regulatory domain. 247 - * @allow_80mhz: 11ac channel with a width of 80Mhz is allowed 248 - * for this regulatory domain (valid only in 5 and 6 Ghz). 249 - * @allow_160mhz: 11ac channel with a width of 160Mhz is allowed 250 - * for this regulatory domain (valid only in 5 and 6 Ghz). 251 - * @allow_320mhz: 11be channel with a width of 320Mhz is allowed 252 - * for this regulatory domain (valid only in 6 Ghz). 253 - * @disable_11ax: 11ax is forbidden for this regulatory domain. 254 - * @disable_11be: 11be is forbidden for this regulatory domain. 255 - */ 256 - struct iwl_reg_capa { 257 - bool allow_40mhz; 258 - bool allow_80mhz; 259 - bool allow_160mhz; 260 - bool allow_320mhz; 261 - bool disable_11ax; 262 - bool disable_11be; 263 - }; 264 284 265 285 static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, 266 286 int chan, u32 flags) ··· 974 1042 iftype_data->he_cap.he_cap_elem.phy_cap_info[2] |= 975 1043 IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO; 976 1044 977 - if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT)) 978 - iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |= 979 - IEEE80211_HE_MAC_CAP2_BCAST_TWT; 980 - 981 1045 if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000 && 982 1046 !is_ap) { 983 1047 iftype_data->vendor_elems.data = iwl_vendor_caps; ··· 1528 1600 } 1529 1601 IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); 1530 1602 1531 - static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, 1532 - int ch_idx, u16 nvm_flags, 1533 - struct iwl_reg_capa reg_capa) 1603 + VISIBLE_IF_IWLWIFI_KUNIT 1604 + u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, 1605 + int ch_idx, u16 nvm_flags, 1606 + struct iwl_reg_capa reg_capa) 1534 1607 { 1535 1608 u32 flags = NL80211_RRF_NO_HT40; 1536 1609 ··· 1621 1692 1622 1693 return flags; 1623 1694 } 1695 + EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_nvm_get_regdom_bw_flags); 1624 1696 1625 1697 static struct iwl_reg_capa iwl_get_reg_capa(u32 flags, u8 resp_ver) 1626 1698 {
+74
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
··· 21 21 IWL_NVM_SBANDS_FLAGS_NO_WIDE_IN_5GHZ = BIT(1), 22 22 }; 23 23 24 + /** 25 + * struct iwl_reg_capa - struct for global regulatory capabilities, Used for 26 + * handling the different APIs of reg_capa_flags. 27 + * 28 + * @allow_40mhz: 11n channel with a width of 40Mhz is allowed 29 + * for this regulatory domain. 30 + * @allow_80mhz: 11ac channel with a width of 80Mhz is allowed 31 + * for this regulatory domain (valid only in 5 and 6 Ghz). 32 + * @allow_160mhz: 11ac channel with a width of 160Mhz is allowed 33 + * for this regulatory domain (valid only in 5 and 6 Ghz). 34 + * @allow_320mhz: 11be channel with a width of 320Mhz is allowed 35 + * for this regulatory domain (valid only in 6 Ghz). 36 + * @disable_11ax: 11ax is forbidden for this regulatory domain. 37 + * @disable_11be: 11be is forbidden for this regulatory domain. 38 + */ 39 + struct iwl_reg_capa { 40 + bool allow_40mhz; 41 + bool allow_80mhz; 42 + bool allow_160mhz; 43 + bool allow_320mhz; 44 + bool disable_11ax; 45 + bool disable_11be; 46 + }; 47 + 48 + /** 49 + * enum iwl_nvm_channel_flags - channel flags in NVM 50 + * @NVM_CHANNEL_VALID: channel is usable for this SKU/geo 51 + * @NVM_CHANNEL_IBSS: usable as an IBSS channel and deprecated 52 + * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. 53 + * @NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY: active scanning allowed and 54 + * AP allowed only in 20 MHz. Valid only 55 + * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. 56 + * @NVM_CHANNEL_ACTIVE: active scanning allowed and allows IBSS 57 + * when %IWL_NVM_SBANDS_FLAGS_LAR enabled. 58 + * @NVM_CHANNEL_RADAR: radar detection required 59 + * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed 60 + * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS 61 + * on same channel on 2.4 or same UNII band on 5.2 62 + * @NVM_CHANNEL_UNIFORM: uniform spreading required 63 + * @NVM_CHANNEL_20MHZ: 20 MHz channel okay 64 + * @NVM_CHANNEL_40MHZ: 40 MHz channel okay 65 + * @NVM_CHANNEL_80MHZ: 80 MHz channel okay 66 + * @NVM_CHANNEL_160MHZ: 160 MHz channel okay 67 + * @NVM_CHANNEL_DC_HIGH: DC HIGH required/allowed (?) 68 + * @NVM_CHANNEL_VLP: client support connection to UHB VLP AP 69 + * @NVM_CHANNEL_AFC: client support connection to UHB AFC AP 70 + * @NVM_CHANNEL_VLP_AP_NOT_ALLOWED: UHB VLP AP not allowed, 71 + * Valid only when %NVM_CHANNEL_VLP is enabled. 72 + */ 73 + enum iwl_nvm_channel_flags { 74 + NVM_CHANNEL_VALID = BIT(0), 75 + NVM_CHANNEL_IBSS = BIT(1), 76 + NVM_CHANNEL_ALLOW_20MHZ_ACTIVITY = BIT(2), 77 + NVM_CHANNEL_ACTIVE = BIT(3), 78 + NVM_CHANNEL_RADAR = BIT(4), 79 + NVM_CHANNEL_INDOOR_ONLY = BIT(5), 80 + NVM_CHANNEL_GO_CONCURRENT = BIT(6), 81 + NVM_CHANNEL_UNIFORM = BIT(7), 82 + NVM_CHANNEL_20MHZ = BIT(8), 83 + NVM_CHANNEL_40MHZ = BIT(9), 84 + NVM_CHANNEL_80MHZ = BIT(10), 85 + NVM_CHANNEL_160MHZ = BIT(11), 86 + NVM_CHANNEL_DC_HIGH = BIT(12), 87 + NVM_CHANNEL_VLP = BIT(13), 88 + NVM_CHANNEL_AFC = BIT(14), 89 + NVM_CHANNEL_VLP_AP_NOT_ALLOWED = BIT(15), 90 + }; 91 + 92 + #if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) 93 + u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, 94 + int ch_idx, u16 nvm_flags, 95 + struct iwl_reg_capa reg_capa); 96 + #endif 97 + 24 98 /* 25 99 * iwl_parse_nvm_data - parse NVM data and return values 26 100 *
+34 -37
drivers/net/wireless/intel/iwlwifi/iwl-trans.c
··· 268 268 269 269 struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, 270 270 struct device *dev, 271 - const struct iwl_mac_cfg *mac_cfg, 272 - unsigned int txcmd_size, 273 - unsigned int txcmd_align) 271 + const struct iwl_mac_cfg *mac_cfg) 274 272 { 275 273 struct iwl_trans *trans; 276 274 #ifdef CONFIG_LOCKDEP ··· 290 292 291 293 INIT_DELAYED_WORK(&trans->restart.wk, iwl_trans_restart_wk); 292 294 293 - snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), 294 - "iwl_cmd_pool:%s", dev_name(trans->dev)); 295 - trans->dev_cmd_pool = 296 - kmem_cache_create(trans->dev_cmd_pool_name, 297 - txcmd_size, txcmd_align, 298 - SLAB_HWCACHE_ALIGN, NULL); 299 - if (!trans->dev_cmd_pool) 300 - return NULL; 301 - 302 295 return trans; 303 296 } 304 297 305 298 void iwl_trans_free(struct iwl_trans *trans) 306 299 { 307 300 cancel_delayed_work_sync(&trans->restart.wk); 308 - kmem_cache_destroy(trans->dev_cmd_pool); 309 301 } 310 302 311 303 int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) ··· 305 317 if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) && 306 318 test_bit(STATUS_RFKILL_OPMODE, &trans->status))) 307 319 return -ERFKILL; 308 - 309 - if (unlikely(test_bit(STATUS_SUSPENDED, &trans->status))) 310 - return -EHOSTDOWN; 311 320 312 321 if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) 313 322 return -EIO; ··· 332 347 return ret; 333 348 } 334 349 IWL_EXPORT_SYMBOL(iwl_trans_send_cmd); 350 + 351 + struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) 352 + { 353 + return iwl_pcie_gen1_2_alloc_tx_cmd(trans); 354 + } 355 + IWL_EXPORT_SYMBOL(iwl_trans_alloc_tx_cmd); 356 + 357 + void iwl_trans_free_tx_cmd(struct iwl_trans *trans, 358 + struct iwl_device_tx_cmd *dev_cmd) 359 + { 360 + iwl_pcie_gen1_2_free_tx_cmd(trans, dev_cmd); 361 + } 362 + IWL_EXPORT_SYMBOL(iwl_trans_free_tx_cmd); 335 363 336 364 /* Comparator for struct iwl_hcmd_names. 337 365 * Used in the binary search over a list of host commands. ··· 397 399 398 400 WARN_ON_ONCE(!trans->conf.rx_mpdu_cmd); 399 401 400 - iwl_trans_pcie_op_mode_enter(trans); 402 + iwl_pcie_gen1_2_op_mode_enter(trans); 401 403 } 402 404 IWL_EXPORT_SYMBOL(iwl_trans_op_mode_enter); 403 405 ··· 406 408 might_sleep(); 407 409 408 410 clear_bit(STATUS_TRANS_RESET_IN_PROGRESS, &trans->status); 409 - /* opmode may not resume if it detects errors */ 410 - clear_bit(STATUS_SUSPENDED, &trans->status); 411 411 412 412 return iwl_trans_pcie_start_hw(trans); 413 413 } ··· 503 507 sanitize_ops, sanitize_ctx); 504 508 } 505 509 506 - int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset) 510 + int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset) 507 511 { 508 - int err; 509 - 510 512 might_sleep(); 511 513 512 - err = iwl_trans_pcie_d3_suspend(trans, test, reset); 513 - 514 - if (!err) 515 - set_bit(STATUS_SUSPENDED, &trans->status); 516 - 517 - return err; 514 + return iwl_trans_pcie_d3_suspend(trans, reset); 518 515 } 519 516 IWL_EXPORT_SYMBOL(iwl_trans_d3_suspend); 520 517 521 - int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, 522 - bool test, bool reset) 518 + int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset) 523 519 { 524 - int err; 525 - 526 520 might_sleep(); 527 521 528 - err = iwl_trans_pcie_d3_resume(trans, status, test, reset); 529 - 530 - clear_bit(STATUS_SUSPENDED, &trans->status); 531 - 532 - return err; 522 + return iwl_trans_pcie_d3_resume(trans, reset); 533 523 } 534 524 IWL_EXPORT_SYMBOL(iwl_trans_d3_resume); 535 525 ··· 807 825 { 808 826 iwl_trans_pcie_ctx_info_v2_set_reduce_power(trans, capa); 809 827 } 828 + 829 + bool iwl_trans_is_pm_supported(struct iwl_trans *trans) 830 + { 831 + if (WARN_ON(trans->mac_cfg->gen2)) 832 + return false; 833 + 834 + return iwl_pcie_gen1_is_pm_supported(trans); 835 + } 836 + IWL_EXPORT_SYMBOL(iwl_trans_is_pm_supported); 837 + 838 + bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans) 839 + { 840 + return iwl_pcie_gen1_2_is_ltr_enabled(trans); 841 + } 842 + IWL_EXPORT_SYMBOL(iwl_trans_is_ltr_enabled);
+27 -54
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
··· 275 275 #define IWL_9000_MAX_RX_HW_QUEUES 1 276 276 277 277 /** 278 - * enum iwl_d3_status - WoWLAN image/device status 279 - * @IWL_D3_STATUS_ALIVE: firmware is still running after resume 280 - * @IWL_D3_STATUS_RESET: device was reset while suspended 281 - */ 282 - enum iwl_d3_status { 283 - IWL_D3_STATUS_ALIVE, 284 - IWL_D3_STATUS_RESET, 285 - }; 286 - 287 - /** 288 278 * enum iwl_trans_status: transport status flags 289 279 * @STATUS_SYNC_HCMD_ACTIVE: a SYNC command is being processed 290 280 * @STATUS_DEVICE_ENABLED: APM is enabled ··· 284 294 * @STATUS_RFKILL_OPMODE: RF-kill state reported to opmode 285 295 * @STATUS_FW_ERROR: the fw is in error state 286 296 * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation 287 - * @STATUS_SUPPRESS_CMD_ERROR_ONCE: suppress "FW error in SYNC CMD" once, 288 - * e.g. for testing 289 297 * @STATUS_IN_SW_RESET: device is undergoing reset, cleared by opmode 290 298 * via iwl_trans_finish_sw_reset() 291 299 * @STATUS_RESET_PENDING: reset worker was scheduled, but didn't dump 292 300 * the firmware state yet 293 301 * @STATUS_TRANS_RESET_IN_PROGRESS: reset is still in progress, don't 294 302 * attempt another reset yet 295 - * @STATUS_SUSPENDED: device is suspended, don't send commands that 296 - * aren't marked accordingly 297 303 */ 298 304 enum iwl_trans_status { 299 305 STATUS_SYNC_HCMD_ACTIVE, ··· 300 314 STATUS_RFKILL_OPMODE, 301 315 STATUS_FW_ERROR, 302 316 STATUS_TRANS_DEAD, 303 - STATUS_SUPPRESS_CMD_ERROR_ONCE, 304 317 STATUS_IN_SW_RESET, 305 318 STATUS_RESET_PENDING, 306 319 STATUS_TRANS_RESET_IN_PROGRESS, 307 - STATUS_SUSPENDED, 308 320 }; 309 321 310 322 static inline int ··· 642 658 * @restart_required: indicates debug restart is required 643 659 * @last_tp_resetfw: last handling of reset during debug timepoint 644 660 * @imr_data: IMR debug data allocation 645 - * @dump_file_name_ext: dump file name extension 646 - * @dump_file_name_ext_valid: dump file name extension if valid or not 647 661 * @num_pc: number of program counter for cpu 648 662 * @pc_data: details of the program counter 649 663 * @yoyo_bin_loaded: tells if a yoyo debug file has been loaded ··· 680 698 bool restart_required; 681 699 u32 last_tp_resetfw; 682 700 struct iwl_imr_data imr_data; 683 - u8 dump_file_name_ext[IWL_FW_INI_MAX_NAME]; 684 - bool dump_file_name_ext_valid; 685 701 u32 num_pc; 686 702 struct iwl_pc_data *pc_data; 687 703 bool yoyo_bin_loaded; ··· 810 830 * @hw_rf_id: the device RF ID 811 831 * @hw_cnv_id: the device CNV ID 812 832 * @hw_crf_id: the device CRF ID 813 - * @hw_wfpm_id: the device wfpm ID 814 833 * @hw_id: the ID of the device / sub-device 815 834 * Bits 0:15 represent the sub-device ID 816 835 * Bits 16:31 represent the device ID. ··· 825 846 u32 hw_rf_id; 826 847 u32 hw_crf_id; 827 848 u32 hw_cnv_id; 828 - u32 hw_wfpm_id; 829 849 u32 hw_id; 830 850 u8 pcie_link_speed; 831 851 u8 num_rxqs; ··· 844 866 * @dev: pointer to struct device * that represents the device 845 867 * @info: device information for use by other layers 846 868 * @pnvm_loaded: indicates PNVM was loaded 847 - * @pm_support: set to true in start_hw if link pm is supported 848 - * @ltr_enabled: set to true if the LTR is enabled 869 + * @suppress_cmd_error_once: suppress "FW error in SYNC CMD" once, 870 + * e.g. for testing 849 871 * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed 850 872 * @reduce_power_loaded: indicates reduced power section was loaded 851 873 * @failed_to_load_reduce_power_image: set to true if pnvm loading failed 852 - * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. 853 - * The user should use iwl_trans_{alloc,free}_tx_cmd. 854 - * @dev_cmd_pool_name: name for the TX command allocation pool 855 874 * @dbgfs_dir: iwlwifi debugfs base dir for this device 856 875 * @sync_cmd_lockdep_map: lockdep map for checking sync commands 857 876 * @dbg: additional debug data, see &struct iwl_trans_debug ··· 880 905 const struct iwl_trans_info info; 881 906 bool reduced_cap_sku; 882 907 bool step_urm; 908 + bool suppress_cmd_error_once; 883 909 884 - bool pm_support; 885 - bool ltr_enabled; 886 910 u8 pnvm_loaded:1; 887 911 u8 fail_to_parse_pnvm_image:1; 888 912 u8 reduce_power_loaded:1; 889 913 u8 failed_to_load_reduce_power_image:1; 890 - 891 - /* The following fields are internal only */ 892 - struct kmem_cache *dev_cmd_pool; 893 - char dev_cmd_pool_name[50]; 894 914 895 915 struct dentry *dbgfs_dir; 896 916 ··· 926 956 927 957 void iwl_trans_stop_device(struct iwl_trans *trans); 928 958 929 - int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, bool reset); 959 + int iwl_trans_d3_suspend(struct iwl_trans *trans, bool reset); 930 960 931 - int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, 932 - bool test, bool reset); 961 + int iwl_trans_d3_resume(struct iwl_trans *trans, bool reset); 933 962 934 963 struct iwl_trans_dump_data * 935 964 iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask, 936 965 const struct iwl_dump_sanitize_ops *sanitize_ops, 937 966 void *sanitize_ctx); 938 967 939 - static inline struct iwl_device_tx_cmd * 940 - iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) 941 - { 942 - return kmem_cache_zalloc(trans->dev_cmd_pool, GFP_ATOMIC); 943 - } 968 + struct iwl_device_tx_cmd *iwl_trans_alloc_tx_cmd(struct iwl_trans *trans); 944 969 945 970 int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd); 946 971 947 - static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, 948 - struct iwl_device_tx_cmd *dev_cmd) 949 - { 950 - kmem_cache_free(trans->dev_cmd_pool, dev_cmd); 951 - } 972 + void iwl_trans_free_tx_cmd(struct iwl_trans *trans, 973 + struct iwl_device_tx_cmd *dev_cmd); 952 974 953 975 int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, 954 976 struct iwl_device_tx_cmd *dev_cmd, int queue); ··· 1167 1205 *****************************************************/ 1168 1206 struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, 1169 1207 struct device *dev, 1170 - const struct iwl_mac_cfg *mac_cfg, 1171 - unsigned int txcmd_size, 1172 - unsigned int txcmd_align); 1208 + const struct iwl_mac_cfg *mac_cfg); 1173 1209 void iwl_trans_free(struct iwl_trans *trans); 1174 1210 1175 1211 static inline bool iwl_trans_is_hw_error_value(u32 val) ··· 1190 1230 return result; 1191 1231 } 1192 1232 1193 - static inline void iwl_trans_suppress_cmd_error_once(struct iwl_trans *trans) 1194 - { 1195 - set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &trans->status); 1196 - } 1197 - 1198 1233 static inline bool iwl_trans_device_enabled(struct iwl_trans *trans) 1199 1234 { 1200 1235 return test_bit(STATUS_DEVICE_ENABLED, &trans->status); ··· 1200 1245 return test_bit(STATUS_TRANS_DEAD, &trans->status); 1201 1246 } 1202 1247 1248 + static inline bool iwl_trans_is_fw_error(struct iwl_trans *trans) 1249 + { 1250 + return test_bit(STATUS_FW_ERROR, &trans->status); 1251 + } 1252 + 1253 + /* 1254 + * This function notifies the transport layer of firmware error, the recovery 1255 + * will be handled by the op mode 1256 + */ 1257 + static inline void iwl_trans_notify_fw_error(struct iwl_trans *trans) 1258 + { 1259 + trans->state = IWL_TRANS_NO_FW; 1260 + set_bit(STATUS_FW_ERROR, &trans->status); 1261 + } 1203 1262 /***************************************************** 1204 1263 * PCIe handling 1205 1264 *****************************************************/ ··· 1257 1288 { 1258 1289 return u32_get_bits(trans->info.hw_id, GENMASK(31, 16)); 1259 1290 } 1291 + 1292 + bool iwl_trans_is_pm_supported(struct iwl_trans *trans); 1293 + 1294 + bool iwl_trans_is_ltr_enabled(struct iwl_trans *trans); 1260 1295 1261 1296 #endif /* __iwl_trans_h__ */
-2
drivers/net/wireless/intel/iwlwifi/mei/sap.h
··· 300 300 * @type: See &enum iwl_sap_msg. 301 301 * @len: The length of the message (header not included). 302 302 * @seq_num: For debug. 303 - * @payload: The payload of the message. 304 303 */ 305 304 struct iwl_sap_hdr { 306 305 __le16 type; 307 306 __le16 len; 308 307 __le32 seq_num; 309 - u8 payload[]; 310 308 }; 311 309 312 310 /**
+355 -200
drivers/net/wireless/intel/iwlwifi/mld/d3.c
··· 11 11 #include "mcc.h" 12 12 #include "sta.h" 13 13 #include "mlo.h" 14 + #include "key.h" 14 15 15 16 #include "fw/api/d3.h" 16 17 #include "fw/api/offload.h" ··· 41 40 struct iwl_mld_resume_key_iter_data { 42 41 struct iwl_mld *mld; 43 42 struct iwl_mld_wowlan_status *wowlan_status; 44 - u32 num_keys, gtk_cipher, igtk_cipher, bigtk_cipher; 45 - bool unhandled_cipher; 46 43 }; 47 44 48 45 struct iwl_mld_suspend_key_iter_data { ··· 70 71 71 72 }; 72 73 74 + struct iwl_mld_wowlan_mlo_key { 75 + u8 key[WOWLAN_KEY_MAX_SIZE]; 76 + u8 idx, type, link_id; 77 + u8 pn[6]; 78 + }; 79 + 73 80 /** 74 81 * struct iwl_mld_wowlan_status - contains wowlan status data from 75 82 * all wowlan notifications ··· 94 89 * @bigtk: data of the last two used gtk's by the FW upon resume 95 90 * @ptk: last seq numbers per tid passed by the FW, 96 91 * holds both in tkip and aes formats 92 + * @num_mlo_keys: number of &struct iwl_mld_wowlan_mlo_key structs 93 + * @mlo_keys: array of MLO keys 97 94 */ 98 95 struct iwl_mld_wowlan_status { 99 96 u32 wakeup_reasons; ··· 115 108 struct ieee80211_key_seq tkip_seq[IWL_MAX_TID_COUNT]; 116 109 117 110 } ptk; 111 + 112 + int num_mlo_keys; 113 + struct iwl_mld_wowlan_mlo_key mlo_keys[WOWLAN_MAX_MLO_KEYS]; 118 114 }; 119 115 120 116 #define NETDETECT_QUERY_BUF_LEN \ ··· 281 271 static void 282 272 iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld, 283 273 struct iwl_mld_wowlan_status *wowlan_status, 284 - const struct iwl_wowlan_gtk_status_v3 *gtk_data, 274 + const struct iwl_wowlan_gtk_status *gtk_data, 285 275 const struct iwl_wowlan_all_rsc_tsc_v5 *sc) 286 276 { 287 277 int status_idx = 0; ··· 293 283 for (int notif_idx = 0; notif_idx < ARRAY_SIZE(wowlan_status->gtk); 294 284 notif_idx++) { 295 285 int rsc_idx; 286 + u8 key_status = gtk_data[notif_idx].key_status; 296 287 297 - if (!(gtk_data[notif_idx].key_len)) 288 + if (!key_status) 298 289 continue; 299 290 300 291 wowlan_status->gtk[status_idx].len = ··· 305 294 wowlan_status->gtk[status_idx].id = 306 295 wowlan_status->gtk[status_idx].flags & 307 296 IWL_WOWLAN_GTK_IDX_MASK; 308 - memcpy(wowlan_status->gtk[status_idx].key, 309 - gtk_data[notif_idx].key, 310 - sizeof(gtk_data[notif_idx].key)); 311 - 312 297 /* The rsc for both gtk keys are stored in gtk[0]->sc->mcast_rsc 313 298 * The gtk ids can be any two numbers between 0 and 3, 314 299 * the id_map maps between the key id and the index in sc->mcast ··· 314 307 iwl_mld_convert_gtk_resume_seq(&wowlan_status->gtk[status_idx], 315 308 sc, rsc_idx); 316 309 317 - /* if it's as long as the TKIP encryption key, copy MIC key */ 318 - if (wowlan_status->gtk[status_idx].len == 319 - NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) 320 - memcpy(wowlan_status->gtk[status_idx].key + 321 - NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, 322 - gtk_data[notif_idx].tkip_mic_key, 323 - sizeof(gtk_data[notif_idx].tkip_mic_key)); 310 + if (key_status == IWL_WOWLAN_STATUS_NEW_KEY) { 311 + memcpy(wowlan_status->gtk[status_idx].key, 312 + gtk_data[notif_idx].key, 313 + sizeof(gtk_data[notif_idx].key)); 314 + 315 + /* if it's as long as the TKIP encryption key, 316 + * copy MIC key 317 + */ 318 + if (wowlan_status->gtk[status_idx].len == 319 + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) 320 + memcpy(wowlan_status->gtk[status_idx].key + 321 + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, 322 + gtk_data[notif_idx].tkip_mic_key, 323 + sizeof(gtk_data[notif_idx].tkip_mic_key)); 324 + } else { 325 + /* If the key status is WOWLAN_STATUS_OLD_KEY, it 326 + * indicates that no key material is present, Set the 327 + * key length to 0 as an indication 328 + */ 329 + wowlan_status->gtk[status_idx].len = 0; 330 + } 324 331 status_idx++; 325 332 } 326 333 } ··· 381 360 iwl_mld_convert_igtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status, 382 361 const struct iwl_wowlan_igtk_status *igtk) 383 362 { 384 - BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key)); 385 - 386 - if (!igtk->key_len) 363 + if (!igtk->key_status) 387 364 return; 365 + 366 + BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key)); 388 367 389 368 wowlan_status->igtk.len = igtk->key_len; 390 369 wowlan_status->igtk.flags = igtk->key_flags; ··· 393 372 IWL_WOWLAN_IGTK_BIGTK_IDX_MASK) + 394 373 WOWLAN_IGTK_MIN_INDEX; 395 374 396 - memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key)); 375 + if (igtk->key_status == IWL_WOWLAN_STATUS_NEW_KEY) 376 + memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key)); 377 + else 378 + /* If the key status is WOWLAN_STATUS_OLD_KEY, it indicates 379 + * that no key material is present. Set the key length to 0 380 + * as an indication. 381 + */ 382 + wowlan_status->igtk.len = 0; 383 + 397 384 iwl_mld_convert_mcast_ipn(&wowlan_status->igtk, igtk); 398 385 } 399 386 ··· 415 386 416 387 for (int notif_idx = 0; notif_idx < WOWLAN_BIGTK_KEYS_NUM; 417 388 notif_idx++) { 418 - if (!bigtk[notif_idx].key_len) 389 + if (!bigtk[notif_idx].key_status) 419 390 continue; 420 391 421 392 wowlan_status->bigtk[status_idx].len = bigtk[notif_idx].key_len; ··· 428 399 429 400 BUILD_BUG_ON(sizeof(wowlan_status->bigtk[status_idx].key) < 430 401 sizeof(bigtk[notif_idx].key)); 431 - memcpy(wowlan_status->bigtk[status_idx].key, 432 - bigtk[notif_idx].key, sizeof(bigtk[notif_idx].key)); 402 + if (bigtk[notif_idx].key_status == IWL_WOWLAN_STATUS_NEW_KEY) 403 + memcpy(wowlan_status->bigtk[status_idx].key, 404 + bigtk[notif_idx].key, 405 + sizeof(bigtk[notif_idx].key)); 406 + else 407 + /* If the key status is WOWLAN_STATUS_OLD_KEY, it 408 + * indicates that no key material is present. Set the 409 + * key length to 0 as an indication. 410 + */ 411 + wowlan_status->bigtk[status_idx].len = 0; 412 + 433 413 iwl_mld_convert_mcast_ipn(&wowlan_status->bigtk[status_idx], 434 414 &bigtk[notif_idx]); 435 415 status_idx++; 436 416 } 417 + } 418 + 419 + static void 420 + iwl_mld_convert_mlo_keys(struct iwl_mld *mld, 421 + const struct iwl_wowlan_info_notif *notif, 422 + struct iwl_mld_wowlan_status *wowlan_status) 423 + { 424 + if (!notif->num_mlo_link_keys) 425 + return; 426 + 427 + wowlan_status->num_mlo_keys = notif->num_mlo_link_keys; 428 + 429 + if (IWL_FW_CHECK(mld, wowlan_status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS, 430 + "Too many MLO keys: %d, max %d\n", 431 + wowlan_status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS)) 432 + wowlan_status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS; 433 + 434 + for (int i = 0; i < wowlan_status->num_mlo_keys; i++) { 435 + const struct iwl_wowlan_mlo_gtk *fw_mlo_key = &notif->mlo_gtks[i]; 436 + struct iwl_mld_wowlan_mlo_key *driver_mlo_key = 437 + &wowlan_status->mlo_keys[i]; 438 + u16 flags = le16_to_cpu(fw_mlo_key->flags); 439 + 440 + driver_mlo_key->link_id = 441 + u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK); 442 + driver_mlo_key->type = 443 + u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK); 444 + driver_mlo_key->idx = 445 + u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK); 446 + 447 + BUILD_BUG_ON(sizeof(driver_mlo_key->key) != sizeof(fw_mlo_key->key)); 448 + BUILD_BUG_ON(sizeof(driver_mlo_key->pn) != sizeof(fw_mlo_key->pn)); 449 + 450 + memcpy(driver_mlo_key->key, fw_mlo_key->key, sizeof(fw_mlo_key->key)); 451 + memcpy(driver_mlo_key->pn, fw_mlo_key->pn, sizeof(fw_mlo_key->pn)); 452 + } 453 + } 454 + 455 + static void 456 + iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5, 457 + struct iwl_wowlan_info_notif *notif) 458 + { 459 + /* Convert GTK from v3 to the new format */ 460 + BUILD_BUG_ON(ARRAY_SIZE(notif->gtk) != ARRAY_SIZE(notif_v5->gtk)); 461 + 462 + for (int i = 0; i < ARRAY_SIZE(notif_v5->gtk); i++) { 463 + const struct iwl_wowlan_gtk_status_v3 *gtk_v3 = &notif_v5->gtk[i]; 464 + struct iwl_wowlan_gtk_status *gtk = &notif->gtk[i]; 465 + 466 + /* Copy key material and metadata */ 467 + BUILD_BUG_ON(sizeof(gtk->key) != sizeof(gtk_v3->key)); 468 + BUILD_BUG_ON(sizeof(gtk->tkip_mic_key) != sizeof(gtk_v3->tkip_mic_key)); 469 + 470 + memcpy(gtk->key, gtk_v3->key, sizeof(gtk_v3->key)); 471 + 472 + gtk->key_len = gtk_v3->key_len; 473 + gtk->key_flags = gtk_v3->key_flags; 474 + 475 + memcpy(gtk->tkip_mic_key, gtk_v3->tkip_mic_key, 476 + sizeof(gtk_v3->tkip_mic_key)); 477 + gtk->sc = gtk_v3->sc; 478 + 479 + /* Set key_status based on whether key material is present. 480 + * in v5, a key is either invalid (should be skipped) or has 481 + * both meta data and the key itself. 482 + */ 483 + if (gtk_v3->key_len) 484 + gtk->key_status = IWL_WOWLAN_STATUS_NEW_KEY; 485 + } 486 + 487 + /* Convert IGTK from v1 to the new format, only one IGTK is passed by FW */ 488 + BUILD_BUG_ON(offsetof(struct iwl_wowlan_igtk_status, key_status) != 489 + sizeof(struct iwl_wowlan_igtk_status_v1)); 490 + 491 + memcpy(&notif->igtk[0], &notif_v5->igtk[0], 492 + offsetof(struct iwl_wowlan_igtk_status, key_status)); 493 + 494 + /* Set key_status based on whether key material is present. 495 + * in v5, a key is either invalid (should be skipped) or has 496 + * both meta data and the key itself. 497 + */ 498 + if (notif_v5->igtk[0].key_len) 499 + notif->igtk[0].key_status = IWL_WOWLAN_STATUS_NEW_KEY; 500 + 501 + /* Convert BIGTK from v1 to the new format */ 502 + BUILD_BUG_ON(ARRAY_SIZE(notif->bigtk) != ARRAY_SIZE(notif_v5->bigtk)); 503 + 504 + for (int i = 0; i < ARRAY_SIZE(notif_v5->bigtk); i++) { 505 + /* Copy everything until key_status */ 506 + memcpy(&notif->bigtk[i], &notif_v5->bigtk[i], 507 + offsetof(struct iwl_wowlan_igtk_status, key_status)); 508 + 509 + /* Set key_status based on whether key material is present. 510 + * in v5, a key is either invalid (should be skipped) or has 511 + * both meta data and the key itself. 512 + */ 513 + if (notif_v5->bigtk[i].key_len) 514 + notif->bigtk[i].key_status = IWL_WOWLAN_STATUS_NEW_KEY; 515 + } 516 + 517 + notif->replay_ctr = notif_v5->replay_ctr; 518 + notif->pattern_number = notif_v5->pattern_number; 519 + notif->qos_seq_ctr = notif_v5->qos_seq_ctr; 520 + notif->wakeup_reasons = notif_v5->wakeup_reasons; 521 + notif->num_of_gtk_rekeys = notif_v5->num_of_gtk_rekeys; 522 + notif->transmitted_ndps = notif_v5->transmitted_ndps; 523 + notif->received_beacons = notif_v5->received_beacons; 524 + notif->tid_tear_down = notif_v5->tid_tear_down; 525 + notif->station_id = notif_v5->station_id; 526 + notif->num_mlo_link_keys = notif_v5->num_mlo_link_keys; 527 + notif->tid_offloaded_tx = notif_v5->tid_offloaded_tx; 528 + 529 + /* Copy MLO GTK keys */ 530 + if (notif_v5->num_mlo_link_keys) { 531 + memcpy(notif->mlo_gtks, notif_v5->mlo_gtks, 532 + notif_v5->num_mlo_link_keys * sizeof(struct iwl_wowlan_mlo_gtk)); 533 + } 534 + } 535 + 536 + static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld, 537 + u32 len, 538 + u32 expected_len, 539 + u8 num_mlo_keys, 540 + int version) 541 + { 542 + u32 len_with_mlo_keys; 543 + 544 + if (IWL_FW_CHECK(mld, len < expected_len, 545 + "Invalid wowlan_info_notif v%d (expected=%u got=%u)\n", 546 + version, expected_len, len)) 547 + return false; 548 + 549 + len_with_mlo_keys = expected_len + 550 + (num_mlo_keys * sizeof(struct iwl_wowlan_mlo_gtk)); 551 + 552 + if (IWL_FW_CHECK(mld, len < len_with_mlo_keys, 553 + "Invalid wowlan_info_notif v%d with MLO keys (expected=%u got=%u)\n", 554 + version, len_with_mlo_keys, len)) 555 + return false; 556 + 557 + return true; 437 558 } 438 559 439 560 static bool ··· 591 412 struct iwl_mld_wowlan_status *wowlan_status, 592 413 struct iwl_rx_packet *pkt) 593 414 { 594 - const struct iwl_wowlan_info_notif *notif = (void *)pkt->data; 595 - u32 expected_len, len = iwl_rx_packet_payload_len(pkt); 415 + const struct iwl_wowlan_info_notif *notif; 416 + struct iwl_wowlan_info_notif *converted_notif __free(kfree) = NULL; 417 + u32 len = iwl_rx_packet_payload_len(pkt); 418 + int wowlan_info_ver = iwl_fw_lookup_notif_ver(mld->fw, 419 + PROT_OFFLOAD_GROUP, 420 + WOWLAN_INFO_NOTIFICATION, 421 + IWL_FW_CMD_VER_UNKNOWN); 596 422 597 - expected_len = sizeof(*notif); 423 + if (wowlan_info_ver == 5) { 424 + /* v5 format - validate before conversion */ 425 + const struct iwl_wowlan_info_notif_v5 *notif_v5 = (void *)pkt->data; 598 426 599 - if (IWL_FW_CHECK(mld, len < expected_len, 600 - "Invalid wowlan_info_notif (expected=%ud got=%ud)\n", 601 - expected_len, len)) 427 + if (!iwl_mld_validate_wowlan_notif_size(mld, len, 428 + sizeof(*notif_v5), 429 + notif_v5->num_mlo_link_keys, 430 + 5)) 431 + return true; 432 + 433 + converted_notif = kzalloc(struct_size(converted_notif, 434 + mlo_gtks, 435 + notif_v5->num_mlo_link_keys), 436 + GFP_ATOMIC); 437 + if (!converted_notif) { 438 + IWL_ERR(mld, 439 + "Failed to allocate memory for converted wowlan_info_notif\n"); 440 + return true; 441 + } 442 + 443 + iwl_mld_convert_wowlan_notif_v5(notif_v5, 444 + converted_notif); 445 + notif = converted_notif; 446 + } else if (wowlan_info_ver == 6) { 447 + notif = (void *)pkt->data; 448 + if (!iwl_mld_validate_wowlan_notif_size(mld, len, 449 + sizeof(*notif), 450 + notif->num_mlo_link_keys, 451 + 6)) 452 + return true; 453 + } else { 454 + /* smaller versions are not supported */ 455 + IWL_WARN(mld, 456 + "Unsupported wowlan_info_notif version %d\n", 457 + wowlan_info_ver); 602 458 return true; 459 + } 603 460 604 461 if (IWL_FW_CHECK(mld, notif->tid_offloaded_tx != IWL_WOWLAN_OFFLOAD_TID, 605 462 "Invalid tid_offloaded_tx %d\n", 606 - wowlan_status->tid_offloaded_tx)) 463 + notif->tid_offloaded_tx)) 607 464 return true; 608 465 609 466 iwl_mld_convert_gtk_resume_data(mld, wowlan_status, notif->gtk, ··· 657 442 wowlan_status->num_of_gtk_rekeys = 658 443 le32_to_cpu(notif->num_of_gtk_rekeys); 659 444 wowlan_status->wakeup_reasons = le32_to_cpu(notif->wakeup_reasons); 445 + 446 + iwl_mld_convert_mlo_keys(mld, notif, wowlan_status); 447 + 660 448 return false; 661 - /* TODO: mlo_links (task=MLO)*/ 662 449 } 663 450 664 451 static bool ··· 836 619 } 837 620 838 621 static void 839 - iwl_mld_set_key_rx_seq(struct ieee80211_key_conf *key, 840 - struct iwl_mld_mcast_key_data *key_data) 622 + iwl_mld_update_mcast_rx_seq(struct ieee80211_key_conf *key, 623 + struct iwl_mld_mcast_key_data *key_data) 841 624 { 842 625 switch (key->cipher) { 843 626 case WLAN_CIPHER_SUITE_CCMP: ··· 904 687 struct iwl_mld_wowlan_status *wowlan_status = data->wowlan_status; 905 688 u8 status_idx; 906 689 907 - /* TODO: check key link id (task=MLO) */ 908 - if (data->unhandled_cipher) 909 - return; 910 - 911 - switch (key->cipher) { 912 - case WLAN_CIPHER_SUITE_WEP40: 913 - case WLAN_CIPHER_SUITE_WEP104: 914 - /* ignore WEP completely, nothing to do */ 915 - return; 916 - case WLAN_CIPHER_SUITE_CCMP: 917 - case WLAN_CIPHER_SUITE_GCMP: 918 - case WLAN_CIPHER_SUITE_GCMP_256: 919 - case WLAN_CIPHER_SUITE_TKIP: 690 + if (key->keyidx >= 0 && key->keyidx <= 3) { 691 + /* PTK */ 920 692 if (sta) { 921 693 iwl_mld_update_ptk_rx_seq(data->mld, wowlan_status, 922 694 sta, key, 923 695 key->cipher == 924 696 WLAN_CIPHER_SUITE_TKIP); 925 - return; 697 + /* GTK */ 698 + } else { 699 + status_idx = key->keyidx == wowlan_status->gtk[1].id; 700 + iwl_mld_update_mcast_rx_seq(key, 701 + &wowlan_status->gtk[status_idx]); 926 702 } 927 - 928 - if (WARN_ON(data->gtk_cipher && 929 - data->gtk_cipher != key->cipher)) 930 - return; 931 - 932 - data->gtk_cipher = key->cipher; 933 - status_idx = key->keyidx == wowlan_status->gtk[1].id; 934 - iwl_mld_set_key_rx_seq(key, &wowlan_status->gtk[status_idx]); 935 - break; 936 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 937 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 938 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 939 - case WLAN_CIPHER_SUITE_AES_CMAC: 940 - if (key->keyidx == 4 || key->keyidx == 5) { 941 - if (WARN_ON(data->igtk_cipher && 942 - data->igtk_cipher != key->cipher)) 943 - return; 944 - 945 - data->igtk_cipher = key->cipher; 946 - if (key->keyidx == wowlan_status->igtk.id) 947 - iwl_mld_set_key_rx_seq(key, &wowlan_status->igtk); 948 - } 949 - if (key->keyidx == 6 || key->keyidx == 7) { 950 - if (WARN_ON(data->bigtk_cipher && 951 - data->bigtk_cipher != key->cipher)) 952 - return; 953 - 954 - data->bigtk_cipher = key->cipher; 955 - status_idx = key->keyidx == wowlan_status->bigtk[1].id; 956 - iwl_mld_set_key_rx_seq(key, &wowlan_status->bigtk[status_idx]); 957 - } 958 - break; 959 - default: 960 - data->unhandled_cipher = true; 961 - return; 962 703 } 963 - data->num_keys++; 704 + 705 + /* IGTK */ 706 + if (key->keyidx == 4 || key->keyidx == 5) { 707 + if (key->keyidx == wowlan_status->igtk.id) 708 + iwl_mld_update_mcast_rx_seq(key, &wowlan_status->igtk); 709 + } 710 + 711 + /* BIGTK */ 712 + if (key->keyidx == 6 || key->keyidx == 7) { 713 + status_idx = key->keyidx == wowlan_status->bigtk[1].id; 714 + iwl_mld_update_mcast_rx_seq(key, 715 + &wowlan_status->bigtk[status_idx]); 716 + } 964 717 } 965 718 966 719 static void 967 720 iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif, 968 721 struct iwl_mld *mld, 969 722 struct iwl_mld_mcast_key_data *key_data, 970 - struct ieee80211_bss_conf *link_conf, 971 - u32 cipher) 723 + struct ieee80211_bss_conf *link_conf) 972 724 { 973 725 struct ieee80211_key_conf *key_config; 974 - struct { 975 - struct ieee80211_key_conf conf; 976 - u8 key[WOWLAN_KEY_MAX_SIZE]; 977 - } conf = { 978 - .conf.cipher = cipher, 979 - .conf.keyidx = key_data->id, 980 - }; 981 726 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 982 - u8 key[WOWLAN_KEY_MAX_SIZE]; 983 - 984 - BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); 985 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP); 986 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256); 987 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP); 988 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_BIP_GMAC_128); 989 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_BIP_GMAC_256); 990 - BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_AES_CMAC); 991 - BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key)); 992 727 993 728 if (!key_data->len) 994 729 return; 995 730 996 - switch (cipher) { 997 - case WLAN_CIPHER_SUITE_CCMP: 998 - case WLAN_CIPHER_SUITE_GCMP: 999 - conf.conf.keylen = WLAN_KEY_LEN_CCMP; 1000 - break; 1001 - case WLAN_CIPHER_SUITE_GCMP_256: 1002 - conf.conf.keylen = WLAN_KEY_LEN_GCMP_256; 1003 - break; 1004 - case WLAN_CIPHER_SUITE_TKIP: 1005 - conf.conf.keylen = WLAN_KEY_LEN_TKIP; 1006 - break; 1007 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1008 - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128; 1009 - break; 1010 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1011 - conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256; 1012 - break; 1013 - case WLAN_CIPHER_SUITE_AES_CMAC: 1014 - conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC; 1015 - break; 1016 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1017 - conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256; 1018 - break; 1019 - default: 1020 - WARN_ON(1); 1021 - } 1022 - 1023 - memcpy(conf.conf.key, key_data->key, conf.conf.keylen); 1024 - 1025 - memcpy(key, key_data->key, sizeof(key_data->key)); 1026 - 1027 - key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key, 1028 - sizeof(key), link_id); 731 + key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key_data->key, 732 + sizeof(key_data->key), link_id); 1029 733 if (IS_ERR(key_config)) 1030 734 return; 1031 735 1032 - iwl_mld_set_key_rx_seq(key_config, key_data); 736 + iwl_mld_update_mcast_rx_seq(key_config, key_data); 1033 737 1034 738 /* The FW holds only one igtk so we keep track of the valid one */ 1035 739 if (key_config->keyidx == 4 || key_config->keyidx == 5) { ··· 969 831 } 970 832 971 833 /* Also keep track of the new BIGTK */ 972 - if ((key_config->keyidx == 6 || key_config->keyidx == 7) && 973 - vif->type == NL80211_IFTYPE_STATION) { 974 - struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 975 - 976 - rcu_assign_pointer(mld_vif->bigtks[key_config->keyidx - 6], key_config); 977 - } 834 + if (key_config->keyidx == 6 || key_config->keyidx == 7) 835 + iwl_mld_track_bigtk(mld, vif, key_config, true); 978 836 } 979 837 980 838 static void 981 - iwl_mld_add_all_rekeys(struct ieee80211_vif *vif, 839 + iwl_mld_add_all_rekeys(struct iwl_mld *mld, 840 + struct ieee80211_vif *vif, 982 841 struct iwl_mld_wowlan_status *wowlan_status, 983 - struct iwl_mld_resume_key_iter_data *key_iter_data, 984 842 struct ieee80211_bss_conf *link_conf) 985 843 { 986 844 int i; 987 845 988 846 for (i = 0; i < ARRAY_SIZE(wowlan_status->gtk); i++) 989 - iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, 990 - &wowlan_status->gtk[i], 991 - link_conf, 992 - key_iter_data->gtk_cipher); 847 + iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->gtk[i], 848 + link_conf); 993 849 994 - iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, 995 - &wowlan_status->igtk, 996 - link_conf, key_iter_data->igtk_cipher); 850 + iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->igtk, link_conf); 997 851 998 852 for (i = 0; i < ARRAY_SIZE(wowlan_status->bigtk); i++) 999 - iwl_mld_add_mcast_rekey(vif, key_iter_data->mld, 1000 - &wowlan_status->bigtk[i], 1001 - link_conf, 1002 - key_iter_data->bigtk_cipher); 853 + iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->bigtk[i], 854 + link_conf); 855 + } 856 + 857 + static void iwl_mld_mlo_rekey(struct iwl_mld *mld, 858 + struct iwl_mld_wowlan_status *wowlan_status, 859 + struct ieee80211_vif *vif) 860 + { 861 + struct iwl_mld_old_mlo_keys *old_keys __free(kfree) = NULL; 862 + 863 + IWL_DEBUG_WOWLAN(mld, "Num of MLO Keys: %d\n", wowlan_status->num_mlo_keys); 864 + 865 + if (!wowlan_status->num_mlo_keys) 866 + return; 867 + 868 + for (int i = 0; i < wowlan_status->num_mlo_keys; i++) { 869 + struct iwl_mld_wowlan_mlo_key *mlo_key = &wowlan_status->mlo_keys[i]; 870 + struct ieee80211_key_conf *key; 871 + struct ieee80211_key_seq seq; 872 + u8 link_id = mlo_key->link_id; 873 + 874 + if (IWL_FW_CHECK(mld, mlo_key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS || 875 + mlo_key->idx >= 8 || 876 + mlo_key->type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES, 877 + "Invalid MLO key link_id %d, idx %d, type %d\n", 878 + mlo_key->link_id, mlo_key->idx, mlo_key->type)) 879 + continue; 880 + 881 + if (!(vif->valid_links & BIT(link_id)) || 882 + (vif->active_links & BIT(link_id))) 883 + continue; 884 + 885 + IWL_DEBUG_WOWLAN(mld, "Add MLO key id %d, link id %d\n", 886 + mlo_key->idx, link_id); 887 + 888 + key = ieee80211_gtk_rekey_add(vif, mlo_key->idx, mlo_key->key, 889 + sizeof(mlo_key->key), link_id); 890 + 891 + if (IS_ERR(key)) 892 + continue; 893 + 894 + /* 895 + * mac80211 expects the PN in big-endian 896 + * also note that seq is a union of all cipher types 897 + * (ccmp, gcmp, cmac, gmac), and they all have the same 898 + * pn field (of length 6) so just copy it to ccmp.pn. 899 + */ 900 + for (int j = 5; j >= 0; j--) 901 + seq.ccmp.pn[5 - j] = mlo_key->pn[j]; 902 + 903 + /* group keys are non-QoS and use TID 0 */ 904 + ieee80211_set_key_rx_seq(key, 0, &seq); 905 + } 1003 906 } 1004 907 1005 908 static bool ··· 1063 884 ieee80211_iter_keys(mld->hw, vif, iwl_mld_resume_keys_iter, 1064 885 &key_iter_data); 1065 886 1066 - if (key_iter_data.unhandled_cipher) 1067 - return false; 1068 - 1069 - IWL_DEBUG_WOWLAN(mld, 1070 - "Number of installed keys: %d, Number of rekeys: %d\n", 1071 - key_iter_data.num_keys, 887 + IWL_DEBUG_WOWLAN(mld, "Number of rekeys: %d\n", 1072 888 wowlan_status->num_of_gtk_rekeys); 1073 889 1074 - if (!key_iter_data.num_keys || !wowlan_status->num_of_gtk_rekeys) 890 + if (!wowlan_status->num_of_gtk_rekeys) 1075 891 return true; 1076 892 1077 - iwl_mld_add_all_rekeys(vif, wowlan_status, &key_iter_data, 893 + iwl_mld_add_all_rekeys(mld, vif, wowlan_status, 1078 894 link_conf); 895 + 896 + iwl_mld_mlo_rekey(mld, wowlan_status, vif); 1079 897 1080 898 ieee80211_gtk_rekey_notify(vif, link_conf->bssid, 1081 899 (void *)&replay_ctr, GFP_KERNEL); 1082 - /* TODO: MLO rekey (task=MLO) */ 1083 900 return true; 1084 901 } 1085 902 ··· 1354 1179 WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION) 1355 1180 }; 1356 1181 struct iwl_notification_wait wait_d3_notif; 1357 - enum iwl_d3_status d3_status; 1358 1182 int ret; 1359 1183 1360 1184 if (with_wowlan) ··· 1369 1195 iwl_mld_handle_d3_notif, 1370 1196 resume_data); 1371 1197 1372 - ret = iwl_trans_d3_resume(mld->trans, &d3_status, false, false); 1373 - if (ret || d3_status != IWL_D3_STATUS_ALIVE) { 1374 - if (d3_status != IWL_D3_STATUS_ALIVE) { 1375 - IWL_INFO(mld, "Device was reset during suspend\n"); 1376 - ret = -ENOENT; 1377 - } else { 1378 - IWL_ERR(mld, "Transport resume failed\n"); 1379 - } 1198 + ret = iwl_trans_d3_resume(mld->trans, false); 1199 + if (ret) { 1200 + /* Avoid sending commands if the FW is dead */ 1201 + iwl_trans_notify_fw_error(mld->trans); 1380 1202 iwl_remove_notification(&mld->notif_wait, &wait_d3_notif); 1381 1203 return ret; 1382 1204 } ··· 1406 1236 1407 1237 iwl_mld_low_latency_stop(mld); 1408 1238 1409 - /* This will happen if iwl_mld_supsend failed with FW error */ 1410 - if (mld->trans->state == IWL_TRANS_NO_FW && 1411 - test_bit(STATUS_FW_ERROR, &mld->trans->status)) 1412 - return -ENODEV; 1413 - 1414 1239 ret = iwl_mld_update_device_power(mld, true); 1415 1240 if (ret) { 1416 1241 IWL_ERR(mld, 1417 1242 "d3 suspend: couldn't send power_device %d\n", ret); 1418 - goto out; 1243 + return ret; 1419 1244 } 1420 1245 1421 1246 ret = iwl_mld_send_cmd_pdu(mld, D3_CONFIG_CMD, ··· 1418 1253 if (ret) { 1419 1254 IWL_ERR(mld, 1420 1255 "d3 suspend: couldn't send D3_CONFIG_CMD %d\n", ret); 1421 - goto out; 1256 + return ret; 1422 1257 } 1423 1258 1424 - ret = iwl_trans_d3_suspend(mld->trans, false, false); 1259 + ret = iwl_trans_d3_suspend(mld->trans, false); 1425 1260 if (ret) { 1426 1261 IWL_ERR(mld, "d3 suspend: trans_d3_suspend failed %d\n", ret); 1262 + /* We are going to stop the FW. Avoid sending commands in that flow */ 1263 + iwl_trans_notify_fw_error(mld->trans); 1427 1264 } else { 1428 1265 /* Async notification might send hcmds, which is not allowed in suspend */ 1429 1266 iwl_mld_cancel_async_notifications(mld); 1430 1267 mld->fw_status.in_d3 = true; 1431 - } 1432 - 1433 - out: 1434 - if (ret) { 1435 - mld->trans->state = IWL_TRANS_NO_FW; 1436 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1437 1268 } 1438 1269 1439 1270 return ret; ··· 1451 1290 iwl_fw_dbg_read_d3_debug_data(&mld->fwrt); 1452 1291 1453 1292 ret = iwl_mld_wait_d3_notif(mld, &resume_data, false); 1293 + if (ret) 1294 + return ret; 1454 1295 1455 1296 if (!ret && (resume_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE)) 1456 1297 return -ENODEV; 1457 1298 1458 - if (ret) { 1459 - mld->trans->state = IWL_TRANS_NO_FW; 1460 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1461 - return ret; 1462 - } 1463 1299 iwl_mld_low_latency_restart(mld); 1464 1300 1465 1301 return iwl_mld_update_device_power(mld, false); ··· 1688 1530 iwl_mld_set_wowlan_config_cmd(struct iwl_mld *mld, 1689 1531 struct cfg80211_wowlan *wowlan, 1690 1532 struct iwl_wowlan_config_cmd *wowlan_config_cmd, 1691 - struct ieee80211_sta *ap_sta) 1533 + struct ieee80211_sta *ap_sta, 1534 + struct ieee80211_bss_conf *link) 1692 1535 { 1693 1536 wowlan_config_cmd->is_11n_connection = 1694 1537 ap_sta->deflink.ht_cap.ht_supported; ··· 1698 1539 1699 1540 if (ap_sta->mfp) 1700 1541 wowlan_config_cmd->flags |= IS_11W_ASSOC; 1542 + 1543 + if (iwl_mld_beacon_protection_enabled(mld, link)) 1544 + wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION; 1701 1545 1702 1546 if (wowlan->disconnect) 1703 1547 wowlan_config_cmd->wakeup_filter |= ··· 1899 1737 return ret; 1900 1738 1901 1739 iwl_mld_set_wowlan_config_cmd(mld, wowlan, 1902 - &wowlan_config_cmd, ap_sta); 1740 + &wowlan_config_cmd, ap_sta, link_conf); 1903 1741 ret = iwl_mld_send_cmd_pdu(mld, WOWLAN_CONFIGURATION, 1904 1742 &wowlan_config_cmd); 1905 1743 if (ret) ··· 1969 1807 }; 1970 1808 int link_id; 1971 1809 int ret; 1972 - bool fw_err = false; 1973 1810 1974 1811 lockdep_assert_wiphy(mld->wiphy); 1975 1812 ··· 2011 1850 ret = iwl_mld_wait_d3_notif(mld, &resume_data, true); 2012 1851 if (ret) { 2013 1852 IWL_ERR(mld, "Couldn't get the d3 notifs %d\n", ret); 2014 - fw_err = true; 2015 1853 goto err; 2016 1854 } 2017 1855 ··· 2047 1887 goto out; 2048 1888 2049 1889 err: 2050 - if (fw_err) { 2051 - mld->trans->state = IWL_TRANS_NO_FW; 2052 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 2053 - } 2054 - 2055 1890 mld->fw_status.in_hw_restart = true; 2056 1891 ret = 1; 2057 1892 out:
+6 -2
drivers/net/wireless/intel/iwlwifi/mld/debugfs.c
··· 86 86 87 87 if (count == 6 && !strcmp(buf, "nolog\n")) { 88 88 mld->fw_status.do_not_dump_once = true; 89 - iwl_trans_suppress_cmd_error_once(mld->trans); 89 + mld->trans->suppress_cmd_error_once = true; 90 90 } 91 91 92 92 /* take the return value to make compiler happy - it will ··· 1001 1001 * If not, this is a per-link dir of a MLO vif, add in it the iwlmld 1002 1002 * dir. 1003 1003 */ 1004 - if (!mld_link_dir) 1004 + if (!mld_link_dir) { 1005 1005 mld_link_dir = debugfs_create_dir("iwlmld", dir); 1006 + } else { 1007 + /* Release the reference from debugfs_lookup */ 1008 + dput(mld_link_dir); 1009 + } 1006 1010 } 1007 1011 1008 1012 static ssize_t _iwl_dbgfs_fixed_rate_write(struct iwl_mld *mld, char *buf,
+11 -28
drivers/net/wireless/intel/iwlwifi/mld/iface.c
··· 115 115 116 116 static void iwl_mld_set_he_support(struct iwl_mld *mld, 117 117 struct ieee80211_vif *vif, 118 - struct iwl_mac_config_cmd *cmd, 119 - int cmd_ver) 118 + struct iwl_mac_config_cmd *cmd) 120 119 { 121 - if (vif->type == NL80211_IFTYPE_AP) { 122 - if (cmd_ver == 2) 123 - cmd->wifi_gen_v2.he_ap_support = cpu_to_le16(1); 124 - else 125 - cmd->wifi_gen.he_ap_support = 1; 126 - } else { 127 - if (cmd_ver == 2) 128 - cmd->wifi_gen_v2.he_support = cpu_to_le16(1); 129 - else 130 - cmd->wifi_gen.he_support = 1; 131 - } 120 + if (vif->type == NL80211_IFTYPE_AP) 121 + cmd->wifi_gen.he_ap_support = 1; 122 + else 123 + cmd->wifi_gen.he_support = 1; 132 124 } 133 125 134 126 /* fill the common part for all interface types */ ··· 132 140 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 133 141 struct ieee80211_bss_conf *link_conf; 134 142 unsigned int link_id; 135 - int cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, 136 - WIDE_ID(MAC_CONF_GROUP, 137 - MAC_CONFIG_CMD), 0); 138 143 139 144 lockdep_assert_wiphy(mld->wiphy); 140 145 ··· 158 169 * and enable both when we have MLO. 159 170 */ 160 171 if (ieee80211_vif_is_mld(vif)) { 161 - iwl_mld_set_he_support(mld, vif, cmd, cmd_ver); 162 - if (cmd_ver == 2) 163 - cmd->wifi_gen_v2.eht_support = cpu_to_le32(1); 164 - else 165 - cmd->wifi_gen.eht_support = 1; 172 + iwl_mld_set_he_support(mld, vif, cmd); 173 + cmd->wifi_gen.eht_support = 1; 166 174 return; 167 175 } 168 176 ··· 167 181 if (!link_conf->he_support) 168 182 continue; 169 183 170 - iwl_mld_set_he_support(mld, vif, cmd, cmd_ver); 184 + iwl_mld_set_he_support(mld, vif, cmd); 171 185 172 186 /* EHT, if supported, was already set above */ 173 187 break; ··· 437 451 return ret; 438 452 } 439 453 440 - int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) 454 + void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif) 441 455 { 442 456 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 443 - int ret; 444 457 445 458 lockdep_assert_wiphy(mld->wiphy); 446 459 447 - ret = iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE); 460 + iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_REMOVE); 448 461 449 462 if (WARN_ON(mld_vif->fw_id >= ARRAY_SIZE(mld->fw_id_to_vif))) 450 - return -EINVAL; 463 + return; 451 464 452 465 RCU_INIT_POINTER(mld->fw_id_to_vif[mld_vif->fw_id], NULL); 453 466 454 467 iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_VIF, 455 468 mld_vif->fw_id); 456 - 457 - return ret; 458 469 } 459 470 460 471 void iwl_mld_set_vif_associated(struct iwl_mld *mld,
+1 -4
drivers/net/wireless/intel/iwlwifi/mld/iface.h
··· 125 125 * @ap_sta: pointer to AP sta, for easier access to it. 126 126 * Relevant only for STA vifs. 127 127 * @authorized: indicates the AP station was set to authorized 128 - * @bigtks: BIGTKs of the AP, for beacon protection. 129 - * Only valid for STA. (FIXME: needs to be per link) 130 128 * @num_associated_stas: number of associated STAs. Relevant only for AP mode. 131 129 * @ap_ibss_active: whether the AP/IBSS was started 132 130 * @cca_40mhz_workaround: When we are connected in 2.4 GHz and 40 MHz, and the ··· 156 158 struct iwl_mld_session_protect session_protect; 157 159 struct ieee80211_sta *ap_sta; 158 160 bool authorized; 159 - struct ieee80211_key_conf __rcu *bigtks[2]; 160 161 u8 num_associated_stas; 161 162 bool ap_ibss_active; 162 163 enum iwl_mld_cca_40mhz_wa_status cca_40mhz_workaround; ··· 224 227 int iwl_mld_mac_fw_action(struct iwl_mld *mld, struct ieee80211_vif *vif, 225 228 u32 action); 226 229 int iwl_mld_add_vif(struct iwl_mld *mld, struct ieee80211_vif *vif); 227 - int iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif); 230 + void iwl_mld_rm_vif(struct iwl_mld *mld, struct ieee80211_vif *vif); 228 231 void iwl_mld_set_vif_associated(struct iwl_mld *mld, 229 232 struct ieee80211_vif *vif); 230 233 u8 iwl_mld_get_fw_bss_vifs_ids(struct iwl_mld *mld);
+38
drivers/net/wireless/intel/iwlwifi/mld/key.c
··· 368 368 &data); 369 369 return data.err; 370 370 } 371 + 372 + void iwl_mld_track_bigtk(struct iwl_mld *mld, 373 + struct ieee80211_vif *vif, 374 + struct ieee80211_key_conf *key, bool add) 375 + { 376 + struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 377 + struct iwl_mld_link *link; 378 + 379 + if (vif->type != NL80211_IFTYPE_STATION) 380 + return; 381 + 382 + if (WARN_ON(key->keyidx < 6 || key->keyidx > 7)) 383 + return; 384 + 385 + if (WARN_ON(key->link_id < 0)) 386 + return; 387 + 388 + link = iwl_mld_link_dereference_check(mld_vif, key->link_id); 389 + if (WARN_ON(!link)) 390 + return; 391 + 392 + if (add) 393 + rcu_assign_pointer(link->bigtks[key->keyidx - 6], key); 394 + else 395 + RCU_INIT_POINTER(link->bigtks[key->keyidx - 6], NULL); 396 + } 397 + 398 + bool iwl_mld_beacon_protection_enabled(struct iwl_mld *mld, 399 + struct ieee80211_bss_conf *link) 400 + { 401 + struct iwl_mld_link *mld_link = iwl_mld_link_from_mac80211(link); 402 + 403 + if (WARN_ON(!mld_link)) 404 + return false; 405 + 406 + return rcu_access_pointer(mld_link->bigtks[0]) || 407 + rcu_access_pointer(mld_link->bigtks[1]); 408 + }
+7
drivers/net/wireless/intel/iwlwifi/mld/key.h
··· 36 36 key->hw_key_idx = STA_KEY_IDX_INVALID; 37 37 } 38 38 39 + void iwl_mld_track_bigtk(struct iwl_mld *mld, 40 + struct ieee80211_vif *vif, 41 + struct ieee80211_key_conf *key, bool add); 42 + 43 + bool iwl_mld_beacon_protection_enabled(struct iwl_mld *mld, 44 + struct ieee80211_bss_conf *link); 45 + 39 46 #endif /* __iwl_mld_key_h__ */
+18 -8
drivers/net/wireless/intel/iwlwifi/mld/link.c
··· 532 532 le32_to_cpu(notif->consec_missed_beacons_other_link); 533 533 struct ieee80211_bss_conf *link_conf = 534 534 iwl_mld_fw_id_to_link_conf(mld, fw_link_id); 535 - u32 bss_param_ch_cnt_link_id; 535 + struct ieee80211_bss_conf *other_link; 536 + u32 bss_param_ch_cnt_link_id, other_link_fw_id; 536 537 struct ieee80211_vif *vif; 537 538 u8 link_id; 538 539 ··· 550 549 551 550 if (WARN_ON(!vif)) 552 551 return; 553 - 554 - mld->trans->dbg.dump_file_name_ext_valid = true; 555 - snprintf(mld->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 556 - "LinkId_%d_MacType_%d", fw_link_id, 557 - iwl_mld_mac80211_iftype_to_fw(vif)); 558 552 559 553 iwl_dbg_tlv_time_point(&mld->fwrt, 560 554 IWL_FW_INI_TIME_POINT_MISSED_BEACONS, &tp_data); ··· 568 572 if (missed_bcon_since_rx > IWL_MLD_MISSED_BEACONS_THRESHOLD) { 569 573 ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC); 570 574 571 - /* try to switch links, no-op if we don't have MLO */ 572 - iwl_mld_int_mlo_scan(mld, vif); 575 + /* Not in EMLSR and we can't hear the link. 576 + * Try to switch to a better link. EMLSR case is handled below. 577 + */ 578 + if (!iwl_mld_emlsr_active(vif)) 579 + iwl_mld_int_mlo_scan(mld, vif); 573 580 } 574 581 575 582 /* no more logic if we're not in EMLSR */ ··· 582 583 /* We are processing a notification before link activation */ 583 584 if (le32_to_cpu(notif->other_link_id) == FW_CTXT_ID_INVALID) 584 585 return; 586 + 587 + other_link_fw_id = le32_to_cpu(notif->other_link_id); 588 + other_link = iwl_mld_fw_id_to_link_conf(mld, other_link_fw_id); 589 + 590 + if (IWL_FW_CHECK(mld, !other_link, "link doesn't exist for: %d\n", 591 + other_link_fw_id)) 592 + return; 593 + 594 + IWL_DEBUG_EHT(mld, 595 + "missed bcn on the other link (link_id=%u): %u\n", 596 + other_link->link_id, scnd_lnk_bcn_lost); 585 597 586 598 /* Exit EMLSR if we lost more than 587 599 * IWL_MLD_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links
+2
drivers/net/wireless/intel/iwlwifi/mld/link.h
··· 36 36 * @he_ru_2mhz_block: 26-tone RU OFDMA transmissions should be blocked. 37 37 * @igtk: fw can only have one IGTK at a time, whereas mac80211 can have two. 38 38 * This tracks the one IGTK that currently exists in FW. 39 + * @bigtks: BIGTKs of the AP. Only valid for STA mode. 39 40 * @bcast_sta: station used for broadcast packets. Used in AP, GO and IBSS. 40 41 * @mcast_sta: station used for multicast packets. Used in AP, GO and IBSS. 41 42 * @mon_sta: station used for TX injection in monitor interface. ··· 60 59 struct ieee80211_chanctx_conf __rcu *chan_ctx; 61 60 bool he_ru_2mhz_block; 62 61 struct ieee80211_key_conf *igtk; 62 + struct ieee80211_key_conf __rcu *bigtks[2]; 63 63 ); 64 64 /* And here fields that survive a fw restart */ 65 65 struct iwl_mld_int_sta bcast_sta;
+6 -13
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
··· 626 626 IEEE80211_VIF_SUPPORTS_CQM_RSSI; 627 627 } 628 628 629 - if (vif->p2p || iwl_fw_lookup_cmd_ver(mld->fw, PHY_CONTEXT_CMD, 0) < 5) 629 + if (vif->p2p) 630 630 vif->driver_flags |= IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW; 631 631 632 632 /* ··· 1966 1966 iwl_fw_runtime_suspend(&mld->fwrt); 1967 1967 1968 1968 ret = iwl_mld_wowlan_suspend(mld, wowlan); 1969 - if (ret) { 1970 - if (ret < 0) { 1971 - mld->trans->state = IWL_TRANS_NO_FW; 1972 - set_bit(STATUS_FW_ERROR, &mld->trans->status); 1973 - } 1969 + if (ret) 1974 1970 return 1; 1975 - } 1976 1971 1977 1972 if (iwl_mld_no_wowlan_suspend(mld)) 1978 1973 return 1; ··· 2060 2065 return -EOPNOTSUPP; 2061 2066 } 2062 2067 2063 - if (vif->type == NL80211_IFTYPE_STATION && 2064 - (keyidx == 6 || keyidx == 7)) 2065 - rcu_assign_pointer(mld_vif->bigtks[keyidx - 6], key); 2068 + if (keyidx == 6 || keyidx == 7) 2069 + iwl_mld_track_bigtk(mld, vif, key, true); 2066 2070 2067 2071 /* After exiting from RFKILL, hostapd configures GTK/ITGK before the 2068 2072 * AP is started, but those keys can't be sent to the FW before the ··· 2110 2116 sta ? iwl_mld_sta_from_mac80211(sta) : NULL; 2111 2117 int keyidx = key->keyidx; 2112 2118 2113 - if (vif->type == NL80211_IFTYPE_STATION && 2114 - (keyidx == 6 || keyidx == 7)) 2115 - RCU_INIT_POINTER(mld_vif->bigtks[keyidx - 6], NULL); 2119 + if (keyidx == 6 || keyidx == 7) 2120 + iwl_mld_track_bigtk(mld, vif, key, false); 2116 2121 2117 2122 if (mld_sta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE && 2118 2123 (key->cipher == WLAN_CIPHER_SUITE_CCMP ||
+4
drivers/net/wireless/intel/iwlwifi/mld/mld.c
··· 147 147 */ 148 148 static const struct iwl_hcmd_names iwl_mld_legacy_names[] = { 149 149 HCMD_NAME(UCODE_ALIVE_NTFY), 150 + HCMD_NAME(REPLY_ERROR), 150 151 HCMD_NAME(INIT_COMPLETE_NOTIF), 151 152 HCMD_NAME(PHY_CONTEXT_CMD), 152 153 HCMD_NAME(SCAN_CFG_CMD), ··· 159 158 HCMD_NAME(LEDS_CMD), 160 159 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION), 161 160 HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION), 161 + HCMD_NAME(PHY_CONFIGURATION_CMD), 162 162 HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD), 163 163 HCMD_NAME(POWER_TABLE_CMD), 164 164 HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), 165 165 HCMD_NAME(BEACON_NOTIFICATION), 166 166 HCMD_NAME(BEACON_TEMPLATE_CMD), 167 167 HCMD_NAME(TX_ANT_CONFIGURATION_CMD), 168 + HCMD_NAME(BT_CONFIG), 168 169 HCMD_NAME(REDUCE_TX_POWER_CMD), 169 170 HCMD_NAME(MISSED_BEACONS_NOTIFICATION), 170 171 HCMD_NAME(MAC_PM_POWER_TABLE), ··· 254 251 HCMD_NAME(TLC_MNG_CONFIG_CMD), 255 252 HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD), 256 253 HCMD_NAME(SCD_QUEUE_CONFIG_CMD), 254 + HCMD_NAME(SEC_KEY_CMD), 257 255 HCMD_NAME(ESR_MODE_NOTIF), 258 256 HCMD_NAME(MONITOR_NOTIF), 259 257 HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
+8 -26
drivers/net/wireless/intel/iwlwifi/mld/mlo.c
··· 357 357 struct ieee80211_vif *vif) 358 358 { 359 359 const struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 360 - enum iwl_mvm_fw_esr_recommendation action; 361 - const struct iwl_esr_mode_notif *notif = NULL; 362 - 363 - if (iwl_fw_lookup_notif_ver(mld_vif->mld->fw, DATA_PATH_GROUP, 364 - ESR_MODE_NOTIF, 0) > 1) { 365 - notif = (void *)data; 366 - action = le32_to_cpu(notif->action); 367 - } else { 368 - const struct iwl_esr_mode_notif_v1 *notif_v1 = (void *)data; 369 - 370 - action = le32_to_cpu(notif_v1->action); 371 - } 360 + const struct iwl_esr_mode_notif *notif = (void *)data; 361 + enum iwl_mvm_fw_esr_recommendation action = le32_to_cpu(notif->action); 372 362 373 363 if (!iwl_mld_vif_has_emlsr_cap(vif)) 374 364 return; 375 365 376 366 switch (action) { 377 367 case ESR_RECOMMEND_LEAVE: 378 - if (notif) 379 - IWL_DEBUG_INFO(mld_vif->mld, 380 - "FW recommend leave reason = 0x%x\n", 381 - le32_to_cpu(notif->leave_reason_mask)); 368 + IWL_DEBUG_INFO(mld_vif->mld, 369 + "FW recommend leave reason = 0x%x\n", 370 + le32_to_cpu(notif->leave_reason_mask)); 382 371 383 372 iwl_mld_exit_emlsr(mld_vif->mld, vif, 384 373 IWL_MLD_EMLSR_EXIT_FW_REQUEST, 385 374 iwl_mld_get_primary_link(vif)); 386 375 break; 387 376 case ESR_FORCE_LEAVE: 388 - if (notif) 389 - IWL_DEBUG_INFO(mld_vif->mld, 390 - "FW force leave reason = 0x%x\n", 391 - le32_to_cpu(notif->leave_reason_mask)); 377 + IWL_DEBUG_INFO(mld_vif->mld, 378 + "FW force leave reason = 0x%x\n", 379 + le32_to_cpu(notif->leave_reason_mask)); 392 380 fallthrough; 393 381 case ESR_RECOMMEND_ENTER: 394 382 default: ··· 723 735 u16 max_grade = 0; 724 736 unsigned long link_id; 725 737 726 - /* 727 - * TODO: don't select links that weren't discovered in the last scan 728 - * This requires mac80211 (or cfg80211) changes to forward/track when 729 - * a BSS was last updated. cfg80211 already tracks this information but 730 - * it is not exposed within the kernel. 731 - */ 732 738 for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 733 739 struct ieee80211_bss_conf *link_conf = 734 740 link_conf_dereference_protected(vif, link_id);
-1
drivers/net/wireless/intel/iwlwifi/mld/notif.c
··· 333 333 CMD_VERSIONS(beacon_notification, 334 334 CMD_VER_ENTRY(6, iwl_extended_beacon_notif)) 335 335 CMD_VERSIONS(emlsr_mode_notif, 336 - CMD_VER_ENTRY(1, iwl_esr_mode_notif_v1) 337 336 CMD_VER_ENTRY(2, iwl_esr_mode_notif)) 338 337 CMD_VERSIONS(emlsr_trans_fail_notif, 339 338 CMD_VER_ENTRY(1, iwl_esr_trans_fail_notif))
+21 -7
drivers/net/wireless/intel/iwlwifi/mld/regulatory.c
··· 163 163 164 164 static int iwl_mld_ppag_send_cmd(struct iwl_mld *mld) 165 165 { 166 - union iwl_ppag_table_cmd cmd = {}; 167 - int ret, len; 166 + struct iwl_fw_runtime *fwrt = &mld->fwrt; 167 + union iwl_ppag_table_cmd cmd = { 168 + .v7.ppag_config_info.table_source = fwrt->ppag_bios_source, 169 + .v7.ppag_config_info.table_revision = fwrt->ppag_bios_rev, 170 + .v7.ppag_config_info.value = cpu_to_le32(fwrt->ppag_flags), 171 + }; 172 + int ret; 168 173 169 - ret = iwl_fill_ppag_table(&mld->fwrt, &cmd, &len); 170 - /* Not supporting PPAG table is a valid scenario */ 171 - if (ret < 0) 172 - return 0; 174 + IWL_DEBUG_RADIO(fwrt, 175 + "PPAG MODE bits going to be sent: %d\n", 176 + fwrt->ppag_flags); 177 + 178 + for (int chain = 0; chain < IWL_NUM_CHAIN_LIMITS; chain++) { 179 + for (int subband = 0; subband < IWL_NUM_SUB_BANDS_V2; subband++) { 180 + cmd.v7.gain[chain][subband] = 181 + fwrt->ppag_chains[chain].subbands[subband]; 182 + IWL_DEBUG_RADIO(fwrt, 183 + "PPAG table: chain[%d] band[%d]: gain = %d\n", 184 + chain, subband, cmd.v7.gain[chain][subband]); 185 + } 186 + } 173 187 174 188 IWL_DEBUG_RADIO(mld, "Sending PER_PLATFORM_ANT_GAIN_CMD\n"); 175 189 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(PHY_OPS_GROUP, 176 190 PER_PLATFORM_ANT_GAIN_CMD), 177 - &cmd, len); 191 + &cmd, sizeof(cmd.v7)); 178 192 if (ret < 0) 179 193 IWL_ERR(mld, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n", 180 194 ret);
+2 -8
drivers/net/wireless/intel/iwlwifi/mld/roc.c
··· 82 82 struct iwl_roc_req cmd = { 83 83 .action = cpu_to_le32(FW_CTXT_ACTION_ADD), 84 84 }; 85 - u8 ver = iwl_fw_lookup_cmd_ver(mld->fw, 86 - WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0); 87 - u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd); 88 85 enum iwl_roc_activity activity; 89 86 int ret = 0; 90 87 ··· 137 140 memcpy(cmd.node_addr, vif->addr, ETH_ALEN); 138 141 139 142 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 140 - &cmd, cmd_len); 143 + &cmd); 141 144 if (ret) { 142 145 IWL_ERR(mld, "Couldn't send the ROC_CMD\n"); 143 146 return ret; ··· 187 190 struct iwl_roc_req cmd = { 188 191 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), 189 192 }; 190 - u8 ver = iwl_fw_lookup_cmd_ver(mld->fw, 191 - WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 0); 192 - u16 cmd_len = ver < 6 ? sizeof(struct iwl_roc_req_v5) : sizeof(cmd); 193 193 int ret; 194 194 195 195 lockdep_assert_wiphy(mld->wiphy); ··· 202 208 cmd.activity = cpu_to_le32(mld_vif->roc_activity); 203 209 204 210 ret = iwl_mld_send_cmd_pdu(mld, WIDE_ID(MAC_CONF_GROUP, ROC_CMD), 205 - &cmd, cmd_len); 211 + &cmd); 206 212 if (ret) 207 213 IWL_ERR(mld, "Couldn't send the command to cancel the ROC\n"); 208 214
+18 -8
drivers/net/wireless/intel/iwlwifi/mld/rx.c
··· 1611 1611 return sta; 1612 1612 } 1613 1613 1614 - #define KEY_IDX_LEN 2 1615 - 1616 1614 static int iwl_mld_rx_mgmt_prot(struct ieee80211_sta *sta, 1617 1615 struct ieee80211_hdr *hdr, 1618 1616 struct ieee80211_rx_status *rx_status, 1619 1617 u32 mpdu_status, 1620 1618 u32 mpdu_len) 1621 1619 { 1620 + struct iwl_mld_link *link; 1622 1621 struct wireless_dev *wdev; 1623 1622 struct iwl_mld_sta *mld_sta; 1624 1623 struct iwl_mld_vif *mld_vif; 1625 1624 u8 keyidx; 1626 1625 struct ieee80211_key_conf *key; 1627 1626 const u8 *frame = (void *)hdr; 1627 + const u8 *mmie; 1628 + u8 link_id; 1628 1629 1629 1630 if ((mpdu_status & IWL_RX_MPDU_STATUS_SEC_MASK) == 1630 1631 IWL_RX_MPDU_STATUS_SEC_NONE) ··· 1658 1657 return 0; 1659 1658 } 1660 1659 1660 + link_id = rx_status->link_valid ? rx_status->link_id : 0; 1661 + link = rcu_dereference(mld_vif->link[link_id]); 1662 + if (WARN_ON_ONCE(!link)) 1663 + return -1; 1664 + 1661 1665 /* both keys will have the same cipher and MIC length, use 1662 1666 * whichever one is available 1663 1667 */ 1664 - key = rcu_dereference(mld_vif->bigtks[0]); 1668 + key = rcu_dereference(link->bigtks[0]); 1665 1669 if (!key) { 1666 - key = rcu_dereference(mld_vif->bigtks[1]); 1670 + key = rcu_dereference(link->bigtks[1]); 1667 1671 if (!key) 1668 1672 goto report; 1669 1673 } 1670 1674 1671 - if (mpdu_len < key->icv_len + IEEE80211_GMAC_PN_LEN + KEY_IDX_LEN) 1675 + /* get the real key ID */ 1676 + if (mpdu_len < key->icv_len) 1672 1677 goto report; 1673 1678 1674 - /* get the real key ID */ 1675 - keyidx = frame[mpdu_len - key->icv_len - IEEE80211_GMAC_PN_LEN - KEY_IDX_LEN]; 1679 + mmie = frame + (mpdu_len - key->icv_len); 1680 + 1681 + /* the position of the key_id in ieee80211_mmie_16 is the same */ 1682 + keyidx = le16_to_cpu(((const struct ieee80211_mmie *) mmie)->key_id); 1683 + 1676 1684 /* and if that's the other key, look it up */ 1677 1685 if (keyidx != key->keyidx) { 1678 1686 /* shouldn't happen since firmware checked, but be safe ··· 1690 1680 if (keyidx != 6 && keyidx != 7) 1691 1681 return -1; 1692 1682 1693 - key = rcu_dereference(mld_vif->bigtks[keyidx - 6]); 1683 + key = rcu_dereference(link->bigtks[keyidx - 6]); 1694 1684 if (!key) 1695 1685 goto report; 1696 1686 }
+1 -3
drivers/net/wireless/intel/iwlwifi/mld/scan.c
··· 504 504 */ 505 505 if (scan_status == IWL_MLD_SCAN_REGULAR && 506 506 ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_AP && 507 - gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE && 508 - iwl_fw_lookup_notif_ver(mld->fw, SCAN_GROUP, 509 - CHANNEL_SURVEY_NOTIF, 0) >= 1) 507 + gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE) 510 508 flags |= IWL_UMAC_SCAN_GEN_FLAGS2_COLLECT_CHANNEL_STATS; 511 509 512 510 return flags;
+3 -5
drivers/net/wireless/intel/iwlwifi/mld/sta.c
··· 401 401 static int iwl_mld_send_sta_cmd(struct iwl_mld *mld, 402 402 const struct iwl_sta_cfg_cmd *cmd) 403 403 { 404 - u32 cmd_id = WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD); 405 - int cmd_len = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0) > 1 ? 406 - sizeof(*cmd) : 407 - sizeof(struct iwl_sta_cfg_cmd_v1); 408 - int ret = iwl_mld_send_cmd_pdu(mld, cmd_id, cmd, cmd_len); 404 + int ret = iwl_mld_send_cmd_pdu(mld, 405 + WIDE_ID(MAC_CONF_GROUP, STA_CONFIG_CMD), 406 + cmd); 409 407 if (ret) 410 408 IWL_ERR(mld, "STA_CONFIG_CMD send failed, ret=0x%x\n", ret); 411 409 return ret;
+7 -4
drivers/net/wireless/intel/iwlwifi/mld/stats.c
··· 379 379 380 380 /* TODO: task=statistics handle CQM notifications */ 381 381 382 - if (sig < IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH) 383 - iwl_mld_int_mlo_scan(mld, vif); 384 - 385 - if (!iwl_mld_emlsr_active(vif)) 382 + if (!iwl_mld_emlsr_active(vif)) { 383 + /* We're not in EMLSR and our signal is bad, 384 + * try to switch link maybe. EMLSR will be handled below. 385 + */ 386 + if (sig < IWL_MLD_LOW_RSSI_MLO_SCAN_THRESH) 387 + iwl_mld_int_mlo_scan(mld, vif); 386 388 return; 389 + } 387 390 388 391 /* We are in EMLSR, check if we need to exit */ 389 392 exit_emlsr_thresh =
+56 -19
drivers/net/wireless/intel/iwlwifi/mld/tlc.c
··· 157 157 static void 158 158 iwl_mld_fill_vht_rates(const struct ieee80211_link_sta *link_sta, 159 159 const struct ieee80211_sta_vht_cap *vht_cap, 160 - struct iwl_tlc_config_cmd_v4 *cmd) 160 + struct iwl_tlc_config_cmd *cmd) 161 161 { 162 - u16 supp; 162 + u32 supp; 163 163 int i, highest_mcs; 164 164 u8 max_nss = link_sta->rx_nss; 165 165 struct ieee80211_vht_cap ieee_vht_cap = { ··· 182 182 if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20) 183 183 supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9); 184 184 185 - cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le16(supp); 185 + cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = cpu_to_le32(supp); 186 186 /* Check if VHT extended NSS indicates that the bandwidth/NSS 187 187 * configuration is supported - only for MCS 0 since we already 188 188 * decoded the MCS bits anyway ourselves. ··· 196 196 } 197 197 } 198 198 199 - static u16 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs) 199 + static u32 iwl_mld_he_mac80211_mcs_to_fw_mcs(u16 mcs) 200 200 { 201 201 switch (mcs) { 202 202 case IEEE80211_HE_MCS_SUPPORT_0_7: ··· 216 216 static void 217 217 iwl_mld_fill_he_rates(const struct ieee80211_link_sta *link_sta, 218 218 const struct ieee80211_sta_he_cap *own_he_cap, 219 - struct iwl_tlc_config_cmd_v4 *cmd) 219 + struct iwl_tlc_config_cmd *cmd) 220 220 { 221 221 const struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap; 222 222 u16 mcs_160 = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); ··· 245 245 if (_mcs_80 > _tx_mcs_80) 246 246 _mcs_80 = _tx_mcs_80; 247 247 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_80] = 248 - cpu_to_le16(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80)); 248 + cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_80)); 249 249 250 250 /* If one side doesn't support - mark both as not supporting */ 251 251 if (_mcs_160 == IEEE80211_HE_MCS_NOT_SUPPORTED || ··· 256 256 if (_mcs_160 > _tx_mcs_160) 257 257 _mcs_160 = _tx_mcs_160; 258 258 cmd->ht_rates[i][IWL_TLC_MCS_PER_BW_160] = 259 - cpu_to_le16(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160)); 259 + cpu_to_le32(iwl_mld_he_mac80211_mcs_to_fw_mcs(_mcs_160)); 260 260 } 261 261 } 262 262 263 - static void iwl_mld_set_eht_mcs(__le16 ht_rates[][3], 263 + static void iwl_mld_set_eht_mcs(__le32 ht_rates[][3], 264 264 enum IWL_TLC_MCS_PER_BW bw, 265 - u8 max_nss, u16 mcs_msk) 265 + u8 max_nss, u32 mcs_msk) 266 266 { 267 267 if (max_nss >= 2) 268 - ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le16(mcs_msk); 268 + ht_rates[IWL_TLC_NSS_2][bw] |= cpu_to_le32(mcs_msk); 269 269 270 270 if (max_nss >= 1) 271 - ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le16(mcs_msk); 271 + ht_rates[IWL_TLC_NSS_1][bw] |= cpu_to_le32(mcs_msk); 272 272 } 273 273 274 274 static const ··· 307 307 const struct ieee80211_link_sta *link_sta, 308 308 const struct ieee80211_sta_he_cap *own_he_cap, 309 309 const struct ieee80211_sta_eht_cap *own_eht_cap, 310 - struct iwl_tlc_config_cmd_v4 *cmd) 310 + struct iwl_tlc_config_cmd *cmd) 311 311 { 312 312 /* peer RX mcs capa */ 313 313 const struct ieee80211_eht_mcs_nss_supp *eht_rx_mcs = ··· 405 405 struct ieee80211_supported_band *sband, 406 406 const struct ieee80211_sta_he_cap *own_he_cap, 407 407 const struct ieee80211_sta_eht_cap *own_eht_cap, 408 - struct iwl_tlc_config_cmd_v4 *cmd) 408 + struct iwl_tlc_config_cmd *cmd) 409 409 { 410 410 int i; 411 411 u16 non_ht_rates = 0; ··· 435 435 } else if (ht_cap->ht_supported) { 436 436 cmd->mode = IWL_TLC_MNG_MODE_HT; 437 437 cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_MCS_PER_BW_80] = 438 - cpu_to_le16(ht_cap->mcs.rx_mask[0]); 438 + cpu_to_le32(ht_cap->mcs.rx_mask[0]); 439 439 440 440 /* the station support only a single receive chain */ 441 441 if (link_sta->smps_mode == IEEE80211_SMPS_STATIC) ··· 443 443 0; 444 444 else 445 445 cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_MCS_PER_BW_80] = 446 - cpu_to_le16(ht_cap->mcs.rx_mask[1]); 446 + cpu_to_le32(ht_cap->mcs.rx_mask[1]); 447 447 } 448 + } 449 + 450 + static void iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd, 451 + struct iwl_tlc_config_cmd_v4 *cmd_v4) 452 + { 453 + /* Copy everything until ht_rates */ 454 + memcpy(cmd_v4, cmd, offsetof(struct iwl_tlc_config_cmd, ht_rates)); 455 + 456 + /* Convert ht_rates from __le32 to __le16 */ 457 + BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates) != ARRAY_SIZE(cmd->ht_rates)); 458 + BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates[0]) != ARRAY_SIZE(cmd->ht_rates[0])); 459 + 460 + for (int nss = 0; nss < ARRAY_SIZE(cmd->ht_rates); nss++) 461 + for (int bw = 0; bw < ARRAY_SIZE(cmd->ht_rates[nss]); bw++) 462 + cmd_v4->ht_rates[nss][bw] = 463 + cpu_to_le16(le32_to_cpu(cmd->ht_rates[nss][bw])); 464 + 465 + /* Copy the rest */ 466 + cmd_v4->max_mpdu_len = cmd->max_mpdu_len; 467 + cmd_v4->max_tx_op = cmd->max_tx_op; 448 468 } 449 469 450 470 static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld, ··· 478 458 ieee80211_get_he_iftype_cap_vif(sband, vif); 479 459 const struct ieee80211_sta_eht_cap *own_eht_cap = 480 460 ieee80211_get_eht_iftype_cap_vif(sband, vif); 481 - struct iwl_tlc_config_cmd_v4 cmd = { 461 + struct iwl_tlc_config_cmd cmd = { 482 462 /* For AP mode, use 20 MHz until the STA is authorized */ 483 463 .max_ch_width = mld_sta->sta_state > IEEE80211_STA_ASSOC ? 484 464 iwl_mld_fw_bw_from_sta_bw(link_sta) : ··· 490 470 .max_mpdu_len = cpu_to_le16(link_sta->agg.max_amsdu_len), 491 471 }; 492 472 int fw_sta_id = iwl_mld_fw_sta_id_from_link_sta(mld, link_sta); 473 + u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD); 474 + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0); 475 + struct iwl_tlc_config_cmd_v4 cmd_v4; 476 + void *cmd_ptr; 477 + u8 cmd_size; 493 478 int ret; 494 479 495 480 if (fw_sta_id < 0) ··· 506 481 own_he_cap, own_eht_cap, 507 482 &cmd); 508 483 484 + if (cmd_ver == 5) { 485 + cmd_ptr = &cmd; 486 + cmd_size = sizeof(cmd); 487 + } else if (cmd_ver == 4) { 488 + iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4); 489 + cmd_ptr = &cmd_v4; 490 + cmd_size = sizeof(cmd_v4); 491 + } else { 492 + IWL_ERR(mld, "Unsupported TLC config cmd version %d\n", 493 + cmd_ver); 494 + return; 495 + } 496 + 509 497 IWL_DEBUG_RATE(mld, 510 498 "TLC CONFIG CMD, sta_id=%d, max_ch_width=%d, mode=%d\n", 511 499 cmd.sta_id, cmd.max_ch_width, cmd.mode); 512 500 513 501 /* Send async since this can be called within a RCU-read section */ 514 - ret = iwl_mld_send_cmd_with_flags_pdu(mld, WIDE_ID(DATA_PATH_GROUP, 515 - TLC_MNG_CONFIG_CMD), 516 - CMD_ASYNC, &cmd); 502 + ret = iwl_mld_send_cmd_with_flags_pdu(mld, cmd_id, CMD_ASYNC, cmd_ptr, 503 + cmd_size); 517 504 if (ret) 518 505 IWL_ERR(mld, "Failed to send TLC cmd (%d)\n", ret); 519 506 }
-131
drivers/net/wireless/intel/iwlwifi/mvm/coex.c
··· 253 253 swap(data->primary, data->secondary); 254 254 } 255 255 256 - /* 257 - * This function receives the LB link id and checks if eSR should be 258 - * enabled or disabled (due to BT coex) 259 - */ 260 - bool 261 - iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, 262 - struct ieee80211_vif *vif, 263 - s32 link_rssi, 264 - bool primary) 265 - { 266 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 267 - bool have_wifi_loss_rate = 268 - iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, 269 - BT_PROFILE_NOTIFICATION, 0) > 4 || 270 - iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP, 271 - PROFILE_NOTIF, 0) >= 1; 272 - u8 wifi_loss_mid_high_rssi; 273 - u8 wifi_loss_low_rssi; 274 - u8 wifi_loss_rate; 275 - 276 - if (iwl_fw_lookup_notif_ver(mvm->fw, BT_COEX_GROUP, 277 - PROFILE_NOTIF, 0) >= 1) { 278 - /* For now, we consider 2.4 GHz band / ANT_A only */ 279 - wifi_loss_mid_high_rssi = 280 - mvm->last_bt_wifi_loss.wifi_loss_mid_high_rssi[PHY_BAND_24][0]; 281 - wifi_loss_low_rssi = 282 - mvm->last_bt_wifi_loss.wifi_loss_low_rssi[PHY_BAND_24][0]; 283 - } else { 284 - wifi_loss_mid_high_rssi = mvm->last_bt_notif.wifi_loss_mid_high_rssi; 285 - wifi_loss_low_rssi = mvm->last_bt_notif.wifi_loss_low_rssi; 286 - } 287 - 288 - if (wifi_loss_low_rssi == BT_OFF) 289 - return true; 290 - 291 - if (primary) 292 - return false; 293 - 294 - /* The feature is not supported */ 295 - if (!have_wifi_loss_rate) 296 - return true; 297 - 298 - 299 - /* 300 - * In case we don't know the RSSI - take the lower wifi loss, 301 - * so we will more likely enter eSR, and if RSSI is low - 302 - * we will get an update on this and exit eSR. 303 - */ 304 - if (!link_rssi) 305 - wifi_loss_rate = wifi_loss_mid_high_rssi; 306 - 307 - else if (mvmvif->esr_active) 308 - /* RSSI needs to get really low to disable eSR... */ 309 - wifi_loss_rate = 310 - link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ? 311 - wifi_loss_low_rssi : 312 - wifi_loss_mid_high_rssi; 313 - else 314 - /* ...And really high before we enable it back */ 315 - wifi_loss_rate = 316 - link_rssi <= -IWL_MVM_BT_COEX_ENABLE_ESR_THRESH ? 317 - wifi_loss_low_rssi : 318 - wifi_loss_mid_high_rssi; 319 - 320 - return wifi_loss_rate <= IWL_MVM_BT_COEX_WIFI_LOSS_THRESH; 321 - } 322 - 323 - void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, 324 - struct ieee80211_vif *vif, 325 - int link_id) 326 - { 327 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 328 - struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id]; 329 - 330 - if (!ieee80211_vif_is_mld(vif) || 331 - !iwl_mvm_vif_from_mac80211(vif)->authorized || 332 - WARN_ON(!link)) 333 - return; 334 - 335 - if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, 336 - (s8)link->beacon_stats.avg_signal, 337 - link_id == iwl_mvm_get_primary_link(vif))) 338 - /* In case we decided to exit eSR - stay with the primary */ 339 - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX, 340 - iwl_mvm_get_primary_link(vif)); 341 - } 342 - 343 256 static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm, 344 257 struct ieee80211_vif *vif, 345 258 struct iwl_bt_iterator_data *data, ··· 297 384 } 298 385 return; 299 386 } 300 - 301 - iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); 302 387 303 388 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2)) 304 389 min_ag_for_static_smps = BT_VERY_HIGH_TRAFFIC; ··· 436 525 iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id); 437 526 } 438 527 439 - /* must be called under rcu_read_lock */ 440 - static void iwl_mvm_bt_coex_notif_iterator(void *_data, u8 *mac, 441 - struct ieee80211_vif *vif) 442 - { 443 - struct iwl_mvm *mvm = _data; 444 - struct ieee80211_bss_conf *link_conf; 445 - unsigned int link_id; 446 - 447 - lockdep_assert_held(&mvm->mutex); 448 - 449 - if (vif->type != NL80211_IFTYPE_STATION) 450 - return; 451 - 452 - for_each_vif_active_link(vif, link_conf, link_id) { 453 - struct ieee80211_chanctx_conf *chanctx_conf = 454 - rcu_dereference_check(link_conf->chanctx_conf, 455 - lockdep_is_held(&mvm->mutex)); 456 - 457 - if ((!chanctx_conf || 458 - chanctx_conf->def.chan->band != NL80211_BAND_2GHZ)) 459 - continue; 460 - 461 - iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); 462 - } 463 - } 464 - 465 528 static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) 466 529 { 467 530 struct iwl_bt_iterator_data data = { ··· 537 652 memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); 538 653 539 654 iwl_mvm_bt_coex_notif_handle(mvm); 540 - } 541 - 542 - void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, 543 - struct iwl_rx_cmd_buffer *rxb) 544 - { 545 - const struct iwl_rx_packet *pkt = rxb_addr(rxb); 546 - const struct iwl_bt_coex_profile_notif *notif = (const void *)pkt->data; 547 - 548 - lockdep_assert_held(&mvm->mutex); 549 - 550 - mvm->last_bt_wifi_loss = *notif; 551 - 552 - ieee80211_iterate_active_interfaces(mvm->hw, 553 - IEEE80211_IFACE_ITER_NORMAL, 554 - iwl_mvm_bt_coex_notif_iterator, 555 - mvm); 556 655 } 557 656 558 657 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+1 -19
drivers/net/wireless/intel/iwlwifi/mvm/constants.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ 2 2 /* 3 3 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH 4 - * Copyright (C) 2013-2014, 2018-2024 Intel Corporation 4 + * Copyright (C) 2013-2014, 2018-2025 Intel Corporation 5 5 * Copyright (C) 2015 Intel Deutschland GmbH 6 6 */ 7 7 #ifndef __MVM_CONSTANTS_H ··· 11 11 #include "fw-api.h" 12 12 13 13 #define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20 14 - #define IWL_MVM_BT_COEX_DISABLE_ESR_THRESH 69 15 - #define IWL_MVM_BT_COEX_ENABLE_ESR_THRESH 63 16 - #define IWL_MVM_BT_COEX_WIFI_LOSS_THRESH 0 17 14 #define IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC 30 18 - #define IWL_MVM_TPT_COUNT_WINDOW_SEC 5 19 - #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS 5 20 - #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH 15 21 - #define IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 11 22 - #define IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH -72 23 15 24 16 #define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC) 25 17 #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) ··· 121 129 #define IWL_MVM_MIN_BEACON_INTERVAL_TU 16 122 130 #define IWL_MVM_AUTO_EML_ENABLE true 123 131 124 - #define IWL_MVM_HIGH_RSSI_THRESH_20MHZ -67 125 - #define IWL_MVM_LOW_RSSI_THRESH_20MHZ -71 126 - #define IWL_MVM_HIGH_RSSI_THRESH_40MHZ -64 127 - #define IWL_MVM_LOW_RSSI_THRESH_40MHZ -67 128 - #define IWL_MVM_HIGH_RSSI_THRESH_80MHZ -61 129 - #define IWL_MVM_LOW_RSSI_THRESH_80MHZ -74 130 - #define IWL_MVM_HIGH_RSSI_THRESH_160MHZ -58 131 - #define IWL_MVM_LOW_RSSI_THRESH_160MHZ -61 132 - 133 - #define IWL_MVM_ENTER_ESR_TPT_THRESH 400 134 132 #endif /* __MVM_CONSTANTS_H */
+44 -338
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
··· 928 928 if (ap_sta->mfp) 929 929 wowlan_config_cmd->flags |= IS_11W_ASSOC; 930 930 931 + if (rcu_access_pointer(mvmvif->bcn_prot.keys[0]) || 932 + rcu_access_pointer(mvmvif->bcn_prot.keys[1])) 933 + wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION; 934 + 931 935 if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) < 6) { 932 936 /* Query the last used seqno and set it */ 933 937 int ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); ··· 1242 1238 } 1243 1239 1244 1240 static int __iwl_mvm_suspend(struct ieee80211_hw *hw, 1245 - struct cfg80211_wowlan *wowlan, 1246 - bool test) 1241 + struct cfg80211_wowlan *wowlan) 1247 1242 { 1248 1243 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1249 1244 struct ieee80211_vif *vif = NULL; 1250 1245 struct iwl_mvm_vif *mvmvif = NULL; 1251 1246 struct ieee80211_sta *ap_sta = NULL; 1252 1247 struct iwl_mvm_vif_link_info *mvm_link; 1253 - struct iwl_d3_manager_config d3_cfg_cmd_data = { 1248 + struct iwl_d3_manager_config d3_cfg_cmd = { 1254 1249 /* 1255 1250 * Program the minimum sleep time to 10 seconds, as many 1256 1251 * platforms have issues processing a wakeup signal while ··· 1257 1254 */ 1258 1255 .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), 1259 1256 }; 1260 - struct iwl_host_cmd d3_cfg_cmd = { 1261 - .id = D3_CONFIG_CMD, 1262 - .flags = CMD_WANT_SKB, 1263 - .data[0] = &d3_cfg_cmd_data, 1264 - .len[0] = sizeof(d3_cfg_cmd_data), 1265 - }; 1266 1257 int ret; 1267 1258 int len __maybe_unused; 1268 1259 bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, 1269 1260 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); 1270 1261 1271 1262 if (!wowlan) { 1272 - /* 1273 - * mac80211 shouldn't get here, but for D3 test 1274 - * it doesn't warrant a warning 1275 - */ 1276 - WARN_ON(!test); 1263 + /* mac80211 shouldn't get here */ 1264 + WARN_ON(1); 1277 1265 return -EINVAL; 1278 1266 } 1279 1267 1280 1268 vif = iwl_mvm_get_bss_vif(mvm); 1281 1269 if (IS_ERR_OR_NULL(vif)) 1282 1270 return 1; 1283 - 1284 - ret = iwl_mvm_block_esr_sync(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN); 1285 - if (ret) 1286 - return ret; 1287 1271 1288 1272 mutex_lock(&mvm->mutex); 1289 1273 ··· 1341 1351 1342 1352 #ifdef CONFIG_IWLWIFI_DEBUGFS 1343 1353 if (mvm->d3_wake_sysassert) 1344 - d3_cfg_cmd_data.wakeup_flags |= 1354 + d3_cfg_cmd.wakeup_flags |= 1345 1355 cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR); 1346 1356 #endif 1347 1357 ··· 1354 1364 iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true); 1355 1365 1356 1366 /* must be last -- this switches firmware state */ 1357 - ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); 1367 + ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, 0, sizeof(d3_cfg_cmd), 1368 + &d3_cfg_cmd); 1358 1369 if (ret) 1359 1370 goto out; 1360 - #ifdef CONFIG_IWLWIFI_DEBUGFS 1361 - len = iwl_rx_packet_payload_len(d3_cfg_cmd.resp_pkt); 1362 - if (len >= sizeof(u32)) { 1363 - mvm->d3_test_pme_ptr = 1364 - le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); 1365 - } 1366 - #endif 1367 - iwl_free_resp(&d3_cfg_cmd); 1368 1371 1369 1372 clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); 1370 1373 1371 - ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image); 1374 + ret = iwl_trans_d3_suspend(mvm->trans, !unified_image); 1372 1375 out: 1373 1376 if (ret < 0) { 1374 1377 iwl_mvm_free_nd(mvm); ··· 1384 1401 iwl_fw_runtime_suspend(&mvm->fwrt); 1385 1402 mutex_unlock(&mvm->mutex); 1386 1403 1387 - return __iwl_mvm_suspend(hw, wowlan, false); 1404 + return __iwl_mvm_suspend(hw, wowlan); 1388 1405 } 1389 1406 1390 1407 struct iwl_multicast_key_data { ··· 1777 1794 struct iwl_mvm_d3_gtk_iter_data { 1778 1795 struct iwl_mvm *mvm; 1779 1796 struct iwl_wowlan_status_data *status; 1780 - u32 gtk_cipher, igtk_cipher, bigtk_cipher; 1781 - bool unhandled_cipher, igtk_support, bigtk_support; 1782 - int num_keys; 1783 1797 }; 1784 - 1785 - static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw, 1786 - struct ieee80211_vif *vif, 1787 - struct ieee80211_sta *sta, 1788 - struct ieee80211_key_conf *key, 1789 - void *_data) 1790 - { 1791 - struct iwl_mvm_d3_gtk_iter_data *data = _data; 1792 - int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1793 - 1794 - if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id) 1795 - return; 1796 - 1797 - if (data->unhandled_cipher) 1798 - return; 1799 - 1800 - switch (key->cipher) { 1801 - case WLAN_CIPHER_SUITE_WEP40: 1802 - case WLAN_CIPHER_SUITE_WEP104: 1803 - /* ignore WEP completely, nothing to do */ 1804 - return; 1805 - case WLAN_CIPHER_SUITE_CCMP: 1806 - case WLAN_CIPHER_SUITE_GCMP: 1807 - case WLAN_CIPHER_SUITE_GCMP_256: 1808 - case WLAN_CIPHER_SUITE_TKIP: 1809 - /* we support these */ 1810 - data->gtk_cipher = key->cipher; 1811 - break; 1812 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1813 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1814 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1815 - case WLAN_CIPHER_SUITE_AES_CMAC: 1816 - /* we support these */ 1817 - if (data->igtk_support && 1818 - (key->keyidx == 4 || key->keyidx == 5)) { 1819 - data->igtk_cipher = key->cipher; 1820 - } else if (data->bigtk_support && 1821 - (key->keyidx == 6 || key->keyidx == 7)) { 1822 - data->bigtk_cipher = key->cipher; 1823 - } else { 1824 - data->unhandled_cipher = true; 1825 - return; 1826 - } 1827 - break; 1828 - default: 1829 - /* everything else - disconnect from AP */ 1830 - data->unhandled_cipher = true; 1831 - return; 1832 - } 1833 - 1834 - data->num_keys++; 1835 - } 1836 1798 1837 1799 static void 1838 1800 iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key, ··· 1822 1894 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1823 1895 1824 1896 if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id) 1825 - return; 1826 - 1827 - if (data->unhandled_cipher) 1828 1897 return; 1829 1898 1830 1899 switch (key->cipher) { ··· 1872 1947 1873 1948 static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status, 1874 1949 struct ieee80211_vif *vif, 1875 - struct iwl_mvm *mvm, u32 gtk_cipher) 1950 + struct iwl_mvm *mvm) 1876 1951 { 1877 1952 int i, j; 1878 1953 struct ieee80211_key_conf *key; 1879 - DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, 1880 - WOWLAN_KEY_MAX_SIZE); 1881 1954 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1882 - u8 key_data[WOWLAN_KEY_MAX_SIZE]; 1883 - 1884 - conf->cipher = gtk_cipher; 1885 - 1886 - BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP); 1887 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_CCMP); 1888 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_GCMP_256); 1889 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < WLAN_KEY_LEN_TKIP); 1890 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(status->gtk[0].key)); 1891 - 1892 - switch (gtk_cipher) { 1893 - case WLAN_CIPHER_SUITE_CCMP: 1894 - case WLAN_CIPHER_SUITE_GCMP: 1895 - conf->keylen = WLAN_KEY_LEN_CCMP; 1896 - break; 1897 - case WLAN_CIPHER_SUITE_GCMP_256: 1898 - conf->keylen = WLAN_KEY_LEN_GCMP_256; 1899 - break; 1900 - case WLAN_CIPHER_SUITE_TKIP: 1901 - conf->keylen = WLAN_KEY_LEN_TKIP; 1902 - break; 1903 - default: 1904 - WARN_ON(1); 1905 - } 1906 1955 1907 1956 for (i = 0; i < ARRAY_SIZE(status->gtk); i++) { 1908 1957 if (!status->gtk[i].len) 1909 1958 continue; 1910 1959 1911 - conf->keyidx = status->gtk[i].id; 1912 1960 IWL_DEBUG_WOWLAN(mvm, 1913 - "Received from FW GTK cipher %d, key index %d\n", 1914 - conf->cipher, conf->keyidx); 1915 - memcpy(conf->key, status->gtk[i].key, 1916 - sizeof(status->gtk[i].key)); 1917 - memcpy(key_data, status->gtk[i].key, sizeof(status->gtk[i].key)); 1961 + "Received from FW GTK: key index %d\n", 1962 + status->gtk[i].id); 1918 1963 1919 - key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id, key_data, 1920 - sizeof(key_data), link_id); 1964 + key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id, 1965 + status->gtk[i].key, 1966 + sizeof(status->gtk[i].key), 1967 + link_id); 1921 1968 if (IS_ERR(key)) { 1922 1969 /* FW may send also the old keys */ 1923 1970 if (PTR_ERR(key) == -EALREADY) ··· 1912 2015 1913 2016 static bool 1914 2017 iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status, 1915 - struct ieee80211_vif *vif, u32 cipher, 2018 + struct ieee80211_vif *vif, 1916 2019 struct iwl_multicast_key_data *key_data) 1917 2020 { 1918 2021 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1919 - DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key, 1920 - WOWLAN_KEY_MAX_SIZE); 1921 2022 struct ieee80211_key_conf *key_config; 1922 2023 struct ieee80211_key_seq seq; 1923 2024 int link_id = vif->active_links ? __ffs(vif->active_links) : -1; 1924 - u8 key[WOWLAN_KEY_MAX_SIZE]; 1925 2025 s8 keyidx = key_data->id; 1926 - 1927 - conf->cipher = cipher; 1928 - conf->keyidx = keyidx; 1929 2026 1930 2027 if (!key_data->len) 1931 2028 return true; 1932 2029 1933 - iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf->cipher); 1934 - 1935 - switch (cipher) { 1936 - case WLAN_CIPHER_SUITE_BIP_GMAC_128: 1937 - conf->keylen = WLAN_KEY_LEN_BIP_GMAC_128; 1938 - break; 1939 - case WLAN_CIPHER_SUITE_BIP_GMAC_256: 1940 - conf->keylen = WLAN_KEY_LEN_BIP_GMAC_256; 1941 - break; 1942 - case WLAN_CIPHER_SUITE_AES_CMAC: 1943 - conf->keylen = WLAN_KEY_LEN_AES_CMAC; 1944 - break; 1945 - case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1946 - conf->keylen = WLAN_KEY_LEN_BIP_CMAC_256; 1947 - break; 1948 - default: 1949 - WARN_ON(1); 1950 - } 1951 - BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(key_data->key)); 1952 - memcpy(conf->key, key_data->key, conf->keylen); 1953 - 1954 - memcpy(key, key_data->key, sizeof(key_data->key)); 1955 - 1956 - key_config = ieee80211_gtk_rekey_add(vif, keyidx, key, sizeof(key), 1957 - link_id); 2030 + key_config = ieee80211_gtk_rekey_add(vif, keyidx, key_data->key, 2031 + sizeof(key_data->key), link_id); 1958 2032 if (IS_ERR(key_config)) { 1959 2033 /* FW may send also the old keys */ 1960 2034 return PTR_ERR(key_config) == -EALREADY; 1961 2035 } 2036 + 2037 + iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, key_config->cipher); 1962 2038 ieee80211_set_key_rx_seq(key_config, 0, &seq); 1963 2039 1964 2040 if (keyidx == 4 || keyidx == 5) { ··· 1985 2115 1986 2116 if (!status || !vif->bss_conf.bssid) 1987 2117 return false; 1988 - 1989 - if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 || 1990 - iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP, 1991 - WOWLAN_INFO_NOTIFICATION, 1992 - 0)) 1993 - gtkdata.igtk_support = true; 1994 - 1995 - if (iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP, 1996 - WOWLAN_INFO_NOTIFICATION, 1997 - 0) >= 3) 1998 - gtkdata.bigtk_support = true; 1999 - 2000 - /* find last GTK that we used initially, if any */ 2001 - ieee80211_iter_keys(mvm->hw, vif, 2002 - iwl_mvm_d3_find_last_keys, &gtkdata); 2003 - /* not trying to keep connections with MFP/unhandled ciphers */ 2004 - if (gtkdata.unhandled_cipher) 2005 - return false; 2006 - if (!gtkdata.num_keys) 2007 - goto out; 2008 - 2009 2118 /* 2010 2119 * invalidate all other GTKs that might still exist and update 2011 2120 * the one that we used ··· 1998 2149 IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n", 1999 2150 status->num_of_gtk_rekeys); 2000 2151 2001 - if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher)) 2152 + if (!iwl_mvm_gtk_rekey(status, vif, mvm)) 2002 2153 return false; 2003 2154 2004 2155 if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif, 2005 - gtkdata.igtk_cipher, 2006 2156 &status->igtk)) 2007 2157 return false; 2008 2158 2009 2159 for (i = 0; i < ARRAY_SIZE(status->bigtk); i++) { 2010 2160 if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif, 2011 - gtkdata.bigtk_cipher, 2012 2161 &status->bigtk[i])) 2013 2162 return false; 2014 2163 } ··· 2015 2168 (void *)&replay_ctr, GFP_KERNEL); 2016 2169 } 2017 2170 2018 - out: 2019 2171 if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, 2020 2172 WOWLAN_GET_STATUSES, 2021 2173 IWL_FW_CMD_VER_UNKNOWN) < 10) { ··· 2082 2236 } 2083 2237 2084 2238 static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status, 2085 - struct iwl_wowlan_igtk_status *data) 2239 + struct iwl_wowlan_igtk_status_v1 *data) 2086 2240 { 2087 2241 int i; 2088 2242 ··· 2106 2260 } 2107 2261 2108 2262 static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status, 2109 - const struct iwl_wowlan_igtk_status *data) 2263 + const struct iwl_wowlan_igtk_status_v1 *data) 2110 2264 { 2111 2265 int data_idx, status_idx = 0; 2112 2266 ··· 2137 2291 } 2138 2292 2139 2293 static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm, 2140 - struct iwl_wowlan_info_notif *data, 2294 + struct iwl_wowlan_info_notif_v5 *data, 2141 2295 struct iwl_wowlan_status_data *status, 2142 2296 u32 len) 2143 2297 { ··· 2573 2727 /* manage d3 resume data */ 2574 2728 struct iwl_d3_data { 2575 2729 struct iwl_wowlan_status_data *status; 2576 - bool test; 2577 2730 u32 d3_end_flags; 2578 2731 u32 notif_expected; /* bitmap - see &enum iwl_d3_notif */ 2579 2732 u32 notif_received; /* bitmap - see &enum iwl_d3_notif */ ··· 2764 2919 2765 2920 if (mvm->net_detect) { 2766 2921 iwl_mvm_query_netdetect_reasons(mvm, vif, d3_data); 2767 - } else { 2768 - bool keep = iwl_mvm_query_wakeup_reasons(mvm, vif, 2769 - d3_data->status); 2770 - 2771 - #ifdef CONFIG_IWLWIFI_DEBUGFS 2772 - if (keep) 2773 - mvm->keep_vif = vif; 2774 - #endif 2775 - 2776 - return keep; 2922 + return false; 2777 2923 } 2778 - return false; 2924 + 2925 + return iwl_mvm_query_wakeup_reasons(mvm, vif, 2926 + d3_data->status); 2779 2927 } 2780 2928 2781 2929 #define IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT (IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET | \ ··· 2907 3069 iwl_mvm_parse_wowlan_info_notif_v3(mvm, notif, 2908 3070 d3_data->status, len); 2909 3071 } else if (wowlan_info_ver == 5) { 2910 - struct iwl_wowlan_info_notif *notif = 3072 + struct iwl_wowlan_info_notif_v5 *notif = 2911 3073 (void *)pkt->data; 2912 3074 2913 3075 iwl_mvm_parse_wowlan_info_notif(mvm, notif, ··· 2981 3143 return d3_data->notif_received == d3_data->notif_expected; 2982 3144 } 2983 3145 2984 - static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm, bool test) 3146 + static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm) 2985 3147 { 2986 3148 int ret; 2987 - enum iwl_d3_status d3_status; 2988 3149 struct iwl_host_cmd cmd = { 2989 3150 .id = D0I3_END_CMD, 2990 3151 .flags = CMD_WANT_SKB, ··· 2991 3154 bool reset = fw_has_capa(&mvm->fw->ucode_capa, 2992 3155 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); 2993 3156 2994 - ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !reset); 3157 + ret = iwl_trans_d3_resume(mvm->trans, !reset); 2995 3158 if (ret) 2996 3159 return ret; 2997 - 2998 - if (d3_status != IWL_D3_STATUS_ALIVE) { 2999 - IWL_INFO(mvm, "Device was reset during suspend\n"); 3000 - return -ENOENT; 3001 - } 3002 3160 3003 3161 /* 3004 3162 * We should trigger resume flow using command only for 22000 family ··· 3039 3207 ARRAY_SIZE(d3_resume_notif), 3040 3208 iwl_mvm_wait_d3_notif, d3_data); 3041 3209 3042 - ret = iwl_mvm_resume_firmware(mvm, d3_data->test); 3210 + ret = iwl_mvm_resume_firmware(mvm); 3043 3211 if (ret) { 3044 3212 iwl_remove_notification(&mvm->notif_wait, &wait_d3_notif); 3045 3213 return ret; ··· 3059 3227 D3_END_NOTIFICATION, 0); 3060 3228 } 3061 3229 3062 - static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) 3230 + static int __iwl_mvm_resume(struct iwl_mvm *mvm) 3063 3231 { 3064 3232 struct ieee80211_vif *vif = NULL; 3065 3233 int ret = 1; 3066 3234 struct iwl_mvm_nd_results results = {}; 3067 3235 struct iwl_d3_data d3_data = { 3068 - .test = test, 3069 3236 .notif_expected = 3070 3237 IWL_D3_NOTIF_WOWLAN_INFO | 3071 3238 IWL_D3_NOTIF_D3_END_NOTIF, ··· 3102 3271 3103 3272 rt_status = iwl_mvm_check_rt_status(mvm, vif); 3104 3273 if (rt_status != FW_ALIVE) { 3105 - set_bit(STATUS_FW_ERROR, &mvm->trans->status); 3274 + iwl_trans_notify_fw_error(mvm->trans); 3106 3275 if (rt_status == FW_ERROR) { 3107 3276 IWL_ERR(mvm, "FW Error occurred during suspend. Restarting.\n"); 3108 3277 iwl_mvm_dump_nic_error_log(mvm); ··· 3129 3298 if (ret) 3130 3299 goto err; 3131 3300 } else { 3132 - ret = iwl_mvm_resume_firmware(mvm, test); 3301 + ret = iwl_mvm_resume_firmware(mvm); 3133 3302 if (ret < 0) 3134 3303 goto err; 3135 3304 } 3136 - 3137 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN); 3138 3305 3139 3306 /* when reset is required we can't send these following commands */ 3140 3307 if (d3_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE) ··· 3175 3346 kfree(d3_data.status); 3176 3347 iwl_mvm_free_nd(mvm); 3177 3348 3178 - if (!d3_data.test && !mvm->net_detect) 3349 + if (!mvm->net_detect) 3179 3350 ieee80211_iterate_active_interfaces_mtx(mvm->hw, 3180 3351 IEEE80211_IFACE_ITER_NORMAL, 3181 3352 iwl_mvm_d3_disconnect_iter, ··· 3214 3385 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 3215 3386 int ret; 3216 3387 3217 - ret = __iwl_mvm_resume(mvm, false); 3388 + ret = __iwl_mvm_resume(mvm); 3218 3389 3219 3390 iwl_mvm_resume_tcm(mvm); 3220 3391 ··· 3249 3420 IWL_ERR(mvm, 3250 3421 "fast suspend: couldn't send D3_CONFIG_CMD %d\n", ret); 3251 3422 3252 - ret = iwl_trans_d3_suspend(mvm->trans, false, false); 3423 + ret = iwl_trans_d3_suspend(mvm->trans, false); 3253 3424 if (ret) 3254 3425 IWL_ERR(mvm, "fast suspend: trans_d3_suspend failed %d\n", ret); 3255 3426 } ··· 3272 3443 3273 3444 rt_status = iwl_mvm_check_rt_status(mvm, NULL); 3274 3445 if (rt_status != FW_ALIVE) { 3275 - set_bit(STATUS_FW_ERROR, &mvm->trans->status); 3446 + iwl_trans_notify_fw_error(mvm->trans); 3276 3447 if (rt_status == FW_ERROR) { 3277 3448 IWL_ERR(mvm, 3278 3449 "iwl_mvm_check_rt_status failed, device is gone during suspend\n"); ··· 3284 3455 &iwl_dump_desc_assert, 3285 3456 false, 0); 3286 3457 } 3287 - mvm->trans->state = IWL_TRANS_NO_FW; 3288 3458 ret = -ENODEV; 3289 3459 3290 3460 goto out; ··· 3301 3473 3302 3474 return ret; 3303 3475 } 3304 - 3305 - #ifdef CONFIG_IWLWIFI_DEBUGFS 3306 - static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) 3307 - { 3308 - struct iwl_mvm *mvm = inode->i_private; 3309 - int err; 3310 - 3311 - if (mvm->d3_test_active) 3312 - return -EBUSY; 3313 - 3314 - file->private_data = inode->i_private; 3315 - 3316 - iwl_mvm_pause_tcm(mvm, true); 3317 - 3318 - iwl_fw_runtime_suspend(&mvm->fwrt); 3319 - 3320 - /* start pseudo D3 */ 3321 - rtnl_lock(); 3322 - wiphy_lock(mvm->hw->wiphy); 3323 - err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); 3324 - wiphy_unlock(mvm->hw->wiphy); 3325 - rtnl_unlock(); 3326 - if (err > 0) 3327 - err = -EINVAL; 3328 - if (err) 3329 - return err; 3330 - 3331 - mvm->d3_test_active = true; 3332 - mvm->keep_vif = NULL; 3333 - return 0; 3334 - } 3335 - 3336 - static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, 3337 - size_t count, loff_t *ppos) 3338 - { 3339 - struct iwl_mvm *mvm = file->private_data; 3340 - unsigned long end = jiffies + 60 * HZ; 3341 - u32 pme_asserted; 3342 - 3343 - while (true) { 3344 - /* read pme_ptr if available */ 3345 - if (mvm->d3_test_pme_ptr) { 3346 - pme_asserted = iwl_trans_read_mem32(mvm->trans, 3347 - mvm->d3_test_pme_ptr); 3348 - if (pme_asserted) 3349 - break; 3350 - } 3351 - 3352 - if (msleep_interruptible(100)) 3353 - break; 3354 - 3355 - if (time_is_before_jiffies(end)) { 3356 - IWL_ERR(mvm, 3357 - "ending pseudo-D3 with timeout after ~60 seconds\n"); 3358 - return -ETIMEDOUT; 3359 - } 3360 - } 3361 - 3362 - return 0; 3363 - } 3364 - 3365 - static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac, 3366 - struct ieee80211_vif *vif) 3367 - { 3368 - /* skip the one we keep connection on */ 3369 - if (_data == vif) 3370 - return; 3371 - 3372 - if (vif->type == NL80211_IFTYPE_STATION) 3373 - ieee80211_connection_loss(vif); 3374 - } 3375 - 3376 - static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) 3377 - { 3378 - struct iwl_mvm *mvm = inode->i_private; 3379 - bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, 3380 - IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); 3381 - 3382 - mvm->d3_test_active = false; 3383 - 3384 - iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt); 3385 - 3386 - rtnl_lock(); 3387 - wiphy_lock(mvm->hw->wiphy); 3388 - __iwl_mvm_resume(mvm, true); 3389 - wiphy_unlock(mvm->hw->wiphy); 3390 - rtnl_unlock(); 3391 - 3392 - iwl_mvm_resume_tcm(mvm); 3393 - 3394 - iwl_fw_runtime_resume(&mvm->fwrt); 3395 - 3396 - iwl_abort_notification_waits(&mvm->notif_wait); 3397 - if (!unified_image) { 3398 - int remaining_time = 10; 3399 - 3400 - ieee80211_restart_hw(mvm->hw); 3401 - 3402 - /* wait for restart and disconnect all interfaces */ 3403 - while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && 3404 - remaining_time > 0) { 3405 - remaining_time--; 3406 - msleep(1000); 3407 - } 3408 - 3409 - if (remaining_time == 0) 3410 - IWL_ERR(mvm, "Timed out waiting for HW restart!\n"); 3411 - } 3412 - 3413 - ieee80211_iterate_active_interfaces_atomic( 3414 - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 3415 - iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif); 3416 - 3417 - return 0; 3418 - } 3419 - 3420 - const struct file_operations iwl_dbgfs_d3_test_ops = { 3421 - .open = iwl_mvm_d3_test_open, 3422 - .read = iwl_mvm_d3_test_read, 3423 - .release = iwl_mvm_d3_test_release, 3424 - }; 3425 - #endif
-94
drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
··· 762 762 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 763 763 } 764 764 765 - static ssize_t iwl_dbgfs_int_mlo_scan_write(struct ieee80211_vif *vif, 766 - char *buf, size_t count, 767 - loff_t *ppos) 768 - { 769 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 770 - struct iwl_mvm *mvm = mvmvif->mvm; 771 - u32 action; 772 - int ret; 773 - 774 - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif)) 775 - return -EINVAL; 776 - 777 - if (kstrtou32(buf, 0, &action)) 778 - return -EINVAL; 779 - 780 - mutex_lock(&mvm->mutex); 781 - 782 - if (!action) { 783 - ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false); 784 - } else if (action == 1) { 785 - ret = iwl_mvm_int_mlo_scan(mvm, vif); 786 - } else { 787 - ret = -EINVAL; 788 - } 789 - 790 - mutex_unlock(&mvm->mutex); 791 - 792 - return ret ?: count; 793 - } 794 - 795 - static ssize_t iwl_dbgfs_esr_disable_reason_read(struct file *file, 796 - char __user *user_buf, 797 - size_t count, loff_t *ppos) 798 - { 799 - struct ieee80211_vif *vif = file->private_data; 800 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 801 - struct iwl_mvm *mvm = mvmvif->mvm; 802 - unsigned long esr_mask; 803 - char *buf; 804 - int bufsz, pos, i; 805 - ssize_t rv; 806 - 807 - mutex_lock(&mvm->mutex); 808 - esr_mask = mvmvif->esr_disable_reason; 809 - mutex_unlock(&mvm->mutex); 810 - 811 - bufsz = hweight32(esr_mask) * 32 + 40; 812 - buf = kmalloc(bufsz, GFP_KERNEL); 813 - if (!buf) 814 - return -ENOMEM; 815 - 816 - pos = scnprintf(buf, bufsz, "EMLSR state: '0x%lx'\nreasons:\n", 817 - esr_mask); 818 - for_each_set_bit(i, &esr_mask, BITS_PER_LONG) 819 - pos += scnprintf(buf + pos, bufsz - pos, " - %s\n", 820 - iwl_get_esr_state_string(BIT(i))); 821 - 822 - rv = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 823 - kfree(buf); 824 - return rv; 825 - } 826 - 827 - static ssize_t iwl_dbgfs_esr_disable_reason_write(struct ieee80211_vif *vif, 828 - char *buf, size_t count, 829 - loff_t *ppos) 830 - { 831 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 832 - struct iwl_mvm *mvm = mvmvif->mvm; 833 - u32 reason; 834 - u8 block; 835 - int ret; 836 - 837 - ret = sscanf(buf, "%u %hhu", &reason, &block); 838 - if (ret < 0) 839 - return ret; 840 - 841 - if (hweight16(reason) != 1 || !(reason & IWL_MVM_BLOCK_ESR_REASONS)) 842 - return -EINVAL; 843 - 844 - mutex_lock(&mvm->mutex); 845 - if (block) 846 - iwl_mvm_block_esr(mvm, vif, reason, 847 - iwl_mvm_get_primary_link(vif)); 848 - else 849 - iwl_mvm_unblock_esr(mvm, vif, reason); 850 - mutex_unlock(&mvm->mutex); 851 - 852 - return count; 853 - } 854 - 855 765 #define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \ 856 766 _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif) 857 767 #define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \ ··· 794 884 MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32); 795 885 MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff); 796 886 MVM_DEBUGFS_READ_WRITE_FILE_OPS(max_tx_op, 10); 797 - MVM_DEBUGFS_WRITE_FILE_OPS(int_mlo_scan, 32); 798 - MVM_DEBUGFS_READ_WRITE_FILE_OPS(esr_disable_reason, 32); 799 887 800 888 void iwl_mvm_vif_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 801 889 { ··· 824 916 MVM_DEBUGFS_ADD_FILE_VIF(max_tx_op, mvmvif->dbgfs_dir, 0600); 825 917 debugfs_create_bool("ftm_unprotected", 0200, mvmvif->dbgfs_dir, 826 918 &mvmvif->ftm_unprotected); 827 - MVM_DEBUGFS_ADD_FILE_VIF(int_mlo_scan, mvmvif->dbgfs_dir, 0200); 828 - MVM_DEBUGFS_ADD_FILE_VIF(esr_disable_reason, mvmvif->dbgfs_dir, 0600); 829 919 830 920 if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && 831 921 mvmvif == mvm->bf_allowed_vif)
+1 -2
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
··· 1134 1134 1135 1135 if (count == 6 && !strcmp(buf, "nolog\n")) { 1136 1136 set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status); 1137 - iwl_trans_suppress_cmd_error_once(mvm->trans); 1137 + mvm->trans->suppress_cmd_error_once = true; 1138 1138 } 1139 1139 1140 1140 /* take the return value to make compiler happy - it will fail anyway */ ··· 2159 2159 MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR); 2160 2160 2161 2161 #ifdef CONFIG_PM_SLEEP 2162 - MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400); 2163 2162 debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir, 2164 2163 &mvm->d3_wake_sysassert); 2165 2164 debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
··· 837 837 .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), 838 838 }; 839 839 840 - if (!mvm->trans->ltr_enabled) 840 + if (!iwl_trans_is_ltr_enabled(mvm->trans)) 841 841 return 0; 842 842 843 843 return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
-809
drivers/net/wireless/intel/iwlwifi/mvm/link.c
··· 5 5 #include "mvm.h" 6 6 #include "time-event.h" 7 7 8 - #define HANDLE_ESR_REASONS(HOW) \ 9 - HOW(BLOCKED_PREVENTION) \ 10 - HOW(BLOCKED_WOWLAN) \ 11 - HOW(BLOCKED_TPT) \ 12 - HOW(BLOCKED_FW) \ 13 - HOW(BLOCKED_NON_BSS) \ 14 - HOW(BLOCKED_ROC) \ 15 - HOW(BLOCKED_TMP_NON_BSS) \ 16 - HOW(EXIT_MISSED_BEACON) \ 17 - HOW(EXIT_LOW_RSSI) \ 18 - HOW(EXIT_COEX) \ 19 - HOW(EXIT_BANDWIDTH) \ 20 - HOW(EXIT_CSA) \ 21 - HOW(EXIT_LINK_USAGE) 22 - 23 - static const char *const iwl_mvm_esr_states_names[] = { 24 - #define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x, 25 - HANDLE_ESR_REASONS(NAME_ENTRY) 26 - }; 27 - 28 - const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state) 29 - { 30 - int offs = ilog2(state); 31 - 32 - if (offs >= ARRAY_SIZE(iwl_mvm_esr_states_names) || 33 - !iwl_mvm_esr_states_names[offs]) 34 - return "UNKNOWN"; 35 - 36 - return iwl_mvm_esr_states_names[offs]; 37 - } 38 - 39 - static void iwl_mvm_print_esr_state(struct iwl_mvm *mvm, u32 mask) 40 - { 41 - #define NAME_FMT(x) "%s" 42 - #define NAME_PR(x) (mask & IWL_MVM_ESR_##x) ? "[" #x "]" : "", 43 - IWL_DEBUG_INFO(mvm, 44 - "EMLSR state = " HANDLE_ESR_REASONS(NAME_FMT) 45 - " (0x%x)\n", 46 - HANDLE_ESR_REASONS(NAME_PR) 47 - mask); 48 - #undef NAME_FMT 49 - #undef NAME_PR 50 - } 51 - 52 8 static int iwl_mvm_link_cmd_send(struct iwl_mvm *mvm, 53 9 struct iwl_link_config_cmd *cmd, 54 10 enum iwl_ctxt_action action) ··· 68 112 cmd.listen_lmac = cpu_to_le32(link_info->listen_lmac); 69 113 70 114 return iwl_mvm_link_cmd_send(mvm, &cmd, FW_CTXT_ACTION_ADD); 71 - } 72 - 73 - struct iwl_mvm_esr_iter_data { 74 - struct ieee80211_vif *vif; 75 - unsigned int link_id; 76 - bool lift_block; 77 - }; 78 - 79 - static void iwl_mvm_esr_vif_iterator(void *_data, u8 *mac, 80 - struct ieee80211_vif *vif) 81 - { 82 - struct iwl_mvm_esr_iter_data *data = _data; 83 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 84 - int link_id; 85 - 86 - if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION) 87 - return; 88 - 89 - for_each_mvm_vif_valid_link(mvmvif, link_id) { 90 - struct iwl_mvm_vif_link_info *link_info = 91 - mvmvif->link[link_id]; 92 - if (vif == data->vif && link_id == data->link_id) 93 - continue; 94 - if (link_info->active) 95 - data->lift_block = false; 96 - } 97 - } 98 - 99 - int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 100 - unsigned int link_id, bool active) 101 - { 102 - /* An active link of a non-station vif blocks EMLSR. Upon activation 103 - * block EMLSR on the bss vif. Upon deactivation, check if this link 104 - * was the last non-station link active, and if so unblock the bss vif 105 - */ 106 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 107 - struct iwl_mvm_esr_iter_data data = { 108 - .vif = vif, 109 - .link_id = link_id, 110 - .lift_block = true, 111 - }; 112 - 113 - if (IS_ERR_OR_NULL(bss_vif)) 114 - return 0; 115 - 116 - if (active) 117 - return iwl_mvm_block_esr_sync(mvm, bss_vif, 118 - IWL_MVM_ESR_BLOCKED_NON_BSS); 119 - 120 - ieee80211_iterate_active_interfaces(mvm->hw, 121 - IEEE80211_IFACE_ITER_NORMAL, 122 - iwl_mvm_esr_vif_iterator, &data); 123 - if (data.lift_block) { 124 - mutex_lock(&mvm->mutex); 125 - iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_NON_BSS); 126 - mutex_unlock(&mvm->mutex); 127 - } 128 - 129 - return 0; 130 115 } 131 116 132 117 int iwl_mvm_link_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ··· 285 388 return ret; 286 389 } 287 390 288 - struct iwl_mvm_rssi_to_grade { 289 - s8 rssi[2]; 290 - u16 grade; 291 - }; 292 - 293 - #define RSSI_TO_GRADE_LINE(_lb, _hb_uhb, _grade) \ 294 - { \ 295 - .rssi = {_lb, _hb_uhb}, \ 296 - .grade = _grade \ 297 - } 298 - 299 - /* 300 - * This array must be sorted by increasing RSSI for proper functionality. 301 - * The grades are actually estimated throughput, represented as fixed-point 302 - * with a scale factor of 1/10. 303 - */ 304 - static const struct iwl_mvm_rssi_to_grade rssi_to_grade_map[] = { 305 - RSSI_TO_GRADE_LINE(-85, -89, 177), 306 - RSSI_TO_GRADE_LINE(-83, -86, 344), 307 - RSSI_TO_GRADE_LINE(-82, -85, 516), 308 - RSSI_TO_GRADE_LINE(-80, -83, 688), 309 - RSSI_TO_GRADE_LINE(-77, -79, 1032), 310 - RSSI_TO_GRADE_LINE(-73, -76, 1376), 311 - RSSI_TO_GRADE_LINE(-70, -74, 1548), 312 - RSSI_TO_GRADE_LINE(-69, -72, 1750), 313 - RSSI_TO_GRADE_LINE(-65, -68, 2064), 314 - RSSI_TO_GRADE_LINE(-61, -66, 2294), 315 - RSSI_TO_GRADE_LINE(-58, -61, 2580), 316 - RSSI_TO_GRADE_LINE(-55, -58, 2868), 317 - RSSI_TO_GRADE_LINE(-46, -55, 3098), 318 - RSSI_TO_GRADE_LINE(-43, -54, 3442) 319 - }; 320 - 321 - #define MAX_GRADE (rssi_to_grade_map[ARRAY_SIZE(rssi_to_grade_map) - 1].grade) 322 - 323 - #define DEFAULT_CHAN_LOAD_LB 30 324 - #define DEFAULT_CHAN_LOAD_HB 15 325 - #define DEFAULT_CHAN_LOAD_UHB 0 326 - 327 - /* Factors calculation is done with fixed-point with a scaling factor of 1/256 */ 328 - #define SCALE_FACTOR 256 329 - 330 - /* Convert a percentage from [0,100] to [0,255] */ 331 - #define NORMALIZE_PERCENT_TO_255(percentage) ((percentage) * SCALE_FACTOR / 100) 332 - 333 - static unsigned int 334 - iwl_mvm_get_puncturing_factor(const struct ieee80211_bss_conf *link_conf) 335 - { 336 - enum nl80211_chan_width chan_width = 337 - link_conf->chanreq.oper.width; 338 - int mhz = nl80211_chan_width_to_mhz(chan_width); 339 - unsigned int n_subchannels, n_punctured, puncturing_penalty; 340 - 341 - if (WARN_ONCE(mhz < 20 || mhz > 320, 342 - "Invalid channel width : (%d)\n", mhz)) 343 - return SCALE_FACTOR; 344 - 345 - /* No puncturing, no penalty */ 346 - if (mhz < 80) 347 - return SCALE_FACTOR; 348 - 349 - /* total number of subchannels */ 350 - n_subchannels = mhz / 20; 351 - /* how many of these are punctured */ 352 - n_punctured = hweight16(link_conf->chanreq.oper.punctured); 353 - 354 - puncturing_penalty = n_punctured * SCALE_FACTOR / n_subchannels; 355 - return SCALE_FACTOR - puncturing_penalty; 356 - } 357 - 358 - static unsigned int 359 - iwl_mvm_get_chan_load(struct ieee80211_bss_conf *link_conf) 360 - { 361 - struct ieee80211_vif *vif = link_conf->vif; 362 - struct iwl_mvm_vif_link_info *mvm_link = 363 - iwl_mvm_vif_from_mac80211(link_conf->vif)->link[link_conf->link_id]; 364 - const struct element *bss_load_elem; 365 - const struct ieee80211_bss_load_elem *bss_load; 366 - enum nl80211_band band = link_conf->chanreq.oper.chan->band; 367 - const struct cfg80211_bss_ies *ies; 368 - unsigned int chan_load; 369 - u32 chan_load_by_us; 370 - 371 - rcu_read_lock(); 372 - if (ieee80211_vif_link_active(vif, link_conf->link_id)) 373 - ies = rcu_dereference(link_conf->bss->beacon_ies); 374 - else 375 - ies = rcu_dereference(link_conf->bss->ies); 376 - 377 - if (ies) 378 - bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD, 379 - ies->data, ies->len); 380 - else 381 - bss_load_elem = NULL; 382 - 383 - /* If there isn't BSS Load element, take the defaults */ 384 - if (!bss_load_elem || 385 - bss_load_elem->datalen != sizeof(*bss_load)) { 386 - rcu_read_unlock(); 387 - switch (band) { 388 - case NL80211_BAND_2GHZ: 389 - chan_load = DEFAULT_CHAN_LOAD_LB; 390 - break; 391 - case NL80211_BAND_5GHZ: 392 - chan_load = DEFAULT_CHAN_LOAD_HB; 393 - break; 394 - case NL80211_BAND_6GHZ: 395 - chan_load = DEFAULT_CHAN_LOAD_UHB; 396 - break; 397 - default: 398 - chan_load = 0; 399 - break; 400 - } 401 - /* The defaults are given in percentage */ 402 - return NORMALIZE_PERCENT_TO_255(chan_load); 403 - } 404 - 405 - bss_load = (const void *)bss_load_elem->data; 406 - /* Channel util is in range 0-255 */ 407 - chan_load = bss_load->channel_util; 408 - rcu_read_unlock(); 409 - 410 - if (!mvm_link || !mvm_link->active) 411 - return chan_load; 412 - 413 - if (WARN_ONCE(!mvm_link->phy_ctxt, 414 - "Active link (%u) without phy ctxt assigned!\n", 415 - link_conf->link_id)) 416 - return chan_load; 417 - 418 - /* channel load by us is given in percentage */ 419 - chan_load_by_us = 420 - NORMALIZE_PERCENT_TO_255(mvm_link->phy_ctxt->channel_load_by_us); 421 - 422 - /* Use only values that firmware sends that can possibly be valid */ 423 - if (chan_load_by_us <= chan_load) 424 - chan_load -= chan_load_by_us; 425 - 426 - return chan_load; 427 - } 428 - 429 - static unsigned int 430 - iwl_mvm_get_chan_load_factor(struct ieee80211_bss_conf *link_conf) 431 - { 432 - return SCALE_FACTOR - iwl_mvm_get_chan_load(link_conf); 433 - } 434 - 435 - /* This function calculates the grade of a link. Returns 0 in error case */ 436 - VISIBLE_IF_IWLWIFI_KUNIT 437 - unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf) 438 - { 439 - enum nl80211_band band; 440 - int i, rssi_idx; 441 - s32 link_rssi; 442 - unsigned int grade = MAX_GRADE; 443 - 444 - if (WARN_ON_ONCE(!link_conf)) 445 - return 0; 446 - 447 - band = link_conf->chanreq.oper.chan->band; 448 - if (WARN_ONCE(band != NL80211_BAND_2GHZ && 449 - band != NL80211_BAND_5GHZ && 450 - band != NL80211_BAND_6GHZ, 451 - "Invalid band (%u)\n", band)) 452 - return 0; 453 - 454 - link_rssi = MBM_TO_DBM(link_conf->bss->signal); 455 - /* 456 - * For 6 GHz the RSSI of the beacons is lower than 457 - * the RSSI of the data. 458 - */ 459 - if (band == NL80211_BAND_6GHZ) 460 - link_rssi += 4; 461 - 462 - rssi_idx = band == NL80211_BAND_2GHZ ? 0 : 1; 463 - 464 - /* No valid RSSI - take the lowest grade */ 465 - if (!link_rssi) 466 - link_rssi = rssi_to_grade_map[0].rssi[rssi_idx]; 467 - 468 - /* Get grade based on RSSI */ 469 - for (i = 0; i < ARRAY_SIZE(rssi_to_grade_map); i++) { 470 - const struct iwl_mvm_rssi_to_grade *line = 471 - &rssi_to_grade_map[i]; 472 - 473 - if (link_rssi > line->rssi[rssi_idx]) 474 - continue; 475 - grade = line->grade; 476 - break; 477 - } 478 - 479 - /* apply the channel load and puncturing factors */ 480 - grade = grade * iwl_mvm_get_chan_load_factor(link_conf) / SCALE_FACTOR; 481 - grade = grade * iwl_mvm_get_puncturing_factor(link_conf) / SCALE_FACTOR; 482 - return grade; 483 - } 484 - EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_get_link_grade); 485 - 486 - static 487 - u8 iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif, 488 - struct iwl_mvm_link_sel_data *data, 489 - unsigned long usable_links, 490 - u8 *best_link_idx) 491 - { 492 - u8 n_data = 0; 493 - u16 max_grade = 0; 494 - unsigned long link_id; 495 - 496 - /* TODO: don't select links that weren't discovered in the last scan */ 497 - for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 498 - struct ieee80211_bss_conf *link_conf = 499 - link_conf_dereference_protected(vif, link_id); 500 - 501 - if (WARN_ON_ONCE(!link_conf)) 502 - continue; 503 - 504 - data[n_data].link_id = link_id; 505 - data[n_data].chandef = &link_conf->chanreq.oper; 506 - data[n_data].signal = link_conf->bss->signal / 100; 507 - data[n_data].grade = iwl_mvm_get_link_grade(link_conf); 508 - 509 - if (data[n_data].grade > max_grade) { 510 - max_grade = data[n_data].grade; 511 - *best_link_idx = n_data; 512 - } 513 - n_data++; 514 - } 515 - 516 - return n_data; 517 - } 518 - 519 - struct iwl_mvm_bw_to_rssi_threshs { 520 - s8 low; 521 - s8 high; 522 - }; 523 - 524 - #define BW_TO_RSSI_THRESHOLDS(_bw) \ 525 - [IWL_PHY_CHANNEL_MODE ## _bw] = { \ 526 - .low = IWL_MVM_LOW_RSSI_THRESH_##_bw##MHZ, \ 527 - .high = IWL_MVM_HIGH_RSSI_THRESH_##_bw##MHZ \ 528 - } 529 - 530 - s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, 531 - const struct cfg80211_chan_def *chandef, 532 - bool low) 533 - { 534 - const struct iwl_mvm_bw_to_rssi_threshs bw_to_rssi_threshs_map[] = { 535 - BW_TO_RSSI_THRESHOLDS(20), 536 - BW_TO_RSSI_THRESHOLDS(40), 537 - BW_TO_RSSI_THRESHOLDS(80), 538 - BW_TO_RSSI_THRESHOLDS(160) 539 - /* 320 MHz has the same thresholds as 20 MHz */ 540 - }; 541 - const struct iwl_mvm_bw_to_rssi_threshs *threshs; 542 - u8 chan_width = iwl_mvm_get_channel_width(chandef); 543 - 544 - if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ && 545 - chandef->chan->band != NL80211_BAND_5GHZ && 546 - chandef->chan->band != NL80211_BAND_6GHZ)) 547 - return S8_MAX; 548 - 549 - /* 6 GHz will always use 20 MHz thresholds, regardless of the BW */ 550 - if (chan_width == IWL_PHY_CHANNEL_MODE320) 551 - chan_width = IWL_PHY_CHANNEL_MODE20; 552 - 553 - threshs = &bw_to_rssi_threshs_map[chan_width]; 554 - 555 - return low ? threshs->low : threshs->high; 556 - } 557 - 558 - static u32 559 - iwl_mvm_esr_disallowed_with_link(struct iwl_mvm *mvm, 560 - struct ieee80211_vif *vif, 561 - const struct iwl_mvm_link_sel_data *link, 562 - bool primary) 563 - { 564 - struct wiphy *wiphy = mvm->hw->wiphy; 565 - struct ieee80211_bss_conf *conf; 566 - enum iwl_mvm_esr_state ret = 0; 567 - s8 thresh; 568 - 569 - conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]); 570 - if (WARN_ON_ONCE(!conf)) 571 - return false; 572 - 573 - /* BT Coex effects eSR mode only if one of the links is on LB */ 574 - if (link->chandef->chan->band == NL80211_BAND_2GHZ && 575 - (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal, 576 - primary))) 577 - ret |= IWL_MVM_ESR_EXIT_COEX; 578 - 579 - thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef, 580 - false); 581 - 582 - if (link->signal < thresh) 583 - ret |= IWL_MVM_ESR_EXIT_LOW_RSSI; 584 - 585 - if (conf->csa_active) 586 - ret |= IWL_MVM_ESR_EXIT_CSA; 587 - 588 - if (ret) { 589 - IWL_DEBUG_INFO(mvm, 590 - "Link %d is not allowed for esr\n", 591 - link->link_id); 592 - iwl_mvm_print_esr_state(mvm, ret); 593 - } 594 - return ret; 595 - } 596 - 597 - VISIBLE_IF_IWLWIFI_KUNIT 598 - bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, 599 - const struct iwl_mvm_link_sel_data *a, 600 - const struct iwl_mvm_link_sel_data *b) 601 - { 602 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 603 - struct iwl_mvm *mvm = mvmvif->mvm; 604 - enum iwl_mvm_esr_state ret = 0; 605 - 606 - /* Per-link considerations */ 607 - if (iwl_mvm_esr_disallowed_with_link(mvm, vif, a, true) || 608 - iwl_mvm_esr_disallowed_with_link(mvm, vif, b, false)) 609 - return false; 610 - 611 - if (a->chandef->chan->band == b->chandef->chan->band || 612 - a->chandef->width != b->chandef->width) 613 - ret |= IWL_MVM_ESR_EXIT_BANDWIDTH; 614 - 615 - if (ret) { 616 - IWL_DEBUG_INFO(mvm, 617 - "Links %d and %d are not a valid pair for EMLSR\n", 618 - a->link_id, b->link_id); 619 - iwl_mvm_print_esr_state(mvm, ret); 620 - return false; 621 - } 622 - 623 - return true; 624 - 625 - } 626 - EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_mld_valid_link_pair); 627 - 628 - /* 629 - * Returns the combined eSR grade of two given links. 630 - * Returns 0 if eSR is not allowed with these 2 links. 631 - */ 632 - static 633 - unsigned int iwl_mvm_get_esr_grade(struct ieee80211_vif *vif, 634 - const struct iwl_mvm_link_sel_data *a, 635 - const struct iwl_mvm_link_sel_data *b, 636 - u8 *primary_id) 637 - { 638 - struct ieee80211_bss_conf *primary_conf; 639 - struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy; 640 - unsigned int primary_load; 641 - 642 - lockdep_assert_wiphy(wiphy); 643 - 644 - /* a is always primary, b is always secondary */ 645 - if (b->grade > a->grade) 646 - swap(a, b); 647 - 648 - *primary_id = a->link_id; 649 - 650 - if (!iwl_mvm_mld_valid_link_pair(vif, a, b)) 651 - return 0; 652 - 653 - primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]); 654 - 655 - if (WARN_ON_ONCE(!primary_conf)) 656 - return 0; 657 - 658 - primary_load = iwl_mvm_get_chan_load(primary_conf); 659 - 660 - return a->grade + 661 - ((b->grade * primary_load) / SCALE_FACTOR); 662 - } 663 - 664 - void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 665 - { 666 - struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS]; 667 - struct iwl_mvm_link_sel_data *best_link; 668 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 669 - u32 max_active_links = iwl_mvm_max_active_links(mvm, vif); 670 - u16 usable_links = ieee80211_vif_usable_links(vif); 671 - u8 best, primary_link, best_in_pair, n_data; 672 - u16 max_esr_grade = 0, new_active_links; 673 - 674 - lockdep_assert_wiphy(mvm->hw->wiphy); 675 - 676 - if (!mvmvif->authorized || !ieee80211_vif_is_mld(vif)) 677 - return; 678 - 679 - if (!IWL_MVM_AUTO_EML_ENABLE) 680 - return; 681 - 682 - /* The logic below is a simple version that doesn't suit more than 2 683 - * links 684 - */ 685 - WARN_ON_ONCE(max_active_links > 2); 686 - 687 - n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links, 688 - &best); 689 - 690 - if (WARN(!n_data, "Couldn't find a valid grade for any link!\n")) 691 - return; 692 - 693 - best_link = &data[best]; 694 - primary_link = best_link->link_id; 695 - new_active_links = BIT(best_link->link_id); 696 - 697 - /* eSR is not supported/blocked, or only one usable link */ 698 - if (max_active_links == 1 || !iwl_mvm_vif_has_esr_cap(mvm, vif) || 699 - mvmvif->esr_disable_reason || n_data == 1) 700 - goto set_active; 701 - 702 - for (u8 a = 0; a < n_data; a++) 703 - for (u8 b = a + 1; b < n_data; b++) { 704 - u16 esr_grade = iwl_mvm_get_esr_grade(vif, &data[a], 705 - &data[b], 706 - &best_in_pair); 707 - 708 - if (esr_grade <= max_esr_grade) 709 - continue; 710 - 711 - max_esr_grade = esr_grade; 712 - primary_link = best_in_pair; 713 - new_active_links = BIT(data[a].link_id) | 714 - BIT(data[b].link_id); 715 - } 716 - 717 - /* No valid pair was found, go with the best link */ 718 - if (hweight16(new_active_links) <= 1) 719 - goto set_active; 720 - 721 - /* For equal grade - prefer EMLSR */ 722 - if (best_link->grade > max_esr_grade) { 723 - primary_link = best_link->link_id; 724 - new_active_links = BIT(best_link->link_id); 725 - } 726 - set_active: 727 - IWL_DEBUG_INFO(mvm, "Link selection result: 0x%x. Primary = %d\n", 728 - new_active_links, primary_link); 729 - ieee80211_set_active_links_async(vif, new_active_links); 730 - mvmvif->link_selection_res = new_active_links; 731 - mvmvif->link_selection_primary = primary_link; 732 - } 733 - 734 391 u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif) 735 392 { 736 393 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ··· 305 854 return mvmvif->primary_link; 306 855 307 856 return __ffs(vif->active_links); 308 - } 309 - 310 - /* 311 - * For non-MLO/single link, this will return the deflink/single active link, 312 - * respectively 313 - */ 314 - u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id) 315 - { 316 - switch (hweight16(vif->active_links)) { 317 - case 0: 318 - return 0; 319 - default: 320 - WARN_ON(1); 321 - fallthrough; 322 - case 1: 323 - return __ffs(vif->active_links); 324 - case 2: 325 - return __ffs(vif->active_links & ~BIT(link_id)); 326 - } 327 - } 328 - 329 - /* Reasons that can cause esr prevention */ 330 - #define IWL_MVM_ESR_PREVENT_REASONS IWL_MVM_ESR_EXIT_MISSED_BEACON 331 - #define IWL_MVM_PREVENT_ESR_TIMEOUT (HZ * 400) 332 - #define IWL_MVM_ESR_PREVENT_SHORT (HZ * 300) 333 - #define IWL_MVM_ESR_PREVENT_LONG (HZ * 600) 334 - 335 - static bool iwl_mvm_check_esr_prevention(struct iwl_mvm *mvm, 336 - struct iwl_mvm_vif *mvmvif, 337 - enum iwl_mvm_esr_state reason) 338 - { 339 - bool timeout_expired = time_after(jiffies, 340 - mvmvif->last_esr_exit.ts + 341 - IWL_MVM_PREVENT_ESR_TIMEOUT); 342 - unsigned long delay; 343 - 344 - lockdep_assert_held(&mvm->mutex); 345 - 346 - /* Only handle reasons that can cause prevention */ 347 - if (!(reason & IWL_MVM_ESR_PREVENT_REASONS)) 348 - return false; 349 - 350 - /* 351 - * Reset the counter if more than 400 seconds have passed between one 352 - * exit and the other, or if we exited due to a different reason. 353 - * Will also reset the counter after the long prevention is done. 354 - */ 355 - if (timeout_expired || mvmvif->last_esr_exit.reason != reason) { 356 - mvmvif->exit_same_reason_count = 1; 357 - return false; 358 - } 359 - 360 - mvmvif->exit_same_reason_count++; 361 - if (WARN_ON(mvmvif->exit_same_reason_count < 2 || 362 - mvmvif->exit_same_reason_count > 3)) 363 - return false; 364 - 365 - mvmvif->esr_disable_reason |= IWL_MVM_ESR_BLOCKED_PREVENTION; 366 - 367 - /* 368 - * For the second exit, use a short prevention, and for the third one, 369 - * use a long prevention. 370 - */ 371 - delay = mvmvif->exit_same_reason_count == 2 ? 372 - IWL_MVM_ESR_PREVENT_SHORT : 373 - IWL_MVM_ESR_PREVENT_LONG; 374 - 375 - IWL_DEBUG_INFO(mvm, 376 - "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n", 377 - delay / HZ, mvmvif->exit_same_reason_count, 378 - iwl_get_esr_state_string(reason), reason); 379 - 380 - wiphy_delayed_work_queue(mvm->hw->wiphy, 381 - &mvmvif->prevent_esr_done_wk, delay); 382 - return true; 383 - } 384 - 385 - #define IWL_MVM_TRIGGER_LINK_SEL_TIME (IWL_MVM_TRIGGER_LINK_SEL_TIME_SEC * HZ) 386 - 387 - /* API to exit eSR mode */ 388 - void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 389 - enum iwl_mvm_esr_state reason, 390 - u8 link_to_keep) 391 - { 392 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 393 - u16 new_active_links; 394 - bool prevented; 395 - 396 - lockdep_assert_held(&mvm->mutex); 397 - 398 - if (!IWL_MVM_AUTO_EML_ENABLE) 399 - return; 400 - 401 - /* Nothing to do */ 402 - if (!mvmvif->esr_active) 403 - return; 404 - 405 - if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized)) 406 - return; 407 - 408 - if (WARN_ON(!(vif->active_links & BIT(link_to_keep)))) 409 - link_to_keep = __ffs(vif->active_links); 410 - 411 - new_active_links = BIT(link_to_keep); 412 - IWL_DEBUG_INFO(mvm, 413 - "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n", 414 - iwl_get_esr_state_string(reason), reason, 415 - vif->active_links, new_active_links); 416 - 417 - ieee80211_set_active_links_async(vif, new_active_links); 418 - 419 - /* Prevent EMLSR if needed */ 420 - prevented = iwl_mvm_check_esr_prevention(mvm, mvmvif, reason); 421 - 422 - /* Remember why and when we exited EMLSR */ 423 - mvmvif->last_esr_exit.ts = jiffies; 424 - mvmvif->last_esr_exit.reason = reason; 425 - 426 - /* 427 - * If EMLSR is prevented now - don't try to get back to EMLSR. 428 - * If we exited due to a blocking event, we will try to get back to 429 - * EMLSR when the corresponding unblocking event will happen. 430 - */ 431 - if (prevented || reason & IWL_MVM_BLOCK_ESR_REASONS) 432 - return; 433 - 434 - /* If EMLSR is not blocked - try enabling it again in 30 seconds */ 435 - wiphy_delayed_work_queue(mvm->hw->wiphy, 436 - &mvmvif->mlo_int_scan_wk, 437 - round_jiffies_relative(IWL_MVM_TRIGGER_LINK_SEL_TIME)); 438 - } 439 - 440 - void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 441 - enum iwl_mvm_esr_state reason, 442 - u8 link_to_keep) 443 - { 444 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 445 - 446 - lockdep_assert_held(&mvm->mutex); 447 - 448 - if (!IWL_MVM_AUTO_EML_ENABLE) 449 - return; 450 - 451 - /* This should be called only with disable reasons */ 452 - if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 453 - return; 454 - 455 - if (mvmvif->esr_disable_reason & reason) 456 - return; 457 - 458 - IWL_DEBUG_INFO(mvm, 459 - "Blocking EMLSR mode. reason = %s (0x%x)\n", 460 - iwl_get_esr_state_string(reason), reason); 461 - 462 - mvmvif->esr_disable_reason |= reason; 463 - 464 - iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); 465 - 466 - iwl_mvm_exit_esr(mvm, vif, reason, link_to_keep); 467 - } 468 - 469 - int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 470 - enum iwl_mvm_esr_state reason) 471 - { 472 - int primary_link = iwl_mvm_get_primary_link(vif); 473 - int ret; 474 - 475 - if (!IWL_MVM_AUTO_EML_ENABLE || !ieee80211_vif_is_mld(vif)) 476 - return 0; 477 - 478 - /* This should be called only with blocking reasons */ 479 - if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 480 - return 0; 481 - 482 - /* leave ESR immediately, not only async with iwl_mvm_block_esr() */ 483 - ret = ieee80211_set_active_links(vif, BIT(primary_link)); 484 - if (ret) 485 - return ret; 486 - 487 - mutex_lock(&mvm->mutex); 488 - /* only additionally block for consistency and to avoid concurrency */ 489 - iwl_mvm_block_esr(mvm, vif, reason, primary_link); 490 - mutex_unlock(&mvm->mutex); 491 - 492 - return 0; 493 - } 494 - 495 - static void iwl_mvm_esr_unblocked(struct iwl_mvm *mvm, 496 - struct ieee80211_vif *vif) 497 - { 498 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 499 - bool need_new_sel = time_after(jiffies, mvmvif->last_esr_exit.ts + 500 - IWL_MVM_TRIGGER_LINK_SEL_TIME); 501 - 502 - lockdep_assert_held(&mvm->mutex); 503 - 504 - if (!ieee80211_vif_is_mld(vif) || !mvmvif->authorized || 505 - mvmvif->esr_active) 506 - return; 507 - 508 - IWL_DEBUG_INFO(mvm, "EMLSR is unblocked\n"); 509 - 510 - /* If we exited due to an EXIT reason, and the exit was in less than 511 - * 30 seconds, then a MLO scan was scheduled already. 512 - */ 513 - if (!need_new_sel && 514 - !(mvmvif->last_esr_exit.reason & IWL_MVM_BLOCK_ESR_REASONS)) { 515 - IWL_DEBUG_INFO(mvm, "Wait for MLO scan\n"); 516 - return; 517 - } 518 - 519 - /* 520 - * If EMLSR was blocked for more than 30 seconds, or the last link 521 - * selection decided to not enter EMLSR, trigger a new scan. 522 - */ 523 - if (need_new_sel || hweight16(mvmvif->link_selection_res) < 2) { 524 - IWL_DEBUG_INFO(mvm, "Trigger MLO scan\n"); 525 - wiphy_delayed_work_queue(mvm->hw->wiphy, 526 - &mvmvif->mlo_int_scan_wk, 0); 527 - /* 528 - * If EMLSR was blocked for less than 30 seconds, and the last link 529 - * selection decided to use EMLSR, activate EMLSR using the previous 530 - * link selection result. 531 - */ 532 - } else { 533 - IWL_DEBUG_INFO(mvm, 534 - "Use the latest link selection result: 0x%x\n", 535 - mvmvif->link_selection_res); 536 - ieee80211_set_active_links_async(vif, 537 - mvmvif->link_selection_res); 538 - } 539 - } 540 - 541 - void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 542 - enum iwl_mvm_esr_state reason) 543 - { 544 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 545 - 546 - lockdep_assert_held(&mvm->mutex); 547 - 548 - if (!IWL_MVM_AUTO_EML_ENABLE) 549 - return; 550 - 551 - /* This should be called only with disable reasons */ 552 - if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS))) 553 - return; 554 - 555 - /* No Change */ 556 - if (!(mvmvif->esr_disable_reason & reason)) 557 - return; 558 - 559 - mvmvif->esr_disable_reason &= ~reason; 560 - 561 - IWL_DEBUG_INFO(mvm, 562 - "Unblocking EMLSR mode. reason = %s (0x%x)\n", 563 - iwl_get_esr_state_string(reason), reason); 564 - iwl_mvm_print_esr_state(mvm, mvmvif->esr_disable_reason); 565 - 566 - if (!mvmvif->esr_disable_reason) 567 - iwl_mvm_esr_unblocked(mvm, vif); 568 857 } 569 858 570 859 void iwl_mvm_init_link(struct iwl_mvm_vif_link_info *link)
-38
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
··· 1586 1586 u32 id = le32_to_cpu(mb->link_id); 1587 1587 union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; 1588 1588 u32 mac_type; 1589 - int link_id; 1590 1589 u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, 1591 1590 MISSED_BEACONS_NOTIFICATION, 1592 1591 0); 1593 1592 u8 new_notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, 1594 1593 MISSED_BEACONS_NOTIF, 0); 1595 - struct ieee80211_bss_conf *bss_conf; 1596 1594 1597 1595 /* If the firmware uses the new notification (from MAC_CONF_GROUP), 1598 1596 * refer to that notification's version. ··· 1615 1617 if (!vif) 1616 1618 return; 1617 1619 1618 - bss_conf = &vif->bss_conf; 1619 - link_id = bss_conf->link_id; 1620 1620 mac_type = iwl_mvm_get_mac_type(vif); 1621 1621 1622 1622 IWL_DEBUG_INFO(mvm, "missed beacon mac_type=%u,\n", mac_type); 1623 - 1624 - mvm->trans->dbg.dump_file_name_ext_valid = true; 1625 - snprintf(mvm->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, 1626 - "MacId_%d_MacType_%d", id, mac_type); 1627 1623 1628 1624 rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons); 1629 1625 rx_missed_bcon_since_rx = ··· 1636 1644 "missed_beacons:%d, missed_beacons_since_rx:%d\n", 1637 1645 rx_missed_bcon, rx_missed_bcon_since_rx); 1638 1646 } 1639 - } else if (link_id >= 0 && hweight16(vif->active_links) > 1) { 1640 - u32 bss_param_ch_cnt_link_id = 1641 - bss_conf->bss_param_ch_cnt_link_id; 1642 - u32 scnd_lnk_bcn_lost = 0; 1643 - 1644 - if (notif_ver >= 5 && 1645 - !IWL_FW_CHECK(mvm, 1646 - le32_to_cpu(mb->other_link_id) == IWL_MVM_FW_LINK_ID_INVALID, 1647 - "No data for other link id but we are in EMLSR active_links: 0x%x\n", 1648 - vif->active_links)) 1649 - scnd_lnk_bcn_lost = 1650 - le32_to_cpu(mb->consec_missed_beacons_other_link); 1651 - 1652 - /* Exit EMLSR if we lost more than 1653 - * IWL_MVM_MISSED_BEACONS_EXIT_ESR_THRESH beacons on boths links 1654 - * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH on any link. 1655 - * OR more than IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED 1656 - * and the link's bss_param_ch_count has changed. 1657 - */ 1658 - if ((rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS && 1659 - scnd_lnk_bcn_lost >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_2_LINKS) || 1660 - rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH || 1661 - (bss_param_ch_cnt_link_id != link_id && 1662 - rx_missed_bcon >= IWL_MVM_BCN_LOSS_EXIT_ESR_THRESH_BSS_PARAM_CHANGED)) 1663 - iwl_mvm_exit_esr(mvm, vif, 1664 - IWL_MVM_ESR_EXIT_MISSED_BEACON, 1665 - iwl_mvm_get_primary_link(vif)); 1666 1647 } else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) { 1667 1648 if (!iwl_mvm_has_new_tx_api(mvm)) 1668 1649 ieee80211_beacon_loss(vif); 1669 1650 else 1670 1651 ieee80211_cqm_beacon_loss_notify(vif, GFP_ATOMIC); 1671 - 1672 - /* try to switch links, no-op if we don't have MLO */ 1673 - iwl_mvm_int_mlo_scan(mvm, vif); 1674 1652 } 1675 1653 1676 1654 iwl_dbg_tlv_time_point(&mvm->fwrt,
+6 -118
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
··· 1425 1425 { 1426 1426 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1427 1427 1428 - /* Stop internal MLO scan, if running */ 1429 - mutex_lock(&mvm->mutex); 1430 - iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_INT_MLO, false); 1431 - mutex_unlock(&mvm->mutex); 1432 - 1433 - wiphy_work_cancel(mvm->hw->wiphy, &mvm->trig_link_selection_wk); 1434 1428 wiphy_work_flush(mvm->hw->wiphy, &mvm->async_handlers_wiphy_wk); 1435 1429 flush_work(&mvm->async_handlers_wk); 1436 1430 flush_work(&mvm->add_stream_wk); ··· 1709 1715 IWL_STA_MULTICAST); 1710 1716 } 1711 1717 1712 - static void iwl_mvm_prevent_esr_done_wk(struct wiphy *wiphy, 1713 - struct wiphy_work *wk) 1714 - { 1715 - struct iwl_mvm_vif *mvmvif = 1716 - container_of(wk, struct iwl_mvm_vif, prevent_esr_done_wk.work); 1717 - struct iwl_mvm *mvm = mvmvif->mvm; 1718 - struct ieee80211_vif *vif = 1719 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1720 - 1721 - guard(mvm)(mvm); 1722 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_PREVENTION); 1723 - } 1724 - 1725 - static void iwl_mvm_mlo_int_scan_wk(struct wiphy *wiphy, struct wiphy_work *wk) 1726 - { 1727 - struct iwl_mvm_vif *mvmvif = container_of(wk, struct iwl_mvm_vif, 1728 - mlo_int_scan_wk.work); 1729 - struct ieee80211_vif *vif = 1730 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1731 - 1732 - guard(mvm)(mvmvif->mvm); 1733 - iwl_mvm_int_mlo_scan(mvmvif->mvm, vif); 1734 - } 1735 - 1736 - static void iwl_mvm_unblock_esr_tpt(struct wiphy *wiphy, struct wiphy_work *wk) 1737 - { 1738 - struct iwl_mvm_vif *mvmvif = 1739 - container_of(wk, struct iwl_mvm_vif, unblock_esr_tpt_wk); 1740 - struct iwl_mvm *mvm = mvmvif->mvm; 1741 - struct ieee80211_vif *vif = 1742 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1743 - 1744 - guard(mvm)(mvm); 1745 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT); 1746 - } 1747 - 1748 - static void iwl_mvm_unblock_esr_tmp_non_bss(struct wiphy *wiphy, 1749 - struct wiphy_work *wk) 1750 - { 1751 - struct iwl_mvm_vif *mvmvif = 1752 - container_of(wk, struct iwl_mvm_vif, 1753 - unblock_esr_tmp_non_bss_wk.work); 1754 - struct iwl_mvm *mvm = mvmvif->mvm; 1755 - struct ieee80211_vif *vif = 1756 - container_of((void *)mvmvif, struct ieee80211_vif, drv_priv); 1757 - 1758 - mutex_lock(&mvm->mutex); 1759 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TMP_NON_BSS); 1760 - mutex_unlock(&mvm->mutex); 1761 - } 1762 - 1763 1718 void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif) 1764 1719 { 1765 1720 lockdep_assert_held(&mvm->mutex); ··· 1720 1777 1721 1778 INIT_DELAYED_WORK(&mvmvif->csa_work, 1722 1779 iwl_mvm_channel_switch_disconnect_wk); 1723 - 1724 - wiphy_delayed_work_init(&mvmvif->prevent_esr_done_wk, 1725 - iwl_mvm_prevent_esr_done_wk); 1726 - 1727 - wiphy_delayed_work_init(&mvmvif->mlo_int_scan_wk, 1728 - iwl_mvm_mlo_int_scan_wk); 1729 - 1730 - wiphy_work_init(&mvmvif->unblock_esr_tpt_wk, 1731 - iwl_mvm_unblock_esr_tpt); 1732 - 1733 - wiphy_delayed_work_init(&mvmvif->unblock_esr_tmp_non_bss_wk, 1734 - iwl_mvm_unblock_esr_tmp_non_bss); 1735 1780 } 1736 1781 1737 1782 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ··· 1856 1925 */ 1857 1926 flush_work(&mvm->roc_done_wk); 1858 1927 } 1859 - 1860 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 1861 - &mvmvif->prevent_esr_done_wk); 1862 - 1863 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 1864 - &mvmvif->mlo_int_scan_wk); 1865 - 1866 - wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk); 1867 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 1868 - &mvmvif->unblock_esr_tmp_non_bss_wk); 1869 1928 1870 1929 cancel_delayed_work_sync(&mvmvif->csa_work); 1871 1930 } ··· 3929 4008 3930 4009 callbacks->mac_ctxt_changed(mvm, vif, false); 3931 4010 iwl_mvm_mei_host_associated(mvm, vif, mvm_sta); 3932 - 3933 - memset(&mvmvif->last_esr_exit, 0, 3934 - sizeof(mvmvif->last_esr_exit)); 3935 - 3936 - iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_TPT, 0); 3937 - 3938 - /* Block until FW notif will arrive */ 3939 - iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW, 0); 3940 - 3941 - /* when client is authorized (AP station marked as such), 3942 - * try to enable the best link(s). 3943 - */ 3944 - if (vif->type == NL80211_IFTYPE_STATION && 3945 - !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) 3946 - iwl_mvm_select_links(mvm, vif); 3947 4011 } 3948 4012 3949 4013 mvm_sta->authorized = true; ··· 3976 4070 3977 4071 /* disable beacon filtering */ 3978 4072 iwl_mvm_disable_beacon_filter(mvm, vif); 3979 - 3980 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 3981 - &mvmvif->prevent_esr_done_wk); 3982 - 3983 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 3984 - &mvmvif->mlo_int_scan_wk); 3985 - 3986 - wiphy_work_cancel(mvm->hw->wiphy, &mvmvif->unblock_esr_tpt_wk); 3987 - wiphy_delayed_work_cancel(mvm->hw->wiphy, 3988 - &mvmvif->unblock_esr_tmp_non_bss_wk); 3989 4073 } 3990 4074 3991 4075 return 0; ··· 4816 4920 const struct iwl_mvm_roc_ops *ops) 4817 4921 { 4818 4922 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 4819 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 4820 4923 u32 lmac_id; 4821 4924 int ret; 4822 4925 ··· 4827 4932 * the work it does can complete and we can accept new frames. 4828 4933 */ 4829 4934 flush_work(&mvm->roc_done_wk); 4830 - 4831 - if (!IS_ERR_OR_NULL(bss_vif)) { 4832 - ret = iwl_mvm_block_esr_sync(mvm, bss_vif, 4833 - IWL_MVM_ESR_BLOCKED_ROC); 4834 - if (ret) 4835 - return ret; 4836 - } 4837 4935 4838 4936 guard(mvm)(mvm); 4839 4937 ··· 5492 5604 } 5493 5605 5494 5606 #define IWL_MAX_CSA_BLOCK_TX 1500 5495 - int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm, 5496 - struct ieee80211_vif *vif, 5497 - struct ieee80211_channel_switch *chsw) 5607 + static int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm, 5608 + struct ieee80211_vif *vif, 5609 + struct ieee80211_channel_switch *chsw) 5498 5610 { 5499 5611 struct ieee80211_vif *csa_vif; 5500 5612 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); ··· 5612 5724 return ret; 5613 5725 } 5614 5726 5615 - static int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, 5616 - struct ieee80211_vif *vif, 5617 - struct ieee80211_channel_switch *chsw) 5727 + int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, 5728 + struct ieee80211_vif *vif, 5729 + struct ieee80211_channel_switch *chsw) 5618 5730 { 5619 5731 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 5620 5732
+1 -137
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
··· 340 340 { 341 341 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 342 342 343 - /* update EMLSR mode */ 344 - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) { 345 - int ret; 346 - 347 - ret = iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id, 348 - true); 349 - /* 350 - * Don't activate this link if failed to exit EMLSR in 351 - * the BSS interface 352 - */ 353 - if (ret) 354 - return ret; 355 - } 356 - 357 343 guard(mvm)(mvm); 358 344 return __iwl_mvm_mld_assign_vif_chanctx(mvm, vif, link_conf, ctx, false); 359 345 } ··· 458 472 iwl_mvm_add_link(mvm, vif, link_conf); 459 473 } 460 474 mutex_unlock(&mvm->mutex); 461 - 462 - /* update EMLSR mode */ 463 - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) 464 - iwl_mvm_esr_non_bss_link(mvm, vif, link_conf->link_id, false); 465 475 } 466 476 467 477 static void ··· 666 684 &callbacks); 667 685 } 668 686 669 - static bool iwl_mvm_esr_bw_criteria(struct iwl_mvm *mvm, 670 - struct ieee80211_vif *vif, 671 - struct ieee80211_bss_conf *link_conf) 672 - { 673 - struct ieee80211_bss_conf *other_link; 674 - int link_id; 675 - 676 - /* Exit EMLSR if links don't have equal bandwidths */ 677 - for_each_vif_active_link(vif, other_link, link_id) { 678 - if (link_id == link_conf->link_id) 679 - continue; 680 - if (link_conf->chanreq.oper.width == 681 - other_link->chanreq.oper.width) 682 - return true; 683 - } 684 - 685 - return false; 686 - } 687 - 688 687 static void 689 688 iwl_mvm_mld_link_info_changed_station(struct iwl_mvm *mvm, 690 689 struct ieee80211_vif *vif, ··· 699 736 IWL_DEBUG_MAC80211(mvm, "Associated in HE mode\n"); 700 737 link_changes |= LINK_CONTEXT_MODIFY_HE_PARAMS; 701 738 } 702 - 703 - if ((changes & BSS_CHANGED_BANDWIDTH) && 704 - ieee80211_vif_link_active(vif, link_conf->link_id) && 705 - mvmvif->esr_active && 706 - !iwl_mvm_esr_bw_criteria(mvm, vif, link_conf)) 707 - iwl_mvm_exit_esr(mvm, vif, 708 - IWL_MVM_ESR_EXIT_BANDWIDTH, 709 - iwl_mvm_get_primary_link(vif)); 710 739 711 740 /* if associated, maybe puncturing changed - we'll check later */ 712 741 if (vif->cfg.assoc) ··· 834 879 if (ret) 835 880 IWL_ERR(mvm, "failed to update power mode\n"); 836 881 } 837 - 838 - if (changes & (BSS_CHANGED_MLD_VALID_LINKS | BSS_CHANGED_MLD_TTLM) && 839 - ieee80211_vif_is_mld(vif) && mvmvif->authorized) 840 - wiphy_delayed_work_queue(mvm->hw->wiphy, 841 - &mvmvif->mlo_int_scan_wk, 0); 842 882 } 843 883 844 884 static void ··· 1189 1239 return NEG_TTLM_RES_ACCEPT; 1190 1240 } 1191 1241 1192 - static int 1193 - iwl_mvm_mld_mac_pre_channel_switch(struct ieee80211_hw *hw, 1194 - struct ieee80211_vif *vif, 1195 - struct ieee80211_channel_switch *chsw) 1196 - { 1197 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1198 - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1199 - int ret; 1200 - 1201 - mutex_lock(&mvm->mutex); 1202 - if (mvmvif->esr_active) { 1203 - u8 primary = iwl_mvm_get_primary_link(vif); 1204 - int selected; 1205 - 1206 - /* prefer primary unless quiet CSA on it */ 1207 - if (chsw->link_id == primary && chsw->block_tx) 1208 - selected = iwl_mvm_get_other_link(vif, primary); 1209 - else 1210 - selected = primary; 1211 - 1212 - /* 1213 - * remembers to tell the firmware that this link can't tx 1214 - * Note that this logic seems to be unrelated to esr, but it 1215 - * really is needed only when esr is active. When we have a 1216 - * single link, the firmware will handle all this on its own. 1217 - * In multi-link scenarios, we can learn about the CSA from 1218 - * another link and this logic is too complex for the firmware 1219 - * to track. 1220 - * Since we want to de-activate the link that got a CSA, we 1221 - * need to tell the firmware not to send any frame on that link 1222 - * as the firmware may not be aware that link is under a CSA 1223 - * with mode=1 (no Tx allowed). 1224 - */ 1225 - if (chsw->block_tx && mvmvif->link[chsw->link_id]) 1226 - mvmvif->link[chsw->link_id]->csa_block_tx = true; 1227 - 1228 - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_CSA, selected); 1229 - mutex_unlock(&mvm->mutex); 1230 - 1231 - /* 1232 - * If we've not kept the link active that's doing the CSA 1233 - * then we don't need to do anything else, just return. 1234 - */ 1235 - if (selected != chsw->link_id) 1236 - return 0; 1237 - 1238 - mutex_lock(&mvm->mutex); 1239 - } 1240 - 1241 - ret = iwl_mvm_pre_channel_switch(mvm, vif, chsw); 1242 - mutex_unlock(&mvm->mutex); 1243 - 1244 - return ret; 1245 - } 1246 - 1247 - #define IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT (5 * HZ) 1248 - 1249 - static void iwl_mvm_mld_prep_add_interface(struct ieee80211_hw *hw, 1250 - enum nl80211_iftype type) 1251 - { 1252 - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1253 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 1254 - struct iwl_mvm_vif *mvmvif; 1255 - int ret; 1256 - 1257 - IWL_DEBUG_MAC80211(mvm, "prep_add_interface: type=%u\n", 1258 - type); 1259 - 1260 - if (IS_ERR_OR_NULL(bss_vif) || 1261 - !(type == NL80211_IFTYPE_AP || 1262 - type == NL80211_IFTYPE_P2P_GO || 1263 - type == NL80211_IFTYPE_P2P_CLIENT)) 1264 - return; 1265 - 1266 - mvmvif = iwl_mvm_vif_from_mac80211(bss_vif); 1267 - ret = iwl_mvm_block_esr_sync(mvm, bss_vif, 1268 - IWL_MVM_ESR_BLOCKED_TMP_NON_BSS); 1269 - if (ret) 1270 - return; 1271 - 1272 - wiphy_delayed_work_queue(mvmvif->mvm->hw->wiphy, 1273 - &mvmvif->unblock_esr_tmp_non_bss_wk, 1274 - IWL_MVM_MLD_UNBLOCK_ESR_NON_BSS_TIMEOUT); 1275 - } 1276 - 1277 1242 const struct ieee80211_ops iwl_mvm_mld_hw_ops = { 1278 1243 .tx = iwl_mvm_mac_tx, 1279 1244 .wake_tx_queue = iwl_mvm_mac_wake_tx_queue, ··· 1242 1377 .tx_last_beacon = iwl_mvm_tx_last_beacon, 1243 1378 1244 1379 .channel_switch = iwl_mvm_channel_switch, 1245 - .pre_channel_switch = iwl_mvm_mld_mac_pre_channel_switch, 1380 + .pre_channel_switch = iwl_mvm_mac_pre_channel_switch, 1246 1381 .post_channel_switch = iwl_mvm_post_channel_switch, 1247 1382 .abort_channel_switch = iwl_mvm_abort_channel_switch, 1248 1383 .channel_switch_rx_beacon = iwl_mvm_channel_switch_rx_beacon, ··· 1283 1418 .change_sta_links = iwl_mvm_mld_change_sta_links, 1284 1419 .can_activate_links = iwl_mvm_mld_can_activate_links, 1285 1420 .can_neg_ttlm = iwl_mvm_mld_can_neg_ttlm, 1286 - .prep_add_interface = iwl_mvm_mld_prep_add_interface, 1287 1421 };
-2
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
··· 852 852 853 853 iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta, link_id); 854 854 } 855 - kfree(mvm_sta->mpdu_counters); 856 - mvm_sta->mpdu_counters = NULL; 857 855 858 856 return ret; 859 857 }
+5 -131
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
··· 348 348 }; 349 349 350 350 /** 351 - * enum iwl_mvm_esr_state - defines reasons for which the EMLSR is exited or 352 - * blocked. 353 - * The low 16 bits are used for blocking reasons, and the 16 higher bits 354 - * are used for exit reasons. 355 - * For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit 356 - * reasons - use iwl_mvm_exit_esr(). 357 - * 358 - * Note: new reasons shall be added to HANDLE_ESR_REASONS as well (for logs) 359 - * 360 - * @IWL_MVM_ESR_BLOCKED_PREVENTION: Prevent EMLSR to avoid entering and exiting 361 - * in a loop. 362 - * @IWL_MVM_ESR_BLOCKED_WOWLAN: WOWLAN is preventing the enablement of EMLSR 363 - * @IWL_MVM_ESR_BLOCKED_TPT: block EMLSR when there is not enough traffic 364 - * @IWL_MVM_ESR_BLOCKED_FW: FW didn't recommended/forced exit from EMLSR 365 - * @IWL_MVM_ESR_BLOCKED_NON_BSS: An active non-BSS interface's link is 366 - * preventing EMLSR 367 - * @IWL_MVM_ESR_BLOCKED_ROC: remain-on-channel is preventing EMLSR 368 - * @IWL_MVM_ESR_BLOCKED_TMP_NON_BSS: An expected active non-BSS interface's link 369 - * is preventing EMLSR. This is a temporary blocking that is set when there 370 - * is an indication that a non-BSS interface is to be added. 371 - * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons 372 - * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR 373 - * due to low RSSI. 374 - * @IWL_MVM_ESR_EXIT_COEX: link is deactivated/not allowed for EMLSR 375 - * due to BT Coex. 376 - * @IWL_MVM_ESR_EXIT_BANDWIDTH: Bandwidths of primary and secondry links 377 - * preventing the enablement of EMLSR 378 - * @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR 379 - * @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link 380 - */ 381 - enum iwl_mvm_esr_state { 382 - IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1, 383 - IWL_MVM_ESR_BLOCKED_WOWLAN = 0x2, 384 - IWL_MVM_ESR_BLOCKED_TPT = 0x4, 385 - IWL_MVM_ESR_BLOCKED_FW = 0x8, 386 - IWL_MVM_ESR_BLOCKED_NON_BSS = 0x10, 387 - IWL_MVM_ESR_BLOCKED_ROC = 0x20, 388 - IWL_MVM_ESR_BLOCKED_TMP_NON_BSS = 0x40, 389 - IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000, 390 - IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000, 391 - IWL_MVM_ESR_EXIT_COEX = 0x40000, 392 - IWL_MVM_ESR_EXIT_BANDWIDTH = 0x80000, 393 - IWL_MVM_ESR_EXIT_CSA = 0x100000, 394 - IWL_MVM_ESR_EXIT_LINK_USAGE = 0x200000, 395 - }; 396 - 397 - #define IWL_MVM_BLOCK_ESR_REASONS 0xffff 398 - 399 - const char *iwl_get_esr_state_string(enum iwl_mvm_esr_state state); 400 - 401 - /** 402 - * struct iwl_mvm_esr_exit - details of the last exit from EMLSR mode. 403 - * @reason: The reason for the last exit from EMLSR. 404 - * &iwl_mvm_prevent_esr_reasons. Will be 0 before exiting EMLSR. 405 - * @ts: the time stamp of the last time we existed EMLSR. 406 - */ 407 - struct iwl_mvm_esr_exit { 408 - unsigned long ts; 409 - enum iwl_mvm_esr_state reason; 410 - }; 411 - 412 - /** 413 351 * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context 414 352 * @mvm: pointer back to the mvm struct 415 353 * @id: between 0 and 3 ··· 381 443 * @deflink: default link data for use in non-MLO 382 444 * @link: link data for each link in MLO 383 445 * @esr_active: indicates eSR mode is active 384 - * @esr_disable_reason: a bitmap of &enum iwl_mvm_esr_state 385 446 * @pm_enabled: indicates powersave is enabled 386 447 * @link_selection_res: bitmap of active links as it was decided in the last 387 448 * link selection. Valid only for a MLO vif after assoc. 0 if there wasn't ··· 388 451 * @link_selection_primary: primary link selected by link selection 389 452 * @primary_link: primary link in eSR. Valid only for an associated MLD vif, 390 453 * and in eSR mode. Valid only for a STA. 391 - * @last_esr_exit: Details of the last exit from EMLSR. 392 - * @exit_same_reason_count: The number of times we exited due to the specified 393 - * @last_esr_exit::reason, only counting exits due to 394 - * &IWL_MVM_ESR_PREVENT_REASONS. 395 - * @prevent_esr_done_wk: work that should be done when esr prevention ends. 396 - * @mlo_int_scan_wk: work for the internal MLO scan. 397 - * @unblock_esr_tpt_wk: work for unblocking EMLSR when tpt is high enough. 398 - * @unblock_esr_tmp_non_bss_wk: work for removing the 399 - * IWL_MVM_ESR_BLOCKED_TMP_NON_BSS blocking for EMLSR. 400 454 * @roc_activity: currently running ROC activity for this vif (or 401 455 * ROC_NUM_ACTIVITIES if no activity is running). 402 456 * @session_prot_connection_loss: the connection was lost due to session ··· 443 515 u8 authorized:1; 444 516 bool ps_disabled; 445 517 446 - u32 esr_disable_reason; 447 518 u32 ap_beacon_time; 448 519 bool bf_enabled; 449 520 bool ba_enabled; ··· 518 591 u16 link_selection_res; 519 592 u8 link_selection_primary; 520 593 u8 primary_link; 521 - struct iwl_mvm_esr_exit last_esr_exit; 522 - u8 exit_same_reason_count; 523 - struct wiphy_delayed_work prevent_esr_done_wk; 524 - struct wiphy_delayed_work mlo_int_scan_wk; 525 - struct wiphy_work unblock_esr_tpt_wk; 526 - struct wiphy_delayed_work unblock_esr_tmp_non_bss_wk; 527 594 528 595 struct iwl_mvm_vif_link_info deflink; 529 596 struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS]; ··· 543 622 IWL_MVM_SCAN_REGULAR = BIT(0), 544 623 IWL_MVM_SCAN_SCHED = BIT(1), 545 624 IWL_MVM_SCAN_NETDETECT = BIT(2), 546 - IWL_MVM_SCAN_INT_MLO = BIT(3), 547 625 548 626 IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8), 549 627 IWL_MVM_SCAN_STOPPING_SCHED = BIT(9), ··· 555 635 IWL_MVM_SCAN_STOPPING_SCHED, 556 636 IWL_MVM_SCAN_NETDETECT_MASK = IWL_MVM_SCAN_NETDETECT | 557 637 IWL_MVM_SCAN_STOPPING_NETDETECT, 558 - IWL_MVM_SCAN_INT_MLO_MASK = IWL_MVM_SCAN_INT_MLO | 559 - IWL_MVM_SCAN_STOPPING_INT_MLO, 560 638 561 639 IWL_MVM_SCAN_STOPPING_MASK = 0xff << IWL_MVM_SCAN_STOPPING_SHIFT, 562 640 IWL_MVM_SCAN_MASK = 0xff, ··· 935 1017 /* For async rx handlers that require the wiphy lock */ 936 1018 struct wiphy_work async_handlers_wiphy_wk; 937 1019 938 - struct wiphy_work trig_link_selection_wk; 939 - 940 1020 struct work_struct roc_done_wk; 941 1021 942 1022 unsigned long init_status; ··· 1119 1203 u8 offload_tid; 1120 1204 #ifdef CONFIG_IWLWIFI_DEBUGFS 1121 1205 bool d3_wake_sysassert; 1122 - bool d3_test_active; 1123 - u32 d3_test_pme_ptr; 1124 - struct ieee80211_vif *keep_vif; 1125 1206 u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */ 1126 1207 #endif 1127 1208 #endif 1128 1209 1129 1210 wait_queue_head_t rx_sync_waitq; 1130 1211 1131 - /* BT-Coex - only one of those will be used */ 1132 - union { 1133 - struct iwl_bt_coex_prof_old_notif last_bt_notif; 1134 - struct iwl_bt_coex_profile_notif last_bt_wifi_loss; 1135 - }; 1212 + struct iwl_bt_coex_prof_old_notif last_bt_notif; 1136 1213 struct iwl_bt_coex_ci_cmd last_bt_ci_cmd; 1137 1214 1138 1215 u8 bt_tx_prio; ··· 2008 2099 int iwl_mvm_disable_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2009 2100 struct ieee80211_bss_conf *link_conf); 2010 2101 2011 - void iwl_mvm_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 2012 2102 u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif); 2013 - u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id); 2014 2103 2015 2104 struct iwl_mvm_link_sel_data { 2016 2105 u8 link_id; ··· 2018 2111 }; 2019 2112 2020 2113 #if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS) 2021 - unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf); 2022 - bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, 2023 - const struct iwl_mvm_link_sel_data *a, 2024 - const struct iwl_mvm_link_sel_data *b); 2025 - 2026 - s8 iwl_mvm_average_dbm_values(const struct iwl_umac_scan_channel_survey_notif *notif); 2027 - 2028 2114 extern const struct iwl_hcmd_arr iwl_mvm_groups[]; 2029 2115 extern const unsigned int iwl_mvm_groups_size; 2030 2116 #endif ··· 2101 2201 int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm); 2102 2202 void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm); 2103 2203 void iwl_mvm_scan_timeout_wk(struct work_struct *work); 2104 - int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 2105 2204 void iwl_mvm_rx_channel_survey_notif(struct iwl_mvm *mvm, 2106 2205 struct iwl_rx_cmd_buffer *rxb); 2107 2206 ··· 2226 2327 int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm); 2227 2328 void iwl_mvm_rx_bt_coex_old_notif(struct iwl_mvm *mvm, 2228 2329 struct iwl_rx_cmd_buffer *rxb); 2229 - void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, 2230 - struct iwl_rx_cmd_buffer *rxb); 2231 2330 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2232 2331 enum ieee80211_rssi_event_data); 2233 2332 void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm); ··· 2826 2929 int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw); 2827 2930 void iwl_mvm_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 2828 2931 struct ieee80211_channel_switch *chsw); 2829 - int iwl_mvm_pre_channel_switch(struct iwl_mvm *mvm, 2830 - struct ieee80211_vif *vif, 2831 - struct ieee80211_channel_switch *chsw); 2932 + int iwl_mvm_mac_pre_channel_switch(struct ieee80211_hw *hw, 2933 + struct ieee80211_vif *vif, 2934 + struct ieee80211_channel_switch *chsw); 2935 + 2832 2936 void iwl_mvm_abort_channel_switch(struct ieee80211_hw *hw, 2833 2937 struct ieee80211_vif *vif, 2834 2938 struct ieee80211_bss_conf *link_conf); ··· 2886 2988 2887 2989 /* EMLSR */ 2888 2990 bool iwl_mvm_vif_has_esr_cap(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 2889 - void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2890 - enum iwl_mvm_esr_state reason, 2891 - u8 link_to_keep); 2892 - int iwl_mvm_block_esr_sync(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2893 - enum iwl_mvm_esr_state reason); 2894 - void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2895 - enum iwl_mvm_esr_state reason); 2896 - void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2897 - enum iwl_mvm_esr_state reason, 2898 - u8 link_to_keep); 2899 - s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, 2900 - const struct cfg80211_chan_def *chandef, 2901 - bool low); 2902 - void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, 2903 - struct ieee80211_vif *vif, 2904 - int link_id); 2905 - bool 2906 - iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, 2907 - struct ieee80211_vif *vif, 2908 - s32 link_rssi, 2909 - bool primary); 2910 - int iwl_mvm_esr_non_bss_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 2911 - unsigned int link_id, bool active); 2912 - 2913 2991 void 2914 2992 iwl_mvm_send_ap_tx_power_constraint_cmd(struct iwl_mvm *mvm, 2915 2993 struct ieee80211_vif *vif,
-53
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
··· 143 143 ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); 144 144 } 145 145 146 - static void iwl_mvm_rx_esr_mode_notif(struct iwl_mvm *mvm, 147 - struct iwl_rx_cmd_buffer *rxb) 148 - { 149 - struct iwl_rx_packet *pkt = rxb_addr(rxb); 150 - struct iwl_esr_mode_notif *notif = (void *)pkt->data; 151 - struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm); 152 - 153 - /* FW recommendations is only for entering EMLSR */ 154 - if (IS_ERR_OR_NULL(vif) || iwl_mvm_vif_from_mac80211(vif)->esr_active) 155 - return; 156 - 157 - if (le32_to_cpu(notif->action) == ESR_RECOMMEND_ENTER) 158 - iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW); 159 - else 160 - iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_FW, 161 - iwl_mvm_get_primary_link(vif)); 162 - } 163 - 164 146 static void iwl_mvm_rx_monitor_notif(struct iwl_mvm *mvm, 165 147 struct iwl_rx_cmd_buffer *rxb) 166 148 { ··· 327 345 RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_old_notif, 328 346 RX_HANDLER_ASYNC_LOCKED_WIPHY, 329 347 struct iwl_bt_coex_prof_old_notif), 330 - RX_HANDLER_GRP(BT_COEX_GROUP, PROFILE_NOTIF, iwl_mvm_rx_bt_coex_notif, 331 - RX_HANDLER_ASYNC_LOCKED_WIPHY, 332 - struct iwl_bt_coex_profile_notif), 333 348 RX_HANDLER_NO_SIZE(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, 334 349 RX_HANDLER_ASYNC_LOCKED), 335 350 RX_HANDLER_NO_SIZE(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, ··· 435 456 iwl_mvm_channel_switch_error_notif, 436 457 RX_HANDLER_ASYNC_UNLOCKED, 437 458 struct iwl_channel_switch_error_notif), 438 - 439 - RX_HANDLER_GRP(DATA_PATH_GROUP, ESR_MODE_NOTIF, 440 - iwl_mvm_rx_esr_mode_notif, 441 - RX_HANDLER_ASYNC_LOCKED_WIPHY, 442 - struct iwl_esr_mode_notif), 443 459 444 460 RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF, 445 461 iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED, ··· 635 661 HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), 636 662 HCMD_NAME(SCD_QUEUE_CONFIG_CMD), 637 663 HCMD_NAME(SEC_KEY_CMD), 638 - HCMD_NAME(ESR_MODE_NOTIF), 639 664 HCMD_NAME(MONITOR_NOTIF), 640 665 HCMD_NAME(THERMAL_DUAL_CHAIN_REQUEST), 641 666 HCMD_NAME(BEACON_FILTER_IN_NOTIF), ··· 1193 1220 .nic_stolen = iwl_mvm_mei_nic_stolen, 1194 1221 }; 1195 1222 1196 - static void iwl_mvm_find_link_selection_vif(void *_data, u8 *mac, 1197 - struct ieee80211_vif *vif) 1198 - { 1199 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1200 - 1201 - if (ieee80211_vif_is_mld(vif) && mvmvif->authorized) 1202 - iwl_mvm_select_links(mvmvif->mvm, vif); 1203 - } 1204 - 1205 - static void iwl_mvm_trig_link_selection(struct wiphy *wiphy, 1206 - struct wiphy_work *wk) 1207 - { 1208 - struct iwl_mvm *mvm = 1209 - container_of(wk, struct iwl_mvm, trig_link_selection_wk); 1210 - 1211 - mutex_lock(&mvm->mutex); 1212 - ieee80211_iterate_active_interfaces(mvm->hw, 1213 - IEEE80211_IFACE_ITER_NORMAL, 1214 - iwl_mvm_find_link_selection_vif, 1215 - NULL); 1216 - mutex_unlock(&mvm->mutex); 1217 - } 1218 - 1219 1223 static struct iwl_op_mode * 1220 1224 iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg, 1221 1225 const struct iwl_fw *fw, struct dentry *dbgfs_dir) ··· 1360 1410 1361 1411 wiphy_work_init(&mvm->async_handlers_wiphy_wk, 1362 1412 iwl_mvm_async_handlers_wiphy_wk); 1363 - 1364 - wiphy_work_init(&mvm->trig_link_selection_wk, 1365 - iwl_mvm_trig_link_selection); 1366 1413 1367 1414 init_waitqueue_head(&mvm->rx_sync_waitq); 1368 1415
-133
drivers/net/wireless/intel/iwlwifi/mvm/rx.c
··· 563 563 int thold = bss_conf->cqm_rssi_thold; 564 564 int hyst = bss_conf->cqm_rssi_hyst; 565 565 int last_event; 566 - s8 exit_esr_thresh; 567 566 568 567 if (sig == 0) { 569 568 IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n"); ··· 618 619 sig, 619 620 GFP_KERNEL); 620 621 } 621 - 622 - /* ESR recalculation */ 623 - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif)) 624 - return; 625 - 626 - /* We're not in EMLSR and our signal is bad, try to switch link maybe */ 627 - if (sig < IWL_MVM_LOW_RSSI_MLO_SCAN_THRESH && !mvmvif->esr_active) { 628 - iwl_mvm_int_mlo_scan(mvm, vif); 629 - return; 630 - } 631 - 632 - /* We are in EMLSR, check if we need to exit */ 633 - exit_esr_thresh = 634 - iwl_mvm_get_esr_rssi_thresh(mvm, 635 - &bss_conf->chanreq.oper, 636 - true); 637 - 638 - if (sig < exit_esr_thresh) 639 - iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_LOW_RSSI, 640 - iwl_mvm_get_other_link(vif, 641 - bss_conf->link_id)); 642 622 } 643 623 644 624 static void iwl_mvm_stat_iterator(void *_data, u8 *mac, ··· 892 914 link_info->beacon_stats.avg_signal = 893 915 -le32_to_cpu(link_stats->beacon_average_energy); 894 916 895 - if (link_info->phy_ctxt && 896 - link_info->phy_ctxt->channel->band == NL80211_BAND_2GHZ) 897 - iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id); 898 - 899 917 /* make sure that beacon statistics don't go backwards with TCM 900 918 * request to clear statistics 901 919 */ ··· 930 956 } 931 957 } 932 958 933 - #define SEC_LINK_MIN_PERC 10 934 - #define SEC_LINK_MIN_TX 3000 935 - #define SEC_LINK_MIN_RX 400 936 - 937 - /* Accept a ~20% short window to avoid issues due to jitter */ 938 - #define IWL_MVM_TPT_MIN_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ * 4 / 5) 939 - 940 - static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm) 941 - { 942 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 943 - struct iwl_mvm_vif *mvmvif; 944 - struct iwl_mvm_sta *mvmsta; 945 - unsigned long total_tx = 0, total_rx = 0; 946 - unsigned long sec_link_tx = 0, sec_link_rx = 0; 947 - u8 sec_link_tx_perc, sec_link_rx_perc; 948 - u8 sec_link; 949 - bool skip = false; 950 - 951 - lockdep_assert_held(&mvm->mutex); 952 - 953 - if (IS_ERR_OR_NULL(bss_vif)) 954 - return; 955 - 956 - mvmvif = iwl_mvm_vif_from_mac80211(bss_vif); 957 - 958 - if (!mvmvif->esr_active || !mvmvif->ap_sta) 959 - return; 960 - 961 - mvmsta = iwl_mvm_sta_from_mac80211(mvmvif->ap_sta); 962 - /* We only count for the AP sta in a MLO connection */ 963 - if (!mvmsta->mpdu_counters) 964 - return; 965 - 966 - /* Get the FW ID of the secondary link */ 967 - sec_link = iwl_mvm_get_other_link(bss_vif, 968 - iwl_mvm_get_primary_link(bss_vif)); 969 - if (WARN_ON(!mvmvif->link[sec_link])) 970 - return; 971 - sec_link = mvmvif->link[sec_link]->fw_link_id; 972 - 973 - /* Sum up RX and TX MPDUs from the different queues/links */ 974 - for (int q = 0; q < mvm->trans->info.num_rxqs; q++) { 975 - spin_lock_bh(&mvmsta->mpdu_counters[q].lock); 976 - 977 - /* The link IDs that doesn't exist will contain 0 */ 978 - for (int link = 0; link < IWL_FW_MAX_LINK_ID; link++) { 979 - total_tx += mvmsta->mpdu_counters[q].per_link[link].tx; 980 - total_rx += mvmsta->mpdu_counters[q].per_link[link].rx; 981 - } 982 - 983 - sec_link_tx += mvmsta->mpdu_counters[q].per_link[sec_link].tx; 984 - sec_link_rx += mvmsta->mpdu_counters[q].per_link[sec_link].rx; 985 - 986 - /* 987 - * In EMLSR we have statistics every 5 seconds, so we can reset 988 - * the counters upon every statistics notification. 989 - * The FW sends the notification regularly, but it will be 990 - * misaligned at the start. Skipping the measurement if it is 991 - * short will synchronize us. 992 - */ 993 - if (jiffies - mvmsta->mpdu_counters[q].window_start < 994 - IWL_MVM_TPT_MIN_COUNT_WINDOW) 995 - skip = true; 996 - mvmsta->mpdu_counters[q].window_start = jiffies; 997 - memset(mvmsta->mpdu_counters[q].per_link, 0, 998 - sizeof(mvmsta->mpdu_counters[q].per_link)); 999 - 1000 - spin_unlock_bh(&mvmsta->mpdu_counters[q].lock); 1001 - } 1002 - 1003 - if (skip) { 1004 - IWL_DEBUG_INFO(mvm, "MPDU statistics window was short\n"); 1005 - return; 1006 - } 1007 - 1008 - IWL_DEBUG_INFO(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n", 1009 - total_tx, total_rx); 1010 - 1011 - /* If we don't have enough MPDUs - exit EMLSR */ 1012 - if (total_tx < IWL_MVM_ENTER_ESR_TPT_THRESH && 1013 - total_rx < IWL_MVM_ENTER_ESR_TPT_THRESH) { 1014 - iwl_mvm_block_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_TPT, 1015 - iwl_mvm_get_primary_link(bss_vif)); 1016 - return; 1017 - } 1018 - 1019 - IWL_DEBUG_INFO(mvm, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n", 1020 - sec_link, sec_link_tx, sec_link_rx); 1021 - 1022 - /* Calculate the percentage of the secondary link TX/RX */ 1023 - sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0; 1024 - sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0; 1025 - 1026 - /* 1027 - * The TX/RX percentage is checked only if it exceeds the required 1028 - * minimum. In addition, RX is checked only if the TX check failed. 1029 - */ 1030 - if ((total_tx > SEC_LINK_MIN_TX && 1031 - sec_link_tx_perc < SEC_LINK_MIN_PERC) || 1032 - (total_rx > SEC_LINK_MIN_RX && 1033 - sec_link_rx_perc < SEC_LINK_MIN_PERC)) 1034 - iwl_mvm_exit_esr(mvm, bss_vif, IWL_MVM_ESR_EXIT_LINK_USAGE, 1035 - iwl_mvm_get_primary_link(bss_vif)); 1036 - } 1037 - 1038 959 void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm, 1039 960 struct iwl_rx_cmd_buffer *rxb) 1040 961 { ··· 957 1088 ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter, 958 1089 average_energy); 959 1090 iwl_mvm_handle_per_phy_stats(mvm, stats->per_phy); 960 - 961 - iwl_mvm_update_esr_mode_tpt(mvm); 962 1091 } 963 1092 964 1093 void iwl_mvm_handle_rx_system_oper_part1_stats(struct iwl_mvm *mvm,
+10 -13
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
··· 332 332 struct ieee80211_key_conf *key; 333 333 u32 len = le16_to_cpu(desc->mpdu_len); 334 334 const u8 *frame = (void *)hdr; 335 + const u8 *mmie; 335 336 336 337 if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE) 337 338 return 0; ··· 376 375 goto report; 377 376 } 378 377 379 - if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2) 378 + if (len < key->icv_len) 380 379 goto report; 381 380 382 381 /* get the real key ID */ 383 - keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2]; 382 + mmie = frame + (len - key->icv_len); 383 + 384 + /* the position of the key_id in ieee80211_mmie_16 is the same */ 385 + keyid = le16_to_cpu(((const struct ieee80211_mmie *) mmie)->key_id); 386 + 384 387 /* and if that's the other key, look it up */ 385 388 if (keyid != key->keyidx) { 386 389 /* ··· 2104 2099 struct ieee80211_sta *sta = NULL; 2105 2100 struct sk_buff *skb; 2106 2101 u8 crypt_len = 0; 2107 - u8 sta_id = le32_get_bits(desc->status, IWL_RX_MPDU_STATUS_STA_ID); 2108 2102 size_t desc_size; 2109 2103 struct iwl_mvm_rx_phy_data phy_data = {}; 2110 2104 u32 format; ··· 2250 2246 rcu_read_lock(); 2251 2247 2252 2248 if (desc->status & cpu_to_le32(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) { 2249 + u8 sta_id = le32_get_bits(desc->status, 2250 + IWL_RX_MPDU_STATUS_STA_ID); 2251 + 2253 2252 if (!WARN_ON_ONCE(sta_id >= mvm->fw->ucode_capa.num_stations)) { 2254 2253 struct ieee80211_link_sta *link_sta; 2255 2254 ··· 2379 2372 u32 reorder_data = le32_to_cpu(desc->reorder_data); 2380 2373 2381 2374 iwl_mvm_agg_rx_received(mvm, reorder_data, baid); 2382 - } 2383 - 2384 - if (ieee80211_is_data(hdr->frame_control)) { 2385 - u8 sub_frame_idx = desc->amsdu_info & 2386 - IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK; 2387 - 2388 - /* 0 means not an A-MSDU, and 1 means a new A-MSDU */ 2389 - if (!sub_frame_idx || sub_frame_idx == 1) 2390 - iwl_mvm_count_mpdu(mvmsta, sta_id, 1, false, 2391 - queue); 2392 2375 } 2393 2376 } 2394 2377
-101
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
··· 1392 1392 { 1393 1393 if (type == IWL_MVM_SCAN_REGULAR) 1394 1394 return IWL_SCAN_PRIORITY_EXT_6; 1395 - if (type == IWL_MVM_SCAN_INT_MLO) 1396 - return IWL_SCAN_PRIORITY_EXT_4; 1397 1395 1398 1396 return IWL_SCAN_PRIORITY_EXT_2; 1399 1397 } ··· 3218 3220 struct iwl_umac_scan_complete *notif = (void *)pkt->data; 3219 3221 u32 uid = __le32_to_cpu(notif->uid); 3220 3222 bool aborted = (notif->status == IWL_SCAN_OFFLOAD_ABORTED); 3221 - bool select_links = false; 3222 3223 3223 3224 mvm->mei_scan_filter.is_mei_limited_scan = false; 3224 3225 ··· 3264 3267 } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { 3265 3268 ieee80211_sched_scan_stopped(mvm->hw); 3266 3269 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 3267 - } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_INT_MLO) { 3268 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan completed\n"); 3269 - /* 3270 - * Other scan types won't necessarily scan for the MLD links channels. 3271 - * Therefore, only select links after successful internal scan. 3272 - */ 3273 - select_links = notif->status == IWL_SCAN_OFFLOAD_COMPLETED; 3274 3270 } 3275 3271 3276 3272 mvm->scan_status &= ~mvm->scan_uid_status[uid]; ··· 3276 3286 mvm->last_ebs_successful = false; 3277 3287 3278 3288 mvm->scan_uid_status[uid] = 0; 3279 - 3280 - if (select_links) 3281 - wiphy_work_queue(mvm->hw->wiphy, &mvm->trig_link_selection_wk); 3282 3289 } 3283 3290 3284 3291 void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, ··· 3470 3483 mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED; 3471 3484 mvm->scan_uid_status[uid] = 0; 3472 3485 } 3473 - uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_INT_MLO); 3474 - if (uid >= 0) { 3475 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan aborted\n"); 3476 - mvm->scan_uid_status[uid] = 0; 3477 - } 3478 3486 3479 3487 uid = iwl_mvm_scan_uid_by_status(mvm, 3480 3488 IWL_MVM_SCAN_STOPPING_REGULAR); ··· 3563 3581 } 3564 3582 3565 3583 return ret; 3566 - } 3567 - 3568 - static int iwl_mvm_int_mlo_scan_start(struct iwl_mvm *mvm, 3569 - struct ieee80211_vif *vif, 3570 - struct ieee80211_channel **channels, 3571 - size_t n_channels) 3572 - { 3573 - struct cfg80211_scan_request *req = NULL; 3574 - struct ieee80211_scan_ies ies = {}; 3575 - size_t size, i; 3576 - int ret; 3577 - 3578 - lockdep_assert_held(&mvm->mutex); 3579 - 3580 - IWL_DEBUG_SCAN(mvm, "Starting Internal MLO scan: n_channels=%zu\n", 3581 - n_channels); 3582 - 3583 - if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif) || 3584 - hweight16(vif->valid_links) == 1) 3585 - return -EINVAL; 3586 - 3587 - size = struct_size(req, channels, n_channels); 3588 - req = kzalloc(size, GFP_KERNEL); 3589 - if (!req) 3590 - return -ENOMEM; 3591 - 3592 - /* set the requested channels */ 3593 - for (i = 0; i < n_channels; i++) 3594 - req->channels[i] = channels[i]; 3595 - 3596 - req->n_channels = n_channels; 3597 - 3598 - /* set the rates */ 3599 - for (i = 0; i < NUM_NL80211_BANDS; i++) 3600 - if (mvm->hw->wiphy->bands[i]) 3601 - req->rates[i] = 3602 - (1 << mvm->hw->wiphy->bands[i]->n_bitrates) - 1; 3603 - 3604 - req->wdev = ieee80211_vif_to_wdev(vif); 3605 - req->wiphy = mvm->hw->wiphy; 3606 - req->scan_start = jiffies; 3607 - req->tsf_report_link_id = -1; 3608 - 3609 - ret = _iwl_mvm_single_scan_start(mvm, vif, req, &ies, 3610 - IWL_MVM_SCAN_INT_MLO); 3611 - kfree(req); 3612 - 3613 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan: ret=%d\n", ret); 3614 - return ret; 3615 - } 3616 - 3617 - int iwl_mvm_int_mlo_scan(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 3618 - { 3619 - struct ieee80211_channel *channels[IEEE80211_MLD_MAX_NUM_LINKS]; 3620 - unsigned long usable_links = ieee80211_vif_usable_links(vif); 3621 - size_t n_channels = 0; 3622 - u8 link_id; 3623 - 3624 - lockdep_assert_held(&mvm->mutex); 3625 - 3626 - if (mvm->scan_status & IWL_MVM_SCAN_INT_MLO) { 3627 - IWL_DEBUG_SCAN(mvm, "Internal MLO scan is already running\n"); 3628 - return -EBUSY; 3629 - } 3630 - 3631 - rcu_read_lock(); 3632 - 3633 - for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { 3634 - struct ieee80211_bss_conf *link_conf = 3635 - rcu_dereference(vif->link_conf[link_id]); 3636 - 3637 - if (WARN_ON_ONCE(!link_conf)) 3638 - continue; 3639 - 3640 - channels[n_channels++] = link_conf->chanreq.oper.chan; 3641 - } 3642 - 3643 - rcu_read_unlock(); 3644 - 3645 - if (!n_channels) 3646 - return -EINVAL; 3647 - 3648 - return iwl_mvm_int_mlo_scan_start(mvm, vif, channels, n_channels); 3649 3584 } 3650 3585 3651 3586 static int iwl_mvm_chanidx_from_phy(struct iwl_mvm *mvm,
-89
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
··· 1835 1835 1836 1836 iwl_mvm_toggle_tx_ant(mvm, &mvm_sta->tx_ant); 1837 1837 1838 - /* MPDUs are counted only when EMLSR is possible */ 1839 - if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && 1840 - !sta->tdls && ieee80211_vif_is_mld(vif)) { 1841 - mvm_sta->mpdu_counters = 1842 - kcalloc(mvm->trans->info.num_rxqs, 1843 - sizeof(*mvm_sta->mpdu_counters), 1844 - GFP_KERNEL); 1845 - if (mvm_sta->mpdu_counters) 1846 - for (int q = 0; q < mvm->trans->info.num_rxqs; q++) 1847 - spin_lock_init(&mvm_sta->mpdu_counters[q].lock); 1848 - } 1849 - 1850 1838 return 0; 1851 1839 } 1852 1840 ··· 4315 4327 &cancel_channel_switch_cmd); 4316 4328 if (ret) 4317 4329 IWL_ERR(mvm, "Failed to cancel the channel switch\n"); 4318 - } 4319 - 4320 - static int iwl_mvm_fw_sta_id_to_fw_link_id(struct iwl_mvm_vif *mvmvif, 4321 - u8 fw_sta_id) 4322 - { 4323 - struct ieee80211_link_sta *link_sta = 4324 - rcu_dereference(mvmvif->mvm->fw_id_to_link_sta[fw_sta_id]); 4325 - struct iwl_mvm_vif_link_info *link; 4326 - 4327 - if (WARN_ON_ONCE(!link_sta)) 4328 - return -EINVAL; 4329 - 4330 - link = mvmvif->link[link_sta->link_id]; 4331 - 4332 - if (WARN_ON_ONCE(!link)) 4333 - return -EINVAL; 4334 - 4335 - return link->fw_link_id; 4336 - } 4337 - 4338 - #define IWL_MVM_TPT_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ) 4339 - 4340 - void iwl_mvm_count_mpdu(struct iwl_mvm_sta *mvm_sta, u8 fw_sta_id, u32 count, 4341 - bool tx, int queue) 4342 - { 4343 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvm_sta->vif); 4344 - struct iwl_mvm *mvm = mvmvif->mvm; 4345 - struct iwl_mvm_tpt_counter *queue_counter; 4346 - struct iwl_mvm_mpdu_counter *link_counter; 4347 - u32 total_mpdus = 0; 4348 - int fw_link_id; 4349 - 4350 - /* Count only for a BSS sta, and only when EMLSR is possible */ 4351 - if (!mvm_sta->mpdu_counters) 4352 - return; 4353 - 4354 - /* Map sta id to link id */ 4355 - fw_link_id = iwl_mvm_fw_sta_id_to_fw_link_id(mvmvif, fw_sta_id); 4356 - if (fw_link_id < 0) 4357 - return; 4358 - 4359 - queue_counter = &mvm_sta->mpdu_counters[queue]; 4360 - link_counter = &queue_counter->per_link[fw_link_id]; 4361 - 4362 - spin_lock_bh(&queue_counter->lock); 4363 - 4364 - if (tx) 4365 - link_counter->tx += count; 4366 - else 4367 - link_counter->rx += count; 4368 - 4369 - /* 4370 - * When not in EMLSR, the window and the decision to enter EMLSR are 4371 - * handled during counting, when in EMLSR - in the statistics flow 4372 - */ 4373 - if (mvmvif->esr_active) 4374 - goto out; 4375 - 4376 - if (time_is_before_jiffies(queue_counter->window_start + 4377 - IWL_MVM_TPT_COUNT_WINDOW)) { 4378 - memset(queue_counter->per_link, 0, 4379 - sizeof(queue_counter->per_link)); 4380 - queue_counter->window_start = jiffies; 4381 - 4382 - IWL_DEBUG_INFO(mvm, "MPDU counters are cleared\n"); 4383 - } 4384 - 4385 - for (int i = 0; i < IWL_FW_MAX_LINK_ID; i++) 4386 - total_mpdus += tx ? queue_counter->per_link[i].tx : 4387 - queue_counter->per_link[i].rx; 4388 - 4389 - if (total_mpdus > IWL_MVM_ENTER_ESR_TPT_THRESH) 4390 - wiphy_work_queue(mvmvif->mvm->hw->wiphy, 4391 - &mvmvif->unblock_esr_tpt_wk); 4392 - 4393 - out: 4394 - spin_unlock_bh(&queue_counter->lock); 4395 4330 }
-24
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
··· 344 344 u8 avg_energy; 345 345 }; 346 346 347 - struct iwl_mvm_mpdu_counter { 348 - u32 tx; 349 - u32 rx; 350 - }; 351 - 352 - /** 353 - * struct iwl_mvm_tpt_counter - per-queue MPDU counter 354 - * 355 - * @lock: Needed to protect the counters when modified from statistics. 356 - * @per_link: per-link counters. 357 - * @window_start: timestamp of the counting-window start 358 - */ 359 - struct iwl_mvm_tpt_counter { 360 - spinlock_t lock; 361 - struct iwl_mvm_mpdu_counter per_link[IWL_FW_MAX_LINK_ID]; 362 - unsigned long window_start; 363 - } ____cacheline_aligned_in_smp; 364 - 365 347 /** 366 348 * struct iwl_mvm_sta - representation of a station in the driver 367 349 * @vif: the interface the station belongs to ··· 391 409 * @link: per link sta entries. For non-MLO only link[0] holds data. For MLO, 392 410 * link[0] points to deflink and link[link_id] is allocated when new link 393 411 * sta is added. 394 - * @mpdu_counters: RX/TX MPDUs counters for each queue. 395 412 * 396 413 * When mac80211 creates a station it reserves some space (hw->sta_data_size) 397 414 * in the structure for use by driver. This structure is placed in that ··· 430 449 431 450 struct iwl_mvm_link_sta deflink; 432 451 struct iwl_mvm_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS]; 433 - 434 - struct iwl_mvm_tpt_counter *mpdu_counters; 435 452 }; 436 453 437 454 u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data); ··· 511 532 512 533 void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm, 513 534 struct iwl_rx_cmd_buffer *rxb); 514 - 515 - void iwl_mvm_count_mpdu(struct iwl_mvm_sta *mvm_sta, u8 fw_sta_id, u32 count, 516 - bool tx, int queue); 517 535 518 536 /* AMPDU */ 519 537 int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/tests/Makefile
··· 1 - iwlmvm-tests-y += module.o links.o hcmd.o 1 + iwlmvm-tests-y += module.o hcmd.o 2 2 3 3 obj-$(CONFIG_IWLWIFI_KUNIT_TESTS) += iwlmvm-tests.o
-433
drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * KUnit tests for channel helper functions 4 - * 5 - * Copyright (C) 2024 Intel Corporation 6 - */ 7 - #include <net/mac80211.h> 8 - #include "../mvm.h" 9 - #include <kunit/test.h> 10 - 11 - MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 12 - 13 - static struct wiphy wiphy = { 14 - .mtx = __MUTEX_INITIALIZER(wiphy.mtx), 15 - }; 16 - 17 - static struct ieee80211_hw hw = { 18 - .wiphy = &wiphy, 19 - }; 20 - 21 - static struct ieee80211_channel chan_5ghz = { 22 - .band = NL80211_BAND_5GHZ, 23 - }; 24 - 25 - static struct ieee80211_channel chan_6ghz = { 26 - .band = NL80211_BAND_6GHZ, 27 - }; 28 - 29 - static struct ieee80211_channel chan_2ghz = { 30 - .band = NL80211_BAND_2GHZ, 31 - }; 32 - 33 - static struct cfg80211_chan_def chandef_a = {}; 34 - 35 - static struct cfg80211_chan_def chandef_b = {}; 36 - 37 - static struct iwl_mvm_phy_ctxt ctx = {}; 38 - 39 - static struct iwl_mvm_vif_link_info mvm_link = { 40 - .phy_ctxt = &ctx, 41 - .active = true 42 - }; 43 - 44 - static struct cfg80211_bss bss = {}; 45 - 46 - static struct ieee80211_bss_conf link_conf = {.bss = &bss}; 47 - 48 - static const struct iwl_fw_cmd_version entry = { 49 - .group = LEGACY_GROUP, 50 - .cmd = BT_PROFILE_NOTIFICATION, 51 - .notif_ver = 4 52 - }; 53 - 54 - static struct iwl_fw fw = { 55 - .ucode_capa = { 56 - .n_cmd_versions = 1, 57 - .cmd_versions = &entry, 58 - }, 59 - }; 60 - 61 - static struct iwl_mvm mvm = { 62 - .hw = &hw, 63 - .fw = &fw, 64 - }; 65 - 66 - static const struct link_grading_case { 67 - const char *desc; 68 - const struct cfg80211_chan_def chandef; 69 - s32 signal; 70 - s16 channel_util; 71 - int chan_load_by_us; 72 - unsigned int grade; 73 - } link_grading_cases[] = { 74 - { 75 - .desc = "UHB, RSSI below range, no factors", 76 - .chandef = { 77 - .chan = &chan_6ghz, 78 - .width = NL80211_CHAN_WIDTH_20, 79 - }, 80 - .signal = -100, 81 - .grade = 177, 82 - }, 83 - { 84 - .desc = "LB, RSSI in range, no factors", 85 - .chandef = { 86 - .chan = &chan_2ghz, 87 - .width = NL80211_CHAN_WIDTH_20, 88 - }, 89 - .signal = -84, 90 - .grade = 344, 91 - }, 92 - { 93 - .desc = "HB, RSSI above range, no factors", 94 - .chandef = { 95 - .chan = &chan_5ghz, 96 - .width = NL80211_CHAN_WIDTH_20, 97 - }, 98 - .signal = -50, 99 - .grade = 3442, 100 - }, 101 - { 102 - .desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor", 103 - .chandef = { 104 - .chan = &chan_5ghz, 105 - .width = NL80211_CHAN_WIDTH_20, 106 - }, 107 - .signal = -66, 108 - .channel_util = 51, 109 - .grade = 1836, 110 - }, 111 - { 112 - .desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor", 113 - .chandef = { 114 - .chan = &chan_2ghz, 115 - .width = NL80211_CHAN_WIDTH_20, 116 - }, 117 - .signal = -61, 118 - .channel_util = 51, 119 - .chan_load_by_us = 10, 120 - .grade = 2061, 121 - }, 122 - { 123 - .desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor", 124 - .chandef = { 125 - .chan = &chan_6ghz, 126 - .width = NL80211_CHAN_WIDTH_20, 127 - }, 128 - .signal = -66, 129 - .channel_util = 102, 130 - .chan_load_by_us = 50, 131 - .grade = 1552, 132 - }, 133 - { .desc = "HB, 80 MHz, no channel load factor, punctured percentage 0", 134 - .chandef = { 135 - .chan = &chan_5ghz, 136 - .width = NL80211_CHAN_WIDTH_80, 137 - .punctured = 0x0000 138 - }, 139 - .signal = -72, 140 - .grade = 1750, 141 - }, 142 - { .desc = "HB, 160 MHz, no channel load factor, punctured percentage 25", 143 - .chandef = { 144 - .chan = &chan_5ghz, 145 - .width = NL80211_CHAN_WIDTH_160, 146 - .punctured = 0x3 147 - }, 148 - .signal = -72, 149 - .grade = 1312, 150 - }, 151 - { .desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)", 152 - .chandef = { 153 - .chan = &chan_6ghz, 154 - .width = NL80211_CHAN_WIDTH_320, 155 - .punctured = 0x3 156 - }, 157 - .signal = -72, 158 - .grade = 1806, 159 - }, 160 - { .desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25", 161 - .chandef = { 162 - .chan = &chan_5ghz, 163 - .width = NL80211_CHAN_WIDTH_160, 164 - .punctured = 0x3 165 - }, 166 - .channel_util = 51, 167 - .chan_load_by_us = 10, 168 - .signal = -72, 169 - .grade = 1179, 170 - }, 171 - }; 172 - 173 - KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc) 174 - 175 - static void setup_link_conf(struct kunit *test) 176 - { 177 - const struct link_grading_case *params = test->param_value; 178 - size_t vif_size = sizeof(struct ieee80211_vif) + 179 - sizeof(struct iwl_mvm_vif); 180 - struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL); 181 - struct ieee80211_bss_load_elem *bss_load; 182 - struct element *element; 183 - size_t ies_size = sizeof(struct cfg80211_bss_ies) + sizeof(*bss_load) + sizeof(element); 184 - struct cfg80211_bss_ies *ies; 185 - struct iwl_mvm_vif *mvmvif; 186 - 187 - KUNIT_ASSERT_NOT_NULL(test, vif); 188 - 189 - mvmvif = iwl_mvm_vif_from_mac80211(vif); 190 - if (params->chan_load_by_us > 0) { 191 - ctx.channel_load_by_us = params->chan_load_by_us; 192 - mvmvif->link[0] = &mvm_link; 193 - } 194 - 195 - link_conf.vif = vif; 196 - link_conf.chanreq.oper = params->chandef; 197 - bss.signal = DBM_TO_MBM(params->signal); 198 - 199 - ies = kunit_kzalloc(test, ies_size, GFP_KERNEL); 200 - KUNIT_ASSERT_NOT_NULL(test, ies); 201 - ies->len = sizeof(*bss_load) + sizeof(struct element); 202 - 203 - element = (void *)ies->data; 204 - element->datalen = sizeof(*bss_load); 205 - element->id = 11; 206 - 207 - bss_load = (void *)element->data; 208 - bss_load->channel_util = params->channel_util; 209 - 210 - rcu_assign_pointer(bss.ies, ies); 211 - rcu_assign_pointer(bss.beacon_ies, ies); 212 - } 213 - 214 - static void test_link_grading(struct kunit *test) 215 - { 216 - const struct link_grading_case *params = test->param_value; 217 - unsigned int ret; 218 - 219 - setup_link_conf(test); 220 - 221 - rcu_read_lock(); 222 - ret = iwl_mvm_get_link_grade(&link_conf); 223 - rcu_read_unlock(); 224 - 225 - KUNIT_EXPECT_EQ(test, ret, params->grade); 226 - 227 - kunit_kfree(test, link_conf.vif); 228 - RCU_INIT_POINTER(bss.ies, NULL); 229 - } 230 - 231 - static struct kunit_case link_grading_test_cases[] = { 232 - KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params), 233 - {} 234 - }; 235 - 236 - static struct kunit_suite link_grading = { 237 - .name = "iwlmvm-link-grading", 238 - .test_cases = link_grading_test_cases, 239 - }; 240 - 241 - kunit_test_suite(link_grading); 242 - 243 - static const struct valid_link_pair_case { 244 - const char *desc; 245 - bool bt; 246 - struct ieee80211_channel *chan_a; 247 - struct ieee80211_channel *chan_b; 248 - enum nl80211_chan_width cw_a; 249 - enum nl80211_chan_width cw_b; 250 - s32 sig_a; 251 - s32 sig_b; 252 - bool csa_a; 253 - bool valid; 254 - } valid_link_pair_cases[] = { 255 - { 256 - .desc = "HB + UHB, valid.", 257 - .chan_a = &chan_6ghz, 258 - .chan_b = &chan_5ghz, 259 - .valid = true, 260 - }, 261 - { 262 - .desc = "LB + HB, no BT.", 263 - .chan_a = &chan_2ghz, 264 - .chan_b = &chan_5ghz, 265 - .valid = true, 266 - }, 267 - { 268 - .desc = "LB + HB, with BT.", 269 - .bt = true, 270 - .chan_a = &chan_2ghz, 271 - .chan_b = &chan_5ghz, 272 - .valid = false, 273 - }, 274 - { 275 - .desc = "Same band", 276 - .chan_a = &chan_2ghz, 277 - .chan_b = &chan_2ghz, 278 - .valid = false, 279 - }, 280 - { 281 - .desc = "RSSI: LB, 20 MHz, low", 282 - .chan_a = &chan_2ghz, 283 - .cw_a = NL80211_CHAN_WIDTH_20, 284 - .sig_a = -68, 285 - .chan_b = &chan_5ghz, 286 - .valid = false, 287 - }, 288 - { 289 - .desc = "RSSI: UHB, 20 MHz, high", 290 - .chan_a = &chan_6ghz, 291 - .cw_a = NL80211_CHAN_WIDTH_20, 292 - .sig_a = -66, 293 - .chan_b = &chan_5ghz, 294 - .cw_b = NL80211_CHAN_WIDTH_20, 295 - .valid = true, 296 - }, 297 - { 298 - .desc = "RSSI: UHB, 40 MHz, low", 299 - .chan_a = &chan_6ghz, 300 - .cw_a = NL80211_CHAN_WIDTH_40, 301 - .sig_a = -65, 302 - .chan_b = &chan_5ghz, 303 - .cw_b = NL80211_CHAN_WIDTH_40, 304 - .valid = false, 305 - }, 306 - { 307 - .desc = "RSSI: UHB, 40 MHz, high", 308 - .chan_a = &chan_6ghz, 309 - .cw_a = NL80211_CHAN_WIDTH_40, 310 - .sig_a = -63, 311 - .chan_b = &chan_5ghz, 312 - .cw_b = NL80211_CHAN_WIDTH_40, 313 - .valid = true, 314 - }, 315 - { 316 - .desc = "RSSI: UHB, 80 MHz, low", 317 - .chan_a = &chan_6ghz, 318 - .cw_a = NL80211_CHAN_WIDTH_80, 319 - .sig_a = -62, 320 - .chan_b = &chan_5ghz, 321 - .cw_b = NL80211_CHAN_WIDTH_80, 322 - .valid = false, 323 - }, 324 - { 325 - .desc = "RSSI: UHB, 80 MHz, high", 326 - .chan_a = &chan_6ghz, 327 - .cw_a = NL80211_CHAN_WIDTH_80, 328 - .sig_a = -60, 329 - .chan_b = &chan_5ghz, 330 - .cw_b = NL80211_CHAN_WIDTH_80, 331 - .valid = true, 332 - }, 333 - { 334 - .desc = "RSSI: UHB, 160 MHz, low", 335 - .chan_a = &chan_6ghz, 336 - .cw_a = NL80211_CHAN_WIDTH_160, 337 - .sig_a = -59, 338 - .chan_b = &chan_5ghz, 339 - .cw_b = NL80211_CHAN_WIDTH_160, 340 - .valid = false, 341 - }, 342 - { 343 - .desc = "RSSI: HB, 160 MHz, high", 344 - .chan_a = &chan_6ghz, 345 - .cw_a = NL80211_CHAN_WIDTH_160, 346 - .sig_a = -5, 347 - .chan_b = &chan_5ghz, 348 - .cw_b = NL80211_CHAN_WIDTH_160, 349 - .valid = true, 350 - }, 351 - { 352 - .desc = "CSA active", 353 - .chan_a = &chan_6ghz, 354 - .cw_a = NL80211_CHAN_WIDTH_160, 355 - .sig_a = -5, 356 - .chan_b = &chan_5ghz, 357 - .cw_b = NL80211_CHAN_WIDTH_160, 358 - .valid = false, 359 - /* same as previous entry with valid=true except for CSA */ 360 - .csa_a = true, 361 - }, 362 - }; 363 - 364 - KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc) 365 - 366 - static void test_valid_link_pair(struct kunit *test) 367 - { 368 - const struct valid_link_pair_case *params = test->param_value; 369 - size_t vif_size = sizeof(struct ieee80211_vif) + 370 - sizeof(struct iwl_mvm_vif); 371 - struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL); 372 - struct iwl_trans *trans = kunit_kzalloc(test, sizeof(struct iwl_trans), 373 - GFP_KERNEL); 374 - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 375 - struct iwl_mvm_link_sel_data link_a = { 376 - .chandef = &chandef_a, 377 - .link_id = 1, 378 - .signal = params->sig_a, 379 - }; 380 - struct iwl_mvm_link_sel_data link_b = { 381 - .chandef = &chandef_b, 382 - .link_id = 5, 383 - .signal = params->sig_b, 384 - }; 385 - struct ieee80211_bss_conf *conf; 386 - bool result; 387 - 388 - KUNIT_ASSERT_NOT_NULL(test, vif); 389 - KUNIT_ASSERT_NOT_NULL(test, trans); 390 - 391 - chandef_a.chan = params->chan_a; 392 - chandef_b.chan = params->chan_b; 393 - 394 - chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20; 395 - chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20; 396 - 397 - mvm.trans = trans; 398 - 399 - mvm.last_bt_notif.wifi_loss_low_rssi = params->bt; 400 - mvmvif->mvm = &mvm; 401 - 402 - conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL); 403 - KUNIT_ASSERT_NOT_NULL(test, conf); 404 - conf->chanreq.oper = chandef_a; 405 - conf->csa_active = params->csa_a; 406 - vif->link_conf[link_a.link_id] = (void __rcu *)conf; 407 - 408 - conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL); 409 - KUNIT_ASSERT_NOT_NULL(test, conf); 410 - conf->chanreq.oper = chandef_b; 411 - vif->link_conf[link_b.link_id] = (void __rcu *)conf; 412 - 413 - wiphy_lock(&wiphy); 414 - result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b); 415 - wiphy_unlock(&wiphy); 416 - 417 - KUNIT_EXPECT_EQ(test, result, params->valid); 418 - 419 - kunit_kfree(test, vif); 420 - kunit_kfree(test, trans); 421 - } 422 - 423 - static struct kunit_case valid_link_pair_test_cases[] = { 424 - KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params), 425 - {}, 426 - }; 427 - 428 - static struct kunit_suite valid_link_pair = { 429 - .name = "iwlmvm-valid-link-pair", 430 - .test_cases = valid_link_pair_test_cases, 431 - }; 432 - 433 - kunit_test_suite(valid_link_pair);
-3
drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
··· 47 47 48 48 static void iwl_mvm_cleanup_roc(struct iwl_mvm *mvm) 49 49 { 50 - struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); 51 50 struct ieee80211_vif *vif = mvm->p2p_device_vif; 52 51 53 52 lockdep_assert_held(&mvm->mutex); ··· 124 125 iwl_mvm_rm_aux_sta(mvm); 125 126 } 126 127 127 - if (!IS_ERR_OR_NULL(bss_vif)) 128 - iwl_mvm_unblock_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_ROC); 129 128 mutex_unlock(&mvm->mutex); 130 129 } 131 130
+1 -7
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
··· 1769 1769 IWL_DEBUG_TX_REPLY(mvm, 1770 1770 "Next reclaimed packet:%d\n", 1771 1771 next_reclaimed); 1772 - if (tid < IWL_MAX_TID_COUNT) 1773 - iwl_mvm_count_mpdu(mvmsta, sta_id, 1, 1774 - true, 0); 1775 1772 } else { 1776 1773 IWL_DEBUG_TX_REPLY(mvm, 1777 1774 "NDP - don't update next_reclaimed\n"); ··· 2147 2150 ba_res->tx_rate, false); 2148 2151 } 2149 2152 2150 - if (mvmsta) { 2153 + if (mvmsta) 2151 2154 iwl_mvm_tx_airtime(mvm, mvmsta, 2152 2155 le32_to_cpu(ba_res->wireless_time)); 2153 2156 2154 - iwl_mvm_count_mpdu(mvmsta, sta_id, 2155 - le16_to_cpu(ba_res->txed), true, 0); 2156 - } 2157 2157 rcu_read_unlock(); 2158 2158 return; 2159 2159 }
-10
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
··· 22 22 { 23 23 int ret; 24 24 25 - #if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) 26 - if (WARN_ON(mvm->d3_test_active)) 27 - return -EIO; 28 - #endif 29 - 30 25 /* 31 26 * Synchronous commands from this op-mode must hold 32 27 * the mutex, this ensures we don't try to send two ··· 73 78 int ret, resp_len; 74 79 75 80 lockdep_assert_held(&mvm->mutex); 76 - 77 - #if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) 78 - if (WARN_ON(mvm->d3_test_active)) 79 - return -EIO; 80 - #endif 81 81 82 82 /* 83 83 * Only synchronous commands can wait for status,
+2 -7
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
··· 1179 1179 static void iwl_pci_remove(struct pci_dev *pdev) 1180 1180 { 1181 1181 struct iwl_trans *trans = pci_get_drvdata(pdev); 1182 - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1183 1182 1184 1183 if (!trans) 1185 1184 return; 1186 1185 1187 - cancel_delayed_work_sync(&trans_pcie->me_recheck_wk); 1188 - 1189 - iwl_drv_stop(trans->drv); 1190 - 1191 - iwl_trans_pcie_free(trans); 1186 + iwl_pcie_gen1_2_remove(trans); 1192 1187 } 1193 1188 1194 1189 #ifdef CONFIG_PM_SLEEP ··· 1255 1260 * won't really know how to recover. 1256 1261 */ 1257 1262 iwl_pcie_prepare_card_hw(trans); 1258 - iwl_finish_nic_init(trans); 1263 + iwl_trans_activate_nic(trans); 1259 1264 iwl_op_mode_device_powered_off(trans->op_mode); 1260 1265 } 1261 1266
+49 -4
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h
··· 400 400 * @me_recheck_wk: worker to recheck WiAMT/CSME presence 401 401 * @invalid_tx_cmd: invalid TX command buffer 402 402 * @wait_command_queue: wait queue for sync commands 403 + * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. 404 + * The user should use iwl_trans_{alloc,free}_tx_cmd. 405 + * @dev_cmd_pool_name: name for the TX command allocation pool 406 + * @pm_support: set to true in start_hw if link pm is supported 407 + * @ltr_enabled: set to true if the LTR is enabled 403 408 */ 404 409 struct iwl_trans_pcie { 405 410 struct iwl_rxq *rxq; ··· 511 506 struct iwl_dma_ptr invalid_tx_cmd; 512 507 513 508 wait_queue_head_t wait_command_queue; 509 + 510 + struct kmem_cache *dev_cmd_pool; 511 + char dev_cmd_pool_name[50]; 512 + 513 + bool pm_support; 514 + bool ltr_enabled; 514 515 }; 515 516 516 517 static inline struct iwl_trans_pcie * ··· 794 783 return le16_to_cpu(tb->hi_n_len) >> 4; 795 784 } 796 785 786 + static inline struct iwl_device_tx_cmd * 787 + iwl_pcie_gen1_2_alloc_tx_cmd(struct iwl_trans *trans) 788 + { 789 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 790 + 791 + return kmem_cache_zalloc(trans_pcie->dev_cmd_pool, GFP_ATOMIC); 792 + } 793 + 794 + static inline void 795 + iwl_pcie_gen1_2_free_tx_cmd(struct iwl_trans *trans, 796 + struct iwl_device_tx_cmd *dev_cmd) 797 + { 798 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 799 + 800 + kmem_cache_free(trans_pcie->dev_cmd_pool, dev_cmd); 801 + } 802 + 797 803 void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, 798 804 struct sk_buff_head *skbs, bool is_flush); 799 805 void iwl_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr); ··· 846 818 trans_pcie->fh_init_mask); 847 819 iwl_write32(trans, CSR_MSIX_HW_INT_MASK_AD, 848 820 trans_pcie->hw_init_mask); 821 + trans_pcie->fh_mask = 0; 822 + trans_pcie->hw_mask = 0; 849 823 } 850 824 IWL_DEBUG_ISR(trans, "Disabled interrupts\n"); 851 825 } ··· 1030 1000 } else { 1031 1001 iwl_write32(trans, CSR_MSIX_FH_INT_MASK_AD, 1032 1002 trans_pcie->fh_init_mask); 1003 + trans_pcie->fh_mask = 0; 1033 1004 iwl_enable_hw_int_msk_msix(trans, 1034 1005 MSIX_HW_INT_CAUSES_REG_RF_KILL); 1035 1006 } ··· 1078 1047 void iwl_pcie_rx_allocator_work(struct work_struct *data); 1079 1048 1080 1049 /* common trans ops for all generations transports */ 1081 - void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans); 1050 + void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans); 1082 1051 int _iwl_trans_pcie_start_hw(struct iwl_trans *trans); 1083 1052 int iwl_trans_pcie_start_hw(struct iwl_trans *trans); 1084 1053 void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans); ··· 1095 1064 const struct iwl_dump_sanitize_ops *sanitize_ops, 1096 1065 void *sanitize_ctx); 1097 1066 int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, 1098 - enum iwl_d3_status *status, 1099 - bool test, bool reset); 1100 - int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset); 1067 + bool reset); 1068 + int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset); 1101 1069 void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable); 1102 1070 void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans); 1103 1071 void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, ··· 1111 1081 const struct pci_device_id *ent, 1112 1082 const struct iwl_mac_cfg *mac_cfg, 1113 1083 u8 __iomem *hw_base, u32 hw_rev); 1084 + void iwl_pcie_gen1_2_remove(struct iwl_trans *trans); 1114 1085 1115 1086 /* transport gen 1 exported functions */ 1116 1087 void iwl_trans_pcie_fw_alive(struct iwl_trans *trans); ··· 1136 1105 struct iwl_dma_ptr *ptr, size_t size); 1137 1106 void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr); 1138 1107 void iwl_pcie_apply_destination(struct iwl_trans *trans); 1108 + int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans); 1139 1109 1140 1110 /* transport gen 2 exported functions */ 1141 1111 int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, ··· 1156 1124 int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue, 1157 1125 struct iwl_trans_rxq_dma_data *data); 1158 1126 1127 + static inline bool iwl_pcie_gen1_is_pm_supported(struct iwl_trans *trans) 1128 + { 1129 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1130 + 1131 + return trans_pcie->pm_support; 1132 + } 1133 + 1134 + static inline bool iwl_pcie_gen1_2_is_ltr_enabled(struct iwl_trans *trans) 1135 + { 1136 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1137 + 1138 + return trans_pcie->ltr_enabled; 1139 + } 1159 1140 #endif /* __iwl_trans_int_pcie_h__ */
+1 -1
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c
··· 47 47 48 48 iwl_pcie_apm_config(trans); 49 49 50 - ret = iwl_finish_nic_init(trans); 50 + ret = iwl_trans_activate_nic(trans); 51 51 if (ret) 52 52 return ret; 53 53
+161 -76
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
··· 25 25 #include "fw/dbg.h" 26 26 #include "fw/api/tx.h" 27 27 #include "fw/acpi.h" 28 - #include "fw/api/tx.h" 29 28 #include "mei/iwl-mei.h" 30 29 #include "internal.h" 31 30 #include "iwl-fh.h" 32 31 #include "pcie/iwl-context-info-v2.h" 33 32 #include "pcie/utils.h" 33 + 34 + #define IWL_HOST_MON_BLOCK_PEMON 0x00 35 + #define IWL_HOST_MON_BLOCK_HIPM 0x22 36 + 37 + #define IWL_HOST_MON_BLOCK_PEMON_VEC0 0x00 38 + #define IWL_HOST_MON_BLOCK_PEMON_VEC1 0x01 39 + #define IWL_HOST_MON_BLOCK_PEMON_WFPM 0x06 40 + 41 + static void iwl_dump_host_monitor_block(struct iwl_trans *trans, 42 + u32 block, u32 vec, u32 iter) 43 + { 44 + int i; 45 + 46 + IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec); 47 + iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec); 48 + for (i = 0; i < iter; i++) 49 + IWL_ERR(trans, " value [iter %d]: 0x%08x\n", 50 + i, iwl_read32(trans, CSR_MONITOR_STATUS_REG)); 51 + } 52 + 53 + static void iwl_pcie_dump_host_monitor(struct iwl_trans *trans) 54 + { 55 + switch (trans->mac_cfg->device_family) { 56 + case IWL_DEVICE_FAMILY_22000: 57 + case IWL_DEVICE_FAMILY_AX210: 58 + IWL_ERR(trans, "CSR_RESET = 0x%x\n", 59 + iwl_read32(trans, CSR_RESET)); 60 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 61 + IWL_HOST_MON_BLOCK_PEMON_VEC0, 15); 62 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 63 + IWL_HOST_MON_BLOCK_PEMON_VEC1, 15); 64 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON, 65 + IWL_HOST_MON_BLOCK_PEMON_WFPM, 15); 66 + iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM, 67 + IWL_HOST_MON_BLOCK_PEMON_VEC0, 1); 68 + break; 69 + default: 70 + return; 71 + } 72 + } 34 73 35 74 /* extended range in FW SRAM */ 36 75 #define IWL_FW_MEM_EXTENDED_START 0x40000 ··· 214 175 iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_DISABLED); 215 176 216 177 pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); 217 - trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); 178 + trans_pcie->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); 218 179 219 180 pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap); 220 - trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN; 181 + trans_pcie->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN; 221 182 IWL_DEBUG_POWER(trans, "L1 %sabled - LTR %sabled\n", 222 183 (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis", 223 - trans->ltr_enabled ? "En" : "Dis"); 184 + trans_pcie->ltr_enabled ? "En" : "Dis"); 224 185 } 225 186 226 187 /* ··· 267 228 if (trans->mac_cfg->base->pll_cfg) 268 229 iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); 269 230 270 - ret = iwl_finish_nic_init(trans); 231 + ret = iwl_trans_activate_nic(trans); 271 232 if (ret) 272 233 return ret; 273 234 ··· 340 301 ret = iwl_trans_pcie_sw_reset(trans, true); 341 302 342 303 if (!ret) 343 - ret = iwl_finish_nic_init(trans); 304 + ret = iwl_trans_activate_nic(trans); 344 305 345 306 if (WARN_ON(ret)) { 346 307 /* Release XTAL ON request */ ··· 1436 1397 } 1437 1398 1438 1399 static void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans, 1439 - bool test, bool reset) 1400 + bool reset) 1440 1401 { 1441 1402 iwl_disable_interrupts(trans); 1442 - 1443 - /* 1444 - * in testing mode, the host stays awake and the 1445 - * hardware won't be reset (not even partially) 1446 - */ 1447 - if (test) 1448 - return; 1449 1403 1450 1404 iwl_pcie_disable_ict(trans); 1451 1405 ··· 1510 1478 return ret; 1511 1479 } 1512 1480 1513 - int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, bool reset) 1481 + int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool reset) 1514 1482 { 1515 1483 int ret; 1516 1484 ··· 1523 1491 if (ret) 1524 1492 return ret; 1525 1493 1526 - iwl_pcie_d3_complete_suspend(trans, test, reset); 1494 + iwl_pcie_d3_complete_suspend(trans, reset); 1527 1495 1528 1496 return 0; 1529 1497 } 1530 1498 1531 1499 int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, 1532 - enum iwl_d3_status *status, 1533 - bool test, bool reset) 1500 + bool reset) 1534 1501 { 1535 1502 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1536 1503 u32 val; 1537 1504 int ret; 1538 - 1539 - if (test) { 1540 - iwl_enable_interrupts(trans); 1541 - *status = IWL_D3_STATUS_ALIVE; 1542 - ret = 0; 1543 - goto out; 1544 - } 1545 1505 1546 1506 if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) 1547 1507 iwl_set_bit(trans, CSR_GP_CNTRL, ··· 1542 1518 iwl_set_bit(trans, CSR_GP_CNTRL, 1543 1519 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1544 1520 1545 - ret = iwl_finish_nic_init(trans); 1546 - if (ret) 1521 + ret = iwl_trans_activate_nic(trans); 1522 + if (ret) { 1523 + IWL_ERR(trans, "Failed to init nic upon resume. err = %d\n", 1524 + ret); 1547 1525 return ret; 1526 + } 1548 1527 1549 1528 /* 1550 1529 * Reconfigure IVAR table in case of MSIX or reset ict table in ··· 1581 1554 iwl_read_umac_prph(trans, WFPM_GP2)); 1582 1555 1583 1556 val = iwl_read32(trans, CSR_RESET); 1584 - if (val & CSR_RESET_REG_FLAG_NEVO_RESET) 1585 - *status = IWL_D3_STATUS_RESET; 1586 - else 1587 - *status = IWL_D3_STATUS_ALIVE; 1588 - 1589 - out: 1590 - if (*status == IWL_D3_STATUS_ALIVE) 1591 - ret = iwl_pcie_d3_handshake(trans, false); 1592 - else 1557 + if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { 1558 + IWL_INFO(trans, "Device was reset during suspend\n"); 1593 1559 trans->state = IWL_TRANS_NO_FW; 1560 + return -ENOENT; 1561 + } 1594 1562 1595 - return ret; 1563 + return iwl_pcie_d3_handshake(trans, false); 1596 1564 } 1597 1565 1598 1566 static void ··· 1766 1744 { 1767 1745 int ret; 1768 1746 1769 - ret = iwl_finish_nic_init(trans); 1747 + ret = iwl_trans_activate_nic(trans); 1770 1748 if (ret < 0) 1771 1749 return ret; 1772 1750 ··· 1904 1882 iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); 1905 1883 } 1906 1884 1907 - void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans) 1885 + void iwl_pcie_gen1_2_op_mode_enter(struct iwl_trans *trans) 1908 1886 { 1909 1887 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1910 1888 ··· 2022 2000 free_percpu(trans_pcie->txqs.tso_hdr_page); 2023 2001 } 2024 2002 2003 + kmem_cache_destroy(trans_pcie->dev_cmd_pool); 2025 2004 iwl_trans_free(trans); 2026 2005 } 2027 2006 ··· 3539 3516 struct iwl_trans_dump_data *dump_data; 3540 3517 u32 len, num_rbs = 0, monitor_len = 0; 3541 3518 int i, ptr; 3542 - bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && 3519 + bool dump_rbs = iwl_trans_is_fw_error(trans) && 3543 3520 !trans->mac_cfg->mq_rx_supported && 3544 3521 dump_mask & BIT(IWL_FW_ERROR_DUMP_RB); 3545 3522 ··· 3707 3684 iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit); 3708 3685 } 3709 3686 3710 - static int iwl_trans_pcie_set_txcmd_info(const struct iwl_mac_cfg *mac_cfg, 3711 - unsigned int *txcmd_size, 3712 - unsigned int *txcmd_align) 3687 + static int iwl_trans_pcie_alloc_txcmd_pool(struct iwl_trans *trans) 3713 3688 { 3714 - if (!mac_cfg->gen2) { 3715 - *txcmd_size = sizeof(struct iwl_tx_cmd_v6); 3716 - *txcmd_align = sizeof(void *); 3717 - } else if (mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { 3718 - *txcmd_size = sizeof(struct iwl_tx_cmd_v9); 3719 - *txcmd_align = 64; 3689 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 3690 + unsigned int txcmd_size, txcmd_align; 3691 + 3692 + if (!trans->mac_cfg->gen2) { 3693 + txcmd_size = sizeof(struct iwl_tx_cmd_v6); 3694 + txcmd_align = sizeof(void *); 3695 + } else if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { 3696 + txcmd_size = sizeof(struct iwl_tx_cmd_v9); 3697 + txcmd_align = 64; 3720 3698 } else { 3721 - *txcmd_size = sizeof(struct iwl_tx_cmd); 3722 - *txcmd_align = 128; 3699 + txcmd_size = sizeof(struct iwl_tx_cmd); 3700 + txcmd_align = 128; 3723 3701 } 3724 3702 3725 - *txcmd_size += sizeof(struct iwl_cmd_header); 3726 - *txcmd_size += 36; /* biggest possible 802.11 header */ 3703 + txcmd_size += sizeof(struct iwl_cmd_header); 3704 + txcmd_size += 36; /* biggest possible 802.11 header */ 3727 3705 3728 3706 /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ 3729 - if (WARN_ON((mac_cfg->gen2 && *txcmd_size >= *txcmd_align))) 3707 + if (WARN_ON((trans->mac_cfg->gen2 && txcmd_size >= txcmd_align))) 3730 3708 return -EINVAL; 3709 + 3710 + snprintf(trans_pcie->dev_cmd_pool_name, 3711 + sizeof(trans_pcie->dev_cmd_pool_name), 3712 + "iwl_cmd_pool:%s", dev_name(trans->dev)); 3713 + 3714 + trans_pcie->dev_cmd_pool = 3715 + kmem_cache_create(trans_pcie->dev_cmd_pool_name, 3716 + txcmd_size, txcmd_align, 3717 + SLAB_HWCACHE_ALIGN, NULL); 3718 + if (!trans_pcie->dev_cmd_pool) 3719 + return -ENOMEM; 3731 3720 3732 3721 return 0; 3733 3722 } ··· 3750 3715 struct iwl_trans_info *info, u8 __iomem *hw_base) 3751 3716 { 3752 3717 struct iwl_trans_pcie *trans_pcie, **priv; 3753 - unsigned int txcmd_size, txcmd_align; 3754 3718 struct iwl_trans *trans; 3755 3719 unsigned int bc_tbl_n_entries; 3756 3720 int ret, addr_size; 3757 3721 3758 - ret = iwl_trans_pcie_set_txcmd_info(mac_cfg, &txcmd_size, 3759 - &txcmd_align); 3760 - if (ret) 3761 - return ERR_PTR(ret); 3762 - 3763 3722 trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, 3764 - mac_cfg, txcmd_size, txcmd_align); 3723 + mac_cfg); 3765 3724 if (!trans) 3766 3725 return ERR_PTR(-ENOMEM); 3767 3726 ··· 3765 3736 3766 3737 /* Initialize the wait queue for commands */ 3767 3738 init_waitqueue_head(&trans_pcie->wait_command_queue); 3739 + 3740 + ret = iwl_trans_pcie_alloc_txcmd_pool(trans); 3741 + if (ret) 3742 + goto out_free_trans; 3768 3743 3769 3744 if (trans->mac_cfg->gen2) { 3770 3745 trans_pcie->txqs.tfd.addr_size = 64; ··· 3789 3756 trans_pcie->txqs.tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); 3790 3757 if (!trans_pcie->txqs.tso_hdr_page) { 3791 3758 ret = -ENOMEM; 3792 - goto out_free_trans; 3759 + goto out_free_txcmd_pool; 3793 3760 } 3794 3761 3795 3762 if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) ··· 3939 3906 free_netdev(trans_pcie->napi_dev); 3940 3907 out_free_tso: 3941 3908 free_percpu(trans_pcie->txqs.tso_hdr_page); 3909 + out_free_txcmd_pool: 3910 + kmem_cache_destroy(trans_pcie->dev_cmd_pool); 3942 3911 out_free_trans: 3943 3912 iwl_trans_free(trans); 3944 3913 return ERR_PTR(ret); ··· 4034 3999 4035 4000 /* Read cdb info (also contains the jacket info if needed in the future */ 4036 4001 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, WFPM_OTP_CFG1_ADDR); 4002 + 4037 4003 IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n", 4038 4004 info->hw_crf_id, info->hw_cnv_id, hw_wfpm_id); 4039 4005 } ··· 4050 4014 u32 val = info->hw_crf_id; 4051 4015 u32 step_id = REG_CRF_ID_STEP(val); 4052 4016 u32 slave_id = REG_CRF_ID_SLAVE(val); 4053 - u32 jacket_id_cnv = REG_CRF_ID_SLAVE(info->hw_cnv_id); 4054 4017 u32 hw_wfpm_id = iwl_read_umac_prph_no_grab(iwl_trans, 4055 4018 WFPM_OTP_CFG1_ADDR); 4056 - u32 jacket_id_wfpm = WFPM_OTP_CFG1_IS_JACKET(hw_wfpm_id); 4057 4019 u32 cdb_id_wfpm = WFPM_OTP_CFG1_IS_CDB(hw_wfpm_id); 4058 4020 4059 4021 /* Map between crf id to rf id */ ··· 4100 4066 IWL_INFO(iwl_trans, "Adding cdb to rf id\n"); 4101 4067 } 4102 4068 4103 - /* Set Jacket capabilities */ 4104 - if (jacket_id_wfpm || jacket_id_cnv) { 4105 - info->hw_rf_id += BIT(29); 4106 - IWL_INFO(iwl_trans, "Adding jacket to rf id\n"); 4107 - } 4108 - 4109 4069 IWL_INFO(iwl_trans, 4110 4070 "Detected rf-type 0x%x step-id 0x%x slave-id 0x%x from crf id 0x%x\n", 4111 4071 REG_CRF_ID_TYPE(val), step_id, slave_id, info->hw_rf_id); 4112 4072 IWL_INFO(iwl_trans, 4113 - "Detected cdb-id 0x%x jacket-id 0x%x from wfpm id 0x%x\n", 4114 - cdb_id_wfpm, jacket_id_wfpm, hw_wfpm_id); 4115 - IWL_INFO(iwl_trans, "Detected jacket-id 0x%x from cnvi id 0x%x\n", 4116 - jacket_id_cnv, info->hw_cnv_id); 4117 - 4073 + "Detected cdb-id 0x%x from wfpm id 0x%x\n", 4074 + cdb_id_wfpm, hw_wfpm_id); 4118 4075 out: 4119 4076 return ret; 4120 4077 } ··· 4188 4163 */ 4189 4164 ret = iwl_pcie_prepare_card_hw(iwl_trans); 4190 4165 if (!ret) { 4191 - ret = iwl_finish_nic_init(iwl_trans); 4166 + ret = iwl_trans_activate_nic(iwl_trans); 4192 4167 if (ret) 4193 4168 goto out_free_trans; 4194 4169 if (iwl_trans_grab_nic_access(iwl_trans)) { ··· 4295 4270 out_free_trans: 4296 4271 iwl_trans_pcie_free(iwl_trans); 4297 4272 return ret; 4273 + } 4274 + 4275 + void iwl_pcie_gen1_2_remove(struct iwl_trans *trans) 4276 + { 4277 + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 4278 + 4279 + cancel_delayed_work_sync(&trans_pcie->me_recheck_wk); 4280 + 4281 + iwl_drv_stop(trans->drv); 4282 + 4283 + iwl_trans_pcie_free(trans); 4284 + } 4285 + 4286 + int iwl_pcie_gen1_2_activate_nic(struct iwl_trans *trans) 4287 + { 4288 + const struct iwl_mac_cfg *mac_cfg = trans->mac_cfg; 4289 + u32 poll_ready; 4290 + int err; 4291 + 4292 + if (mac_cfg->bisr_workaround) { 4293 + /* ensure the TOP FSM isn't still in previous reset */ 4294 + mdelay(2); 4295 + } 4296 + 4297 + /* 4298 + * Set "initialization complete" bit to move adapter from 4299 + * D0U* --> D0A* (powered-up active) state. 4300 + */ 4301 + if (mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { 4302 + iwl_set_bit(trans, CSR_GP_CNTRL, 4303 + CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ | 4304 + CSR_GP_CNTRL_REG_FLAG_MAC_INIT); 4305 + poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_STATUS; 4306 + } else { 4307 + iwl_set_bit(trans, CSR_GP_CNTRL, 4308 + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 4309 + poll_ready = CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY; 4310 + } 4311 + 4312 + if (mac_cfg->device_family == IWL_DEVICE_FAMILY_8000) 4313 + udelay(2); 4314 + 4315 + /* 4316 + * Wait for clock stabilization; once stabilized, access to 4317 + * device-internal resources is supported, e.g. iwl_write_prph() 4318 + * and accesses to uCode SRAM. 4319 + */ 4320 + err = iwl_poll_bits(trans, CSR_GP_CNTRL, poll_ready, 25000); 4321 + if (err < 0) { 4322 + IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); 4323 + 4324 + iwl_pcie_dump_host_monitor(trans); 4325 + } 4326 + 4327 + if (mac_cfg->bisr_workaround) { 4328 + /* ensure BISR shift has finished */ 4329 + udelay(200); 4330 + } 4331 + 4332 + return err; 4298 4333 }
+3 -2
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/tx.c
··· 2602 2602 } 2603 2603 2604 2604 if (test_bit(STATUS_FW_ERROR, &trans->status)) { 2605 - if (!test_and_clear_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, 2606 - &trans->status)) { 2605 + if (trans->suppress_cmd_error_once) { 2606 + trans->suppress_cmd_error_once = false; 2607 + } else { 2607 2608 IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str); 2608 2609 dump_stack(); 2609 2610 }
+1 -1
drivers/net/wireless/intel/iwlwifi/tests/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 2 3 - iwlwifi-tests-y += module.o devinfo.o utils.o 3 + iwlwifi-tests-y += module.o devinfo.o utils.o nvm_parse.o 4 4 5 5 ccflags-y += -I$(src)/../ 6 6
+72
drivers/net/wireless/intel/iwlwifi/tests/nvm_parse.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * KUnit tests for NVM parse 4 + * 5 + * Copyright (C) 2025 Intel Corporation 6 + */ 7 + #include <kunit/static_stub.h> 8 + #include <kunit/test.h> 9 + #include <iwl-nvm-parse.h> 10 + 11 + MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 12 + 13 + static const struct nvm_flag_case { 14 + const char *desc; 15 + u16 nvm_flags; 16 + u32 reg_rule_flags; 17 + u32 set_reg_rule_flags; 18 + u32 clear_reg_rule_flags; 19 + } nvm_flag_cases[] = { 20 + { 21 + .desc = "Restricting VLP client and AP access", 22 + .nvm_flags = 0, 23 + .set_reg_rule_flags = NL80211_RRF_NO_6GHZ_VLP_CLIENT, 24 + .clear_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP, 25 + }, 26 + { 27 + .desc = "Allow VLP client and AP access", 28 + .nvm_flags = NVM_CHANNEL_VLP, 29 + .set_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP, 30 + .clear_reg_rule_flags = NL80211_RRF_NO_6GHZ_VLP_CLIENT, 31 + }, 32 + { 33 + .desc = "Allow VLP client access, while restricting AP access", 34 + .nvm_flags = NVM_CHANNEL_VLP | NVM_CHANNEL_VLP_AP_NOT_ALLOWED, 35 + .set_reg_rule_flags = 0, 36 + .clear_reg_rule_flags = NL80211_RRF_ALLOW_6GHZ_VLP_AP | 37 + NL80211_RRF_NO_6GHZ_VLP_CLIENT, 38 + }, 39 + }; 40 + 41 + KUNIT_ARRAY_PARAM_DESC(nvm_flag, nvm_flag_cases, desc) 42 + 43 + static void test_nvm_flags(struct kunit *test) 44 + { 45 + const struct nvm_flag_case *params = test->param_value; 46 + struct iwl_reg_capa reg_capa = {}; 47 + u32 flags = 0; 48 + 49 + flags = iwl_nvm_get_regdom_bw_flags(NULL, 0, params->nvm_flags, 50 + reg_capa); 51 + 52 + if ((params->set_reg_rule_flags & flags) != params->set_reg_rule_flags) 53 + KUNIT_FAIL(test, "Expected set bits:0x%08x flags:0x%08x\n", 54 + params->set_reg_rule_flags, flags); 55 + 56 + if (params->clear_reg_rule_flags & flags) 57 + KUNIT_FAIL(test, "Expected clear bits:0x%08x flags:0x%08x\n", 58 + params->clear_reg_rule_flags, flags); 59 + } 60 + 61 + static struct kunit_case nvm_flags_test_cases[] = { 62 + KUNIT_CASE_PARAM(test_nvm_flags, 63 + nvm_flag_gen_params), 64 + {}, 65 + }; 66 + 67 + static struct kunit_suite nvm_flags_suite = { 68 + .name = "iwlwifi-nvm_flags", 69 + .test_cases = nvm_flags_test_cases, 70 + }; 71 + 72 + kunit_test_suite(nvm_flags_suite);
+1 -1
drivers/net/wireless/intersil/p54/txrx.c
··· 317 317 tim_len = tim[1]; 318 318 tim_ie = (struct ieee80211_tim_ie *) &tim[2]; 319 319 320 - new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid); 320 + new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid, false); 321 321 if (new_psm != priv->powersave_override) { 322 322 priv->powersave_override = new_psm; 323 323 p54_set_ps(priv);
+3 -4
drivers/net/wireless/marvell/mwifiex/cfg80211.c
··· 686 686 return; 687 687 } 688 688 689 - /* Don't send world or same regdom info to firmware */ 690 - if (strncmp(request->alpha2, "00", 2) && 691 - strncmp(request->alpha2, adapter->country_code, 692 - sizeof(request->alpha2))) { 689 + /* Don't send same regdom info to firmware */ 690 + if (strncmp(request->alpha2, adapter->country_code, 691 + sizeof(request->alpha2)) != 0) { 693 692 memcpy(adapter->country_code, request->alpha2, 694 693 sizeof(request->alpha2)); 695 694 mwifiex_send_domain_info_cmd_fw(wiphy);
+5
drivers/net/wireless/marvell/mwifiex/main.c
··· 494 494 return; 495 495 } 496 496 497 + if (adapter->rgpower_data) { 498 + release_firmware(adapter->rgpower_data); 499 + adapter->rgpower_data = NULL; 500 + } 501 + 497 502 mwifiex_unregister(adapter); 498 503 pr_debug("info: %s: free adapter\n", __func__); 499 504 }
+3
drivers/net/wireless/marvell/mwifiex/main.h
··· 982 982 u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; 983 983 u16 max_mgmt_ie_index; 984 984 const struct firmware *cal_data; 985 + const struct firmware *rgpower_data; 985 986 struct device_node *dt_node; 986 987 987 988 /* 11AC */ ··· 1580 1579 int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, 1581 1580 struct device_node *node, const char *prefix); 1582 1581 void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv); 1582 + int mwifiex_send_rgpower_table(struct mwifiex_private *priv, const u8 *data, 1583 + const size_t size); 1583 1584 1584 1585 extern const struct ethtool_ops mwifiex_ethtool_ops; 1585 1586
+113
drivers/net/wireless/marvell/mwifiex/sta_cmd.c
··· 1483 1483 return 0; 1484 1484 } 1485 1485 1486 + static int mwifiex_rgpower_table_advance_to_content(u8 **pos, const u8 *data, 1487 + const size_t size) 1488 + { 1489 + while (*pos - data < size) { 1490 + /* skip spaces, tabs and empty lines */ 1491 + if (**pos == '\r' || **pos == '\n' || **pos == '\0' || 1492 + isspace(**pos)) { 1493 + (*pos)++; 1494 + continue; 1495 + } 1496 + /* skip line comments */ 1497 + if (**pos == '#') { 1498 + *pos = strchr(*pos, '\n'); 1499 + if (!*pos) 1500 + return -EINVAL; 1501 + (*pos)++; 1502 + continue; 1503 + } 1504 + return 0; 1505 + } 1506 + return 0; 1507 + } 1508 + 1509 + int mwifiex_send_rgpower_table(struct mwifiex_private *priv, const u8 *data, 1510 + const size_t size) 1511 + { 1512 + int ret = 0; 1513 + bool start_raw = false; 1514 + u8 *ptr, *token, *pos = NULL; 1515 + u8 *_data __free(kfree) = NULL; 1516 + struct mwifiex_adapter *adapter = priv->adapter; 1517 + struct mwifiex_ds_misc_cmd *hostcmd __free(kfree) = NULL; 1518 + 1519 + hostcmd = kzalloc(sizeof(*hostcmd), GFP_KERNEL); 1520 + if (!hostcmd) 1521 + return -ENOMEM; 1522 + 1523 + _data = kmemdup(data, size, GFP_KERNEL); 1524 + if (!_data) 1525 + return -ENOMEM; 1526 + 1527 + pos = _data; 1528 + ptr = hostcmd->cmd; 1529 + while ((pos - _data) < size) { 1530 + ret = mwifiex_rgpower_table_advance_to_content(&pos, _data, size); 1531 + if (ret) { 1532 + mwifiex_dbg( 1533 + adapter, ERROR, 1534 + "%s: failed to advance to content in rgpower table\n", 1535 + __func__); 1536 + return ret; 1537 + } 1538 + 1539 + if (*pos == '}' && start_raw) { 1540 + hostcmd->len = get_unaligned_le16(&hostcmd->cmd[2]); 1541 + ret = mwifiex_send_cmd(priv, 0, 0, 0, hostcmd, false); 1542 + if (ret) { 1543 + mwifiex_dbg(adapter, ERROR, 1544 + "%s: failed to send hostcmd %d\n", 1545 + __func__, ret); 1546 + return ret; 1547 + } 1548 + 1549 + memset(hostcmd->cmd, 0, MWIFIEX_SIZE_OF_CMD_BUFFER); 1550 + ptr = hostcmd->cmd; 1551 + start_raw = false; 1552 + pos++; 1553 + continue; 1554 + } 1555 + 1556 + if (!start_raw) { 1557 + pos = strchr(pos, '='); 1558 + if (pos) { 1559 + pos = strchr(pos, '{'); 1560 + if (pos) { 1561 + start_raw = true; 1562 + pos++; 1563 + continue; 1564 + } 1565 + } 1566 + mwifiex_dbg(adapter, ERROR, 1567 + "%s: syntax error in hostcmd\n", __func__); 1568 + return -EINVAL; 1569 + } 1570 + 1571 + if (start_raw) { 1572 + while ((*pos != '\r' && *pos != '\n') && 1573 + (token = strsep((char **)&pos, " "))) { 1574 + if (ptr - hostcmd->cmd >= 1575 + MWIFIEX_SIZE_OF_CMD_BUFFER) { 1576 + mwifiex_dbg( 1577 + adapter, ERROR, 1578 + "%s: hostcmd is larger than %d, aborting\n", 1579 + __func__, MWIFIEX_SIZE_OF_CMD_BUFFER); 1580 + return -ENOMEM; 1581 + } 1582 + 1583 + ret = kstrtou8(token, 16, ptr); 1584 + if (ret < 0) { 1585 + mwifiex_dbg( 1586 + adapter, ERROR, 1587 + "%s: failed to parse hostcmd %d token: %s\n", 1588 + __func__, ret, token); 1589 + return ret; 1590 + } 1591 + ptr++; 1592 + } 1593 + } 1594 + } 1595 + 1596 + return ret; 1597 + } 1598 + 1486 1599 /* This function prepares command of set_cfg_data. */ 1487 1600 static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, 1488 1601 struct host_cmd_ds_command *cmd, void *data_buf)
+57 -1
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
··· 180 180 return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); 181 181 } 182 182 183 - void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv) 183 + static void mwifiex_dnld_dt_txpwr_table(struct mwifiex_private *priv) 184 184 { 185 185 if (priv->adapter->dt_node) { 186 186 char txpwr[] = {"marvell,00_txpwrlimit"}; ··· 188 188 memcpy(&txpwr[8], priv->adapter->country_code, 2); 189 189 mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); 190 190 } 191 + } 192 + 193 + static int mwifiex_request_rgpower_table(struct mwifiex_private *priv) 194 + { 195 + struct mwifiex_802_11d_domain_reg *domain_info = &priv->adapter->domain_reg; 196 + struct mwifiex_adapter *adapter = priv->adapter; 197 + char rgpower_table_name[30]; 198 + char country_code[3]; 199 + 200 + strscpy(country_code, domain_info->country_code, sizeof(country_code)); 201 + 202 + /* World regulatory domain "00" has WW as country code */ 203 + if (strncmp(country_code, "00", 2) == 0) 204 + strscpy(country_code, "WW", sizeof(country_code)); 205 + 206 + snprintf(rgpower_table_name, sizeof(rgpower_table_name), 207 + "nxp/rgpower_%s.bin", country_code); 208 + 209 + mwifiex_dbg(adapter, INFO, "info: %s: requesting regulatory power table %s\n", 210 + __func__, rgpower_table_name); 211 + 212 + if (adapter->rgpower_data) { 213 + release_firmware(adapter->rgpower_data); 214 + adapter->rgpower_data = NULL; 215 + } 216 + 217 + if ((request_firmware(&adapter->rgpower_data, rgpower_table_name, 218 + adapter->dev))) { 219 + mwifiex_dbg( 220 + adapter, INFO, 221 + "info: %s: failed to request regulatory power table\n", 222 + __func__); 223 + return -EIO; 224 + } 225 + 226 + return 0; 227 + } 228 + 229 + static int mwifiex_dnld_rgpower_table(struct mwifiex_private *priv) 230 + { 231 + int ret; 232 + 233 + ret = mwifiex_request_rgpower_table(priv); 234 + if (ret) 235 + return ret; 236 + 237 + return mwifiex_send_rgpower_table(priv, priv->adapter->rgpower_data->data, 238 + priv->adapter->rgpower_data->size); 239 + } 240 + 241 + void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv) 242 + { 243 + if (mwifiex_dnld_rgpower_table(priv) == 0) 244 + return; 245 + 246 + mwifiex_dnld_dt_txpwr_table(priv); 191 247 } 192 248 193 249 static int mwifiex_process_country_ie(struct mwifiex_private *priv,
-7
drivers/net/wireless/microchip/wilc1000/cfg80211.c
··· 794 794 return 0; 795 795 } 796 796 797 - static int change_bss(struct wiphy *wiphy, struct net_device *dev, 798 - struct bss_parameters *params) 799 - { 800 - return 0; 801 - } 802 - 803 797 static int set_wiphy_params(struct wiphy *wiphy, int radio_idx, u32 changed) 804 798 { 805 799 int ret = -EINVAL; ··· 1703 1709 .change_station = change_station, 1704 1710 .get_station = get_station, 1705 1711 .dump_station = dump_station, 1706 - .change_bss = change_bss, 1707 1712 .set_wiphy_params = set_wiphy_params, 1708 1713 1709 1714 .external_auth = external_auth,
+1 -1
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
··· 679 679 /* Check whenever the PHY can be turned off again. */ 680 680 681 681 /* 1. What about buffered unicast traffic for our AID? */ 682 - cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid); 682 + cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid, false); 683 683 684 684 /* 2. Maybe the AP wants to send multicast/broadcast data? */ 685 685 cam |= (tim_ie->bitmap_ctrl & 0x01);
+1 -1
drivers/net/wireless/realtek/rtlwifi/ps.c
··· 519 519 520 520 /* 1. What about buffered unicast traffic for our AID? */ 521 521 u_buffed = ieee80211_check_tim(tim_ie, tim_len, 522 - rtlpriv->mac80211.assoc_id); 522 + rtlpriv->mac80211.assoc_id, false); 523 523 524 524 /* 2. Maybe the AP wants to send multicast/broadcast data? */ 525 525 m_buffed = tim_ie->bitmap_ctrl & 0x01;
-8
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
··· 2441 2441 return ret; 2442 2442 } 2443 2443 2444 - static int cfg80211_rtw_change_bss(struct wiphy *wiphy, 2445 - struct net_device *ndev, 2446 - struct bss_parameters *params) 2447 - { 2448 - return 0; 2449 - } 2450 - 2451 2444 void rtw_cfg80211_rx_action(struct adapter *adapter, u8 *frame, uint frame_len, const char *msg) 2452 2445 { 2453 2446 s32 freq; ··· 2697 2704 .del_station = cfg80211_rtw_del_station, 2698 2705 .change_station = cfg80211_rtw_change_station, 2699 2706 .dump_station = cfg80211_rtw_dump_station, 2700 - .change_bss = cfg80211_rtw_change_bss, 2701 2707 2702 2708 .mgmt_tx = cfg80211_rtw_mgmt_tx, 2703 2709 };
+256 -9
include/linux/ieee80211.h
··· 220 220 #define IEEE80211_MAX_AID_S1G 8191 221 221 #define IEEE80211_MAX_TIM_LEN 251 222 222 #define IEEE80211_MAX_MESH_PEERINGS 63 223 + 224 + /* S1G encoding types */ 225 + #define IEEE80211_S1G_TIM_ENC_MODE_BLOCK 0 226 + #define IEEE80211_S1G_TIM_ENC_MODE_SINGLE 1 227 + #define IEEE80211_S1G_TIM_ENC_MODE_OLB 2 228 + 223 229 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section 224 230 6.2.1.1.2. 225 231 ··· 4763 4757 return 1024 * tu; 4764 4758 } 4765 4759 4766 - /** 4767 - * ieee80211_check_tim - check if AID bit is set in TIM 4768 - * @tim: the TIM IE 4769 - * @tim_len: length of the TIM IE 4770 - * @aid: the AID to look for 4771 - * Return: whether or not traffic is indicated in the TIM for the given AID 4772 - */ 4773 - static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim, 4774 - u8 tim_len, u16 aid) 4760 + static inline bool __ieee80211_check_tim(const struct ieee80211_tim_ie *tim, 4761 + u8 tim_len, u16 aid) 4775 4762 { 4776 4763 u8 mask; 4777 4764 u8 index, indexn1, indexn2; ··· 4785 4786 index -= indexn1; 4786 4787 4787 4788 return !!(tim->virtual_map[index] & mask); 4789 + } 4790 + 4791 + struct s1g_tim_aid { 4792 + u16 aid; 4793 + u8 target_blk; /* Target block index */ 4794 + u8 target_subblk; /* Target subblock index */ 4795 + u8 target_subblk_bit; /* Target subblock bit */ 4796 + }; 4797 + 4798 + struct s1g_tim_enc_block { 4799 + u8 enc_mode; 4800 + bool inverse; 4801 + const u8 *ptr; 4802 + u8 len; 4803 + 4804 + /* 4805 + * For an OLB encoded block that spans multiple blocks, this 4806 + * is the offset into the span described by that encoded block. 4807 + */ 4808 + u8 olb_blk_offset; 4809 + }; 4810 + 4811 + /* 4812 + * Helper routines to quickly extract the length of an encoded block. Validation 4813 + * is also performed to ensure the length extracted lies within the TIM. 4814 + */ 4815 + 4816 + static inline int ieee80211_s1g_len_bitmap(const u8 *ptr, const u8 *end) 4817 + { 4818 + u8 blkmap; 4819 + u8 n_subblks; 4820 + 4821 + if (ptr >= end) 4822 + return -EINVAL; 4823 + 4824 + blkmap = *ptr; 4825 + n_subblks = hweight8(blkmap); 4826 + 4827 + if (ptr + 1 + n_subblks > end) 4828 + return -EINVAL; 4829 + 4830 + return 1 + n_subblks; 4831 + } 4832 + 4833 + static inline int ieee80211_s1g_len_single(const u8 *ptr, const u8 *end) 4834 + { 4835 + return (ptr + 1 > end) ? -EINVAL : 1; 4836 + } 4837 + 4838 + static inline int ieee80211_s1g_len_olb(const u8 *ptr, const u8 *end) 4839 + { 4840 + if (ptr >= end) 4841 + return -EINVAL; 4842 + 4843 + return (ptr + 1 + *ptr > end) ? -EINVAL : 1 + *ptr; 4844 + } 4845 + 4846 + /* 4847 + * Enumerate all encoded blocks until we find the encoded block that describes 4848 + * our target AID. OLB is a special case as a single encoded block can describe 4849 + * multiple blocks as a single encoded block. 4850 + */ 4851 + static inline int ieee80211_s1g_find_target_block(struct s1g_tim_enc_block *enc, 4852 + const struct s1g_tim_aid *aid, 4853 + const u8 *ptr, const u8 *end) 4854 + { 4855 + /* need at least block-control octet */ 4856 + while (ptr + 1 <= end) { 4857 + u8 ctrl = *ptr++; 4858 + u8 mode = ctrl & 0x03; 4859 + bool contains, inverse = ctrl & BIT(2); 4860 + u8 span, blk_off = ctrl >> 3; 4861 + int len; 4862 + 4863 + switch (mode) { 4864 + case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 4865 + len = ieee80211_s1g_len_bitmap(ptr, end); 4866 + contains = blk_off == aid->target_blk; 4867 + break; 4868 + case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 4869 + len = ieee80211_s1g_len_single(ptr, end); 4870 + contains = blk_off == aid->target_blk; 4871 + break; 4872 + case IEEE80211_S1G_TIM_ENC_MODE_OLB: 4873 + len = ieee80211_s1g_len_olb(ptr, end); 4874 + /* 4875 + * An OLB encoded block can describe more then one 4876 + * block, meaning an encoded OLB block can span more 4877 + * then a single block. 4878 + */ 4879 + if (len > 0) { 4880 + /* Minus one for the length octet */ 4881 + span = DIV_ROUND_UP(len - 1, 8); 4882 + /* 4883 + * Check if our target block lies within the 4884 + * block span described by this encoded block. 4885 + */ 4886 + contains = (aid->target_blk >= blk_off) && 4887 + (aid->target_blk < blk_off + span); 4888 + } 4889 + break; 4890 + default: 4891 + return -EOPNOTSUPP; 4892 + } 4893 + 4894 + if (len < 0) 4895 + return len; 4896 + 4897 + if (contains) { 4898 + enc->enc_mode = mode; 4899 + enc->inverse = inverse; 4900 + enc->ptr = ptr; 4901 + enc->len = (u8)len; 4902 + enc->olb_blk_offset = blk_off; 4903 + return 0; 4904 + } 4905 + 4906 + ptr += len; 4907 + } 4908 + 4909 + return -ENOENT; 4910 + } 4911 + 4912 + static inline bool ieee80211_s1g_parse_bitmap(struct s1g_tim_enc_block *enc, 4913 + struct s1g_tim_aid *aid) 4914 + { 4915 + const u8 *ptr = enc->ptr; 4916 + u8 blkmap = *ptr++; 4917 + 4918 + /* 4919 + * If our block bitmap does not contain a set bit that corresponds 4920 + * to our AID, it could mean a variety of things depending on if 4921 + * the encoding mode is inverted or not. 4922 + * 4923 + * 1. If inverted, it means the entire subblock is present and hence 4924 + * our AID has been set. 4925 + * 2. If not inverted, it means our subblock is not present and hence 4926 + * it is all zero meaning our AID is not set. 4927 + */ 4928 + if (!(blkmap & BIT(aid->target_subblk))) 4929 + return enc->inverse; 4930 + 4931 + /* 4932 + * Increment ptr by the number of set subblocks that appear before our 4933 + * target subblock. If our target subblock is 0, do nothing as ptr 4934 + * already points to our target subblock. 4935 + */ 4936 + if (aid->target_subblk) 4937 + ptr += hweight8(blkmap & GENMASK(aid->target_subblk - 1, 0)); 4938 + 4939 + return !!(*ptr & BIT(aid->target_subblk_bit)) ^ enc->inverse; 4940 + } 4941 + 4942 + static inline bool ieee80211_s1g_parse_single(struct s1g_tim_enc_block *enc, 4943 + struct s1g_tim_aid *aid) 4944 + { 4945 + /* 4946 + * Single AID mode describes, as the name suggests, a single AID 4947 + * within the block described by the encoded block. The octet 4948 + * contains the 6 LSBs of the AID described in the block. The other 4949 + * 2 bits are reserved. When inversed, every single AID described 4950 + * by the current block have buffered traffic except for the AID 4951 + * described in the single AID octet. 4952 + */ 4953 + return ((*enc->ptr & 0x3f) == (aid->aid & 0x3f)) ^ enc->inverse; 4954 + } 4955 + 4956 + static inline bool ieee80211_s1g_parse_olb(struct s1g_tim_enc_block *enc, 4957 + struct s1g_tim_aid *aid) 4958 + { 4959 + const u8 *ptr = enc->ptr; 4960 + u8 blk_len = *ptr++; 4961 + /* 4962 + * Given an OLB encoded block that describes multiple blocks, 4963 + * calculate the offset into the span. Then calculate the 4964 + * subblock location normally. 4965 + */ 4966 + u16 span_offset = aid->target_blk - enc->olb_blk_offset; 4967 + u16 subblk_idx = span_offset * 8 + aid->target_subblk; 4968 + 4969 + if (subblk_idx >= blk_len) 4970 + return enc->inverse; 4971 + 4972 + return !!(ptr[subblk_idx] & BIT(aid->target_subblk_bit)) ^ enc->inverse; 4973 + } 4974 + 4975 + /* 4976 + * An S1G PVB has 3 non optional encoding types, each that can be inverted. 4977 + * An S1G PVB is constructed with zero or more encoded block subfields. Each 4978 + * encoded block represents a single "block" of AIDs (64), and each encoded 4979 + * block can contain one of the 3 encoding types alongside a single bit for 4980 + * whether the bits should be inverted. 4981 + * 4982 + * As the standard makes no guarantee about the ordering of encoded blocks, 4983 + * we must parse every encoded block in the worst case scenario given an 4984 + * AID that lies within the last block. 4985 + */ 4986 + static inline bool ieee80211_s1g_check_tim(const struct ieee80211_tim_ie *tim, 4987 + u8 tim_len, u16 aid) 4988 + { 4989 + int err; 4990 + struct s1g_tim_aid target_aid; 4991 + struct s1g_tim_enc_block enc_blk; 4992 + 4993 + if (tim_len < 3) 4994 + return false; 4995 + 4996 + target_aid.aid = aid; 4997 + target_aid.target_blk = (aid >> 6) & 0x1f; 4998 + target_aid.target_subblk = (aid >> 3) & 0x7; 4999 + target_aid.target_subblk_bit = aid & 0x7; 5000 + 5001 + /* 5002 + * Find our AIDs target encoded block and fill &enc_blk with the 5003 + * encoded blocks information. If no entry is found or an error 5004 + * occurs return false. 5005 + */ 5006 + err = ieee80211_s1g_find_target_block(&enc_blk, &target_aid, 5007 + tim->virtual_map, 5008 + (const u8 *)tim + tim_len + 2); 5009 + if (err) 5010 + return false; 5011 + 5012 + switch (enc_blk.enc_mode) { 5013 + case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: 5014 + return ieee80211_s1g_parse_bitmap(&enc_blk, &target_aid); 5015 + case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: 5016 + return ieee80211_s1g_parse_single(&enc_blk, &target_aid); 5017 + case IEEE80211_S1G_TIM_ENC_MODE_OLB: 5018 + return ieee80211_s1g_parse_olb(&enc_blk, &target_aid); 5019 + default: 5020 + return false; 5021 + } 5022 + } 5023 + 5024 + /** 5025 + * ieee80211_check_tim - check if AID bit is set in TIM 5026 + * @tim: the TIM IE 5027 + * @tim_len: length of the TIM IE 5028 + * @aid: the AID to look for 5029 + * @s1g: whether the TIM is from an S1G PPDU 5030 + * Return: whether or not traffic is indicated in the TIM for the given AID 5031 + */ 5032 + static inline bool ieee80211_check_tim(const struct ieee80211_tim_ie *tim, 5033 + u8 tim_len, u16 aid, bool s1g) 5034 + { 5035 + return s1g ? ieee80211_s1g_check_tim(tim, tim_len, aid) : 5036 + __ieee80211_check_tim(tim, tim_len, aid); 4788 5037 } 4789 5038 4790 5039 /**
+1 -1
include/linux/mmc/sdio_ids.h
··· 77 77 #define SDIO_DEVICE_ID_BROADCOM_43439 0xa9af 78 78 #define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf 79 79 #define SDIO_DEVICE_ID_BROADCOM_43751 0xaae7 80 - #define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752 0xaae8 80 + #define SDIO_DEVICE_ID_BROADCOM_43752 0xaae8 81 81 82 82 #define SDIO_VENDOR_ID_CYPRESS 0x04b4 83 83 #define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439 0xbd3d
+33 -1
include/net/cfg80211.h
··· 841 841 u8 ht_mcs[IEEE80211_HT_MCS_MASK_LEN]; 842 842 u16 vht_mcs[NL80211_VHT_NSS_MAX]; 843 843 u16 he_mcs[NL80211_HE_NSS_MAX]; 844 + u16 eht_mcs[NL80211_EHT_NSS_MAX]; 844 845 enum nl80211_txrate_gi gi; 845 846 enum nl80211_he_gi he_gi; 847 + enum nl80211_eht_gi eht_gi; 846 848 enum nl80211_he_ltf he_ltf; 849 + enum nl80211_eht_ltf eht_ltf; 847 850 } control[NUM_NL80211_BANDS]; 848 851 }; 849 852 ··· 2457 2454 u32 path_change_count; 2458 2455 2459 2456 int generation; 2457 + }; 2458 + 2459 + /** 2460 + * enum wiphy_bss_param_flags - bit positions for supported bss parameters. 2461 + * 2462 + * @WIPHY_BSS_PARAM_CTS_PROT: support changing CTS protection. 2463 + * @WIPHY_BSS_PARAM_SHORT_PREAMBLE: support changing short preamble usage. 2464 + * @WIPHY_BSS_PARAM_SHORT_SLOT_TIME: support changing short slot time usage. 2465 + * @WIPHY_BSS_PARAM_BASIC_RATES: support reconfiguring basic rates. 2466 + * @WIPHY_BSS_PARAM_AP_ISOLATE: support changing AP isolation. 2467 + * @WIPHY_BSS_PARAM_HT_OPMODE: support changing HT operating mode. 2468 + * @WIPHY_BSS_PARAM_P2P_CTWINDOW: support reconfiguring ctwindow. 2469 + * @WIPHY_BSS_PARAM_P2P_OPPPS: support changing P2P opportunistic power-save. 2470 + */ 2471 + enum wiphy_bss_param_flags { 2472 + WIPHY_BSS_PARAM_CTS_PROT = BIT(0), 2473 + WIPHY_BSS_PARAM_SHORT_PREAMBLE = BIT(1), 2474 + WIPHY_BSS_PARAM_SHORT_SLOT_TIME = BIT(2), 2475 + WIPHY_BSS_PARAM_BASIC_RATES = BIT(3), 2476 + WIPHY_BSS_PARAM_AP_ISOLATE = BIT(4), 2477 + WIPHY_BSS_PARAM_HT_OPMODE = BIT(5), 2478 + WIPHY_BSS_PARAM_P2P_CTWINDOW = BIT(6), 2479 + WIPHY_BSS_PARAM_P2P_OPPPS = BIT(7), 2460 2480 }; 2461 2481 2462 2482 /** ··· 5808 5782 * and probe responses. This value should be set if the driver 5809 5783 * wishes to limit the number of csa counters. Default (0) means 5810 5784 * infinite. 5785 + * @bss_param_support: bitmask indicating which bss_parameters as defined in 5786 + * &struct bss_parameters the driver can actually handle in the 5787 + * .change_bss() callback. The bit positions are defined in &enum 5788 + * wiphy_bss_param_flags. 5789 + * 5811 5790 * @bss_select_support: bitmask indicating the BSS selection criteria supported 5812 5791 * by the driver in the .connect() callback. The bit position maps to the 5813 5792 * attribute indices defined in &enum nl80211_bss_select_attr. ··· 5998 5967 5999 5968 u8 max_num_csa_counters; 6000 5969 5970 + u32 bss_param_support; 6001 5971 u32 bss_select_support; 6002 5972 6003 5973 u8 nan_supported_bands; ··· 9580 9548 * @wiphy: the wiphy 9581 9549 * @chan: channel for which the supported radio index is required 9582 9550 * 9583 - * Return: radio index on success or a negative error code 9551 + * Return: radio index on success or -EINVAL otherwise 9584 9552 */ 9585 9553 int cfg80211_get_radio_idx_by_chan(struct wiphy *wiphy, 9586 9554 const struct ieee80211_channel *chan);
+48 -3
include/uapi/linux/nl80211.h
··· 1943 1943 * The driver must also specify support for this with the extended 1944 1944 * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, 1945 1945 * NL80211_EXT_FEATURE_BEACON_RATE_HT, 1946 - * NL80211_EXT_FEATURE_BEACON_RATE_VHT and 1947 - * NL80211_EXT_FEATURE_BEACON_RATE_HE. 1946 + * NL80211_EXT_FEATURE_BEACON_RATE_VHT, 1947 + * NL80211_EXT_FEATURE_BEACON_RATE_HE and 1948 + * NL80211_EXT_FEATURE_BEACON_RATE_EHT. 1948 1949 * 1949 1950 * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain 1950 1951 * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. ··· 2284 2283 * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). 2285 2284 * This is similar to @NL80211_ATTR_STA_AID but with a difference of being 2286 2285 * allowed to be used with the first @NL80211_CMD_SET_STATION command to 2287 - * update a TDLS peer STA entry. 2286 + * update a TDLS peer STA entry. For S1G interfaces, this is limited to 2287 + * 1600 for the current mac80211 implementation. 2288 2288 * 2289 2289 * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information. 2290 2290 * ··· 2930 2928 * required alongside this attribute. Refer to 2931 2929 * @enum nl80211_s1g_short_beacon_attrs for the attribute definitions. 2932 2930 * 2931 + * @NL80211_ATTR_BSS_PARAM: nested attribute used with %NL80211_CMD_GET_WIPHY 2932 + * which indicates which BSS parameters can be modified. The attribute can 2933 + * also be used as flag attribute by user-space in %NL80211_CMD_SET_BSS to 2934 + * indicate that it wants strict checking on the BSS parameters to be 2935 + * modified. 2936 + * 2933 2937 * @NUM_NL80211_ATTR: total number of nl80211_attrs available 2934 2938 * @NL80211_ATTR_MAX: highest attribute number currently defined 2935 2939 * @__NL80211_ATTR_AFTER_LAST: internal use ··· 3497 3489 3498 3490 NL80211_ATTR_S1G_LONG_BEACON_PERIOD, 3499 3491 NL80211_ATTR_S1G_SHORT_BEACON, 3492 + NL80211_ATTR_BSS_PARAM, 3500 3493 3501 3494 /* add attributes here, update the policy in nl80211.c */ 3502 3495 ··· 3742 3733 NL80211_RATE_INFO_EHT_GI_0_8, 3743 3734 NL80211_RATE_INFO_EHT_GI_1_6, 3744 3735 NL80211_RATE_INFO_EHT_GI_3_2, 3736 + }; 3737 + 3738 + /** 3739 + * enum nl80211_eht_ltf - EHT long training field 3740 + * @NL80211_RATE_INFO_EHT_1XLTF: 3.2 usec 3741 + * @NL80211_RATE_INFO_EHT_2XLTF: 6.4 usec 3742 + * @NL80211_RATE_INFO_EHT_4XLTF: 12.8 usec 3743 + * @NL80211_RATE_INFO_EHT_6XLTF: 19.2 usec 3744 + * @NL80211_RATE_INFO_EHT_8XLTF: 25.6 usec 3745 + */ 3746 + enum nl80211_eht_ltf { 3747 + NL80211_RATE_INFO_EHT_1XLTF, 3748 + NL80211_RATE_INFO_EHT_2XLTF, 3749 + NL80211_RATE_INFO_EHT_4XLTF, 3750 + NL80211_RATE_INFO_EHT_6XLTF, 3751 + NL80211_RATE_INFO_EHT_8XLTF, 3745 3752 }; 3746 3753 3747 3754 /** ··· 5506 5481 * see &struct nl80211_txrate_he 5507 5482 * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. 5508 5483 * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. 5484 + * @NL80211_TXRATE_EHT: EHT rates allowed for TX rate selection, 5485 + * see &struct nl80211_txrate_eht 5486 + * @NL80211_TXRATE_EHT_GI: configure EHT GI, (u8, see &enum nl80211_eht_gi) 5487 + * @NL80211_TXRATE_EHT_LTF: configure EHT LTF, (u8, see &enum nl80211_eht_ltf) 5509 5488 * @__NL80211_TXRATE_AFTER_LAST: internal 5510 5489 * @NL80211_TXRATE_MAX: highest TX rate attribute 5511 5490 */ ··· 5522 5493 NL80211_TXRATE_HE, 5523 5494 NL80211_TXRATE_HE_GI, 5524 5495 NL80211_TXRATE_HE_LTF, 5496 + NL80211_TXRATE_EHT, 5497 + NL80211_TXRATE_EHT_GI, 5498 + NL80211_TXRATE_EHT_LTF, 5525 5499 5526 5500 /* keep last */ 5527 5501 __NL80211_TXRATE_AFTER_LAST, ··· 5555 5523 NL80211_TXRATE_DEFAULT_GI, 5556 5524 NL80211_TXRATE_FORCE_SGI, 5557 5525 NL80211_TXRATE_FORCE_LGI, 5526 + }; 5527 + 5528 + #define NL80211_EHT_NSS_MAX 16 5529 + /** 5530 + * struct nl80211_txrate_eht - EHT MCS/NSS txrate bitmap 5531 + * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) 5532 + */ 5533 + struct nl80211_txrate_eht { 5534 + __u16 mcs[NL80211_EHT_NSS_MAX]; 5558 5535 }; 5559 5536 5560 5537 /** ··· 6690 6649 * (signaling and payload protected) A-MSDUs and this shall be advertised 6691 6650 * in the RSNXE. 6692 6651 * 6652 + * @NL80211_EXT_FEATURE_BEACON_RATE_EHT: Driver supports beacon rate 6653 + * configuration (AP/mesh) with EHT rates. 6654 + * 6693 6655 * @NUM_NL80211_EXT_FEATURES: number of extended features. 6694 6656 * @MAX_NL80211_EXT_FEATURES: highest extended feature index. 6695 6657 */ ··· 6768 6724 NL80211_EXT_FEATURE_OWE_OFFLOAD_AP, 6769 6725 NL80211_EXT_FEATURE_DFS_CONCURRENT, 6770 6726 NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT, 6727 + NL80211_EXT_FEATURE_BEACON_RATE_EHT, 6771 6728 6772 6729 /* add new features before the definition below */ 6773 6730 NUM_NL80211_EXT_FEATURES,
+25 -19
net/mac80211/cfg.c
··· 2171 2171 2172 2172 /* 2173 2173 * cfg80211 validates this (1-2007) and allows setting the AID 2174 - * only when creating a new station entry 2174 + * only when creating a new station entry. For S1G APs, the current 2175 + * implementation supports a maximum of 1600 AIDs. 2175 2176 */ 2176 - if (params->aid) 2177 + if (params->aid) { 2178 + if (sdata->vif.cfg.s1g && 2179 + params->aid > IEEE80211_MAX_SUPPORTED_S1G_AID) 2180 + return -EINVAL; 2181 + 2177 2182 sta->sta.aid = params->aid; 2183 + } 2178 2184 2179 2185 /* 2180 2186 * Some of the following updates would be racy if called on an ··· 3007 3001 struct cfg80211_scan_request *req) 3008 3002 { 3009 3003 struct ieee80211_sub_if_data *sdata; 3004 + struct ieee80211_link_data *link; 3005 + struct ieee80211_channel *chan; 3006 + int radio_idx; 3010 3007 3011 3008 sdata = IEEE80211_WDEV_TO_SUB_IF(req->wdev); 3012 3009 ··· 3037 3028 * the frames sent while scanning on other channel will be 3038 3029 * lost) 3039 3030 */ 3040 - if (ieee80211_num_beaconing_links(sdata) && 3041 - (!(wiphy->features & NL80211_FEATURE_AP_SCAN) || 3042 - !(req->flags & NL80211_SCAN_FLAG_AP))) 3043 - return -EOPNOTSUPP; 3031 + for_each_link_data(sdata, link) { 3032 + /* if the link is not beaconing, ignore it */ 3033 + if (!sdata_dereference(link->u.ap.beacon, sdata)) 3034 + continue; 3035 + 3036 + chan = link->conf->chanreq.oper.chan; 3037 + radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan); 3038 + 3039 + if (ieee80211_is_radio_idx_in_scan_req(wiphy, req, 3040 + radio_idx) && 3041 + (!(wiphy->features & NL80211_FEATURE_AP_SCAN) || 3042 + !(req->flags & NL80211_SCAN_FLAG_AP))) 3043 + return -EOPNOTSUPP; 3044 + } 3044 3045 break; 3045 3046 case NL80211_IFTYPE_NAN: 3046 3047 default: ··· 3696 3677 if (list_empty(&local->roc_list) && !local->scanning) 3697 3678 return false; 3698 3679 3699 - if (wiphy->n_radio < 2) 3700 - return true; 3701 - 3702 3680 req_radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chandef->chan); 3703 - if (req_radio_idx < 0) 3704 - return true; 3705 3681 3706 3682 if (local->scanning) { 3707 3683 scan_req = wiphy_dereference(wiphy, local->scan_req); ··· 3715 3701 list_for_each_entry(roc, &local->roc_list, list) { 3716 3702 chan_radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, 3717 3703 roc->chan); 3718 - /* 3719 - * The roc work is added but chan_radio_idx is invalid. 3720 - * Should not happen but if it does, let's not take 3721 - * risk and return true. 3722 - */ 3723 - if (chan_radio_idx < 0) 3724 - return true; 3725 - 3726 3704 if (chan_radio_idx == req_radio_idx) 3727 3705 return true; 3728 3706 }
-11
net/mac80211/chan.c
··· 659 659 660 660 for_each_sdata_link(local, link) { 661 661 if (link->radar_required) { 662 - if (wiphy->n_radio < 2) 663 - return true; 664 - 665 662 chan = link->conf->chanreq.oper.chan; 666 663 radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan); 667 - /* 668 - * The radio index (radio_idx) is expected to be valid, 669 - * as it's derived from a channel tied to a link. If 670 - * it's invalid (i.e., negative), return true to avoid 671 - * potential issues with radar-sensitive operations. 672 - */ 673 - if (radio_idx < 0) 674 - return true; 675 664 676 665 if (ieee80211_is_radio_idx_in_scan_req(wiphy, req, 677 666 radio_idx))
+4 -2
net/mac80211/ethtool.c
··· 48 48 "rx_duplicates", "rx_fragments", "rx_dropped", 49 49 "tx_packets", "tx_bytes", 50 50 "tx_filtered", "tx_retry_failed", "tx_retries", 51 - "sta_state", "txrate", "rxrate", "signal", 52 - "channel", "noise", "ch_time", "ch_time_busy", 51 + "tx_handlers_drop", "sta_state", "txrate", "rxrate", 52 + "signal", "channel", "noise", "ch_time", "ch_time_busy", 53 53 "ch_time_ext_busy", "ch_time_rx", "ch_time_tx" 54 54 }; 55 55 #define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats) ··· 120 120 i = 0; 121 121 ADD_STA_STATS(&sta->deflink); 122 122 123 + data[i++] = sdata->tx_handlers_drop; 123 124 data[i++] = sta->sta_state; 124 125 125 126 ··· 146 145 sta_set_sinfo(sta, &sinfo, false); 147 146 i = 0; 148 147 ADD_STA_STATS(&sta->deflink); 148 + data[i++] = sdata->tx_handlers_drop; 149 149 } 150 150 } 151 151
+9
net/mac80211/ieee80211_i.h
··· 86 86 87 87 #define IEEE80211_MAX_NAN_INSTANCE_ID 255 88 88 89 + /* 90 + * Current mac80211 implementation supports a maximum of 1600 AIDS 91 + * for S1G interfaces. With regards to an S1G TIM, this covers 25 blocks 92 + * as each block is 64 AIDs. 93 + */ 94 + #define IEEE80211_MAX_SUPPORTED_S1G_AID 1600 95 + #define IEEE80211_MAX_SUPPORTED_S1G_TIM_BLOCKS 25 96 + 89 97 enum ieee80211_status_data { 90 98 IEEE80211_STATUS_TYPE_MASK = 0x00f, 91 99 IEEE80211_STATUS_TYPE_INVALID = 0, ··· 1218 1210 } debugfs; 1219 1211 #endif 1220 1212 1213 + u32 tx_handlers_drop; 1221 1214 /* must be last, dynamically sized area in this! */ 1222 1215 struct ieee80211_vif vif; 1223 1216 };
+8 -3
net/mac80211/main.c
··· 862 862 if (emulate_chanctx || ops->remain_on_channel) 863 863 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 864 864 865 + wiphy->bss_param_support = WIPHY_BSS_PARAM_CTS_PROT | 866 + WIPHY_BSS_PARAM_SHORT_PREAMBLE | 867 + WIPHY_BSS_PARAM_SHORT_SLOT_TIME | 868 + WIPHY_BSS_PARAM_BASIC_RATES | 869 + WIPHY_BSS_PARAM_AP_ISOLATE | 870 + WIPHY_BSS_PARAM_HT_OPMODE | 871 + WIPHY_BSS_PARAM_P2P_CTWINDOW | 872 + WIPHY_BSS_PARAM_P2P_OPPPS; 865 873 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | 866 874 NL80211_FEATURE_SAE | 867 875 NL80211_FEATURE_HT_IBSS | ··· 1170 1162 return -EINVAL; 1171 1163 1172 1164 if (WARN_ON(!ieee80211_hw_check(hw, MFP_CAPABLE))) 1173 - return -EINVAL; 1174 - 1175 - if (WARN_ON(!ieee80211_hw_check(hw, CONNECTION_MONITOR))) 1176 1165 return -EINVAL; 1177 1166 1178 1167 if (WARN_ON(ieee80211_hw_check(hw, NEED_DTIM_BEFORE_ASSOC)))
+3
net/mac80211/mesh.c
··· 624 624 if (!sband) 625 625 return -EINVAL; 626 626 627 + if (sband->band != NL80211_BAND_6GHZ) 628 + return 0; 629 + 627 630 iftd = ieee80211_get_sband_iftype_data(sband, 628 631 NL80211_IFTYPE_MESH_POINT); 629 632 /* The device doesn't support HE in mesh mode or at all */
+1 -1
net/mac80211/mesh_ps.c
··· 586 586 587 587 if (sta->mesh->plink_state == NL80211_PLINK_ESTAB) 588 588 has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len, 589 - sta->mesh->aid); 589 + sta->mesh->aid, false); 590 590 591 591 if (has_buffered) 592 592 mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
+21 -17
net/mac80211/mlme.c
··· 1850 1850 ieee80211_put_he_cap(skb, sdata, sband, 1851 1851 &assoc_data->link[link_id].conn); 1852 1852 ADD_PRESENT_EXT_ELEM(WLAN_EID_EXT_HE_CAPABILITY); 1853 - ieee80211_put_he_6ghz_cap(skb, sdata, smps_mode); 1853 + if (sband->band == NL80211_BAND_6GHZ) 1854 + ieee80211_put_he_6ghz_cap(skb, sdata, smps_mode); 1854 1855 } 1855 1856 1856 1857 /* ··· 2113 2112 sizeof(struct ieee80211_he_mcs_nss_supp) + 2114 2113 IEEE80211_HE_PPE_THRES_MAX_LEN; 2115 2114 2116 - if (sband->band == NL80211_BAND_6GHZ) 2115 + if (sband->band == NL80211_BAND_6GHZ) { 2117 2116 size += 2 + 1 + sizeof(struct ieee80211_he_6ghz_capa); 2117 + /* reg connection */ 2118 + size += 4; 2119 + } 2118 2120 2119 2121 size += 2 + 1 + sizeof(struct ieee80211_eht_cap_elem) + 2120 2122 sizeof(struct ieee80211_eht_mcs_nss_supp) + ··· 2191 2187 2 + /* ext capa & op */ 2192 2188 2; /* EML capa */ 2193 2189 2194 - /* 2195 - * The capability elements were already considered above; 2196 - * note this over-estimates a bit because there's no 2197 - * STA profile for the assoc link. 2198 - */ 2190 + /* The capability elements were already considered above */ 2199 2191 size += (n_links - 1) * 2200 2192 (1 + 1 + /* subelement ID/length */ 2201 2193 2 + /* STA control */ ··· 5729 5729 he_cap_elem = cfg80211_find_ext_elem(WLAN_EID_EXT_HE_CAPABILITY, 5730 5730 ies->data, ies->len); 5731 5731 5732 - if (!he_cap_elem || he_cap_elem->datalen < sizeof(*he_cap)) 5732 + if (!he_cap_elem || he_cap_elem->datalen < sizeof(*he_cap) + 1) 5733 5733 return chains; 5734 5734 5735 5735 /* skip one byte ext_tag_id */ ··· 6356 6356 }; 6357 6357 u8 ap_mld_addr[ETH_ALEN] __aligned(2); 6358 6358 unsigned int link_id; 6359 + u16 max_aid = IEEE80211_MAX_AID; 6359 6360 6360 6361 lockdep_assert_wiphy(sdata->local->hw.wiphy); 6361 6362 ··· 6383 6382 reassoc = ieee80211_is_reassoc_resp(mgmt->frame_control); 6384 6383 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); 6385 6384 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 6386 - if (assoc_data->s1g) 6385 + if (assoc_data->s1g) { 6387 6386 elem_start = mgmt->u.s1g_assoc_resp.variable; 6388 - else 6387 + max_aid = IEEE80211_MAX_SUPPORTED_S1G_AID; 6388 + } else { 6389 6389 elem_start = mgmt->u.assoc_resp.variable; 6390 + } 6390 6391 6391 6392 /* 6392 6393 * Note: this may not be perfect, AP might misbehave - if ··· 6412 6409 6413 6410 if (elems->aid_resp) 6414 6411 aid = le16_to_cpu(elems->aid_resp->aid); 6415 - else if (assoc_data->s1g) 6416 - aid = 0; /* TODO */ 6417 6412 else 6418 6413 aid = le16_to_cpu(mgmt->u.assoc_resp.aid); 6419 6414 6420 6415 /* 6421 - * The 5 MSB of the AID field are reserved 6422 - * (802.11-2016 9.4.1.8 AID field) 6416 + * The 5 MSB of the AID field are reserved for a non-S1G STA. For 6417 + * an S1G STA the 3 MSBs are reserved. 6418 + * (802.11-2016 9.4.1.8 AID field). 6423 6419 */ 6424 - aid &= 0x7ff; 6420 + aid &= assoc_data->s1g ? 0x1fff : 0x7ff; 6425 6421 6426 6422 sdata_info(sdata, 6427 6423 "RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n", ··· 6457 6455 event.u.mlme.reason = status_code; 6458 6456 drv_event_callback(sdata->local, sdata, &event); 6459 6457 } else { 6460 - if (aid == 0 || aid > IEEE80211_MAX_AID) { 6458 + if (aid == 0 || aid > max_aid) { 6461 6459 sdata_info(sdata, 6462 6460 "invalid AID value %d (out of range), turn off PS\n", 6463 6461 aid); ··· 6495 6493 } 6496 6494 6497 6495 sdata->vif.cfg.aid = aid; 6496 + sdata->vif.cfg.s1g = assoc_data->s1g; 6498 6497 6499 6498 if (!ieee80211_assoc_success(sdata, mgmt, elems, 6500 6499 elem_start, elem_len)) { ··· 7443 7440 ncrc = elems->crc; 7444 7441 7445 7442 if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) && 7446 - ieee80211_check_tim(elems->tim, elems->tim_len, vif_cfg->aid)) { 7443 + ieee80211_check_tim(elems->tim, elems->tim_len, vif_cfg->aid, 7444 + vif_cfg->s1g)) { 7447 7445 if (local->hw.conf.dynamic_ps_timeout > 0) { 7448 7446 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 7449 7447 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+9 -4
net/mac80211/sta_info.c
··· 2962 2962 struct ieee80211_sub_if_data *sdata = sta->sdata; 2963 2963 struct ieee80211_local *local = sdata->local; 2964 2964 u32 thr = 0; 2965 - int i, ac, cpu, link_id; 2965 + int i, ac, cpu; 2966 2966 struct ieee80211_sta_rx_stats *last_rxstats; 2967 2967 2968 2968 last_rxstats = sta_get_last_rx_stats(sta, -1); ··· 3204 3204 if (sta->sta.valid_links) { 3205 3205 struct ieee80211_link_data *link; 3206 3206 struct link_sta_info *link_sta; 3207 + int link_id; 3207 3208 3208 3209 ether_addr_copy(sinfo->mld_addr, sta->addr); 3210 + 3211 + /* assign valid links first for iteration */ 3212 + sinfo->valid_links = sta->sta.valid_links; 3213 + 3209 3214 for_each_valid_link(sinfo, link_id) { 3210 3215 link_sta = wiphy_dereference(sta->local->hw.wiphy, 3211 3216 sta->link[link_id]); 3212 3217 link = wiphy_dereference(sdata->local->hw.wiphy, 3213 3218 sdata->link[link_id]); 3214 3219 3215 - if (!link_sta || !sinfo->links[link_id] || !link) 3220 + if (!link_sta || !sinfo->links[link_id] || !link) { 3221 + sinfo->valid_links &= ~BIT(link_id); 3216 3222 continue; 3217 - 3218 - sinfo->valid_links = sta->sta.valid_links; 3223 + } 3219 3224 sta_set_link_sinfo(sta, sinfo->links[link_id], 3220 3225 link, tidstats); 3221 3226 }
+1 -1
net/mac80211/tests/Makefile
··· 1 - mac80211-tests-y += module.o util.o elems.o mfp.o tpe.o chan-mode.o 1 + mac80211-tests-y += module.o util.o elems.o mfp.o tpe.o chan-mode.o s1g_tim.o 2 2 3 3 obj-$(CONFIG_MAC80211_KUNIT_TEST) += mac80211-tests.o
+356
net/mac80211/tests/s1g_tim.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * KUnit tests for S1G TIM PVB decoding. This test suite covers 4 + * IEEE80211-2024 Annex L figures 8, 9, 10, 12, 13, 14. ADE mode 5 + * is not covered as it is an optional encoding format and is not 6 + * currently supported by mac80211. 7 + * 8 + * Copyright (C) 2025 Morse Micro 9 + */ 10 + #include <linux/ieee80211.h> 11 + #include <kunit/test.h> 12 + #include <kunit/test-bug.h> 13 + 14 + #define MAX_AID 128 15 + 16 + #define BC(enc_mode, inverse, blk_off) \ 17 + ((((blk_off) & 0x1f) << 3) | ((inverse) ? BIT(2) : 0) | \ 18 + ((enc_mode) & 0x3)) 19 + 20 + static void byte_to_bitstr(u8 v, char *out) 21 + { 22 + for (int b = 7; b >= 0; b--) 23 + *out++ = (v & BIT(b)) ? '1' : '0'; 24 + *out = '\0'; 25 + } 26 + 27 + static void dump_tim_bits(struct kunit *test, 28 + const struct ieee80211_tim_ie *tim, u8 tim_len) 29 + { 30 + const u8 *ptr = tim->virtual_map; 31 + const u8 *end = (const u8 *)tim + tim_len; 32 + unsigned int oct = 1; 33 + unsigned int blk = 0; 34 + char bits[9]; 35 + 36 + while (ptr < end) { 37 + u8 ctrl = *ptr++; 38 + u8 mode = ctrl & 0x03; 39 + bool inverse = ctrl & BIT(2); 40 + u8 blk_off = ctrl >> 3; 41 + 42 + kunit_info( 43 + test, "Block %u (ENC=%s, blk_off=%u, inverse=%u)", blk, 44 + (mode == IEEE80211_S1G_TIM_ENC_MODE_BLOCK) ? "BLOCK" : 45 + (mode == IEEE80211_S1G_TIM_ENC_MODE_SINGLE) ? "SINGLE" : 46 + "OLB", 47 + blk_off, inverse); 48 + 49 + byte_to_bitstr(ctrl, bits); 50 + kunit_info(test, " octet %2u (ctrl) : %s (0x%02x)", oct, 51 + bits, ctrl); 52 + ++oct; 53 + 54 + switch (mode) { 55 + case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: { 56 + u8 blkmap = *ptr++; 57 + 58 + byte_to_bitstr(blkmap, bits); 59 + kunit_info(test, " octet %2u (blk-map) : %s (0x%02x)", 60 + oct, bits, blkmap); 61 + ++oct; 62 + 63 + for (u8 sb = 0; sb < 8; sb++) { 64 + if (!(blkmap & BIT(sb))) 65 + continue; 66 + u8 sub = *ptr++; 67 + 68 + byte_to_bitstr(sub, bits); 69 + kunit_info( 70 + test, 71 + " octet %2u (SB %2u) : %s (0x%02x)", 72 + oct, sb, bits, sub); 73 + ++oct; 74 + } 75 + break; 76 + } 77 + case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: { 78 + u8 single = *ptr++; 79 + 80 + byte_to_bitstr(single, bits); 81 + kunit_info(test, " octet %2u (single) : %s (0x%02x)", 82 + oct, bits, single); 83 + ++oct; 84 + break; 85 + } 86 + case IEEE80211_S1G_TIM_ENC_MODE_OLB: { 87 + u8 len = *ptr++; 88 + 89 + byte_to_bitstr(len, bits); 90 + kunit_info(test, " octet %2u (len=%2u) : %s (0x%02x)", 91 + oct, len, bits, len); 92 + ++oct; 93 + 94 + for (u8 i = 0; i < len && ptr < end; i++) { 95 + u8 sub = *ptr++; 96 + 97 + byte_to_bitstr(sub, bits); 98 + kunit_info( 99 + test, 100 + " octet %2u (SB %2u) : %s (0x%02x)", 101 + oct, i, bits, sub); 102 + ++oct; 103 + } 104 + break; 105 + } 106 + default: 107 + kunit_info(test, " ** unknown encoding 0x%x **", mode); 108 + return; 109 + } 110 + blk++; 111 + } 112 + } 113 + 114 + static void tim_push(u8 **p, u8 v) 115 + { 116 + *(*p)++ = v; 117 + } 118 + 119 + static void tim_begin(struct ieee80211_tim_ie *tim, u8 **p) 120 + { 121 + tim->dtim_count = 0; 122 + tim->dtim_period = 1; 123 + tim->bitmap_ctrl = 0; 124 + *p = tim->virtual_map; 125 + } 126 + 127 + static u8 tim_end(struct ieee80211_tim_ie *tim, u8 *tail) 128 + { 129 + return tail - (u8 *)tim; 130 + } 131 + 132 + static void pvb_add_block_bitmap(u8 **p, u8 blk_off, bool inverse, u8 blk_bmap, 133 + const u8 *subblocks) 134 + { 135 + u8 enc = IEEE80211_S1G_TIM_ENC_MODE_BLOCK; 136 + u8 n = hweight8(blk_bmap); 137 + 138 + tim_push(p, BC(enc, inverse, blk_off)); 139 + tim_push(p, blk_bmap); 140 + 141 + for (u8 i = 0; i < n; i++) 142 + tim_push(p, subblocks[i]); 143 + } 144 + 145 + static void pvb_add_single_aid(u8 **p, u8 blk_off, bool inverse, u8 single6) 146 + { 147 + u8 enc = IEEE80211_S1G_TIM_ENC_MODE_SINGLE; 148 + 149 + tim_push(p, BC(enc, inverse, blk_off)); 150 + tim_push(p, single6 & GENMASK(5, 0)); 151 + } 152 + 153 + static void pvb_add_olb(u8 **p, u8 blk_off, bool inverse, const u8 *subblocks, 154 + u8 len) 155 + { 156 + u8 enc = IEEE80211_S1G_TIM_ENC_MODE_OLB; 157 + 158 + tim_push(p, BC(enc, inverse, blk_off)); 159 + tim_push(p, len); 160 + for (u8 i = 0; i < len; i++) 161 + tim_push(p, subblocks[i]); 162 + } 163 + 164 + static void check_all_aids(struct kunit *test, 165 + const struct ieee80211_tim_ie *tim, u8 tim_len, 166 + const unsigned long *expected) 167 + { 168 + for (u16 aid = 1; aid <= MAX_AID; aid++) { 169 + bool want = test_bit(aid, expected); 170 + bool got = ieee80211_s1g_check_tim(tim, tim_len, aid); 171 + 172 + KUNIT_ASSERT_EQ_MSG(test, got, want, 173 + "AID %u mismatch (got=%d want=%d)", aid, 174 + got, want); 175 + } 176 + } 177 + 178 + static void fill_bitmap(unsigned long *bm, const u16 *list, size_t n) 179 + { 180 + size_t i; 181 + 182 + bitmap_zero(bm, MAX_AID + 1); 183 + for (i = 0; i < n; i++) 184 + __set_bit(list[i], bm); 185 + } 186 + 187 + static void fill_bitmap_inverse(unsigned long *bm, u16 max_aid, 188 + const u16 *except, size_t n_except) 189 + { 190 + bitmap_zero(bm, MAX_AID + 1); 191 + for (u16 aid = 1; aid <= max_aid; aid++) 192 + __set_bit(aid, bm); 193 + 194 + for (size_t i = 0; i < n_except; i++) 195 + if (except[i] <= max_aid) 196 + __clear_bit(except[i], bm); 197 + } 198 + 199 + static void s1g_tim_block_test(struct kunit *test) 200 + { 201 + u8 buf[256] = {}; 202 + struct ieee80211_tim_ie *tim = (void *)buf; 203 + u8 *p, tim_len; 204 + static const u8 subblocks[] = { 205 + 0x42, /* SB m=0: AIDs 1,6 */ 206 + 0xA0, /* SB m=2: AIDs 21,23 */ 207 + }; 208 + u8 blk_bmap = 0x05; /* bits 0 and 2 set */ 209 + bool inverse = false; 210 + static const u16 set_list[] = { 1, 6, 21, 23 }; 211 + DECLARE_BITMAP(exp, MAX_AID + 1); 212 + 213 + tim_begin(tim, &p); 214 + pvb_add_block_bitmap(&p, 0, inverse, blk_bmap, subblocks); 215 + tim_len = tim_end(tim, p); 216 + 217 + fill_bitmap(exp, set_list, ARRAY_SIZE(set_list)); 218 + 219 + dump_tim_bits(test, tim, tim_len); 220 + check_all_aids(test, tim, tim_len, exp); 221 + } 222 + 223 + static void s1g_tim_single_test(struct kunit *test) 224 + { 225 + u8 buf[256] = {}; 226 + struct ieee80211_tim_ie *tim = (void *)buf; 227 + u8 *p, tim_len; 228 + bool inverse = false; 229 + u8 blk_off = 0; 230 + u8 single6 = 0x1f; /* 31 */ 231 + static const u16 set_list[] = { 31 }; 232 + DECLARE_BITMAP(exp, MAX_AID + 1); 233 + 234 + tim_begin(tim, &p); 235 + pvb_add_single_aid(&p, blk_off, inverse, single6); 236 + tim_len = tim_end(tim, p); 237 + 238 + fill_bitmap(exp, set_list, ARRAY_SIZE(set_list)); 239 + 240 + dump_tim_bits(test, tim, tim_len); 241 + check_all_aids(test, tim, tim_len, exp); 242 + } 243 + 244 + static void s1g_tim_olb_test(struct kunit *test) 245 + { 246 + u8 buf[256] = {}; 247 + struct ieee80211_tim_ie *tim = (void *)buf; 248 + u8 *p, tim_len; 249 + bool inverse = false; 250 + u8 blk_off = 0; 251 + static const u16 set_list[] = { 1, 6, 13, 15, 17, 22, 29, 31, 33, 252 + 38, 45, 47, 49, 54, 61, 63, 65, 70 }; 253 + static const u8 subblocks[] = { 0x42, 0xA0, 0x42, 0xA0, 0x42, 254 + 0xA0, 0x42, 0xA0, 0x42 }; 255 + u8 len = ARRAY_SIZE(subblocks); 256 + DECLARE_BITMAP(exp, MAX_AID + 1); 257 + 258 + tim_begin(tim, &p); 259 + pvb_add_olb(&p, blk_off, inverse, subblocks, len); 260 + tim_len = tim_end(tim, p); 261 + 262 + fill_bitmap(exp, set_list, ARRAY_SIZE(set_list)); 263 + 264 + dump_tim_bits(test, tim, tim_len); 265 + check_all_aids(test, tim, tim_len, exp); 266 + } 267 + 268 + static void s1g_tim_inverse_block_test(struct kunit *test) 269 + { 270 + u8 buf[256] = {}; 271 + struct ieee80211_tim_ie *tim = (void *)buf; 272 + u8 *p, tim_len; 273 + /* Same sub-block content as Figure L-8, but inverse = true */ 274 + static const u8 subblocks[] = { 275 + 0x42, /* SB m=0: AIDs 1,6 */ 276 + 0xA0, /* SB m=2: AIDs 21,23 */ 277 + }; 278 + u8 blk_bmap = 0x05; 279 + bool inverse = true; 280 + /* All AIDs except 1,6,21,23 are set */ 281 + static const u16 except[] = { 1, 6, 21, 23 }; 282 + DECLARE_BITMAP(exp, MAX_AID + 1); 283 + 284 + tim_begin(tim, &p); 285 + pvb_add_block_bitmap(&p, 0, inverse, blk_bmap, subblocks); 286 + tim_len = tim_end(tim, p); 287 + 288 + fill_bitmap_inverse(exp, 63, except, ARRAY_SIZE(except)); 289 + 290 + dump_tim_bits(test, tim, tim_len); 291 + check_all_aids(test, tim, tim_len, exp); 292 + } 293 + 294 + static void s1g_tim_inverse_single_test(struct kunit *test) 295 + { 296 + u8 buf[256] = {}; 297 + struct ieee80211_tim_ie *tim = (void *)buf; 298 + u8 *p, tim_len; 299 + bool inverse = true; 300 + u8 blk_off = 0; 301 + u8 single6 = 0x1f; /* 31 */ 302 + /* All AIDs except 31 are set */ 303 + static const u16 except[] = { 31 }; 304 + DECLARE_BITMAP(exp, MAX_AID + 1); 305 + 306 + tim_begin(tim, &p); 307 + pvb_add_single_aid(&p, blk_off, inverse, single6); 308 + tim_len = tim_end(tim, p); 309 + 310 + fill_bitmap_inverse(exp, 63, except, ARRAY_SIZE(except)); 311 + 312 + dump_tim_bits(test, tim, tim_len); 313 + check_all_aids(test, tim, tim_len, exp); 314 + } 315 + 316 + static void s1g_tim_inverse_olb_test(struct kunit *test) 317 + { 318 + u8 buf[256] = {}; 319 + struct ieee80211_tim_ie *tim = (void *)buf; 320 + u8 *p, tim_len; 321 + bool inverse = true; 322 + u8 blk_off = 0, len; 323 + /* All AIDs except the list below are set */ 324 + static const u16 except[] = { 1, 6, 13, 15, 17, 22, 29, 31, 33, 325 + 38, 45, 47, 49, 54, 61, 63, 65, 70 }; 326 + static const u8 subblocks[] = { 0x42, 0xA0, 0x42, 0xA0, 0x42, 327 + 0xA0, 0x42, 0xA0, 0x42 }; 328 + len = ARRAY_SIZE(subblocks); 329 + DECLARE_BITMAP(exp, MAX_AID + 1); 330 + 331 + tim_begin(tim, &p); 332 + pvb_add_olb(&p, blk_off, inverse, subblocks, len); 333 + tim_len = tim_end(tim, p); 334 + 335 + fill_bitmap_inverse(exp, 127, except, ARRAY_SIZE(except)); 336 + 337 + dump_tim_bits(test, tim, tim_len); 338 + check_all_aids(test, tim, tim_len, exp); 339 + } 340 + 341 + static struct kunit_case s1g_tim_test_cases[] = { 342 + KUNIT_CASE(s1g_tim_block_test), 343 + KUNIT_CASE(s1g_tim_single_test), 344 + KUNIT_CASE(s1g_tim_olb_test), 345 + KUNIT_CASE(s1g_tim_inverse_block_test), 346 + KUNIT_CASE(s1g_tim_inverse_single_test), 347 + KUNIT_CASE(s1g_tim_inverse_olb_test), 348 + {} 349 + }; 350 + 351 + static struct kunit_suite s1g_tim = { 352 + .name = "mac80211-s1g-tim", 353 + .test_cases = s1g_tim_test_cases, 354 + }; 355 + 356 + kunit_test_suite(s1g_tim);
+133 -40
net/mac80211/tx.c
··· 1814 1814 1815 1815 txh_done: 1816 1816 if (unlikely(res == TX_DROP)) { 1817 + tx->sdata->tx_handlers_drop++; 1817 1818 I802_DEBUG_INC(tx->local->tx_handlers_drop); 1818 1819 if (tx->skb) 1819 1820 ieee80211_free_txskb(&tx->local->hw, tx->skb); ··· 1859 1858 1860 1859 txh_done: 1861 1860 if (unlikely(res == TX_DROP)) { 1861 + tx->sdata->tx_handlers_drop++; 1862 1862 I802_DEBUG_INC(tx->local->tx_handlers_drop); 1863 1863 if (tx->skb) 1864 1864 ieee80211_free_txskb(&tx->local->hw, tx->skb); ··· 1944 1942 1945 1943 if (unlikely(res_prepare == TX_DROP)) { 1946 1944 ieee80211_free_txskb(&local->hw, skb); 1945 + tx.sdata->tx_handlers_drop++; 1947 1946 return true; 1948 1947 } else if (unlikely(res_prepare == TX_QUEUED)) { 1949 1948 return true; ··· 3731 3728 r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs, 3732 3729 fast_tx->key, &tx); 3733 3730 tx.skb = NULL; 3734 - if (r == TX_DROP) 3731 + if (r == TX_DROP) { 3732 + tx.sdata->tx_handlers_drop++; 3735 3733 goto free; 3734 + } 3736 3735 3737 3736 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 3738 3737 sdata = container_of(sdata->bss, ··· 4887 4882 4888 4883 /* functions for drivers to get certain frames */ 4889 4884 4885 + static void ieee80211_beacon_add_tim_pvb(struct ps_data *ps, 4886 + struct sk_buff *skb, 4887 + bool mcast_traffic) 4888 + { 4889 + int i, n1 = 0, n2; 4890 + 4891 + /* 4892 + * Find largest even number N1 so that bits numbered 1 through 4893 + * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits 4894 + * (N2 + 1) x 8 through 2007 are 0. 4895 + */ 4896 + for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) { 4897 + if (ps->tim[i]) { 4898 + n1 = i & 0xfe; 4899 + break; 4900 + } 4901 + } 4902 + n2 = n1; 4903 + for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) { 4904 + if (ps->tim[i]) { 4905 + n2 = i; 4906 + break; 4907 + } 4908 + } 4909 + 4910 + /* Bitmap control */ 4911 + skb_put_u8(skb, n1 | mcast_traffic); 4912 + /* Part Virt Bitmap */ 4913 + skb_put_data(skb, ps->tim + n1, n2 - n1 + 1); 4914 + } 4915 + 4916 + /* 4917 + * mac80211 currently supports encoding using block bitmap mode, non 4918 + * inversed. The current implementation supports up to 1600 AIDs. 4919 + * 4920 + * Block bitmap encoding breaks down the AID bitmap into blocks of 64 4921 + * AIDs. Each block contains between 0 and 8 subblocks. Each subblock 4922 + * describes 8 AIDs and the presence of a subblock is determined by 4923 + * the block bitmap. 4924 + */ 4925 + static void ieee80211_s1g_beacon_add_tim_pvb(struct ps_data *ps, 4926 + struct sk_buff *skb, 4927 + bool mcast_traffic) 4928 + { 4929 + int blk; 4930 + 4931 + /* 4932 + * Emit a bitmap control block with a page slice number of 31 and a 4933 + * page index of 0 which indicates as per IEEE80211-2024 9.4.2.5.1 4934 + * that the entire page (2048 bits) indicated by the page index 4935 + * is encoded in the partial virtual bitmap. 4936 + */ 4937 + skb_put_u8(skb, mcast_traffic | (31 << 1)); 4938 + 4939 + /* Emit an encoded block for each non-zero sub-block */ 4940 + for (blk = 0; blk < IEEE80211_MAX_SUPPORTED_S1G_TIM_BLOCKS; blk++) { 4941 + u8 blk_bmap = 0; 4942 + int sblk; 4943 + 4944 + for (sblk = 0; sblk < 8; sblk++) { 4945 + int sblk_idx = blk * 8 + sblk; 4946 + 4947 + /* 4948 + * If the current subblock is non-zero, increase the 4949 + * number of subblocks to emit for the current block. 4950 + */ 4951 + if (ps->tim[sblk_idx]) 4952 + blk_bmap |= BIT(sblk); 4953 + } 4954 + 4955 + /* If the current block contains no non-zero sublocks */ 4956 + if (!blk_bmap) 4957 + continue; 4958 + 4959 + /* 4960 + * Emit a block control byte for the current encoded block 4961 + * with an encoding mode of block bitmap (0x0), not inverse 4962 + * (0x0) and the current block offset (5 bits) 4963 + */ 4964 + skb_put_u8(skb, blk << 3); 4965 + 4966 + /* 4967 + * Emit the block bitmap for the current encoded block which 4968 + * contains the present subblocks. 4969 + */ 4970 + skb_put_u8(skb, blk_bmap); 4971 + 4972 + /* Emit the present subblocks */ 4973 + for (sblk = 0; sblk < 8; sblk++) { 4974 + int sblk_idx = blk * 8 + sblk; 4975 + 4976 + if (!(blk_bmap & BIT(sblk))) 4977 + continue; 4978 + 4979 + skb_put_u8(skb, ps->tim[sblk_idx]); 4980 + } 4981 + } 4982 + } 4983 + 4890 4984 static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, 4891 4985 struct ieee80211_link_data *link, 4892 4986 struct ps_data *ps, struct sk_buff *skb, 4893 4987 bool is_template) 4894 4988 { 4895 - u8 *pos, *tim; 4896 - int aid0 = 0; 4897 - int i, have_bits = 0, n1, n2; 4989 + struct element *tim; 4990 + bool mcast_traffic = false, have_bits = false; 4898 4991 struct ieee80211_bss_conf *link_conf = link->conf; 4992 + bool s1g = ieee80211_get_link_sband(link)->band == NL80211_BAND_S1GHZ; 4899 4993 4900 4994 /* Generate bitmap for TIM only if there are any STAs in power save 4901 4995 * mode. */ ··· 5002 4898 /* in the hope that this is faster than 5003 4899 * checking byte-for-byte */ 5004 4900 have_bits = !bitmap_empty((unsigned long *)ps->tim, 5005 - IEEE80211_MAX_AID+1); 4901 + IEEE80211_MAX_AID + 1); 4902 + 5006 4903 if (!is_template) { 5007 4904 if (ps->dtim_count == 0) 5008 4905 ps->dtim_count = link_conf->dtim_period - 1; ··· 5011 4906 ps->dtim_count--; 5012 4907 } 5013 4908 5014 - tim = pos = skb_put(skb, 5); 5015 - *pos++ = WLAN_EID_TIM; 5016 - *pos++ = 3; 5017 - *pos++ = ps->dtim_count; 5018 - *pos++ = link_conf->dtim_period; 4909 + /* Length is set after parsing the AID bitmap */ 4910 + tim = skb_put(skb, sizeof(struct element)); 4911 + tim->id = WLAN_EID_TIM; 4912 + skb_put_u8(skb, ps->dtim_count); 4913 + skb_put_u8(skb, link_conf->dtim_period); 5019 4914 5020 4915 if (ps->dtim_count == 0 && !skb_queue_empty(&ps->bc_buf)) 5021 - aid0 = 1; 4916 + mcast_traffic = true; 5022 4917 5023 - ps->dtim_bc_mc = aid0 == 1; 4918 + ps->dtim_bc_mc = mcast_traffic; 5024 4919 5025 4920 if (have_bits) { 5026 - /* Find largest even number N1 so that bits numbered 1 through 5027 - * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits 5028 - * (N2 + 1) x 8 through 2007 are 0. */ 5029 - n1 = 0; 5030 - for (i = 0; i < IEEE80211_MAX_TIM_LEN; i++) { 5031 - if (ps->tim[i]) { 5032 - n1 = i & 0xfe; 5033 - break; 5034 - } 5035 - } 5036 - n2 = n1; 5037 - for (i = IEEE80211_MAX_TIM_LEN - 1; i >= n1; i--) { 5038 - if (ps->tim[i]) { 5039 - n2 = i; 5040 - break; 5041 - } 5042 - } 5043 - 5044 - /* Bitmap control */ 5045 - *pos++ = n1 | aid0; 5046 - /* Part Virt Bitmap */ 5047 - skb_put_data(skb, ps->tim + n1, n2 - n1 + 1); 5048 - 5049 - tim[1] = n2 - n1 + 4; 4921 + if (s1g) 4922 + ieee80211_s1g_beacon_add_tim_pvb(ps, skb, 4923 + mcast_traffic); 4924 + else 4925 + ieee80211_beacon_add_tim_pvb(ps, skb, mcast_traffic); 5050 4926 } else { 5051 - *pos++ = aid0; /* Bitmap control */ 5052 - 5053 - if (ieee80211_get_link_sband(link)->band != NL80211_BAND_S1GHZ) { 5054 - tim[1] = 4; 4927 + /* 4928 + * If there is no buffered unicast traffic for an S1G 4929 + * interface, we can exclude the bitmap control. This is in 4930 + * contrast to other phy types as they do include the bitmap 4931 + * control and pvb even when there is no buffered traffic. 4932 + */ 4933 + if (!s1g) { 4934 + /* Bitmap control */ 4935 + skb_put_u8(skb, mcast_traffic); 5055 4936 /* Part Virt Bitmap */ 5056 4937 skb_put_u8(skb, 0); 5057 4938 } 5058 4939 } 4940 + 4941 + tim->datalen = skb_tail_pointer(skb) - tim->data; 5059 4942 } 5060 4943 5061 4944 static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
+9 -11
net/mac80211/util.c
··· 1756 1756 bool sched_scan_stopped = false; 1757 1757 bool suspended = local->suspended; 1758 1758 bool in_reconfig = false; 1759 - u32 rts_threshold; 1760 1759 1761 1760 lockdep_assert_wiphy(local->hw.wiphy); 1762 1761 ··· 1831 1832 /* setup RTS threshold */ 1832 1833 if (hw->wiphy->n_radio > 0) { 1833 1834 for (i = 0; i < hw->wiphy->n_radio; i++) { 1834 - rts_threshold = hw->wiphy->radio_cfg[i].rts_threshold; 1835 + u32 rts_threshold = 1836 + hw->wiphy->radio_cfg[i].rts_threshold; 1837 + 1835 1838 drv_set_rts_threshold(local, i, rts_threshold); 1836 1839 } 1837 1840 } else { ··· 4023 4022 for (i = 0; i < scan_req->n_channels; i++) { 4024 4023 chan = scan_req->channels[i]; 4025 4024 chan_radio_idx = cfg80211_get_radio_idx_by_chan(wiphy, chan); 4026 - /* 4027 - * The chan_radio_idx should be valid since it's taken from a 4028 - * valid scan request. 4029 - * However, if chan_radio_idx is unexpectedly invalid (negative), 4030 - * we take a conservative approach and assume the scan request 4031 - * might use the specified radio_idx. Hence, return true. 4032 - */ 4033 - if (WARN_ON(chan_radio_idx < 0)) 4034 - return true; 4035 4025 4026 + /* The radio index either matched successfully, or an error 4027 + * occurred. For example, if radio-level information is 4028 + * missing, the same error value is returned. This 4029 + * typically implies a single-radio setup, in which case 4030 + * the operation should not be allowed. 4031 + */ 4036 4032 if (chan_radio_idx == radio_idx) 4037 4033 return true; 4038 4034 }
+9
net/wireless/core.c
··· 1018 1018 1019 1019 rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH; 1020 1020 1021 + if (rdev->wiphy.bss_param_support & WIPHY_BSS_PARAM_P2P_CTWINDOW) 1022 + rdev->wiphy.features |= NL80211_FEATURE_P2P_GO_CTWIN; 1023 + else if (rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN) 1024 + rdev->wiphy.bss_param_support |= WIPHY_BSS_PARAM_P2P_CTWINDOW; 1025 + if (rdev->wiphy.bss_param_support & WIPHY_BSS_PARAM_P2P_OPPPS) 1026 + rdev->wiphy.features |= NL80211_FEATURE_P2P_GO_OPPPS; 1027 + else if (rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS) 1028 + rdev->wiphy.bss_param_support |= WIPHY_BSS_PARAM_P2P_OPPPS; 1029 + 1021 1030 rtnl_lock(); 1022 1031 wiphy_lock(&rdev->wiphy); 1023 1032 res = device_add(&rdev->wiphy.dev);
+1 -1
net/wireless/ethtool.c
··· 23 23 else 24 24 strscpy(info->fw_version, "N/A", sizeof(info->fw_version)); 25 25 26 - strscpy(info->bus_info, dev_name(wiphy_dev(wdev->wiphy)), 26 + strscpy(info->bus_info, dev_name(pdev), 27 27 sizeof(info->bus_info)); 28 28 } 29 29 EXPORT_SYMBOL(cfg80211_get_drvinfo);
+305 -13
net/wireless/nl80211.c
··· 411 411 [NL80211_TXRATE_HE_LTF] = NLA_POLICY_RANGE(NLA_U8, 412 412 NL80211_RATE_INFO_HE_1XLTF, 413 413 NL80211_RATE_INFO_HE_4XLTF), 414 + [NL80211_TXRATE_EHT] = NLA_POLICY_EXACT_LEN(sizeof(struct nl80211_txrate_eht)), 415 + [NL80211_TXRATE_EHT_GI] = NLA_POLICY_RANGE(NLA_U8, 416 + NL80211_RATE_INFO_EHT_GI_0_8, 417 + NL80211_RATE_INFO_EHT_GI_3_2), 418 + [NL80211_TXRATE_EHT_LTF] = NLA_POLICY_RANGE(NLA_U8, 419 + NL80211_RATE_INFO_EHT_1XLTF, 420 + NL80211_RATE_INFO_EHT_8XLTF), 421 + 414 422 }; 415 423 416 424 static const struct nla_policy ··· 879 871 [NL80211_ATTR_S1G_LONG_BEACON_PERIOD] = NLA_POLICY_MIN(NLA_U8, 2), 880 872 [NL80211_ATTR_S1G_SHORT_BEACON] = 881 873 NLA_POLICY_NESTED(nl80211_s1g_short_beacon), 874 + [NL80211_ATTR_BSS_PARAM] = { .type = NLA_FLAG }, 882 875 }; 883 876 884 877 /* policy for the key attributes */ ··· 3028 3019 rdev->wiphy.ext_features)) 3029 3020 goto nla_put_failure; 3030 3021 3022 + if (rdev->wiphy.bss_param_support) { 3023 + struct nlattr *nested; 3024 + u32 parsup = rdev->wiphy.bss_param_support; 3025 + 3026 + nested = nla_nest_start(msg, NL80211_ATTR_BSS_PARAM); 3027 + if (!nested) 3028 + goto nla_put_failure; 3029 + 3030 + if ((parsup & WIPHY_BSS_PARAM_CTS_PROT) && 3031 + nla_put_flag(msg, NL80211_ATTR_BSS_CTS_PROT)) 3032 + goto nla_put_failure; 3033 + if ((parsup & WIPHY_BSS_PARAM_SHORT_PREAMBLE) && 3034 + nla_put_flag(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE)) 3035 + goto nla_put_failure; 3036 + if ((parsup & WIPHY_BSS_PARAM_SHORT_SLOT_TIME) && 3037 + nla_put_flag(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME)) 3038 + goto nla_put_failure; 3039 + if ((parsup & WIPHY_BSS_PARAM_BASIC_RATES) && 3040 + nla_put_flag(msg, NL80211_ATTR_BSS_BASIC_RATES)) 3041 + goto nla_put_failure; 3042 + if ((parsup & WIPHY_BSS_PARAM_AP_ISOLATE) && 3043 + nla_put_flag(msg, NL80211_ATTR_AP_ISOLATE)) 3044 + goto nla_put_failure; 3045 + if ((parsup & WIPHY_BSS_PARAM_HT_OPMODE) && 3046 + nla_put_flag(msg, NL80211_ATTR_BSS_HT_OPMODE)) 3047 + goto nla_put_failure; 3048 + if ((parsup & WIPHY_BSS_PARAM_P2P_CTWINDOW) && 3049 + nla_put_flag(msg, NL80211_ATTR_P2P_CTWINDOW)) 3050 + goto nla_put_failure; 3051 + if ((parsup & WIPHY_BSS_PARAM_P2P_OPPPS) && 3052 + nla_put_flag(msg, NL80211_ATTR_P2P_OPPPS)) 3053 + goto nla_put_failure; 3054 + nla_nest_end(msg, nested); 3055 + } 3031 3056 if (rdev->wiphy.bss_select_support) { 3032 3057 struct nlattr *nested; 3033 3058 u32 bss_select_support = rdev->wiphy.bss_select_support; ··· 5436 5393 return true; 5437 5394 } 5438 5395 5396 + static void eht_build_mcs_mask(struct genl_info *info, 5397 + const struct ieee80211_sta_eht_cap *eht_cap, 5398 + u8 mcs_nss_len, u16 *mcs_mask) 5399 + { 5400 + struct net_device *dev = info->user_ptr[1]; 5401 + struct wireless_dev *wdev = dev->ieee80211_ptr; 5402 + u8 nss, mcs_7 = 0, mcs_9 = 0, mcs_11 = 0, mcs_13 = 0; 5403 + unsigned int link_id = nl80211_link_id(info->attrs); 5404 + 5405 + if (mcs_nss_len == 4) { 5406 + const struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs = 5407 + &eht_cap->eht_mcs_nss_supp.only_20mhz; 5408 + 5409 + mcs_7 = u8_get_bits(mcs->rx_tx_mcs7_max_nss, 5410 + IEEE80211_EHT_MCS_NSS_TX); 5411 + mcs_9 = u8_get_bits(mcs->rx_tx_mcs9_max_nss, 5412 + IEEE80211_EHT_MCS_NSS_TX); 5413 + mcs_11 = u8_get_bits(mcs->rx_tx_mcs11_max_nss, 5414 + IEEE80211_EHT_MCS_NSS_TX); 5415 + mcs_13 = u8_get_bits(mcs->rx_tx_mcs13_max_nss, 5416 + IEEE80211_EHT_MCS_NSS_TX); 5417 + 5418 + } else { 5419 + const struct ieee80211_eht_mcs_nss_supp_bw *mcs; 5420 + enum nl80211_chan_width width; 5421 + 5422 + switch (wdev->iftype) { 5423 + case NL80211_IFTYPE_ADHOC: 5424 + width = wdev->u.ibss.chandef.width; 5425 + break; 5426 + case NL80211_IFTYPE_MESH_POINT: 5427 + width = wdev->u.mesh.chandef.width; 5428 + break; 5429 + case NL80211_IFTYPE_OCB: 5430 + width = wdev->u.ocb.chandef.width; 5431 + break; 5432 + default: 5433 + if (wdev->valid_links) 5434 + width = wdev->links[link_id].ap.chandef.width; 5435 + else 5436 + width = wdev->u.ap.preset_chandef.width; 5437 + break; 5438 + } 5439 + 5440 + switch (width) { 5441 + case NL80211_CHAN_WIDTH_320: 5442 + mcs = &eht_cap->eht_mcs_nss_supp.bw._320; 5443 + break; 5444 + case NL80211_CHAN_WIDTH_160: 5445 + mcs = &eht_cap->eht_mcs_nss_supp.bw._160; 5446 + break; 5447 + default: 5448 + mcs = &eht_cap->eht_mcs_nss_supp.bw._80; 5449 + break; 5450 + } 5451 + 5452 + mcs_7 = u8_get_bits(mcs->rx_tx_mcs9_max_nss, 5453 + IEEE80211_EHT_MCS_NSS_TX); 5454 + mcs_9 = u8_get_bits(mcs->rx_tx_mcs9_max_nss, 5455 + IEEE80211_EHT_MCS_NSS_TX); 5456 + mcs_11 = u8_get_bits(mcs->rx_tx_mcs11_max_nss, 5457 + IEEE80211_EHT_MCS_NSS_TX); 5458 + mcs_13 = u8_get_bits(mcs->rx_tx_mcs13_max_nss, 5459 + IEEE80211_EHT_MCS_NSS_TX); 5460 + } 5461 + 5462 + /* Enable MCS 14 for NSS 0 */ 5463 + if (eht_cap->eht_cap_elem.phy_cap_info[6] & 5464 + IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP) 5465 + mcs_mask[0] |= 0x4000; 5466 + 5467 + /* Enable MCS 15 for NSS 0 */ 5468 + mcs_mask[0] |= 0x8000; 5469 + 5470 + for (nss = 0; nss < NL80211_EHT_NSS_MAX; nss++) { 5471 + if (!mcs_7) 5472 + continue; 5473 + mcs_mask[nss] |= 0x00FF; 5474 + mcs_7--; 5475 + 5476 + if (!mcs_9) 5477 + continue; 5478 + mcs_mask[nss] |= 0x0300; 5479 + mcs_9--; 5480 + 5481 + if (!mcs_11) 5482 + continue; 5483 + mcs_mask[nss] |= 0x0C00; 5484 + mcs_11--; 5485 + 5486 + if (!mcs_13) 5487 + continue; 5488 + mcs_mask[nss] |= 0x3000; 5489 + mcs_13--; 5490 + } 5491 + } 5492 + 5493 + static bool eht_set_mcs_mask(struct genl_info *info, struct wireless_dev *wdev, 5494 + struct ieee80211_supported_band *sband, 5495 + struct nl80211_txrate_eht *txrate, 5496 + u16 mcs[NL80211_EHT_NSS_MAX]) 5497 + { 5498 + const struct ieee80211_sta_he_cap *he_cap; 5499 + const struct ieee80211_sta_eht_cap *eht_cap; 5500 + u16 tx_mcs_mask[NL80211_EHT_NSS_MAX] = { 0 }; 5501 + u8 i, mcs_nss_len; 5502 + 5503 + he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype); 5504 + if (!he_cap) 5505 + return false; 5506 + 5507 + eht_cap = ieee80211_get_eht_iftype_cap(sband, wdev->iftype); 5508 + if (!eht_cap) 5509 + return false; 5510 + 5511 + /* Checks for MCS 14 */ 5512 + if (txrate->mcs[0] & 0x4000) { 5513 + if (sband->band != NL80211_BAND_6GHZ) 5514 + return false; 5515 + 5516 + if (!(eht_cap->eht_cap_elem.phy_cap_info[6] & 5517 + IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP)) 5518 + return false; 5519 + } 5520 + 5521 + mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, 5522 + &eht_cap->eht_cap_elem, 5523 + wdev->iftype == 5524 + NL80211_IFTYPE_STATION); 5525 + 5526 + if (mcs_nss_len == 3) { 5527 + /* Supported iftypes for setting non-20 MHZ only EHT MCS */ 5528 + switch (wdev->iftype) { 5529 + case NL80211_IFTYPE_ADHOC: 5530 + case NL80211_IFTYPE_AP: 5531 + case NL80211_IFTYPE_P2P_GO: 5532 + case NL80211_IFTYPE_MESH_POINT: 5533 + case NL80211_IFTYPE_OCB: 5534 + break; 5535 + default: 5536 + return false; 5537 + } 5538 + } 5539 + 5540 + /* Build eht_mcs_mask from EHT and HE capabilities */ 5541 + eht_build_mcs_mask(info, eht_cap, mcs_nss_len, tx_mcs_mask); 5542 + 5543 + memset(mcs, 0, sizeof(u16) * NL80211_EHT_NSS_MAX); 5544 + for (i = 0; i < NL80211_EHT_NSS_MAX; i++) { 5545 + if ((tx_mcs_mask[i] & txrate->mcs[i]) == txrate->mcs[i]) 5546 + mcs[i] = txrate->mcs[i]; 5547 + else 5548 + return false; 5549 + } 5550 + 5551 + return true; 5552 + } 5553 + 5439 5554 static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, 5440 5555 struct nlattr *attrs[], 5441 5556 enum nl80211_attrs attr, ··· 5614 5413 /* Default to all rates enabled */ 5615 5414 for (i = 0; i < NUM_NL80211_BANDS; i++) { 5616 5415 const struct ieee80211_sta_he_cap *he_cap; 5416 + const struct ieee80211_sta_eht_cap *eht_cap; 5417 + u8 mcs_nss_len; 5617 5418 5618 5419 if (!default_all_enabled) 5619 5420 break; ··· 5644 5441 5645 5442 mask->control[i].he_gi = 0xFF; 5646 5443 mask->control[i].he_ltf = 0xFF; 5444 + 5445 + eht_cap = ieee80211_get_eht_iftype_cap(sband, wdev->iftype); 5446 + if (!eht_cap) 5447 + continue; 5448 + 5449 + mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem, 5450 + &eht_cap->eht_cap_elem, 5451 + wdev->iftype == 5452 + NL80211_IFTYPE_STATION); 5453 + 5454 + eht_build_mcs_mask(info, eht_cap, mcs_nss_len, 5455 + mask->control[i].eht_mcs); 5456 + 5457 + mask->control[i].eht_gi = 0xFF; 5458 + mask->control[i].eht_ltf = 0xFF; 5647 5459 } 5648 5460 5649 5461 /* if no rates are given set it back to the defaults */ ··· 5730 5512 mask->control[band].he_ltf = 5731 5513 nla_get_u8(tb[NL80211_TXRATE_HE_LTF]); 5732 5514 5515 + if (tb[NL80211_TXRATE_EHT] && 5516 + !eht_set_mcs_mask(info, wdev, sband, 5517 + nla_data(tb[NL80211_TXRATE_EHT]), 5518 + mask->control[band].eht_mcs)) 5519 + return -EINVAL; 5520 + 5521 + if (tb[NL80211_TXRATE_EHT_GI]) 5522 + mask->control[band].eht_gi = 5523 + nla_get_u8(tb[NL80211_TXRATE_EHT_GI]); 5524 + if (tb[NL80211_TXRATE_EHT_LTF]) 5525 + mask->control[band].eht_ltf = 5526 + nla_get_u8(tb[NL80211_TXRATE_EHT_LTF]); 5527 + 5733 5528 if (mask->control[band].legacy == 0) { 5734 - /* don't allow empty legacy rates if HT, VHT or HE 5529 + /* don't allow empty legacy rates if HT, VHT, HE or EHT 5735 5530 * are not even supported. 5736 5531 */ 5737 5532 if (!(rdev->wiphy.bands[band]->ht_cap.ht_supported || 5738 5533 rdev->wiphy.bands[band]->vht_cap.vht_supported || 5739 - ieee80211_get_he_iftype_cap(sband, wdev->iftype))) 5534 + ieee80211_get_he_iftype_cap(sband, wdev->iftype) || 5535 + ieee80211_get_eht_iftype_cap(sband, wdev->iftype))) 5740 5536 return -EINVAL; 5741 5537 5742 5538 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) ··· 5763 5531 5764 5532 for (i = 0; i < NL80211_HE_NSS_MAX; i++) 5765 5533 if (mask->control[band].he_mcs[i]) 5534 + goto out; 5535 + 5536 + for (i = 0; i < NL80211_EHT_NSS_MAX; i++) 5537 + if (mask->control[band].eht_mcs[i]) 5766 5538 goto out; 5767 5539 5768 5540 /* legacy and mcs rates may not be both empty */ ··· 5782 5546 enum nl80211_band band, 5783 5547 struct cfg80211_bitrate_mask *beacon_rate) 5784 5548 { 5785 - u32 count_ht, count_vht, count_he, i; 5549 + u32 count_ht, count_vht, count_he, count_eht, i; 5786 5550 u32 rate = beacon_rate->control[band].legacy; 5787 5551 5788 5552 /* Allow only one rate */ ··· 5828 5592 return -EINVAL; 5829 5593 } 5830 5594 5831 - if ((count_ht && count_vht && count_he) || 5832 - (!rate && !count_ht && !count_vht && !count_he)) 5595 + count_eht = 0; 5596 + for (i = 0; i < NL80211_EHT_NSS_MAX; i++) { 5597 + if (hweight16(beacon_rate->control[band].eht_mcs[i]) > 1) { 5598 + return -EINVAL; 5599 + } else if (beacon_rate->control[band].eht_mcs[i]) { 5600 + count_eht++; 5601 + if (count_eht > 1) 5602 + return -EINVAL; 5603 + } 5604 + if (count_eht && rate) 5605 + return -EINVAL; 5606 + } 5607 + 5608 + if ((count_ht && count_vht && count_he && count_eht) || 5609 + (!rate && !count_ht && !count_vht && !count_he && !count_eht)) 5833 5610 return -EINVAL; 5834 5611 5835 5612 if (rate && ··· 5860 5611 if (count_he && 5861 5612 !wiphy_ext_feature_isset(&rdev->wiphy, 5862 5613 NL80211_EXT_FEATURE_BEACON_RATE_HE)) 5614 + return -EINVAL; 5615 + 5616 + if (count_eht && 5617 + !wiphy_ext_feature_isset(&rdev->wiphy, 5618 + NL80211_EXT_FEATURE_BEACON_RATE_EHT)) 5863 5619 return -EINVAL; 5864 5620 5865 5621 return 0; ··· 9084 8830 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 9085 8831 struct net_device *dev = info->user_ptr[1]; 9086 8832 struct bss_parameters params; 8833 + u32 bss_param_support = rdev->wiphy.bss_param_support; 8834 + u32 changed = 0; 8835 + bool strict; 9087 8836 9088 8837 memset(&params, 0, sizeof(params)); 9089 8838 params.link_id = nl80211_link_id_or_invalid(info->attrs); ··· 9099 8842 params.p2p_ctwindow = -1; 9100 8843 params.p2p_opp_ps = -1; 9101 8844 9102 - if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) 8845 + strict = nla_get_flag(info->attrs[NL80211_ATTR_BSS_PARAM]); 8846 + if (info->attrs[NL80211_ATTR_BSS_CTS_PROT]) { 8847 + if (strict && !(bss_param_support & WIPHY_BSS_PARAM_CTS_PROT)) 8848 + return -EINVAL; 9103 8849 params.use_cts_prot = 9104 8850 nla_get_u8(info->attrs[NL80211_ATTR_BSS_CTS_PROT]); 9105 - if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) 8851 + changed |= WIPHY_BSS_PARAM_CTS_PROT; 8852 + } 8853 + if (info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]) { 8854 + if (strict && 8855 + !(bss_param_support & WIPHY_BSS_PARAM_SHORT_PREAMBLE)) 8856 + return -EINVAL; 9106 8857 params.use_short_preamble = 9107 8858 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_PREAMBLE]); 9108 - if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) 8859 + changed |= WIPHY_BSS_PARAM_SHORT_PREAMBLE; 8860 + } 8861 + if (info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]) { 8862 + if (strict && 8863 + !(bss_param_support & WIPHY_BSS_PARAM_SHORT_SLOT_TIME)) 8864 + return -EINVAL; 9109 8865 params.use_short_slot_time = 9110 8866 nla_get_u8(info->attrs[NL80211_ATTR_BSS_SHORT_SLOT_TIME]); 8867 + changed |= WIPHY_BSS_PARAM_SHORT_SLOT_TIME; 8868 + } 9111 8869 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { 8870 + if (strict && 8871 + !(bss_param_support & WIPHY_BSS_PARAM_BASIC_RATES)) 8872 + return -EINVAL; 9112 8873 params.basic_rates = 9113 8874 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 9114 8875 params.basic_rates_len = 9115 8876 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); 8877 + changed |= WIPHY_BSS_PARAM_BASIC_RATES; 9116 8878 } 9117 - if (info->attrs[NL80211_ATTR_AP_ISOLATE]) 9118 - params.ap_isolate = !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); 9119 - if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE]) 8879 + if (info->attrs[NL80211_ATTR_AP_ISOLATE]) { 8880 + if (strict && !(bss_param_support & WIPHY_BSS_PARAM_AP_ISOLATE)) 8881 + return -EINVAL; 8882 + params.ap_isolate = 8883 + !!nla_get_u8(info->attrs[NL80211_ATTR_AP_ISOLATE]); 8884 + changed |= WIPHY_BSS_PARAM_AP_ISOLATE; 8885 + } 8886 + if (info->attrs[NL80211_ATTR_BSS_HT_OPMODE]) { 8887 + if (strict && !(bss_param_support & WIPHY_BSS_PARAM_HT_OPMODE)) 8888 + return -EINVAL; 9120 8889 params.ht_opmode = 9121 8890 nla_get_u16(info->attrs[NL80211_ATTR_BSS_HT_OPMODE]); 8891 + changed |= WIPHY_BSS_PARAM_HT_OPMODE; 8892 + } 9122 8893 9123 8894 if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) { 9124 8895 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) ··· 9154 8869 params.p2p_ctwindow = 9155 8870 nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]); 9156 8871 if (params.p2p_ctwindow != 0 && 9157 - !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) 8872 + !(bss_param_support & WIPHY_BSS_PARAM_P2P_CTWINDOW)) 9158 8873 return -EINVAL; 8874 + changed |= WIPHY_BSS_PARAM_P2P_CTWINDOW; 9159 8875 } 9160 8876 9161 8877 if (info->attrs[NL80211_ATTR_P2P_OPPPS]) { ··· 9165 8879 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 9166 8880 return -EINVAL; 9167 8881 tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]); 8882 + if (tmp && !(bss_param_support & WIPHY_BSS_PARAM_P2P_OPPPS)) 8883 + return -EINVAL; 9168 8884 params.p2p_opp_ps = tmp; 9169 8885 if (params.p2p_opp_ps && 9170 - !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) 8886 + !(rdev->wiphy.bss_param_support & WIPHY_BSS_PARAM_P2P_OPPPS)) 9171 8887 return -EINVAL; 9172 8888 } 9173 8889 ··· 9179 8891 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 9180 8892 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 9181 8893 return -EOPNOTSUPP; 8894 + 8895 + changed &= rdev->wiphy.bss_param_support; 8896 + if (!changed) 8897 + return 0; 9182 8898 9183 8899 return rdev_change_bss(rdev, dev, &params); 9184 8900 }
+7 -2
net/wireless/scan.c
··· 1816 1816 WARN_ON(ies != old_ies); 1817 1817 1818 1818 rcu_assign_pointer(bss->pub.beacon_ies, new_ies); 1819 + 1820 + bss->ts = known->ts; 1821 + bss->pub.ts_boottime = known->pub.ts_boottime; 1819 1822 } 1820 1823 } 1821 1824 ··· 1885 1882 { 1886 1883 lockdep_assert_held(&rdev->bss_lock); 1887 1884 1885 + /* Update time stamps */ 1886 + known->ts = new->ts; 1887 + known->pub.ts_boottime = new->pub.ts_boottime; 1888 + 1888 1889 /* Update IEs */ 1889 1890 if (rcu_access_pointer(new->pub.proberesp_ies)) { 1890 1891 const struct cfg80211_bss_ies *old; ··· 1952 1945 if (signal_valid) 1953 1946 known->pub.signal = new->pub.signal; 1954 1947 known->pub.capability = new->pub.capability; 1955 - known->ts = new->ts; 1956 - known->pub.ts_boottime = new->pub.ts_boottime; 1957 1948 known->parent_tsf = new->parent_tsf; 1958 1949 known->pub.chains = new->pub.chains; 1959 1950 memcpy(known->pub.chain_signal, new->pub.chain_signal,
-56
net/wireless/trace.h
··· 3137 3137 TP_ARGS(netdev, macaddr) 3138 3138 ); 3139 3139 3140 - DECLARE_EVENT_CLASS(netdev_evt_only, 3141 - TP_PROTO(struct net_device *netdev), 3142 - TP_ARGS(netdev), 3143 - TP_STRUCT__entry( 3144 - NETDEV_ENTRY 3145 - ), 3146 - TP_fast_assign( 3147 - NETDEV_ASSIGN; 3148 - ), 3149 - TP_printk(NETDEV_PR_FMT , NETDEV_PR_ARG) 3150 - ); 3151 - 3152 - DEFINE_EVENT(netdev_evt_only, cfg80211_send_rx_auth, 3153 - TP_PROTO(struct net_device *netdev), 3154 - TP_ARGS(netdev) 3155 - ); 3156 - 3157 3140 TRACE_EVENT(cfg80211_send_rx_assoc, 3158 3141 TP_PROTO(struct net_device *netdev, 3159 3142 const struct cfg80211_rx_assoc_resp_data *data), ··· 3461 3478 TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d prohibited_flags=0x%x permitting_flags=0x%x", 3462 3479 WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype, 3463 3480 __entry->prohibited_flags, __entry->permitting_flags) 3464 - ); 3465 - 3466 - TRACE_EVENT(cfg80211_chandef_dfs_required, 3467 - TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), 3468 - TP_ARGS(wiphy, chandef), 3469 - TP_STRUCT__entry( 3470 - WIPHY_ENTRY 3471 - CHAN_DEF_ENTRY 3472 - ), 3473 - TP_fast_assign( 3474 - WIPHY_ASSIGN; 3475 - CHAN_DEF_ASSIGN(chandef); 3476 - ), 3477 - TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, 3478 - WIPHY_PR_ARG, CHAN_DEF_PR_ARG) 3479 3481 ); 3480 3482 3481 3483 TRACE_EVENT(cfg80211_ch_switch_notify, ··· 3828 3860 DEFINE_EVENT(cfg80211_bss_evt, cfg80211_return_bss, 3829 3861 TP_PROTO(struct cfg80211_bss *pub), 3830 3862 TP_ARGS(pub) 3831 - ); 3832 - 3833 - TRACE_EVENT(cfg80211_return_uint, 3834 - TP_PROTO(unsigned int ret), 3835 - TP_ARGS(ret), 3836 - TP_STRUCT__entry( 3837 - __field(unsigned int, ret) 3838 - ), 3839 - TP_fast_assign( 3840 - __entry->ret = ret; 3841 - ), 3842 - TP_printk("ret: %d", __entry->ret) 3843 - ); 3844 - 3845 - TRACE_EVENT(cfg80211_return_u32, 3846 - TP_PROTO(u32 ret), 3847 - TP_ARGS(ret), 3848 - TP_STRUCT__entry( 3849 - __field(u32, ret) 3850 - ), 3851 - TP_fast_assign( 3852 - __entry->ret = ret; 3853 - ), 3854 - TP_printk("ret: %u", __entry->ret) 3855 3863 ); 3856 3864 3857 3865 TRACE_EVENT(cfg80211_report_wowlan_wakeup,
+1 -1
net/wireless/util.c
··· 2584 2584 } 2585 2585 } 2586 2586 2587 - return -ENOENT; 2587 + return -EINVAL; 2588 2588 } 2589 2589 EXPORT_SYMBOL(cfg80211_get_radio_idx_by_chan); 2590 2590