diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-06-25 15:29:03 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-06-25 15:29:03 -0400 |
commit | 5f4ef7197db98a40e43904806612a8ccf609c0a3 (patch) | |
tree | f637867461ac228db910989299c11509ed0ea129 | |
parent | 855df36de365fb3b49eb06c352015e3d215b43fe (diff) | |
parent | c47af22ad630e03053f3eeefd19bd8274989ffbb (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
31 files changed, 609 insertions, 177 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index f2c1439566b5..760c45c34ef3 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c | |||
@@ -40,6 +40,10 @@ | |||
40 | #include "commands.h" | 40 | #include "commands.h" |
41 | #include "power.h" | 41 | #include "power.h" |
42 | 42 | ||
43 | static bool force_cam; | ||
44 | module_param(force_cam, bool, 0644); | ||
45 | MODULE_PARM_DESC(force_cam, "force continuously aware mode (no power saving at all)"); | ||
46 | |||
43 | /* | 47 | /* |
44 | * Setting power level allows the card to go to sleep when not busy. | 48 | * Setting power level allows the card to go to sleep when not busy. |
45 | * | 49 | * |
@@ -288,6 +292,11 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
288 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; | 292 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; |
289 | int dtimper; | 293 | int dtimper; |
290 | 294 | ||
295 | if (force_cam) { | ||
296 | iwl_power_sleep_cam_cmd(priv, cmd); | ||
297 | return; | ||
298 | } | ||
299 | |||
291 | dtimper = priv->hw->conf.ps_dtim_period ?: 1; | 300 | dtimper = priv->hw->conf.ps_dtim_period ?: 1; |
292 | 301 | ||
293 | if (priv->wowlan) | 302 | if (priv->wowlan) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index 51c41531d81d..51486cc9d943 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c | |||
@@ -67,7 +67,7 @@ | |||
67 | #include "iwl-agn-hw.h" | 67 | #include "iwl-agn-hw.h" |
68 | 68 | ||
69 | /* Highest firmware API version supported */ | 69 | /* Highest firmware API version supported */ |
70 | #define IWL8000_UCODE_API_MAX 8 | 70 | #define IWL8000_UCODE_API_MAX 9 |
71 | 71 | ||
72 | /* Oldest version we won't warn about */ | 72 | /* Oldest version we won't warn about */ |
73 | #define IWL8000_UCODE_API_OK 8 | 73 | #define IWL8000_UCODE_API_OK 8 |
@@ -119,10 +119,9 @@ const struct iwl_cfg iwl8260_2ac_cfg = { | |||
119 | .ht_params = &iwl8000_ht_params, | 119 | .ht_params = &iwl8000_ht_params, |
120 | .nvm_ver = IWL8000_NVM_VERSION, | 120 | .nvm_ver = IWL8000_NVM_VERSION, |
121 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 121 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
122 | .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000, | ||
123 | }; | 122 | }; |
124 | 123 | ||
125 | const struct iwl_cfg iwl8260_n_cfg = { | 124 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { |
126 | .name = "Intel(R) Dual Band Wireless-AC 8260", | 125 | .name = "Intel(R) Dual Band Wireless-AC 8260", |
127 | .fw_name_pre = IWL8000_FW_PRE, | 126 | .fw_name_pre = IWL8000_FW_PRE, |
128 | IWL_DEVICE_8000, | 127 | IWL_DEVICE_8000, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index b7047905f41a..034c2fc4b69f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -337,7 +337,7 @@ extern const struct iwl_cfg iwl7265_2ac_cfg; | |||
337 | extern const struct iwl_cfg iwl7265_2n_cfg; | 337 | extern const struct iwl_cfg iwl7265_2n_cfg; |
338 | extern const struct iwl_cfg iwl7265_n_cfg; | 338 | extern const struct iwl_cfg iwl7265_n_cfg; |
339 | extern const struct iwl_cfg iwl8260_2ac_cfg; | 339 | extern const struct iwl_cfg iwl8260_2ac_cfg; |
340 | extern const struct iwl_cfg iwl8260_n_cfg; | 340 | extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; |
341 | #endif /* CONFIG_IWLMVM */ | 341 | #endif /* CONFIG_IWLMVM */ |
342 | 342 | ||
343 | #endif /* __IWL_CONFIG_H__ */ | 343 | #endif /* __IWL_CONFIG_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index f2a5c12269a3..bb842f4732dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -155,6 +155,8 @@ static struct iwlwifi_opmode_table { | |||
155 | [MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL }, | 155 | [MVM_OP_MODE] = { .name = "iwlmvm", .ops = NULL }, |
156 | }; | 156 | }; |
157 | 157 | ||
158 | #define IWL_DEFAULT_SCAN_CHANNELS 40 | ||
159 | |||
158 | /* | 160 | /* |
159 | * struct fw_sec: Just for the image parsing proccess. | 161 | * struct fw_sec: Just for the image parsing proccess. |
160 | * For the fw storage we are using struct fw_desc. | 162 | * For the fw storage we are using struct fw_desc. |
@@ -565,6 +567,8 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
565 | } | 567 | } |
566 | 568 | ||
567 | drv->fw.ucode_ver = le32_to_cpu(ucode->ver); | 569 | drv->fw.ucode_ver = le32_to_cpu(ucode->ver); |
570 | memcpy(drv->fw.human_readable, ucode->human_readable, | ||
571 | sizeof(drv->fw.human_readable)); | ||
568 | build = le32_to_cpu(ucode->build); | 572 | build = le32_to_cpu(ucode->build); |
569 | 573 | ||
570 | if (build) | 574 | if (build) |
@@ -819,6 +823,12 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
819 | if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len)) | 823 | if (iwl_store_cscheme(&drv->fw, tlv_data, tlv_len)) |
820 | goto invalid_tlv_len; | 824 | goto invalid_tlv_len; |
821 | break; | 825 | break; |
826 | case IWL_UCODE_TLV_N_SCAN_CHANNELS: | ||
827 | if (tlv_len != sizeof(u32)) | ||
828 | goto invalid_tlv_len; | ||
829 | capa->n_scan_channels = | ||
830 | le32_to_cpup((__le32 *)tlv_data); | ||
831 | break; | ||
822 | default: | 832 | default: |
823 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); | 833 | IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type); |
824 | break; | 834 | break; |
@@ -973,6 +983,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) | |||
973 | fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; | 983 | fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH; |
974 | fw->ucode_capa.standard_phy_calibration_size = | 984 | fw->ucode_capa.standard_phy_calibration_size = |
975 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; | 985 | IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; |
986 | fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; | ||
976 | 987 | ||
977 | if (!api_ok) | 988 | if (!api_ok) |
978 | api_ok = api_max; | 989 | api_ok = api_max; |
@@ -1394,3 +1405,7 @@ module_param_named(power_level, iwlwifi_mod_params.power_level, | |||
1394 | int, S_IRUGO); | 1405 | int, S_IRUGO); |
1395 | MODULE_PARM_DESC(power_level, | 1406 | MODULE_PARM_DESC(power_level, |
1396 | "default power save level (range from 1 - 5, default: 1)"); | 1407 | "default power save level (range from 1 - 5, default: 1)"); |
1408 | |||
1409 | module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO); | ||
1410 | MODULE_PARM_DESC(dbgm, | ||
1411 | "firmware monitor - to debug FW (default: false - needs lots of memory)"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index c44cf1149648..07ff7e0028ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | |||
@@ -779,7 +779,6 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | |||
779 | if (cfg->ht_params->ht40_bands & BIT(band)) { | 779 | if (cfg->ht_params->ht40_bands & BIT(band)) { |
780 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 780 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
781 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | 781 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; |
782 | ht_info->mcs.rx_mask[4] = 0x01; | ||
783 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | 782 | max_bit_rate = MAX_BIT_RATE_40_MHZ; |
784 | } | 783 | } |
785 | 784 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index 2953ffceda38..ced5ba95c23d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | |||
@@ -74,12 +74,17 @@ | |||
74 | * @IWL_FW_ERROR_DUMP_RXF: | 74 | * @IWL_FW_ERROR_DUMP_RXF: |
75 | * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as | 75 | * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as |
76 | * &struct iwl_fw_error_dump_txcmd packets | 76 | * &struct iwl_fw_error_dump_txcmd packets |
77 | * @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info | ||
78 | * info on the device / firmware. | ||
79 | * @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor | ||
77 | */ | 80 | */ |
78 | enum iwl_fw_error_dump_type { | 81 | enum iwl_fw_error_dump_type { |
79 | IWL_FW_ERROR_DUMP_SRAM = 0, | 82 | IWL_FW_ERROR_DUMP_SRAM = 0, |
80 | IWL_FW_ERROR_DUMP_REG = 1, | 83 | IWL_FW_ERROR_DUMP_REG = 1, |
81 | IWL_FW_ERROR_DUMP_RXF = 2, | 84 | IWL_FW_ERROR_DUMP_RXF = 2, |
82 | IWL_FW_ERROR_DUMP_TXCMD = 3, | 85 | IWL_FW_ERROR_DUMP_TXCMD = 3, |
86 | IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4, | ||
87 | IWL_FW_ERROR_DUMP_FW_MONITOR = 5, | ||
83 | 88 | ||
84 | IWL_FW_ERROR_DUMP_MAX, | 89 | IWL_FW_ERROR_DUMP_MAX, |
85 | }; | 90 | }; |
@@ -120,13 +125,50 @@ struct iwl_fw_error_dump_txcmd { | |||
120 | u8 data[]; | 125 | u8 data[]; |
121 | } __packed; | 126 | } __packed; |
122 | 127 | ||
128 | enum iwl_fw_error_dump_family { | ||
129 | IWL_FW_ERROR_DUMP_FAMILY_7 = 7, | ||
130 | IWL_FW_ERROR_DUMP_FAMILY_8 = 8, | ||
131 | }; | ||
132 | |||
133 | /** | ||
134 | * struct iwl_fw_error_dump_info - info on the device / firmware | ||
135 | * @device_family: the family of the device (7 / 8) | ||
136 | * @hw_step: the step of the device | ||
137 | * @fw_human_readable: human readable FW version | ||
138 | * @dev_human_readable: name of the device | ||
139 | * @bus_human_readable: name of the bus used | ||
140 | */ | ||
141 | struct iwl_fw_error_dump_info { | ||
142 | __le32 device_family; | ||
143 | __le32 hw_step; | ||
144 | u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ]; | ||
145 | u8 dev_human_readable[64]; | ||
146 | u8 bus_human_readable[8]; | ||
147 | } __packed; | ||
148 | |||
149 | /** | ||
150 | * struct iwl_fw_error_fw_mon - FW monitor data | ||
151 | * @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer | ||
152 | * @fw_mon_base_ptr: base pointer of the data | ||
153 | * @fw_mon_cycle_cnt: number of wrap arounds | ||
154 | * @reserved: for future use | ||
155 | * @data: captured data | ||
156 | */ | ||
157 | struct iwl_fw_error_fw_mon { | ||
158 | __le32 fw_mon_wr_ptr; | ||
159 | __le32 fw_mon_base_ptr; | ||
160 | __le32 fw_mon_cycle_cnt; | ||
161 | __le32 reserved[3]; | ||
162 | u8 data[]; | ||
163 | } __packed; | ||
164 | |||
123 | /** | 165 | /** |
124 | * iwl_mvm_fw_error_next_data - advance fw error dump data pointer | 166 | * iwl_fw_error_next_data - advance fw error dump data pointer |
125 | * @data: previous data block | 167 | * @data: previous data block |
126 | * Returns: next data block | 168 | * Returns: next data block |
127 | */ | 169 | */ |
128 | static inline struct iwl_fw_error_dump_data * | 170 | static inline struct iwl_fw_error_dump_data * |
129 | iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data) | 171 | iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) |
130 | { | 172 | { |
131 | return (void *)(data->data + le32_to_cpu(data->len)); | 173 | return (void *)(data->data + le32_to_cpu(data->len)); |
132 | } | 174 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index b45e576a4b57..929a8063354c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -128,6 +128,7 @@ enum iwl_ucode_tlv_type { | |||
128 | IWL_UCODE_TLV_CSCHEME = 28, | 128 | IWL_UCODE_TLV_CSCHEME = 28, |
129 | IWL_UCODE_TLV_API_CHANGES_SET = 29, | 129 | IWL_UCODE_TLV_API_CHANGES_SET = 29, |
130 | IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30, | 130 | IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30, |
131 | IWL_UCODE_TLV_N_SCAN_CHANNELS = 31, | ||
131 | }; | 132 | }; |
132 | 133 | ||
133 | struct iwl_ucode_tlv { | 134 | struct iwl_ucode_tlv { |
@@ -136,7 +137,8 @@ struct iwl_ucode_tlv { | |||
136 | u8 data[0]; | 137 | u8 data[0]; |
137 | }; | 138 | }; |
138 | 139 | ||
139 | #define IWL_TLV_UCODE_MAGIC 0x0a4c5749 | 140 | #define IWL_TLV_UCODE_MAGIC 0x0a4c5749 |
141 | #define FW_VER_HUMAN_READABLE_SZ 64 | ||
140 | 142 | ||
141 | struct iwl_tlv_ucode_header { | 143 | struct iwl_tlv_ucode_header { |
142 | /* | 144 | /* |
@@ -147,7 +149,7 @@ struct iwl_tlv_ucode_header { | |||
147 | */ | 149 | */ |
148 | __le32 zero; | 150 | __le32 zero; |
149 | __le32 magic; | 151 | __le32 magic; |
150 | u8 human_readable[64]; | 152 | u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; |
151 | __le32 ver; /* major/minor/API/serial */ | 153 | __le32 ver; /* major/minor/API/serial */ |
152 | __le32 build; | 154 | __le32 build; |
153 | __le64 ignore; | 155 | __le64 ignore; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 0aa7c0085c9f..13e5d69845e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -65,6 +65,8 @@ | |||
65 | #include <linux/types.h> | 65 | #include <linux/types.h> |
66 | #include <net/mac80211.h> | 66 | #include <net/mac80211.h> |
67 | 67 | ||
68 | #include "iwl-fw-file.h" | ||
69 | |||
68 | /** | 70 | /** |
69 | * enum iwl_ucode_tlv_flag - ucode API flags | 71 | * enum iwl_ucode_tlv_flag - ucode API flags |
70 | * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously | 72 | * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously |
@@ -117,11 +119,15 @@ enum iwl_ucode_tlv_flag { | |||
117 | /** | 119 | /** |
118 | * enum iwl_ucode_tlv_api - ucode api | 120 | * enum iwl_ucode_tlv_api - ucode api |
119 | * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. | 121 | * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field. |
122 | * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification | ||
120 | * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA. | 123 | * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA. |
124 | * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit. | ||
121 | */ | 125 | */ |
122 | enum iwl_ucode_tlv_api { | 126 | enum iwl_ucode_tlv_api { |
123 | IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0), | 127 | IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0), |
128 | IWL_UCODE_TLV_CAPA_EXTENDED_BEACON = BIT(1), | ||
124 | IWL_UCODE_TLV_API_CSA_FLOW = BIT(4), | 129 | IWL_UCODE_TLV_API_CSA_FLOW = BIT(4), |
130 | IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5), | ||
125 | }; | 131 | }; |
126 | 132 | ||
127 | /** | 133 | /** |
@@ -178,6 +184,7 @@ enum iwl_ucode_sec { | |||
178 | 184 | ||
179 | struct iwl_ucode_capabilities { | 185 | struct iwl_ucode_capabilities { |
180 | u32 max_probe_length; | 186 | u32 max_probe_length; |
187 | u32 n_scan_channels; | ||
181 | u32 standard_phy_calibration_size; | 188 | u32 standard_phy_calibration_size; |
182 | u32 flags; | 189 | u32 flags; |
183 | u32 api[IWL_API_ARRAY_SIZE]; | 190 | u32 api[IWL_API_ARRAY_SIZE]; |
@@ -311,6 +318,7 @@ struct iwl_fw { | |||
311 | bool mvm_fw; | 318 | bool mvm_fw; |
312 | 319 | ||
313 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; | 320 | struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; |
321 | u8 human_readable[FW_VER_HUMAN_READABLE_SZ]; | ||
314 | }; | 322 | }; |
315 | 323 | ||
316 | #endif /* __iwl_fw_h__ */ | 324 | #endif /* __iwl_fw_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index d051857729ab..f2d39cb011fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -103,6 +103,7 @@ enum iwl_disable_11n { | |||
103 | * @power_level: power level, default = 1 | 103 | * @power_level: power level, default = 1 |
104 | * @debug_level: levels are IWL_DL_* | 104 | * @debug_level: levels are IWL_DL_* |
105 | * @ant_coupling: antenna coupling in dB, default = 0 | 105 | * @ant_coupling: antenna coupling in dB, default = 0 |
106 | * @fw_monitor: allow to use firmware monitor | ||
106 | */ | 107 | */ |
107 | struct iwl_mod_params { | 108 | struct iwl_mod_params { |
108 | int sw_crypto; | 109 | int sw_crypto; |
@@ -120,6 +121,7 @@ struct iwl_mod_params { | |||
120 | int ant_coupling; | 121 | int ant_coupling; |
121 | char *nvm_file; | 122 | char *nvm_file; |
122 | bool uapsd_disable; | 123 | bool uapsd_disable; |
124 | bool fw_monitor; | ||
123 | }; | 125 | }; |
124 | 126 | ||
125 | #endif /* #__iwl_modparams_h__ */ | 127 | #endif /* #__iwl_modparams_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 85eee79c495c..f0ae038f3339 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -174,7 +174,9 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = { | |||
174 | * @NVM_CHANNEL_IBSS: usable as an IBSS channel | 174 | * @NVM_CHANNEL_IBSS: usable as an IBSS channel |
175 | * @NVM_CHANNEL_ACTIVE: active scanning allowed | 175 | * @NVM_CHANNEL_ACTIVE: active scanning allowed |
176 | * @NVM_CHANNEL_RADAR: radar detection required | 176 | * @NVM_CHANNEL_RADAR: radar detection required |
177 | * @NVM_CHANNEL_DFS: dynamic freq selection candidate | 177 | * @NVM_CHANNEL_INDOOR_ONLY: only indoor use is allowed |
178 | * @NVM_CHANNEL_GO_CONCURRENT: GO operation is allowed when connected to BSS | ||
179 | * on same channel on 2.4 or same UNII band on 5.2 | ||
178 | * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?) | 180 | * @NVM_CHANNEL_WIDE: 20 MHz channel okay (?) |
179 | * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) | 181 | * @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?) |
180 | * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?) | 182 | * @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?) |
@@ -185,7 +187,8 @@ enum iwl_nvm_channel_flags { | |||
185 | NVM_CHANNEL_IBSS = BIT(1), | 187 | NVM_CHANNEL_IBSS = BIT(1), |
186 | NVM_CHANNEL_ACTIVE = BIT(3), | 188 | NVM_CHANNEL_ACTIVE = BIT(3), |
187 | NVM_CHANNEL_RADAR = BIT(4), | 189 | NVM_CHANNEL_RADAR = BIT(4), |
188 | NVM_CHANNEL_DFS = BIT(7), | 190 | NVM_CHANNEL_INDOOR_ONLY = BIT(5), |
191 | NVM_CHANNEL_GO_CONCURRENT = BIT(6), | ||
189 | NVM_CHANNEL_WIDE = BIT(8), | 192 | NVM_CHANNEL_WIDE = BIT(8), |
190 | NVM_CHANNEL_40MHZ = BIT(9), | 193 | NVM_CHANNEL_40MHZ = BIT(9), |
191 | NVM_CHANNEL_80MHZ = BIT(10), | 194 | NVM_CHANNEL_80MHZ = BIT(10), |
@@ -273,6 +276,16 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
273 | if (ch_flags & NVM_CHANNEL_RADAR) | 276 | if (ch_flags & NVM_CHANNEL_RADAR) |
274 | channel->flags |= IEEE80211_CHAN_RADAR; | 277 | channel->flags |= IEEE80211_CHAN_RADAR; |
275 | 278 | ||
279 | if (ch_flags & NVM_CHANNEL_INDOOR_ONLY) | ||
280 | channel->flags |= IEEE80211_CHAN_INDOOR_ONLY; | ||
281 | |||
282 | /* Set the GO concurrent flag only in case that NO_IR is set. | ||
283 | * Otherwise it is meaningless | ||
284 | */ | ||
285 | if ((ch_flags & NVM_CHANNEL_GO_CONCURRENT) && | ||
286 | (channel->flags & IEEE80211_CHAN_NO_IR)) | ||
287 | channel->flags |= IEEE80211_CHAN_GO_CONCURRENT; | ||
288 | |||
276 | /* Initialize regulatory-based run-time data */ | 289 | /* Initialize regulatory-based run-time data */ |
277 | 290 | ||
278 | /* | 291 | /* |
@@ -282,7 +295,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
282 | channel->max_power = DEFAULT_MAX_TX_POWER; | 295 | channel->max_power = DEFAULT_MAX_TX_POWER; |
283 | is_5ghz = channel->band == IEEE80211_BAND_5GHZ; | 296 | is_5ghz = channel->band == IEEE80211_BAND_5GHZ; |
284 | IWL_DEBUG_EEPROM(dev, | 297 | IWL_DEBUG_EEPROM(dev, |
285 | "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | 298 | "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", |
286 | channel->hw_value, | 299 | channel->hw_value, |
287 | is_5ghz ? "5.2" : "2.4", | 300 | is_5ghz ? "5.2" : "2.4", |
288 | CHECK_AND_PRINT_I(VALID), | 301 | CHECK_AND_PRINT_I(VALID), |
@@ -290,7 +303,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
290 | CHECK_AND_PRINT_I(ACTIVE), | 303 | CHECK_AND_PRINT_I(ACTIVE), |
291 | CHECK_AND_PRINT_I(RADAR), | 304 | CHECK_AND_PRINT_I(RADAR), |
292 | CHECK_AND_PRINT_I(WIDE), | 305 | CHECK_AND_PRINT_I(WIDE), |
293 | CHECK_AND_PRINT_I(DFS), | 306 | CHECK_AND_PRINT_I(INDOOR_ONLY), |
307 | CHECK_AND_PRINT_I(GO_CONCURRENT), | ||
294 | ch_flags, | 308 | ch_flags, |
295 | channel->max_power, | 309 | channel->max_power, |
296 | ((ch_flags & NVM_CHANNEL_IBSS) && | 310 | ((ch_flags & NVM_CHANNEL_IBSS) && |
@@ -462,7 +476,8 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg, | |||
462 | data->hw_addr[5] = hw_addr[4]; | 476 | data->hw_addr[5] = hw_addr[4]; |
463 | } | 477 | } |
464 | 478 | ||
465 | static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg, | 479 | static void iwl_set_hw_address_family_8000(struct device *dev, |
480 | const struct iwl_cfg *cfg, | ||
466 | struct iwl_nvm_data *data, | 481 | struct iwl_nvm_data *data, |
467 | const __le16 *mac_override, | 482 | const __le16 *mac_override, |
468 | const __le16 *nvm_hw) | 483 | const __le16 *nvm_hw) |
@@ -481,20 +496,28 @@ static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg, | |||
481 | data->hw_addr[4] = hw_addr[5]; | 496 | data->hw_addr[4] = hw_addr[5]; |
482 | data->hw_addr[5] = hw_addr[4]; | 497 | data->hw_addr[5] = hw_addr[4]; |
483 | 498 | ||
484 | if (is_valid_ether_addr(hw_addr)) | 499 | if (is_valid_ether_addr(data->hw_addr)) |
485 | return; | 500 | return; |
501 | |||
502 | IWL_ERR_DEV(dev, | ||
503 | "mac address from nvm override section is not valid\n"); | ||
486 | } | 504 | } |
487 | 505 | ||
488 | /* take the MAC address from the OTP */ | 506 | if (nvm_hw) { |
489 | hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000); | 507 | /* take the MAC address from the OTP */ |
490 | data->hw_addr[0] = hw_addr[3]; | 508 | hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000); |
491 | data->hw_addr[1] = hw_addr[2]; | 509 | data->hw_addr[0] = hw_addr[3]; |
492 | data->hw_addr[2] = hw_addr[1]; | 510 | data->hw_addr[1] = hw_addr[2]; |
493 | data->hw_addr[3] = hw_addr[0]; | 511 | data->hw_addr[2] = hw_addr[1]; |
512 | data->hw_addr[3] = hw_addr[0]; | ||
513 | |||
514 | hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000); | ||
515 | data->hw_addr[4] = hw_addr[1]; | ||
516 | data->hw_addr[5] = hw_addr[0]; | ||
517 | return; | ||
518 | } | ||
494 | 519 | ||
495 | hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000); | 520 | IWL_ERR_DEV(dev, "mac address is not found\n"); |
496 | data->hw_addr[4] = hw_addr[1]; | ||
497 | data->hw_addr[5] = hw_addr[0]; | ||
498 | } | 521 | } |
499 | 522 | ||
500 | struct iwl_nvm_data * | 523 | struct iwl_nvm_data * |
@@ -556,7 +579,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | |||
556 | rx_chains); | 579 | rx_chains); |
557 | } else { | 580 | } else { |
558 | /* MAC address in family 8000 */ | 581 | /* MAC address in family 8000 */ |
559 | iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw); | 582 | iwl_set_hw_address_family_8000(dev, cfg, data, mac_override, |
583 | nvm_hw); | ||
560 | 584 | ||
561 | iwl_init_sbands(dev, cfg, data, regulatory, | 585 | iwl_init_sbands(dev, cfg, data, regulatory, |
562 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, | 586 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 4997e27672b3..47033a35a402 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -359,4 +359,10 @@ enum secure_load_status_reg { | |||
359 | #define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10) | 359 | #define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10) |
360 | #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) | 360 | #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) |
361 | 361 | ||
362 | /* FW monitor */ | ||
363 | #define MON_BUFF_BASE_ADDR (0xa03c3c) | ||
364 | #define MON_BUFF_END_ADDR (0xa03c40) | ||
365 | #define MON_BUFF_WRPTR (0xa03c44) | ||
366 | #define MON_BUFF_CYCLE_CNT (0xa03c48) | ||
367 | |||
362 | #endif /* __iwl_prph_h__ */ | 368 | #endif /* __iwl_prph_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index c8c3b38228f0..7e0388a32912 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -100,12 +100,13 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
100 | 100 | ||
101 | #undef EVENT_PRIO_ANT | 101 | #undef EVENT_PRIO_ANT |
102 | 102 | ||
103 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) | ||
104 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) | ||
105 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) | 103 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) |
106 | 104 | ||
107 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 105 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
108 | { | 106 | { |
107 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) | ||
108 | return 0; | ||
109 | |||
109 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0, | 110 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0, |
110 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | 111 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), |
111 | &iwl_bt_prio_tbl); | 112 | &iwl_bt_prio_tbl); |
@@ -535,7 +536,7 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) | |||
535 | if (!chanctx_conf || | 536 | if (!chanctx_conf || |
536 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | 537 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { |
537 | rcu_read_unlock(); | 538 | rcu_read_unlock(); |
538 | return BT_COEX_LOOSE_LUT; | 539 | return BT_COEX_INVALID_LUT; |
539 | } | 540 | } |
540 | 541 | ||
541 | ret = BT_COEX_TX_DIS_LUT; | 542 | ret = BT_COEX_TX_DIS_LUT; |
@@ -578,6 +579,29 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
578 | return -ENOMEM; | 579 | return -ENOMEM; |
579 | cmd.data[0] = bt_cmd; | 580 | cmd.data[0] = bt_cmd; |
580 | 581 | ||
582 | lockdep_assert_held(&mvm->mutex); | ||
583 | |||
584 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) { | ||
585 | switch (mvm->bt_force_ant_mode) { | ||
586 | case BT_FORCE_ANT_AUTO: | ||
587 | flags = BT_COEX_AUTO; | ||
588 | break; | ||
589 | case BT_FORCE_ANT_BT: | ||
590 | flags = BT_COEX_BT; | ||
591 | break; | ||
592 | case BT_FORCE_ANT_WIFI: | ||
593 | flags = BT_COEX_WIFI; | ||
594 | break; | ||
595 | default: | ||
596 | WARN_ON(1); | ||
597 | flags = 0; | ||
598 | } | ||
599 | |||
600 | bt_cmd->flags = cpu_to_le32(flags); | ||
601 | bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE); | ||
602 | goto send_cmd; | ||
603 | } | ||
604 | |||
581 | bt_cmd->max_kill = 5; | 605 | bt_cmd->max_kill = 5; |
582 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD; | 606 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD; |
583 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; | 607 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; |
@@ -642,6 +666,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
642 | bt_cmd->kill_cts_msk = | 666 | bt_cmd->kill_cts_msk = |
643 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | 667 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); |
644 | 668 | ||
669 | send_cmd: | ||
645 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 670 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
646 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | 671 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); |
647 | 672 | ||
@@ -780,9 +805,9 @@ void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm, | |||
780 | 805 | ||
781 | mvmvif->bf_data.last_bt_coex_event = rssi; | 806 | mvmvif->bf_data.last_bt_coex_event = rssi; |
782 | mvmvif->bf_data.bt_coex_max_thold = | 807 | mvmvif->bf_data.bt_coex_max_thold = |
783 | enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0; | 808 | enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0; |
784 | mvmvif->bf_data.bt_coex_min_thold = | 809 | mvmvif->bf_data.bt_coex_min_thold = |
785 | enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0; | 810 | enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0; |
786 | } | 811 | } |
787 | 812 | ||
788 | /* must be called under rcu_read_lock */ | 813 | /* must be called under rcu_read_lock */ |
@@ -919,7 +944,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
919 | /* if the RSSI isn't valid, fake it is very low */ | 944 | /* if the RSSI isn't valid, fake it is very low */ |
920 | if (!ave_rssi) | 945 | if (!ave_rssi) |
921 | ave_rssi = -100; | 946 | ave_rssi = -100; |
922 | if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) { | 947 | if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) { |
923 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) | 948 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true)) |
924 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 949 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
925 | 950 | ||
@@ -930,7 +955,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
930 | * the iteration, if one interface's rssi isn't good enough, | 955 | * the iteration, if one interface's rssi isn't good enough, |
931 | * bt_kill_msk will be set to default values. | 956 | * bt_kill_msk will be set to default values. |
932 | */ | 957 | */ |
933 | } else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) { | 958 | } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) { |
934 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | 959 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) |
935 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 960 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
936 | 961 | ||
@@ -955,6 +980,10 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
955 | struct iwl_bt_coex_ci_cmd cmd = {}; | 980 | struct iwl_bt_coex_ci_cmd cmd = {}; |
956 | u8 ci_bw_idx; | 981 | u8 ci_bw_idx; |
957 | 982 | ||
983 | /* Ignore updates if we are in force mode */ | ||
984 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) | ||
985 | return; | ||
986 | |||
958 | rcu_read_lock(); | 987 | rcu_read_lock(); |
959 | ieee80211_iterate_active_interfaces_atomic( | 988 | ieee80211_iterate_active_interfaces_atomic( |
960 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 989 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
@@ -1121,6 +1150,10 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1121 | 1150 | ||
1122 | lockdep_assert_held(&mvm->mutex); | 1151 | lockdep_assert_held(&mvm->mutex); |
1123 | 1152 | ||
1153 | /* Ignore updates if we are in force mode */ | ||
1154 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) | ||
1155 | return; | ||
1156 | |||
1124 | /* | 1157 | /* |
1125 | * Rssi update while not associated - can happen since the statistics | 1158 | * Rssi update while not associated - can happen since the statistics |
1126 | * are handled asynchronously | 1159 | * are handled asynchronously |
@@ -1177,9 +1210,12 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, | |||
1177 | BT_HIGH_TRAFFIC) | 1210 | BT_HIGH_TRAFFIC) |
1178 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | 1211 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; |
1179 | 1212 | ||
1213 | if (mvm->last_bt_notif.ttc_enabled) | ||
1214 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
1215 | |||
1180 | lut_type = iwl_get_coex_type(mvm, mvmsta->vif); | 1216 | lut_type = iwl_get_coex_type(mvm, mvmsta->vif); |
1181 | 1217 | ||
1182 | if (lut_type == BT_COEX_LOOSE_LUT) | 1218 | if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT) |
1183 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | 1219 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; |
1184 | 1220 | ||
1185 | /* tight coex, high bt traffic, reduce AGG time limit */ | 1221 | /* tight coex, high bt traffic, reduce AGG time limit */ |
@@ -1190,18 +1226,29 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | |||
1190 | struct ieee80211_sta *sta) | 1226 | struct ieee80211_sta *sta) |
1191 | { | 1227 | { |
1192 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1228 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1229 | enum iwl_bt_coex_lut_type lut_type; | ||
1230 | |||
1231 | if (mvm->last_bt_notif.ttc_enabled) | ||
1232 | return true; | ||
1193 | 1233 | ||
1194 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | 1234 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < |
1195 | BT_HIGH_TRAFFIC) | 1235 | BT_HIGH_TRAFFIC) |
1196 | return true; | 1236 | return true; |
1197 | 1237 | ||
1198 | /* | 1238 | /* |
1199 | * In Tight, BT can't Rx while we Tx, so use both antennas since BT is | 1239 | * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas |
1200 | * already killed. | 1240 | * since BT is already killed. |
1201 | * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we | 1241 | * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while |
1202 | * Tx. | 1242 | * we Tx. |
1243 | * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO. | ||
1203 | */ | 1244 | */ |
1204 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; | 1245 | lut_type = iwl_get_coex_type(mvm, mvmsta->vif); |
1246 | return lut_type != BT_COEX_LOOSE_LUT; | ||
1247 | } | ||
1248 | |||
1249 | bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm) | ||
1250 | { | ||
1251 | return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF; | ||
1205 | } | 1252 | } |
1206 | 1253 | ||
1207 | bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, | 1254 | bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, |
@@ -1274,6 +1321,10 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, | |||
1274 | 1321 | ||
1275 | lockdep_assert_held(&mvm->mutex); | 1322 | lockdep_assert_held(&mvm->mutex); |
1276 | 1323 | ||
1324 | /* Ignore updates if we are in force mode */ | ||
1325 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) | ||
1326 | return 0; | ||
1327 | |||
1277 | if (ant_isolation == mvm->last_ant_isol) | 1328 | if (ant_isolation == mvm->last_ant_isol) |
1278 | return 0; | 1329 | return 0; |
1279 | 1330 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index 51685693af2e..ca79f7160573 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -79,6 +79,8 @@ | |||
79 | #define IWL_MVM_PS_SNOOZE_WINDOW 50 | 79 | #define IWL_MVM_PS_SNOOZE_WINDOW 50 |
80 | #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 | 80 | #define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25 |
81 | #define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64 | 81 | #define IWL_MVM_LOWLAT_QUOTA_MIN_PERCENT 64 |
82 | #define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH 62 | ||
83 | #define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH 65 | ||
82 | #define IWL_MVM_BT_COEX_SYNC2SCO 1 | 84 | #define IWL_MVM_BT_COEX_SYNC2SCO 1 |
83 | #define IWL_MVM_BT_COEX_CORUNNING 1 | 85 | #define IWL_MVM_BT_COEX_CORUNNING 1 |
84 | #define IWL_MVM_BT_COEX_MPLUT 1 | 86 | #define IWL_MVM_BT_COEX_MPLUT 1 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 29ca72695eaa..602bbd29ec5a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -455,6 +455,43 @@ iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf, | |||
455 | return count; | 455 | return count; |
456 | } | 456 | } |
457 | 457 | ||
458 | static ssize_t | ||
459 | iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf, | ||
460 | size_t count, loff_t *ppos) | ||
461 | { | ||
462 | static const char * const modes_str[BT_FORCE_ANT_MAX] = { | ||
463 | [BT_FORCE_ANT_DIS] = "dis", | ||
464 | [BT_FORCE_ANT_AUTO] = "auto", | ||
465 | [BT_FORCE_ANT_BT] = "bt", | ||
466 | [BT_FORCE_ANT_WIFI] = "wifi", | ||
467 | }; | ||
468 | int ret, bt_force_ant_mode; | ||
469 | |||
470 | for (bt_force_ant_mode = 0; | ||
471 | bt_force_ant_mode < ARRAY_SIZE(modes_str); | ||
472 | bt_force_ant_mode++) { | ||
473 | if (!strcmp(buf, modes_str[bt_force_ant_mode])) | ||
474 | break; | ||
475 | } | ||
476 | |||
477 | if (bt_force_ant_mode >= ARRAY_SIZE(modes_str)) | ||
478 | return -EINVAL; | ||
479 | |||
480 | ret = 0; | ||
481 | mutex_lock(&mvm->mutex); | ||
482 | if (mvm->bt_force_ant_mode == bt_force_ant_mode) | ||
483 | goto out; | ||
484 | |||
485 | mvm->bt_force_ant_mode = bt_force_ant_mode; | ||
486 | IWL_DEBUG_COEX(mvm, "Force mode: %s\n", | ||
487 | modes_str[mvm->bt_force_ant_mode]); | ||
488 | ret = iwl_send_bt_init_conf(mvm); | ||
489 | |||
490 | out: | ||
491 | mutex_unlock(&mvm->mutex); | ||
492 | return ret ?: count; | ||
493 | } | ||
494 | |||
458 | #define PRINT_STATS_LE32(_str, _val) \ | 495 | #define PRINT_STATS_LE32(_str, _val) \ |
459 | pos += scnprintf(buf + pos, bufsz - pos, \ | 496 | pos += scnprintf(buf + pos, bufsz - pos, \ |
460 | fmt_table, _str, \ | 497 | fmt_table, _str, \ |
@@ -1101,6 +1138,7 @@ MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats); | |||
1101 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); | 1138 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10); |
1102 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); | 1139 | MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10); |
1103 | MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); | 1140 | MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); |
1141 | MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); | ||
1104 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | 1142 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); |
1105 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | 1143 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); |
1106 | 1144 | ||
@@ -1142,6 +1180,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1142 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); | 1180 | MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); |
1143 | MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); | 1181 | MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR); |
1144 | MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR); | 1182 | MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, S_IWUSR); |
1183 | MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, S_IWUSR); | ||
1145 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, | 1184 | MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, |
1146 | S_IWUSR | S_IRUSR); | 1185 | S_IWUSR | S_IRUSR); |
1147 | MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); | 1186 | MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, S_IWUSR | S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h index 5fe82c29c8ad..39cb33a19862 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | |||
@@ -76,6 +76,9 @@ | |||
76 | * @BT_COEX_2W: | 76 | * @BT_COEX_2W: |
77 | * @BT_COEX_3W: | 77 | * @BT_COEX_3W: |
78 | * @BT_COEX_NW: | 78 | * @BT_COEX_NW: |
79 | * @BT_COEX_AUTO: | ||
80 | * @BT_COEX_BT: Antenna is for BT (manufacuring tests) | ||
81 | * @BT_COEX_WIFI: Antenna is for BT (manufacuring tests) | ||
79 | * @BT_COEX_SYNC2SCO: | 82 | * @BT_COEX_SYNC2SCO: |
80 | * @BT_COEX_CORUNNING: | 83 | * @BT_COEX_CORUNNING: |
81 | * @BT_COEX_MPLUT: | 84 | * @BT_COEX_MPLUT: |
@@ -89,6 +92,9 @@ enum iwl_bt_coex_flags { | |||
89 | BT_COEX_2W = 0x1 << BT_COEX_MODE_POS, | 92 | BT_COEX_2W = 0x1 << BT_COEX_MODE_POS, |
90 | BT_COEX_3W = 0x2 << BT_COEX_MODE_POS, | 93 | BT_COEX_3W = 0x2 << BT_COEX_MODE_POS, |
91 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, | 94 | BT_COEX_NW = 0x3 << BT_COEX_MODE_POS, |
95 | BT_COEX_AUTO = 0x5 << BT_COEX_MODE_POS, | ||
96 | BT_COEX_BT = 0x6 << BT_COEX_MODE_POS, | ||
97 | BT_COEX_WIFI = 0x7 << BT_COEX_MODE_POS, | ||
92 | BT_COEX_SYNC2SCO = BIT(7), | 98 | BT_COEX_SYNC2SCO = BIT(7), |
93 | BT_COEX_CORUNNING = BIT(8), | 99 | BT_COEX_CORUNNING = BIT(8), |
94 | BT_COEX_MPLUT = BIT(9), | 100 | BT_COEX_MPLUT = BIT(9), |
@@ -299,6 +305,7 @@ enum iwl_bt_activity_grading { | |||
299 | * @bt_traffic_load: load of BT traffic | 305 | * @bt_traffic_load: load of BT traffic |
300 | * @bt_agg_traffic_load: aggregated load of BT traffic | 306 | * @bt_agg_traffic_load: aggregated load of BT traffic |
301 | * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant | 307 | * @bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant |
308 | * @ttc_enabled: true if ttc has been enabled by the firmware | ||
302 | * @primary_ch_lut: LUT used for primary channel | 309 | * @primary_ch_lut: LUT used for primary channel |
303 | * @secondary_ch_lut: LUT used for secondary channel | 310 | * @secondary_ch_lut: LUT used for secondary channel |
304 | * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading | 311 | * @bt_activity_grading: the activity of BT enum %iwl_bt_activity_grading |
@@ -311,7 +318,8 @@ struct iwl_bt_coex_profile_notif { | |||
311 | u8 bt_traffic_load; | 318 | u8 bt_traffic_load; |
312 | u8 bt_agg_traffic_load; | 319 | u8 bt_agg_traffic_load; |
313 | u8 bt_ci_compliance; | 320 | u8 bt_ci_compliance; |
314 | u8 reserved[3]; | 321 | u8 ttc_enabled; |
322 | __le16 reserved; | ||
315 | 323 | ||
316 | __le32 primary_ch_lut; | 324 | __le32 primary_ch_lut; |
317 | __le32 secondary_ch_lut; | 325 | __le32 secondary_ch_lut; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index cbbcd8e284e4..c3a8c86b550d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -336,7 +336,7 @@ struct iwl_beacon_filter_cmd { | |||
336 | #define IWL_BF_DEBUG_FLAG_D0I3 0 | 336 | #define IWL_BF_DEBUG_FLAG_D0I3 0 |
337 | 337 | ||
338 | #define IWL_BF_ESCAPE_TIMER_DEFAULT 50 | 338 | #define IWL_BF_ESCAPE_TIMER_DEFAULT 50 |
339 | #define IWL_BF_ESCAPE_TIMER_D0I3 1024 | 339 | #define IWL_BF_ESCAPE_TIMER_D0I3 0 |
340 | #define IWL_BF_ESCAPE_TIMER_MAX 1024 | 340 | #define IWL_BF_ESCAPE_TIMER_MAX 1024 |
341 | #define IWL_BF_ESCAPE_TIMER_MIN 0 | 341 | #define IWL_BF_ESCAPE_TIMER_MIN 0 |
342 | 342 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 6959fda3fe09..1d586923d5b7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -170,18 +170,12 @@ enum iwl_scan_type { | |||
170 | }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */ | 170 | }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */ |
171 | 171 | ||
172 | /** | 172 | /** |
173 | * Maximal number of channels to scan | ||
174 | * it should be equal to: | ||
175 | * max(IWL_NUM_CHANNELS, IWL_NUM_CHANNELS_FAMILY_8000) | ||
176 | */ | ||
177 | #define MAX_NUM_SCAN_CHANNELS 50 | ||
178 | |||
179 | /** | ||
180 | * struct iwl_scan_cmd - scan request command | 173 | * struct iwl_scan_cmd - scan request command |
181 | * ( SCAN_REQUEST_CMD = 0x80 ) | 174 | * ( SCAN_REQUEST_CMD = 0x80 ) |
182 | * @len: command length in bytes | 175 | * @len: command length in bytes |
183 | * @scan_flags: scan flags from SCAN_FLAGS_* | 176 | * @scan_flags: scan flags from SCAN_FLAGS_* |
184 | * @channel_count: num of channels in channel list (1 - MAX_NUM_SCAN_CHANNELS) | 177 | * @channel_count: num of channels in channel list |
178 | * (1 - ucode_capa.n_scan_channels) | ||
185 | * @quiet_time: in msecs, dwell this time for active scan on quiet channels | 179 | * @quiet_time: in msecs, dwell this time for active scan on quiet channels |
186 | * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than | 180 | * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than |
187 | * this number of packets were received (typically 1) | 181 | * this number of packets were received (typically 1) |
@@ -345,7 +339,7 @@ struct iwl_scan_results_notif { | |||
345 | * @last_channel: last channel that was scanned | 339 | * @last_channel: last channel that was scanned |
346 | * @tsf_low: TSF timer (lower half) in usecs | 340 | * @tsf_low: TSF timer (lower half) in usecs |
347 | * @tsf_high: TSF timer (higher half) in usecs | 341 | * @tsf_high: TSF timer (higher half) in usecs |
348 | * @results: all scan results, only "scanned_channels" of them are valid | 342 | * @results: array of scan results, only "scanned_channels" of them are valid |
349 | */ | 343 | */ |
350 | struct iwl_scan_complete_notif { | 344 | struct iwl_scan_complete_notif { |
351 | u8 scanned_channels; | 345 | u8 scanned_channels; |
@@ -354,11 +348,10 @@ struct iwl_scan_complete_notif { | |||
354 | u8 last_channel; | 348 | u8 last_channel; |
355 | __le32 tsf_low; | 349 | __le32 tsf_low; |
356 | __le32 tsf_high; | 350 | __le32 tsf_high; |
357 | struct iwl_scan_results_notif results[MAX_NUM_SCAN_CHANNELS]; | 351 | struct iwl_scan_results_notif results[]; |
358 | } __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */ | 352 | } __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */ |
359 | 353 | ||
360 | /* scan offload */ | 354 | /* scan offload */ |
361 | #define IWL_MAX_SCAN_CHANNELS 40 | ||
362 | #define IWL_SCAN_MAX_BLACKLIST_LEN 64 | 355 | #define IWL_SCAN_MAX_BLACKLIST_LEN 64 |
363 | #define IWL_SCAN_SHORT_BLACKLIST_LEN 16 | 356 | #define IWL_SCAN_SHORT_BLACKLIST_LEN 16 |
364 | #define IWL_SCAN_MAX_PROFILES 11 | 357 | #define IWL_SCAN_MAX_PROFILES 11 |
@@ -423,36 +416,24 @@ enum iwl_scan_offload_channel_flags { | |||
423 | IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL = BIT(25), | 416 | IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL = BIT(25), |
424 | }; | 417 | }; |
425 | 418 | ||
426 | /** | 419 | /* channel configuration for struct iwl_scan_offload_cfg. Each channels needs: |
427 | * iwl_scan_channel_cfg - SCAN_CHANNEL_CFG_S | 420 | * __le32 type: bitmap; bits 1-20 are for directed scan to i'th ssid and |
428 | * @type: bitmap - see enum iwl_scan_offload_channel_flags. | 421 | * see enum iwl_scan_offload_channel_flags. |
429 | * 0: passive (0) or active (1) scan. | 422 | * __le16 channel_number: channel number 1-13 etc. |
430 | * 1-20: directed scan to i'th ssid. | 423 | * __le16 iter_count: repetition count for the channel. |
431 | * 22: channel width configuation - 1 for narrow. | 424 | * __le32 iter_interval: interval between two innteration on one channel. |
432 | * 24: full scan. | 425 | * u8 active_dwell. |
433 | * 25: partial scan. | 426 | * u8 passive_dwell. |
434 | * @channel_number: channel number 1-13 etc. | ||
435 | * @iter_count: repetition count for the channel. | ||
436 | * @iter_interval: interval between two innteration on one channel. | ||
437 | * @dwell_time: entry 0 - active scan, entry 1 - passive scan. | ||
438 | */ | 427 | */ |
439 | struct iwl_scan_channel_cfg { | 428 | #define IWL_SCAN_CHAN_SIZE 14 |
440 | __le32 type[IWL_MAX_SCAN_CHANNELS]; | ||
441 | __le16 channel_number[IWL_MAX_SCAN_CHANNELS]; | ||
442 | __le16 iter_count[IWL_MAX_SCAN_CHANNELS]; | ||
443 | __le32 iter_interval[IWL_MAX_SCAN_CHANNELS]; | ||
444 | u8 dwell_time[IWL_MAX_SCAN_CHANNELS][2]; | ||
445 | } __packed; | ||
446 | 429 | ||
447 | /** | 430 | /** |
448 | * iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S | 431 | * iwl_scan_offload_cfg - SCAN_OFFLOAD_CONFIG_API_S |
449 | * @scan_cmd: scan command fixed part | 432 | * @scan_cmd: scan command fixed part |
450 | * @channel_cfg: scan channel configuration | 433 | * @data: scan channel configuration and probe request frames |
451 | * @data: probe request frames (one per band) | ||
452 | */ | 434 | */ |
453 | struct iwl_scan_offload_cfg { | 435 | struct iwl_scan_offload_cfg { |
454 | struct iwl_scan_offload_cmd scan_cmd; | 436 | struct iwl_scan_offload_cmd scan_cmd; |
455 | struct iwl_scan_channel_cfg channel_cfg; | ||
456 | u8 data[0]; | 437 | u8 data[0]; |
457 | } __packed; | 438 | } __packed; |
458 | 439 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h index 39cebee8016f..47bd0406355d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h | |||
@@ -67,7 +67,7 @@ | |||
67 | * enum iwl_sta_flags - flags for the ADD_STA host command | 67 | * enum iwl_sta_flags - flags for the ADD_STA host command |
68 | * @STA_FLG_REDUCED_TX_PWR_CTRL: | 68 | * @STA_FLG_REDUCED_TX_PWR_CTRL: |
69 | * @STA_FLG_REDUCED_TX_PWR_DATA: | 69 | * @STA_FLG_REDUCED_TX_PWR_DATA: |
70 | * @STA_FLG_FLG_ANT_MSK: Antenna selection | 70 | * @STA_FLG_DISABLE_TX: set if TX should be disabled |
71 | * @STA_FLG_PS: set if STA is in Power Save | 71 | * @STA_FLG_PS: set if STA is in Power Save |
72 | * @STA_FLG_INVALID: set if STA is invalid | 72 | * @STA_FLG_INVALID: set if STA is invalid |
73 | * @STA_FLG_DLP_EN: Direct Link Protocol is enabled | 73 | * @STA_FLG_DLP_EN: Direct Link Protocol is enabled |
@@ -91,10 +91,7 @@ enum iwl_sta_flags { | |||
91 | STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3), | 91 | STA_FLG_REDUCED_TX_PWR_CTRL = BIT(3), |
92 | STA_FLG_REDUCED_TX_PWR_DATA = BIT(6), | 92 | STA_FLG_REDUCED_TX_PWR_DATA = BIT(6), |
93 | 93 | ||
94 | STA_FLG_FLG_ANT_A = (1 << 4), | 94 | STA_FLG_DISABLE_TX = BIT(4), |
95 | STA_FLG_FLG_ANT_B = (2 << 4), | ||
96 | STA_FLG_FLG_ANT_MSK = (STA_FLG_FLG_ANT_A | | ||
97 | STA_FLG_FLG_ANT_B), | ||
98 | 95 | ||
99 | STA_FLG_PS = BIT(8), | 96 | STA_FLG_PS = BIT(8), |
100 | STA_FLG_DRAIN_FLOW = BIT(12), | 97 | STA_FLG_DRAIN_FLOW = BIT(12), |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 6cc5f52b807f..bdd6ff648626 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | |||
@@ -549,6 +549,20 @@ struct iwl_beacon_notif { | |||
549 | } __packed; | 549 | } __packed; |
550 | 550 | ||
551 | /** | 551 | /** |
552 | * struct iwl_extended_beacon_notif - notifies about beacon transmission | ||
553 | * @beacon_notify_hdr: tx response command associated with the beacon | ||
554 | * @tsf: last beacon tsf | ||
555 | * @ibss_mgr_status: whether IBSS is manager | ||
556 | * @gp2: last beacon time in gp2 | ||
557 | */ | ||
558 | struct iwl_extended_beacon_notif { | ||
559 | struct iwl_mvm_tx_resp beacon_notify_hdr; | ||
560 | __le64 tsf; | ||
561 | __le32 ibss_mgr_status; | ||
562 | __le32 gp2; | ||
563 | } __packed; /* BEACON_NTFY_API_S_VER_5 */ | ||
564 | |||
565 | /** | ||
552 | * enum iwl_dump_control - dump (flush) control flags | 566 | * enum iwl_dump_control - dump (flush) control flags |
553 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty | 567 | * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty |
554 | * and the TFD queues are empty. | 568 | * and the TFD queues are empty. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 8b5302777632..aad36212c4d7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -904,7 +904,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
904 | struct iwl_mac_beacon_cmd beacon_cmd = {}; | 904 | struct iwl_mac_beacon_cmd beacon_cmd = {}; |
905 | struct ieee80211_tx_info *info; | 905 | struct ieee80211_tx_info *info; |
906 | u32 beacon_skb_len; | 906 | u32 beacon_skb_len; |
907 | u32 rate; | 907 | u32 rate, tx_flags; |
908 | 908 | ||
909 | if (WARN_ON(!beacon)) | 909 | if (WARN_ON(!beacon)) |
910 | return -EINVAL; | 910 | return -EINVAL; |
@@ -914,14 +914,17 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
914 | /* TODO: for now the beacon template id is set to be the mac context id. | 914 | /* TODO: for now the beacon template id is set to be the mac context id. |
915 | * Might be better to handle it as another resource ... */ | 915 | * Might be better to handle it as another resource ... */ |
916 | beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); | 916 | beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); |
917 | info = IEEE80211_SKB_CB(beacon); | ||
917 | 918 | ||
918 | /* Set up TX command fields */ | 919 | /* Set up TX command fields */ |
919 | beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len); | 920 | beacon_cmd.tx.len = cpu_to_le16((u16)beacon_skb_len); |
920 | beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id; | 921 | beacon_cmd.tx.sta_id = mvmvif->bcast_sta.sta_id; |
921 | beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); | 922 | beacon_cmd.tx.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); |
922 | beacon_cmd.tx.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | | 923 | tx_flags = TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_TSF; |
923 | TX_CMD_FLG_BT_DIS | | 924 | tx_flags |= |
924 | TX_CMD_FLG_TSF); | 925 | iwl_mvm_bt_coex_tx_prio(mvm, (void *)beacon->data, info, 0) << |
926 | TX_CMD_FLG_BT_PRIO_POS; | ||
927 | beacon_cmd.tx.tx_flags = cpu_to_le32(tx_flags); | ||
925 | 928 | ||
926 | mvm->mgmt_last_antenna_idx = | 929 | mvm->mgmt_last_antenna_idx = |
927 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, | 930 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, |
@@ -931,8 +934,6 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, | |||
931 | cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) << | 934 | cpu_to_le32(BIT(mvm->mgmt_last_antenna_idx) << |
932 | RATE_MCS_ANT_POS); | 935 | RATE_MCS_ANT_POS); |
933 | 936 | ||
934 | info = IEEE80211_SKB_CB(beacon); | ||
935 | |||
936 | if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) { | 937 | if (info->band == IEEE80211_BAND_5GHZ || vif->p2p) { |
937 | rate = IWL_FIRST_OFDM_RATE; | 938 | rate = IWL_FIRST_OFDM_RATE; |
938 | } else { | 939 | } else { |
@@ -1205,19 +1206,31 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | |||
1205 | struct iwl_device_cmd *cmd) | 1206 | struct iwl_device_cmd *cmd) |
1206 | { | 1207 | { |
1207 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 1208 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1208 | struct iwl_beacon_notif *beacon = (void *)pkt->data; | 1209 | struct iwl_mvm_tx_resp *beacon_notify_hdr; |
1209 | u16 status __maybe_unused = | 1210 | u64 tsf; |
1210 | le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
1211 | u32 rate __maybe_unused = | ||
1212 | le32_to_cpu(beacon->beacon_notify_hdr.initial_rate); | ||
1213 | 1211 | ||
1214 | lockdep_assert_held(&mvm->mutex); | 1212 | lockdep_assert_held(&mvm->mutex); |
1215 | 1213 | ||
1216 | IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n", | 1214 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_CAPA_EXTENDED_BEACON) { |
1217 | status & TX_STATUS_MSK, | 1215 | struct iwl_extended_beacon_notif *beacon = (void *)pkt->data; |
1218 | beacon->beacon_notify_hdr.failure_frame, | 1216 | |
1219 | le64_to_cpu(beacon->tsf), | 1217 | beacon_notify_hdr = &beacon->beacon_notify_hdr; |
1220 | rate); | 1218 | tsf = le64_to_cpu(beacon->tsf); |
1219 | mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2); | ||
1220 | } else { | ||
1221 | struct iwl_beacon_notif *beacon = (void *)pkt->data; | ||
1222 | |||
1223 | beacon_notify_hdr = &beacon->beacon_notify_hdr; | ||
1224 | tsf = le64_to_cpu(beacon->tsf); | ||
1225 | } | ||
1226 | |||
1227 | IWL_DEBUG_RX(mvm, | ||
1228 | "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n", | ||
1229 | le16_to_cpu(beacon_notify_hdr->status.status) & | ||
1230 | TX_STATUS_MSK, | ||
1231 | beacon_notify_hdr->failure_frame, tsf, | ||
1232 | mvm->ap_last_beacon_gp2, | ||
1233 | le32_to_cpu(beacon_notify_hdr->initial_rate)); | ||
1221 | 1234 | ||
1222 | if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) { | 1235 | if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) { |
1223 | if (!ieee80211_csa_is_complete(mvm->csa_vif)) { | 1236 | if (!ieee80211_csa_is_complete(mvm->csa_vif)) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7dd363dd3ad3..72e3146625f8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -374,6 +374,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
374 | hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; | 374 | hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; |
375 | 375 | ||
376 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 376 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
377 | NL80211_FEATURE_LOW_PRIORITY_SCAN | | ||
377 | NL80211_FEATURE_P2P_GO_OPPPS; | 378 | NL80211_FEATURE_P2P_GO_OPPPS; |
378 | 379 | ||
379 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 380 | mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
@@ -688,6 +689,16 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) | |||
688 | iwl_mvm_restart_cleanup(mvm); | 689 | iwl_mvm_restart_cleanup(mvm); |
689 | 690 | ||
690 | ret = iwl_mvm_up(mvm); | 691 | ret = iwl_mvm_up(mvm); |
692 | |||
693 | if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | ||
694 | /* Something went wrong - we need to finish some cleanup | ||
695 | * that normally iwl_mvm_mac_restart_complete() below | ||
696 | * would do. | ||
697 | */ | ||
698 | clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | ||
699 | iwl_mvm_d0i3_enable_tx(mvm, NULL); | ||
700 | } | ||
701 | |||
691 | mutex_unlock(&mvm->mutex); | 702 | mutex_unlock(&mvm->mutex); |
692 | 703 | ||
693 | return ret; | 704 | return ret; |
@@ -1464,6 +1475,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
1464 | mutex_lock(&mvm->mutex); | 1475 | mutex_lock(&mvm->mutex); |
1465 | 1476 | ||
1466 | mvmvif->ap_ibss_active = false; | 1477 | mvmvif->ap_ibss_active = false; |
1478 | mvm->ap_last_beacon_gp2 = 0; | ||
1467 | 1479 | ||
1468 | iwl_mvm_bt_coex_vif_change(mvm); | 1480 | iwl_mvm_bt_coex_vif_change(mvm); |
1469 | 1481 | ||
@@ -1543,7 +1555,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | |||
1543 | struct cfg80211_scan_request *req = &hw_req->req; | 1555 | struct cfg80211_scan_request *req = &hw_req->req; |
1544 | int ret; | 1556 | int ret; |
1545 | 1557 | ||
1546 | if (req->n_channels == 0 || req->n_channels > MAX_NUM_SCAN_CHANNELS) | 1558 | if (req->n_channels == 0 || |
1559 | req->n_channels > mvm->fw->ucode_capa.n_scan_channels) | ||
1547 | return -EINVAL; | 1560 | return -EINVAL; |
1548 | 1561 | ||
1549 | mutex_lock(&mvm->mutex); | 1562 | mutex_lock(&mvm->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 97630f9a7cb9..f7e54a57f46d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -235,6 +235,15 @@ enum iwl_mvm_ref_type { | |||
235 | IWL_MVM_REF_COUNT, | 235 | IWL_MVM_REF_COUNT, |
236 | }; | 236 | }; |
237 | 237 | ||
238 | enum iwl_bt_force_ant_mode { | ||
239 | BT_FORCE_ANT_DIS = 0, | ||
240 | BT_FORCE_ANT_AUTO, | ||
241 | BT_FORCE_ANT_BT, | ||
242 | BT_FORCE_ANT_WIFI, | ||
243 | |||
244 | BT_FORCE_ANT_MAX, | ||
245 | }; | ||
246 | |||
238 | /** | 247 | /** |
239 | * struct iwl_mvm_vif_bf_data - beacon filtering related data | 248 | * struct iwl_mvm_vif_bf_data - beacon filtering related data |
240 | * @bf_enabled: indicates if beacon filtering is enabled | 249 | * @bf_enabled: indicates if beacon filtering is enabled |
@@ -629,6 +638,7 @@ struct iwl_mvm { | |||
629 | u32 last_ant_isol; | 638 | u32 last_ant_isol; |
630 | u8 last_corun_lut; | 639 | u8 last_corun_lut; |
631 | u8 bt_tx_prio; | 640 | u8 bt_tx_prio; |
641 | enum iwl_bt_force_ant_mode bt_force_ant_mode; | ||
632 | 642 | ||
633 | /* Thermal Throttling and CTkill */ | 643 | /* Thermal Throttling and CTkill */ |
634 | struct iwl_mvm_tt_mgmt thermal_throttle; | 644 | struct iwl_mvm_tt_mgmt thermal_throttle; |
@@ -648,6 +658,9 @@ struct iwl_mvm { | |||
648 | bool ps_disabled; | 658 | bool ps_disabled; |
649 | 659 | ||
650 | struct ieee80211_vif *csa_vif; | 660 | struct ieee80211_vif *csa_vif; |
661 | |||
662 | /* system time of last beacon (for AP/GO interface) */ | ||
663 | u32 ap_last_beacon_gp2; | ||
651 | }; | 664 | }; |
652 | 665 | ||
653 | /* Extract MVM priv from op_mode and _hw */ | 666 | /* Extract MVM priv from op_mode and _hw */ |
@@ -963,6 +976,7 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm, | |||
963 | struct ieee80211_sta *sta); | 976 | struct ieee80211_sta *sta); |
964 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, | 977 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, |
965 | struct ieee80211_sta *sta); | 978 | struct ieee80211_sta *sta); |
979 | bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm); | ||
966 | bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, | 980 | bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, |
967 | enum ieee80211_band band); | 981 | enum ieee80211_band band); |
968 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, | 982 | u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 808f78f6fbf9..1f1a550828fa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -69,7 +69,9 @@ | |||
69 | 69 | ||
70 | /* Default NVM size to read */ | 70 | /* Default NVM size to read */ |
71 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) | 71 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) |
72 | #define IWL_MAX_NVM_SECTION_SIZE 7000 | 72 | #define IWL_MAX_NVM_SECTION_SIZE 0x1b58 |
73 | #define IWL_MAX_NVM_8000A_SECTION_SIZE 0xffc | ||
74 | #define IWL_MAX_NVM_8000B_SECTION_SIZE 0x1ffc | ||
73 | 75 | ||
74 | #define NVM_WRITE_OPCODE 1 | 76 | #define NVM_WRITE_OPCODE 1 |
75 | #define NVM_READ_OPCODE 0 | 77 | #define NVM_READ_OPCODE 0 |
@@ -219,7 +221,7 @@ static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section, | |||
219 | * without overflowing, so no check is needed. | 221 | * without overflowing, so no check is needed. |
220 | */ | 222 | */ |
221 | static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | 223 | static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, |
222 | u8 *data) | 224 | u8 *data, u32 size_read) |
223 | { | 225 | { |
224 | u16 length, offset = 0; | 226 | u16 length, offset = 0; |
225 | int ret; | 227 | int ret; |
@@ -231,6 +233,13 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
231 | 233 | ||
232 | /* Read the NVM until exhausted (reading less than requested) */ | 234 | /* Read the NVM until exhausted (reading less than requested) */ |
233 | while (ret == length) { | 235 | while (ret == length) { |
236 | /* Check no memory assumptions fail and cause an overflow */ | ||
237 | if ((size_read + offset + length) > | ||
238 | mvm->cfg->base_params->eeprom_size) { | ||
239 | IWL_ERR(mvm, "EEPROM size is too small for NVM\n"); | ||
240 | return -ENOBUFS; | ||
241 | } | ||
242 | |||
234 | ret = iwl_nvm_read_chunk(mvm, section, offset, length, data); | 243 | ret = iwl_nvm_read_chunk(mvm, section, offset, length, data); |
235 | if (ret < 0) { | 244 | if (ret < 0) { |
236 | IWL_DEBUG_EEPROM(mvm->trans->dev, | 245 | IWL_DEBUG_EEPROM(mvm->trans->dev, |
@@ -326,6 +335,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
326 | u8 data[]; | 335 | u8 data[]; |
327 | } *file_sec; | 336 | } *file_sec; |
328 | const u8 *eof, *temp; | 337 | const u8 *eof, *temp; |
338 | int max_section_size; | ||
329 | 339 | ||
330 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) | 340 | #define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) |
331 | #define NVM_WORD2_ID(x) (x >> 12) | 341 | #define NVM_WORD2_ID(x) (x >> 12) |
@@ -334,6 +344,14 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
334 | 344 | ||
335 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); | 345 | IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); |
336 | 346 | ||
347 | /* Maximal size depends on HW family and step */ | ||
348 | if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
349 | max_section_size = IWL_MAX_NVM_SECTION_SIZE; | ||
350 | else if ((mvm->trans->hw_rev & 0xc) == 0) /* Family 8000 A-step */ | ||
351 | max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE; | ||
352 | else /* Family 8000 B-step */ | ||
353 | max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE; | ||
354 | |||
337 | /* | 355 | /* |
338 | * Obtain NVM image via request_firmware. Since we already used | 356 | * Obtain NVM image via request_firmware. Since we already used |
339 | * request_firmware_nowait() for the firmware binary load and only | 357 | * request_firmware_nowait() for the firmware binary load and only |
@@ -392,7 +410,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
392 | le16_to_cpu(file_sec->word1)); | 410 | le16_to_cpu(file_sec->word1)); |
393 | } | 411 | } |
394 | 412 | ||
395 | if (section_size > IWL_MAX_NVM_SECTION_SIZE) { | 413 | if (section_size > max_section_size) { |
396 | IWL_ERR(mvm, "ERROR - section too large (%d)\n", | 414 | IWL_ERR(mvm, "ERROR - section too large (%d)\n", |
397 | section_size); | 415 | section_size); |
398 | ret = -EINVAL; | 416 | ret = -EINVAL; |
@@ -459,6 +477,7 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm) | |||
459 | int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) | 477 | int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) |
460 | { | 478 | { |
461 | int ret, section; | 479 | int ret, section; |
480 | u32 size_read = 0; | ||
462 | u8 *nvm_buffer, *temp; | 481 | u8 *nvm_buffer, *temp; |
463 | 482 | ||
464 | if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) | 483 | if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS)) |
@@ -475,9 +494,11 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) | |||
475 | return -ENOMEM; | 494 | return -ENOMEM; |
476 | for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) { | 495 | for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) { |
477 | /* we override the constness for initial read */ | 496 | /* we override the constness for initial read */ |
478 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | 497 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer, |
498 | size_read); | ||
479 | if (ret < 0) | 499 | if (ret < 0) |
480 | continue; | 500 | continue; |
501 | size_read += ret; | ||
481 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | 502 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
482 | if (!temp) { | 503 | if (!temp) { |
483 | ret = -ENOMEM; | 504 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index cc2f7de396de..7bb763f3052b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -504,7 +504,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
504 | 504 | ||
505 | scan_size = sizeof(struct iwl_scan_cmd) + | 505 | scan_size = sizeof(struct iwl_scan_cmd) + |
506 | mvm->fw->ucode_capa.max_probe_length + | 506 | mvm->fw->ucode_capa.max_probe_length + |
507 | (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel)); | 507 | (mvm->fw->ucode_capa.n_scan_channels * |
508 | sizeof(struct iwl_scan_channel)); | ||
508 | mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL); | 509 | mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL); |
509 | if (!mvm->scan_cmd) | 510 | if (!mvm->scan_cmd) |
510 | goto out_free; | 511 | goto out_free; |
@@ -826,6 +827,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
826 | { | 827 | { |
827 | struct iwl_fw_error_dump_file *dump_file; | 828 | struct iwl_fw_error_dump_file *dump_file; |
828 | struct iwl_fw_error_dump_data *dump_data; | 829 | struct iwl_fw_error_dump_data *dump_data; |
830 | struct iwl_fw_error_dump_info *dump_info; | ||
829 | u32 file_len; | 831 | u32 file_len; |
830 | u32 trans_len; | 832 | u32 trans_len; |
831 | 833 | ||
@@ -834,10 +836,11 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
834 | if (mvm->fw_error_dump) | 836 | if (mvm->fw_error_dump) |
835 | return; | 837 | return; |
836 | 838 | ||
837 | file_len = mvm->fw_error_sram_len + | 839 | file_len = sizeof(*dump_file) + |
840 | sizeof(*dump_data) * 3 + | ||
841 | mvm->fw_error_sram_len + | ||
838 | mvm->fw_error_rxf_len + | 842 | mvm->fw_error_rxf_len + |
839 | sizeof(*dump_file) + | 843 | sizeof(*dump_info); |
840 | sizeof(*dump_data) * 2; | ||
841 | 844 | ||
842 | trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0); | 845 | trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0); |
843 | if (trans_len) | 846 | if (trans_len) |
@@ -852,11 +855,27 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
852 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); | 855 | dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); |
853 | dump_file->file_len = cpu_to_le32(file_len); | 856 | dump_file->file_len = cpu_to_le32(file_len); |
854 | dump_data = (void *)dump_file->data; | 857 | dump_data = (void *)dump_file->data; |
858 | |||
859 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO); | ||
860 | dump_data->len = cpu_to_le32(sizeof(*dump_info)); | ||
861 | dump_info = (void *) dump_data->data; | ||
862 | dump_info->device_family = | ||
863 | mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000 ? | ||
864 | cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) : | ||
865 | cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8); | ||
866 | memcpy(dump_info->fw_human_readable, mvm->fw->human_readable, | ||
867 | sizeof(dump_info->fw_human_readable)); | ||
868 | strncpy(dump_info->dev_human_readable, mvm->cfg->name, | ||
869 | sizeof(dump_info->dev_human_readable)); | ||
870 | strncpy(dump_info->bus_human_readable, mvm->dev->bus->name, | ||
871 | sizeof(dump_info->bus_human_readable)); | ||
872 | |||
873 | dump_data = iwl_fw_error_next_data(dump_data); | ||
855 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF); | 874 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF); |
856 | dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len); | 875 | dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len); |
857 | memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len); | 876 | memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len); |
858 | 877 | ||
859 | dump_data = iwl_mvm_fw_error_next_data(dump_data); | 878 | dump_data = iwl_fw_error_next_data(dump_data); |
860 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM); | 879 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM); |
861 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); | 880 | dump_data->len = cpu_to_le32(mvm->fw_error_sram_len); |
862 | 881 | ||
@@ -876,7 +895,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
876 | mvm->fw_error_sram_len = 0; | 895 | mvm->fw_error_sram_len = 0; |
877 | 896 | ||
878 | if (trans_len) { | 897 | if (trans_len) { |
879 | void *buf = iwl_mvm_fw_error_next_data(dump_data); | 898 | void *buf = iwl_fw_error_next_data(dump_data); |
880 | u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf, | 899 | u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf, |
881 | trans_len); | 900 | trans_len); |
882 | dump_data = (void *)((u8 *)buf + real_trans_len); | 901 | dump_data = (void *)((u8 *)buf + real_trans_len); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 3206fa097255..f2dde5604a80 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -275,7 +275,7 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, | |||
275 | 275 | ||
276 | static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | 276 | static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, |
277 | struct ieee80211_vif *vif, | 277 | struct ieee80211_vif *vif, |
278 | int n_ssids, | 278 | int n_ssids, u32 flags, |
279 | struct iwl_mvm_scan_params *params) | 279 | struct iwl_mvm_scan_params *params) |
280 | { | 280 | { |
281 | bool global_bound = false; | 281 | bool global_bound = false; |
@@ -297,6 +297,9 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm, | |||
297 | params->max_out_time = 250; | 297 | params->max_out_time = 250; |
298 | } | 298 | } |
299 | 299 | ||
300 | if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY) | ||
301 | params->max_out_time = 200; | ||
302 | |||
300 | not_bound: | 303 | not_bound: |
301 | 304 | ||
302 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { | 305 | for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { |
@@ -333,16 +336,14 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
333 | 336 | ||
334 | IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n"); | 337 | IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n"); |
335 | mvm->scan_status = IWL_MVM_SCAN_OS; | 338 | mvm->scan_status = IWL_MVM_SCAN_OS; |
336 | memset(cmd, 0, sizeof(struct iwl_scan_cmd) + | 339 | memset(cmd, 0, ksize(cmd)); |
337 | mvm->fw->ucode_capa.max_probe_length + | ||
338 | (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel))); | ||
339 | 340 | ||
340 | cmd->channel_count = (u8)req->n_channels; | 341 | cmd->channel_count = (u8)req->n_channels; |
341 | cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); | 342 | cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); |
342 | cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | 343 | cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); |
343 | cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); | 344 | cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm); |
344 | 345 | ||
345 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, ¶ms); | 346 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, req->flags, ¶ms); |
346 | cmd->max_out_time = cpu_to_le32(params.max_out_time); | 347 | cmd->max_out_time = cpu_to_le32(params.max_out_time); |
347 | cmd->suspend_time = cpu_to_le32(params.suspend_time); | 348 | cmd->suspend_time = cpu_to_le32(params.suspend_time); |
348 | if (params.passive_fragmented) | 349 | if (params.passive_fragmented) |
@@ -597,9 +598,7 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm, | |||
597 | struct iwl_scan_offload_cmd *scan, | 598 | struct iwl_scan_offload_cmd *scan, |
598 | struct iwl_mvm_scan_params *params) | 599 | struct iwl_mvm_scan_params *params) |
599 | { | 600 | { |
600 | scan->channel_count = | 601 | scan->channel_count = req->n_channels; |
601 | mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels + | ||
602 | mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | ||
603 | scan->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); | 602 | scan->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME); |
604 | scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); | 603 | scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH); |
605 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; | 604 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT; |
@@ -676,68 +675,50 @@ static void iwl_scan_offload_build_ssid(struct cfg80211_sched_scan_request *req, | |||
676 | 675 | ||
677 | static void iwl_build_channel_cfg(struct iwl_mvm *mvm, | 676 | static void iwl_build_channel_cfg(struct iwl_mvm *mvm, |
678 | struct cfg80211_sched_scan_request *req, | 677 | struct cfg80211_sched_scan_request *req, |
679 | struct iwl_scan_channel_cfg *channels, | 678 | u8 *channels_buffer, |
680 | enum ieee80211_band band, | 679 | enum ieee80211_band band, |
681 | int *head, int *tail, | 680 | int *head, |
682 | u32 ssid_bitmap, | 681 | u32 ssid_bitmap, |
683 | struct iwl_mvm_scan_params *params) | 682 | struct iwl_mvm_scan_params *params) |
684 | { | 683 | { |
685 | struct ieee80211_supported_band *s_band; | 684 | u32 n_channels = mvm->fw->ucode_capa.n_scan_channels; |
686 | int n_channels = req->n_channels; | 685 | __le32 *type = (__le32 *)channels_buffer; |
687 | int i, j, index = 0; | 686 | __le16 *channel_number = (__le16 *)(type + n_channels); |
688 | bool partial; | 687 | __le16 *iter_count = channel_number + n_channels; |
688 | __le32 *iter_interval = (__le32 *)(iter_count + n_channels); | ||
689 | u8 *active_dwell = (u8 *)(iter_interval + n_channels); | ||
690 | u8 *passive_dwell = active_dwell + n_channels; | ||
691 | int i, index = 0; | ||
692 | |||
693 | for (i = 0; i < req->n_channels; i++) { | ||
694 | struct ieee80211_channel *chan = req->channels[i]; | ||
695 | |||
696 | if (chan->band != band) | ||
697 | continue; | ||
689 | 698 | ||
690 | /* | 699 | index = *head; |
691 | * We have to configure all supported channels, even if we don't want to | 700 | (*head)++; |
692 | * scan on them, but we have to send channels in the order that we want | 701 | |
693 | * to scan. So add requested channels to head of the list and others to | 702 | channel_number[index] = cpu_to_le16(chan->hw_value); |
694 | * the end. | 703 | active_dwell[index] = params->dwell[band].active; |
695 | */ | 704 | passive_dwell[index] = params->dwell[band].passive; |
696 | s_band = &mvm->nvm_data->bands[band]; | ||
697 | |||
698 | for (i = 0; i < s_band->n_channels && *head <= *tail; i++) { | ||
699 | partial = false; | ||
700 | for (j = 0; j < n_channels; j++) | ||
701 | if (s_band->channels[i].center_freq == | ||
702 | req->channels[j]->center_freq) { | ||
703 | index = *head; | ||
704 | (*head)++; | ||
705 | /* | ||
706 | * Channels that came with the request will be | ||
707 | * in partial scan . | ||
708 | */ | ||
709 | partial = true; | ||
710 | break; | ||
711 | } | ||
712 | if (!partial) { | ||
713 | index = *tail; | ||
714 | (*tail)--; | ||
715 | } | ||
716 | channels->channel_number[index] = | ||
717 | cpu_to_le16(ieee80211_frequency_to_channel( | ||
718 | s_band->channels[i].center_freq)); | ||
719 | channels->dwell_time[index][0] = params->dwell[band].active; | ||
720 | channels->dwell_time[index][1] = params->dwell[band].passive; | ||
721 | 705 | ||
722 | channels->iter_count[index] = cpu_to_le16(1); | 706 | iter_count[index] = cpu_to_le16(1); |
723 | channels->iter_interval[index] = 0; | 707 | iter_interval[index] = 0; |
724 | 708 | ||
725 | if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR)) | 709 | if (!(chan->flags & IEEE80211_CHAN_NO_IR)) |
726 | channels->type[index] |= | 710 | type[index] |= |
727 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); | 711 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE); |
728 | 712 | ||
729 | channels->type[index] |= | 713 | type[index] |= cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL | |
730 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL); | 714 | IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL); |
731 | if (partial) | ||
732 | channels->type[index] |= | ||
733 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL); | ||
734 | 715 | ||
735 | if (s_band->channels[i].flags & IEEE80211_CHAN_NO_HT40) | 716 | if (chan->flags & IEEE80211_CHAN_NO_HT40) |
736 | channels->type[index] |= | 717 | type[index] |= |
737 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW); | 718 | cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW); |
738 | 719 | ||
739 | /* scan for all SSIDs from req->ssids */ | 720 | /* scan for all SSIDs from req->ssids */ |
740 | channels->type[index] |= cpu_to_le32(ssid_bitmap); | 721 | type[index] |= cpu_to_le32(ssid_bitmap); |
741 | } | 722 | } |
742 | } | 723 | } |
743 | 724 | ||
@@ -749,10 +730,10 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
749 | int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; | 730 | int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels; |
750 | int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; | 731 | int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels; |
751 | int head = 0; | 732 | int head = 0; |
752 | int tail = band_2ghz + band_5ghz - 1; | ||
753 | u32 ssid_bitmap; | 733 | u32 ssid_bitmap; |
754 | int cmd_len; | 734 | int cmd_len; |
755 | int ret; | 735 | int ret; |
736 | u8 *probes; | ||
756 | 737 | ||
757 | struct iwl_scan_offload_cfg *scan_cfg; | 738 | struct iwl_scan_offload_cfg *scan_cfg; |
758 | struct iwl_host_cmd cmd = { | 739 | struct iwl_host_cmd cmd = { |
@@ -763,13 +744,17 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
763 | lockdep_assert_held(&mvm->mutex); | 744 | lockdep_assert_held(&mvm->mutex); |
764 | 745 | ||
765 | cmd_len = sizeof(struct iwl_scan_offload_cfg) + | 746 | cmd_len = sizeof(struct iwl_scan_offload_cfg) + |
747 | mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE + | ||
766 | 2 * SCAN_OFFLOAD_PROBE_REQ_SIZE; | 748 | 2 * SCAN_OFFLOAD_PROBE_REQ_SIZE; |
767 | 749 | ||
768 | scan_cfg = kzalloc(cmd_len, GFP_KERNEL); | 750 | scan_cfg = kzalloc(cmd_len, GFP_KERNEL); |
769 | if (!scan_cfg) | 751 | if (!scan_cfg) |
770 | return -ENOMEM; | 752 | return -ENOMEM; |
771 | 753 | ||
772 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, ¶ms); | 754 | probes = scan_cfg->data + |
755 | mvm->fw->ucode_capa.n_scan_channels * IWL_SCAN_CHAN_SIZE; | ||
756 | |||
757 | iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, ¶ms); | ||
773 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, ¶ms); | 758 | iwl_build_scan_cmd(mvm, vif, req, &scan_cfg->scan_cmd, ¶ms); |
774 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); | 759 | scan_cfg->scan_cmd.len = cpu_to_le16(cmd_len); |
775 | 760 | ||
@@ -779,19 +764,19 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm, | |||
779 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | 764 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, |
780 | IEEE80211_BAND_2GHZ, | 765 | IEEE80211_BAND_2GHZ, |
781 | &scan_cfg->scan_cmd.tx_cmd[0], | 766 | &scan_cfg->scan_cmd.tx_cmd[0], |
782 | scan_cfg->data); | 767 | probes); |
783 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | 768 | iwl_build_channel_cfg(mvm, req, scan_cfg->data, |
784 | IEEE80211_BAND_2GHZ, &head, &tail, | 769 | IEEE80211_BAND_2GHZ, &head, |
785 | ssid_bitmap, ¶ms); | 770 | ssid_bitmap, ¶ms); |
786 | } | 771 | } |
787 | if (band_5ghz) { | 772 | if (band_5ghz) { |
788 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, | 773 | iwl_scan_offload_build_tx_cmd(mvm, vif, ies, |
789 | IEEE80211_BAND_5GHZ, | 774 | IEEE80211_BAND_5GHZ, |
790 | &scan_cfg->scan_cmd.tx_cmd[1], | 775 | &scan_cfg->scan_cmd.tx_cmd[1], |
791 | scan_cfg->data + | 776 | probes + |
792 | SCAN_OFFLOAD_PROBE_REQ_SIZE); | 777 | SCAN_OFFLOAD_PROBE_REQ_SIZE); |
793 | iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg, | 778 | iwl_build_channel_cfg(mvm, req, scan_cfg->data, |
794 | IEEE80211_BAND_5GHZ, &head, &tail, | 779 | IEEE80211_BAND_5GHZ, &head, |
795 | ssid_bitmap, ¶ms); | 780 | ssid_bitmap, ¶ms); |
796 | } | 781 | } |
797 | 782 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 1fb01ea2e704..d3a6cf7558eb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -1448,3 +1448,23 @@ int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm, | |||
1448 | 1448 | ||
1449 | return 0; | 1449 | return 0; |
1450 | } | 1450 | } |
1451 | |||
1452 | void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, | ||
1453 | struct iwl_mvm_sta *mvmsta, bool disable) | ||
1454 | { | ||
1455 | struct iwl_mvm_add_sta_cmd cmd = { | ||
1456 | .add_modify = STA_MODE_MODIFY, | ||
1457 | .sta_id = mvmsta->sta_id, | ||
1458 | .station_flags = disable ? cpu_to_le32(STA_FLG_DISABLE_TX) : 0, | ||
1459 | .station_flags_msk = cpu_to_le32(STA_FLG_DISABLE_TX), | ||
1460 | .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), | ||
1461 | }; | ||
1462 | int ret; | ||
1463 | |||
1464 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_DISABLE_STA_TX)) | ||
1465 | return; | ||
1466 | |||
1467 | ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); | ||
1468 | if (ret) | ||
1469 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | ||
1470 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index d98e8a2142b8..10c1a5352651 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -404,5 +404,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | |||
404 | bool agg); | 404 | bool agg); |
405 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | 405 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
406 | bool drain); | 406 | bool drain); |
407 | void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, | ||
408 | struct iwl_mvm_sta *mvmsta, bool disable); | ||
407 | 409 | ||
408 | #endif /* __sta_h__ */ | 410 | #endif /* __sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 3846a6c41eb1..4f7cff506ee7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -205,7 +205,13 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, | |||
205 | mvm->mgmt_last_antenna_idx = | 205 | mvm->mgmt_last_antenna_idx = |
206 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, | 206 | iwl_mvm_next_antenna(mvm, mvm->fw->valid_tx_ant, |
207 | mvm->mgmt_last_antenna_idx); | 207 | mvm->mgmt_last_antenna_idx); |
208 | rate_flags = BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; | 208 | |
209 | if (info->band == IEEE80211_BAND_2GHZ && | ||
210 | !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) | ||
211 | rate_flags = BIT(ANT_A) << RATE_MCS_ANT_POS; | ||
212 | else | ||
213 | rate_flags = | ||
214 | BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; | ||
209 | 215 | ||
210 | /* Set CCK flag as needed */ | 216 | /* Set CCK flag as needed */ |
211 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | 217 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 6c22b23a2845..78f72c34438a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -260,6 +260,9 @@ iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | |||
260 | * @wd_timeout: queue watchdog timeout (jiffies) | 260 | * @wd_timeout: queue watchdog timeout (jiffies) |
261 | * @reg_lock: protect hw register access | 261 | * @reg_lock: protect hw register access |
262 | * @cmd_in_flight: true when we have a host command in flight | 262 | * @cmd_in_flight: true when we have a host command in flight |
263 | * @fw_mon_phys: physical address of the buffer for the firmware monitor | ||
264 | * @fw_mon_page: points to the first page of the buffer for the firmware monitor | ||
265 | * @fw_mon_size: size of the buffer for the firmware monitor | ||
263 | */ | 266 | */ |
264 | struct iwl_trans_pcie { | 267 | struct iwl_trans_pcie { |
265 | struct iwl_rxq rxq; | 268 | struct iwl_rxq rxq; |
@@ -312,6 +315,10 @@ struct iwl_trans_pcie { | |||
312 | /*protect hw register */ | 315 | /*protect hw register */ |
313 | spinlock_t reg_lock; | 316 | spinlock_t reg_lock; |
314 | bool cmd_in_flight; | 317 | bool cmd_in_flight; |
318 | |||
319 | dma_addr_t fw_mon_phys; | ||
320 | struct page *fw_mon_page; | ||
321 | u32 fw_mon_size; | ||
315 | }; | 322 | }; |
316 | 323 | ||
317 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 324 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 788085bc65d7..5703a3d7799b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -76,6 +76,68 @@ | |||
76 | #include "iwl-fw-error-dump.h" | 76 | #include "iwl-fw-error-dump.h" |
77 | #include "internal.h" | 77 | #include "internal.h" |
78 | 78 | ||
79 | static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans) | ||
80 | { | ||
81 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
82 | |||
83 | if (!trans_pcie->fw_mon_page) | ||
84 | return; | ||
85 | |||
86 | dma_unmap_page(trans->dev, trans_pcie->fw_mon_phys, | ||
87 | trans_pcie->fw_mon_size, DMA_FROM_DEVICE); | ||
88 | __free_pages(trans_pcie->fw_mon_page, | ||
89 | get_order(trans_pcie->fw_mon_size)); | ||
90 | trans_pcie->fw_mon_page = NULL; | ||
91 | trans_pcie->fw_mon_phys = 0; | ||
92 | trans_pcie->fw_mon_size = 0; | ||
93 | } | ||
94 | |||
95 | static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans) | ||
96 | { | ||
97 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
98 | struct page *page; | ||
99 | dma_addr_t phys; | ||
100 | u32 size; | ||
101 | u8 power; | ||
102 | |||
103 | if (trans_pcie->fw_mon_page) { | ||
104 | dma_sync_single_for_device(trans->dev, trans_pcie->fw_mon_phys, | ||
105 | trans_pcie->fw_mon_size, | ||
106 | DMA_FROM_DEVICE); | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | phys = 0; | ||
111 | for (power = 26; power >= 11; power--) { | ||
112 | int order; | ||
113 | |||
114 | size = BIT(power); | ||
115 | order = get_order(size); | ||
116 | page = alloc_pages(__GFP_COMP | __GFP_NOWARN | __GFP_ZERO, | ||
117 | order); | ||
118 | if (!page) | ||
119 | continue; | ||
120 | |||
121 | phys = dma_map_page(trans->dev, page, 0, PAGE_SIZE << order, | ||
122 | DMA_FROM_DEVICE); | ||
123 | if (dma_mapping_error(trans->dev, phys)) { | ||
124 | __free_pages(page, order); | ||
125 | continue; | ||
126 | } | ||
127 | IWL_INFO(trans, | ||
128 | "Allocated 0x%08x bytes (order %d) for firmware monitor.\n", | ||
129 | size, order); | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | if (!page) | ||
134 | return; | ||
135 | |||
136 | trans_pcie->fw_mon_page = page; | ||
137 | trans_pcie->fw_mon_phys = phys; | ||
138 | trans_pcie->fw_mon_size = size; | ||
139 | } | ||
140 | |||
79 | static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) | 141 | static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg) |
80 | { | 142 | { |
81 | iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, | 143 | iwl_write32(trans, HEEP_CTRL_WRD_PCIEX_CTRL_REG, |
@@ -675,6 +737,7 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans, | |||
675 | static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | 737 | static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, |
676 | const struct fw_img *image) | 738 | const struct fw_img *image) |
677 | { | 739 | { |
740 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
678 | int ret = 0; | 741 | int ret = 0; |
679 | int first_ucode_section; | 742 | int first_ucode_section; |
680 | 743 | ||
@@ -733,6 +796,20 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | |||
733 | return ret; | 796 | return ret; |
734 | } | 797 | } |
735 | 798 | ||
799 | /* supported for 7000 only for the moment */ | ||
800 | if (iwlwifi_mod_params.fw_monitor && | ||
801 | trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | ||
802 | iwl_pcie_alloc_fw_monitor(trans); | ||
803 | |||
804 | if (trans_pcie->fw_mon_size) { | ||
805 | iwl_write_prph(trans, MON_BUFF_BASE_ADDR, | ||
806 | trans_pcie->fw_mon_phys >> 4); | ||
807 | iwl_write_prph(trans, MON_BUFF_END_ADDR, | ||
808 | (trans_pcie->fw_mon_phys + | ||
809 | trans_pcie->fw_mon_size) >> 4); | ||
810 | } | ||
811 | } | ||
812 | |||
736 | /* release CPU reset */ | 813 | /* release CPU reset */ |
737 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | 814 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) |
738 | iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT); | 815 | iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT); |
@@ -1126,6 +1203,8 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1126 | if (trans_pcie->napi.poll) | 1203 | if (trans_pcie->napi.poll) |
1127 | netif_napi_del(&trans_pcie->napi); | 1204 | netif_napi_del(&trans_pcie->napi); |
1128 | 1205 | ||
1206 | iwl_pcie_free_fw_monitor(trans); | ||
1207 | |||
1129 | kfree(trans); | 1208 | kfree(trans); |
1130 | } | 1209 | } |
1131 | 1210 | ||
@@ -1494,10 +1573,12 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
1494 | txq = &trans_pcie->txq[cnt]; | 1573 | txq = &trans_pcie->txq[cnt]; |
1495 | q = &txq->q; | 1574 | q = &txq->q; |
1496 | pos += scnprintf(buf + pos, bufsz - pos, | 1575 | pos += scnprintf(buf + pos, bufsz - pos, |
1497 | "hwq %.2d: read=%u write=%u use=%d stop=%d\n", | 1576 | "hwq %.2d: read=%u write=%u use=%d stop=%d need_update=%d%s\n", |
1498 | cnt, q->read_ptr, q->write_ptr, | 1577 | cnt, q->read_ptr, q->write_ptr, |
1499 | !!test_bit(cnt, trans_pcie->queue_used), | 1578 | !!test_bit(cnt, trans_pcie->queue_used), |
1500 | !!test_bit(cnt, trans_pcie->queue_stopped)); | 1579 | !!test_bit(cnt, trans_pcie->queue_stopped), |
1580 | txq->need_update, | ||
1581 | (cnt == trans_pcie->cmd_queue ? " HCMD" : "")); | ||
1501 | } | 1582 | } |
1502 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1583 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1503 | kfree(buf); | 1584 | kfree(buf); |
@@ -1519,6 +1600,10 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1519 | rxq->read); | 1600 | rxq->read); |
1520 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | 1601 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", |
1521 | rxq->write); | 1602 | rxq->write); |
1603 | pos += scnprintf(buf + pos, bufsz - pos, "write_actual: %u\n", | ||
1604 | rxq->write_actual); | ||
1605 | pos += scnprintf(buf + pos, bufsz - pos, "need_update: %d\n", | ||
1606 | rxq->need_update); | ||
1522 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | 1607 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", |
1523 | rxq->free_count); | 1608 | rxq->free_count); |
1524 | if (rxq->rb_stts) { | 1609 | if (rxq->rb_stts) { |
@@ -1698,10 +1783,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, | |||
1698 | u32 len; | 1783 | u32 len; |
1699 | int i, ptr; | 1784 | int i, ptr; |
1700 | 1785 | ||
1786 | len = sizeof(*data) + | ||
1787 | cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); | ||
1788 | |||
1789 | if (trans_pcie->fw_mon_page) | ||
1790 | len += sizeof(*data) + sizeof(struct iwl_fw_error_fw_mon) + | ||
1791 | trans_pcie->fw_mon_size; | ||
1792 | |||
1701 | if (!buf) | 1793 | if (!buf) |
1702 | return sizeof(*data) + | 1794 | return len; |
1703 | cmdq->q.n_window * (sizeof(*txcmd) + | ||
1704 | TFD_MAX_PAYLOAD_SIZE); | ||
1705 | 1795 | ||
1706 | len = 0; | 1796 | len = 0; |
1707 | data = buf; | 1797 | data = buf; |
@@ -1729,7 +1819,40 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans, | |||
1729 | spin_unlock_bh(&cmdq->lock); | 1819 | spin_unlock_bh(&cmdq->lock); |
1730 | 1820 | ||
1731 | data->len = cpu_to_le32(len); | 1821 | data->len = cpu_to_le32(len); |
1732 | return sizeof(*data) + len; | 1822 | len += sizeof(*data); |
1823 | |||
1824 | if (trans_pcie->fw_mon_page) { | ||
1825 | struct iwl_fw_error_fw_mon *fw_mon_data; | ||
1826 | |||
1827 | data = iwl_fw_error_next_data(data); | ||
1828 | data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR); | ||
1829 | data->len = cpu_to_le32(trans_pcie->fw_mon_size + | ||
1830 | sizeof(*fw_mon_data)); | ||
1831 | fw_mon_data = (void *)data->data; | ||
1832 | fw_mon_data->fw_mon_wr_ptr = | ||
1833 | cpu_to_le32(iwl_read_prph(trans, MON_BUFF_WRPTR)); | ||
1834 | fw_mon_data->fw_mon_cycle_cnt = | ||
1835 | cpu_to_le32(iwl_read_prph(trans, MON_BUFF_CYCLE_CNT)); | ||
1836 | fw_mon_data->fw_mon_base_ptr = | ||
1837 | cpu_to_le32(iwl_read_prph(trans, MON_BUFF_BASE_ADDR)); | ||
1838 | |||
1839 | /* | ||
1840 | * The firmware is now asserted, it won't write anything to | ||
1841 | * the buffer. CPU can take ownership to fetch the data. | ||
1842 | * The buffer will be handed back to the device before the | ||
1843 | * firmware will be restarted. | ||
1844 | */ | ||
1845 | dma_sync_single_for_cpu(trans->dev, trans_pcie->fw_mon_phys, | ||
1846 | trans_pcie->fw_mon_size, | ||
1847 | DMA_FROM_DEVICE); | ||
1848 | memcpy(fw_mon_data->data, page_address(trans_pcie->fw_mon_page), | ||
1849 | trans_pcie->fw_mon_size); | ||
1850 | |||
1851 | len += sizeof(*data) + sizeof(*fw_mon_data) + | ||
1852 | trans_pcie->fw_mon_size; | ||
1853 | } | ||
1854 | |||
1855 | return len; | ||
1733 | } | 1856 | } |
1734 | #else | 1857 | #else |
1735 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | 1858 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, |
@@ -1870,6 +1993,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | |||
1870 | } | 1993 | } |
1871 | 1994 | ||
1872 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); | 1995 | trans->hw_rev = iwl_read32(trans, CSR_HW_REV); |
1996 | /* | ||
1997 | * In the 8000 HW family the format of the 4 bytes of CSR_HW_REV have | ||
1998 | * changed, and now the revision step also includes bit 0-1 (no more | ||
1999 | * "dash" value). To keep hw_rev backwards compatible - we'll store it | ||
2000 | * in the old format. | ||
2001 | */ | ||
2002 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
2003 | trans->hw_rev = (trans->hw_rev & 0xfff0) | | ||
2004 | ((trans->hw_rev << 2) & 0xc); | ||
2005 | |||
1873 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; | 2006 | trans->hw_id = (pdev->device << 16) + pdev->subsystem_device; |
1874 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), | 2007 | snprintf(trans->hw_id_str, sizeof(trans->hw_id_str), |
1875 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); | 2008 | "PCI ID: 0x%04X:0x%04X", pdev->device, pdev->subsystem_device); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 038940afbdc5..6acccb19c4f3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1438,6 +1438,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1438 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 1438 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
1439 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); | 1439 | spin_unlock_irqrestore(&trans_pcie->reg_lock, flags); |
1440 | trans_pcie->cmd_in_flight = false; | 1440 | trans_pcie->cmd_in_flight = false; |
1441 | IWL_ERR(trans, "Failed to wake NIC for hcmd\n"); | ||
1441 | idx = -EIO; | 1442 | idx = -EIO; |
1442 | goto out; | 1443 | goto out; |
1443 | } | 1444 | } |