diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
34 files changed, 717 insertions, 227 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 562772d85102..c160dad03037 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -109,7 +109,7 @@ extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg; | |||
109 | 109 | ||
110 | struct iwl_ucode_capabilities; | 110 | struct iwl_ucode_capabilities; |
111 | 111 | ||
112 | extern struct ieee80211_ops iwlagn_hw_ops; | 112 | extern const struct ieee80211_ops iwlagn_hw_ops; |
113 | 113 | ||
114 | static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) | 114 | static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) |
115 | { | 115 | { |
@@ -480,7 +480,7 @@ do { \ | |||
480 | } while (0) | 480 | } while (0) |
481 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 481 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
482 | 482 | ||
483 | extern const char *iwl_dvm_cmd_strings[REPLY_MAX]; | 483 | extern const char *const iwl_dvm_cmd_strings[REPLY_MAX]; |
484 | 484 | ||
485 | static inline const char *iwl_dvm_get_cmd_string(u8 cmd) | 485 | static inline const char *iwl_dvm_get_cmd_string(u8 cmd) |
486 | { | 486 | { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 7b140e487deb..758c54eeb206 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
@@ -317,7 +317,7 @@ static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { | |||
317 | .nrg_th_cca = 62, | 317 | .nrg_th_cca = 62, |
318 | }; | 318 | }; |
319 | 319 | ||
320 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | 320 | static const struct iwl_sensitivity_ranges iwl5150_sensitivity = { |
321 | .min_nrg_cck = 95, | 321 | .min_nrg_cck = 95, |
322 | .auto_corr_min_ofdm = 90, | 322 | .auto_corr_min_ofdm = 90, |
323 | .auto_corr_min_ofdm_mrc = 170, | 323 | .auto_corr_min_ofdm_mrc = 170, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 73086c1629ca..dd55c9cf7ba8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -1582,7 +1582,7 @@ static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | |||
1582 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1582 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
1583 | } | 1583 | } |
1584 | 1584 | ||
1585 | struct ieee80211_ops iwlagn_hw_ops = { | 1585 | const struct ieee80211_ops iwlagn_hw_ops = { |
1586 | .tx = iwlagn_mac_tx, | 1586 | .tx = iwlagn_mac_tx, |
1587 | .start = iwlagn_mac_start, | 1587 | .start = iwlagn_mac_start, |
1588 | .stop = iwlagn_mac_stop, | 1588 | .stop = iwlagn_mac_stop, |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index 7a1bc1c547e1..cd8377346aff 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #define IWL_CMD_ENTRY(x) [x] = #x | 40 | #define IWL_CMD_ENTRY(x) [x] = #x |
41 | 41 | ||
42 | const char *iwl_dvm_cmd_strings[REPLY_MAX] = { | 42 | const char *const iwl_dvm_cmd_strings[REPLY_MAX] = { |
43 | IWL_CMD_ENTRY(REPLY_ALIVE), | 43 | IWL_CMD_ENTRY(REPLY_ALIVE), |
44 | IWL_CMD_ENTRY(REPLY_ERROR), | 44 | IWL_CMD_ENTRY(REPLY_ERROR), |
45 | IWL_CMD_ENTRY(REPLY_ECHO), | 45 | IWL_CMD_ENTRY(REPLY_ECHO), |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index bcfdcfb4485e..0a3e841b44a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -404,6 +404,38 @@ static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data) | |||
404 | return 0; | 404 | return 0; |
405 | } | 405 | } |
406 | 406 | ||
407 | static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data, | ||
408 | struct iwl_ucode_capabilities *capa) | ||
409 | { | ||
410 | const struct iwl_ucode_api *ucode_api = (void *)data; | ||
411 | u32 api_index = le32_to_cpu(ucode_api->api_index); | ||
412 | |||
413 | if (api_index >= IWL_API_ARRAY_SIZE) { | ||
414 | IWL_ERR(drv, "api_index larger than supported by driver\n"); | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | |||
418 | capa->api[api_index] = le32_to_cpu(ucode_api->api_flags); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data, | ||
424 | struct iwl_ucode_capabilities *capa) | ||
425 | { | ||
426 | const struct iwl_ucode_capa *ucode_capa = (void *)data; | ||
427 | u32 api_index = le32_to_cpu(ucode_capa->api_index); | ||
428 | |||
429 | if (api_index >= IWL_CAPABILITIES_ARRAY_SIZE) { | ||
430 | IWL_ERR(drv, "api_index larger than supported by driver\n"); | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | capa->capa[api_index] = le32_to_cpu(ucode_capa->api_capa); | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
407 | static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, | 439 | static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, |
408 | const struct firmware *ucode_raw, | 440 | const struct firmware *ucode_raw, |
409 | struct iwl_firmware_pieces *pieces) | 441 | struct iwl_firmware_pieces *pieces) |
@@ -638,6 +670,18 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
638 | */ | 670 | */ |
639 | capa->flags = le32_to_cpup((__le32 *)tlv_data); | 671 | capa->flags = le32_to_cpup((__le32 *)tlv_data); |
640 | break; | 672 | break; |
673 | case IWL_UCODE_TLV_API_CHANGES_SET: | ||
674 | if (tlv_len != sizeof(struct iwl_ucode_api)) | ||
675 | goto invalid_tlv_len; | ||
676 | if (iwl_set_ucode_api_flags(drv, tlv_data, capa)) | ||
677 | goto tlv_error; | ||
678 | break; | ||
679 | case IWL_UCODE_TLV_ENABLED_CAPABILITIES: | ||
680 | if (tlv_len != sizeof(struct iwl_ucode_capa)) | ||
681 | goto invalid_tlv_len; | ||
682 | if (iwl_set_ucode_capabilities(drv, tlv_data, capa)) | ||
683 | goto tlv_error; | ||
684 | break; | ||
641 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: | 685 | case IWL_UCODE_TLV_INIT_EVTLOG_PTR: |
642 | if (tlv_len != sizeof(u32)) | 686 | if (tlv_len != sizeof(u32)) |
643 | goto invalid_tlv_len; | 687 | goto invalid_tlv_len; |
@@ -728,6 +772,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
728 | if (tlv_len != sizeof(u32)) | 772 | if (tlv_len != sizeof(u32)) |
729 | goto invalid_tlv_len; | 773 | goto invalid_tlv_len; |
730 | drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); | 774 | drv->fw.phy_config = le32_to_cpup((__le32 *)tlv_data); |
775 | drv->fw.valid_tx_ant = (drv->fw.phy_config & | ||
776 | FW_PHY_CFG_TX_CHAIN) >> | ||
777 | FW_PHY_CFG_TX_CHAIN_POS; | ||
778 | drv->fw.valid_rx_ant = (drv->fw.phy_config & | ||
779 | FW_PHY_CFG_RX_CHAIN) >> | ||
780 | FW_PHY_CFG_RX_CHAIN_POS; | ||
731 | break; | 781 | break; |
732 | case IWL_UCODE_TLV_SECURE_SEC_RT: | 782 | case IWL_UCODE_TLV_SECURE_SEC_RT: |
733 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, | 783 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, |
@@ -1301,8 +1351,7 @@ MODULE_PARM_DESC(antenna_coupling, | |||
1301 | 1351 | ||
1302 | module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); | 1352 | module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); |
1303 | MODULE_PARM_DESC(wd_disable, | 1353 | MODULE_PARM_DESC(wd_disable, |
1304 | "Disable stuck queue watchdog timer 0=system default, " | 1354 | "Disable stuck queue watchdog timer 0=system default, 1=disable (default: 1)"); |
1305 | "1=disable, 2=enable (default: 0)"); | ||
1306 | 1355 | ||
1307 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); | 1356 | module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); |
1308 | MODULE_PARM_DESC(nvm_file, "NVM file name"); | 1357 | MODULE_PARM_DESC(nvm_file, "NVM file name"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index 592c01e11013..3c72cb710b0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h | |||
@@ -70,6 +70,20 @@ | |||
70 | #define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation" | 70 | #define DRV_COPYRIGHT "Copyright(c) 2003- 2014 Intel Corporation" |
71 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 71 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
72 | 72 | ||
73 | /* radio config bits (actual values from NVM definition) */ | ||
74 | #define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
75 | #define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
76 | #define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
77 | #define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
78 | #define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
79 | #define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
80 | |||
81 | #define NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(x) (x & 0xF) | ||
82 | #define NVM_RF_CFG_DASH_MSK_FAMILY_8000(x) ((x >> 4) & 0xF) | ||
83 | #define NVM_RF_CFG_STEP_MSK_FAMILY_8000(x) ((x >> 8) & 0xF) | ||
84 | #define NVM_RF_CFG_TYPE_MSK_FAMILY_8000(x) ((x >> 12) & 0xFFF) | ||
85 | #define NVM_RF_CFG_TX_ANT_MSK_FAMILY_8000(x) ((x >> 24) & 0xF) | ||
86 | #define NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(x) ((x >> 28) & 0xF) | ||
73 | 87 | ||
74 | /** | 88 | /** |
75 | * DOC: Driver system flows - drv component | 89 | * DOC: Driver system flows - drv component |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index e3c7deafabe6..f0548b8a64b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | |||
@@ -81,16 +81,17 @@ struct iwl_nvm_data { | |||
81 | bool sku_cap_band_24GHz_enable; | 81 | bool sku_cap_band_24GHz_enable; |
82 | bool sku_cap_band_52GHz_enable; | 82 | bool sku_cap_band_52GHz_enable; |
83 | bool sku_cap_11n_enable; | 83 | bool sku_cap_11n_enable; |
84 | bool sku_cap_11ac_enable; | ||
84 | bool sku_cap_amt_enable; | 85 | bool sku_cap_amt_enable; |
85 | bool sku_cap_ipan_enable; | 86 | bool sku_cap_ipan_enable; |
86 | 87 | ||
87 | u8 radio_cfg_type; | 88 | u16 radio_cfg_type; |
88 | u8 radio_cfg_step; | 89 | u8 radio_cfg_step; |
89 | u8 radio_cfg_dash; | 90 | u8 radio_cfg_dash; |
90 | u8 radio_cfg_pnum; | 91 | u8 radio_cfg_pnum; |
91 | u8 valid_tx_ant, valid_rx_ant; | 92 | u8 valid_tx_ant, valid_rx_ant; |
92 | 93 | ||
93 | u16 nvm_version; | 94 | u32 nvm_version; |
94 | s8 max_tx_pwr_half_dbm; | 95 | s8 max_tx_pwr_half_dbm; |
95 | 96 | ||
96 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 97 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 88e2d6eb569f..b45e576a4b57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -126,6 +126,8 @@ enum iwl_ucode_tlv_type { | |||
126 | IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, | 126 | IWL_UCODE_TLV_SECURE_SEC_WOWLAN = 26, |
127 | IWL_UCODE_TLV_NUM_OF_CPU = 27, | 127 | IWL_UCODE_TLV_NUM_OF_CPU = 27, |
128 | IWL_UCODE_TLV_CSCHEME = 28, | 128 | IWL_UCODE_TLV_CSCHEME = 28, |
129 | IWL_UCODE_TLV_API_CHANGES_SET = 29, | ||
130 | IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30, | ||
129 | }; | 131 | }; |
130 | 132 | ||
131 | struct iwl_ucode_tlv { | 133 | struct iwl_ucode_tlv { |
@@ -158,4 +160,19 @@ struct iwl_tlv_ucode_header { | |||
158 | u8 data[0]; | 160 | u8 data[0]; |
159 | }; | 161 | }; |
160 | 162 | ||
163 | /* | ||
164 | * ucode TLVs | ||
165 | * | ||
166 | * ability to get extension for: flags & capabilities from ucode binaries files | ||
167 | */ | ||
168 | struct iwl_ucode_api { | ||
169 | __le32 api_index; | ||
170 | __le32 api_flags; | ||
171 | } __packed; | ||
172 | |||
173 | struct iwl_ucode_capa { | ||
174 | __le32 api_index; | ||
175 | __le32 api_capa; | ||
176 | } __packed; | ||
177 | |||
161 | #endif /* __iwl_fw_file_h__ */ | 178 | #endif /* __iwl_fw_file_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index f80ba586c253..f04ff871dc6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -92,8 +92,8 @@ | |||
92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API | 92 | * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API |
93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command | 93 | * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command |
94 | * containing CAM (Continuous Active Mode) indication. | 94 | * containing CAM (Continuous Active Mode) indication. |
95 | * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a | 95 | * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and |
96 | * single bound interface). | 96 | * P2P client interfaces simultaneously if they are in different bindings. |
97 | * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save | 97 | * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save |
98 | * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. | 98 | * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering. |
99 | * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients | 99 | * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients |
@@ -118,7 +118,7 @@ enum iwl_ucode_tlv_flag { | |||
118 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), | 118 | IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17), |
119 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), | 119 | IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), |
120 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), | 120 | IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD = BIT(20), |
121 | IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21), | 121 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22), |
122 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), | 122 | IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), |
123 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), | 123 | IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), |
124 | IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), | 124 | IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29), |
@@ -165,11 +165,15 @@ enum iwl_ucode_sec { | |||
165 | * just an offset to the HW address. | 165 | * just an offset to the HW address. |
166 | */ | 166 | */ |
167 | #define IWL_UCODE_SECTION_MAX 12 | 167 | #define IWL_UCODE_SECTION_MAX 12 |
168 | #define IWL_API_ARRAY_SIZE 1 | ||
169 | #define IWL_CAPABILITIES_ARRAY_SIZE 1 | ||
168 | 170 | ||
169 | struct iwl_ucode_capabilities { | 171 | struct iwl_ucode_capabilities { |
170 | u32 max_probe_length; | 172 | u32 max_probe_length; |
171 | u32 standard_phy_calibration_size; | 173 | u32 standard_phy_calibration_size; |
172 | u32 flags; | 174 | u32 flags; |
175 | u32 api[IWL_API_ARRAY_SIZE]; | ||
176 | u32 capa[IWL_CAPABILITIES_ARRAY_SIZE]; | ||
173 | }; | 177 | }; |
174 | 178 | ||
175 | /* one for each uCode image (inst/data, init/runtime/wowlan) */ | 179 | /* one for each uCode image (inst/data, init/runtime/wowlan) */ |
@@ -288,22 +292,12 @@ struct iwl_fw { | |||
288 | 292 | ||
289 | struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX]; | 293 | struct iwl_tlv_calib_ctrl default_calib[IWL_UCODE_TYPE_MAX]; |
290 | u32 phy_config; | 294 | u32 phy_config; |
295 | u8 valid_tx_ant; | ||
296 | u8 valid_rx_ant; | ||
291 | 297 | ||
292 | bool mvm_fw; | 298 | bool mvm_fw; |
293 | 299 | ||
294 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; | 300 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; |
295 | }; | 301 | }; |
296 | 302 | ||
297 | static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw) | ||
298 | { | ||
299 | return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >> | ||
300 | FW_PHY_CFG_TX_CHAIN_POS; | ||
301 | } | ||
302 | |||
303 | static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw) | ||
304 | { | ||
305 | return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >> | ||
306 | FW_PHY_CFG_RX_CHAIN_POS; | ||
307 | } | ||
308 | |||
309 | #endif /* __iwl_fw_h__ */ | 303 | #endif /* __iwl_fw_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index b29075c3da8e..d994317db85b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -96,7 +96,7 @@ enum iwl_disable_11n { | |||
96 | * use IWL_[DIS,EN]ABLE_HT_* constants | 96 | * use IWL_[DIS,EN]ABLE_HT_* constants |
97 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 | 97 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 |
98 | * @restart_fw: restart firmware, default = 1 | 98 | * @restart_fw: restart firmware, default = 1 |
99 | * @wd_disable: enable stuck queue check, default = 0 | 99 | * @wd_disable: disable stuck queue check, default = 1 |
100 | * @bt_coex_active: enable bt coex, default = true | 100 | * @bt_coex_active: enable bt coex, default = true |
101 | * @led_mode: system default, default = 0 | 101 | * @led_mode: system default, default = 0 |
102 | * @power_save: disable power save, default = false | 102 | * @power_save: disable power save, default = false |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 53b9cad50477..2f962ec0b750 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -71,7 +71,7 @@ enum wkp_nvm_offsets { | |||
71 | /* NVM HW-Section offset (in words) definitions */ | 71 | /* NVM HW-Section offset (in words) definitions */ |
72 | HW_ADDR = 0x15, | 72 | HW_ADDR = 0x15, |
73 | 73 | ||
74 | /* NVM SW-Section offset (in words) definitions */ | 74 | /* NVM SW-Section offset (in words) definitions */ |
75 | NVM_SW_SECTION = 0x1C0, | 75 | NVM_SW_SECTION = 0x1C0, |
76 | NVM_VERSION = 0, | 76 | NVM_VERSION = 0, |
77 | RADIO_CFG = 1, | 77 | RADIO_CFG = 1, |
@@ -79,11 +79,32 @@ enum wkp_nvm_offsets { | |||
79 | N_HW_ADDRS = 3, | 79 | N_HW_ADDRS = 3, |
80 | NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION, | 80 | NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION, |
81 | 81 | ||
82 | /* NVM calibration section offset (in words) definitions */ | 82 | /* NVM calibration section offset (in words) definitions */ |
83 | NVM_CALIB_SECTION = 0x2B8, | 83 | NVM_CALIB_SECTION = 0x2B8, |
84 | XTAL_CALIB = 0x316 - NVM_CALIB_SECTION | 84 | XTAL_CALIB = 0x316 - NVM_CALIB_SECTION |
85 | }; | 85 | }; |
86 | 86 | ||
87 | enum family_8000_nvm_offsets { | ||
88 | /* NVM HW-Section offset (in words) definitions */ | ||
89 | HW_ADDR0_FAMILY_8000 = 0x12, | ||
90 | HW_ADDR1_FAMILY_8000 = 0x16, | ||
91 | MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1, | ||
92 | |||
93 | /* NVM SW-Section offset (in words) definitions */ | ||
94 | NVM_SW_SECTION_FAMILY_8000 = 0x1C0, | ||
95 | NVM_VERSION_FAMILY_8000 = 0, | ||
96 | RADIO_CFG_FAMILY_8000 = 2, | ||
97 | SKU_FAMILY_8000 = 4, | ||
98 | N_HW_ADDRS_FAMILY_8000 = 5, | ||
99 | |||
100 | /* NVM REGULATORY -Section offset (in words) definitions */ | ||
101 | NVM_CHANNELS_FAMILY_8000 = 0, | ||
102 | |||
103 | /* NVM calibration section offset (in words) definitions */ | ||
104 | NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8, | ||
105 | XTAL_CALIB_FAMILY_8000 = 0x316 - NVM_CALIB_SECTION_FAMILY_8000 | ||
106 | }; | ||
107 | |||
87 | /* SKU Capabilities (actual values from NVM definition) */ | 108 | /* SKU Capabilities (actual values from NVM definition) */ |
88 | enum nvm_sku_bits { | 109 | enum nvm_sku_bits { |
89 | NVM_SKU_CAP_BAND_24GHZ = BIT(0), | 110 | NVM_SKU_CAP_BAND_24GHZ = BIT(0), |
@@ -92,14 +113,6 @@ enum nvm_sku_bits { | |||
92 | NVM_SKU_CAP_11AC_ENABLE = BIT(3), | 113 | NVM_SKU_CAP_11AC_ENABLE = BIT(3), |
93 | }; | 114 | }; |
94 | 115 | ||
95 | /* radio config bits (actual values from NVM definition) */ | ||
96 | #define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
97 | #define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
98 | #define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
99 | #define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
100 | #define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
101 | #define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
102 | |||
103 | /* | 116 | /* |
104 | * These are the channel numbers in the order that they are stored in the NVM | 117 | * These are the channel numbers in the order that they are stored in the NVM |
105 | */ | 118 | */ |
@@ -112,7 +125,17 @@ static const u8 iwl_nvm_channels[] = { | |||
112 | 149, 153, 157, 161, 165 | 125 | 149, 153, 157, 161, 165 |
113 | }; | 126 | }; |
114 | 127 | ||
128 | static const u8 iwl_nvm_channels_family_8000[] = { | ||
129 | /* 2.4 GHz */ | ||
130 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | ||
131 | /* 5 GHz */ | ||
132 | 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, | ||
133 | 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, | ||
134 | 149, 153, 157, 161, 165, 169, 173, 177, 181 | ||
135 | }; | ||
136 | |||
115 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) | 137 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) |
138 | #define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000) | ||
116 | #define NUM_2GHZ_CHANNELS 14 | 139 | #define NUM_2GHZ_CHANNELS 14 |
117 | #define FIRST_2GHZ_HT_MINUS 5 | 140 | #define FIRST_2GHZ_HT_MINUS 5 |
118 | #define LAST_2GHZ_HT_PLUS 9 | 141 | #define LAST_2GHZ_HT_PLUS 9 |
@@ -179,8 +202,18 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
179 | struct ieee80211_channel *channel; | 202 | struct ieee80211_channel *channel; |
180 | u16 ch_flags; | 203 | u16 ch_flags; |
181 | bool is_5ghz; | 204 | bool is_5ghz; |
205 | int num_of_ch; | ||
206 | const u8 *nvm_chan; | ||
207 | |||
208 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { | ||
209 | num_of_ch = IWL_NUM_CHANNELS; | ||
210 | nvm_chan = &iwl_nvm_channels[0]; | ||
211 | } else { | ||
212 | num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000; | ||
213 | nvm_chan = &iwl_nvm_channels_family_8000[0]; | ||
214 | } | ||
182 | 215 | ||
183 | for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) { | 216 | for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { |
184 | ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); | 217 | ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); |
185 | 218 | ||
186 | if (ch_idx >= NUM_2GHZ_CHANNELS && | 219 | if (ch_idx >= NUM_2GHZ_CHANNELS && |
@@ -190,7 +223,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
190 | if (!(ch_flags & NVM_CHANNEL_VALID)) { | 223 | if (!(ch_flags & NVM_CHANNEL_VALID)) { |
191 | IWL_DEBUG_EEPROM(dev, | 224 | IWL_DEBUG_EEPROM(dev, |
192 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | 225 | "Ch. %d Flags %x [%sGHz] - No traffic\n", |
193 | iwl_nvm_channels[ch_idx], | 226 | nvm_chan[ch_idx], |
194 | ch_flags, | 227 | ch_flags, |
195 | (ch_idx >= NUM_2GHZ_CHANNELS) ? | 228 | (ch_idx >= NUM_2GHZ_CHANNELS) ? |
196 | "5.2" : "2.4"); | 229 | "5.2" : "2.4"); |
@@ -200,7 +233,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
200 | channel = &data->channels[n_channels]; | 233 | channel = &data->channels[n_channels]; |
201 | n_channels++; | 234 | n_channels++; |
202 | 235 | ||
203 | channel->hw_value = iwl_nvm_channels[ch_idx]; | 236 | channel->hw_value = nvm_chan[ch_idx]; |
204 | channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ? | 237 | channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ? |
205 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 238 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
206 | channel->center_freq = | 239 | channel->center_freq = |
@@ -211,11 +244,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
211 | channel->flags = IEEE80211_CHAN_NO_HT40; | 244 | channel->flags = IEEE80211_CHAN_NO_HT40; |
212 | if (ch_idx < NUM_2GHZ_CHANNELS && | 245 | if (ch_idx < NUM_2GHZ_CHANNELS && |
213 | (ch_flags & NVM_CHANNEL_40MHZ)) { | 246 | (ch_flags & NVM_CHANNEL_40MHZ)) { |
214 | if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS) | 247 | if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS) |
215 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 248 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
216 | if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS) | 249 | if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS) |
217 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 250 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
218 | } else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT && | 251 | } else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT && |
219 | (ch_flags & NVM_CHANNEL_40MHZ)) { | 252 | (ch_flags & NVM_CHANNEL_40MHZ)) { |
220 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) | 253 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) |
221 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 254 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
@@ -307,14 +340,23 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
307 | } | 340 | } |
308 | 341 | ||
309 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 342 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
310 | struct iwl_nvm_data *data, const __le16 *nvm_sw, | 343 | struct iwl_nvm_data *data, |
311 | bool enable_vht, u8 tx_chains, u8 rx_chains) | 344 | const __le16 *ch_section, bool enable_vht, |
345 | u8 tx_chains, u8 rx_chains) | ||
312 | { | 346 | { |
313 | int n_channels = iwl_init_channel_map(dev, cfg, data, | 347 | int n_channels; |
314 | &nvm_sw[NVM_CHANNELS]); | ||
315 | int n_used = 0; | 348 | int n_used = 0; |
316 | struct ieee80211_supported_band *sband; | 349 | struct ieee80211_supported_band *sband; |
317 | 350 | ||
351 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
352 | n_channels = iwl_init_channel_map( | ||
353 | dev, cfg, data, | ||
354 | &ch_section[NVM_CHANNELS]); | ||
355 | else | ||
356 | n_channels = iwl_init_channel_map( | ||
357 | dev, cfg, data, | ||
358 | &ch_section[NVM_CHANNELS_FAMILY_8000]); | ||
359 | |||
318 | sband = &data->bands[IEEE80211_BAND_2GHZ]; | 360 | sband = &data->bands[IEEE80211_BAND_2GHZ]; |
319 | sband->band = IEEE80211_BAND_2GHZ; | 361 | sband->band = IEEE80211_BAND_2GHZ; |
320 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; | 362 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; |
@@ -340,67 +382,150 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
340 | n_used, n_channels); | 382 | n_used, n_channels); |
341 | } | 383 | } |
342 | 384 | ||
385 | static int iwl_get_sku(const struct iwl_cfg *cfg, | ||
386 | const __le16 *nvm_sw) | ||
387 | { | ||
388 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
389 | return le16_to_cpup(nvm_sw + SKU); | ||
390 | else | ||
391 | return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000)); | ||
392 | } | ||
393 | |||
394 | static int iwl_get_nvm_version(const struct iwl_cfg *cfg, | ||
395 | const __le16 *nvm_sw) | ||
396 | { | ||
397 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
398 | return le16_to_cpup(nvm_sw + NVM_VERSION); | ||
399 | else | ||
400 | return le32_to_cpup((__le32 *)(nvm_sw + | ||
401 | NVM_VERSION_FAMILY_8000)); | ||
402 | } | ||
403 | |||
404 | static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, | ||
405 | const __le16 *nvm_sw) | ||
406 | { | ||
407 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
408 | return le16_to_cpup(nvm_sw + RADIO_CFG); | ||
409 | else | ||
410 | return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000)); | ||
411 | } | ||
412 | |||
413 | #define N_HW_ADDRS_MASK_FAMILY_8000 0xF | ||
414 | static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, | ||
415 | const __le16 *nvm_sw) | ||
416 | { | ||
417 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
418 | return le16_to_cpup(nvm_sw + N_HW_ADDRS); | ||
419 | else | ||
420 | return le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000)) | ||
421 | & N_HW_ADDRS_MASK_FAMILY_8000; | ||
422 | } | ||
423 | |||
424 | static void iwl_set_radio_cfg(const struct iwl_cfg *cfg, | ||
425 | struct iwl_nvm_data *data, | ||
426 | u32 radio_cfg) | ||
427 | { | ||
428 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { | ||
429 | data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg); | ||
430 | data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg); | ||
431 | data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg); | ||
432 | data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg); | ||
433 | return; | ||
434 | } | ||
435 | |||
436 | /* set the radio configuration for family 8000 */ | ||
437 | data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK_FAMILY_8000(radio_cfg); | ||
438 | data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg); | ||
439 | data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg); | ||
440 | data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg); | ||
441 | } | ||
442 | |||
443 | static void iwl_set_hw_address(const struct iwl_cfg *cfg, | ||
444 | struct iwl_nvm_data *data, | ||
445 | const __le16 *nvm_sec) | ||
446 | { | ||
447 | u8 hw_addr[ETH_ALEN]; | ||
448 | |||
449 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
450 | memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN); | ||
451 | else | ||
452 | memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000, | ||
453 | ETH_ALEN); | ||
454 | |||
455 | /* The byte order is little endian 16 bit, meaning 214365 */ | ||
456 | data->hw_addr[0] = hw_addr[1]; | ||
457 | data->hw_addr[1] = hw_addr[0]; | ||
458 | data->hw_addr[2] = hw_addr[3]; | ||
459 | data->hw_addr[3] = hw_addr[2]; | ||
460 | data->hw_addr[4] = hw_addr[5]; | ||
461 | data->hw_addr[5] = hw_addr[4]; | ||
462 | } | ||
463 | |||
343 | struct iwl_nvm_data * | 464 | struct iwl_nvm_data * |
344 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 465 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
345 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 466 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
346 | const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains) | 467 | const __le16 *nvm_calib, const __le16 *regulatory, |
468 | const __le16 *mac_override, u8 tx_chains, u8 rx_chains) | ||
347 | { | 469 | { |
348 | struct iwl_nvm_data *data; | 470 | struct iwl_nvm_data *data; |
349 | u8 hw_addr[ETH_ALEN]; | 471 | u32 sku; |
350 | u16 radio_cfg, sku; | 472 | u32 radio_cfg; |
351 | 473 | ||
352 | data = kzalloc(sizeof(*data) + | 474 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
353 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | 475 | data = kzalloc(sizeof(*data) + |
354 | GFP_KERNEL); | 476 | sizeof(struct ieee80211_channel) * |
477 | IWL_NUM_CHANNELS, | ||
478 | GFP_KERNEL); | ||
479 | else | ||
480 | data = kzalloc(sizeof(*data) + | ||
481 | sizeof(struct ieee80211_channel) * | ||
482 | IWL_NUM_CHANNELS_FAMILY_8000, | ||
483 | GFP_KERNEL); | ||
355 | if (!data) | 484 | if (!data) |
356 | return NULL; | 485 | return NULL; |
357 | 486 | ||
358 | data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION); | 487 | data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw); |
359 | 488 | ||
360 | radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG); | 489 | radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw); |
361 | data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg); | 490 | iwl_set_radio_cfg(cfg, data, radio_cfg); |
362 | data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg); | ||
363 | data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg); | ||
364 | data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg); | ||
365 | data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
366 | data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
367 | 491 | ||
368 | sku = le16_to_cpup(nvm_sw + SKU); | 492 | sku = iwl_get_sku(cfg, nvm_sw); |
369 | data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; | 493 | data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; |
370 | data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; | 494 | data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; |
371 | data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; | 495 | data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; |
496 | data->sku_cap_11ac_enable = sku & NVM_SKU_CAP_11AC_ENABLE; | ||
372 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | 497 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) |
373 | data->sku_cap_11n_enable = false; | 498 | data->sku_cap_11n_enable = false; |
374 | 499 | ||
375 | /* check overrides (some devices have wrong NVM) */ | 500 | data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); |
376 | if (cfg->valid_tx_ant) | ||
377 | data->valid_tx_ant = cfg->valid_tx_ant; | ||
378 | if (cfg->valid_rx_ant) | ||
379 | data->valid_rx_ant = cfg->valid_rx_ant; | ||
380 | 501 | ||
381 | if (!data->valid_tx_ant || !data->valid_rx_ant) { | 502 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
382 | IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", | 503 | /* Checking for required sections */ |
383 | data->valid_tx_ant, data->valid_rx_ant); | 504 | if (!nvm_calib) { |
384 | kfree(data); | 505 | IWL_ERR_DEV(dev, |
385 | return NULL; | 506 | "Can't parse empty Calib NVM sections\n"); |
507 | kfree(data); | ||
508 | return NULL; | ||
509 | } | ||
510 | /* in family 8000 Xtal calibration values moved to OTP */ | ||
511 | data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); | ||
512 | data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); | ||
386 | } | 513 | } |
387 | 514 | ||
388 | data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS); | 515 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
516 | iwl_set_hw_address(cfg, data, nvm_hw); | ||
389 | 517 | ||
390 | data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); | 518 | iwl_init_sbands(dev, cfg, data, nvm_sw, |
391 | data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); | 519 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, |
520 | rx_chains); | ||
521 | } else { | ||
522 | /* MAC address in family 8000 */ | ||
523 | iwl_set_hw_address(cfg, data, mac_override); | ||
392 | 524 | ||
393 | /* The byte order is little endian 16 bit, meaning 214365 */ | 525 | iwl_init_sbands(dev, cfg, data, regulatory, |
394 | memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN); | 526 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, |
395 | data->hw_addr[0] = hw_addr[1]; | 527 | rx_chains); |
396 | data->hw_addr[1] = hw_addr[0]; | 528 | } |
397 | data->hw_addr[2] = hw_addr[3]; | ||
398 | data->hw_addr[3] = hw_addr[2]; | ||
399 | data->hw_addr[4] = hw_addr[5]; | ||
400 | data->hw_addr[5] = hw_addr[4]; | ||
401 | |||
402 | iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE, | ||
403 | tx_chains, rx_chains); | ||
404 | 529 | ||
405 | data->calib_version = 255; | 530 | data->calib_version = 255; |
406 | 531 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index 0c4399aba8c6..c9c45a39d212 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | |||
@@ -75,6 +75,7 @@ | |||
75 | struct iwl_nvm_data * | 75 | struct iwl_nvm_data * |
76 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 76 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
77 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 77 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
78 | const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains); | 78 | const __le16 *nvm_calib, const __le16 *regulatory, |
79 | const __le16 *mac_override, u8 tx_chains, u8 rx_chains); | ||
79 | 80 | ||
80 | #endif /* __iwl_nvm_parse_h__ */ | 81 | #endif /* __iwl_nvm_parse_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7b19274b550f..8cdb0dd618a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -393,7 +393,7 @@ struct iwl_trans_config { | |||
393 | bool rx_buf_size_8k; | 393 | bool rx_buf_size_8k; |
394 | bool bc_table_dword; | 394 | bool bc_table_dword; |
395 | unsigned int queue_watchdog_timeout; | 395 | unsigned int queue_watchdog_timeout; |
396 | const char **command_names; | 396 | const char *const *command_names; |
397 | }; | 397 | }; |
398 | 398 | ||
399 | struct iwl_trans; | 399 | struct iwl_trans; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 29b4396018b1..f64e972191eb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
@@ -591,7 +591,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
591 | iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && | 591 | iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && |
592 | ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || | 592 | ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) || |
593 | (vif->type == NL80211_IFTYPE_STATION && vif->p2p && | 593 | (vif->type == NL80211_IFTYPE_STATION && vif->p2p && |
594 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS))) | 594 | mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM))) |
595 | MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | | 595 | MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | |
596 | S_IRUSR); | 596 | S_IRUSR); |
597 | 597 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 6853e5efe522..e0ff43ed2482 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -531,6 +531,76 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file, | |||
531 | } | 531 | } |
532 | #undef PRINT_STAT_LE32 | 532 | #undef PRINT_STAT_LE32 |
533 | 533 | ||
534 | static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm, | ||
535 | char __user *user_buf, size_t count, | ||
536 | loff_t *ppos, | ||
537 | struct iwl_mvm_frame_stats *stats) | ||
538 | { | ||
539 | char *buff; | ||
540 | int pos = 0, idx, i; | ||
541 | int ret; | ||
542 | size_t bufsz = 1024; | ||
543 | |||
544 | buff = kmalloc(bufsz, GFP_KERNEL); | ||
545 | if (!buff) | ||
546 | return -ENOMEM; | ||
547 | |||
548 | spin_lock_bh(&mvm->drv_stats_lock); | ||
549 | pos += scnprintf(buff + pos, bufsz - pos, | ||
550 | "Legacy/HT/VHT\t:\t%d/%d/%d\n", | ||
551 | stats->legacy_frames, | ||
552 | stats->ht_frames, | ||
553 | stats->vht_frames); | ||
554 | pos += scnprintf(buff + pos, bufsz - pos, "20/40/80\t:\t%d/%d/%d\n", | ||
555 | stats->bw_20_frames, | ||
556 | stats->bw_40_frames, | ||
557 | stats->bw_80_frames); | ||
558 | pos += scnprintf(buff + pos, bufsz - pos, "NGI/SGI\t\t:\t%d/%d\n", | ||
559 | stats->ngi_frames, | ||
560 | stats->sgi_frames); | ||
561 | pos += scnprintf(buff + pos, bufsz - pos, "SISO/MIMO2\t:\t%d/%d\n", | ||
562 | stats->siso_frames, | ||
563 | stats->mimo2_frames); | ||
564 | pos += scnprintf(buff + pos, bufsz - pos, "FAIL/SCSS\t:\t%d/%d\n", | ||
565 | stats->fail_frames, | ||
566 | stats->success_frames); | ||
567 | pos += scnprintf(buff + pos, bufsz - pos, "MPDUs agg\t:\t%d\n", | ||
568 | stats->agg_frames); | ||
569 | pos += scnprintf(buff + pos, bufsz - pos, "A-MPDUs\t\t:\t%d\n", | ||
570 | stats->ampdu_count); | ||
571 | pos += scnprintf(buff + pos, bufsz - pos, "Avg MPDUs/A-MPDU:\t%d\n", | ||
572 | stats->ampdu_count > 0 ? | ||
573 | (stats->agg_frames / stats->ampdu_count) : 0); | ||
574 | |||
575 | pos += scnprintf(buff + pos, bufsz - pos, "Last Rates\n"); | ||
576 | |||
577 | idx = stats->last_frame_idx - 1; | ||
578 | for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) { | ||
579 | idx = (idx + 1) % ARRAY_SIZE(stats->last_rates); | ||
580 | if (stats->last_rates[idx] == 0) | ||
581 | continue; | ||
582 | pos += scnprintf(buff + pos, bufsz - pos, "Rate[%d]: ", | ||
583 | (int)(ARRAY_SIZE(stats->last_rates) - i)); | ||
584 | pos += rs_pretty_print_rate(buff + pos, stats->last_rates[idx]); | ||
585 | } | ||
586 | spin_unlock_bh(&mvm->drv_stats_lock); | ||
587 | |||
588 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos); | ||
589 | kfree(buff); | ||
590 | |||
591 | return ret; | ||
592 | } | ||
593 | |||
594 | static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file, | ||
595 | char __user *user_buf, size_t count, | ||
596 | loff_t *ppos) | ||
597 | { | ||
598 | struct iwl_mvm *mvm = file->private_data; | ||
599 | |||
600 | return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos, | ||
601 | &mvm->drv_rx_stats); | ||
602 | } | ||
603 | |||
534 | static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, | 604 | static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf, |
535 | size_t count, loff_t *ppos) | 605 | size_t count, loff_t *ppos) |
536 | { | 606 | { |
@@ -591,7 +661,7 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, | |||
591 | return -EINVAL; | 661 | return -EINVAL; |
592 | if (scan_rx_ant > ANT_ABC) | 662 | if (scan_rx_ant > ANT_ABC) |
593 | return -EINVAL; | 663 | return -EINVAL; |
594 | if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw)) | 664 | if (scan_rx_ant & ~mvm->fw->valid_rx_ant) |
595 | return -EINVAL; | 665 | return -EINVAL; |
596 | 666 | ||
597 | mvm->scan_rx_ant = scan_rx_ant; | 667 | mvm->scan_rx_ant = scan_rx_ant; |
@@ -907,6 +977,49 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf, | |||
907 | #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ | 977 | #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \ |
908 | MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) | 978 | MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) |
909 | 979 | ||
980 | static ssize_t | ||
981 | iwl_dbgfs_prph_reg_read(struct file *file, | ||
982 | char __user *user_buf, | ||
983 | size_t count, loff_t *ppos) | ||
984 | { | ||
985 | struct iwl_mvm *mvm = file->private_data; | ||
986 | int pos = 0; | ||
987 | char buf[32]; | ||
988 | const size_t bufsz = sizeof(buf); | ||
989 | |||
990 | if (!mvm->dbgfs_prph_reg_addr) | ||
991 | return -EINVAL; | ||
992 | |||
993 | pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n", | ||
994 | mvm->dbgfs_prph_reg_addr, | ||
995 | iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr)); | ||
996 | |||
997 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
998 | } | ||
999 | |||
1000 | static ssize_t | ||
1001 | iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf, | ||
1002 | size_t count, loff_t *ppos) | ||
1003 | { | ||
1004 | u8 args; | ||
1005 | u32 value; | ||
1006 | |||
1007 | args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value); | ||
1008 | /* if we only want to set the reg address - nothing more to do */ | ||
1009 | if (args == 1) | ||
1010 | goto out; | ||
1011 | |||
1012 | /* otherwise, make sure we have both address and value */ | ||
1013 | if (args != 2) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value); | ||
1017 | out: | ||
1018 | return count; | ||
1019 | } | ||
1020 | |||
1021 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); | ||
1022 | |||
910 | /* Device wide debugfs entries */ | 1023 | /* Device wide debugfs entries */ |
911 | MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); | 1024 | MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); |
912 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); | 1025 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); |
@@ -916,6 +1029,7 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif); | |||
916 | MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); | 1029 | MVM_DEBUGFS_READ_FILE_OPS(bt_cmd); |
917 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); | 1030 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64); |
918 | MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); | 1031 | MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats); |
1032 | MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats); | ||
919 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); | 1033 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); |
920 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); | 1034 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); |
921 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | 1035 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); |
@@ -947,10 +1061,12 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
947 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, | 1061 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, |
948 | S_IRUSR | S_IWUSR); | 1062 | S_IRUSR | S_IWUSR); |
949 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); | 1063 | MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR); |
1064 | MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR); | ||
950 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 1065 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
951 | MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); | 1066 | MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); |
952 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, | 1067 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, |
953 | S_IWUSR | S_IRUSR); | 1068 | S_IWUSR | S_IRUSR); |
1069 | MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | ||
954 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1070 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
955 | 1071 | ||
956 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1072 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h index 85057219cc43..39148b5bb332 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | |||
@@ -257,7 +257,8 @@ enum { | |||
257 | 257 | ||
258 | /* Bit 17-18: (0) SS, (1) SS*2 */ | 258 | /* Bit 17-18: (0) SS, (1) SS*2 */ |
259 | #define RATE_MCS_STBC_POS 17 | 259 | #define RATE_MCS_STBC_POS 17 |
260 | #define RATE_MCS_STBC_MSK (1 << RATE_MCS_STBC_POS) | 260 | #define RATE_MCS_HT_STBC_MSK (3 << RATE_MCS_STBC_POS) |
261 | #define RATE_MCS_VHT_STBC_MSK (1 << RATE_MCS_STBC_POS) | ||
261 | 262 | ||
262 | /* Bit 19: (0) Beamforming is off, (1) Beamforming is on */ | 263 | /* Bit 19: (0) Beamforming is off, (1) Beamforming is on */ |
263 | #define RATE_MCS_BF_POS 19 | 264 | #define RATE_MCS_BF_POS 19 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index a7c88f1402e9..807fa525cafe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -306,7 +306,6 @@ struct iwl_phy_cfg_cmd { | |||
306 | #define PHY_CFG_RX_CHAIN_B BIT(13) | 306 | #define PHY_CFG_RX_CHAIN_B BIT(13) |
307 | #define PHY_CFG_RX_CHAIN_C BIT(14) | 307 | #define PHY_CFG_RX_CHAIN_C BIT(14) |
308 | 308 | ||
309 | #define NVM_MAX_NUM_SECTIONS 11 | ||
310 | 309 | ||
311 | /* Target of the NVM_ACCESS_CMD */ | 310 | /* Target of the NVM_ACCESS_CMD */ |
312 | enum { | 311 | enum { |
@@ -318,8 +317,11 @@ enum { | |||
318 | /* Section types for NVM_ACCESS_CMD */ | 317 | /* Section types for NVM_ACCESS_CMD */ |
319 | enum { | 318 | enum { |
320 | NVM_SECTION_TYPE_SW = 1, | 319 | NVM_SECTION_TYPE_SW = 1, |
320 | NVM_SECTION_TYPE_REGULATORY = 3, | ||
321 | NVM_SECTION_TYPE_CALIBRATION = 4, | 321 | NVM_SECTION_TYPE_CALIBRATION = 4, |
322 | NVM_SECTION_TYPE_PRODUCTION = 5, | 322 | NVM_SECTION_TYPE_PRODUCTION = 5, |
323 | NVM_SECTION_TYPE_MAC_OVERRIDE = 11, | ||
324 | NVM_MAX_NUM_SECTIONS = 12, | ||
323 | }; | 325 | }; |
324 | 326 | ||
325 | /** | 327 | /** |
@@ -710,6 +712,7 @@ enum { | |||
710 | TE_V2_NOTIF_HOST_FRAG_END = BIT(5), | 712 | TE_V2_NOTIF_HOST_FRAG_END = BIT(5), |
711 | TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), | 713 | TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), |
712 | TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), | 714 | TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), |
715 | T2_V2_START_IMMEDIATELY = BIT(11), | ||
713 | 716 | ||
714 | TE_V2_NOTIF_MSK = 0xff, | 717 | TE_V2_NOTIF_MSK = 0xff, |
715 | 718 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index bae75b308fc0..7ce20062f32d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -130,7 +130,6 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
130 | } else { | 130 | } else { |
131 | palive2 = (void *)pkt->data; | 131 | palive2 = (void *)pkt->data; |
132 | 132 | ||
133 | mvm->support_umac_log = true; | ||
134 | mvm->error_event_table = | 133 | mvm->error_event_table = |
135 | le32_to_cpu(palive2->error_event_table_ptr); | 134 | le32_to_cpu(palive2->error_event_table_ptr); |
136 | mvm->log_event_table = | 135 | mvm->log_event_table = |
@@ -141,6 +140,9 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
141 | 140 | ||
142 | alive_data->valid = le16_to_cpu(palive2->status) == | 141 | alive_data->valid = le16_to_cpu(palive2->status) == |
143 | IWL_ALIVE_STATUS_OK; | 142 | IWL_ALIVE_STATUS_OK; |
143 | if (mvm->umac_error_event_table) | ||
144 | mvm->support_umac_log = true; | ||
145 | |||
144 | IWL_DEBUG_FW(mvm, | 146 | IWL_DEBUG_FW(mvm, |
145 | "Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", | 147 | "Alive VER2 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", |
146 | le16_to_cpu(palive2->status), palive2->ver_type, | 148 | le16_to_cpu(palive2->status), palive2->ver_type, |
@@ -320,7 +322,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
320 | } | 322 | } |
321 | 323 | ||
322 | /* Send TX valid antennas before triggering calibrations */ | 324 | /* Send TX valid antennas before triggering calibrations */ |
323 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); | 325 | ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); |
324 | if (ret) | 326 | if (ret) |
325 | goto error; | 327 | goto error; |
326 | 328 | ||
@@ -356,8 +358,6 @@ out: | |||
356 | GFP_KERNEL); | 358 | GFP_KERNEL); |
357 | if (!mvm->nvm_data) | 359 | if (!mvm->nvm_data) |
358 | return -ENOMEM; | 360 | return -ENOMEM; |
359 | mvm->nvm_data->valid_rx_ant = 1; | ||
360 | mvm->nvm_data->valid_tx_ant = 1; | ||
361 | mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels; | 361 | mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels; |
362 | mvm->nvm_data->bands[0].n_channels = 1; | 362 | mvm->nvm_data->bands[0].n_channels = 1; |
363 | mvm->nvm_data->bands[0].n_bitrates = 1; | 363 | mvm->nvm_data->bands[0].n_bitrates = 1; |
@@ -369,8 +369,6 @@ out: | |||
369 | return ret; | 369 | return ret; |
370 | } | 370 | } |
371 | 371 | ||
372 | #define UCODE_CALIB_TIMEOUT (2*HZ) | ||
373 | |||
374 | int iwl_mvm_up(struct iwl_mvm *mvm) | 372 | int iwl_mvm_up(struct iwl_mvm *mvm) |
375 | { | 373 | { |
376 | int ret, i; | 374 | int ret, i; |
@@ -422,7 +420,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
422 | if (ret) | 420 | if (ret) |
423 | IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); | 421 | IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); |
424 | 422 | ||
425 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); | 423 | ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); |
426 | if (ret) | 424 | if (ret) |
427 | goto error; | 425 | goto error; |
428 | 426 | ||
@@ -507,7 +505,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) | |||
507 | goto error; | 505 | goto error; |
508 | } | 506 | } |
509 | 507 | ||
510 | ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); | 508 | ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); |
511 | if (ret) | 509 | if (ret) |
512 | goto error; | 510 | goto error; |
513 | 511 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 5c21aabb40cb..9ccec10bba16 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -952,7 +952,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
952 | TX_CMD_FLG_TSF); | 952 | TX_CMD_FLG_TSF); |
953 | 953 | ||
954 | mvm->mgmt_last_antenna_idx = | 954 | mvm->mgmt_last_antenna_idx = |
955 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), | 955 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, |
956 | mvm->mgmt_last_antenna_idx); | 956 | mvm->mgmt_last_antenna_idx); |
957 | 957 | ||
958 | beacon_cmd.tx.rate_n_flags = | 958 | beacon_cmd.tx.rate_n_flags = |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index a49d1ef13f42..c2ab6a3318cb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #include <linux/ip.h> | 68 | #include <linux/ip.h> |
69 | #include <linux/if_arp.h> | 69 | #include <linux/if_arp.h> |
70 | #include <net/mac80211.h> | 70 | #include <net/mac80211.h> |
71 | #include <net/ieee80211_radiotap.h> | ||
71 | #include <net/tcp.h> | 72 | #include <net/tcp.h> |
72 | 73 | ||
73 | #include "iwl-op-mode.h" | 74 | #include "iwl-op-mode.h" |
@@ -280,6 +281,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
280 | 281 | ||
281 | hw->queues = mvm->first_agg_queue; | 282 | hw->queues = mvm->first_agg_queue; |
282 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; | 283 | hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; |
284 | hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC | | ||
285 | IEEE80211_RADIOTAP_MCS_HAVE_STBC; | ||
286 | hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC; | ||
283 | hw->rate_control_algorithm = "iwl-mvm-rs"; | 287 | hw->rate_control_algorithm = "iwl-mvm-rs"; |
284 | 288 | ||
285 | /* | 289 | /* |
@@ -1319,7 +1323,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
1319 | mvmvif->ap_ibss_active = true; | 1323 | mvmvif->ap_ibss_active = true; |
1320 | 1324 | ||
1321 | /* power updated needs to be done before quotas */ | 1325 | /* power updated needs to be done before quotas */ |
1322 | mvm->bound_vif_cnt++; | ||
1323 | iwl_mvm_power_update_mac(mvm, vif); | 1326 | iwl_mvm_power_update_mac(mvm, vif); |
1324 | 1327 | ||
1325 | ret = iwl_mvm_update_quotas(mvm, vif); | 1328 | ret = iwl_mvm_update_quotas(mvm, vif); |
@@ -1338,7 +1341,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
1338 | return 0; | 1341 | return 0; |
1339 | 1342 | ||
1340 | out_quota_failed: | 1343 | out_quota_failed: |
1341 | mvm->bound_vif_cnt--; | ||
1342 | iwl_mvm_power_update_mac(mvm, vif); | 1344 | iwl_mvm_power_update_mac(mvm, vif); |
1343 | mvmvif->ap_ibss_active = false; | 1345 | mvmvif->ap_ibss_active = false; |
1344 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 1346 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
@@ -1375,7 +1377,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
1375 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); | 1377 | iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta); |
1376 | iwl_mvm_binding_remove_vif(mvm, vif); | 1378 | iwl_mvm_binding_remove_vif(mvm, vif); |
1377 | 1379 | ||
1378 | mvm->bound_vif_cnt--; | ||
1379 | iwl_mvm_power_update_mac(mvm, vif); | 1380 | iwl_mvm_power_update_mac(mvm, vif); |
1380 | 1381 | ||
1381 | iwl_mvm_mac_ctxt_remove(mvm, vif); | 1382 | iwl_mvm_mac_ctxt_remove(mvm, vif); |
@@ -1764,14 +1765,16 @@ out: | |||
1764 | return ret; | 1765 | return ret; |
1765 | } | 1766 | } |
1766 | 1767 | ||
1767 | static void iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, | 1768 | static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw, |
1768 | struct ieee80211_vif *vif) | 1769 | struct ieee80211_vif *vif) |
1769 | { | 1770 | { |
1770 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1771 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1771 | 1772 | ||
1772 | mutex_lock(&mvm->mutex); | 1773 | mutex_lock(&mvm->mutex); |
1773 | iwl_mvm_sched_scan_stop(mvm); | 1774 | iwl_mvm_sched_scan_stop(mvm); |
1774 | mutex_unlock(&mvm->mutex); | 1775 | mutex_unlock(&mvm->mutex); |
1776 | |||
1777 | return 0; | ||
1775 | } | 1778 | } |
1776 | 1779 | ||
1777 | static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, | 1780 | static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, |
@@ -2109,7 +2112,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
2109 | * Power state must be updated before quotas, | 2112 | * Power state must be updated before quotas, |
2110 | * otherwise fw will complain. | 2113 | * otherwise fw will complain. |
2111 | */ | 2114 | */ |
2112 | mvm->bound_vif_cnt++; | ||
2113 | iwl_mvm_power_update_mac(mvm, vif); | 2115 | iwl_mvm_power_update_mac(mvm, vif); |
2114 | 2116 | ||
2115 | /* Setting the quota at this stage is only required for monitor | 2117 | /* Setting the quota at this stage is only required for monitor |
@@ -2127,7 +2129,6 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
2127 | 2129 | ||
2128 | out_remove_binding: | 2130 | out_remove_binding: |
2129 | iwl_mvm_binding_remove_vif(mvm, vif); | 2131 | iwl_mvm_binding_remove_vif(mvm, vif); |
2130 | mvm->bound_vif_cnt--; | ||
2131 | iwl_mvm_power_update_mac(mvm, vif); | 2132 | iwl_mvm_power_update_mac(mvm, vif); |
2132 | out_unlock: | 2133 | out_unlock: |
2133 | mutex_unlock(&mvm->mutex); | 2134 | mutex_unlock(&mvm->mutex); |
@@ -2160,7 +2161,6 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
2160 | } | 2161 | } |
2161 | 2162 | ||
2162 | iwl_mvm_binding_remove_vif(mvm, vif); | 2163 | iwl_mvm_binding_remove_vif(mvm, vif); |
2163 | mvm->bound_vif_cnt--; | ||
2164 | iwl_mvm_power_update_mac(mvm, vif); | 2164 | iwl_mvm_power_update_mac(mvm, vif); |
2165 | 2165 | ||
2166 | out_unlock: | 2166 | out_unlock: |
@@ -2251,7 +2251,7 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw, | |||
2251 | } | 2251 | } |
2252 | #endif | 2252 | #endif |
2253 | 2253 | ||
2254 | struct ieee80211_ops iwl_mvm_hw_ops = { | 2254 | const struct ieee80211_ops iwl_mvm_hw_ops = { |
2255 | .tx = iwl_mvm_mac_tx, | 2255 | .tx = iwl_mvm_mac_tx, |
2256 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 2256 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
2257 | .start = iwl_mvm_mac_start, | 2257 | .start = iwl_mvm_mac_start, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index ad0315abf765..302cf779c172 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -91,8 +91,7 @@ enum iwl_mvm_tx_fifo { | |||
91 | IWL_MVM_TX_FIFO_MCAST = 5, | 91 | IWL_MVM_TX_FIFO_MCAST = 5, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | extern struct ieee80211_ops iwl_mvm_hw_ops; | 94 | extern const struct ieee80211_ops iwl_mvm_hw_ops; |
95 | extern const struct iwl_mvm_power_ops pm_mac_ops; | ||
96 | 95 | ||
97 | /** | 96 | /** |
98 | * struct iwl_mvm_mod_params - module parameters for iwlmvm | 97 | * struct iwl_mvm_mod_params - module parameters for iwlmvm |
@@ -426,6 +425,28 @@ struct iwl_mvm_tt_mgmt { | |||
426 | bool throttle; | 425 | bool throttle; |
427 | }; | 426 | }; |
428 | 427 | ||
428 | #define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8 | ||
429 | |||
430 | struct iwl_mvm_frame_stats { | ||
431 | u32 legacy_frames; | ||
432 | u32 ht_frames; | ||
433 | u32 vht_frames; | ||
434 | u32 bw_20_frames; | ||
435 | u32 bw_40_frames; | ||
436 | u32 bw_80_frames; | ||
437 | u32 bw_160_frames; | ||
438 | u32 sgi_frames; | ||
439 | u32 ngi_frames; | ||
440 | u32 siso_frames; | ||
441 | u32 mimo2_frames; | ||
442 | u32 agg_frames; | ||
443 | u32 ampdu_count; | ||
444 | u32 success_frames; | ||
445 | u32 fail_frames; | ||
446 | u32 last_rates[IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES]; | ||
447 | int last_frame_idx; | ||
448 | }; | ||
449 | |||
429 | struct iwl_mvm { | 450 | struct iwl_mvm { |
430 | /* for logger access */ | 451 | /* for logger access */ |
431 | struct device *dev; | 452 | struct device *dev; |
@@ -519,6 +540,7 @@ struct iwl_mvm { | |||
519 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 540 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
520 | struct dentry *debugfs_dir; | 541 | struct dentry *debugfs_dir; |
521 | u32 dbgfs_sram_offset, dbgfs_sram_len; | 542 | u32 dbgfs_sram_offset, dbgfs_sram_len; |
543 | u32 dbgfs_prph_reg_addr; | ||
522 | bool disable_power_off; | 544 | bool disable_power_off; |
523 | bool disable_power_off_d3; | 545 | bool disable_power_off_d3; |
524 | 546 | ||
@@ -526,6 +548,9 @@ struct iwl_mvm { | |||
526 | struct debugfs_blob_wrapper nvm_sw_blob; | 548 | struct debugfs_blob_wrapper nvm_sw_blob; |
527 | struct debugfs_blob_wrapper nvm_calib_blob; | 549 | struct debugfs_blob_wrapper nvm_calib_blob; |
528 | struct debugfs_blob_wrapper nvm_prod_blob; | 550 | struct debugfs_blob_wrapper nvm_prod_blob; |
551 | |||
552 | struct iwl_mvm_frame_stats drv_rx_stats; | ||
553 | spinlock_t drv_stats_lock; | ||
529 | #endif | 554 | #endif |
530 | 555 | ||
531 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; | 556 | struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; |
@@ -587,8 +612,6 @@ struct iwl_mvm { | |||
587 | u8 first_agg_queue; | 612 | u8 first_agg_queue; |
588 | u8 last_agg_queue; | 613 | u8 last_agg_queue; |
589 | 614 | ||
590 | u8 bound_vif_cnt; | ||
591 | |||
592 | /* Indicate if device power save is allowed */ | 615 | /* Indicate if device power save is allowed */ |
593 | bool ps_disabled; | 616 | bool ps_disabled; |
594 | /* Indicate if device power management is allowed */ | 617 | /* Indicate if device power management is allowed */ |
@@ -812,6 +835,10 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
812 | 835 | ||
813 | /* rate scaling */ | 836 | /* rate scaling */ |
814 | int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); | 837 | int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); |
838 | void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, | ||
839 | struct iwl_mvm_frame_stats *stats, | ||
840 | u32 rate, bool agg); | ||
841 | int rs_pretty_print_rate(char *buf, const u32 rate); | ||
815 | 842 | ||
816 | /* power management */ | 843 | /* power management */ |
817 | int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm); | 844 | int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 2d5251b3600c..cf2d09f53782 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -228,13 +228,23 @@ static struct iwl_nvm_data * | |||
228 | iwl_parse_nvm_sections(struct iwl_mvm *mvm) | 228 | iwl_parse_nvm_sections(struct iwl_mvm *mvm) |
229 | { | 229 | { |
230 | struct iwl_nvm_section *sections = mvm->nvm_sections; | 230 | struct iwl_nvm_section *sections = mvm->nvm_sections; |
231 | const __le16 *hw, *sw, *calib; | 231 | const __le16 *hw, *sw, *calib, *regulatory, *mac_override; |
232 | 232 | ||
233 | /* Checking for required sections */ | 233 | /* Checking for required sections */ |
234 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || | 234 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
235 | !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { | 235 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || |
236 | IWL_ERR(mvm, "Can't parse empty NVM sections\n"); | 236 | !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { |
237 | return NULL; | 237 | IWL_ERR(mvm, "Can't parse empty NVM sections\n"); |
238 | return NULL; | ||
239 | } | ||
240 | } else { | ||
241 | if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || | ||
242 | !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data || | ||
243 | !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { | ||
244 | IWL_ERR(mvm, | ||
245 | "Can't parse empty family 8000 NVM sections\n"); | ||
246 | return NULL; | ||
247 | } | ||
238 | } | 248 | } |
239 | 249 | ||
240 | if (WARN_ON(!mvm->cfg)) | 250 | if (WARN_ON(!mvm->cfg)) |
@@ -243,9 +253,14 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
243 | hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; | 253 | hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; |
244 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; | 254 | sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; |
245 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; | 255 | calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; |
256 | regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; | ||
257 | mac_override = | ||
258 | (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data; | ||
259 | |||
246 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, | 260 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, |
247 | iwl_fw_valid_tx_ant(mvm->fw), | 261 | regulatory, mac_override, |
248 | iwl_fw_valid_rx_ant(mvm->fw)); | 262 | mvm->fw->valid_tx_ant, |
263 | mvm->fw->valid_rx_ant); | ||
249 | } | 264 | } |
250 | 265 | ||
251 | #define MAX_NVM_FILE_LEN 16384 | 266 | #define MAX_NVM_FILE_LEN 16384 |
@@ -285,6 +300,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
285 | 300 | ||
286 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) | 301 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) |
287 | #define NVM_WORD2_ID(x) (x >> 12) | 302 | #define NVM_WORD2_ID(x) (x >> 12) |
303 | #define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8)) | ||
304 | #define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4) | ||
288 | 305 | ||
289 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); | 306 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); |
290 | 307 | ||
@@ -335,8 +352,16 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
335 | break; | 352 | break; |
336 | } | 353 | } |
337 | 354 | ||
338 | section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1)); | 355 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
339 | section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2)); | 356 | section_size = |
357 | 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1)); | ||
358 | section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2)); | ||
359 | } else { | ||
360 | section_size = 2 * NVM_WORD2_LEN_FAMILY_8000( | ||
361 | le16_to_cpu(file_sec->word2)); | ||
362 | section_id = NVM_WORD1_ID_FAMILY_8000( | ||
363 | le16_to_cpu(file_sec->word1)); | ||
364 | } | ||
340 | 365 | ||
341 | if (section_size > IWL_MAX_NVM_SECTION_SIZE) { | 366 | if (section_size > IWL_MAX_NVM_SECTION_SIZE) { |
342 | IWL_ERR(mvm, "ERROR - section too large (%d)\n", | 367 | IWL_ERR(mvm, "ERROR - section too large (%d)\n", |
@@ -406,6 +431,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
406 | { | 431 | { |
407 | int ret, i, section; | 432 | int ret, i, section; |
408 | u8 *nvm_buffer, *temp; | 433 | u8 *nvm_buffer, *temp; |
434 | int nvm_to_read[NVM_MAX_NUM_SECTIONS]; | ||
435 | int num_of_sections_to_read; | ||
409 | 436 | ||
410 | if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) | 437 | if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) |
411 | return -EINVAL; | 438 | return -EINVAL; |
@@ -418,12 +445,20 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
418 | return ret; | 445 | return ret; |
419 | } else { | 446 | } else { |
420 | /* list of NVM sections we are allowed/need to read */ | 447 | /* list of NVM sections we are allowed/need to read */ |
421 | int nvm_to_read[] = { | 448 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
422 | mvm->cfg->nvm_hw_section_num, | 449 | nvm_to_read[0] = mvm->cfg->nvm_hw_section_num; |
423 | NVM_SECTION_TYPE_SW, | 450 | nvm_to_read[1] = NVM_SECTION_TYPE_SW; |
424 | NVM_SECTION_TYPE_CALIBRATION, | 451 | nvm_to_read[2] = NVM_SECTION_TYPE_CALIBRATION; |
425 | NVM_SECTION_TYPE_PRODUCTION, | 452 | nvm_to_read[3] = NVM_SECTION_TYPE_PRODUCTION; |
426 | }; | 453 | num_of_sections_to_read = 4; |
454 | } else { | ||
455 | nvm_to_read[0] = NVM_SECTION_TYPE_SW; | ||
456 | nvm_to_read[1] = NVM_SECTION_TYPE_CALIBRATION; | ||
457 | nvm_to_read[2] = NVM_SECTION_TYPE_PRODUCTION; | ||
458 | nvm_to_read[3] = NVM_SECTION_TYPE_REGULATORY; | ||
459 | nvm_to_read[4] = NVM_SECTION_TYPE_MAC_OVERRIDE; | ||
460 | num_of_sections_to_read = 5; | ||
461 | } | ||
427 | 462 | ||
428 | /* Read From FW NVM */ | 463 | /* Read From FW NVM */ |
429 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); | 464 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); |
@@ -433,7 +468,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
433 | GFP_KERNEL); | 468 | GFP_KERNEL); |
434 | if (!nvm_buffer) | 469 | if (!nvm_buffer) |
435 | return -ENOMEM; | 470 | return -ENOMEM; |
436 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 471 | for (i = 0; i < num_of_sections_to_read; i++) { |
437 | section = nvm_to_read[i]; | 472 | section = nvm_to_read[i]; |
438 | /* we override the constness for initial read */ | 473 | /* we override the constness for initial read */ |
439 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | 474 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index a46f0b8b0870..ae347fb16a5d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -245,7 +245,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
245 | #undef RX_HANDLER | 245 | #undef RX_HANDLER |
246 | #define CMD(x) [x] = #x | 246 | #define CMD(x) [x] = #x |
247 | 247 | ||
248 | static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { | 248 | static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { |
249 | CMD(MVM_ALIVE), | 249 | CMD(MVM_ALIVE), |
250 | CMD(REPLY_ERROR), | 250 | CMD(REPLY_ERROR), |
251 | CMD(INIT_COMPLETE_NOTIF), | 251 | CMD(INIT_COMPLETE_NOTIF), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index b7268c0b3333..237efe0ac1c4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | |||
@@ -156,13 +156,13 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, | |||
156 | idle_cnt = chains_static; | 156 | idle_cnt = chains_static; |
157 | active_cnt = chains_dynamic; | 157 | active_cnt = chains_dynamic; |
158 | 158 | ||
159 | cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) << | 159 | cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant << |
160 | PHY_RX_CHAIN_VALID_POS); | 160 | PHY_RX_CHAIN_VALID_POS); |
161 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); | 161 | cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); |
162 | cmd->rxchain_info |= cpu_to_le32(active_cnt << | 162 | cmd->rxchain_info |= cpu_to_le32(active_cnt << |
163 | PHY_RX_CHAIN_MIMO_CNT_POS); | 163 | PHY_RX_CHAIN_MIMO_CNT_POS); |
164 | 164 | ||
165 | cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw)); | 165 | cmd->txchain_info = cpu_to_le32(mvm->fw->valid_tx_ant); |
166 | } | 166 | } |
167 | 167 | ||
168 | /* | 168 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 4da1ea44f39a..def6ec5173b9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -425,7 +425,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, | |||
425 | return 0; | 425 | return 0; |
426 | 426 | ||
427 | if (vif->p2p && | 427 | if (vif->p2p && |
428 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS)) | 428 | !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) |
429 | return 0; | 429 | return 0; |
430 | 430 | ||
431 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 431 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); |
@@ -511,8 +511,11 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, | |||
511 | struct iwl_power_constraint { | 511 | struct iwl_power_constraint { |
512 | struct ieee80211_vif *bf_vif; | 512 | struct ieee80211_vif *bf_vif; |
513 | struct ieee80211_vif *bss_vif; | 513 | struct ieee80211_vif *bss_vif; |
514 | u16 bss_phyctx_id; | ||
515 | u16 p2p_phyctx_id; | ||
514 | bool pm_disabled; | 516 | bool pm_disabled; |
515 | bool ps_disabled; | 517 | bool ps_disabled; |
518 | struct iwl_mvm *mvm; | ||
516 | }; | 519 | }; |
517 | 520 | ||
518 | static void iwl_mvm_power_iterator(void *_data, u8 *mac, | 521 | static void iwl_mvm_power_iterator(void *_data, u8 *mac, |
@@ -520,6 +523,7 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, | |||
520 | { | 523 | { |
521 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 524 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
522 | struct iwl_power_constraint *power_iterator = _data; | 525 | struct iwl_power_constraint *power_iterator = _data; |
526 | struct iwl_mvm *mvm = power_iterator->mvm; | ||
523 | 527 | ||
524 | switch (ieee80211_vif_type_p2p(vif)) { | 528 | switch (ieee80211_vif_type_p2p(vif)) { |
525 | case NL80211_IFTYPE_P2P_DEVICE: | 529 | case NL80211_IFTYPE_P2P_DEVICE: |
@@ -539,11 +543,28 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, | |||
539 | break; | 543 | break; |
540 | 544 | ||
541 | case NL80211_IFTYPE_P2P_CLIENT: | 545 | case NL80211_IFTYPE_P2P_CLIENT: |
542 | /* no BSS power mgmt if we have a P2P client*/ | 546 | if (mvmvif->phy_ctxt) |
543 | power_iterator->pm_disabled = true; | 547 | power_iterator->p2p_phyctx_id = mvmvif->phy_ctxt->id; |
548 | |||
549 | IWL_DEBUG_POWER(mvm, "p2p: p2p_id=%d, bss_id=%d\n", | ||
550 | power_iterator->p2p_phyctx_id, | ||
551 | power_iterator->bss_phyctx_id); | ||
552 | if (!(mvm->fw->ucode_capa.flags & | ||
553 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) { | ||
554 | /* no BSS power mgmt if we have a P2P client*/ | ||
555 | power_iterator->pm_disabled = true; | ||
556 | } else if (power_iterator->p2p_phyctx_id < MAX_PHYS && | ||
557 | power_iterator->bss_phyctx_id < MAX_PHYS && | ||
558 | power_iterator->p2p_phyctx_id == | ||
559 | power_iterator->bss_phyctx_id) { | ||
560 | power_iterator->pm_disabled = true; | ||
561 | } | ||
544 | break; | 562 | break; |
545 | 563 | ||
546 | case NL80211_IFTYPE_STATION: | 564 | case NL80211_IFTYPE_STATION: |
565 | if (mvmvif->phy_ctxt) | ||
566 | power_iterator->bss_phyctx_id = mvmvif->phy_ctxt->id; | ||
567 | |||
547 | /* we should have only one BSS vif */ | 568 | /* we should have only one BSS vif */ |
548 | WARN_ON(power_iterator->bss_vif); | 569 | WARN_ON(power_iterator->bss_vif); |
549 | power_iterator->bss_vif = vif; | 570 | power_iterator->bss_vif = vif; |
@@ -551,6 +572,17 @@ static void iwl_mvm_power_iterator(void *_data, u8 *mac, | |||
551 | if (mvmvif->bf_data.bf_enabled && | 572 | if (mvmvif->bf_data.bf_enabled && |
552 | !WARN_ON(power_iterator->bf_vif)) | 573 | !WARN_ON(power_iterator->bf_vif)) |
553 | power_iterator->bf_vif = vif; | 574 | power_iterator->bf_vif = vif; |
575 | |||
576 | IWL_DEBUG_POWER(mvm, "bss: p2p_id=%d, bss_id=%d\n", | ||
577 | power_iterator->p2p_phyctx_id, | ||
578 | power_iterator->bss_phyctx_id); | ||
579 | if (mvm->fw->ucode_capa.flags & | ||
580 | IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM && | ||
581 | (power_iterator->p2p_phyctx_id < MAX_PHYS && | ||
582 | power_iterator->bss_phyctx_id < MAX_PHYS && | ||
583 | power_iterator->p2p_phyctx_id == | ||
584 | power_iterator->bss_phyctx_id)) | ||
585 | power_iterator->pm_disabled = true; | ||
554 | break; | 586 | break; |
555 | 587 | ||
556 | default: | 588 | default: |
@@ -572,16 +604,16 @@ iwl_mvm_power_get_global_constraint(struct iwl_mvm *mvm, | |||
572 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, | 604 | ieee80211_iterate_active_interfaces_atomic(mvm->hw, |
573 | IEEE80211_IFACE_ITER_NORMAL, | 605 | IEEE80211_IFACE_ITER_NORMAL, |
574 | iwl_mvm_power_iterator, constraint); | 606 | iwl_mvm_power_iterator, constraint); |
575 | |||
576 | /* TODO: remove this and determine this variable in the iterator */ | ||
577 | if (mvm->bound_vif_cnt > 1) | ||
578 | constraint->pm_disabled = true; | ||
579 | } | 607 | } |
580 | 608 | ||
581 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 609 | int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif) |
582 | { | 610 | { |
583 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 611 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
584 | struct iwl_power_constraint constraint = {}; | 612 | struct iwl_power_constraint constraint = { |
613 | .p2p_phyctx_id = MAX_PHYS, | ||
614 | .bss_phyctx_id = MAX_PHYS, | ||
615 | .mvm = mvm, | ||
616 | }; | ||
585 | bool ba_enable; | 617 | bool ba_enable; |
586 | int ret; | 618 | int ret; |
587 | 619 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 32bb8075121c..399709f2be2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -166,7 +166,7 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
166 | if (sta->smps_mode == IEEE80211_SMPS_STATIC) | 166 | if (sta->smps_mode == IEEE80211_SMPS_STATIC) |
167 | return false; | 167 | return false; |
168 | 168 | ||
169 | if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2) | 169 | if (num_of_ant(mvm->fw->valid_tx_ant) < 2) |
170 | return false; | 170 | return false; |
171 | 171 | ||
172 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) | 172 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) |
@@ -917,7 +917,7 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, | |||
917 | 917 | ||
918 | 918 | ||
919 | if (num_of_ant(rate->ant) > 1) | 919 | if (num_of_ant(rate->ant) > 1) |
920 | rate->ant = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | 920 | rate->ant = first_antenna(mvm->fw->valid_tx_ant); |
921 | 921 | ||
922 | /* Relevant in both switching to SISO or Legacy */ | 922 | /* Relevant in both switching to SISO or Legacy */ |
923 | rate->sgi = false; | 923 | rate->sgi = false; |
@@ -1477,7 +1477,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | |||
1477 | const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; | 1477 | const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; |
1478 | const struct rs_tx_column *next_col; | 1478 | const struct rs_tx_column *next_col; |
1479 | allow_column_func_t allow_func; | 1479 | allow_column_func_t allow_func; |
1480 | u8 valid_ants = iwl_fw_valid_tx_ant(mvm->fw); | 1480 | u8 valid_ants = mvm->fw->valid_tx_ant; |
1481 | const u16 *expected_tpt_tbl; | 1481 | const u16 *expected_tpt_tbl; |
1482 | s32 tpt, max_expected_tpt; | 1482 | s32 tpt, max_expected_tpt; |
1483 | 1483 | ||
@@ -2089,7 +2089,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, | |||
2089 | 2089 | ||
2090 | i = lq_sta->last_txrate_idx; | 2090 | i = lq_sta->last_txrate_idx; |
2091 | 2091 | ||
2092 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | 2092 | valid_tx_ant = mvm->fw->valid_tx_ant; |
2093 | 2093 | ||
2094 | if (!lq_sta->search_better_tbl) | 2094 | if (!lq_sta->search_better_tbl) |
2095 | active_tbl = lq_sta->active_tbl; | 2095 | active_tbl = lq_sta->active_tbl; |
@@ -2240,6 +2240,73 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta, | |||
2240 | } | 2240 | } |
2241 | } | 2241 | } |
2242 | 2242 | ||
2243 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
2244 | static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm, | ||
2245 | struct iwl_mvm_frame_stats *stats) | ||
2246 | { | ||
2247 | spin_lock_bh(&mvm->drv_stats_lock); | ||
2248 | memset(stats, 0, sizeof(*stats)); | ||
2249 | spin_unlock_bh(&mvm->drv_stats_lock); | ||
2250 | } | ||
2251 | |||
2252 | void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, | ||
2253 | struct iwl_mvm_frame_stats *stats, | ||
2254 | u32 rate, bool agg) | ||
2255 | { | ||
2256 | u8 nss = 0, mcs = 0; | ||
2257 | |||
2258 | spin_lock(&mvm->drv_stats_lock); | ||
2259 | |||
2260 | if (agg) | ||
2261 | stats->agg_frames++; | ||
2262 | |||
2263 | stats->success_frames++; | ||
2264 | |||
2265 | switch (rate & RATE_MCS_CHAN_WIDTH_MSK) { | ||
2266 | case RATE_MCS_CHAN_WIDTH_20: | ||
2267 | stats->bw_20_frames++; | ||
2268 | break; | ||
2269 | case RATE_MCS_CHAN_WIDTH_40: | ||
2270 | stats->bw_40_frames++; | ||
2271 | break; | ||
2272 | case RATE_MCS_CHAN_WIDTH_80: | ||
2273 | stats->bw_80_frames++; | ||
2274 | break; | ||
2275 | default: | ||
2276 | WARN_ONCE(1, "bad BW. rate 0x%x", rate); | ||
2277 | } | ||
2278 | |||
2279 | if (rate & RATE_MCS_HT_MSK) { | ||
2280 | stats->ht_frames++; | ||
2281 | mcs = rate & RATE_HT_MCS_RATE_CODE_MSK; | ||
2282 | nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1; | ||
2283 | } else if (rate & RATE_MCS_VHT_MSK) { | ||
2284 | stats->vht_frames++; | ||
2285 | mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK; | ||
2286 | nss = ((rate & RATE_VHT_MCS_NSS_MSK) >> | ||
2287 | RATE_VHT_MCS_NSS_POS) + 1; | ||
2288 | } else { | ||
2289 | stats->legacy_frames++; | ||
2290 | } | ||
2291 | |||
2292 | if (nss == 1) | ||
2293 | stats->siso_frames++; | ||
2294 | else if (nss == 2) | ||
2295 | stats->mimo2_frames++; | ||
2296 | |||
2297 | if (rate & RATE_MCS_SGI_MSK) | ||
2298 | stats->sgi_frames++; | ||
2299 | else | ||
2300 | stats->ngi_frames++; | ||
2301 | |||
2302 | stats->last_rates[stats->last_frame_idx] = rate; | ||
2303 | stats->last_frame_idx = (stats->last_frame_idx + 1) % | ||
2304 | ARRAY_SIZE(stats->last_rates); | ||
2305 | |||
2306 | spin_unlock(&mvm->drv_stats_lock); | ||
2307 | } | ||
2308 | #endif | ||
2309 | |||
2243 | /* | 2310 | /* |
2244 | * Called after adding a new station to initialize rate scaling | 2311 | * Called after adding a new station to initialize rate scaling |
2245 | */ | 2312 | */ |
@@ -2319,7 +2386,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2319 | 2386 | ||
2320 | /* These values will be overridden later */ | 2387 | /* These values will be overridden later */ |
2321 | lq_sta->lq.single_stream_ant_msk = | 2388 | lq_sta->lq.single_stream_ant_msk = |
2322 | first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); | 2389 | first_antenna(mvm->fw->valid_tx_ant); |
2323 | lq_sta->lq.dual_stream_ant_msk = ANT_AB; | 2390 | lq_sta->lq.dual_stream_ant_msk = ANT_AB; |
2324 | 2391 | ||
2325 | /* as default allow aggregation for all tids */ | 2392 | /* as default allow aggregation for all tids */ |
@@ -2334,7 +2401,9 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2334 | #ifdef CONFIG_MAC80211_DEBUGFS | 2401 | #ifdef CONFIG_MAC80211_DEBUGFS |
2335 | lq_sta->dbg_fixed_rate = 0; | 2402 | lq_sta->dbg_fixed_rate = 0; |
2336 | #endif | 2403 | #endif |
2337 | 2404 | #ifdef CONFIG_IWLWIFI_DEBUGFS | |
2405 | iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats); | ||
2406 | #endif | ||
2338 | rs_initialize_lq(mvm, sta, lq_sta, band, init); | 2407 | rs_initialize_lq(mvm, sta, lq_sta, band, init); |
2339 | } | 2408 | } |
2340 | 2409 | ||
@@ -2445,7 +2514,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
2445 | 2514 | ||
2446 | memcpy(&rate, initial_rate, sizeof(rate)); | 2515 | memcpy(&rate, initial_rate, sizeof(rate)); |
2447 | 2516 | ||
2448 | valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw); | 2517 | valid_tx_ant = mvm->fw->valid_tx_ant; |
2449 | 2518 | ||
2450 | if (is_siso(&rate)) { | 2519 | if (is_siso(&rate)) { |
2451 | num_rates = RS_INITIAL_SISO_NUM_RATES; | 2520 | num_rates = RS_INITIAL_SISO_NUM_RATES; |
@@ -2546,7 +2615,7 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, | |||
2546 | } | 2615 | } |
2547 | 2616 | ||
2548 | #ifdef CONFIG_MAC80211_DEBUGFS | 2617 | #ifdef CONFIG_MAC80211_DEBUGFS |
2549 | static int rs_pretty_print_rate(char *buf, const u32 rate) | 2618 | int rs_pretty_print_rate(char *buf, const u32 rate) |
2550 | { | 2619 | { |
2551 | 2620 | ||
2552 | char *type, *bw; | 2621 | char *type, *bw; |
@@ -2595,7 +2664,7 @@ static int rs_pretty_print_rate(char *buf, const u32 rate) | |||
2595 | return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n", | 2664 | return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n", |
2596 | type, rs_pretty_ant(ant), bw, mcs, nss, | 2665 | type, rs_pretty_ant(ant), bw, mcs, nss, |
2597 | (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", | 2666 | (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ", |
2598 | (rate & RATE_MCS_STBC_MSK) ? "STBC " : "", | 2667 | (rate & RATE_MCS_HT_STBC_MSK) ? "STBC " : "", |
2599 | (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", | 2668 | (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "", |
2600 | (rate & RATE_MCS_BF_MSK) ? "BF " : "", | 2669 | (rate & RATE_MCS_BF_MSK) ? "BF " : "", |
2601 | (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); | 2670 | (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : ""); |
@@ -2676,9 +2745,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2676 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 2745 | desc += sprintf(buff+desc, "fixed rate 0x%X\n", |
2677 | lq_sta->dbg_fixed_rate); | 2746 | lq_sta->dbg_fixed_rate); |
2678 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 2747 | desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", |
2679 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_A) ? "ANT_A," : "", | 2748 | (mvm->fw->valid_tx_ant & ANT_A) ? "ANT_A," : "", |
2680 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "", | 2749 | (mvm->fw->valid_tx_ant & ANT_B) ? "ANT_B," : "", |
2681 | (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : ""); | 2750 | (mvm->fw->valid_tx_ant & ANT_C) ? "ANT_C" : ""); |
2682 | desc += sprintf(buff+desc, "lq type %s\n", | 2751 | desc += sprintf(buff+desc, "lq type %s\n", |
2683 | (is_legacy(rate)) ? "legacy" : | 2752 | (is_legacy(rate)) ? "legacy" : |
2684 | is_vht(rate) ? "VHT" : "HT"); | 2753 | is_vht(rate) ? "VHT" : "HT"); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index fa3c1393e103..6061553a5e44 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -77,6 +77,15 @@ int iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
77 | 77 | ||
78 | memcpy(&mvm->last_phy_info, pkt->data, sizeof(mvm->last_phy_info)); | 78 | memcpy(&mvm->last_phy_info, pkt->data, sizeof(mvm->last_phy_info)); |
79 | mvm->ampdu_ref++; | 79 | mvm->ampdu_ref++; |
80 | |||
81 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
82 | if (mvm->last_phy_info.phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) { | ||
83 | spin_lock(&mvm->drv_stats_lock); | ||
84 | mvm->drv_rx_stats.ampdu_count++; | ||
85 | spin_unlock(&mvm->drv_stats_lock); | ||
86 | } | ||
87 | #endif | ||
88 | |||
80 | return 0; | 89 | return 0; |
81 | } | 90 | } |
82 | 91 | ||
@@ -368,21 +377,33 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
368 | rx_status.flag |= RX_FLAG_SHORT_GI; | 377 | rx_status.flag |= RX_FLAG_SHORT_GI; |
369 | if (rate_n_flags & RATE_HT_MCS_GF_MSK) | 378 | if (rate_n_flags & RATE_HT_MCS_GF_MSK) |
370 | rx_status.flag |= RX_FLAG_HT_GF; | 379 | rx_status.flag |= RX_FLAG_HT_GF; |
380 | if (rate_n_flags & RATE_MCS_LDPC_MSK) | ||
381 | rx_status.flag |= RX_FLAG_LDPC; | ||
371 | if (rate_n_flags & RATE_MCS_HT_MSK) { | 382 | if (rate_n_flags & RATE_MCS_HT_MSK) { |
383 | u8 stbc = (rate_n_flags & RATE_MCS_HT_STBC_MSK) >> | ||
384 | RATE_MCS_STBC_POS; | ||
372 | rx_status.flag |= RX_FLAG_HT; | 385 | rx_status.flag |= RX_FLAG_HT; |
373 | rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; | 386 | rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK; |
387 | rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT; | ||
374 | } else if (rate_n_flags & RATE_MCS_VHT_MSK) { | 388 | } else if (rate_n_flags & RATE_MCS_VHT_MSK) { |
389 | u8 stbc = (rate_n_flags & RATE_MCS_VHT_STBC_MSK) >> | ||
390 | RATE_MCS_STBC_POS; | ||
375 | rx_status.vht_nss = | 391 | rx_status.vht_nss = |
376 | ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> | 392 | ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> |
377 | RATE_VHT_MCS_NSS_POS) + 1; | 393 | RATE_VHT_MCS_NSS_POS) + 1; |
378 | rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; | 394 | rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; |
379 | rx_status.flag |= RX_FLAG_VHT; | 395 | rx_status.flag |= RX_FLAG_VHT; |
396 | rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT; | ||
380 | } else { | 397 | } else { |
381 | rx_status.rate_idx = | 398 | rx_status.rate_idx = |
382 | iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, | 399 | iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, |
383 | rx_status.band); | 400 | rx_status.band); |
384 | } | 401 | } |
385 | 402 | ||
403 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
404 | iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags, | ||
405 | rx_status.flag & RX_FLAG_AMPDU_DETAILS); | ||
406 | #endif | ||
386 | iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status, | 407 | iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status, |
387 | rxb, &rx_status); | 408 | rxb, &rx_status); |
388 | return 0; | 409 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index eba55cc3352d..713efd71efe2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -82,7 +82,7 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) | |||
82 | if (mvm->scan_rx_ant != ANT_NONE) | 82 | if (mvm->scan_rx_ant != ANT_NONE) |
83 | rx_ant = mvm->scan_rx_ant; | 83 | rx_ant = mvm->scan_rx_ant; |
84 | else | 84 | else |
85 | rx_ant = iwl_fw_valid_rx_ant(mvm->fw); | 85 | rx_ant = mvm->fw->valid_rx_ant; |
86 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; | 86 | rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; |
87 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; | 87 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; |
88 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; | 88 | rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; |
@@ -124,7 +124,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band, | |||
124 | u32 tx_ant; | 124 | u32 tx_ant; |
125 | 125 | ||
126 | mvm->scan_last_antenna_idx = | 126 | mvm->scan_last_antenna_idx = |
127 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), | 127 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, |
128 | mvm->scan_last_antenna_idx); | 128 | mvm->scan_last_antenna_idx); |
129 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; | 129 | tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; |
130 | 130 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index e145dd41e85e..61331245ad93 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -438,7 +438,8 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, | |||
438 | time_cmd.duration = cpu_to_le32(duration); | 438 | time_cmd.duration = cpu_to_le32(duration); |
439 | time_cmd.repeat = 1; | 439 | time_cmd.repeat = 1; |
440 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | | 440 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
441 | TE_V2_NOTIF_HOST_EVENT_END); | 441 | TE_V2_NOTIF_HOST_EVENT_END | |
442 | T2_V2_START_IMMEDIATELY); | ||
442 | 443 | ||
443 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 444 | iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
444 | } | 445 | } |
@@ -553,7 +554,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
553 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); | 554 | time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); |
554 | time_cmd.repeat = 1; | 555 | time_cmd.repeat = 1; |
555 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | | 556 | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | |
556 | TE_V2_NOTIF_HOST_EVENT_END); | 557 | TE_V2_NOTIF_HOST_EVENT_END | |
558 | T2_V2_START_IMMEDIATELY); | ||
557 | 559 | ||
558 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); | 560 | return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); |
559 | } | 561 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 98096fa364cd..0ba96654d2c3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -122,7 +122,7 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, | |||
122 | * it | 122 | * it |
123 | */ | 123 | */ |
124 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); | 124 | WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); |
125 | } else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { | 125 | } else if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) { |
126 | tx_cmd->pm_frame_timeout = cpu_to_le16(2); | 126 | tx_cmd->pm_frame_timeout = cpu_to_le16(2); |
127 | } else { | 127 | } else { |
128 | tx_cmd->pm_frame_timeout = 0; | 128 | tx_cmd->pm_frame_timeout = 0; |
@@ -207,7 +207,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, | |||
207 | rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); | 207 | rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx); |
208 | 208 | ||
209 | mvm->mgmt_last_antenna_idx = | 209 | mvm->mgmt_last_antenna_idx = |
210 | iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw), | 210 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, |
211 | mvm->mgmt_last_antenna_idx); | 211 | mvm->mgmt_last_antenna_idx); |
212 | rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; | 212 | rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; |
213 | 213 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 1493f79e67e0..bbfe529d7b64 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -289,8 +289,8 @@ u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx) | |||
289 | return last_idx; | 289 | return last_idx; |
290 | } | 290 | } |
291 | 291 | ||
292 | static struct { | 292 | static const struct { |
293 | char *name; | 293 | const char *name; |
294 | u8 num; | 294 | u8 num; |
295 | } advanced_lookup[] = { | 295 | } advanced_lookup[] = { |
296 | { "NMI_INTERRUPT_WDG", 0x34 }, | 296 | { "NMI_INTERRUPT_WDG", 0x34 }, |
@@ -589,7 +589,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
589 | lockdep_assert_held(&mvm->mutex); | 589 | lockdep_assert_held(&mvm->mutex); |
590 | 590 | ||
591 | /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */ | 591 | /* SMPS is irrelevant for NICs that don't have at least 2 RX antenna */ |
592 | if (num_of_ant(iwl_fw_valid_rx_ant(mvm->fw)) == 1) | 592 | if (num_of_ant(mvm->fw->valid_rx_ant) == 1) |
593 | return; | 593 | return; |
594 | 594 | ||
595 | if (vif->type == NL80211_IFTYPE_AP) | 595 | if (vif->type == NL80211_IFTYPE_AP) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index e851f26fd44c..3120bc5bb12d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -304,7 +304,7 @@ struct iwl_trans_pcie { | |||
304 | bool bc_table_dword; | 304 | bool bc_table_dword; |
305 | u32 rx_page_order; | 305 | u32 rx_page_order; |
306 | 306 | ||
307 | const char **command_names; | 307 | const char *const *command_names; |
308 | 308 | ||
309 | /* queue watchdog */ | 309 | /* queue watchdog */ |
310 | unsigned long wd_timeout; | 310 | unsigned long wd_timeout; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 41f684deff97..cf49f6ce0ff8 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -155,37 +155,26 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, | |||
155 | if (rxq->need_update == 0) | 155 | if (rxq->need_update == 0) |
156 | goto exit_unlock; | 156 | goto exit_unlock; |
157 | 157 | ||
158 | if (trans->cfg->base_params->shadow_reg_enable) { | 158 | /* |
159 | /* shadow register enabled */ | 159 | * explicitly wake up the NIC if: |
160 | /* Device expects a multiple of 8 */ | 160 | * 1. shadow registers aren't enabled |
161 | rxq->write_actual = (rxq->write & ~0x7); | 161 | * 2. there is a chance that the NIC is asleep |
162 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); | 162 | */ |
163 | } else { | 163 | if (!trans->cfg->base_params->shadow_reg_enable && |
164 | /* If power-saving is in use, make sure device is awake */ | 164 | test_bit(STATUS_TPOWER_PMI, &trans->status)) { |
165 | if (test_bit(STATUS_TPOWER_PMI, &trans->status)) { | 165 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
166 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); | 166 | |
167 | 167 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | |
168 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 168 | IWL_DEBUG_INFO(trans, "Rx queue requesting wakeup, GP1 = 0x%x\n", |
169 | IWL_DEBUG_INFO(trans, | 169 | reg); |
170 | "Rx queue requesting wakeup," | 170 | iwl_set_bit(trans, CSR_GP_CNTRL, |
171 | " GP1 = 0x%x\n", reg); | 171 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
172 | iwl_set_bit(trans, CSR_GP_CNTRL, | 172 | goto exit_unlock; |
173 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
174 | goto exit_unlock; | ||
175 | } | ||
176 | |||
177 | rxq->write_actual = (rxq->write & ~0x7); | ||
178 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, | ||
179 | rxq->write_actual); | ||
180 | |||
181 | /* Else device is assumed to be awake */ | ||
182 | } else { | ||
183 | /* Device expects a multiple of 8 */ | ||
184 | rxq->write_actual = (rxq->write & ~0x7); | ||
185 | iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, | ||
186 | rxq->write_actual); | ||
187 | } | 173 | } |
188 | } | 174 | } |
175 | |||
176 | rxq->write_actual = round_down(rxq->write, 8); | ||
177 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); | ||
189 | rxq->need_update = 0; | 178 | rxq->need_update = 0; |
190 | 179 | ||
191 | exit_unlock: | 180 | exit_unlock: |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 254126447c68..3b0c72c10054 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | 207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, |
208 | le32_to_cpu(txq->scratchbufs[i].scratch)); | 208 | le32_to_cpu(txq->scratchbufs[i].scratch)); |
209 | 209 | ||
210 | iwl_trans_fw_error(trans); | 210 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1); |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
@@ -296,43 +296,38 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) | |||
296 | if (txq->need_update == 0) | 296 | if (txq->need_update == 0) |
297 | return; | 297 | return; |
298 | 298 | ||
299 | if (trans->cfg->base_params->shadow_reg_enable || | 299 | /* |
300 | txq_id == trans_pcie->cmd_queue) { | 300 | * explicitly wake up the NIC if: |
301 | /* shadow register enabled */ | 301 | * 1. shadow registers aren't enabled |
302 | iwl_write32(trans, HBUS_TARG_WRPTR, | 302 | * 2. NIC is woken up for CMD regardless of shadow outside this function |
303 | txq->q.write_ptr | (txq_id << 8)); | 303 | * 3. there is a chance that the NIC is asleep |
304 | } else { | 304 | */ |
305 | /* if we're trying to save power */ | 305 | if (!trans->cfg->base_params->shadow_reg_enable && |
306 | if (test_bit(STATUS_TPOWER_PMI, &trans->status)) { | 306 | txq_id != trans_pcie->cmd_queue && |
307 | /* wake up nic if it's powered down ... | 307 | test_bit(STATUS_TPOWER_PMI, &trans->status)) { |
308 | * uCode will wake up, and interrupt us again, so next | ||
309 | * time we'll skip this part. */ | ||
310 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); | ||
311 | |||
312 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | ||
313 | IWL_DEBUG_INFO(trans, | ||
314 | "Tx queue %d requesting wakeup," | ||
315 | " GP1 = 0x%x\n", txq_id, reg); | ||
316 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
317 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
318 | return; | ||
319 | } | ||
320 | |||
321 | IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, | ||
322 | txq->q.write_ptr); | ||
323 | |||
324 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | ||
325 | txq->q.write_ptr | (txq_id << 8)); | ||
326 | |||
327 | /* | 308 | /* |
328 | * else not in power-save mode, | 309 | * wake up nic if it's powered down ... |
329 | * uCode will never sleep when we're | 310 | * uCode will wake up, and interrupt us again, so next |
330 | * trying to tx (during RFKILL, we're not trying to tx). | 311 | * time we'll skip this part. |
331 | */ | 312 | */ |
332 | } else | 313 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
333 | iwl_write32(trans, HBUS_TARG_WRPTR, | 314 | |
334 | txq->q.write_ptr | (txq_id << 8)); | 315 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
316 | IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", | ||
317 | txq_id, reg); | ||
318 | iwl_set_bit(trans, CSR_GP_CNTRL, | ||
319 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
320 | return; | ||
321 | } | ||
335 | } | 322 | } |
323 | |||
324 | /* | ||
325 | * if not in power-save mode, uCode will never sleep when we're | ||
326 | * trying to tx (during RFKILL, we're not trying to tx). | ||
327 | */ | ||
328 | IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr); | ||
329 | iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); | ||
330 | |||
336 | txq->need_update = 0; | 331 | txq->need_update = 0; |
337 | } | 332 | } |
338 | 333 | ||
@@ -1029,7 +1024,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
1029 | if (nfreed++ > 0) { | 1024 | if (nfreed++ > 0) { |
1030 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", | 1025 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", |
1031 | idx, q->write_ptr, q->read_ptr); | 1026 | idx, q->write_ptr, q->read_ptr); |
1032 | iwl_trans_fw_error(trans); | 1027 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1); |
1033 | } | 1028 | } |
1034 | } | 1029 | } |
1035 | 1030 | ||
@@ -1588,6 +1583,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1588 | get_cmd_string(trans_pcie, cmd->id)); | 1583 | get_cmd_string(trans_pcie, cmd->id)); |
1589 | ret = -ETIMEDOUT; | 1584 | ret = -ETIMEDOUT; |
1590 | 1585 | ||
1586 | iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1); | ||
1591 | iwl_trans_fw_error(trans); | 1587 | iwl_trans_fw_error(trans); |
1592 | 1588 | ||
1593 | goto cancel; | 1589 | goto cancel; |