diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
48 files changed, 8858 insertions, 7210 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 4e378faee650..7c7235385513 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -9,7 +9,10 @@ CFLAGS_iwl-devtrace.o := -I$(src) | |||
9 | 9 | ||
10 | # AGN | 10 | # AGN |
11 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 11 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | ||
14 | iwlagn-objs += iwl-agn-lib.o | ||
15 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | ||
13 | 16 | ||
14 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 17 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
15 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 18 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
@@ -19,5 +22,6 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | |||
19 | # 3945 | 22 | # 3945 |
20 | obj-$(CONFIG_IWL3945) += iwl3945.o | 23 | obj-$(CONFIG_IWL3945) += iwl3945.o |
21 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o | 24 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o |
25 | iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o | ||
22 | 26 | ||
23 | ccflags-y += -D__CHECK_ENDIAN__ | 27 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3bf2e6e9b2d9..6be2992f8f21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -42,9 +42,11 @@ | |||
42 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-agn.h" | ||
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 47 | #include "iwl-agn-hw.h" |
47 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn-debugfs.h" | ||
48 | 50 | ||
49 | /* Highest firmware API version supported */ | 51 | /* Highest firmware API version supported */ |
50 | #define IWL1000_UCODE_API_MAX 3 | 52 | #define IWL1000_UCODE_API_MAX 3 |
@@ -117,7 +119,7 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = { | |||
117 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | 119 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) |
118 | { | 120 | { |
119 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 121 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
120 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 122 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
121 | priv->cfg->num_of_queues = | 123 | priv->cfg->num_of_queues = |
122 | priv->cfg->mod_params->num_of_queues; | 124 | priv->cfg->mod_params->num_of_queues; |
123 | 125 | ||
@@ -125,13 +127,13 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
125 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 127 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
126 | priv->hw_params.scd_bc_tbls_size = | 128 | priv->hw_params.scd_bc_tbls_size = |
127 | priv->cfg->num_of_queues * | 129 | priv->cfg->num_of_queues * |
128 | sizeof(struct iwl5000_scd_bc_tbl); | 130 | sizeof(struct iwlagn_scd_bc_tbl); |
129 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 131 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
130 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 132 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
131 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 133 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
132 | 134 | ||
133 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 135 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
134 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 136 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
135 | 137 | ||
136 | priv->hw_params.max_bsm_size = 0; | 138 | priv->hw_params.max_bsm_size = 0; |
137 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 139 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -161,25 +163,25 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
161 | 163 | ||
162 | static struct iwl_lib_ops iwl1000_lib = { | 164 | static struct iwl_lib_ops iwl1000_lib = { |
163 | .set_hw_params = iwl1000_hw_set_hw_params, | 165 | .set_hw_params = iwl1000_hw_set_hw_params, |
164 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 166 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
165 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 167 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
166 | .txq_set_sched = iwl5000_txq_set_sched, | 168 | .txq_set_sched = iwlagn_txq_set_sched, |
167 | .txq_agg_enable = iwl5000_txq_agg_enable, | 169 | .txq_agg_enable = iwlagn_txq_agg_enable, |
168 | .txq_agg_disable = iwl5000_txq_agg_disable, | 170 | .txq_agg_disable = iwlagn_txq_agg_disable, |
169 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 171 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
170 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 172 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
171 | .txq_init = iwl_hw_tx_queue_init, | 173 | .txq_init = iwl_hw_tx_queue_init, |
172 | .rx_handler_setup = iwl5000_rx_handler_setup, | 174 | .rx_handler_setup = iwlagn_rx_handler_setup, |
173 | .setup_deferred_work = iwl5000_setup_deferred_work, | 175 | .setup_deferred_work = iwlagn_setup_deferred_work, |
174 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 176 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
175 | .load_ucode = iwl5000_load_ucode, | 177 | .load_ucode = iwlagn_load_ucode, |
176 | .dump_nic_event_log = iwl_dump_nic_event_log, | 178 | .dump_nic_event_log = iwl_dump_nic_event_log, |
177 | .dump_nic_error_log = iwl_dump_nic_error_log, | 179 | .dump_nic_error_log = iwl_dump_nic_error_log, |
178 | .dump_csr = iwl_dump_csr, | 180 | .dump_csr = iwl_dump_csr, |
179 | .dump_fh = iwl_dump_fh, | 181 | .dump_fh = iwl_dump_fh, |
180 | .init_alive_start = iwl5000_init_alive_start, | 182 | .init_alive_start = iwlagn_init_alive_start, |
181 | .alive_notify = iwl5000_alive_notify, | 183 | .alive_notify = iwlagn_alive_notify, |
182 | .send_tx_power = iwl5000_send_tx_power, | 184 | .send_tx_power = iwlagn_send_tx_power, |
183 | .update_chain_flags = iwl_update_chain_flags, | 185 | .update_chain_flags = iwl_update_chain_flags, |
184 | .apm_ops = { | 186 | .apm_ops = { |
185 | .init = iwl_apm_init, | 187 | .init = iwl_apm_init, |
@@ -189,40 +191,47 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
189 | }, | 191 | }, |
190 | .eeprom_ops = { | 192 | .eeprom_ops = { |
191 | .regulatory_bands = { | 193 | .regulatory_bands = { |
192 | EEPROM_5000_REG_BAND_1_CHANNELS, | 194 | EEPROM_REG_BAND_1_CHANNELS, |
193 | EEPROM_5000_REG_BAND_2_CHANNELS, | 195 | EEPROM_REG_BAND_2_CHANNELS, |
194 | EEPROM_5000_REG_BAND_3_CHANNELS, | 196 | EEPROM_REG_BAND_3_CHANNELS, |
195 | EEPROM_5000_REG_BAND_4_CHANNELS, | 197 | EEPROM_REG_BAND_4_CHANNELS, |
196 | EEPROM_5000_REG_BAND_5_CHANNELS, | 198 | EEPROM_REG_BAND_5_CHANNELS, |
197 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 199 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
198 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 200 | EEPROM_REG_BAND_52_HT40_CHANNELS |
199 | }, | 201 | }, |
200 | .verify_signature = iwlcore_eeprom_verify_signature, | 202 | .verify_signature = iwlcore_eeprom_verify_signature, |
201 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 203 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
202 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 204 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
203 | .calib_version = iwl5000_eeprom_calib_version, | 205 | .calib_version = iwlagn_eeprom_calib_version, |
204 | .query_addr = iwl5000_eeprom_query_addr, | 206 | .query_addr = iwlagn_eeprom_query_addr, |
205 | }, | 207 | }, |
206 | .post_associate = iwl_post_associate, | 208 | .post_associate = iwl_post_associate, |
207 | .isr = iwl_isr_ict, | 209 | .isr = iwl_isr_ict, |
208 | .config_ap = iwl_config_ap, | 210 | .config_ap = iwl_config_ap, |
209 | .temp_ops = { | 211 | .temp_ops = { |
210 | .temperature = iwl5000_temperature, | 212 | .temperature = iwlagn_temperature, |
211 | .set_ct_kill = iwl1000_set_ct_threshold, | 213 | .set_ct_kill = iwl1000_set_ct_threshold, |
212 | }, | 214 | }, |
213 | .add_bcast_station = iwl_add_bcast_station, | 215 | .manage_ibss_station = iwlagn_manage_ibss_station, |
216 | .debugfs_ops = { | ||
217 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
218 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
219 | .general_stats_read = iwl_ucode_general_stats_read, | ||
220 | }, | ||
221 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
222 | .check_plcp_health = iwl_good_plcp_health, | ||
223 | .check_ack_health = iwl_good_ack_health, | ||
214 | }; | 224 | }; |
215 | 225 | ||
216 | static const struct iwl_ops iwl1000_ops = { | 226 | static const struct iwl_ops iwl1000_ops = { |
217 | .ucode = &iwl5000_ucode, | ||
218 | .lib = &iwl1000_lib, | 227 | .lib = &iwl1000_lib, |
219 | .hcmd = &iwl5000_hcmd, | 228 | .hcmd = &iwlagn_hcmd, |
220 | .utils = &iwl5000_hcmd_utils, | 229 | .utils = &iwlagn_hcmd_utils, |
221 | .led = &iwlagn_led_ops, | 230 | .led = &iwlagn_led_ops, |
222 | }; | 231 | }; |
223 | 232 | ||
224 | struct iwl_cfg iwl1000_bgn_cfg = { | 233 | struct iwl_cfg iwl1000_bgn_cfg = { |
225 | .name = "1000 Series BGN", | 234 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN", |
226 | .fw_name_pre = IWL1000_FW_PRE, | 235 | .fw_name_pre = IWL1000_FW_PRE, |
227 | .ucode_api_max = IWL1000_UCODE_API_MAX, | 236 | .ucode_api_max = IWL1000_UCODE_API_MAX, |
228 | .ucode_api_min = IWL1000_UCODE_API_MIN, | 237 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
@@ -230,10 +239,10 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
230 | .ops = &iwl1000_ops, | 239 | .ops = &iwl1000_ops, |
231 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 240 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
232 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 241 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
233 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 242 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
234 | .num_of_queues = IWL50_NUM_QUEUES, | 243 | .num_of_queues = IWLAGN_NUM_QUEUES, |
235 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 244 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
236 | .mod_params = &iwl50_mod_params, | 245 | .mod_params = &iwlagn_mod_params, |
237 | .valid_tx_ant = ANT_A, | 246 | .valid_tx_ant = ANT_A, |
238 | .valid_rx_ant = ANT_AB, | 247 | .valid_rx_ant = ANT_AB, |
239 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 248 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -248,10 +257,15 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
248 | .support_ct_kill_exit = true, | 257 | .support_ct_kill_exit = true, |
249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 258 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
250 | .chain_noise_scale = 1000, | 259 | .chain_noise_scale = 1000, |
260 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
261 | .max_event_log_size = 128, | ||
262 | .ucode_tracing = true, | ||
263 | .sensitivity_calib_by_driver = true, | ||
264 | .chain_noise_calib_by_driver = true, | ||
251 | }; | 265 | }; |
252 | 266 | ||
253 | struct iwl_cfg iwl1000_bg_cfg = { | 267 | struct iwl_cfg iwl1000_bg_cfg = { |
254 | .name = "1000 Series BG", | 268 | .name = "Intel(R) Centrino(R) Wireless-N 1000 BG", |
255 | .fw_name_pre = IWL1000_FW_PRE, | 269 | .fw_name_pre = IWL1000_FW_PRE, |
256 | .ucode_api_max = IWL1000_UCODE_API_MAX, | 270 | .ucode_api_max = IWL1000_UCODE_API_MAX, |
257 | .ucode_api_min = IWL1000_UCODE_API_MIN, | 271 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
@@ -259,10 +273,10 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
259 | .ops = &iwl1000_ops, | 273 | .ops = &iwl1000_ops, |
260 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 274 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
261 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 275 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
262 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 276 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
263 | .num_of_queues = IWL50_NUM_QUEUES, | 277 | .num_of_queues = IWLAGN_NUM_QUEUES, |
264 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 278 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
265 | .mod_params = &iwl50_mod_params, | 279 | .mod_params = &iwlagn_mod_params, |
266 | .valid_tx_ant = ANT_A, | 280 | .valid_tx_ant = ANT_A, |
267 | .valid_rx_ant = ANT_AB, | 281 | .valid_rx_ant = ANT_AB, |
268 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 282 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -270,12 +284,16 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
270 | .use_bsm = false, | 284 | .use_bsm = false, |
271 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 285 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
272 | .shadow_ram_support = false, | 286 | .shadow_ram_support = false, |
273 | .ht_greenfield_support = true, | ||
274 | .led_compensation = 51, | 287 | .led_compensation = 51, |
275 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 288 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
276 | .support_ct_kill_exit = true, | 289 | .support_ct_kill_exit = true, |
277 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 290 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
278 | .chain_noise_scale = 1000, | 291 | .chain_noise_scale = 1000, |
292 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
293 | .max_event_log_size = 128, | ||
294 | .ucode_tracing = true, | ||
295 | .sensitivity_calib_by_driver = true, | ||
296 | .chain_noise_calib_by_driver = true, | ||
279 | }; | 297 | }; |
280 | 298 | ||
281 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 299 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c new file mode 100644 index 000000000000..6a9c64a50e36 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c | |||
@@ -0,0 +1,500 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include "iwl-3945-debugfs.h" | ||
30 | |||
31 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | ||
32 | char __user *user_buf, | ||
33 | size_t count, loff_t *ppos) | ||
34 | { | ||
35 | struct iwl_priv *priv = file->private_data; | ||
36 | int pos = 0; | ||
37 | char *buf; | ||
38 | int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 + | ||
39 | sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400; | ||
40 | ssize_t ret; | ||
41 | struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; | ||
42 | struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; | ||
43 | struct iwl39_statistics_rx_non_phy *general, *accum_general; | ||
44 | struct iwl39_statistics_rx_non_phy *delta_general, *max_general; | ||
45 | |||
46 | if (!iwl_is_alive(priv)) | ||
47 | return -EAGAIN; | ||
48 | |||
49 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
50 | if (!buf) { | ||
51 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
52 | return -ENOMEM; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * The statistic information display here is based on | ||
57 | * the last statistics notification from uCode | ||
58 | * might not reflect the current uCode activity | ||
59 | */ | ||
60 | ofdm = &priv->_3945.statistics.rx.ofdm; | ||
61 | cck = &priv->_3945.statistics.rx.cck; | ||
62 | general = &priv->_3945.statistics.rx.general; | ||
63 | accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm; | ||
64 | accum_cck = &priv->_3945.accum_statistics.rx.cck; | ||
65 | accum_general = &priv->_3945.accum_statistics.rx.general; | ||
66 | delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm; | ||
67 | delta_cck = &priv->_3945.delta_statistics.rx.cck; | ||
68 | delta_general = &priv->_3945.delta_statistics.rx.general; | ||
69 | max_ofdm = &priv->_3945.max_delta.rx.ofdm; | ||
70 | max_cck = &priv->_3945.max_delta.rx.cck; | ||
71 | max_general = &priv->_3945.max_delta.rx.general; | ||
72 | |||
73 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
74 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
75 | "acumulative delta max\n", | ||
76 | "Statistics_Rx - OFDM:"); | ||
77 | pos += scnprintf(buf + pos, bufsz - pos, | ||
78 | " %-30s %10u %10u %10u %10u\n", | ||
79 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), | ||
80 | accum_ofdm->ina_cnt, | ||
81 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); | ||
82 | pos += scnprintf(buf + pos, bufsz - pos, | ||
83 | " %-30s %10u %10u %10u %10u\n", | ||
84 | "fina_cnt:", | ||
85 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, | ||
86 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); | ||
87 | pos += scnprintf(buf + pos, bufsz - pos, | ||
88 | " %-30s %10u %10u %10u %10u\n", "plcp_err:", | ||
89 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, | ||
90 | delta_ofdm->plcp_err, max_ofdm->plcp_err); | ||
91 | pos += scnprintf(buf + pos, bufsz - pos, | ||
92 | " %-30s %10u %10u %10u %10u\n", "crc32_err:", | ||
93 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, | ||
94 | delta_ofdm->crc32_err, max_ofdm->crc32_err); | ||
95 | pos += scnprintf(buf + pos, bufsz - pos, | ||
96 | " %-30s %10u %10u %10u %10u\n", "overrun_err:", | ||
97 | le32_to_cpu(ofdm->overrun_err), | ||
98 | accum_ofdm->overrun_err, delta_ofdm->overrun_err, | ||
99 | max_ofdm->overrun_err); | ||
100 | pos += scnprintf(buf + pos, bufsz - pos, | ||
101 | " %-30s %10u %10u %10u %10u\n", | ||
102 | "early_overrun_err:", | ||
103 | le32_to_cpu(ofdm->early_overrun_err), | ||
104 | accum_ofdm->early_overrun_err, | ||
105 | delta_ofdm->early_overrun_err, | ||
106 | max_ofdm->early_overrun_err); | ||
107 | pos += scnprintf(buf + pos, bufsz - pos, | ||
108 | " %-30s %10u %10u %10u %10u\n", | ||
109 | "crc32_good:", le32_to_cpu(ofdm->crc32_good), | ||
110 | accum_ofdm->crc32_good, delta_ofdm->crc32_good, | ||
111 | max_ofdm->crc32_good); | ||
112 | pos += scnprintf(buf + pos, bufsz - pos, | ||
113 | " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:", | ||
114 | le32_to_cpu(ofdm->false_alarm_cnt), | ||
115 | accum_ofdm->false_alarm_cnt, | ||
116 | delta_ofdm->false_alarm_cnt, | ||
117 | max_ofdm->false_alarm_cnt); | ||
118 | pos += scnprintf(buf + pos, bufsz - pos, | ||
119 | " %-30s %10u %10u %10u %10u\n", | ||
120 | "fina_sync_err_cnt:", | ||
121 | le32_to_cpu(ofdm->fina_sync_err_cnt), | ||
122 | accum_ofdm->fina_sync_err_cnt, | ||
123 | delta_ofdm->fina_sync_err_cnt, | ||
124 | max_ofdm->fina_sync_err_cnt); | ||
125 | pos += scnprintf(buf + pos, bufsz - pos, | ||
126 | " %-30s %10u %10u %10u %10u\n", | ||
127 | "sfd_timeout:", | ||
128 | le32_to_cpu(ofdm->sfd_timeout), | ||
129 | accum_ofdm->sfd_timeout, | ||
130 | delta_ofdm->sfd_timeout, | ||
131 | max_ofdm->sfd_timeout); | ||
132 | pos += scnprintf(buf + pos, bufsz - pos, | ||
133 | " %-30s %10u %10u %10u %10u\n", | ||
134 | "fina_timeout:", | ||
135 | le32_to_cpu(ofdm->fina_timeout), | ||
136 | accum_ofdm->fina_timeout, | ||
137 | delta_ofdm->fina_timeout, | ||
138 | max_ofdm->fina_timeout); | ||
139 | pos += scnprintf(buf + pos, bufsz - pos, | ||
140 | " %-30s %10u %10u %10u %10u\n", | ||
141 | "unresponded_rts:", | ||
142 | le32_to_cpu(ofdm->unresponded_rts), | ||
143 | accum_ofdm->unresponded_rts, | ||
144 | delta_ofdm->unresponded_rts, | ||
145 | max_ofdm->unresponded_rts); | ||
146 | pos += scnprintf(buf + pos, bufsz - pos, | ||
147 | " %-30s %10u %10u %10u %10u\n", | ||
148 | "rxe_frame_lmt_ovrun:", | ||
149 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | ||
150 | accum_ofdm->rxe_frame_limit_overrun, | ||
151 | delta_ofdm->rxe_frame_limit_overrun, | ||
152 | max_ofdm->rxe_frame_limit_overrun); | ||
153 | pos += scnprintf(buf + pos, bufsz - pos, | ||
154 | " %-30s %10u %10u %10u %10u\n", | ||
155 | "sent_ack_cnt:", | ||
156 | le32_to_cpu(ofdm->sent_ack_cnt), | ||
157 | accum_ofdm->sent_ack_cnt, | ||
158 | delta_ofdm->sent_ack_cnt, | ||
159 | max_ofdm->sent_ack_cnt); | ||
160 | pos += scnprintf(buf + pos, bufsz - pos, | ||
161 | " %-30s %10u %10u %10u %10u\n", | ||
162 | "sent_cts_cnt:", | ||
163 | le32_to_cpu(ofdm->sent_cts_cnt), | ||
164 | accum_ofdm->sent_cts_cnt, | ||
165 | delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); | ||
166 | |||
167 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
168 | "acumulative delta max\n", | ||
169 | "Statistics_Rx - CCK:"); | ||
170 | pos += scnprintf(buf + pos, bufsz - pos, | ||
171 | " %-30s %10u %10u %10u %10u\n", | ||
172 | "ina_cnt:", | ||
173 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, | ||
174 | delta_cck->ina_cnt, max_cck->ina_cnt); | ||
175 | pos += scnprintf(buf + pos, bufsz - pos, | ||
176 | " %-30s %10u %10u %10u %10u\n", | ||
177 | "fina_cnt:", | ||
178 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, | ||
179 | delta_cck->fina_cnt, max_cck->fina_cnt); | ||
180 | pos += scnprintf(buf + pos, bufsz - pos, | ||
181 | " %-30s %10u %10u %10u %10u\n", | ||
182 | "plcp_err:", | ||
183 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, | ||
184 | delta_cck->plcp_err, max_cck->plcp_err); | ||
185 | pos += scnprintf(buf + pos, bufsz - pos, | ||
186 | " %-30s %10u %10u %10u %10u\n", | ||
187 | "crc32_err:", | ||
188 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, | ||
189 | delta_cck->crc32_err, max_cck->crc32_err); | ||
190 | pos += scnprintf(buf + pos, bufsz - pos, | ||
191 | " %-30s %10u %10u %10u %10u\n", | ||
192 | "overrun_err:", | ||
193 | le32_to_cpu(cck->overrun_err), | ||
194 | accum_cck->overrun_err, | ||
195 | delta_cck->overrun_err, max_cck->overrun_err); | ||
196 | pos += scnprintf(buf + pos, bufsz - pos, | ||
197 | " %-30s %10u %10u %10u %10u\n", | ||
198 | "early_overrun_err:", | ||
199 | le32_to_cpu(cck->early_overrun_err), | ||
200 | accum_cck->early_overrun_err, | ||
201 | delta_cck->early_overrun_err, | ||
202 | max_cck->early_overrun_err); | ||
203 | pos += scnprintf(buf + pos, bufsz - pos, | ||
204 | " %-30s %10u %10u %10u %10u\n", | ||
205 | "crc32_good:", | ||
206 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, | ||
207 | delta_cck->crc32_good, | ||
208 | max_cck->crc32_good); | ||
209 | pos += scnprintf(buf + pos, bufsz - pos, | ||
210 | " %-30s %10u %10u %10u %10u\n", | ||
211 | "false_alarm_cnt:", | ||
212 | le32_to_cpu(cck->false_alarm_cnt), | ||
213 | accum_cck->false_alarm_cnt, | ||
214 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); | ||
215 | pos += scnprintf(buf + pos, bufsz - pos, | ||
216 | " %-30s %10u %10u %10u %10u\n", | ||
217 | "fina_sync_err_cnt:", | ||
218 | le32_to_cpu(cck->fina_sync_err_cnt), | ||
219 | accum_cck->fina_sync_err_cnt, | ||
220 | delta_cck->fina_sync_err_cnt, | ||
221 | max_cck->fina_sync_err_cnt); | ||
222 | pos += scnprintf(buf + pos, bufsz - pos, | ||
223 | " %-30s %10u %10u %10u %10u\n", | ||
224 | "sfd_timeout:", | ||
225 | le32_to_cpu(cck->sfd_timeout), | ||
226 | accum_cck->sfd_timeout, | ||
227 | delta_cck->sfd_timeout, max_cck->sfd_timeout); | ||
228 | pos += scnprintf(buf + pos, bufsz - pos, | ||
229 | " %-30s %10u %10u %10u %10u\n", | ||
230 | "fina_timeout:", | ||
231 | le32_to_cpu(cck->fina_timeout), | ||
232 | accum_cck->fina_timeout, | ||
233 | delta_cck->fina_timeout, max_cck->fina_timeout); | ||
234 | pos += scnprintf(buf + pos, bufsz - pos, | ||
235 | " %-30s %10u %10u %10u %10u\n", | ||
236 | "unresponded_rts:", | ||
237 | le32_to_cpu(cck->unresponded_rts), | ||
238 | accum_cck->unresponded_rts, | ||
239 | delta_cck->unresponded_rts, | ||
240 | max_cck->unresponded_rts); | ||
241 | pos += scnprintf(buf + pos, bufsz - pos, | ||
242 | " %-30s %10u %10u %10u %10u\n", | ||
243 | "rxe_frame_lmt_ovrun:", | ||
244 | le32_to_cpu(cck->rxe_frame_limit_overrun), | ||
245 | accum_cck->rxe_frame_limit_overrun, | ||
246 | delta_cck->rxe_frame_limit_overrun, | ||
247 | max_cck->rxe_frame_limit_overrun); | ||
248 | pos += scnprintf(buf + pos, bufsz - pos, | ||
249 | " %-30s %10u %10u %10u %10u\n", | ||
250 | "sent_ack_cnt:", | ||
251 | le32_to_cpu(cck->sent_ack_cnt), | ||
252 | accum_cck->sent_ack_cnt, | ||
253 | delta_cck->sent_ack_cnt, | ||
254 | max_cck->sent_ack_cnt); | ||
255 | pos += scnprintf(buf + pos, bufsz - pos, | ||
256 | " %-30s %10u %10u %10u %10u\n", | ||
257 | "sent_cts_cnt:", | ||
258 | le32_to_cpu(cck->sent_cts_cnt), | ||
259 | accum_cck->sent_cts_cnt, | ||
260 | delta_cck->sent_cts_cnt, | ||
261 | max_cck->sent_cts_cnt); | ||
262 | |||
263 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
264 | "acumulative delta max\n", | ||
265 | "Statistics_Rx - GENERAL:"); | ||
266 | pos += scnprintf(buf + pos, bufsz - pos, | ||
267 | " %-30s %10u %10u %10u %10u\n", | ||
268 | "bogus_cts:", | ||
269 | le32_to_cpu(general->bogus_cts), | ||
270 | accum_general->bogus_cts, | ||
271 | delta_general->bogus_cts, max_general->bogus_cts); | ||
272 | pos += scnprintf(buf + pos, bufsz - pos, | ||
273 | " %-30s %10u %10u %10u %10u\n", | ||
274 | "bogus_ack:", | ||
275 | le32_to_cpu(general->bogus_ack), | ||
276 | accum_general->bogus_ack, | ||
277 | delta_general->bogus_ack, max_general->bogus_ack); | ||
278 | pos += scnprintf(buf + pos, bufsz - pos, | ||
279 | " %-30s %10u %10u %10u %10u\n", | ||
280 | "non_bssid_frames:", | ||
281 | le32_to_cpu(general->non_bssid_frames), | ||
282 | accum_general->non_bssid_frames, | ||
283 | delta_general->non_bssid_frames, | ||
284 | max_general->non_bssid_frames); | ||
285 | pos += scnprintf(buf + pos, bufsz - pos, | ||
286 | " %-30s %10u %10u %10u %10u\n", | ||
287 | "filtered_frames:", | ||
288 | le32_to_cpu(general->filtered_frames), | ||
289 | accum_general->filtered_frames, | ||
290 | delta_general->filtered_frames, | ||
291 | max_general->filtered_frames); | ||
292 | pos += scnprintf(buf + pos, bufsz - pos, | ||
293 | " %-30s %10u %10u %10u %10u\n", | ||
294 | "non_channel_beacons:", | ||
295 | le32_to_cpu(general->non_channel_beacons), | ||
296 | accum_general->non_channel_beacons, | ||
297 | delta_general->non_channel_beacons, | ||
298 | max_general->non_channel_beacons); | ||
299 | |||
300 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
301 | kfree(buf); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | ssize_t iwl3945_ucode_tx_stats_read(struct file *file, | ||
306 | char __user *user_buf, | ||
307 | size_t count, loff_t *ppos) | ||
308 | { | ||
309 | struct iwl_priv *priv = file->private_data; | ||
310 | int pos = 0; | ||
311 | char *buf; | ||
312 | int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250; | ||
313 | ssize_t ret; | ||
314 | struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; | ||
315 | |||
316 | if (!iwl_is_alive(priv)) | ||
317 | return -EAGAIN; | ||
318 | |||
319 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
320 | if (!buf) { | ||
321 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
322 | return -ENOMEM; | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * The statistic information display here is based on | ||
327 | * the last statistics notification from uCode | ||
328 | * might not reflect the current uCode activity | ||
329 | */ | ||
330 | tx = &priv->_3945.statistics.tx; | ||
331 | accum_tx = &priv->_3945.accum_statistics.tx; | ||
332 | delta_tx = &priv->_3945.delta_statistics.tx; | ||
333 | max_tx = &priv->_3945.max_delta.tx; | ||
334 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
335 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
336 | "acumulative delta max\n", | ||
337 | "Statistics_Tx:"); | ||
338 | pos += scnprintf(buf + pos, bufsz - pos, | ||
339 | " %-30s %10u %10u %10u %10u\n", | ||
340 | "preamble:", | ||
341 | le32_to_cpu(tx->preamble_cnt), | ||
342 | accum_tx->preamble_cnt, | ||
343 | delta_tx->preamble_cnt, max_tx->preamble_cnt); | ||
344 | pos += scnprintf(buf + pos, bufsz - pos, | ||
345 | " %-30s %10u %10u %10u %10u\n", | ||
346 | "rx_detected_cnt:", | ||
347 | le32_to_cpu(tx->rx_detected_cnt), | ||
348 | accum_tx->rx_detected_cnt, | ||
349 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); | ||
350 | pos += scnprintf(buf + pos, bufsz - pos, | ||
351 | " %-30s %10u %10u %10u %10u\n", | ||
352 | "bt_prio_defer_cnt:", | ||
353 | le32_to_cpu(tx->bt_prio_defer_cnt), | ||
354 | accum_tx->bt_prio_defer_cnt, | ||
355 | delta_tx->bt_prio_defer_cnt, | ||
356 | max_tx->bt_prio_defer_cnt); | ||
357 | pos += scnprintf(buf + pos, bufsz - pos, | ||
358 | " %-30s %10u %10u %10u %10u\n", | ||
359 | "bt_prio_kill_cnt:", | ||
360 | le32_to_cpu(tx->bt_prio_kill_cnt), | ||
361 | accum_tx->bt_prio_kill_cnt, | ||
362 | delta_tx->bt_prio_kill_cnt, | ||
363 | max_tx->bt_prio_kill_cnt); | ||
364 | pos += scnprintf(buf + pos, bufsz - pos, | ||
365 | " %-30s %10u %10u %10u %10u\n", | ||
366 | "few_bytes_cnt:", | ||
367 | le32_to_cpu(tx->few_bytes_cnt), | ||
368 | accum_tx->few_bytes_cnt, | ||
369 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); | ||
370 | pos += scnprintf(buf + pos, bufsz - pos, | ||
371 | " %-30s %10u %10u %10u %10u\n", | ||
372 | "cts_timeout:", | ||
373 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, | ||
374 | delta_tx->cts_timeout, max_tx->cts_timeout); | ||
375 | pos += scnprintf(buf + pos, bufsz - pos, | ||
376 | " %-30s %10u %10u %10u %10u\n", | ||
377 | "ack_timeout:", | ||
378 | le32_to_cpu(tx->ack_timeout), | ||
379 | accum_tx->ack_timeout, | ||
380 | delta_tx->ack_timeout, max_tx->ack_timeout); | ||
381 | pos += scnprintf(buf + pos, bufsz - pos, | ||
382 | " %-30s %10u %10u %10u %10u\n", | ||
383 | "expected_ack_cnt:", | ||
384 | le32_to_cpu(tx->expected_ack_cnt), | ||
385 | accum_tx->expected_ack_cnt, | ||
386 | delta_tx->expected_ack_cnt, | ||
387 | max_tx->expected_ack_cnt); | ||
388 | pos += scnprintf(buf + pos, bufsz - pos, | ||
389 | " %-30s %10u %10u %10u %10u\n", | ||
390 | "actual_ack_cnt:", | ||
391 | le32_to_cpu(tx->actual_ack_cnt), | ||
392 | accum_tx->actual_ack_cnt, | ||
393 | delta_tx->actual_ack_cnt, | ||
394 | max_tx->actual_ack_cnt); | ||
395 | |||
396 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
397 | kfree(buf); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | ssize_t iwl3945_ucode_general_stats_read(struct file *file, | ||
402 | char __user *user_buf, | ||
403 | size_t count, loff_t *ppos) | ||
404 | { | ||
405 | struct iwl_priv *priv = file->private_data; | ||
406 | int pos = 0; | ||
407 | char *buf; | ||
408 | int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300; | ||
409 | ssize_t ret; | ||
410 | struct iwl39_statistics_general *general, *accum_general; | ||
411 | struct iwl39_statistics_general *delta_general, *max_general; | ||
412 | struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; | ||
413 | struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div; | ||
414 | |||
415 | if (!iwl_is_alive(priv)) | ||
416 | return -EAGAIN; | ||
417 | |||
418 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
419 | if (!buf) { | ||
420 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
421 | return -ENOMEM; | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * The statistic information display here is based on | ||
426 | * the last statistics notification from uCode | ||
427 | * might not reflect the current uCode activity | ||
428 | */ | ||
429 | general = &priv->_3945.statistics.general; | ||
430 | dbg = &priv->_3945.statistics.general.dbg; | ||
431 | div = &priv->_3945.statistics.general.div; | ||
432 | accum_general = &priv->_3945.accum_statistics.general; | ||
433 | delta_general = &priv->_3945.delta_statistics.general; | ||
434 | max_general = &priv->_3945.max_delta.general; | ||
435 | accum_dbg = &priv->_3945.accum_statistics.general.dbg; | ||
436 | delta_dbg = &priv->_3945.delta_statistics.general.dbg; | ||
437 | max_dbg = &priv->_3945.max_delta.general.dbg; | ||
438 | accum_div = &priv->_3945.accum_statistics.general.div; | ||
439 | delta_div = &priv->_3945.delta_statistics.general.div; | ||
440 | max_div = &priv->_3945.max_delta.general.div; | ||
441 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
442 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
443 | "acumulative delta max\n", | ||
444 | "Statistics_General:"); | ||
445 | pos += scnprintf(buf + pos, bufsz - pos, | ||
446 | " %-30s %10u %10u %10u %10u\n", | ||
447 | "burst_check:", | ||
448 | le32_to_cpu(dbg->burst_check), | ||
449 | accum_dbg->burst_check, | ||
450 | delta_dbg->burst_check, max_dbg->burst_check); | ||
451 | pos += scnprintf(buf + pos, bufsz - pos, | ||
452 | " %-30s %10u %10u %10u %10u\n", | ||
453 | "burst_count:", | ||
454 | le32_to_cpu(dbg->burst_count), | ||
455 | accum_dbg->burst_count, | ||
456 | delta_dbg->burst_count, max_dbg->burst_count); | ||
457 | pos += scnprintf(buf + pos, bufsz - pos, | ||
458 | " %-30s %10u %10u %10u %10u\n", | ||
459 | "sleep_time:", | ||
460 | le32_to_cpu(general->sleep_time), | ||
461 | accum_general->sleep_time, | ||
462 | delta_general->sleep_time, max_general->sleep_time); | ||
463 | pos += scnprintf(buf + pos, bufsz - pos, | ||
464 | " %-30s %10u %10u %10u %10u\n", | ||
465 | "slots_out:", | ||
466 | le32_to_cpu(general->slots_out), | ||
467 | accum_general->slots_out, | ||
468 | delta_general->slots_out, max_general->slots_out); | ||
469 | pos += scnprintf(buf + pos, bufsz - pos, | ||
470 | " %-30s %10u %10u %10u %10u\n", | ||
471 | "slots_idle:", | ||
472 | le32_to_cpu(general->slots_idle), | ||
473 | accum_general->slots_idle, | ||
474 | delta_general->slots_idle, max_general->slots_idle); | ||
475 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | ||
476 | le32_to_cpu(general->ttl_timestamp)); | ||
477 | pos += scnprintf(buf + pos, bufsz - pos, | ||
478 | " %-30s %10u %10u %10u %10u\n", | ||
479 | "tx_on_a:", | ||
480 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, | ||
481 | delta_div->tx_on_a, max_div->tx_on_a); | ||
482 | pos += scnprintf(buf + pos, bufsz - pos, | ||
483 | " %-30s %10u %10u %10u %10u\n", | ||
484 | "tx_on_b:", | ||
485 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, | ||
486 | delta_div->tx_on_b, max_div->tx_on_b); | ||
487 | pos += scnprintf(buf + pos, bufsz - pos, | ||
488 | " %-30s %10u %10u %10u %10u\n", | ||
489 | "exec_time:", | ||
490 | le32_to_cpu(div->exec_time), accum_div->exec_time, | ||
491 | delta_div->exec_time, max_div->exec_time); | ||
492 | pos += scnprintf(buf + pos, bufsz - pos, | ||
493 | " %-30s %10u %10u %10u %10u\n", | ||
494 | "probe_time:", | ||
495 | le32_to_cpu(div->probe_time), accum_div->probe_time, | ||
496 | delta_div->probe_time, max_div->probe_time); | ||
497 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
498 | kfree(buf); | ||
499 | return ret; | ||
500 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h new file mode 100644 index 000000000000..70809c53c215 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include "iwl-dev.h" | ||
30 | #include "iwl-core.h" | ||
31 | #include "iwl-debug.h" | ||
32 | |||
33 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
34 | ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, | ||
35 | size_t count, loff_t *ppos); | ||
36 | ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf, | ||
37 | size_t count, loff_t *ppos); | ||
38 | ssize_t iwl3945_ucode_general_stats_read(struct file *file, | ||
39 | char __user *user_buf, size_t count, | ||
40 | loff_t *ppos); | ||
41 | #else | ||
42 | static ssize_t iwl3945_ucode_rx_stats_read(struct file *file, | ||
43 | char __user *user_buf, size_t count, | ||
44 | loff_t *ppos) | ||
45 | { | ||
46 | return 0; | ||
47 | } | ||
48 | static ssize_t iwl3945_ucode_tx_stats_read(struct file *file, | ||
49 | char __user *user_buf, size_t count, | ||
50 | loff_t *ppos) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | static ssize_t iwl3945_ucode_general_stats_read(struct file *file, | ||
55 | char __user *user_buf, | ||
56 | size_t count, loff_t *ppos) | ||
57 | { | ||
58 | return 0; | ||
59 | } | ||
60 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 3a876a8ece38..91bcb4e3cdfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -71,13 +71,11 @@ | |||
71 | 71 | ||
72 | #include "iwl-eeprom.h" | 72 | #include "iwl-eeprom.h" |
73 | 73 | ||
74 | /* Time constants */ | ||
75 | #define SHORT_SLOT_TIME 9 | ||
76 | #define LONG_SLOT_TIME 20 | ||
77 | |||
78 | /* RSSI to dBm */ | 74 | /* RSSI to dBm */ |
79 | #define IWL39_RSSI_OFFSET 95 | 75 | #define IWL39_RSSI_OFFSET 95 |
80 | 76 | ||
77 | #define IWL_DEFAULT_TX_POWER 0x0F | ||
78 | |||
81 | /* | 79 | /* |
82 | * EEPROM related constants, enums, and structures. | 80 | * EEPROM related constants, enums, and structures. |
83 | */ | 81 | */ |
@@ -228,7 +226,6 @@ struct iwl3945_eeprom { | |||
228 | 226 | ||
229 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ | 227 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ |
230 | #define IWL39_NUM_QUEUES 5 | 228 | #define IWL39_NUM_QUEUES 5 |
231 | #define IWL_NUM_SCAN_RATES (2) | ||
232 | 229 | ||
233 | #define IWL_DEFAULT_TX_RETRY 15 | 230 | #define IWL_DEFAULT_TX_RETRY 15 |
234 | 231 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 902c4d4293e9..8e84a08ff951 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -330,16 +330,25 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, | |||
330 | 330 | ||
331 | } | 331 | } |
332 | 332 | ||
333 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | 333 | /* |
334 | struct ieee80211_sta *sta, void *priv_sta) | 334 | * Called after adding a new station to initialize rate scaling |
335 | */ | ||
336 | void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) | ||
335 | { | 337 | { |
336 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 338 | struct ieee80211_hw *hw = priv->hw; |
337 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 339 | struct ieee80211_conf *conf = &priv->hw->conf; |
340 | struct iwl3945_sta_priv *psta; | ||
341 | struct iwl3945_rs_sta *rs_sta; | ||
342 | struct ieee80211_supported_band *sband; | ||
338 | int i; | 343 | int i; |
339 | 344 | ||
340 | IWL_DEBUG_RATE(priv, "enter\n"); | 345 | IWL_DEBUG_INFO(priv, "enter\n"); |
346 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
347 | goto out; | ||
341 | 348 | ||
342 | spin_lock_init(&rs_sta->lock); | 349 | psta = (struct iwl3945_sta_priv *) sta->drv_priv; |
350 | rs_sta = &psta->rs_sta; | ||
351 | sband = hw->wiphy->bands[conf->channel->band]; | ||
343 | 352 | ||
344 | rs_sta->priv = priv; | 353 | rs_sta->priv = priv; |
345 | 354 | ||
@@ -352,9 +361,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
352 | rs_sta->last_flush = jiffies; | 361 | rs_sta->last_flush = jiffies; |
353 | rs_sta->flush_time = IWL_RATE_FLUSH; | 362 | rs_sta->flush_time = IWL_RATE_FLUSH; |
354 | rs_sta->last_tx_packets = 0; | 363 | rs_sta->last_tx_packets = 0; |
355 | rs_sta->ibss_sta_added = 0; | ||
356 | 364 | ||
357 | init_timer(&rs_sta->rate_scale_flush); | ||
358 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; | 365 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; |
359 | rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; | 366 | rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; |
360 | 367 | ||
@@ -373,16 +380,18 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
373 | } | 380 | } |
374 | } | 381 | } |
375 | 382 | ||
376 | priv->sta_supp_rates = sta->supp_rates[sband->band]; | 383 | priv->_3945.sta_supp_rates = sta->supp_rates[sband->band]; |
377 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ | 384 | /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ |
378 | if (sband->band == IEEE80211_BAND_5GHZ) { | 385 | if (sband->band == IEEE80211_BAND_5GHZ) { |
379 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 386 | rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
380 | priv->sta_supp_rates = priv->sta_supp_rates << | 387 | priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates << |
381 | IWL_FIRST_OFDM_RATE; | 388 | IWL_FIRST_OFDM_RATE; |
382 | } | 389 | } |
383 | 390 | ||
391 | out: | ||
392 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
384 | 393 | ||
385 | IWL_DEBUG_RATE(priv, "leave\n"); | 394 | IWL_DEBUG_INFO(priv, "leave\n"); |
386 | } | 395 | } |
387 | 396 | ||
388 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 397 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
@@ -406,6 +415,9 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) | |||
406 | 415 | ||
407 | rs_sta = &psta->rs_sta; | 416 | rs_sta = &psta->rs_sta; |
408 | 417 | ||
418 | spin_lock_init(&rs_sta->lock); | ||
419 | init_timer(&rs_sta->rate_scale_flush); | ||
420 | |||
409 | IWL_DEBUG_RATE(priv, "leave\n"); | 421 | IWL_DEBUG_RATE(priv, "leave\n"); |
410 | 422 | ||
411 | return rs_sta; | 423 | return rs_sta; |
@@ -414,13 +426,14 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) | |||
414 | static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, | 426 | static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, |
415 | void *priv_sta) | 427 | void *priv_sta) |
416 | { | 428 | { |
417 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | 429 | struct iwl3945_rs_sta *rs_sta = priv_sta; |
418 | struct iwl3945_rs_sta *rs_sta = &psta->rs_sta; | ||
419 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | ||
420 | 430 | ||
421 | IWL_DEBUG_RATE(priv, "enter\n"); | 431 | /* |
432 | * Be careful not to use any members of iwl3945_rs_sta (like trying | ||
433 | * to use iwl_priv to print out debugging) since it may not be fully | ||
434 | * initialized at this point. | ||
435 | */ | ||
422 | del_timer_sync(&rs_sta->rate_scale_flush); | 436 | del_timer_sync(&rs_sta->rate_scale_flush); |
423 | IWL_DEBUG_RATE(priv, "leave\n"); | ||
424 | } | 437 | } |
425 | 438 | ||
426 | 439 | ||
@@ -459,6 +472,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband | |||
459 | return; | 472 | return; |
460 | } | 473 | } |
461 | 474 | ||
475 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
476 | if (!rs_sta->priv) { | ||
477 | IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n"); | ||
478 | return; | ||
479 | } | ||
480 | |||
481 | |||
462 | rs_sta->tx_packets++; | 482 | rs_sta->tx_packets++; |
463 | 483 | ||
464 | scale_rate_index = first_index; | 484 | scale_rate_index = first_index; |
@@ -525,8 +545,6 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband | |||
525 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 545 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
526 | 546 | ||
527 | IWL_DEBUG_RATE(priv, "leave\n"); | 547 | IWL_DEBUG_RATE(priv, "leave\n"); |
528 | |||
529 | return; | ||
530 | } | 548 | } |
531 | 549 | ||
532 | static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, | 550 | static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, |
@@ -626,14 +644,19 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
626 | u32 fail_count; | 644 | u32 fail_count; |
627 | s8 scale_action = 0; | 645 | s8 scale_action = 0; |
628 | unsigned long flags; | 646 | unsigned long flags; |
629 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
630 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; | 647 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; |
631 | s8 max_rate_idx = -1; | 648 | s8 max_rate_idx = -1; |
632 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 649 | struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; |
633 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 650 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
634 | 651 | ||
635 | IWL_DEBUG_RATE(priv, "enter\n"); | 652 | IWL_DEBUG_RATE(priv, "enter\n"); |
636 | 653 | ||
654 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
655 | if (rs_sta && !rs_sta->priv) { | ||
656 | IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n"); | ||
657 | priv_sta = NULL; | ||
658 | } | ||
659 | |||
637 | if (rate_control_send_low(sta, priv_sta, txrc)) | 660 | if (rate_control_send_low(sta, priv_sta, txrc)) |
638 | return; | 661 | return; |
639 | 662 | ||
@@ -651,20 +674,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
651 | if (sband->band == IEEE80211_BAND_5GHZ) | 674 | if (sband->band == IEEE80211_BAND_5GHZ) |
652 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; | 675 | rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; |
653 | 676 | ||
654 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
655 | !rs_sta->ibss_sta_added) { | ||
656 | u8 sta_id = iwl_find_station(priv, hdr->addr1); | ||
657 | |||
658 | if (sta_id == IWL_INVALID_STATION) { | ||
659 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", | ||
660 | hdr->addr1); | ||
661 | sta_id = iwl_add_station(priv, hdr->addr1, false, | ||
662 | CMD_ASYNC, NULL); | ||
663 | } | ||
664 | if (sta_id != IWL_INVALID_STATION) | ||
665 | rs_sta->ibss_sta_added = 1; | ||
666 | } | ||
667 | |||
668 | spin_lock_irqsave(&rs_sta->lock, flags); | 677 | spin_lock_irqsave(&rs_sta->lock, flags); |
669 | 678 | ||
670 | /* for recent assoc, choose best rate regarding | 679 | /* for recent assoc, choose best rate regarding |
@@ -884,12 +893,22 @@ static void iwl3945_remove_debugfs(void *priv, void *priv_sta) | |||
884 | } | 893 | } |
885 | #endif | 894 | #endif |
886 | 895 | ||
896 | /* | ||
897 | * Initialization of rate scaling information is done by driver after | ||
898 | * the station is added. Since mac80211 calls this function before a | ||
899 | * station is added we ignore it. | ||
900 | */ | ||
901 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | ||
902 | struct ieee80211_sta *sta, void *priv_sta) | ||
903 | { | ||
904 | } | ||
905 | |||
887 | static struct rate_control_ops rs_ops = { | 906 | static struct rate_control_ops rs_ops = { |
888 | .module = NULL, | 907 | .module = NULL, |
889 | .name = RS_NAME, | 908 | .name = RS_NAME, |
890 | .tx_status = rs_tx_status, | 909 | .tx_status = rs_tx_status, |
891 | .get_rate = rs_get_rate, | 910 | .get_rate = rs_get_rate, |
892 | .rate_init = rs_rate_init, | 911 | .rate_init = rs_rate_init_stub, |
893 | .alloc = rs_alloc, | 912 | .alloc = rs_alloc, |
894 | .free = rs_free, | 913 | .free = rs_free, |
895 | .alloc_sta = rs_alloc_sta, | 914 | .alloc_sta = rs_alloc_sta, |
@@ -900,7 +919,6 @@ static struct rate_control_ops rs_ops = { | |||
900 | #endif | 919 | #endif |
901 | 920 | ||
902 | }; | 921 | }; |
903 | |||
904 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | 922 | void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) |
905 | { | 923 | { |
906 | struct iwl_priv *priv = hw->priv; | 924 | struct iwl_priv *priv = hw->priv; |
@@ -917,6 +935,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
917 | sta = ieee80211_find_sta(priv->vif, | 935 | sta = ieee80211_find_sta(priv->vif, |
918 | priv->stations[sta_id].sta.sta.addr); | 936 | priv->stations[sta_id].sta.sta.addr); |
919 | if (!sta) { | 937 | if (!sta) { |
938 | IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n"); | ||
920 | rcu_read_unlock(); | 939 | rcu_read_unlock(); |
921 | return; | 940 | return; |
922 | } | 941 | } |
@@ -947,7 +966,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
947 | 966 | ||
948 | spin_unlock_irqrestore(&rs_sta->lock, flags); | 967 | spin_unlock_irqrestore(&rs_sta->lock, flags); |
949 | 968 | ||
950 | rssi = priv->last_rx_rssi; | 969 | rssi = priv->_3945.last_rx_rssi; |
951 | if (rssi == 0) | 970 | if (rssi == 0) |
952 | rssi = IWL_MIN_RSSI_VAL; | 971 | rssi = IWL_MIN_RSSI_VAL; |
953 | 972 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0728054a22d4..068f7f8435c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include "iwl-helpers.h" | 50 | #include "iwl-helpers.h" |
51 | #include "iwl-led.h" | 51 | #include "iwl-led.h" |
52 | #include "iwl-3945-led.h" | 52 | #include "iwl-3945-led.h" |
53 | #include "iwl-3945-debugfs.h" | ||
53 | 54 | ||
54 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ | 55 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ |
55 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 56 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
@@ -192,12 +193,12 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) | |||
192 | } | 193 | } |
193 | 194 | ||
194 | #ifdef CONFIG_IWLWIFI_DEBUG | 195 | #ifdef CONFIG_IWLWIFI_DEBUG |
195 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 196 | #define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x |
196 | 197 | ||
197 | static const char *iwl3945_get_tx_fail_reason(u32 status) | 198 | static const char *iwl3945_get_tx_fail_reason(u32 status) |
198 | { | 199 | { |
199 | switch (status & TX_STATUS_MSK) { | 200 | switch (status & TX_STATUS_MSK) { |
200 | case TX_STATUS_SUCCESS: | 201 | case TX_3945_STATUS_SUCCESS: |
201 | return "SUCCESS"; | 202 | return "SUCCESS"; |
202 | TX_STATUS_ENTRY(SHORT_LIMIT); | 203 | TX_STATUS_ENTRY(SHORT_LIMIT); |
203 | TX_STATUS_ENTRY(LONG_LIMIT); | 204 | TX_STATUS_ENTRY(LONG_LIMIT); |
@@ -243,7 +244,7 @@ int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) | |||
243 | next_rate = IWL_RATE_6M_INDEX; | 244 | next_rate = IWL_RATE_6M_INDEX; |
244 | break; | 245 | break; |
245 | case IEEE80211_BAND_2GHZ: | 246 | case IEEE80211_BAND_2GHZ: |
246 | if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && | 247 | if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && |
247 | iwl_is_associated(priv)) { | 248 | iwl_is_associated(priv)) { |
248 | if (rate == IWL_RATE_11M_INDEX) | 249 | if (rate == IWL_RATE_11M_INDEX) |
249 | next_rate = IWL_RATE_5M_INDEX; | 250 | next_rate = IWL_RATE_5M_INDEX; |
@@ -293,7 +294,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | |||
293 | * iwl3945_rx_reply_tx - Handle Tx response | 294 | * iwl3945_rx_reply_tx - Handle Tx response |
294 | */ | 295 | */ |
295 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | 296 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, |
296 | struct iwl_rx_mem_buffer *rxb) | 297 | struct iwl_rx_mem_buffer *rxb) |
297 | { | 298 | { |
298 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 299 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
299 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 300 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
@@ -351,18 +352,143 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
351 | * RX handler implementations | 352 | * RX handler implementations |
352 | * | 353 | * |
353 | *****************************************************************************/ | 354 | *****************************************************************************/ |
355 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
356 | /* | ||
357 | * based on the assumption of all statistics counter are in DWORD | ||
358 | * FIXME: This function is for debugging, do not deal with | ||
359 | * the case of counters roll-over. | ||
360 | */ | ||
361 | static void iwl3945_accumulative_statistics(struct iwl_priv *priv, | ||
362 | __le32 *stats) | ||
363 | { | ||
364 | int i; | ||
365 | __le32 *prev_stats; | ||
366 | u32 *accum_stats; | ||
367 | u32 *delta, *max_delta; | ||
368 | |||
369 | prev_stats = (__le32 *)&priv->_3945.statistics; | ||
370 | accum_stats = (u32 *)&priv->_3945.accum_statistics; | ||
371 | delta = (u32 *)&priv->_3945.delta_statistics; | ||
372 | max_delta = (u32 *)&priv->_3945.max_delta; | ||
373 | |||
374 | for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics); | ||
375 | i += sizeof(__le32), stats++, prev_stats++, delta++, | ||
376 | max_delta++, accum_stats++) { | ||
377 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { | ||
378 | *delta = (le32_to_cpu(*stats) - | ||
379 | le32_to_cpu(*prev_stats)); | ||
380 | *accum_stats += *delta; | ||
381 | if (*delta > *max_delta) | ||
382 | *max_delta = *delta; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | /* reset accumulative statistics for "no-counter" type statistics */ | ||
387 | priv->_3945.accum_statistics.general.temperature = | ||
388 | priv->_3945.statistics.general.temperature; | ||
389 | priv->_3945.accum_statistics.general.ttl_timestamp = | ||
390 | priv->_3945.statistics.general.ttl_timestamp; | ||
391 | } | ||
392 | #endif | ||
393 | |||
394 | /** | ||
395 | * iwl3945_good_plcp_health - checks for plcp error. | ||
396 | * | ||
397 | * When the plcp error is exceeding the thresholds, reset the radio | ||
398 | * to improve the throughput. | ||
399 | */ | ||
400 | static bool iwl3945_good_plcp_health(struct iwl_priv *priv, | ||
401 | struct iwl_rx_packet *pkt) | ||
402 | { | ||
403 | bool rc = true; | ||
404 | struct iwl3945_notif_statistics current_stat; | ||
405 | int combined_plcp_delta; | ||
406 | unsigned int plcp_msec; | ||
407 | unsigned long plcp_received_jiffies; | ||
408 | |||
409 | memcpy(¤t_stat, pkt->u.raw, sizeof(struct | ||
410 | iwl3945_notif_statistics)); | ||
411 | /* | ||
412 | * check for plcp_err and trigger radio reset if it exceeds | ||
413 | * the plcp error threshold plcp_delta. | ||
414 | */ | ||
415 | plcp_received_jiffies = jiffies; | ||
416 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
417 | (long) priv->plcp_jiffies); | ||
418 | priv->plcp_jiffies = plcp_received_jiffies; | ||
419 | /* | ||
420 | * check to make sure plcp_msec is not 0 to prevent division | ||
421 | * by zero. | ||
422 | */ | ||
423 | if (plcp_msec) { | ||
424 | combined_plcp_delta = | ||
425 | (le32_to_cpu(current_stat.rx.ofdm.plcp_err) - | ||
426 | le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err)); | ||
427 | |||
428 | if ((combined_plcp_delta > 0) && | ||
429 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
430 | priv->cfg->plcp_delta_threshold) { | ||
431 | /* | ||
432 | * if plcp_err exceed the threshold, the following | ||
433 | * data is printed in csv format: | ||
434 | * Text: plcp_err exceeded %d, | ||
435 | * Received ofdm.plcp_err, | ||
436 | * Current ofdm.plcp_err, | ||
437 | * combined_plcp_delta, | ||
438 | * plcp_msec | ||
439 | */ | ||
440 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " | ||
441 | "%u, %d, %u mSecs\n", | ||
442 | priv->cfg->plcp_delta_threshold, | ||
443 | le32_to_cpu(current_stat.rx.ofdm.plcp_err), | ||
444 | combined_plcp_delta, plcp_msec); | ||
445 | /* | ||
446 | * Reset the RF radio due to the high plcp | ||
447 | * error rate | ||
448 | */ | ||
449 | rc = false; | ||
450 | } | ||
451 | } | ||
452 | return rc; | ||
453 | } | ||
354 | 454 | ||
355 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 455 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
356 | struct iwl_rx_mem_buffer *rxb) | 456 | struct iwl_rx_mem_buffer *rxb) |
357 | { | 457 | { |
358 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 458 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
459 | |||
359 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 460 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
360 | (int)sizeof(struct iwl3945_notif_statistics), | 461 | (int)sizeof(struct iwl3945_notif_statistics), |
361 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 462 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
463 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
464 | iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); | ||
465 | #endif | ||
466 | iwl_recover_from_statistics(priv, pkt); | ||
467 | |||
468 | memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics)); | ||
469 | } | ||
470 | |||
471 | void iwl3945_reply_statistics(struct iwl_priv *priv, | ||
472 | struct iwl_rx_mem_buffer *rxb) | ||
473 | { | ||
474 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
475 | __le32 *flag = (__le32 *)&pkt->u.raw; | ||
362 | 476 | ||
363 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 477 | if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { |
478 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
479 | memset(&priv->_3945.accum_statistics, 0, | ||
480 | sizeof(struct iwl3945_notif_statistics)); | ||
481 | memset(&priv->_3945.delta_statistics, 0, | ||
482 | sizeof(struct iwl3945_notif_statistics)); | ||
483 | memset(&priv->_3945.max_delta, 0, | ||
484 | sizeof(struct iwl3945_notif_statistics)); | ||
485 | #endif | ||
486 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | ||
487 | } | ||
488 | iwl3945_hw_rx_statistics(priv, rxb); | ||
364 | } | 489 | } |
365 | 490 | ||
491 | |||
366 | /****************************************************************************** | 492 | /****************************************************************************** |
367 | * | 493 | * |
368 | * Misc. internal state and helper functions | 494 | * Misc. internal state and helper functions |
@@ -487,7 +613,7 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, | |||
487 | * but you can hack it to show more, if you'd like to. */ | 613 | * but you can hack it to show more, if you'd like to. */ |
488 | if (dataframe) | 614 | if (dataframe) |
489 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | 615 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " |
490 | "len=%u, rssi=%d, chnl=%d, rate=%d, \n", | 616 | "len=%u, rssi=%d, chnl=%d, rate=%d,\n", |
491 | title, le16_to_cpu(fc), header->addr1[5], | 617 | title, le16_to_cpu(fc), header->addr1[5], |
492 | length, rssi, channel, rate); | 618 | length, rssi, channel, rate); |
493 | else { | 619 | else { |
@@ -549,7 +675,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
549 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 675 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
550 | u16 len = le16_to_cpu(rx_hdr->len); | 676 | u16 len = le16_to_cpu(rx_hdr->len); |
551 | struct sk_buff *skb; | 677 | struct sk_buff *skb; |
552 | int ret; | ||
553 | __le16 fc = hdr->frame_control; | 678 | __le16 fc = hdr->frame_control; |
554 | 679 | ||
555 | /* We received data from the HW, so stop the watchdog */ | 680 | /* We received data from the HW, so stop the watchdog */ |
@@ -566,9 +691,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
566 | return; | 691 | return; |
567 | } | 692 | } |
568 | 693 | ||
569 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | 694 | skb = dev_alloc_skb(128); |
570 | if (!skb) { | 695 | if (!skb) { |
571 | IWL_ERR(priv, "alloc_skb failed\n"); | 696 | IWL_ERR(priv, "dev_alloc_skb failed\n"); |
572 | return; | 697 | return; |
573 | } | 698 | } |
574 | 699 | ||
@@ -577,37 +702,13 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
577 | (struct ieee80211_hdr *)rxb_addr(rxb), | 702 | (struct ieee80211_hdr *)rxb_addr(rxb), |
578 | le32_to_cpu(rx_end->status), stats); | 703 | le32_to_cpu(rx_end->status), stats); |
579 | 704 | ||
580 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
581 | skb_add_rx_frag(skb, 0, rxb->page, | 705 | skb_add_rx_frag(skb, 0, rxb->page, |
582 | (void *)rx_hdr->payload - (void *)pkt, len); | 706 | (void *)rx_hdr->payload - (void *)pkt, len); |
583 | 707 | ||
584 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
585 | * linear SKB for management frame and data frame requires | ||
586 | * software decryption or software defragementation. */ | ||
587 | if (ieee80211_is_mgmt(fc) || | ||
588 | ieee80211_has_protected(fc) || | ||
589 | ieee80211_has_morefrags(fc) || | ||
590 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) | ||
591 | ret = skb_linearize(skb); | ||
592 | else | ||
593 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
594 | 0 : -ENOMEM; | ||
595 | |||
596 | if (ret) { | ||
597 | kfree_skb(skb); | ||
598 | goto out; | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * XXX: We cannot touch the page and its virtual memory (pkt) after | ||
603 | * here. It might have already been freed by the above skb change. | ||
604 | */ | ||
605 | |||
606 | iwl_update_stats(priv, false, fc, len); | 708 | iwl_update_stats(priv, false, fc, len); |
607 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | 709 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); |
608 | 710 | ||
609 | ieee80211_rx(priv->hw, skb); | 711 | ieee80211_rx(priv->hw, skb); |
610 | out: | ||
611 | priv->alloc_rxb_page--; | 712 | priv->alloc_rxb_page--; |
612 | rxb->page = NULL; | 713 | rxb->page = NULL; |
613 | } | 714 | } |
@@ -623,9 +724,8 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
623 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 724 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
624 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 725 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
625 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 726 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
626 | int snr; | 727 | u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg); |
627 | u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); | 728 | u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff); |
628 | u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
629 | u8 network_packet; | 729 | u8 network_packet; |
630 | 730 | ||
631 | rx_status.flag = 0; | 731 | rx_status.flag = 0; |
@@ -663,53 +763,29 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
663 | /* Convert 3945's rssi indicator to dBm */ | 763 | /* Convert 3945's rssi indicator to dBm */ |
664 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; | 764 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; |
665 | 765 | ||
666 | /* Set default noise value to -127 */ | 766 | IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n", |
667 | if (priv->last_rx_noise == 0) | 767 | rx_status.signal, rx_stats_sig_avg, |
668 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 768 | rx_stats_noise_diff); |
669 | |||
670 | /* 3945 provides noise info for OFDM frames only. | ||
671 | * sig_avg and noise_diff are measured by the 3945's digital signal | ||
672 | * processor (DSP), and indicate linear levels of signal level and | ||
673 | * distortion/noise within the packet preamble after | ||
674 | * automatic gain control (AGC). sig_avg should stay fairly | ||
675 | * constant if the radio's AGC is working well. | ||
676 | * Since these values are linear (not dB or dBm), linear | ||
677 | * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). | ||
678 | * Convert linear SNR to dB SNR, then subtract that from rssi dBm | ||
679 | * to obtain noise level in dBm. | ||
680 | * Calculate rx_status.signal (quality indicator in %) based on SNR. */ | ||
681 | if (rx_stats_noise_diff) { | ||
682 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | ||
683 | rx_status.noise = rx_status.signal - | ||
684 | iwl3945_calc_db_from_ratio(snr); | ||
685 | } else { | ||
686 | rx_status.noise = priv->last_rx_noise; | ||
687 | } | ||
688 | |||
689 | |||
690 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", | ||
691 | rx_status.signal, rx_status.noise, | ||
692 | rx_stats_sig_avg, rx_stats_noise_diff); | ||
693 | 769 | ||
694 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 770 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
695 | 771 | ||
696 | network_packet = iwl3945_is_network_packet(priv, header); | 772 | network_packet = iwl3945_is_network_packet(priv, header); |
697 | 773 | ||
698 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", | 774 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n", |
699 | network_packet ? '*' : ' ', | 775 | network_packet ? '*' : ' ', |
700 | le16_to_cpu(rx_hdr->channel), | 776 | le16_to_cpu(rx_hdr->channel), |
701 | rx_status.signal, rx_status.signal, | 777 | rx_status.signal, rx_status.signal, |
702 | rx_status.noise, rx_status.rate_idx); | 778 | rx_status.rate_idx); |
703 | 779 | ||
704 | /* Set "1" to report good data frames in groups of 100 */ | 780 | /* Set "1" to report good data frames in groups of 100 */ |
705 | iwl3945_dbg_report_frame(priv, pkt, header, 1); | 781 | iwl3945_dbg_report_frame(priv, pkt, header, 1); |
706 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); | 782 | iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); |
707 | 783 | ||
708 | if (network_packet) { | 784 | if (network_packet) { |
709 | priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); | 785 | priv->_3945.last_beacon_time = |
710 | priv->last_tsf = le64_to_cpu(rx_end->timestamp); | 786 | le32_to_cpu(rx_end->beacon_timestamp); |
711 | priv->last_rx_rssi = rx_status.signal; | 787 | priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); |
712 | priv->last_rx_noise = rx_status.noise; | 788 | priv->_3945.last_rx_rssi = rx_status.signal; |
713 | } | 789 | } |
714 | 790 | ||
715 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); | 791 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); |
@@ -871,7 +947,8 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
871 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); | 947 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
872 | } | 948 | } |
873 | 949 | ||
874 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) | 950 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, |
951 | u16 tx_rate, u8 flags) | ||
875 | { | 952 | { |
876 | unsigned long flags_spin; | 953 | unsigned long flags_spin; |
877 | struct iwl_station_entry *station; | 954 | struct iwl_station_entry *station; |
@@ -957,7 +1034,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv) | |||
957 | iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); | 1034 | iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); |
958 | 1035 | ||
959 | iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, | 1036 | iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, |
960 | priv->shared_phys); | 1037 | priv->_3945.shared_phys); |
961 | 1038 | ||
962 | iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, | 1039 | iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, |
963 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | | 1040 | FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | |
@@ -1049,7 +1126,7 @@ static void iwl3945_nic_config(struct iwl_priv *priv) | |||
1049 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); | 1126 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); |
1050 | 1127 | ||
1051 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) | 1128 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) |
1052 | IWL_DEBUG_INFO(priv, "RTP type \n"); | 1129 | IWL_DEBUG_INFO(priv, "RTP type\n"); |
1053 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { | 1130 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { |
1054 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); | 1131 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); |
1055 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1132 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
@@ -1607,7 +1684,7 @@ static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv, | |||
1607 | int power; | 1684 | int power; |
1608 | 1685 | ||
1609 | /* Get this chnlgrp's rate-to-max/clip-powers table */ | 1686 | /* Get this chnlgrp's rate-to-max/clip-powers table */ |
1610 | clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; | 1687 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; |
1611 | 1688 | ||
1612 | /* Get this channel's rate-to-current-power settings table */ | 1689 | /* Get this channel's rate-to-current-power settings table */ |
1613 | power_info = ch_info->power_info; | 1690 | power_info = ch_info->power_info; |
@@ -1701,6 +1778,11 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) | |||
1701 | int ref_temp; | 1778 | int ref_temp; |
1702 | int temperature = priv->temperature; | 1779 | int temperature = priv->temperature; |
1703 | 1780 | ||
1781 | if (priv->disable_tx_power_cal || | ||
1782 | test_bit(STATUS_SCANNING, &priv->status)) { | ||
1783 | /* do not perform tx power calibration */ | ||
1784 | return 0; | ||
1785 | } | ||
1704 | /* set up new Tx power info for each and every channel, 2.4 and 5.x */ | 1786 | /* set up new Tx power info for each and every channel, 2.4 and 5.x */ |
1705 | for (i = 0; i < priv->channel_count; i++) { | 1787 | for (i = 0; i < priv->channel_count; i++) { |
1706 | ch_info = &priv->channel_info[i]; | 1788 | ch_info = &priv->channel_info[i]; |
@@ -1733,7 +1815,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) | |||
1733 | } | 1815 | } |
1734 | 1816 | ||
1735 | /* Get this chnlgrp's rate-to-max/clip-powers table */ | 1817 | /* Get this chnlgrp's rate-to-max/clip-powers table */ |
1736 | clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; | 1818 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; |
1737 | 1819 | ||
1738 | /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ | 1820 | /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ |
1739 | for (scan_tbl_index = 0; | 1821 | for (scan_tbl_index = 0; |
@@ -1911,6 +1993,8 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1911 | "configuration (%d).\n", rc); | 1993 | "configuration (%d).\n", rc); |
1912 | return rc; | 1994 | return rc; |
1913 | } | 1995 | } |
1996 | iwl_clear_ucode_stations(priv); | ||
1997 | iwl_restore_stations(priv); | ||
1914 | } | 1998 | } |
1915 | 1999 | ||
1916 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | 2000 | IWL_DEBUG_INFO(priv, "Sending RXON\n" |
@@ -1941,7 +2025,10 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1941 | 2025 | ||
1942 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | 2026 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); |
1943 | 2027 | ||
1944 | iwl_clear_stations_table(priv); | 2028 | if (!new_assoc) { |
2029 | iwl_clear_ucode_stations(priv); | ||
2030 | iwl_restore_stations(priv); | ||
2031 | } | ||
1945 | 2032 | ||
1946 | /* If we issue a new RXON command which required a tune then we must | 2033 | /* If we issue a new RXON command which required a tune then we must |
1947 | * send a new TXPOWER command or we won't be able to Tx any frames */ | 2034 | * send a new TXPOWER command or we won't be able to Tx any frames */ |
@@ -1951,19 +2038,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1951 | return rc; | 2038 | return rc; |
1952 | } | 2039 | } |
1953 | 2040 | ||
1954 | /* Add the broadcast address so we can send broadcast frames */ | ||
1955 | priv->cfg->ops->lib->add_bcast_station(priv); | ||
1956 | |||
1957 | /* If we have set the ASSOC_MSK and we are in BSS mode then | ||
1958 | * add the IWL_AP_ID to the station rate table */ | ||
1959 | if (iwl_is_associated(priv) && | ||
1960 | (priv->iw_mode == NL80211_IFTYPE_STATION)) | ||
1961 | if (iwl_add_station(priv, priv->active_rxon.bssid_addr, | ||
1962 | true, CMD_SYNC, NULL) == IWL_INVALID_STATION) { | ||
1963 | IWL_ERR(priv, "Error adding AP address for transmit\n"); | ||
1964 | return -EIO; | ||
1965 | } | ||
1966 | |||
1967 | /* Init the hardware's rate fallback order based on the band */ | 2041 | /* Init the hardware's rate fallback order based on the band */ |
1968 | rc = iwl3945_init_hw_rate_table(priv); | 2042 | rc = iwl3945_init_hw_rate_table(priv); |
1969 | if (rc) { | 2043 | if (rc) { |
@@ -1998,13 +2072,13 @@ void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) | |||
1998 | 2072 | ||
1999 | reschedule: | 2073 | reschedule: |
2000 | queue_delayed_work(priv->workqueue, | 2074 | queue_delayed_work(priv->workqueue, |
2001 | &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ); | 2075 | &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ); |
2002 | } | 2076 | } |
2003 | 2077 | ||
2004 | static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) | 2078 | static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) |
2005 | { | 2079 | { |
2006 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 2080 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
2007 | thermal_periodic.work); | 2081 | _3945.thermal_periodic.work); |
2008 | 2082 | ||
2009 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2083 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2010 | return; | 2084 | return; |
@@ -2140,7 +2214,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) | |||
2140 | * power peaks, without too much distortion (clipping). | 2214 | * power peaks, without too much distortion (clipping). |
2141 | */ | 2215 | */ |
2142 | /* we'll fill in this array with h/w max power levels */ | 2216 | /* we'll fill in this array with h/w max power levels */ |
2143 | clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers; | 2217 | clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers; |
2144 | 2218 | ||
2145 | /* divide factory saturation power by 2 to find -3dB level */ | 2219 | /* divide factory saturation power by 2 to find -3dB level */ |
2146 | satur_pwr = (s8) (group->saturation_power >> 1); | 2220 | satur_pwr = (s8) (group->saturation_power >> 1); |
@@ -2224,7 +2298,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) | |||
2224 | iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); | 2298 | iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); |
2225 | 2299 | ||
2226 | /* Get this chnlgrp's rate->max/clip-powers table */ | 2300 | /* Get this chnlgrp's rate->max/clip-powers table */ |
2227 | clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; | 2301 | clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers; |
2228 | 2302 | ||
2229 | /* calculate power index *adjustment* value according to | 2303 | /* calculate power index *adjustment* value according to |
2230 | * diff between current temperature and factory temperature */ | 2304 | * diff between current temperature and factory temperature */ |
@@ -2332,7 +2406,7 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
2332 | { | 2406 | { |
2333 | int txq_id = txq->q.id; | 2407 | int txq_id = txq->q.id; |
2334 | 2408 | ||
2335 | struct iwl3945_shared *shared_data = priv->shared_virt; | 2409 | struct iwl3945_shared *shared_data = priv->_3945.shared_virt; |
2336 | 2410 | ||
2337 | shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); | 2411 | shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); |
2338 | 2412 | ||
@@ -2385,6 +2459,30 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
2385 | return (u16)sizeof(struct iwl3945_addsta_cmd); | 2459 | return (u16)sizeof(struct iwl3945_addsta_cmd); |
2386 | } | 2460 | } |
2387 | 2461 | ||
2462 | static int iwl3945_manage_ibss_station(struct iwl_priv *priv, | ||
2463 | struct ieee80211_vif *vif, bool add) | ||
2464 | { | ||
2465 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
2466 | int ret; | ||
2467 | |||
2468 | if (add) { | ||
2469 | ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false, | ||
2470 | &vif_priv->ibss_bssid_sta_id); | ||
2471 | if (ret) | ||
2472 | return ret; | ||
2473 | |||
2474 | iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, | ||
2475 | (priv->band == IEEE80211_BAND_5GHZ) ? | ||
2476 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, | ||
2477 | CMD_ASYNC); | ||
2478 | iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); | ||
2479 | |||
2480 | return 0; | ||
2481 | } | ||
2482 | |||
2483 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, | ||
2484 | vif->bss_conf.bssid); | ||
2485 | } | ||
2388 | 2486 | ||
2389 | /** | 2487 | /** |
2390 | * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table | 2488 | * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table |
@@ -2432,7 +2530,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) | |||
2432 | /* If an OFDM rate is used, have it fall back to the | 2530 | /* If an OFDM rate is used, have it fall back to the |
2433 | * 1M CCK rates */ | 2531 | * 1M CCK rates */ |
2434 | 2532 | ||
2435 | if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && | 2533 | if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) && |
2436 | iwl_is_associated(priv)) { | 2534 | iwl_is_associated(priv)) { |
2437 | 2535 | ||
2438 | index = IWL_FIRST_CCK_RATE; | 2536 | index = IWL_FIRST_CCK_RATE; |
@@ -2471,12 +2569,12 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2471 | memset((void *)&priv->hw_params, 0, | 2569 | memset((void *)&priv->hw_params, 0, |
2472 | sizeof(struct iwl_hw_params)); | 2570 | sizeof(struct iwl_hw_params)); |
2473 | 2571 | ||
2474 | priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, | 2572 | priv->_3945.shared_virt = |
2475 | sizeof(struct iwl3945_shared), | 2573 | dma_alloc_coherent(&priv->pci_dev->dev, |
2476 | &priv->shared_phys, GFP_KERNEL); | 2574 | sizeof(struct iwl3945_shared), |
2477 | if (!priv->shared_virt) { | 2575 | &priv->_3945.shared_phys, GFP_KERNEL); |
2576 | if (!priv->_3945.shared_virt) { | ||
2478 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 2577 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
2479 | mutex_unlock(&priv->mutex); | ||
2480 | return -ENOMEM; | 2578 | return -ENOMEM; |
2481 | } | 2579 | } |
2482 | 2580 | ||
@@ -2537,13 +2635,13 @@ void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv) | |||
2537 | 2635 | ||
2538 | void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) | 2636 | void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) |
2539 | { | 2637 | { |
2540 | INIT_DELAYED_WORK(&priv->thermal_periodic, | 2638 | INIT_DELAYED_WORK(&priv->_3945.thermal_periodic, |
2541 | iwl3945_bg_reg_txpower_periodic); | 2639 | iwl3945_bg_reg_txpower_periodic); |
2542 | } | 2640 | } |
2543 | 2641 | ||
2544 | void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) | 2642 | void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) |
2545 | { | 2643 | { |
2546 | cancel_delayed_work(&priv->thermal_periodic); | 2644 | cancel_delayed_work(&priv->_3945.thermal_periodic); |
2547 | } | 2645 | } |
2548 | 2646 | ||
2549 | /* check contents of special bootstrap uCode SRAM */ | 2647 | /* check contents of special bootstrap uCode SRAM */ |
@@ -2714,48 +2812,10 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) | |||
2714 | return 0; | 2812 | return 0; |
2715 | } | 2813 | } |
2716 | 2814 | ||
2717 | #define IWL3945_UCODE_GET(item) \ | ||
2718 | static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
2719 | u32 api_ver) \ | ||
2720 | { \ | ||
2721 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2722 | } | ||
2723 | |||
2724 | static u32 iwl3945_ucode_get_header_size(u32 api_ver) | ||
2725 | { | ||
2726 | return UCODE_HEADER_SIZE(1); | ||
2727 | } | ||
2728 | static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2729 | u32 api_ver) | ||
2730 | { | ||
2731 | return 0; | ||
2732 | } | ||
2733 | static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
2734 | u32 api_ver) | ||
2735 | { | ||
2736 | return (u8 *) ucode->u.v1.data; | ||
2737 | } | ||
2738 | |||
2739 | IWL3945_UCODE_GET(inst_size); | ||
2740 | IWL3945_UCODE_GET(data_size); | ||
2741 | IWL3945_UCODE_GET(init_size); | ||
2742 | IWL3945_UCODE_GET(init_data_size); | ||
2743 | IWL3945_UCODE_GET(boot_size); | ||
2744 | |||
2745 | static struct iwl_hcmd_ops iwl3945_hcmd = { | 2815 | static struct iwl_hcmd_ops iwl3945_hcmd = { |
2746 | .rxon_assoc = iwl3945_send_rxon_assoc, | 2816 | .rxon_assoc = iwl3945_send_rxon_assoc, |
2747 | .commit_rxon = iwl3945_commit_rxon, | 2817 | .commit_rxon = iwl3945_commit_rxon, |
2748 | }; | 2818 | .send_bt_config = iwl_send_bt_config, |
2749 | |||
2750 | static struct iwl_ucode_ops iwl3945_ucode = { | ||
2751 | .get_header_size = iwl3945_ucode_get_header_size, | ||
2752 | .get_build = iwl3945_ucode_get_build, | ||
2753 | .get_inst_size = iwl3945_ucode_get_inst_size, | ||
2754 | .get_data_size = iwl3945_ucode_get_data_size, | ||
2755 | .get_init_size = iwl3945_ucode_get_init_size, | ||
2756 | .get_init_data_size = iwl3945_ucode_get_init_data_size, | ||
2757 | .get_boot_size = iwl3945_ucode_get_boot_size, | ||
2758 | .get_data = iwl3945_ucode_get_data, | ||
2759 | }; | 2819 | }; |
2760 | 2820 | ||
2761 | static struct iwl_lib_ops iwl3945_lib = { | 2821 | static struct iwl_lib_ops iwl3945_lib = { |
@@ -2791,17 +2851,24 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2791 | .post_associate = iwl3945_post_associate, | 2851 | .post_associate = iwl3945_post_associate, |
2792 | .isr = iwl_isr_legacy, | 2852 | .isr = iwl_isr_legacy, |
2793 | .config_ap = iwl3945_config_ap, | 2853 | .config_ap = iwl3945_config_ap, |
2794 | .add_bcast_station = iwl3945_add_bcast_station, | 2854 | .manage_ibss_station = iwl3945_manage_ibss_station, |
2855 | .check_plcp_health = iwl3945_good_plcp_health, | ||
2856 | |||
2857 | .debugfs_ops = { | ||
2858 | .rx_stats_read = iwl3945_ucode_rx_stats_read, | ||
2859 | .tx_stats_read = iwl3945_ucode_tx_stats_read, | ||
2860 | .general_stats_read = iwl3945_ucode_general_stats_read, | ||
2861 | }, | ||
2795 | }; | 2862 | }; |
2796 | 2863 | ||
2797 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2864 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { |
2798 | .get_hcmd_size = iwl3945_get_hcmd_size, | 2865 | .get_hcmd_size = iwl3945_get_hcmd_size, |
2799 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, | 2866 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, |
2800 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2867 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2868 | .request_scan = iwl3945_request_scan, | ||
2801 | }; | 2869 | }; |
2802 | 2870 | ||
2803 | static const struct iwl_ops iwl3945_ops = { | 2871 | static const struct iwl_ops iwl3945_ops = { |
2804 | .ucode = &iwl3945_ucode, | ||
2805 | .lib = &iwl3945_lib, | 2872 | .lib = &iwl3945_lib, |
2806 | .hcmd = &iwl3945_hcmd, | 2873 | .hcmd = &iwl3945_hcmd, |
2807 | .utils = &iwl3945_hcmd_utils, | 2874 | .utils = &iwl3945_hcmd_utils, |
@@ -2826,7 +2893,10 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2826 | .ht_greenfield_support = false, | 2893 | .ht_greenfield_support = false, |
2827 | .led_compensation = 64, | 2894 | .led_compensation = 64, |
2828 | .broken_powersave = true, | 2895 | .broken_powersave = true, |
2829 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2896 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
2897 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
2898 | .max_event_log_size = 512, | ||
2899 | .tx_power_by_driver = true, | ||
2830 | }; | 2900 | }; |
2831 | 2901 | ||
2832 | static struct iwl_cfg iwl3945_abg_cfg = { | 2902 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2844,7 +2914,10 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2844 | .ht_greenfield_support = false, | 2914 | .ht_greenfield_support = false, |
2845 | .led_compensation = 64, | 2915 | .led_compensation = 64, |
2846 | .broken_powersave = true, | 2916 | .broken_powersave = true, |
2847 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2917 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
2918 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
2919 | .max_event_log_size = 512, | ||
2920 | .tx_power_by_driver = true, | ||
2848 | }; | 2921 | }; |
2849 | 2922 | ||
2850 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | 2923 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 452dfd5456c6..bb2aeebf3652 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -95,7 +95,6 @@ struct iwl3945_rs_sta { | |||
95 | u8 tgg; | 95 | u8 tgg; |
96 | u8 flush_pending; | 96 | u8 flush_pending; |
97 | u8 start_rate; | 97 | u8 start_rate; |
98 | u8 ibss_sta_added; | ||
99 | struct timer_list rate_scale_flush; | 98 | struct timer_list rate_scale_flush; |
100 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; | 99 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; |
101 | #ifdef CONFIG_MAC80211_DEBUGFS | 100 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -107,7 +106,12 @@ struct iwl3945_rs_sta { | |||
107 | }; | 106 | }; |
108 | 107 | ||
109 | 108 | ||
109 | /* | ||
110 | * The common struct MUST be first because it is shared between | ||
111 | * 3945 and agn! | ||
112 | */ | ||
110 | struct iwl3945_sta_priv { | 113 | struct iwl3945_sta_priv { |
114 | struct iwl_station_priv_common common; | ||
111 | struct iwl3945_rs_sta rs_sta; | 115 | struct iwl3945_rs_sta rs_sta; |
112 | }; | 116 | }; |
113 | 117 | ||
@@ -212,13 +216,6 @@ extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
212 | char **buf, bool display); | 216 | char **buf, bool display); |
213 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | 217 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); |
214 | 218 | ||
215 | /* | ||
216 | * Currently used by iwl-3945-rs... look at restructuring so that it doesn't | ||
217 | * call this... todo... fix that. | ||
218 | */ | ||
219 | extern u8 iwl3945_sync_station(struct iwl_priv *priv, int sta_id, | ||
220 | u16 tx_rate, u8 flags); | ||
221 | |||
222 | /****************************************************************************** | 219 | /****************************************************************************** |
223 | * | 220 | * |
224 | * Functions implemented in iwl-[34]*.c which are forward declared here | 221 | * Functions implemented in iwl-[34]*.c which are forward declared here |
@@ -265,10 +262,14 @@ extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv); | |||
265 | extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); | 262 | extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); |
266 | extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 263 | extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
267 | struct iwl_rx_mem_buffer *rxb); | 264 | struct iwl_rx_mem_buffer *rxb); |
265 | void iwl3945_reply_statistics(struct iwl_priv *priv, | ||
266 | struct iwl_rx_mem_buffer *rxb); | ||
268 | extern void iwl3945_disable_events(struct iwl_priv *priv); | 267 | extern void iwl3945_disable_events(struct iwl_priv *priv); |
269 | extern int iwl4965_get_temperature(const struct iwl_priv *priv); | 268 | extern int iwl4965_get_temperature(const struct iwl_priv *priv); |
270 | extern void iwl3945_post_associate(struct iwl_priv *priv); | 269 | extern void iwl3945_post_associate(struct iwl_priv *priv, |
271 | extern void iwl3945_config_ap(struct iwl_priv *priv); | 270 | struct ieee80211_vif *vif); |
271 | extern void iwl3945_config_ap(struct iwl_priv *priv, | ||
272 | struct ieee80211_vif *vif); | ||
272 | 273 | ||
273 | /** | 274 | /** |
274 | * iwl3945_hw_find_station - Find station id for a given BSSID | 275 | * iwl3945_hw_find_station - Find station id for a given BSSID |
@@ -287,14 +288,15 @@ extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv); | |||
287 | extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv); | 288 | extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv); |
288 | extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv); | 289 | extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv); |
289 | extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); | 290 | extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); |
290 | extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, | ||
291 | u16 tx_rate, u8 flags); | ||
292 | 291 | ||
293 | extern const struct iwl_channel_info *iwl3945_get_channel_info( | 292 | extern const struct iwl_channel_info *iwl3945_get_channel_info( |
294 | const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); | 293 | const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); |
295 | 294 | ||
296 | extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); | 295 | extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); |
297 | 296 | ||
297 | /* scanning */ | ||
298 | void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
299 | |||
298 | /* Requires full declaration of iwl_priv before including */ | 300 | /* Requires full declaration of iwl_priv before including */ |
299 | #include "iwl-io.h" | 301 | #include "iwl-io.h" |
300 | 302 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 67ef562e8db1..cd4b61ae25b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -81,26 +81,6 @@ | |||
81 | */ | 81 | */ |
82 | #define IWL49_FIRST_AMPDU_QUEUE 7 | 82 | #define IWL49_FIRST_AMPDU_QUEUE 7 |
83 | 83 | ||
84 | /* Time constants */ | ||
85 | #define SHORT_SLOT_TIME 9 | ||
86 | #define LONG_SLOT_TIME 20 | ||
87 | |||
88 | /* RSSI to dBm */ | ||
89 | #define IWL49_RSSI_OFFSET 44 | ||
90 | |||
91 | |||
92 | /* PCI registers */ | ||
93 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
94 | |||
95 | /* PCI register values */ | ||
96 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
97 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
98 | |||
99 | #define IWL_NUM_SCAN_RATES (2) | ||
100 | |||
101 | #define IWL_DEFAULT_TX_RETRY 15 | ||
102 | |||
103 | |||
104 | /* Sizes and addresses for instruction and data memory (SRAM) in | 84 | /* Sizes and addresses for instruction and data memory (SRAM) in |
105 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | 85 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ |
106 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) | 86 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) |
@@ -393,10 +373,6 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) | |||
393 | * location(s) in command (struct iwl4965_txpowertable_cmd). | 373 | * location(s) in command (struct iwl4965_txpowertable_cmd). |
394 | */ | 374 | */ |
395 | 375 | ||
396 | /* Limit range of txpower output target to be between these values */ | ||
397 | #define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ | ||
398 | #define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ | ||
399 | |||
400 | /** | 376 | /** |
401 | * When MIMO is used (2 transmitters operating simultaneously), driver should | 377 | * When MIMO is used (2 transmitters operating simultaneously), driver should |
402 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit | 378 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8972166386cb..d3afddae8d9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include "iwl-calib.h" | 46 | #include "iwl-calib.h" |
47 | #include "iwl-sta.h" | 47 | #include "iwl-sta.h" |
48 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn.h" | ||
50 | #include "iwl-agn-debugfs.h" | ||
49 | 51 | ||
50 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 52 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
51 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 53 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); |
@@ -60,14 +62,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | |||
60 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" | 62 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" |
61 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) | 63 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) |
62 | 64 | ||
63 | |||
64 | /* module parameters */ | ||
65 | static struct iwl_mod_params iwl4965_mod_params = { | ||
66 | .amsdu_size_8K = 1, | ||
67 | .restart_fw = 1, | ||
68 | /* the rest are 0 by default */ | ||
69 | }; | ||
70 | |||
71 | /* check contents of special bootstrap uCode SRAM */ | 65 | /* check contents of special bootstrap uCode SRAM */ |
72 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | 66 | static int iwl4965_verify_bsm(struct iwl_priv *priv) |
73 | { | 67 | { |
@@ -417,7 +411,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
417 | sizeof(cmd), &cmd); | 411 | sizeof(cmd), &cmd); |
418 | if (ret) | 412 | if (ret) |
419 | IWL_DEBUG_CALIB(priv, "fail sending cmd " | 413 | IWL_DEBUG_CALIB(priv, "fail sending cmd " |
420 | "REPLY_PHY_CALIBRATION_CMD \n"); | 414 | "REPLY_PHY_CALIBRATION_CMD\n"); |
421 | 415 | ||
422 | /* TODO we might want recalculate | 416 | /* TODO we might want recalculate |
423 | * rx_chain in rxon cmd */ | 417 | * rx_chain in rxon cmd */ |
@@ -502,14 +496,14 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, | |||
502 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 496 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
503 | } | 497 | } |
504 | 498 | ||
505 | static const u16 default_queue_to_tx_fifo[] = { | 499 | static const s8 default_queue_to_tx_fifo[] = { |
506 | IWL_TX_FIFO_AC3, | 500 | IWL_TX_FIFO_VO, |
507 | IWL_TX_FIFO_AC2, | 501 | IWL_TX_FIFO_VI, |
508 | IWL_TX_FIFO_AC1, | 502 | IWL_TX_FIFO_BE, |
509 | IWL_TX_FIFO_AC0, | 503 | IWL_TX_FIFO_BK, |
510 | IWL49_CMD_FIFO_NUM, | 504 | IWL49_CMD_FIFO_NUM, |
511 | IWL_TX_FIFO_HCCA_1, | 505 | IWL_TX_FIFO_UNUSED, |
512 | IWL_TX_FIFO_HCCA_2 | 506 | IWL_TX_FIFO_UNUSED, |
513 | }; | 507 | }; |
514 | 508 | ||
515 | static int iwl4965_alive_notify(struct iwl_priv *priv) | 509 | static int iwl4965_alive_notify(struct iwl_priv *priv) |
@@ -589,9 +583,15 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
589 | /* reset to 0 to enable all the queue first */ | 583 | /* reset to 0 to enable all the queue first */ |
590 | priv->txq_ctx_active_msk = 0; | 584 | priv->txq_ctx_active_msk = 0; |
591 | /* Map each Tx/cmd queue to its corresponding fifo */ | 585 | /* Map each Tx/cmd queue to its corresponding fifo */ |
586 | BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7); | ||
592 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 587 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
593 | int ac = default_queue_to_tx_fifo[i]; | 588 | int ac = default_queue_to_tx_fifo[i]; |
589 | |||
594 | iwl_txq_ctx_activate(priv, i); | 590 | iwl_txq_ctx_activate(priv, i); |
591 | |||
592 | if (ac == IWL_TX_FIFO_UNUSED) | ||
593 | continue; | ||
594 | |||
595 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | 595 | iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); |
596 | } | 596 | } |
597 | 597 | ||
@@ -1613,19 +1613,19 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) | |||
1613 | 1613 | ||
1614 | /* get absolute value */ | 1614 | /* get absolute value */ |
1615 | if (temp_diff < 0) { | 1615 | if (temp_diff < 0) { |
1616 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff); | 1616 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff); |
1617 | temp_diff = -temp_diff; | 1617 | temp_diff = -temp_diff; |
1618 | } else if (temp_diff == 0) | 1618 | } else if (temp_diff == 0) |
1619 | IWL_DEBUG_POWER(priv, "Same temp, \n"); | 1619 | IWL_DEBUG_POWER(priv, "Temperature unchanged\n"); |
1620 | else | 1620 | else |
1621 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff); | 1621 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff); |
1622 | 1622 | ||
1623 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { | 1623 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { |
1624 | IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n"); | 1624 | IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n"); |
1625 | return 0; | 1625 | return 0; |
1626 | } | 1626 | } |
1627 | 1627 | ||
1628 | IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n"); | 1628 | IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n"); |
1629 | 1629 | ||
1630 | return 1; | 1630 | return 1; |
1631 | } | 1631 | } |
@@ -1874,7 +1874,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1876 | info->flags |= iwl_tx_status_to_mac80211(status); | 1876 | info->flags |= iwl_tx_status_to_mac80211(status); |
1877 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1877 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); |
1878 | /* FIXME: code repetition end */ | 1878 | /* FIXME: code repetition end */ |
1879 | 1879 | ||
1880 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | 1880 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", |
@@ -1953,6 +1953,60 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1953 | return 0; | 1953 | return 0; |
1954 | } | 1954 | } |
1955 | 1955 | ||
1956 | static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | ||
1957 | { | ||
1958 | int i; | ||
1959 | int start = 0; | ||
1960 | int ret = IWL_INVALID_STATION; | ||
1961 | unsigned long flags; | ||
1962 | |||
1963 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || | ||
1964 | (priv->iw_mode == NL80211_IFTYPE_AP)) | ||
1965 | start = IWL_STA_ID; | ||
1966 | |||
1967 | if (is_broadcast_ether_addr(addr)) | ||
1968 | return priv->hw_params.bcast_sta_id; | ||
1969 | |||
1970 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1971 | for (i = start; i < priv->hw_params.max_stations; i++) | ||
1972 | if (priv->stations[i].used && | ||
1973 | (!compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
1974 | addr))) { | ||
1975 | ret = i; | ||
1976 | goto out; | ||
1977 | } | ||
1978 | |||
1979 | IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", | ||
1980 | addr, priv->num_stations); | ||
1981 | |||
1982 | out: | ||
1983 | /* | ||
1984 | * It may be possible that more commands interacting with stations | ||
1985 | * arrive before we completed processing the adding of | ||
1986 | * station | ||
1987 | */ | ||
1988 | if (ret != IWL_INVALID_STATION && | ||
1989 | (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || | ||
1990 | ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && | ||
1991 | (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { | ||
1992 | IWL_ERR(priv, "Requested station info for sta %d before ready.\n", | ||
1993 | ret); | ||
1994 | ret = IWL_INVALID_STATION; | ||
1995 | } | ||
1996 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1997 | return ret; | ||
1998 | } | ||
1999 | |||
2000 | static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | ||
2001 | { | ||
2002 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | ||
2003 | return IWL_AP_ID; | ||
2004 | } else { | ||
2005 | u8 *da = ieee80211_get_DA(hdr); | ||
2006 | return iwl_find_station(priv, da); | ||
2007 | } | ||
2008 | } | ||
2009 | |||
1956 | /** | 2010 | /** |
1957 | * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response | 2011 | * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response |
1958 | */ | 2012 | */ |
@@ -2014,7 +2068,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2014 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | 2068 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); |
2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2069 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
2016 | "%d index %d\n", scd_ssn , index); | 2070 | "%d index %d\n", scd_ssn , index); |
2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2071 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
2018 | if (qc) | 2072 | if (qc) |
2019 | iwl_free_tfds_in_queue(priv, sta_id, | 2073 | iwl_free_tfds_in_queue(priv, sta_id, |
2020 | tid, freed); | 2074 | tid, freed); |
@@ -2031,7 +2085,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2031 | } else { | 2085 | } else { |
2032 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2086 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2033 | info->flags |= iwl_tx_status_to_mac80211(status); | 2087 | info->flags |= iwl_tx_status_to_mac80211(status); |
2034 | iwl_hwrate_to_tx_control(priv, | 2088 | iwlagn_hwrate_to_tx_control(priv, |
2035 | le32_to_cpu(tx_resp->rate_n_flags), | 2089 | le32_to_cpu(tx_resp->rate_n_flags), |
2036 | info); | 2090 | info); |
2037 | 2091 | ||
@@ -2042,7 +2096,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2042 | le32_to_cpu(tx_resp->rate_n_flags), | 2096 | le32_to_cpu(tx_resp->rate_n_flags), |
2043 | tx_resp->failure_frame); | 2097 | tx_resp->failure_frame); |
2044 | 2098 | ||
2045 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2099 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
2046 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2100 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2047 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2101 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
2048 | else if (sta_id == IWL_INVALID_STATION) | 2102 | else if (sta_id == IWL_INVALID_STATION) |
@@ -2053,10 +2107,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2053 | iwl_wake_queue(priv, txq_id); | 2107 | iwl_wake_queue(priv, txq_id); |
2054 | } | 2108 | } |
2055 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2109 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2056 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2110 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
2057 | 2111 | ||
2058 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | 2112 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
2059 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
2060 | } | 2113 | } |
2061 | 2114 | ||
2062 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2115 | static int iwl4965_calc_rssi(struct iwl_priv *priv, |
@@ -2090,7 +2143,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, | |||
2090 | 2143 | ||
2091 | /* dBm = max_rssi dB - agc dB - constant. | 2144 | /* dBm = max_rssi dB - agc dB - constant. |
2092 | * Higher AGC (higher radio gain) means lower signal. */ | 2145 | * Higher AGC (higher radio gain) means lower signal. */ |
2093 | return max_rssi - agc - IWL49_RSSI_OFFSET; | 2146 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; |
2094 | } | 2147 | } |
2095 | 2148 | ||
2096 | 2149 | ||
@@ -2098,7 +2151,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, | |||
2098 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 2151 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
2099 | { | 2152 | { |
2100 | /* Legacy Rx frames */ | 2153 | /* Legacy Rx frames */ |
2101 | priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; | 2154 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; |
2102 | /* Tx response */ | 2155 | /* Tx response */ |
2103 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2156 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
2104 | } | 2157 | } |
@@ -2113,50 +2166,13 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) | |||
2113 | cancel_work_sync(&priv->txpower_work); | 2166 | cancel_work_sync(&priv->txpower_work); |
2114 | } | 2167 | } |
2115 | 2168 | ||
2116 | #define IWL4965_UCODE_GET(item) \ | ||
2117 | static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
2118 | u32 api_ver) \ | ||
2119 | { \ | ||
2120 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2121 | } | ||
2122 | |||
2123 | static u32 iwl4965_ucode_get_header_size(u32 api_ver) | ||
2124 | { | ||
2125 | return UCODE_HEADER_SIZE(1); | ||
2126 | } | ||
2127 | static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2128 | u32 api_ver) | ||
2129 | { | ||
2130 | return 0; | ||
2131 | } | ||
2132 | static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
2133 | u32 api_ver) | ||
2134 | { | ||
2135 | return (u8 *) ucode->u.v1.data; | ||
2136 | } | ||
2137 | |||
2138 | IWL4965_UCODE_GET(inst_size); | ||
2139 | IWL4965_UCODE_GET(data_size); | ||
2140 | IWL4965_UCODE_GET(init_size); | ||
2141 | IWL4965_UCODE_GET(init_data_size); | ||
2142 | IWL4965_UCODE_GET(boot_size); | ||
2143 | |||
2144 | static struct iwl_hcmd_ops iwl4965_hcmd = { | 2169 | static struct iwl_hcmd_ops iwl4965_hcmd = { |
2145 | .rxon_assoc = iwl4965_send_rxon_assoc, | 2170 | .rxon_assoc = iwl4965_send_rxon_assoc, |
2146 | .commit_rxon = iwl_commit_rxon, | 2171 | .commit_rxon = iwl_commit_rxon, |
2147 | .set_rxon_chain = iwl_set_rxon_chain, | 2172 | .set_rxon_chain = iwl_set_rxon_chain, |
2173 | .send_bt_config = iwl_send_bt_config, | ||
2148 | }; | 2174 | }; |
2149 | 2175 | ||
2150 | static struct iwl_ucode_ops iwl4965_ucode = { | ||
2151 | .get_header_size = iwl4965_ucode_get_header_size, | ||
2152 | .get_build = iwl4965_ucode_get_build, | ||
2153 | .get_inst_size = iwl4965_ucode_get_inst_size, | ||
2154 | .get_data_size = iwl4965_ucode_get_data_size, | ||
2155 | .get_init_size = iwl4965_ucode_get_init_size, | ||
2156 | .get_init_data_size = iwl4965_ucode_get_init_data_size, | ||
2157 | .get_boot_size = iwl4965_ucode_get_boot_size, | ||
2158 | .get_data = iwl4965_ucode_get_data, | ||
2159 | }; | ||
2160 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | 2176 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { |
2161 | .get_hcmd_size = iwl4965_get_hcmd_size, | 2177 | .get_hcmd_size = iwl4965_get_hcmd_size, |
2162 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2178 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
@@ -2164,6 +2180,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2164 | .gain_computation = iwl4965_gain_computation, | 2180 | .gain_computation = iwl4965_gain_computation, |
2165 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2181 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2166 | .calc_rssi = iwl4965_calc_rssi, | 2182 | .calc_rssi = iwl4965_calc_rssi, |
2183 | .request_scan = iwlagn_request_scan, | ||
2167 | }; | 2184 | }; |
2168 | 2185 | ||
2169 | static struct iwl_lib_ops iwl4965_lib = { | 2186 | static struct iwl_lib_ops iwl4965_lib = { |
@@ -2184,6 +2201,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2184 | .load_ucode = iwl4965_load_bsm, | 2201 | .load_ucode = iwl4965_load_bsm, |
2185 | .dump_nic_event_log = iwl_dump_nic_event_log, | 2202 | .dump_nic_event_log = iwl_dump_nic_event_log, |
2186 | .dump_nic_error_log = iwl_dump_nic_error_log, | 2203 | .dump_nic_error_log = iwl_dump_nic_error_log, |
2204 | .dump_fh = iwl_dump_fh, | ||
2187 | .set_channel_switch = iwl4965_hw_channel_switch, | 2205 | .set_channel_switch = iwl4965_hw_channel_switch, |
2188 | .apm_ops = { | 2206 | .apm_ops = { |
2189 | .init = iwl_apm_init, | 2207 | .init = iwl_apm_init, |
@@ -2216,11 +2234,16 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2216 | .temperature = iwl4965_temperature_calib, | 2234 | .temperature = iwl4965_temperature_calib, |
2217 | .set_ct_kill = iwl4965_set_ct_threshold, | 2235 | .set_ct_kill = iwl4965_set_ct_threshold, |
2218 | }, | 2236 | }, |
2219 | .add_bcast_station = iwl_add_bcast_station, | 2237 | .manage_ibss_station = iwlagn_manage_ibss_station, |
2238 | .debugfs_ops = { | ||
2239 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
2240 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
2241 | .general_stats_read = iwl_ucode_general_stats_read, | ||
2242 | }, | ||
2243 | .check_plcp_health = iwl_good_plcp_health, | ||
2220 | }; | 2244 | }; |
2221 | 2245 | ||
2222 | static const struct iwl_ops iwl4965_ops = { | 2246 | static const struct iwl_ops iwl4965_ops = { |
2223 | .ucode = &iwl4965_ucode, | ||
2224 | .lib = &iwl4965_lib, | 2247 | .lib = &iwl4965_lib, |
2225 | .hcmd = &iwl4965_hcmd, | 2248 | .hcmd = &iwl4965_hcmd, |
2226 | .utils = &iwl4965_hcmd_utils, | 2249 | .utils = &iwl4965_hcmd_utils, |
@@ -2228,7 +2251,7 @@ static const struct iwl_ops iwl4965_ops = { | |||
2228 | }; | 2251 | }; |
2229 | 2252 | ||
2230 | struct iwl_cfg iwl4965_agn_cfg = { | 2253 | struct iwl_cfg iwl4965_agn_cfg = { |
2231 | .name = "4965AGN", | 2254 | .name = "Intel(R) Wireless WiFi Link 4965AGN", |
2232 | .fw_name_pre = IWL4965_FW_PRE, | 2255 | .fw_name_pre = IWL4965_FW_PRE, |
2233 | .ucode_api_max = IWL4965_UCODE_API_MAX, | 2256 | .ucode_api_max = IWL4965_UCODE_API_MAX, |
2234 | .ucode_api_min = IWL4965_UCODE_API_MIN, | 2257 | .ucode_api_min = IWL4965_UCODE_API_MIN, |
@@ -2239,7 +2262,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2239 | .ops = &iwl4965_ops, | 2262 | .ops = &iwl4965_ops, |
2240 | .num_of_queues = IWL49_NUM_QUEUES, | 2263 | .num_of_queues = IWL49_NUM_QUEUES, |
2241 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | 2264 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, |
2242 | .mod_params = &iwl4965_mod_params, | 2265 | .mod_params = &iwlagn_mod_params, |
2243 | .valid_tx_ant = ANT_AB, | 2266 | .valid_tx_ant = ANT_AB, |
2244 | .valid_rx_ant = ANT_ABC, | 2267 | .valid_rx_ant = ANT_ABC, |
2245 | .pll_cfg_val = 0, | 2268 | .pll_cfg_val = 0, |
@@ -2251,27 +2274,20 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2251 | .led_compensation = 61, | 2274 | .led_compensation = 61, |
2252 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2275 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
2253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2276 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2277 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
2278 | .temperature_kelvin = true, | ||
2279 | .max_event_log_size = 512, | ||
2280 | .tx_power_by_driver = true, | ||
2281 | .ucode_tracing = true, | ||
2282 | .sensitivity_calib_by_driver = true, | ||
2283 | .chain_noise_calib_by_driver = true, | ||
2284 | /* | ||
2285 | * Force use of chains B and C for scan RX on 5 GHz band | ||
2286 | * because the device has off-channel reception on chain A. | ||
2287 | */ | ||
2288 | .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, | ||
2254 | }; | 2289 | }; |
2255 | 2290 | ||
2256 | /* Module firmware */ | 2291 | /* Module firmware */ |
2257 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | 2292 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2258 | 2293 | ||
2259 | module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); | ||
2260 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | ||
2261 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); | ||
2262 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | ||
2263 | module_param_named( | ||
2264 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); | ||
2265 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | ||
2266 | |||
2267 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); | ||
2268 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
2269 | /* 11n */ | ||
2270 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); | ||
2271 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
2272 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, | ||
2273 | int, S_IRUGO); | ||
2274 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | ||
2275 | |||
2276 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); | ||
2277 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 714e032f6217..146e6431ae95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -68,25 +68,6 @@ | |||
68 | #ifndef __iwl_5000_hw_h__ | 68 | #ifndef __iwl_5000_hw_h__ |
69 | #define __iwl_5000_hw_h__ | 69 | #define __iwl_5000_hw_h__ |
70 | 70 | ||
71 | #define IWL50_RTC_INST_LOWER_BOUND (0x000000) | ||
72 | #define IWL50_RTC_INST_UPPER_BOUND (0x020000) | ||
73 | |||
74 | #define IWL50_RTC_DATA_LOWER_BOUND (0x800000) | ||
75 | #define IWL50_RTC_DATA_UPPER_BOUND (0x80C000) | ||
76 | |||
77 | #define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \ | ||
78 | IWL50_RTC_INST_LOWER_BOUND) | ||
79 | #define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \ | ||
80 | IWL50_RTC_DATA_LOWER_BOUND) | ||
81 | |||
82 | /* EEPROM */ | ||
83 | #define IWL_5000_EEPROM_IMG_SIZE 2048 | ||
84 | |||
85 | #define IWL50_CMD_FIFO_NUM 7 | ||
86 | #define IWL50_NUM_QUEUES 20 | ||
87 | #define IWL50_NUM_AMPDU_QUEUES 10 | ||
88 | #define IWL50_FIRST_AMPDU_QUEUE 10 | ||
89 | |||
90 | /* 5150 only */ | 71 | /* 5150 only */ |
91 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | 72 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) |
92 | 73 | ||
@@ -103,19 +84,5 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | |||
103 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | 84 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); |
104 | } | 85 | } |
105 | 86 | ||
106 | /* Fixed (non-configurable) rx data from phy */ | ||
107 | |||
108 | /** | ||
109 | * struct iwl5000_schedq_bc_tbl scheduler byte count table | ||
110 | * base physical address of iwl5000_shared | ||
111 | * is provided to SCD_DRAM_BASE_ADDR | ||
112 | * @tfd_offset 0-12 - tx command byte count | ||
113 | * 12-16 - station index | ||
114 | */ | ||
115 | struct iwl5000_scd_bc_tbl { | ||
116 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
117 | } __attribute__ ((packed)); | ||
118 | |||
119 | |||
120 | #endif /* __iwl_5000_hw_h__ */ | 87 | #endif /* __iwl_5000_hw_h__ */ |
121 | 88 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e476acb53aa7..a28af7eb67eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * file called LICENSE. | 19 | * file called LICENSE. |
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
22 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
23 | * | 24 | * |
24 | *****************************************************************************/ | 25 | *****************************************************************************/ |
@@ -43,9 +44,11 @@ | |||
43 | #include "iwl-io.h" | 44 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 45 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
47 | #include "iwl-agn.h" | ||
46 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn-hw.h" | ||
47 | #include "iwl-5000-hw.h" | 50 | #include "iwl-5000-hw.h" |
48 | #include "iwl-6000-hw.h" | 51 | #include "iwl-agn-debugfs.h" |
49 | 52 | ||
50 | /* Highest firmware API version supported */ | 53 | /* Highest firmware API version supported */ |
51 | #define IWL5000_UCODE_API_MAX 2 | 54 | #define IWL5000_UCODE_API_MAX 2 |
@@ -63,18 +66,8 @@ | |||
63 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" | 66 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" |
64 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) | 67 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) |
65 | 68 | ||
66 | static const u16 iwl5000_default_queue_to_tx_fifo[] = { | ||
67 | IWL_TX_FIFO_AC3, | ||
68 | IWL_TX_FIFO_AC2, | ||
69 | IWL_TX_FIFO_AC1, | ||
70 | IWL_TX_FIFO_AC0, | ||
71 | IWL50_CMD_FIFO_NUM, | ||
72 | IWL_TX_FIFO_HCCA_1, | ||
73 | IWL_TX_FIFO_HCCA_2 | ||
74 | }; | ||
75 | |||
76 | /* NIC configuration for 5000 series */ | 69 | /* NIC configuration for 5000 series */ |
77 | void iwl5000_nic_config(struct iwl_priv *priv) | 70 | static void iwl5000_nic_config(struct iwl_priv *priv) |
78 | { | 71 | { |
79 | unsigned long flags; | 72 | unsigned long flags; |
80 | u16 radio_cfg; | 73 | u16 radio_cfg; |
@@ -107,162 +100,6 @@ void iwl5000_nic_config(struct iwl_priv *priv) | |||
107 | spin_unlock_irqrestore(&priv->lock, flags); | 100 | spin_unlock_irqrestore(&priv->lock, flags); |
108 | } | 101 | } |
109 | 102 | ||
110 | |||
111 | /* | ||
112 | * EEPROM | ||
113 | */ | ||
114 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | ||
115 | { | ||
116 | u16 offset = 0; | ||
117 | |||
118 | if ((address & INDIRECT_ADDRESS) == 0) | ||
119 | return address; | ||
120 | |||
121 | switch (address & INDIRECT_TYPE_MSK) { | ||
122 | case INDIRECT_HOST: | ||
123 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | ||
124 | break; | ||
125 | case INDIRECT_GENERAL: | ||
126 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | ||
127 | break; | ||
128 | case INDIRECT_REGULATORY: | ||
129 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | ||
130 | break; | ||
131 | case INDIRECT_CALIBRATION: | ||
132 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | ||
133 | break; | ||
134 | case INDIRECT_PROCESS_ADJST: | ||
135 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | ||
136 | break; | ||
137 | case INDIRECT_OTHERS: | ||
138 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | ||
139 | break; | ||
140 | default: | ||
141 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
142 | address & INDIRECT_TYPE_MSK); | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | /* translate the offset from words to byte */ | ||
147 | return (address & ADDRESS_MSK) + (offset << 1); | ||
148 | } | ||
149 | |||
150 | u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) | ||
151 | { | ||
152 | struct iwl_eeprom_calib_hdr { | ||
153 | u8 version; | ||
154 | u8 pa_type; | ||
155 | u16 voltage; | ||
156 | } *hdr; | ||
157 | |||
158 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
159 | EEPROM_5000_CALIB_ALL); | ||
160 | return hdr->version; | ||
161 | |||
162 | } | ||
163 | |||
164 | static void iwl5000_gain_computation(struct iwl_priv *priv, | ||
165 | u32 average_noise[NUM_RX_CHAINS], | ||
166 | u16 min_average_noise_antenna_i, | ||
167 | u32 min_average_noise, | ||
168 | u8 default_chain) | ||
169 | { | ||
170 | int i; | ||
171 | s32 delta_g; | ||
172 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
173 | |||
174 | /* | ||
175 | * Find Gain Code for the chains based on "default chain" | ||
176 | */ | ||
177 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
178 | if ((data->disconn_array[i])) { | ||
179 | data->delta_gain_code[i] = 0; | ||
180 | continue; | ||
181 | } | ||
182 | |||
183 | delta_g = (priv->cfg->chain_noise_scale * | ||
184 | ((s32)average_noise[default_chain] - | ||
185 | (s32)average_noise[i])) / 1500; | ||
186 | |||
187 | /* bound gain by 2 bits value max, 3rd bit is sign */ | ||
188 | data->delta_gain_code[i] = | ||
189 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
190 | |||
191 | if (delta_g < 0) | ||
192 | /* | ||
193 | * set negative sign ... | ||
194 | * note to Intel developers: This is uCode API format, | ||
195 | * not the format of any internal device registers. | ||
196 | * Do not change this format for e.g. 6050 or similar | ||
197 | * devices. Change format only if more resolution | ||
198 | * (i.e. more than 2 bits magnitude) is needed. | ||
199 | */ | ||
200 | data->delta_gain_code[i] |= (1 << 2); | ||
201 | } | ||
202 | |||
203 | IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", | ||
204 | data->delta_gain_code[1], data->delta_gain_code[2]); | ||
205 | |||
206 | if (!data->radio_write) { | ||
207 | struct iwl_calib_chain_noise_gain_cmd cmd; | ||
208 | |||
209 | memset(&cmd, 0, sizeof(cmd)); | ||
210 | |||
211 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | ||
212 | cmd.hdr.first_group = 0; | ||
213 | cmd.hdr.groups_num = 1; | ||
214 | cmd.hdr.data_valid = 1; | ||
215 | cmd.delta_gain_1 = data->delta_gain_code[1]; | ||
216 | cmd.delta_gain_2 = data->delta_gain_code[2]; | ||
217 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | ||
218 | sizeof(cmd), &cmd, NULL); | ||
219 | |||
220 | data->radio_write = 1; | ||
221 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
222 | } | ||
223 | |||
224 | data->chain_noise_a = 0; | ||
225 | data->chain_noise_b = 0; | ||
226 | data->chain_noise_c = 0; | ||
227 | data->chain_signal_a = 0; | ||
228 | data->chain_signal_b = 0; | ||
229 | data->chain_signal_c = 0; | ||
230 | data->beacon_count = 0; | ||
231 | } | ||
232 | |||
233 | static void iwl5000_chain_noise_reset(struct iwl_priv *priv) | ||
234 | { | ||
235 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
236 | int ret; | ||
237 | |||
238 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | ||
239 | struct iwl_calib_chain_noise_reset_cmd cmd; | ||
240 | memset(&cmd, 0, sizeof(cmd)); | ||
241 | |||
242 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | ||
243 | cmd.hdr.first_group = 0; | ||
244 | cmd.hdr.groups_num = 1; | ||
245 | cmd.hdr.data_valid = 1; | ||
246 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
247 | sizeof(cmd), &cmd); | ||
248 | if (ret) | ||
249 | IWL_ERR(priv, | ||
250 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
251 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
252 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
257 | __le32 *tx_flags) | ||
258 | { | ||
259 | if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
260 | (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
261 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
262 | else | ||
263 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
264 | } | ||
265 | |||
266 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | 103 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { |
267 | .min_nrg_cck = 95, | 104 | .min_nrg_cck = 95, |
268 | .max_nrg_cck = 0, /* not used, set to 0 */ | 105 | .max_nrg_cck = 0, /* not used, set to 0 */ |
@@ -314,14 +151,6 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
314 | .nrg_th_cca = 62, | 151 | .nrg_th_cca = 62, |
315 | }; | 152 | }; |
316 | 153 | ||
317 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | ||
318 | size_t offset) | ||
319 | { | ||
320 | u32 address = eeprom_indirect_address(priv, offset); | ||
321 | BUG_ON(address >= priv->cfg->eeprom_size); | ||
322 | return &priv->eeprom[address]; | ||
323 | } | ||
324 | |||
325 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | 154 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) |
326 | { | 155 | { |
327 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | 156 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; |
@@ -337,356 +166,10 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |||
337 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | 166 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; |
338 | } | 167 | } |
339 | 168 | ||
340 | /* | 169 | static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
341 | * Calibration | ||
342 | */ | ||
343 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) | ||
344 | { | ||
345 | struct iwl_calib_xtal_freq_cmd cmd; | ||
346 | __le16 *xtal_calib = | ||
347 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | ||
348 | |||
349 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | ||
350 | cmd.hdr.first_group = 0; | ||
351 | cmd.hdr.groups_num = 1; | ||
352 | cmd.hdr.data_valid = 1; | ||
353 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||
354 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | ||
355 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | ||
356 | (u8 *)&cmd, sizeof(cmd)); | ||
357 | } | ||
358 | |||
359 | static int iwl5000_send_calib_cfg(struct iwl_priv *priv) | ||
360 | { | ||
361 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
362 | struct iwl_host_cmd cmd = { | ||
363 | .id = CALIBRATION_CFG_CMD, | ||
364 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
365 | .data = &calib_cfg_cmd, | ||
366 | }; | ||
367 | |||
368 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
369 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
370 | calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; | ||
371 | calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; | ||
372 | calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; | ||
373 | |||
374 | return iwl_send_cmd(priv, &cmd); | ||
375 | } | ||
376 | |||
377 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, | ||
378 | struct iwl_rx_mem_buffer *rxb) | ||
379 | { | ||
380 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
381 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | ||
382 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
383 | int index; | ||
384 | |||
385 | /* reduce the size of the length field itself */ | ||
386 | len -= 4; | ||
387 | |||
388 | /* Define the order in which the results will be sent to the runtime | ||
389 | * uCode. iwl_send_calib_results sends them in a row according to their | ||
390 | * index. We sort them here */ | ||
391 | switch (hdr->op_code) { | ||
392 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
393 | index = IWL_CALIB_DC; | ||
394 | break; | ||
395 | case IWL_PHY_CALIBRATE_LO_CMD: | ||
396 | index = IWL_CALIB_LO; | ||
397 | break; | ||
398 | case IWL_PHY_CALIBRATE_TX_IQ_CMD: | ||
399 | index = IWL_CALIB_TX_IQ; | ||
400 | break; | ||
401 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | ||
402 | index = IWL_CALIB_TX_IQ_PERD; | ||
403 | break; | ||
404 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
405 | index = IWL_CALIB_BASE_BAND; | ||
406 | break; | ||
407 | default: | ||
408 | IWL_ERR(priv, "Unknown calibration notification %d\n", | ||
409 | hdr->op_code); | ||
410 | return; | ||
411 | } | ||
412 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | ||
413 | } | ||
414 | |||
415 | static void iwl5000_rx_calib_complete(struct iwl_priv *priv, | ||
416 | struct iwl_rx_mem_buffer *rxb) | ||
417 | { | ||
418 | IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); | ||
419 | queue_work(priv->workqueue, &priv->restart); | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * ucode | ||
424 | */ | ||
425 | static int iwl5000_load_section(struct iwl_priv *priv, const char *name, | ||
426 | struct fw_desc *image, u32 dst_addr) | ||
427 | { | ||
428 | dma_addr_t phy_addr = image->p_addr; | ||
429 | u32 byte_cnt = image->len; | ||
430 | int ret; | ||
431 | |||
432 | priv->ucode_write_complete = 0; | ||
433 | |||
434 | iwl_write_direct32(priv, | ||
435 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
436 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
437 | |||
438 | iwl_write_direct32(priv, | ||
439 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
440 | |||
441 | iwl_write_direct32(priv, | ||
442 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
443 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
444 | |||
445 | iwl_write_direct32(priv, | ||
446 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
447 | (iwl_get_dma_hi_addr(phy_addr) | ||
448 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
449 | |||
450 | iwl_write_direct32(priv, | ||
451 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
452 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
453 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
454 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
455 | |||
456 | iwl_write_direct32(priv, | ||
457 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
458 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
459 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
460 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
461 | |||
462 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); | ||
463 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
464 | priv->ucode_write_complete, 5 * HZ); | ||
465 | if (ret == -ERESTARTSYS) { | ||
466 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
467 | "to interrupt\n", name); | ||
468 | return ret; | ||
469 | } | ||
470 | if (!ret) { | ||
471 | IWL_ERR(priv, "Could not load the %s uCode section\n", | ||
472 | name); | ||
473 | return -ETIMEDOUT; | ||
474 | } | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int iwl5000_load_given_ucode(struct iwl_priv *priv, | ||
480 | struct fw_desc *inst_image, | ||
481 | struct fw_desc *data_image) | ||
482 | { | ||
483 | int ret = 0; | ||
484 | |||
485 | ret = iwl5000_load_section(priv, "INST", inst_image, | ||
486 | IWL50_RTC_INST_LOWER_BOUND); | ||
487 | if (ret) | ||
488 | return ret; | ||
489 | |||
490 | return iwl5000_load_section(priv, "DATA", data_image, | ||
491 | IWL50_RTC_DATA_LOWER_BOUND); | ||
492 | } | ||
493 | |||
494 | int iwl5000_load_ucode(struct iwl_priv *priv) | ||
495 | { | ||
496 | int ret = 0; | ||
497 | |||
498 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
499 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
500 | IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); | ||
501 | ret = iwl5000_load_given_ucode(priv, | ||
502 | &priv->ucode_init, &priv->ucode_init_data); | ||
503 | if (!ret) { | ||
504 | IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); | ||
505 | priv->ucode_type = UCODE_INIT; | ||
506 | } | ||
507 | } else { | ||
508 | IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " | ||
509 | "Loading runtime ucode...\n"); | ||
510 | ret = iwl5000_load_given_ucode(priv, | ||
511 | &priv->ucode_code, &priv->ucode_data); | ||
512 | if (!ret) { | ||
513 | IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); | ||
514 | priv->ucode_type = UCODE_RT; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | void iwl5000_init_alive_start(struct iwl_priv *priv) | ||
522 | { | ||
523 | int ret = 0; | ||
524 | |||
525 | /* Check alive response for "valid" sign from uCode */ | ||
526 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
527 | /* We had an error bringing up the hardware, so take it | ||
528 | * all the way back down so we can try again */ | ||
529 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
530 | goto restart; | ||
531 | } | ||
532 | |||
533 | /* initialize uCode was loaded... verify inst image. | ||
534 | * This is a paranoid check, because we would not have gotten the | ||
535 | * "initialize" alive if code weren't properly loaded. */ | ||
536 | if (iwl_verify_ucode(priv)) { | ||
537 | /* Runtime instruction load was bad; | ||
538 | * take it all the way back down so we can try again */ | ||
539 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
540 | goto restart; | ||
541 | } | ||
542 | |||
543 | iwl_clear_stations_table(priv); | ||
544 | ret = priv->cfg->ops->lib->alive_notify(priv); | ||
545 | if (ret) { | ||
546 | IWL_WARN(priv, | ||
547 | "Could not complete ALIVE transition: %d\n", ret); | ||
548 | goto restart; | ||
549 | } | ||
550 | |||
551 | iwl5000_send_calib_cfg(priv); | ||
552 | return; | ||
553 | |||
554 | restart: | ||
555 | /* real restart (first load init_ucode) */ | ||
556 | queue_work(priv->workqueue, &priv->restart); | ||
557 | } | ||
558 | |||
559 | static void iwl5000_set_wr_ptrs(struct iwl_priv *priv, | ||
560 | int txq_id, u32 index) | ||
561 | { | ||
562 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
563 | (index & 0xff) | (txq_id << 8)); | ||
564 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); | ||
565 | } | ||
566 | |||
567 | static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, | ||
568 | struct iwl_tx_queue *txq, | ||
569 | int tx_fifo_id, int scd_retry) | ||
570 | { | ||
571 | int txq_id = txq->q.id; | ||
572 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
573 | |||
574 | iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
575 | (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
576 | (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
577 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
578 | IWL50_SCD_QUEUE_STTS_REG_MSK); | ||
579 | |||
580 | txq->sched_retry = scd_retry; | ||
581 | |||
582 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", | ||
583 | active ? "Activate" : "Deactivate", | ||
584 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | ||
585 | } | ||
586 | |||
587 | int iwl5000_alive_notify(struct iwl_priv *priv) | ||
588 | { | ||
589 | u32 a; | ||
590 | unsigned long flags; | ||
591 | int i, chan; | ||
592 | u32 reg_val; | ||
593 | |||
594 | spin_lock_irqsave(&priv->lock, flags); | ||
595 | |||
596 | priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); | ||
597 | a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; | ||
598 | for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; | ||
599 | a += 4) | ||
600 | iwl_write_targ_mem(priv, a, 0); | ||
601 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | ||
602 | a += 4) | ||
603 | iwl_write_targ_mem(priv, a, 0); | ||
604 | for (; a < priv->scd_base_addr + | ||
605 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
606 | iwl_write_targ_mem(priv, a, 0); | ||
607 | |||
608 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | ||
609 | priv->scd_bc_tbls.dma >> 10); | ||
610 | |||
611 | /* Enable DMA channel */ | ||
612 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
613 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
614 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
615 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
616 | |||
617 | /* Update FH chicken bits */ | ||
618 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
619 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
620 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
621 | |||
622 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | ||
623 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | ||
624 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | ||
625 | |||
626 | /* initiate the queues */ | ||
627 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
628 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); | ||
629 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
630 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
631 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
632 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
633 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
634 | sizeof(u32), | ||
635 | ((SCD_WIN_SIZE << | ||
636 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
637 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
638 | ((SCD_FRAME_LIMIT << | ||
639 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
640 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
641 | } | ||
642 | |||
643 | iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, | ||
644 | IWL_MASK(0, priv->hw_params.max_txq_num)); | ||
645 | |||
646 | /* Activate all Tx DMA/FIFO channels */ | ||
647 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | ||
648 | |||
649 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | ||
650 | |||
651 | /* make sure all queue are not stopped */ | ||
652 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
653 | for (i = 0; i < 4; i++) | ||
654 | atomic_set(&priv->queue_stop_count[i], 0); | ||
655 | |||
656 | /* reset to 0 to enable all the queue first */ | ||
657 | priv->txq_ctx_active_msk = 0; | ||
658 | /* map qos queues to fifos one-to-one */ | ||
659 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { | ||
660 | int ac = iwl5000_default_queue_to_tx_fifo[i]; | ||
661 | iwl_txq_ctx_activate(priv, i); | ||
662 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
663 | } | ||
664 | |||
665 | /* | ||
666 | * TODO - need to initialize these queues and map them to FIFOs | ||
667 | * in the loop above, not only mark them as active. We do this | ||
668 | * because we want the first aggregation queue to be queue #10, | ||
669 | * but do not use 8 or 9 otherwise yet. | ||
670 | */ | ||
671 | iwl_txq_ctx_activate(priv, 7); | ||
672 | iwl_txq_ctx_activate(priv, 8); | ||
673 | iwl_txq_ctx_activate(priv, 9); | ||
674 | |||
675 | spin_unlock_irqrestore(&priv->lock, flags); | ||
676 | |||
677 | |||
678 | iwl_send_wimax_coex(priv); | ||
679 | |||
680 | iwl5000_set_Xtal_calib(priv); | ||
681 | iwl_send_calib_results(priv); | ||
682 | |||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | ||
687 | { | 170 | { |
688 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 171 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
689 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 172 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
690 | priv->cfg->num_of_queues = | 173 | priv->cfg->num_of_queues = |
691 | priv->cfg->mod_params->num_of_queues; | 174 | priv->cfg->mod_params->num_of_queues; |
692 | 175 | ||
@@ -694,13 +177,13 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
694 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 177 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
695 | priv->hw_params.scd_bc_tbls_size = | 178 | priv->hw_params.scd_bc_tbls_size = |
696 | priv->cfg->num_of_queues * | 179 | priv->cfg->num_of_queues * |
697 | sizeof(struct iwl5000_scd_bc_tbl); | 180 | sizeof(struct iwlagn_scd_bc_tbl); |
698 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 181 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
699 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 182 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
700 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 183 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
701 | 184 | ||
702 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 185 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
703 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 186 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
704 | 187 | ||
705 | priv->hw_params.max_bsm_size = 0; | 188 | priv->hw_params.max_bsm_size = 0; |
706 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 189 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -717,571 +200,61 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
717 | 200 | ||
718 | /* Set initial sensitivity parameters */ | 201 | /* Set initial sensitivity parameters */ |
719 | /* Set initial calibration set */ | 202 | /* Set initial calibration set */ |
720 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 203 | priv->hw_params.sens = &iwl5000_sensitivity; |
721 | case CSR_HW_REV_TYPE_5150: | 204 | priv->hw_params.calib_init_cfg = |
722 | priv->hw_params.sens = &iwl5150_sensitivity; | 205 | BIT(IWL_CALIB_XTAL) | |
723 | priv->hw_params.calib_init_cfg = | 206 | BIT(IWL_CALIB_LO) | |
724 | BIT(IWL_CALIB_DC) | | 207 | BIT(IWL_CALIB_TX_IQ) | |
725 | BIT(IWL_CALIB_LO) | | 208 | BIT(IWL_CALIB_TX_IQ_PERD) | |
726 | BIT(IWL_CALIB_TX_IQ) | | 209 | BIT(IWL_CALIB_BASE_BAND); |
727 | BIT(IWL_CALIB_BASE_BAND); | ||
728 | |||
729 | break; | ||
730 | default: | ||
731 | priv->hw_params.sens = &iwl5000_sensitivity; | ||
732 | priv->hw_params.calib_init_cfg = | ||
733 | BIT(IWL_CALIB_XTAL) | | ||
734 | BIT(IWL_CALIB_LO) | | ||
735 | BIT(IWL_CALIB_TX_IQ) | | ||
736 | BIT(IWL_CALIB_TX_IQ_PERD) | | ||
737 | BIT(IWL_CALIB_BASE_BAND); | ||
738 | break; | ||
739 | } | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | /** | ||
745 | * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
746 | */ | ||
747 | void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
748 | struct iwl_tx_queue *txq, | ||
749 | u16 byte_cnt) | ||
750 | { | ||
751 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
752 | int write_ptr = txq->q.write_ptr; | ||
753 | int txq_id = txq->q.id; | ||
754 | u8 sec_ctl = 0; | ||
755 | u8 sta_id = 0; | ||
756 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
757 | __le16 bc_ent; | ||
758 | |||
759 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
760 | |||
761 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
762 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | ||
763 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | ||
764 | |||
765 | switch (sec_ctl & TX_CMD_SEC_MSK) { | ||
766 | case TX_CMD_SEC_CCM: | ||
767 | len += CCMP_MIC_LEN; | ||
768 | break; | ||
769 | case TX_CMD_SEC_TKIP: | ||
770 | len += TKIP_ICV_LEN; | ||
771 | break; | ||
772 | case TX_CMD_SEC_WEP: | ||
773 | len += WEP_IV_LEN + WEP_ICV_LEN; | ||
774 | break; | ||
775 | } | ||
776 | } | ||
777 | |||
778 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | ||
779 | |||
780 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
781 | |||
782 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
783 | scd_bc_tbl[txq_id]. | ||
784 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
785 | } | ||
786 | |||
787 | void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
788 | struct iwl_tx_queue *txq) | ||
789 | { | ||
790 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
791 | int txq_id = txq->q.id; | ||
792 | int read_ptr = txq->q.read_ptr; | ||
793 | u8 sta_id = 0; | ||
794 | __le16 bc_ent; | ||
795 | |||
796 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | ||
797 | |||
798 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
799 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | ||
800 | |||
801 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | ||
802 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | ||
803 | |||
804 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
805 | scd_bc_tbl[txq_id]. | ||
806 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | ||
807 | } | ||
808 | |||
809 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
810 | u16 txq_id) | ||
811 | { | ||
812 | u32 tbl_dw_addr; | ||
813 | u32 tbl_dw; | ||
814 | u16 scd_q2ratid; | ||
815 | |||
816 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
817 | |||
818 | tbl_dw_addr = priv->scd_base_addr + | ||
819 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
820 | |||
821 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
822 | |||
823 | if (txq_id & 0x1) | ||
824 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
825 | else | ||
826 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
827 | |||
828 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) | ||
833 | { | ||
834 | /* Simply stop the queue, but don't change any configuration; | ||
835 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
836 | iwl_write_prph(priv, | ||
837 | IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
838 | (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
839 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
840 | } | ||
841 | |||
842 | int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
843 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
844 | { | ||
845 | unsigned long flags; | ||
846 | u16 ra_tid; | ||
847 | |||
848 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | ||
849 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
850 | <= txq_id)) { | ||
851 | IWL_WARN(priv, | ||
852 | "queue number out of range: %d, must be %d to %d\n", | ||
853 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
854 | IWL50_FIRST_AMPDU_QUEUE + | ||
855 | priv->cfg->num_of_ampdu_queues - 1); | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | |||
859 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
860 | |||
861 | /* Modify device's station table to Tx this TID */ | ||
862 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
863 | |||
864 | spin_lock_irqsave(&priv->lock, flags); | ||
865 | |||
866 | /* Stop this Tx queue before configuring it */ | ||
867 | iwl5000_tx_queue_stop_scheduler(priv, txq_id); | ||
868 | |||
869 | /* Map receiver-address / traffic-ID to this queue */ | ||
870 | iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
871 | |||
872 | /* Set this queue as a chain-building queue */ | ||
873 | iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); | ||
874 | |||
875 | /* enable aggregations for the queue */ | ||
876 | iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); | ||
877 | |||
878 | /* Place first TFD at index corresponding to start sequence number. | ||
879 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
880 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
881 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
882 | iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
883 | |||
884 | /* Set up Tx window size and frame limit for this queue */ | ||
885 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
886 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | ||
887 | sizeof(u32), | ||
888 | ((SCD_WIN_SIZE << | ||
889 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
890 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
891 | ((SCD_FRAME_LIMIT << | ||
892 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
893 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
894 | |||
895 | iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
896 | |||
897 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
898 | iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
899 | |||
900 | spin_unlock_irqrestore(&priv->lock, flags); | ||
901 | 210 | ||
902 | return 0; | 211 | return 0; |
903 | } | 212 | } |
904 | 213 | ||
905 | int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | 214 | static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) |
906 | u16 ssn_idx, u8 tx_fifo) | ||
907 | { | 215 | { |
908 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | 216 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
909 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | 217 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
910 | <= txq_id)) { | 218 | priv->cfg->num_of_queues = |
911 | IWL_ERR(priv, | 219 | priv->cfg->mod_params->num_of_queues; |
912 | "queue number out of range: %d, must be %d to %d\n", | ||
913 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
914 | IWL50_FIRST_AMPDU_QUEUE + | ||
915 | priv->cfg->num_of_ampdu_queues - 1); | ||
916 | return -EINVAL; | ||
917 | } | ||
918 | |||
919 | iwl5000_tx_queue_stop_scheduler(priv, txq_id); | ||
920 | |||
921 | iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); | ||
922 | |||
923 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
924 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
925 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
926 | iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
927 | |||
928 | iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
929 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
930 | iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
936 | { | ||
937 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | ||
938 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | ||
939 | memcpy(addsta, cmd, size); | ||
940 | /* resrved in 5000 */ | ||
941 | addsta->rate_n_flags = cpu_to_le16(0); | ||
942 | return size; | ||
943 | } | ||
944 | |||
945 | |||
946 | /* | ||
947 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
948 | * must be called under priv->lock and mac access | ||
949 | */ | ||
950 | void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
951 | { | ||
952 | iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); | ||
953 | } | ||
954 | |||
955 | |||
956 | static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | ||
957 | { | ||
958 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
959 | tx_resp->frame_count) & MAX_SN; | ||
960 | } | ||
961 | |||
962 | static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | ||
963 | struct iwl_ht_agg *agg, | ||
964 | struct iwl5000_tx_resp *tx_resp, | ||
965 | int txq_id, u16 start_idx) | ||
966 | { | ||
967 | u16 status; | ||
968 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
969 | struct ieee80211_tx_info *info = NULL; | ||
970 | struct ieee80211_hdr *hdr = NULL; | ||
971 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
972 | int i, sh, idx; | ||
973 | u16 seq; | ||
974 | |||
975 | if (agg->wait_for_ba) | ||
976 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
977 | |||
978 | agg->frame_count = tx_resp->frame_count; | ||
979 | agg->start_idx = start_idx; | ||
980 | agg->rate_n_flags = rate_n_flags; | ||
981 | agg->bitmap = 0; | ||
982 | |||
983 | /* # frames attempted by Tx command */ | ||
984 | if (agg->frame_count == 1) { | ||
985 | /* Only one frame was attempted; no block-ack will arrive */ | ||
986 | status = le16_to_cpu(frame_status[0].status); | ||
987 | idx = start_idx; | ||
988 | |||
989 | /* FIXME: code repetition */ | ||
990 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
991 | agg->frame_count, agg->start_idx, idx); | ||
992 | |||
993 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
994 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
995 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
996 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
997 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
998 | |||
999 | /* FIXME: code repetition end */ | ||
1000 | |||
1001 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
1002 | status & 0xff, tx_resp->failure_frame); | ||
1003 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
1004 | |||
1005 | agg->wait_for_ba = 0; | ||
1006 | } else { | ||
1007 | /* Two or more frames were attempted; expect block-ack */ | ||
1008 | u64 bitmap = 0; | ||
1009 | int start = agg->start_idx; | ||
1010 | |||
1011 | /* Construct bit-map of pending frames within Tx window */ | ||
1012 | for (i = 0; i < agg->frame_count; i++) { | ||
1013 | u16 sc; | ||
1014 | status = le16_to_cpu(frame_status[i].status); | ||
1015 | seq = le16_to_cpu(frame_status[i].sequence); | ||
1016 | idx = SEQ_TO_INDEX(seq); | ||
1017 | txq_id = SEQ_TO_QUEUE(seq); | ||
1018 | |||
1019 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
1020 | AGG_TX_STATE_ABORT_MSK)) | ||
1021 | continue; | ||
1022 | 220 | ||
1023 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | 221 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
1024 | agg->frame_count, txq_id, idx); | 222 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
223 | priv->hw_params.scd_bc_tbls_size = | ||
224 | priv->cfg->num_of_queues * | ||
225 | sizeof(struct iwlagn_scd_bc_tbl); | ||
226 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
227 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | ||
228 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | ||
1025 | 229 | ||
1026 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | 230 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
1027 | if (!hdr) { | 231 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
1028 | IWL_ERR(priv, | ||
1029 | "BUG_ON idx doesn't point to valid skb" | ||
1030 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
1031 | return -1; | ||
1032 | } | ||
1033 | 232 | ||
1034 | sc = le16_to_cpu(hdr->seq_ctrl); | 233 | priv->hw_params.max_bsm_size = 0; |
1035 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | 234 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
1036 | IWL_ERR(priv, | 235 | BIT(IEEE80211_BAND_5GHZ); |
1037 | "BUG_ON idx doesn't match seq control" | 236 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; |
1038 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
1039 | idx, SEQ_TO_SN(sc), | ||
1040 | hdr->seq_ctrl); | ||
1041 | return -1; | ||
1042 | } | ||
1043 | 237 | ||
1044 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | 238 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
1045 | i, idx, SEQ_TO_SN(sc)); | 239 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); |
240 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
241 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
1046 | 242 | ||
1047 | sh = idx - start; | 243 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) |
1048 | if (sh > 64) { | 244 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); |
1049 | sh = (start - idx) + 0xff; | ||
1050 | bitmap = bitmap << sh; | ||
1051 | sh = 0; | ||
1052 | start = idx; | ||
1053 | } else if (sh < -64) | ||
1054 | sh = 0xff - (start - idx); | ||
1055 | else if (sh < 0) { | ||
1056 | sh = start - idx; | ||
1057 | start = idx; | ||
1058 | bitmap = bitmap << sh; | ||
1059 | sh = 0; | ||
1060 | } | ||
1061 | bitmap |= 1ULL << sh; | ||
1062 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
1063 | start, (unsigned long long)bitmap); | ||
1064 | } | ||
1065 | 245 | ||
1066 | agg->bitmap = bitmap; | 246 | /* Set initial sensitivity parameters */ |
1067 | agg->start_idx = start; | 247 | /* Set initial calibration set */ |
1068 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | 248 | priv->hw_params.sens = &iwl5150_sensitivity; |
1069 | agg->frame_count, agg->start_idx, | 249 | priv->hw_params.calib_init_cfg = |
1070 | (unsigned long long)agg->bitmap); | 250 | BIT(IWL_CALIB_DC) | |
251 | BIT(IWL_CALIB_LO) | | ||
252 | BIT(IWL_CALIB_TX_IQ) | | ||
253 | BIT(IWL_CALIB_BASE_BAND); | ||
1071 | 254 | ||
1072 | if (bitmap) | ||
1073 | agg->wait_for_ba = 1; | ||
1074 | } | ||
1075 | return 0; | 255 | return 0; |
1076 | } | 256 | } |
1077 | 257 | ||
1078 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | ||
1079 | struct iwl_rx_mem_buffer *rxb) | ||
1080 | { | ||
1081 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1082 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
1083 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
1084 | int index = SEQ_TO_INDEX(sequence); | ||
1085 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1086 | struct ieee80211_tx_info *info; | ||
1087 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
1088 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
1089 | int tid; | ||
1090 | int sta_id; | ||
1091 | int freed; | ||
1092 | |||
1093 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
1094 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
1095 | "is out of range [0-%d] %d %d\n", txq_id, | ||
1096 | index, txq->q.n_bd, txq->q.write_ptr, | ||
1097 | txq->q.read_ptr); | ||
1098 | return; | ||
1099 | } | ||
1100 | |||
1101 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
1102 | memset(&info->status, 0, sizeof(info->status)); | ||
1103 | |||
1104 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | ||
1105 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | ||
1106 | |||
1107 | if (txq->sched_retry) { | ||
1108 | const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp); | ||
1109 | struct iwl_ht_agg *agg = NULL; | ||
1110 | |||
1111 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1112 | |||
1113 | iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
1114 | |||
1115 | /* check if BAR is needed */ | ||
1116 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
1117 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1118 | |||
1119 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
1120 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
1121 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " | ||
1122 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
1123 | scd_ssn , index, txq_id, txq->swq_id); | ||
1124 | |||
1125 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
1126 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1127 | |||
1128 | if (priv->mac80211_registered && | ||
1129 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1130 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { | ||
1131 | if (agg->state == IWL_AGG_OFF) | ||
1132 | iwl_wake_queue(priv, txq_id); | ||
1133 | else | ||
1134 | iwl_wake_queue(priv, txq->swq_id); | ||
1135 | } | ||
1136 | } | ||
1137 | } else { | ||
1138 | BUG_ON(txq_id != txq->swq_id); | ||
1139 | |||
1140 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
1141 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
1142 | iwl_hwrate_to_tx_control(priv, | ||
1143 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1144 | info); | ||
1145 | |||
1146 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
1147 | "0x%x retries %d\n", | ||
1148 | txq_id, | ||
1149 | iwl_get_tx_fail_reason(status), status, | ||
1150 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1151 | tx_resp->failure_frame); | ||
1152 | |||
1153 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
1154 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1155 | |||
1156 | if (priv->mac80211_registered && | ||
1157 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
1158 | iwl_wake_queue(priv, txq_id); | ||
1159 | } | ||
1160 | |||
1161 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | ||
1162 | |||
1163 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
1164 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
1165 | } | ||
1166 | |||
1167 | /* Currently 5000 is the superset of everything */ | ||
1168 | u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) | ||
1169 | { | ||
1170 | return len; | ||
1171 | } | ||
1172 | |||
1173 | void iwl5000_setup_deferred_work(struct iwl_priv *priv) | ||
1174 | { | ||
1175 | /* in 5000 the tx power calibration is done in uCode */ | ||
1176 | priv->disable_tx_power_cal = 1; | ||
1177 | } | ||
1178 | |||
1179 | void iwl5000_rx_handler_setup(struct iwl_priv *priv) | ||
1180 | { | ||
1181 | /* init calibration handlers */ | ||
1182 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
1183 | iwl5000_rx_calib_result; | ||
1184 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
1185 | iwl5000_rx_calib_complete; | ||
1186 | priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx; | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | int iwl5000_hw_valid_rtc_data_addr(u32 addr) | ||
1191 | { | ||
1192 | return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && | ||
1193 | (addr < IWL50_RTC_DATA_UPPER_BOUND); | ||
1194 | } | ||
1195 | |||
1196 | static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) | ||
1197 | { | ||
1198 | int ret = 0; | ||
1199 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
1200 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
1201 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
1202 | |||
1203 | if ((rxon1->flags == rxon2->flags) && | ||
1204 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
1205 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
1206 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
1207 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
1208 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
1209 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
1210 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
1211 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
1212 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
1213 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
1214 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
1215 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
1220 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
1221 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
1222 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
1223 | rxon_assoc.reserved1 = 0; | ||
1224 | rxon_assoc.reserved2 = 0; | ||
1225 | rxon_assoc.reserved3 = 0; | ||
1226 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
1227 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
1228 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
1229 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
1230 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
1231 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
1232 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
1233 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
1234 | |||
1235 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
1236 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
1237 | if (ret) | ||
1238 | return ret; | ||
1239 | |||
1240 | return ret; | ||
1241 | } | ||
1242 | int iwl5000_send_tx_power(struct iwl_priv *priv) | ||
1243 | { | ||
1244 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | ||
1245 | u8 tx_ant_cfg_cmd; | ||
1246 | |||
1247 | /* half dBm need to multiply */ | ||
1248 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||
1249 | |||
1250 | if (priv->tx_power_lmt_in_half_dbm && | ||
1251 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
1252 | /* | ||
1253 | * For the newer devices which using enhanced/extend tx power | ||
1254 | * table in EEPROM, the format is in half dBm. driver need to | ||
1255 | * convert to dBm format before report to mac80211. | ||
1256 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
1257 | * lost. driver will perform "round-up" operation before | ||
1258 | * reporting, but it will cause 1/2 dBm tx power over the | ||
1259 | * regulatory limit. Perform the checking here, if the | ||
1260 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
1261 | * half-dBm format), lower the tx power based on EEPROM | ||
1262 | */ | ||
1263 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
1264 | } | ||
1265 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | ||
1266 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | ||
1267 | |||
1268 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
1269 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | ||
1270 | else | ||
1271 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | ||
1272 | |||
1273 | return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, | ||
1274 | sizeof(tx_power_cmd), &tx_power_cmd, | ||
1275 | NULL); | ||
1276 | } | ||
1277 | |||
1278 | void iwl5000_temperature(struct iwl_priv *priv) | ||
1279 | { | ||
1280 | /* store temperature from statistics (in Celsius) */ | ||
1281 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
1282 | iwl_tt_handler(priv); | ||
1283 | } | ||
1284 | |||
1285 | static void iwl5150_temperature(struct iwl_priv *priv) | 258 | static void iwl5150_temperature(struct iwl_priv *priv) |
1286 | { | 259 | { |
1287 | u32 vt = 0; | 260 | u32 vt = 0; |
@@ -1294,100 +267,6 @@ static void iwl5150_temperature(struct iwl_priv *priv) | |||
1294 | iwl_tt_handler(priv); | 267 | iwl_tt_handler(priv); |
1295 | } | 268 | } |
1296 | 269 | ||
1297 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
1298 | int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
1299 | struct iwl_rx_phy_res *rx_resp) | ||
1300 | { | ||
1301 | /* data from PHY/DSP regarding signal strength, etc., | ||
1302 | * contents are always there, not configurable by host | ||
1303 | */ | ||
1304 | struct iwl5000_non_cfg_phy *ncphy = | ||
1305 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
1306 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
1307 | u8 agc; | ||
1308 | |||
1309 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
1310 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
1311 | |||
1312 | /* Find max rssi among 3 possible receivers. | ||
1313 | * These values are measured by the digital signal processor (DSP). | ||
1314 | * They should stay fairly constant even as the signal strength varies, | ||
1315 | * if the radio's automatic gain control (AGC) is working right. | ||
1316 | * AGC value (see below) will provide the "interesting" info. | ||
1317 | */ | ||
1318 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
1319 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
1320 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
1321 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
1322 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
1323 | |||
1324 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
1325 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
1326 | |||
1327 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
1328 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
1329 | |||
1330 | /* dBm = max_rssi dB - agc dB - constant. | ||
1331 | * Higher AGC (higher radio gain) means lower signal. */ | ||
1332 | return max_rssi - agc - IWL49_RSSI_OFFSET; | ||
1333 | } | ||
1334 | |||
1335 | static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
1336 | { | ||
1337 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
1338 | .valid = cpu_to_le32(valid_tx_ant), | ||
1339 | }; | ||
1340 | |||
1341 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
1342 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
1343 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
1344 | sizeof(struct iwl_tx_ant_config_cmd), | ||
1345 | &tx_ant_cmd); | ||
1346 | } else { | ||
1347 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
1348 | return -EOPNOTSUPP; | ||
1349 | } | ||
1350 | } | ||
1351 | |||
1352 | |||
1353 | #define IWL5000_UCODE_GET(item) \ | ||
1354 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
1355 | u32 api_ver) \ | ||
1356 | { \ | ||
1357 | if (api_ver <= 2) \ | ||
1358 | return le32_to_cpu(ucode->u.v1.item); \ | ||
1359 | return le32_to_cpu(ucode->u.v2.item); \ | ||
1360 | } | ||
1361 | |||
1362 | static u32 iwl5000_ucode_get_header_size(u32 api_ver) | ||
1363 | { | ||
1364 | if (api_ver <= 2) | ||
1365 | return UCODE_HEADER_SIZE(1); | ||
1366 | return UCODE_HEADER_SIZE(2); | ||
1367 | } | ||
1368 | |||
1369 | static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
1370 | u32 api_ver) | ||
1371 | { | ||
1372 | if (api_ver <= 2) | ||
1373 | return 0; | ||
1374 | return le32_to_cpu(ucode->u.v2.build); | ||
1375 | } | ||
1376 | |||
1377 | static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
1378 | u32 api_ver) | ||
1379 | { | ||
1380 | if (api_ver <= 2) | ||
1381 | return (u8 *) ucode->u.v1.data; | ||
1382 | return (u8 *) ucode->u.v2.data; | ||
1383 | } | ||
1384 | |||
1385 | IWL5000_UCODE_GET(inst_size); | ||
1386 | IWL5000_UCODE_GET(data_size); | ||
1387 | IWL5000_UCODE_GET(init_size); | ||
1388 | IWL5000_UCODE_GET(init_data_size); | ||
1389 | IWL5000_UCODE_GET(boot_size); | ||
1390 | |||
1391 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 270 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
1392 | { | 271 | { |
1393 | struct iwl5000_channel_switch_cmd cmd; | 272 | struct iwl5000_channel_switch_cmd cmd; |
@@ -1420,54 +299,27 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1420 | return iwl_send_cmd_sync(priv, &hcmd); | 299 | return iwl_send_cmd_sync(priv, &hcmd); |
1421 | } | 300 | } |
1422 | 301 | ||
1423 | struct iwl_hcmd_ops iwl5000_hcmd = { | 302 | static struct iwl_lib_ops iwl5000_lib = { |
1424 | .rxon_assoc = iwl5000_send_rxon_assoc, | ||
1425 | .commit_rxon = iwl_commit_rxon, | ||
1426 | .set_rxon_chain = iwl_set_rxon_chain, | ||
1427 | .set_tx_ant = iwl5000_send_tx_ant_config, | ||
1428 | }; | ||
1429 | |||
1430 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | ||
1431 | .get_hcmd_size = iwl5000_get_hcmd_size, | ||
1432 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | ||
1433 | .gain_computation = iwl5000_gain_computation, | ||
1434 | .chain_noise_reset = iwl5000_chain_noise_reset, | ||
1435 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
1436 | .calc_rssi = iwl5000_calc_rssi, | ||
1437 | }; | ||
1438 | |||
1439 | struct iwl_ucode_ops iwl5000_ucode = { | ||
1440 | .get_header_size = iwl5000_ucode_get_header_size, | ||
1441 | .get_build = iwl5000_ucode_get_build, | ||
1442 | .get_inst_size = iwl5000_ucode_get_inst_size, | ||
1443 | .get_data_size = iwl5000_ucode_get_data_size, | ||
1444 | .get_init_size = iwl5000_ucode_get_init_size, | ||
1445 | .get_init_data_size = iwl5000_ucode_get_init_data_size, | ||
1446 | .get_boot_size = iwl5000_ucode_get_boot_size, | ||
1447 | .get_data = iwl5000_ucode_get_data, | ||
1448 | }; | ||
1449 | |||
1450 | struct iwl_lib_ops iwl5000_lib = { | ||
1451 | .set_hw_params = iwl5000_hw_set_hw_params, | 303 | .set_hw_params = iwl5000_hw_set_hw_params, |
1452 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 304 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
1453 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 305 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
1454 | .txq_set_sched = iwl5000_txq_set_sched, | 306 | .txq_set_sched = iwlagn_txq_set_sched, |
1455 | .txq_agg_enable = iwl5000_txq_agg_enable, | 307 | .txq_agg_enable = iwlagn_txq_agg_enable, |
1456 | .txq_agg_disable = iwl5000_txq_agg_disable, | 308 | .txq_agg_disable = iwlagn_txq_agg_disable, |
1457 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 309 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1458 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 310 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1459 | .txq_init = iwl_hw_tx_queue_init, | 311 | .txq_init = iwl_hw_tx_queue_init, |
1460 | .rx_handler_setup = iwl5000_rx_handler_setup, | 312 | .rx_handler_setup = iwlagn_rx_handler_setup, |
1461 | .setup_deferred_work = iwl5000_setup_deferred_work, | 313 | .setup_deferred_work = iwlagn_setup_deferred_work, |
1462 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 314 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
1463 | .dump_nic_event_log = iwl_dump_nic_event_log, | 315 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1464 | .dump_nic_error_log = iwl_dump_nic_error_log, | 316 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1465 | .dump_csr = iwl_dump_csr, | 317 | .dump_csr = iwl_dump_csr, |
1466 | .dump_fh = iwl_dump_fh, | 318 | .dump_fh = iwl_dump_fh, |
1467 | .load_ucode = iwl5000_load_ucode, | 319 | .load_ucode = iwlagn_load_ucode, |
1468 | .init_alive_start = iwl5000_init_alive_start, | 320 | .init_alive_start = iwlagn_init_alive_start, |
1469 | .alive_notify = iwl5000_alive_notify, | 321 | .alive_notify = iwlagn_alive_notify, |
1470 | .send_tx_power = iwl5000_send_tx_power, | 322 | .send_tx_power = iwlagn_send_tx_power, |
1471 | .update_chain_flags = iwl_update_chain_flags, | 323 | .update_chain_flags = iwl_update_chain_flags, |
1472 | .set_channel_switch = iwl5000_hw_channel_switch, | 324 | .set_channel_switch = iwl5000_hw_channel_switch, |
1473 | .apm_ops = { | 325 | .apm_ops = { |
@@ -1478,50 +330,58 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1478 | }, | 330 | }, |
1479 | .eeprom_ops = { | 331 | .eeprom_ops = { |
1480 | .regulatory_bands = { | 332 | .regulatory_bands = { |
1481 | EEPROM_5000_REG_BAND_1_CHANNELS, | 333 | EEPROM_REG_BAND_1_CHANNELS, |
1482 | EEPROM_5000_REG_BAND_2_CHANNELS, | 334 | EEPROM_REG_BAND_2_CHANNELS, |
1483 | EEPROM_5000_REG_BAND_3_CHANNELS, | 335 | EEPROM_REG_BAND_3_CHANNELS, |
1484 | EEPROM_5000_REG_BAND_4_CHANNELS, | 336 | EEPROM_REG_BAND_4_CHANNELS, |
1485 | EEPROM_5000_REG_BAND_5_CHANNELS, | 337 | EEPROM_REG_BAND_5_CHANNELS, |
1486 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 338 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
1487 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 339 | EEPROM_REG_BAND_52_HT40_CHANNELS |
1488 | }, | 340 | }, |
1489 | .verify_signature = iwlcore_eeprom_verify_signature, | 341 | .verify_signature = iwlcore_eeprom_verify_signature, |
1490 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 342 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
1491 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 343 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
1492 | .calib_version = iwl5000_eeprom_calib_version, | 344 | .calib_version = iwlagn_eeprom_calib_version, |
1493 | .query_addr = iwl5000_eeprom_query_addr, | 345 | .query_addr = iwlagn_eeprom_query_addr, |
1494 | }, | 346 | }, |
1495 | .post_associate = iwl_post_associate, | 347 | .post_associate = iwl_post_associate, |
1496 | .isr = iwl_isr_ict, | 348 | .isr = iwl_isr_ict, |
1497 | .config_ap = iwl_config_ap, | 349 | .config_ap = iwl_config_ap, |
1498 | .temp_ops = { | 350 | .temp_ops = { |
1499 | .temperature = iwl5000_temperature, | 351 | .temperature = iwlagn_temperature, |
1500 | .set_ct_kill = iwl5000_set_ct_threshold, | 352 | .set_ct_kill = iwl5000_set_ct_threshold, |
1501 | }, | 353 | }, |
1502 | .add_bcast_station = iwl_add_bcast_station, | 354 | .manage_ibss_station = iwlagn_manage_ibss_station, |
355 | .debugfs_ops = { | ||
356 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
357 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
358 | .general_stats_read = iwl_ucode_general_stats_read, | ||
359 | }, | ||
360 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
361 | .check_plcp_health = iwl_good_plcp_health, | ||
362 | .check_ack_health = iwl_good_ack_health, | ||
1503 | }; | 363 | }; |
1504 | 364 | ||
1505 | static struct iwl_lib_ops iwl5150_lib = { | 365 | static struct iwl_lib_ops iwl5150_lib = { |
1506 | .set_hw_params = iwl5000_hw_set_hw_params, | 366 | .set_hw_params = iwl5150_hw_set_hw_params, |
1507 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 367 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
1508 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 368 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
1509 | .txq_set_sched = iwl5000_txq_set_sched, | 369 | .txq_set_sched = iwlagn_txq_set_sched, |
1510 | .txq_agg_enable = iwl5000_txq_agg_enable, | 370 | .txq_agg_enable = iwlagn_txq_agg_enable, |
1511 | .txq_agg_disable = iwl5000_txq_agg_disable, | 371 | .txq_agg_disable = iwlagn_txq_agg_disable, |
1512 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 372 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1513 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 373 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1514 | .txq_init = iwl_hw_tx_queue_init, | 374 | .txq_init = iwl_hw_tx_queue_init, |
1515 | .rx_handler_setup = iwl5000_rx_handler_setup, | 375 | .rx_handler_setup = iwlagn_rx_handler_setup, |
1516 | .setup_deferred_work = iwl5000_setup_deferred_work, | 376 | .setup_deferred_work = iwlagn_setup_deferred_work, |
1517 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 377 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
1518 | .dump_nic_event_log = iwl_dump_nic_event_log, | 378 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1519 | .dump_nic_error_log = iwl_dump_nic_error_log, | 379 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1520 | .dump_csr = iwl_dump_csr, | 380 | .dump_csr = iwl_dump_csr, |
1521 | .load_ucode = iwl5000_load_ucode, | 381 | .load_ucode = iwlagn_load_ucode, |
1522 | .init_alive_start = iwl5000_init_alive_start, | 382 | .init_alive_start = iwlagn_init_alive_start, |
1523 | .alive_notify = iwl5000_alive_notify, | 383 | .alive_notify = iwlagn_alive_notify, |
1524 | .send_tx_power = iwl5000_send_tx_power, | 384 | .send_tx_power = iwlagn_send_tx_power, |
1525 | .update_chain_flags = iwl_update_chain_flags, | 385 | .update_chain_flags = iwl_update_chain_flags, |
1526 | .set_channel_switch = iwl5000_hw_channel_switch, | 386 | .set_channel_switch = iwl5000_hw_channel_switch, |
1527 | .apm_ops = { | 387 | .apm_ops = { |
@@ -1532,19 +392,19 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1532 | }, | 392 | }, |
1533 | .eeprom_ops = { | 393 | .eeprom_ops = { |
1534 | .regulatory_bands = { | 394 | .regulatory_bands = { |
1535 | EEPROM_5000_REG_BAND_1_CHANNELS, | 395 | EEPROM_REG_BAND_1_CHANNELS, |
1536 | EEPROM_5000_REG_BAND_2_CHANNELS, | 396 | EEPROM_REG_BAND_2_CHANNELS, |
1537 | EEPROM_5000_REG_BAND_3_CHANNELS, | 397 | EEPROM_REG_BAND_3_CHANNELS, |
1538 | EEPROM_5000_REG_BAND_4_CHANNELS, | 398 | EEPROM_REG_BAND_4_CHANNELS, |
1539 | EEPROM_5000_REG_BAND_5_CHANNELS, | 399 | EEPROM_REG_BAND_5_CHANNELS, |
1540 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 400 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
1541 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 401 | EEPROM_REG_BAND_52_HT40_CHANNELS |
1542 | }, | 402 | }, |
1543 | .verify_signature = iwlcore_eeprom_verify_signature, | 403 | .verify_signature = iwlcore_eeprom_verify_signature, |
1544 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 404 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
1545 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 405 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
1546 | .calib_version = iwl5000_eeprom_calib_version, | 406 | .calib_version = iwlagn_eeprom_calib_version, |
1547 | .query_addr = iwl5000_eeprom_query_addr, | 407 | .query_addr = iwlagn_eeprom_query_addr, |
1548 | }, | 408 | }, |
1549 | .post_associate = iwl_post_associate, | 409 | .post_associate = iwl_post_associate, |
1550 | .isr = iwl_isr_ict, | 410 | .isr = iwl_isr_ict, |
@@ -1553,45 +413,44 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1553 | .temperature = iwl5150_temperature, | 413 | .temperature = iwl5150_temperature, |
1554 | .set_ct_kill = iwl5150_set_ct_threshold, | 414 | .set_ct_kill = iwl5150_set_ct_threshold, |
1555 | }, | 415 | }, |
1556 | .add_bcast_station = iwl_add_bcast_station, | 416 | .manage_ibss_station = iwlagn_manage_ibss_station, |
417 | .debugfs_ops = { | ||
418 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
419 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
420 | .general_stats_read = iwl_ucode_general_stats_read, | ||
421 | }, | ||
422 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
423 | .check_plcp_health = iwl_good_plcp_health, | ||
424 | .check_ack_health = iwl_good_ack_health, | ||
1557 | }; | 425 | }; |
1558 | 426 | ||
1559 | static const struct iwl_ops iwl5000_ops = { | 427 | static const struct iwl_ops iwl5000_ops = { |
1560 | .ucode = &iwl5000_ucode, | ||
1561 | .lib = &iwl5000_lib, | 428 | .lib = &iwl5000_lib, |
1562 | .hcmd = &iwl5000_hcmd, | 429 | .hcmd = &iwlagn_hcmd, |
1563 | .utils = &iwl5000_hcmd_utils, | 430 | .utils = &iwlagn_hcmd_utils, |
1564 | .led = &iwlagn_led_ops, | 431 | .led = &iwlagn_led_ops, |
1565 | }; | 432 | }; |
1566 | 433 | ||
1567 | static const struct iwl_ops iwl5150_ops = { | 434 | static const struct iwl_ops iwl5150_ops = { |
1568 | .ucode = &iwl5000_ucode, | ||
1569 | .lib = &iwl5150_lib, | 435 | .lib = &iwl5150_lib, |
1570 | .hcmd = &iwl5000_hcmd, | 436 | .hcmd = &iwlagn_hcmd, |
1571 | .utils = &iwl5000_hcmd_utils, | 437 | .utils = &iwlagn_hcmd_utils, |
1572 | .led = &iwlagn_led_ops, | 438 | .led = &iwlagn_led_ops, |
1573 | }; | 439 | }; |
1574 | 440 | ||
1575 | struct iwl_mod_params iwl50_mod_params = { | ||
1576 | .amsdu_size_8K = 1, | ||
1577 | .restart_fw = 1, | ||
1578 | /* the rest are 0 by default */ | ||
1579 | }; | ||
1580 | |||
1581 | |||
1582 | struct iwl_cfg iwl5300_agn_cfg = { | 441 | struct iwl_cfg iwl5300_agn_cfg = { |
1583 | .name = "5300AGN", | 442 | .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", |
1584 | .fw_name_pre = IWL5000_FW_PRE, | 443 | .fw_name_pre = IWL5000_FW_PRE, |
1585 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 444 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1586 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 445 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1587 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 446 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1588 | .ops = &iwl5000_ops, | 447 | .ops = &iwl5000_ops, |
1589 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 448 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1590 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 449 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1591 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 450 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1592 | .num_of_queues = IWL50_NUM_QUEUES, | 451 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1593 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 452 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1594 | .mod_params = &iwl50_mod_params, | 453 | .mod_params = &iwlagn_mod_params, |
1595 | .valid_tx_ant = ANT_ABC, | 454 | .valid_tx_ant = ANT_ABC, |
1596 | .valid_rx_ant = ANT_ABC, | 455 | .valid_rx_ant = ANT_ABC, |
1597 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 456 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1603,21 +462,26 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1603 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 462 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1604 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 463 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1605 | .chain_noise_scale = 1000, | 464 | .chain_noise_scale = 1000, |
465 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
466 | .max_event_log_size = 512, | ||
467 | .ucode_tracing = true, | ||
468 | .sensitivity_calib_by_driver = true, | ||
469 | .chain_noise_calib_by_driver = true, | ||
1606 | }; | 470 | }; |
1607 | 471 | ||
1608 | struct iwl_cfg iwl5100_bgn_cfg = { | 472 | struct iwl_cfg iwl5100_bgn_cfg = { |
1609 | .name = "5100BGN", | 473 | .name = "Intel(R) WiFi Link 5100 BGN", |
1610 | .fw_name_pre = IWL5000_FW_PRE, | 474 | .fw_name_pre = IWL5000_FW_PRE, |
1611 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 475 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1612 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 476 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1613 | .sku = IWL_SKU_G|IWL_SKU_N, | 477 | .sku = IWL_SKU_G|IWL_SKU_N, |
1614 | .ops = &iwl5000_ops, | 478 | .ops = &iwl5000_ops, |
1615 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 479 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1616 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 480 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1617 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 481 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1618 | .num_of_queues = IWL50_NUM_QUEUES, | 482 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1619 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 483 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1620 | .mod_params = &iwl50_mod_params, | 484 | .mod_params = &iwlagn_mod_params, |
1621 | .valid_tx_ant = ANT_B, | 485 | .valid_tx_ant = ANT_B, |
1622 | .valid_rx_ant = ANT_AB, | 486 | .valid_rx_ant = ANT_AB, |
1623 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 487 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1629,21 +493,26 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
1629 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 493 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1630 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 494 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1631 | .chain_noise_scale = 1000, | 495 | .chain_noise_scale = 1000, |
496 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
497 | .max_event_log_size = 512, | ||
498 | .ucode_tracing = true, | ||
499 | .sensitivity_calib_by_driver = true, | ||
500 | .chain_noise_calib_by_driver = true, | ||
1632 | }; | 501 | }; |
1633 | 502 | ||
1634 | struct iwl_cfg iwl5100_abg_cfg = { | 503 | struct iwl_cfg iwl5100_abg_cfg = { |
1635 | .name = "5100ABG", | 504 | .name = "Intel(R) WiFi Link 5100 ABG", |
1636 | .fw_name_pre = IWL5000_FW_PRE, | 505 | .fw_name_pre = IWL5000_FW_PRE, |
1637 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 506 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1638 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 507 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1639 | .sku = IWL_SKU_A|IWL_SKU_G, | 508 | .sku = IWL_SKU_A|IWL_SKU_G, |
1640 | .ops = &iwl5000_ops, | 509 | .ops = &iwl5000_ops, |
1641 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 510 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1642 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 511 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1643 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 512 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1644 | .num_of_queues = IWL50_NUM_QUEUES, | 513 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1645 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 514 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1646 | .mod_params = &iwl50_mod_params, | 515 | .mod_params = &iwlagn_mod_params, |
1647 | .valid_tx_ant = ANT_B, | 516 | .valid_tx_ant = ANT_B, |
1648 | .valid_rx_ant = ANT_AB, | 517 | .valid_rx_ant = ANT_AB, |
1649 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 518 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1653,21 +522,26 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1653 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 522 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1654 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 523 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1655 | .chain_noise_scale = 1000, | 524 | .chain_noise_scale = 1000, |
525 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
526 | .max_event_log_size = 512, | ||
527 | .ucode_tracing = true, | ||
528 | .sensitivity_calib_by_driver = true, | ||
529 | .chain_noise_calib_by_driver = true, | ||
1656 | }; | 530 | }; |
1657 | 531 | ||
1658 | struct iwl_cfg iwl5100_agn_cfg = { | 532 | struct iwl_cfg iwl5100_agn_cfg = { |
1659 | .name = "5100AGN", | 533 | .name = "Intel(R) WiFi Link 5100 AGN", |
1660 | .fw_name_pre = IWL5000_FW_PRE, | 534 | .fw_name_pre = IWL5000_FW_PRE, |
1661 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 535 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1662 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 536 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1663 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 537 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1664 | .ops = &iwl5000_ops, | 538 | .ops = &iwl5000_ops, |
1665 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 539 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1666 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 540 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1667 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 541 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1668 | .num_of_queues = IWL50_NUM_QUEUES, | 542 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1669 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 543 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1670 | .mod_params = &iwl50_mod_params, | 544 | .mod_params = &iwlagn_mod_params, |
1671 | .valid_tx_ant = ANT_B, | 545 | .valid_tx_ant = ANT_B, |
1672 | .valid_rx_ant = ANT_AB, | 546 | .valid_rx_ant = ANT_AB, |
1673 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 547 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1679,21 +553,26 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1679 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 553 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1680 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 554 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1681 | .chain_noise_scale = 1000, | 555 | .chain_noise_scale = 1000, |
556 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
557 | .max_event_log_size = 512, | ||
558 | .ucode_tracing = true, | ||
559 | .sensitivity_calib_by_driver = true, | ||
560 | .chain_noise_calib_by_driver = true, | ||
1682 | }; | 561 | }; |
1683 | 562 | ||
1684 | struct iwl_cfg iwl5350_agn_cfg = { | 563 | struct iwl_cfg iwl5350_agn_cfg = { |
1685 | .name = "5350AGN", | 564 | .name = "Intel(R) WiMAX/WiFi Link 5350 AGN", |
1686 | .fw_name_pre = IWL5000_FW_PRE, | 565 | .fw_name_pre = IWL5000_FW_PRE, |
1687 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 566 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1688 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 567 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1689 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 568 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1690 | .ops = &iwl5000_ops, | 569 | .ops = &iwl5000_ops, |
1691 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 570 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1692 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 571 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1693 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 572 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1694 | .num_of_queues = IWL50_NUM_QUEUES, | 573 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1695 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 574 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1696 | .mod_params = &iwl50_mod_params, | 575 | .mod_params = &iwlagn_mod_params, |
1697 | .valid_tx_ant = ANT_ABC, | 576 | .valid_tx_ant = ANT_ABC, |
1698 | .valid_rx_ant = ANT_ABC, | 577 | .valid_rx_ant = ANT_ABC, |
1699 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 578 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1705,21 +584,26 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1705 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 584 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1706 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 585 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1707 | .chain_noise_scale = 1000, | 586 | .chain_noise_scale = 1000, |
587 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
588 | .max_event_log_size = 512, | ||
589 | .ucode_tracing = true, | ||
590 | .sensitivity_calib_by_driver = true, | ||
591 | .chain_noise_calib_by_driver = true, | ||
1708 | }; | 592 | }; |
1709 | 593 | ||
1710 | struct iwl_cfg iwl5150_agn_cfg = { | 594 | struct iwl_cfg iwl5150_agn_cfg = { |
1711 | .name = "5150AGN", | 595 | .name = "Intel(R) WiMAX/WiFi Link 5150 AGN", |
1712 | .fw_name_pre = IWL5150_FW_PRE, | 596 | .fw_name_pre = IWL5150_FW_PRE, |
1713 | .ucode_api_max = IWL5150_UCODE_API_MAX, | 597 | .ucode_api_max = IWL5150_UCODE_API_MAX, |
1714 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 598 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
1715 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 599 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1716 | .ops = &iwl5150_ops, | 600 | .ops = &iwl5150_ops, |
1717 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 601 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1718 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 602 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1719 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 603 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1720 | .num_of_queues = IWL50_NUM_QUEUES, | 604 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1721 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 605 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1722 | .mod_params = &iwl50_mod_params, | 606 | .mod_params = &iwlagn_mod_params, |
1723 | .valid_tx_ant = ANT_A, | 607 | .valid_tx_ant = ANT_A, |
1724 | .valid_rx_ant = ANT_AB, | 608 | .valid_rx_ant = ANT_AB, |
1725 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 609 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1731,21 +615,26 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1731 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 615 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1732 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 616 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1733 | .chain_noise_scale = 1000, | 617 | .chain_noise_scale = 1000, |
618 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
619 | .max_event_log_size = 512, | ||
620 | .ucode_tracing = true, | ||
621 | .sensitivity_calib_by_driver = true, | ||
622 | .chain_noise_calib_by_driver = true, | ||
1734 | }; | 623 | }; |
1735 | 624 | ||
1736 | struct iwl_cfg iwl5150_abg_cfg = { | 625 | struct iwl_cfg iwl5150_abg_cfg = { |
1737 | .name = "5150ABG", | 626 | .name = "Intel(R) WiMAX/WiFi Link 5150 ABG", |
1738 | .fw_name_pre = IWL5150_FW_PRE, | 627 | .fw_name_pre = IWL5150_FW_PRE, |
1739 | .ucode_api_max = IWL5150_UCODE_API_MAX, | 628 | .ucode_api_max = IWL5150_UCODE_API_MAX, |
1740 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 629 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
1741 | .sku = IWL_SKU_A|IWL_SKU_G, | 630 | .sku = IWL_SKU_A|IWL_SKU_G, |
1742 | .ops = &iwl5150_ops, | 631 | .ops = &iwl5150_ops, |
1743 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 632 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1744 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 633 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1745 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 634 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1746 | .num_of_queues = IWL50_NUM_QUEUES, | 635 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1747 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 636 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1748 | .mod_params = &iwl50_mod_params, | 637 | .mod_params = &iwlagn_mod_params, |
1749 | .valid_tx_ant = ANT_A, | 638 | .valid_tx_ant = ANT_A, |
1750 | .valid_rx_ant = ANT_AB, | 639 | .valid_rx_ant = ANT_AB, |
1751 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 640 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1755,20 +644,12 @@ struct iwl_cfg iwl5150_abg_cfg = { | |||
1755 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 644 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1756 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 645 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1757 | .chain_noise_scale = 1000, | 646 | .chain_noise_scale = 1000, |
647 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
648 | .max_event_log_size = 512, | ||
649 | .ucode_tracing = true, | ||
650 | .sensitivity_calib_by_driver = true, | ||
651 | .chain_noise_calib_by_driver = true, | ||
1758 | }; | 652 | }; |
1759 | 653 | ||
1760 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 654 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1761 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | 655 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); |
1762 | |||
1763 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO); | ||
1764 | MODULE_PARM_DESC(swcrypto50, | ||
1765 | "using software crypto engine (default 0 [hardware])\n"); | ||
1766 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO); | ||
1767 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | ||
1768 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO); | ||
1769 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); | ||
1770 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, | ||
1771 | int, S_IRUGO); | ||
1772 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | ||
1773 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO); | ||
1774 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c4844adff92a..9fbf54cd3e1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -42,18 +42,22 @@ | |||
42 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-agn.h" | ||
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 47 | #include "iwl-agn-hw.h" |
47 | #include "iwl-6000-hw.h" | 48 | #include "iwl-6000-hw.h" |
48 | #include "iwl-agn-led.h" | 49 | #include "iwl-agn-led.h" |
50 | #include "iwl-agn-debugfs.h" | ||
49 | 51 | ||
50 | /* Highest firmware API version supported */ | 52 | /* Highest firmware API version supported */ |
51 | #define IWL6000_UCODE_API_MAX 4 | 53 | #define IWL6000_UCODE_API_MAX 4 |
52 | #define IWL6050_UCODE_API_MAX 4 | 54 | #define IWL6050_UCODE_API_MAX 4 |
55 | #define IWL6000G2_UCODE_API_MAX 4 | ||
53 | 56 | ||
54 | /* Lowest firmware API version supported */ | 57 | /* Lowest firmware API version supported */ |
55 | #define IWL6000_UCODE_API_MIN 4 | 58 | #define IWL6000_UCODE_API_MIN 4 |
56 | #define IWL6050_UCODE_API_MIN 4 | 59 | #define IWL6050_UCODE_API_MIN 4 |
60 | #define IWL6000G2_UCODE_API_MIN 4 | ||
57 | 61 | ||
58 | #define IWL6000_FW_PRE "iwlwifi-6000-" | 62 | #define IWL6000_FW_PRE "iwlwifi-6000-" |
59 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" | 63 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" |
@@ -63,6 +67,11 @@ | |||
63 | #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" | 67 | #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" |
64 | #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) | 68 | #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) |
65 | 69 | ||
70 | #define IWL6000G2A_FW_PRE "iwlwifi-6000g2a-" | ||
71 | #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" | ||
72 | #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) | ||
73 | |||
74 | |||
66 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | 75 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) |
67 | { | 76 | { |
68 | /* want Celsius */ | 77 | /* want Celsius */ |
@@ -136,7 +145,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
136 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | 145 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) |
137 | { | 146 | { |
138 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 147 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
139 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 148 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
140 | priv->cfg->num_of_queues = | 149 | priv->cfg->num_of_queues = |
141 | priv->cfg->mod_params->num_of_queues; | 150 | priv->cfg->mod_params->num_of_queues; |
142 | 151 | ||
@@ -144,7 +153,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
144 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 153 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
145 | priv->hw_params.scd_bc_tbls_size = | 154 | priv->hw_params.scd_bc_tbls_size = |
146 | priv->cfg->num_of_queues * | 155 | priv->cfg->num_of_queues * |
147 | sizeof(struct iwl5000_scd_bc_tbl); | 156 | sizeof(struct iwlagn_scd_bc_tbl); |
148 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 157 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
149 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 158 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
150 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 159 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
@@ -168,24 +177,56 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
168 | /* Set initial sensitivity parameters */ | 177 | /* Set initial sensitivity parameters */ |
169 | /* Set initial calibration set */ | 178 | /* Set initial calibration set */ |
170 | priv->hw_params.sens = &iwl6000_sensitivity; | 179 | priv->hw_params.sens = &iwl6000_sensitivity; |
171 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 180 | priv->hw_params.calib_init_cfg = |
172 | case CSR_HW_REV_TYPE_6x50: | 181 | BIT(IWL_CALIB_XTAL) | |
173 | priv->hw_params.calib_init_cfg = | 182 | BIT(IWL_CALIB_LO) | |
174 | BIT(IWL_CALIB_XTAL) | | 183 | BIT(IWL_CALIB_TX_IQ) | |
175 | BIT(IWL_CALIB_DC) | | 184 | BIT(IWL_CALIB_BASE_BAND); |
176 | BIT(IWL_CALIB_LO) | | 185 | |
177 | BIT(IWL_CALIB_TX_IQ) | | 186 | return 0; |
178 | BIT(IWL_CALIB_BASE_BAND); | 187 | } |
179 | 188 | ||
180 | break; | 189 | static int iwl6050_hw_set_hw_params(struct iwl_priv *priv) |
181 | default: | 190 | { |
182 | priv->hw_params.calib_init_cfg = | 191 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
183 | BIT(IWL_CALIB_XTAL) | | 192 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
184 | BIT(IWL_CALIB_LO) | | 193 | priv->cfg->num_of_queues = |
185 | BIT(IWL_CALIB_TX_IQ) | | 194 | priv->cfg->mod_params->num_of_queues; |
186 | BIT(IWL_CALIB_BASE_BAND); | 195 | |
187 | break; | 196 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
188 | } | 197 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
198 | priv->hw_params.scd_bc_tbls_size = | ||
199 | priv->cfg->num_of_queues * | ||
200 | sizeof(struct iwlagn_scd_bc_tbl); | ||
201 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
202 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | ||
203 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | ||
204 | |||
205 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | ||
206 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | ||
207 | |||
208 | priv->hw_params.max_bsm_size = 0; | ||
209 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
210 | BIT(IEEE80211_BAND_5GHZ); | ||
211 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
212 | |||
213 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | ||
214 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | ||
215 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
216 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
217 | |||
218 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | ||
219 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | ||
220 | |||
221 | /* Set initial sensitivity parameters */ | ||
222 | /* Set initial calibration set */ | ||
223 | priv->hw_params.sens = &iwl6000_sensitivity; | ||
224 | priv->hw_params.calib_init_cfg = | ||
225 | BIT(IWL_CALIB_XTAL) | | ||
226 | BIT(IWL_CALIB_DC) | | ||
227 | BIT(IWL_CALIB_LO) | | ||
228 | BIT(IWL_CALIB_TX_IQ) | | ||
229 | BIT(IWL_CALIB_BASE_BAND); | ||
189 | 230 | ||
190 | return 0; | 231 | return 0; |
191 | } | 232 | } |
@@ -225,25 +266,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
225 | 266 | ||
226 | static struct iwl_lib_ops iwl6000_lib = { | 267 | static struct iwl_lib_ops iwl6000_lib = { |
227 | .set_hw_params = iwl6000_hw_set_hw_params, | 268 | .set_hw_params = iwl6000_hw_set_hw_params, |
228 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 269 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
229 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 270 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
230 | .txq_set_sched = iwl5000_txq_set_sched, | 271 | .txq_set_sched = iwlagn_txq_set_sched, |
231 | .txq_agg_enable = iwl5000_txq_agg_enable, | 272 | .txq_agg_enable = iwlagn_txq_agg_enable, |
232 | .txq_agg_disable = iwl5000_txq_agg_disable, | 273 | .txq_agg_disable = iwlagn_txq_agg_disable, |
233 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 274 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
234 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 275 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
235 | .txq_init = iwl_hw_tx_queue_init, | 276 | .txq_init = iwl_hw_tx_queue_init, |
236 | .rx_handler_setup = iwl5000_rx_handler_setup, | 277 | .rx_handler_setup = iwlagn_rx_handler_setup, |
237 | .setup_deferred_work = iwl5000_setup_deferred_work, | 278 | .setup_deferred_work = iwlagn_setup_deferred_work, |
238 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 279 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
239 | .load_ucode = iwl5000_load_ucode, | 280 | .load_ucode = iwlagn_load_ucode, |
240 | .dump_nic_event_log = iwl_dump_nic_event_log, | 281 | .dump_nic_event_log = iwl_dump_nic_event_log, |
241 | .dump_nic_error_log = iwl_dump_nic_error_log, | 282 | .dump_nic_error_log = iwl_dump_nic_error_log, |
242 | .dump_csr = iwl_dump_csr, | 283 | .dump_csr = iwl_dump_csr, |
243 | .dump_fh = iwl_dump_fh, | 284 | .dump_fh = iwl_dump_fh, |
244 | .init_alive_start = iwl5000_init_alive_start, | 285 | .init_alive_start = iwlagn_init_alive_start, |
245 | .alive_notify = iwl5000_alive_notify, | 286 | .alive_notify = iwlagn_alive_notify, |
246 | .send_tx_power = iwl5000_send_tx_power, | 287 | .send_tx_power = iwlagn_send_tx_power, |
247 | .update_chain_flags = iwl_update_chain_flags, | 288 | .update_chain_flags = iwl_update_chain_flags, |
248 | .set_channel_switch = iwl6000_hw_channel_switch, | 289 | .set_channel_switch = iwl6000_hw_channel_switch, |
249 | .apm_ops = { | 290 | .apm_ops = { |
@@ -254,60 +295,67 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
254 | }, | 295 | }, |
255 | .eeprom_ops = { | 296 | .eeprom_ops = { |
256 | .regulatory_bands = { | 297 | .regulatory_bands = { |
257 | EEPROM_5000_REG_BAND_1_CHANNELS, | 298 | EEPROM_REG_BAND_1_CHANNELS, |
258 | EEPROM_5000_REG_BAND_2_CHANNELS, | 299 | EEPROM_REG_BAND_2_CHANNELS, |
259 | EEPROM_5000_REG_BAND_3_CHANNELS, | 300 | EEPROM_REG_BAND_3_CHANNELS, |
260 | EEPROM_5000_REG_BAND_4_CHANNELS, | 301 | EEPROM_REG_BAND_4_CHANNELS, |
261 | EEPROM_5000_REG_BAND_5_CHANNELS, | 302 | EEPROM_REG_BAND_5_CHANNELS, |
262 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 303 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, |
263 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 304 | EEPROM_REG_BAND_52_HT40_CHANNELS |
264 | }, | 305 | }, |
265 | .verify_signature = iwlcore_eeprom_verify_signature, | 306 | .verify_signature = iwlcore_eeprom_verify_signature, |
266 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 307 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
267 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 308 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
268 | .calib_version = iwl5000_eeprom_calib_version, | 309 | .calib_version = iwlagn_eeprom_calib_version, |
269 | .query_addr = iwl5000_eeprom_query_addr, | 310 | .query_addr = iwlagn_eeprom_query_addr, |
270 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | 311 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, |
271 | }, | 312 | }, |
272 | .post_associate = iwl_post_associate, | 313 | .post_associate = iwl_post_associate, |
273 | .isr = iwl_isr_ict, | 314 | .isr = iwl_isr_ict, |
274 | .config_ap = iwl_config_ap, | 315 | .config_ap = iwl_config_ap, |
275 | .temp_ops = { | 316 | .temp_ops = { |
276 | .temperature = iwl5000_temperature, | 317 | .temperature = iwlagn_temperature, |
277 | .set_ct_kill = iwl6000_set_ct_threshold, | 318 | .set_ct_kill = iwl6000_set_ct_threshold, |
278 | }, | 319 | }, |
279 | .add_bcast_station = iwl_add_bcast_station, | 320 | .manage_ibss_station = iwlagn_manage_ibss_station, |
321 | .debugfs_ops = { | ||
322 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
323 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
324 | .general_stats_read = iwl_ucode_general_stats_read, | ||
325 | }, | ||
326 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
327 | .check_plcp_health = iwl_good_plcp_health, | ||
328 | .check_ack_health = iwl_good_ack_health, | ||
280 | }; | 329 | }; |
281 | 330 | ||
282 | static const struct iwl_ops iwl6000_ops = { | 331 | static const struct iwl_ops iwl6000_ops = { |
283 | .ucode = &iwl5000_ucode, | ||
284 | .lib = &iwl6000_lib, | 332 | .lib = &iwl6000_lib, |
285 | .hcmd = &iwl5000_hcmd, | 333 | .hcmd = &iwlagn_hcmd, |
286 | .utils = &iwl5000_hcmd_utils, | 334 | .utils = &iwlagn_hcmd_utils, |
287 | .led = &iwlagn_led_ops, | 335 | .led = &iwlagn_led_ops, |
288 | }; | 336 | }; |
289 | 337 | ||
290 | static struct iwl_lib_ops iwl6050_lib = { | 338 | static struct iwl_lib_ops iwl6050_lib = { |
291 | .set_hw_params = iwl6000_hw_set_hw_params, | 339 | .set_hw_params = iwl6050_hw_set_hw_params, |
292 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 340 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
293 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 341 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
294 | .txq_set_sched = iwl5000_txq_set_sched, | 342 | .txq_set_sched = iwlagn_txq_set_sched, |
295 | .txq_agg_enable = iwl5000_txq_agg_enable, | 343 | .txq_agg_enable = iwlagn_txq_agg_enable, |
296 | .txq_agg_disable = iwl5000_txq_agg_disable, | 344 | .txq_agg_disable = iwlagn_txq_agg_disable, |
297 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 345 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
298 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 346 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
299 | .txq_init = iwl_hw_tx_queue_init, | 347 | .txq_init = iwl_hw_tx_queue_init, |
300 | .rx_handler_setup = iwl5000_rx_handler_setup, | 348 | .rx_handler_setup = iwlagn_rx_handler_setup, |
301 | .setup_deferred_work = iwl5000_setup_deferred_work, | 349 | .setup_deferred_work = iwlagn_setup_deferred_work, |
302 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 350 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
303 | .load_ucode = iwl5000_load_ucode, | 351 | .load_ucode = iwlagn_load_ucode, |
304 | .dump_nic_event_log = iwl_dump_nic_event_log, | 352 | .dump_nic_event_log = iwl_dump_nic_event_log, |
305 | .dump_nic_error_log = iwl_dump_nic_error_log, | 353 | .dump_nic_error_log = iwl_dump_nic_error_log, |
306 | .dump_csr = iwl_dump_csr, | 354 | .dump_csr = iwl_dump_csr, |
307 | .dump_fh = iwl_dump_fh, | 355 | .dump_fh = iwl_dump_fh, |
308 | .init_alive_start = iwl5000_init_alive_start, | 356 | .init_alive_start = iwlagn_init_alive_start, |
309 | .alive_notify = iwl5000_alive_notify, | 357 | .alive_notify = iwlagn_alive_notify, |
310 | .send_tx_power = iwl5000_send_tx_power, | 358 | .send_tx_power = iwlagn_send_tx_power, |
311 | .update_chain_flags = iwl_update_chain_flags, | 359 | .update_chain_flags = iwl_update_chain_flags, |
312 | .set_channel_switch = iwl6000_hw_channel_switch, | 360 | .set_channel_switch = iwl6000_hw_channel_switch, |
313 | .apm_ops = { | 361 | .apm_ops = { |
@@ -318,45 +366,90 @@ static struct iwl_lib_ops iwl6050_lib = { | |||
318 | }, | 366 | }, |
319 | .eeprom_ops = { | 367 | .eeprom_ops = { |
320 | .regulatory_bands = { | 368 | .regulatory_bands = { |
321 | EEPROM_5000_REG_BAND_1_CHANNELS, | 369 | EEPROM_REG_BAND_1_CHANNELS, |
322 | EEPROM_5000_REG_BAND_2_CHANNELS, | 370 | EEPROM_REG_BAND_2_CHANNELS, |
323 | EEPROM_5000_REG_BAND_3_CHANNELS, | 371 | EEPROM_REG_BAND_3_CHANNELS, |
324 | EEPROM_5000_REG_BAND_4_CHANNELS, | 372 | EEPROM_REG_BAND_4_CHANNELS, |
325 | EEPROM_5000_REG_BAND_5_CHANNELS, | 373 | EEPROM_REG_BAND_5_CHANNELS, |
326 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 374 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, |
327 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 375 | EEPROM_REG_BAND_52_HT40_CHANNELS |
328 | }, | 376 | }, |
329 | .verify_signature = iwlcore_eeprom_verify_signature, | 377 | .verify_signature = iwlcore_eeprom_verify_signature, |
330 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 378 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
331 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 379 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
332 | .calib_version = iwl5000_eeprom_calib_version, | 380 | .calib_version = iwlagn_eeprom_calib_version, |
333 | .query_addr = iwl5000_eeprom_query_addr, | 381 | .query_addr = iwlagn_eeprom_query_addr, |
334 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | 382 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, |
335 | }, | 383 | }, |
336 | .post_associate = iwl_post_associate, | 384 | .post_associate = iwl_post_associate, |
337 | .isr = iwl_isr_ict, | 385 | .isr = iwl_isr_ict, |
338 | .config_ap = iwl_config_ap, | 386 | .config_ap = iwl_config_ap, |
339 | .temp_ops = { | 387 | .temp_ops = { |
340 | .temperature = iwl5000_temperature, | 388 | .temperature = iwlagn_temperature, |
341 | .set_ct_kill = iwl6000_set_ct_threshold, | 389 | .set_ct_kill = iwl6000_set_ct_threshold, |
342 | .set_calib_version = iwl6050_set_calib_version, | 390 | .set_calib_version = iwl6050_set_calib_version, |
343 | }, | 391 | }, |
344 | .add_bcast_station = iwl_add_bcast_station, | 392 | .manage_ibss_station = iwlagn_manage_ibss_station, |
393 | .debugfs_ops = { | ||
394 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
395 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
396 | .general_stats_read = iwl_ucode_general_stats_read, | ||
397 | }, | ||
398 | .recover_from_tx_stall = iwl_bg_monitor_recover, | ||
399 | .check_plcp_health = iwl_good_plcp_health, | ||
400 | .check_ack_health = iwl_good_ack_health, | ||
345 | }; | 401 | }; |
346 | 402 | ||
347 | static const struct iwl_ops iwl6050_ops = { | 403 | static const struct iwl_ops iwl6050_ops = { |
348 | .ucode = &iwl5000_ucode, | ||
349 | .lib = &iwl6050_lib, | 404 | .lib = &iwl6050_lib, |
350 | .hcmd = &iwl5000_hcmd, | 405 | .hcmd = &iwlagn_hcmd, |
351 | .utils = &iwl5000_hcmd_utils, | 406 | .utils = &iwlagn_hcmd_utils, |
352 | .led = &iwlagn_led_ops, | 407 | .led = &iwlagn_led_ops, |
353 | }; | 408 | }; |
354 | 409 | ||
410 | |||
411 | struct iwl_cfg iwl6000g2a_2agn_cfg = { | ||
412 | .name = "6000 Series 2x2 AGN Gen2a", | ||
413 | .fw_name_pre = IWL6000G2A_FW_PRE, | ||
414 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, | ||
415 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, | ||
416 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
417 | .ops = &iwl6000_ops, | ||
418 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
419 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, | ||
420 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, | ||
421 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
422 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
423 | .mod_params = &iwlagn_mod_params, | ||
424 | .valid_tx_ant = ANT_AB, | ||
425 | .valid_rx_ant = ANT_AB, | ||
426 | .pll_cfg_val = 0, | ||
427 | .set_l0s = true, | ||
428 | .use_bsm = false, | ||
429 | .pa_type = IWL_PA_SYSTEM, | ||
430 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
431 | .shadow_ram_support = true, | ||
432 | .ht_greenfield_support = true, | ||
433 | .led_compensation = 51, | ||
434 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
435 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
436 | .supports_idle = true, | ||
437 | .adv_thermal_throttle = true, | ||
438 | .support_ct_kill_exit = true, | ||
439 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
440 | .chain_noise_scale = 1000, | ||
441 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
442 | .max_event_log_size = 512, | ||
443 | .ucode_tracing = true, | ||
444 | .sensitivity_calib_by_driver = true, | ||
445 | .chain_noise_calib_by_driver = true, | ||
446 | }; | ||
447 | |||
355 | /* | 448 | /* |
356 | * "i": Internal configuration, use internal Power Amplifier | 449 | * "i": Internal configuration, use internal Power Amplifier |
357 | */ | 450 | */ |
358 | struct iwl_cfg iwl6000i_2agn_cfg = { | 451 | struct iwl_cfg iwl6000i_2agn_cfg = { |
359 | .name = "6000 Series 2x2 AGN", | 452 | .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", |
360 | .fw_name_pre = IWL6000_FW_PRE, | 453 | .fw_name_pre = IWL6000_FW_PRE, |
361 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 454 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
362 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 455 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -364,10 +457,10 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
364 | .ops = &iwl6000_ops, | 457 | .ops = &iwl6000_ops, |
365 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 458 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
366 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 459 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
367 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 460 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
368 | .num_of_queues = IWL50_NUM_QUEUES, | 461 | .num_of_queues = IWLAGN_NUM_QUEUES, |
369 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 462 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
370 | .mod_params = &iwl50_mod_params, | 463 | .mod_params = &iwlagn_mod_params, |
371 | .valid_tx_ant = ANT_BC, | 464 | .valid_tx_ant = ANT_BC, |
372 | .valid_rx_ant = ANT_BC, | 465 | .valid_rx_ant = ANT_BC, |
373 | .pll_cfg_val = 0, | 466 | .pll_cfg_val = 0, |
@@ -385,10 +478,15 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
385 | .support_ct_kill_exit = true, | 478 | .support_ct_kill_exit = true, |
386 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 479 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
387 | .chain_noise_scale = 1000, | 480 | .chain_noise_scale = 1000, |
481 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
482 | .max_event_log_size = 1024, | ||
483 | .ucode_tracing = true, | ||
484 | .sensitivity_calib_by_driver = true, | ||
485 | .chain_noise_calib_by_driver = true, | ||
388 | }; | 486 | }; |
389 | 487 | ||
390 | struct iwl_cfg iwl6000i_2abg_cfg = { | 488 | struct iwl_cfg iwl6000i_2abg_cfg = { |
391 | .name = "6000 Series 2x2 ABG", | 489 | .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG", |
392 | .fw_name_pre = IWL6000_FW_PRE, | 490 | .fw_name_pre = IWL6000_FW_PRE, |
393 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 491 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
394 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 492 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -396,10 +494,10 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
396 | .ops = &iwl6000_ops, | 494 | .ops = &iwl6000_ops, |
397 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 495 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
398 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 496 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
399 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 497 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
400 | .num_of_queues = IWL50_NUM_QUEUES, | 498 | .num_of_queues = IWLAGN_NUM_QUEUES, |
401 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 499 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
402 | .mod_params = &iwl50_mod_params, | 500 | .mod_params = &iwlagn_mod_params, |
403 | .valid_tx_ant = ANT_BC, | 501 | .valid_tx_ant = ANT_BC, |
404 | .valid_rx_ant = ANT_BC, | 502 | .valid_rx_ant = ANT_BC, |
405 | .pll_cfg_val = 0, | 503 | .pll_cfg_val = 0, |
@@ -408,7 +506,6 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
408 | .pa_type = IWL_PA_INTERNAL, | 506 | .pa_type = IWL_PA_INTERNAL, |
409 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 507 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
410 | .shadow_ram_support = true, | 508 | .shadow_ram_support = true, |
411 | .ht_greenfield_support = true, | ||
412 | .led_compensation = 51, | 509 | .led_compensation = 51, |
413 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 510 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
414 | .supports_idle = true, | 511 | .supports_idle = true, |
@@ -416,10 +513,15 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
416 | .support_ct_kill_exit = true, | 513 | .support_ct_kill_exit = true, |
417 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 514 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
418 | .chain_noise_scale = 1000, | 515 | .chain_noise_scale = 1000, |
516 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
517 | .max_event_log_size = 1024, | ||
518 | .ucode_tracing = true, | ||
519 | .sensitivity_calib_by_driver = true, | ||
520 | .chain_noise_calib_by_driver = true, | ||
419 | }; | 521 | }; |
420 | 522 | ||
421 | struct iwl_cfg iwl6000i_2bg_cfg = { | 523 | struct iwl_cfg iwl6000i_2bg_cfg = { |
422 | .name = "6000 Series 2x2 BG", | 524 | .name = "Intel(R) Centrino(R) Advanced-N 6200 BG", |
423 | .fw_name_pre = IWL6000_FW_PRE, | 525 | .fw_name_pre = IWL6000_FW_PRE, |
424 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 526 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
425 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 527 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -427,10 +529,10 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
427 | .ops = &iwl6000_ops, | 529 | .ops = &iwl6000_ops, |
428 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 530 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
429 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 531 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
430 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 532 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
431 | .num_of_queues = IWL50_NUM_QUEUES, | 533 | .num_of_queues = IWLAGN_NUM_QUEUES, |
432 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 534 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
433 | .mod_params = &iwl50_mod_params, | 535 | .mod_params = &iwlagn_mod_params, |
434 | .valid_tx_ant = ANT_BC, | 536 | .valid_tx_ant = ANT_BC, |
435 | .valid_rx_ant = ANT_BC, | 537 | .valid_rx_ant = ANT_BC, |
436 | .pll_cfg_val = 0, | 538 | .pll_cfg_val = 0, |
@@ -439,7 +541,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
439 | .pa_type = IWL_PA_INTERNAL, | 541 | .pa_type = IWL_PA_INTERNAL, |
440 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 542 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
441 | .shadow_ram_support = true, | 543 | .shadow_ram_support = true, |
442 | .ht_greenfield_support = true, | ||
443 | .led_compensation = 51, | 544 | .led_compensation = 51, |
444 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 545 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
445 | .supports_idle = true, | 546 | .supports_idle = true, |
@@ -447,10 +548,15 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
447 | .support_ct_kill_exit = true, | 548 | .support_ct_kill_exit = true, |
448 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 549 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
449 | .chain_noise_scale = 1000, | 550 | .chain_noise_scale = 1000, |
551 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
552 | .max_event_log_size = 1024, | ||
553 | .ucode_tracing = true, | ||
554 | .sensitivity_calib_by_driver = true, | ||
555 | .chain_noise_calib_by_driver = true, | ||
450 | }; | 556 | }; |
451 | 557 | ||
452 | struct iwl_cfg iwl6050_2agn_cfg = { | 558 | struct iwl_cfg iwl6050_2agn_cfg = { |
453 | .name = "6050 Series 2x2 AGN", | 559 | .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN", |
454 | .fw_name_pre = IWL6050_FW_PRE, | 560 | .fw_name_pre = IWL6050_FW_PRE, |
455 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 561 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
456 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 562 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
@@ -458,10 +564,10 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
458 | .ops = &iwl6050_ops, | 564 | .ops = &iwl6050_ops, |
459 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 565 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
460 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 566 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
461 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 567 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
462 | .num_of_queues = IWL50_NUM_QUEUES, | 568 | .num_of_queues = IWLAGN_NUM_QUEUES, |
463 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 569 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
464 | .mod_params = &iwl50_mod_params, | 570 | .mod_params = &iwlagn_mod_params, |
465 | .valid_tx_ant = ANT_AB, | 571 | .valid_tx_ant = ANT_AB, |
466 | .valid_rx_ant = ANT_AB, | 572 | .valid_rx_ant = ANT_AB, |
467 | .pll_cfg_val = 0, | 573 | .pll_cfg_val = 0, |
@@ -479,10 +585,15 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
479 | .support_ct_kill_exit = true, | 585 | .support_ct_kill_exit = true, |
480 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 586 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
481 | .chain_noise_scale = 1500, | 587 | .chain_noise_scale = 1500, |
588 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
589 | .max_event_log_size = 1024, | ||
590 | .ucode_tracing = true, | ||
591 | .sensitivity_calib_by_driver = true, | ||
592 | .chain_noise_calib_by_driver = true, | ||
482 | }; | 593 | }; |
483 | 594 | ||
484 | struct iwl_cfg iwl6050_2abg_cfg = { | 595 | struct iwl_cfg iwl6050_2abg_cfg = { |
485 | .name = "6050 Series 2x2 ABG", | 596 | .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG", |
486 | .fw_name_pre = IWL6050_FW_PRE, | 597 | .fw_name_pre = IWL6050_FW_PRE, |
487 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 598 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
488 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 599 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
@@ -490,10 +601,10 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
490 | .ops = &iwl6050_ops, | 601 | .ops = &iwl6050_ops, |
491 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 602 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
492 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 603 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
493 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 604 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
494 | .num_of_queues = IWL50_NUM_QUEUES, | 605 | .num_of_queues = IWLAGN_NUM_QUEUES, |
495 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 606 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
496 | .mod_params = &iwl50_mod_params, | 607 | .mod_params = &iwlagn_mod_params, |
497 | .valid_tx_ant = ANT_AB, | 608 | .valid_tx_ant = ANT_AB, |
498 | .valid_rx_ant = ANT_AB, | 609 | .valid_rx_ant = ANT_AB, |
499 | .pll_cfg_val = 0, | 610 | .pll_cfg_val = 0, |
@@ -502,7 +613,6 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
502 | .pa_type = IWL_PA_SYSTEM, | 613 | .pa_type = IWL_PA_SYSTEM, |
503 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | 614 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
504 | .shadow_ram_support = true, | 615 | .shadow_ram_support = true, |
505 | .ht_greenfield_support = true, | ||
506 | .led_compensation = 51, | 616 | .led_compensation = 51, |
507 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 617 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
508 | .supports_idle = true, | 618 | .supports_idle = true, |
@@ -510,10 +620,15 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
510 | .support_ct_kill_exit = true, | 620 | .support_ct_kill_exit = true, |
511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 621 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
512 | .chain_noise_scale = 1500, | 622 | .chain_noise_scale = 1500, |
623 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
624 | .max_event_log_size = 1024, | ||
625 | .ucode_tracing = true, | ||
626 | .sensitivity_calib_by_driver = true, | ||
627 | .chain_noise_calib_by_driver = true, | ||
513 | }; | 628 | }; |
514 | 629 | ||
515 | struct iwl_cfg iwl6000_3agn_cfg = { | 630 | struct iwl_cfg iwl6000_3agn_cfg = { |
516 | .name = "6000 Series 3x3 AGN", | 631 | .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN", |
517 | .fw_name_pre = IWL6000_FW_PRE, | 632 | .fw_name_pre = IWL6000_FW_PRE, |
518 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 633 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
519 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 634 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
@@ -521,10 +636,10 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
521 | .ops = &iwl6000_ops, | 636 | .ops = &iwl6000_ops, |
522 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 637 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
523 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 638 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
524 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 639 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
525 | .num_of_queues = IWL50_NUM_QUEUES, | 640 | .num_of_queues = IWLAGN_NUM_QUEUES, |
526 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 641 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
527 | .mod_params = &iwl50_mod_params, | 642 | .mod_params = &iwlagn_mod_params, |
528 | .valid_tx_ant = ANT_ABC, | 643 | .valid_tx_ant = ANT_ABC, |
529 | .valid_rx_ant = ANT_ABC, | 644 | .valid_rx_ant = ANT_ABC, |
530 | .pll_cfg_val = 0, | 645 | .pll_cfg_val = 0, |
@@ -542,7 +657,13 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
542 | .support_ct_kill_exit = true, | 657 | .support_ct_kill_exit = true, |
543 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 658 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
544 | .chain_noise_scale = 1000, | 659 | .chain_noise_scale = 1000, |
660 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
661 | .max_event_log_size = 1024, | ||
662 | .ucode_tracing = true, | ||
663 | .sensitivity_calib_by_driver = true, | ||
664 | .chain_noise_calib_by_driver = true, | ||
545 | }; | 665 | }; |
546 | 666 | ||
547 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 667 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
548 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); | 668 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); |
669 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c new file mode 100644 index 000000000000..48c023b4ca36 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -0,0 +1,850 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include "iwl-agn-debugfs.h" | ||
30 | |||
31 | ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | ||
32 | size_t count, loff_t *ppos) | ||
33 | { | ||
34 | struct iwl_priv *priv = file->private_data; | ||
35 | int pos = 0; | ||
36 | char *buf; | ||
37 | int bufsz = sizeof(struct statistics_rx_phy) * 40 + | ||
38 | sizeof(struct statistics_rx_non_phy) * 40 + | ||
39 | sizeof(struct statistics_rx_ht_phy) * 40 + 400; | ||
40 | ssize_t ret; | ||
41 | struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; | ||
42 | struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; | ||
43 | struct statistics_rx_non_phy *general, *accum_general; | ||
44 | struct statistics_rx_non_phy *delta_general, *max_general; | ||
45 | struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; | ||
46 | |||
47 | if (!iwl_is_alive(priv)) | ||
48 | return -EAGAIN; | ||
49 | |||
50 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
51 | if (!buf) { | ||
52 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
53 | return -ENOMEM; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * the statistic information display here is based on | ||
58 | * the last statistics notification from uCode | ||
59 | * might not reflect the current uCode activity | ||
60 | */ | ||
61 | ofdm = &priv->statistics.rx.ofdm; | ||
62 | cck = &priv->statistics.rx.cck; | ||
63 | general = &priv->statistics.rx.general; | ||
64 | ht = &priv->statistics.rx.ofdm_ht; | ||
65 | accum_ofdm = &priv->accum_statistics.rx.ofdm; | ||
66 | accum_cck = &priv->accum_statistics.rx.cck; | ||
67 | accum_general = &priv->accum_statistics.rx.general; | ||
68 | accum_ht = &priv->accum_statistics.rx.ofdm_ht; | ||
69 | delta_ofdm = &priv->delta_statistics.rx.ofdm; | ||
70 | delta_cck = &priv->delta_statistics.rx.cck; | ||
71 | delta_general = &priv->delta_statistics.rx.general; | ||
72 | delta_ht = &priv->delta_statistics.rx.ofdm_ht; | ||
73 | max_ofdm = &priv->max_delta.rx.ofdm; | ||
74 | max_cck = &priv->max_delta.rx.cck; | ||
75 | max_general = &priv->max_delta.rx.general; | ||
76 | max_ht = &priv->max_delta.rx.ofdm_ht; | ||
77 | |||
78 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
79 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
80 | "acumulative delta max\n", | ||
81 | "Statistics_Rx - OFDM:"); | ||
82 | pos += scnprintf(buf + pos, bufsz - pos, | ||
83 | " %-30s %10u %10u %10u %10u\n", | ||
84 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), | ||
85 | accum_ofdm->ina_cnt, | ||
86 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); | ||
87 | pos += scnprintf(buf + pos, bufsz - pos, | ||
88 | " %-30s %10u %10u %10u %10u\n", | ||
89 | "fina_cnt:", | ||
90 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, | ||
91 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); | ||
92 | pos += scnprintf(buf + pos, bufsz - pos, | ||
93 | " %-30s %10u %10u %10u %10u\n", | ||
94 | "plcp_err:", | ||
95 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, | ||
96 | delta_ofdm->plcp_err, max_ofdm->plcp_err); | ||
97 | pos += scnprintf(buf + pos, bufsz - pos, | ||
98 | " %-30s %10u %10u %10u %10u\n", "crc32_err:", | ||
99 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, | ||
100 | delta_ofdm->crc32_err, max_ofdm->crc32_err); | ||
101 | pos += scnprintf(buf + pos, bufsz - pos, | ||
102 | " %-30s %10u %10u %10u %10u\n", "overrun_err:", | ||
103 | le32_to_cpu(ofdm->overrun_err), | ||
104 | accum_ofdm->overrun_err, delta_ofdm->overrun_err, | ||
105 | max_ofdm->overrun_err); | ||
106 | pos += scnprintf(buf + pos, bufsz - pos, | ||
107 | " %-30s %10u %10u %10u %10u\n", | ||
108 | "early_overrun_err:", | ||
109 | le32_to_cpu(ofdm->early_overrun_err), | ||
110 | accum_ofdm->early_overrun_err, | ||
111 | delta_ofdm->early_overrun_err, | ||
112 | max_ofdm->early_overrun_err); | ||
113 | pos += scnprintf(buf + pos, bufsz - pos, | ||
114 | " %-30s %10u %10u %10u %10u\n", | ||
115 | "crc32_good:", le32_to_cpu(ofdm->crc32_good), | ||
116 | accum_ofdm->crc32_good, delta_ofdm->crc32_good, | ||
117 | max_ofdm->crc32_good); | ||
118 | pos += scnprintf(buf + pos, bufsz - pos, | ||
119 | " %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:", | ||
120 | le32_to_cpu(ofdm->false_alarm_cnt), | ||
121 | accum_ofdm->false_alarm_cnt, | ||
122 | delta_ofdm->false_alarm_cnt, | ||
123 | max_ofdm->false_alarm_cnt); | ||
124 | pos += scnprintf(buf + pos, bufsz - pos, | ||
125 | " %-30s %10u %10u %10u %10u\n", | ||
126 | "fina_sync_err_cnt:", | ||
127 | le32_to_cpu(ofdm->fina_sync_err_cnt), | ||
128 | accum_ofdm->fina_sync_err_cnt, | ||
129 | delta_ofdm->fina_sync_err_cnt, | ||
130 | max_ofdm->fina_sync_err_cnt); | ||
131 | pos += scnprintf(buf + pos, bufsz - pos, | ||
132 | " %-30s %10u %10u %10u %10u\n", "sfd_timeout:", | ||
133 | le32_to_cpu(ofdm->sfd_timeout), | ||
134 | accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, | ||
135 | max_ofdm->sfd_timeout); | ||
136 | pos += scnprintf(buf + pos, bufsz - pos, | ||
137 | " %-30s %10u %10u %10u %10u\n", "fina_timeout:", | ||
138 | le32_to_cpu(ofdm->fina_timeout), | ||
139 | accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, | ||
140 | max_ofdm->fina_timeout); | ||
141 | pos += scnprintf(buf + pos, bufsz - pos, | ||
142 | " %-30s %10u %10u %10u %10u\n", | ||
143 | "unresponded_rts:", | ||
144 | le32_to_cpu(ofdm->unresponded_rts), | ||
145 | accum_ofdm->unresponded_rts, | ||
146 | delta_ofdm->unresponded_rts, | ||
147 | max_ofdm->unresponded_rts); | ||
148 | pos += scnprintf(buf + pos, bufsz - pos, | ||
149 | " %-30s %10u %10u %10u %10u\n", | ||
150 | "rxe_frame_lmt_ovrun:", | ||
151 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | ||
152 | accum_ofdm->rxe_frame_limit_overrun, | ||
153 | delta_ofdm->rxe_frame_limit_overrun, | ||
154 | max_ofdm->rxe_frame_limit_overrun); | ||
155 | pos += scnprintf(buf + pos, bufsz - pos, | ||
156 | " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:", | ||
157 | le32_to_cpu(ofdm->sent_ack_cnt), | ||
158 | accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, | ||
159 | max_ofdm->sent_ack_cnt); | ||
160 | pos += scnprintf(buf + pos, bufsz - pos, | ||
161 | " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:", | ||
162 | le32_to_cpu(ofdm->sent_cts_cnt), | ||
163 | accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, | ||
164 | max_ofdm->sent_cts_cnt); | ||
165 | pos += scnprintf(buf + pos, bufsz - pos, | ||
166 | " %-30s %10u %10u %10u %10u\n", | ||
167 | "sent_ba_rsp_cnt:", | ||
168 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), | ||
169 | accum_ofdm->sent_ba_rsp_cnt, | ||
170 | delta_ofdm->sent_ba_rsp_cnt, | ||
171 | max_ofdm->sent_ba_rsp_cnt); | ||
172 | pos += scnprintf(buf + pos, bufsz - pos, | ||
173 | " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:", | ||
174 | le32_to_cpu(ofdm->dsp_self_kill), | ||
175 | accum_ofdm->dsp_self_kill, | ||
176 | delta_ofdm->dsp_self_kill, | ||
177 | max_ofdm->dsp_self_kill); | ||
178 | pos += scnprintf(buf + pos, bufsz - pos, | ||
179 | " %-30s %10u %10u %10u %10u\n", | ||
180 | "mh_format_err:", | ||
181 | le32_to_cpu(ofdm->mh_format_err), | ||
182 | accum_ofdm->mh_format_err, | ||
183 | delta_ofdm->mh_format_err, | ||
184 | max_ofdm->mh_format_err); | ||
185 | pos += scnprintf(buf + pos, bufsz - pos, | ||
186 | " %-30s %10u %10u %10u %10u\n", | ||
187 | "re_acq_main_rssi_sum:", | ||
188 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), | ||
189 | accum_ofdm->re_acq_main_rssi_sum, | ||
190 | delta_ofdm->re_acq_main_rssi_sum, | ||
191 | max_ofdm->re_acq_main_rssi_sum); | ||
192 | |||
193 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
194 | "acumulative delta max\n", | ||
195 | "Statistics_Rx - CCK:"); | ||
196 | pos += scnprintf(buf + pos, bufsz - pos, | ||
197 | " %-30s %10u %10u %10u %10u\n", | ||
198 | "ina_cnt:", | ||
199 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, | ||
200 | delta_cck->ina_cnt, max_cck->ina_cnt); | ||
201 | pos += scnprintf(buf + pos, bufsz - pos, | ||
202 | " %-30s %10u %10u %10u %10u\n", | ||
203 | "fina_cnt:", | ||
204 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, | ||
205 | delta_cck->fina_cnt, max_cck->fina_cnt); | ||
206 | pos += scnprintf(buf + pos, bufsz - pos, | ||
207 | " %-30s %10u %10u %10u %10u\n", | ||
208 | "plcp_err:", | ||
209 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, | ||
210 | delta_cck->plcp_err, max_cck->plcp_err); | ||
211 | pos += scnprintf(buf + pos, bufsz - pos, | ||
212 | " %-30s %10u %10u %10u %10u\n", | ||
213 | "crc32_err:", | ||
214 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, | ||
215 | delta_cck->crc32_err, max_cck->crc32_err); | ||
216 | pos += scnprintf(buf + pos, bufsz - pos, | ||
217 | " %-30s %10u %10u %10u %10u\n", | ||
218 | "overrun_err:", | ||
219 | le32_to_cpu(cck->overrun_err), | ||
220 | accum_cck->overrun_err, delta_cck->overrun_err, | ||
221 | max_cck->overrun_err); | ||
222 | pos += scnprintf(buf + pos, bufsz - pos, | ||
223 | " %-30s %10u %10u %10u %10u\n", | ||
224 | "early_overrun_err:", | ||
225 | le32_to_cpu(cck->early_overrun_err), | ||
226 | accum_cck->early_overrun_err, | ||
227 | delta_cck->early_overrun_err, | ||
228 | max_cck->early_overrun_err); | ||
229 | pos += scnprintf(buf + pos, bufsz - pos, | ||
230 | " %-30s %10u %10u %10u %10u\n", | ||
231 | "crc32_good:", | ||
232 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, | ||
233 | delta_cck->crc32_good, max_cck->crc32_good); | ||
234 | pos += scnprintf(buf + pos, bufsz - pos, | ||
235 | " %-30s %10u %10u %10u %10u\n", | ||
236 | "false_alarm_cnt:", | ||
237 | le32_to_cpu(cck->false_alarm_cnt), | ||
238 | accum_cck->false_alarm_cnt, | ||
239 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); | ||
240 | pos += scnprintf(buf + pos, bufsz - pos, | ||
241 | " %-30s %10u %10u %10u %10u\n", | ||
242 | "fina_sync_err_cnt:", | ||
243 | le32_to_cpu(cck->fina_sync_err_cnt), | ||
244 | accum_cck->fina_sync_err_cnt, | ||
245 | delta_cck->fina_sync_err_cnt, | ||
246 | max_cck->fina_sync_err_cnt); | ||
247 | pos += scnprintf(buf + pos, bufsz - pos, | ||
248 | " %-30s %10u %10u %10u %10u\n", | ||
249 | "sfd_timeout:", | ||
250 | le32_to_cpu(cck->sfd_timeout), | ||
251 | accum_cck->sfd_timeout, delta_cck->sfd_timeout, | ||
252 | max_cck->sfd_timeout); | ||
253 | pos += scnprintf(buf + pos, bufsz - pos, | ||
254 | " %-30s %10u %10u %10u %10u\n", "fina_timeout:", | ||
255 | le32_to_cpu(cck->fina_timeout), | ||
256 | accum_cck->fina_timeout, delta_cck->fina_timeout, | ||
257 | max_cck->fina_timeout); | ||
258 | pos += scnprintf(buf + pos, bufsz - pos, | ||
259 | " %-30s %10u %10u %10u %10u\n", | ||
260 | "unresponded_rts:", | ||
261 | le32_to_cpu(cck->unresponded_rts), | ||
262 | accum_cck->unresponded_rts, delta_cck->unresponded_rts, | ||
263 | max_cck->unresponded_rts); | ||
264 | pos += scnprintf(buf + pos, bufsz - pos, | ||
265 | " %-30s %10u %10u %10u %10u\n", | ||
266 | "rxe_frame_lmt_ovrun:", | ||
267 | le32_to_cpu(cck->rxe_frame_limit_overrun), | ||
268 | accum_cck->rxe_frame_limit_overrun, | ||
269 | delta_cck->rxe_frame_limit_overrun, | ||
270 | max_cck->rxe_frame_limit_overrun); | ||
271 | pos += scnprintf(buf + pos, bufsz - pos, | ||
272 | " %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:", | ||
273 | le32_to_cpu(cck->sent_ack_cnt), | ||
274 | accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, | ||
275 | max_cck->sent_ack_cnt); | ||
276 | pos += scnprintf(buf + pos, bufsz - pos, | ||
277 | " %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:", | ||
278 | le32_to_cpu(cck->sent_cts_cnt), | ||
279 | accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, | ||
280 | max_cck->sent_cts_cnt); | ||
281 | pos += scnprintf(buf + pos, bufsz - pos, | ||
282 | " %-30s %10u %10u %10u %10u\n", "sent_ba_rsp_cnt:", | ||
283 | le32_to_cpu(cck->sent_ba_rsp_cnt), | ||
284 | accum_cck->sent_ba_rsp_cnt, | ||
285 | delta_cck->sent_ba_rsp_cnt, | ||
286 | max_cck->sent_ba_rsp_cnt); | ||
287 | pos += scnprintf(buf + pos, bufsz - pos, | ||
288 | " %-30s %10u %10u %10u %10u\n", "dsp_self_kill:", | ||
289 | le32_to_cpu(cck->dsp_self_kill), | ||
290 | accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, | ||
291 | max_cck->dsp_self_kill); | ||
292 | pos += scnprintf(buf + pos, bufsz - pos, | ||
293 | " %-30s %10u %10u %10u %10u\n", "mh_format_err:", | ||
294 | le32_to_cpu(cck->mh_format_err), | ||
295 | accum_cck->mh_format_err, delta_cck->mh_format_err, | ||
296 | max_cck->mh_format_err); | ||
297 | pos += scnprintf(buf + pos, bufsz - pos, | ||
298 | " %-30s %10u %10u %10u %10u\n", | ||
299 | "re_acq_main_rssi_sum:", | ||
300 | le32_to_cpu(cck->re_acq_main_rssi_sum), | ||
301 | accum_cck->re_acq_main_rssi_sum, | ||
302 | delta_cck->re_acq_main_rssi_sum, | ||
303 | max_cck->re_acq_main_rssi_sum); | ||
304 | |||
305 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
306 | "acumulative delta max\n", | ||
307 | "Statistics_Rx - GENERAL:"); | ||
308 | pos += scnprintf(buf + pos, bufsz - pos, | ||
309 | " %-30s %10u %10u %10u %10u\n", "bogus_cts:", | ||
310 | le32_to_cpu(general->bogus_cts), | ||
311 | accum_general->bogus_cts, delta_general->bogus_cts, | ||
312 | max_general->bogus_cts); | ||
313 | pos += scnprintf(buf + pos, bufsz - pos, | ||
314 | " %-30s %10u %10u %10u %10u\n", "bogus_ack:", | ||
315 | le32_to_cpu(general->bogus_ack), | ||
316 | accum_general->bogus_ack, delta_general->bogus_ack, | ||
317 | max_general->bogus_ack); | ||
318 | pos += scnprintf(buf + pos, bufsz - pos, | ||
319 | " %-30s %10u %10u %10u %10u\n", | ||
320 | "non_bssid_frames:", | ||
321 | le32_to_cpu(general->non_bssid_frames), | ||
322 | accum_general->non_bssid_frames, | ||
323 | delta_general->non_bssid_frames, | ||
324 | max_general->non_bssid_frames); | ||
325 | pos += scnprintf(buf + pos, bufsz - pos, | ||
326 | " %-30s %10u %10u %10u %10u\n", | ||
327 | "filtered_frames:", | ||
328 | le32_to_cpu(general->filtered_frames), | ||
329 | accum_general->filtered_frames, | ||
330 | delta_general->filtered_frames, | ||
331 | max_general->filtered_frames); | ||
332 | pos += scnprintf(buf + pos, bufsz - pos, | ||
333 | " %-30s %10u %10u %10u %10u\n", | ||
334 | "non_channel_beacons:", | ||
335 | le32_to_cpu(general->non_channel_beacons), | ||
336 | accum_general->non_channel_beacons, | ||
337 | delta_general->non_channel_beacons, | ||
338 | max_general->non_channel_beacons); | ||
339 | pos += scnprintf(buf + pos, bufsz - pos, | ||
340 | " %-30s %10u %10u %10u %10u\n", | ||
341 | "channel_beacons:", | ||
342 | le32_to_cpu(general->channel_beacons), | ||
343 | accum_general->channel_beacons, | ||
344 | delta_general->channel_beacons, | ||
345 | max_general->channel_beacons); | ||
346 | pos += scnprintf(buf + pos, bufsz - pos, | ||
347 | " %-30s %10u %10u %10u %10u\n", | ||
348 | "num_missed_bcon:", | ||
349 | le32_to_cpu(general->num_missed_bcon), | ||
350 | accum_general->num_missed_bcon, | ||
351 | delta_general->num_missed_bcon, | ||
352 | max_general->num_missed_bcon); | ||
353 | pos += scnprintf(buf + pos, bufsz - pos, | ||
354 | " %-30s %10u %10u %10u %10u\n", | ||
355 | "adc_rx_saturation_time:", | ||
356 | le32_to_cpu(general->adc_rx_saturation_time), | ||
357 | accum_general->adc_rx_saturation_time, | ||
358 | delta_general->adc_rx_saturation_time, | ||
359 | max_general->adc_rx_saturation_time); | ||
360 | pos += scnprintf(buf + pos, bufsz - pos, | ||
361 | " %-30s %10u %10u %10u %10u\n", | ||
362 | "ina_detect_search_tm:", | ||
363 | le32_to_cpu(general->ina_detection_search_time), | ||
364 | accum_general->ina_detection_search_time, | ||
365 | delta_general->ina_detection_search_time, | ||
366 | max_general->ina_detection_search_time); | ||
367 | pos += scnprintf(buf + pos, bufsz - pos, | ||
368 | " %-30s %10u %10u %10u %10u\n", | ||
369 | "beacon_silence_rssi_a:", | ||
370 | le32_to_cpu(general->beacon_silence_rssi_a), | ||
371 | accum_general->beacon_silence_rssi_a, | ||
372 | delta_general->beacon_silence_rssi_a, | ||
373 | max_general->beacon_silence_rssi_a); | ||
374 | pos += scnprintf(buf + pos, bufsz - pos, | ||
375 | " %-30s %10u %10u %10u %10u\n", | ||
376 | "beacon_silence_rssi_b:", | ||
377 | le32_to_cpu(general->beacon_silence_rssi_b), | ||
378 | accum_general->beacon_silence_rssi_b, | ||
379 | delta_general->beacon_silence_rssi_b, | ||
380 | max_general->beacon_silence_rssi_b); | ||
381 | pos += scnprintf(buf + pos, bufsz - pos, | ||
382 | " %-30s %10u %10u %10u %10u\n", | ||
383 | "beacon_silence_rssi_c:", | ||
384 | le32_to_cpu(general->beacon_silence_rssi_c), | ||
385 | accum_general->beacon_silence_rssi_c, | ||
386 | delta_general->beacon_silence_rssi_c, | ||
387 | max_general->beacon_silence_rssi_c); | ||
388 | pos += scnprintf(buf + pos, bufsz - pos, | ||
389 | " %-30s %10u %10u %10u %10u\n", | ||
390 | "interference_data_flag:", | ||
391 | le32_to_cpu(general->interference_data_flag), | ||
392 | accum_general->interference_data_flag, | ||
393 | delta_general->interference_data_flag, | ||
394 | max_general->interference_data_flag); | ||
395 | pos += scnprintf(buf + pos, bufsz - pos, | ||
396 | " %-30s %10u %10u %10u %10u\n", | ||
397 | "channel_load:", | ||
398 | le32_to_cpu(general->channel_load), | ||
399 | accum_general->channel_load, | ||
400 | delta_general->channel_load, | ||
401 | max_general->channel_load); | ||
402 | pos += scnprintf(buf + pos, bufsz - pos, | ||
403 | " %-30s %10u %10u %10u %10u\n", | ||
404 | "dsp_false_alarms:", | ||
405 | le32_to_cpu(general->dsp_false_alarms), | ||
406 | accum_general->dsp_false_alarms, | ||
407 | delta_general->dsp_false_alarms, | ||
408 | max_general->dsp_false_alarms); | ||
409 | pos += scnprintf(buf + pos, bufsz - pos, | ||
410 | " %-30s %10u %10u %10u %10u\n", | ||
411 | "beacon_rssi_a:", | ||
412 | le32_to_cpu(general->beacon_rssi_a), | ||
413 | accum_general->beacon_rssi_a, | ||
414 | delta_general->beacon_rssi_a, | ||
415 | max_general->beacon_rssi_a); | ||
416 | pos += scnprintf(buf + pos, bufsz - pos, | ||
417 | " %-30s %10u %10u %10u %10u\n", | ||
418 | "beacon_rssi_b:", | ||
419 | le32_to_cpu(general->beacon_rssi_b), | ||
420 | accum_general->beacon_rssi_b, | ||
421 | delta_general->beacon_rssi_b, | ||
422 | max_general->beacon_rssi_b); | ||
423 | pos += scnprintf(buf + pos, bufsz - pos, | ||
424 | " %-30s %10u %10u %10u %10u\n", | ||
425 | "beacon_rssi_c:", | ||
426 | le32_to_cpu(general->beacon_rssi_c), | ||
427 | accum_general->beacon_rssi_c, | ||
428 | delta_general->beacon_rssi_c, | ||
429 | max_general->beacon_rssi_c); | ||
430 | pos += scnprintf(buf + pos, bufsz - pos, | ||
431 | " %-30s %10u %10u %10u %10u\n", | ||
432 | "beacon_energy_a:", | ||
433 | le32_to_cpu(general->beacon_energy_a), | ||
434 | accum_general->beacon_energy_a, | ||
435 | delta_general->beacon_energy_a, | ||
436 | max_general->beacon_energy_a); | ||
437 | pos += scnprintf(buf + pos, bufsz - pos, | ||
438 | " %-30s %10u %10u %10u %10u\n", | ||
439 | "beacon_energy_b:", | ||
440 | le32_to_cpu(general->beacon_energy_b), | ||
441 | accum_general->beacon_energy_b, | ||
442 | delta_general->beacon_energy_b, | ||
443 | max_general->beacon_energy_b); | ||
444 | pos += scnprintf(buf + pos, bufsz - pos, | ||
445 | " %-30s %10u %10u %10u %10u\n", | ||
446 | "beacon_energy_c:", | ||
447 | le32_to_cpu(general->beacon_energy_c), | ||
448 | accum_general->beacon_energy_c, | ||
449 | delta_general->beacon_energy_c, | ||
450 | max_general->beacon_energy_c); | ||
451 | |||
452 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); | ||
453 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
454 | "acumulative delta max\n", | ||
455 | "Statistics_Rx - OFDM_HT:"); | ||
456 | pos += scnprintf(buf + pos, bufsz - pos, | ||
457 | " %-30s %10u %10u %10u %10u\n", | ||
458 | "plcp_err:", | ||
459 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, | ||
460 | delta_ht->plcp_err, max_ht->plcp_err); | ||
461 | pos += scnprintf(buf + pos, bufsz - pos, | ||
462 | " %-30s %10u %10u %10u %10u\n", | ||
463 | "overrun_err:", | ||
464 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, | ||
465 | delta_ht->overrun_err, max_ht->overrun_err); | ||
466 | pos += scnprintf(buf + pos, bufsz - pos, | ||
467 | " %-30s %10u %10u %10u %10u\n", | ||
468 | "early_overrun_err:", | ||
469 | le32_to_cpu(ht->early_overrun_err), | ||
470 | accum_ht->early_overrun_err, | ||
471 | delta_ht->early_overrun_err, | ||
472 | max_ht->early_overrun_err); | ||
473 | pos += scnprintf(buf + pos, bufsz - pos, | ||
474 | " %-30s %10u %10u %10u %10u\n", | ||
475 | "crc32_good:", | ||
476 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, | ||
477 | delta_ht->crc32_good, max_ht->crc32_good); | ||
478 | pos += scnprintf(buf + pos, bufsz - pos, | ||
479 | " %-30s %10u %10u %10u %10u\n", | ||
480 | "crc32_err:", | ||
481 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, | ||
482 | delta_ht->crc32_err, max_ht->crc32_err); | ||
483 | pos += scnprintf(buf + pos, bufsz - pos, | ||
484 | " %-30s %10u %10u %10u %10u\n", | ||
485 | "mh_format_err:", | ||
486 | le32_to_cpu(ht->mh_format_err), | ||
487 | accum_ht->mh_format_err, | ||
488 | delta_ht->mh_format_err, max_ht->mh_format_err); | ||
489 | pos += scnprintf(buf + pos, bufsz - pos, | ||
490 | " %-30s %10u %10u %10u %10u\n", | ||
491 | "agg_crc32_good:", | ||
492 | le32_to_cpu(ht->agg_crc32_good), | ||
493 | accum_ht->agg_crc32_good, | ||
494 | delta_ht->agg_crc32_good, max_ht->agg_crc32_good); | ||
495 | pos += scnprintf(buf + pos, bufsz - pos, | ||
496 | " %-30s %10u %10u %10u %10u\n", | ||
497 | "agg_mpdu_cnt:", | ||
498 | le32_to_cpu(ht->agg_mpdu_cnt), | ||
499 | accum_ht->agg_mpdu_cnt, | ||
500 | delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); | ||
501 | pos += scnprintf(buf + pos, bufsz - pos, | ||
502 | " %-30s %10u %10u %10u %10u\n", | ||
503 | "agg_cnt:", | ||
504 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, | ||
505 | delta_ht->agg_cnt, max_ht->agg_cnt); | ||
506 | pos += scnprintf(buf + pos, bufsz - pos, | ||
507 | " %-30s %10u %10u %10u %10u\n", | ||
508 | "unsupport_mcs:", | ||
509 | le32_to_cpu(ht->unsupport_mcs), | ||
510 | accum_ht->unsupport_mcs, | ||
511 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); | ||
512 | |||
513 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
514 | kfree(buf); | ||
515 | return ret; | ||
516 | } | ||
517 | |||
518 | ssize_t iwl_ucode_tx_stats_read(struct file *file, | ||
519 | char __user *user_buf, | ||
520 | size_t count, loff_t *ppos) | ||
521 | { | ||
522 | struct iwl_priv *priv = file->private_data; | ||
523 | int pos = 0; | ||
524 | char *buf; | ||
525 | int bufsz = (sizeof(struct statistics_tx) * 48) + 250; | ||
526 | ssize_t ret; | ||
527 | struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; | ||
528 | |||
529 | if (!iwl_is_alive(priv)) | ||
530 | return -EAGAIN; | ||
531 | |||
532 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
533 | if (!buf) { | ||
534 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
535 | return -ENOMEM; | ||
536 | } | ||
537 | |||
538 | /* the statistic information display here is based on | ||
539 | * the last statistics notification from uCode | ||
540 | * might not reflect the current uCode activity | ||
541 | */ | ||
542 | tx = &priv->statistics.tx; | ||
543 | accum_tx = &priv->accum_statistics.tx; | ||
544 | delta_tx = &priv->delta_statistics.tx; | ||
545 | max_tx = &priv->max_delta.tx; | ||
546 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
547 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
548 | "acumulative delta max\n", | ||
549 | "Statistics_Tx:"); | ||
550 | pos += scnprintf(buf + pos, bufsz - pos, | ||
551 | " %-30s %10u %10u %10u %10u\n", | ||
552 | "preamble:", | ||
553 | le32_to_cpu(tx->preamble_cnt), | ||
554 | accum_tx->preamble_cnt, | ||
555 | delta_tx->preamble_cnt, max_tx->preamble_cnt); | ||
556 | pos += scnprintf(buf + pos, bufsz - pos, | ||
557 | " %-30s %10u %10u %10u %10u\n", | ||
558 | "rx_detected_cnt:", | ||
559 | le32_to_cpu(tx->rx_detected_cnt), | ||
560 | accum_tx->rx_detected_cnt, | ||
561 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); | ||
562 | pos += scnprintf(buf + pos, bufsz - pos, | ||
563 | " %-30s %10u %10u %10u %10u\n", | ||
564 | "bt_prio_defer_cnt:", | ||
565 | le32_to_cpu(tx->bt_prio_defer_cnt), | ||
566 | accum_tx->bt_prio_defer_cnt, | ||
567 | delta_tx->bt_prio_defer_cnt, | ||
568 | max_tx->bt_prio_defer_cnt); | ||
569 | pos += scnprintf(buf + pos, bufsz - pos, | ||
570 | " %-30s %10u %10u %10u %10u\n", | ||
571 | "bt_prio_kill_cnt:", | ||
572 | le32_to_cpu(tx->bt_prio_kill_cnt), | ||
573 | accum_tx->bt_prio_kill_cnt, | ||
574 | delta_tx->bt_prio_kill_cnt, | ||
575 | max_tx->bt_prio_kill_cnt); | ||
576 | pos += scnprintf(buf + pos, bufsz - pos, | ||
577 | " %-30s %10u %10u %10u %10u\n", | ||
578 | "few_bytes_cnt:", | ||
579 | le32_to_cpu(tx->few_bytes_cnt), | ||
580 | accum_tx->few_bytes_cnt, | ||
581 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); | ||
582 | pos += scnprintf(buf + pos, bufsz - pos, | ||
583 | " %-30s %10u %10u %10u %10u\n", | ||
584 | "cts_timeout:", | ||
585 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, | ||
586 | delta_tx->cts_timeout, max_tx->cts_timeout); | ||
587 | pos += scnprintf(buf + pos, bufsz - pos, | ||
588 | " %-30s %10u %10u %10u %10u\n", | ||
589 | "ack_timeout:", | ||
590 | le32_to_cpu(tx->ack_timeout), | ||
591 | accum_tx->ack_timeout, | ||
592 | delta_tx->ack_timeout, max_tx->ack_timeout); | ||
593 | pos += scnprintf(buf + pos, bufsz - pos, | ||
594 | " %-30s %10u %10u %10u %10u\n", | ||
595 | "expected_ack_cnt:", | ||
596 | le32_to_cpu(tx->expected_ack_cnt), | ||
597 | accum_tx->expected_ack_cnt, | ||
598 | delta_tx->expected_ack_cnt, | ||
599 | max_tx->expected_ack_cnt); | ||
600 | pos += scnprintf(buf + pos, bufsz - pos, | ||
601 | " %-30s %10u %10u %10u %10u\n", | ||
602 | "actual_ack_cnt:", | ||
603 | le32_to_cpu(tx->actual_ack_cnt), | ||
604 | accum_tx->actual_ack_cnt, | ||
605 | delta_tx->actual_ack_cnt, | ||
606 | max_tx->actual_ack_cnt); | ||
607 | pos += scnprintf(buf + pos, bufsz - pos, | ||
608 | " %-30s %10u %10u %10u %10u\n", | ||
609 | "dump_msdu_cnt:", | ||
610 | le32_to_cpu(tx->dump_msdu_cnt), | ||
611 | accum_tx->dump_msdu_cnt, | ||
612 | delta_tx->dump_msdu_cnt, | ||
613 | max_tx->dump_msdu_cnt); | ||
614 | pos += scnprintf(buf + pos, bufsz - pos, | ||
615 | " %-30s %10u %10u %10u %10u\n", | ||
616 | "abort_nxt_frame_mismatch:", | ||
617 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), | ||
618 | accum_tx->burst_abort_next_frame_mismatch_cnt, | ||
619 | delta_tx->burst_abort_next_frame_mismatch_cnt, | ||
620 | max_tx->burst_abort_next_frame_mismatch_cnt); | ||
621 | pos += scnprintf(buf + pos, bufsz - pos, | ||
622 | " %-30s %10u %10u %10u %10u\n", | ||
623 | "abort_missing_nxt_frame:", | ||
624 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), | ||
625 | accum_tx->burst_abort_missing_next_frame_cnt, | ||
626 | delta_tx->burst_abort_missing_next_frame_cnt, | ||
627 | max_tx->burst_abort_missing_next_frame_cnt); | ||
628 | pos += scnprintf(buf + pos, bufsz - pos, | ||
629 | " %-30s %10u %10u %10u %10u\n", | ||
630 | "cts_timeout_collision:", | ||
631 | le32_to_cpu(tx->cts_timeout_collision), | ||
632 | accum_tx->cts_timeout_collision, | ||
633 | delta_tx->cts_timeout_collision, | ||
634 | max_tx->cts_timeout_collision); | ||
635 | pos += scnprintf(buf + pos, bufsz - pos, | ||
636 | " %-30s %10u %10u %10u %10u\n", | ||
637 | "ack_ba_timeout_collision:", | ||
638 | le32_to_cpu(tx->ack_or_ba_timeout_collision), | ||
639 | accum_tx->ack_or_ba_timeout_collision, | ||
640 | delta_tx->ack_or_ba_timeout_collision, | ||
641 | max_tx->ack_or_ba_timeout_collision); | ||
642 | pos += scnprintf(buf + pos, bufsz - pos, | ||
643 | " %-30s %10u %10u %10u %10u\n", | ||
644 | "agg ba_timeout:", | ||
645 | le32_to_cpu(tx->agg.ba_timeout), | ||
646 | accum_tx->agg.ba_timeout, | ||
647 | delta_tx->agg.ba_timeout, | ||
648 | max_tx->agg.ba_timeout); | ||
649 | pos += scnprintf(buf + pos, bufsz - pos, | ||
650 | " %-30s %10u %10u %10u %10u\n", | ||
651 | "agg ba_resched_frames:", | ||
652 | le32_to_cpu(tx->agg.ba_reschedule_frames), | ||
653 | accum_tx->agg.ba_reschedule_frames, | ||
654 | delta_tx->agg.ba_reschedule_frames, | ||
655 | max_tx->agg.ba_reschedule_frames); | ||
656 | pos += scnprintf(buf + pos, bufsz - pos, | ||
657 | " %-30s %10u %10u %10u %10u\n", | ||
658 | "agg scd_query_agg_frame:", | ||
659 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), | ||
660 | accum_tx->agg.scd_query_agg_frame_cnt, | ||
661 | delta_tx->agg.scd_query_agg_frame_cnt, | ||
662 | max_tx->agg.scd_query_agg_frame_cnt); | ||
663 | pos += scnprintf(buf + pos, bufsz - pos, | ||
664 | " %-30s %10u %10u %10u %10u\n", | ||
665 | "agg scd_query_no_agg:", | ||
666 | le32_to_cpu(tx->agg.scd_query_no_agg), | ||
667 | accum_tx->agg.scd_query_no_agg, | ||
668 | delta_tx->agg.scd_query_no_agg, | ||
669 | max_tx->agg.scd_query_no_agg); | ||
670 | pos += scnprintf(buf + pos, bufsz - pos, | ||
671 | " %-30s %10u %10u %10u %10u\n", | ||
672 | "agg scd_query_agg:", | ||
673 | le32_to_cpu(tx->agg.scd_query_agg), | ||
674 | accum_tx->agg.scd_query_agg, | ||
675 | delta_tx->agg.scd_query_agg, | ||
676 | max_tx->agg.scd_query_agg); | ||
677 | pos += scnprintf(buf + pos, bufsz - pos, | ||
678 | " %-30s %10u %10u %10u %10u\n", | ||
679 | "agg scd_query_mismatch:", | ||
680 | le32_to_cpu(tx->agg.scd_query_mismatch), | ||
681 | accum_tx->agg.scd_query_mismatch, | ||
682 | delta_tx->agg.scd_query_mismatch, | ||
683 | max_tx->agg.scd_query_mismatch); | ||
684 | pos += scnprintf(buf + pos, bufsz - pos, | ||
685 | " %-30s %10u %10u %10u %10u\n", | ||
686 | "agg frame_not_ready:", | ||
687 | le32_to_cpu(tx->agg.frame_not_ready), | ||
688 | accum_tx->agg.frame_not_ready, | ||
689 | delta_tx->agg.frame_not_ready, | ||
690 | max_tx->agg.frame_not_ready); | ||
691 | pos += scnprintf(buf + pos, bufsz - pos, | ||
692 | " %-30s %10u %10u %10u %10u\n", | ||
693 | "agg underrun:", | ||
694 | le32_to_cpu(tx->agg.underrun), | ||
695 | accum_tx->agg.underrun, | ||
696 | delta_tx->agg.underrun, max_tx->agg.underrun); | ||
697 | pos += scnprintf(buf + pos, bufsz - pos, | ||
698 | " %-30s %10u %10u %10u %10u\n", | ||
699 | "agg bt_prio_kill:", | ||
700 | le32_to_cpu(tx->agg.bt_prio_kill), | ||
701 | accum_tx->agg.bt_prio_kill, | ||
702 | delta_tx->agg.bt_prio_kill, | ||
703 | max_tx->agg.bt_prio_kill); | ||
704 | pos += scnprintf(buf + pos, bufsz - pos, | ||
705 | " %-30s %10u %10u %10u %10u\n", | ||
706 | "agg rx_ba_rsp_cnt:", | ||
707 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), | ||
708 | accum_tx->agg.rx_ba_rsp_cnt, | ||
709 | delta_tx->agg.rx_ba_rsp_cnt, | ||
710 | max_tx->agg.rx_ba_rsp_cnt); | ||
711 | |||
712 | if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | ||
713 | pos += scnprintf(buf + pos, bufsz - pos, | ||
714 | "tx power: (1/2 dB step)\n"); | ||
715 | if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a) | ||
716 | pos += scnprintf(buf + pos, bufsz - pos, | ||
717 | "\tantenna A: 0x%X\n", | ||
718 | tx->tx_power.ant_a); | ||
719 | if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b) | ||
720 | pos += scnprintf(buf + pos, bufsz - pos, | ||
721 | "\tantenna B: 0x%X\n", | ||
722 | tx->tx_power.ant_b); | ||
723 | if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c) | ||
724 | pos += scnprintf(buf + pos, bufsz - pos, | ||
725 | "\tantenna C: 0x%X\n", | ||
726 | tx->tx_power.ant_c); | ||
727 | } | ||
728 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
729 | kfree(buf); | ||
730 | return ret; | ||
731 | } | ||
732 | |||
733 | ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | ||
734 | size_t count, loff_t *ppos) | ||
735 | { | ||
736 | struct iwl_priv *priv = file->private_data; | ||
737 | int pos = 0; | ||
738 | char *buf; | ||
739 | int bufsz = sizeof(struct statistics_general) * 10 + 300; | ||
740 | ssize_t ret; | ||
741 | struct statistics_general *general, *accum_general; | ||
742 | struct statistics_general *delta_general, *max_general; | ||
743 | struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; | ||
744 | struct statistics_div *div, *accum_div, *delta_div, *max_div; | ||
745 | |||
746 | if (!iwl_is_alive(priv)) | ||
747 | return -EAGAIN; | ||
748 | |||
749 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
750 | if (!buf) { | ||
751 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
752 | return -ENOMEM; | ||
753 | } | ||
754 | |||
755 | /* the statistic information display here is based on | ||
756 | * the last statistics notification from uCode | ||
757 | * might not reflect the current uCode activity | ||
758 | */ | ||
759 | general = &priv->statistics.general; | ||
760 | dbg = &priv->statistics.general.dbg; | ||
761 | div = &priv->statistics.general.div; | ||
762 | accum_general = &priv->accum_statistics.general; | ||
763 | delta_general = &priv->delta_statistics.general; | ||
764 | max_general = &priv->max_delta.general; | ||
765 | accum_dbg = &priv->accum_statistics.general.dbg; | ||
766 | delta_dbg = &priv->delta_statistics.general.dbg; | ||
767 | max_dbg = &priv->max_delta.general.dbg; | ||
768 | accum_div = &priv->accum_statistics.general.div; | ||
769 | delta_div = &priv->delta_statistics.general.div; | ||
770 | max_div = &priv->max_delta.general.div; | ||
771 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
772 | pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" | ||
773 | "acumulative delta max\n", | ||
774 | "Statistics_General:"); | ||
775 | pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n", | ||
776 | "temperature:", | ||
777 | le32_to_cpu(general->temperature)); | ||
778 | pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n", | ||
779 | "temperature_m:", | ||
780 | le32_to_cpu(general->temperature_m)); | ||
781 | pos += scnprintf(buf + pos, bufsz - pos, | ||
782 | " %-30s %10u %10u %10u %10u\n", | ||
783 | "burst_check:", | ||
784 | le32_to_cpu(dbg->burst_check), | ||
785 | accum_dbg->burst_check, | ||
786 | delta_dbg->burst_check, max_dbg->burst_check); | ||
787 | pos += scnprintf(buf + pos, bufsz - pos, | ||
788 | " %-30s %10u %10u %10u %10u\n", | ||
789 | "burst_count:", | ||
790 | le32_to_cpu(dbg->burst_count), | ||
791 | accum_dbg->burst_count, | ||
792 | delta_dbg->burst_count, max_dbg->burst_count); | ||
793 | pos += scnprintf(buf + pos, bufsz - pos, | ||
794 | " %-30s %10u %10u %10u %10u\n", | ||
795 | "sleep_time:", | ||
796 | le32_to_cpu(general->sleep_time), | ||
797 | accum_general->sleep_time, | ||
798 | delta_general->sleep_time, max_general->sleep_time); | ||
799 | pos += scnprintf(buf + pos, bufsz - pos, | ||
800 | " %-30s %10u %10u %10u %10u\n", | ||
801 | "slots_out:", | ||
802 | le32_to_cpu(general->slots_out), | ||
803 | accum_general->slots_out, | ||
804 | delta_general->slots_out, max_general->slots_out); | ||
805 | pos += scnprintf(buf + pos, bufsz - pos, | ||
806 | " %-30s %10u %10u %10u %10u\n", | ||
807 | "slots_idle:", | ||
808 | le32_to_cpu(general->slots_idle), | ||
809 | accum_general->slots_idle, | ||
810 | delta_general->slots_idle, max_general->slots_idle); | ||
811 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | ||
812 | le32_to_cpu(general->ttl_timestamp)); | ||
813 | pos += scnprintf(buf + pos, bufsz - pos, | ||
814 | " %-30s %10u %10u %10u %10u\n", | ||
815 | "tx_on_a:", | ||
816 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, | ||
817 | delta_div->tx_on_a, max_div->tx_on_a); | ||
818 | pos += scnprintf(buf + pos, bufsz - pos, | ||
819 | " %-30s %10u %10u %10u %10u\n", | ||
820 | "tx_on_b:", | ||
821 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, | ||
822 | delta_div->tx_on_b, max_div->tx_on_b); | ||
823 | pos += scnprintf(buf + pos, bufsz - pos, | ||
824 | " %-30s %10u %10u %10u %10u\n", | ||
825 | "exec_time:", | ||
826 | le32_to_cpu(div->exec_time), accum_div->exec_time, | ||
827 | delta_div->exec_time, max_div->exec_time); | ||
828 | pos += scnprintf(buf + pos, bufsz - pos, | ||
829 | " %-30s %10u %10u %10u %10u\n", | ||
830 | "probe_time:", | ||
831 | le32_to_cpu(div->probe_time), accum_div->probe_time, | ||
832 | delta_div->probe_time, max_div->probe_time); | ||
833 | pos += scnprintf(buf + pos, bufsz - pos, | ||
834 | " %-30s %10u %10u %10u %10u\n", | ||
835 | "rx_enable_counter:", | ||
836 | le32_to_cpu(general->rx_enable_counter), | ||
837 | accum_general->rx_enable_counter, | ||
838 | delta_general->rx_enable_counter, | ||
839 | max_general->rx_enable_counter); | ||
840 | pos += scnprintf(buf + pos, bufsz - pos, | ||
841 | " %-30s %10u %10u %10u %10u\n", | ||
842 | "num_of_sos_states:", | ||
843 | le32_to_cpu(general->num_of_sos_states), | ||
844 | accum_general->num_of_sos_states, | ||
845 | delta_general->num_of_sos_states, | ||
846 | max_general->num_of_sos_states); | ||
847 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
848 | kfree(buf); | ||
849 | return ret; | ||
850 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h new file mode 100644 index 000000000000..59b1f25f0d85 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include "iwl-dev.h" | ||
30 | #include "iwl-core.h" | ||
31 | #include "iwl-debug.h" | ||
32 | |||
33 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
34 | ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | ||
35 | size_t count, loff_t *ppos); | ||
36 | ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, | ||
37 | size_t count, loff_t *ppos); | ||
38 | ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | ||
39 | size_t count, loff_t *ppos); | ||
40 | #else | ||
41 | static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | ||
42 | size_t count, loff_t *ppos) | ||
43 | { | ||
44 | return 0; | ||
45 | } | ||
46 | static ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, | ||
47 | size_t count, loff_t *ppos) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | ||
52 | size_t count, loff_t *ppos) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c new file mode 100644 index 000000000000..44ef5d93befc --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-agn.h" | ||
39 | |||
40 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | ||
41 | { | ||
42 | int ret = 0; | ||
43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
44 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
45 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
46 | |||
47 | if ((rxon1->flags == rxon2->flags) && | ||
48 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
49 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
50 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
51 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
52 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
53 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
54 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
55 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
56 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
57 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
58 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
59 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
64 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
65 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
66 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
67 | rxon_assoc.reserved1 = 0; | ||
68 | rxon_assoc.reserved2 = 0; | ||
69 | rxon_assoc.reserved3 = 0; | ||
70 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
71 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
72 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
73 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
74 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
75 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
76 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
77 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
78 | |||
79 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
80 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
88 | { | ||
89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
90 | .valid = cpu_to_le32(valid_tx_ant), | ||
91 | }; | ||
92 | |||
93 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
94 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
95 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
96 | sizeof(struct iwl_tx_ant_config_cmd), | ||
97 | &tx_ant_cmd); | ||
98 | } else { | ||
99 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
100 | return -EOPNOTSUPP; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | /* Currently this is the superset of everything */ | ||
105 | static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) | ||
106 | { | ||
107 | return len; | ||
108 | } | ||
109 | |||
110 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
111 | { | ||
112 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | ||
113 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | ||
114 | memcpy(addsta, cmd, size); | ||
115 | /* resrved in 5000 */ | ||
116 | addsta->rate_n_flags = cpu_to_le16(0); | ||
117 | return size; | ||
118 | } | ||
119 | |||
120 | static void iwlagn_gain_computation(struct iwl_priv *priv, | ||
121 | u32 average_noise[NUM_RX_CHAINS], | ||
122 | u16 min_average_noise_antenna_i, | ||
123 | u32 min_average_noise, | ||
124 | u8 default_chain) | ||
125 | { | ||
126 | int i; | ||
127 | s32 delta_g; | ||
128 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
129 | |||
130 | /* | ||
131 | * Find Gain Code for the chains based on "default chain" | ||
132 | */ | ||
133 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
134 | if ((data->disconn_array[i])) { | ||
135 | data->delta_gain_code[i] = 0; | ||
136 | continue; | ||
137 | } | ||
138 | |||
139 | delta_g = (priv->cfg->chain_noise_scale * | ||
140 | ((s32)average_noise[default_chain] - | ||
141 | (s32)average_noise[i])) / 1500; | ||
142 | |||
143 | /* bound gain by 2 bits value max, 3rd bit is sign */ | ||
144 | data->delta_gain_code[i] = | ||
145 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
146 | |||
147 | if (delta_g < 0) | ||
148 | /* | ||
149 | * set negative sign ... | ||
150 | * note to Intel developers: This is uCode API format, | ||
151 | * not the format of any internal device registers. | ||
152 | * Do not change this format for e.g. 6050 or similar | ||
153 | * devices. Change format only if more resolution | ||
154 | * (i.e. more than 2 bits magnitude) is needed. | ||
155 | */ | ||
156 | data->delta_gain_code[i] |= (1 << 2); | ||
157 | } | ||
158 | |||
159 | IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", | ||
160 | data->delta_gain_code[1], data->delta_gain_code[2]); | ||
161 | |||
162 | if (!data->radio_write) { | ||
163 | struct iwl_calib_chain_noise_gain_cmd cmd; | ||
164 | |||
165 | memset(&cmd, 0, sizeof(cmd)); | ||
166 | |||
167 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | ||
168 | cmd.hdr.first_group = 0; | ||
169 | cmd.hdr.groups_num = 1; | ||
170 | cmd.hdr.data_valid = 1; | ||
171 | cmd.delta_gain_1 = data->delta_gain_code[1]; | ||
172 | cmd.delta_gain_2 = data->delta_gain_code[2]; | ||
173 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | ||
174 | sizeof(cmd), &cmd, NULL); | ||
175 | |||
176 | data->radio_write = 1; | ||
177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
178 | } | ||
179 | |||
180 | data->chain_noise_a = 0; | ||
181 | data->chain_noise_b = 0; | ||
182 | data->chain_noise_c = 0; | ||
183 | data->chain_signal_a = 0; | ||
184 | data->chain_signal_b = 0; | ||
185 | data->chain_signal_c = 0; | ||
186 | data->beacon_count = 0; | ||
187 | } | ||
188 | |||
189 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | ||
190 | { | ||
191 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
192 | int ret; | ||
193 | |||
194 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | ||
195 | struct iwl_calib_chain_noise_reset_cmd cmd; | ||
196 | memset(&cmd, 0, sizeof(cmd)); | ||
197 | |||
198 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | ||
199 | cmd.hdr.first_group = 0; | ||
200 | cmd.hdr.groups_num = 1; | ||
201 | cmd.hdr.data_valid = 1; | ||
202 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
203 | sizeof(cmd), &cmd); | ||
204 | if (ret) | ||
205 | IWL_ERR(priv, | ||
206 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
207 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
208 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
213 | __le32 *tx_flags) | ||
214 | { | ||
215 | if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
216 | (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
217 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
218 | else | ||
219 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
220 | } | ||
221 | |||
222 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
223 | static int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
224 | struct iwl_rx_phy_res *rx_resp) | ||
225 | { | ||
226 | /* data from PHY/DSP regarding signal strength, etc., | ||
227 | * contents are always there, not configurable by host | ||
228 | */ | ||
229 | struct iwl5000_non_cfg_phy *ncphy = | ||
230 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
231 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
232 | u8 agc; | ||
233 | |||
234 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
235 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
236 | |||
237 | /* Find max rssi among 3 possible receivers. | ||
238 | * These values are measured by the digital signal processor (DSP). | ||
239 | * They should stay fairly constant even as the signal strength varies, | ||
240 | * if the radio's automatic gain control (AGC) is working right. | ||
241 | * AGC value (see below) will provide the "interesting" info. | ||
242 | */ | ||
243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
244 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
245 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
246 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
247 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
248 | |||
249 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
250 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
251 | |||
252 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
253 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
254 | |||
255 | /* dBm = max_rssi dB - agc dB - constant. | ||
256 | * Higher AGC (higher radio gain) means lower signal. */ | ||
257 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | ||
258 | } | ||
259 | |||
260 | struct iwl_hcmd_ops iwlagn_hcmd = { | ||
261 | .rxon_assoc = iwlagn_send_rxon_assoc, | ||
262 | .commit_rxon = iwl_commit_rxon, | ||
263 | .set_rxon_chain = iwl_set_rxon_chain, | ||
264 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
265 | .send_bt_config = iwl_send_bt_config, | ||
266 | }; | ||
267 | |||
268 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | ||
269 | .get_hcmd_size = iwlagn_get_hcmd_size, | ||
270 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | ||
271 | .gain_computation = iwlagn_gain_computation, | ||
272 | .chain_noise_reset = iwlagn_chain_noise_reset, | ||
273 | .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag, | ||
274 | .calc_rssi = iwlagn_calc_rssi, | ||
275 | .request_scan = iwlagn_request_scan, | ||
276 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h new file mode 100644 index 000000000000..f9a3fbb6338f --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | /* | ||
64 | * Please use this file (iwl-agn-hw.h) only for hardware-related definitions. | ||
65 | */ | ||
66 | |||
67 | #ifndef __iwl_agn_hw_h__ | ||
68 | #define __iwl_agn_hw_h__ | ||
69 | |||
70 | #define IWLAGN_RTC_INST_LOWER_BOUND (0x000000) | ||
71 | #define IWLAGN_RTC_INST_UPPER_BOUND (0x020000) | ||
72 | |||
73 | #define IWLAGN_RTC_DATA_LOWER_BOUND (0x800000) | ||
74 | #define IWLAGN_RTC_DATA_UPPER_BOUND (0x80C000) | ||
75 | |||
76 | #define IWLAGN_RTC_INST_SIZE (IWLAGN_RTC_INST_UPPER_BOUND - \ | ||
77 | IWLAGN_RTC_INST_LOWER_BOUND) | ||
78 | #define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \ | ||
79 | IWLAGN_RTC_DATA_LOWER_BOUND) | ||
80 | |||
81 | /* RSSI to dBm */ | ||
82 | #define IWLAGN_RSSI_OFFSET 44 | ||
83 | |||
84 | /* PCI registers */ | ||
85 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
86 | |||
87 | /* PCI register values */ | ||
88 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
89 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
90 | |||
91 | #define IWLAGN_DEFAULT_TX_RETRY 15 | ||
92 | |||
93 | /* Limit range of txpower output target to be between these values */ | ||
94 | #define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */ | ||
95 | #define IWLAGN_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ | ||
96 | |||
97 | /* EEPROM */ | ||
98 | #define IWLAGN_EEPROM_IMG_SIZE 2048 | ||
99 | |||
100 | #define IWLAGN_CMD_FIFO_NUM 7 | ||
101 | #define IWLAGN_NUM_QUEUES 20 | ||
102 | #define IWLAGN_NUM_AMPDU_QUEUES 10 | ||
103 | #define IWLAGN_FIRST_AMPDU_QUEUE 10 | ||
104 | |||
105 | /* Fixed (non-configurable) rx data from phy */ | ||
106 | |||
107 | /** | ||
108 | * struct iwlagn_schedq_bc_tbl scheduler byte count table | ||
109 | * base physical address provided by SCD_DRAM_BASE_ADDR | ||
110 | * @tfd_offset 0-12 - tx command byte count | ||
111 | * 12-16 - station index | ||
112 | */ | ||
113 | struct iwlagn_scd_bc_tbl { | ||
114 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
115 | } __attribute__ ((packed)); | ||
116 | |||
117 | |||
118 | #endif /* __iwl_agn_hw_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c new file mode 100644 index 000000000000..a273e373b7b0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c | |||
@@ -0,0 +1,307 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <net/mac80211.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-agn.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | |||
40 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | ||
41 | |||
42 | /* Free dram table */ | ||
43 | void iwl_free_isr_ict(struct iwl_priv *priv) | ||
44 | { | ||
45 | if (priv->_agn.ict_tbl_vir) { | ||
46 | dma_free_coherent(&priv->pci_dev->dev, | ||
47 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
48 | priv->_agn.ict_tbl_vir, | ||
49 | priv->_agn.ict_tbl_dma); | ||
50 | priv->_agn.ict_tbl_vir = NULL; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | |||
55 | /* allocate dram shared table it is a PAGE_SIZE aligned | ||
56 | * also reset all data related to ICT table interrupt. | ||
57 | */ | ||
58 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | ||
59 | { | ||
60 | |||
61 | if (priv->cfg->use_isr_legacy) | ||
62 | return 0; | ||
63 | /* allocate shrared data table */ | ||
64 | priv->_agn.ict_tbl_vir = | ||
65 | dma_alloc_coherent(&priv->pci_dev->dev, | ||
66 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
67 | &priv->_agn.ict_tbl_dma, GFP_KERNEL); | ||
68 | if (!priv->_agn.ict_tbl_vir) | ||
69 | return -ENOMEM; | ||
70 | |||
71 | /* align table to PAGE_SIZE boundry */ | ||
72 | priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE); | ||
73 | |||
74 | IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", | ||
75 | (unsigned long long)priv->_agn.ict_tbl_dma, | ||
76 | (unsigned long long)priv->_agn.aligned_ict_tbl_dma, | ||
77 | (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); | ||
78 | |||
79 | priv->_agn.ict_tbl = priv->_agn.ict_tbl_vir + | ||
80 | (priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma); | ||
81 | |||
82 | IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", | ||
83 | priv->_agn.ict_tbl, priv->_agn.ict_tbl_vir, | ||
84 | (int)(priv->_agn.aligned_ict_tbl_dma - priv->_agn.ict_tbl_dma)); | ||
85 | |||
86 | /* reset table and index to all 0 */ | ||
87 | memset(priv->_agn.ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); | ||
88 | priv->_agn.ict_index = 0; | ||
89 | |||
90 | /* add periodic RX interrupt */ | ||
91 | priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | /* Device is going up inform it about using ICT interrupt table, | ||
96 | * also we need to tell the driver to start using ICT interrupt. | ||
97 | */ | ||
98 | int iwl_reset_ict(struct iwl_priv *priv) | ||
99 | { | ||
100 | u32 val; | ||
101 | unsigned long flags; | ||
102 | |||
103 | if (!priv->_agn.ict_tbl_vir) | ||
104 | return 0; | ||
105 | |||
106 | spin_lock_irqsave(&priv->lock, flags); | ||
107 | iwl_disable_interrupts(priv); | ||
108 | |||
109 | memset(&priv->_agn.ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); | ||
110 | |||
111 | val = priv->_agn.aligned_ict_tbl_dma >> PAGE_SHIFT; | ||
112 | |||
113 | val |= CSR_DRAM_INT_TBL_ENABLE; | ||
114 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; | ||
115 | |||
116 | IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " | ||
117 | "aligned dma address %Lx\n", | ||
118 | val, (unsigned long long)priv->_agn.aligned_ict_tbl_dma); | ||
119 | |||
120 | iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); | ||
121 | priv->_agn.use_ict = true; | ||
122 | priv->_agn.ict_index = 0; | ||
123 | iwl_write32(priv, CSR_INT, priv->inta_mask); | ||
124 | iwl_enable_interrupts(priv); | ||
125 | spin_unlock_irqrestore(&priv->lock, flags); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /* Device is going down disable ict interrupt usage */ | ||
131 | void iwl_disable_ict(struct iwl_priv *priv) | ||
132 | { | ||
133 | unsigned long flags; | ||
134 | |||
135 | spin_lock_irqsave(&priv->lock, flags); | ||
136 | priv->_agn.use_ict = false; | ||
137 | spin_unlock_irqrestore(&priv->lock, flags); | ||
138 | } | ||
139 | |||
140 | static irqreturn_t iwl_isr(int irq, void *data) | ||
141 | { | ||
142 | struct iwl_priv *priv = data; | ||
143 | u32 inta, inta_mask; | ||
144 | unsigned long flags; | ||
145 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
146 | u32 inta_fh; | ||
147 | #endif | ||
148 | if (!priv) | ||
149 | return IRQ_NONE; | ||
150 | |||
151 | spin_lock_irqsave(&priv->lock, flags); | ||
152 | |||
153 | /* Disable (but don't clear!) interrupts here to avoid | ||
154 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
155 | * If we have something to service, the tasklet will re-enable ints. | ||
156 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
157 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
158 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
159 | |||
160 | /* Discover which interrupts are active/pending */ | ||
161 | inta = iwl_read32(priv, CSR_INT); | ||
162 | |||
163 | /* Ignore interrupt if there's nothing in NIC to service. | ||
164 | * This may be due to IRQ shared with another device, | ||
165 | * or due to sporadic interrupts thrown from our NIC. */ | ||
166 | if (!inta) { | ||
167 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
168 | goto none; | ||
169 | } | ||
170 | |||
171 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
172 | /* Hardware disappeared. It might have already raised | ||
173 | * an interrupt */ | ||
174 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
175 | goto unplugged; | ||
176 | } | ||
177 | |||
178 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
179 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
180 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
181 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | ||
182 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | ||
183 | } | ||
184 | #endif | ||
185 | |||
186 | priv->_agn.inta |= inta; | ||
187 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
188 | if (likely(inta)) | ||
189 | tasklet_schedule(&priv->irq_tasklet); | ||
190 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | ||
191 | iwl_enable_interrupts(priv); | ||
192 | |||
193 | unplugged: | ||
194 | spin_unlock_irqrestore(&priv->lock, flags); | ||
195 | return IRQ_HANDLED; | ||
196 | |||
197 | none: | ||
198 | /* re-enable interrupts here since we don't have anything to service. */ | ||
199 | /* only Re-enable if diabled by irq and no schedules tasklet. */ | ||
200 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | ||
201 | iwl_enable_interrupts(priv); | ||
202 | |||
203 | spin_unlock_irqrestore(&priv->lock, flags); | ||
204 | return IRQ_NONE; | ||
205 | } | ||
206 | |||
207 | /* interrupt handler using ict table, with this interrupt driver will | ||
208 | * stop using INTA register to get device's interrupt, reading this register | ||
209 | * is expensive, device will write interrupts in ICT dram table, increment | ||
210 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
211 | * entries from current index up to table entry with 0 value. the result is | ||
212 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
213 | * set index. | ||
214 | */ | ||
215 | irqreturn_t iwl_isr_ict(int irq, void *data) | ||
216 | { | ||
217 | struct iwl_priv *priv = data; | ||
218 | u32 inta, inta_mask; | ||
219 | u32 val = 0; | ||
220 | unsigned long flags; | ||
221 | |||
222 | if (!priv) | ||
223 | return IRQ_NONE; | ||
224 | |||
225 | /* dram interrupt table not set yet, | ||
226 | * use legacy interrupt. | ||
227 | */ | ||
228 | if (!priv->_agn.use_ict) | ||
229 | return iwl_isr(irq, data); | ||
230 | |||
231 | spin_lock_irqsave(&priv->lock, flags); | ||
232 | |||
233 | /* Disable (but don't clear!) interrupts here to avoid | ||
234 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
235 | * If we have something to service, the tasklet will re-enable ints. | ||
236 | * If we *don't* have something, we'll re-enable before leaving here. | ||
237 | */ | ||
238 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
239 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
240 | |||
241 | |||
242 | /* Ignore interrupt if there's nothing in NIC to service. | ||
243 | * This may be due to IRQ shared with another device, | ||
244 | * or due to sporadic interrupts thrown from our NIC. */ | ||
245 | if (!priv->_agn.ict_tbl[priv->_agn.ict_index]) { | ||
246 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
247 | goto none; | ||
248 | } | ||
249 | |||
250 | /* read all entries that not 0 start with ict_index */ | ||
251 | while (priv->_agn.ict_tbl[priv->_agn.ict_index]) { | ||
252 | |||
253 | val |= le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index]); | ||
254 | IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", | ||
255 | priv->_agn.ict_index, | ||
256 | le32_to_cpu(priv->_agn.ict_tbl[priv->_agn.ict_index])); | ||
257 | priv->_agn.ict_tbl[priv->_agn.ict_index] = 0; | ||
258 | priv->_agn.ict_index = iwl_queue_inc_wrap(priv->_agn.ict_index, | ||
259 | ICT_COUNT); | ||
260 | |||
261 | } | ||
262 | |||
263 | /* We should not get this value, just ignore it. */ | ||
264 | if (val == 0xffffffff) | ||
265 | val = 0; | ||
266 | |||
267 | /* | ||
268 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
269 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
270 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
271 | * so we use them to decide on the real state of the Rx bit. | ||
272 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
273 | */ | ||
274 | if (val & 0xC0000) | ||
275 | val |= 0x8000; | ||
276 | |||
277 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
278 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | ||
279 | inta, inta_mask, val); | ||
280 | |||
281 | inta &= priv->inta_mask; | ||
282 | priv->_agn.inta |= inta; | ||
283 | |||
284 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
285 | if (likely(inta)) | ||
286 | tasklet_schedule(&priv->irq_tasklet); | ||
287 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) { | ||
288 | /* Allow interrupt if was disabled by this handler and | ||
289 | * no tasklet was schedules, We should not enable interrupt, | ||
290 | * tasklet will enable it. | ||
291 | */ | ||
292 | iwl_enable_interrupts(priv); | ||
293 | } | ||
294 | |||
295 | spin_unlock_irqrestore(&priv->lock, flags); | ||
296 | return IRQ_HANDLED; | ||
297 | |||
298 | none: | ||
299 | /* re-enable interrupts here since we don't have anything to service. | ||
300 | * only Re-enable if disabled by irq. | ||
301 | */ | ||
302 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | ||
303 | iwl_enable_interrupts(priv); | ||
304 | |||
305 | spin_unlock_irqrestore(&priv->lock, flags); | ||
306 | return IRQ_NONE; | ||
307 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c new file mode 100644 index 000000000000..1004cfc403b1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -0,0 +1,1530 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #include <linux/etherdevice.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | #include "iwl-agn-hw.h" | ||
40 | #include "iwl-agn.h" | ||
41 | #include "iwl-sta.h" | ||
42 | |||
43 | static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | ||
44 | { | ||
45 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
46 | tx_resp->frame_count) & MAX_SN; | ||
47 | } | ||
48 | |||
49 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | ||
50 | struct iwl_ht_agg *agg, | ||
51 | struct iwl5000_tx_resp *tx_resp, | ||
52 | int txq_id, u16 start_idx) | ||
53 | { | ||
54 | u16 status; | ||
55 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
56 | struct ieee80211_tx_info *info = NULL; | ||
57 | struct ieee80211_hdr *hdr = NULL; | ||
58 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
59 | int i, sh, idx; | ||
60 | u16 seq; | ||
61 | |||
62 | if (agg->wait_for_ba) | ||
63 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
64 | |||
65 | agg->frame_count = tx_resp->frame_count; | ||
66 | agg->start_idx = start_idx; | ||
67 | agg->rate_n_flags = rate_n_flags; | ||
68 | agg->bitmap = 0; | ||
69 | |||
70 | /* # frames attempted by Tx command */ | ||
71 | if (agg->frame_count == 1) { | ||
72 | /* Only one frame was attempted; no block-ack will arrive */ | ||
73 | status = le16_to_cpu(frame_status[0].status); | ||
74 | idx = start_idx; | ||
75 | |||
76 | /* FIXME: code repetition */ | ||
77 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
78 | agg->frame_count, agg->start_idx, idx); | ||
79 | |||
80 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
81 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
82 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
83 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
84 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
85 | |||
86 | /* FIXME: code repetition end */ | ||
87 | |||
88 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
89 | status & 0xff, tx_resp->failure_frame); | ||
90 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
91 | |||
92 | agg->wait_for_ba = 0; | ||
93 | } else { | ||
94 | /* Two or more frames were attempted; expect block-ack */ | ||
95 | u64 bitmap = 0; | ||
96 | int start = agg->start_idx; | ||
97 | |||
98 | /* Construct bit-map of pending frames within Tx window */ | ||
99 | for (i = 0; i < agg->frame_count; i++) { | ||
100 | u16 sc; | ||
101 | status = le16_to_cpu(frame_status[i].status); | ||
102 | seq = le16_to_cpu(frame_status[i].sequence); | ||
103 | idx = SEQ_TO_INDEX(seq); | ||
104 | txq_id = SEQ_TO_QUEUE(seq); | ||
105 | |||
106 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
107 | AGG_TX_STATE_ABORT_MSK)) | ||
108 | continue; | ||
109 | |||
110 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | ||
111 | agg->frame_count, txq_id, idx); | ||
112 | |||
113 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
114 | if (!hdr) { | ||
115 | IWL_ERR(priv, | ||
116 | "BUG_ON idx doesn't point to valid skb" | ||
117 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
118 | return -1; | ||
119 | } | ||
120 | |||
121 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
122 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
123 | IWL_ERR(priv, | ||
124 | "BUG_ON idx doesn't match seq control" | ||
125 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
126 | idx, SEQ_TO_SN(sc), | ||
127 | hdr->seq_ctrl); | ||
128 | return -1; | ||
129 | } | ||
130 | |||
131 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | ||
132 | i, idx, SEQ_TO_SN(sc)); | ||
133 | |||
134 | sh = idx - start; | ||
135 | if (sh > 64) { | ||
136 | sh = (start - idx) + 0xff; | ||
137 | bitmap = bitmap << sh; | ||
138 | sh = 0; | ||
139 | start = idx; | ||
140 | } else if (sh < -64) | ||
141 | sh = 0xff - (start - idx); | ||
142 | else if (sh < 0) { | ||
143 | sh = start - idx; | ||
144 | start = idx; | ||
145 | bitmap = bitmap << sh; | ||
146 | sh = 0; | ||
147 | } | ||
148 | bitmap |= 1ULL << sh; | ||
149 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
150 | start, (unsigned long long)bitmap); | ||
151 | } | ||
152 | |||
153 | agg->bitmap = bitmap; | ||
154 | agg->start_idx = start; | ||
155 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | ||
156 | agg->frame_count, agg->start_idx, | ||
157 | (unsigned long long)agg->bitmap); | ||
158 | |||
159 | if (bitmap) | ||
160 | agg->wait_for_ba = 1; | ||
161 | } | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | void iwl_check_abort_status(struct iwl_priv *priv, | ||
166 | u8 frame_count, u32 status) | ||
167 | { | ||
168 | if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { | ||
169 | IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n"); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | ||
174 | struct iwl_rx_mem_buffer *rxb) | ||
175 | { | ||
176 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
177 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
178 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
179 | int index = SEQ_TO_INDEX(sequence); | ||
180 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
181 | struct ieee80211_tx_info *info; | ||
182 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
183 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
184 | int tid; | ||
185 | int sta_id; | ||
186 | int freed; | ||
187 | |||
188 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
189 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
190 | "is out of range [0-%d] %d %d\n", txq_id, | ||
191 | index, txq->q.n_bd, txq->q.write_ptr, | ||
192 | txq->q.read_ptr); | ||
193 | return; | ||
194 | } | ||
195 | |||
196 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
197 | memset(&info->status, 0, sizeof(info->status)); | ||
198 | |||
199 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | ||
200 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | ||
201 | |||
202 | if (txq->sched_retry) { | ||
203 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); | ||
204 | struct iwl_ht_agg *agg = NULL; | ||
205 | |||
206 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
207 | |||
208 | iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
209 | |||
210 | /* check if BAR is needed */ | ||
211 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
212 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
213 | |||
214 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
215 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
216 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " | ||
217 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
218 | scd_ssn , index, txq_id, txq->swq_id); | ||
219 | |||
220 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
221 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
222 | |||
223 | if (priv->mac80211_registered && | ||
224 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
225 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { | ||
226 | if (agg->state == IWL_AGG_OFF) | ||
227 | iwl_wake_queue(priv, txq_id); | ||
228 | else | ||
229 | iwl_wake_queue(priv, txq->swq_id); | ||
230 | } | ||
231 | } | ||
232 | } else { | ||
233 | BUG_ON(txq_id != txq->swq_id); | ||
234 | |||
235 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
236 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
237 | iwlagn_hwrate_to_tx_control(priv, | ||
238 | le32_to_cpu(tx_resp->rate_n_flags), | ||
239 | info); | ||
240 | |||
241 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
242 | "0x%x retries %d\n", | ||
243 | txq_id, | ||
244 | iwl_get_tx_fail_reason(status), status, | ||
245 | le32_to_cpu(tx_resp->rate_n_flags), | ||
246 | tx_resp->failure_frame); | ||
247 | |||
248 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
249 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
250 | |||
251 | if (priv->mac80211_registered && | ||
252 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
253 | iwl_wake_queue(priv, txq_id); | ||
254 | } | ||
255 | |||
256 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | ||
257 | |||
258 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | ||
259 | } | ||
260 | |||
261 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) | ||
262 | { | ||
263 | /* init calibration handlers */ | ||
264 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
265 | iwlagn_rx_calib_result; | ||
266 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
267 | iwlagn_rx_calib_complete; | ||
268 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | ||
269 | } | ||
270 | |||
271 | void iwlagn_setup_deferred_work(struct iwl_priv *priv) | ||
272 | { | ||
273 | /* in agn, the tx power calibration is done in uCode */ | ||
274 | priv->disable_tx_power_cal = 1; | ||
275 | } | ||
276 | |||
277 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) | ||
278 | { | ||
279 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | ||
280 | (addr < IWLAGN_RTC_DATA_UPPER_BOUND); | ||
281 | } | ||
282 | |||
283 | int iwlagn_send_tx_power(struct iwl_priv *priv) | ||
284 | { | ||
285 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | ||
286 | u8 tx_ant_cfg_cmd; | ||
287 | |||
288 | /* half dBm need to multiply */ | ||
289 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||
290 | |||
291 | if (priv->tx_power_lmt_in_half_dbm && | ||
292 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
293 | /* | ||
294 | * For the newer devices which using enhanced/extend tx power | ||
295 | * table in EEPROM, the format is in half dBm. driver need to | ||
296 | * convert to dBm format before report to mac80211. | ||
297 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
298 | * lost. driver will perform "round-up" operation before | ||
299 | * reporting, but it will cause 1/2 dBm tx power over the | ||
300 | * regulatory limit. Perform the checking here, if the | ||
301 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
302 | * half-dBm format), lower the tx power based on EEPROM | ||
303 | */ | ||
304 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
305 | } | ||
306 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | ||
307 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | ||
308 | |||
309 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
310 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | ||
311 | else | ||
312 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | ||
313 | |||
314 | return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, | ||
315 | sizeof(tx_power_cmd), &tx_power_cmd, | ||
316 | NULL); | ||
317 | } | ||
318 | |||
319 | void iwlagn_temperature(struct iwl_priv *priv) | ||
320 | { | ||
321 | /* store temperature from statistics (in Celsius) */ | ||
322 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
323 | iwl_tt_handler(priv); | ||
324 | } | ||
325 | |||
326 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | ||
327 | { | ||
328 | struct iwl_eeprom_calib_hdr { | ||
329 | u8 version; | ||
330 | u8 pa_type; | ||
331 | u16 voltage; | ||
332 | } *hdr; | ||
333 | |||
334 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
335 | EEPROM_CALIB_ALL); | ||
336 | return hdr->version; | ||
337 | |||
338 | } | ||
339 | |||
340 | /* | ||
341 | * EEPROM | ||
342 | */ | ||
343 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | ||
344 | { | ||
345 | u16 offset = 0; | ||
346 | |||
347 | if ((address & INDIRECT_ADDRESS) == 0) | ||
348 | return address; | ||
349 | |||
350 | switch (address & INDIRECT_TYPE_MSK) { | ||
351 | case INDIRECT_HOST: | ||
352 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); | ||
353 | break; | ||
354 | case INDIRECT_GENERAL: | ||
355 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); | ||
356 | break; | ||
357 | case INDIRECT_REGULATORY: | ||
358 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); | ||
359 | break; | ||
360 | case INDIRECT_CALIBRATION: | ||
361 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); | ||
362 | break; | ||
363 | case INDIRECT_PROCESS_ADJST: | ||
364 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); | ||
365 | break; | ||
366 | case INDIRECT_OTHERS: | ||
367 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); | ||
368 | break; | ||
369 | default: | ||
370 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
371 | address & INDIRECT_TYPE_MSK); | ||
372 | break; | ||
373 | } | ||
374 | |||
375 | /* translate the offset from words to byte */ | ||
376 | return (address & ADDRESS_MSK) + (offset << 1); | ||
377 | } | ||
378 | |||
379 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | ||
380 | size_t offset) | ||
381 | { | ||
382 | u32 address = eeprom_indirect_address(priv, offset); | ||
383 | BUG_ON(address >= priv->cfg->eeprom_size); | ||
384 | return &priv->eeprom[address]; | ||
385 | } | ||
386 | |||
387 | struct iwl_mod_params iwlagn_mod_params = { | ||
388 | .amsdu_size_8K = 1, | ||
389 | .restart_fw = 1, | ||
390 | /* the rest are 0 by default */ | ||
391 | }; | ||
392 | |||
393 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
394 | { | ||
395 | unsigned long flags; | ||
396 | int i; | ||
397 | spin_lock_irqsave(&rxq->lock, flags); | ||
398 | INIT_LIST_HEAD(&rxq->rx_free); | ||
399 | INIT_LIST_HEAD(&rxq->rx_used); | ||
400 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
401 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
402 | /* In the reset function, these buffers may have been allocated | ||
403 | * to an SKB, so we need to unmap and free potential storage */ | ||
404 | if (rxq->pool[i].page != NULL) { | ||
405 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
406 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
407 | PCI_DMA_FROMDEVICE); | ||
408 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
409 | rxq->pool[i].page = NULL; | ||
410 | } | ||
411 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
412 | } | ||
413 | |||
414 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
415 | rxq->queue[i] = NULL; | ||
416 | |||
417 | /* Set us so that we have processed and used all buffers, but have | ||
418 | * not restocked the Rx queue with fresh buffers */ | ||
419 | rxq->read = rxq->write = 0; | ||
420 | rxq->write_actual = 0; | ||
421 | rxq->free_count = 0; | ||
422 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
423 | } | ||
424 | |||
425 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
426 | { | ||
427 | u32 rb_size; | ||
428 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
429 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
430 | |||
431 | if (!priv->cfg->use_isr_legacy) | ||
432 | rb_timeout = RX_RB_TIMEOUT; | ||
433 | |||
434 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
435 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
436 | else | ||
437 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
438 | |||
439 | /* Stop Rx DMA */ | ||
440 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
441 | |||
442 | /* Reset driver's Rx queue write index */ | ||
443 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
444 | |||
445 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
446 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
447 | (u32)(rxq->dma_addr >> 8)); | ||
448 | |||
449 | /* Tell device where in DRAM to update its Rx status */ | ||
450 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
451 | rxq->rb_stts_dma >> 4); | ||
452 | |||
453 | /* Enable Rx DMA | ||
454 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
455 | * the credit mechanism in 5000 HW RX FIFO | ||
456 | * Direct rx interrupts to hosts | ||
457 | * Rx buffer size 4 or 8k | ||
458 | * RB timeout 0x10 | ||
459 | * 256 RBDs | ||
460 | */ | ||
461 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
462 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
463 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
464 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
465 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
466 | rb_size| | ||
467 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
468 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
469 | |||
470 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
471 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | int iwlagn_hw_nic_init(struct iwl_priv *priv) | ||
477 | { | ||
478 | unsigned long flags; | ||
479 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
480 | int ret; | ||
481 | |||
482 | /* nic_init */ | ||
483 | spin_lock_irqsave(&priv->lock, flags); | ||
484 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
485 | |||
486 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
487 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
488 | |||
489 | spin_unlock_irqrestore(&priv->lock, flags); | ||
490 | |||
491 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
492 | |||
493 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
494 | |||
495 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
496 | if (!rxq->bd) { | ||
497 | ret = iwl_rx_queue_alloc(priv); | ||
498 | if (ret) { | ||
499 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
500 | return -ENOMEM; | ||
501 | } | ||
502 | } else | ||
503 | iwlagn_rx_queue_reset(priv, rxq); | ||
504 | |||
505 | iwlagn_rx_replenish(priv); | ||
506 | |||
507 | iwlagn_rx_init(priv, rxq); | ||
508 | |||
509 | spin_lock_irqsave(&priv->lock, flags); | ||
510 | |||
511 | rxq->need_update = 1; | ||
512 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
513 | |||
514 | spin_unlock_irqrestore(&priv->lock, flags); | ||
515 | |||
516 | /* Allocate or reset and init all Tx and Command queues */ | ||
517 | if (!priv->txq) { | ||
518 | ret = iwlagn_txq_ctx_alloc(priv); | ||
519 | if (ret) | ||
520 | return ret; | ||
521 | } else | ||
522 | iwlagn_txq_ctx_reset(priv); | ||
523 | |||
524 | set_bit(STATUS_INIT, &priv->status); | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
531 | */ | ||
532 | static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
533 | dma_addr_t dma_addr) | ||
534 | { | ||
535 | return cpu_to_le32((u32)(dma_addr >> 8)); | ||
536 | } | ||
537 | |||
538 | /** | ||
539 | * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool | ||
540 | * | ||
541 | * If there are slots in the RX queue that need to be restocked, | ||
542 | * and we have free pre-allocated buffers, fill the ranks as much | ||
543 | * as we can, pulling from rx_free. | ||
544 | * | ||
545 | * This moves the 'write' index forward to catch up with 'processed', and | ||
546 | * also updates the memory address in the firmware to reference the new | ||
547 | * target buffer. | ||
548 | */ | ||
549 | void iwlagn_rx_queue_restock(struct iwl_priv *priv) | ||
550 | { | ||
551 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
552 | struct list_head *element; | ||
553 | struct iwl_rx_mem_buffer *rxb; | ||
554 | unsigned long flags; | ||
555 | |||
556 | spin_lock_irqsave(&rxq->lock, flags); | ||
557 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
558 | /* The overwritten rxb must be a used one */ | ||
559 | rxb = rxq->queue[rxq->write]; | ||
560 | BUG_ON(rxb && rxb->page); | ||
561 | |||
562 | /* Get next free Rx buffer, remove from free list */ | ||
563 | element = rxq->rx_free.next; | ||
564 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
565 | list_del(element); | ||
566 | |||
567 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
568 | rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, | ||
569 | rxb->page_dma); | ||
570 | rxq->queue[rxq->write] = rxb; | ||
571 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
572 | rxq->free_count--; | ||
573 | } | ||
574 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
575 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
576 | * refill it */ | ||
577 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
578 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
579 | |||
580 | |||
581 | /* If we've added more space for the firmware to place data, tell it. | ||
582 | * Increment device's write pointer in multiples of 8. */ | ||
583 | if (rxq->write_actual != (rxq->write & ~0x7)) { | ||
584 | spin_lock_irqsave(&rxq->lock, flags); | ||
585 | rxq->need_update = 1; | ||
586 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
587 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free | ||
593 | * | ||
594 | * When moving to rx_free an SKB is allocated for the slot. | ||
595 | * | ||
596 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
597 | * This is called as a scheduled work item (except for during initialization) | ||
598 | */ | ||
599 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
600 | { | ||
601 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
602 | struct list_head *element; | ||
603 | struct iwl_rx_mem_buffer *rxb; | ||
604 | struct page *page; | ||
605 | unsigned long flags; | ||
606 | gfp_t gfp_mask = priority; | ||
607 | |||
608 | while (1) { | ||
609 | spin_lock_irqsave(&rxq->lock, flags); | ||
610 | if (list_empty(&rxq->rx_used)) { | ||
611 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
612 | return; | ||
613 | } | ||
614 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
615 | |||
616 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
617 | gfp_mask |= __GFP_NOWARN; | ||
618 | |||
619 | if (priv->hw_params.rx_page_order > 0) | ||
620 | gfp_mask |= __GFP_COMP; | ||
621 | |||
622 | /* Alloc a new receive buffer */ | ||
623 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
624 | if (!page) { | ||
625 | if (net_ratelimit()) | ||
626 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " | ||
627 | "order: %d\n", | ||
628 | priv->hw_params.rx_page_order); | ||
629 | |||
630 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
631 | net_ratelimit()) | ||
632 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", | ||
633 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
634 | rxq->free_count); | ||
635 | /* We don't reschedule replenish work here -- we will | ||
636 | * call the restock method and if it still needs | ||
637 | * more buffers it will schedule replenish */ | ||
638 | return; | ||
639 | } | ||
640 | |||
641 | spin_lock_irqsave(&rxq->lock, flags); | ||
642 | |||
643 | if (list_empty(&rxq->rx_used)) { | ||
644 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
645 | __free_pages(page, priv->hw_params.rx_page_order); | ||
646 | return; | ||
647 | } | ||
648 | element = rxq->rx_used.next; | ||
649 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
650 | list_del(element); | ||
651 | |||
652 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
653 | |||
654 | BUG_ON(rxb->page); | ||
655 | rxb->page = page; | ||
656 | /* Get physical address of the RB */ | ||
657 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
658 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
659 | PCI_DMA_FROMDEVICE); | ||
660 | /* dma address must be no more than 36 bits */ | ||
661 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | ||
662 | /* and also 256 byte aligned! */ | ||
663 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | ||
664 | |||
665 | spin_lock_irqsave(&rxq->lock, flags); | ||
666 | |||
667 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
668 | rxq->free_count++; | ||
669 | priv->alloc_rxb_page++; | ||
670 | |||
671 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
672 | } | ||
673 | } | ||
674 | |||
675 | void iwlagn_rx_replenish(struct iwl_priv *priv) | ||
676 | { | ||
677 | unsigned long flags; | ||
678 | |||
679 | iwlagn_rx_allocate(priv, GFP_KERNEL); | ||
680 | |||
681 | spin_lock_irqsave(&priv->lock, flags); | ||
682 | iwlagn_rx_queue_restock(priv); | ||
683 | spin_unlock_irqrestore(&priv->lock, flags); | ||
684 | } | ||
685 | |||
686 | void iwlagn_rx_replenish_now(struct iwl_priv *priv) | ||
687 | { | ||
688 | iwlagn_rx_allocate(priv, GFP_ATOMIC); | ||
689 | |||
690 | iwlagn_rx_queue_restock(priv); | ||
691 | } | ||
692 | |||
693 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
694 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
695 | * This free routine walks the list of POOL entries and if SKB is set to | ||
696 | * non NULL it is unmapped and freed | ||
697 | */ | ||
698 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
699 | { | ||
700 | int i; | ||
701 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
702 | if (rxq->pool[i].page != NULL) { | ||
703 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
704 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
705 | PCI_DMA_FROMDEVICE); | ||
706 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
707 | rxq->pool[i].page = NULL; | ||
708 | } | ||
709 | } | ||
710 | |||
711 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
712 | rxq->dma_addr); | ||
713 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
714 | rxq->rb_stts, rxq->rb_stts_dma); | ||
715 | rxq->bd = NULL; | ||
716 | rxq->rb_stts = NULL; | ||
717 | } | ||
718 | |||
719 | int iwlagn_rxq_stop(struct iwl_priv *priv) | ||
720 | { | ||
721 | |||
722 | /* stop Rx DMA */ | ||
723 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
724 | iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
725 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
731 | { | ||
732 | int idx = 0; | ||
733 | int band_offset = 0; | ||
734 | |||
735 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
736 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
737 | idx = (rate_n_flags & 0xff); | ||
738 | return idx; | ||
739 | /* Legacy rate format, search for match in table */ | ||
740 | } else { | ||
741 | if (band == IEEE80211_BAND_5GHZ) | ||
742 | band_offset = IWL_FIRST_OFDM_RATE; | ||
743 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
744 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
745 | return idx - band_offset; | ||
746 | } | ||
747 | |||
748 | return -1; | ||
749 | } | ||
750 | |||
751 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
752 | static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
753 | struct iwl_rx_phy_res *rx_resp) | ||
754 | { | ||
755 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
756 | } | ||
757 | |||
758 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
759 | /** | ||
760 | * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions | ||
761 | * | ||
762 | * You may hack this function to show different aspects of received frames, | ||
763 | * including selective frame dumps. | ||
764 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
765 | * All beacon and probe response frames are printed. | ||
766 | */ | ||
767 | static void iwlagn_dbg_report_frame(struct iwl_priv *priv, | ||
768 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
769 | struct ieee80211_hdr *header, int group100) | ||
770 | { | ||
771 | u32 to_us; | ||
772 | u32 print_summary = 0; | ||
773 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
774 | u32 hundred = 0; | ||
775 | u32 dataframe = 0; | ||
776 | __le16 fc; | ||
777 | u16 seq_ctl; | ||
778 | u16 channel; | ||
779 | u16 phy_flags; | ||
780 | u32 rate_n_flags; | ||
781 | u32 tsf_low; | ||
782 | int rssi; | ||
783 | |||
784 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
785 | return; | ||
786 | |||
787 | /* MAC header */ | ||
788 | fc = header->frame_control; | ||
789 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
790 | |||
791 | /* metadata */ | ||
792 | channel = le16_to_cpu(phy_res->channel); | ||
793 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
794 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
795 | |||
796 | /* signal statistics */ | ||
797 | rssi = iwlagn_calc_rssi(priv, phy_res); | ||
798 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
799 | |||
800 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
801 | |||
802 | /* if data frame is to us and all is good, | ||
803 | * (optionally) print summary for only 1 out of every 100 */ | ||
804 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
805 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
806 | dataframe = 1; | ||
807 | if (!group100) | ||
808 | print_summary = 1; /* print each frame */ | ||
809 | else if (priv->framecnt_to_us < 100) { | ||
810 | priv->framecnt_to_us++; | ||
811 | print_summary = 0; | ||
812 | } else { | ||
813 | priv->framecnt_to_us = 0; | ||
814 | print_summary = 1; | ||
815 | hundred = 1; | ||
816 | } | ||
817 | } else { | ||
818 | /* print summary for all other frames */ | ||
819 | print_summary = 1; | ||
820 | } | ||
821 | |||
822 | if (print_summary) { | ||
823 | char *title; | ||
824 | int rate_idx; | ||
825 | u32 bitrate; | ||
826 | |||
827 | if (hundred) | ||
828 | title = "100Frames"; | ||
829 | else if (ieee80211_has_retry(fc)) | ||
830 | title = "Retry"; | ||
831 | else if (ieee80211_is_assoc_resp(fc)) | ||
832 | title = "AscRsp"; | ||
833 | else if (ieee80211_is_reassoc_resp(fc)) | ||
834 | title = "RasRsp"; | ||
835 | else if (ieee80211_is_probe_resp(fc)) { | ||
836 | title = "PrbRsp"; | ||
837 | print_dump = 1; /* dump frame contents */ | ||
838 | } else if (ieee80211_is_beacon(fc)) { | ||
839 | title = "Beacon"; | ||
840 | print_dump = 1; /* dump frame contents */ | ||
841 | } else if (ieee80211_is_atim(fc)) | ||
842 | title = "ATIM"; | ||
843 | else if (ieee80211_is_auth(fc)) | ||
844 | title = "Auth"; | ||
845 | else if (ieee80211_is_deauth(fc)) | ||
846 | title = "DeAuth"; | ||
847 | else if (ieee80211_is_disassoc(fc)) | ||
848 | title = "DisAssoc"; | ||
849 | else | ||
850 | title = "Frame"; | ||
851 | |||
852 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
853 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
854 | bitrate = 0; | ||
855 | WARN_ON_ONCE(1); | ||
856 | } else { | ||
857 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
858 | } | ||
859 | |||
860 | /* print frame summary. | ||
861 | * MAC addresses show just the last byte (for brevity), | ||
862 | * but you can hack it to show more, if you'd like to. */ | ||
863 | if (dataframe) | ||
864 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
865 | "len=%u, rssi=%d, chnl=%d, rate=%u,\n", | ||
866 | title, le16_to_cpu(fc), header->addr1[5], | ||
867 | length, rssi, channel, bitrate); | ||
868 | else { | ||
869 | /* src/dst addresses assume managed mode */ | ||
870 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
871 | "len=%u, rssi=%d, tim=%lu usec, " | ||
872 | "phy=0x%02x, chnl=%d\n", | ||
873 | title, le16_to_cpu(fc), header->addr1[5], | ||
874 | header->addr3[5], length, rssi, | ||
875 | tsf_low - priv->scan_start_tsf, | ||
876 | phy_flags, channel); | ||
877 | } | ||
878 | } | ||
879 | if (print_dump) | ||
880 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
881 | } | ||
882 | #endif | ||
883 | |||
884 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
885 | { | ||
886 | u32 decrypt_out = 0; | ||
887 | |||
888 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
889 | RX_RES_STATUS_STATION_FOUND) | ||
890 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
891 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
892 | |||
893 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
894 | |||
895 | /* packet was not encrypted */ | ||
896 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
897 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
898 | return decrypt_out; | ||
899 | |||
900 | /* packet was encrypted with unknown alg */ | ||
901 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
902 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
903 | return decrypt_out; | ||
904 | |||
905 | /* decryption was not done in HW */ | ||
906 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
907 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
908 | return decrypt_out; | ||
909 | |||
910 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
911 | |||
912 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
913 | /* alg is CCM: check MIC only */ | ||
914 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
915 | /* Bad MIC */ | ||
916 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
917 | else | ||
918 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
919 | |||
920 | break; | ||
921 | |||
922 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
923 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
924 | /* Bad TTAK */ | ||
925 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
926 | break; | ||
927 | } | ||
928 | /* fall through if TTAK OK */ | ||
929 | default: | ||
930 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
931 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
932 | else | ||
933 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
934 | break; | ||
935 | } | ||
936 | |||
937 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
938 | decrypt_in, decrypt_out); | ||
939 | |||
940 | return decrypt_out; | ||
941 | } | ||
942 | |||
943 | static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
944 | struct ieee80211_hdr *hdr, | ||
945 | u16 len, | ||
946 | u32 ampdu_status, | ||
947 | struct iwl_rx_mem_buffer *rxb, | ||
948 | struct ieee80211_rx_status *stats) | ||
949 | { | ||
950 | struct sk_buff *skb; | ||
951 | __le16 fc = hdr->frame_control; | ||
952 | |||
953 | /* We only process data packets if the interface is open */ | ||
954 | if (unlikely(!priv->is_open)) { | ||
955 | IWL_DEBUG_DROP_LIMIT(priv, | ||
956 | "Dropping packet while interface is not open.\n"); | ||
957 | return; | ||
958 | } | ||
959 | |||
960 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
961 | if (!priv->cfg->mod_params->sw_crypto && | ||
962 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
963 | return; | ||
964 | |||
965 | skb = dev_alloc_skb(128); | ||
966 | if (!skb) { | ||
967 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
968 | return; | ||
969 | } | ||
970 | |||
971 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
972 | |||
973 | iwl_update_stats(priv, false, fc, len); | ||
974 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
975 | |||
976 | ieee80211_rx(priv->hw, skb); | ||
977 | priv->alloc_rxb_page--; | ||
978 | rxb->page = NULL; | ||
979 | } | ||
980 | |||
981 | /* Called for REPLY_RX (legacy ABG frames), or | ||
982 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
983 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
984 | struct iwl_rx_mem_buffer *rxb) | ||
985 | { | ||
986 | struct ieee80211_hdr *header; | ||
987 | struct ieee80211_rx_status rx_status; | ||
988 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
989 | struct iwl_rx_phy_res *phy_res; | ||
990 | __le32 rx_pkt_status; | ||
991 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
992 | u32 len; | ||
993 | u32 ampdu_status; | ||
994 | u32 rate_n_flags; | ||
995 | |||
996 | /** | ||
997 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
998 | * REPLY_RX: physical layer info is in this buffer | ||
999 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1000 | * command and cached in priv->last_phy_res | ||
1001 | * | ||
1002 | * Here we set up local variables depending on which command is | ||
1003 | * received. | ||
1004 | */ | ||
1005 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1006 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1007 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1008 | + phy_res->cfg_phy_cnt); | ||
1009 | |||
1010 | len = le16_to_cpu(phy_res->byte_count); | ||
1011 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1012 | phy_res->cfg_phy_cnt + len); | ||
1013 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1014 | } else { | ||
1015 | if (!priv->_agn.last_phy_res_valid) { | ||
1016 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1017 | return; | ||
1018 | } | ||
1019 | phy_res = &priv->_agn.last_phy_res; | ||
1020 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1021 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1022 | len = le16_to_cpu(amsdu->byte_count); | ||
1023 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1024 | ampdu_status = iwlagn_translate_rx_status(priv, | ||
1025 | le32_to_cpu(rx_pkt_status)); | ||
1026 | } | ||
1027 | |||
1028 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1029 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1030 | phy_res->cfg_phy_cnt); | ||
1031 | return; | ||
1032 | } | ||
1033 | |||
1034 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1035 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1036 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1037 | le32_to_cpu(rx_pkt_status)); | ||
1038 | return; | ||
1039 | } | ||
1040 | |||
1041 | /* This will be used in several places later */ | ||
1042 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1043 | |||
1044 | /* rx_status carries information about the packet to mac80211 */ | ||
1045 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1046 | rx_status.freq = | ||
1047 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1048 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1049 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1050 | rx_status.rate_idx = | ||
1051 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1052 | rx_status.flag = 0; | ||
1053 | |||
1054 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1055 | * this W/A doesn't propagate it to the mac80211 */ | ||
1056 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1057 | |||
1058 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1059 | |||
1060 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1061 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | ||
1062 | |||
1063 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1064 | /* Set "1" to report good data frames in groups of 100 */ | ||
1065 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1066 | iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1067 | #endif | ||
1068 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1069 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1070 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1071 | |||
1072 | /* | ||
1073 | * "antenna number" | ||
1074 | * | ||
1075 | * It seems that the antenna field in the phy flags value | ||
1076 | * is actually a bit field. This is undefined by radiotap, | ||
1077 | * it wants an actual antenna number but I always get "7" | ||
1078 | * for most legacy frames I receive indicating that the | ||
1079 | * same frame was received on all three RX chains. | ||
1080 | * | ||
1081 | * I think this field should be removed in favor of a | ||
1082 | * new 802.11n radiotap field "RX chains" that is defined | ||
1083 | * as a bitmask. | ||
1084 | */ | ||
1085 | rx_status.antenna = | ||
1086 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1087 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1088 | |||
1089 | /* set the preamble flag if appropriate */ | ||
1090 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1091 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1092 | |||
1093 | /* Set up the HT phy flags */ | ||
1094 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1095 | rx_status.flag |= RX_FLAG_HT; | ||
1096 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1097 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1098 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1099 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1100 | |||
1101 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1102 | rxb, &rx_status); | ||
1103 | } | ||
1104 | |||
1105 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1106 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1107 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1108 | struct iwl_rx_mem_buffer *rxb) | ||
1109 | { | ||
1110 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1111 | priv->_agn.last_phy_res_valid = true; | ||
1112 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | ||
1113 | sizeof(struct iwl_rx_phy_res)); | ||
1114 | } | ||
1115 | |||
1116 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||
1117 | struct ieee80211_vif *vif, | ||
1118 | enum ieee80211_band band, | ||
1119 | struct iwl_scan_channel *scan_ch) | ||
1120 | { | ||
1121 | const struct ieee80211_supported_band *sband; | ||
1122 | const struct iwl_channel_info *ch_info; | ||
1123 | u16 passive_dwell = 0; | ||
1124 | u16 active_dwell = 0; | ||
1125 | int i, added = 0; | ||
1126 | u16 channel = 0; | ||
1127 | |||
1128 | sband = iwl_get_hw_mode(priv, band); | ||
1129 | if (!sband) { | ||
1130 | IWL_ERR(priv, "invalid band\n"); | ||
1131 | return added; | ||
1132 | } | ||
1133 | |||
1134 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
1135 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
1136 | |||
1137 | if (passive_dwell <= active_dwell) | ||
1138 | passive_dwell = active_dwell + 1; | ||
1139 | |||
1140 | /* only scan single channel, good enough to reset the RF */ | ||
1141 | /* pick the first valid not in-use channel */ | ||
1142 | if (band == IEEE80211_BAND_5GHZ) { | ||
1143 | for (i = 14; i < priv->channel_count; i++) { | ||
1144 | if (priv->channel_info[i].channel != | ||
1145 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
1146 | channel = priv->channel_info[i].channel; | ||
1147 | ch_info = iwl_get_channel_info(priv, | ||
1148 | band, channel); | ||
1149 | if (is_channel_valid(ch_info)) | ||
1150 | break; | ||
1151 | } | ||
1152 | } | ||
1153 | } else { | ||
1154 | for (i = 0; i < 14; i++) { | ||
1155 | if (priv->channel_info[i].channel != | ||
1156 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
1157 | channel = | ||
1158 | priv->channel_info[i].channel; | ||
1159 | ch_info = iwl_get_channel_info(priv, | ||
1160 | band, channel); | ||
1161 | if (is_channel_valid(ch_info)) | ||
1162 | break; | ||
1163 | } | ||
1164 | } | ||
1165 | } | ||
1166 | if (channel) { | ||
1167 | scan_ch->channel = cpu_to_le16(channel); | ||
1168 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
1169 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
1170 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
1171 | /* Set txpower levels to defaults */ | ||
1172 | scan_ch->dsp_atten = 110; | ||
1173 | if (band == IEEE80211_BAND_5GHZ) | ||
1174 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
1175 | else | ||
1176 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
1177 | added++; | ||
1178 | } else | ||
1179 | IWL_ERR(priv, "no valid channel found\n"); | ||
1180 | return added; | ||
1181 | } | ||
1182 | |||
1183 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||
1184 | struct ieee80211_vif *vif, | ||
1185 | enum ieee80211_band band, | ||
1186 | u8 is_active, u8 n_probes, | ||
1187 | struct iwl_scan_channel *scan_ch) | ||
1188 | { | ||
1189 | struct ieee80211_channel *chan; | ||
1190 | const struct ieee80211_supported_band *sband; | ||
1191 | const struct iwl_channel_info *ch_info; | ||
1192 | u16 passive_dwell = 0; | ||
1193 | u16 active_dwell = 0; | ||
1194 | int added, i; | ||
1195 | u16 channel; | ||
1196 | |||
1197 | sband = iwl_get_hw_mode(priv, band); | ||
1198 | if (!sband) | ||
1199 | return 0; | ||
1200 | |||
1201 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | ||
1202 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); | ||
1203 | |||
1204 | if (passive_dwell <= active_dwell) | ||
1205 | passive_dwell = active_dwell + 1; | ||
1206 | |||
1207 | for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { | ||
1208 | chan = priv->scan_request->channels[i]; | ||
1209 | |||
1210 | if (chan->band != band) | ||
1211 | continue; | ||
1212 | |||
1213 | channel = ieee80211_frequency_to_channel(chan->center_freq); | ||
1214 | scan_ch->channel = cpu_to_le16(channel); | ||
1215 | |||
1216 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
1217 | if (!is_channel_valid(ch_info)) { | ||
1218 | IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", | ||
1219 | channel); | ||
1220 | continue; | ||
1221 | } | ||
1222 | |||
1223 | if (!is_active || is_channel_passive(ch_info) || | ||
1224 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
1225 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
1226 | else | ||
1227 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | ||
1228 | |||
1229 | if (n_probes) | ||
1230 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); | ||
1231 | |||
1232 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
1233 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
1234 | |||
1235 | /* Set txpower levels to defaults */ | ||
1236 | scan_ch->dsp_atten = 110; | ||
1237 | |||
1238 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
1239 | * power level: | ||
1240 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
1241 | */ | ||
1242 | if (band == IEEE80211_BAND_5GHZ) | ||
1243 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
1244 | else | ||
1245 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
1246 | |||
1247 | IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", | ||
1248 | channel, le32_to_cpu(scan_ch->type), | ||
1249 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
1250 | "ACTIVE" : "PASSIVE", | ||
1251 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
1252 | active_dwell : passive_dwell); | ||
1253 | |||
1254 | scan_ch++; | ||
1255 | added++; | ||
1256 | } | ||
1257 | |||
1258 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); | ||
1259 | return added; | ||
1260 | } | ||
1261 | |||
1262 | void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||
1263 | { | ||
1264 | struct iwl_host_cmd cmd = { | ||
1265 | .id = REPLY_SCAN_CMD, | ||
1266 | .len = sizeof(struct iwl_scan_cmd), | ||
1267 | .flags = CMD_SIZE_HUGE, | ||
1268 | }; | ||
1269 | struct iwl_scan_cmd *scan; | ||
1270 | struct ieee80211_conf *conf = NULL; | ||
1271 | u32 rate_flags = 0; | ||
1272 | u16 cmd_len; | ||
1273 | u16 rx_chain = 0; | ||
1274 | enum ieee80211_band band; | ||
1275 | u8 n_probes = 0; | ||
1276 | u8 rx_ant = priv->hw_params.valid_rx_ant; | ||
1277 | u8 rate; | ||
1278 | bool is_active = false; | ||
1279 | int chan_mod; | ||
1280 | u8 active_chains; | ||
1281 | |||
1282 | conf = ieee80211_get_hw_conf(priv->hw); | ||
1283 | |||
1284 | cancel_delayed_work(&priv->scan_check); | ||
1285 | |||
1286 | if (!iwl_is_ready(priv)) { | ||
1287 | IWL_WARN(priv, "request scan called when driver not ready.\n"); | ||
1288 | goto done; | ||
1289 | } | ||
1290 | |||
1291 | /* Make sure the scan wasn't canceled before this queued work | ||
1292 | * was given the chance to run... */ | ||
1293 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
1294 | goto done; | ||
1295 | |||
1296 | /* This should never be called or scheduled if there is currently | ||
1297 | * a scan active in the hardware. */ | ||
1298 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
1299 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " | ||
1300 | "Ignoring second request.\n"); | ||
1301 | goto done; | ||
1302 | } | ||
1303 | |||
1304 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
1305 | IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); | ||
1306 | goto done; | ||
1307 | } | ||
1308 | |||
1309 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
1310 | IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); | ||
1311 | goto done; | ||
1312 | } | ||
1313 | |||
1314 | if (iwl_is_rfkill(priv)) { | ||
1315 | IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); | ||
1316 | goto done; | ||
1317 | } | ||
1318 | |||
1319 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
1320 | IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); | ||
1321 | goto done; | ||
1322 | } | ||
1323 | |||
1324 | if (!priv->scan_cmd) { | ||
1325 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | ||
1326 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
1327 | if (!priv->scan_cmd) { | ||
1328 | IWL_DEBUG_SCAN(priv, | ||
1329 | "fail to allocate memory for scan\n"); | ||
1330 | goto done; | ||
1331 | } | ||
1332 | } | ||
1333 | scan = priv->scan_cmd; | ||
1334 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | ||
1335 | |||
1336 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | ||
1337 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | ||
1338 | |||
1339 | if (iwl_is_associated(priv)) { | ||
1340 | u16 interval = 0; | ||
1341 | u32 extra; | ||
1342 | u32 suspend_time = 100; | ||
1343 | u32 scan_suspend_time = 100; | ||
1344 | unsigned long flags; | ||
1345 | |||
1346 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | ||
1347 | spin_lock_irqsave(&priv->lock, flags); | ||
1348 | interval = vif ? vif->bss_conf.beacon_int : 0; | ||
1349 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1350 | |||
1351 | scan->suspend_time = 0; | ||
1352 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
1353 | if (!interval) | ||
1354 | interval = suspend_time; | ||
1355 | |||
1356 | extra = (suspend_time / interval) << 22; | ||
1357 | scan_suspend_time = (extra | | ||
1358 | ((suspend_time % interval) * 1024)); | ||
1359 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | ||
1360 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | ||
1361 | scan_suspend_time, interval); | ||
1362 | } | ||
1363 | |||
1364 | if (priv->is_internal_short_scan) { | ||
1365 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
1366 | } else if (priv->scan_request->n_ssids) { | ||
1367 | int i, p = 0; | ||
1368 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | ||
1369 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
1370 | /* always does wildcard anyway */ | ||
1371 | if (!priv->scan_request->ssids[i].ssid_len) | ||
1372 | continue; | ||
1373 | scan->direct_scan[p].id = WLAN_EID_SSID; | ||
1374 | scan->direct_scan[p].len = | ||
1375 | priv->scan_request->ssids[i].ssid_len; | ||
1376 | memcpy(scan->direct_scan[p].ssid, | ||
1377 | priv->scan_request->ssids[i].ssid, | ||
1378 | priv->scan_request->ssids[i].ssid_len); | ||
1379 | n_probes++; | ||
1380 | p++; | ||
1381 | } | ||
1382 | is_active = true; | ||
1383 | } else | ||
1384 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | ||
1385 | |||
1386 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | ||
1387 | scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; | ||
1388 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
1389 | |||
1390 | switch (priv->scan_band) { | ||
1391 | case IEEE80211_BAND_2GHZ: | ||
1392 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | ||
1393 | chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) | ||
1394 | >> RXON_FLG_CHANNEL_MODE_POS; | ||
1395 | if (chan_mod == CHANNEL_MODE_PURE_40) { | ||
1396 | rate = IWL_RATE_6M_PLCP; | ||
1397 | } else { | ||
1398 | rate = IWL_RATE_1M_PLCP; | ||
1399 | rate_flags = RATE_MCS_CCK_MSK; | ||
1400 | } | ||
1401 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; | ||
1402 | break; | ||
1403 | case IEEE80211_BAND_5GHZ: | ||
1404 | rate = IWL_RATE_6M_PLCP; | ||
1405 | /* | ||
1406 | * If active scanning is requested but a certain channel is | ||
1407 | * marked passive, we can do active scanning if we detect | ||
1408 | * transmissions. | ||
1409 | * | ||
1410 | * There is an issue with some firmware versions that triggers | ||
1411 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
1412 | * on a radar channel even though this means that we should NOT | ||
1413 | * send probes. | ||
1414 | * | ||
1415 | * The "good CRC threshold" is the number of frames that we | ||
1416 | * need to receive during our dwell time on a channel before | ||
1417 | * sending out probes -- setting this to a huge value will | ||
1418 | * mean we never reach it, but at the same time work around | ||
1419 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
1420 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
1421 | */ | ||
1422 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
1423 | IWL_GOOD_CRC_TH_NEVER; | ||
1424 | break; | ||
1425 | default: | ||
1426 | IWL_WARN(priv, "Invalid scan band count\n"); | ||
1427 | goto done; | ||
1428 | } | ||
1429 | |||
1430 | band = priv->scan_band; | ||
1431 | |||
1432 | if (priv->cfg->scan_antennas[band]) | ||
1433 | rx_ant = priv->cfg->scan_antennas[band]; | ||
1434 | |||
1435 | priv->scan_tx_ant[band] = | ||
1436 | iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); | ||
1437 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | ||
1438 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | ||
1439 | |||
1440 | /* In power save mode use one chain, otherwise use all chains */ | ||
1441 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
1442 | /* rx_ant has been set to all valid chains previously */ | ||
1443 | active_chains = rx_ant & | ||
1444 | ((u8)(priv->chain_noise_data.active_chains)); | ||
1445 | if (!active_chains) | ||
1446 | active_chains = rx_ant; | ||
1447 | |||
1448 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
1449 | priv->chain_noise_data.active_chains); | ||
1450 | |||
1451 | rx_ant = first_antenna(active_chains); | ||
1452 | } | ||
1453 | /* MIMO is not used here, but value is required */ | ||
1454 | rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | ||
1455 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||
1456 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | ||
1457 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||
1458 | scan->rx_chain = cpu_to_le16(rx_chain); | ||
1459 | if (!priv->is_internal_short_scan) { | ||
1460 | cmd_len = iwl_fill_probe_req(priv, | ||
1461 | (struct ieee80211_mgmt *)scan->data, | ||
1462 | priv->scan_request->ie, | ||
1463 | priv->scan_request->ie_len, | ||
1464 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
1465 | } else { | ||
1466 | cmd_len = iwl_fill_probe_req(priv, | ||
1467 | (struct ieee80211_mgmt *)scan->data, | ||
1468 | NULL, 0, | ||
1469 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
1470 | |||
1471 | } | ||
1472 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | ||
1473 | |||
1474 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | ||
1475 | RXON_FILTER_BCON_AWARE_MSK); | ||
1476 | |||
1477 | if (priv->is_internal_short_scan) { | ||
1478 | scan->channel_count = | ||
1479 | iwl_get_single_channel_for_scan(priv, vif, band, | ||
1480 | (void *)&scan->data[le16_to_cpu( | ||
1481 | scan->tx_cmd.len)]); | ||
1482 | } else { | ||
1483 | scan->channel_count = | ||
1484 | iwl_get_channels_for_scan(priv, vif, band, | ||
1485 | is_active, n_probes, | ||
1486 | (void *)&scan->data[le16_to_cpu( | ||
1487 | scan->tx_cmd.len)]); | ||
1488 | } | ||
1489 | if (scan->channel_count == 0) { | ||
1490 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | ||
1491 | goto done; | ||
1492 | } | ||
1493 | |||
1494 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + | ||
1495 | scan->channel_count * sizeof(struct iwl_scan_channel); | ||
1496 | cmd.data = scan; | ||
1497 | scan->len = cpu_to_le16(cmd.len); | ||
1498 | |||
1499 | set_bit(STATUS_SCAN_HW, &priv->status); | ||
1500 | if (iwl_send_cmd_sync(priv, &cmd)) | ||
1501 | goto done; | ||
1502 | |||
1503 | queue_delayed_work(priv->workqueue, &priv->scan_check, | ||
1504 | IWL_SCAN_CHECK_WATCHDOG); | ||
1505 | |||
1506 | return; | ||
1507 | |||
1508 | done: | ||
1509 | /* Cannot perform scan. Make sure we clear scanning | ||
1510 | * bits from status so next scan request can be performed. | ||
1511 | * If we don't clear scanning status bit here all next scan | ||
1512 | * will fail | ||
1513 | */ | ||
1514 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
1515 | clear_bit(STATUS_SCANNING, &priv->status); | ||
1516 | /* inform mac80211 scan aborted */ | ||
1517 | queue_work(priv->workqueue, &priv->scan_completed); | ||
1518 | } | ||
1519 | |||
1520 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | ||
1521 | struct ieee80211_vif *vif, bool add) | ||
1522 | { | ||
1523 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1524 | |||
1525 | if (add) | ||
1526 | return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true, | ||
1527 | &vif_priv->ibss_bssid_sta_id); | ||
1528 | return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, | ||
1529 | vif->bss_conf.bssid); | ||
1530 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 1460116d329f..cf4a95bae4ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -295,11 +295,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) | |||
295 | return tl->total; | 295 | return tl->total; |
296 | } | 296 | } |
297 | 297 | ||
298 | static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | 298 | static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, |
299 | struct iwl_lq_sta *lq_data, u8 tid, | 299 | struct iwl_lq_sta *lq_data, u8 tid, |
300 | struct ieee80211_sta *sta) | 300 | struct ieee80211_sta *sta) |
301 | { | 301 | { |
302 | int ret; | 302 | int ret = -EAGAIN; |
303 | 303 | ||
304 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 304 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
305 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 305 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
@@ -313,29 +313,29 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
313 | */ | 313 | */ |
314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | 314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", |
315 | tid); | 315 | tid); |
316 | ret = ieee80211_stop_tx_ba_session(sta, tid, | 316 | ieee80211_stop_tx_ba_session(sta, tid, |
317 | WLAN_BACK_INITIATOR); | 317 | WLAN_BACK_INITIATOR); |
318 | } | 318 | } |
319 | } | 319 | } else |
320 | IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); | ||
321 | return ret; | ||
320 | } | 322 | } |
321 | 323 | ||
322 | static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, | 324 | static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, |
323 | struct iwl_lq_sta *lq_data, | 325 | struct iwl_lq_sta *lq_data, |
324 | struct ieee80211_sta *sta) | 326 | struct ieee80211_sta *sta) |
325 | { | 327 | { |
326 | if ((tid < TID_MAX_LOAD_COUNT)) | 328 | if ((tid < TID_MAX_LOAD_COUNT) && |
327 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 329 | !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { |
328 | else if (tid == IWL_AGG_ALL_TID) | 330 | if (priv->cfg->use_rts_for_ht) { |
329 | for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) | 331 | /* |
330 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 332 | * switch to RTS/CTS if it is the prefer protection |
331 | if (priv->cfg->use_rts_for_ht) { | 333 | * method for HT traffic |
332 | /* | 334 | */ |
333 | * switch to RTS/CTS if it is the prefer protection method | 335 | IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); |
334 | * for HT traffic | 336 | priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; |
335 | */ | 337 | iwlcore_commit_rxon(priv); |
336 | IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); | 338 | } |
337 | priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; | ||
338 | iwlcore_commit_rxon(priv); | ||
339 | } | 339 | } |
340 | } | 340 | } |
341 | 341 | ||
@@ -611,10 +611,6 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, | |||
611 | struct ieee80211_hdr *hdr, | 611 | struct ieee80211_hdr *hdr, |
612 | enum iwl_table_type rate_type) | 612 | enum iwl_table_type rate_type) |
613 | { | 613 | { |
614 | if (hdr && is_multicast_ether_addr(hdr->addr1) && | ||
615 | lq_sta->active_rate_basic) | ||
616 | return lq_sta->active_rate_basic; | ||
617 | |||
618 | if (is_legacy(rate_type)) { | 614 | if (is_legacy(rate_type)) { |
619 | return lq_sta->active_legacy_rate; | 615 | return lq_sta->active_legacy_rate; |
620 | } else { | 616 | } else { |
@@ -775,6 +771,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
775 | 771 | ||
776 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 772 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
777 | 773 | ||
774 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
775 | if (!lq_sta) { | ||
776 | IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n"); | ||
777 | return; | ||
778 | } else if (!lq_sta->drv) { | ||
779 | IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); | ||
780 | return; | ||
781 | } | ||
782 | |||
778 | if (!ieee80211_is_data(hdr->frame_control) || | 783 | if (!ieee80211_is_data(hdr->frame_control) || |
779 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 784 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
780 | return; | 785 | return; |
@@ -784,10 +789,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
784 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 789 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
785 | return; | 790 | return; |
786 | 791 | ||
787 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
788 | !lq_sta->ibss_sta_added) | ||
789 | return; | ||
790 | |||
791 | /* | 792 | /* |
792 | * Ignore this Tx frame response if its initial rate doesn't match | 793 | * Ignore this Tx frame response if its initial rate doesn't match |
793 | * that of latest Link Quality command. There may be stragglers | 794 | * that of latest Link Quality command. There may be stragglers |
@@ -833,7 +834,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
833 | lq_sta->missed_rate_counter++; | 834 | lq_sta->missed_rate_counter++; |
834 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 835 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
835 | lq_sta->missed_rate_counter = 0; | 836 | lq_sta->missed_rate_counter = 0; |
836 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 837 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
837 | } | 838 | } |
838 | /* Regardless, ignore this status info for outdated rate */ | 839 | /* Regardless, ignore this status info for outdated rate */ |
839 | return; | 840 | return; |
@@ -867,14 +868,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, | 868 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
868 | &rs_index); | 869 | &rs_index); |
869 | rs_collect_tx_data(curr_tbl, rs_index, | 870 | rs_collect_tx_data(curr_tbl, rs_index, |
870 | info->status.ampdu_ack_len, | 871 | info->status.ampdu_len, |
871 | info->status.ampdu_ack_map); | 872 | info->status.ampdu_ack_len); |
872 | 873 | ||
873 | /* Update success/fail counts if not searching for new mode */ | 874 | /* Update success/fail counts if not searching for new mode */ |
874 | if (lq_sta->stay_in_tbl) { | 875 | if (lq_sta->stay_in_tbl) { |
875 | lq_sta->total_success += info->status.ampdu_ack_map; | 876 | lq_sta->total_success += info->status.ampdu_ack_len; |
876 | lq_sta->total_failed += (info->status.ampdu_ack_len - | 877 | lq_sta->total_failed += (info->status.ampdu_len - |
877 | info->status.ampdu_ack_map); | 878 | info->status.ampdu_ack_len); |
878 | } | 879 | } |
879 | } else { | 880 | } else { |
880 | /* | 881 | /* |
@@ -1913,7 +1914,7 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv, | |||
1913 | /* Update uCode's rate table. */ | 1914 | /* Update uCode's rate table. */ |
1914 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); | 1915 | rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); |
1915 | rs_fill_link_cmd(priv, lq_sta, rate); | 1916 | rs_fill_link_cmd(priv, lq_sta, rate); |
1916 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 1917 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
1917 | 1918 | ||
1918 | return rate; | 1919 | return rate; |
1919 | } | 1920 | } |
@@ -2002,7 +2003,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2002 | /* rates available for this association, and for modulation mode */ | 2003 | /* rates available for this association, and for modulation mode */ |
2003 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); | 2004 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); |
2004 | 2005 | ||
2005 | IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); | 2006 | IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask); |
2006 | 2007 | ||
2007 | /* mask with station rate restriction */ | 2008 | /* mask with station rate restriction */ |
2008 | if (is_legacy(tbl->lq_type)) { | 2009 | if (is_legacy(tbl->lq_type)) { |
@@ -2077,10 +2078,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2077 | } | 2078 | } |
2078 | /* Else we have enough samples; calculate estimate of | 2079 | /* Else we have enough samples; calculate estimate of |
2079 | * actual average throughput */ | 2080 | * actual average throughput */ |
2080 | 2081 | if (window->average_tpt != ((window->success_ratio * | |
2081 | /* Sanity-check TPT calculations */ | 2082 | tbl->expected_tpt[index] + 64) / 128)) { |
2082 | BUG_ON(window->average_tpt != ((window->success_ratio * | 2083 | IWL_ERR(priv, "expected_tpt should have been calculated by now\n"); |
2083 | tbl->expected_tpt[index] + 64) / 128)); | 2084 | window->average_tpt = ((window->success_ratio * |
2085 | tbl->expected_tpt[index] + 64) / 128); | ||
2086 | } | ||
2084 | 2087 | ||
2085 | /* If we are searching for better modulation mode, check success. */ | 2088 | /* If we are searching for better modulation mode, check success. */ |
2086 | if (lq_sta->search_better_tbl && | 2089 | if (lq_sta->search_better_tbl && |
@@ -2289,7 +2292,7 @@ lq_update: | |||
2289 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", | 2292 | IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", |
2290 | tbl->current_rate, index); | 2293 | tbl->current_rate, index); |
2291 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); | 2294 | rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); |
2292 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2295 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC, false); |
2293 | } else | 2296 | } else |
2294 | done_search = 1; | 2297 | done_search = 1; |
2295 | } | 2298 | } |
@@ -2334,11 +2337,22 @@ out: | |||
2334 | tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); | 2337 | tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); |
2335 | i = index; | 2338 | i = index; |
2336 | lq_sta->last_txrate_idx = i; | 2339 | lq_sta->last_txrate_idx = i; |
2337 | |||
2338 | return; | ||
2339 | } | 2340 | } |
2340 | 2341 | ||
2341 | 2342 | /** | |
2343 | * rs_initialize_lq - Initialize a station's hardware rate table | ||
2344 | * | ||
2345 | * The uCode's station table contains a table of fallback rates | ||
2346 | * for automatic fallback during transmission. | ||
2347 | * | ||
2348 | * NOTE: This sets up a default set of values. These will be replaced later | ||
2349 | * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of | ||
2350 | * rc80211_simple. | ||
2351 | * | ||
2352 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
2353 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
2354 | * which requires station table entry to exist). | ||
2355 | */ | ||
2342 | static void rs_initialize_lq(struct iwl_priv *priv, | 2356 | static void rs_initialize_lq(struct iwl_priv *priv, |
2343 | struct ieee80211_conf *conf, | 2357 | struct ieee80211_conf *conf, |
2344 | struct ieee80211_sta *sta, | 2358 | struct ieee80211_sta *sta, |
@@ -2357,10 +2371,6 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2357 | 2371 | ||
2358 | i = lq_sta->last_txrate_idx; | 2372 | i = lq_sta->last_txrate_idx; |
2359 | 2373 | ||
2360 | if ((lq_sta->lq.sta_id == 0xff) && | ||
2361 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) | ||
2362 | goto out; | ||
2363 | |||
2364 | valid_tx_ant = priv->hw_params.valid_tx_ant; | 2374 | valid_tx_ant = priv->hw_params.valid_tx_ant; |
2365 | 2375 | ||
2366 | if (!lq_sta->search_better_tbl) | 2376 | if (!lq_sta->search_better_tbl) |
@@ -2388,7 +2398,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2388 | tbl->current_rate = rate; | 2398 | tbl->current_rate = rate; |
2389 | rs_set_expected_tpt_table(lq_sta, tbl); | 2399 | rs_set_expected_tpt_table(lq_sta, tbl); |
2390 | rs_fill_link_cmd(NULL, lq_sta, rate); | 2400 | rs_fill_link_cmd(NULL, lq_sta, rate); |
2391 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2401 | priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq; |
2402 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_SYNC, true); | ||
2392 | out: | 2403 | out: |
2393 | return; | 2404 | return; |
2394 | } | 2405 | } |
@@ -2399,10 +2410,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2399 | 2410 | ||
2400 | struct sk_buff *skb = txrc->skb; | 2411 | struct sk_buff *skb = txrc->skb; |
2401 | struct ieee80211_supported_band *sband = txrc->sband; | 2412 | struct ieee80211_supported_band *sband = txrc->sband; |
2402 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2413 | struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; |
2403 | struct ieee80211_conf *conf = &priv->hw->conf; | ||
2404 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2405 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
2406 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2414 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2407 | struct iwl_lq_sta *lq_sta = priv_sta; | 2415 | struct iwl_lq_sta *lq_sta = priv_sta; |
2408 | int rate_idx; | 2416 | int rate_idx; |
@@ -2420,30 +2428,18 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2420 | lq_sta->max_rate_idx = -1; | 2428 | lq_sta->max_rate_idx = -1; |
2421 | } | 2429 | } |
2422 | 2430 | ||
2431 | /* Treat uninitialized rate scaling data same as non-existing. */ | ||
2432 | if (lq_sta && !lq_sta->drv) { | ||
2433 | IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n"); | ||
2434 | priv_sta = NULL; | ||
2435 | } | ||
2436 | |||
2423 | /* Send management frames and NO_ACK data using lowest rate. */ | 2437 | /* Send management frames and NO_ACK data using lowest rate. */ |
2424 | if (rate_control_send_low(sta, priv_sta, txrc)) | 2438 | if (rate_control_send_low(sta, priv_sta, txrc)) |
2425 | return; | 2439 | return; |
2426 | 2440 | ||
2427 | rate_idx = lq_sta->last_txrate_idx; | 2441 | rate_idx = lq_sta->last_txrate_idx; |
2428 | 2442 | ||
2429 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
2430 | !lq_sta->ibss_sta_added) { | ||
2431 | u8 sta_id = iwl_find_station(priv, hdr->addr1); | ||
2432 | |||
2433 | if (sta_id == IWL_INVALID_STATION) { | ||
2434 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", | ||
2435 | hdr->addr1); | ||
2436 | sta_id = iwl_add_station(priv, hdr->addr1, | ||
2437 | false, CMD_ASYNC, ht_cap); | ||
2438 | } | ||
2439 | if ((sta_id != IWL_INVALID_STATION)) { | ||
2440 | lq_sta->lq.sta_id = sta_id; | ||
2441 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | ||
2442 | lq_sta->ibss_sta_added = 1; | ||
2443 | rs_initialize_lq(priv, conf, sta, lq_sta); | ||
2444 | } | ||
2445 | } | ||
2446 | |||
2447 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { | 2443 | if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { |
2448 | rate_idx -= IWL_FIRST_OFDM_RATE; | 2444 | rate_idx -= IWL_FIRST_OFDM_RATE; |
2449 | /* 6M and 9M shared same MCS index */ | 2445 | /* 6M and 9M shared same MCS index */ |
@@ -2493,16 +2489,25 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | |||
2493 | return lq_sta; | 2489 | return lq_sta; |
2494 | } | 2490 | } |
2495 | 2491 | ||
2496 | static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | 2492 | /* |
2497 | struct ieee80211_sta *sta, void *priv_sta) | 2493 | * Called after adding a new station to initialize rate scaling |
2494 | */ | ||
2495 | void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) | ||
2498 | { | 2496 | { |
2499 | int i, j; | 2497 | int i, j; |
2500 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2498 | struct ieee80211_hw *hw = priv->hw; |
2501 | struct ieee80211_conf *conf = &priv->hw->conf; | 2499 | struct ieee80211_conf *conf = &priv->hw->conf; |
2502 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2500 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
2503 | struct iwl_lq_sta *lq_sta = priv_sta; | 2501 | struct iwl_station_priv *sta_priv; |
2502 | struct iwl_lq_sta *lq_sta; | ||
2503 | struct ieee80211_supported_band *sband; | ||
2504 | |||
2505 | sta_priv = (struct iwl_station_priv *) sta->drv_priv; | ||
2506 | lq_sta = &sta_priv->lq_sta; | ||
2507 | sband = hw->wiphy->bands[conf->channel->band]; | ||
2504 | 2508 | ||
2505 | lq_sta->lq.sta_id = 0xff; | 2509 | |
2510 | lq_sta->lq.sta_id = sta_id; | ||
2506 | 2511 | ||
2507 | for (j = 0; j < LQ_SIZE; j++) | 2512 | for (j = 0; j < LQ_SIZE; j++) |
2508 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2513 | for (i = 0; i < IWL_RATE_COUNT; i++) |
@@ -2514,39 +2519,18 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2514 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2519 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2515 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2520 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
2516 | 2521 | ||
2517 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); | 2522 | IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init for station %d ***\n", |
2523 | sta_id); | ||
2518 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 2524 | /* TODO: what is a good starting rate for STA? About middle? Maybe not |
2519 | * the lowest or the highest rate.. Could consider using RSSI from | 2525 | * the lowest or the highest rate.. Could consider using RSSI from |
2520 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 2526 | * previous packets? Need to have IEEE 802.1X auth succeed immediately |
2521 | * after assoc.. */ | 2527 | * after assoc.. */ |
2522 | 2528 | ||
2523 | lq_sta->ibss_sta_added = 0; | ||
2524 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | ||
2525 | u8 sta_id = iwl_find_station(priv, | ||
2526 | sta->addr); | ||
2527 | |||
2528 | /* for IBSS the call are from tasklet */ | ||
2529 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | ||
2530 | |||
2531 | if (sta_id == IWL_INVALID_STATION) { | ||
2532 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | ||
2533 | sta_id = iwl_add_station(priv, sta->addr, false, | ||
2534 | CMD_ASYNC, ht_cap); | ||
2535 | } | ||
2536 | if ((sta_id != IWL_INVALID_STATION)) { | ||
2537 | lq_sta->lq.sta_id = sta_id; | ||
2538 | lq_sta->lq.rs_table[0].rate_n_flags = 0; | ||
2539 | } | ||
2540 | /* FIXME: this is w/a remove it later */ | ||
2541 | priv->assoc_station_added = 1; | ||
2542 | } | ||
2543 | |||
2544 | lq_sta->is_dup = 0; | 2529 | lq_sta->is_dup = 0; |
2545 | lq_sta->max_rate_idx = -1; | 2530 | lq_sta->max_rate_idx = -1; |
2546 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2531 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
2547 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); | 2532 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); |
2548 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2533 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); |
2549 | lq_sta->active_rate_basic = priv->active_rate_basic; | ||
2550 | lq_sta->band = priv->band; | 2534 | lq_sta->band = priv->band; |
2551 | /* | 2535 | /* |
2552 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2536 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), |
@@ -2574,8 +2558,17 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2574 | lq_sta->active_mimo3_rate); | 2558 | lq_sta->active_mimo3_rate); |
2575 | 2559 | ||
2576 | /* These values will be overridden later */ | 2560 | /* These values will be overridden later */ |
2577 | lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; | 2561 | lq_sta->lq.general_params.single_stream_ant_msk = |
2578 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 2562 | first_antenna(priv->hw_params.valid_tx_ant); |
2563 | lq_sta->lq.general_params.dual_stream_ant_msk = | ||
2564 | priv->hw_params.valid_tx_ant & | ||
2565 | ~first_antenna(priv->hw_params.valid_tx_ant); | ||
2566 | if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | ||
2567 | lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | ||
2568 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | ||
2569 | lq_sta->lq.general_params.dual_stream_ant_msk = | ||
2570 | priv->hw_params.valid_tx_ant; | ||
2571 | } | ||
2579 | 2572 | ||
2580 | /* as default allow aggregation for all tids */ | 2573 | /* as default allow aggregation for all tids */ |
2581 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; | 2574 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; |
@@ -2794,7 +2787,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2794 | 2787 | ||
2795 | if (lq_sta->dbg_fixed_rate) { | 2788 | if (lq_sta->dbg_fixed_rate) { |
2796 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); | 2789 | rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); |
2797 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); | 2790 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false); |
2798 | } | 2791 | } |
2799 | 2792 | ||
2800 | return count; | 2793 | return count; |
@@ -2950,12 +2943,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, | |||
2950 | desc += sprintf(buff+desc, | 2943 | desc += sprintf(buff+desc, |
2951 | "Bit Rate= %d Mb/s\n", | 2944 | "Bit Rate= %d Mb/s\n", |
2952 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); | 2945 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); |
2953 | desc += sprintf(buff+desc, | ||
2954 | "Signal Level= %d dBm\tNoise Level= %d dBm\n", | ||
2955 | priv->last_rx_rssi, priv->last_rx_noise); | ||
2956 | desc += sprintf(buff+desc, | ||
2957 | "Tsf= 0x%llx\tBeacon time= 0x%08X\n", | ||
2958 | priv->last_tsf, priv->last_beacon_time); | ||
2959 | 2946 | ||
2960 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2947 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
2961 | return ret; | 2948 | return ret; |
@@ -2995,12 +2982,21 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) | |||
2995 | } | 2982 | } |
2996 | #endif | 2983 | #endif |
2997 | 2984 | ||
2985 | /* | ||
2986 | * Initialization of rate scaling information is done by driver after | ||
2987 | * the station is added. Since mac80211 calls this function before a | ||
2988 | * station is added we ignore it. | ||
2989 | */ | ||
2990 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | ||
2991 | struct ieee80211_sta *sta, void *priv_sta) | ||
2992 | { | ||
2993 | } | ||
2998 | static struct rate_control_ops rs_ops = { | 2994 | static struct rate_control_ops rs_ops = { |
2999 | .module = NULL, | 2995 | .module = NULL, |
3000 | .name = RS_NAME, | 2996 | .name = RS_NAME, |
3001 | .tx_status = rs_tx_status, | 2997 | .tx_status = rs_tx_status, |
3002 | .get_rate = rs_get_rate, | 2998 | .get_rate = rs_get_rate, |
3003 | .rate_init = rs_rate_init, | 2999 | .rate_init = rs_rate_init_stub, |
3004 | .alloc = rs_alloc, | 3000 | .alloc = rs_alloc, |
3005 | .free = rs_free, | 3001 | .free = rs_free, |
3006 | .alloc_sta = rs_alloc_sta, | 3002 | .alloc_sta = rs_alloc_sta, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index e71923961e69..8292f6d48ec6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -403,7 +403,6 @@ struct iwl_lq_sta { | |||
403 | u8 is_green; | 403 | u8 is_green; |
404 | u8 is_dup; | 404 | u8 is_dup; |
405 | enum ieee80211_band band; | 405 | enum ieee80211_band band; |
406 | u8 ibss_sta_added; | ||
407 | 406 | ||
408 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 407 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
409 | u32 supp_rates; | 408 | u32 supp_rates; |
@@ -411,7 +410,6 @@ struct iwl_lq_sta { | |||
411 | u16 active_siso_rate; | 410 | u16 active_siso_rate; |
412 | u16 active_mimo2_rate; | 411 | u16 active_mimo2_rate; |
413 | u16 active_mimo3_rate; | 412 | u16 active_mimo3_rate; |
414 | u16 active_rate_basic; | ||
415 | s8 max_rate_idx; /* Max rate set by user */ | 413 | s8 max_rate_idx; /* Max rate set by user */ |
416 | u8 missed_rate_counter; | 414 | u8 missed_rate_counter; |
417 | 415 | ||
@@ -479,6 +477,12 @@ static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) | |||
479 | */ | 477 | */ |
480 | extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); | 478 | extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); |
481 | 479 | ||
480 | /* Initialize station's rate scaling information after adding station */ | ||
481 | extern void iwl_rs_rate_init(struct iwl_priv *priv, | ||
482 | struct ieee80211_sta *sta, u8 sta_id); | ||
483 | extern void iwl3945_rs_rate_init(struct iwl_priv *priv, | ||
484 | struct ieee80211_sta *sta, u8 sta_id); | ||
485 | |||
482 | /** | 486 | /** |
483 | * iwl_rate_control_register - Register the rate control algorithm callbacks | 487 | * iwl_rate_control_register - Register the rate control algorithm callbacks |
484 | * | 488 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c new file mode 100644 index 000000000000..c402bfc83f36 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -0,0 +1,1340 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-sta.h" | ||
38 | #include "iwl-io.h" | ||
39 | #include "iwl-helpers.h" | ||
40 | #include "iwl-agn-hw.h" | ||
41 | #include "iwl-agn.h" | ||
42 | |||
43 | /* | ||
44 | * mac80211 queues, ACs, hardware queues, FIFOs. | ||
45 | * | ||
46 | * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues | ||
47 | * | ||
48 | * Mac80211 uses the following numbers, which we get as from it | ||
49 | * by way of skb_get_queue_mapping(skb): | ||
50 | * | ||
51 | * VO 0 | ||
52 | * VI 1 | ||
53 | * BE 2 | ||
54 | * BK 3 | ||
55 | * | ||
56 | * | ||
57 | * Regular (not A-MPDU) frames are put into hardware queues corresponding | ||
58 | * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their | ||
59 | * own queue per aggregation session (RA/TID combination), such queues are | ||
60 | * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In | ||
61 | * order to map frames to the right queue, we also need an AC->hw queue | ||
62 | * mapping. This is implemented here. | ||
63 | * | ||
64 | * Due to the way hw queues are set up (by the hw specific modules like | ||
65 | * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity | ||
66 | * mapping. | ||
67 | */ | ||
68 | |||
69 | static const u8 tid_to_ac[] = { | ||
70 | /* this matches the mac80211 numbers */ | ||
71 | 2, 3, 3, 2, 1, 1, 0, 0 | ||
72 | }; | ||
73 | |||
74 | static const u8 ac_to_fifo[] = { | ||
75 | IWL_TX_FIFO_VO, | ||
76 | IWL_TX_FIFO_VI, | ||
77 | IWL_TX_FIFO_BE, | ||
78 | IWL_TX_FIFO_BK, | ||
79 | }; | ||
80 | |||
81 | static inline int get_fifo_from_ac(u8 ac) | ||
82 | { | ||
83 | return ac_to_fifo[ac]; | ||
84 | } | ||
85 | |||
86 | static inline int get_ac_from_tid(u16 tid) | ||
87 | { | ||
88 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
89 | return tid_to_ac[tid]; | ||
90 | |||
91 | /* no support for TIDs 8-15 yet */ | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | static inline int get_fifo_from_tid(u16 tid) | ||
96 | { | ||
97 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
98 | return get_fifo_from_ac(tid_to_ac[tid]); | ||
99 | |||
100 | /* no support for TIDs 8-15 yet */ | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
106 | */ | ||
107 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
108 | struct iwl_tx_queue *txq, | ||
109 | u16 byte_cnt) | ||
110 | { | ||
111 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
112 | int write_ptr = txq->q.write_ptr; | ||
113 | int txq_id = txq->q.id; | ||
114 | u8 sec_ctl = 0; | ||
115 | u8 sta_id = 0; | ||
116 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
117 | __le16 bc_ent; | ||
118 | |||
119 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
120 | |||
121 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
122 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | ||
123 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | ||
124 | |||
125 | switch (sec_ctl & TX_CMD_SEC_MSK) { | ||
126 | case TX_CMD_SEC_CCM: | ||
127 | len += CCMP_MIC_LEN; | ||
128 | break; | ||
129 | case TX_CMD_SEC_TKIP: | ||
130 | len += TKIP_ICV_LEN; | ||
131 | break; | ||
132 | case TX_CMD_SEC_WEP: | ||
133 | len += WEP_IV_LEN + WEP_ICV_LEN; | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | ||
139 | |||
140 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
141 | |||
142 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
143 | scd_bc_tbl[txq_id]. | ||
144 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
145 | } | ||
146 | |||
147 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
148 | struct iwl_tx_queue *txq) | ||
149 | { | ||
150 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
151 | int txq_id = txq->q.id; | ||
152 | int read_ptr = txq->q.read_ptr; | ||
153 | u8 sta_id = 0; | ||
154 | __le16 bc_ent; | ||
155 | |||
156 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | ||
157 | |||
158 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
159 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | ||
160 | |||
161 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | ||
162 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | ||
163 | |||
164 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
165 | scd_bc_tbl[txq_id]. | ||
166 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | ||
167 | } | ||
168 | |||
169 | static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
170 | u16 txq_id) | ||
171 | { | ||
172 | u32 tbl_dw_addr; | ||
173 | u32 tbl_dw; | ||
174 | u16 scd_q2ratid; | ||
175 | |||
176 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
177 | |||
178 | tbl_dw_addr = priv->scd_base_addr + | ||
179 | IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
180 | |||
181 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
182 | |||
183 | if (txq_id & 0x1) | ||
184 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
185 | else | ||
186 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
187 | |||
188 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) | ||
194 | { | ||
195 | /* Simply stop the queue, but don't change any configuration; | ||
196 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
197 | iwl_write_prph(priv, | ||
198 | IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), | ||
199 | (0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
200 | (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
201 | } | ||
202 | |||
203 | void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | ||
204 | int txq_id, u32 index) | ||
205 | { | ||
206 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
207 | (index & 0xff) | (txq_id << 8)); | ||
208 | iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index); | ||
209 | } | ||
210 | |||
211 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | ||
212 | struct iwl_tx_queue *txq, | ||
213 | int tx_fifo_id, int scd_retry) | ||
214 | { | ||
215 | int txq_id = txq->q.id; | ||
216 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
217 | |||
218 | iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), | ||
219 | (active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
220 | (tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
221 | (1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
222 | IWLAGN_SCD_QUEUE_STTS_REG_MSK); | ||
223 | |||
224 | txq->sched_retry = scd_retry; | ||
225 | |||
226 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", | ||
227 | active ? "Activate" : "Deactivate", | ||
228 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | ||
229 | } | ||
230 | |||
231 | int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
232 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
233 | { | ||
234 | unsigned long flags; | ||
235 | u16 ra_tid; | ||
236 | |||
237 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | ||
238 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
239 | <= txq_id)) { | ||
240 | IWL_WARN(priv, | ||
241 | "queue number out of range: %d, must be %d to %d\n", | ||
242 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
243 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
244 | priv->cfg->num_of_ampdu_queues - 1); | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
248 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
249 | |||
250 | /* Modify device's station table to Tx this TID */ | ||
251 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
252 | |||
253 | spin_lock_irqsave(&priv->lock, flags); | ||
254 | |||
255 | /* Stop this Tx queue before configuring it */ | ||
256 | iwlagn_tx_queue_stop_scheduler(priv, txq_id); | ||
257 | |||
258 | /* Map receiver-address / traffic-ID to this queue */ | ||
259 | iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
260 | |||
261 | /* Set this queue as a chain-building queue */ | ||
262 | iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<<txq_id)); | ||
263 | |||
264 | /* enable aggregations for the queue */ | ||
265 | iwl_set_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1<<txq_id)); | ||
266 | |||
267 | /* Place first TFD at index corresponding to start sequence number. | ||
268 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
269 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
270 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
271 | iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
272 | |||
273 | /* Set up Tx window size and frame limit for this queue */ | ||
274 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
275 | IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | ||
276 | sizeof(u32), | ||
277 | ((SCD_WIN_SIZE << | ||
278 | IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
279 | IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
280 | ((SCD_FRAME_LIMIT << | ||
281 | IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
282 | IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
283 | |||
284 | iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
285 | |||
286 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
287 | iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
288 | |||
289 | spin_unlock_irqrestore(&priv->lock, flags); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
295 | u16 ssn_idx, u8 tx_fifo) | ||
296 | { | ||
297 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | ||
298 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
299 | <= txq_id)) { | ||
300 | IWL_ERR(priv, | ||
301 | "queue number out of range: %d, must be %d to %d\n", | ||
302 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
303 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
304 | priv->cfg->num_of_ampdu_queues - 1); | ||
305 | return -EINVAL; | ||
306 | } | ||
307 | |||
308 | iwlagn_tx_queue_stop_scheduler(priv, txq_id); | ||
309 | |||
310 | iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id)); | ||
311 | |||
312 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
313 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
314 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
315 | iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
316 | |||
317 | iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
318 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
319 | iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
326 | * must be called under priv->lock and mac access | ||
327 | */ | ||
328 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
329 | { | ||
330 | iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); | ||
331 | } | ||
332 | |||
333 | static inline int get_queue_from_ac(u16 ac) | ||
334 | { | ||
335 | return ac; | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | * handle build REPLY_TX command notification. | ||
340 | */ | ||
341 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | ||
342 | struct iwl_tx_cmd *tx_cmd, | ||
343 | struct ieee80211_tx_info *info, | ||
344 | struct ieee80211_hdr *hdr, | ||
345 | u8 std_id) | ||
346 | { | ||
347 | __le16 fc = hdr->frame_control; | ||
348 | __le32 tx_flags = tx_cmd->tx_flags; | ||
349 | |||
350 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
351 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
352 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
353 | if (ieee80211_is_mgmt(fc)) | ||
354 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
355 | if (ieee80211_is_probe_resp(fc) && | ||
356 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
357 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
358 | } else { | ||
359 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
360 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
361 | } | ||
362 | |||
363 | if (ieee80211_is_back_req(fc)) | ||
364 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
365 | |||
366 | |||
367 | tx_cmd->sta_id = std_id; | ||
368 | if (ieee80211_has_morefrags(fc)) | ||
369 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
370 | |||
371 | if (ieee80211_is_data_qos(fc)) { | ||
372 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
373 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
374 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
375 | } else { | ||
376 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
377 | } | ||
378 | |||
379 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | ||
380 | |||
381 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
382 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
383 | |||
384 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
385 | if (ieee80211_is_mgmt(fc)) { | ||
386 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
387 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
388 | else | ||
389 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
390 | } else { | ||
391 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
392 | } | ||
393 | |||
394 | tx_cmd->driver_txop = 0; | ||
395 | tx_cmd->tx_flags = tx_flags; | ||
396 | tx_cmd->next_frame_len = 0; | ||
397 | } | ||
398 | |||
399 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
400 | |||
401 | static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | ||
402 | struct iwl_tx_cmd *tx_cmd, | ||
403 | struct ieee80211_tx_info *info, | ||
404 | __le16 fc) | ||
405 | { | ||
406 | u32 rate_flags; | ||
407 | int rate_idx; | ||
408 | u8 rts_retry_limit; | ||
409 | u8 data_retry_limit; | ||
410 | u8 rate_plcp; | ||
411 | |||
412 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
413 | if (ieee80211_is_probe_resp(fc)) | ||
414 | data_retry_limit = 3; | ||
415 | else | ||
416 | data_retry_limit = IWLAGN_DEFAULT_TX_RETRY; | ||
417 | tx_cmd->data_retry_limit = data_retry_limit; | ||
418 | |||
419 | /* Set retry limit on RTS packets */ | ||
420 | rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; | ||
421 | if (data_retry_limit < rts_retry_limit) | ||
422 | rts_retry_limit = data_retry_limit; | ||
423 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
424 | |||
425 | /* DATA packets will use the uCode station table for rate/antenna | ||
426 | * selection */ | ||
427 | if (ieee80211_is_data(fc)) { | ||
428 | tx_cmd->initial_rate_index = 0; | ||
429 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
435 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
436 | * this band. Also use the lowest supported rate if the stored rate | ||
437 | * index is invalid. | ||
438 | */ | ||
439 | rate_idx = info->control.rates[0].idx; | ||
440 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
441 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
442 | rate_idx = rate_lowest_index(&priv->bands[info->band], | ||
443 | info->control.sta); | ||
444 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
445 | if (info->band == IEEE80211_BAND_5GHZ) | ||
446 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
447 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
448 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
449 | /* Zero out flags for this packet */ | ||
450 | rate_flags = 0; | ||
451 | |||
452 | /* Set CCK flag as needed */ | ||
453 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
454 | rate_flags |= RATE_MCS_CCK_MSK; | ||
455 | |||
456 | /* Set up RTS and CTS flags for certain packets */ | ||
457 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
458 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
459 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
460 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
461 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
462 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
463 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
464 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
465 | } | ||
466 | break; | ||
467 | default: | ||
468 | break; | ||
469 | } | ||
470 | |||
471 | /* Set up antennas */ | ||
472 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | ||
473 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
474 | |||
475 | /* Set the rate in the TX cmd */ | ||
476 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
477 | } | ||
478 | |||
479 | static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
480 | struct ieee80211_tx_info *info, | ||
481 | struct iwl_tx_cmd *tx_cmd, | ||
482 | struct sk_buff *skb_frag, | ||
483 | int sta_id) | ||
484 | { | ||
485 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
486 | |||
487 | switch (keyconf->alg) { | ||
488 | case ALG_CCMP: | ||
489 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
490 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
491 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
492 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
493 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
494 | break; | ||
495 | |||
496 | case ALG_TKIP: | ||
497 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
498 | ieee80211_get_tkip_key(keyconf, skb_frag, | ||
499 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
500 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
501 | break; | ||
502 | |||
503 | case ALG_WEP: | ||
504 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
505 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
506 | |||
507 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
508 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
509 | |||
510 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
511 | |||
512 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
513 | "with key %d\n", keyconf->keyidx); | ||
514 | break; | ||
515 | |||
516 | default: | ||
517 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | ||
518 | break; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * start REPLY_TX command process | ||
524 | */ | ||
525 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
526 | { | ||
527 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
528 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
529 | struct ieee80211_sta *sta = info->control.sta; | ||
530 | struct iwl_station_priv *sta_priv = NULL; | ||
531 | struct iwl_tx_queue *txq; | ||
532 | struct iwl_queue *q; | ||
533 | struct iwl_device_cmd *out_cmd; | ||
534 | struct iwl_cmd_meta *out_meta; | ||
535 | struct iwl_tx_cmd *tx_cmd; | ||
536 | int swq_id, txq_id; | ||
537 | dma_addr_t phys_addr; | ||
538 | dma_addr_t txcmd_phys; | ||
539 | dma_addr_t scratch_phys; | ||
540 | u16 len, len_org, firstlen, secondlen; | ||
541 | u16 seq_number = 0; | ||
542 | __le16 fc; | ||
543 | u8 hdr_len; | ||
544 | u8 sta_id; | ||
545 | u8 wait_write_ptr = 0; | ||
546 | u8 tid = 0; | ||
547 | u8 *qc = NULL; | ||
548 | unsigned long flags; | ||
549 | |||
550 | spin_lock_irqsave(&priv->lock, flags); | ||
551 | if (iwl_is_rfkill(priv)) { | ||
552 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
553 | goto drop_unlock; | ||
554 | } | ||
555 | |||
556 | fc = hdr->frame_control; | ||
557 | |||
558 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
559 | if (ieee80211_is_auth(fc)) | ||
560 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
561 | else if (ieee80211_is_assoc_req(fc)) | ||
562 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
563 | else if (ieee80211_is_reassoc_req(fc)) | ||
564 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
565 | #endif | ||
566 | |||
567 | hdr_len = ieee80211_hdrlen(fc); | ||
568 | |||
569 | /* Find index into station table for destination station */ | ||
570 | if (!info->control.sta) | ||
571 | sta_id = priv->hw_params.bcast_sta_id; | ||
572 | else | ||
573 | sta_id = iwl_sta_id(info->control.sta); | ||
574 | if (sta_id == IWL_INVALID_STATION) { | ||
575 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
576 | hdr->addr1); | ||
577 | goto drop_unlock; | ||
578 | } | ||
579 | |||
580 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
581 | |||
582 | if (sta) | ||
583 | sta_priv = (void *)sta->drv_priv; | ||
584 | |||
585 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
586 | sta_priv->asleep) { | ||
587 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
588 | /* | ||
589 | * This sends an asynchronous command to the device, | ||
590 | * but we can rely on it being processed before the | ||
591 | * next frame is processed -- and the next frame to | ||
592 | * this station is the one that will consume this | ||
593 | * counter. | ||
594 | * For now set the counter to just 1 since we do not | ||
595 | * support uAPSD yet. | ||
596 | */ | ||
597 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
598 | } | ||
599 | |||
600 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | ||
601 | if (ieee80211_is_data_qos(fc)) { | ||
602 | qc = ieee80211_get_qos_ctl(hdr); | ||
603 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
604 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
605 | goto drop_unlock; | ||
606 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | ||
607 | seq_number &= IEEE80211_SCTL_SEQ; | ||
608 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
609 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
610 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
611 | seq_number += 0x10; | ||
612 | /* aggregation is on for this <sta,tid> */ | ||
613 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
614 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
615 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | txq = &priv->txq[txq_id]; | ||
620 | swq_id = txq->swq_id; | ||
621 | q = &txq->q; | ||
622 | |||
623 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | ||
624 | goto drop_unlock; | ||
625 | |||
626 | if (ieee80211_is_data_qos(fc)) | ||
627 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
628 | |||
629 | /* Set up driver data for this TFD */ | ||
630 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
631 | txq->txb[q->write_ptr].skb[0] = skb; | ||
632 | |||
633 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
634 | out_cmd = txq->cmd[q->write_ptr]; | ||
635 | out_meta = &txq->meta[q->write_ptr]; | ||
636 | tx_cmd = &out_cmd->cmd.tx; | ||
637 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
638 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | ||
639 | |||
640 | /* | ||
641 | * Set up the Tx-command (not MAC!) header. | ||
642 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
643 | * after Tx, uCode's Tx response will return this value so driver can | ||
644 | * locate the frame within the tx queue and do post-tx processing. | ||
645 | */ | ||
646 | out_cmd->hdr.cmd = REPLY_TX; | ||
647 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
648 | INDEX_TO_SEQ(q->write_ptr))); | ||
649 | |||
650 | /* Copy MAC header from skb into command buffer */ | ||
651 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
652 | |||
653 | |||
654 | /* Total # bytes to be transmitted */ | ||
655 | len = (u16)skb->len; | ||
656 | tx_cmd->len = cpu_to_le16(len); | ||
657 | |||
658 | if (info->control.hw_key) | ||
659 | iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | ||
660 | |||
661 | /* TODO need this for burst mode later on */ | ||
662 | iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | ||
663 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
664 | |||
665 | iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); | ||
666 | |||
667 | iwl_update_stats(priv, true, fc, len); | ||
668 | /* | ||
669 | * Use the first empty entry in this queue's command buffer array | ||
670 | * to contain the Tx command and MAC header concatenated together | ||
671 | * (payload data will be in another buffer). | ||
672 | * Size of this varies, due to varying MAC header length. | ||
673 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
674 | * of the MAC header (device reads on dword boundaries). | ||
675 | * We'll tell device about this padding later. | ||
676 | */ | ||
677 | len = sizeof(struct iwl_tx_cmd) + | ||
678 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
679 | |||
680 | len_org = len; | ||
681 | firstlen = len = (len + 3) & ~3; | ||
682 | |||
683 | if (len_org != len) | ||
684 | len_org = 1; | ||
685 | else | ||
686 | len_org = 0; | ||
687 | |||
688 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
689 | if (len_org) | ||
690 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
691 | |||
692 | /* Physical address of this Tx command's header (not MAC header!), | ||
693 | * within command buffer array. */ | ||
694 | txcmd_phys = pci_map_single(priv->pci_dev, | ||
695 | &out_cmd->hdr, len, | ||
696 | PCI_DMA_BIDIRECTIONAL); | ||
697 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
698 | pci_unmap_len_set(out_meta, len, len); | ||
699 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
700 | * first entry */ | ||
701 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
702 | txcmd_phys, len, 1, 0); | ||
703 | |||
704 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
705 | txq->need_update = 1; | ||
706 | if (qc) | ||
707 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
708 | } else { | ||
709 | wait_write_ptr = 1; | ||
710 | txq->need_update = 0; | ||
711 | } | ||
712 | |||
713 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
714 | * if any (802.11 null frames have no payload). */ | ||
715 | secondlen = len = skb->len - hdr_len; | ||
716 | if (len) { | ||
717 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
718 | len, PCI_DMA_TODEVICE); | ||
719 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
720 | phys_addr, len, | ||
721 | 0, 0); | ||
722 | } | ||
723 | |||
724 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
725 | offsetof(struct iwl_tx_cmd, scratch); | ||
726 | |||
727 | len = sizeof(struct iwl_tx_cmd) + | ||
728 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
729 | /* take back ownership of DMA buffer to enable update */ | ||
730 | pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, | ||
731 | len, PCI_DMA_BIDIRECTIONAL); | ||
732 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
733 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
734 | |||
735 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", | ||
736 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
737 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
738 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
739 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
740 | |||
741 | /* Set up entry for this TFD in Tx byte-count array */ | ||
742 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
743 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | ||
744 | le16_to_cpu(tx_cmd->len)); | ||
745 | |||
746 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | ||
747 | len, PCI_DMA_BIDIRECTIONAL); | ||
748 | |||
749 | trace_iwlwifi_dev_tx(priv, | ||
750 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
751 | sizeof(struct iwl_tfd), | ||
752 | &out_cmd->hdr, firstlen, | ||
753 | skb->data + hdr_len, secondlen); | ||
754 | |||
755 | /* Tell device the write index *just past* this latest filled TFD */ | ||
756 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
757 | iwl_txq_update_write_ptr(priv, txq); | ||
758 | spin_unlock_irqrestore(&priv->lock, flags); | ||
759 | |||
760 | /* | ||
761 | * At this point the frame is "transmitted" successfully | ||
762 | * and we will get a TX status notification eventually, | ||
763 | * regardless of the value of ret. "ret" only indicates | ||
764 | * whether or not we should update the write pointer. | ||
765 | */ | ||
766 | |||
767 | /* avoid atomic ops if it isn't an associated client */ | ||
768 | if (sta_priv && sta_priv->client) | ||
769 | atomic_inc(&sta_priv->pending_frames); | ||
770 | |||
771 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | ||
772 | if (wait_write_ptr) { | ||
773 | spin_lock_irqsave(&priv->lock, flags); | ||
774 | txq->need_update = 1; | ||
775 | iwl_txq_update_write_ptr(priv, txq); | ||
776 | spin_unlock_irqrestore(&priv->lock, flags); | ||
777 | } else { | ||
778 | iwl_stop_queue(priv, txq->swq_id); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | return 0; | ||
783 | |||
784 | drop_unlock: | ||
785 | spin_unlock_irqrestore(&priv->lock, flags); | ||
786 | return -1; | ||
787 | } | ||
788 | |||
789 | static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, | ||
790 | struct iwl_dma_ptr *ptr, size_t size) | ||
791 | { | ||
792 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, | ||
793 | GFP_KERNEL); | ||
794 | if (!ptr->addr) | ||
795 | return -ENOMEM; | ||
796 | ptr->size = size; | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, | ||
801 | struct iwl_dma_ptr *ptr) | ||
802 | { | ||
803 | if (unlikely(!ptr->addr)) | ||
804 | return; | ||
805 | |||
806 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); | ||
807 | memset(ptr, 0, sizeof(*ptr)); | ||
808 | } | ||
809 | |||
810 | /** | ||
811 | * iwlagn_hw_txq_ctx_free - Free TXQ Context | ||
812 | * | ||
813 | * Destroy all TX DMA queues and structures | ||
814 | */ | ||
815 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | ||
816 | { | ||
817 | int txq_id; | ||
818 | |||
819 | /* Tx queues */ | ||
820 | if (priv->txq) { | ||
821 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
822 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
823 | iwl_cmd_queue_free(priv); | ||
824 | else | ||
825 | iwl_tx_queue_free(priv, txq_id); | ||
826 | } | ||
827 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
828 | |||
829 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
830 | |||
831 | /* free tx queue structure */ | ||
832 | iwl_free_txq_mem(priv); | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * iwlagn_txq_ctx_alloc - allocate TX queue context | ||
837 | * Allocate all Tx DMA structures and initialize them | ||
838 | * | ||
839 | * @param priv | ||
840 | * @return error code | ||
841 | */ | ||
842 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) | ||
843 | { | ||
844 | int ret; | ||
845 | int txq_id, slots_num; | ||
846 | unsigned long flags; | ||
847 | |||
848 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
849 | iwlagn_hw_txq_ctx_free(priv); | ||
850 | |||
851 | ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
852 | priv->hw_params.scd_bc_tbls_size); | ||
853 | if (ret) { | ||
854 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
855 | goto error_bc_tbls; | ||
856 | } | ||
857 | /* Alloc keep-warm buffer */ | ||
858 | ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
859 | if (ret) { | ||
860 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
861 | goto error_kw; | ||
862 | } | ||
863 | |||
864 | /* allocate tx queue structure */ | ||
865 | ret = iwl_alloc_txq_mem(priv); | ||
866 | if (ret) | ||
867 | goto error; | ||
868 | |||
869 | spin_lock_irqsave(&priv->lock, flags); | ||
870 | |||
871 | /* Turn off all Tx DMA fifos */ | ||
872 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
873 | |||
874 | /* Tell NIC where to find the "keep warm" buffer */ | ||
875 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
876 | |||
877 | spin_unlock_irqrestore(&priv->lock, flags); | ||
878 | |||
879 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
880 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
881 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
882 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
883 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
884 | txq_id); | ||
885 | if (ret) { | ||
886 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
887 | goto error; | ||
888 | } | ||
889 | } | ||
890 | |||
891 | return ret; | ||
892 | |||
893 | error: | ||
894 | iwlagn_hw_txq_ctx_free(priv); | ||
895 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
896 | error_kw: | ||
897 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
898 | error_bc_tbls: | ||
899 | return ret; | ||
900 | } | ||
901 | |||
902 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | ||
903 | { | ||
904 | int txq_id, slots_num; | ||
905 | unsigned long flags; | ||
906 | |||
907 | spin_lock_irqsave(&priv->lock, flags); | ||
908 | |||
909 | /* Turn off all Tx DMA fifos */ | ||
910 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
911 | |||
912 | /* Tell NIC where to find the "keep warm" buffer */ | ||
913 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
914 | |||
915 | spin_unlock_irqrestore(&priv->lock, flags); | ||
916 | |||
917 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
918 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
919 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
920 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
921 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
922 | } | ||
923 | } | ||
924 | |||
925 | /** | ||
926 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
927 | */ | ||
928 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | ||
929 | { | ||
930 | int ch; | ||
931 | unsigned long flags; | ||
932 | |||
933 | /* Turn off all Tx DMA fifos */ | ||
934 | spin_lock_irqsave(&priv->lock, flags); | ||
935 | |||
936 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
937 | |||
938 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
939 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
940 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
941 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
942 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
943 | 1000); | ||
944 | } | ||
945 | spin_unlock_irqrestore(&priv->lock, flags); | ||
946 | } | ||
947 | |||
948 | /* | ||
949 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
950 | * Called only when finding queue for aggregation. | ||
951 | * Should never return anything < 7, because they should already | ||
952 | * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) | ||
953 | */ | ||
954 | static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) | ||
955 | { | ||
956 | int txq_id; | ||
957 | |||
958 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
959 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
960 | return txq_id; | ||
961 | return -1; | ||
962 | } | ||
963 | |||
964 | int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
965 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | ||
966 | { | ||
967 | int sta_id; | ||
968 | int tx_fifo; | ||
969 | int txq_id; | ||
970 | int ret; | ||
971 | unsigned long flags; | ||
972 | struct iwl_tid_data *tid_data; | ||
973 | |||
974 | tx_fifo = get_fifo_from_tid(tid); | ||
975 | if (unlikely(tx_fifo < 0)) | ||
976 | return tx_fifo; | ||
977 | |||
978 | IWL_WARN(priv, "%s on ra = %pM tid = %d\n", | ||
979 | __func__, sta->addr, tid); | ||
980 | |||
981 | sta_id = iwl_sta_id(sta); | ||
982 | if (sta_id == IWL_INVALID_STATION) { | ||
983 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
984 | return -ENXIO; | ||
985 | } | ||
986 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
987 | return -EINVAL; | ||
988 | |||
989 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
990 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
991 | return -ENXIO; | ||
992 | } | ||
993 | |||
994 | txq_id = iwlagn_txq_ctx_activate_free(priv); | ||
995 | if (txq_id == -1) { | ||
996 | IWL_ERR(priv, "No free aggregation queue available\n"); | ||
997 | return -ENXIO; | ||
998 | } | ||
999 | |||
1000 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1001 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1002 | *ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1003 | tid_data->agg.txq_id = txq_id; | ||
1004 | priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id); | ||
1005 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1006 | |||
1007 | ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, | ||
1008 | sta_id, tid, *ssn); | ||
1009 | if (ret) | ||
1010 | return ret; | ||
1011 | |||
1012 | if (tid_data->tfds_in_queue == 0) { | ||
1013 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1014 | tid_data->agg.state = IWL_AGG_ON; | ||
1015 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1016 | } else { | ||
1017 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | ||
1018 | tid_data->tfds_in_queue); | ||
1019 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
1020 | } | ||
1021 | return ret; | ||
1022 | } | ||
1023 | |||
1024 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
1025 | struct ieee80211_sta *sta, u16 tid) | ||
1026 | { | ||
1027 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
1028 | struct iwl_tid_data *tid_data; | ||
1029 | int write_ptr, read_ptr; | ||
1030 | unsigned long flags; | ||
1031 | |||
1032 | tx_fifo_id = get_fifo_from_tid(tid); | ||
1033 | if (unlikely(tx_fifo_id < 0)) | ||
1034 | return tx_fifo_id; | ||
1035 | |||
1036 | sta_id = iwl_sta_id(sta); | ||
1037 | |||
1038 | if (sta_id == IWL_INVALID_STATION) { | ||
1039 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
1040 | return -ENXIO; | ||
1041 | } | ||
1042 | |||
1043 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1044 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1045 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1046 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1047 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1052 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1053 | |||
1054 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1055 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
1056 | txq_id = tid_data->agg.txq_id; | ||
1057 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
1058 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
1059 | |||
1060 | /* The queue is not empty */ | ||
1061 | if (write_ptr != read_ptr) { | ||
1062 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | ||
1063 | priv->stations[sta_id].tid[tid].agg.state = | ||
1064 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1069 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1070 | |||
1071 | spin_lock_irqsave(&priv->lock, flags); | ||
1072 | /* | ||
1073 | * the only reason this call can fail is queue number out of range, | ||
1074 | * which can happen if uCode is reloaded and all the station | ||
1075 | * information are lost. if it is outside the range, there is no need | ||
1076 | * to deactivate the uCode queue, just return "success" to allow | ||
1077 | * mac80211 to clean up it own data. | ||
1078 | */ | ||
1079 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1080 | tx_fifo_id); | ||
1081 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1082 | |||
1083 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | int iwlagn_txq_check_empty(struct iwl_priv *priv, | ||
1089 | int sta_id, u8 tid, int txq_id) | ||
1090 | { | ||
1091 | struct iwl_queue *q = &priv->txq[txq_id].q; | ||
1092 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
1093 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
1094 | |||
1095 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1096 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1097 | /* We are reclaiming the last packet of the */ | ||
1098 | /* aggregated HW queue */ | ||
1099 | if ((txq_id == tid_data->agg.txq_id) && | ||
1100 | (q->read_ptr == q->write_ptr)) { | ||
1101 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1102 | int tx_fifo = get_fifo_from_tid(tid); | ||
1103 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | ||
1104 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | ||
1105 | ssn, tx_fifo); | ||
1106 | tid_data->agg.state = IWL_AGG_OFF; | ||
1107 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1108 | } | ||
1109 | break; | ||
1110 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1111 | /* We are reclaiming the last packet of the queue */ | ||
1112 | if (tid_data->tfds_in_queue == 0) { | ||
1113 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | ||
1114 | tid_data->agg.state = IWL_AGG_ON; | ||
1115 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1116 | } | ||
1117 | break; | ||
1118 | } | ||
1119 | return 0; | ||
1120 | } | ||
1121 | |||
1122 | static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1123 | { | ||
1124 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1125 | struct ieee80211_sta *sta; | ||
1126 | struct iwl_station_priv *sta_priv; | ||
1127 | |||
1128 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1129 | if (sta) { | ||
1130 | sta_priv = (void *)sta->drv_priv; | ||
1131 | /* avoid atomic ops if this isn't a client */ | ||
1132 | if (sta_priv->client && | ||
1133 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1134 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1135 | } | ||
1136 | |||
1137 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1138 | } | ||
1139 | |||
1140 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | ||
1141 | { | ||
1142 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1143 | struct iwl_queue *q = &txq->q; | ||
1144 | struct iwl_tx_info *tx_info; | ||
1145 | int nfreed = 0; | ||
1146 | struct ieee80211_hdr *hdr; | ||
1147 | |||
1148 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1149 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1150 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1151 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | for (index = iwl_queue_inc_wrap(index, q->n_bd); | ||
1156 | q->read_ptr != index; | ||
1157 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1158 | |||
1159 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
1160 | iwlagn_tx_status(priv, tx_info->skb[0]); | ||
1161 | |||
1162 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | ||
1163 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | ||
1164 | nfreed++; | ||
1165 | tx_info->skb[0] = NULL; | ||
1166 | |||
1167 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | ||
1168 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1169 | |||
1170 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
1171 | } | ||
1172 | return nfreed; | ||
1173 | } | ||
1174 | |||
1175 | /** | ||
1176 | * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1177 | * | ||
1178 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1179 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1180 | */ | ||
1181 | static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1182 | struct iwl_ht_agg *agg, | ||
1183 | struct iwl_compressed_ba_resp *ba_resp) | ||
1184 | |||
1185 | { | ||
1186 | int i, sh, ack; | ||
1187 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1188 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1189 | u64 bitmap; | ||
1190 | int successes = 0; | ||
1191 | struct ieee80211_tx_info *info; | ||
1192 | |||
1193 | if (unlikely(!agg->wait_for_ba)) { | ||
1194 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1195 | return -EINVAL; | ||
1196 | } | ||
1197 | |||
1198 | /* Mark that the expected block-ack response arrived */ | ||
1199 | agg->wait_for_ba = 0; | ||
1200 | IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1201 | |||
1202 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1203 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); | ||
1204 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1205 | sh += 0x100; | ||
1206 | |||
1207 | /* don't use 64-bit values for now */ | ||
1208 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1209 | |||
1210 | if (agg->frame_count > (64 - sh)) { | ||
1211 | IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); | ||
1212 | return -1; | ||
1213 | } | ||
1214 | |||
1215 | /* check for success or failure according to the | ||
1216 | * transmitted bitmap and block-ack bitmap */ | ||
1217 | bitmap &= agg->bitmap; | ||
1218 | |||
1219 | /* For each frame attempted in aggregation, | ||
1220 | * update driver's record of tx frame's status. */ | ||
1221 | for (i = 0; i < agg->frame_count ; i++) { | ||
1222 | ack = bitmap & (1ULL << i); | ||
1223 | successes += !!ack; | ||
1224 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | ||
1225 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | ||
1226 | agg->start_idx + i); | ||
1227 | } | ||
1228 | |||
1229 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1230 | memset(&info->status, 0, sizeof(info->status)); | ||
1231 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1232 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1233 | info->status.ampdu_ack_len = successes; | ||
1234 | info->status.ampdu_ack_map = bitmap; | ||
1235 | info->status.ampdu_len = agg->frame_count; | ||
1236 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1237 | |||
1238 | IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); | ||
1239 | |||
1240 | return 0; | ||
1241 | } | ||
1242 | |||
1243 | /** | ||
1244 | * translate ucode response to mac80211 tx status control values | ||
1245 | */ | ||
1246 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
1247 | struct ieee80211_tx_info *info) | ||
1248 | { | ||
1249 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | ||
1250 | |||
1251 | info->antenna_sel_tx = | ||
1252 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
1253 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1254 | r->flags |= IEEE80211_TX_RC_MCS; | ||
1255 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
1256 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
1257 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1258 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
1259 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
1260 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
1261 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1262 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
1263 | r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
1264 | } | ||
1265 | |||
1266 | /** | ||
1267 | * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1268 | * | ||
1269 | * Handles block-acknowledge notification from device, which reports success | ||
1270 | * of frames sent via aggregation. | ||
1271 | */ | ||
1272 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1273 | struct iwl_rx_mem_buffer *rxb) | ||
1274 | { | ||
1275 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1276 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1277 | struct iwl_tx_queue *txq = NULL; | ||
1278 | struct iwl_ht_agg *agg; | ||
1279 | int index; | ||
1280 | int sta_id; | ||
1281 | int tid; | ||
1282 | |||
1283 | /* "flow" corresponds to Tx queue */ | ||
1284 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1285 | |||
1286 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1287 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1288 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1289 | |||
1290 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1291 | IWL_ERR(priv, | ||
1292 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1293 | return; | ||
1294 | } | ||
1295 | |||
1296 | txq = &priv->txq[scd_flow]; | ||
1297 | sta_id = ba_resp->sta_id; | ||
1298 | tid = ba_resp->tid; | ||
1299 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1300 | |||
1301 | /* Find index just before block-ack window */ | ||
1302 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1303 | |||
1304 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1305 | |||
1306 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1307 | "sta_id = %d\n", | ||
1308 | agg->wait_for_ba, | ||
1309 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1310 | ba_resp->sta_id); | ||
1311 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1312 | "%d, scd_ssn = %d\n", | ||
1313 | ba_resp->tid, | ||
1314 | ba_resp->seq_ctl, | ||
1315 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1316 | ba_resp->scd_flow, | ||
1317 | ba_resp->scd_ssn); | ||
1318 | IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", | ||
1319 | agg->start_idx, | ||
1320 | (unsigned long long)agg->bitmap); | ||
1321 | |||
1322 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1323 | iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1324 | |||
1325 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1326 | * block-ack window (we assume that they've been successfully | ||
1327 | * transmitted ... if not, it's too late anyway). */ | ||
1328 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1329 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1330 | int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); | ||
1331 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1332 | |||
1333 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1334 | priv->mac80211_registered && | ||
1335 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
1336 | iwl_wake_queue(priv, txq->swq_id); | ||
1337 | |||
1338 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); | ||
1339 | } | ||
1340 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c new file mode 100644 index 000000000000..637286c396fe --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -0,0 +1,425 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | #include "iwl-agn-hw.h" | ||
40 | #include "iwl-agn.h" | ||
41 | |||
42 | static const s8 iwlagn_default_queue_to_tx_fifo[] = { | ||
43 | IWL_TX_FIFO_VO, | ||
44 | IWL_TX_FIFO_VI, | ||
45 | IWL_TX_FIFO_BE, | ||
46 | IWL_TX_FIFO_BK, | ||
47 | IWLAGN_CMD_FIFO_NUM, | ||
48 | IWL_TX_FIFO_UNUSED, | ||
49 | IWL_TX_FIFO_UNUSED, | ||
50 | IWL_TX_FIFO_UNUSED, | ||
51 | IWL_TX_FIFO_UNUSED, | ||
52 | IWL_TX_FIFO_UNUSED, | ||
53 | }; | ||
54 | |||
55 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | ||
56 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | ||
57 | 0, COEX_UNASSOC_IDLE_FLAGS}, | ||
58 | {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, | ||
59 | 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, | ||
60 | {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, | ||
61 | 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, | ||
62 | {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, | ||
63 | 0, COEX_CALIBRATION_FLAGS}, | ||
64 | {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, | ||
65 | 0, COEX_PERIODIC_CALIBRATION_FLAGS}, | ||
66 | {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, | ||
67 | 0, COEX_CONNECTION_ESTAB_FLAGS}, | ||
68 | {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, | ||
69 | 0, COEX_ASSOCIATED_IDLE_FLAGS}, | ||
70 | {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, | ||
71 | 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, | ||
72 | {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, | ||
73 | 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, | ||
74 | {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, | ||
75 | 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, | ||
76 | {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, | ||
77 | {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, | ||
78 | {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, | ||
79 | 0, COEX_STAND_ALONE_DEBUG_FLAGS}, | ||
80 | {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, | ||
81 | 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, | ||
82 | {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, | ||
83 | {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * ucode | ||
88 | */ | ||
89 | static int iwlagn_load_section(struct iwl_priv *priv, const char *name, | ||
90 | struct fw_desc *image, u32 dst_addr) | ||
91 | { | ||
92 | dma_addr_t phy_addr = image->p_addr; | ||
93 | u32 byte_cnt = image->len; | ||
94 | int ret; | ||
95 | |||
96 | priv->ucode_write_complete = 0; | ||
97 | |||
98 | iwl_write_direct32(priv, | ||
99 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
100 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
101 | |||
102 | iwl_write_direct32(priv, | ||
103 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
104 | |||
105 | iwl_write_direct32(priv, | ||
106 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
107 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
108 | |||
109 | iwl_write_direct32(priv, | ||
110 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
111 | (iwl_get_dma_hi_addr(phy_addr) | ||
112 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
113 | |||
114 | iwl_write_direct32(priv, | ||
115 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
116 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
117 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
118 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
119 | |||
120 | iwl_write_direct32(priv, | ||
121 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
122 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
123 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
124 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
125 | |||
126 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); | ||
127 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
128 | priv->ucode_write_complete, 5 * HZ); | ||
129 | if (ret == -ERESTARTSYS) { | ||
130 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
131 | "to interrupt\n", name); | ||
132 | return ret; | ||
133 | } | ||
134 | if (!ret) { | ||
135 | IWL_ERR(priv, "Could not load the %s uCode section\n", | ||
136 | name); | ||
137 | return -ETIMEDOUT; | ||
138 | } | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int iwlagn_load_given_ucode(struct iwl_priv *priv, | ||
144 | struct fw_desc *inst_image, | ||
145 | struct fw_desc *data_image) | ||
146 | { | ||
147 | int ret = 0; | ||
148 | |||
149 | ret = iwlagn_load_section(priv, "INST", inst_image, | ||
150 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
151 | if (ret) | ||
152 | return ret; | ||
153 | |||
154 | return iwlagn_load_section(priv, "DATA", data_image, | ||
155 | IWLAGN_RTC_DATA_LOWER_BOUND); | ||
156 | } | ||
157 | |||
158 | int iwlagn_load_ucode(struct iwl_priv *priv) | ||
159 | { | ||
160 | int ret = 0; | ||
161 | |||
162 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
163 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
164 | IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); | ||
165 | ret = iwlagn_load_given_ucode(priv, | ||
166 | &priv->ucode_init, &priv->ucode_init_data); | ||
167 | if (!ret) { | ||
168 | IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); | ||
169 | priv->ucode_type = UCODE_INIT; | ||
170 | } | ||
171 | } else { | ||
172 | IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " | ||
173 | "Loading runtime ucode...\n"); | ||
174 | ret = iwlagn_load_given_ucode(priv, | ||
175 | &priv->ucode_code, &priv->ucode_data); | ||
176 | if (!ret) { | ||
177 | IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); | ||
178 | priv->ucode_type = UCODE_RT; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Calibration | ||
187 | */ | ||
188 | static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) | ||
189 | { | ||
190 | struct iwl_calib_xtal_freq_cmd cmd; | ||
191 | __le16 *xtal_calib = | ||
192 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); | ||
193 | |||
194 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | ||
195 | cmd.hdr.first_group = 0; | ||
196 | cmd.hdr.groups_num = 1; | ||
197 | cmd.hdr.data_valid = 1; | ||
198 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||
199 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | ||
200 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | ||
201 | (u8 *)&cmd, sizeof(cmd)); | ||
202 | } | ||
203 | |||
204 | static int iwlagn_send_calib_cfg(struct iwl_priv *priv) | ||
205 | { | ||
206 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
207 | struct iwl_host_cmd cmd = { | ||
208 | .id = CALIBRATION_CFG_CMD, | ||
209 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
210 | .data = &calib_cfg_cmd, | ||
211 | }; | ||
212 | |||
213 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
214 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
215 | calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; | ||
216 | calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; | ||
217 | calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; | ||
218 | |||
219 | return iwl_send_cmd(priv, &cmd); | ||
220 | } | ||
221 | |||
222 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
223 | struct iwl_rx_mem_buffer *rxb) | ||
224 | { | ||
225 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
226 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | ||
227 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
228 | int index; | ||
229 | |||
230 | /* reduce the size of the length field itself */ | ||
231 | len -= 4; | ||
232 | |||
233 | /* Define the order in which the results will be sent to the runtime | ||
234 | * uCode. iwl_send_calib_results sends them in a row according to | ||
235 | * their index. We sort them here | ||
236 | */ | ||
237 | switch (hdr->op_code) { | ||
238 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
239 | index = IWL_CALIB_DC; | ||
240 | break; | ||
241 | case IWL_PHY_CALIBRATE_LO_CMD: | ||
242 | index = IWL_CALIB_LO; | ||
243 | break; | ||
244 | case IWL_PHY_CALIBRATE_TX_IQ_CMD: | ||
245 | index = IWL_CALIB_TX_IQ; | ||
246 | break; | ||
247 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | ||
248 | index = IWL_CALIB_TX_IQ_PERD; | ||
249 | break; | ||
250 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
251 | index = IWL_CALIB_BASE_BAND; | ||
252 | break; | ||
253 | default: | ||
254 | IWL_ERR(priv, "Unknown calibration notification %d\n", | ||
255 | hdr->op_code); | ||
256 | return; | ||
257 | } | ||
258 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | ||
259 | } | ||
260 | |||
261 | void iwlagn_rx_calib_complete(struct iwl_priv *priv, | ||
262 | struct iwl_rx_mem_buffer *rxb) | ||
263 | { | ||
264 | IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); | ||
265 | queue_work(priv->workqueue, &priv->restart); | ||
266 | } | ||
267 | |||
268 | void iwlagn_init_alive_start(struct iwl_priv *priv) | ||
269 | { | ||
270 | int ret = 0; | ||
271 | |||
272 | /* Check alive response for "valid" sign from uCode */ | ||
273 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
274 | /* We had an error bringing up the hardware, so take it | ||
275 | * all the way back down so we can try again */ | ||
276 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
277 | goto restart; | ||
278 | } | ||
279 | |||
280 | /* initialize uCode was loaded... verify inst image. | ||
281 | * This is a paranoid check, because we would not have gotten the | ||
282 | * "initialize" alive if code weren't properly loaded. */ | ||
283 | if (iwl_verify_ucode(priv)) { | ||
284 | /* Runtime instruction load was bad; | ||
285 | * take it all the way back down so we can try again */ | ||
286 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
287 | goto restart; | ||
288 | } | ||
289 | |||
290 | ret = priv->cfg->ops->lib->alive_notify(priv); | ||
291 | if (ret) { | ||
292 | IWL_WARN(priv, | ||
293 | "Could not complete ALIVE transition: %d\n", ret); | ||
294 | goto restart; | ||
295 | } | ||
296 | |||
297 | iwlagn_send_calib_cfg(priv); | ||
298 | return; | ||
299 | |||
300 | restart: | ||
301 | /* real restart (first load init_ucode) */ | ||
302 | queue_work(priv->workqueue, &priv->restart); | ||
303 | } | ||
304 | |||
305 | static int iwlagn_send_wimax_coex(struct iwl_priv *priv) | ||
306 | { | ||
307 | struct iwl_wimax_coex_cmd coex_cmd; | ||
308 | |||
309 | if (priv->cfg->support_wimax_coexist) { | ||
310 | /* UnMask wake up src at associated sleep */ | ||
311 | coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; | ||
312 | |||
313 | /* UnMask wake up src at unassociated sleep */ | ||
314 | coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; | ||
315 | memcpy(coex_cmd.sta_prio, cu_priorities, | ||
316 | sizeof(struct iwl_wimax_coex_event_entry) * | ||
317 | COEX_NUM_OF_EVENTS); | ||
318 | |||
319 | /* enabling the coexistence feature */ | ||
320 | coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; | ||
321 | |||
322 | /* enabling the priorities tables */ | ||
323 | coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; | ||
324 | } else { | ||
325 | /* coexistence is disabled */ | ||
326 | memset(&coex_cmd, 0, sizeof(coex_cmd)); | ||
327 | } | ||
328 | return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, | ||
329 | sizeof(coex_cmd), &coex_cmd); | ||
330 | } | ||
331 | |||
332 | int iwlagn_alive_notify(struct iwl_priv *priv) | ||
333 | { | ||
334 | u32 a; | ||
335 | unsigned long flags; | ||
336 | int i, chan; | ||
337 | u32 reg_val; | ||
338 | |||
339 | spin_lock_irqsave(&priv->lock, flags); | ||
340 | |||
341 | priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); | ||
342 | a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET; | ||
343 | for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET; | ||
344 | a += 4) | ||
345 | iwl_write_targ_mem(priv, a, 0); | ||
346 | for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET; | ||
347 | a += 4) | ||
348 | iwl_write_targ_mem(priv, a, 0); | ||
349 | for (; a < priv->scd_base_addr + | ||
350 | IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
351 | iwl_write_targ_mem(priv, a, 0); | ||
352 | |||
353 | iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR, | ||
354 | priv->scd_bc_tbls.dma >> 10); | ||
355 | |||
356 | /* Enable DMA channel */ | ||
357 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
358 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
359 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
360 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
361 | |||
362 | /* Update FH chicken bits */ | ||
363 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
364 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
365 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
366 | |||
367 | iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, | ||
368 | IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | ||
369 | iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0); | ||
370 | |||
371 | /* initiate the queues */ | ||
372 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
373 | iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0); | ||
374 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
375 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
376 | IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
377 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
378 | IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
379 | sizeof(u32), | ||
380 | ((SCD_WIN_SIZE << | ||
381 | IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
382 | IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
383 | ((SCD_FRAME_LIMIT << | ||
384 | IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
385 | IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
386 | } | ||
387 | |||
388 | iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, | ||
389 | IWL_MASK(0, priv->hw_params.max_txq_num)); | ||
390 | |||
391 | /* Activate all Tx DMA/FIFO channels */ | ||
392 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | ||
393 | |||
394 | iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | ||
395 | |||
396 | /* make sure all queue are not stopped */ | ||
397 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
398 | for (i = 0; i < 4; i++) | ||
399 | atomic_set(&priv->queue_stop_count[i], 0); | ||
400 | |||
401 | /* reset to 0 to enable all the queue first */ | ||
402 | priv->txq_ctx_active_msk = 0; | ||
403 | /* map qos queues to fifos one-to-one */ | ||
404 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); | ||
405 | |||
406 | for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { | ||
407 | int ac = iwlagn_default_queue_to_tx_fifo[i]; | ||
408 | |||
409 | iwl_txq_ctx_activate(priv, i); | ||
410 | |||
411 | if (ac == IWL_TX_FIFO_UNUSED) | ||
412 | continue; | ||
413 | |||
414 | iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
415 | } | ||
416 | |||
417 | spin_unlock_irqrestore(&priv->lock, flags); | ||
418 | |||
419 | iwlagn_send_wimax_coex(priv); | ||
420 | |||
421 | iwlagn_set_Xtal_calib(priv); | ||
422 | iwl_send_calib_results(priv); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8b8e3e1cbb44..aef4f71f1981 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include "iwl-helpers.h" | 55 | #include "iwl-helpers.h" |
56 | #include "iwl-sta.h" | 56 | #include "iwl-sta.h" |
57 | #include "iwl-calib.h" | 57 | #include "iwl-calib.h" |
58 | #include "iwl-agn.h" | ||
58 | 59 | ||
59 | 60 | ||
60 | /****************************************************************************** | 61 | /****************************************************************************** |
@@ -83,13 +84,6 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | |||
83 | MODULE_LICENSE("GPL"); | 84 | MODULE_LICENSE("GPL"); |
84 | MODULE_ALIAS("iwl4965"); | 85 | MODULE_ALIAS("iwl4965"); |
85 | 86 | ||
86 | /*************** STATION TABLE MANAGEMENT **** | ||
87 | * mac80211 should be examined to determine if sta_info is duplicating | ||
88 | * the functionality provided here | ||
89 | */ | ||
90 | |||
91 | /**************************************************************/ | ||
92 | |||
93 | /** | 87 | /** |
94 | * iwl_commit_rxon - commit staging_rxon to hardware | 88 | * iwl_commit_rxon - commit staging_rxon to hardware |
95 | * | 89 | * |
@@ -144,9 +138,6 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
144 | return 0; | 138 | return 0; |
145 | } | 139 | } |
146 | 140 | ||
147 | /* station table will be cleared */ | ||
148 | priv->assoc_station_added = 0; | ||
149 | |||
150 | /* If we are currently associated and the new config requires | 141 | /* If we are currently associated and the new config requires |
151 | * an RXON_ASSOC and the new config wants the associated mask enabled, | 142 | * an RXON_ASSOC and the new config wants the associated mask enabled, |
152 | * we must clear the associated from the active configuration | 143 | * we must clear the associated from the active configuration |
@@ -166,6 +157,13 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
166 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); | 157 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); |
167 | return ret; | 158 | return ret; |
168 | } | 159 | } |
160 | iwl_clear_ucode_stations(priv); | ||
161 | iwl_restore_stations(priv); | ||
162 | ret = iwl_restore_default_wep_keys(priv); | ||
163 | if (ret) { | ||
164 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | ||
165 | return ret; | ||
166 | } | ||
169 | } | 167 | } |
170 | 168 | ||
171 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | 169 | IWL_DEBUG_INFO(priv, "Sending RXON\n" |
@@ -179,9 +177,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
179 | iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); | 177 | iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); |
180 | 178 | ||
181 | /* Apply the new configuration | 179 | /* Apply the new configuration |
182 | * RXON unassoc clears the station table in uCode, send it before | 180 | * RXON unassoc clears the station table in uCode so restoration of |
183 | * we add the bcast station. If assoc bit is set, we will send RXON | 181 | * stations is needed after it (the RXON command) completes |
184 | * after having added the bcast and bssid station. | ||
185 | */ | 182 | */ |
186 | if (!new_assoc) { | 183 | if (!new_assoc) { |
187 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | 184 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, |
@@ -190,35 +187,19 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
190 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | 187 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); |
191 | return ret; | 188 | return ret; |
192 | } | 189 | } |
190 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); | ||
193 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 191 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
192 | iwl_clear_ucode_stations(priv); | ||
193 | iwl_restore_stations(priv); | ||
194 | ret = iwl_restore_default_wep_keys(priv); | ||
195 | if (ret) { | ||
196 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | ||
197 | return ret; | ||
198 | } | ||
194 | } | 199 | } |
195 | 200 | ||
196 | iwl_clear_stations_table(priv); | ||
197 | |||
198 | priv->start_calib = 0; | 201 | priv->start_calib = 0; |
199 | |||
200 | /* Add the broadcast address so we can send broadcast frames */ | ||
201 | priv->cfg->ops->lib->add_bcast_station(priv); | ||
202 | |||
203 | |||
204 | /* If we have set the ASSOC_MSK and we are in BSS mode then | ||
205 | * add the IWL_AP_ID to the station rate table */ | ||
206 | if (new_assoc) { | 202 | if (new_assoc) { |
207 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | ||
208 | ret = iwl_rxon_add_station(priv, | ||
209 | priv->active_rxon.bssid_addr, 1); | ||
210 | if (ret == IWL_INVALID_STATION) { | ||
211 | IWL_ERR(priv, | ||
212 | "Error adding AP address for TX.\n"); | ||
213 | return -EIO; | ||
214 | } | ||
215 | priv->assoc_station_added = 1; | ||
216 | if (priv->default_wep_key && | ||
217 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
218 | IWL_ERR(priv, | ||
219 | "Could not send WEP static key.\n"); | ||
220 | } | ||
221 | |||
222 | /* | 203 | /* |
223 | * allow CTS-to-self if possible for new association. | 204 | * allow CTS-to-self if possible for new association. |
224 | * this is relevant only for 5000 series and up, | 205 | * this is relevant only for 5000 series and up, |
@@ -907,10 +888,10 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
907 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = | 888 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = |
908 | iwl_rx_missed_beacon_notif; | 889 | iwl_rx_missed_beacon_notif; |
909 | /* Rx handlers */ | 890 | /* Rx handlers */ |
910 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; | 891 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy; |
911 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; | 892 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx; |
912 | /* block ack */ | 893 | /* block ack */ |
913 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba; | 894 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; |
914 | /* Set up hardware specific Rx handlers */ | 895 | /* Set up hardware specific Rx handlers */ |
915 | priv->cfg->ops->lib->rx_handler_setup(priv); | 896 | priv->cfg->ops->lib->rx_handler_setup(priv); |
916 | } | 897 | } |
@@ -1038,7 +1019,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1038 | count++; | 1019 | count++; |
1039 | if (count >= 8) { | 1020 | if (count >= 8) { |
1040 | rxq->read = i; | 1021 | rxq->read = i; |
1041 | iwl_rx_replenish_now(priv); | 1022 | iwlagn_rx_replenish_now(priv); |
1042 | count = 0; | 1023 | count = 0; |
1043 | } | 1024 | } |
1044 | } | 1025 | } |
@@ -1047,9 +1028,9 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1047 | /* Backtrack one entry */ | 1028 | /* Backtrack one entry */ |
1048 | rxq->read = i; | 1029 | rxq->read = i; |
1049 | if (fill_rx) | 1030 | if (fill_rx) |
1050 | iwl_rx_replenish_now(priv); | 1031 | iwlagn_rx_replenish_now(priv); |
1051 | else | 1032 | else |
1052 | iwl_rx_queue_restock(priv); | 1033 | iwlagn_rx_queue_restock(priv); |
1053 | } | 1034 | } |
1054 | 1035 | ||
1055 | /* call this function to flush any scheduled tasklet */ | 1036 | /* call this function to flush any scheduled tasklet */ |
@@ -1267,9 +1248,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1267 | * hardware bugs here by ACKing all the possible interrupts so that | 1248 | * hardware bugs here by ACKing all the possible interrupts so that |
1268 | * interrupt coalescing can still be achieved. | 1249 | * interrupt coalescing can still be achieved. |
1269 | */ | 1250 | */ |
1270 | iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); | 1251 | iwl_write32(priv, CSR_INT, priv->_agn.inta | ~priv->inta_mask); |
1271 | 1252 | ||
1272 | inta = priv->inta; | 1253 | inta = priv->_agn.inta; |
1273 | 1254 | ||
1274 | #ifdef CONFIG_IWLWIFI_DEBUG | 1255 | #ifdef CONFIG_IWLWIFI_DEBUG |
1275 | if (iwl_get_debug_level(priv) & IWL_DL_ISR) { | 1256 | if (iwl_get_debug_level(priv) & IWL_DL_ISR) { |
@@ -1282,8 +1263,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1282 | 1263 | ||
1283 | spin_unlock_irqrestore(&priv->lock, flags); | 1264 | spin_unlock_irqrestore(&priv->lock, flags); |
1284 | 1265 | ||
1285 | /* saved interrupt in inta variable now we can reset priv->inta */ | 1266 | /* saved interrupt in inta variable now we can reset priv->_agn.inta */ |
1286 | priv->inta = 0; | 1267 | priv->_agn.inta = 0; |
1287 | 1268 | ||
1288 | /* Now service all interrupt bits discovered above. */ | 1269 | /* Now service all interrupt bits discovered above. */ |
1289 | if (inta & CSR_INT_BIT_HW_ERR) { | 1270 | if (inta & CSR_INT_BIT_HW_ERR) { |
@@ -1448,6 +1429,60 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1448 | iwl_enable_interrupts(priv); | 1429 | iwl_enable_interrupts(priv); |
1449 | } | 1430 | } |
1450 | 1431 | ||
1432 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
1433 | #define ACK_CNT_RATIO (50) | ||
1434 | #define BA_TIMEOUT_CNT (5) | ||
1435 | #define BA_TIMEOUT_MAX (16) | ||
1436 | |||
1437 | /** | ||
1438 | * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. | ||
1439 | * | ||
1440 | * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding | ||
1441 | * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal | ||
1442 | * operation state. | ||
1443 | */ | ||
1444 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
1445 | struct iwl_rx_packet *pkt) | ||
1446 | { | ||
1447 | bool rc = true; | ||
1448 | int actual_ack_cnt_delta, expected_ack_cnt_delta; | ||
1449 | int ba_timeout_delta; | ||
1450 | |||
1451 | actual_ack_cnt_delta = | ||
1452 | le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
1453 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
1454 | expected_ack_cnt_delta = | ||
1455 | le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - | ||
1456 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
1457 | ba_timeout_delta = | ||
1458 | le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - | ||
1459 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
1460 | if ((priv->_agn.agg_tids_count > 0) && | ||
1461 | (expected_ack_cnt_delta > 0) && | ||
1462 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) | ||
1463 | < ACK_CNT_RATIO) && | ||
1464 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
1465 | IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," | ||
1466 | " expected_ack_cnt = %d\n", | ||
1467 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
1468 | |||
1469 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1470 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
1471 | priv->delta_statistics.tx.rx_detected_cnt); | ||
1472 | IWL_DEBUG_RADIO(priv, | ||
1473 | "ack_or_ba_timeout_collision delta = %d\n", | ||
1474 | priv->delta_statistics.tx. | ||
1475 | ack_or_ba_timeout_collision); | ||
1476 | #endif | ||
1477 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
1478 | ba_timeout_delta); | ||
1479 | if (!actual_ack_cnt_delta && | ||
1480 | (ba_timeout_delta >= BA_TIMEOUT_MAX)) | ||
1481 | rc = false; | ||
1482 | } | ||
1483 | return rc; | ||
1484 | } | ||
1485 | |||
1451 | 1486 | ||
1452 | /****************************************************************************** | 1487 | /****************************************************************************** |
1453 | * | 1488 | * |
@@ -1471,9 +1506,13 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
1471 | iwl_write32(priv, CSR_RESET, 0); | 1506 | iwl_write32(priv, CSR_RESET, 0); |
1472 | } | 1507 | } |
1473 | 1508 | ||
1509 | struct iwlagn_ucode_capabilities { | ||
1510 | u32 max_probe_length; | ||
1511 | }; | ||
1474 | 1512 | ||
1475 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | 1513 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); |
1476 | static int iwl_mac_setup_register(struct iwl_priv *priv); | 1514 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
1515 | struct iwlagn_ucode_capabilities *capa); | ||
1477 | 1516 | ||
1478 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | 1517 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) |
1479 | { | 1518 | { |
@@ -1500,6 +1539,199 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | |||
1500 | iwl_ucode_callback); | 1539 | iwl_ucode_callback); |
1501 | } | 1540 | } |
1502 | 1541 | ||
1542 | struct iwlagn_firmware_pieces { | ||
1543 | const void *inst, *data, *init, *init_data, *boot; | ||
1544 | size_t inst_size, data_size, init_size, init_data_size, boot_size; | ||
1545 | |||
1546 | u32 build; | ||
1547 | }; | ||
1548 | |||
1549 | static int iwlagn_load_legacy_firmware(struct iwl_priv *priv, | ||
1550 | const struct firmware *ucode_raw, | ||
1551 | struct iwlagn_firmware_pieces *pieces) | ||
1552 | { | ||
1553 | struct iwl_ucode_header *ucode = (void *)ucode_raw->data; | ||
1554 | u32 api_ver, hdr_size; | ||
1555 | const u8 *src; | ||
1556 | |||
1557 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
1558 | api_ver = IWL_UCODE_API(priv->ucode_ver); | ||
1559 | |||
1560 | switch (api_ver) { | ||
1561 | default: | ||
1562 | /* | ||
1563 | * 4965 doesn't revision the firmware file format | ||
1564 | * along with the API version, it always uses v1 | ||
1565 | * file format. | ||
1566 | */ | ||
1567 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != | ||
1568 | CSR_HW_REV_TYPE_4965) { | ||
1569 | hdr_size = 28; | ||
1570 | if (ucode_raw->size < hdr_size) { | ||
1571 | IWL_ERR(priv, "File size too small!\n"); | ||
1572 | return -EINVAL; | ||
1573 | } | ||
1574 | pieces->build = le32_to_cpu(ucode->u.v2.build); | ||
1575 | pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size); | ||
1576 | pieces->data_size = le32_to_cpu(ucode->u.v2.data_size); | ||
1577 | pieces->init_size = le32_to_cpu(ucode->u.v2.init_size); | ||
1578 | pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size); | ||
1579 | pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size); | ||
1580 | src = ucode->u.v2.data; | ||
1581 | break; | ||
1582 | } | ||
1583 | /* fall through for 4965 */ | ||
1584 | case 0: | ||
1585 | case 1: | ||
1586 | case 2: | ||
1587 | hdr_size = 24; | ||
1588 | if (ucode_raw->size < hdr_size) { | ||
1589 | IWL_ERR(priv, "File size too small!\n"); | ||
1590 | return -EINVAL; | ||
1591 | } | ||
1592 | pieces->build = 0; | ||
1593 | pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size); | ||
1594 | pieces->data_size = le32_to_cpu(ucode->u.v1.data_size); | ||
1595 | pieces->init_size = le32_to_cpu(ucode->u.v1.init_size); | ||
1596 | pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size); | ||
1597 | pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size); | ||
1598 | src = ucode->u.v1.data; | ||
1599 | break; | ||
1600 | } | ||
1601 | |||
1602 | /* Verify size of file vs. image size info in file's header */ | ||
1603 | if (ucode_raw->size != hdr_size + pieces->inst_size + | ||
1604 | pieces->data_size + pieces->init_size + | ||
1605 | pieces->init_data_size + pieces->boot_size) { | ||
1606 | |||
1607 | IWL_ERR(priv, | ||
1608 | "uCode file size %d does not match expected size\n", | ||
1609 | (int)ucode_raw->size); | ||
1610 | return -EINVAL; | ||
1611 | } | ||
1612 | |||
1613 | pieces->inst = src; | ||
1614 | src += pieces->inst_size; | ||
1615 | pieces->data = src; | ||
1616 | src += pieces->data_size; | ||
1617 | pieces->init = src; | ||
1618 | src += pieces->init_size; | ||
1619 | pieces->init_data = src; | ||
1620 | src += pieces->init_data_size; | ||
1621 | pieces->boot = src; | ||
1622 | src += pieces->boot_size; | ||
1623 | |||
1624 | return 0; | ||
1625 | } | ||
1626 | |||
1627 | static int iwlagn_wanted_ucode_alternative = 1; | ||
1628 | |||
1629 | static int iwlagn_load_firmware(struct iwl_priv *priv, | ||
1630 | const struct firmware *ucode_raw, | ||
1631 | struct iwlagn_firmware_pieces *pieces, | ||
1632 | struct iwlagn_ucode_capabilities *capa) | ||
1633 | { | ||
1634 | struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data; | ||
1635 | struct iwl_ucode_tlv *tlv; | ||
1636 | size_t len = ucode_raw->size; | ||
1637 | const u8 *data; | ||
1638 | int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp; | ||
1639 | u64 alternatives; | ||
1640 | |||
1641 | if (len < sizeof(*ucode)) | ||
1642 | return -EINVAL; | ||
1643 | |||
1644 | if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) | ||
1645 | return -EINVAL; | ||
1646 | |||
1647 | /* | ||
1648 | * Check which alternatives are present, and "downgrade" | ||
1649 | * when the chosen alternative is not present, warning | ||
1650 | * the user when that happens. Some files may not have | ||
1651 | * any alternatives, so don't warn in that case. | ||
1652 | */ | ||
1653 | alternatives = le64_to_cpu(ucode->alternatives); | ||
1654 | tmp = wanted_alternative; | ||
1655 | if (wanted_alternative > 63) | ||
1656 | wanted_alternative = 63; | ||
1657 | while (wanted_alternative && !(alternatives & BIT(wanted_alternative))) | ||
1658 | wanted_alternative--; | ||
1659 | if (wanted_alternative && wanted_alternative != tmp) | ||
1660 | IWL_WARN(priv, | ||
1661 | "uCode alternative %d not available, choosing %d\n", | ||
1662 | tmp, wanted_alternative); | ||
1663 | |||
1664 | priv->ucode_ver = le32_to_cpu(ucode->ver); | ||
1665 | pieces->build = le32_to_cpu(ucode->build); | ||
1666 | data = ucode->data; | ||
1667 | |||
1668 | len -= sizeof(*ucode); | ||
1669 | |||
1670 | while (len >= sizeof(*tlv)) { | ||
1671 | u32 tlv_len; | ||
1672 | enum iwl_ucode_tlv_type tlv_type; | ||
1673 | u16 tlv_alt; | ||
1674 | const u8 *tlv_data; | ||
1675 | |||
1676 | len -= sizeof(*tlv); | ||
1677 | tlv = (void *)data; | ||
1678 | |||
1679 | tlv_len = le32_to_cpu(tlv->length); | ||
1680 | tlv_type = le16_to_cpu(tlv->type); | ||
1681 | tlv_alt = le16_to_cpu(tlv->alternative); | ||
1682 | tlv_data = tlv->data; | ||
1683 | |||
1684 | if (len < tlv_len) | ||
1685 | return -EINVAL; | ||
1686 | len -= ALIGN(tlv_len, 4); | ||
1687 | data += sizeof(*tlv) + ALIGN(tlv_len, 4); | ||
1688 | |||
1689 | /* | ||
1690 | * Alternative 0 is always valid. | ||
1691 | * | ||
1692 | * Skip alternative TLVs that are not selected. | ||
1693 | */ | ||
1694 | if (tlv_alt != 0 && tlv_alt != wanted_alternative) | ||
1695 | continue; | ||
1696 | |||
1697 | switch (tlv_type) { | ||
1698 | case IWL_UCODE_TLV_INST: | ||
1699 | pieces->inst = tlv_data; | ||
1700 | pieces->inst_size = tlv_len; | ||
1701 | break; | ||
1702 | case IWL_UCODE_TLV_DATA: | ||
1703 | pieces->data = tlv_data; | ||
1704 | pieces->data_size = tlv_len; | ||
1705 | break; | ||
1706 | case IWL_UCODE_TLV_INIT: | ||
1707 | pieces->init = tlv_data; | ||
1708 | pieces->init_size = tlv_len; | ||
1709 | break; | ||
1710 | case IWL_UCODE_TLV_INIT_DATA: | ||
1711 | pieces->init_data = tlv_data; | ||
1712 | pieces->init_data_size = tlv_len; | ||
1713 | break; | ||
1714 | case IWL_UCODE_TLV_BOOT: | ||
1715 | pieces->boot = tlv_data; | ||
1716 | pieces->boot_size = tlv_len; | ||
1717 | break; | ||
1718 | case IWL_UCODE_TLV_PROBE_MAX_LEN: | ||
1719 | if (tlv_len != 4) | ||
1720 | return -EINVAL; | ||
1721 | capa->max_probe_length = | ||
1722 | le32_to_cpup((__le32 *)tlv_data); | ||
1723 | break; | ||
1724 | default: | ||
1725 | break; | ||
1726 | } | ||
1727 | } | ||
1728 | |||
1729 | if (len) | ||
1730 | return -EINVAL; | ||
1731 | |||
1732 | return 0; | ||
1733 | } | ||
1734 | |||
1503 | /** | 1735 | /** |
1504 | * iwl_ucode_callback - callback when firmware was loaded | 1736 | * iwl_ucode_callback - callback when firmware was loaded |
1505 | * | 1737 | * |
@@ -1510,14 +1742,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1510 | { | 1742 | { |
1511 | struct iwl_priv *priv = context; | 1743 | struct iwl_priv *priv = context; |
1512 | struct iwl_ucode_header *ucode; | 1744 | struct iwl_ucode_header *ucode; |
1745 | int err; | ||
1746 | struct iwlagn_firmware_pieces pieces; | ||
1513 | const unsigned int api_max = priv->cfg->ucode_api_max; | 1747 | const unsigned int api_max = priv->cfg->ucode_api_max; |
1514 | const unsigned int api_min = priv->cfg->ucode_api_min; | 1748 | const unsigned int api_min = priv->cfg->ucode_api_min; |
1515 | u8 *src; | 1749 | u32 api_ver; |
1516 | size_t len; | 1750 | char buildstr[25]; |
1517 | u32 api_ver, build; | 1751 | u32 build; |
1518 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | 1752 | struct iwlagn_ucode_capabilities ucode_capa = { |
1519 | int err; | 1753 | .max_probe_length = 200, |
1520 | u16 eeprom_ver; | 1754 | }; |
1755 | |||
1756 | memset(&pieces, 0, sizeof(pieces)); | ||
1521 | 1757 | ||
1522 | if (!ucode_raw) { | 1758 | if (!ucode_raw) { |
1523 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", | 1759 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", |
@@ -1528,8 +1764,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1528 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", | 1764 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", |
1529 | priv->firmware_name, ucode_raw->size); | 1765 | priv->firmware_name, ucode_raw->size); |
1530 | 1766 | ||
1531 | /* Make sure that we got at least the v1 header! */ | 1767 | /* Make sure that we got at least the API version number */ |
1532 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { | 1768 | if (ucode_raw->size < 4) { |
1533 | IWL_ERR(priv, "File size way too small!\n"); | 1769 | IWL_ERR(priv, "File size way too small!\n"); |
1534 | goto try_again; | 1770 | goto try_again; |
1535 | } | 1771 | } |
@@ -1537,21 +1773,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1537 | /* Data from ucode file: header followed by uCode images */ | 1773 | /* Data from ucode file: header followed by uCode images */ |
1538 | ucode = (struct iwl_ucode_header *)ucode_raw->data; | 1774 | ucode = (struct iwl_ucode_header *)ucode_raw->data; |
1539 | 1775 | ||
1540 | priv->ucode_ver = le32_to_cpu(ucode->ver); | 1776 | if (ucode->ver) |
1777 | err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces); | ||
1778 | else | ||
1779 | err = iwlagn_load_firmware(priv, ucode_raw, &pieces, | ||
1780 | &ucode_capa); | ||
1781 | |||
1782 | if (err) | ||
1783 | goto try_again; | ||
1784 | |||
1541 | api_ver = IWL_UCODE_API(priv->ucode_ver); | 1785 | api_ver = IWL_UCODE_API(priv->ucode_ver); |
1542 | build = priv->cfg->ops->ucode->get_build(ucode, api_ver); | 1786 | build = pieces.build; |
1543 | inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); | ||
1544 | data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); | ||
1545 | init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); | ||
1546 | init_data_size = | ||
1547 | priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); | ||
1548 | boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); | ||
1549 | src = priv->cfg->ops->ucode->get_data(ucode, api_ver); | ||
1550 | |||
1551 | /* api_ver should match the api version forming part of the | ||
1552 | * firmware filename ... but we don't check for that and only rely | ||
1553 | * on the API version read from firmware header from here on forward */ | ||
1554 | 1787 | ||
1788 | /* | ||
1789 | * api_ver should match the api version forming part of the | ||
1790 | * firmware filename ... but we don't check for that and only rely | ||
1791 | * on the API version read from firmware header from here on forward | ||
1792 | */ | ||
1555 | if (api_ver < api_min || api_ver > api_max) { | 1793 | if (api_ver < api_min || api_ver > api_max) { |
1556 | IWL_ERR(priv, "Driver unable to support your firmware API. " | 1794 | IWL_ERR(priv, "Driver unable to support your firmware API. " |
1557 | "Driver supports v%u, firmware is v%u.\n", | 1795 | "Driver supports v%u, firmware is v%u.\n", |
@@ -1565,40 +1803,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1565 | "from http://www.intellinuxwireless.org.\n", | 1803 | "from http://www.intellinuxwireless.org.\n", |
1566 | api_max, api_ver); | 1804 | api_max, api_ver); |
1567 | 1805 | ||
1568 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", | 1806 | if (build) |
1569 | IWL_UCODE_MAJOR(priv->ucode_ver), | 1807 | sprintf(buildstr, " build %u", build); |
1570 | IWL_UCODE_MINOR(priv->ucode_ver), | 1808 | else |
1571 | IWL_UCODE_API(priv->ucode_ver), | 1809 | buildstr[0] = '\0'; |
1572 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1810 | |
1811 | IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n", | ||
1812 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
1813 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
1814 | IWL_UCODE_API(priv->ucode_ver), | ||
1815 | IWL_UCODE_SERIAL(priv->ucode_ver), | ||
1816 | buildstr); | ||
1573 | 1817 | ||
1574 | snprintf(priv->hw->wiphy->fw_version, | 1818 | snprintf(priv->hw->wiphy->fw_version, |
1575 | sizeof(priv->hw->wiphy->fw_version), | 1819 | sizeof(priv->hw->wiphy->fw_version), |
1576 | "%u.%u.%u.%u", | 1820 | "%u.%u.%u.%u%s", |
1577 | IWL_UCODE_MAJOR(priv->ucode_ver), | 1821 | IWL_UCODE_MAJOR(priv->ucode_ver), |
1578 | IWL_UCODE_MINOR(priv->ucode_ver), | 1822 | IWL_UCODE_MINOR(priv->ucode_ver), |
1579 | IWL_UCODE_API(priv->ucode_ver), | 1823 | IWL_UCODE_API(priv->ucode_ver), |
1580 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1824 | IWL_UCODE_SERIAL(priv->ucode_ver), |
1581 | 1825 | buildstr); | |
1582 | if (build) | ||
1583 | IWL_DEBUG_INFO(priv, "Build %u\n", build); | ||
1584 | |||
1585 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
1586 | IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", | ||
1587 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
1588 | ? "OTP" : "EEPROM", eeprom_ver); | ||
1589 | |||
1590 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | ||
1591 | priv->ucode_ver); | ||
1592 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | ||
1593 | inst_size); | ||
1594 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", | ||
1595 | data_size); | ||
1596 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", | ||
1597 | init_size); | ||
1598 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", | ||
1599 | init_data_size); | ||
1600 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", | ||
1601 | boot_size); | ||
1602 | 1826 | ||
1603 | /* | 1827 | /* |
1604 | * For any of the failures below (before allocating pci memory) | 1828 | * For any of the failures below (before allocating pci memory) |
@@ -1606,43 +1830,47 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1606 | * user just got a corrupted version of the latest API. | 1830 | * user just got a corrupted version of the latest API. |
1607 | */ | 1831 | */ |
1608 | 1832 | ||
1609 | /* Verify size of file vs. image size info in file's header */ | 1833 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", |
1610 | if (ucode_raw->size != | 1834 | priv->ucode_ver); |
1611 | priv->cfg->ops->ucode->get_header_size(api_ver) + | 1835 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n", |
1612 | inst_size + data_size + init_size + | 1836 | pieces.inst_size); |
1613 | init_data_size + boot_size) { | 1837 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n", |
1614 | 1838 | pieces.data_size); | |
1615 | IWL_DEBUG_INFO(priv, | 1839 | IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n", |
1616 | "uCode file size %d does not match expected size\n", | 1840 | pieces.init_size); |
1617 | (int)ucode_raw->size); | 1841 | IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n", |
1618 | goto try_again; | 1842 | pieces.init_data_size); |
1619 | } | 1843 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n", |
1844 | pieces.boot_size); | ||
1620 | 1845 | ||
1621 | /* Verify that uCode images will fit in card's SRAM */ | 1846 | /* Verify that uCode images will fit in card's SRAM */ |
1622 | if (inst_size > priv->hw_params.max_inst_size) { | 1847 | if (pieces.inst_size > priv->hw_params.max_inst_size) { |
1623 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", | 1848 | IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n", |
1624 | inst_size); | 1849 | pieces.inst_size); |
1625 | goto try_again; | 1850 | goto try_again; |
1626 | } | 1851 | } |
1627 | 1852 | ||
1628 | if (data_size > priv->hw_params.max_data_size) { | 1853 | if (pieces.data_size > priv->hw_params.max_data_size) { |
1629 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", | 1854 | IWL_ERR(priv, "uCode data len %Zd too large to fit in\n", |
1630 | data_size); | 1855 | pieces.data_size); |
1631 | goto try_again; | 1856 | goto try_again; |
1632 | } | 1857 | } |
1633 | if (init_size > priv->hw_params.max_inst_size) { | 1858 | |
1634 | IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", | 1859 | if (pieces.init_size > priv->hw_params.max_inst_size) { |
1635 | init_size); | 1860 | IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n", |
1861 | pieces.init_size); | ||
1636 | goto try_again; | 1862 | goto try_again; |
1637 | } | 1863 | } |
1638 | if (init_data_size > priv->hw_params.max_data_size) { | 1864 | |
1639 | IWL_INFO(priv, "uCode init data len %d too large to fit in\n", | 1865 | if (pieces.init_data_size > priv->hw_params.max_data_size) { |
1640 | init_data_size); | 1866 | IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n", |
1867 | pieces.init_data_size); | ||
1641 | goto try_again; | 1868 | goto try_again; |
1642 | } | 1869 | } |
1643 | if (boot_size > priv->hw_params.max_bsm_size) { | 1870 | |
1644 | IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", | 1871 | if (pieces.boot_size > priv->hw_params.max_bsm_size) { |
1645 | boot_size); | 1872 | IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n", |
1873 | pieces.boot_size); | ||
1646 | goto try_again; | 1874 | goto try_again; |
1647 | } | 1875 | } |
1648 | 1876 | ||
@@ -1651,13 +1879,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1651 | /* Runtime instructions and 2 copies of data: | 1879 | /* Runtime instructions and 2 copies of data: |
1652 | * 1) unmodified from disk | 1880 | * 1) unmodified from disk |
1653 | * 2) backup cache for save/restore during power-downs */ | 1881 | * 2) backup cache for save/restore during power-downs */ |
1654 | priv->ucode_code.len = inst_size; | 1882 | priv->ucode_code.len = pieces.inst_size; |
1655 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); | 1883 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); |
1656 | 1884 | ||
1657 | priv->ucode_data.len = data_size; | 1885 | priv->ucode_data.len = pieces.data_size; |
1658 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); | 1886 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); |
1659 | 1887 | ||
1660 | priv->ucode_data_backup.len = data_size; | 1888 | priv->ucode_data_backup.len = pieces.data_size; |
1661 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); | 1889 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); |
1662 | 1890 | ||
1663 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || | 1891 | if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || |
@@ -1665,11 +1893,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1665 | goto err_pci_alloc; | 1893 | goto err_pci_alloc; |
1666 | 1894 | ||
1667 | /* Initialization instructions and data */ | 1895 | /* Initialization instructions and data */ |
1668 | if (init_size && init_data_size) { | 1896 | if (pieces.init_size && pieces.init_data_size) { |
1669 | priv->ucode_init.len = init_size; | 1897 | priv->ucode_init.len = pieces.init_size; |
1670 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); | 1898 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); |
1671 | 1899 | ||
1672 | priv->ucode_init_data.len = init_data_size; | 1900 | priv->ucode_init_data.len = pieces.init_data_size; |
1673 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); | 1901 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); |
1674 | 1902 | ||
1675 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) | 1903 | if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) |
@@ -1677,8 +1905,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1677 | } | 1905 | } |
1678 | 1906 | ||
1679 | /* Bootstrap (instructions only, no data) */ | 1907 | /* Bootstrap (instructions only, no data) */ |
1680 | if (boot_size) { | 1908 | if (pieces.boot_size) { |
1681 | priv->ucode_boot.len = boot_size; | 1909 | priv->ucode_boot.len = pieces.boot_size; |
1682 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); | 1910 | iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); |
1683 | 1911 | ||
1684 | if (!priv->ucode_boot.v_addr) | 1912 | if (!priv->ucode_boot.v_addr) |
@@ -1688,51 +1916,48 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1688 | /* Copy images into buffers for card's bus-master reads ... */ | 1916 | /* Copy images into buffers for card's bus-master reads ... */ |
1689 | 1917 | ||
1690 | /* Runtime instructions (first block of data in file) */ | 1918 | /* Runtime instructions (first block of data in file) */ |
1691 | len = inst_size; | 1919 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", |
1692 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); | 1920 | pieces.inst_size); |
1693 | memcpy(priv->ucode_code.v_addr, src, len); | 1921 | memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size); |
1694 | src += len; | ||
1695 | 1922 | ||
1696 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | 1923 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", |
1697 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | 1924 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); |
1698 | 1925 | ||
1699 | /* Runtime data (2nd block) | 1926 | /* |
1700 | * NOTE: Copy into backup buffer will be done in iwl_up() */ | 1927 | * Runtime data |
1701 | len = data_size; | 1928 | * NOTE: Copy into backup buffer will be done in iwl_up() |
1702 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); | 1929 | */ |
1703 | memcpy(priv->ucode_data.v_addr, src, len); | 1930 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", |
1704 | memcpy(priv->ucode_data_backup.v_addr, src, len); | 1931 | pieces.data_size); |
1705 | src += len; | 1932 | memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size); |
1706 | 1933 | memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size); | |
1707 | /* Initialization instructions (3rd block) */ | 1934 | |
1708 | if (init_size) { | 1935 | /* Initialization instructions */ |
1709 | len = init_size; | 1936 | if (pieces.init_size) { |
1710 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", | 1937 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", |
1711 | len); | 1938 | pieces.init_size); |
1712 | memcpy(priv->ucode_init.v_addr, src, len); | 1939 | memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size); |
1713 | src += len; | ||
1714 | } | 1940 | } |
1715 | 1941 | ||
1716 | /* Initialization data (4th block) */ | 1942 | /* Initialization data */ |
1717 | if (init_data_size) { | 1943 | if (pieces.init_data_size) { |
1718 | len = init_data_size; | ||
1719 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", | 1944 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", |
1720 | len); | 1945 | pieces.init_data_size); |
1721 | memcpy(priv->ucode_init_data.v_addr, src, len); | 1946 | memcpy(priv->ucode_init_data.v_addr, pieces.init_data, |
1722 | src += len; | 1947 | pieces.init_data_size); |
1723 | } | 1948 | } |
1724 | 1949 | ||
1725 | /* Bootstrap instructions (5th block) */ | 1950 | /* Bootstrap instructions */ |
1726 | len = boot_size; | 1951 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", |
1727 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); | 1952 | pieces.boot_size); |
1728 | memcpy(priv->ucode_boot.v_addr, src, len); | 1953 | memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); |
1729 | 1954 | ||
1730 | /************************************************** | 1955 | /************************************************** |
1731 | * This is still part of probe() in a sense... | 1956 | * This is still part of probe() in a sense... |
1732 | * | 1957 | * |
1733 | * 9. Setup and register with mac80211 and debugfs | 1958 | * 9. Setup and register with mac80211 and debugfs |
1734 | **************************************************/ | 1959 | **************************************************/ |
1735 | err = iwl_mac_setup_register(priv); | 1960 | err = iwl_mac_setup_register(priv, &ucode_capa); |
1736 | if (err) | 1961 | if (err) |
1737 | goto out_unbind; | 1962 | goto out_unbind; |
1738 | 1963 | ||
@@ -1742,6 +1967,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1742 | 1967 | ||
1743 | /* We have our copies now, allow OS release its copies */ | 1968 | /* We have our copies now, allow OS release its copies */ |
1744 | release_firmware(ucode_raw); | 1969 | release_firmware(ucode_raw); |
1970 | complete(&priv->_agn.firmware_loading_complete); | ||
1745 | return; | 1971 | return; |
1746 | 1972 | ||
1747 | try_again: | 1973 | try_again: |
@@ -1755,6 +1981,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1755 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 1981 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
1756 | iwl_dealloc_ucode_pci(priv); | 1982 | iwl_dealloc_ucode_pci(priv); |
1757 | out_unbind: | 1983 | out_unbind: |
1984 | complete(&priv->_agn.firmware_loading_complete); | ||
1758 | device_release_driver(&priv->pci_dev->dev); | 1985 | device_release_driver(&priv->pci_dev->dev); |
1759 | release_firmware(ucode_raw); | 1986 | release_firmware(ucode_raw); |
1760 | } | 1987 | } |
@@ -1809,6 +2036,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1809 | u32 data2, line; | 2036 | u32 data2, line; |
1810 | u32 desc, time, count, base, data1; | 2037 | u32 desc, time, count, base, data1; |
1811 | u32 blink1, blink2, ilink1, ilink2; | 2038 | u32 blink1, blink2, ilink1, ilink2; |
2039 | u32 pc, hcmd; | ||
1812 | 2040 | ||
1813 | if (priv->ucode_type == UCODE_INIT) | 2041 | if (priv->ucode_type == UCODE_INIT) |
1814 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | 2042 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); |
@@ -1831,6 +2059,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1831 | } | 2059 | } |
1832 | 2060 | ||
1833 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); | 2061 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); |
2062 | pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); | ||
1834 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); | 2063 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); |
1835 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); | 2064 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); |
1836 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); | 2065 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); |
@@ -1839,6 +2068,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1839 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); | 2068 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); |
1840 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | 2069 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); |
1841 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | 2070 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); |
2071 | hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); | ||
1842 | 2072 | ||
1843 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, | 2073 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, |
1844 | blink1, blink2, ilink1, ilink2); | 2074 | blink1, blink2, ilink1, ilink2); |
@@ -1847,10 +2077,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1847 | "data1 data2 line\n"); | 2077 | "data1 data2 line\n"); |
1848 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | 2078 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", |
1849 | desc_lookup(desc), desc, time, data1, data2, line); | 2079 | desc_lookup(desc), desc, time, data1, data2, line); |
1850 | IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); | 2080 | IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); |
1851 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, | 2081 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", |
1852 | ilink1, ilink2); | 2082 | pc, blink1, blink2, ilink1, ilink2, hcmd); |
1853 | |||
1854 | } | 2083 | } |
1855 | 2084 | ||
1856 | #define EVENT_START_OFFSET (4 * sizeof(u32)) | 2085 | #define EVENT_START_OFFSET (4 * sizeof(u32)) |
@@ -1966,9 +2195,6 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1966 | return pos; | 2195 | return pos; |
1967 | } | 2196 | } |
1968 | 2197 | ||
1969 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | ||
1970 | #define MAX_EVENT_LOG_SIZE (512) | ||
1971 | |||
1972 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) | 2198 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) |
1973 | 2199 | ||
1974 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | 2200 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
@@ -2001,16 +2227,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2001 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2227 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
2002 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2228 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
2003 | 2229 | ||
2004 | if (capacity > MAX_EVENT_LOG_SIZE) { | 2230 | if (capacity > priv->cfg->max_event_log_size) { |
2005 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 2231 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
2006 | capacity, MAX_EVENT_LOG_SIZE); | 2232 | capacity, priv->cfg->max_event_log_size); |
2007 | capacity = MAX_EVENT_LOG_SIZE; | 2233 | capacity = priv->cfg->max_event_log_size; |
2008 | } | 2234 | } |
2009 | 2235 | ||
2010 | if (next_entry > MAX_EVENT_LOG_SIZE) { | 2236 | if (next_entry > priv->cfg->max_event_log_size) { |
2011 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 2237 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
2012 | next_entry, MAX_EVENT_LOG_SIZE); | 2238 | next_entry, priv->cfg->max_event_log_size); |
2013 | next_entry = MAX_EVENT_LOG_SIZE; | 2239 | next_entry = priv->cfg->max_event_log_size; |
2014 | } | 2240 | } |
2015 | 2241 | ||
2016 | size = num_wraps ? capacity : next_entry; | 2242 | size = num_wraps ? capacity : next_entry; |
@@ -2095,7 +2321,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2095 | goto restart; | 2321 | goto restart; |
2096 | } | 2322 | } |
2097 | 2323 | ||
2098 | iwl_clear_stations_table(priv); | ||
2099 | ret = priv->cfg->ops->lib->alive_notify(priv); | 2324 | ret = priv->cfg->ops->lib->alive_notify(priv); |
2100 | if (ret) { | 2325 | if (ret) { |
2101 | IWL_WARN(priv, | 2326 | IWL_WARN(priv, |
@@ -2106,13 +2331,19 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2106 | /* After the ALIVE response, we can send host commands to the uCode */ | 2331 | /* After the ALIVE response, we can send host commands to the uCode */ |
2107 | set_bit(STATUS_ALIVE, &priv->status); | 2332 | set_bit(STATUS_ALIVE, &priv->status); |
2108 | 2333 | ||
2334 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
2335 | /* Enable timer to monitor the driver queues */ | ||
2336 | mod_timer(&priv->monitor_recover, | ||
2337 | jiffies + | ||
2338 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2339 | } | ||
2340 | |||
2109 | if (iwl_is_rfkill(priv)) | 2341 | if (iwl_is_rfkill(priv)) |
2110 | return; | 2342 | return; |
2111 | 2343 | ||
2112 | ieee80211_wake_queues(priv->hw); | 2344 | ieee80211_wake_queues(priv->hw); |
2113 | 2345 | ||
2114 | priv->active_rate = priv->rates_mask; | 2346 | priv->active_rate = IWL_RATES_MASK; |
2115 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | ||
2116 | 2347 | ||
2117 | /* Configure Tx antenna selection based on H/W config */ | 2348 | /* Configure Tx antenna selection based on H/W config */ |
2118 | if (priv->cfg->ops->hcmd->set_tx_ant) | 2349 | if (priv->cfg->ops->hcmd->set_tx_ant) |
@@ -2126,7 +2357,7 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2126 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2357 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2127 | } else { | 2358 | } else { |
2128 | /* Initialize our rx_config data */ | 2359 | /* Initialize our rx_config data */ |
2129 | iwl_connection_init_rx_config(priv, priv->iw_mode); | 2360 | iwl_connection_init_rx_config(priv, NULL); |
2130 | 2361 | ||
2131 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2362 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2132 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2363 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
@@ -2135,7 +2366,7 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2135 | } | 2366 | } |
2136 | 2367 | ||
2137 | /* Configure Bluetooth device coexistence support */ | 2368 | /* Configure Bluetooth device coexistence support */ |
2138 | iwl_send_bt_config(priv); | 2369 | priv->cfg->ops->hcmd->send_bt_config(priv); |
2139 | 2370 | ||
2140 | iwl_reset_run_time_calib(priv); | 2371 | iwl_reset_run_time_calib(priv); |
2141 | 2372 | ||
@@ -2152,18 +2383,8 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2152 | wake_up_interruptible(&priv->wait_command_queue); | 2383 | wake_up_interruptible(&priv->wait_command_queue); |
2153 | 2384 | ||
2154 | iwl_power_update_mode(priv, true); | 2385 | iwl_power_update_mode(priv, true); |
2386 | IWL_DEBUG_INFO(priv, "Updated power mode\n"); | ||
2155 | 2387 | ||
2156 | /* reassociate for ADHOC mode */ | ||
2157 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | ||
2158 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | ||
2159 | priv->vif); | ||
2160 | if (beacon) | ||
2161 | iwl_mac_beacon_update(priv->hw, beacon); | ||
2162 | } | ||
2163 | |||
2164 | |||
2165 | if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) | ||
2166 | iwl_set_mode(priv, priv->iw_mode); | ||
2167 | 2388 | ||
2168 | return; | 2389 | return; |
2169 | 2390 | ||
@@ -2183,7 +2404,9 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2183 | if (!exit_pending) | 2404 | if (!exit_pending) |
2184 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2405 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2185 | 2406 | ||
2186 | iwl_clear_stations_table(priv); | 2407 | iwl_clear_ucode_stations(priv); |
2408 | iwl_dealloc_bcast_station(priv); | ||
2409 | iwl_clear_driver_stations(priv); | ||
2187 | 2410 | ||
2188 | /* Unblock any waiting calls */ | 2411 | /* Unblock any waiting calls */ |
2189 | wake_up_interruptible_all(&priv->wait_command_queue); | 2412 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2231,8 +2454,8 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2231 | /* device going down, Stop using ICT table */ | 2454 | /* device going down, Stop using ICT table */ |
2232 | iwl_disable_ict(priv); | 2455 | iwl_disable_ict(priv); |
2233 | 2456 | ||
2234 | iwl_txq_ctx_stop(priv); | 2457 | iwlagn_txq_ctx_stop(priv); |
2235 | iwl_rxq_stop(priv); | 2458 | iwlagn_rxq_stop(priv); |
2236 | 2459 | ||
2237 | /* Power-down device's busmaster DMA clocks */ | 2460 | /* Power-down device's busmaster DMA clocks */ |
2238 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); | 2461 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
@@ -2292,7 +2515,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) | |||
2292 | { | 2515 | { |
2293 | int ret = 0; | 2516 | int ret = 0; |
2294 | 2517 | ||
2295 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n"); | 2518 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); |
2296 | 2519 | ||
2297 | ret = iwl_set_hw_ready(priv); | 2520 | ret = iwl_set_hw_ready(priv); |
2298 | if (priv->hw_ready) | 2521 | if (priv->hw_ready) |
@@ -2330,6 +2553,10 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2330 | return -EIO; | 2553 | return -EIO; |
2331 | } | 2554 | } |
2332 | 2555 | ||
2556 | ret = iwl_alloc_bcast_station(priv, true); | ||
2557 | if (ret) | ||
2558 | return ret; | ||
2559 | |||
2333 | iwl_prepare_card_hw(priv); | 2560 | iwl_prepare_card_hw(priv); |
2334 | 2561 | ||
2335 | if (!priv->hw_ready) { | 2562 | if (!priv->hw_ready) { |
@@ -2353,7 +2580,7 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2353 | 2580 | ||
2354 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 2581 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2355 | 2582 | ||
2356 | ret = iwl_hw_nic_init(priv); | 2583 | ret = iwlagn_hw_nic_init(priv); |
2357 | if (ret) { | 2584 | if (ret) { |
2358 | IWL_ERR(priv, "Unable to init nic\n"); | 2585 | IWL_ERR(priv, "Unable to init nic\n"); |
2359 | return ret; | 2586 | return ret; |
@@ -2380,8 +2607,6 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2380 | 2607 | ||
2381 | for (i = 0; i < MAX_HW_RESTARTS; i++) { | 2608 | for (i = 0; i < MAX_HW_RESTARTS; i++) { |
2382 | 2609 | ||
2383 | iwl_clear_stations_table(priv); | ||
2384 | |||
2385 | /* load bootstrap state machine, | 2610 | /* load bootstrap state machine, |
2386 | * load bootstrap program into processor's memory, | 2611 | * load bootstrap program into processor's memory, |
2387 | * prepare to load the "initialize" uCode */ | 2612 | * prepare to load the "initialize" uCode */ |
@@ -2467,7 +2692,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
2467 | } | 2692 | } |
2468 | 2693 | ||
2469 | mutex_unlock(&priv->mutex); | 2694 | mutex_unlock(&priv->mutex); |
2470 | return; | ||
2471 | } | 2695 | } |
2472 | 2696 | ||
2473 | static void iwl_bg_restart(struct work_struct *data) | 2697 | static void iwl_bg_restart(struct work_struct *data) |
@@ -2505,34 +2729,28 @@ static void iwl_bg_rx_replenish(struct work_struct *data) | |||
2505 | return; | 2729 | return; |
2506 | 2730 | ||
2507 | mutex_lock(&priv->mutex); | 2731 | mutex_lock(&priv->mutex); |
2508 | iwl_rx_replenish(priv); | 2732 | iwlagn_rx_replenish(priv); |
2509 | mutex_unlock(&priv->mutex); | 2733 | mutex_unlock(&priv->mutex); |
2510 | } | 2734 | } |
2511 | 2735 | ||
2512 | #define IWL_DELAY_NEXT_SCAN (HZ*2) | 2736 | #define IWL_DELAY_NEXT_SCAN (HZ*2) |
2513 | 2737 | ||
2514 | void iwl_post_associate(struct iwl_priv *priv) | 2738 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2515 | { | 2739 | { |
2516 | struct ieee80211_conf *conf = NULL; | 2740 | struct ieee80211_conf *conf = NULL; |
2517 | int ret = 0; | 2741 | int ret = 0; |
2518 | unsigned long flags; | ||
2519 | 2742 | ||
2520 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2743 | if (!vif || !priv->is_open) |
2744 | return; | ||
2745 | |||
2746 | if (vif->type == NL80211_IFTYPE_AP) { | ||
2521 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 2747 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
2522 | return; | 2748 | return; |
2523 | } | 2749 | } |
2524 | 2750 | ||
2525 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | ||
2526 | priv->assoc_id, priv->active_rxon.bssid_addr); | ||
2527 | |||
2528 | |||
2529 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2751 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2530 | return; | 2752 | return; |
2531 | 2753 | ||
2532 | |||
2533 | if (!priv->vif || !priv->is_open) | ||
2534 | return; | ||
2535 | |||
2536 | iwl_scan_cancel_timeout(priv, 200); | 2754 | iwl_scan_cancel_timeout(priv, 200); |
2537 | 2755 | ||
2538 | conf = ieee80211_get_hw_conf(priv->hw); | 2756 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -2540,7 +2758,7 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2540 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2758 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2541 | iwlcore_commit_rxon(priv); | 2759 | iwlcore_commit_rxon(priv); |
2542 | 2760 | ||
2543 | iwl_setup_rxon_timing(priv); | 2761 | iwl_setup_rxon_timing(priv, vif); |
2544 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 2762 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
2545 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 2763 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
2546 | if (ret) | 2764 | if (ret) |
@@ -2554,56 +2772,44 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2554 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2772 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2555 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2773 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2556 | 2774 | ||
2557 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 2775 | priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); |
2558 | 2776 | ||
2559 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 2777 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
2560 | priv->assoc_id, priv->beacon_int); | 2778 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
2561 | 2779 | ||
2562 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 2780 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
2563 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 2781 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
2564 | else | 2782 | else |
2565 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 2783 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2566 | 2784 | ||
2567 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 2785 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2568 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 2786 | if (vif->bss_conf.assoc_capability & |
2787 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2569 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 2788 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
2570 | else | 2789 | else |
2571 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2790 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2572 | 2791 | ||
2573 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 2792 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2574 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 2793 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
2575 | |||
2576 | } | 2794 | } |
2577 | 2795 | ||
2578 | iwlcore_commit_rxon(priv); | 2796 | iwlcore_commit_rxon(priv); |
2579 | 2797 | ||
2580 | switch (priv->iw_mode) { | 2798 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", |
2799 | vif->bss_conf.aid, priv->active_rxon.bssid_addr); | ||
2800 | |||
2801 | switch (vif->type) { | ||
2581 | case NL80211_IFTYPE_STATION: | 2802 | case NL80211_IFTYPE_STATION: |
2582 | break; | 2803 | break; |
2583 | |||
2584 | case NL80211_IFTYPE_ADHOC: | 2804 | case NL80211_IFTYPE_ADHOC: |
2585 | |||
2586 | /* assume default assoc id */ | ||
2587 | priv->assoc_id = 1; | ||
2588 | |||
2589 | iwl_rxon_add_station(priv, priv->bssid, 0); | ||
2590 | iwl_send_beacon_cmd(priv); | 2805 | iwl_send_beacon_cmd(priv); |
2591 | |||
2592 | break; | 2806 | break; |
2593 | |||
2594 | default: | 2807 | default: |
2595 | IWL_ERR(priv, "%s Should not be called in %d mode\n", | 2808 | IWL_ERR(priv, "%s Should not be called in %d mode\n", |
2596 | __func__, priv->iw_mode); | 2809 | __func__, vif->type); |
2597 | break; | 2810 | break; |
2598 | } | 2811 | } |
2599 | 2812 | ||
2600 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | ||
2601 | priv->assoc_station_added = 1; | ||
2602 | |||
2603 | spin_lock_irqsave(&priv->lock, flags); | ||
2604 | iwl_activate_qos(priv, 0); | ||
2605 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2606 | |||
2607 | /* the chain noise calibration will enabled PM upon completion | 2813 | /* the chain noise calibration will enabled PM upon completion |
2608 | * If chain noise has already been run, then we need to enable | 2814 | * If chain noise has already been run, then we need to enable |
2609 | * power management here */ | 2815 | * power management here */ |
@@ -2628,7 +2834,8 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2628 | * Not a mac80211 entry point function, but it fits in with all the | 2834 | * Not a mac80211 entry point function, but it fits in with all the |
2629 | * other mac80211 functions grouped here. | 2835 | * other mac80211 functions grouped here. |
2630 | */ | 2836 | */ |
2631 | static int iwl_mac_setup_register(struct iwl_priv *priv) | 2837 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
2838 | struct iwlagn_ucode_capabilities *capa) | ||
2632 | { | 2839 | { |
2633 | int ret; | 2840 | int ret; |
2634 | struct ieee80211_hw *hw = priv->hw; | 2841 | struct ieee80211_hw *hw = priv->hw; |
@@ -2636,7 +2843,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2636 | 2843 | ||
2637 | /* Tell mac80211 our characteristics */ | 2844 | /* Tell mac80211 our characteristics */ |
2638 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2845 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
2639 | IEEE80211_HW_NOISE_DBM | | ||
2640 | IEEE80211_HW_AMPDU_AGGREGATION | | 2846 | IEEE80211_HW_AMPDU_AGGREGATION | |
2641 | IEEE80211_HW_SPECTRUM_MGMT; | 2847 | IEEE80211_HW_SPECTRUM_MGMT; |
2642 | 2848 | ||
@@ -2649,6 +2855,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2649 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | 2855 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; |
2650 | 2856 | ||
2651 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 2857 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
2858 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
2859 | |||
2652 | hw->wiphy->interface_modes = | 2860 | hw->wiphy->interface_modes = |
2653 | BIT(NL80211_IFTYPE_STATION) | | 2861 | BIT(NL80211_IFTYPE_STATION) | |
2654 | BIT(NL80211_IFTYPE_ADHOC); | 2862 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2664,7 +2872,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) | |||
2664 | 2872 | ||
2665 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 2873 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
2666 | /* we create the 802.11 header and a zero-length SSID element */ | 2874 | /* we create the 802.11 header and a zero-length SSID element */ |
2667 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | 2875 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; |
2668 | 2876 | ||
2669 | /* Default value; 4 EDCA QOS priorities */ | 2877 | /* Default value; 4 EDCA QOS priorities */ |
2670 | hw->queues = 4; | 2878 | hw->queues = 4; |
@@ -2770,17 +2978,16 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2770 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | 2978 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, |
2771 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | 2979 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); |
2772 | 2980 | ||
2773 | if (iwl_tx_skb(priv, skb)) | 2981 | if (iwlagn_tx_skb(priv, skb)) |
2774 | dev_kfree_skb_any(skb); | 2982 | dev_kfree_skb_any(skb); |
2775 | 2983 | ||
2776 | IWL_DEBUG_MACDUMP(priv, "leave\n"); | 2984 | IWL_DEBUG_MACDUMP(priv, "leave\n"); |
2777 | return NETDEV_TX_OK; | 2985 | return NETDEV_TX_OK; |
2778 | } | 2986 | } |
2779 | 2987 | ||
2780 | void iwl_config_ap(struct iwl_priv *priv) | 2988 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2781 | { | 2989 | { |
2782 | int ret = 0; | 2990 | int ret = 0; |
2783 | unsigned long flags; | ||
2784 | 2991 | ||
2785 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2992 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2786 | return; | 2993 | return; |
@@ -2793,7 +3000,7 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2793 | iwlcore_commit_rxon(priv); | 3000 | iwlcore_commit_rxon(priv); |
2794 | 3001 | ||
2795 | /* RXON Timing */ | 3002 | /* RXON Timing */ |
2796 | iwl_setup_rxon_timing(priv); | 3003 | iwl_setup_rxon_timing(priv, vif); |
2797 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 3004 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
2798 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 3005 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
2799 | if (ret) | 3006 | if (ret) |
@@ -2807,9 +3014,10 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2807 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3014 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2808 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 3015 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2809 | 3016 | ||
2810 | /* FIXME: what should be the assoc_id for AP? */ | 3017 | priv->staging_rxon.assoc_id = 0; |
2811 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 3018 | |
2812 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3019 | if (vif->bss_conf.assoc_capability & |
3020 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
2813 | priv->staging_rxon.flags |= | 3021 | priv->staging_rxon.flags |= |
2814 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3022 | RXON_FLG_SHORT_PREAMBLE_MSK; |
2815 | else | 3023 | else |
@@ -2817,26 +3025,21 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2817 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3025 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
2818 | 3026 | ||
2819 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3027 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
2820 | if (priv->assoc_capability & | 3028 | if (vif->bss_conf.assoc_capability & |
2821 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3029 | WLAN_CAPABILITY_SHORT_SLOT_TIME) |
2822 | priv->staging_rxon.flags |= | 3030 | priv->staging_rxon.flags |= |
2823 | RXON_FLG_SHORT_SLOT_MSK; | 3031 | RXON_FLG_SHORT_SLOT_MSK; |
2824 | else | 3032 | else |
2825 | priv->staging_rxon.flags &= | 3033 | priv->staging_rxon.flags &= |
2826 | ~RXON_FLG_SHORT_SLOT_MSK; | 3034 | ~RXON_FLG_SHORT_SLOT_MSK; |
2827 | 3035 | ||
2828 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 3036 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2829 | priv->staging_rxon.flags &= | 3037 | priv->staging_rxon.flags &= |
2830 | ~RXON_FLG_SHORT_SLOT_MSK; | 3038 | ~RXON_FLG_SHORT_SLOT_MSK; |
2831 | } | 3039 | } |
2832 | /* restore RXON assoc */ | 3040 | /* restore RXON assoc */ |
2833 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3041 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2834 | iwlcore_commit_rxon(priv); | 3042 | iwlcore_commit_rxon(priv); |
2835 | iwl_reset_qos(priv); | ||
2836 | spin_lock_irqsave(&priv->lock, flags); | ||
2837 | iwl_activate_qos(priv, 1); | ||
2838 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2839 | iwl_add_bcast_station(priv); | ||
2840 | } | 3043 | } |
2841 | iwl_send_beacon_cmd(priv); | 3044 | iwl_send_beacon_cmd(priv); |
2842 | 3045 | ||
@@ -2855,8 +3058,7 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
2855 | struct iwl_priv *priv = hw->priv; | 3058 | struct iwl_priv *priv = hw->priv; |
2856 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 3059 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2857 | 3060 | ||
2858 | iwl_update_tkip_key(priv, keyconf, | 3061 | iwl_update_tkip_key(priv, keyconf, sta, |
2859 | sta ? sta->addr : iwl_bcast_addr, | ||
2860 | iv32, phase1key); | 3062 | iv32, phase1key); |
2861 | 3063 | ||
2862 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3064 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2868,7 +3070,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2868 | struct ieee80211_key_conf *key) | 3070 | struct ieee80211_key_conf *key) |
2869 | { | 3071 | { |
2870 | struct iwl_priv *priv = hw->priv; | 3072 | struct iwl_priv *priv = hw->priv; |
2871 | const u8 *addr; | ||
2872 | int ret; | 3073 | int ret; |
2873 | u8 sta_id; | 3074 | u8 sta_id; |
2874 | bool is_default_wep_key = false; | 3075 | bool is_default_wep_key = false; |
@@ -2879,25 +3080,29 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2879 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); | 3080 | IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); |
2880 | return -EOPNOTSUPP; | 3081 | return -EOPNOTSUPP; |
2881 | } | 3082 | } |
2882 | addr = sta ? sta->addr : iwl_bcast_addr; | ||
2883 | sta_id = iwl_find_station(priv, addr); | ||
2884 | if (sta_id == IWL_INVALID_STATION) { | ||
2885 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
2886 | addr); | ||
2887 | return -EINVAL; | ||
2888 | 3083 | ||
3084 | if (sta) { | ||
3085 | sta_id = iwl_sta_id(sta); | ||
3086 | |||
3087 | if (sta_id == IWL_INVALID_STATION) { | ||
3088 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | ||
3089 | sta->addr); | ||
3090 | return -EINVAL; | ||
3091 | } | ||
3092 | } else { | ||
3093 | sta_id = priv->hw_params.bcast_sta_id; | ||
2889 | } | 3094 | } |
2890 | 3095 | ||
2891 | mutex_lock(&priv->mutex); | 3096 | mutex_lock(&priv->mutex); |
2892 | iwl_scan_cancel_timeout(priv, 100); | 3097 | iwl_scan_cancel_timeout(priv, 100); |
2893 | mutex_unlock(&priv->mutex); | ||
2894 | 3098 | ||
2895 | /* If we are getting WEP group key and we didn't receive any key mapping | 3099 | /* |
3100 | * If we are getting WEP group key and we didn't receive any key mapping | ||
2896 | * so far, we are in legacy wep mode (group key only), otherwise we are | 3101 | * so far, we are in legacy wep mode (group key only), otherwise we are |
2897 | * in 1X mode. | 3102 | * in 1X mode. |
2898 | * In legacy wep mode, we use another host command to the uCode */ | 3103 | * In legacy wep mode, we use another host command to the uCode. |
2899 | if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && | 3104 | */ |
2900 | priv->iw_mode != NL80211_IFTYPE_AP) { | 3105 | if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { |
2901 | if (cmd == SET_KEY) | 3106 | if (cmd == SET_KEY) |
2902 | is_default_wep_key = !priv->key_mapping_key; | 3107 | is_default_wep_key = !priv->key_mapping_key; |
2903 | else | 3108 | else |
@@ -2926,6 +3131,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2926 | ret = -EINVAL; | 3131 | ret = -EINVAL; |
2927 | } | 3132 | } |
2928 | 3133 | ||
3134 | mutex_unlock(&priv->mutex); | ||
2929 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3135 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2930 | 3136 | ||
2931 | return ret; | 3137 | return ret; |
@@ -2933,8 +3139,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2933 | 3139 | ||
2934 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 3140 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
2935 | struct ieee80211_vif *vif, | 3141 | struct ieee80211_vif *vif, |
2936 | enum ieee80211_ampdu_mlme_action action, | 3142 | enum ieee80211_ampdu_mlme_action action, |
2937 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 3143 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2938 | { | 3144 | { |
2939 | struct iwl_priv *priv = hw->priv; | 3145 | struct iwl_priv *priv = hw->priv; |
2940 | int ret; | 3146 | int ret; |
@@ -2948,20 +3154,31 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2948 | switch (action) { | 3154 | switch (action) { |
2949 | case IEEE80211_AMPDU_RX_START: | 3155 | case IEEE80211_AMPDU_RX_START: |
2950 | IWL_DEBUG_HT(priv, "start Rx\n"); | 3156 | IWL_DEBUG_HT(priv, "start Rx\n"); |
2951 | return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); | 3157 | return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); |
2952 | case IEEE80211_AMPDU_RX_STOP: | 3158 | case IEEE80211_AMPDU_RX_STOP: |
2953 | IWL_DEBUG_HT(priv, "stop Rx\n"); | 3159 | IWL_DEBUG_HT(priv, "stop Rx\n"); |
2954 | ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); | 3160 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
2955 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3161 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2956 | return 0; | 3162 | return 0; |
2957 | else | 3163 | else |
2958 | return ret; | 3164 | return ret; |
2959 | case IEEE80211_AMPDU_TX_START: | 3165 | case IEEE80211_AMPDU_TX_START: |
2960 | IWL_DEBUG_HT(priv, "start Tx\n"); | 3166 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2961 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 3167 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
3168 | if (ret == 0) { | ||
3169 | priv->_agn.agg_tids_count++; | ||
3170 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | ||
3171 | priv->_agn.agg_tids_count); | ||
3172 | } | ||
3173 | return ret; | ||
2962 | case IEEE80211_AMPDU_TX_STOP: | 3174 | case IEEE80211_AMPDU_TX_STOP: |
2963 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 3175 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2964 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); | 3176 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
3177 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { | ||
3178 | priv->_agn.agg_tids_count--; | ||
3179 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | ||
3180 | priv->_agn.agg_tids_count); | ||
3181 | } | ||
2965 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3182 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2966 | return 0; | 3183 | return 0; |
2967 | else | 3184 | else |
@@ -2977,18 +3194,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2977 | return 0; | 3194 | return 0; |
2978 | } | 3195 | } |
2979 | 3196 | ||
2980 | static int iwl_mac_get_stats(struct ieee80211_hw *hw, | ||
2981 | struct ieee80211_low_level_stats *stats) | ||
2982 | { | ||
2983 | struct iwl_priv *priv = hw->priv; | ||
2984 | |||
2985 | priv = hw->priv; | ||
2986 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2987 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2988 | |||
2989 | return 0; | ||
2990 | } | ||
2991 | |||
2992 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | 3197 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, |
2993 | struct ieee80211_vif *vif, | 3198 | struct ieee80211_vif *vif, |
2994 | enum sta_notify_cmd cmd, | 3199 | enum sta_notify_cmd cmd, |
@@ -2998,18 +3203,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
2998 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | 3203 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; |
2999 | int sta_id; | 3204 | int sta_id; |
3000 | 3205 | ||
3001 | /* | ||
3002 | * TODO: We really should use this callback to | ||
3003 | * actually maintain the station table in | ||
3004 | * the device. | ||
3005 | */ | ||
3006 | |||
3007 | switch (cmd) { | 3206 | switch (cmd) { |
3008 | case STA_NOTIFY_ADD: | ||
3009 | atomic_set(&sta_priv->pending_frames, 0); | ||
3010 | if (vif->type == NL80211_IFTYPE_AP) | ||
3011 | sta_priv->client = true; | ||
3012 | break; | ||
3013 | case STA_NOTIFY_SLEEP: | 3207 | case STA_NOTIFY_SLEEP: |
3014 | WARN_ON(!sta_priv->client); | 3208 | WARN_ON(!sta_priv->client); |
3015 | sta_priv->asleep = true; | 3209 | sta_priv->asleep = true; |
@@ -3021,7 +3215,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
3021 | if (!sta_priv->asleep) | 3215 | if (!sta_priv->asleep) |
3022 | break; | 3216 | break; |
3023 | sta_priv->asleep = false; | 3217 | sta_priv->asleep = false; |
3024 | sta_id = iwl_find_station(priv, sta->addr); | 3218 | sta_id = iwl_sta_id(sta); |
3025 | if (sta_id != IWL_INVALID_STATION) | 3219 | if (sta_id != IWL_INVALID_STATION) |
3026 | iwl_sta_modify_ps_wake(priv, sta_id); | 3220 | iwl_sta_modify_ps_wake(priv, sta_id); |
3027 | break; | 3221 | break; |
@@ -3030,6 +3224,44 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
3030 | } | 3224 | } |
3031 | } | 3225 | } |
3032 | 3226 | ||
3227 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | ||
3228 | struct ieee80211_vif *vif, | ||
3229 | struct ieee80211_sta *sta) | ||
3230 | { | ||
3231 | struct iwl_priv *priv = hw->priv; | ||
3232 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
3233 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | ||
3234 | int ret; | ||
3235 | u8 sta_id; | ||
3236 | |||
3237 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3238 | |||
3239 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | ||
3240 | sta->addr); | ||
3241 | |||
3242 | atomic_set(&sta_priv->pending_frames, 0); | ||
3243 | if (vif->type == NL80211_IFTYPE_AP) | ||
3244 | sta_priv->client = true; | ||
3245 | |||
3246 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, | ||
3247 | &sta_id); | ||
3248 | if (ret) { | ||
3249 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
3250 | sta->addr, ret); | ||
3251 | /* Should we return success if return code is EEXIST ? */ | ||
3252 | return ret; | ||
3253 | } | ||
3254 | |||
3255 | sta_priv->common.sta_id = sta_id; | ||
3256 | |||
3257 | /* Initialize rate scaling */ | ||
3258 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
3259 | sta->addr); | ||
3260 | iwl_rs_rate_init(priv, sta, sta_id); | ||
3261 | |||
3262 | return 0; | ||
3263 | } | ||
3264 | |||
3033 | /***************************************************************************** | 3265 | /***************************************************************************** |
3034 | * | 3266 | * |
3035 | * sysfs attributes | 3267 | * sysfs attributes |
@@ -3130,125 +3362,6 @@ static ssize_t store_tx_power(struct device *d, | |||
3130 | 3362 | ||
3131 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); | 3363 | static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); |
3132 | 3364 | ||
3133 | static ssize_t show_flags(struct device *d, | ||
3134 | struct device_attribute *attr, char *buf) | ||
3135 | { | ||
3136 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3137 | |||
3138 | return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); | ||
3139 | } | ||
3140 | |||
3141 | static ssize_t store_flags(struct device *d, | ||
3142 | struct device_attribute *attr, | ||
3143 | const char *buf, size_t count) | ||
3144 | { | ||
3145 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3146 | unsigned long val; | ||
3147 | u32 flags; | ||
3148 | int ret = strict_strtoul(buf, 0, &val); | ||
3149 | if (ret) | ||
3150 | return ret; | ||
3151 | flags = (u32)val; | ||
3152 | |||
3153 | mutex_lock(&priv->mutex); | ||
3154 | if (le32_to_cpu(priv->staging_rxon.flags) != flags) { | ||
3155 | /* Cancel any currently running scans... */ | ||
3156 | if (iwl_scan_cancel_timeout(priv, 100)) | ||
3157 | IWL_WARN(priv, "Could not cancel scan.\n"); | ||
3158 | else { | ||
3159 | IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); | ||
3160 | priv->staging_rxon.flags = cpu_to_le32(flags); | ||
3161 | iwlcore_commit_rxon(priv); | ||
3162 | } | ||
3163 | } | ||
3164 | mutex_unlock(&priv->mutex); | ||
3165 | |||
3166 | return count; | ||
3167 | } | ||
3168 | |||
3169 | static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); | ||
3170 | |||
3171 | static ssize_t show_filter_flags(struct device *d, | ||
3172 | struct device_attribute *attr, char *buf) | ||
3173 | { | ||
3174 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3175 | |||
3176 | return sprintf(buf, "0x%04X\n", | ||
3177 | le32_to_cpu(priv->active_rxon.filter_flags)); | ||
3178 | } | ||
3179 | |||
3180 | static ssize_t store_filter_flags(struct device *d, | ||
3181 | struct device_attribute *attr, | ||
3182 | const char *buf, size_t count) | ||
3183 | { | ||
3184 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3185 | unsigned long val; | ||
3186 | u32 filter_flags; | ||
3187 | int ret = strict_strtoul(buf, 0, &val); | ||
3188 | if (ret) | ||
3189 | return ret; | ||
3190 | filter_flags = (u32)val; | ||
3191 | |||
3192 | mutex_lock(&priv->mutex); | ||
3193 | if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { | ||
3194 | /* Cancel any currently running scans... */ | ||
3195 | if (iwl_scan_cancel_timeout(priv, 100)) | ||
3196 | IWL_WARN(priv, "Could not cancel scan.\n"); | ||
3197 | else { | ||
3198 | IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " | ||
3199 | "0x%04X\n", filter_flags); | ||
3200 | priv->staging_rxon.filter_flags = | ||
3201 | cpu_to_le32(filter_flags); | ||
3202 | iwlcore_commit_rxon(priv); | ||
3203 | } | ||
3204 | } | ||
3205 | mutex_unlock(&priv->mutex); | ||
3206 | |||
3207 | return count; | ||
3208 | } | ||
3209 | |||
3210 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | ||
3211 | store_filter_flags); | ||
3212 | |||
3213 | |||
3214 | static ssize_t show_statistics(struct device *d, | ||
3215 | struct device_attribute *attr, char *buf) | ||
3216 | { | ||
3217 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3218 | u32 size = sizeof(struct iwl_notif_statistics); | ||
3219 | u32 len = 0, ofs = 0; | ||
3220 | u8 *data = (u8 *)&priv->statistics; | ||
3221 | int rc = 0; | ||
3222 | |||
3223 | if (!iwl_is_alive(priv)) | ||
3224 | return -EAGAIN; | ||
3225 | |||
3226 | mutex_lock(&priv->mutex); | ||
3227 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
3228 | mutex_unlock(&priv->mutex); | ||
3229 | |||
3230 | if (rc) { | ||
3231 | len = sprintf(buf, | ||
3232 | "Error sending statistics request: 0x%08X\n", rc); | ||
3233 | return len; | ||
3234 | } | ||
3235 | |||
3236 | while (size && (PAGE_SIZE - len)) { | ||
3237 | hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, | ||
3238 | PAGE_SIZE - len, 1); | ||
3239 | len = strlen(buf); | ||
3240 | if (PAGE_SIZE - len) | ||
3241 | buf[len++] = '\n'; | ||
3242 | |||
3243 | ofs += 16; | ||
3244 | size -= min(size, 16U); | ||
3245 | } | ||
3246 | |||
3247 | return len; | ||
3248 | } | ||
3249 | |||
3250 | static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); | ||
3251 | |||
3252 | static ssize_t show_rts_ht_protection(struct device *d, | 3365 | static ssize_t show_rts_ht_protection(struct device *d, |
3253 | struct device_attribute *attr, char *buf) | 3366 | struct device_attribute *attr, char *buf) |
3254 | { | 3367 | { |
@@ -3316,6 +3429,13 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3316 | priv->ucode_trace.data = (unsigned long)priv; | 3429 | priv->ucode_trace.data = (unsigned long)priv; |
3317 | priv->ucode_trace.function = iwl_bg_ucode_trace; | 3430 | priv->ucode_trace.function = iwl_bg_ucode_trace; |
3318 | 3431 | ||
3432 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
3433 | init_timer(&priv->monitor_recover); | ||
3434 | priv->monitor_recover.data = (unsigned long)priv; | ||
3435 | priv->monitor_recover.function = | ||
3436 | priv->cfg->ops->lib->recover_from_tx_stall; | ||
3437 | } | ||
3438 | |||
3319 | if (!priv->cfg->use_isr_legacy) | 3439 | if (!priv->cfg->use_isr_legacy) |
3320 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3440 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3321 | iwl_irq_tasklet, (unsigned long)priv); | 3441 | iwl_irq_tasklet, (unsigned long)priv); |
@@ -3331,10 +3451,13 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3331 | 3451 | ||
3332 | cancel_delayed_work_sync(&priv->init_alive_start); | 3452 | cancel_delayed_work_sync(&priv->init_alive_start); |
3333 | cancel_delayed_work(&priv->scan_check); | 3453 | cancel_delayed_work(&priv->scan_check); |
3454 | cancel_work_sync(&priv->start_internal_scan); | ||
3334 | cancel_delayed_work(&priv->alive_start); | 3455 | cancel_delayed_work(&priv->alive_start); |
3335 | cancel_work_sync(&priv->beacon_update); | 3456 | cancel_work_sync(&priv->beacon_update); |
3336 | del_timer_sync(&priv->statistics_periodic); | 3457 | del_timer_sync(&priv->statistics_periodic); |
3337 | del_timer_sync(&priv->ucode_trace); | 3458 | del_timer_sync(&priv->ucode_trace); |
3459 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
3460 | del_timer_sync(&priv->monitor_recover); | ||
3338 | } | 3461 | } |
3339 | 3462 | ||
3340 | static void iwl_init_hw_rates(struct iwl_priv *priv, | 3463 | static void iwl_init_hw_rates(struct iwl_priv *priv, |
@@ -3372,9 +3495,6 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3372 | mutex_init(&priv->mutex); | 3495 | mutex_init(&priv->mutex); |
3373 | mutex_init(&priv->sync_cmd_mutex); | 3496 | mutex_init(&priv->sync_cmd_mutex); |
3374 | 3497 | ||
3375 | /* Clear the driver's (not device's) station table */ | ||
3376 | iwl_clear_stations_table(priv); | ||
3377 | |||
3378 | priv->ieee_channels = NULL; | 3498 | priv->ieee_channels = NULL; |
3379 | priv->ieee_rates = NULL; | 3499 | priv->ieee_rates = NULL; |
3380 | priv->band = IEEE80211_BAND_2GHZ; | 3500 | priv->band = IEEE80211_BAND_2GHZ; |
@@ -3382,6 +3502,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3382 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3502 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3383 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | 3503 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; |
3384 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3504 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3505 | priv->_agn.agg_tids_count = 0; | ||
3385 | 3506 | ||
3386 | /* initialize force reset */ | 3507 | /* initialize force reset */ |
3387 | priv->force_reset[IWL_RF_RESET].reset_duration = | 3508 | priv->force_reset[IWL_RF_RESET].reset_duration = |
@@ -3395,16 +3516,10 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3395 | 3516 | ||
3396 | iwl_init_scan_params(priv); | 3517 | iwl_init_scan_params(priv); |
3397 | 3518 | ||
3398 | iwl_reset_qos(priv); | ||
3399 | |||
3400 | priv->qos_data.qos_active = 0; | ||
3401 | priv->qos_data.qos_cap.val = 0; | ||
3402 | |||
3403 | priv->rates_mask = IWL_RATES_MASK; | ||
3404 | /* Set the tx_power_user_lmt to the lowest power level | 3519 | /* Set the tx_power_user_lmt to the lowest power level |
3405 | * this value will get overwritten by channel max power avg | 3520 | * this value will get overwritten by channel max power avg |
3406 | * from eeprom */ | 3521 | * from eeprom */ |
3407 | priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; | 3522 | priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; |
3408 | 3523 | ||
3409 | ret = iwl_init_channel_map(priv); | 3524 | ret = iwl_init_channel_map(priv); |
3410 | if (ret) { | 3525 | if (ret) { |
@@ -3432,13 +3547,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv) | |||
3432 | iwl_calib_free_results(priv); | 3547 | iwl_calib_free_results(priv); |
3433 | iwlcore_free_geos(priv); | 3548 | iwlcore_free_geos(priv); |
3434 | iwl_free_channel_map(priv); | 3549 | iwl_free_channel_map(priv); |
3435 | kfree(priv->scan); | 3550 | kfree(priv->scan_cmd); |
3436 | } | 3551 | } |
3437 | 3552 | ||
3438 | static struct attribute *iwl_sysfs_entries[] = { | 3553 | static struct attribute *iwl_sysfs_entries[] = { |
3439 | &dev_attr_flags.attr, | ||
3440 | &dev_attr_filter_flags.attr, | ||
3441 | &dev_attr_statistics.attr, | ||
3442 | &dev_attr_temperature.attr, | 3554 | &dev_attr_temperature.attr, |
3443 | &dev_attr_tx_power.attr, | 3555 | &dev_attr_tx_power.attr, |
3444 | &dev_attr_rts_ht_protection.attr, | 3556 | &dev_attr_rts_ht_protection.attr, |
@@ -3463,13 +3575,14 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3463 | .configure_filter = iwl_configure_filter, | 3575 | .configure_filter = iwl_configure_filter, |
3464 | .set_key = iwl_mac_set_key, | 3576 | .set_key = iwl_mac_set_key, |
3465 | .update_tkip_key = iwl_mac_update_tkip_key, | 3577 | .update_tkip_key = iwl_mac_update_tkip_key, |
3466 | .get_stats = iwl_mac_get_stats, | ||
3467 | .conf_tx = iwl_mac_conf_tx, | 3578 | .conf_tx = iwl_mac_conf_tx, |
3468 | .reset_tsf = iwl_mac_reset_tsf, | 3579 | .reset_tsf = iwl_mac_reset_tsf, |
3469 | .bss_info_changed = iwl_bss_info_changed, | 3580 | .bss_info_changed = iwl_bss_info_changed, |
3470 | .ampdu_action = iwl_mac_ampdu_action, | 3581 | .ampdu_action = iwl_mac_ampdu_action, |
3471 | .hw_scan = iwl_mac_hw_scan, | 3582 | .hw_scan = iwl_mac_hw_scan, |
3472 | .sta_notify = iwl_mac_sta_notify, | 3583 | .sta_notify = iwl_mac_sta_notify, |
3584 | .sta_add = iwlagn_mac_sta_add, | ||
3585 | .sta_remove = iwl_mac_sta_remove, | ||
3473 | }; | 3586 | }; |
3474 | 3587 | ||
3475 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3588 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3573,7 +3686,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3573 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | 3686 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
3574 | 3687 | ||
3575 | iwl_hw_detect(priv); | 3688 | iwl_hw_detect(priv); |
3576 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", | 3689 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", |
3577 | priv->cfg->name, priv->hw_rev); | 3690 | priv->cfg->name, priv->hw_rev); |
3578 | 3691 | ||
3579 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | 3692 | /* We disable the RETRY_TIMEOUT register (0x41) to keep |
@@ -3671,6 +3784,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3671 | iwl_power_initialize(priv); | 3784 | iwl_power_initialize(priv); |
3672 | iwl_tt_initialize(priv); | 3785 | iwl_tt_initialize(priv); |
3673 | 3786 | ||
3787 | init_completion(&priv->_agn.firmware_loading_complete); | ||
3788 | |||
3674 | err = iwl_request_firmware(priv, true); | 3789 | err = iwl_request_firmware(priv, true); |
3675 | if (err) | 3790 | if (err) |
3676 | goto out_remove_sysfs; | 3791 | goto out_remove_sysfs; |
@@ -3711,6 +3826,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3711 | if (!priv) | 3826 | if (!priv) |
3712 | return; | 3827 | return; |
3713 | 3828 | ||
3829 | wait_for_completion(&priv->_agn.firmware_loading_complete); | ||
3830 | |||
3714 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); | 3831 | IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); |
3715 | 3832 | ||
3716 | iwl_dbgfs_unregister(priv); | 3833 | iwl_dbgfs_unregister(priv); |
@@ -3751,10 +3868,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3751 | iwl_dealloc_ucode_pci(priv); | 3868 | iwl_dealloc_ucode_pci(priv); |
3752 | 3869 | ||
3753 | if (priv->rxq.bd) | 3870 | if (priv->rxq.bd) |
3754 | iwl_rx_queue_free(priv, &priv->rxq); | 3871 | iwlagn_rx_queue_free(priv, &priv->rxq); |
3755 | iwl_hw_txq_ctx_free(priv); | 3872 | iwlagn_hw_txq_ctx_free(priv); |
3756 | 3873 | ||
3757 | iwl_clear_stations_table(priv); | ||
3758 | iwl_eeprom_free(priv); | 3874 | iwl_eeprom_free(priv); |
3759 | 3875 | ||
3760 | 3876 | ||
@@ -3869,6 +3985,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3869 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | 3985 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, |
3870 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3986 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3871 | 3987 | ||
3988 | /* 6x00 Series Gen2a */ | ||
3989 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)}, | ||
3990 | {IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)}, | ||
3991 | {IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)}, | ||
3992 | |||
3872 | /* 6x50 WiFi/WiMax Series */ | 3993 | /* 6x50 WiFi/WiMax Series */ |
3873 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3994 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
3874 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, | 3995 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, |
@@ -3950,3 +4071,38 @@ module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); | |||
3950 | MODULE_PARM_DESC(debug, "debug output mask"); | 4071 | MODULE_PARM_DESC(debug, "debug output mask"); |
3951 | #endif | 4072 | #endif |
3952 | 4073 | ||
4074 | module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); | ||
4075 | MODULE_PARM_DESC(swcrypto50, | ||
4076 | "using crypto in software (default 0 [hardware]) (deprecated)"); | ||
4077 | module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); | ||
4078 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | ||
4079 | module_param_named(queues_num50, | ||
4080 | iwlagn_mod_params.num_of_queues, int, S_IRUGO); | ||
4081 | MODULE_PARM_DESC(queues_num50, | ||
4082 | "number of hw queues in 50xx series (deprecated)"); | ||
4083 | module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); | ||
4084 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
4085 | module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); | ||
4086 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); | ||
4087 | module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); | ||
4088 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
4089 | module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, | ||
4090 | int, S_IRUGO); | ||
4091 | MODULE_PARM_DESC(amsdu_size_8K50, | ||
4092 | "enable 8K amsdu size in 50XX series (deprecated)"); | ||
4093 | module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, | ||
4094 | int, S_IRUGO); | ||
4095 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | ||
4096 | module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); | ||
4097 | MODULE_PARM_DESC(fw_restart50, | ||
4098 | "restart firmware in case of error (deprecated)"); | ||
4099 | module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); | ||
4100 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | ||
4101 | module_param_named( | ||
4102 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); | ||
4103 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | ||
4104 | |||
4105 | module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int, | ||
4106 | S_IRUGO); | ||
4107 | MODULE_PARM_DESC(ucode_alternative, | ||
4108 | "specify ucode alternative to use from ucode file"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h new file mode 100644 index 000000000000..2d748053358e --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -0,0 +1,181 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | *****************************************************************************/ | ||
62 | |||
63 | #ifndef __iwl_agn_h__ | ||
64 | #define __iwl_agn_h__ | ||
65 | |||
66 | #include "iwl-dev.h" | ||
67 | |||
68 | extern struct iwl_mod_params iwlagn_mod_params; | ||
69 | extern struct iwl_hcmd_ops iwlagn_hcmd; | ||
70 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; | ||
71 | |||
72 | int iwl_reset_ict(struct iwl_priv *priv); | ||
73 | void iwl_disable_ict(struct iwl_priv *priv); | ||
74 | int iwl_alloc_isr_ict(struct iwl_priv *priv); | ||
75 | void iwl_free_isr_ict(struct iwl_priv *priv); | ||
76 | irqreturn_t iwl_isr_ict(int irq, void *data); | ||
77 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
78 | struct iwl_rx_packet *pkt); | ||
79 | |||
80 | /* tx queue */ | ||
81 | void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | ||
82 | int txq_id, u32 index); | ||
83 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | ||
84 | struct iwl_tx_queue *txq, | ||
85 | int tx_fifo_id, int scd_retry); | ||
86 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
87 | struct iwl_tx_queue *txq, | ||
88 | u16 byte_cnt); | ||
89 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
90 | struct iwl_tx_queue *txq); | ||
91 | int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
92 | int tx_fifo, int sta_id, int tid, u16 ssn_idx); | ||
93 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
94 | u16 ssn_idx, u8 tx_fifo); | ||
95 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); | ||
96 | |||
97 | /* uCode */ | ||
98 | int iwlagn_load_ucode(struct iwl_priv *priv); | ||
99 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
100 | struct iwl_rx_mem_buffer *rxb); | ||
101 | void iwlagn_rx_calib_complete(struct iwl_priv *priv, | ||
102 | struct iwl_rx_mem_buffer *rxb); | ||
103 | void iwlagn_init_alive_start(struct iwl_priv *priv); | ||
104 | int iwlagn_alive_notify(struct iwl_priv *priv); | ||
105 | |||
106 | /* lib */ | ||
107 | void iwl_check_abort_status(struct iwl_priv *priv, | ||
108 | u8 frame_count, u32 status); | ||
109 | void iwlagn_rx_handler_setup(struct iwl_priv *priv); | ||
110 | void iwlagn_setup_deferred_work(struct iwl_priv *priv); | ||
111 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); | ||
112 | int iwlagn_send_tx_power(struct iwl_priv *priv); | ||
113 | void iwlagn_temperature(struct iwl_priv *priv); | ||
114 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); | ||
115 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | ||
116 | size_t offset); | ||
117 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
118 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
119 | int iwlagn_hw_nic_init(struct iwl_priv *priv); | ||
120 | |||
121 | /* rx */ | ||
122 | void iwlagn_rx_queue_restock(struct iwl_priv *priv); | ||
123 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); | ||
124 | void iwlagn_rx_replenish(struct iwl_priv *priv); | ||
125 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); | ||
126 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
127 | int iwlagn_rxq_stop(struct iwl_priv *priv); | ||
128 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | ||
129 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
130 | struct iwl_rx_mem_buffer *rxb); | ||
131 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
132 | struct iwl_rx_mem_buffer *rxb); | ||
133 | |||
134 | /* tx */ | ||
135 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
136 | struct ieee80211_tx_info *info); | ||
137 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
138 | int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
139 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | ||
140 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
141 | struct ieee80211_sta *sta, u16 tid); | ||
142 | int iwlagn_txq_check_empty(struct iwl_priv *priv, | ||
143 | int sta_id, u8 tid, int txq_id); | ||
144 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
145 | struct iwl_rx_mem_buffer *rxb); | ||
146 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | ||
147 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); | ||
148 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); | ||
149 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv); | ||
150 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); | ||
151 | |||
152 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | ||
153 | { | ||
154 | status &= TX_STATUS_MSK; | ||
155 | |||
156 | switch (status) { | ||
157 | case TX_STATUS_SUCCESS: | ||
158 | case TX_STATUS_DIRECT_DONE: | ||
159 | return IEEE80211_TX_STAT_ACK; | ||
160 | case TX_STATUS_FAIL_DEST_PS: | ||
161 | return IEEE80211_TX_STAT_TX_FILTERED; | ||
162 | default: | ||
163 | return 0; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | static inline bool iwl_is_tx_success(u32 status) | ||
168 | { | ||
169 | status &= TX_STATUS_MSK; | ||
170 | return (status == TX_STATUS_SUCCESS) || | ||
171 | (status == TX_STATUS_DIRECT_DONE); | ||
172 | } | ||
173 | |||
174 | /* scan */ | ||
175 | void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
176 | |||
177 | /* station mgmt */ | ||
178 | int iwlagn_manage_ibss_station(struct iwl_priv *priv, | ||
179 | struct ieee80211_vif *vif, bool add); | ||
180 | |||
181 | #endif /* __iwl_agn_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 8b516c5ff0bb..7e8227773213 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -593,7 +593,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
593 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); | 593 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); |
594 | 594 | ||
595 | if (!rx_enable_time) { | 595 | if (!rx_enable_time) { |
596 | IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n"); | 596 | IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n"); |
597 | return; | 597 | return; |
598 | } | 598 | } |
599 | 599 | ||
@@ -638,8 +638,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
638 | iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); | 638 | iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); |
639 | iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); | 639 | iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); |
640 | iwl_sensitivity_write(priv); | 640 | iwl_sensitivity_write(priv); |
641 | |||
642 | return; | ||
643 | } | 641 | } |
644 | EXPORT_SYMBOL(iwl_sensitivity_calibration); | 642 | EXPORT_SYMBOL(iwl_sensitivity_calibration); |
645 | 643 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b3..9aab020c474b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -106,7 +106,7 @@ enum { | |||
106 | REPLY_TX = 0x1c, | 106 | REPLY_TX = 0x1c, |
107 | REPLY_RATE_SCALE = 0x47, /* 3945 only */ | 107 | REPLY_RATE_SCALE = 0x47, /* 3945 only */ |
108 | REPLY_LEDS_CMD = 0x48, | 108 | REPLY_LEDS_CMD = 0x48, |
109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ | 109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ |
110 | 110 | ||
111 | /* WiMAX coexistence */ | 111 | /* WiMAX coexistence */ |
112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ | 112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ |
@@ -512,8 +512,9 @@ struct iwl_init_alive_resp { | |||
512 | * | 512 | * |
513 | * Entries without timestamps contain only event_id and data. | 513 | * Entries without timestamps contain only event_id and data. |
514 | * | 514 | * |
515 | * | ||
515 | * 2) error_event_table_ptr indicates base of the error log. This contains | 516 | * 2) error_event_table_ptr indicates base of the error log. This contains |
516 | * information about any uCode error that occurs. For 4965, the format | 517 | * information about any uCode error that occurs. For agn, the format |
517 | * of the error log is: | 518 | * of the error log is: |
518 | * | 519 | * |
519 | * __le32 valid; (nonzero) valid, (0) log is empty | 520 | * __le32 valid; (nonzero) valid, (0) log is empty |
@@ -529,6 +530,30 @@ struct iwl_init_alive_resp { | |||
529 | * __le32 bcon_time; beacon timer | 530 | * __le32 bcon_time; beacon timer |
530 | * __le32 tsf_low; network timestamp function timer | 531 | * __le32 tsf_low; network timestamp function timer |
531 | * __le32 tsf_hi; network timestamp function timer | 532 | * __le32 tsf_hi; network timestamp function timer |
533 | * __le32 gp1; GP1 timer register | ||
534 | * __le32 gp2; GP2 timer register | ||
535 | * __le32 gp3; GP3 timer register | ||
536 | * __le32 ucode_ver; uCode version | ||
537 | * __le32 hw_ver; HW Silicon version | ||
538 | * __le32 brd_ver; HW board version | ||
539 | * __le32 log_pc; log program counter | ||
540 | * __le32 frame_ptr; frame pointer | ||
541 | * __le32 stack_ptr; stack pointer | ||
542 | * __le32 hcmd; last host command | ||
543 | * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag | ||
544 | * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag | ||
545 | * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag | ||
546 | * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag | ||
547 | * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt | ||
548 | * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT | ||
549 | * __le32 wait_event; wait event() caller address | ||
550 | * __le32 l2p_control; L2pControlField | ||
551 | * __le32 l2p_duration; L2pDurationField | ||
552 | * __le32 l2p_mhvalid; L2pMhValidBits | ||
553 | * __le32 l2p_addr_match; L2pAddrMatchStat | ||
554 | * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) | ||
555 | * __le32 u_timestamp; indicate when the date and time of the compilation | ||
556 | * __le32 reserved; | ||
532 | * | 557 | * |
533 | * The Linux driver can print both logs to the system log when a uCode error | 558 | * The Linux driver can print both logs to the system log when a uCode error |
534 | * occurs. | 559 | * occurs. |
@@ -1418,7 +1443,7 @@ struct iwl4965_rx_mpdu_res_start { | |||
1418 | 1443 | ||
1419 | /* 1: Ignore Bluetooth priority for this frame. | 1444 | /* 1: Ignore Bluetooth priority for this frame. |
1420 | * 0: Delay Tx until Bluetooth device is done (normal usage). */ | 1445 | * 0: Delay Tx until Bluetooth device is done (normal usage). */ |
1421 | #define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12) | 1446 | #define TX_CMD_FLG_IGNORE_BT cpu_to_le32(1 << 12) |
1422 | 1447 | ||
1423 | /* 1: uCode overrides sequence control field in MAC header. | 1448 | /* 1: uCode overrides sequence control field in MAC header. |
1424 | * 0: Driver provides sequence control field in MAC header. | 1449 | * 0: Driver provides sequence control field in MAC header. |
@@ -1637,7 +1662,7 @@ struct iwl_tx_cmd { | |||
1637 | struct ieee80211_hdr hdr[0]; | 1662 | struct ieee80211_hdr hdr[0]; |
1638 | } __attribute__ ((packed)); | 1663 | } __attribute__ ((packed)); |
1639 | 1664 | ||
1640 | /* TX command response is sent after *all* transmission attempts. | 1665 | /* TX command response is sent after *3945* transmission attempts. |
1641 | * | 1666 | * |
1642 | * NOTES: | 1667 | * NOTES: |
1643 | * | 1668 | * |
@@ -1665,24 +1690,65 @@ struct iwl_tx_cmd { | |||
1665 | * control line. Receiving is still allowed in this case. | 1690 | * control line. Receiving is still allowed in this case. |
1666 | */ | 1691 | */ |
1667 | enum { | 1692 | enum { |
1693 | TX_3945_STATUS_SUCCESS = 0x01, | ||
1694 | TX_3945_STATUS_DIRECT_DONE = 0x02, | ||
1695 | TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, | ||
1696 | TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, | ||
1697 | TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, | ||
1698 | TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, | ||
1699 | TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, | ||
1700 | TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, | ||
1701 | TX_3945_STATUS_FAIL_DEST_PS = 0x88, | ||
1702 | TX_3945_STATUS_FAIL_ABORTED = 0x89, | ||
1703 | TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, | ||
1704 | TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, | ||
1705 | TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, | ||
1706 | TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, | ||
1707 | TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, | ||
1708 | TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, | ||
1709 | TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, | ||
1710 | TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, | ||
1711 | }; | ||
1712 | |||
1713 | /* | ||
1714 | * TX command response is sent after *agn* transmission attempts. | ||
1715 | * | ||
1716 | * both postpone and abort status are expected behavior from uCode. there is | ||
1717 | * no special operation required from driver; except for RFKILL_FLUSH, | ||
1718 | * which required tx flush host command to flush all the tx frames in queues | ||
1719 | */ | ||
1720 | enum { | ||
1668 | TX_STATUS_SUCCESS = 0x01, | 1721 | TX_STATUS_SUCCESS = 0x01, |
1669 | TX_STATUS_DIRECT_DONE = 0x02, | 1722 | TX_STATUS_DIRECT_DONE = 0x02, |
1723 | /* postpone TX */ | ||
1724 | TX_STATUS_POSTPONE_DELAY = 0x40, | ||
1725 | TX_STATUS_POSTPONE_FEW_BYTES = 0x41, | ||
1726 | TX_STATUS_POSTPONE_BT_PRIO = 0x42, | ||
1727 | TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43, | ||
1728 | TX_STATUS_POSTPONE_CALC_TTAK = 0x44, | ||
1729 | /* abort TX */ | ||
1730 | TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81, | ||
1670 | TX_STATUS_FAIL_SHORT_LIMIT = 0x82, | 1731 | TX_STATUS_FAIL_SHORT_LIMIT = 0x82, |
1671 | TX_STATUS_FAIL_LONG_LIMIT = 0x83, | 1732 | TX_STATUS_FAIL_LONG_LIMIT = 0x83, |
1672 | TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, | 1733 | TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, |
1673 | TX_STATUS_FAIL_MGMNT_ABORT = 0x85, | 1734 | TX_STATUS_FAIL_DRAIN_FLOW = 0x85, |
1674 | TX_STATUS_FAIL_NEXT_FRAG = 0x86, | 1735 | TX_STATUS_FAIL_RFKILL_FLUSH = 0x86, |
1675 | TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, | 1736 | TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, |
1676 | TX_STATUS_FAIL_DEST_PS = 0x88, | 1737 | TX_STATUS_FAIL_DEST_PS = 0x88, |
1677 | TX_STATUS_FAIL_ABORTED = 0x89, | 1738 | TX_STATUS_FAIL_HOST_ABORTED = 0x89, |
1678 | TX_STATUS_FAIL_BT_RETRY = 0x8a, | 1739 | TX_STATUS_FAIL_BT_RETRY = 0x8a, |
1679 | TX_STATUS_FAIL_STA_INVALID = 0x8b, | 1740 | TX_STATUS_FAIL_STA_INVALID = 0x8b, |
1680 | TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, | 1741 | TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, |
1681 | TX_STATUS_FAIL_TID_DISABLE = 0x8d, | 1742 | TX_STATUS_FAIL_TID_DISABLE = 0x8d, |
1682 | TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e, | 1743 | TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e, |
1683 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, | 1744 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, |
1684 | TX_STATUS_FAIL_TX_LOCKED = 0x90, | 1745 | /* uCode drop due to FW drop request */ |
1685 | TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, | 1746 | TX_STATUS_FAIL_FW_DROP = 0x90, |
1747 | /* | ||
1748 | * uCode drop due to station color mismatch | ||
1749 | * between tx command and station table | ||
1750 | */ | ||
1751 | TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91, | ||
1686 | }; | 1752 | }; |
1687 | 1753 | ||
1688 | #define TX_PACKET_MODE_REGULAR 0x0000 | 1754 | #define TX_PACKET_MODE_REGULAR 0x0000 |
@@ -1704,30 +1770,6 @@ enum { | |||
1704 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ | 1770 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ |
1705 | }; | 1771 | }; |
1706 | 1772 | ||
1707 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | ||
1708 | { | ||
1709 | status &= TX_STATUS_MSK; | ||
1710 | |||
1711 | switch (status) { | ||
1712 | case TX_STATUS_SUCCESS: | ||
1713 | case TX_STATUS_DIRECT_DONE: | ||
1714 | return IEEE80211_TX_STAT_ACK; | ||
1715 | case TX_STATUS_FAIL_DEST_PS: | ||
1716 | return IEEE80211_TX_STAT_TX_FILTERED; | ||
1717 | default: | ||
1718 | return 0; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | static inline bool iwl_is_tx_success(u32 status) | ||
1723 | { | ||
1724 | status &= TX_STATUS_MSK; | ||
1725 | return (status == TX_STATUS_SUCCESS) || | ||
1726 | (status == TX_STATUS_DIRECT_DONE); | ||
1727 | } | ||
1728 | |||
1729 | |||
1730 | |||
1731 | /* ******************************* | 1773 | /* ******************************* |
1732 | * TX aggregation status | 1774 | * TX aggregation status |
1733 | ******************************* */ | 1775 | ******************************* */ |
@@ -2621,10 +2663,11 @@ struct iwl_ssid_ie { | |||
2621 | #define PROBE_OPTION_MAX_3945 4 | 2663 | #define PROBE_OPTION_MAX_3945 4 |
2622 | #define PROBE_OPTION_MAX 20 | 2664 | #define PROBE_OPTION_MAX 20 |
2623 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) | 2665 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) |
2624 | #define IWL_GOOD_CRC_TH cpu_to_le16(1) | 2666 | #define IWL_GOOD_CRC_TH_DISABLED 0 |
2667 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) | ||
2668 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) | ||
2625 | #define IWL_MAX_SCAN_SIZE 1024 | 2669 | #define IWL_MAX_SCAN_SIZE 1024 |
2626 | #define IWL_MAX_CMD_SIZE 4096 | 2670 | #define IWL_MAX_CMD_SIZE 4096 |
2627 | #define IWL_MAX_PROBE_REQUEST 200 | ||
2628 | 2671 | ||
2629 | /* | 2672 | /* |
2630 | * REPLY_SCAN_CMD = 0x80 (command) | 2673 | * REPLY_SCAN_CMD = 0x80 (command) |
@@ -3084,6 +3127,11 @@ struct statistics_tx { | |||
3084 | __le32 cts_timeout_collision; | 3127 | __le32 cts_timeout_collision; |
3085 | __le32 ack_or_ba_timeout_collision; | 3128 | __le32 ack_or_ba_timeout_collision; |
3086 | struct statistics_tx_non_phy_agg agg; | 3129 | struct statistics_tx_non_phy_agg agg; |
3130 | /* | ||
3131 | * "tx_power" are optional parameters provided by uCode, | ||
3132 | * 6000 series is the only device provide the information, | ||
3133 | * Those are reserved fields for all the other devices | ||
3134 | */ | ||
3087 | struct statistics_tx_power tx_power; | 3135 | struct statistics_tx_power tx_power; |
3088 | __le32 reserved1; | 3136 | __le32 reserved1; |
3089 | } __attribute__ ((packed)); | 3137 | } __attribute__ ((packed)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3352f7086632..5a7eca8fb789 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -66,38 +66,7 @@ MODULE_LICENSE("GPL"); | |||
66 | */ | 66 | */ |
67 | static bool bt_coex_active = true; | 67 | static bool bt_coex_active = true; |
68 | module_param(bt_coex_active, bool, S_IRUGO); | 68 | module_param(bt_coex_active, bool, S_IRUGO); |
69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); | 69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); |
70 | |||
71 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | ||
72 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | ||
73 | 0, COEX_UNASSOC_IDLE_FLAGS}, | ||
74 | {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, | ||
75 | 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, | ||
76 | {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, | ||
77 | 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, | ||
78 | {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, | ||
79 | 0, COEX_CALIBRATION_FLAGS}, | ||
80 | {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, | ||
81 | 0, COEX_PERIODIC_CALIBRATION_FLAGS}, | ||
82 | {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, | ||
83 | 0, COEX_CONNECTION_ESTAB_FLAGS}, | ||
84 | {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, | ||
85 | 0, COEX_ASSOCIATED_IDLE_FLAGS}, | ||
86 | {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, | ||
87 | 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, | ||
88 | {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, | ||
89 | 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, | ||
90 | {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, | ||
91 | 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, | ||
92 | {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, | ||
93 | {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, | ||
94 | {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, | ||
95 | 0, COEX_STAND_ALONE_DEBUG_FLAGS}, | ||
96 | {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, | ||
97 | 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, | ||
98 | {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, | ||
99 | {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} | ||
100 | }; | ||
101 | 70 | ||
102 | #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ | 71 | #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ |
103 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 72 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
@@ -115,8 +84,6 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | |||
115 | u32 iwl_debug_level; | 84 | u32 iwl_debug_level; |
116 | EXPORT_SYMBOL(iwl_debug_level); | 85 | EXPORT_SYMBOL(iwl_debug_level); |
117 | 86 | ||
118 | static irqreturn_t iwl_isr(int irq, void *data); | ||
119 | |||
120 | /* | 87 | /* |
121 | * Parameter order: | 88 | * Parameter order: |
122 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate | 89 | * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate |
@@ -143,30 +110,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { | |||
143 | }; | 110 | }; |
144 | EXPORT_SYMBOL(iwl_rates); | 111 | EXPORT_SYMBOL(iwl_rates); |
145 | 112 | ||
146 | /** | ||
147 | * translate ucode response to mac80211 tx status control values | ||
148 | */ | ||
149 | void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
150 | struct ieee80211_tx_info *info) | ||
151 | { | ||
152 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | ||
153 | |||
154 | info->antenna_sel_tx = | ||
155 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
156 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
157 | r->flags |= IEEE80211_TX_RC_MCS; | ||
158 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
159 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
160 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
161 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
162 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
163 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
164 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
165 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
166 | r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
167 | } | ||
168 | EXPORT_SYMBOL(iwl_hwrate_to_tx_control); | ||
169 | |||
170 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | 113 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) |
171 | { | 114 | { |
172 | int idx = 0; | 115 | int idx = 0; |
@@ -198,27 +141,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
198 | } | 141 | } |
199 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); | 142 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); |
200 | 143 | ||
201 | int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
202 | { | ||
203 | int idx = 0; | ||
204 | int band_offset = 0; | ||
205 | |||
206 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
207 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
208 | idx = (rate_n_flags & 0xff); | ||
209 | return idx; | ||
210 | /* Legacy rate format, search for match in table */ | ||
211 | } else { | ||
212 | if (band == IEEE80211_BAND_5GHZ) | ||
213 | band_offset = IWL_FIRST_OFDM_RATE; | ||
214 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
215 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
216 | return idx - band_offset; | ||
217 | } | ||
218 | |||
219 | return -1; | ||
220 | } | ||
221 | |||
222 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | 144 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) |
223 | { | 145 | { |
224 | int i; | 146 | int i; |
@@ -268,74 +190,16 @@ void iwl_hw_detect(struct iwl_priv *priv) | |||
268 | } | 190 | } |
269 | EXPORT_SYMBOL(iwl_hw_detect); | 191 | EXPORT_SYMBOL(iwl_hw_detect); |
270 | 192 | ||
271 | int iwl_hw_nic_init(struct iwl_priv *priv) | ||
272 | { | ||
273 | unsigned long flags; | ||
274 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
275 | int ret; | ||
276 | |||
277 | /* nic_init */ | ||
278 | spin_lock_irqsave(&priv->lock, flags); | ||
279 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
280 | |||
281 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
282 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
283 | |||
284 | spin_unlock_irqrestore(&priv->lock, flags); | ||
285 | |||
286 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
287 | |||
288 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
289 | |||
290 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
291 | if (!rxq->bd) { | ||
292 | ret = iwl_rx_queue_alloc(priv); | ||
293 | if (ret) { | ||
294 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
295 | return -ENOMEM; | ||
296 | } | ||
297 | } else | ||
298 | iwl_rx_queue_reset(priv, rxq); | ||
299 | |||
300 | iwl_rx_replenish(priv); | ||
301 | |||
302 | iwl_rx_init(priv, rxq); | ||
303 | |||
304 | spin_lock_irqsave(&priv->lock, flags); | ||
305 | |||
306 | rxq->need_update = 1; | ||
307 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
308 | |||
309 | spin_unlock_irqrestore(&priv->lock, flags); | ||
310 | |||
311 | /* Allocate or reset and init all Tx and Command queues */ | ||
312 | if (!priv->txq) { | ||
313 | ret = iwl_txq_ctx_alloc(priv); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | } else | ||
317 | iwl_txq_ctx_reset(priv); | ||
318 | |||
319 | set_bit(STATUS_INIT, &priv->status); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | EXPORT_SYMBOL(iwl_hw_nic_init); | ||
324 | |||
325 | /* | 193 | /* |
326 | * QoS support | 194 | * QoS support |
327 | */ | 195 | */ |
328 | void iwl_activate_qos(struct iwl_priv *priv, u8 force) | 196 | static void iwl_update_qos(struct iwl_priv *priv) |
329 | { | 197 | { |
330 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 198 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
331 | return; | 199 | return; |
332 | 200 | ||
333 | priv->qos_data.def_qos_parm.qos_flags = 0; | 201 | priv->qos_data.def_qos_parm.qos_flags = 0; |
334 | 202 | ||
335 | if (priv->qos_data.qos_cap.q_AP.queue_request && | ||
336 | !priv->qos_data.qos_cap.q_AP.txop_request) | ||
337 | priv->qos_data.def_qos_parm.qos_flags |= | ||
338 | QOS_PARAM_FLG_TXOP_TYPE_MSK; | ||
339 | if (priv->qos_data.qos_active) | 203 | if (priv->qos_data.qos_active) |
340 | priv->qos_data.def_qos_parm.qos_flags |= | 204 | priv->qos_data.def_qos_parm.qos_flags |= |
341 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | 205 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; |
@@ -343,118 +207,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force) | |||
343 | if (priv->current_ht_config.is_ht) | 207 | if (priv->current_ht_config.is_ht) |
344 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | 208 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; |
345 | 209 | ||
346 | if (force || iwl_is_associated(priv)) { | 210 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", |
347 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", | 211 | priv->qos_data.qos_active, |
348 | priv->qos_data.qos_active, | 212 | priv->qos_data.def_qos_parm.qos_flags); |
349 | priv->qos_data.def_qos_parm.qos_flags); | ||
350 | 213 | ||
351 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, | 214 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, |
352 | sizeof(struct iwl_qosparam_cmd), | 215 | sizeof(struct iwl_qosparam_cmd), |
353 | &priv->qos_data.def_qos_parm, NULL); | 216 | &priv->qos_data.def_qos_parm, NULL); |
354 | } | ||
355 | } | 217 | } |
356 | EXPORT_SYMBOL(iwl_activate_qos); | ||
357 | |||
358 | /* | ||
359 | * AC CWmin CW max AIFSN TXOP Limit TXOP Limit | ||
360 | * (802.11b) (802.11a/g) | ||
361 | * AC_BK 15 1023 7 0 0 | ||
362 | * AC_BE 15 1023 3 0 0 | ||
363 | * AC_VI 7 15 2 6.016ms 3.008ms | ||
364 | * AC_VO 3 7 2 3.264ms 1.504ms | ||
365 | */ | ||
366 | void iwl_reset_qos(struct iwl_priv *priv) | ||
367 | { | ||
368 | u16 cw_min = 15; | ||
369 | u16 cw_max = 1023; | ||
370 | u8 aifs = 2; | ||
371 | bool is_legacy = false; | ||
372 | unsigned long flags; | ||
373 | int i; | ||
374 | |||
375 | spin_lock_irqsave(&priv->lock, flags); | ||
376 | /* QoS always active in AP and ADHOC mode | ||
377 | * In STA mode wait for association | ||
378 | */ | ||
379 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC || | ||
380 | priv->iw_mode == NL80211_IFTYPE_AP) | ||
381 | priv->qos_data.qos_active = 1; | ||
382 | else | ||
383 | priv->qos_data.qos_active = 0; | ||
384 | |||
385 | /* check for legacy mode */ | ||
386 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && | ||
387 | (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || | ||
388 | (priv->iw_mode == NL80211_IFTYPE_STATION && | ||
389 | (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { | ||
390 | cw_min = 31; | ||
391 | is_legacy = 1; | ||
392 | } | ||
393 | |||
394 | if (priv->qos_data.qos_active) | ||
395 | aifs = 3; | ||
396 | |||
397 | /* AC_BE */ | ||
398 | priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); | ||
399 | priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); | ||
400 | priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; | ||
401 | priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; | ||
402 | priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; | ||
403 | |||
404 | if (priv->qos_data.qos_active) { | ||
405 | /* AC_BK */ | ||
406 | i = 1; | ||
407 | priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); | ||
408 | priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); | ||
409 | priv->qos_data.def_qos_parm.ac[i].aifsn = 7; | ||
410 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | ||
411 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
412 | |||
413 | /* AC_VI */ | ||
414 | i = 2; | ||
415 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
416 | cpu_to_le16((cw_min + 1) / 2 - 1); | ||
417 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
418 | cpu_to_le16(cw_min); | ||
419 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | ||
420 | if (is_legacy) | ||
421 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
422 | cpu_to_le16(6016); | ||
423 | else | ||
424 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
425 | cpu_to_le16(3008); | ||
426 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
427 | |||
428 | /* AC_VO */ | ||
429 | i = 3; | ||
430 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
431 | cpu_to_le16((cw_min + 1) / 4 - 1); | ||
432 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
433 | cpu_to_le16((cw_min + 1) / 2 - 1); | ||
434 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | ||
435 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
436 | if (is_legacy) | ||
437 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
438 | cpu_to_le16(3264); | ||
439 | else | ||
440 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
441 | cpu_to_le16(1504); | ||
442 | } else { | ||
443 | for (i = 1; i < 4; i++) { | ||
444 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
445 | cpu_to_le16(cw_min); | ||
446 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
447 | cpu_to_le16(cw_max); | ||
448 | priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; | ||
449 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | ||
450 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
451 | } | ||
452 | } | ||
453 | IWL_DEBUG_QOS(priv, "set QoS to default \n"); | ||
454 | |||
455 | spin_unlock_irqrestore(&priv->lock, flags); | ||
456 | } | ||
457 | EXPORT_SYMBOL(iwl_reset_qos); | ||
458 | 218 | ||
459 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | 219 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |
460 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | 220 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ |
@@ -721,7 +481,7 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | |||
721 | return new_val; | 481 | return new_val; |
722 | } | 482 | } |
723 | 483 | ||
724 | void iwl_setup_rxon_timing(struct iwl_priv *priv) | 484 | void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) |
725 | { | 485 | { |
726 | u64 tsf; | 486 | u64 tsf; |
727 | s32 interval_tm, rem; | 487 | s32 interval_tm, rem; |
@@ -735,15 +495,14 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv) | |||
735 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); | 495 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); |
736 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); | 496 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); |
737 | 497 | ||
738 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | 498 | beacon_int = vif->bss_conf.beacon_int; |
739 | beacon_int = priv->beacon_int; | ||
740 | priv->rxon_timing.atim_window = 0; | ||
741 | } else { | ||
742 | beacon_int = priv->vif->bss_conf.beacon_int; | ||
743 | 499 | ||
500 | if (vif->type == NL80211_IFTYPE_ADHOC) { | ||
744 | /* TODO: we need to get atim_window from upper stack | 501 | /* TODO: we need to get atim_window from upper stack |
745 | * for now we set to 0 */ | 502 | * for now we set to 0 */ |
746 | priv->rxon_timing.atim_window = 0; | 503 | priv->rxon_timing.atim_window = 0; |
504 | } else { | ||
505 | priv->rxon_timing.atim_window = 0; | ||
747 | } | 506 | } |
748 | 507 | ||
749 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | 508 | beacon_int = iwl_adjust_beacon_interval(beacon_int, |
@@ -903,23 +662,10 @@ EXPORT_SYMBOL(iwl_full_rxon_required); | |||
903 | 662 | ||
904 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) | 663 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) |
905 | { | 664 | { |
906 | int i; | 665 | /* |
907 | int rate_mask; | 666 | * Assign the lowest rate -- should really get this from |
908 | 667 | * the beacon skb from mac80211. | |
909 | /* Set rate mask*/ | 668 | */ |
910 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
911 | rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; | ||
912 | else | ||
913 | rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; | ||
914 | |||
915 | /* Find lowest valid rate */ | ||
916 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; | ||
917 | i = iwl_rates[i].next_ieee) { | ||
918 | if (rate_mask & (1 << i)) | ||
919 | return iwl_rates[i].plcp; | ||
920 | } | ||
921 | |||
922 | /* No valid rate was found. Assign the lowest one */ | ||
923 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | 669 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) |
924 | return IWL_RATE_1M_PLCP; | 670 | return IWL_RATE_1M_PLCP; |
925 | else | 671 | else |
@@ -991,7 +737,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | |||
991 | "extension channel offset 0x%x\n", | 737 | "extension channel offset 0x%x\n", |
992 | le32_to_cpu(rxon->flags), ht_conf->ht_protection, | 738 | le32_to_cpu(rxon->flags), ht_conf->ht_protection, |
993 | ht_conf->extension_chan_offset); | 739 | ht_conf->extension_chan_offset); |
994 | return; | ||
995 | } | 740 | } |
996 | EXPORT_SYMBOL(iwl_set_rxon_ht); | 741 | EXPORT_SYMBOL(iwl_set_rxon_ht); |
997 | 742 | ||
@@ -1051,19 +796,6 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) | |||
1051 | } | 796 | } |
1052 | 797 | ||
1053 | /** | 798 | /** |
1054 | * iwl_is_monitor_mode - Determine if interface in monitor mode | ||
1055 | * | ||
1056 | * priv->iw_mode is set in add_interface, but add_interface is | ||
1057 | * never called for monitor mode. The only way mac80211 informs us about | ||
1058 | * monitor mode is through configuring filters (call to configure_filter). | ||
1059 | */ | ||
1060 | bool iwl_is_monitor_mode(struct iwl_priv *priv) | ||
1061 | { | ||
1062 | return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); | ||
1063 | } | ||
1064 | EXPORT_SYMBOL(iwl_is_monitor_mode); | ||
1065 | |||
1066 | /** | ||
1067 | * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image | 799 | * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image |
1068 | * | 800 | * |
1069 | * Selects how many and which Rx receivers/antennas/chains to use. | 801 | * Selects how many and which Rx receivers/antennas/chains to use. |
@@ -1106,19 +838,6 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
1106 | rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; | 838 | rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; |
1107 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; | 839 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; |
1108 | 840 | ||
1109 | /* copied from 'iwl_bg_request_scan()' */ | ||
1110 | /* Force use of chains B and C (0x6) for Rx for 4965 | ||
1111 | * Avoid A (0x1) because of its off-channel reception on A-band. | ||
1112 | * MIMO is not used here, but value is required */ | ||
1113 | if (iwl_is_monitor_mode(priv) && | ||
1114 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && | ||
1115 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { | ||
1116 | rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; | ||
1117 | rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; | ||
1118 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||
1119 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||
1120 | } | ||
1121 | |||
1122 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); | 841 | priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); |
1123 | 842 | ||
1124 | if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) | 843 | if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) |
@@ -1174,8 +893,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | |||
1174 | } | 893 | } |
1175 | EXPORT_SYMBOL(iwl_set_rxon_channel); | 894 | EXPORT_SYMBOL(iwl_set_rxon_channel); |
1176 | 895 | ||
1177 | void iwl_set_flags_for_band(struct iwl_priv *priv, | 896 | static void iwl_set_flags_for_band(struct iwl_priv *priv, |
1178 | enum ieee80211_band band) | 897 | enum ieee80211_band band, |
898 | struct ieee80211_vif *vif) | ||
1179 | { | 899 | { |
1180 | if (band == IEEE80211_BAND_5GHZ) { | 900 | if (band == IEEE80211_BAND_5GHZ) { |
1181 | priv->staging_rxon.flags &= | 901 | priv->staging_rxon.flags &= |
@@ -1184,12 +904,12 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, | |||
1184 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 904 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
1185 | } else { | 905 | } else { |
1186 | /* Copied from iwl_post_associate() */ | 906 | /* Copied from iwl_post_associate() */ |
1187 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 907 | if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) |
1188 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 908 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
1189 | else | 909 | else |
1190 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 910 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
1191 | 911 | ||
1192 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 912 | if (vif && vif->type == NL80211_IFTYPE_ADHOC) |
1193 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 913 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
1194 | 914 | ||
1195 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; | 915 | priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; |
@@ -1201,13 +921,18 @@ void iwl_set_flags_for_band(struct iwl_priv *priv, | |||
1201 | /* | 921 | /* |
1202 | * initialize rxon structure with default values from eeprom | 922 | * initialize rxon structure with default values from eeprom |
1203 | */ | 923 | */ |
1204 | void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) | 924 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
925 | struct ieee80211_vif *vif) | ||
1205 | { | 926 | { |
1206 | const struct iwl_channel_info *ch_info; | 927 | const struct iwl_channel_info *ch_info; |
928 | enum nl80211_iftype type = NL80211_IFTYPE_STATION; | ||
929 | |||
930 | if (vif) | ||
931 | type = vif->type; | ||
1207 | 932 | ||
1208 | memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); | 933 | memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); |
1209 | 934 | ||
1210 | switch (mode) { | 935 | switch (type) { |
1211 | case NL80211_IFTYPE_AP: | 936 | case NL80211_IFTYPE_AP: |
1212 | priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; | 937 | priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; |
1213 | break; | 938 | break; |
@@ -1225,7 +950,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) | |||
1225 | break; | 950 | break; |
1226 | 951 | ||
1227 | default: | 952 | default: |
1228 | IWL_ERR(priv, "Unsupported interface type %d\n", mode); | 953 | IWL_ERR(priv, "Unsupported interface type %d\n", type); |
1229 | break; | 954 | break; |
1230 | } | 955 | } |
1231 | 956 | ||
@@ -1244,18 +969,10 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) | |||
1244 | if (!ch_info) | 969 | if (!ch_info) |
1245 | ch_info = &priv->channel_info[0]; | 970 | ch_info = &priv->channel_info[0]; |
1246 | 971 | ||
1247 | /* | ||
1248 | * in some case A channels are all non IBSS | ||
1249 | * in this case force B/G channel | ||
1250 | */ | ||
1251 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | ||
1252 | !(is_channel_ibss(ch_info))) | ||
1253 | ch_info = &priv->channel_info[0]; | ||
1254 | |||
1255 | priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); | 972 | priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); |
1256 | priv->band = ch_info->band; | 973 | priv->band = ch_info->band; |
1257 | 974 | ||
1258 | iwl_set_flags_for_band(priv, priv->band); | 975 | iwl_set_flags_for_band(priv, priv->band, vif); |
1259 | 976 | ||
1260 | priv->staging_rxon.ofdm_basic_rates = | 977 | priv->staging_rxon.ofdm_basic_rates = |
1261 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 978 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
@@ -1286,7 +1003,6 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1286 | } | 1003 | } |
1287 | 1004 | ||
1288 | priv->active_rate = 0; | 1005 | priv->active_rate = 0; |
1289 | priv->active_rate_basic = 0; | ||
1290 | 1006 | ||
1291 | for (i = 0; i < hw->n_bitrates; i++) { | 1007 | for (i = 0; i < hw->n_bitrates; i++) { |
1292 | rate = &(hw->bitrates[i]); | 1008 | rate = &(hw->bitrates[i]); |
@@ -1294,30 +1010,13 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1294 | priv->active_rate |= (1 << rate->hw_value); | 1010 | priv->active_rate |= (1 << rate->hw_value); |
1295 | } | 1011 | } |
1296 | 1012 | ||
1297 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n", | 1013 | IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); |
1298 | priv->active_rate, priv->active_rate_basic); | ||
1299 | 1014 | ||
1300 | /* | 1015 | priv->staging_rxon.cck_basic_rates = |
1301 | * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) | 1016 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; |
1302 | * otherwise set it to the default of all CCK rates and 6, 12, 24 for | 1017 | |
1303 | * OFDM | 1018 | priv->staging_rxon.ofdm_basic_rates = |
1304 | */ | 1019 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
1305 | if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) | ||
1306 | priv->staging_rxon.cck_basic_rates = | ||
1307 | ((priv->active_rate_basic & | ||
1308 | IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; | ||
1309 | else | ||
1310 | priv->staging_rxon.cck_basic_rates = | ||
1311 | (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; | ||
1312 | |||
1313 | if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) | ||
1314 | priv->staging_rxon.ofdm_basic_rates = | ||
1315 | ((priv->active_rate_basic & | ||
1316 | (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> | ||
1317 | IWL_FIRST_OFDM_RATE) & 0xFF; | ||
1318 | else | ||
1319 | priv->staging_rxon.ofdm_basic_rates = | ||
1320 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | ||
1321 | } | 1020 | } |
1322 | 1021 | ||
1323 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1022 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
@@ -1374,6 +1073,9 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1374 | /* Cancel currently queued command. */ | 1073 | /* Cancel currently queued command. */ |
1375 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1074 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1376 | 1075 | ||
1076 | IWL_ERR(priv, "Loaded firmware version: %s\n", | ||
1077 | priv->hw->wiphy->fw_version); | ||
1078 | |||
1377 | priv->cfg->ops->lib->dump_nic_error_log(priv); | 1079 | priv->cfg->ops->lib->dump_nic_error_log(priv); |
1378 | if (priv->cfg->ops->lib->dump_csr) | 1080 | if (priv->cfg->ops->lib->dump_csr) |
1379 | priv->cfg->ops->lib->dump_csr(priv); | 1081 | priv->cfg->ops->lib->dump_csr(priv); |
@@ -1401,7 +1103,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1401 | } | 1103 | } |
1402 | EXPORT_SYMBOL(iwl_irq_handle_error); | 1104 | EXPORT_SYMBOL(iwl_irq_handle_error); |
1403 | 1105 | ||
1404 | int iwl_apm_stop_master(struct iwl_priv *priv) | 1106 | static int iwl_apm_stop_master(struct iwl_priv *priv) |
1405 | { | 1107 | { |
1406 | int ret = 0; | 1108 | int ret = 0; |
1407 | 1109 | ||
@@ -1417,7 +1119,6 @@ int iwl_apm_stop_master(struct iwl_priv *priv) | |||
1417 | 1119 | ||
1418 | return ret; | 1120 | return ret; |
1419 | } | 1121 | } |
1420 | EXPORT_SYMBOL(iwl_apm_stop_master); | ||
1421 | 1122 | ||
1422 | void iwl_apm_stop(struct iwl_priv *priv) | 1123 | void iwl_apm_stop(struct iwl_priv *priv) |
1423 | { | 1124 | { |
@@ -1561,41 +1262,33 @@ void iwl_configure_filter(struct ieee80211_hw *hw, | |||
1561 | u64 multicast) | 1262 | u64 multicast) |
1562 | { | 1263 | { |
1563 | struct iwl_priv *priv = hw->priv; | 1264 | struct iwl_priv *priv = hw->priv; |
1564 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; | 1265 | __le32 filter_or = 0, filter_nand = 0; |
1266 | |||
1267 | #define CHK(test, flag) do { \ | ||
1268 | if (*total_flags & (test)) \ | ||
1269 | filter_or |= (flag); \ | ||
1270 | else \ | ||
1271 | filter_nand |= (flag); \ | ||
1272 | } while (0) | ||
1565 | 1273 | ||
1566 | IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", | 1274 | IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", |
1567 | changed_flags, *total_flags); | 1275 | changed_flags, *total_flags); |
1568 | 1276 | ||
1569 | if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { | 1277 | CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); |
1570 | if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) | 1278 | CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK); |
1571 | *filter_flags |= RXON_FILTER_PROMISC_MSK; | 1279 | CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); |
1572 | else | 1280 | CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); |
1573 | *filter_flags &= ~RXON_FILTER_PROMISC_MSK; | ||
1574 | } | ||
1575 | if (changed_flags & FIF_ALLMULTI) { | ||
1576 | if (*total_flags & FIF_ALLMULTI) | ||
1577 | *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; | ||
1578 | else | ||
1579 | *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; | ||
1580 | } | ||
1581 | if (changed_flags & FIF_CONTROL) { | ||
1582 | if (*total_flags & FIF_CONTROL) | ||
1583 | *filter_flags |= RXON_FILTER_CTL2HOST_MSK; | ||
1584 | else | ||
1585 | *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; | ||
1586 | } | ||
1587 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
1588 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
1589 | *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; | ||
1590 | else | ||
1591 | *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; | ||
1592 | } | ||
1593 | 1281 | ||
1594 | /* We avoid iwl_commit_rxon here to commit the new filter flags | 1282 | #undef CHK |
1595 | * since mac80211 will call ieee80211_hw_config immediately. | 1283 | |
1596 | * (mc_list is not supported at this time). Otherwise, we need to | 1284 | mutex_lock(&priv->mutex); |
1597 | * queue a background iwl_commit_rxon work. | 1285 | |
1598 | */ | 1286 | priv->staging_rxon.filter_flags &= ~filter_nand; |
1287 | priv->staging_rxon.filter_flags |= filter_or; | ||
1288 | |||
1289 | iwlcore_commit_rxon(priv); | ||
1290 | |||
1291 | mutex_unlock(&priv->mutex); | ||
1599 | 1292 | ||
1600 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | | 1293 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | |
1601 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 1294 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
@@ -1626,10 +1319,11 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1626 | int ret = 0; | 1319 | int ret = 0; |
1627 | s8 prev_tx_power = priv->tx_power_user_lmt; | 1320 | s8 prev_tx_power = priv->tx_power_user_lmt; |
1628 | 1321 | ||
1629 | if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { | 1322 | if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { |
1630 | IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n", | 1323 | IWL_WARN(priv, |
1324 | "Requested user TXPOWER %d below lower limit %d.\n", | ||
1631 | tx_power, | 1325 | tx_power, |
1632 | IWL_TX_POWER_TARGET_POWER_MIN); | 1326 | IWLAGN_TX_POWER_TARGET_POWER_MIN); |
1633 | return -EINVAL; | 1327 | return -EINVAL; |
1634 | } | 1328 | } |
1635 | 1329 | ||
@@ -1668,286 +1362,16 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1668 | } | 1362 | } |
1669 | EXPORT_SYMBOL(iwl_set_tx_power); | 1363 | EXPORT_SYMBOL(iwl_set_tx_power); |
1670 | 1364 | ||
1671 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | ||
1672 | |||
1673 | /* Free dram table */ | ||
1674 | void iwl_free_isr_ict(struct iwl_priv *priv) | ||
1675 | { | ||
1676 | if (priv->ict_tbl_vir) { | ||
1677 | dma_free_coherent(&priv->pci_dev->dev, | ||
1678 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
1679 | priv->ict_tbl_vir, priv->ict_tbl_dma); | ||
1680 | priv->ict_tbl_vir = NULL; | ||
1681 | } | ||
1682 | } | ||
1683 | EXPORT_SYMBOL(iwl_free_isr_ict); | ||
1684 | |||
1685 | |||
1686 | /* allocate dram shared table it is a PAGE_SIZE aligned | ||
1687 | * also reset all data related to ICT table interrupt. | ||
1688 | */ | ||
1689 | int iwl_alloc_isr_ict(struct iwl_priv *priv) | ||
1690 | { | ||
1691 | |||
1692 | if (priv->cfg->use_isr_legacy) | ||
1693 | return 0; | ||
1694 | /* allocate shrared data table */ | ||
1695 | priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, | ||
1696 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, | ||
1697 | &priv->ict_tbl_dma, GFP_KERNEL); | ||
1698 | if (!priv->ict_tbl_vir) | ||
1699 | return -ENOMEM; | ||
1700 | |||
1701 | /* align table to PAGE_SIZE boundry */ | ||
1702 | priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); | ||
1703 | |||
1704 | IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", | ||
1705 | (unsigned long long)priv->ict_tbl_dma, | ||
1706 | (unsigned long long)priv->aligned_ict_tbl_dma, | ||
1707 | (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); | ||
1708 | |||
1709 | priv->ict_tbl = priv->ict_tbl_vir + | ||
1710 | (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); | ||
1711 | |||
1712 | IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", | ||
1713 | priv->ict_tbl, priv->ict_tbl_vir, | ||
1714 | (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); | ||
1715 | |||
1716 | /* reset table and index to all 0 */ | ||
1717 | memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); | ||
1718 | priv->ict_index = 0; | ||
1719 | |||
1720 | /* add periodic RX interrupt */ | ||
1721 | priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; | ||
1722 | return 0; | ||
1723 | } | ||
1724 | EXPORT_SYMBOL(iwl_alloc_isr_ict); | ||
1725 | |||
1726 | /* Device is going up inform it about using ICT interrupt table, | ||
1727 | * also we need to tell the driver to start using ICT interrupt. | ||
1728 | */ | ||
1729 | int iwl_reset_ict(struct iwl_priv *priv) | ||
1730 | { | ||
1731 | u32 val; | ||
1732 | unsigned long flags; | ||
1733 | |||
1734 | if (!priv->ict_tbl_vir) | ||
1735 | return 0; | ||
1736 | |||
1737 | spin_lock_irqsave(&priv->lock, flags); | ||
1738 | iwl_disable_interrupts(priv); | ||
1739 | |||
1740 | memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); | ||
1741 | |||
1742 | val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; | ||
1743 | |||
1744 | val |= CSR_DRAM_INT_TBL_ENABLE; | ||
1745 | val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; | ||
1746 | |||
1747 | IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " | ||
1748 | "aligned dma address %Lx\n", | ||
1749 | val, (unsigned long long)priv->aligned_ict_tbl_dma); | ||
1750 | |||
1751 | iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); | ||
1752 | priv->use_ict = true; | ||
1753 | priv->ict_index = 0; | ||
1754 | iwl_write32(priv, CSR_INT, priv->inta_mask); | ||
1755 | iwl_enable_interrupts(priv); | ||
1756 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1757 | |||
1758 | return 0; | ||
1759 | } | ||
1760 | EXPORT_SYMBOL(iwl_reset_ict); | ||
1761 | |||
1762 | /* Device is going down disable ict interrupt usage */ | ||
1763 | void iwl_disable_ict(struct iwl_priv *priv) | ||
1764 | { | ||
1765 | unsigned long flags; | ||
1766 | |||
1767 | spin_lock_irqsave(&priv->lock, flags); | ||
1768 | priv->use_ict = false; | ||
1769 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1770 | } | ||
1771 | EXPORT_SYMBOL(iwl_disable_ict); | ||
1772 | |||
1773 | /* interrupt handler using ict table, with this interrupt driver will | ||
1774 | * stop using INTA register to get device's interrupt, reading this register | ||
1775 | * is expensive, device will write interrupts in ICT dram table, increment | ||
1776 | * index then will fire interrupt to driver, driver will OR all ICT table | ||
1777 | * entries from current index up to table entry with 0 value. the result is | ||
1778 | * the interrupt we need to service, driver will set the entries back to 0 and | ||
1779 | * set index. | ||
1780 | */ | ||
1781 | irqreturn_t iwl_isr_ict(int irq, void *data) | ||
1782 | { | ||
1783 | struct iwl_priv *priv = data; | ||
1784 | u32 inta, inta_mask; | ||
1785 | u32 val = 0; | ||
1786 | |||
1787 | if (!priv) | ||
1788 | return IRQ_NONE; | ||
1789 | |||
1790 | /* dram interrupt table not set yet, | ||
1791 | * use legacy interrupt. | ||
1792 | */ | ||
1793 | if (!priv->use_ict) | ||
1794 | return iwl_isr(irq, data); | ||
1795 | |||
1796 | spin_lock(&priv->lock); | ||
1797 | |||
1798 | /* Disable (but don't clear!) interrupts here to avoid | ||
1799 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
1800 | * If we have something to service, the tasklet will re-enable ints. | ||
1801 | * If we *don't* have something, we'll re-enable before leaving here. | ||
1802 | */ | ||
1803 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
1804 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1805 | |||
1806 | |||
1807 | /* Ignore interrupt if there's nothing in NIC to service. | ||
1808 | * This may be due to IRQ shared with another device, | ||
1809 | * or due to sporadic interrupts thrown from our NIC. */ | ||
1810 | if (!priv->ict_tbl[priv->ict_index]) { | ||
1811 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
1812 | goto none; | ||
1813 | } | ||
1814 | |||
1815 | /* read all entries that not 0 start with ict_index */ | ||
1816 | while (priv->ict_tbl[priv->ict_index]) { | ||
1817 | |||
1818 | val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); | ||
1819 | IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", | ||
1820 | priv->ict_index, | ||
1821 | le32_to_cpu(priv->ict_tbl[priv->ict_index])); | ||
1822 | priv->ict_tbl[priv->ict_index] = 0; | ||
1823 | priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, | ||
1824 | ICT_COUNT); | ||
1825 | |||
1826 | } | ||
1827 | |||
1828 | /* We should not get this value, just ignore it. */ | ||
1829 | if (val == 0xffffffff) | ||
1830 | val = 0; | ||
1831 | |||
1832 | /* | ||
1833 | * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit | ||
1834 | * (bit 15 before shifting it to 31) to clear when using interrupt | ||
1835 | * coalescing. fortunately, bits 18 and 19 stay set when this happens | ||
1836 | * so we use them to decide on the real state of the Rx bit. | ||
1837 | * In order words, bit 15 is set if bit 18 or bit 19 are set. | ||
1838 | */ | ||
1839 | if (val & 0xC0000) | ||
1840 | val |= 0x8000; | ||
1841 | |||
1842 | inta = (0xff & val) | ((0xff00 & val) << 16); | ||
1843 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | ||
1844 | inta, inta_mask, val); | ||
1845 | |||
1846 | inta &= priv->inta_mask; | ||
1847 | priv->inta |= inta; | ||
1848 | |||
1849 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
1850 | if (likely(inta)) | ||
1851 | tasklet_schedule(&priv->irq_tasklet); | ||
1852 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { | ||
1853 | /* Allow interrupt if was disabled by this handler and | ||
1854 | * no tasklet was schedules, We should not enable interrupt, | ||
1855 | * tasklet will enable it. | ||
1856 | */ | ||
1857 | iwl_enable_interrupts(priv); | ||
1858 | } | ||
1859 | |||
1860 | spin_unlock(&priv->lock); | ||
1861 | return IRQ_HANDLED; | ||
1862 | |||
1863 | none: | ||
1864 | /* re-enable interrupts here since we don't have anything to service. | ||
1865 | * only Re-enable if disabled by irq. | ||
1866 | */ | ||
1867 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1868 | iwl_enable_interrupts(priv); | ||
1869 | |||
1870 | spin_unlock(&priv->lock); | ||
1871 | return IRQ_NONE; | ||
1872 | } | ||
1873 | EXPORT_SYMBOL(iwl_isr_ict); | ||
1874 | |||
1875 | |||
1876 | static irqreturn_t iwl_isr(int irq, void *data) | ||
1877 | { | ||
1878 | struct iwl_priv *priv = data; | ||
1879 | u32 inta, inta_mask; | ||
1880 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1881 | u32 inta_fh; | ||
1882 | #endif | ||
1883 | if (!priv) | ||
1884 | return IRQ_NONE; | ||
1885 | |||
1886 | spin_lock(&priv->lock); | ||
1887 | |||
1888 | /* Disable (but don't clear!) interrupts here to avoid | ||
1889 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
1890 | * If we have something to service, the tasklet will re-enable ints. | ||
1891 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
1892 | inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ | ||
1893 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1894 | |||
1895 | /* Discover which interrupts are active/pending */ | ||
1896 | inta = iwl_read32(priv, CSR_INT); | ||
1897 | |||
1898 | /* Ignore interrupt if there's nothing in NIC to service. | ||
1899 | * This may be due to IRQ shared with another device, | ||
1900 | * or due to sporadic interrupts thrown from our NIC. */ | ||
1901 | if (!inta) { | ||
1902 | IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); | ||
1903 | goto none; | ||
1904 | } | ||
1905 | |||
1906 | if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { | ||
1907 | /* Hardware disappeared. It might have already raised | ||
1908 | * an interrupt */ | ||
1909 | IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
1910 | goto unplugged; | ||
1911 | } | ||
1912 | |||
1913 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1914 | if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { | ||
1915 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | ||
1916 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | ||
1917 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | ||
1918 | } | ||
1919 | #endif | ||
1920 | |||
1921 | priv->inta |= inta; | ||
1922 | /* iwl_irq_tasklet() will service interrupts and re-enable them */ | ||
1923 | if (likely(inta)) | ||
1924 | tasklet_schedule(&priv->irq_tasklet); | ||
1925 | else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1926 | iwl_enable_interrupts(priv); | ||
1927 | |||
1928 | unplugged: | ||
1929 | spin_unlock(&priv->lock); | ||
1930 | return IRQ_HANDLED; | ||
1931 | |||
1932 | none: | ||
1933 | /* re-enable interrupts here since we don't have anything to service. */ | ||
1934 | /* only Re-enable if diabled by irq and no schedules tasklet. */ | ||
1935 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) | ||
1936 | iwl_enable_interrupts(priv); | ||
1937 | |||
1938 | spin_unlock(&priv->lock); | ||
1939 | return IRQ_NONE; | ||
1940 | } | ||
1941 | |||
1942 | irqreturn_t iwl_isr_legacy(int irq, void *data) | 1365 | irqreturn_t iwl_isr_legacy(int irq, void *data) |
1943 | { | 1366 | { |
1944 | struct iwl_priv *priv = data; | 1367 | struct iwl_priv *priv = data; |
1945 | u32 inta, inta_mask; | 1368 | u32 inta, inta_mask; |
1946 | u32 inta_fh; | 1369 | u32 inta_fh; |
1370 | unsigned long flags; | ||
1947 | if (!priv) | 1371 | if (!priv) |
1948 | return IRQ_NONE; | 1372 | return IRQ_NONE; |
1949 | 1373 | ||
1950 | spin_lock(&priv->lock); | 1374 | spin_lock_irqsave(&priv->lock, flags); |
1951 | 1375 | ||
1952 | /* Disable (but don't clear!) interrupts here to avoid | 1376 | /* Disable (but don't clear!) interrupts here to avoid |
1953 | * back-to-back ISRs and sporadic interrupts from our NIC. | 1377 | * back-to-back ISRs and sporadic interrupts from our NIC. |
@@ -1985,7 +1409,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1985 | tasklet_schedule(&priv->irq_tasklet); | 1409 | tasklet_schedule(&priv->irq_tasklet); |
1986 | 1410 | ||
1987 | unplugged: | 1411 | unplugged: |
1988 | spin_unlock(&priv->lock); | 1412 | spin_unlock_irqrestore(&priv->lock, flags); |
1989 | return IRQ_HANDLED; | 1413 | return IRQ_HANDLED; |
1990 | 1414 | ||
1991 | none: | 1415 | none: |
@@ -1993,12 +1417,12 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1993 | /* only Re-enable if diabled by irq */ | 1417 | /* only Re-enable if diabled by irq */ |
1994 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1418 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1995 | iwl_enable_interrupts(priv); | 1419 | iwl_enable_interrupts(priv); |
1996 | spin_unlock(&priv->lock); | 1420 | spin_unlock_irqrestore(&priv->lock, flags); |
1997 | return IRQ_NONE; | 1421 | return IRQ_NONE; |
1998 | } | 1422 | } |
1999 | EXPORT_SYMBOL(iwl_isr_legacy); | 1423 | EXPORT_SYMBOL(iwl_isr_legacy); |
2000 | 1424 | ||
2001 | int iwl_send_bt_config(struct iwl_priv *priv) | 1425 | void iwl_send_bt_config(struct iwl_priv *priv) |
2002 | { | 1426 | { |
2003 | struct iwl_bt_cmd bt_cmd = { | 1427 | struct iwl_bt_cmd bt_cmd = { |
2004 | .lead_time = BT_LEAD_TIME_DEF, | 1428 | .lead_time = BT_LEAD_TIME_DEF, |
@@ -2015,8 +1439,9 @@ int iwl_send_bt_config(struct iwl_priv *priv) | |||
2015 | IWL_DEBUG_INFO(priv, "BT coex %s\n", | 1439 | IWL_DEBUG_INFO(priv, "BT coex %s\n", |
2016 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); | 1440 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); |
2017 | 1441 | ||
2018 | return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 1442 | if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
2019 | sizeof(struct iwl_bt_cmd), &bt_cmd); | 1443 | sizeof(struct iwl_bt_cmd), &bt_cmd)) |
1444 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | ||
2020 | } | 1445 | } |
2021 | EXPORT_SYMBOL(iwl_send_bt_config); | 1446 | EXPORT_SYMBOL(iwl_send_bt_config); |
2022 | 1447 | ||
@@ -2306,12 +1731,6 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2306 | cpu_to_le16((params->txop * 32)); | 1731 | cpu_to_le16((params->txop * 32)); |
2307 | 1732 | ||
2308 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; | 1733 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; |
2309 | priv->qos_data.qos_active = 1; | ||
2310 | |||
2311 | if (priv->iw_mode == NL80211_IFTYPE_AP) | ||
2312 | iwl_activate_qos(priv, 1); | ||
2313 | else if (priv->assoc_id && iwl_is_associated(priv)) | ||
2314 | iwl_activate_qos(priv, 0); | ||
2315 | 1734 | ||
2316 | spin_unlock_irqrestore(&priv->lock, flags); | 1735 | spin_unlock_irqrestore(&priv->lock, flags); |
2317 | 1736 | ||
@@ -2321,12 +1740,13 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2321 | EXPORT_SYMBOL(iwl_mac_conf_tx); | 1740 | EXPORT_SYMBOL(iwl_mac_conf_tx); |
2322 | 1741 | ||
2323 | static void iwl_ht_conf(struct iwl_priv *priv, | 1742 | static void iwl_ht_conf(struct iwl_priv *priv, |
2324 | struct ieee80211_bss_conf *bss_conf) | 1743 | struct ieee80211_vif *vif) |
2325 | { | 1744 | { |
2326 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 1745 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2327 | struct ieee80211_sta *sta; | 1746 | struct ieee80211_sta *sta; |
1747 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
2328 | 1748 | ||
2329 | IWL_DEBUG_MAC80211(priv, "enter: \n"); | 1749 | IWL_DEBUG_MAC80211(priv, "enter:\n"); |
2330 | 1750 | ||
2331 | if (!ht_conf->is_ht) | 1751 | if (!ht_conf->is_ht) |
2332 | return; | 1752 | return; |
@@ -2338,10 +1758,10 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2338 | 1758 | ||
2339 | ht_conf->single_chain_sufficient = false; | 1759 | ht_conf->single_chain_sufficient = false; |
2340 | 1760 | ||
2341 | switch (priv->iw_mode) { | 1761 | switch (vif->type) { |
2342 | case NL80211_IFTYPE_STATION: | 1762 | case NL80211_IFTYPE_STATION: |
2343 | rcu_read_lock(); | 1763 | rcu_read_lock(); |
2344 | sta = ieee80211_find_sta(priv->vif, priv->bssid); | 1764 | sta = ieee80211_find_sta(vif, bss_conf->bssid); |
2345 | if (sta) { | 1765 | if (sta) { |
2346 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1766 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
2347 | int maxstreams; | 1767 | int maxstreams; |
@@ -2379,7 +1799,6 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2379 | 1799 | ||
2380 | static inline void iwl_set_no_assoc(struct iwl_priv *priv) | 1800 | static inline void iwl_set_no_assoc(struct iwl_priv *priv) |
2381 | { | 1801 | { |
2382 | priv->assoc_id = 0; | ||
2383 | iwl_led_disassociate(priv); | 1802 | iwl_led_disassociate(priv); |
2384 | /* | 1803 | /* |
2385 | * inform the ucode that there is no longer an | 1804 | * inform the ucode that there is no longer an |
@@ -2392,7 +1811,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv) | |||
2392 | iwlcore_commit_rxon(priv); | 1811 | iwlcore_commit_rxon(priv); |
2393 | } | 1812 | } |
2394 | 1813 | ||
2395 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | ||
2396 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | 1814 | void iwl_bss_info_changed(struct ieee80211_hw *hw, |
2397 | struct ieee80211_vif *vif, | 1815 | struct ieee80211_vif *vif, |
2398 | struct ieee80211_bss_conf *bss_conf, | 1816 | struct ieee80211_bss_conf *bss_conf, |
@@ -2408,14 +1826,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2408 | 1826 | ||
2409 | mutex_lock(&priv->mutex); | 1827 | mutex_lock(&priv->mutex); |
2410 | 1828 | ||
2411 | if (changes & BSS_CHANGED_BEACON && | 1829 | if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { |
2412 | priv->iw_mode == NL80211_IFTYPE_AP) { | ||
2413 | dev_kfree_skb(priv->ibss_beacon); | 1830 | dev_kfree_skb(priv->ibss_beacon); |
2414 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); | 1831 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
2415 | } | 1832 | } |
2416 | 1833 | ||
2417 | if (changes & BSS_CHANGED_BEACON_INT) { | 1834 | if (changes & BSS_CHANGED_BEACON_INT) { |
2418 | priv->beacon_int = bss_conf->beacon_int; | ||
2419 | /* TODO: in AP mode, do something to make this take effect */ | 1835 | /* TODO: in AP mode, do something to make this take effect */ |
2420 | } | 1836 | } |
2421 | 1837 | ||
@@ -2435,8 +1851,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2435 | } | 1851 | } |
2436 | 1852 | ||
2437 | /* mac80211 only sets assoc when in STATION mode */ | 1853 | /* mac80211 only sets assoc when in STATION mode */ |
2438 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC || | 1854 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { |
2439 | bss_conf->assoc) { | ||
2440 | memcpy(priv->staging_rxon.bssid_addr, | 1855 | memcpy(priv->staging_rxon.bssid_addr, |
2441 | bss_conf->bssid, ETH_ALEN); | 1856 | bss_conf->bssid, ETH_ALEN); |
2442 | 1857 | ||
@@ -2454,7 +1869,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2454 | * mac80211 decides to do both changes at once because | 1869 | * mac80211 decides to do both changes at once because |
2455 | * it will invoke post_associate. | 1870 | * it will invoke post_associate. |
2456 | */ | 1871 | */ |
2457 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && | 1872 | if (vif->type == NL80211_IFTYPE_ADHOC && |
2458 | changes & BSS_CHANGED_BEACON) { | 1873 | changes & BSS_CHANGED_BEACON) { |
2459 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1874 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
2460 | 1875 | ||
@@ -2497,7 +1912,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2497 | } | 1912 | } |
2498 | 1913 | ||
2499 | if (changes & BSS_CHANGED_HT) { | 1914 | if (changes & BSS_CHANGED_HT) { |
2500 | iwl_ht_conf(priv, bss_conf); | 1915 | iwl_ht_conf(priv, vif); |
2501 | 1916 | ||
2502 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1917 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2503 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 1918 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
@@ -2506,28 +1921,17 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2506 | if (changes & BSS_CHANGED_ASSOC) { | 1921 | if (changes & BSS_CHANGED_ASSOC) { |
2507 | IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); | 1922 | IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); |
2508 | if (bss_conf->assoc) { | 1923 | if (bss_conf->assoc) { |
2509 | priv->assoc_id = bss_conf->aid; | ||
2510 | priv->beacon_int = bss_conf->beacon_int; | ||
2511 | priv->timestamp = bss_conf->timestamp; | 1924 | priv->timestamp = bss_conf->timestamp; |
2512 | priv->assoc_capability = bss_conf->assoc_capability; | ||
2513 | 1925 | ||
2514 | iwl_led_associate(priv); | 1926 | iwl_led_associate(priv); |
2515 | 1927 | ||
2516 | /* | ||
2517 | * We have just associated, don't start scan too early | ||
2518 | * leave time for EAPOL exchange to complete. | ||
2519 | * | ||
2520 | * XXX: do this in mac80211 | ||
2521 | */ | ||
2522 | priv->next_scan_jiffies = jiffies + | ||
2523 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; | ||
2524 | if (!iwl_is_rfkill(priv)) | 1928 | if (!iwl_is_rfkill(priv)) |
2525 | priv->cfg->ops->lib->post_associate(priv); | 1929 | priv->cfg->ops->lib->post_associate(priv, vif); |
2526 | } else | 1930 | } else |
2527 | iwl_set_no_assoc(priv); | 1931 | iwl_set_no_assoc(priv); |
2528 | } | 1932 | } |
2529 | 1933 | ||
2530 | if (changes && iwl_is_associated(priv) && priv->assoc_id) { | 1934 | if (changes && iwl_is_associated(priv) && bss_conf->aid) { |
2531 | IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", | 1935 | IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", |
2532 | changes); | 1936 | changes); |
2533 | ret = iwl_send_rxon_assoc(priv); | 1937 | ret = iwl_send_rxon_assoc(priv); |
@@ -2544,11 +1948,20 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2544 | memcpy(priv->staging_rxon.bssid_addr, | 1948 | memcpy(priv->staging_rxon.bssid_addr, |
2545 | bss_conf->bssid, ETH_ALEN); | 1949 | bss_conf->bssid, ETH_ALEN); |
2546 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | 1950 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); |
2547 | iwlcore_config_ap(priv); | 1951 | iwlcore_config_ap(priv, vif); |
2548 | } else | 1952 | } else |
2549 | iwl_set_no_assoc(priv); | 1953 | iwl_set_no_assoc(priv); |
2550 | } | 1954 | } |
2551 | 1955 | ||
1956 | if (changes & BSS_CHANGED_IBSS) { | ||
1957 | ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif, | ||
1958 | bss_conf->ibss_joined); | ||
1959 | if (ret) | ||
1960 | IWL_ERR(priv, "failed to %s IBSS station %pM\n", | ||
1961 | bss_conf->ibss_joined ? "add" : "remove", | ||
1962 | bss_conf->bssid); | ||
1963 | } | ||
1964 | |||
2552 | mutex_unlock(&priv->mutex); | 1965 | mutex_unlock(&priv->mutex); |
2553 | 1966 | ||
2554 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1967 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2568,11 +1981,6 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2568 | return -EIO; | 1981 | return -EIO; |
2569 | } | 1982 | } |
2570 | 1983 | ||
2571 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | ||
2572 | IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); | ||
2573 | return -EIO; | ||
2574 | } | ||
2575 | |||
2576 | spin_lock_irqsave(&priv->lock, flags); | 1984 | spin_lock_irqsave(&priv->lock, flags); |
2577 | 1985 | ||
2578 | if (priv->ibss_beacon) | 1986 | if (priv->ibss_beacon) |
@@ -2580,59 +1988,31 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2580 | 1988 | ||
2581 | priv->ibss_beacon = skb; | 1989 | priv->ibss_beacon = skb; |
2582 | 1990 | ||
2583 | priv->assoc_id = 0; | ||
2584 | timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | 1991 | timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; |
2585 | priv->timestamp = le64_to_cpu(timestamp); | 1992 | priv->timestamp = le64_to_cpu(timestamp); |
2586 | 1993 | ||
2587 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 1994 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2588 | spin_unlock_irqrestore(&priv->lock, flags); | 1995 | spin_unlock_irqrestore(&priv->lock, flags); |
2589 | 1996 | ||
2590 | iwl_reset_qos(priv); | 1997 | priv->cfg->ops->lib->post_associate(priv, priv->vif); |
2591 | |||
2592 | priv->cfg->ops->lib->post_associate(priv); | ||
2593 | |||
2594 | 1998 | ||
2595 | return 0; | 1999 | return 0; |
2596 | } | 2000 | } |
2597 | EXPORT_SYMBOL(iwl_mac_beacon_update); | 2001 | EXPORT_SYMBOL(iwl_mac_beacon_update); |
2598 | 2002 | ||
2599 | int iwl_set_mode(struct iwl_priv *priv, int mode) | 2003 | static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2600 | { | 2004 | { |
2601 | if (mode == NL80211_IFTYPE_ADHOC) { | 2005 | iwl_connection_init_rx_config(priv, vif); |
2602 | const struct iwl_channel_info *ch_info; | ||
2603 | |||
2604 | ch_info = iwl_get_channel_info(priv, | ||
2605 | priv->band, | ||
2606 | le16_to_cpu(priv->staging_rxon.channel)); | ||
2607 | |||
2608 | if (!ch_info || !is_channel_ibss(ch_info)) { | ||
2609 | IWL_ERR(priv, "channel %d not IBSS channel\n", | ||
2610 | le16_to_cpu(priv->staging_rxon.channel)); | ||
2611 | return -EINVAL; | ||
2612 | } | ||
2613 | } | ||
2614 | |||
2615 | iwl_connection_init_rx_config(priv, mode); | ||
2616 | 2006 | ||
2617 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2007 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2618 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2008 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2619 | 2009 | ||
2620 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | 2010 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); |
2621 | 2011 | ||
2622 | iwl_clear_stations_table(priv); | 2012 | return iwlcore_commit_rxon(priv); |
2623 | |||
2624 | /* dont commit rxon if rf-kill is on*/ | ||
2625 | if (!iwl_is_ready_rf(priv)) | ||
2626 | return -EAGAIN; | ||
2627 | |||
2628 | iwlcore_commit_rxon(priv); | ||
2629 | |||
2630 | return 0; | ||
2631 | } | 2013 | } |
2632 | EXPORT_SYMBOL(iwl_set_mode); | ||
2633 | 2014 | ||
2634 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 2015 | int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
2635 | struct ieee80211_vif *vif) | ||
2636 | { | 2016 | { |
2637 | struct iwl_priv *priv = hw->priv; | 2017 | struct iwl_priv *priv = hw->priv; |
2638 | int err = 0; | 2018 | int err = 0; |
@@ -2641,6 +2021,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2641 | 2021 | ||
2642 | mutex_lock(&priv->mutex); | 2022 | mutex_lock(&priv->mutex); |
2643 | 2023 | ||
2024 | if (WARN_ON(!iwl_is_ready_rf(priv))) { | ||
2025 | err = -EINVAL; | ||
2026 | goto out; | ||
2027 | } | ||
2028 | |||
2644 | if (priv->vif) { | 2029 | if (priv->vif) { |
2645 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 2030 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); |
2646 | err = -EOPNOTSUPP; | 2031 | err = -EOPNOTSUPP; |
@@ -2650,15 +2035,18 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2650 | priv->vif = vif; | 2035 | priv->vif = vif; |
2651 | priv->iw_mode = vif->type; | 2036 | priv->iw_mode = vif->type; |
2652 | 2037 | ||
2653 | if (vif->addr) { | 2038 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); |
2654 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); | 2039 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
2655 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); | 2040 | |
2656 | } | 2041 | err = iwl_set_mode(priv, vif); |
2042 | if (err) | ||
2043 | goto out_err; | ||
2657 | 2044 | ||
2658 | if (iwl_set_mode(priv, vif->type) == -EAGAIN) | 2045 | goto out; |
2659 | /* we are not ready, will run again when ready */ | ||
2660 | set_bit(STATUS_MODE_PENDING, &priv->status); | ||
2661 | 2046 | ||
2047 | out_err: | ||
2048 | priv->vif = NULL; | ||
2049 | priv->iw_mode = NL80211_IFTYPE_STATION; | ||
2662 | out: | 2050 | out: |
2663 | mutex_unlock(&priv->mutex); | 2051 | mutex_unlock(&priv->mutex); |
2664 | 2052 | ||
@@ -2668,7 +2056,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2668 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2056 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2669 | 2057 | ||
2670 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 2058 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
2671 | struct ieee80211_vif *vif) | 2059 | struct ieee80211_vif *vif) |
2672 | { | 2060 | { |
2673 | struct iwl_priv *priv = hw->priv; | 2061 | struct iwl_priv *priv = hw->priv; |
2674 | 2062 | ||
@@ -2694,10 +2082,6 @@ EXPORT_SYMBOL(iwl_mac_remove_interface); | |||
2694 | 2082 | ||
2695 | /** | 2083 | /** |
2696 | * iwl_mac_config - mac80211 config callback | 2084 | * iwl_mac_config - mac80211 config callback |
2697 | * | ||
2698 | * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to | ||
2699 | * be set inappropriately and the driver currently sets the hardware up to | ||
2700 | * use it whenever needed. | ||
2701 | */ | 2085 | */ |
2702 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | 2086 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) |
2703 | { | 2087 | { |
@@ -2752,15 +2136,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2752 | goto set_ch_out; | 2136 | goto set_ch_out; |
2753 | } | 2137 | } |
2754 | 2138 | ||
2755 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && | ||
2756 | !is_channel_ibss(ch_info)) { | ||
2757 | IWL_ERR(priv, "channel %d in band %d not " | ||
2758 | "IBSS channel\n", | ||
2759 | conf->channel->hw_value, conf->channel->band); | ||
2760 | ret = -EINVAL; | ||
2761 | goto set_ch_out; | ||
2762 | } | ||
2763 | |||
2764 | spin_lock_irqsave(&priv->lock, flags); | 2139 | spin_lock_irqsave(&priv->lock, flags); |
2765 | 2140 | ||
2766 | /* Configure HT40 channels */ | 2141 | /* Configure HT40 channels */ |
@@ -2794,7 +2169,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2794 | iwl_set_rxon_channel(priv, conf->channel); | 2169 | iwl_set_rxon_channel(priv, conf->channel); |
2795 | iwl_set_rxon_ht(priv, ht_conf); | 2170 | iwl_set_rxon_ht(priv, ht_conf); |
2796 | 2171 | ||
2797 | iwl_set_flags_for_band(priv, conf->channel->band); | 2172 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); |
2798 | spin_unlock_irqrestore(&priv->lock, flags); | 2173 | spin_unlock_irqrestore(&priv->lock, flags); |
2799 | if (iwl_is_associated(priv) && | 2174 | if (iwl_is_associated(priv) && |
2800 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | 2175 | (le16_to_cpu(priv->active_rxon.channel) != ch) && |
@@ -2833,6 +2208,15 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2833 | iwl_set_tx_power(priv, conf->power_level, false); | 2208 | iwl_set_tx_power(priv, conf->power_level, false); |
2834 | } | 2209 | } |
2835 | 2210 | ||
2211 | if (changed & IEEE80211_CONF_CHANGE_QOS) { | ||
2212 | bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS); | ||
2213 | |||
2214 | spin_lock_irqsave(&priv->lock, flags); | ||
2215 | priv->qos_data.qos_active = qos_active; | ||
2216 | iwl_update_qos(priv); | ||
2217 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2218 | } | ||
2219 | |||
2836 | if (!iwl_is_ready(priv)) { | 2220 | if (!iwl_is_ready(priv)) { |
2837 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2221 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2838 | goto out; | 2222 | goto out; |
@@ -2867,12 +2251,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2867 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); | 2251 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); |
2868 | spin_unlock_irqrestore(&priv->lock, flags); | 2252 | spin_unlock_irqrestore(&priv->lock, flags); |
2869 | 2253 | ||
2870 | iwl_reset_qos(priv); | ||
2871 | |||
2872 | spin_lock_irqsave(&priv->lock, flags); | 2254 | spin_lock_irqsave(&priv->lock, flags); |
2873 | priv->assoc_id = 0; | ||
2874 | priv->assoc_capability = 0; | ||
2875 | priv->assoc_station_added = 0; | ||
2876 | 2255 | ||
2877 | /* new association get rid of ibss beacon skb */ | 2256 | /* new association get rid of ibss beacon skb */ |
2878 | if (priv->ibss_beacon) | 2257 | if (priv->ibss_beacon) |
@@ -2880,10 +2259,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2880 | 2259 | ||
2881 | priv->ibss_beacon = NULL; | 2260 | priv->ibss_beacon = NULL; |
2882 | 2261 | ||
2883 | priv->beacon_int = priv->vif->bss_conf.beacon_int; | ||
2884 | priv->timestamp = 0; | 2262 | priv->timestamp = 0; |
2885 | if ((priv->iw_mode == NL80211_IFTYPE_STATION)) | ||
2886 | priv->beacon_int = 0; | ||
2887 | 2263 | ||
2888 | spin_unlock_irqrestore(&priv->lock, flags); | 2264 | spin_unlock_irqrestore(&priv->lock, flags); |
2889 | 2265 | ||
@@ -2896,17 +2272,9 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2896 | /* we are restarting association process | 2272 | /* we are restarting association process |
2897 | * clear RXON_FILTER_ASSOC_MSK bit | 2273 | * clear RXON_FILTER_ASSOC_MSK bit |
2898 | */ | 2274 | */ |
2899 | if (priv->iw_mode != NL80211_IFTYPE_AP) { | 2275 | iwl_scan_cancel_timeout(priv, 100); |
2900 | iwl_scan_cancel_timeout(priv, 100); | 2276 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2901 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2277 | iwlcore_commit_rxon(priv); |
2902 | iwlcore_commit_rxon(priv); | ||
2903 | } | ||
2904 | |||
2905 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { | ||
2906 | IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); | ||
2907 | mutex_unlock(&priv->mutex); | ||
2908 | return; | ||
2909 | } | ||
2910 | 2278 | ||
2911 | iwl_set_rate(priv); | 2279 | iwl_set_rate(priv); |
2912 | 2280 | ||
@@ -2923,7 +2291,7 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv) | |||
2923 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, | 2291 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, |
2924 | GFP_KERNEL); | 2292 | GFP_KERNEL); |
2925 | if (!priv->txq) { | 2293 | if (!priv->txq) { |
2926 | IWL_ERR(priv, "Not enough memory for txq \n"); | 2294 | IWL_ERR(priv, "Not enough memory for txq\n"); |
2927 | return -ENOMEM; | 2295 | return -ENOMEM; |
2928 | } | 2296 | } |
2929 | return 0; | 2297 | return 0; |
@@ -2937,34 +2305,6 @@ void iwl_free_txq_mem(struct iwl_priv *priv) | |||
2937 | } | 2305 | } |
2938 | EXPORT_SYMBOL(iwl_free_txq_mem); | 2306 | EXPORT_SYMBOL(iwl_free_txq_mem); |
2939 | 2307 | ||
2940 | int iwl_send_wimax_coex(struct iwl_priv *priv) | ||
2941 | { | ||
2942 | struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd); | ||
2943 | |||
2944 | if (priv->cfg->support_wimax_coexist) { | ||
2945 | /* UnMask wake up src at associated sleep */ | ||
2946 | coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK; | ||
2947 | |||
2948 | /* UnMask wake up src at unassociated sleep */ | ||
2949 | coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; | ||
2950 | memcpy(coex_cmd.sta_prio, cu_priorities, | ||
2951 | sizeof(struct iwl_wimax_coex_event_entry) * | ||
2952 | COEX_NUM_OF_EVENTS); | ||
2953 | |||
2954 | /* enabling the coexistence feature */ | ||
2955 | coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; | ||
2956 | |||
2957 | /* enabling the priorities tables */ | ||
2958 | coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; | ||
2959 | } else { | ||
2960 | /* coexistence is disabled */ | ||
2961 | memset(&coex_cmd, 0, sizeof(coex_cmd)); | ||
2962 | } | ||
2963 | return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, | ||
2964 | sizeof(coex_cmd), &coex_cmd); | ||
2965 | } | ||
2966 | EXPORT_SYMBOL(iwl_send_wimax_coex); | ||
2967 | |||
2968 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 2308 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
2969 | 2309 | ||
2970 | #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) | 2310 | #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) |
@@ -3358,7 +2698,6 @@ static void iwl_force_rf_reset(struct iwl_priv *priv) | |||
3358 | */ | 2698 | */ |
3359 | IWL_DEBUG_INFO(priv, "perform radio reset.\n"); | 2699 | IWL_DEBUG_INFO(priv, "perform radio reset.\n"); |
3360 | iwl_internal_short_hw_scan(priv); | 2700 | iwl_internal_short_hw_scan(priv); |
3361 | return; | ||
3362 | } | 2701 | } |
3363 | 2702 | ||
3364 | 2703 | ||
@@ -3404,6 +2743,99 @@ int iwl_force_reset(struct iwl_priv *priv, int mode) | |||
3404 | } | 2743 | } |
3405 | return 0; | 2744 | return 0; |
3406 | } | 2745 | } |
2746 | EXPORT_SYMBOL(iwl_force_reset); | ||
2747 | |||
2748 | /** | ||
2749 | * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover | ||
2750 | * | ||
2751 | * During normal condition (no queue is stuck), the timer is continually set to | ||
2752 | * execute every monitor_recover_period milliseconds after the last timer | ||
2753 | * expired. When the queue read_ptr is at the same place, the timer is | ||
2754 | * shorten to 100mSecs. This is | ||
2755 | * 1) to reduce the chance that the read_ptr may wrap around (not stuck) | ||
2756 | * 2) to detect the stuck queues quicker before the station and AP can | ||
2757 | * disassociate each other. | ||
2758 | * | ||
2759 | * This function monitors all the tx queues and recover from it if any | ||
2760 | * of the queues are stuck. | ||
2761 | * 1. It first check the cmd queue for stuck conditions. If it is stuck, | ||
2762 | * it will recover by resetting the firmware and return. | ||
2763 | * 2. Then, it checks for station association. If it associates it will check | ||
2764 | * other queues. If any queue is stuck, it will recover by resetting | ||
2765 | * the firmware. | ||
2766 | * Note: It the number of times the queue read_ptr to be at the same place to | ||
2767 | * be MAX_REPEAT+1 in order to consider to be stuck. | ||
2768 | */ | ||
2769 | /* | ||
2770 | * The maximum number of times the read pointer of the tx queue at the | ||
2771 | * same place without considering to be stuck. | ||
2772 | */ | ||
2773 | #define MAX_REPEAT (2) | ||
2774 | static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) | ||
2775 | { | ||
2776 | struct iwl_tx_queue *txq; | ||
2777 | struct iwl_queue *q; | ||
2778 | |||
2779 | txq = &priv->txq[cnt]; | ||
2780 | q = &txq->q; | ||
2781 | /* queue is empty, skip */ | ||
2782 | if (q->read_ptr != q->write_ptr) { | ||
2783 | if (q->read_ptr == q->last_read_ptr) { | ||
2784 | /* a queue has not been read from last time */ | ||
2785 | if (q->repeat_same_read_ptr > MAX_REPEAT) { | ||
2786 | IWL_ERR(priv, | ||
2787 | "queue %d stuck %d time. Fw reload.\n", | ||
2788 | q->id, q->repeat_same_read_ptr); | ||
2789 | q->repeat_same_read_ptr = 0; | ||
2790 | iwl_force_reset(priv, IWL_FW_RESET); | ||
2791 | } else { | ||
2792 | q->repeat_same_read_ptr++; | ||
2793 | IWL_DEBUG_RADIO(priv, | ||
2794 | "queue %d, not read %d time\n", | ||
2795 | q->id, | ||
2796 | q->repeat_same_read_ptr); | ||
2797 | mod_timer(&priv->monitor_recover, jiffies + | ||
2798 | msecs_to_jiffies(IWL_ONE_HUNDRED_MSECS)); | ||
2799 | } | ||
2800 | return 1; | ||
2801 | } else { | ||
2802 | q->last_read_ptr = q->read_ptr; | ||
2803 | q->repeat_same_read_ptr = 0; | ||
2804 | } | ||
2805 | } | ||
2806 | return 0; | ||
2807 | } | ||
2808 | |||
2809 | void iwl_bg_monitor_recover(unsigned long data) | ||
2810 | { | ||
2811 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
2812 | int cnt; | ||
2813 | |||
2814 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2815 | return; | ||
2816 | |||
2817 | /* monitor and check for stuck cmd queue */ | ||
2818 | if (iwl_check_stuck_queue(priv, IWL_CMD_QUEUE_NUM)) | ||
2819 | return; | ||
2820 | |||
2821 | /* monitor and check for other stuck queues */ | ||
2822 | if (iwl_is_associated(priv)) { | ||
2823 | for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { | ||
2824 | /* skip as we already checked the command queue */ | ||
2825 | if (cnt == IWL_CMD_QUEUE_NUM) | ||
2826 | continue; | ||
2827 | if (iwl_check_stuck_queue(priv, cnt)) | ||
2828 | return; | ||
2829 | } | ||
2830 | } | ||
2831 | /* | ||
2832 | * Reschedule the timer to occur in | ||
2833 | * priv->cfg->monitor_recover_period | ||
2834 | */ | ||
2835 | mod_timer(&priv->monitor_recover, | ||
2836 | jiffies + msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2837 | } | ||
2838 | EXPORT_SYMBOL(iwl_bg_monitor_recover); | ||
3407 | 2839 | ||
3408 | #ifdef CONFIG_PM | 2840 | #ifdef CONFIG_PM |
3409 | 2841 | ||
@@ -3433,6 +2865,12 @@ int iwl_pci_resume(struct pci_dev *pdev) | |||
3433 | struct iwl_priv *priv = pci_get_drvdata(pdev); | 2865 | struct iwl_priv *priv = pci_get_drvdata(pdev); |
3434 | int ret; | 2866 | int ret; |
3435 | 2867 | ||
2868 | /* | ||
2869 | * We disable the RETRY_TIMEOUT register (0x41) to keep | ||
2870 | * PCI Tx retries from interfering with C3 CPU state. | ||
2871 | */ | ||
2872 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | ||
2873 | |||
3436 | pci_set_power_state(pdev, PCI_D0); | 2874 | pci_set_power_state(pdev, PCI_D0); |
3437 | ret = pci_enable_device(pdev); | 2875 | ret = pci_enable_device(pdev); |
3438 | if (ret) | 2876 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 732590f5fe30..7e5a5ba41fd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -90,6 +90,7 @@ struct iwl_hcmd_ops { | |||
90 | int (*commit_rxon)(struct iwl_priv *priv); | 90 | int (*commit_rxon)(struct iwl_priv *priv); |
91 | void (*set_rxon_chain)(struct iwl_priv *priv); | 91 | void (*set_rxon_chain)(struct iwl_priv *priv); |
92 | int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); | 92 | int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); |
93 | void (*send_bt_config)(struct iwl_priv *priv); | ||
93 | }; | 94 | }; |
94 | 95 | ||
95 | struct iwl_hcmd_utils_ops { | 96 | struct iwl_hcmd_utils_ops { |
@@ -105,6 +106,7 @@ struct iwl_hcmd_utils_ops { | |||
105 | __le32 *tx_flags); | 106 | __le32 *tx_flags); |
106 | int (*calc_rssi)(struct iwl_priv *priv, | 107 | int (*calc_rssi)(struct iwl_priv *priv, |
107 | struct iwl_rx_phy_res *rx_resp); | 108 | struct iwl_rx_phy_res *rx_resp); |
109 | void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
108 | }; | 110 | }; |
109 | 111 | ||
110 | struct iwl_apm_ops { | 112 | struct iwl_apm_ops { |
@@ -114,23 +116,21 @@ struct iwl_apm_ops { | |||
114 | int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); | 116 | int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); |
115 | }; | 117 | }; |
116 | 118 | ||
119 | struct iwl_debugfs_ops { | ||
120 | ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, | ||
121 | size_t count, loff_t *ppos); | ||
122 | ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf, | ||
123 | size_t count, loff_t *ppos); | ||
124 | ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, | ||
125 | size_t count, loff_t *ppos); | ||
126 | }; | ||
127 | |||
117 | struct iwl_temp_ops { | 128 | struct iwl_temp_ops { |
118 | void (*temperature)(struct iwl_priv *priv); | 129 | void (*temperature)(struct iwl_priv *priv); |
119 | void (*set_ct_kill)(struct iwl_priv *priv); | 130 | void (*set_ct_kill)(struct iwl_priv *priv); |
120 | void (*set_calib_version)(struct iwl_priv *priv); | 131 | void (*set_calib_version)(struct iwl_priv *priv); |
121 | }; | 132 | }; |
122 | 133 | ||
123 | struct iwl_ucode_ops { | ||
124 | u32 (*get_header_size)(u32); | ||
125 | u32 (*get_build)(const struct iwl_ucode_header *, u32); | ||
126 | u32 (*get_inst_size)(const struct iwl_ucode_header *, u32); | ||
127 | u32 (*get_data_size)(const struct iwl_ucode_header *, u32); | ||
128 | u32 (*get_init_size)(const struct iwl_ucode_header *, u32); | ||
129 | u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32); | ||
130 | u32 (*get_boot_size)(const struct iwl_ucode_header *, u32); | ||
131 | u8 * (*get_data)(const struct iwl_ucode_header *, u32); | ||
132 | }; | ||
133 | |||
134 | struct iwl_lib_ops { | 134 | struct iwl_lib_ops { |
135 | /* set hw dependent parameters */ | 135 | /* set hw dependent parameters */ |
136 | int (*set_hw_params)(struct iwl_priv *priv); | 136 | int (*set_hw_params)(struct iwl_priv *priv); |
@@ -180,8 +180,9 @@ struct iwl_lib_ops { | |||
180 | /* power */ | 180 | /* power */ |
181 | int (*send_tx_power) (struct iwl_priv *priv); | 181 | int (*send_tx_power) (struct iwl_priv *priv); |
182 | void (*update_chain_flags)(struct iwl_priv *priv); | 182 | void (*update_chain_flags)(struct iwl_priv *priv); |
183 | void (*post_associate) (struct iwl_priv *priv); | 183 | void (*post_associate)(struct iwl_priv *priv, |
184 | void (*config_ap) (struct iwl_priv *priv); | 184 | struct ieee80211_vif *vif); |
185 | void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif); | ||
185 | irqreturn_t (*isr) (int irq, void *data); | 186 | irqreturn_t (*isr) (int irq, void *data); |
186 | 187 | ||
187 | /* eeprom operations (as defined in iwl-eeprom.h) */ | 188 | /* eeprom operations (as defined in iwl-eeprom.h) */ |
@@ -190,7 +191,17 @@ struct iwl_lib_ops { | |||
190 | /* temperature */ | 191 | /* temperature */ |
191 | struct iwl_temp_ops temp_ops; | 192 | struct iwl_temp_ops temp_ops; |
192 | /* station management */ | 193 | /* station management */ |
193 | void (*add_bcast_station)(struct iwl_priv *priv); | 194 | int (*manage_ibss_station)(struct iwl_priv *priv, |
195 | struct ieee80211_vif *vif, bool add); | ||
196 | /* recover from tx queue stall */ | ||
197 | void (*recover_from_tx_stall)(unsigned long data); | ||
198 | /* check for plcp health */ | ||
199 | bool (*check_plcp_health)(struct iwl_priv *priv, | ||
200 | struct iwl_rx_packet *pkt); | ||
201 | /* check for ack health */ | ||
202 | bool (*check_ack_health)(struct iwl_priv *priv, | ||
203 | struct iwl_rx_packet *pkt); | ||
204 | struct iwl_debugfs_ops debugfs_ops; | ||
194 | }; | 205 | }; |
195 | 206 | ||
196 | struct iwl_led_ops { | 207 | struct iwl_led_ops { |
@@ -200,7 +211,6 @@ struct iwl_led_ops { | |||
200 | }; | 211 | }; |
201 | 212 | ||
202 | struct iwl_ops { | 213 | struct iwl_ops { |
203 | const struct iwl_ucode_ops *ucode; | ||
204 | const struct iwl_lib_ops *lib; | 214 | const struct iwl_lib_ops *lib; |
205 | const struct iwl_hcmd_ops *hcmd; | 215 | const struct iwl_hcmd_ops *hcmd; |
206 | const struct iwl_hcmd_utils_ops *utils; | 216 | const struct iwl_hcmd_utils_ops *utils; |
@@ -237,6 +247,18 @@ struct iwl_mod_params { | |||
237 | * @support_wimax_coexist: support wimax/wifi co-exist | 247 | * @support_wimax_coexist: support wimax/wifi co-exist |
238 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | 248 | * @plcp_delta_threshold: plcp error rate threshold used to trigger |
239 | * radio tuning when there is a high receiving plcp error rate | 249 | * radio tuning when there is a high receiving plcp error rate |
250 | * @chain_noise_scale: default chain noise scale used for gain computation | ||
251 | * @monitor_recover_period: default timer used to check stuck queues | ||
252 | * @temperature_kelvin: temperature report by uCode in kelvin | ||
253 | * @max_event_log_size: size of event log buffer size for ucode event logging | ||
254 | * @tx_power_by_driver: tx power calibration performed by driver | ||
255 | * instead of uCode | ||
256 | * @ucode_tracing: support ucode continuous tracing | ||
257 | * @sensitivity_calib_by_driver: driver has the capability to perform | ||
258 | * sensitivity calibration operation | ||
259 | * @chain_noise_calib_by_driver: driver has the capability to perform | ||
260 | * chain noise calibration operation | ||
261 | * @scan_antennas: available antenna for scan operation | ||
240 | * | 262 | * |
241 | * We enable the driver to be backward compatible wrt API version. The | 263 | * We enable the driver to be backward compatible wrt API version. The |
242 | * driver specifies which APIs it supports (with @ucode_api_max being the | 264 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -295,6 +317,15 @@ struct iwl_cfg { | |||
295 | const bool support_wimax_coexist; | 317 | const bool support_wimax_coexist; |
296 | u8 plcp_delta_threshold; | 318 | u8 plcp_delta_threshold; |
297 | s32 chain_noise_scale; | 319 | s32 chain_noise_scale; |
320 | /* timer period for monitor the driver queues */ | ||
321 | u32 monitor_recover_period; | ||
322 | bool temperature_kelvin; | ||
323 | u32 max_event_log_size; | ||
324 | const bool tx_power_by_driver; | ||
325 | const bool ucode_tracing; | ||
326 | const bool sensitivity_calib_by_driver; | ||
327 | const bool chain_noise_calib_by_driver; | ||
328 | u8 scan_antennas[IEEE80211_NUM_BANDS]; | ||
298 | }; | 329 | }; |
299 | 330 | ||
300 | /*************************** | 331 | /*************************** |
@@ -304,8 +335,7 @@ struct iwl_cfg { | |||
304 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | 335 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, |
305 | struct ieee80211_ops *hw_ops); | 336 | struct ieee80211_ops *hw_ops); |
306 | void iwl_hw_detect(struct iwl_priv *priv); | 337 | void iwl_hw_detect(struct iwl_priv *priv); |
307 | void iwl_reset_qos(struct iwl_priv *priv); | 338 | void iwl_activate_qos(struct iwl_priv *priv); |
308 | void iwl_activate_qos(struct iwl_priv *priv, u8 force); | ||
309 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 339 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
310 | const struct ieee80211_tx_queue_params *params); | 340 | const struct ieee80211_tx_queue_params *params); |
311 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); | 341 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); |
@@ -316,8 +346,8 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); | |||
316 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); | 346 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); |
317 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 347 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
318 | struct ieee80211_sta_ht_cap *sta_ht_inf); | 348 | struct ieee80211_sta_ht_cap *sta_ht_inf); |
319 | void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); | 349 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
320 | void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode); | 350 | struct ieee80211_vif *vif); |
321 | int iwl_set_decrypted_flag(struct iwl_priv *priv, | 351 | int iwl_set_decrypted_flag(struct iwl_priv *priv, |
322 | struct ieee80211_hdr *hdr, | 352 | struct ieee80211_hdr *hdr, |
323 | u32 decrypt_res, | 353 | u32 decrypt_res, |
@@ -326,29 +356,25 @@ void iwl_irq_handle_error(struct iwl_priv *priv); | |||
326 | void iwl_configure_filter(struct ieee80211_hw *hw, | 356 | void iwl_configure_filter(struct ieee80211_hw *hw, |
327 | unsigned int changed_flags, | 357 | unsigned int changed_flags, |
328 | unsigned int *total_flags, u64 multicast); | 358 | unsigned int *total_flags, u64 multicast); |
329 | int iwl_hw_nic_init(struct iwl_priv *priv); | ||
330 | int iwl_set_hw_params(struct iwl_priv *priv); | 359 | int iwl_set_hw_params(struct iwl_priv *priv); |
331 | bool iwl_is_monitor_mode(struct iwl_priv *priv); | 360 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); |
332 | void iwl_post_associate(struct iwl_priv *priv); | ||
333 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | 361 | void iwl_bss_info_changed(struct ieee80211_hw *hw, |
334 | struct ieee80211_vif *vif, | 362 | struct ieee80211_vif *vif, |
335 | struct ieee80211_bss_conf *bss_conf, | 363 | struct ieee80211_bss_conf *bss_conf, |
336 | u32 changes); | 364 | u32 changes); |
337 | int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | 365 | int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); |
338 | int iwl_commit_rxon(struct iwl_priv *priv); | 366 | int iwl_commit_rxon(struct iwl_priv *priv); |
339 | int iwl_set_mode(struct iwl_priv *priv, int mode); | ||
340 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 367 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
341 | struct ieee80211_vif *vif); | 368 | struct ieee80211_vif *vif); |
342 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 369 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
343 | struct ieee80211_vif *vif); | 370 | struct ieee80211_vif *vif); |
344 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); | 371 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); |
345 | void iwl_config_ap(struct iwl_priv *priv); | 372 | void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); |
346 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); | 373 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); |
347 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | 374 | int iwl_alloc_txq_mem(struct iwl_priv *priv); |
348 | void iwl_free_txq_mem(struct iwl_priv *priv); | 375 | void iwl_free_txq_mem(struct iwl_priv *priv); |
349 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | 376 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, |
350 | __le32 *tx_flags); | 377 | __le32 *tx_flags); |
351 | int iwl_send_wimax_coex(struct iwl_priv *priv); | ||
352 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 378 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
353 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); | 379 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); |
354 | void iwl_free_traffic_mem(struct iwl_priv *priv); | 380 | void iwl_free_traffic_mem(struct iwl_priv *priv); |
@@ -411,26 +437,24 @@ void iwl_rx_reply_error(struct iwl_priv *priv, | |||
411 | /***************************************************** | 437 | /***************************************************** |
412 | * RX | 438 | * RX |
413 | ******************************************************/ | 439 | ******************************************************/ |
414 | void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
415 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 440 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
416 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 441 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
417 | void iwl_rx_handle(struct iwl_priv *priv); | 442 | void iwl_rx_handle(struct iwl_priv *priv); |
418 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 443 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
419 | struct iwl_rx_queue *q); | 444 | struct iwl_rx_queue *q); |
420 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
421 | void iwl_rx_replenish(struct iwl_priv *priv); | ||
422 | void iwl_rx_replenish_now(struct iwl_priv *priv); | ||
423 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
424 | void iwl_rx_queue_restock(struct iwl_priv *priv); | ||
425 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 445 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
426 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); | ||
427 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 446 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
428 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | ||
429 | /* Handlers */ | 447 | /* Handlers */ |
430 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 448 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
431 | struct iwl_rx_mem_buffer *rxb); | 449 | struct iwl_rx_mem_buffer *rxb); |
432 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 450 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
433 | struct iwl_rx_mem_buffer *rxb); | 451 | struct iwl_rx_mem_buffer *rxb); |
452 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
453 | struct iwl_rx_packet *pkt); | ||
454 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
455 | struct iwl_rx_packet *pkt); | ||
456 | void iwl_recover_from_statistics(struct iwl_priv *priv, | ||
457 | struct iwl_rx_packet *pkt); | ||
434 | void iwl_rx_statistics(struct iwl_priv *priv, | 458 | void iwl_rx_statistics(struct iwl_priv *priv, |
435 | struct iwl_rx_mem_buffer *rxb); | 459 | struct iwl_rx_mem_buffer *rxb); |
436 | void iwl_reply_statistics(struct iwl_priv *priv, | 460 | void iwl_reply_statistics(struct iwl_priv *priv, |
@@ -442,14 +466,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
442 | /***************************************************** | 466 | /***************************************************** |
443 | * TX | 467 | * TX |
444 | ******************************************************/ | 468 | ******************************************************/ |
445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); | ||
446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 469 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
448 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 470 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
449 | struct iwl_tx_queue *txq, | 471 | struct iwl_tx_queue *txq, |
450 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 472 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
451 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
452 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | ||
453 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 473 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
454 | struct iwl_tx_queue *txq); | 474 | struct iwl_tx_queue *txq); |
455 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 475 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
@@ -460,9 +480,6 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 480 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
461 | int slots_num, u32 txq_id); | 481 | int slots_num, u32 txq_id); |
462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 482 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | ||
464 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | ||
465 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); | ||
466 | /***************************************************** | 483 | /***************************************************** |
467 | * TX power | 484 | * TX power |
468 | ****************************************************/ | 485 | ****************************************************/ |
@@ -472,10 +489,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); | |||
472 | * Rate | 489 | * Rate |
473 | ******************************************************************************/ | 490 | ******************************************************************************/ |
474 | 491 | ||
475 | void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
476 | struct ieee80211_tx_info *info); | ||
477 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | 492 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); |
478 | int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | ||
479 | 493 | ||
480 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); | 494 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); |
481 | 495 | ||
@@ -505,8 +519,11 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) | |||
505 | void iwl_init_scan_params(struct iwl_priv *priv); | 519 | void iwl_init_scan_params(struct iwl_priv *priv); |
506 | int iwl_scan_cancel(struct iwl_priv *priv); | 520 | int iwl_scan_cancel(struct iwl_priv *priv); |
507 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 521 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
508 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); | 522 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, |
509 | int iwl_internal_short_hw_scan(struct iwl_priv *priv); | 523 | struct ieee80211_vif *vif, |
524 | struct cfg80211_scan_request *req); | ||
525 | void iwl_bg_start_internal_scan(struct work_struct *work); | ||
526 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | ||
510 | int iwl_force_reset(struct iwl_priv *priv, int mode); | 527 | int iwl_force_reset(struct iwl_priv *priv, int mode); |
511 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 528 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
512 | const u8 *ie, int ie_len, int left); | 529 | const u8 *ie, int ie_len, int left); |
@@ -515,7 +532,8 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
515 | enum ieee80211_band band, | 532 | enum ieee80211_band band, |
516 | u8 n_probes); | 533 | u8 n_probes); |
517 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 534 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
518 | enum ieee80211_band band); | 535 | enum ieee80211_band band, |
536 | struct ieee80211_vif *vif); | ||
519 | void iwl_bg_scan_check(struct work_struct *data); | 537 | void iwl_bg_scan_check(struct work_struct *data); |
520 | void iwl_bg_abort_scan(struct work_struct *work); | 538 | void iwl_bg_abort_scan(struct work_struct *work); |
521 | void iwl_bg_scan_completed(struct work_struct *work); | 539 | void iwl_bg_scan_completed(struct work_struct *work); |
@@ -530,6 +548,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | |||
530 | #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ | 548 | #define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ |
531 | #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ | 549 | #define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ |
532 | 550 | ||
551 | #define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) | ||
533 | 552 | ||
534 | /******************************************************************************* | 553 | /******************************************************************************* |
535 | * Calibrations - implemented in iwl-calib.c | 554 | * Calibrations - implemented in iwl-calib.c |
@@ -563,11 +582,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, | |||
563 | * PCI * | 582 | * PCI * |
564 | *****************************************************/ | 583 | *****************************************************/ |
565 | irqreturn_t iwl_isr_legacy(int irq, void *data); | 584 | irqreturn_t iwl_isr_legacy(int irq, void *data); |
566 | int iwl_reset_ict(struct iwl_priv *priv); | ||
567 | void iwl_disable_ict(struct iwl_priv *priv); | ||
568 | int iwl_alloc_isr_ict(struct iwl_priv *priv); | ||
569 | void iwl_free_isr_ict(struct iwl_priv *priv); | ||
570 | irqreturn_t iwl_isr_ict(int irq, void *data); | ||
571 | 585 | ||
572 | static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) | 586 | static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) |
573 | { | 587 | { |
@@ -577,6 +591,9 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) | |||
577 | pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); | 591 | pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); |
578 | return pci_lnk_ctl; | 592 | return pci_lnk_ctl; |
579 | } | 593 | } |
594 | |||
595 | void iwl_bg_monitor_recover(unsigned long data); | ||
596 | |||
580 | #ifdef CONFIG_PM | 597 | #ifdef CONFIG_PM |
581 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); | 598 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); |
582 | int iwl_pci_resume(struct pci_dev *pdev); | 599 | int iwl_pci_resume(struct pci_dev *pdev); |
@@ -625,7 +642,6 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
625 | #define STATUS_SCAN_HW 15 | 642 | #define STATUS_SCAN_HW 15 |
626 | #define STATUS_POWER_PMI 16 | 643 | #define STATUS_POWER_PMI 16 |
627 | #define STATUS_FW_ERROR 17 | 644 | #define STATUS_FW_ERROR 17 |
628 | #define STATUS_MODE_PENDING 18 | ||
629 | 645 | ||
630 | 646 | ||
631 | static inline int iwl_is_ready(struct iwl_priv *priv) | 647 | static inline int iwl_is_ready(struct iwl_priv *priv) |
@@ -672,23 +688,16 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) | |||
672 | } | 688 | } |
673 | 689 | ||
674 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | 690 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); |
675 | extern int iwl_send_bt_config(struct iwl_priv *priv); | 691 | extern void iwl_send_bt_config(struct iwl_priv *priv); |
676 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | 692 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
677 | u8 flags, bool clear); | 693 | u8 flags, bool clear); |
678 | extern int iwl_verify_ucode(struct iwl_priv *priv); | 694 | extern int iwl_verify_ucode(struct iwl_priv *priv); |
679 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 695 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
680 | struct iwl_link_quality_cmd *lq, u8 flags); | 696 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
681 | extern void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
682 | struct iwl_rx_mem_buffer *rxb); | ||
683 | extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
684 | struct iwl_rx_mem_buffer *rxb); | ||
685 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
686 | struct iwl_rx_mem_buffer *rxb); | ||
687 | void iwl_apm_stop(struct iwl_priv *priv); | 697 | void iwl_apm_stop(struct iwl_priv *priv); |
688 | int iwl_apm_stop_master(struct iwl_priv *priv); | ||
689 | int iwl_apm_init(struct iwl_priv *priv); | 698 | int iwl_apm_init(struct iwl_priv *priv); |
690 | 699 | ||
691 | void iwl_setup_rxon_timing(struct iwl_priv *priv); | 700 | void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); |
692 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 701 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
693 | { | 702 | { |
694 | return priv->cfg->ops->hcmd->rxon_assoc(priv); | 703 | return priv->cfg->ops->hcmd->rxon_assoc(priv); |
@@ -697,9 +706,10 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv) | |||
697 | { | 706 | { |
698 | return priv->cfg->ops->hcmd->commit_rxon(priv); | 707 | return priv->cfg->ops->hcmd->commit_rxon(priv); |
699 | } | 708 | } |
700 | static inline void iwlcore_config_ap(struct iwl_priv *priv) | 709 | static inline void iwlcore_config_ap(struct iwl_priv *priv, |
710 | struct ieee80211_vif *vif) | ||
701 | { | 711 | { |
702 | priv->cfg->ops->lib->config_ap(priv); | 712 | priv->cfg->ops->lib->config_ap(priv, vif); |
703 | } | 713 | } |
704 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | 714 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( |
705 | struct iwl_priv *priv, enum ieee80211_band band) | 715 | struct iwl_priv *priv, enum ieee80211_band band) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 808b7146bead..254c35ae8b38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -298,6 +298,7 @@ | |||
298 | #define CSR_HW_REV_TYPE_1000 (0x0000060) | 298 | #define CSR_HW_REV_TYPE_1000 (0x0000060) |
299 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) | 299 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) |
300 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) | 300 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) |
301 | #define CSR_HW_REV_TYPE_6x00g2 (0x00000B0) | ||
301 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) | 302 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) |
302 | 303 | ||
303 | /* EEPROM REG */ | 304 | /* EEPROM REG */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 1c7b53d511c7..5c2bcef5df0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -78,6 +78,8 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | |||
78 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 78 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
79 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | 79 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); |
80 | void iwl_dbgfs_unregister(struct iwl_priv *priv); | 80 | void iwl_dbgfs_unregister(struct iwl_priv *priv); |
81 | extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, | ||
82 | int bufsz); | ||
81 | #else | 83 | #else |
82 | static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 84 | static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) |
83 | { | 85 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index b6e1b0ebe230..9659c5d01df9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -106,6 +106,26 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ | |||
106 | .open = iwl_dbgfs_open_file_generic, \ | 106 | .open = iwl_dbgfs_open_file_generic, \ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | ||
110 | { | ||
111 | int p = 0; | ||
112 | |||
113 | p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", | ||
114 | le32_to_cpu(priv->statistics.flag)); | ||
115 | if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) | ||
116 | p += scnprintf(buf + p, bufsz - p, | ||
117 | "\tStatistics have been cleared\n"); | ||
118 | p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", | ||
119 | (le32_to_cpu(priv->statistics.flag) & | ||
120 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
121 | ? "2.4 GHz" : "5.2 GHz"); | ||
122 | p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", | ||
123 | (le32_to_cpu(priv->statistics.flag) & | ||
124 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
125 | ? "enabled" : "disabled"); | ||
126 | return p; | ||
127 | } | ||
128 | EXPORT_SYMBOL(iwl_dbgfs_statistics_flag); | ||
109 | 129 | ||
110 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | 130 | static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, |
111 | char __user *user_buf, | 131 | char __user *user_buf, |
@@ -561,8 +581,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
561 | test_bit(STATUS_POWER_PMI, &priv->status)); | 581 | test_bit(STATUS_POWER_PMI, &priv->status)); |
562 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", | 582 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", |
563 | test_bit(STATUS_FW_ERROR, &priv->status)); | 583 | test_bit(STATUS_FW_ERROR, &priv->status)); |
564 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n", | ||
565 | test_bit(STATUS_MODE_PENDING, &priv->status)); | ||
566 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 584 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
567 | } | 585 | } |
568 | 586 | ||
@@ -661,7 +679,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
661 | int pos = 0, i; | 679 | int pos = 0, i; |
662 | char buf[256]; | 680 | char buf[256]; |
663 | const size_t bufsz = sizeof(buf); | 681 | const size_t bufsz = sizeof(buf); |
664 | ssize_t ret; | ||
665 | 682 | ||
666 | for (i = 0; i < AC_NUM; i++) { | 683 | for (i = 0; i < AC_NUM; i++) { |
667 | pos += scnprintf(buf + pos, bufsz - pos, | 684 | pos += scnprintf(buf + pos, bufsz - pos, |
@@ -673,8 +690,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
673 | priv->qos_data.def_qos_parm.ac[i].aifsn, | 690 | priv->qos_data.def_qos_parm.ac[i].aifsn, |
674 | priv->qos_data.def_qos_parm.ac[i].edca_txop); | 691 | priv->qos_data.def_qos_parm.ac[i].edca_txop); |
675 | } | 692 | } |
676 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 693 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
677 | return ret; | ||
678 | } | 694 | } |
679 | 695 | ||
680 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | 696 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, |
@@ -684,7 +700,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | |||
684 | int pos = 0; | 700 | int pos = 0; |
685 | char buf[256]; | 701 | char buf[256]; |
686 | const size_t bufsz = sizeof(buf); | 702 | const size_t bufsz = sizeof(buf); |
687 | ssize_t ret; | ||
688 | 703 | ||
689 | pos += scnprintf(buf + pos, bufsz - pos, | 704 | pos += scnprintf(buf + pos, bufsz - pos, |
690 | "allow blinking: %s\n", | 705 | "allow blinking: %s\n", |
@@ -698,8 +713,7 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | |||
698 | priv->last_blink_time); | 713 | priv->last_blink_time); |
699 | } | 714 | } |
700 | 715 | ||
701 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 716 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
702 | return ret; | ||
703 | } | 717 | } |
704 | 718 | ||
705 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 719 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, |
@@ -712,7 +726,6 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | |||
712 | char buf[100]; | 726 | char buf[100]; |
713 | int pos = 0; | 727 | int pos = 0; |
714 | const size_t bufsz = sizeof(buf); | 728 | const size_t bufsz = sizeof(buf); |
715 | ssize_t ret; | ||
716 | 729 | ||
717 | pos += scnprintf(buf + pos, bufsz - pos, | 730 | pos += scnprintf(buf + pos, bufsz - pos, |
718 | "Thermal Throttling Mode: %s\n", | 731 | "Thermal Throttling Mode: %s\n", |
@@ -732,8 +745,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | |||
732 | "HT mode: %d\n", | 745 | "HT mode: %d\n", |
733 | restriction->is_ht); | 746 | restriction->is_ht); |
734 | } | 747 | } |
735 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 748 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
736 | return ret; | ||
737 | } | 749 | } |
738 | 750 | ||
739 | static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, | 751 | static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, |
@@ -770,13 +782,11 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | |||
770 | char buf[100]; | 782 | char buf[100]; |
771 | int pos = 0; | 783 | int pos = 0; |
772 | const size_t bufsz = sizeof(buf); | 784 | const size_t bufsz = sizeof(buf); |
773 | ssize_t ret; | ||
774 | 785 | ||
775 | pos += scnprintf(buf + pos, bufsz - pos, | 786 | pos += scnprintf(buf + pos, bufsz - pos, |
776 | "11n 40MHz Mode: %s\n", | 787 | "11n 40MHz Mode: %s\n", |
777 | priv->disable_ht40 ? "Disabled" : "Enabled"); | 788 | priv->disable_ht40 ? "Disabled" : "Enabled"); |
778 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 789 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
779 | return ret; | ||
780 | } | 790 | } |
781 | 791 | ||
782 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | 792 | static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, |
@@ -1044,474 +1054,13 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1044 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1054 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1045 | } | 1055 | } |
1046 | 1056 | ||
1047 | static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, | ||
1048 | int bufsz) | ||
1049 | { | ||
1050 | int p = 0; | ||
1051 | |||
1052 | p += scnprintf(buf + p, bufsz - p, | ||
1053 | "Statistics Flag(0x%X):\n", | ||
1054 | le32_to_cpu(priv->statistics.flag)); | ||
1055 | if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) | ||
1056 | p += scnprintf(buf + p, bufsz - p, | ||
1057 | "\tStatistics have been cleared\n"); | ||
1058 | p += scnprintf(buf + p, bufsz - p, | ||
1059 | "\tOperational Frequency: %s\n", | ||
1060 | (le32_to_cpu(priv->statistics.flag) & | ||
1061 | UCODE_STATISTICS_FREQUENCY_MSK) | ||
1062 | ? "2.4 GHz" : "5.2 GHz"); | ||
1063 | p += scnprintf(buf + p, bufsz - p, | ||
1064 | "\tTGj Narrow Band: %s\n", | ||
1065 | (le32_to_cpu(priv->statistics.flag) & | ||
1066 | UCODE_STATISTICS_NARROW_BAND_MSK) | ||
1067 | ? "enabled" : "disabled"); | ||
1068 | return p; | ||
1069 | } | ||
1070 | |||
1071 | static const char ucode_stats_header[] = | ||
1072 | "%-32s current acumulative delta max\n"; | ||
1073 | static const char ucode_stats_short_format[] = | ||
1074 | " %-30s %10u\n"; | ||
1075 | static const char ucode_stats_format[] = | ||
1076 | " %-30s %10u %10u %10u %10u\n"; | ||
1077 | |||
1078 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | 1057 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, |
1079 | char __user *user_buf, | 1058 | char __user *user_buf, |
1080 | size_t count, loff_t *ppos) | 1059 | size_t count, loff_t *ppos) |
1081 | { | 1060 | { |
1082 | struct iwl_priv *priv = file->private_data; | 1061 | struct iwl_priv *priv = file->private_data; |
1083 | int pos = 0; | 1062 | return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, |
1084 | char *buf; | 1063 | user_buf, count, ppos); |
1085 | int bufsz = sizeof(struct statistics_rx_phy) * 40 + | ||
1086 | sizeof(struct statistics_rx_non_phy) * 40 + | ||
1087 | sizeof(struct statistics_rx_ht_phy) * 40 + 400; | ||
1088 | ssize_t ret; | ||
1089 | struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; | ||
1090 | struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; | ||
1091 | struct statistics_rx_non_phy *general, *accum_general; | ||
1092 | struct statistics_rx_non_phy *delta_general, *max_general; | ||
1093 | struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; | ||
1094 | |||
1095 | if (!iwl_is_alive(priv)) | ||
1096 | return -EAGAIN; | ||
1097 | |||
1098 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1099 | if (!buf) { | ||
1100 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
1101 | return -ENOMEM; | ||
1102 | } | ||
1103 | |||
1104 | /* the statistic information display here is based on | ||
1105 | * the last statistics notification from uCode | ||
1106 | * might not reflect the current uCode activity | ||
1107 | */ | ||
1108 | ofdm = &priv->statistics.rx.ofdm; | ||
1109 | cck = &priv->statistics.rx.cck; | ||
1110 | general = &priv->statistics.rx.general; | ||
1111 | ht = &priv->statistics.rx.ofdm_ht; | ||
1112 | accum_ofdm = &priv->accum_statistics.rx.ofdm; | ||
1113 | accum_cck = &priv->accum_statistics.rx.cck; | ||
1114 | accum_general = &priv->accum_statistics.rx.general; | ||
1115 | accum_ht = &priv->accum_statistics.rx.ofdm_ht; | ||
1116 | delta_ofdm = &priv->delta_statistics.rx.ofdm; | ||
1117 | delta_cck = &priv->delta_statistics.rx.cck; | ||
1118 | delta_general = &priv->delta_statistics.rx.general; | ||
1119 | delta_ht = &priv->delta_statistics.rx.ofdm_ht; | ||
1120 | max_ofdm = &priv->max_delta.rx.ofdm; | ||
1121 | max_cck = &priv->max_delta.rx.cck; | ||
1122 | max_general = &priv->max_delta.rx.general; | ||
1123 | max_ht = &priv->max_delta.rx.ofdm_ht; | ||
1124 | |||
1125 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
1126 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, | ||
1127 | "Statistics_Rx - OFDM:"); | ||
1128 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1129 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), | ||
1130 | accum_ofdm->ina_cnt, | ||
1131 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); | ||
1132 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1133 | "fina_cnt:", | ||
1134 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, | ||
1135 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); | ||
1136 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1137 | "plcp_err:", | ||
1138 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, | ||
1139 | delta_ofdm->plcp_err, max_ofdm->plcp_err); | ||
1140 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1141 | "crc32_err:", | ||
1142 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, | ||
1143 | delta_ofdm->crc32_err, max_ofdm->crc32_err); | ||
1144 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1145 | "overrun_err:", | ||
1146 | le32_to_cpu(ofdm->overrun_err), | ||
1147 | accum_ofdm->overrun_err, | ||
1148 | delta_ofdm->overrun_err, max_ofdm->overrun_err); | ||
1149 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1150 | "early_overrun_err:", | ||
1151 | le32_to_cpu(ofdm->early_overrun_err), | ||
1152 | accum_ofdm->early_overrun_err, | ||
1153 | delta_ofdm->early_overrun_err, | ||
1154 | max_ofdm->early_overrun_err); | ||
1155 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1156 | "crc32_good:", | ||
1157 | le32_to_cpu(ofdm->crc32_good), | ||
1158 | accum_ofdm->crc32_good, | ||
1159 | delta_ofdm->crc32_good, max_ofdm->crc32_good); | ||
1160 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1161 | "false_alarm_cnt:", | ||
1162 | le32_to_cpu(ofdm->false_alarm_cnt), | ||
1163 | accum_ofdm->false_alarm_cnt, | ||
1164 | delta_ofdm->false_alarm_cnt, | ||
1165 | max_ofdm->false_alarm_cnt); | ||
1166 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1167 | "fina_sync_err_cnt:", | ||
1168 | le32_to_cpu(ofdm->fina_sync_err_cnt), | ||
1169 | accum_ofdm->fina_sync_err_cnt, | ||
1170 | delta_ofdm->fina_sync_err_cnt, | ||
1171 | max_ofdm->fina_sync_err_cnt); | ||
1172 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1173 | "sfd_timeout:", | ||
1174 | le32_to_cpu(ofdm->sfd_timeout), | ||
1175 | accum_ofdm->sfd_timeout, | ||
1176 | delta_ofdm->sfd_timeout, | ||
1177 | max_ofdm->sfd_timeout); | ||
1178 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1179 | "fina_timeout:", | ||
1180 | le32_to_cpu(ofdm->fina_timeout), | ||
1181 | accum_ofdm->fina_timeout, | ||
1182 | delta_ofdm->fina_timeout, | ||
1183 | max_ofdm->fina_timeout); | ||
1184 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1185 | "unresponded_rts:", | ||
1186 | le32_to_cpu(ofdm->unresponded_rts), | ||
1187 | accum_ofdm->unresponded_rts, | ||
1188 | delta_ofdm->unresponded_rts, | ||
1189 | max_ofdm->unresponded_rts); | ||
1190 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1191 | "rxe_frame_lmt_ovrun:", | ||
1192 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | ||
1193 | accum_ofdm->rxe_frame_limit_overrun, | ||
1194 | delta_ofdm->rxe_frame_limit_overrun, | ||
1195 | max_ofdm->rxe_frame_limit_overrun); | ||
1196 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1197 | "sent_ack_cnt:", | ||
1198 | le32_to_cpu(ofdm->sent_ack_cnt), | ||
1199 | accum_ofdm->sent_ack_cnt, | ||
1200 | delta_ofdm->sent_ack_cnt, | ||
1201 | max_ofdm->sent_ack_cnt); | ||
1202 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1203 | "sent_cts_cnt:", | ||
1204 | le32_to_cpu(ofdm->sent_cts_cnt), | ||
1205 | accum_ofdm->sent_cts_cnt, | ||
1206 | delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); | ||
1207 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1208 | "sent_ba_rsp_cnt:", | ||
1209 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), | ||
1210 | accum_ofdm->sent_ba_rsp_cnt, | ||
1211 | delta_ofdm->sent_ba_rsp_cnt, | ||
1212 | max_ofdm->sent_ba_rsp_cnt); | ||
1213 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1214 | "dsp_self_kill:", | ||
1215 | le32_to_cpu(ofdm->dsp_self_kill), | ||
1216 | accum_ofdm->dsp_self_kill, | ||
1217 | delta_ofdm->dsp_self_kill, | ||
1218 | max_ofdm->dsp_self_kill); | ||
1219 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1220 | "mh_format_err:", | ||
1221 | le32_to_cpu(ofdm->mh_format_err), | ||
1222 | accum_ofdm->mh_format_err, | ||
1223 | delta_ofdm->mh_format_err, | ||
1224 | max_ofdm->mh_format_err); | ||
1225 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1226 | "re_acq_main_rssi_sum:", | ||
1227 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), | ||
1228 | accum_ofdm->re_acq_main_rssi_sum, | ||
1229 | delta_ofdm->re_acq_main_rssi_sum, | ||
1230 | max_ofdm->re_acq_main_rssi_sum); | ||
1231 | |||
1232 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, | ||
1233 | "Statistics_Rx - CCK:"); | ||
1234 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1235 | "ina_cnt:", | ||
1236 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, | ||
1237 | delta_cck->ina_cnt, max_cck->ina_cnt); | ||
1238 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1239 | "fina_cnt:", | ||
1240 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, | ||
1241 | delta_cck->fina_cnt, max_cck->fina_cnt); | ||
1242 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1243 | "plcp_err:", | ||
1244 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, | ||
1245 | delta_cck->plcp_err, max_cck->plcp_err); | ||
1246 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1247 | "crc32_err:", | ||
1248 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, | ||
1249 | delta_cck->crc32_err, max_cck->crc32_err); | ||
1250 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1251 | "overrun_err:", | ||
1252 | le32_to_cpu(cck->overrun_err), | ||
1253 | accum_cck->overrun_err, | ||
1254 | delta_cck->overrun_err, max_cck->overrun_err); | ||
1255 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1256 | "early_overrun_err:", | ||
1257 | le32_to_cpu(cck->early_overrun_err), | ||
1258 | accum_cck->early_overrun_err, | ||
1259 | delta_cck->early_overrun_err, | ||
1260 | max_cck->early_overrun_err); | ||
1261 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1262 | "crc32_good:", | ||
1263 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, | ||
1264 | delta_cck->crc32_good, | ||
1265 | max_cck->crc32_good); | ||
1266 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1267 | "false_alarm_cnt:", | ||
1268 | le32_to_cpu(cck->false_alarm_cnt), | ||
1269 | accum_cck->false_alarm_cnt, | ||
1270 | delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); | ||
1271 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1272 | "fina_sync_err_cnt:", | ||
1273 | le32_to_cpu(cck->fina_sync_err_cnt), | ||
1274 | accum_cck->fina_sync_err_cnt, | ||
1275 | delta_cck->fina_sync_err_cnt, | ||
1276 | max_cck->fina_sync_err_cnt); | ||
1277 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1278 | "sfd_timeout:", | ||
1279 | le32_to_cpu(cck->sfd_timeout), | ||
1280 | accum_cck->sfd_timeout, | ||
1281 | delta_cck->sfd_timeout, max_cck->sfd_timeout); | ||
1282 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1283 | "fina_timeout:", | ||
1284 | le32_to_cpu(cck->fina_timeout), | ||
1285 | accum_cck->fina_timeout, | ||
1286 | delta_cck->fina_timeout, max_cck->fina_timeout); | ||
1287 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1288 | "unresponded_rts:", | ||
1289 | le32_to_cpu(cck->unresponded_rts), | ||
1290 | accum_cck->unresponded_rts, | ||
1291 | delta_cck->unresponded_rts, | ||
1292 | max_cck->unresponded_rts); | ||
1293 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1294 | "rxe_frame_lmt_ovrun:", | ||
1295 | le32_to_cpu(cck->rxe_frame_limit_overrun), | ||
1296 | accum_cck->rxe_frame_limit_overrun, | ||
1297 | delta_cck->rxe_frame_limit_overrun, | ||
1298 | max_cck->rxe_frame_limit_overrun); | ||
1299 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1300 | "sent_ack_cnt:", | ||
1301 | le32_to_cpu(cck->sent_ack_cnt), | ||
1302 | accum_cck->sent_ack_cnt, | ||
1303 | delta_cck->sent_ack_cnt, | ||
1304 | max_cck->sent_ack_cnt); | ||
1305 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1306 | "sent_cts_cnt:", | ||
1307 | le32_to_cpu(cck->sent_cts_cnt), | ||
1308 | accum_cck->sent_cts_cnt, | ||
1309 | delta_cck->sent_cts_cnt, | ||
1310 | max_cck->sent_cts_cnt); | ||
1311 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1312 | "sent_ba_rsp_cnt:", | ||
1313 | le32_to_cpu(cck->sent_ba_rsp_cnt), | ||
1314 | accum_cck->sent_ba_rsp_cnt, | ||
1315 | delta_cck->sent_ba_rsp_cnt, | ||
1316 | max_cck->sent_ba_rsp_cnt); | ||
1317 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1318 | "dsp_self_kill:", | ||
1319 | le32_to_cpu(cck->dsp_self_kill), | ||
1320 | accum_cck->dsp_self_kill, | ||
1321 | delta_cck->dsp_self_kill, | ||
1322 | max_cck->dsp_self_kill); | ||
1323 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1324 | "mh_format_err:", | ||
1325 | le32_to_cpu(cck->mh_format_err), | ||
1326 | accum_cck->mh_format_err, | ||
1327 | delta_cck->mh_format_err, max_cck->mh_format_err); | ||
1328 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1329 | "re_acq_main_rssi_sum:", | ||
1330 | le32_to_cpu(cck->re_acq_main_rssi_sum), | ||
1331 | accum_cck->re_acq_main_rssi_sum, | ||
1332 | delta_cck->re_acq_main_rssi_sum, | ||
1333 | max_cck->re_acq_main_rssi_sum); | ||
1334 | |||
1335 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, | ||
1336 | "Statistics_Rx - GENERAL:"); | ||
1337 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1338 | "bogus_cts:", | ||
1339 | le32_to_cpu(general->bogus_cts), | ||
1340 | accum_general->bogus_cts, | ||
1341 | delta_general->bogus_cts, max_general->bogus_cts); | ||
1342 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1343 | "bogus_ack:", | ||
1344 | le32_to_cpu(general->bogus_ack), | ||
1345 | accum_general->bogus_ack, | ||
1346 | delta_general->bogus_ack, max_general->bogus_ack); | ||
1347 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1348 | "non_bssid_frames:", | ||
1349 | le32_to_cpu(general->non_bssid_frames), | ||
1350 | accum_general->non_bssid_frames, | ||
1351 | delta_general->non_bssid_frames, | ||
1352 | max_general->non_bssid_frames); | ||
1353 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1354 | "filtered_frames:", | ||
1355 | le32_to_cpu(general->filtered_frames), | ||
1356 | accum_general->filtered_frames, | ||
1357 | delta_general->filtered_frames, | ||
1358 | max_general->filtered_frames); | ||
1359 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1360 | "non_channel_beacons:", | ||
1361 | le32_to_cpu(general->non_channel_beacons), | ||
1362 | accum_general->non_channel_beacons, | ||
1363 | delta_general->non_channel_beacons, | ||
1364 | max_general->non_channel_beacons); | ||
1365 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1366 | "channel_beacons:", | ||
1367 | le32_to_cpu(general->channel_beacons), | ||
1368 | accum_general->channel_beacons, | ||
1369 | delta_general->channel_beacons, | ||
1370 | max_general->channel_beacons); | ||
1371 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1372 | "num_missed_bcon:", | ||
1373 | le32_to_cpu(general->num_missed_bcon), | ||
1374 | accum_general->num_missed_bcon, | ||
1375 | delta_general->num_missed_bcon, | ||
1376 | max_general->num_missed_bcon); | ||
1377 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1378 | "adc_rx_saturation_time:", | ||
1379 | le32_to_cpu(general->adc_rx_saturation_time), | ||
1380 | accum_general->adc_rx_saturation_time, | ||
1381 | delta_general->adc_rx_saturation_time, | ||
1382 | max_general->adc_rx_saturation_time); | ||
1383 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1384 | "ina_detect_search_tm:", | ||
1385 | le32_to_cpu(general->ina_detection_search_time), | ||
1386 | accum_general->ina_detection_search_time, | ||
1387 | delta_general->ina_detection_search_time, | ||
1388 | max_general->ina_detection_search_time); | ||
1389 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1390 | "beacon_silence_rssi_a:", | ||
1391 | le32_to_cpu(general->beacon_silence_rssi_a), | ||
1392 | accum_general->beacon_silence_rssi_a, | ||
1393 | delta_general->beacon_silence_rssi_a, | ||
1394 | max_general->beacon_silence_rssi_a); | ||
1395 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1396 | "beacon_silence_rssi_b:", | ||
1397 | le32_to_cpu(general->beacon_silence_rssi_b), | ||
1398 | accum_general->beacon_silence_rssi_b, | ||
1399 | delta_general->beacon_silence_rssi_b, | ||
1400 | max_general->beacon_silence_rssi_b); | ||
1401 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1402 | "beacon_silence_rssi_c:", | ||
1403 | le32_to_cpu(general->beacon_silence_rssi_c), | ||
1404 | accum_general->beacon_silence_rssi_c, | ||
1405 | delta_general->beacon_silence_rssi_c, | ||
1406 | max_general->beacon_silence_rssi_c); | ||
1407 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1408 | "interference_data_flag:", | ||
1409 | le32_to_cpu(general->interference_data_flag), | ||
1410 | accum_general->interference_data_flag, | ||
1411 | delta_general->interference_data_flag, | ||
1412 | max_general->interference_data_flag); | ||
1413 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1414 | "channel_load:", | ||
1415 | le32_to_cpu(general->channel_load), | ||
1416 | accum_general->channel_load, | ||
1417 | delta_general->channel_load, | ||
1418 | max_general->channel_load); | ||
1419 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1420 | "dsp_false_alarms:", | ||
1421 | le32_to_cpu(general->dsp_false_alarms), | ||
1422 | accum_general->dsp_false_alarms, | ||
1423 | delta_general->dsp_false_alarms, | ||
1424 | max_general->dsp_false_alarms); | ||
1425 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1426 | "beacon_rssi_a:", | ||
1427 | le32_to_cpu(general->beacon_rssi_a), | ||
1428 | accum_general->beacon_rssi_a, | ||
1429 | delta_general->beacon_rssi_a, | ||
1430 | max_general->beacon_rssi_a); | ||
1431 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1432 | "beacon_rssi_b:", | ||
1433 | le32_to_cpu(general->beacon_rssi_b), | ||
1434 | accum_general->beacon_rssi_b, | ||
1435 | delta_general->beacon_rssi_b, | ||
1436 | max_general->beacon_rssi_b); | ||
1437 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1438 | "beacon_rssi_c:", | ||
1439 | le32_to_cpu(general->beacon_rssi_c), | ||
1440 | accum_general->beacon_rssi_c, | ||
1441 | delta_general->beacon_rssi_c, | ||
1442 | max_general->beacon_rssi_c); | ||
1443 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1444 | "beacon_energy_a:", | ||
1445 | le32_to_cpu(general->beacon_energy_a), | ||
1446 | accum_general->beacon_energy_a, | ||
1447 | delta_general->beacon_energy_a, | ||
1448 | max_general->beacon_energy_a); | ||
1449 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1450 | "beacon_energy_b:", | ||
1451 | le32_to_cpu(general->beacon_energy_b), | ||
1452 | accum_general->beacon_energy_b, | ||
1453 | delta_general->beacon_energy_b, | ||
1454 | max_general->beacon_energy_b); | ||
1455 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1456 | "beacon_energy_c:", | ||
1457 | le32_to_cpu(general->beacon_energy_c), | ||
1458 | accum_general->beacon_energy_c, | ||
1459 | delta_general->beacon_energy_c, | ||
1460 | max_general->beacon_energy_c); | ||
1461 | |||
1462 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); | ||
1463 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, | ||
1464 | "Statistics_Rx - OFDM_HT:"); | ||
1465 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1466 | "plcp_err:", | ||
1467 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, | ||
1468 | delta_ht->plcp_err, max_ht->plcp_err); | ||
1469 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1470 | "overrun_err:", | ||
1471 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, | ||
1472 | delta_ht->overrun_err, max_ht->overrun_err); | ||
1473 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1474 | "early_overrun_err:", | ||
1475 | le32_to_cpu(ht->early_overrun_err), | ||
1476 | accum_ht->early_overrun_err, | ||
1477 | delta_ht->early_overrun_err, | ||
1478 | max_ht->early_overrun_err); | ||
1479 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1480 | "crc32_good:", | ||
1481 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, | ||
1482 | delta_ht->crc32_good, max_ht->crc32_good); | ||
1483 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1484 | "crc32_err:", | ||
1485 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, | ||
1486 | delta_ht->crc32_err, max_ht->crc32_err); | ||
1487 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1488 | "mh_format_err:", | ||
1489 | le32_to_cpu(ht->mh_format_err), | ||
1490 | accum_ht->mh_format_err, | ||
1491 | delta_ht->mh_format_err, max_ht->mh_format_err); | ||
1492 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1493 | "agg_crc32_good:", | ||
1494 | le32_to_cpu(ht->agg_crc32_good), | ||
1495 | accum_ht->agg_crc32_good, | ||
1496 | delta_ht->agg_crc32_good, max_ht->agg_crc32_good); | ||
1497 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1498 | "agg_mpdu_cnt:", | ||
1499 | le32_to_cpu(ht->agg_mpdu_cnt), | ||
1500 | accum_ht->agg_mpdu_cnt, | ||
1501 | delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); | ||
1502 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1503 | "agg_cnt:", | ||
1504 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, | ||
1505 | delta_ht->agg_cnt, max_ht->agg_cnt); | ||
1506 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1507 | "unsupport_mcs:", | ||
1508 | le32_to_cpu(ht->unsupport_mcs), | ||
1509 | accum_ht->unsupport_mcs, | ||
1510 | delta_ht->unsupport_mcs, max_ht->unsupport_mcs); | ||
1511 | |||
1512 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1513 | kfree(buf); | ||
1514 | return ret; | ||
1515 | } | 1064 | } |
1516 | 1065 | ||
1517 | static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | 1066 | static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, |
@@ -1519,173 +1068,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1519 | size_t count, loff_t *ppos) | 1068 | size_t count, loff_t *ppos) |
1520 | { | 1069 | { |
1521 | struct iwl_priv *priv = file->private_data; | 1070 | struct iwl_priv *priv = file->private_data; |
1522 | int pos = 0; | 1071 | return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, |
1523 | char *buf; | 1072 | user_buf, count, ppos); |
1524 | int bufsz = (sizeof(struct statistics_tx) * 48) + 250; | ||
1525 | ssize_t ret; | ||
1526 | struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; | ||
1527 | |||
1528 | if (!iwl_is_alive(priv)) | ||
1529 | return -EAGAIN; | ||
1530 | |||
1531 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1532 | if (!buf) { | ||
1533 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
1534 | return -ENOMEM; | ||
1535 | } | ||
1536 | |||
1537 | /* the statistic information display here is based on | ||
1538 | * the last statistics notification from uCode | ||
1539 | * might not reflect the current uCode activity | ||
1540 | */ | ||
1541 | tx = &priv->statistics.tx; | ||
1542 | accum_tx = &priv->accum_statistics.tx; | ||
1543 | delta_tx = &priv->delta_statistics.tx; | ||
1544 | max_tx = &priv->max_delta.tx; | ||
1545 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
1546 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, | ||
1547 | "Statistics_Tx:"); | ||
1548 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1549 | "preamble:", | ||
1550 | le32_to_cpu(tx->preamble_cnt), | ||
1551 | accum_tx->preamble_cnt, | ||
1552 | delta_tx->preamble_cnt, max_tx->preamble_cnt); | ||
1553 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1554 | "rx_detected_cnt:", | ||
1555 | le32_to_cpu(tx->rx_detected_cnt), | ||
1556 | accum_tx->rx_detected_cnt, | ||
1557 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); | ||
1558 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1559 | "bt_prio_defer_cnt:", | ||
1560 | le32_to_cpu(tx->bt_prio_defer_cnt), | ||
1561 | accum_tx->bt_prio_defer_cnt, | ||
1562 | delta_tx->bt_prio_defer_cnt, | ||
1563 | max_tx->bt_prio_defer_cnt); | ||
1564 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1565 | "bt_prio_kill_cnt:", | ||
1566 | le32_to_cpu(tx->bt_prio_kill_cnt), | ||
1567 | accum_tx->bt_prio_kill_cnt, | ||
1568 | delta_tx->bt_prio_kill_cnt, | ||
1569 | max_tx->bt_prio_kill_cnt); | ||
1570 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1571 | "few_bytes_cnt:", | ||
1572 | le32_to_cpu(tx->few_bytes_cnt), | ||
1573 | accum_tx->few_bytes_cnt, | ||
1574 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); | ||
1575 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1576 | "cts_timeout:", | ||
1577 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, | ||
1578 | delta_tx->cts_timeout, max_tx->cts_timeout); | ||
1579 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1580 | "ack_timeout:", | ||
1581 | le32_to_cpu(tx->ack_timeout), | ||
1582 | accum_tx->ack_timeout, | ||
1583 | delta_tx->ack_timeout, max_tx->ack_timeout); | ||
1584 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1585 | "expected_ack_cnt:", | ||
1586 | le32_to_cpu(tx->expected_ack_cnt), | ||
1587 | accum_tx->expected_ack_cnt, | ||
1588 | delta_tx->expected_ack_cnt, | ||
1589 | max_tx->expected_ack_cnt); | ||
1590 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1591 | "actual_ack_cnt:", | ||
1592 | le32_to_cpu(tx->actual_ack_cnt), | ||
1593 | accum_tx->actual_ack_cnt, | ||
1594 | delta_tx->actual_ack_cnt, | ||
1595 | max_tx->actual_ack_cnt); | ||
1596 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1597 | "dump_msdu_cnt:", | ||
1598 | le32_to_cpu(tx->dump_msdu_cnt), | ||
1599 | accum_tx->dump_msdu_cnt, | ||
1600 | delta_tx->dump_msdu_cnt, | ||
1601 | max_tx->dump_msdu_cnt); | ||
1602 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1603 | "abort_nxt_frame_mismatch:", | ||
1604 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), | ||
1605 | accum_tx->burst_abort_next_frame_mismatch_cnt, | ||
1606 | delta_tx->burst_abort_next_frame_mismatch_cnt, | ||
1607 | max_tx->burst_abort_next_frame_mismatch_cnt); | ||
1608 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1609 | "abort_missing_nxt_frame:", | ||
1610 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), | ||
1611 | accum_tx->burst_abort_missing_next_frame_cnt, | ||
1612 | delta_tx->burst_abort_missing_next_frame_cnt, | ||
1613 | max_tx->burst_abort_missing_next_frame_cnt); | ||
1614 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1615 | "cts_timeout_collision:", | ||
1616 | le32_to_cpu(tx->cts_timeout_collision), | ||
1617 | accum_tx->cts_timeout_collision, | ||
1618 | delta_tx->cts_timeout_collision, | ||
1619 | max_tx->cts_timeout_collision); | ||
1620 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1621 | "ack_ba_timeout_collision:", | ||
1622 | le32_to_cpu(tx->ack_or_ba_timeout_collision), | ||
1623 | accum_tx->ack_or_ba_timeout_collision, | ||
1624 | delta_tx->ack_or_ba_timeout_collision, | ||
1625 | max_tx->ack_or_ba_timeout_collision); | ||
1626 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1627 | "agg ba_timeout:", | ||
1628 | le32_to_cpu(tx->agg.ba_timeout), | ||
1629 | accum_tx->agg.ba_timeout, | ||
1630 | delta_tx->agg.ba_timeout, | ||
1631 | max_tx->agg.ba_timeout); | ||
1632 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1633 | "agg ba_resched_frames:", | ||
1634 | le32_to_cpu(tx->agg.ba_reschedule_frames), | ||
1635 | accum_tx->agg.ba_reschedule_frames, | ||
1636 | delta_tx->agg.ba_reschedule_frames, | ||
1637 | max_tx->agg.ba_reschedule_frames); | ||
1638 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1639 | "agg scd_query_agg_frame:", | ||
1640 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), | ||
1641 | accum_tx->agg.scd_query_agg_frame_cnt, | ||
1642 | delta_tx->agg.scd_query_agg_frame_cnt, | ||
1643 | max_tx->agg.scd_query_agg_frame_cnt); | ||
1644 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1645 | "agg scd_query_no_agg:", | ||
1646 | le32_to_cpu(tx->agg.scd_query_no_agg), | ||
1647 | accum_tx->agg.scd_query_no_agg, | ||
1648 | delta_tx->agg.scd_query_no_agg, | ||
1649 | max_tx->agg.scd_query_no_agg); | ||
1650 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1651 | "agg scd_query_agg:", | ||
1652 | le32_to_cpu(tx->agg.scd_query_agg), | ||
1653 | accum_tx->agg.scd_query_agg, | ||
1654 | delta_tx->agg.scd_query_agg, | ||
1655 | max_tx->agg.scd_query_agg); | ||
1656 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1657 | "agg scd_query_mismatch:", | ||
1658 | le32_to_cpu(tx->agg.scd_query_mismatch), | ||
1659 | accum_tx->agg.scd_query_mismatch, | ||
1660 | delta_tx->agg.scd_query_mismatch, | ||
1661 | max_tx->agg.scd_query_mismatch); | ||
1662 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1663 | "agg frame_not_ready:", | ||
1664 | le32_to_cpu(tx->agg.frame_not_ready), | ||
1665 | accum_tx->agg.frame_not_ready, | ||
1666 | delta_tx->agg.frame_not_ready, | ||
1667 | max_tx->agg.frame_not_ready); | ||
1668 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1669 | "agg underrun:", | ||
1670 | le32_to_cpu(tx->agg.underrun), | ||
1671 | accum_tx->agg.underrun, | ||
1672 | delta_tx->agg.underrun, max_tx->agg.underrun); | ||
1673 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1674 | "agg bt_prio_kill:", | ||
1675 | le32_to_cpu(tx->agg.bt_prio_kill), | ||
1676 | accum_tx->agg.bt_prio_kill, | ||
1677 | delta_tx->agg.bt_prio_kill, | ||
1678 | max_tx->agg.bt_prio_kill); | ||
1679 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1680 | "agg rx_ba_rsp_cnt:", | ||
1681 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), | ||
1682 | accum_tx->agg.rx_ba_rsp_cnt, | ||
1683 | delta_tx->agg.rx_ba_rsp_cnt, | ||
1684 | max_tx->agg.rx_ba_rsp_cnt); | ||
1685 | |||
1686 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1687 | kfree(buf); | ||
1688 | return ret; | ||
1689 | } | 1073 | } |
1690 | 1074 | ||
1691 | static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | 1075 | static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, |
@@ -1693,107 +1077,8 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1693 | size_t count, loff_t *ppos) | 1077 | size_t count, loff_t *ppos) |
1694 | { | 1078 | { |
1695 | struct iwl_priv *priv = file->private_data; | 1079 | struct iwl_priv *priv = file->private_data; |
1696 | int pos = 0; | 1080 | return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, |
1697 | char *buf; | 1081 | user_buf, count, ppos); |
1698 | int bufsz = sizeof(struct statistics_general) * 10 + 300; | ||
1699 | ssize_t ret; | ||
1700 | struct statistics_general *general, *accum_general; | ||
1701 | struct statistics_general *delta_general, *max_general; | ||
1702 | struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; | ||
1703 | struct statistics_div *div, *accum_div, *delta_div, *max_div; | ||
1704 | |||
1705 | if (!iwl_is_alive(priv)) | ||
1706 | return -EAGAIN; | ||
1707 | |||
1708 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1709 | if (!buf) { | ||
1710 | IWL_ERR(priv, "Can not allocate Buffer\n"); | ||
1711 | return -ENOMEM; | ||
1712 | } | ||
1713 | |||
1714 | /* the statistic information display here is based on | ||
1715 | * the last statistics notification from uCode | ||
1716 | * might not reflect the current uCode activity | ||
1717 | */ | ||
1718 | general = &priv->statistics.general; | ||
1719 | dbg = &priv->statistics.general.dbg; | ||
1720 | div = &priv->statistics.general.div; | ||
1721 | accum_general = &priv->accum_statistics.general; | ||
1722 | delta_general = &priv->delta_statistics.general; | ||
1723 | max_general = &priv->max_delta.general; | ||
1724 | accum_dbg = &priv->accum_statistics.general.dbg; | ||
1725 | delta_dbg = &priv->delta_statistics.general.dbg; | ||
1726 | max_dbg = &priv->max_delta.general.dbg; | ||
1727 | accum_div = &priv->accum_statistics.general.div; | ||
1728 | delta_div = &priv->delta_statistics.general.div; | ||
1729 | max_div = &priv->max_delta.general.div; | ||
1730 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | ||
1731 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, | ||
1732 | "Statistics_General:"); | ||
1733 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, | ||
1734 | "temperature:", | ||
1735 | le32_to_cpu(general->temperature)); | ||
1736 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, | ||
1737 | "temperature_m:", | ||
1738 | le32_to_cpu(general->temperature_m)); | ||
1739 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1740 | "burst_check:", | ||
1741 | le32_to_cpu(dbg->burst_check), | ||
1742 | accum_dbg->burst_check, | ||
1743 | delta_dbg->burst_check, max_dbg->burst_check); | ||
1744 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1745 | "burst_count:", | ||
1746 | le32_to_cpu(dbg->burst_count), | ||
1747 | accum_dbg->burst_count, | ||
1748 | delta_dbg->burst_count, max_dbg->burst_count); | ||
1749 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1750 | "sleep_time:", | ||
1751 | le32_to_cpu(general->sleep_time), | ||
1752 | accum_general->sleep_time, | ||
1753 | delta_general->sleep_time, max_general->sleep_time); | ||
1754 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1755 | "slots_out:", | ||
1756 | le32_to_cpu(general->slots_out), | ||
1757 | accum_general->slots_out, | ||
1758 | delta_general->slots_out, max_general->slots_out); | ||
1759 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1760 | "slots_idle:", | ||
1761 | le32_to_cpu(general->slots_idle), | ||
1762 | accum_general->slots_idle, | ||
1763 | delta_general->slots_idle, max_general->slots_idle); | ||
1764 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | ||
1765 | le32_to_cpu(general->ttl_timestamp)); | ||
1766 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1767 | "tx_on_a:", | ||
1768 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, | ||
1769 | delta_div->tx_on_a, max_div->tx_on_a); | ||
1770 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1771 | "tx_on_b:", | ||
1772 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, | ||
1773 | delta_div->tx_on_b, max_div->tx_on_b); | ||
1774 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1775 | "exec_time:", | ||
1776 | le32_to_cpu(div->exec_time), accum_div->exec_time, | ||
1777 | delta_div->exec_time, max_div->exec_time); | ||
1778 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1779 | "probe_time:", | ||
1780 | le32_to_cpu(div->probe_time), accum_div->probe_time, | ||
1781 | delta_div->probe_time, max_div->probe_time); | ||
1782 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1783 | "rx_enable_counter:", | ||
1784 | le32_to_cpu(general->rx_enable_counter), | ||
1785 | accum_general->rx_enable_counter, | ||
1786 | delta_general->rx_enable_counter, | ||
1787 | max_general->rx_enable_counter); | ||
1788 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | ||
1789 | "num_of_sos_states:", | ||
1790 | le32_to_cpu(general->num_of_sos_states), | ||
1791 | accum_general->num_of_sos_states, | ||
1792 | delta_general->num_of_sos_states, | ||
1793 | max_general->num_of_sos_states); | ||
1794 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1795 | kfree(buf); | ||
1796 | return ret; | ||
1797 | } | 1082 | } |
1798 | 1083 | ||
1799 | static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, | 1084 | static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, |
@@ -1935,46 +1220,6 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, | |||
1935 | return ret; | 1220 | return ret; |
1936 | } | 1221 | } |
1937 | 1222 | ||
1938 | static ssize_t iwl_dbgfs_tx_power_read(struct file *file, | ||
1939 | char __user *user_buf, | ||
1940 | size_t count, loff_t *ppos) { | ||
1941 | |||
1942 | struct iwl_priv *priv = file->private_data; | ||
1943 | char buf[128]; | ||
1944 | int pos = 0; | ||
1945 | const size_t bufsz = sizeof(buf); | ||
1946 | struct statistics_tx *tx; | ||
1947 | |||
1948 | if (!iwl_is_alive(priv)) | ||
1949 | pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); | ||
1950 | else { | ||
1951 | tx = &priv->statistics.tx; | ||
1952 | if (tx->tx_power.ant_a || | ||
1953 | tx->tx_power.ant_b || | ||
1954 | tx->tx_power.ant_c) { | ||
1955 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1956 | "tx power: (1/2 dB step)\n"); | ||
1957 | if ((priv->cfg->valid_tx_ant & ANT_A) && | ||
1958 | tx->tx_power.ant_a) | ||
1959 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1960 | "\tantenna A: 0x%X\n", | ||
1961 | tx->tx_power.ant_a); | ||
1962 | if ((priv->cfg->valid_tx_ant & ANT_B) && | ||
1963 | tx->tx_power.ant_b) | ||
1964 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1965 | "\tantenna B: 0x%X\n", | ||
1966 | tx->tx_power.ant_b); | ||
1967 | if ((priv->cfg->valid_tx_ant & ANT_C) && | ||
1968 | tx->tx_power.ant_c) | ||
1969 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1970 | "\tantenna C: 0x%X\n", | ||
1971 | tx->tx_power.ant_c); | ||
1972 | } else | ||
1973 | pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); | ||
1974 | } | ||
1975 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1976 | } | ||
1977 | |||
1978 | static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | 1223 | static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, |
1979 | char __user *user_buf, | 1224 | char __user *user_buf, |
1980 | size_t count, loff_t *ppos) | 1225 | size_t count, loff_t *ppos) |
@@ -2052,7 +1297,6 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | |||
2052 | int pos = 0; | 1297 | int pos = 0; |
2053 | char buf[128]; | 1298 | char buf[128]; |
2054 | const size_t bufsz = sizeof(buf); | 1299 | const size_t bufsz = sizeof(buf); |
2055 | ssize_t ret; | ||
2056 | 1300 | ||
2057 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | 1301 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", |
2058 | priv->event_log.ucode_trace ? "On" : "Off"); | 1302 | priv->event_log.ucode_trace ? "On" : "Off"); |
@@ -2063,8 +1307,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | |||
2063 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | 1307 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", |
2064 | priv->event_log.wraps_more_count); | 1308 | priv->event_log.wraps_more_count); |
2065 | 1309 | ||
2066 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1310 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2067 | return ret; | ||
2068 | } | 1311 | } |
2069 | 1312 | ||
2070 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | 1313 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, |
@@ -2096,6 +1339,31 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | |||
2096 | return count; | 1339 | return count; |
2097 | } | 1340 | } |
2098 | 1341 | ||
1342 | static ssize_t iwl_dbgfs_rxon_flags_read(struct file *file, | ||
1343 | char __user *user_buf, | ||
1344 | size_t count, loff_t *ppos) { | ||
1345 | |||
1346 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
1347 | int len = 0; | ||
1348 | char buf[20]; | ||
1349 | |||
1350 | len = sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.flags)); | ||
1351 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1352 | } | ||
1353 | |||
1354 | static ssize_t iwl_dbgfs_rxon_filter_flags_read(struct file *file, | ||
1355 | char __user *user_buf, | ||
1356 | size_t count, loff_t *ppos) { | ||
1357 | |||
1358 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
1359 | int len = 0; | ||
1360 | char buf[20]; | ||
1361 | |||
1362 | len = sprintf(buf, "0x%04X\n", | ||
1363 | le32_to_cpu(priv->active_rxon.filter_flags)); | ||
1364 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1365 | } | ||
1366 | |||
2099 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | 1367 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, |
2100 | char __user *user_buf, | 1368 | char __user *user_buf, |
2101 | size_t count, loff_t *ppos) | 1369 | size_t count, loff_t *ppos) |
@@ -2125,13 +1393,11 @@ static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, | |||
2125 | int pos = 0; | 1393 | int pos = 0; |
2126 | char buf[12]; | 1394 | char buf[12]; |
2127 | const size_t bufsz = sizeof(buf); | 1395 | const size_t bufsz = sizeof(buf); |
2128 | ssize_t ret; | ||
2129 | 1396 | ||
2130 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | 1397 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", |
2131 | priv->missed_beacon_threshold); | 1398 | priv->missed_beacon_threshold); |
2132 | 1399 | ||
2133 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1400 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2134 | return ret; | ||
2135 | } | 1401 | } |
2136 | 1402 | ||
2137 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | 1403 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, |
@@ -2160,27 +1426,6 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | |||
2160 | return count; | 1426 | return count; |
2161 | } | 1427 | } |
2162 | 1428 | ||
2163 | static ssize_t iwl_dbgfs_internal_scan_write(struct file *file, | ||
2164 | const char __user *user_buf, | ||
2165 | size_t count, loff_t *ppos) | ||
2166 | { | ||
2167 | struct iwl_priv *priv = file->private_data; | ||
2168 | char buf[8]; | ||
2169 | int buf_size; | ||
2170 | int scan; | ||
2171 | |||
2172 | memset(buf, 0, sizeof(buf)); | ||
2173 | buf_size = min(count, sizeof(buf) - 1); | ||
2174 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2175 | return -EFAULT; | ||
2176 | if (sscanf(buf, "%d", &scan) != 1) | ||
2177 | return -EINVAL; | ||
2178 | |||
2179 | iwl_internal_short_hw_scan(priv); | ||
2180 | |||
2181 | return count; | ||
2182 | } | ||
2183 | |||
2184 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | 1429 | static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, |
2185 | char __user *user_buf, | 1430 | char __user *user_buf, |
2186 | size_t count, loff_t *ppos) { | 1431 | size_t count, loff_t *ppos) { |
@@ -2189,13 +1434,11 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, | |||
2189 | int pos = 0; | 1434 | int pos = 0; |
2190 | char buf[12]; | 1435 | char buf[12]; |
2191 | const size_t bufsz = sizeof(buf); | 1436 | const size_t bufsz = sizeof(buf); |
2192 | ssize_t ret; | ||
2193 | 1437 | ||
2194 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | 1438 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", |
2195 | priv->cfg->plcp_delta_threshold); | 1439 | priv->cfg->plcp_delta_threshold); |
2196 | 1440 | ||
2197 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1441 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
2198 | return ret; | ||
2199 | } | 1442 | } |
2200 | 1443 | ||
2201 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | 1444 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, |
@@ -2288,7 +1531,6 @@ DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | |||
2288 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | 1531 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); |
2289 | DEBUGFS_READ_FILE_OPS(sensitivity); | 1532 | DEBUGFS_READ_FILE_OPS(sensitivity); |
2290 | DEBUGFS_READ_FILE_OPS(chain_noise); | 1533 | DEBUGFS_READ_FILE_OPS(chain_noise); |
2291 | DEBUGFS_READ_FILE_OPS(tx_power); | ||
2292 | DEBUGFS_READ_FILE_OPS(power_save_status); | 1534 | DEBUGFS_READ_FILE_OPS(power_save_status); |
2293 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | 1535 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); |
2294 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 1536 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); |
@@ -2296,9 +1538,10 @@ DEBUGFS_WRITE_FILE_OPS(csr); | |||
2296 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | 1538 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); |
2297 | DEBUGFS_READ_FILE_OPS(fh_reg); | 1539 | DEBUGFS_READ_FILE_OPS(fh_reg); |
2298 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | 1540 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); |
2299 | DEBUGFS_WRITE_FILE_OPS(internal_scan); | ||
2300 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | 1541 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); |
2301 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | 1542 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); |
1543 | DEBUGFS_READ_FILE_OPS(rxon_flags); | ||
1544 | DEBUGFS_READ_FILE_OPS(rxon_filter_flags); | ||
2302 | 1545 | ||
2303 | /* | 1546 | /* |
2304 | * Create the debugfs files and directories | 1547 | * Create the debugfs files and directories |
@@ -2334,8 +1577,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2334 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); | 1577 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); |
2335 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); | 1578 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); |
2336 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); | 1579 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); |
2337 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); | 1580 | if (!priv->cfg->broken_powersave) { |
2338 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); | 1581 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, |
1582 | S_IWUSR | S_IRUSR); | ||
1583 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); | ||
1584 | } | ||
2339 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); | 1585 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); |
2340 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); | 1586 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); |
2341 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); | 1587 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); |
@@ -2343,29 +1589,33 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2343 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); | 1589 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); |
2344 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); | 1590 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); |
2345 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); | 1591 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); |
2346 | DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR); | ||
2347 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); | 1592 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); |
2348 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); | 1593 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); |
2349 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); | 1594 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); |
2350 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); | 1595 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); |
2351 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); | 1596 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); |
2352 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | 1597 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); |
2353 | DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); | ||
2354 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | 1598 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); |
2355 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | 1599 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); |
2356 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 1600 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); |
2357 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | 1601 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
2358 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 1602 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
2359 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); | 1603 | |
1604 | if (priv->cfg->sensitivity_calib_by_driver) | ||
2360 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); | 1605 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
1606 | if (priv->cfg->chain_noise_calib_by_driver) | ||
2361 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 1607 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
1608 | if (priv->cfg->ucode_tracing) | ||
2362 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 1609 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); |
2363 | } | 1610 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
2364 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); | 1611 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
2365 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 1612 | if (priv->cfg->sensitivity_calib_by_driver) |
2366 | &priv->disable_chain_noise_cal); | 1613 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, |
2367 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || | 1614 | &priv->disable_sens_cal); |
2368 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) | 1615 | if (priv->cfg->chain_noise_calib_by_driver) |
1616 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | ||
1617 | &priv->disable_chain_noise_cal); | ||
1618 | if (priv->cfg->tx_power_by_driver) | ||
2369 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, | 1619 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, |
2370 | &priv->disable_tx_power_cal); | 1620 | &priv->disable_tx_power_cal); |
2371 | return 0; | 1621 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6054c5fba0c1..f3f3473c5c7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "iwl-debug.h" | 43 | #include "iwl-debug.h" |
44 | #include "iwl-4965-hw.h" | 44 | #include "iwl-4965-hw.h" |
45 | #include "iwl-3945-hw.h" | 45 | #include "iwl-3945-hw.h" |
46 | #include "iwl-agn-hw.h" | ||
46 | #include "iwl-led.h" | 47 | #include "iwl-led.h" |
47 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
48 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
@@ -56,6 +57,7 @@ extern struct iwl_cfg iwl5100_bgn_cfg; | |||
56 | extern struct iwl_cfg iwl5100_abg_cfg; | 57 | extern struct iwl_cfg iwl5100_abg_cfg; |
57 | extern struct iwl_cfg iwl5150_agn_cfg; | 58 | extern struct iwl_cfg iwl5150_agn_cfg; |
58 | extern struct iwl_cfg iwl5150_abg_cfg; | 59 | extern struct iwl_cfg iwl5150_abg_cfg; |
60 | extern struct iwl_cfg iwl6000g2a_2agn_cfg; | ||
59 | extern struct iwl_cfg iwl6000i_2agn_cfg; | 61 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
60 | extern struct iwl_cfg iwl6000i_2abg_cfg; | 62 | extern struct iwl_cfg iwl6000i_2abg_cfg; |
61 | extern struct iwl_cfg iwl6000i_2bg_cfg; | 63 | extern struct iwl_cfg iwl6000i_2bg_cfg; |
@@ -67,45 +69,6 @@ extern struct iwl_cfg iwl1000_bg_cfg; | |||
67 | 69 | ||
68 | struct iwl_tx_queue; | 70 | struct iwl_tx_queue; |
69 | 71 | ||
70 | /* shared structures from iwl-5000.c */ | ||
71 | extern struct iwl_mod_params iwl50_mod_params; | ||
72 | extern struct iwl_ucode_ops iwl5000_ucode; | ||
73 | extern struct iwl_lib_ops iwl5000_lib; | ||
74 | extern struct iwl_hcmd_ops iwl5000_hcmd; | ||
75 | extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; | ||
76 | |||
77 | /* shared functions from iwl-5000.c */ | ||
78 | extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); | ||
79 | extern u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, | ||
80 | u8 *data); | ||
81 | extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
82 | __le32 *tx_flags); | ||
83 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
84 | struct iwl_rx_phy_res *rx_resp); | ||
85 | extern void iwl5000_nic_config(struct iwl_priv *priv); | ||
86 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); | ||
87 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | ||
88 | size_t offset); | ||
89 | extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
90 | struct iwl_tx_queue *txq, | ||
91 | u16 byte_cnt); | ||
92 | extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
93 | struct iwl_tx_queue *txq); | ||
94 | extern int iwl5000_load_ucode(struct iwl_priv *priv); | ||
95 | extern void iwl5000_init_alive_start(struct iwl_priv *priv); | ||
96 | extern int iwl5000_alive_notify(struct iwl_priv *priv); | ||
97 | extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv); | ||
98 | extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
99 | int tx_fifo, int sta_id, int tid, u16 ssn_idx); | ||
100 | extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
101 | u16 ssn_idx, u8 tx_fifo); | ||
102 | extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask); | ||
103 | extern void iwl5000_setup_deferred_work(struct iwl_priv *priv); | ||
104 | extern void iwl5000_rx_handler_setup(struct iwl_priv *priv); | ||
105 | extern int iwl5000_hw_valid_rtc_data_addr(u32 addr); | ||
106 | extern int iwl5000_send_tx_power(struct iwl_priv *priv); | ||
107 | extern void iwl5000_temperature(struct iwl_priv *priv); | ||
108 | |||
109 | /* CT-KILL constants */ | 72 | /* CT-KILL constants */ |
110 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ | 73 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ |
111 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ | 74 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ |
@@ -183,6 +146,10 @@ struct iwl_queue { | |||
183 | int n_bd; /* number of BDs in this queue */ | 146 | int n_bd; /* number of BDs in this queue */ |
184 | int write_ptr; /* 1-st empty entry (index) host_w*/ | 147 | int write_ptr; /* 1-st empty entry (index) host_w*/ |
185 | int read_ptr; /* last used entry (index) host_r*/ | 148 | int read_ptr; /* last used entry (index) host_r*/ |
149 | /* use for monitoring and recovering the stuck queue */ | ||
150 | int last_read_ptr; /* storing the last read_ptr */ | ||
151 | /* number of time read_ptr and last_read_ptr are the same */ | ||
152 | u8 repeat_same_read_ptr; | ||
186 | dma_addr_t dma_addr; /* physical addr for BD's */ | 153 | dma_addr_t dma_addr; /* physical addr for BD's */ |
187 | int n_window; /* safe queue window */ | 154 | int n_window; /* safe queue window */ |
188 | u32 id; | 155 | u32 id; |
@@ -304,13 +271,11 @@ struct iwl_channel_info { | |||
304 | struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; | 271 | struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; |
305 | }; | 272 | }; |
306 | 273 | ||
307 | #define IWL_TX_FIFO_AC0 0 | 274 | #define IWL_TX_FIFO_BK 0 |
308 | #define IWL_TX_FIFO_AC1 1 | 275 | #define IWL_TX_FIFO_BE 1 |
309 | #define IWL_TX_FIFO_AC2 2 | 276 | #define IWL_TX_FIFO_VI 2 |
310 | #define IWL_TX_FIFO_AC3 3 | 277 | #define IWL_TX_FIFO_VO 3 |
311 | #define IWL_TX_FIFO_HCCA_1 5 | 278 | #define IWL_TX_FIFO_UNUSED -1 |
312 | #define IWL_TX_FIFO_HCCA_2 6 | ||
313 | #define IWL_TX_FIFO_NONE 7 | ||
314 | 279 | ||
315 | /* Minimum number of queues. MAX_NUM is defined in hw specific files. | 280 | /* Minimum number of queues. MAX_NUM is defined in hw specific files. |
316 | * Set the minimum to accommodate the 4 standard TX queues, 1 command | 281 | * Set the minimum to accommodate the 4 standard TX queues, 1 command |
@@ -361,13 +326,6 @@ enum { | |||
361 | 326 | ||
362 | #define DEF_CMD_PAYLOAD_SIZE 320 | 327 | #define DEF_CMD_PAYLOAD_SIZE 320 |
363 | 328 | ||
364 | /* | ||
365 | * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header, | ||
366 | * SNAP header and alignment. It should also be big enough for 802.11 | ||
367 | * control frames. | ||
368 | */ | ||
369 | #define IWL_LINK_HDR_MAX 64 | ||
370 | |||
371 | /** | 329 | /** |
372 | * struct iwl_device_cmd | 330 | * struct iwl_device_cmd |
373 | * | 331 | * |
@@ -519,38 +477,28 @@ struct iwl_ht_config { | |||
519 | u8 non_GF_STA_present; | 477 | u8 non_GF_STA_present; |
520 | }; | 478 | }; |
521 | 479 | ||
522 | union iwl_qos_capabity { | ||
523 | struct { | ||
524 | u8 edca_count:4; /* bit 0-3 */ | ||
525 | u8 q_ack:1; /* bit 4 */ | ||
526 | u8 queue_request:1; /* bit 5 */ | ||
527 | u8 txop_request:1; /* bit 6 */ | ||
528 | u8 reserved:1; /* bit 7 */ | ||
529 | } q_AP; | ||
530 | struct { | ||
531 | u8 acvo_APSD:1; /* bit 0 */ | ||
532 | u8 acvi_APSD:1; /* bit 1 */ | ||
533 | u8 ac_bk_APSD:1; /* bit 2 */ | ||
534 | u8 ac_be_APSD:1; /* bit 3 */ | ||
535 | u8 q_ack:1; /* bit 4 */ | ||
536 | u8 max_len:2; /* bit 5-6 */ | ||
537 | u8 more_data_ack:1; /* bit 7 */ | ||
538 | } q_STA; | ||
539 | u8 val; | ||
540 | }; | ||
541 | |||
542 | /* QoS structures */ | 480 | /* QoS structures */ |
543 | struct iwl_qos_info { | 481 | struct iwl_qos_info { |
544 | int qos_active; | 482 | int qos_active; |
545 | union iwl_qos_capabity qos_cap; | ||
546 | struct iwl_qosparam_cmd def_qos_parm; | 483 | struct iwl_qosparam_cmd def_qos_parm; |
547 | }; | 484 | }; |
548 | 485 | ||
486 | /* | ||
487 | * Structure should be accessed with sta_lock held. When station addition | ||
488 | * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only | ||
489 | * the commands (iwl_addsta_cmd and iwl_link_quality_cmd) without sta_lock | ||
490 | * held. | ||
491 | */ | ||
549 | struct iwl_station_entry { | 492 | struct iwl_station_entry { |
550 | struct iwl_addsta_cmd sta; | 493 | struct iwl_addsta_cmd sta; |
551 | struct iwl_tid_data tid[MAX_TID_COUNT]; | 494 | struct iwl_tid_data tid[MAX_TID_COUNT]; |
552 | u8 used; | 495 | u8 used; |
553 | struct iwl_hw_key keyinfo; | 496 | struct iwl_hw_key keyinfo; |
497 | struct iwl_link_quality_cmd *lq; | ||
498 | }; | ||
499 | |||
500 | struct iwl_station_priv_common { | ||
501 | u8 sta_id; | ||
554 | }; | 502 | }; |
555 | 503 | ||
556 | /* | 504 | /* |
@@ -559,14 +507,28 @@ struct iwl_station_entry { | |||
559 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) | 507 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) |
560 | * in the structure for use by driver. This structure is places in that | 508 | * in the structure for use by driver. This structure is places in that |
561 | * space. | 509 | * space. |
510 | * | ||
511 | * The common struct MUST be first because it is shared between | ||
512 | * 3945 and agn! | ||
562 | */ | 513 | */ |
563 | struct iwl_station_priv { | 514 | struct iwl_station_priv { |
515 | struct iwl_station_priv_common common; | ||
564 | struct iwl_lq_sta lq_sta; | 516 | struct iwl_lq_sta lq_sta; |
565 | atomic_t pending_frames; | 517 | atomic_t pending_frames; |
566 | bool client; | 518 | bool client; |
567 | bool asleep; | 519 | bool asleep; |
568 | }; | 520 | }; |
569 | 521 | ||
522 | /** | ||
523 | * struct iwl_vif_priv - driver's private per-interface information | ||
524 | * | ||
525 | * When mac80211 allocates a virtual interface, it can allocate | ||
526 | * space for us to put data into. | ||
527 | */ | ||
528 | struct iwl_vif_priv { | ||
529 | u8 ibss_bssid_sta_id; | ||
530 | }; | ||
531 | |||
570 | /* one for each uCode image (inst/data, boot/init/runtime) */ | 532 | /* one for each uCode image (inst/data, boot/init/runtime) */ |
571 | struct fw_desc { | 533 | struct fw_desc { |
572 | void *v_addr; /* access by driver */ | 534 | void *v_addr; /* access by driver */ |
@@ -574,7 +536,7 @@ struct fw_desc { | |||
574 | u32 len; /* bytes */ | 536 | u32 len; /* bytes */ |
575 | }; | 537 | }; |
576 | 538 | ||
577 | /* uCode file layout */ | 539 | /* v1/v2 uCode file layout */ |
578 | struct iwl_ucode_header { | 540 | struct iwl_ucode_header { |
579 | __le32 ver; /* major/minor/API/serial */ | 541 | __le32 ver; /* major/minor/API/serial */ |
580 | union { | 542 | union { |
@@ -597,7 +559,62 @@ struct iwl_ucode_header { | |||
597 | } v2; | 559 | } v2; |
598 | } u; | 560 | } u; |
599 | }; | 561 | }; |
600 | #define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28) | 562 | |
563 | /* | ||
564 | * new TLV uCode file layout | ||
565 | * | ||
566 | * The new TLV file format contains TLVs, that each specify | ||
567 | * some piece of data. To facilitate "groups", for example | ||
568 | * different instruction image with different capabilities, | ||
569 | * bundled with the same init image, an alternative mechanism | ||
570 | * is provided: | ||
571 | * When the alternative field is 0, that means that the item | ||
572 | * is always valid. When it is non-zero, then it is only | ||
573 | * valid in conjunction with items of the same alternative, | ||
574 | * in which case the driver (user) selects one alternative | ||
575 | * to use. | ||
576 | */ | ||
577 | |||
578 | enum iwl_ucode_tlv_type { | ||
579 | IWL_UCODE_TLV_INVALID = 0, /* unused */ | ||
580 | IWL_UCODE_TLV_INST = 1, | ||
581 | IWL_UCODE_TLV_DATA = 2, | ||
582 | IWL_UCODE_TLV_INIT = 3, | ||
583 | IWL_UCODE_TLV_INIT_DATA = 4, | ||
584 | IWL_UCODE_TLV_BOOT = 5, | ||
585 | IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */ | ||
586 | }; | ||
587 | |||
588 | struct iwl_ucode_tlv { | ||
589 | __le16 type; /* see above */ | ||
590 | __le16 alternative; /* see comment */ | ||
591 | __le32 length; /* not including type/length fields */ | ||
592 | u8 data[0]; | ||
593 | } __attribute__ ((packed)); | ||
594 | |||
595 | #define IWL_TLV_UCODE_MAGIC 0x0a4c5749 | ||
596 | |||
597 | struct iwl_tlv_ucode_header { | ||
598 | /* | ||
599 | * The TLV style ucode header is distinguished from | ||
600 | * the v1/v2 style header by first four bytes being | ||
601 | * zero, as such is an invalid combination of | ||
602 | * major/minor/API/serial versions. | ||
603 | */ | ||
604 | __le32 zero; | ||
605 | __le32 magic; | ||
606 | u8 human_readable[64]; | ||
607 | __le32 ver; /* major/minor/API/serial */ | ||
608 | __le32 build; | ||
609 | __le64 alternatives; /* bitmask of valid alternatives */ | ||
610 | /* | ||
611 | * The data contained herein has a TLV layout, | ||
612 | * see above for the TLV header and types. | ||
613 | * Note that each TLV is padded to a length | ||
614 | * that is a multiple of 4 for alignment. | ||
615 | */ | ||
616 | u8 data[0]; | ||
617 | }; | ||
601 | 618 | ||
602 | struct iwl4965_ibss_seq { | 619 | struct iwl4965_ibss_seq { |
603 | u8 mac[ETH_ALEN]; | 620 | u8 mac[ETH_ALEN]; |
@@ -1039,6 +1056,11 @@ struct iwl_event_log { | |||
1039 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) | 1056 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) |
1040 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) | 1057 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) |
1041 | 1058 | ||
1059 | /* timer constants use to monitor and recover stuck tx queues in mSecs */ | ||
1060 | #define IWL_MONITORING_PERIOD (1000) | ||
1061 | #define IWL_ONE_HUNDRED_MSECS (100) | ||
1062 | #define IWL_SIXTY_SECS (60000) | ||
1063 | |||
1042 | enum iwl_reset { | 1064 | enum iwl_reset { |
1043 | IWL_RF_RESET = 0, | 1065 | IWL_RF_RESET = 0, |
1044 | IWL_FW_RESET, | 1066 | IWL_FW_RESET, |
@@ -1092,10 +1114,6 @@ struct iwl_priv { | |||
1092 | struct iwl_channel_info *channel_info; /* channel info array */ | 1114 | struct iwl_channel_info *channel_info; /* channel info array */ |
1093 | u8 channel_count; /* # of channels */ | 1115 | u8 channel_count; /* # of channels */ |
1094 | 1116 | ||
1095 | /* each calibration channel group in the EEPROM has a derived | ||
1096 | * clip setting for each rate. 3945 only.*/ | ||
1097 | const struct iwl3945_clip_group clip39_groups[5]; | ||
1098 | |||
1099 | /* thermal calibration */ | 1117 | /* thermal calibration */ |
1100 | s32 temperature; /* degrees Kelvin */ | 1118 | s32 temperature; /* degrees Kelvin */ |
1101 | s32 last_temperature; | 1119 | s32 last_temperature; |
@@ -1104,12 +1122,10 @@ struct iwl_priv { | |||
1104 | struct iwl_calib_result calib_results[IWL_CALIB_MAX]; | 1122 | struct iwl_calib_result calib_results[IWL_CALIB_MAX]; |
1105 | 1123 | ||
1106 | /* Scan related variables */ | 1124 | /* Scan related variables */ |
1107 | unsigned long next_scan_jiffies; | ||
1108 | unsigned long scan_start; | 1125 | unsigned long scan_start; |
1109 | unsigned long scan_pass_start; | ||
1110 | unsigned long scan_start_tsf; | 1126 | unsigned long scan_start_tsf; |
1111 | void *scan; | 1127 | void *scan_cmd; |
1112 | int scan_bands; | 1128 | enum ieee80211_band scan_band; |
1113 | struct cfg80211_scan_request *scan_request; | 1129 | struct cfg80211_scan_request *scan_request; |
1114 | bool is_internal_short_scan; | 1130 | bool is_internal_short_scan; |
1115 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; | 1131 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; |
@@ -1168,16 +1184,13 @@ struct iwl_priv { | |||
1168 | u64 led_tpt; | 1184 | u64 led_tpt; |
1169 | 1185 | ||
1170 | u16 active_rate; | 1186 | u16 active_rate; |
1171 | u16 active_rate_basic; | ||
1172 | 1187 | ||
1173 | u8 assoc_station_added; | ||
1174 | u8 start_calib; | 1188 | u8 start_calib; |
1175 | struct iwl_sensitivity_data sensitivity_data; | 1189 | struct iwl_sensitivity_data sensitivity_data; |
1176 | struct iwl_chain_noise_data chain_noise_data; | 1190 | struct iwl_chain_noise_data chain_noise_data; |
1177 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; | 1191 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; |
1178 | 1192 | ||
1179 | struct iwl_ht_config current_ht_config; | 1193 | struct iwl_ht_config current_ht_config; |
1180 | u8 last_phy_res[100]; | ||
1181 | 1194 | ||
1182 | /* Rate scaling data */ | 1195 | /* Rate scaling data */ |
1183 | u8 retry_rate; | 1196 | u8 retry_rate; |
@@ -1197,9 +1210,6 @@ struct iwl_priv { | |||
1197 | 1210 | ||
1198 | unsigned long status; | 1211 | unsigned long status; |
1199 | 1212 | ||
1200 | int last_rx_rssi; /* From Rx packet statistics */ | ||
1201 | int last_rx_noise; /* From beacon statistics */ | ||
1202 | |||
1203 | /* counts mgmt, ctl, and data packets */ | 1213 | /* counts mgmt, ctl, and data packets */ |
1204 | struct traffic_stats tx_stats; | 1214 | struct traffic_stats tx_stats; |
1205 | struct traffic_stats rx_stats; | 1215 | struct traffic_stats rx_stats; |
@@ -1218,18 +1228,14 @@ struct iwl_priv { | |||
1218 | #endif | 1228 | #endif |
1219 | 1229 | ||
1220 | /* context information */ | 1230 | /* context information */ |
1221 | u16 rates_mask; | 1231 | u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ |
1222 | |||
1223 | u8 bssid[ETH_ALEN]; | ||
1224 | u16 rts_threshold; | ||
1225 | u8 mac_addr[ETH_ALEN]; | 1232 | u8 mac_addr[ETH_ALEN]; |
1226 | 1233 | ||
1227 | /*station table variables */ | 1234 | /*station table variables */ |
1228 | spinlock_t sta_lock; | 1235 | spinlock_t sta_lock; |
1229 | int num_stations; | 1236 | int num_stations; |
1230 | struct iwl_station_entry stations[IWL_STATION_COUNT]; | 1237 | struct iwl_station_entry stations[IWL_STATION_COUNT]; |
1231 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; | 1238 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ |
1232 | u8 default_wep_key; | ||
1233 | u8 key_mapping_key; | 1239 | u8 key_mapping_key; |
1234 | unsigned long ucode_key_table; | 1240 | unsigned long ucode_key_table; |
1235 | 1241 | ||
@@ -1244,10 +1250,6 @@ struct iwl_priv { | |||
1244 | 1250 | ||
1245 | u8 mac80211_registered; | 1251 | u8 mac80211_registered; |
1246 | 1252 | ||
1247 | /* Rx'd packet timing information */ | ||
1248 | u32 last_beacon_time; | ||
1249 | u64 last_tsf; | ||
1250 | |||
1251 | /* eeprom -- this is in the card's little endian byte order */ | 1253 | /* eeprom -- this is in the card's little endian byte order */ |
1252 | u8 *eeprom; | 1254 | u8 *eeprom; |
1253 | int nvm_device_type; | 1255 | int nvm_device_type; |
@@ -1259,29 +1261,67 @@ struct iwl_priv { | |||
1259 | 1261 | ||
1260 | /* Last Rx'd beacon timestamp */ | 1262 | /* Last Rx'd beacon timestamp */ |
1261 | u64 timestamp; | 1263 | u64 timestamp; |
1262 | u16 beacon_int; | ||
1263 | struct ieee80211_vif *vif; | 1264 | struct ieee80211_vif *vif; |
1264 | 1265 | ||
1265 | /*Added for 3945 */ | 1266 | union { |
1266 | void *shared_virt; | 1267 | #if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE) |
1267 | dma_addr_t shared_phys; | 1268 | struct { |
1268 | /*End*/ | 1269 | void *shared_virt; |
1269 | struct iwl_hw_params hw_params; | 1270 | dma_addr_t shared_phys; |
1270 | 1271 | ||
1271 | /* INT ICT Table */ | 1272 | struct delayed_work thermal_periodic; |
1272 | __le32 *ict_tbl; | 1273 | struct delayed_work rfkill_poll; |
1273 | dma_addr_t ict_tbl_dma; | 1274 | |
1274 | dma_addr_t aligned_ict_tbl_dma; | 1275 | struct iwl3945_notif_statistics statistics; |
1275 | int ict_index; | 1276 | #ifdef CONFIG_IWLWIFI_DEBUG |
1276 | void *ict_tbl_vir; | 1277 | struct iwl3945_notif_statistics accum_statistics; |
1277 | u32 inta; | 1278 | struct iwl3945_notif_statistics delta_statistics; |
1278 | bool use_ict; | 1279 | struct iwl3945_notif_statistics max_delta; |
1280 | #endif | ||
1281 | |||
1282 | u32 sta_supp_rates; | ||
1283 | int last_rx_rssi; /* From Rx packet statistics */ | ||
1284 | |||
1285 | /* Rx'd packet timing information */ | ||
1286 | u32 last_beacon_time; | ||
1287 | u64 last_tsf; | ||
1288 | |||
1289 | /* | ||
1290 | * each calibration channel group in the | ||
1291 | * EEPROM has a derived clip setting for | ||
1292 | * each rate. | ||
1293 | */ | ||
1294 | const struct iwl3945_clip_group clip_groups[5]; | ||
1295 | |||
1296 | } _3945; | ||
1297 | #endif | ||
1298 | #if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) | ||
1299 | struct { | ||
1300 | /* INT ICT Table */ | ||
1301 | __le32 *ict_tbl; | ||
1302 | void *ict_tbl_vir; | ||
1303 | dma_addr_t ict_tbl_dma; | ||
1304 | dma_addr_t aligned_ict_tbl_dma; | ||
1305 | int ict_index; | ||
1306 | u32 inta; | ||
1307 | bool use_ict; | ||
1308 | /* | ||
1309 | * reporting the number of tids has AGG on. 0 means | ||
1310 | * no AGGREGATION | ||
1311 | */ | ||
1312 | u8 agg_tids_count; | ||
1313 | |||
1314 | struct iwl_rx_phy_res last_phy_res; | ||
1315 | bool last_phy_res_valid; | ||
1316 | |||
1317 | struct completion firmware_loading_complete; | ||
1318 | } _agn; | ||
1319 | #endif | ||
1320 | }; | ||
1321 | |||
1322 | struct iwl_hw_params hw_params; | ||
1279 | 1323 | ||
1280 | u32 inta_mask; | 1324 | u32 inta_mask; |
1281 | /* Current association information needed to configure the | ||
1282 | * hardware */ | ||
1283 | u16 assoc_id; | ||
1284 | u16 assoc_capability; | ||
1285 | 1325 | ||
1286 | struct iwl_qos_info qos_data; | 1326 | struct iwl_qos_info qos_data; |
1287 | 1327 | ||
@@ -1291,11 +1331,11 @@ struct iwl_priv { | |||
1291 | struct work_struct scan_completed; | 1331 | struct work_struct scan_completed; |
1292 | struct work_struct rx_replenish; | 1332 | struct work_struct rx_replenish; |
1293 | struct work_struct abort_scan; | 1333 | struct work_struct abort_scan; |
1294 | struct work_struct request_scan; | ||
1295 | struct work_struct beacon_update; | 1334 | struct work_struct beacon_update; |
1296 | struct work_struct tt_work; | 1335 | struct work_struct tt_work; |
1297 | struct work_struct ct_enter; | 1336 | struct work_struct ct_enter; |
1298 | struct work_struct ct_exit; | 1337 | struct work_struct ct_exit; |
1338 | struct work_struct start_internal_scan; | ||
1299 | 1339 | ||
1300 | struct tasklet_struct irq_tasklet; | 1340 | struct tasklet_struct irq_tasklet; |
1301 | 1341 | ||
@@ -1303,10 +1343,6 @@ struct iwl_priv { | |||
1303 | struct delayed_work alive_start; | 1343 | struct delayed_work alive_start; |
1304 | struct delayed_work scan_check; | 1344 | struct delayed_work scan_check; |
1305 | 1345 | ||
1306 | /*For 3945 only*/ | ||
1307 | struct delayed_work thermal_periodic; | ||
1308 | struct delayed_work rfkill_poll; | ||
1309 | |||
1310 | /* TX Power */ | 1346 | /* TX Power */ |
1311 | s8 tx_power_user_lmt; | 1347 | s8 tx_power_user_lmt; |
1312 | s8 tx_power_device_lmt; | 1348 | s8 tx_power_device_lmt; |
@@ -1338,13 +1374,8 @@ struct iwl_priv { | |||
1338 | struct work_struct run_time_calib_work; | 1374 | struct work_struct run_time_calib_work; |
1339 | struct timer_list statistics_periodic; | 1375 | struct timer_list statistics_periodic; |
1340 | struct timer_list ucode_trace; | 1376 | struct timer_list ucode_trace; |
1377 | struct timer_list monitor_recover; | ||
1341 | bool hw_ready; | 1378 | bool hw_ready; |
1342 | /*For 3945*/ | ||
1343 | #define IWL_DEFAULT_TX_POWER 0x0F | ||
1344 | |||
1345 | struct iwl3945_notif_statistics statistics_39; | ||
1346 | |||
1347 | u32 sta_supp_rates; | ||
1348 | 1379 | ||
1349 | struct iwl_event_log event_log; | 1380 | struct iwl_event_log event_log; |
1350 | }; /*iwl_priv */ | 1381 | }; /*iwl_priv */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 2ffc2edbf4f0..4a487639d932 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -37,6 +37,7 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8); | |||
37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); | 37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); |
38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | 38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); |
39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | 39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); |
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx); | ||
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | 41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); |
41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | 42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); |
42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | 43 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index fb5bb487f3bc..ee11452519e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -590,9 +590,16 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
590 | e[addr / 2] = cpu_to_le16(r >> 16); | 590 | e[addr / 2] = cpu_to_le16(r >> 16); |
591 | } | 591 | } |
592 | } | 592 | } |
593 | |||
594 | IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", | ||
595 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
596 | ? "OTP" : "EEPROM", | ||
597 | iwl_eeprom_query16(priv, EEPROM_VERSION)); | ||
598 | |||
593 | ret = 0; | 599 | ret = 0; |
594 | done: | 600 | done: |
595 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); | 601 | priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); |
602 | |||
596 | err: | 603 | err: |
597 | if (ret) | 604 | if (ret) |
598 | iwl_eeprom_free(priv); | 605 | iwl_eeprom_free(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 4e1ba824dc50..95aa202c85e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -172,37 +172,41 @@ struct iwl_eeprom_enhanced_txpwr { | |||
172 | #define EEPROM_5000_TX_POWER_VERSION (4) | 172 | #define EEPROM_5000_TX_POWER_VERSION (4) |
173 | #define EEPROM_5000_EEPROM_VERSION (0x11A) | 173 | #define EEPROM_5000_EEPROM_VERSION (0x11A) |
174 | 174 | ||
175 | /*5000 calibrations */ | 175 | /* 5000 and up calibration */ |
176 | #define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | 176 | #define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) |
177 | #define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL) | 177 | #define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL) |
178 | #define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL) | 178 | |
179 | 179 | /* 5000 temperature */ | |
180 | /* 5000 links */ | 180 | #define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) |
181 | #define EEPROM_5000_LINK_HOST (2*0x64) | 181 | |
182 | #define EEPROM_5000_LINK_GENERAL (2*0x65) | 182 | /* agn links */ |
183 | #define EEPROM_5000_LINK_REGULATORY (2*0x66) | 183 | #define EEPROM_LINK_HOST (2*0x64) |
184 | #define EEPROM_5000_LINK_CALIBRATION (2*0x67) | 184 | #define EEPROM_LINK_GENERAL (2*0x65) |
185 | #define EEPROM_5000_LINK_PROCESS_ADJST (2*0x68) | 185 | #define EEPROM_LINK_REGULATORY (2*0x66) |
186 | #define EEPROM_5000_LINK_OTHERS (2*0x69) | 186 | #define EEPROM_LINK_CALIBRATION (2*0x67) |
187 | 187 | #define EEPROM_LINK_PROCESS_ADJST (2*0x68) | |
188 | /* 5000 regulatory - indirect access */ | 188 | #define EEPROM_LINK_OTHERS (2*0x69) |
189 | #define EEPROM_5000_REG_SKU_ID ((0x02)\ | 189 | |
190 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ | 190 | /* agn regulatory - indirect access */ |
191 | #define EEPROM_5000_REG_BAND_1_CHANNELS ((0x08)\ | 191 | #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ |
192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ | 192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ |
193 | #define EEPROM_5000_REG_BAND_2_CHANNELS ((0x26)\ | 193 | #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ |
194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ | 194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ |
195 | #define EEPROM_5000_REG_BAND_3_CHANNELS ((0x42)\ | 195 | #define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ |
196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ | 196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ |
197 | #define EEPROM_5000_REG_BAND_4_CHANNELS ((0x5C)\ | 197 | #define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ |
198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
199 | #define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ | 199 | #define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ |
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ | 200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ |
201 | #define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\ | 201 | #define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ |
202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | 202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ |
203 | #define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ | 203 | #define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ |
204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
205 | 205 | ||
206 | /* 6000 regulatory - indirect access */ | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\ | ||
208 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
209 | |||
206 | /* 6000 and up regulatory tx power - indirect access */ | 210 | /* 6000 and up regulatory tx power - indirect access */ |
207 | /* max. elements per section */ | 211 | /* max. elements per section */ |
208 | #define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) | 212 | #define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) |
@@ -261,14 +265,21 @@ struct iwl_eeprom_enhanced_txpwr { | |||
261 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 265 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
262 | 266 | ||
263 | /* 1000 Specific */ | 267 | /* 1000 Specific */ |
268 | #define EEPROM_1000_TX_POWER_VERSION (4) | ||
264 | #define EEPROM_1000_EEPROM_VERSION (0x15C) | 269 | #define EEPROM_1000_EEPROM_VERSION (0x15C) |
265 | 270 | ||
266 | /* 6x00 Specific */ | 271 | /* 6x00 Specific */ |
272 | #define EEPROM_6000_TX_POWER_VERSION (4) | ||
267 | #define EEPROM_6000_EEPROM_VERSION (0x434) | 273 | #define EEPROM_6000_EEPROM_VERSION (0x434) |
268 | 274 | ||
269 | /* 6x50 Specific */ | 275 | /* 6x50 Specific */ |
276 | #define EEPROM_6050_TX_POWER_VERSION (4) | ||
270 | #define EEPROM_6050_EEPROM_VERSION (0x532) | 277 | #define EEPROM_6050_EEPROM_VERSION (0x532) |
271 | 278 | ||
279 | /* 6x00g2 Specific */ | ||
280 | #define EEPROM_6000G2_TX_POWER_VERSION (6) | ||
281 | #define EEPROM_6000G2_EEPROM_VERSION (0x709) | ||
282 | |||
272 | /* OTP */ | 283 | /* OTP */ |
273 | /* lower blocks contain EEPROM image and calibration data */ | 284 | /* lower blocks contain EEPROM image and calibration data */ |
274 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ | 285 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 73681c4fefe7..51f89e7ba681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -169,7 +169,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
169 | mutex_lock(&priv->sync_cmd_mutex); | 169 | mutex_lock(&priv->sync_cmd_mutex); |
170 | 170 | ||
171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); | 171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); |
172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", | 172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", |
173 | get_cmd_string(cmd->id)); | 173 | get_cmd_string(cmd->id)); |
174 | 174 | ||
175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); | 175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); |
@@ -191,7 +191,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
192 | 192 | ||
193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | 194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
195 | get_cmd_string(cmd->id)); | 195 | get_cmd_string(cmd->id)); |
196 | ret = -ETIMEDOUT; | 196 | ret = -ETIMEDOUT; |
197 | goto cancel; | 197 | goto cancel; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 51a67fb2e185..3ff6b9d25a10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -31,6 +31,9 @@ | |||
31 | #define __iwl_helpers_h__ | 31 | #define __iwl_helpers_h__ |
32 | 32 | ||
33 | #include <linux/ctype.h> | 33 | #include <linux/ctype.h> |
34 | #include <net/mac80211.h> | ||
35 | |||
36 | #include "iwl-io.h" | ||
34 | 37 | ||
35 | #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) | 38 | #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) |
36 | 39 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 16eb3ced9b30..0203a3bbf872 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -298,7 +298,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, | |||
298 | struct iwl_priv *priv, u32 reg) | 298 | struct iwl_priv *priv, u32 reg) |
299 | { | 299 | { |
300 | u32 value = _iwl_read_direct32(priv, reg); | 300 | u32 value = _iwl_read_direct32(priv, reg); |
301 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, | 301 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, |
302 | f, l); | 302 | f, l); |
303 | return value; | 303 | return value; |
304 | } | 304 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index a6f9c918aabc..db5bfcb036ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -46,7 +46,7 @@ | |||
46 | static int led_mode; | 46 | static int led_mode; |
47 | module_param(led_mode, int, S_IRUGO); | 47 | module_param(led_mode, int, S_IRUGO); |
48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " | 48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " |
49 | "(default 0)\n"); | 49 | "(default 0)"); |
50 | 50 | ||
51 | 51 | ||
52 | static const struct { | 52 | static const struct { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 548dac2f6a96..cda6a94d6cc9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -318,10 +318,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
318 | update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || | 318 | update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || |
319 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; | 319 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; |
320 | 320 | ||
321 | if (priv->vif) | 321 | dtimper = priv->hw->conf.ps_dtim_period ?: 1; |
322 | dtimper = priv->hw->conf.ps_dtim_period; | ||
323 | else | ||
324 | dtimper = 1; | ||
325 | 322 | ||
326 | if (priv->cfg->broken_powersave) | 323 | if (priv->cfg->broken_powersave) |
327 | iwl_power_sleep_cam_cmd(priv, &cmd); | 324 | iwl_power_sleep_cam_cmd(priv, &cmd); |
@@ -384,10 +381,10 @@ EXPORT_SYMBOL(iwl_ht_enabled); | |||
384 | 381 | ||
385 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | 382 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) |
386 | { | 383 | { |
387 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | 384 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
388 | bool within_margin = false; | 385 | bool within_margin = false; |
389 | 386 | ||
390 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 387 | if (priv->cfg->temperature_kelvin) |
391 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 388 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
392 | 389 | ||
393 | if (!priv->thermal_throttle.advanced_tt) | 390 | if (!priv->thermal_throttle.advanced_tt) |
@@ -840,12 +837,12 @@ EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | |||
840 | static void iwl_bg_tt_work(struct work_struct *work) | 837 | static void iwl_bg_tt_work(struct work_struct *work) |
841 | { | 838 | { |
842 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | 839 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); |
843 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | 840 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
844 | 841 | ||
845 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 842 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
846 | return; | 843 | return; |
847 | 844 | ||
848 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 845 | if (priv->cfg->temperature_kelvin) |
849 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 846 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
850 | 847 | ||
851 | if (!priv->thermal_throttle.advanced_tt) | 848 | if (!priv->thermal_throttle.advanced_tt) |
@@ -875,7 +872,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
875 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | 872 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); |
876 | struct iwl_tt_trans *transaction; | 873 | struct iwl_tt_trans *transaction; |
877 | 874 | ||
878 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); | 875 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); |
879 | 876 | ||
880 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | 877 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); |
881 | 878 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index d2d2a9174900..b1f101caf19d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -254,7 +254,7 @@ | |||
254 | * device. A queue maps to only one (selectable by driver) Tx DMA channel, | 254 | * device. A queue maps to only one (selectable by driver) Tx DMA channel, |
255 | * but one DMA channel may take input from several queues. | 255 | * but one DMA channel may take input from several queues. |
256 | * | 256 | * |
257 | * Tx DMA channels have dedicated purposes. For 4965, they are used as follows | 257 | * Tx DMA FIFOs have dedicated purposes. For 4965, they are used as follows |
258 | * (cf. default_queue_to_tx_fifo in iwl-4965.c): | 258 | * (cf. default_queue_to_tx_fifo in iwl-4965.c): |
259 | * | 259 | * |
260 | * 0 -- EDCA BK (background) frames, lowest priority | 260 | * 0 -- EDCA BK (background) frames, lowest priority |
@@ -262,20 +262,20 @@ | |||
262 | * 2 -- EDCA VI (video) frames, higher priority | 262 | * 2 -- EDCA VI (video) frames, higher priority |
263 | * 3 -- EDCA VO (voice) and management frames, highest priority | 263 | * 3 -- EDCA VO (voice) and management frames, highest priority |
264 | * 4 -- Commands (e.g. RXON, etc.) | 264 | * 4 -- Commands (e.g. RXON, etc.) |
265 | * 5 -- HCCA short frames | 265 | * 5 -- unused (HCCA) |
266 | * 6 -- HCCA long frames | 266 | * 6 -- unused (HCCA) |
267 | * 7 -- not used by driver (device-internal only) | 267 | * 7 -- not used by driver (device-internal only) |
268 | * | 268 | * |
269 | * For 5000 series and up, they are used slightly differently | 269 | * For 5000 series and up, they are used differently |
270 | * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): | 270 | * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): |
271 | * | 271 | * |
272 | * 0 -- EDCA BK (background) frames, lowest priority | 272 | * 0 -- EDCA BK (background) frames, lowest priority |
273 | * 1 -- EDCA BE (best effort) frames, normal priority | 273 | * 1 -- EDCA BE (best effort) frames, normal priority |
274 | * 2 -- EDCA VI (video) frames, higher priority | 274 | * 2 -- EDCA VI (video) frames, higher priority |
275 | * 3 -- EDCA VO (voice) and management frames, highest priority | 275 | * 3 -- EDCA VO (voice) and management frames, highest priority |
276 | * 4 -- (TBD) | 276 | * 4 -- unused |
277 | * 5 -- HCCA short frames | 277 | * 5 -- unused |
278 | * 6 -- HCCA long frames | 278 | * 6 -- unused |
279 | * 7 -- Commands | 279 | * 7 -- Commands |
280 | * | 280 | * |
281 | * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. | 281 | * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. |
@@ -529,48 +529,48 @@ | |||
529 | #define IWL_SCD_TXFIFO_POS_RA (4) | 529 | #define IWL_SCD_TXFIFO_POS_RA (4) |
530 | #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) | 530 | #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) |
531 | 531 | ||
532 | /* 5000 SCD */ | 532 | /* agn SCD */ |
533 | #define IWL50_SCD_QUEUE_STTS_REG_POS_TXF (0) | 533 | #define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF (0) |
534 | #define IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) | 534 | #define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) |
535 | #define IWL50_SCD_QUEUE_STTS_REG_POS_WSL (4) | 535 | #define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL (4) |
536 | #define IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) | 536 | #define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) |
537 | #define IWL50_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) | 537 | #define IWLAGN_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) |
538 | 538 | ||
539 | #define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) | 539 | #define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) |
540 | #define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) | 540 | #define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) |
541 | #define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) | 541 | #define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) |
542 | #define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) | 542 | #define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) |
543 | #define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) | 543 | #define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) |
544 | #define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) | 544 | #define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) |
545 | #define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) | 545 | #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) |
546 | #define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) | 546 | #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) |
547 | 547 | ||
548 | #define IWL50_SCD_CONTEXT_DATA_OFFSET (0x600) | 548 | #define IWLAGN_SCD_CONTEXT_DATA_OFFSET (0x600) |
549 | #define IWL50_SCD_TX_STTS_BITMAP_OFFSET (0x7B1) | 549 | #define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET (0x7B1) |
550 | #define IWL50_SCD_TRANSLATE_TBL_OFFSET (0x7E0) | 550 | #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET (0x7E0) |
551 | 551 | ||
552 | #define IWL50_SCD_CONTEXT_QUEUE_OFFSET(x)\ | 552 | #define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ |
553 | (IWL50_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) | 553 | (IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) |
554 | 554 | ||
555 | #define IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ | 555 | #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ |
556 | ((IWL50_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) | 556 | ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) |
557 | 557 | ||
558 | #define IWL50_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ | 558 | #define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ |
559 | (~(1<<IWL_CMD_QUEUE_NUM))) | 559 | (~(1<<IWL_CMD_QUEUE_NUM))) |
560 | 560 | ||
561 | #define IWL50_SCD_BASE (PRPH_BASE + 0xa02c00) | 561 | #define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00) |
562 | 562 | ||
563 | #define IWL50_SCD_SRAM_BASE_ADDR (IWL50_SCD_BASE + 0x0) | 563 | #define IWLAGN_SCD_SRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x0) |
564 | #define IWL50_SCD_DRAM_BASE_ADDR (IWL50_SCD_BASE + 0x8) | 564 | #define IWLAGN_SCD_DRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x8) |
565 | #define IWL50_SCD_AIT (IWL50_SCD_BASE + 0x0c) | 565 | #define IWLAGN_SCD_AIT (IWLAGN_SCD_BASE + 0x0c) |
566 | #define IWL50_SCD_TXFACT (IWL50_SCD_BASE + 0x10) | 566 | #define IWLAGN_SCD_TXFACT (IWLAGN_SCD_BASE + 0x10) |
567 | #define IWL50_SCD_ACTIVE (IWL50_SCD_BASE + 0x14) | 567 | #define IWLAGN_SCD_ACTIVE (IWLAGN_SCD_BASE + 0x14) |
568 | #define IWL50_SCD_QUEUE_WRPTR(x) (IWL50_SCD_BASE + 0x18 + (x) * 4) | 568 | #define IWLAGN_SCD_QUEUE_WRPTR(x) (IWLAGN_SCD_BASE + 0x18 + (x) * 4) |
569 | #define IWL50_SCD_QUEUE_RDPTR(x) (IWL50_SCD_BASE + 0x68 + (x) * 4) | 569 | #define IWLAGN_SCD_QUEUE_RDPTR(x) (IWLAGN_SCD_BASE + 0x68 + (x) * 4) |
570 | #define IWL50_SCD_QUEUECHAIN_SEL (IWL50_SCD_BASE + 0xe8) | 570 | #define IWLAGN_SCD_QUEUECHAIN_SEL (IWLAGN_SCD_BASE + 0xe8) |
571 | #define IWL50_SCD_AGGR_SEL (IWL50_SCD_BASE + 0x248) | 571 | #define IWLAGN_SCD_AGGR_SEL (IWLAGN_SCD_BASE + 0x248) |
572 | #define IWL50_SCD_INTERRUPT_MASK (IWL50_SCD_BASE + 0x108) | 572 | #define IWLAGN_SCD_INTERRUPT_MASK (IWLAGN_SCD_BASE + 0x108) |
573 | #define IWL50_SCD_QUEUE_STATUS_BITS(x) (IWL50_SCD_BASE + 0x10c + (x) * 4) | 573 | #define IWLAGN_SCD_QUEUE_STATUS_BITS(x) (IWLAGN_SCD_BASE + 0x10c + (x) * 4) |
574 | 574 | ||
575 | /*********************** END TX SCHEDULER *************************************/ | 575 | /*********************** END TX SCHEDULER *************************************/ |
576 | 576 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index e5eb339107dd..0a5d7cf25196 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -163,197 +163,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
163 | spin_unlock_irqrestore(&q->lock, flags); | 163 | spin_unlock_irqrestore(&q->lock, flags); |
164 | } | 164 | } |
165 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 165 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
166 | /** | ||
167 | * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
168 | */ | ||
169 | static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
170 | dma_addr_t dma_addr) | ||
171 | { | ||
172 | return cpu_to_le32((u32)(dma_addr >> 8)); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * iwl_rx_queue_restock - refill RX queue from pre-allocated pool | ||
177 | * | ||
178 | * If there are slots in the RX queue that need to be restocked, | ||
179 | * and we have free pre-allocated buffers, fill the ranks as much | ||
180 | * as we can, pulling from rx_free. | ||
181 | * | ||
182 | * This moves the 'write' index forward to catch up with 'processed', and | ||
183 | * also updates the memory address in the firmware to reference the new | ||
184 | * target buffer. | ||
185 | */ | ||
186 | void iwl_rx_queue_restock(struct iwl_priv *priv) | ||
187 | { | ||
188 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
189 | struct list_head *element; | ||
190 | struct iwl_rx_mem_buffer *rxb; | ||
191 | unsigned long flags; | ||
192 | int write; | ||
193 | |||
194 | spin_lock_irqsave(&rxq->lock, flags); | ||
195 | write = rxq->write & ~0x7; | ||
196 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
197 | /* Get next free Rx buffer, remove from free list */ | ||
198 | element = rxq->rx_free.next; | ||
199 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
200 | list_del(element); | ||
201 | |||
202 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
203 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma); | ||
204 | rxq->queue[rxq->write] = rxb; | ||
205 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
206 | rxq->free_count--; | ||
207 | } | ||
208 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
209 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
210 | * refill it */ | ||
211 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
212 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
213 | |||
214 | |||
215 | /* If we've added more space for the firmware to place data, tell it. | ||
216 | * Increment device's write pointer in multiples of 8. */ | ||
217 | if (rxq->write_actual != (rxq->write & ~0x7)) { | ||
218 | spin_lock_irqsave(&rxq->lock, flags); | ||
219 | rxq->need_update = 1; | ||
220 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
221 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
222 | } | ||
223 | } | ||
224 | EXPORT_SYMBOL(iwl_rx_queue_restock); | ||
225 | |||
226 | |||
227 | /** | ||
228 | * iwl_rx_replenish - Move all used packet from rx_used to rx_free | ||
229 | * | ||
230 | * When moving to rx_free an SKB is allocated for the slot. | ||
231 | * | ||
232 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
233 | * This is called as a scheduled work item (except for during initialization) | ||
234 | */ | ||
235 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
236 | { | ||
237 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
238 | struct list_head *element; | ||
239 | struct iwl_rx_mem_buffer *rxb; | ||
240 | struct page *page; | ||
241 | unsigned long flags; | ||
242 | gfp_t gfp_mask = priority; | ||
243 | |||
244 | while (1) { | ||
245 | spin_lock_irqsave(&rxq->lock, flags); | ||
246 | if (list_empty(&rxq->rx_used)) { | ||
247 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
248 | return; | ||
249 | } | ||
250 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
251 | |||
252 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
253 | gfp_mask |= __GFP_NOWARN; | ||
254 | |||
255 | if (priv->hw_params.rx_page_order > 0) | ||
256 | gfp_mask |= __GFP_COMP; | ||
257 | |||
258 | /* Alloc a new receive buffer */ | ||
259 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
260 | if (!page) { | ||
261 | if (net_ratelimit()) | ||
262 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " | ||
263 | "order: %d\n", | ||
264 | priv->hw_params.rx_page_order); | ||
265 | |||
266 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
267 | net_ratelimit()) | ||
268 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", | ||
269 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
270 | rxq->free_count); | ||
271 | /* We don't reschedule replenish work here -- we will | ||
272 | * call the restock method and if it still needs | ||
273 | * more buffers it will schedule replenish */ | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | spin_lock_irqsave(&rxq->lock, flags); | ||
278 | |||
279 | if (list_empty(&rxq->rx_used)) { | ||
280 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
281 | __free_pages(page, priv->hw_params.rx_page_order); | ||
282 | return; | ||
283 | } | ||
284 | element = rxq->rx_used.next; | ||
285 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
286 | list_del(element); | ||
287 | |||
288 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
289 | |||
290 | rxb->page = page; | ||
291 | /* Get physical address of the RB */ | ||
292 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
293 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
294 | PCI_DMA_FROMDEVICE); | ||
295 | /* dma address must be no more than 36 bits */ | ||
296 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | ||
297 | /* and also 256 byte aligned! */ | ||
298 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | ||
299 | |||
300 | spin_lock_irqsave(&rxq->lock, flags); | ||
301 | |||
302 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
303 | rxq->free_count++; | ||
304 | priv->alloc_rxb_page++; | ||
305 | |||
306 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void iwl_rx_replenish(struct iwl_priv *priv) | ||
311 | { | ||
312 | unsigned long flags; | ||
313 | |||
314 | iwl_rx_allocate(priv, GFP_KERNEL); | ||
315 | |||
316 | spin_lock_irqsave(&priv->lock, flags); | ||
317 | iwl_rx_queue_restock(priv); | ||
318 | spin_unlock_irqrestore(&priv->lock, flags); | ||
319 | } | ||
320 | EXPORT_SYMBOL(iwl_rx_replenish); | ||
321 | |||
322 | void iwl_rx_replenish_now(struct iwl_priv *priv) | ||
323 | { | ||
324 | iwl_rx_allocate(priv, GFP_ATOMIC); | ||
325 | |||
326 | iwl_rx_queue_restock(priv); | ||
327 | } | ||
328 | EXPORT_SYMBOL(iwl_rx_replenish_now); | ||
329 | |||
330 | |||
331 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
332 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
333 | * This free routine walks the list of POOL entries and if SKB is set to | ||
334 | * non NULL it is unmapped and freed | ||
335 | */ | ||
336 | void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
337 | { | ||
338 | int i; | ||
339 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
340 | if (rxq->pool[i].page != NULL) { | ||
341 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
342 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
343 | PCI_DMA_FROMDEVICE); | ||
344 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
345 | rxq->pool[i].page = NULL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
350 | rxq->dma_addr); | ||
351 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
352 | rxq->rb_stts, rxq->rb_stts_dma); | ||
353 | rxq->bd = NULL; | ||
354 | rxq->rb_stts = NULL; | ||
355 | } | ||
356 | EXPORT_SYMBOL(iwl_rx_queue_free); | ||
357 | 166 | ||
358 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 167 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
359 | { | 168 | { |
@@ -396,98 +205,6 @@ err_bd: | |||
396 | } | 205 | } |
397 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | 206 | EXPORT_SYMBOL(iwl_rx_queue_alloc); |
398 | 207 | ||
399 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
400 | { | ||
401 | unsigned long flags; | ||
402 | int i; | ||
403 | spin_lock_irqsave(&rxq->lock, flags); | ||
404 | INIT_LIST_HEAD(&rxq->rx_free); | ||
405 | INIT_LIST_HEAD(&rxq->rx_used); | ||
406 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
407 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
408 | /* In the reset function, these buffers may have been allocated | ||
409 | * to an SKB, so we need to unmap and free potential storage */ | ||
410 | if (rxq->pool[i].page != NULL) { | ||
411 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
412 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
413 | PCI_DMA_FROMDEVICE); | ||
414 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
415 | rxq->pool[i].page = NULL; | ||
416 | } | ||
417 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
418 | } | ||
419 | |||
420 | /* Set us so that we have processed and used all buffers, but have | ||
421 | * not restocked the Rx queue with fresh buffers */ | ||
422 | rxq->read = rxq->write = 0; | ||
423 | rxq->write_actual = 0; | ||
424 | rxq->free_count = 0; | ||
425 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
426 | } | ||
427 | |||
428 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
429 | { | ||
430 | u32 rb_size; | ||
431 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
432 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
433 | |||
434 | if (!priv->cfg->use_isr_legacy) | ||
435 | rb_timeout = RX_RB_TIMEOUT; | ||
436 | |||
437 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
438 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
439 | else | ||
440 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
441 | |||
442 | /* Stop Rx DMA */ | ||
443 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
444 | |||
445 | /* Reset driver's Rx queue write index */ | ||
446 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
447 | |||
448 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
449 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
450 | (u32)(rxq->dma_addr >> 8)); | ||
451 | |||
452 | /* Tell device where in DRAM to update its Rx status */ | ||
453 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
454 | rxq->rb_stts_dma >> 4); | ||
455 | |||
456 | /* Enable Rx DMA | ||
457 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
458 | * the credit mechanism in 5000 HW RX FIFO | ||
459 | * Direct rx interrupts to hosts | ||
460 | * Rx buffer size 4 or 8k | ||
461 | * RB timeout 0x10 | ||
462 | * 256 RBDs | ||
463 | */ | ||
464 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
465 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
466 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
467 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
468 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
469 | rb_size| | ||
470 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
471 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
472 | |||
473 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
474 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | int iwl_rxq_stop(struct iwl_priv *priv) | ||
480 | { | ||
481 | |||
482 | /* stop Rx DMA */ | ||
483 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
484 | iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
485 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | EXPORT_SYMBOL(iwl_rxq_stop); | ||
490 | |||
491 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 208 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
492 | struct iwl_rx_mem_buffer *rxb) | 209 | struct iwl_rx_mem_buffer *rxb) |
493 | 210 | ||
@@ -543,6 +260,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
543 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | 260 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; |
544 | int bcn_silence_c = | 261 | int bcn_silence_c = |
545 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | 262 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; |
263 | int last_rx_noise; | ||
546 | 264 | ||
547 | if (bcn_silence_a) { | 265 | if (bcn_silence_a) { |
548 | total_silence += bcn_silence_a; | 266 | total_silence += bcn_silence_a; |
@@ -559,13 +277,13 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
559 | 277 | ||
560 | /* Average among active antennas */ | 278 | /* Average among active antennas */ |
561 | if (num_active_rx) | 279 | if (num_active_rx) |
562 | priv->last_rx_noise = (total_silence / num_active_rx) - 107; | 280 | last_rx_noise = (total_silence / num_active_rx) - 107; |
563 | else | 281 | else |
564 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 282 | last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
565 | 283 | ||
566 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", | 284 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", |
567 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | 285 | bcn_silence_a, bcn_silence_b, bcn_silence_c, |
568 | priv->last_rx_noise); | 286 | last_rx_noise); |
569 | } | 287 | } |
570 | 288 | ||
571 | #ifdef CONFIG_IWLWIFI_DEBUG | 289 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -617,29 +335,20 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
617 | 335 | ||
618 | #define REG_RECALIB_PERIOD (60) | 336 | #define REG_RECALIB_PERIOD (60) |
619 | 337 | ||
620 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | 338 | /** |
621 | void iwl_rx_statistics(struct iwl_priv *priv, | 339 | * iwl_good_plcp_health - checks for plcp error. |
622 | struct iwl_rx_mem_buffer *rxb) | 340 | * |
341 | * When the plcp error is exceeding the thresholds, reset the radio | ||
342 | * to improve the throughput. | ||
343 | */ | ||
344 | bool iwl_good_plcp_health(struct iwl_priv *priv, | ||
345 | struct iwl_rx_packet *pkt) | ||
623 | { | 346 | { |
624 | int change; | 347 | bool rc = true; |
625 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
626 | int combined_plcp_delta; | 348 | int combined_plcp_delta; |
627 | unsigned int plcp_msec; | 349 | unsigned int plcp_msec; |
628 | unsigned long plcp_received_jiffies; | 350 | unsigned long plcp_received_jiffies; |
629 | 351 | ||
630 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
631 | (int)sizeof(priv->statistics), | ||
632 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
633 | |||
634 | change = ((priv->statistics.general.temperature != | ||
635 | pkt->u.stats.general.temperature) || | ||
636 | ((priv->statistics.flag & | ||
637 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | ||
638 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | ||
639 | |||
640 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
641 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
642 | #endif | ||
643 | /* | 352 | /* |
644 | * check for plcp_err and trigger radio reset if it exceeds | 353 | * check for plcp_err and trigger radio reset if it exceeds |
645 | * the plcp error threshold plcp_delta. | 354 | * the plcp error threshold plcp_delta. |
@@ -660,11 +369,11 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
660 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); | 369 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); |
661 | 370 | ||
662 | if ((combined_plcp_delta > 0) && | 371 | if ((combined_plcp_delta > 0) && |
663 | ((combined_plcp_delta * 100) / plcp_msec) > | 372 | ((combined_plcp_delta * 100) / plcp_msec) > |
664 | priv->cfg->plcp_delta_threshold) { | 373 | priv->cfg->plcp_delta_threshold) { |
665 | /* | 374 | /* |
666 | * if plcp_err exceed the threshold, the following | 375 | * if plcp_err exceed the threshold, |
667 | * data is printed in csv format: | 376 | * the following data is printed in csv format: |
668 | * Text: plcp_err exceeded %d, | 377 | * Text: plcp_err exceeded %d, |
669 | * Received ofdm.plcp_err, | 378 | * Received ofdm.plcp_err, |
670 | * Current ofdm.plcp_err, | 379 | * Current ofdm.plcp_err, |
@@ -673,22 +382,76 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
673 | * combined_plcp_delta, | 382 | * combined_plcp_delta, |
674 | * plcp_msec | 383 | * plcp_msec |
675 | */ | 384 | */ |
676 | IWL_DEBUG_RADIO(priv, PLCP_MSG, | 385 | IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " |
386 | "%u, %u, %u, %u, %d, %u mSecs\n", | ||
677 | priv->cfg->plcp_delta_threshold, | 387 | priv->cfg->plcp_delta_threshold, |
678 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | 388 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), |
679 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), | 389 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), |
680 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | 390 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), |
681 | le32_to_cpu( | 391 | le32_to_cpu( |
682 | priv->statistics.rx.ofdm_ht.plcp_err), | 392 | priv->statistics.rx.ofdm_ht.plcp_err), |
683 | combined_plcp_delta, plcp_msec); | 393 | combined_plcp_delta, plcp_msec); |
394 | rc = false; | ||
395 | } | ||
396 | } | ||
397 | return rc; | ||
398 | } | ||
399 | EXPORT_SYMBOL(iwl_good_plcp_health); | ||
684 | 400 | ||
685 | /* | 401 | void iwl_recover_from_statistics(struct iwl_priv *priv, |
686 | * Reset the RF radio due to the high plcp | 402 | struct iwl_rx_packet *pkt) |
687 | * error rate | 403 | { |
688 | */ | 404 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
689 | iwl_force_reset(priv, IWL_RF_RESET); | 405 | return; |
406 | if (iwl_is_associated(priv)) { | ||
407 | if (priv->cfg->ops->lib->check_ack_health) { | ||
408 | if (!priv->cfg->ops->lib->check_ack_health( | ||
409 | priv, pkt)) { | ||
410 | /* | ||
411 | * low ack count detected | ||
412 | * restart Firmware | ||
413 | */ | ||
414 | IWL_ERR(priv, "low ack count detected, " | ||
415 | "restart firmware\n"); | ||
416 | if (!iwl_force_reset(priv, IWL_FW_RESET)) | ||
417 | return; | ||
418 | } | ||
419 | } | ||
420 | if (priv->cfg->ops->lib->check_plcp_health) { | ||
421 | if (!priv->cfg->ops->lib->check_plcp_health( | ||
422 | priv, pkt)) { | ||
423 | /* | ||
424 | * high plcp error detected | ||
425 | * reset Radio | ||
426 | */ | ||
427 | iwl_force_reset(priv, IWL_RF_RESET); | ||
428 | } | ||
690 | } | 429 | } |
691 | } | 430 | } |
431 | } | ||
432 | EXPORT_SYMBOL(iwl_recover_from_statistics); | ||
433 | |||
434 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
435 | struct iwl_rx_mem_buffer *rxb) | ||
436 | { | ||
437 | int change; | ||
438 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
439 | |||
440 | |||
441 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | ||
442 | (int)sizeof(priv->statistics), | ||
443 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
444 | |||
445 | change = ((priv->statistics.general.temperature != | ||
446 | pkt->u.stats.general.temperature) || | ||
447 | ((priv->statistics.flag & | ||
448 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | ||
449 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | ||
450 | |||
451 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
452 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
453 | #endif | ||
454 | iwl_recover_from_statistics(priv, pkt); | ||
692 | 455 | ||
693 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | 456 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); |
694 | 457 | ||
@@ -731,139 +494,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
731 | } | 494 | } |
732 | EXPORT_SYMBOL(iwl_reply_statistics); | 495 | EXPORT_SYMBOL(iwl_reply_statistics); |
733 | 496 | ||
734 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
735 | static inline int iwl_calc_rssi(struct iwl_priv *priv, | ||
736 | struct iwl_rx_phy_res *rx_resp) | ||
737 | { | ||
738 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
739 | } | ||
740 | |||
741 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
742 | /** | ||
743 | * iwl_dbg_report_frame - dump frame to syslog during debug sessions | ||
744 | * | ||
745 | * You may hack this function to show different aspects of received frames, | ||
746 | * including selective frame dumps. | ||
747 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
748 | * All beacon and probe response frames are printed. | ||
749 | */ | ||
750 | static void iwl_dbg_report_frame(struct iwl_priv *priv, | ||
751 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
752 | struct ieee80211_hdr *header, int group100) | ||
753 | { | ||
754 | u32 to_us; | ||
755 | u32 print_summary = 0; | ||
756 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
757 | u32 hundred = 0; | ||
758 | u32 dataframe = 0; | ||
759 | __le16 fc; | ||
760 | u16 seq_ctl; | ||
761 | u16 channel; | ||
762 | u16 phy_flags; | ||
763 | u32 rate_n_flags; | ||
764 | u32 tsf_low; | ||
765 | int rssi; | ||
766 | |||
767 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
768 | return; | ||
769 | |||
770 | /* MAC header */ | ||
771 | fc = header->frame_control; | ||
772 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
773 | |||
774 | /* metadata */ | ||
775 | channel = le16_to_cpu(phy_res->channel); | ||
776 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
777 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
778 | |||
779 | /* signal statistics */ | ||
780 | rssi = iwl_calc_rssi(priv, phy_res); | ||
781 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
782 | |||
783 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
784 | |||
785 | /* if data frame is to us and all is good, | ||
786 | * (optionally) print summary for only 1 out of every 100 */ | ||
787 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
788 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
789 | dataframe = 1; | ||
790 | if (!group100) | ||
791 | print_summary = 1; /* print each frame */ | ||
792 | else if (priv->framecnt_to_us < 100) { | ||
793 | priv->framecnt_to_us++; | ||
794 | print_summary = 0; | ||
795 | } else { | ||
796 | priv->framecnt_to_us = 0; | ||
797 | print_summary = 1; | ||
798 | hundred = 1; | ||
799 | } | ||
800 | } else { | ||
801 | /* print summary for all other frames */ | ||
802 | print_summary = 1; | ||
803 | } | ||
804 | |||
805 | if (print_summary) { | ||
806 | char *title; | ||
807 | int rate_idx; | ||
808 | u32 bitrate; | ||
809 | |||
810 | if (hundred) | ||
811 | title = "100Frames"; | ||
812 | else if (ieee80211_has_retry(fc)) | ||
813 | title = "Retry"; | ||
814 | else if (ieee80211_is_assoc_resp(fc)) | ||
815 | title = "AscRsp"; | ||
816 | else if (ieee80211_is_reassoc_resp(fc)) | ||
817 | title = "RasRsp"; | ||
818 | else if (ieee80211_is_probe_resp(fc)) { | ||
819 | title = "PrbRsp"; | ||
820 | print_dump = 1; /* dump frame contents */ | ||
821 | } else if (ieee80211_is_beacon(fc)) { | ||
822 | title = "Beacon"; | ||
823 | print_dump = 1; /* dump frame contents */ | ||
824 | } else if (ieee80211_is_atim(fc)) | ||
825 | title = "ATIM"; | ||
826 | else if (ieee80211_is_auth(fc)) | ||
827 | title = "Auth"; | ||
828 | else if (ieee80211_is_deauth(fc)) | ||
829 | title = "DeAuth"; | ||
830 | else if (ieee80211_is_disassoc(fc)) | ||
831 | title = "DisAssoc"; | ||
832 | else | ||
833 | title = "Frame"; | ||
834 | |||
835 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
836 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
837 | bitrate = 0; | ||
838 | WARN_ON_ONCE(1); | ||
839 | } else { | ||
840 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
841 | } | ||
842 | |||
843 | /* print frame summary. | ||
844 | * MAC addresses show just the last byte (for brevity), | ||
845 | * but you can hack it to show more, if you'd like to. */ | ||
846 | if (dataframe) | ||
847 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
848 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
849 | title, le16_to_cpu(fc), header->addr1[5], | ||
850 | length, rssi, channel, bitrate); | ||
851 | else { | ||
852 | /* src/dst addresses assume managed mode */ | ||
853 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
854 | "len=%u, rssi=%d, tim=%lu usec, " | ||
855 | "phy=0x%02x, chnl=%d\n", | ||
856 | title, le16_to_cpu(fc), header->addr1[5], | ||
857 | header->addr3[5], length, rssi, | ||
858 | tsf_low - priv->scan_start_tsf, | ||
859 | phy_flags, channel); | ||
860 | } | ||
861 | } | ||
862 | if (print_dump) | ||
863 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
864 | } | ||
865 | #endif | ||
866 | |||
867 | /* | 497 | /* |
868 | * returns non-zero if packet should be dropped | 498 | * returns non-zero if packet should be dropped |
869 | */ | 499 | */ |
@@ -911,305 +541,3 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
911 | return 0; | 541 | return 0; |
912 | } | 542 | } |
913 | EXPORT_SYMBOL(iwl_set_decrypted_flag); | 543 | EXPORT_SYMBOL(iwl_set_decrypted_flag); |
914 | |||
915 | static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
916 | { | ||
917 | u32 decrypt_out = 0; | ||
918 | |||
919 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
920 | RX_RES_STATUS_STATION_FOUND) | ||
921 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
922 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
923 | |||
924 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
925 | |||
926 | /* packet was not encrypted */ | ||
927 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
928 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
929 | return decrypt_out; | ||
930 | |||
931 | /* packet was encrypted with unknown alg */ | ||
932 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
933 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
934 | return decrypt_out; | ||
935 | |||
936 | /* decryption was not done in HW */ | ||
937 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
938 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
939 | return decrypt_out; | ||
940 | |||
941 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
942 | |||
943 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
944 | /* alg is CCM: check MIC only */ | ||
945 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
946 | /* Bad MIC */ | ||
947 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
948 | else | ||
949 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
950 | |||
951 | break; | ||
952 | |||
953 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
954 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
955 | /* Bad TTAK */ | ||
956 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
957 | break; | ||
958 | } | ||
959 | /* fall through if TTAK OK */ | ||
960 | default: | ||
961 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
962 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
963 | else | ||
964 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
965 | break; | ||
966 | }; | ||
967 | |||
968 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
969 | decrypt_in, decrypt_out); | ||
970 | |||
971 | return decrypt_out; | ||
972 | } | ||
973 | |||
974 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
975 | struct ieee80211_hdr *hdr, | ||
976 | u16 len, | ||
977 | u32 ampdu_status, | ||
978 | struct iwl_rx_mem_buffer *rxb, | ||
979 | struct ieee80211_rx_status *stats) | ||
980 | { | ||
981 | struct sk_buff *skb; | ||
982 | int ret = 0; | ||
983 | __le16 fc = hdr->frame_control; | ||
984 | |||
985 | /* We only process data packets if the interface is open */ | ||
986 | if (unlikely(!priv->is_open)) { | ||
987 | IWL_DEBUG_DROP_LIMIT(priv, | ||
988 | "Dropping packet while interface is not open.\n"); | ||
989 | return; | ||
990 | } | ||
991 | |||
992 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
993 | if (!priv->cfg->mod_params->sw_crypto && | ||
994 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
995 | return; | ||
996 | |||
997 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | ||
998 | if (!skb) { | ||
999 | IWL_ERR(priv, "alloc_skb failed\n"); | ||
1000 | return; | ||
1001 | } | ||
1002 | |||
1003 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
1004 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
1005 | |||
1006 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
1007 | * linear SKB for management frame and data frame requires | ||
1008 | * software decryption or software defragementation. */ | ||
1009 | if (ieee80211_is_mgmt(fc) || | ||
1010 | ieee80211_has_protected(fc) || | ||
1011 | ieee80211_has_morefrags(fc) || | ||
1012 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || | ||
1013 | (ieee80211_is_data_qos(fc) && | ||
1014 | *ieee80211_get_qos_ctl(hdr) & | ||
1015 | IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) | ||
1016 | ret = skb_linearize(skb); | ||
1017 | else | ||
1018 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
1019 | 0 : -ENOMEM; | ||
1020 | |||
1021 | if (ret) { | ||
1022 | kfree_skb(skb); | ||
1023 | goto out; | ||
1024 | } | ||
1025 | |||
1026 | /* | ||
1027 | * XXX: We cannot touch the page and its virtual memory (hdr) after | ||
1028 | * here. It might have already been freed by the above skb change. | ||
1029 | */ | ||
1030 | |||
1031 | iwl_update_stats(priv, false, fc, len); | ||
1032 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
1033 | |||
1034 | ieee80211_rx(priv->hw, skb); | ||
1035 | out: | ||
1036 | priv->alloc_rxb_page--; | ||
1037 | rxb->page = NULL; | ||
1038 | } | ||
1039 | |||
1040 | /* This is necessary only for a number of statistics, see the caller. */ | ||
1041 | static int iwl_is_network_packet(struct iwl_priv *priv, | ||
1042 | struct ieee80211_hdr *header) | ||
1043 | { | ||
1044 | /* Filter incoming packets to determine if they are targeted toward | ||
1045 | * this network, discarding packets coming from ourselves */ | ||
1046 | switch (priv->iw_mode) { | ||
1047 | case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ | ||
1048 | /* packets to our IBSS update information */ | ||
1049 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
1050 | case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ | ||
1051 | /* packets to our IBSS update information */ | ||
1052 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
1053 | default: | ||
1054 | return 1; | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | /* Called for REPLY_RX (legacy ABG frames), or | ||
1059 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
1060 | void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
1061 | struct iwl_rx_mem_buffer *rxb) | ||
1062 | { | ||
1063 | struct ieee80211_hdr *header; | ||
1064 | struct ieee80211_rx_status rx_status; | ||
1065 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1066 | struct iwl_rx_phy_res *phy_res; | ||
1067 | __le32 rx_pkt_status; | ||
1068 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
1069 | u32 len; | ||
1070 | u32 ampdu_status; | ||
1071 | u32 rate_n_flags; | ||
1072 | |||
1073 | /** | ||
1074 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
1075 | * REPLY_RX: physical layer info is in this buffer | ||
1076 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1077 | * command and cached in priv->last_phy_res | ||
1078 | * | ||
1079 | * Here we set up local variables depending on which command is | ||
1080 | * received. | ||
1081 | */ | ||
1082 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1083 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1084 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1085 | + phy_res->cfg_phy_cnt); | ||
1086 | |||
1087 | len = le16_to_cpu(phy_res->byte_count); | ||
1088 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1089 | phy_res->cfg_phy_cnt + len); | ||
1090 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1091 | } else { | ||
1092 | if (!priv->last_phy_res[0]) { | ||
1093 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1094 | return; | ||
1095 | } | ||
1096 | phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
1097 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1098 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1099 | len = le16_to_cpu(amsdu->byte_count); | ||
1100 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1101 | ampdu_status = iwl_translate_rx_status(priv, | ||
1102 | le32_to_cpu(rx_pkt_status)); | ||
1103 | } | ||
1104 | |||
1105 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1106 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1107 | phy_res->cfg_phy_cnt); | ||
1108 | return; | ||
1109 | } | ||
1110 | |||
1111 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1112 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1113 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1114 | le32_to_cpu(rx_pkt_status)); | ||
1115 | return; | ||
1116 | } | ||
1117 | |||
1118 | /* This will be used in several places later */ | ||
1119 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1120 | |||
1121 | /* rx_status carries information about the packet to mac80211 */ | ||
1122 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1123 | rx_status.freq = | ||
1124 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1125 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1126 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1127 | rx_status.rate_idx = | ||
1128 | iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1129 | rx_status.flag = 0; | ||
1130 | |||
1131 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1132 | * this W/A doesn't propagate it to the mac80211 */ | ||
1133 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1134 | |||
1135 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1136 | |||
1137 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1138 | rx_status.signal = iwl_calc_rssi(priv, phy_res); | ||
1139 | |||
1140 | /* Meaningful noise values are available only from beacon statistics, | ||
1141 | * which are gathered only when associated, and indicate noise | ||
1142 | * only for the associated network channel ... | ||
1143 | * Ignore these noise values while scanning (other channels) */ | ||
1144 | if (iwl_is_associated(priv) && | ||
1145 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
1146 | rx_status.noise = priv->last_rx_noise; | ||
1147 | } else { | ||
1148 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1149 | } | ||
1150 | |||
1151 | /* Reset beacon noise level if not associated. */ | ||
1152 | if (!iwl_is_associated(priv)) | ||
1153 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1154 | |||
1155 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1156 | /* Set "1" to report good data frames in groups of 100 */ | ||
1157 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1158 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1159 | #endif | ||
1160 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1161 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", | ||
1162 | rx_status.signal, rx_status.noise, | ||
1163 | (unsigned long long)rx_status.mactime); | ||
1164 | |||
1165 | /* | ||
1166 | * "antenna number" | ||
1167 | * | ||
1168 | * It seems that the antenna field in the phy flags value | ||
1169 | * is actually a bit field. This is undefined by radiotap, | ||
1170 | * it wants an actual antenna number but I always get "7" | ||
1171 | * for most legacy frames I receive indicating that the | ||
1172 | * same frame was received on all three RX chains. | ||
1173 | * | ||
1174 | * I think this field should be removed in favor of a | ||
1175 | * new 802.11n radiotap field "RX chains" that is defined | ||
1176 | * as a bitmask. | ||
1177 | */ | ||
1178 | rx_status.antenna = | ||
1179 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1180 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1181 | |||
1182 | /* set the preamble flag if appropriate */ | ||
1183 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1184 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1185 | |||
1186 | /* Set up the HT phy flags */ | ||
1187 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1188 | rx_status.flag |= RX_FLAG_HT; | ||
1189 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1190 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1191 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1192 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1193 | |||
1194 | if (iwl_is_network_packet(priv, header)) { | ||
1195 | priv->last_rx_rssi = rx_status.signal; | ||
1196 | priv->last_beacon_time = priv->ucode_beacon_time; | ||
1197 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); | ||
1198 | } | ||
1199 | |||
1200 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1201 | rxb, &rx_status); | ||
1202 | } | ||
1203 | EXPORT_SYMBOL(iwl_rx_reply_rx); | ||
1204 | |||
1205 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1206 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1207 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1208 | struct iwl_rx_mem_buffer *rxb) | ||
1209 | { | ||
1210 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1211 | priv->last_phy_res[0] = 1; | ||
1212 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1213 | sizeof(struct iwl_rx_phy_res)); | ||
1214 | } | ||
1215 | EXPORT_SYMBOL(iwl_rx_reply_rx_phy); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 9ab0e412bf10..107e173112f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -69,9 +69,8 @@ int iwl_scan_cancel(struct iwl_priv *priv) | |||
69 | } | 69 | } |
70 | 70 | ||
71 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 71 | if (test_bit(STATUS_SCANNING, &priv->status)) { |
72 | if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 72 | if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) { |
73 | IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); | 73 | IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); |
74 | set_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
75 | queue_work(priv->workqueue, &priv->abort_scan); | 74 | queue_work(priv->workqueue, &priv->abort_scan); |
76 | 75 | ||
77 | } else | 76 | } else |
@@ -201,9 +200,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, | |||
201 | le32_to_cpu(notif->statistics[0]), | 200 | le32_to_cpu(notif->statistics[0]), |
202 | le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); | 201 | le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); |
203 | #endif | 202 | #endif |
204 | |||
205 | if (!priv->is_internal_short_scan) | ||
206 | priv->next_scan_jiffies = 0; | ||
207 | } | 203 | } |
208 | 204 | ||
209 | /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ | 205 | /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ |
@@ -223,49 +219,24 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
223 | /* The HW is no longer scanning */ | 219 | /* The HW is no longer scanning */ |
224 | clear_bit(STATUS_SCAN_HW, &priv->status); | 220 | clear_bit(STATUS_SCAN_HW, &priv->status); |
225 | 221 | ||
226 | IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", | 222 | IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n", |
227 | (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? | 223 | (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2", |
228 | "2.4" : "5.2", | ||
229 | jiffies_to_msecs(elapsed_jiffies | 224 | jiffies_to_msecs(elapsed_jiffies |
230 | (priv->scan_pass_start, jiffies))); | 225 | (priv->scan_start, jiffies))); |
231 | 226 | ||
232 | /* Remove this scanned band from the list of pending | 227 | /* |
233 | * bands to scan, band G precedes A in order of scanning | 228 | * If a request to abort was given, or the scan did not succeed |
234 | * as seen in iwl_bg_request_scan */ | ||
235 | if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) | ||
236 | priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); | ||
237 | else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) | ||
238 | priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); | ||
239 | |||
240 | /* If a request to abort was given, or the scan did not succeed | ||
241 | * then we reset the scan state machine and terminate, | 229 | * then we reset the scan state machine and terminate, |
242 | * re-queuing another scan if one has been requested */ | 230 | * re-queuing another scan if one has been requested |
243 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 231 | */ |
232 | if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status)) | ||
244 | IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); | 233 | IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); |
245 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
246 | } else { | ||
247 | /* If there are more bands on this scan pass reschedule */ | ||
248 | if (priv->scan_bands) | ||
249 | goto reschedule; | ||
250 | } | ||
251 | |||
252 | if (!priv->is_internal_short_scan) | ||
253 | priv->next_scan_jiffies = 0; | ||
254 | 234 | ||
255 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); | 235 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); |
256 | 236 | ||
257 | clear_bit(STATUS_SCANNING, &priv->status); | 237 | clear_bit(STATUS_SCANNING, &priv->status); |
258 | 238 | ||
259 | IWL_DEBUG_INFO(priv, "Scan took %dms\n", | ||
260 | jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); | ||
261 | |||
262 | queue_work(priv->workqueue, &priv->scan_completed); | 239 | queue_work(priv->workqueue, &priv->scan_completed); |
263 | |||
264 | return; | ||
265 | |||
266 | reschedule: | ||
267 | priv->scan_pass_start = jiffies; | ||
268 | queue_work(priv->workqueue, &priv->request_scan); | ||
269 | } | 240 | } |
270 | 241 | ||
271 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | 242 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) |
@@ -294,7 +265,8 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
294 | EXPORT_SYMBOL(iwl_get_active_dwell_time); | 265 | EXPORT_SYMBOL(iwl_get_active_dwell_time); |
295 | 266 | ||
296 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 267 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
297 | enum ieee80211_band band) | 268 | enum ieee80211_band band, |
269 | struct ieee80211_vif *vif) | ||
298 | { | 270 | { |
299 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? | 271 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? |
300 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : | 272 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : |
@@ -304,7 +276,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
304 | /* If we're associated, we clamp the maximum passive | 276 | /* If we're associated, we clamp the maximum passive |
305 | * dwell time to be 98% of the beacon interval (minus | 277 | * dwell time to be 98% of the beacon interval (minus |
306 | * 2 * channel tune time) */ | 278 | * 2 * channel tune time) */ |
307 | passive = priv->beacon_int; | 279 | passive = vif ? vif->bss_conf.beacon_int : 0; |
308 | if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) | 280 | if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) |
309 | passive = IWL_PASSIVE_DWELL_BASE; | 281 | passive = IWL_PASSIVE_DWELL_BASE; |
310 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 282 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; |
@@ -314,150 +286,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
314 | } | 286 | } |
315 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); | 287 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); |
316 | 288 | ||
317 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||
318 | enum ieee80211_band band, | ||
319 | struct iwl_scan_channel *scan_ch) | ||
320 | { | ||
321 | const struct ieee80211_supported_band *sband; | ||
322 | const struct iwl_channel_info *ch_info; | ||
323 | u16 passive_dwell = 0; | ||
324 | u16 active_dwell = 0; | ||
325 | int i, added = 0; | ||
326 | u16 channel = 0; | ||
327 | |||
328 | sband = iwl_get_hw_mode(priv, band); | ||
329 | if (!sband) { | ||
330 | IWL_ERR(priv, "invalid band\n"); | ||
331 | return added; | ||
332 | } | ||
333 | |||
334 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
335 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
336 | |||
337 | if (passive_dwell <= active_dwell) | ||
338 | passive_dwell = active_dwell + 1; | ||
339 | |||
340 | /* only scan single channel, good enough to reset the RF */ | ||
341 | /* pick the first valid not in-use channel */ | ||
342 | if (band == IEEE80211_BAND_5GHZ) { | ||
343 | for (i = 14; i < priv->channel_count; i++) { | ||
344 | if (priv->channel_info[i].channel != | ||
345 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
346 | channel = priv->channel_info[i].channel; | ||
347 | ch_info = iwl_get_channel_info(priv, | ||
348 | band, channel); | ||
349 | if (is_channel_valid(ch_info)) | ||
350 | break; | ||
351 | } | ||
352 | } | ||
353 | } else { | ||
354 | for (i = 0; i < 14; i++) { | ||
355 | if (priv->channel_info[i].channel != | ||
356 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
357 | channel = | ||
358 | priv->channel_info[i].channel; | ||
359 | ch_info = iwl_get_channel_info(priv, | ||
360 | band, channel); | ||
361 | if (is_channel_valid(ch_info)) | ||
362 | break; | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | if (channel) { | ||
367 | scan_ch->channel = cpu_to_le16(channel); | ||
368 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
369 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
370 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
371 | /* Set txpower levels to defaults */ | ||
372 | scan_ch->dsp_atten = 110; | ||
373 | if (band == IEEE80211_BAND_5GHZ) | ||
374 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
375 | else | ||
376 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
377 | added++; | ||
378 | } else | ||
379 | IWL_ERR(priv, "no valid channel found\n"); | ||
380 | return added; | ||
381 | } | ||
382 | |||
383 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||
384 | enum ieee80211_band band, | ||
385 | u8 is_active, u8 n_probes, | ||
386 | struct iwl_scan_channel *scan_ch) | ||
387 | { | ||
388 | struct ieee80211_channel *chan; | ||
389 | const struct ieee80211_supported_band *sband; | ||
390 | const struct iwl_channel_info *ch_info; | ||
391 | u16 passive_dwell = 0; | ||
392 | u16 active_dwell = 0; | ||
393 | int added, i; | ||
394 | u16 channel; | ||
395 | |||
396 | sband = iwl_get_hw_mode(priv, band); | ||
397 | if (!sband) | ||
398 | return 0; | ||
399 | |||
400 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | ||
401 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
402 | |||
403 | if (passive_dwell <= active_dwell) | ||
404 | passive_dwell = active_dwell + 1; | ||
405 | |||
406 | for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { | ||
407 | chan = priv->scan_request->channels[i]; | ||
408 | |||
409 | if (chan->band != band) | ||
410 | continue; | ||
411 | |||
412 | channel = ieee80211_frequency_to_channel(chan->center_freq); | ||
413 | scan_ch->channel = cpu_to_le16(channel); | ||
414 | |||
415 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
416 | if (!is_channel_valid(ch_info)) { | ||
417 | IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", | ||
418 | channel); | ||
419 | continue; | ||
420 | } | ||
421 | |||
422 | if (!is_active || is_channel_passive(ch_info) || | ||
423 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
424 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
425 | else | ||
426 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | ||
427 | |||
428 | if (n_probes) | ||
429 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); | ||
430 | |||
431 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
432 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
433 | |||
434 | /* Set txpower levels to defaults */ | ||
435 | scan_ch->dsp_atten = 110; | ||
436 | |||
437 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
438 | * power level: | ||
439 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
440 | */ | ||
441 | if (band == IEEE80211_BAND_5GHZ) | ||
442 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
443 | else | ||
444 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
445 | |||
446 | IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", | ||
447 | channel, le32_to_cpu(scan_ch->type), | ||
448 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
449 | "ACTIVE" : "PASSIVE", | ||
450 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
451 | active_dwell : passive_dwell); | ||
452 | |||
453 | scan_ch++; | ||
454 | added++; | ||
455 | } | ||
456 | |||
457 | IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); | ||
458 | return added; | ||
459 | } | ||
460 | |||
461 | void iwl_init_scan_params(struct iwl_priv *priv) | 289 | void iwl_init_scan_params(struct iwl_priv *priv) |
462 | { | 290 | { |
463 | u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; | 291 | u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; |
@@ -468,32 +296,36 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
468 | } | 296 | } |
469 | EXPORT_SYMBOL(iwl_init_scan_params); | 297 | EXPORT_SYMBOL(iwl_init_scan_params); |
470 | 298 | ||
471 | static int iwl_scan_initiate(struct iwl_priv *priv) | 299 | static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
472 | { | 300 | { |
301 | WARN_ON(!mutex_is_locked(&priv->mutex)); | ||
302 | |||
473 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 303 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); |
474 | set_bit(STATUS_SCANNING, &priv->status); | 304 | set_bit(STATUS_SCANNING, &priv->status); |
475 | priv->is_internal_short_scan = false; | 305 | priv->is_internal_short_scan = false; |
476 | priv->scan_start = jiffies; | 306 | priv->scan_start = jiffies; |
477 | priv->scan_pass_start = priv->scan_start; | ||
478 | 307 | ||
479 | queue_work(priv->workqueue, &priv->request_scan); | 308 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) |
309 | return -EOPNOTSUPP; | ||
310 | |||
311 | priv->cfg->ops->utils->request_scan(priv, vif); | ||
480 | 312 | ||
481 | return 0; | 313 | return 0; |
482 | } | 314 | } |
483 | 315 | ||
484 | #define IWL_DELAY_NEXT_SCAN (HZ*2) | ||
485 | |||
486 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, | 316 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, |
487 | struct cfg80211_scan_request *req) | 317 | struct ieee80211_vif *vif, |
318 | struct cfg80211_scan_request *req) | ||
488 | { | 319 | { |
489 | unsigned long flags; | ||
490 | struct iwl_priv *priv = hw->priv; | 320 | struct iwl_priv *priv = hw->priv; |
491 | int ret, i; | 321 | int ret; |
492 | 322 | ||
493 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 323 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
494 | 324 | ||
325 | if (req->n_channels == 0) | ||
326 | return -EINVAL; | ||
327 | |||
495 | mutex_lock(&priv->mutex); | 328 | mutex_lock(&priv->mutex); |
496 | spin_lock_irqsave(&priv->lock, flags); | ||
497 | 329 | ||
498 | if (!iwl_is_ready_rf(priv)) { | 330 | if (!iwl_is_ready_rf(priv)) { |
499 | ret = -EIO; | 331 | ret = -EIO; |
@@ -513,30 +345,15 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
513 | goto out_unlock; | 345 | goto out_unlock; |
514 | } | 346 | } |
515 | 347 | ||
516 | /* We don't schedule scan within next_scan_jiffies period. | 348 | /* mac80211 will only ask for one band at a time */ |
517 | * Avoid scanning during possible EAPOL exchange, return | 349 | priv->scan_band = req->channels[0]->band; |
518 | * success immediately. | ||
519 | */ | ||
520 | if (priv->next_scan_jiffies && | ||
521 | time_after(priv->next_scan_jiffies, jiffies)) { | ||
522 | IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n"); | ||
523 | queue_work(priv->workqueue, &priv->scan_completed); | ||
524 | ret = 0; | ||
525 | goto out_unlock; | ||
526 | } | ||
527 | |||
528 | priv->scan_bands = 0; | ||
529 | for (i = 0; i < req->n_channels; i++) | ||
530 | priv->scan_bands |= BIT(req->channels[i]->band); | ||
531 | |||
532 | priv->scan_request = req; | 350 | priv->scan_request = req; |
533 | 351 | ||
534 | ret = iwl_scan_initiate(priv); | 352 | ret = iwl_scan_initiate(priv, vif); |
535 | 353 | ||
536 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 354 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
537 | 355 | ||
538 | out_unlock: | 356 | out_unlock: |
539 | spin_unlock_irqrestore(&priv->lock, flags); | ||
540 | mutex_unlock(&priv->mutex); | 357 | mutex_unlock(&priv->mutex); |
541 | 358 | ||
542 | return ret; | 359 | return ret; |
@@ -547,43 +364,47 @@ EXPORT_SYMBOL(iwl_mac_hw_scan); | |||
547 | * internal short scan, this function should only been called while associated. | 364 | * internal short scan, this function should only been called while associated. |
548 | * It will reset and tune the radio to prevent possible RF related problem | 365 | * It will reset and tune the radio to prevent possible RF related problem |
549 | */ | 366 | */ |
550 | int iwl_internal_short_hw_scan(struct iwl_priv *priv) | 367 | void iwl_internal_short_hw_scan(struct iwl_priv *priv) |
551 | { | 368 | { |
552 | int ret = 0; | 369 | queue_work(priv->workqueue, &priv->start_internal_scan); |
370 | } | ||
371 | |||
372 | void iwl_bg_start_internal_scan(struct work_struct *work) | ||
373 | { | ||
374 | struct iwl_priv *priv = | ||
375 | container_of(work, struct iwl_priv, start_internal_scan); | ||
376 | |||
377 | mutex_lock(&priv->mutex); | ||
553 | 378 | ||
554 | if (!iwl_is_ready_rf(priv)) { | 379 | if (!iwl_is_ready_rf(priv)) { |
555 | ret = -EIO; | ||
556 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | 380 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); |
557 | goto out; | 381 | goto unlock; |
558 | } | 382 | } |
383 | |||
559 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 384 | if (test_bit(STATUS_SCANNING, &priv->status)) { |
560 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 385 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
561 | ret = -EAGAIN; | 386 | goto unlock; |
562 | goto out; | ||
563 | } | 387 | } |
388 | |||
564 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 389 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { |
565 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | 390 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); |
566 | ret = -EAGAIN; | 391 | goto unlock; |
567 | goto out; | ||
568 | } | 392 | } |
569 | 393 | ||
570 | priv->scan_bands = 0; | 394 | priv->scan_band = priv->band; |
571 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
572 | priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); | ||
573 | else | ||
574 | priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); | ||
575 | 395 | ||
576 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); | 396 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); |
577 | set_bit(STATUS_SCANNING, &priv->status); | 397 | set_bit(STATUS_SCANNING, &priv->status); |
578 | priv->is_internal_short_scan = true; | 398 | priv->is_internal_short_scan = true; |
579 | queue_work(priv->workqueue, &priv->request_scan); | ||
580 | 399 | ||
581 | out: | 400 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) |
582 | return ret; | 401 | goto unlock; |
583 | } | ||
584 | EXPORT_SYMBOL(iwl_internal_short_hw_scan); | ||
585 | 402 | ||
586 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) | 403 | priv->cfg->ops->utils->request_scan(priv, NULL); |
404 | unlock: | ||
405 | mutex_unlock(&priv->mutex); | ||
406 | } | ||
407 | EXPORT_SYMBOL(iwl_bg_start_internal_scan); | ||
587 | 408 | ||
588 | void iwl_bg_scan_check(struct work_struct *data) | 409 | void iwl_bg_scan_check(struct work_struct *data) |
589 | { | 410 | { |
@@ -646,276 +467,15 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
646 | if (WARN_ON(left < ie_len)) | 467 | if (WARN_ON(left < ie_len)) |
647 | return len; | 468 | return len; |
648 | 469 | ||
649 | if (ies) | 470 | if (ies && ie_len) { |
650 | memcpy(pos, ies, ie_len); | 471 | memcpy(pos, ies, ie_len); |
651 | len += ie_len; | 472 | len += ie_len; |
652 | left -= ie_len; | 473 | } |
653 | 474 | ||
654 | return (u16)len; | 475 | return (u16)len; |
655 | } | 476 | } |
656 | EXPORT_SYMBOL(iwl_fill_probe_req); | 477 | EXPORT_SYMBOL(iwl_fill_probe_req); |
657 | 478 | ||
658 | static void iwl_bg_request_scan(struct work_struct *data) | ||
659 | { | ||
660 | struct iwl_priv *priv = | ||
661 | container_of(data, struct iwl_priv, request_scan); | ||
662 | struct iwl_host_cmd cmd = { | ||
663 | .id = REPLY_SCAN_CMD, | ||
664 | .len = sizeof(struct iwl_scan_cmd), | ||
665 | .flags = CMD_SIZE_HUGE, | ||
666 | }; | ||
667 | struct iwl_scan_cmd *scan; | ||
668 | struct ieee80211_conf *conf = NULL; | ||
669 | int ret = 0; | ||
670 | u32 rate_flags = 0; | ||
671 | u16 cmd_len; | ||
672 | u16 rx_chain = 0; | ||
673 | enum ieee80211_band band; | ||
674 | u8 n_probes = 0; | ||
675 | u8 rx_ant = priv->hw_params.valid_rx_ant; | ||
676 | u8 rate; | ||
677 | bool is_active = false; | ||
678 | int chan_mod; | ||
679 | u8 active_chains; | ||
680 | |||
681 | conf = ieee80211_get_hw_conf(priv->hw); | ||
682 | |||
683 | mutex_lock(&priv->mutex); | ||
684 | |||
685 | cancel_delayed_work(&priv->scan_check); | ||
686 | |||
687 | if (!iwl_is_ready(priv)) { | ||
688 | IWL_WARN(priv, "request scan called when driver not ready.\n"); | ||
689 | goto done; | ||
690 | } | ||
691 | |||
692 | /* Make sure the scan wasn't canceled before this queued work | ||
693 | * was given the chance to run... */ | ||
694 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
695 | goto done; | ||
696 | |||
697 | /* This should never be called or scheduled if there is currently | ||
698 | * a scan active in the hardware. */ | ||
699 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
700 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " | ||
701 | "Ignoring second request.\n"); | ||
702 | ret = -EIO; | ||
703 | goto done; | ||
704 | } | ||
705 | |||
706 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
707 | IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); | ||
708 | goto done; | ||
709 | } | ||
710 | |||
711 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
712 | IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); | ||
713 | goto done; | ||
714 | } | ||
715 | |||
716 | if (iwl_is_rfkill(priv)) { | ||
717 | IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); | ||
718 | goto done; | ||
719 | } | ||
720 | |||
721 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
722 | IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); | ||
723 | goto done; | ||
724 | } | ||
725 | |||
726 | if (!priv->scan_bands) { | ||
727 | IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); | ||
728 | goto done; | ||
729 | } | ||
730 | |||
731 | if (!priv->scan) { | ||
732 | priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + | ||
733 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
734 | if (!priv->scan) { | ||
735 | ret = -ENOMEM; | ||
736 | goto done; | ||
737 | } | ||
738 | } | ||
739 | scan = priv->scan; | ||
740 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | ||
741 | |||
742 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | ||
743 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | ||
744 | |||
745 | if (iwl_is_associated(priv)) { | ||
746 | u16 interval = 0; | ||
747 | u32 extra; | ||
748 | u32 suspend_time = 100; | ||
749 | u32 scan_suspend_time = 100; | ||
750 | unsigned long flags; | ||
751 | |||
752 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | ||
753 | spin_lock_irqsave(&priv->lock, flags); | ||
754 | interval = priv->beacon_int; | ||
755 | spin_unlock_irqrestore(&priv->lock, flags); | ||
756 | |||
757 | scan->suspend_time = 0; | ||
758 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
759 | if (!interval) | ||
760 | interval = suspend_time; | ||
761 | |||
762 | extra = (suspend_time / interval) << 22; | ||
763 | scan_suspend_time = (extra | | ||
764 | ((suspend_time % interval) * 1024)); | ||
765 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | ||
766 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | ||
767 | scan_suspend_time, interval); | ||
768 | } | ||
769 | |||
770 | if (priv->is_internal_short_scan) { | ||
771 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
772 | } else if (priv->scan_request->n_ssids) { | ||
773 | int i, p = 0; | ||
774 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | ||
775 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
776 | /* always does wildcard anyway */ | ||
777 | if (!priv->scan_request->ssids[i].ssid_len) | ||
778 | continue; | ||
779 | scan->direct_scan[p].id = WLAN_EID_SSID; | ||
780 | scan->direct_scan[p].len = | ||
781 | priv->scan_request->ssids[i].ssid_len; | ||
782 | memcpy(scan->direct_scan[p].ssid, | ||
783 | priv->scan_request->ssids[i].ssid, | ||
784 | priv->scan_request->ssids[i].ssid_len); | ||
785 | n_probes++; | ||
786 | p++; | ||
787 | } | ||
788 | is_active = true; | ||
789 | } else | ||
790 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | ||
791 | |||
792 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | ||
793 | scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; | ||
794 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
795 | |||
796 | |||
797 | if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { | ||
798 | band = IEEE80211_BAND_2GHZ; | ||
799 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | ||
800 | chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) | ||
801 | >> RXON_FLG_CHANNEL_MODE_POS; | ||
802 | if (chan_mod == CHANNEL_MODE_PURE_40) { | ||
803 | rate = IWL_RATE_6M_PLCP; | ||
804 | } else { | ||
805 | rate = IWL_RATE_1M_PLCP; | ||
806 | rate_flags = RATE_MCS_CCK_MSK; | ||
807 | } | ||
808 | scan->good_CRC_th = 0; | ||
809 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { | ||
810 | band = IEEE80211_BAND_5GHZ; | ||
811 | rate = IWL_RATE_6M_PLCP; | ||
812 | /* | ||
813 | * If active scaning is requested but a certain channel | ||
814 | * is marked passive, we can do active scanning if we | ||
815 | * detect transmissions. | ||
816 | */ | ||
817 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | ||
818 | |||
819 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | ||
820 | * Avoid A (0x1) because of its off-channel reception on A-band. | ||
821 | */ | ||
822 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | ||
823 | rx_ant = ANT_BC; | ||
824 | } else { | ||
825 | IWL_WARN(priv, "Invalid scan band count\n"); | ||
826 | goto done; | ||
827 | } | ||
828 | |||
829 | priv->scan_tx_ant[band] = | ||
830 | iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); | ||
831 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | ||
832 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | ||
833 | |||
834 | /* In power save mode use one chain, otherwise use all chains */ | ||
835 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
836 | /* rx_ant has been set to all valid chains previously */ | ||
837 | active_chains = rx_ant & | ||
838 | ((u8)(priv->chain_noise_data.active_chains)); | ||
839 | if (!active_chains) | ||
840 | active_chains = rx_ant; | ||
841 | |||
842 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
843 | priv->chain_noise_data.active_chains); | ||
844 | |||
845 | rx_ant = first_antenna(active_chains); | ||
846 | } | ||
847 | /* MIMO is not used here, but value is required */ | ||
848 | rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | ||
849 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||
850 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | ||
851 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||
852 | scan->rx_chain = cpu_to_le16(rx_chain); | ||
853 | if (!priv->is_internal_short_scan) { | ||
854 | cmd_len = iwl_fill_probe_req(priv, | ||
855 | (struct ieee80211_mgmt *)scan->data, | ||
856 | priv->scan_request->ie, | ||
857 | priv->scan_request->ie_len, | ||
858 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
859 | } else { | ||
860 | cmd_len = iwl_fill_probe_req(priv, | ||
861 | (struct ieee80211_mgmt *)scan->data, | ||
862 | NULL, 0, | ||
863 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
864 | |||
865 | } | ||
866 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | ||
867 | if (iwl_is_monitor_mode(priv)) | ||
868 | scan->filter_flags = RXON_FILTER_PROMISC_MSK; | ||
869 | |||
870 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | ||
871 | RXON_FILTER_BCON_AWARE_MSK); | ||
872 | |||
873 | if (priv->is_internal_short_scan) { | ||
874 | scan->channel_count = | ||
875 | iwl_get_single_channel_for_scan(priv, band, | ||
876 | (void *)&scan->data[le16_to_cpu( | ||
877 | scan->tx_cmd.len)]); | ||
878 | } else { | ||
879 | scan->channel_count = | ||
880 | iwl_get_channels_for_scan(priv, band, | ||
881 | is_active, n_probes, | ||
882 | (void *)&scan->data[le16_to_cpu( | ||
883 | scan->tx_cmd.len)]); | ||
884 | } | ||
885 | if (scan->channel_count == 0) { | ||
886 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | ||
887 | goto done; | ||
888 | } | ||
889 | |||
890 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + | ||
891 | scan->channel_count * sizeof(struct iwl_scan_channel); | ||
892 | cmd.data = scan; | ||
893 | scan->len = cpu_to_le16(cmd.len); | ||
894 | |||
895 | set_bit(STATUS_SCAN_HW, &priv->status); | ||
896 | ret = iwl_send_cmd_sync(priv, &cmd); | ||
897 | if (ret) | ||
898 | goto done; | ||
899 | |||
900 | queue_delayed_work(priv->workqueue, &priv->scan_check, | ||
901 | IWL_SCAN_CHECK_WATCHDOG); | ||
902 | |||
903 | mutex_unlock(&priv->mutex); | ||
904 | return; | ||
905 | |||
906 | done: | ||
907 | /* Cannot perform scan. Make sure we clear scanning | ||
908 | * bits from status so next scan request can be performed. | ||
909 | * If we don't clear scanning status bit here all next scan | ||
910 | * will fail | ||
911 | */ | ||
912 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
913 | clear_bit(STATUS_SCANNING, &priv->status); | ||
914 | /* inform mac80211 scan aborted */ | ||
915 | queue_work(priv->workqueue, &priv->scan_completed); | ||
916 | mutex_unlock(&priv->mutex); | ||
917 | } | ||
918 | |||
919 | void iwl_bg_abort_scan(struct work_struct *work) | 479 | void iwl_bg_abort_scan(struct work_struct *work) |
920 | { | 480 | { |
921 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); | 481 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); |
@@ -963,8 +523,8 @@ EXPORT_SYMBOL(iwl_bg_scan_completed); | |||
963 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 523 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |
964 | { | 524 | { |
965 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 525 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); |
966 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); | ||
967 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 526 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); |
527 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | ||
968 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 528 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
969 | } | 529 | } |
970 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); | 530 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 4a6686fa6b36..85ed235ac901 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -29,57 +29,12 @@ | |||
29 | 29 | ||
30 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
32 | #include <linux/sched.h> | ||
32 | 33 | ||
33 | #include "iwl-dev.h" | 34 | #include "iwl-dev.h" |
34 | #include "iwl-core.h" | 35 | #include "iwl-core.h" |
35 | #include "iwl-sta.h" | 36 | #include "iwl-sta.h" |
36 | 37 | ||
37 | #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ | ||
38 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ | ||
39 | |||
40 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | ||
41 | { | ||
42 | int i; | ||
43 | int start = 0; | ||
44 | int ret = IWL_INVALID_STATION; | ||
45 | unsigned long flags; | ||
46 | |||
47 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || | ||
48 | (priv->iw_mode == NL80211_IFTYPE_AP)) | ||
49 | start = IWL_STA_ID; | ||
50 | |||
51 | if (is_broadcast_ether_addr(addr)) | ||
52 | return priv->hw_params.bcast_sta_id; | ||
53 | |||
54 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
55 | for (i = start; i < priv->hw_params.max_stations; i++) | ||
56 | if (priv->stations[i].used && | ||
57 | (!compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
58 | addr))) { | ||
59 | ret = i; | ||
60 | goto out; | ||
61 | } | ||
62 | |||
63 | IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", | ||
64 | addr, priv->num_stations); | ||
65 | |||
66 | out: | ||
67 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
68 | return ret; | ||
69 | } | ||
70 | EXPORT_SYMBOL(iwl_find_station); | ||
71 | |||
72 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | ||
73 | { | ||
74 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | ||
75 | return IWL_AP_ID; | ||
76 | } else { | ||
77 | u8 *da = ieee80211_get_DA(hdr); | ||
78 | return iwl_find_station(priv, da); | ||
79 | } | ||
80 | } | ||
81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | ||
82 | |||
83 | /* priv->sta_lock must be held */ | 38 | /* priv->sta_lock must be held */ |
84 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 39 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) |
85 | { | 40 | { |
@@ -132,7 +87,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
132 | sta_id); | 87 | sta_id); |
133 | break; | 88 | break; |
134 | case ADD_STA_MODIFY_NON_EXIST_STA: | 89 | case ADD_STA_MODIFY_NON_EXIST_STA: |
135 | IWL_ERR(priv, "Attempting to modify non-existing station %d \n", | 90 | IWL_ERR(priv, "Attempting to modify non-existing station %d\n", |
136 | sta_id); | 91 | sta_id); |
137 | break; | 92 | break; |
138 | default: | 93 | default: |
@@ -158,13 +113,6 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
158 | priv->stations[sta_id].sta.mode == | 113 | priv->stations[sta_id].sta.mode == |
159 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | 114 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", |
160 | addsta->sta.addr); | 115 | addsta->sta.addr); |
161 | |||
162 | /* | ||
163 | * Determine if we wanted to modify or add a station, | ||
164 | * if adding a station succeeded we have some more initialization | ||
165 | * to do when using station notification. TODO | ||
166 | */ | ||
167 | |||
168 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 116 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
169 | } | 117 | } |
170 | 118 | ||
@@ -190,6 +138,10 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
190 | .flags = flags, | 138 | .flags = flags, |
191 | .data = data, | 139 | .data = data, |
192 | }; | 140 | }; |
141 | u8 sta_id __maybe_unused = sta->sta.sta_id; | ||
142 | |||
143 | IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", | ||
144 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); | ||
193 | 145 | ||
194 | if (flags & CMD_ASYNC) | 146 | if (flags & CMD_ASYNC) |
195 | cmd.callback = iwl_add_sta_callback; | 147 | cmd.callback = iwl_add_sta_callback; |
@@ -263,18 +215,19 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | |||
263 | } | 215 | } |
264 | 216 | ||
265 | /** | 217 | /** |
266 | * iwl_add_station - Add station to tables in driver and device | 218 | * iwl_prep_station - Prepare station information for addition |
219 | * | ||
220 | * should be called with sta_lock held | ||
267 | */ | 221 | */ |
268 | u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | 222 | static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, |
269 | struct ieee80211_sta_ht_cap *ht_info) | 223 | bool is_ap, |
224 | struct ieee80211_sta_ht_cap *ht_info) | ||
270 | { | 225 | { |
271 | struct iwl_station_entry *station; | 226 | struct iwl_station_entry *station; |
272 | unsigned long flags_spin; | ||
273 | int i; | 227 | int i; |
274 | int sta_id = IWL_INVALID_STATION; | 228 | u8 sta_id = IWL_INVALID_STATION; |
275 | u16 rate; | 229 | u16 rate; |
276 | 230 | ||
277 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
278 | if (is_ap) | 231 | if (is_ap) |
279 | sta_id = IWL_AP_ID; | 232 | sta_id = IWL_AP_ID; |
280 | else if (is_broadcast_ether_addr(addr)) | 233 | else if (is_broadcast_ether_addr(addr)) |
@@ -292,20 +245,32 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
292 | sta_id = i; | 245 | sta_id = i; |
293 | } | 246 | } |
294 | 247 | ||
295 | /* These two conditions have the same outcome, but keep them separate | 248 | /* |
296 | since they have different meanings */ | 249 | * These two conditions have the same outcome, but keep them |
297 | if (unlikely(sta_id == IWL_INVALID_STATION)) { | 250 | * separate |
298 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 251 | */ |
252 | if (unlikely(sta_id == IWL_INVALID_STATION)) | ||
253 | return sta_id; | ||
254 | |||
255 | /* | ||
256 | * uCode is not able to deal with multiple requests to add a | ||
257 | * station. Keep track if one is in progress so that we do not send | ||
258 | * another. | ||
259 | */ | ||
260 | if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { | ||
261 | IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", | ||
262 | sta_id); | ||
299 | return sta_id; | 263 | return sta_id; |
300 | } | 264 | } |
301 | 265 | ||
302 | if (priv->stations[sta_id].used && | 266 | if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && |
267 | (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) && | ||
303 | !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { | 268 | !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { |
304 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 269 | IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", |
270 | sta_id, addr); | ||
305 | return sta_id; | 271 | return sta_id; |
306 | } | 272 | } |
307 | 273 | ||
308 | |||
309 | station = &priv->stations[sta_id]; | 274 | station = &priv->stations[sta_id]; |
310 | station->used = IWL_STA_DRIVER_ACTIVE; | 275 | station->used = IWL_STA_DRIVER_ACTIVE; |
311 | IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", | 276 | IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", |
@@ -319,10 +284,12 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
319 | station->sta.sta.sta_id = sta_id; | 284 | station->sta.sta.sta_id = sta_id; |
320 | station->sta.station_flags = 0; | 285 | station->sta.station_flags = 0; |
321 | 286 | ||
322 | /* BCAST station and IBSS stations do not work in HT mode */ | 287 | /* |
323 | if (sta_id != priv->hw_params.bcast_sta_id && | 288 | * OK to call unconditionally, since local stations (IBSS BSSID |
324 | priv->iw_mode != NL80211_IFTYPE_ADHOC) | 289 | * STA and broadcast STA) pass in a NULL ht_info, and mac80211 |
325 | iwl_set_ht_add_station(priv, sta_id, ht_info); | 290 | * doesn't allow HT IBSS. |
291 | */ | ||
292 | iwl_set_ht_add_station(priv, sta_id, ht_info); | ||
326 | 293 | ||
327 | /* 3945 only */ | 294 | /* 3945 only */ |
328 | rate = (priv->band == IEEE80211_BAND_5GHZ) ? | 295 | rate = (priv->band == IEEE80211_BAND_5GHZ) ? |
@@ -330,86 +297,221 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
330 | /* Turn on both antennas for the station... */ | 297 | /* Turn on both antennas for the station... */ |
331 | station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); | 298 | station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); |
332 | 299 | ||
300 | return sta_id; | ||
301 | |||
302 | } | ||
303 | |||
304 | #define STA_WAIT_TIMEOUT (HZ/2) | ||
305 | |||
306 | /** | ||
307 | * iwl_add_station_common - | ||
308 | */ | ||
309 | int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | ||
310 | bool is_ap, | ||
311 | struct ieee80211_sta_ht_cap *ht_info, | ||
312 | u8 *sta_id_r) | ||
313 | { | ||
314 | struct iwl_station_entry *station; | ||
315 | unsigned long flags_spin; | ||
316 | int ret = 0; | ||
317 | u8 sta_id; | ||
318 | |||
319 | *sta_id_r = 0; | ||
320 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
321 | sta_id = iwl_prep_station(priv, addr, is_ap, ht_info); | ||
322 | if (sta_id == IWL_INVALID_STATION) { | ||
323 | IWL_ERR(priv, "Unable to prepare station %pM for addition\n", | ||
324 | addr); | ||
325 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * uCode is not able to deal with multiple requests to add a | ||
331 | * station. Keep track if one is in progress so that we do not send | ||
332 | * another. | ||
333 | */ | ||
334 | if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) { | ||
335 | IWL_DEBUG_INFO(priv, "STA %d already in process of being added.\n", | ||
336 | sta_id); | ||
337 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
338 | return -EEXIST; | ||
339 | } | ||
340 | |||
341 | if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) && | ||
342 | (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | ||
343 | IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not adding again.\n", | ||
344 | sta_id, addr); | ||
345 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
346 | return -EEXIST; | ||
347 | } | ||
348 | |||
349 | priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; | ||
350 | station = &priv->stations[sta_id]; | ||
333 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 351 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
334 | 352 | ||
335 | /* Add station to device's station table */ | 353 | /* Add station to device's station table */ |
336 | iwl_send_add_sta(priv, &station->sta, flags); | 354 | ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); |
337 | return sta_id; | 355 | if (ret) { |
356 | IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr); | ||
357 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
358 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | ||
359 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
360 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
361 | } | ||
362 | *sta_id_r = sta_id; | ||
363 | return ret; | ||
364 | } | ||
365 | EXPORT_SYMBOL(iwl_add_station_common); | ||
366 | |||
367 | static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, | ||
368 | u8 sta_id) | ||
369 | { | ||
370 | int i, r; | ||
371 | struct iwl_link_quality_cmd *link_cmd; | ||
372 | u32 rate_flags; | ||
373 | |||
374 | link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); | ||
375 | if (!link_cmd) { | ||
376 | IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n"); | ||
377 | return NULL; | ||
378 | } | ||
379 | /* Set up the rate scaling to start at selected rate, fall back | ||
380 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
381 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
382 | r = IWL_RATE_6M_INDEX; | ||
383 | else | ||
384 | r = IWL_RATE_1M_INDEX; | ||
338 | 385 | ||
386 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
387 | rate_flags = 0; | ||
388 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
389 | rate_flags |= RATE_MCS_CCK_MSK; | ||
390 | |||
391 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | ||
392 | RATE_MCS_ANT_POS; | ||
393 | |||
394 | link_cmd->rs_table[i].rate_n_flags = | ||
395 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
396 | r = iwl_get_prev_ieee_rate(r); | ||
397 | } | ||
398 | |||
399 | link_cmd->general_params.single_stream_ant_msk = | ||
400 | first_antenna(priv->hw_params.valid_tx_ant); | ||
401 | |||
402 | link_cmd->general_params.dual_stream_ant_msk = | ||
403 | priv->hw_params.valid_tx_ant & | ||
404 | ~first_antenna(priv->hw_params.valid_tx_ant); | ||
405 | if (!link_cmd->general_params.dual_stream_ant_msk) { | ||
406 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | ||
407 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | ||
408 | link_cmd->general_params.dual_stream_ant_msk = | ||
409 | priv->hw_params.valid_tx_ant; | ||
410 | } | ||
411 | |||
412 | link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
413 | link_cmd->agg_params.agg_time_limit = | ||
414 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
415 | |||
416 | link_cmd->sta_id = sta_id; | ||
417 | |||
418 | return link_cmd; | ||
339 | } | 419 | } |
340 | EXPORT_SYMBOL(iwl_add_station); | ||
341 | 420 | ||
342 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr) | 421 | /* |
422 | * iwl_add_bssid_station - Add the special IBSS BSSID station | ||
423 | * | ||
424 | * Function sleeps. | ||
425 | */ | ||
426 | int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, | ||
427 | u8 *sta_id_r) | ||
343 | { | 428 | { |
429 | int ret; | ||
430 | u8 sta_id; | ||
431 | struct iwl_link_quality_cmd *link_cmd; | ||
344 | unsigned long flags; | 432 | unsigned long flags; |
345 | u8 sta_id = iwl_find_station(priv, addr); | ||
346 | 433 | ||
347 | BUG_ON(sta_id == IWL_INVALID_STATION); | 434 | if (*sta_id_r) |
435 | *sta_id_r = IWL_INVALID_STATION; | ||
348 | 436 | ||
349 | IWL_DEBUG_ASSOC(priv, "Removed STA from Ucode: %pM\n", addr); | 437 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); |
438 | if (ret) { | ||
439 | IWL_ERR(priv, "Unable to add station %pM\n", addr); | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | if (sta_id_r) | ||
444 | *sta_id_r = sta_id; | ||
350 | 445 | ||
351 | spin_lock_irqsave(&priv->sta_lock, flags); | 446 | spin_lock_irqsave(&priv->sta_lock, flags); |
447 | priv->stations[sta_id].used |= IWL_STA_LOCAL; | ||
448 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
352 | 449 | ||
353 | /* Ucode must be active and driver must be non active */ | 450 | if (init_rs) { |
354 | if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) | 451 | /* Set up default rate scaling table in device's station table */ |
355 | IWL_ERR(priv, "removed non active STA %d\n", sta_id); | 452 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); |
453 | if (!link_cmd) { | ||
454 | IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", | ||
455 | addr); | ||
456 | return -ENOMEM; | ||
457 | } | ||
356 | 458 | ||
357 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; | 459 | ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); |
460 | if (ret) | ||
461 | IWL_ERR(priv, "Link quality command failed (%d)\n", ret); | ||
358 | 462 | ||
359 | memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); | 463 | spin_lock_irqsave(&priv->sta_lock, flags); |
360 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 464 | priv->stations[sta_id].lq = link_cmd; |
465 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
466 | } | ||
467 | |||
468 | return 0; | ||
361 | } | 469 | } |
470 | EXPORT_SYMBOL(iwl_add_bssid_station); | ||
362 | 471 | ||
363 | static void iwl_remove_sta_callback(struct iwl_priv *priv, | 472 | /** |
364 | struct iwl_device_cmd *cmd, | 473 | * iwl_sta_ucode_deactivate - deactivate ucode status for a station |
365 | struct iwl_rx_packet *pkt) | 474 | * |
475 | * priv->sta_lock must be held | ||
476 | */ | ||
477 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) | ||
366 | { | 478 | { |
367 | struct iwl_rem_sta_cmd *rm_sta = | 479 | /* Ucode must be active and driver must be non active */ |
368 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; | 480 | if ((priv->stations[sta_id].used & |
369 | const u8 *addr = rm_sta->addr; | 481 | (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE) |
482 | IWL_ERR(priv, "removed non active STA %u\n", sta_id); | ||
370 | 483 | ||
371 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | 484 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; |
372 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | ||
373 | pkt->hdr.flags); | ||
374 | return; | ||
375 | } | ||
376 | 485 | ||
377 | switch (pkt->u.rem_sta.status) { | 486 | memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); |
378 | case REM_STA_SUCCESS_MSK: | 487 | IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id); |
379 | iwl_sta_ucode_deactivate(priv, addr); | ||
380 | break; | ||
381 | default: | ||
382 | IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); | ||
383 | break; | ||
384 | } | ||
385 | } | 488 | } |
386 | 489 | ||
387 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | 490 | static int iwl_send_remove_station(struct iwl_priv *priv, |
388 | u8 flags) | 491 | struct iwl_station_entry *station) |
389 | { | 492 | { |
390 | struct iwl_rx_packet *pkt; | 493 | struct iwl_rx_packet *pkt; |
391 | int ret; | 494 | int ret; |
392 | 495 | ||
496 | unsigned long flags_spin; | ||
393 | struct iwl_rem_sta_cmd rm_sta_cmd; | 497 | struct iwl_rem_sta_cmd rm_sta_cmd; |
394 | 498 | ||
395 | struct iwl_host_cmd cmd = { | 499 | struct iwl_host_cmd cmd = { |
396 | .id = REPLY_REMOVE_STA, | 500 | .id = REPLY_REMOVE_STA, |
397 | .len = sizeof(struct iwl_rem_sta_cmd), | 501 | .len = sizeof(struct iwl_rem_sta_cmd), |
398 | .flags = flags, | 502 | .flags = CMD_SYNC, |
399 | .data = &rm_sta_cmd, | 503 | .data = &rm_sta_cmd, |
400 | }; | 504 | }; |
401 | 505 | ||
402 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); | 506 | memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); |
403 | rm_sta_cmd.num_sta = 1; | 507 | rm_sta_cmd.num_sta = 1; |
404 | memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN); | 508 | memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); |
509 | |||
510 | cmd.flags |= CMD_WANT_SKB; | ||
405 | 511 | ||
406 | if (flags & CMD_ASYNC) | ||
407 | cmd.callback = iwl_remove_sta_callback; | ||
408 | else | ||
409 | cmd.flags |= CMD_WANT_SKB; | ||
410 | ret = iwl_send_cmd(priv, &cmd); | 512 | ret = iwl_send_cmd(priv, &cmd); |
411 | 513 | ||
412 | if (ret || (flags & CMD_ASYNC)) | 514 | if (ret) |
413 | return ret; | 515 | return ret; |
414 | 516 | ||
415 | pkt = (struct iwl_rx_packet *)cmd.reply_page; | 517 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
@@ -422,7 +524,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
422 | if (!ret) { | 524 | if (!ret) { |
423 | switch (pkt->u.rem_sta.status) { | 525 | switch (pkt->u.rem_sta.status) { |
424 | case REM_STA_SUCCESS_MSK: | 526 | case REM_STA_SUCCESS_MSK: |
425 | iwl_sta_ucode_deactivate(priv, addr); | 527 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
528 | iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); | ||
529 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
426 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 530 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
427 | break; | 531 | break; |
428 | default: | 532 | default: |
@@ -439,45 +543,48 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
439 | /** | 543 | /** |
440 | * iwl_remove_station - Remove driver's knowledge of station. | 544 | * iwl_remove_station - Remove driver's knowledge of station. |
441 | */ | 545 | */ |
442 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | 546 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, |
547 | const u8 *addr) | ||
443 | { | 548 | { |
444 | int sta_id = IWL_INVALID_STATION; | 549 | struct iwl_station_entry *station; |
445 | int i, ret = -EINVAL; | ||
446 | unsigned long flags; | 550 | unsigned long flags; |
447 | 551 | ||
448 | spin_lock_irqsave(&priv->sta_lock, flags); | 552 | if (!iwl_is_ready(priv)) { |
553 | IWL_DEBUG_INFO(priv, | ||
554 | "Unable to remove station %pM, device not ready.\n", | ||
555 | addr); | ||
556 | /* | ||
557 | * It is typical for stations to be removed when we are | ||
558 | * going down. Return success since device will be down | ||
559 | * soon anyway | ||
560 | */ | ||
561 | return 0; | ||
562 | } | ||
449 | 563 | ||
450 | if (is_ap) | 564 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", |
451 | sta_id = IWL_AP_ID; | 565 | sta_id, addr); |
452 | else if (is_broadcast_ether_addr(addr)) | ||
453 | sta_id = priv->hw_params.bcast_sta_id; | ||
454 | else | ||
455 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) | ||
456 | if (priv->stations[i].used && | ||
457 | !compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
458 | addr)) { | ||
459 | sta_id = i; | ||
460 | break; | ||
461 | } | ||
462 | 566 | ||
463 | if (unlikely(sta_id == IWL_INVALID_STATION)) | 567 | if (WARN_ON(sta_id == IWL_INVALID_STATION)) |
464 | goto out; | 568 | return -EINVAL; |
465 | 569 | ||
466 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", | 570 | spin_lock_irqsave(&priv->sta_lock, flags); |
467 | sta_id, addr); | ||
468 | 571 | ||
469 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { | 572 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { |
470 | IWL_ERR(priv, "Removing %pM but non DRIVER active\n", | 573 | IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", |
471 | addr); | 574 | addr); |
472 | goto out; | 575 | goto out_err; |
473 | } | 576 | } |
474 | 577 | ||
475 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | 578 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { |
476 | IWL_ERR(priv, "Removing %pM but non UCODE active\n", | 579 | IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", |
477 | addr); | 580 | addr); |
478 | goto out; | 581 | goto out_err; |
479 | } | 582 | } |
480 | 583 | ||
584 | if (priv->stations[sta_id].used & IWL_STA_LOCAL) { | ||
585 | kfree(priv->stations[sta_id].lq); | ||
586 | priv->stations[sta_id].lq = NULL; | ||
587 | } | ||
481 | 588 | ||
482 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | 589 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; |
483 | 590 | ||
@@ -485,47 +592,112 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
485 | 592 | ||
486 | BUG_ON(priv->num_stations < 0); | 593 | BUG_ON(priv->num_stations < 0); |
487 | 594 | ||
595 | station = &priv->stations[sta_id]; | ||
488 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 596 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
489 | 597 | ||
490 | ret = iwl_send_remove_station(priv, addr, CMD_ASYNC); | 598 | return iwl_send_remove_station(priv, station); |
491 | return ret; | 599 | out_err: |
492 | out: | ||
493 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 600 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
494 | return ret; | 601 | return -EINVAL; |
495 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(iwl_remove_station); | ||
496 | 604 | ||
497 | /** | 605 | /** |
498 | * iwl_clear_stations_table - Clear the driver's station table | 606 | * iwl_clear_ucode_stations - clear ucode station table bits |
499 | * | 607 | * |
500 | * NOTE: This does not clear or otherwise alter the device's station table. | 608 | * This function clears all the bits in the driver indicating |
609 | * which stations are active in the ucode. Call when something | ||
610 | * other than explicit station management would cause this in | ||
611 | * the ucode, e.g. unassociated RXON. | ||
501 | */ | 612 | */ |
502 | void iwl_clear_stations_table(struct iwl_priv *priv) | 613 | void iwl_clear_ucode_stations(struct iwl_priv *priv) |
503 | { | 614 | { |
504 | unsigned long flags; | ||
505 | int i; | 615 | int i; |
616 | unsigned long flags_spin; | ||
617 | bool cleared = false; | ||
506 | 618 | ||
507 | spin_lock_irqsave(&priv->sta_lock, flags); | 619 | IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); |
508 | 620 | ||
509 | if (iwl_is_alive(priv) && | 621 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
510 | !test_bit(STATUS_EXIT_PENDING, &priv->status) && | 622 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
511 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) | 623 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { |
512 | IWL_ERR(priv, "Couldn't clear the station table\n"); | 624 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); |
625 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
626 | cleared = true; | ||
627 | } | ||
628 | } | ||
629 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
630 | |||
631 | if (!cleared) | ||
632 | IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n"); | ||
633 | } | ||
634 | EXPORT_SYMBOL(iwl_clear_ucode_stations); | ||
635 | |||
636 | /** | ||
637 | * iwl_restore_stations() - Restore driver known stations to device | ||
638 | * | ||
639 | * All stations considered active by driver, but not present in ucode, is | ||
640 | * restored. | ||
641 | * | ||
642 | * Function sleeps. | ||
643 | */ | ||
644 | void iwl_restore_stations(struct iwl_priv *priv) | ||
645 | { | ||
646 | struct iwl_station_entry *station; | ||
647 | unsigned long flags_spin; | ||
648 | int i; | ||
649 | bool found = false; | ||
650 | int ret; | ||
513 | 651 | ||
514 | priv->num_stations = 0; | 652 | if (!iwl_is_ready(priv)) { |
515 | memset(priv->stations, 0, sizeof(priv->stations)); | 653 | IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); |
654 | return; | ||
655 | } | ||
516 | 656 | ||
517 | /* clean ucode key table bit map */ | 657 | IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); |
518 | priv->ucode_key_table = 0; | 658 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
659 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
660 | if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) && | ||
661 | !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) { | ||
662 | IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n", | ||
663 | priv->stations[i].sta.sta.addr); | ||
664 | priv->stations[i].sta.mode = 0; | ||
665 | priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS; | ||
666 | found = true; | ||
667 | } | ||
668 | } | ||
519 | 669 | ||
520 | /* keep track of static keys */ | 670 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
521 | for (i = 0; i < WEP_KEYS_MAX ; i++) { | 671 | if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { |
522 | if (priv->wep_keys[i].key_size) | 672 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
523 | set_bit(i, &priv->ucode_key_table); | 673 | station = &priv->stations[i]; |
674 | ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC); | ||
675 | if (ret) { | ||
676 | IWL_ERR(priv, "Adding station %pM failed.\n", | ||
677 | station->sta.sta.addr); | ||
678 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
679 | priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; | ||
680 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
681 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
682 | } | ||
683 | /* | ||
684 | * Rate scaling has already been initialized, send | ||
685 | * current LQ command | ||
686 | */ | ||
687 | if (station->lq) | ||
688 | iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); | ||
689 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
690 | priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
691 | } | ||
524 | } | 692 | } |
525 | 693 | ||
526 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 694 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
695 | if (!found) | ||
696 | IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n"); | ||
697 | else | ||
698 | IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n"); | ||
527 | } | 699 | } |
528 | EXPORT_SYMBOL(iwl_clear_stations_table); | 700 | EXPORT_SYMBOL(iwl_restore_stations); |
529 | 701 | ||
530 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | 702 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) |
531 | { | 703 | { |
@@ -539,7 +711,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | |||
539 | } | 711 | } |
540 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); | 712 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); |
541 | 713 | ||
542 | int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | 714 | static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) |
543 | { | 715 | { |
544 | int i, not_empty = 0; | 716 | int i, not_empty = 0; |
545 | u8 buff[sizeof(struct iwl_wep_cmd) + | 717 | u8 buff[sizeof(struct iwl_wep_cmd) + |
@@ -549,9 +721,11 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
549 | struct iwl_host_cmd cmd = { | 721 | struct iwl_host_cmd cmd = { |
550 | .id = REPLY_WEPKEY, | 722 | .id = REPLY_WEPKEY, |
551 | .data = wep_cmd, | 723 | .data = wep_cmd, |
552 | .flags = CMD_ASYNC, | 724 | .flags = CMD_SYNC, |
553 | }; | 725 | }; |
554 | 726 | ||
727 | might_sleep(); | ||
728 | |||
555 | memset(wep_cmd, 0, cmd_size + | 729 | memset(wep_cmd, 0, cmd_size + |
556 | (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); | 730 | (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); |
557 | 731 | ||
@@ -581,33 +755,34 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
581 | else | 755 | else |
582 | return 0; | 756 | return 0; |
583 | } | 757 | } |
584 | EXPORT_SYMBOL(iwl_send_static_wepkey_cmd); | 758 | |
759 | int iwl_restore_default_wep_keys(struct iwl_priv *priv) | ||
760 | { | ||
761 | WARN_ON(!mutex_is_locked(&priv->mutex)); | ||
762 | |||
763 | return iwl_send_static_wepkey_cmd(priv, 0); | ||
764 | } | ||
765 | EXPORT_SYMBOL(iwl_restore_default_wep_keys); | ||
585 | 766 | ||
586 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | 767 | int iwl_remove_default_wep_key(struct iwl_priv *priv, |
587 | struct ieee80211_key_conf *keyconf) | 768 | struct ieee80211_key_conf *keyconf) |
588 | { | 769 | { |
589 | int ret; | 770 | int ret; |
590 | unsigned long flags; | ||
591 | 771 | ||
592 | spin_lock_irqsave(&priv->sta_lock, flags); | 772 | WARN_ON(!mutex_is_locked(&priv->mutex)); |
773 | |||
593 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", | 774 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", |
594 | keyconf->keyidx); | 775 | keyconf->keyidx); |
595 | 776 | ||
596 | if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) | ||
597 | IWL_ERR(priv, "index %d not used in uCode key table.\n", | ||
598 | keyconf->keyidx); | ||
599 | |||
600 | priv->default_wep_key--; | ||
601 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); | 777 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); |
602 | if (iwl_is_rfkill(priv)) { | 778 | if (iwl_is_rfkill(priv)) { |
603 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); | 779 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); |
604 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 780 | /* but keys in device are clear anyway so return success */ |
605 | return 0; | 781 | return 0; |
606 | } | 782 | } |
607 | ret = iwl_send_static_wepkey_cmd(priv, 1); | 783 | ret = iwl_send_static_wepkey_cmd(priv, 1); |
608 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", | 784 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", |
609 | keyconf->keyidx, ret); | 785 | keyconf->keyidx, ret); |
610 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
611 | 786 | ||
612 | return ret; | 787 | return ret; |
613 | } | 788 | } |
@@ -617,7 +792,8 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
617 | struct ieee80211_key_conf *keyconf) | 792 | struct ieee80211_key_conf *keyconf) |
618 | { | 793 | { |
619 | int ret; | 794 | int ret; |
620 | unsigned long flags; | 795 | |
796 | WARN_ON(!mutex_is_locked(&priv->mutex)); | ||
621 | 797 | ||
622 | if (keyconf->keylen != WEP_KEY_LEN_128 && | 798 | if (keyconf->keylen != WEP_KEY_LEN_128 && |
623 | keyconf->keylen != WEP_KEY_LEN_64) { | 799 | keyconf->keylen != WEP_KEY_LEN_64) { |
@@ -629,13 +805,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
629 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 805 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
630 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; | 806 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; |
631 | 807 | ||
632 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
633 | priv->default_wep_key++; | ||
634 | |||
635 | if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) | ||
636 | IWL_ERR(priv, "index %d already used in uCode key table.\n", | ||
637 | keyconf->keyidx); | ||
638 | |||
639 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 808 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; |
640 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | 809 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, |
641 | keyconf->keylen); | 810 | keyconf->keylen); |
@@ -643,7 +812,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
643 | ret = iwl_send_static_wepkey_cmd(priv, 0); | 812 | ret = iwl_send_static_wepkey_cmd(priv, 0); |
644 | IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", | 813 | IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", |
645 | keyconf->keylen, keyconf->keyidx, ret); | 814 | keyconf->keylen, keyconf->keyidx, ret); |
646 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
647 | 815 | ||
648 | return ret; | 816 | return ret; |
649 | } | 817 | } |
@@ -798,18 +966,23 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
798 | 966 | ||
799 | void iwl_update_tkip_key(struct iwl_priv *priv, | 967 | void iwl_update_tkip_key(struct iwl_priv *priv, |
800 | struct ieee80211_key_conf *keyconf, | 968 | struct ieee80211_key_conf *keyconf, |
801 | const u8 *addr, u32 iv32, u16 *phase1key) | 969 | struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) |
802 | { | 970 | { |
803 | u8 sta_id = IWL_INVALID_STATION; | 971 | u8 sta_id; |
804 | unsigned long flags; | 972 | unsigned long flags; |
805 | int i; | 973 | int i; |
806 | 974 | ||
807 | sta_id = iwl_find_station(priv, addr); | 975 | if (sta) { |
808 | if (sta_id == IWL_INVALID_STATION) { | 976 | sta_id = iwl_sta_id(sta); |
809 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | 977 | |
810 | addr); | 978 | if (sta_id == IWL_INVALID_STATION) { |
811 | return; | 979 | IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", |
812 | } | 980 | sta->addr); |
981 | return; | ||
982 | } | ||
983 | } else | ||
984 | sta_id = priv->hw_params.bcast_sta_id; | ||
985 | |||
813 | 986 | ||
814 | if (iwl_scan_cancel(priv)) { | 987 | if (iwl_scan_cancel(priv)) { |
815 | /* cancel scan failed, just live w/ bad key and rely | 988 | /* cancel scan failed, just live w/ bad key and rely |
@@ -885,7 +1058,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
885 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1058 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
886 | 1059 | ||
887 | if (iwl_is_rfkill(priv)) { | 1060 | if (iwl_is_rfkill(priv)) { |
888 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); | 1061 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); |
889 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1062 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
890 | return 0; | 1063 | return 0; |
891 | } | 1064 | } |
@@ -948,253 +1121,149 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, | |||
948 | } | 1121 | } |
949 | #endif | 1122 | #endif |
950 | 1123 | ||
951 | int iwl_send_lq_cmd(struct iwl_priv *priv, | ||
952 | struct iwl_link_quality_cmd *lq, u8 flags) | ||
953 | { | ||
954 | struct iwl_host_cmd cmd = { | ||
955 | .id = REPLY_TX_LINK_QUALITY_CMD, | ||
956 | .len = sizeof(struct iwl_link_quality_cmd), | ||
957 | .flags = flags, | ||
958 | .data = lq, | ||
959 | }; | ||
960 | |||
961 | if ((lq->sta_id == 0xFF) && | ||
962 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) | ||
963 | return -EINVAL; | ||
964 | |||
965 | if (lq->sta_id == 0xFF) | ||
966 | lq->sta_id = IWL_AP_ID; | ||
967 | |||
968 | iwl_dump_lq_cmd(priv, lq); | ||
969 | |||
970 | if (iwl_is_associated(priv) && priv->assoc_station_added) | ||
971 | return iwl_send_cmd(priv, &cmd); | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | EXPORT_SYMBOL(iwl_send_lq_cmd); | ||
976 | |||
977 | /** | 1124 | /** |
978 | * iwl_sta_init_lq - Initialize a station's hardware rate table | 1125 | * is_lq_table_valid() - Test one aspect of LQ cmd for validity |
979 | * | ||
980 | * The uCode's station table contains a table of fallback rates | ||
981 | * for automatic fallback during transmission. | ||
982 | * | ||
983 | * NOTE: This sets up a default set of values. These will be replaced later | ||
984 | * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of | ||
985 | * rc80211_simple. | ||
986 | * | 1126 | * |
987 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | 1127 | * It sometimes happens when a HT rate has been in use and we |
988 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | 1128 | * loose connectivity with AP then mac80211 will first tell us that the |
989 | * which requires station table entry to exist). | 1129 | * current channel is not HT anymore before removing the station. In such a |
1130 | * scenario the RXON flags will be updated to indicate we are not | ||
1131 | * communicating HT anymore, but the LQ command may still contain HT rates. | ||
1132 | * Test for this to prevent driver from sending LQ command between the time | ||
1133 | * RXON flags are updated and when LQ command is updated. | ||
990 | */ | 1134 | */ |
991 | static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) | 1135 | static bool is_lq_table_valid(struct iwl_priv *priv, |
1136 | struct iwl_link_quality_cmd *lq) | ||
992 | { | 1137 | { |
993 | int i, r; | 1138 | int i; |
994 | struct iwl_link_quality_cmd link_cmd = { | 1139 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
995 | .reserved1 = 0, | ||
996 | }; | ||
997 | u32 rate_flags; | ||
998 | 1140 | ||
999 | /* Set up the rate scaling to start at selected rate, fall back | 1141 | if (ht_conf->is_ht) |
1000 | * all the way down to 1M in IEEE order, and then spin on 1M */ | 1142 | return true; |
1001 | if (is_ap) | ||
1002 | r = IWL_RATE_54M_INDEX; | ||
1003 | else if (priv->band == IEEE80211_BAND_5GHZ) | ||
1004 | r = IWL_RATE_6M_INDEX; | ||
1005 | else | ||
1006 | r = IWL_RATE_1M_INDEX; | ||
1007 | 1143 | ||
1144 | IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", | ||
1145 | priv->active_rxon.channel); | ||
1008 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | 1146 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { |
1009 | rate_flags = 0; | 1147 | if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { |
1010 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | 1148 | IWL_DEBUG_INFO(priv, |
1011 | rate_flags |= RATE_MCS_CCK_MSK; | 1149 | "index %d of LQ expects HT channel\n", |
1012 | 1150 | i); | |
1013 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 1151 | return false; |
1014 | RATE_MCS_ANT_POS; | 1152 | } |
1015 | |||
1016 | link_cmd.rs_table[i].rate_n_flags = | ||
1017 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
1018 | r = iwl_get_prev_ieee_rate(r); | ||
1019 | } | 1153 | } |
1020 | 1154 | return true; | |
1021 | link_cmd.general_params.single_stream_ant_msk = | ||
1022 | first_antenna(priv->hw_params.valid_tx_ant); | ||
1023 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
1024 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
1025 | link_cmd.agg_params.agg_time_limit = | ||
1026 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
1027 | |||
1028 | /* Update the rate scaling for control frame Tx to AP */ | ||
1029 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; | ||
1030 | |||
1031 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
1032 | sizeof(link_cmd), &link_cmd, NULL); | ||
1033 | } | 1155 | } |
1034 | 1156 | ||
1035 | /** | 1157 | /** |
1036 | * iwl_rxon_add_station - add station into station table. | 1158 | * iwl_send_lq_cmd() - Send link quality command |
1159 | * @init: This command is sent as part of station initialization right | ||
1160 | * after station has been added. | ||
1037 | * | 1161 | * |
1038 | * there is only one AP station with id= IWL_AP_ID | 1162 | * The link quality command is sent as the last step of station creation. |
1039 | * NOTE: mutex must be held before calling this function | 1163 | * This is the special case in which init is set and we call a callback in |
1164 | * this case to clear the state indicating that station creation is in | ||
1165 | * progress. | ||
1040 | */ | 1166 | */ |
1041 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | 1167 | int iwl_send_lq_cmd(struct iwl_priv *priv, |
1168 | struct iwl_link_quality_cmd *lq, u8 flags, bool init) | ||
1042 | { | 1169 | { |
1043 | struct ieee80211_sta *sta; | 1170 | int ret = 0; |
1044 | struct ieee80211_sta_ht_cap ht_config; | 1171 | unsigned long flags_spin; |
1045 | struct ieee80211_sta_ht_cap *cur_ht_config = NULL; | ||
1046 | u8 sta_id; | ||
1047 | 1172 | ||
1048 | /* | 1173 | struct iwl_host_cmd cmd = { |
1049 | * Set HT capabilities. It is ok to set this struct even if not using | 1174 | .id = REPLY_TX_LINK_QUALITY_CMD, |
1050 | * HT config: the priv->current_ht_config.is_ht flag will just be false | 1175 | .len = sizeof(struct iwl_link_quality_cmd), |
1051 | */ | 1176 | .flags = flags, |
1052 | rcu_read_lock(); | 1177 | .data = lq, |
1053 | sta = ieee80211_find_sta(priv->vif, addr); | 1178 | }; |
1054 | if (sta) { | ||
1055 | memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); | ||
1056 | cur_ht_config = &ht_config; | ||
1057 | } | ||
1058 | rcu_read_unlock(); | ||
1059 | 1179 | ||
1060 | /* Add station to device's station table */ | 1180 | if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) |
1061 | sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); | 1181 | return -EINVAL; |
1062 | 1182 | ||
1063 | /* Set up default rate scaling table in device's station table */ | 1183 | iwl_dump_lq_cmd(priv, lq); |
1064 | iwl_sta_init_lq(priv, addr, is_ap); | 1184 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); |
1065 | 1185 | ||
1066 | return sta_id; | 1186 | if (is_lq_table_valid(priv, lq)) |
1187 | ret = iwl_send_cmd(priv, &cmd); | ||
1188 | else | ||
1189 | ret = -EINVAL; | ||
1190 | |||
1191 | if (cmd.flags & CMD_ASYNC) | ||
1192 | return ret; | ||
1193 | |||
1194 | if (init) { | ||
1195 | IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", | ||
1196 | lq->sta_id); | ||
1197 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | ||
1198 | priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
1199 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | ||
1200 | } | ||
1201 | return ret; | ||
1067 | } | 1202 | } |
1068 | EXPORT_SYMBOL(iwl_rxon_add_station); | 1203 | EXPORT_SYMBOL(iwl_send_lq_cmd); |
1069 | 1204 | ||
1070 | /** | 1205 | /** |
1071 | * iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table | 1206 | * iwl_alloc_bcast_station - add broadcast station into driver's station table. |
1072 | * | 1207 | * |
1073 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | 1208 | * This adds the broadcast station into the driver's station table |
1074 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | 1209 | * and marks it driver active, so that it will be restored to the |
1075 | * which requires station table entry to exist). | 1210 | * device at the next best time. |
1076 | */ | 1211 | */ |
1077 | static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) | 1212 | int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) |
1078 | { | 1213 | { |
1079 | int i, r; | 1214 | struct iwl_link_quality_cmd *link_cmd; |
1080 | struct iwl_link_quality_cmd link_cmd = { | 1215 | unsigned long flags; |
1081 | .reserved1 = 0, | 1216 | u8 sta_id; |
1082 | }; | ||
1083 | u32 rate_flags; | ||
1084 | |||
1085 | /* Set up the rate scaling to start at selected rate, fall back | ||
1086 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
1087 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
1088 | r = IWL_RATE_6M_INDEX; | ||
1089 | else | ||
1090 | r = IWL_RATE_1M_INDEX; | ||
1091 | |||
1092 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
1093 | rate_flags = 0; | ||
1094 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
1095 | rate_flags |= RATE_MCS_CCK_MSK; | ||
1096 | 1217 | ||
1097 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 1218 | spin_lock_irqsave(&priv->sta_lock, flags); |
1098 | RATE_MCS_ANT_POS; | 1219 | sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL); |
1220 | if (sta_id == IWL_INVALID_STATION) { | ||
1221 | IWL_ERR(priv, "Unable to prepare broadcast station\n"); | ||
1222 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1099 | 1223 | ||
1100 | link_cmd.rs_table[i].rate_n_flags = | 1224 | return -EINVAL; |
1101 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
1102 | r = iwl_get_prev_ieee_rate(r); | ||
1103 | } | 1225 | } |
1104 | 1226 | ||
1105 | link_cmd.general_params.single_stream_ant_msk = | 1227 | priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; |
1106 | first_antenna(priv->hw_params.valid_tx_ant); | 1228 | priv->stations[sta_id].used |= IWL_STA_BCAST; |
1107 | link_cmd.general_params.dual_stream_ant_msk = 3; | 1229 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1108 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
1109 | link_cmd.agg_params.agg_time_limit = | ||
1110 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
1111 | |||
1112 | /* Update the rate scaling for control frame Tx to AP */ | ||
1113 | link_cmd.sta_id = priv->hw_params.bcast_sta_id; | ||
1114 | |||
1115 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
1116 | sizeof(link_cmd), &link_cmd, NULL); | ||
1117 | } | ||
1118 | |||
1119 | 1230 | ||
1120 | /** | 1231 | if (init_lq) { |
1121 | * iwl_add_bcast_station - add broadcast station into station table. | 1232 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); |
1122 | */ | 1233 | if (!link_cmd) { |
1123 | void iwl_add_bcast_station(struct iwl_priv *priv) | 1234 | IWL_ERR(priv, |
1124 | { | 1235 | "Unable to initialize rate scaling for bcast station.\n"); |
1125 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | 1236 | return -ENOMEM; |
1126 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | 1237 | } |
1127 | 1238 | ||
1128 | /* Set up default rate scaling table in device's station table */ | 1239 | spin_lock_irqsave(&priv->sta_lock, flags); |
1129 | iwl_sta_init_bcast_lq(priv); | 1240 | priv->stations[sta_id].lq = link_cmd; |
1130 | } | 1241 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1131 | EXPORT_SYMBOL(iwl_add_bcast_station); | 1242 | } |
1132 | 1243 | ||
1133 | /** | 1244 | return 0; |
1134 | * iwl3945_add_bcast_station - add broadcast station into station table. | ||
1135 | */ | ||
1136 | void iwl3945_add_bcast_station(struct iwl_priv *priv) | ||
1137 | { | ||
1138 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | ||
1139 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | ||
1140 | } | 1245 | } |
1141 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | 1246 | EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); |
1142 | 1247 | ||
1143 | /** | 1248 | void iwl_dealloc_bcast_station(struct iwl_priv *priv) |
1144 | * iwl_get_sta_id - Find station's index within station table | ||
1145 | * | ||
1146 | * If new IBSS station, create new entry in station table | ||
1147 | */ | ||
1148 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | ||
1149 | { | 1249 | { |
1150 | int sta_id; | 1250 | unsigned long flags; |
1151 | __le16 fc = hdr->frame_control; | 1251 | int i; |
1152 | |||
1153 | /* If this frame is broadcast or management, use broadcast station id */ | ||
1154 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) | ||
1155 | return priv->hw_params.bcast_sta_id; | ||
1156 | |||
1157 | switch (priv->iw_mode) { | ||
1158 | |||
1159 | /* If we are a client station in a BSS network, use the special | ||
1160 | * AP station entry (that's the only station we communicate with) */ | ||
1161 | case NL80211_IFTYPE_STATION: | ||
1162 | return IWL_AP_ID; | ||
1163 | |||
1164 | /* If we are an AP, then find the station, or use BCAST */ | ||
1165 | case NL80211_IFTYPE_AP: | ||
1166 | sta_id = iwl_find_station(priv, hdr->addr1); | ||
1167 | if (sta_id != IWL_INVALID_STATION) | ||
1168 | return sta_id; | ||
1169 | return priv->hw_params.bcast_sta_id; | ||
1170 | |||
1171 | /* If this frame is going out to an IBSS network, find the station, | ||
1172 | * or create a new station table entry */ | ||
1173 | case NL80211_IFTYPE_ADHOC: | ||
1174 | sta_id = iwl_find_station(priv, hdr->addr1); | ||
1175 | if (sta_id != IWL_INVALID_STATION) | ||
1176 | return sta_id; | ||
1177 | |||
1178 | /* Create new station table entry */ | ||
1179 | sta_id = iwl_add_station(priv, hdr->addr1, false, | ||
1180 | CMD_ASYNC, NULL); | ||
1181 | |||
1182 | if (sta_id != IWL_INVALID_STATION) | ||
1183 | return sta_id; | ||
1184 | |||
1185 | IWL_DEBUG_DROP(priv, "Station %pM not in station map. " | ||
1186 | "Defaulting to broadcast...\n", | ||
1187 | hdr->addr1); | ||
1188 | iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); | ||
1189 | return priv->hw_params.bcast_sta_id; | ||
1190 | 1252 | ||
1191 | default: | 1253 | spin_lock_irqsave(&priv->sta_lock, flags); |
1192 | IWL_WARN(priv, "Unknown mode of operation: %d\n", | 1254 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
1193 | priv->iw_mode); | 1255 | if (!(priv->stations[i].used & IWL_STA_BCAST)) |
1194 | return priv->hw_params.bcast_sta_id; | 1256 | continue; |
1257 | |||
1258 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
1259 | priv->num_stations--; | ||
1260 | BUG_ON(priv->num_stations < 0); | ||
1261 | kfree(priv->stations[i].lq); | ||
1262 | priv->stations[i].lq = NULL; | ||
1195 | } | 1263 | } |
1264 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1196 | } | 1265 | } |
1197 | EXPORT_SYMBOL(iwl_get_sta_id); | 1266 | EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); |
1198 | 1267 | ||
1199 | /** | 1268 | /** |
1200 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table | 1269 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table |
@@ -1214,13 +1283,13 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) | |||
1214 | } | 1283 | } |
1215 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); | 1284 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); |
1216 | 1285 | ||
1217 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | 1286 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, |
1218 | const u8 *addr, int tid, u16 ssn) | 1287 | int tid, u16 ssn) |
1219 | { | 1288 | { |
1220 | unsigned long flags; | 1289 | unsigned long flags; |
1221 | int sta_id; | 1290 | int sta_id; |
1222 | 1291 | ||
1223 | sta_id = iwl_find_station(priv, addr); | 1292 | sta_id = iwl_sta_id(sta); |
1224 | if (sta_id == IWL_INVALID_STATION) | 1293 | if (sta_id == IWL_INVALID_STATION) |
1225 | return -ENXIO; | 1294 | return -ENXIO; |
1226 | 1295 | ||
@@ -1233,16 +1302,17 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, | |||
1233 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1302 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1234 | 1303 | ||
1235 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | 1304 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, |
1236 | CMD_ASYNC); | 1305 | CMD_ASYNC); |
1237 | } | 1306 | } |
1238 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); | 1307 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); |
1239 | 1308 | ||
1240 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | 1309 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, |
1310 | int tid) | ||
1241 | { | 1311 | { |
1242 | unsigned long flags; | 1312 | unsigned long flags; |
1243 | int sta_id; | 1313 | int sta_id; |
1244 | 1314 | ||
1245 | sta_id = iwl_find_station(priv, addr); | 1315 | sta_id = iwl_sta_id(sta); |
1246 | if (sta_id == IWL_INVALID_STATION) { | 1316 | if (sta_id == IWL_INVALID_STATION) { |
1247 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | 1317 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); |
1248 | return -ENXIO; | 1318 | return -ENXIO; |
@@ -1291,3 +1361,22 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1291 | 1361 | ||
1292 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1362 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1293 | } | 1363 | } |
1364 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | ||
1365 | |||
1366 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, | ||
1367 | struct ieee80211_vif *vif, | ||
1368 | struct ieee80211_sta *sta) | ||
1369 | { | ||
1370 | struct iwl_priv *priv = hw->priv; | ||
1371 | struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; | ||
1372 | int ret; | ||
1373 | |||
1374 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", | ||
1375 | sta->addr); | ||
1376 | ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); | ||
1377 | if (ret) | ||
1378 | IWL_ERR(priv, "Error removing station %pM\n", | ||
1379 | sta->addr); | ||
1380 | return ret; | ||
1381 | } | ||
1382 | EXPORT_SYMBOL(iwl_mac_sta_remove); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 2dc35fe28f56..c2a453a1a991 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -29,44 +29,82 @@ | |||
29 | #ifndef __iwl_sta_h__ | 29 | #ifndef __iwl_sta_h__ |
30 | #define __iwl_sta_h__ | 30 | #define __iwl_sta_h__ |
31 | 31 | ||
32 | #include "iwl-dev.h" | ||
33 | |||
32 | #define HW_KEY_DYNAMIC 0 | 34 | #define HW_KEY_DYNAMIC 0 |
33 | #define HW_KEY_DEFAULT 1 | 35 | #define HW_KEY_DEFAULT 1 |
34 | 36 | ||
35 | /** | 37 | #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ |
36 | * iwl_find_station - Find station id for a given BSSID | 38 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ |
37 | * @bssid: MAC address of station ID to find | 39 | #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of |
38 | */ | 40 | being activated */ |
39 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); | 41 | #define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211; |
42 | (this is for the IBSS BSSID stations) */ | ||
43 | #define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */ | ||
44 | |||
40 | 45 | ||
41 | int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); | ||
42 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | 46 | int iwl_remove_default_wep_key(struct iwl_priv *priv, |
43 | struct ieee80211_key_conf *key); | 47 | struct ieee80211_key_conf *key); |
44 | int iwl_set_default_wep_key(struct iwl_priv *priv, | 48 | int iwl_set_default_wep_key(struct iwl_priv *priv, |
45 | struct ieee80211_key_conf *key); | 49 | struct ieee80211_key_conf *key); |
50 | int iwl_restore_default_wep_keys(struct iwl_priv *priv); | ||
46 | int iwl_set_dynamic_key(struct iwl_priv *priv, | 51 | int iwl_set_dynamic_key(struct iwl_priv *priv, |
47 | struct ieee80211_key_conf *key, u8 sta_id); | 52 | struct ieee80211_key_conf *key, u8 sta_id); |
48 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | 53 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
49 | struct ieee80211_key_conf *key, u8 sta_id); | 54 | struct ieee80211_key_conf *key, u8 sta_id); |
50 | void iwl_update_tkip_key(struct iwl_priv *priv, | 55 | void iwl_update_tkip_key(struct iwl_priv *priv, |
51 | struct ieee80211_key_conf *keyconf, | 56 | struct ieee80211_key_conf *keyconf, |
52 | const u8 *addr, u32 iv32, u16 *phase1key); | 57 | struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); |
53 | 58 | ||
54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 59 | void iwl_restore_stations(struct iwl_priv *priv); |
55 | void iwl_add_bcast_station(struct iwl_priv *priv); | 60 | void iwl_clear_ucode_stations(struct iwl_priv *priv); |
56 | void iwl3945_add_bcast_station(struct iwl_priv *priv); | 61 | int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); |
57 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 62 | void iwl_dealloc_bcast_station(struct iwl_priv *priv); |
58 | void iwl_clear_stations_table(struct iwl_priv *priv); | ||
59 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | 63 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); |
60 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | ||
61 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | ||
62 | int iwl_send_add_sta(struct iwl_priv *priv, | 64 | int iwl_send_add_sta(struct iwl_priv *priv, |
63 | struct iwl_addsta_cmd *sta, u8 flags); | 65 | struct iwl_addsta_cmd *sta, u8 flags); |
64 | u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | 66 | int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, |
65 | struct ieee80211_sta_ht_cap *ht_info); | 67 | u8 *sta_id_r); |
68 | int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | ||
69 | bool is_ap, | ||
70 | struct ieee80211_sta_ht_cap *ht_info, | ||
71 | u8 *sta_id_r); | ||
72 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | ||
73 | const u8 *addr); | ||
74 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
75 | struct ieee80211_sta *sta); | ||
66 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); | 76 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); |
67 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | 77 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, |
68 | const u8 *addr, int tid, u16 ssn); | 78 | int tid, u16 ssn); |
69 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); | 79 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, |
80 | int tid); | ||
70 | void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); | 81 | void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); |
71 | void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); | 82 | void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); |
83 | |||
84 | /** | ||
85 | * iwl_clear_driver_stations - clear knowledge of all stations from driver | ||
86 | * @priv: iwl priv struct | ||
87 | * | ||
88 | * This is called during iwl_down() to make sure that in the case | ||
89 | * we're coming there from a hardware restart mac80211 will be | ||
90 | * able to reconfigure stations -- if we're getting there in the | ||
91 | * normal down flow then the stations will already be cleared. | ||
92 | */ | ||
93 | static inline void iwl_clear_driver_stations(struct iwl_priv *priv) | ||
94 | { | ||
95 | unsigned long flags; | ||
96 | |||
97 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
98 | memset(priv->stations, 0, sizeof(priv->stations)); | ||
99 | priv->num_stations = 0; | ||
100 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
101 | } | ||
102 | |||
103 | static inline int iwl_sta_id(struct ieee80211_sta *sta) | ||
104 | { | ||
105 | if (WARN_ON(!sta)) | ||
106 | return IWL_INVALID_STATION; | ||
107 | |||
108 | return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; | ||
109 | } | ||
72 | #endif /* __iwl_sta_h__ */ | 110 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 8dd0c036d547..1ece2ea09773 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -38,47 +38,6 @@ | |||
38 | #include "iwl-io.h" | 38 | #include "iwl-io.h" |
39 | #include "iwl-helpers.h" | 39 | #include "iwl-helpers.h" |
40 | 40 | ||
41 | static const u16 default_tid_to_tx_fifo[] = { | ||
42 | IWL_TX_FIFO_AC1, | ||
43 | IWL_TX_FIFO_AC0, | ||
44 | IWL_TX_FIFO_AC0, | ||
45 | IWL_TX_FIFO_AC1, | ||
46 | IWL_TX_FIFO_AC2, | ||
47 | IWL_TX_FIFO_AC2, | ||
48 | IWL_TX_FIFO_AC3, | ||
49 | IWL_TX_FIFO_AC3, | ||
50 | IWL_TX_FIFO_NONE, | ||
51 | IWL_TX_FIFO_NONE, | ||
52 | IWL_TX_FIFO_NONE, | ||
53 | IWL_TX_FIFO_NONE, | ||
54 | IWL_TX_FIFO_NONE, | ||
55 | IWL_TX_FIFO_NONE, | ||
56 | IWL_TX_FIFO_NONE, | ||
57 | IWL_TX_FIFO_NONE, | ||
58 | IWL_TX_FIFO_AC3 | ||
59 | }; | ||
60 | |||
61 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | ||
62 | struct iwl_dma_ptr *ptr, size_t size) | ||
63 | { | ||
64 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, | ||
65 | GFP_KERNEL); | ||
66 | if (!ptr->addr) | ||
67 | return -ENOMEM; | ||
68 | ptr->size = size; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | ||
73 | struct iwl_dma_ptr *ptr) | ||
74 | { | ||
75 | if (unlikely(!ptr->addr)) | ||
76 | return; | ||
77 | |||
78 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); | ||
79 | memset(ptr, 0, sizeof(*ptr)); | ||
80 | } | ||
81 | |||
82 | /** | 41 | /** |
83 | * iwl_txq_update_write_ptr - Send new write index to hardware | 42 | * iwl_txq_update_write_ptr - Send new write index to hardware |
84 | */ | 43 | */ |
@@ -310,6 +269,8 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | |||
310 | q->high_mark = 2; | 269 | q->high_mark = 2; |
311 | 270 | ||
312 | q->write_ptr = q->read_ptr = 0; | 271 | q->write_ptr = q->read_ptr = 0; |
272 | q->last_read_ptr = 0; | ||
273 | q->repeat_same_read_ptr = 0; | ||
313 | 274 | ||
314 | return 0; | 275 | return 0; |
315 | } | 276 | } |
@@ -454,611 +415,6 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
454 | } | 415 | } |
455 | EXPORT_SYMBOL(iwl_tx_queue_reset); | 416 | EXPORT_SYMBOL(iwl_tx_queue_reset); |
456 | 417 | ||
457 | /** | ||
458 | * iwl_hw_txq_ctx_free - Free TXQ Context | ||
459 | * | ||
460 | * Destroy all TX DMA queues and structures | ||
461 | */ | ||
462 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | ||
463 | { | ||
464 | int txq_id; | ||
465 | |||
466 | /* Tx queues */ | ||
467 | if (priv->txq) { | ||
468 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
469 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
470 | iwl_cmd_queue_free(priv); | ||
471 | else | ||
472 | iwl_tx_queue_free(priv, txq_id); | ||
473 | } | ||
474 | iwl_free_dma_ptr(priv, &priv->kw); | ||
475 | |||
476 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
477 | |||
478 | /* free tx queue structure */ | ||
479 | iwl_free_txq_mem(priv); | ||
480 | } | ||
481 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | ||
482 | |||
483 | /** | ||
484 | * iwl_txq_ctx_alloc - allocate TX queue context | ||
485 | * Allocate all Tx DMA structures and initialize them | ||
486 | * | ||
487 | * @param priv | ||
488 | * @return error code | ||
489 | */ | ||
490 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) | ||
491 | { | ||
492 | int ret; | ||
493 | int txq_id, slots_num; | ||
494 | unsigned long flags; | ||
495 | |||
496 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
497 | iwl_hw_txq_ctx_free(priv); | ||
498 | |||
499 | ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
500 | priv->hw_params.scd_bc_tbls_size); | ||
501 | if (ret) { | ||
502 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
503 | goto error_bc_tbls; | ||
504 | } | ||
505 | /* Alloc keep-warm buffer */ | ||
506 | ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
507 | if (ret) { | ||
508 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
509 | goto error_kw; | ||
510 | } | ||
511 | |||
512 | /* allocate tx queue structure */ | ||
513 | ret = iwl_alloc_txq_mem(priv); | ||
514 | if (ret) | ||
515 | goto error; | ||
516 | |||
517 | spin_lock_irqsave(&priv->lock, flags); | ||
518 | |||
519 | /* Turn off all Tx DMA fifos */ | ||
520 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
521 | |||
522 | /* Tell NIC where to find the "keep warm" buffer */ | ||
523 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
524 | |||
525 | spin_unlock_irqrestore(&priv->lock, flags); | ||
526 | |||
527 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
528 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
529 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
530 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
531 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
532 | txq_id); | ||
533 | if (ret) { | ||
534 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
535 | goto error; | ||
536 | } | ||
537 | } | ||
538 | |||
539 | return ret; | ||
540 | |||
541 | error: | ||
542 | iwl_hw_txq_ctx_free(priv); | ||
543 | iwl_free_dma_ptr(priv, &priv->kw); | ||
544 | error_kw: | ||
545 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
546 | error_bc_tbls: | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | void iwl_txq_ctx_reset(struct iwl_priv *priv) | ||
551 | { | ||
552 | int txq_id, slots_num; | ||
553 | unsigned long flags; | ||
554 | |||
555 | spin_lock_irqsave(&priv->lock, flags); | ||
556 | |||
557 | /* Turn off all Tx DMA fifos */ | ||
558 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
559 | |||
560 | /* Tell NIC where to find the "keep warm" buffer */ | ||
561 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
562 | |||
563 | spin_unlock_irqrestore(&priv->lock, flags); | ||
564 | |||
565 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
566 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
567 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
568 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
569 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | /** | ||
574 | * iwl_txq_ctx_stop - Stop all Tx DMA channels | ||
575 | */ | ||
576 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | ||
577 | { | ||
578 | int ch; | ||
579 | unsigned long flags; | ||
580 | |||
581 | /* Turn off all Tx DMA fifos */ | ||
582 | spin_lock_irqsave(&priv->lock, flags); | ||
583 | |||
584 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
585 | |||
586 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
587 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
588 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
589 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
590 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
591 | 1000); | ||
592 | } | ||
593 | spin_unlock_irqrestore(&priv->lock, flags); | ||
594 | } | ||
595 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | ||
596 | |||
597 | /* | ||
598 | * handle build REPLY_TX command notification. | ||
599 | */ | ||
600 | static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, | ||
601 | struct iwl_tx_cmd *tx_cmd, | ||
602 | struct ieee80211_tx_info *info, | ||
603 | struct ieee80211_hdr *hdr, | ||
604 | u8 std_id) | ||
605 | { | ||
606 | __le16 fc = hdr->frame_control; | ||
607 | __le32 tx_flags = tx_cmd->tx_flags; | ||
608 | |||
609 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
610 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
611 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
612 | if (ieee80211_is_mgmt(fc)) | ||
613 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
614 | if (ieee80211_is_probe_resp(fc) && | ||
615 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
616 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
617 | } else { | ||
618 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
619 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
620 | } | ||
621 | |||
622 | if (ieee80211_is_back_req(fc)) | ||
623 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
624 | |||
625 | |||
626 | tx_cmd->sta_id = std_id; | ||
627 | if (ieee80211_has_morefrags(fc)) | ||
628 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
629 | |||
630 | if (ieee80211_is_data_qos(fc)) { | ||
631 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
632 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
633 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
634 | } else { | ||
635 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
636 | } | ||
637 | |||
638 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | ||
639 | |||
640 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
641 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
642 | |||
643 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
644 | if (ieee80211_is_mgmt(fc)) { | ||
645 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
646 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
647 | else | ||
648 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
649 | } else { | ||
650 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
651 | } | ||
652 | |||
653 | tx_cmd->driver_txop = 0; | ||
654 | tx_cmd->tx_flags = tx_flags; | ||
655 | tx_cmd->next_frame_len = 0; | ||
656 | } | ||
657 | |||
658 | #define RTS_HCCA_RETRY_LIMIT 3 | ||
659 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
660 | |||
661 | static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, | ||
662 | struct iwl_tx_cmd *tx_cmd, | ||
663 | struct ieee80211_tx_info *info, | ||
664 | __le16 fc, int is_hcca) | ||
665 | { | ||
666 | u32 rate_flags; | ||
667 | int rate_idx; | ||
668 | u8 rts_retry_limit; | ||
669 | u8 data_retry_limit; | ||
670 | u8 rate_plcp; | ||
671 | |||
672 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
673 | if (ieee80211_is_probe_resp(fc)) | ||
674 | data_retry_limit = 3; | ||
675 | else | ||
676 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
677 | tx_cmd->data_retry_limit = data_retry_limit; | ||
678 | |||
679 | /* Set retry limit on RTS packets */ | ||
680 | rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT : | ||
681 | RTS_DFAULT_RETRY_LIMIT; | ||
682 | if (data_retry_limit < rts_retry_limit) | ||
683 | rts_retry_limit = data_retry_limit; | ||
684 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
685 | |||
686 | /* DATA packets will use the uCode station table for rate/antenna | ||
687 | * selection */ | ||
688 | if (ieee80211_is_data(fc)) { | ||
689 | tx_cmd->initial_rate_index = 0; | ||
690 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
691 | return; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
696 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
697 | * this band. Also use the lowest supported rate if the stored rate | ||
698 | * index is invalid. | ||
699 | */ | ||
700 | rate_idx = info->control.rates[0].idx; | ||
701 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
702 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
703 | rate_idx = rate_lowest_index(&priv->bands[info->band], | ||
704 | info->control.sta); | ||
705 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
706 | if (info->band == IEEE80211_BAND_5GHZ) | ||
707 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
708 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
709 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
710 | /* Zero out flags for this packet */ | ||
711 | rate_flags = 0; | ||
712 | |||
713 | /* Set CCK flag as needed */ | ||
714 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
715 | rate_flags |= RATE_MCS_CCK_MSK; | ||
716 | |||
717 | /* Set up RTS and CTS flags for certain packets */ | ||
718 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
719 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
720 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
721 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
722 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
723 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
724 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
725 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
726 | } | ||
727 | break; | ||
728 | default: | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | /* Set up antennas */ | ||
733 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | ||
734 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
735 | |||
736 | /* Set the rate in the TX cmd */ | ||
737 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
738 | } | ||
739 | |||
740 | static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
741 | struct ieee80211_tx_info *info, | ||
742 | struct iwl_tx_cmd *tx_cmd, | ||
743 | struct sk_buff *skb_frag, | ||
744 | int sta_id) | ||
745 | { | ||
746 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
747 | |||
748 | switch (keyconf->alg) { | ||
749 | case ALG_CCMP: | ||
750 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
751 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
752 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
753 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
754 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
755 | break; | ||
756 | |||
757 | case ALG_TKIP: | ||
758 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
759 | ieee80211_get_tkip_key(keyconf, skb_frag, | ||
760 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
761 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
762 | break; | ||
763 | |||
764 | case ALG_WEP: | ||
765 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
766 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
767 | |||
768 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
769 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
770 | |||
771 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
772 | |||
773 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
774 | "with key %d\n", keyconf->keyidx); | ||
775 | break; | ||
776 | |||
777 | default: | ||
778 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | ||
779 | break; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | /* | ||
784 | * start REPLY_TX command process | ||
785 | */ | ||
786 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
787 | { | ||
788 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
789 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
790 | struct ieee80211_sta *sta = info->control.sta; | ||
791 | struct iwl_station_priv *sta_priv = NULL; | ||
792 | struct iwl_tx_queue *txq; | ||
793 | struct iwl_queue *q; | ||
794 | struct iwl_device_cmd *out_cmd; | ||
795 | struct iwl_cmd_meta *out_meta; | ||
796 | struct iwl_tx_cmd *tx_cmd; | ||
797 | int swq_id, txq_id; | ||
798 | dma_addr_t phys_addr; | ||
799 | dma_addr_t txcmd_phys; | ||
800 | dma_addr_t scratch_phys; | ||
801 | u16 len, len_org, firstlen, secondlen; | ||
802 | u16 seq_number = 0; | ||
803 | __le16 fc; | ||
804 | u8 hdr_len; | ||
805 | u8 sta_id; | ||
806 | u8 wait_write_ptr = 0; | ||
807 | u8 tid = 0; | ||
808 | u8 *qc = NULL; | ||
809 | unsigned long flags; | ||
810 | |||
811 | spin_lock_irqsave(&priv->lock, flags); | ||
812 | if (iwl_is_rfkill(priv)) { | ||
813 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
814 | goto drop_unlock; | ||
815 | } | ||
816 | |||
817 | fc = hdr->frame_control; | ||
818 | |||
819 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
820 | if (ieee80211_is_auth(fc)) | ||
821 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
822 | else if (ieee80211_is_assoc_req(fc)) | ||
823 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
824 | else if (ieee80211_is_reassoc_req(fc)) | ||
825 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
826 | #endif | ||
827 | |||
828 | /* drop all non-injected data frame if we are not associated */ | ||
829 | if (ieee80211_is_data(fc) && | ||
830 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
831 | (!iwl_is_associated(priv) || | ||
832 | ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || | ||
833 | !priv->assoc_station_added)) { | ||
834 | IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); | ||
835 | goto drop_unlock; | ||
836 | } | ||
837 | |||
838 | hdr_len = ieee80211_hdrlen(fc); | ||
839 | |||
840 | /* Find (or create) index into station table for destination station */ | ||
841 | if (info->flags & IEEE80211_TX_CTL_INJECTED) | ||
842 | sta_id = priv->hw_params.bcast_sta_id; | ||
843 | else | ||
844 | sta_id = iwl_get_sta_id(priv, hdr); | ||
845 | if (sta_id == IWL_INVALID_STATION) { | ||
846 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
847 | hdr->addr1); | ||
848 | goto drop_unlock; | ||
849 | } | ||
850 | |||
851 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
852 | |||
853 | if (sta) | ||
854 | sta_priv = (void *)sta->drv_priv; | ||
855 | |||
856 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
857 | sta_priv->asleep) { | ||
858 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
859 | /* | ||
860 | * This sends an asynchronous command to the device, | ||
861 | * but we can rely on it being processed before the | ||
862 | * next frame is processed -- and the next frame to | ||
863 | * this station is the one that will consume this | ||
864 | * counter. | ||
865 | * For now set the counter to just 1 since we do not | ||
866 | * support uAPSD yet. | ||
867 | */ | ||
868 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
869 | } | ||
870 | |||
871 | txq_id = skb_get_queue_mapping(skb); | ||
872 | if (ieee80211_is_data_qos(fc)) { | ||
873 | qc = ieee80211_get_qos_ctl(hdr); | ||
874 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
875 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
876 | goto drop_unlock; | ||
877 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | ||
878 | seq_number &= IEEE80211_SCTL_SEQ; | ||
879 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
880 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
881 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
882 | seq_number += 0x10; | ||
883 | /* aggregation is on for this <sta,tid> */ | ||
884 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
885 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
886 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
887 | } | ||
888 | } | ||
889 | |||
890 | txq = &priv->txq[txq_id]; | ||
891 | swq_id = txq->swq_id; | ||
892 | q = &txq->q; | ||
893 | |||
894 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | ||
895 | goto drop_unlock; | ||
896 | |||
897 | if (ieee80211_is_data_qos(fc)) | ||
898 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
899 | |||
900 | /* Set up driver data for this TFD */ | ||
901 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
902 | txq->txb[q->write_ptr].skb[0] = skb; | ||
903 | |||
904 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
905 | out_cmd = txq->cmd[q->write_ptr]; | ||
906 | out_meta = &txq->meta[q->write_ptr]; | ||
907 | tx_cmd = &out_cmd->cmd.tx; | ||
908 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
909 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | ||
910 | |||
911 | /* | ||
912 | * Set up the Tx-command (not MAC!) header. | ||
913 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
914 | * after Tx, uCode's Tx response will return this value so driver can | ||
915 | * locate the frame within the tx queue and do post-tx processing. | ||
916 | */ | ||
917 | out_cmd->hdr.cmd = REPLY_TX; | ||
918 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
919 | INDEX_TO_SEQ(q->write_ptr))); | ||
920 | |||
921 | /* Copy MAC header from skb into command buffer */ | ||
922 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
923 | |||
924 | |||
925 | /* Total # bytes to be transmitted */ | ||
926 | len = (u16)skb->len; | ||
927 | tx_cmd->len = cpu_to_le16(len); | ||
928 | |||
929 | if (info->control.hw_key) | ||
930 | iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | ||
931 | |||
932 | /* TODO need this for burst mode later on */ | ||
933 | iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | ||
934 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
935 | |||
936 | /* set is_hcca to 0; it probably will never be implemented */ | ||
937 | iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0); | ||
938 | |||
939 | iwl_update_stats(priv, true, fc, len); | ||
940 | /* | ||
941 | * Use the first empty entry in this queue's command buffer array | ||
942 | * to contain the Tx command and MAC header concatenated together | ||
943 | * (payload data will be in another buffer). | ||
944 | * Size of this varies, due to varying MAC header length. | ||
945 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
946 | * of the MAC header (device reads on dword boundaries). | ||
947 | * We'll tell device about this padding later. | ||
948 | */ | ||
949 | len = sizeof(struct iwl_tx_cmd) + | ||
950 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
951 | |||
952 | len_org = len; | ||
953 | firstlen = len = (len + 3) & ~3; | ||
954 | |||
955 | if (len_org != len) | ||
956 | len_org = 1; | ||
957 | else | ||
958 | len_org = 0; | ||
959 | |||
960 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
961 | if (len_org) | ||
962 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
963 | |||
964 | /* Physical address of this Tx command's header (not MAC header!), | ||
965 | * within command buffer array. */ | ||
966 | txcmd_phys = pci_map_single(priv->pci_dev, | ||
967 | &out_cmd->hdr, len, | ||
968 | PCI_DMA_BIDIRECTIONAL); | ||
969 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
970 | pci_unmap_len_set(out_meta, len, len); | ||
971 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
972 | * first entry */ | ||
973 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
974 | txcmd_phys, len, 1, 0); | ||
975 | |||
976 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
977 | txq->need_update = 1; | ||
978 | if (qc) | ||
979 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
980 | } else { | ||
981 | wait_write_ptr = 1; | ||
982 | txq->need_update = 0; | ||
983 | } | ||
984 | |||
985 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
986 | * if any (802.11 null frames have no payload). */ | ||
987 | secondlen = len = skb->len - hdr_len; | ||
988 | if (len) { | ||
989 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
990 | len, PCI_DMA_TODEVICE); | ||
991 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
992 | phys_addr, len, | ||
993 | 0, 0); | ||
994 | } | ||
995 | |||
996 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
997 | offsetof(struct iwl_tx_cmd, scratch); | ||
998 | |||
999 | len = sizeof(struct iwl_tx_cmd) + | ||
1000 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
1001 | /* take back ownership of DMA buffer to enable update */ | ||
1002 | pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, | ||
1003 | len, PCI_DMA_BIDIRECTIONAL); | ||
1004 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1005 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1006 | |||
1007 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | ||
1008 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
1009 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | ||
1010 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
1011 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
1012 | |||
1013 | /* Set up entry for this TFD in Tx byte-count array */ | ||
1014 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1015 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | ||
1016 | le16_to_cpu(tx_cmd->len)); | ||
1017 | |||
1018 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | ||
1019 | len, PCI_DMA_BIDIRECTIONAL); | ||
1020 | |||
1021 | trace_iwlwifi_dev_tx(priv, | ||
1022 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
1023 | sizeof(struct iwl_tfd), | ||
1024 | &out_cmd->hdr, firstlen, | ||
1025 | skb->data + hdr_len, secondlen); | ||
1026 | |||
1027 | /* Tell device the write index *just past* this latest filled TFD */ | ||
1028 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
1029 | iwl_txq_update_write_ptr(priv, txq); | ||
1030 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1031 | |||
1032 | /* | ||
1033 | * At this point the frame is "transmitted" successfully | ||
1034 | * and we will get a TX status notification eventually, | ||
1035 | * regardless of the value of ret. "ret" only indicates | ||
1036 | * whether or not we should update the write pointer. | ||
1037 | */ | ||
1038 | |||
1039 | /* avoid atomic ops if it isn't an associated client */ | ||
1040 | if (sta_priv && sta_priv->client) | ||
1041 | atomic_inc(&sta_priv->pending_frames); | ||
1042 | |||
1043 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | ||
1044 | if (wait_write_ptr) { | ||
1045 | spin_lock_irqsave(&priv->lock, flags); | ||
1046 | txq->need_update = 1; | ||
1047 | iwl_txq_update_write_ptr(priv, txq); | ||
1048 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1049 | } else { | ||
1050 | iwl_stop_queue(priv, txq->swq_id); | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | return 0; | ||
1055 | |||
1056 | drop_unlock: | ||
1057 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1058 | return -1; | ||
1059 | } | ||
1060 | EXPORT_SYMBOL(iwl_tx_skb); | ||
1061 | |||
1062 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 418 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
1063 | 419 | ||
1064 | /** | 420 | /** |
@@ -1192,61 +548,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1192 | return idx; | 548 | return idx; |
1193 | } | 549 | } |
1194 | 550 | ||
1195 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1196 | { | ||
1197 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1198 | struct ieee80211_sta *sta; | ||
1199 | struct iwl_station_priv *sta_priv; | ||
1200 | |||
1201 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1202 | if (sta) { | ||
1203 | sta_priv = (void *)sta->drv_priv; | ||
1204 | /* avoid atomic ops if this isn't a client */ | ||
1205 | if (sta_priv->client && | ||
1206 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1207 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1208 | } | ||
1209 | |||
1210 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1211 | } | ||
1212 | |||
1213 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | ||
1214 | { | ||
1215 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1216 | struct iwl_queue *q = &txq->q; | ||
1217 | struct iwl_tx_info *tx_info; | ||
1218 | int nfreed = 0; | ||
1219 | struct ieee80211_hdr *hdr; | ||
1220 | |||
1221 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1222 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1223 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1224 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1228 | for (index = iwl_queue_inc_wrap(index, q->n_bd); | ||
1229 | q->read_ptr != index; | ||
1230 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1231 | |||
1232 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
1233 | iwl_tx_status(priv, tx_info->skb[0]); | ||
1234 | |||
1235 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | ||
1236 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | ||
1237 | nfreed++; | ||
1238 | tx_info->skb[0] = NULL; | ||
1239 | |||
1240 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | ||
1241 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1242 | |||
1243 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
1244 | } | ||
1245 | return nfreed; | ||
1246 | } | ||
1247 | EXPORT_SYMBOL(iwl_tx_queue_reclaim); | ||
1248 | |||
1249 | |||
1250 | /** | 551 | /** |
1251 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd | 552 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd |
1252 | * | 553 | * |
@@ -1340,7 +641,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1340 | 641 | ||
1341 | if (!(meta->flags & CMD_ASYNC)) { | 642 | if (!(meta->flags & CMD_ASYNC)) { |
1342 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 643 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1343 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | 644 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
1344 | get_cmd_string(cmd->hdr.cmd)); | 645 | get_cmd_string(cmd->hdr.cmd)); |
1345 | wake_up_interruptible(&priv->wait_command_queue); | 646 | wake_up_interruptible(&priv->wait_command_queue); |
1346 | } | 647 | } |
@@ -1348,358 +649,37 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1348 | } | 649 | } |
1349 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 650 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
1350 | 651 | ||
1351 | /* | ||
1352 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
1353 | * Called only when finding queue for aggregation. | ||
1354 | * Should never return anything < 7, because they should already | ||
1355 | * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). | ||
1356 | */ | ||
1357 | static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) | ||
1358 | { | ||
1359 | int txq_id; | ||
1360 | |||
1361 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
1362 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
1363 | return txq_id; | ||
1364 | return -1; | ||
1365 | } | ||
1366 | |||
1367 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | ||
1368 | { | ||
1369 | int sta_id; | ||
1370 | int tx_fifo; | ||
1371 | int txq_id; | ||
1372 | int ret; | ||
1373 | unsigned long flags; | ||
1374 | struct iwl_tid_data *tid_data; | ||
1375 | |||
1376 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | ||
1377 | tx_fifo = default_tid_to_tx_fifo[tid]; | ||
1378 | else | ||
1379 | return -EINVAL; | ||
1380 | |||
1381 | IWL_WARN(priv, "%s on ra = %pM tid = %d\n", | ||
1382 | __func__, ra, tid); | ||
1383 | |||
1384 | sta_id = iwl_find_station(priv, ra); | ||
1385 | if (sta_id == IWL_INVALID_STATION) { | ||
1386 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
1387 | return -ENXIO; | ||
1388 | } | ||
1389 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1390 | return -EINVAL; | ||
1391 | |||
1392 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
1393 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
1394 | return -ENXIO; | ||
1395 | } | ||
1396 | |||
1397 | txq_id = iwl_txq_ctx_activate_free(priv); | ||
1398 | if (txq_id == -1) { | ||
1399 | IWL_ERR(priv, "No free aggregation queue available\n"); | ||
1400 | return -ENXIO; | ||
1401 | } | ||
1402 | |||
1403 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1404 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1405 | *ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1406 | tid_data->agg.txq_id = txq_id; | ||
1407 | priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); | ||
1408 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1409 | |||
1410 | ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, | ||
1411 | sta_id, tid, *ssn); | ||
1412 | if (ret) | ||
1413 | return ret; | ||
1414 | |||
1415 | if (tid_data->tfds_in_queue == 0) { | ||
1416 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1417 | tid_data->agg.state = IWL_AGG_ON; | ||
1418 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1419 | } else { | ||
1420 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | ||
1421 | tid_data->tfds_in_queue); | ||
1422 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
1423 | } | ||
1424 | return ret; | ||
1425 | } | ||
1426 | EXPORT_SYMBOL(iwl_tx_agg_start); | ||
1427 | |||
1428 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | ||
1429 | { | ||
1430 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
1431 | struct iwl_tid_data *tid_data; | ||
1432 | int write_ptr, read_ptr; | ||
1433 | unsigned long flags; | ||
1434 | |||
1435 | if (!ra) { | ||
1436 | IWL_ERR(priv, "ra = NULL\n"); | ||
1437 | return -EINVAL; | ||
1438 | } | ||
1439 | |||
1440 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1441 | return -EINVAL; | ||
1442 | |||
1443 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | ||
1444 | tx_fifo_id = default_tid_to_tx_fifo[tid]; | ||
1445 | else | ||
1446 | return -EINVAL; | ||
1447 | |||
1448 | sta_id = iwl_find_station(priv, ra); | ||
1449 | |||
1450 | if (sta_id == IWL_INVALID_STATION) { | ||
1451 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
1452 | return -ENXIO; | ||
1453 | } | ||
1454 | |||
1455 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1456 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1457 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1458 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1459 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1464 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1465 | |||
1466 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1467 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
1468 | txq_id = tid_data->agg.txq_id; | ||
1469 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
1470 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
1471 | |||
1472 | /* The queue is not empty */ | ||
1473 | if (write_ptr != read_ptr) { | ||
1474 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | ||
1475 | priv->stations[sta_id].tid[tid].agg.state = | ||
1476 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
1477 | return 0; | ||
1478 | } | ||
1479 | |||
1480 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1481 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1482 | |||
1483 | spin_lock_irqsave(&priv->lock, flags); | ||
1484 | /* | ||
1485 | * the only reason this call can fail is queue number out of range, | ||
1486 | * which can happen if uCode is reloaded and all the station | ||
1487 | * information are lost. if it is outside the range, there is no need | ||
1488 | * to deactivate the uCode queue, just return "success" to allow | ||
1489 | * mac80211 to clean up it own data. | ||
1490 | */ | ||
1491 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1492 | tx_fifo_id); | ||
1493 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1494 | |||
1495 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1496 | |||
1497 | return 0; | ||
1498 | } | ||
1499 | EXPORT_SYMBOL(iwl_tx_agg_stop); | ||
1500 | |||
1501 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | ||
1502 | { | ||
1503 | struct iwl_queue *q = &priv->txq[txq_id].q; | ||
1504 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
1505 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
1506 | |||
1507 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1508 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1509 | /* We are reclaiming the last packet of the */ | ||
1510 | /* aggregated HW queue */ | ||
1511 | if ((txq_id == tid_data->agg.txq_id) && | ||
1512 | (q->read_ptr == q->write_ptr)) { | ||
1513 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1514 | int tx_fifo = default_tid_to_tx_fifo[tid]; | ||
1515 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | ||
1516 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | ||
1517 | ssn, tx_fifo); | ||
1518 | tid_data->agg.state = IWL_AGG_OFF; | ||
1519 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1520 | } | ||
1521 | break; | ||
1522 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1523 | /* We are reclaiming the last packet of the queue */ | ||
1524 | if (tid_data->tfds_in_queue == 0) { | ||
1525 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | ||
1526 | tid_data->agg.state = IWL_AGG_ON; | ||
1527 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1528 | } | ||
1529 | break; | ||
1530 | } | ||
1531 | return 0; | ||
1532 | } | ||
1533 | EXPORT_SYMBOL(iwl_txq_check_empty); | ||
1534 | |||
1535 | /** | ||
1536 | * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1537 | * | ||
1538 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1539 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1540 | */ | ||
1541 | static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1542 | struct iwl_ht_agg *agg, | ||
1543 | struct iwl_compressed_ba_resp *ba_resp) | ||
1544 | |||
1545 | { | ||
1546 | int i, sh, ack; | ||
1547 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1548 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1549 | u64 bitmap; | ||
1550 | int successes = 0; | ||
1551 | struct ieee80211_tx_info *info; | ||
1552 | |||
1553 | if (unlikely(!agg->wait_for_ba)) { | ||
1554 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1555 | return -EINVAL; | ||
1556 | } | ||
1557 | |||
1558 | /* Mark that the expected block-ack response arrived */ | ||
1559 | agg->wait_for_ba = 0; | ||
1560 | IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1561 | |||
1562 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1563 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); | ||
1564 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1565 | sh += 0x100; | ||
1566 | |||
1567 | /* don't use 64-bit values for now */ | ||
1568 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1569 | |||
1570 | if (agg->frame_count > (64 - sh)) { | ||
1571 | IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); | ||
1572 | return -1; | ||
1573 | } | ||
1574 | |||
1575 | /* check for success or failure according to the | ||
1576 | * transmitted bitmap and block-ack bitmap */ | ||
1577 | bitmap &= agg->bitmap; | ||
1578 | |||
1579 | /* For each frame attempted in aggregation, | ||
1580 | * update driver's record of tx frame's status. */ | ||
1581 | for (i = 0; i < agg->frame_count ; i++) { | ||
1582 | ack = bitmap & (1ULL << i); | ||
1583 | successes += !!ack; | ||
1584 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | ||
1585 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | ||
1586 | agg->start_idx + i); | ||
1587 | } | ||
1588 | |||
1589 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1590 | memset(&info->status, 0, sizeof(info->status)); | ||
1591 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1592 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1593 | info->status.ampdu_ack_map = successes; | ||
1594 | info->status.ampdu_ack_len = agg->frame_count; | ||
1595 | iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1596 | |||
1597 | IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); | ||
1598 | |||
1599 | return 0; | ||
1600 | } | ||
1601 | |||
1602 | /** | ||
1603 | * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1604 | * | ||
1605 | * Handles block-acknowledge notification from device, which reports success | ||
1606 | * of frames sent via aggregation. | ||
1607 | */ | ||
1608 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1609 | struct iwl_rx_mem_buffer *rxb) | ||
1610 | { | ||
1611 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1612 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1613 | struct iwl_tx_queue *txq = NULL; | ||
1614 | struct iwl_ht_agg *agg; | ||
1615 | int index; | ||
1616 | int sta_id; | ||
1617 | int tid; | ||
1618 | |||
1619 | /* "flow" corresponds to Tx queue */ | ||
1620 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1621 | |||
1622 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1623 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1624 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1625 | |||
1626 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1627 | IWL_ERR(priv, | ||
1628 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1629 | return; | ||
1630 | } | ||
1631 | |||
1632 | txq = &priv->txq[scd_flow]; | ||
1633 | sta_id = ba_resp->sta_id; | ||
1634 | tid = ba_resp->tid; | ||
1635 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1636 | |||
1637 | /* Find index just before block-ack window */ | ||
1638 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1639 | |||
1640 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1641 | |||
1642 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1643 | "sta_id = %d\n", | ||
1644 | agg->wait_for_ba, | ||
1645 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1646 | ba_resp->sta_id); | ||
1647 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1648 | "%d, scd_ssn = %d\n", | ||
1649 | ba_resp->tid, | ||
1650 | ba_resp->seq_ctl, | ||
1651 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1652 | ba_resp->scd_flow, | ||
1653 | ba_resp->scd_ssn); | ||
1654 | IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", | ||
1655 | agg->start_idx, | ||
1656 | (unsigned long long)agg->bitmap); | ||
1657 | |||
1658 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1659 | iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1660 | |||
1661 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1662 | * block-ack window (we assume that they've been successfully | ||
1663 | * transmitted ... if not, it's too late anyway). */ | ||
1664 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1665 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1666 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); | ||
1667 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1668 | |||
1669 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1670 | priv->mac80211_registered && | ||
1671 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
1672 | iwl_wake_queue(priv, txq->swq_id); | ||
1673 | |||
1674 | iwl_txq_check_empty(priv, sta_id, tid, scd_flow); | ||
1675 | } | ||
1676 | } | ||
1677 | EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); | ||
1678 | |||
1679 | #ifdef CONFIG_IWLWIFI_DEBUG | 652 | #ifdef CONFIG_IWLWIFI_DEBUG |
1680 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 653 | #define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x |
654 | #define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x | ||
1681 | 655 | ||
1682 | const char *iwl_get_tx_fail_reason(u32 status) | 656 | const char *iwl_get_tx_fail_reason(u32 status) |
1683 | { | 657 | { |
1684 | switch (status & TX_STATUS_MSK) { | 658 | switch (status & TX_STATUS_MSK) { |
1685 | case TX_STATUS_SUCCESS: | 659 | case TX_STATUS_SUCCESS: |
1686 | return "SUCCESS"; | 660 | return "SUCCESS"; |
1687 | TX_STATUS_ENTRY(SHORT_LIMIT); | 661 | TX_STATUS_POSTPONE(DELAY); |
1688 | TX_STATUS_ENTRY(LONG_LIMIT); | 662 | TX_STATUS_POSTPONE(FEW_BYTES); |
1689 | TX_STATUS_ENTRY(FIFO_UNDERRUN); | 663 | TX_STATUS_POSTPONE(BT_PRIO); |
1690 | TX_STATUS_ENTRY(MGMNT_ABORT); | 664 | TX_STATUS_POSTPONE(QUIET_PERIOD); |
1691 | TX_STATUS_ENTRY(NEXT_FRAG); | 665 | TX_STATUS_POSTPONE(CALC_TTAK); |
1692 | TX_STATUS_ENTRY(LIFE_EXPIRE); | 666 | TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); |
1693 | TX_STATUS_ENTRY(DEST_PS); | 667 | TX_STATUS_FAIL(SHORT_LIMIT); |
1694 | TX_STATUS_ENTRY(ABORTED); | 668 | TX_STATUS_FAIL(LONG_LIMIT); |
1695 | TX_STATUS_ENTRY(BT_RETRY); | 669 | TX_STATUS_FAIL(FIFO_UNDERRUN); |
1696 | TX_STATUS_ENTRY(STA_INVALID); | 670 | TX_STATUS_FAIL(DRAIN_FLOW); |
1697 | TX_STATUS_ENTRY(FRAG_DROPPED); | 671 | TX_STATUS_FAIL(RFKILL_FLUSH); |
1698 | TX_STATUS_ENTRY(TID_DISABLE); | 672 | TX_STATUS_FAIL(LIFE_EXPIRE); |
1699 | TX_STATUS_ENTRY(FRAME_FLUSHED); | 673 | TX_STATUS_FAIL(DEST_PS); |
1700 | TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); | 674 | TX_STATUS_FAIL(HOST_ABORTED); |
1701 | TX_STATUS_ENTRY(TX_LOCKED); | 675 | TX_STATUS_FAIL(BT_RETRY); |
1702 | TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); | 676 | TX_STATUS_FAIL(STA_INVALID); |
677 | TX_STATUS_FAIL(FRAG_DROPPED); | ||
678 | TX_STATUS_FAIL(TID_DISABLE); | ||
679 | TX_STATUS_FAIL(FIFO_FLUSHED); | ||
680 | TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); | ||
681 | TX_STATUS_FAIL(FW_DROP); | ||
682 | TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP); | ||
1703 | } | 683 | } |
1704 | 684 | ||
1705 | return "UNKNOWN"; | 685 | return "UNKNOWN"; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b55e4f39a9e1..3e5bffb6034f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -352,11 +352,11 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) | |||
352 | 352 | ||
353 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) | 353 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) |
354 | { | 354 | { |
355 | if (priv->shared_virt) | 355 | if (priv->_3945.shared_virt) |
356 | dma_free_coherent(&priv->pci_dev->dev, | 356 | dma_free_coherent(&priv->pci_dev->dev, |
357 | sizeof(struct iwl3945_shared), | 357 | sizeof(struct iwl3945_shared), |
358 | priv->shared_virt, | 358 | priv->_3945.shared_virt, |
359 | priv->shared_phys); | 359 | priv->_3945.shared_phys); |
360 | } | 360 | } |
361 | 361 | ||
362 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | 362 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, |
@@ -505,24 +505,15 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
505 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | 505 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); |
506 | #endif | 506 | #endif |
507 | 507 | ||
508 | /* drop all non-injected data frame if we are not associated */ | ||
509 | if (ieee80211_is_data(fc) && | ||
510 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
511 | (!iwl_is_associated(priv) || | ||
512 | ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { | ||
513 | IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); | ||
514 | goto drop_unlock; | ||
515 | } | ||
516 | |||
517 | spin_unlock_irqrestore(&priv->lock, flags); | 508 | spin_unlock_irqrestore(&priv->lock, flags); |
518 | 509 | ||
519 | hdr_len = ieee80211_hdrlen(fc); | 510 | hdr_len = ieee80211_hdrlen(fc); |
520 | 511 | ||
521 | /* Find (or create) index into station table for destination station */ | 512 | /* Find index into station table for destination station */ |
522 | if (info->flags & IEEE80211_TX_CTL_INJECTED) | 513 | if (!info->control.sta) |
523 | sta_id = priv->hw_params.bcast_sta_id; | 514 | sta_id = priv->hw_params.bcast_sta_id; |
524 | else | 515 | else |
525 | sta_id = iwl_get_sta_id(priv, hdr); | 516 | sta_id = iwl_sta_id(info->control.sta); |
526 | if (sta_id == IWL_INVALID_STATION) { | 517 | if (sta_id == IWL_INVALID_STATION) { |
527 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 518 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
528 | hdr->addr1); | 519 | hdr->addr1); |
@@ -607,9 +598,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
607 | txq->need_update = 0; | 598 | txq->need_update = 0; |
608 | } | 599 | } |
609 | 600 | ||
610 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 601 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", |
611 | le16_to_cpu(out_cmd->hdr.sequence)); | 602 | le16_to_cpu(out_cmd->hdr.sequence)); |
612 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | 603 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); |
613 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); | 604 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); |
614 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, | 605 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, |
615 | ieee80211_hdrlen(fc)); | 606 | ieee80211_hdrlen(fc)); |
@@ -754,7 +745,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
754 | if (iwl_is_associated(priv)) | 745 | if (iwl_is_associated(priv)) |
755 | add_time = | 746 | add_time = |
756 | iwl3945_usecs_to_beacons( | 747 | iwl3945_usecs_to_beacons( |
757 | le64_to_cpu(params->start_time) - priv->last_tsf, | 748 | le64_to_cpu(params->start_time) - priv->_3945.last_tsf, |
758 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 749 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
759 | 750 | ||
760 | memset(&spectrum, 0, sizeof(spectrum)); | 751 | memset(&spectrum, 0, sizeof(spectrum)); |
@@ -768,7 +759,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
768 | 759 | ||
769 | if (iwl_is_associated(priv)) | 760 | if (iwl_is_associated(priv)) |
770 | spectrum.start_time = | 761 | spectrum.start_time = |
771 | iwl3945_add_beacon_time(priv->last_beacon_time, | 762 | iwl3945_add_beacon_time(priv->_3945.last_beacon_time, |
772 | add_time, | 763 | add_time, |
773 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | 764 | le16_to_cpu(priv->rxon_timing.beacon_interval)); |
774 | else | 765 | else |
@@ -857,7 +848,6 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, | |||
857 | #endif | 848 | #endif |
858 | 849 | ||
859 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); | 850 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); |
860 | return; | ||
861 | } | 851 | } |
862 | 852 | ||
863 | static void iwl3945_bg_beacon_update(struct work_struct *work) | 853 | static void iwl3945_bg_beacon_update(struct work_struct *work) |
@@ -966,7 +956,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | |||
966 | * statistics request from the host as well as for the periodic | 956 | * statistics request from the host as well as for the periodic |
967 | * statistics notifications (after received beacons) from the uCode. | 957 | * statistics notifications (after received beacons) from the uCode. |
968 | */ | 958 | */ |
969 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; | 959 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics; |
970 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; | 960 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; |
971 | 961 | ||
972 | iwl_setup_rx_scan_handlers(priv); | 962 | iwl_setup_rx_scan_handlers(priv); |
@@ -1613,9 +1603,6 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1613 | return pos; | 1603 | return pos; |
1614 | } | 1604 | } |
1615 | 1605 | ||
1616 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | ||
1617 | #define IWL3945_MAX_EVENT_LOG_SIZE (512) | ||
1618 | |||
1619 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) | 1606 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) |
1620 | 1607 | ||
1621 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | 1608 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
@@ -1642,16 +1629,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
1642 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 1629 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1643 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 1630 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1644 | 1631 | ||
1645 | if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) { | 1632 | if (capacity > priv->cfg->max_event_log_size) { |
1646 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 1633 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
1647 | capacity, IWL3945_MAX_EVENT_LOG_SIZE); | 1634 | capacity, priv->cfg->max_event_log_size); |
1648 | capacity = IWL3945_MAX_EVENT_LOG_SIZE; | 1635 | capacity = priv->cfg->max_event_log_size; |
1649 | } | 1636 | } |
1650 | 1637 | ||
1651 | if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) { | 1638 | if (next_entry > priv->cfg->max_event_log_size) { |
1652 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 1639 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
1653 | next_entry, IWL3945_MAX_EVENT_LOG_SIZE); | 1640 | next_entry, priv->cfg->max_event_log_size); |
1654 | next_entry = IWL3945_MAX_EVENT_LOG_SIZE; | 1641 | next_entry = priv->cfg->max_event_log_size; |
1655 | } | 1642 | } |
1656 | 1643 | ||
1657 | size = num_wraps ? capacity : next_entry; | 1644 | size = num_wraps ? capacity : next_entry; |
@@ -1860,7 +1847,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1860 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | 1847 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, |
1861 | enum ieee80211_band band, | 1848 | enum ieee80211_band band, |
1862 | u8 is_active, u8 n_probes, | 1849 | u8 is_active, u8 n_probes, |
1863 | struct iwl3945_scan_channel *scan_ch) | 1850 | struct iwl3945_scan_channel *scan_ch, |
1851 | struct ieee80211_vif *vif) | ||
1864 | { | 1852 | { |
1865 | struct ieee80211_channel *chan; | 1853 | struct ieee80211_channel *chan; |
1866 | const struct ieee80211_supported_band *sband; | 1854 | const struct ieee80211_supported_band *sband; |
@@ -1874,7 +1862,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | |||
1874 | return 0; | 1862 | return 0; |
1875 | 1863 | ||
1876 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | 1864 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); |
1877 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | 1865 | passive_dwell = iwl_get_passive_dwell_time(priv, band, vif); |
1878 | 1866 | ||
1879 | if (passive_dwell <= active_dwell) | 1867 | if (passive_dwell <= active_dwell) |
1880 | passive_dwell = active_dwell + 1; | 1868 | passive_dwell = active_dwell + 1; |
@@ -1947,7 +1935,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | |||
1947 | added++; | 1935 | added++; |
1948 | } | 1936 | } |
1949 | 1937 | ||
1950 | IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); | 1938 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); |
1951 | return added; | 1939 | return added; |
1952 | } | 1940 | } |
1953 | 1941 | ||
@@ -2122,6 +2110,28 @@ static void iwl3945_nic_start(struct iwl_priv *priv) | |||
2122 | iwl_write32(priv, CSR_RESET, 0); | 2110 | iwl_write32(priv, CSR_RESET, 0); |
2123 | } | 2111 | } |
2124 | 2112 | ||
2113 | #define IWL3945_UCODE_GET(item) \ | ||
2114 | static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\ | ||
2115 | { \ | ||
2116 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2117 | } | ||
2118 | |||
2119 | static u32 iwl3945_ucode_get_header_size(u32 api_ver) | ||
2120 | { | ||
2121 | return 24; | ||
2122 | } | ||
2123 | |||
2124 | static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode) | ||
2125 | { | ||
2126 | return (u8 *) ucode->u.v1.data; | ||
2127 | } | ||
2128 | |||
2129 | IWL3945_UCODE_GET(inst_size); | ||
2130 | IWL3945_UCODE_GET(data_size); | ||
2131 | IWL3945_UCODE_GET(init_size); | ||
2132 | IWL3945_UCODE_GET(init_data_size); | ||
2133 | IWL3945_UCODE_GET(boot_size); | ||
2134 | |||
2125 | /** | 2135 | /** |
2126 | * iwl3945_read_ucode - Read uCode images from disk file. | 2136 | * iwl3945_read_ucode - Read uCode images from disk file. |
2127 | * | 2137 | * |
@@ -2170,7 +2180,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2170 | goto error; | 2180 | goto error; |
2171 | 2181 | ||
2172 | /* Make sure that we got at least our header! */ | 2182 | /* Make sure that we got at least our header! */ |
2173 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { | 2183 | if (ucode_raw->size < iwl3945_ucode_get_header_size(1)) { |
2174 | IWL_ERR(priv, "File size way too small!\n"); | 2184 | IWL_ERR(priv, "File size way too small!\n"); |
2175 | ret = -EINVAL; | 2185 | ret = -EINVAL; |
2176 | goto err_release; | 2186 | goto err_release; |
@@ -2181,13 +2191,12 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2181 | 2191 | ||
2182 | priv->ucode_ver = le32_to_cpu(ucode->ver); | 2192 | priv->ucode_ver = le32_to_cpu(ucode->ver); |
2183 | api_ver = IWL_UCODE_API(priv->ucode_ver); | 2193 | api_ver = IWL_UCODE_API(priv->ucode_ver); |
2184 | inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); | 2194 | inst_size = iwl3945_ucode_get_inst_size(ucode); |
2185 | data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); | 2195 | data_size = iwl3945_ucode_get_data_size(ucode); |
2186 | init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); | 2196 | init_size = iwl3945_ucode_get_init_size(ucode); |
2187 | init_data_size = | 2197 | init_data_size = iwl3945_ucode_get_init_data_size(ucode); |
2188 | priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); | 2198 | boot_size = iwl3945_ucode_get_boot_size(ucode); |
2189 | boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); | 2199 | src = iwl3945_ucode_get_data(ucode); |
2190 | src = priv->cfg->ops->ucode->get_data(ucode, api_ver); | ||
2191 | 2200 | ||
2192 | /* api_ver should match the api version forming part of the | 2201 | /* api_ver should match the api version forming part of the |
2193 | * firmware filename ... but we don't check for that and only rely | 2202 | * firmware filename ... but we don't check for that and only rely |
@@ -2236,7 +2245,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2236 | 2245 | ||
2237 | 2246 | ||
2238 | /* Verify size of file vs. image size info in file's header */ | 2247 | /* Verify size of file vs. image size info in file's header */ |
2239 | if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + | 2248 | if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) + |
2240 | inst_size + data_size + init_size + | 2249 | inst_size + data_size + init_size + |
2241 | init_data_size + boot_size) { | 2250 | init_data_size + boot_size) { |
2242 | 2251 | ||
@@ -2490,8 +2499,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2490 | goto restart; | 2499 | goto restart; |
2491 | } | 2500 | } |
2492 | 2501 | ||
2493 | iwl_clear_stations_table(priv); | ||
2494 | |||
2495 | rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); | 2502 | rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); |
2496 | IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); | 2503 | IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); |
2497 | 2504 | ||
@@ -2513,13 +2520,19 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2513 | /* After the ALIVE response, we can send commands to 3945 uCode */ | 2520 | /* After the ALIVE response, we can send commands to 3945 uCode */ |
2514 | set_bit(STATUS_ALIVE, &priv->status); | 2521 | set_bit(STATUS_ALIVE, &priv->status); |
2515 | 2522 | ||
2523 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
2524 | /* Enable timer to monitor the driver queues */ | ||
2525 | mod_timer(&priv->monitor_recover, | ||
2526 | jiffies + | ||
2527 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2528 | } | ||
2529 | |||
2516 | if (iwl_is_rfkill(priv)) | 2530 | if (iwl_is_rfkill(priv)) |
2517 | return; | 2531 | return; |
2518 | 2532 | ||
2519 | ieee80211_wake_queues(priv->hw); | 2533 | ieee80211_wake_queues(priv->hw); |
2520 | 2534 | ||
2521 | priv->active_rate = priv->rates_mask; | 2535 | priv->active_rate = IWL_RATES_MASK; |
2522 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | ||
2523 | 2536 | ||
2524 | iwl_power_update_mode(priv, true); | 2537 | iwl_power_update_mode(priv, true); |
2525 | 2538 | ||
@@ -2531,11 +2544,11 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2531 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2544 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2532 | } else { | 2545 | } else { |
2533 | /* Initialize our rx_config data */ | 2546 | /* Initialize our rx_config data */ |
2534 | iwl_connection_init_rx_config(priv, priv->iw_mode); | 2547 | iwl_connection_init_rx_config(priv, NULL); |
2535 | } | 2548 | } |
2536 | 2549 | ||
2537 | /* Configure Bluetooth device coexistence support */ | 2550 | /* Configure Bluetooth device coexistence support */ |
2538 | iwl_send_bt_config(priv); | 2551 | priv->cfg->ops->hcmd->send_bt_config(priv); |
2539 | 2552 | ||
2540 | /* Configure the adapter for unassociated operation */ | 2553 | /* Configure the adapter for unassociated operation */ |
2541 | iwlcore_commit_rxon(priv); | 2554 | iwlcore_commit_rxon(priv); |
@@ -2548,17 +2561,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2548 | set_bit(STATUS_READY, &priv->status); | 2561 | set_bit(STATUS_READY, &priv->status); |
2549 | wake_up_interruptible(&priv->wait_command_queue); | 2562 | wake_up_interruptible(&priv->wait_command_queue); |
2550 | 2563 | ||
2551 | /* reassociate for ADHOC mode */ | ||
2552 | if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { | ||
2553 | struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, | ||
2554 | priv->vif); | ||
2555 | if (beacon) | ||
2556 | iwl_mac_beacon_update(priv->hw, beacon); | ||
2557 | } | ||
2558 | |||
2559 | if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) | ||
2560 | iwl_set_mode(priv, priv->iw_mode); | ||
2561 | |||
2562 | return; | 2564 | return; |
2563 | 2565 | ||
2564 | restart: | 2566 | restart: |
@@ -2580,7 +2582,10 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2580 | if (!exit_pending) | 2582 | if (!exit_pending) |
2581 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2583 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2582 | 2584 | ||
2583 | iwl_clear_stations_table(priv); | 2585 | /* Station information will now be cleared in device */ |
2586 | iwl_clear_ucode_stations(priv); | ||
2587 | iwl_dealloc_bcast_station(priv); | ||
2588 | iwl_clear_driver_stations(priv); | ||
2584 | 2589 | ||
2585 | /* Unblock any waiting calls */ | 2590 | /* Unblock any waiting calls */ |
2586 | wake_up_interruptible_all(&priv->wait_command_queue); | 2591 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2661,6 +2666,10 @@ static int __iwl3945_up(struct iwl_priv *priv) | |||
2661 | { | 2666 | { |
2662 | int rc, i; | 2667 | int rc, i; |
2663 | 2668 | ||
2669 | rc = iwl_alloc_bcast_station(priv, false); | ||
2670 | if (rc) | ||
2671 | return rc; | ||
2672 | |||
2664 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 2673 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
2665 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); | 2674 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); |
2666 | return -EIO; | 2675 | return -EIO; |
@@ -2714,12 +2723,10 @@ static int __iwl3945_up(struct iwl_priv *priv) | |||
2714 | 2723 | ||
2715 | for (i = 0; i < MAX_HW_RESTARTS; i++) { | 2724 | for (i = 0; i < MAX_HW_RESTARTS; i++) { |
2716 | 2725 | ||
2717 | iwl_clear_stations_table(priv); | ||
2718 | |||
2719 | /* load bootstrap state machine, | 2726 | /* load bootstrap state machine, |
2720 | * load bootstrap program into processor's memory, | 2727 | * load bootstrap program into processor's memory, |
2721 | * prepare to load the "initialize" uCode */ | 2728 | * prepare to load the "initialize" uCode */ |
2722 | priv->cfg->ops->lib->load_ucode(priv); | 2729 | rc = priv->cfg->ops->lib->load_ucode(priv); |
2723 | 2730 | ||
2724 | if (rc) { | 2731 | if (rc) { |
2725 | IWL_ERR(priv, | 2732 | IWL_ERR(priv, |
@@ -2787,7 +2794,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data) | |||
2787 | static void iwl3945_rfkill_poll(struct work_struct *data) | 2794 | static void iwl3945_rfkill_poll(struct work_struct *data) |
2788 | { | 2795 | { |
2789 | struct iwl_priv *priv = | 2796 | struct iwl_priv *priv = |
2790 | container_of(data, struct iwl_priv, rfkill_poll.work); | 2797 | container_of(data, struct iwl_priv, _3945.rfkill_poll.work); |
2791 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); | 2798 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); |
2792 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) | 2799 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) |
2793 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | 2800 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); |
@@ -2806,22 +2813,18 @@ static void iwl3945_rfkill_poll(struct work_struct *data) | |||
2806 | 2813 | ||
2807 | /* Keep this running, even if radio now enabled. This will be | 2814 | /* Keep this running, even if radio now enabled. This will be |
2808 | * cancelled in mac_start() if system decides to start again */ | 2815 | * cancelled in mac_start() if system decides to start again */ |
2809 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 2816 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, |
2810 | round_jiffies_relative(2 * HZ)); | 2817 | round_jiffies_relative(2 * HZ)); |
2811 | 2818 | ||
2812 | } | 2819 | } |
2813 | 2820 | ||
2814 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) | 2821 | void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) |
2815 | static void iwl3945_bg_request_scan(struct work_struct *data) | ||
2816 | { | 2822 | { |
2817 | struct iwl_priv *priv = | ||
2818 | container_of(data, struct iwl_priv, request_scan); | ||
2819 | struct iwl_host_cmd cmd = { | 2823 | struct iwl_host_cmd cmd = { |
2820 | .id = REPLY_SCAN_CMD, | 2824 | .id = REPLY_SCAN_CMD, |
2821 | .len = sizeof(struct iwl3945_scan_cmd), | 2825 | .len = sizeof(struct iwl3945_scan_cmd), |
2822 | .flags = CMD_SIZE_HUGE, | 2826 | .flags = CMD_SIZE_HUGE, |
2823 | }; | 2827 | }; |
2824 | int rc = 0; | ||
2825 | struct iwl3945_scan_cmd *scan; | 2828 | struct iwl3945_scan_cmd *scan; |
2826 | struct ieee80211_conf *conf = NULL; | 2829 | struct ieee80211_conf *conf = NULL; |
2827 | u8 n_probes = 0; | 2830 | u8 n_probes = 0; |
@@ -2830,8 +2833,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2830 | 2833 | ||
2831 | conf = ieee80211_get_hw_conf(priv->hw); | 2834 | conf = ieee80211_get_hw_conf(priv->hw); |
2832 | 2835 | ||
2833 | mutex_lock(&priv->mutex); | ||
2834 | |||
2835 | cancel_delayed_work(&priv->scan_check); | 2836 | cancel_delayed_work(&priv->scan_check); |
2836 | 2837 | ||
2837 | if (!iwl_is_ready(priv)) { | 2838 | if (!iwl_is_ready(priv)) { |
@@ -2849,7 +2850,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2849 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | 2850 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { |
2850 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " | 2851 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " |
2851 | "Ignoring second request.\n"); | 2852 | "Ignoring second request.\n"); |
2852 | rc = -EIO; | ||
2853 | goto done; | 2853 | goto done; |
2854 | } | 2854 | } |
2855 | 2855 | ||
@@ -2875,20 +2875,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2875 | goto done; | 2875 | goto done; |
2876 | } | 2876 | } |
2877 | 2877 | ||
2878 | if (!priv->scan_bands) { | 2878 | if (!priv->scan_cmd) { |
2879 | IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); | 2879 | priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) + |
2880 | goto done; | 2880 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); |
2881 | } | 2881 | if (!priv->scan_cmd) { |
2882 | 2882 | IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n"); | |
2883 | if (!priv->scan) { | ||
2884 | priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + | ||
2885 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
2886 | if (!priv->scan) { | ||
2887 | rc = -ENOMEM; | ||
2888 | goto done; | 2883 | goto done; |
2889 | } | 2884 | } |
2890 | } | 2885 | } |
2891 | scan = priv->scan; | 2886 | scan = priv->scan_cmd; |
2892 | memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); | 2887 | memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); |
2893 | 2888 | ||
2894 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | 2889 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; |
@@ -2904,7 +2899,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2904 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 2899 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
2905 | 2900 | ||
2906 | spin_lock_irqsave(&priv->lock, flags); | 2901 | spin_lock_irqsave(&priv->lock, flags); |
2907 | interval = priv->beacon_int; | 2902 | interval = vif ? vif->bss_conf.beacon_int : 0; |
2908 | spin_unlock_irqrestore(&priv->lock, flags); | 2903 | spin_unlock_irqrestore(&priv->lock, flags); |
2909 | 2904 | ||
2910 | scan->suspend_time = 0; | 2905 | scan->suspend_time = 0; |
@@ -2927,7 +2922,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2927 | scan_suspend_time, interval); | 2922 | scan_suspend_time, interval); |
2928 | } | 2923 | } |
2929 | 2924 | ||
2930 | if (priv->scan_request->n_ssids) { | 2925 | if (priv->is_internal_short_scan) { |
2926 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
2927 | } else if (priv->scan_request->n_ssids) { | ||
2931 | int i, p = 0; | 2928 | int i, p = 0; |
2932 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 2929 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
2933 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 2930 | for (i = 0; i < priv->scan_request->n_ssids; i++) { |
@@ -2955,41 +2952,49 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2955 | 2952 | ||
2956 | /* flags + rate selection */ | 2953 | /* flags + rate selection */ |
2957 | 2954 | ||
2958 | if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { | 2955 | switch (priv->scan_band) { |
2956 | case IEEE80211_BAND_2GHZ: | ||
2959 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | 2957 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; |
2960 | scan->tx_cmd.rate = IWL_RATE_1M_PLCP; | 2958 | scan->tx_cmd.rate = IWL_RATE_1M_PLCP; |
2961 | scan->good_CRC_th = 0; | 2959 | scan->good_CRC_th = 0; |
2962 | band = IEEE80211_BAND_2GHZ; | 2960 | band = IEEE80211_BAND_2GHZ; |
2963 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { | 2961 | break; |
2962 | case IEEE80211_BAND_5GHZ: | ||
2964 | scan->tx_cmd.rate = IWL_RATE_6M_PLCP; | 2963 | scan->tx_cmd.rate = IWL_RATE_6M_PLCP; |
2965 | /* | 2964 | /* |
2966 | * If active scaning is requested but a certain channel | 2965 | * If active scaning is requested but a certain channel |
2967 | * is marked passive, we can do active scanning if we | 2966 | * is marked passive, we can do active scanning if we |
2968 | * detect transmissions. | 2967 | * detect transmissions. |
2969 | */ | 2968 | */ |
2970 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 2969 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
2970 | IWL_GOOD_CRC_TH_DISABLED; | ||
2971 | band = IEEE80211_BAND_5GHZ; | 2971 | band = IEEE80211_BAND_5GHZ; |
2972 | } else { | 2972 | break; |
2973 | IWL_WARN(priv, "Invalid scan band count\n"); | 2973 | default: |
2974 | IWL_WARN(priv, "Invalid scan band\n"); | ||
2974 | goto done; | 2975 | goto done; |
2975 | } | 2976 | } |
2976 | 2977 | ||
2977 | scan->tx_cmd.len = cpu_to_le16( | 2978 | if (!priv->is_internal_short_scan) { |
2979 | scan->tx_cmd.len = cpu_to_le16( | ||
2978 | iwl_fill_probe_req(priv, | 2980 | iwl_fill_probe_req(priv, |
2979 | (struct ieee80211_mgmt *)scan->data, | 2981 | (struct ieee80211_mgmt *)scan->data, |
2980 | priv->scan_request->ie, | 2982 | priv->scan_request->ie, |
2981 | priv->scan_request->ie_len, | 2983 | priv->scan_request->ie_len, |
2982 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | 2984 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); |
2983 | 2985 | } else { | |
2986 | scan->tx_cmd.len = cpu_to_le16( | ||
2987 | iwl_fill_probe_req(priv, | ||
2988 | (struct ieee80211_mgmt *)scan->data, | ||
2989 | NULL, 0, | ||
2990 | IWL_MAX_SCAN_SIZE - sizeof(*scan))); | ||
2991 | } | ||
2984 | /* select Rx antennas */ | 2992 | /* select Rx antennas */ |
2985 | scan->flags |= iwl3945_get_antenna_flags(priv); | 2993 | scan->flags |= iwl3945_get_antenna_flags(priv); |
2986 | 2994 | ||
2987 | if (iwl_is_monitor_mode(priv)) | ||
2988 | scan->filter_flags = RXON_FILTER_PROMISC_MSK; | ||
2989 | |||
2990 | scan->channel_count = | 2995 | scan->channel_count = |
2991 | iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, | 2996 | iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, |
2992 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | 2997 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); |
2993 | 2998 | ||
2994 | if (scan->channel_count == 0) { | 2999 | if (scan->channel_count == 0) { |
2995 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | 3000 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); |
@@ -3002,14 +3007,12 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
3002 | scan->len = cpu_to_le16(cmd.len); | 3007 | scan->len = cpu_to_le16(cmd.len); |
3003 | 3008 | ||
3004 | set_bit(STATUS_SCAN_HW, &priv->status); | 3009 | set_bit(STATUS_SCAN_HW, &priv->status); |
3005 | rc = iwl_send_cmd_sync(priv, &cmd); | 3010 | if (iwl_send_cmd_sync(priv, &cmd)) |
3006 | if (rc) | ||
3007 | goto done; | 3011 | goto done; |
3008 | 3012 | ||
3009 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 3013 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
3010 | IWL_SCAN_CHECK_WATCHDOG); | 3014 | IWL_SCAN_CHECK_WATCHDOG); |
3011 | 3015 | ||
3012 | mutex_unlock(&priv->mutex); | ||
3013 | return; | 3016 | return; |
3014 | 3017 | ||
3015 | done: | 3018 | done: |
@@ -3023,7 +3026,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
3023 | 3026 | ||
3024 | /* inform mac80211 scan aborted */ | 3027 | /* inform mac80211 scan aborted */ |
3025 | queue_work(priv->workqueue, &priv->scan_completed); | 3028 | queue_work(priv->workqueue, &priv->scan_completed); |
3026 | mutex_unlock(&priv->mutex); | ||
3027 | } | 3029 | } |
3028 | 3030 | ||
3029 | static void iwl3945_bg_restart(struct work_struct *data) | 3031 | static void iwl3945_bg_restart(struct work_struct *data) |
@@ -3065,28 +3067,25 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data) | |||
3065 | mutex_unlock(&priv->mutex); | 3067 | mutex_unlock(&priv->mutex); |
3066 | } | 3068 | } |
3067 | 3069 | ||
3068 | #define IWL_DELAY_NEXT_SCAN (HZ*2) | 3070 | void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) |
3069 | |||
3070 | void iwl3945_post_associate(struct iwl_priv *priv) | ||
3071 | { | 3071 | { |
3072 | int rc = 0; | 3072 | int rc = 0; |
3073 | struct ieee80211_conf *conf = NULL; | 3073 | struct ieee80211_conf *conf = NULL; |
3074 | 3074 | ||
3075 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 3075 | if (!vif || !priv->is_open) |
3076 | return; | ||
3077 | |||
3078 | if (vif->type == NL80211_IFTYPE_AP) { | ||
3076 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 3079 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
3077 | return; | 3080 | return; |
3078 | } | 3081 | } |
3079 | 3082 | ||
3080 | |||
3081 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", | 3083 | IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", |
3082 | priv->assoc_id, priv->active_rxon.bssid_addr); | 3084 | vif->bss_conf.aid, priv->active_rxon.bssid_addr); |
3083 | 3085 | ||
3084 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3086 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3085 | return; | 3087 | return; |
3086 | 3088 | ||
3087 | if (!priv->vif || !priv->is_open) | ||
3088 | return; | ||
3089 | |||
3090 | iwl_scan_cancel_timeout(priv, 200); | 3089 | iwl_scan_cancel_timeout(priv, 200); |
3091 | 3090 | ||
3092 | conf = ieee80211_get_hw_conf(priv->hw); | 3091 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -3095,7 +3094,7 @@ void iwl3945_post_associate(struct iwl_priv *priv) | |||
3095 | iwlcore_commit_rxon(priv); | 3094 | iwlcore_commit_rxon(priv); |
3096 | 3095 | ||
3097 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 3096 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); |
3098 | iwl_setup_rxon_timing(priv); | 3097 | iwl_setup_rxon_timing(priv, vif); |
3099 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 3098 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
3100 | sizeof(priv->rxon_timing), &priv->rxon_timing); | 3099 | sizeof(priv->rxon_timing), &priv->rxon_timing); |
3101 | if (rc) | 3100 | if (rc) |
@@ -3104,57 +3103,40 @@ void iwl3945_post_associate(struct iwl_priv *priv) | |||
3104 | 3103 | ||
3105 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3104 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3106 | 3105 | ||
3107 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 3106 | priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid); |
3108 | 3107 | ||
3109 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", | 3108 | IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", |
3110 | priv->assoc_id, priv->beacon_int); | 3109 | vif->bss_conf.aid, vif->bss_conf.beacon_int); |
3111 | 3110 | ||
3112 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3111 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
3113 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 3112 | priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; |
3114 | else | 3113 | else |
3115 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3114 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3116 | 3115 | ||
3117 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3116 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3118 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3117 | if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) |
3119 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 3118 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
3120 | else | 3119 | else |
3121 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3120 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
3122 | 3121 | ||
3123 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 3122 | if (vif->type == NL80211_IFTYPE_ADHOC) |
3124 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | 3123 | priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; |
3125 | |||
3126 | } | 3124 | } |
3127 | 3125 | ||
3128 | iwlcore_commit_rxon(priv); | 3126 | iwlcore_commit_rxon(priv); |
3129 | 3127 | ||
3130 | switch (priv->iw_mode) { | 3128 | switch (vif->type) { |
3131 | case NL80211_IFTYPE_STATION: | 3129 | case NL80211_IFTYPE_STATION: |
3132 | iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); | 3130 | iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); |
3133 | break; | 3131 | break; |
3134 | |||
3135 | case NL80211_IFTYPE_ADHOC: | 3132 | case NL80211_IFTYPE_ADHOC: |
3136 | |||
3137 | priv->assoc_id = 1; | ||
3138 | iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL); | ||
3139 | iwl3945_sync_sta(priv, IWL_STA_ID, | ||
3140 | (priv->band == IEEE80211_BAND_5GHZ) ? | ||
3141 | IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, | ||
3142 | CMD_ASYNC); | ||
3143 | iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); | ||
3144 | iwl3945_send_beacon_cmd(priv); | 3133 | iwl3945_send_beacon_cmd(priv); |
3145 | |||
3146 | break; | 3134 | break; |
3147 | |||
3148 | default: | 3135 | default: |
3149 | IWL_ERR(priv, "%s Should not be called in %d mode\n", | 3136 | IWL_ERR(priv, "%s Should not be called in %d mode\n", |
3150 | __func__, priv->iw_mode); | 3137 | __func__, vif->type); |
3151 | break; | 3138 | break; |
3152 | } | 3139 | } |
3153 | |||
3154 | iwl_activate_qos(priv, 0); | ||
3155 | |||
3156 | /* we have just associated, don't start scan too early */ | ||
3157 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; | ||
3158 | } | 3140 | } |
3159 | 3141 | ||
3160 | /***************************************************************************** | 3142 | /***************************************************************************** |
@@ -3213,7 +3195,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
3213 | 3195 | ||
3214 | /* ucode is running and will send rfkill notifications, | 3196 | /* ucode is running and will send rfkill notifications, |
3215 | * no need to poll the killswitch state anymore */ | 3197 | * no need to poll the killswitch state anymore */ |
3216 | cancel_delayed_work(&priv->rfkill_poll); | 3198 | cancel_delayed_work(&priv->_3945.rfkill_poll); |
3217 | 3199 | ||
3218 | iwl_led_start(priv); | 3200 | iwl_led_start(priv); |
3219 | 3201 | ||
@@ -3254,7 +3236,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw) | |||
3254 | flush_workqueue(priv->workqueue); | 3236 | flush_workqueue(priv->workqueue); |
3255 | 3237 | ||
3256 | /* start polling the killswitch state again */ | 3238 | /* start polling the killswitch state again */ |
3257 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 3239 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, |
3258 | round_jiffies_relative(2 * HZ)); | 3240 | round_jiffies_relative(2 * HZ)); |
3259 | 3241 | ||
3260 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3242 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -3276,7 +3258,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3276 | return NETDEV_TX_OK; | 3258 | return NETDEV_TX_OK; |
3277 | } | 3259 | } |
3278 | 3260 | ||
3279 | void iwl3945_config_ap(struct iwl_priv *priv) | 3261 | void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) |
3280 | { | 3262 | { |
3281 | int rc = 0; | 3263 | int rc = 0; |
3282 | 3264 | ||
@@ -3292,7 +3274,7 @@ void iwl3945_config_ap(struct iwl_priv *priv) | |||
3292 | 3274 | ||
3293 | /* RXON Timing */ | 3275 | /* RXON Timing */ |
3294 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 3276 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); |
3295 | iwl_setup_rxon_timing(priv); | 3277 | iwl_setup_rxon_timing(priv, vif); |
3296 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | 3278 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, |
3297 | sizeof(priv->rxon_timing), | 3279 | sizeof(priv->rxon_timing), |
3298 | &priv->rxon_timing); | 3280 | &priv->rxon_timing); |
@@ -3300,9 +3282,10 @@ void iwl3945_config_ap(struct iwl_priv *priv) | |||
3300 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3282 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3301 | "Attempting to continue.\n"); | 3283 | "Attempting to continue.\n"); |
3302 | 3284 | ||
3303 | /* FIXME: what should be the assoc_id for AP? */ | 3285 | priv->staging_rxon.assoc_id = 0; |
3304 | priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); | 3286 | |
3305 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | 3287 | if (vif->bss_conf.assoc_capability & |
3288 | WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
3306 | priv->staging_rxon.flags |= | 3289 | priv->staging_rxon.flags |= |
3307 | RXON_FLG_SHORT_PREAMBLE_MSK; | 3290 | RXON_FLG_SHORT_PREAMBLE_MSK; |
3308 | else | 3291 | else |
@@ -3310,22 +3293,21 @@ void iwl3945_config_ap(struct iwl_priv *priv) | |||
3310 | ~RXON_FLG_SHORT_PREAMBLE_MSK; | 3293 | ~RXON_FLG_SHORT_PREAMBLE_MSK; |
3311 | 3294 | ||
3312 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { | 3295 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { |
3313 | if (priv->assoc_capability & | 3296 | if (vif->bss_conf.assoc_capability & |
3314 | WLAN_CAPABILITY_SHORT_SLOT_TIME) | 3297 | WLAN_CAPABILITY_SHORT_SLOT_TIME) |
3315 | priv->staging_rxon.flags |= | 3298 | priv->staging_rxon.flags |= |
3316 | RXON_FLG_SHORT_SLOT_MSK; | 3299 | RXON_FLG_SHORT_SLOT_MSK; |
3317 | else | 3300 | else |
3318 | priv->staging_rxon.flags &= | 3301 | priv->staging_rxon.flags &= |
3319 | ~RXON_FLG_SHORT_SLOT_MSK; | 3302 | ~RXON_FLG_SHORT_SLOT_MSK; |
3320 | 3303 | ||
3321 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC) | 3304 | if (vif->type == NL80211_IFTYPE_ADHOC) |
3322 | priv->staging_rxon.flags &= | 3305 | priv->staging_rxon.flags &= |
3323 | ~RXON_FLG_SHORT_SLOT_MSK; | 3306 | ~RXON_FLG_SHORT_SLOT_MSK; |
3324 | } | 3307 | } |
3325 | /* restore RXON assoc */ | 3308 | /* restore RXON assoc */ |
3326 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3309 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3327 | iwlcore_commit_rxon(priv); | 3310 | iwlcore_commit_rxon(priv); |
3328 | iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL); | ||
3329 | } | 3311 | } |
3330 | iwl3945_send_beacon_cmd(priv); | 3312 | iwl3945_send_beacon_cmd(priv); |
3331 | 3313 | ||
@@ -3340,7 +3322,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3340 | struct ieee80211_key_conf *key) | 3322 | struct ieee80211_key_conf *key) |
3341 | { | 3323 | { |
3342 | struct iwl_priv *priv = hw->priv; | 3324 | struct iwl_priv *priv = hw->priv; |
3343 | const u8 *addr; | ||
3344 | int ret = 0; | 3325 | int ret = 0; |
3345 | u8 sta_id = IWL_INVALID_STATION; | 3326 | u8 sta_id = IWL_INVALID_STATION; |
3346 | u8 static_key; | 3327 | u8 static_key; |
@@ -3352,21 +3333,24 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3352 | return -EOPNOTSUPP; | 3333 | return -EOPNOTSUPP; |
3353 | } | 3334 | } |
3354 | 3335 | ||
3355 | addr = sta ? sta->addr : iwl_bcast_addr; | ||
3356 | static_key = !iwl_is_associated(priv); | 3336 | static_key = !iwl_is_associated(priv); |
3357 | 3337 | ||
3358 | if (!static_key) { | 3338 | if (!static_key) { |
3359 | sta_id = iwl_find_station(priv, addr); | 3339 | if (!sta) { |
3360 | if (sta_id == IWL_INVALID_STATION) { | 3340 | sta_id = priv->hw_params.bcast_sta_id; |
3361 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | 3341 | } else { |
3362 | addr); | 3342 | sta_id = iwl_sta_id(sta); |
3363 | return -EINVAL; | 3343 | if (sta_id == IWL_INVALID_STATION) { |
3344 | IWL_DEBUG_MAC80211(priv, | ||
3345 | "leave - %pM not in station map.\n", | ||
3346 | sta->addr); | ||
3347 | return -EINVAL; | ||
3348 | } | ||
3364 | } | 3349 | } |
3365 | } | 3350 | } |
3366 | 3351 | ||
3367 | mutex_lock(&priv->mutex); | 3352 | mutex_lock(&priv->mutex); |
3368 | iwl_scan_cancel_timeout(priv, 100); | 3353 | iwl_scan_cancel_timeout(priv, 100); |
3369 | mutex_unlock(&priv->mutex); | ||
3370 | 3354 | ||
3371 | switch (cmd) { | 3355 | switch (cmd) { |
3372 | case SET_KEY: | 3356 | case SET_KEY: |
@@ -3387,11 +3371,45 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3387 | ret = -EINVAL; | 3371 | ret = -EINVAL; |
3388 | } | 3372 | } |
3389 | 3373 | ||
3374 | mutex_unlock(&priv->mutex); | ||
3390 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3375 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3391 | 3376 | ||
3392 | return ret; | 3377 | return ret; |
3393 | } | 3378 | } |
3394 | 3379 | ||
3380 | static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | ||
3381 | struct ieee80211_vif *vif, | ||
3382 | struct ieee80211_sta *sta) | ||
3383 | { | ||
3384 | struct iwl_priv *priv = hw->priv; | ||
3385 | struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv; | ||
3386 | int ret; | ||
3387 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | ||
3388 | u8 sta_id; | ||
3389 | |||
3390 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3391 | |||
3392 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | ||
3393 | sta->addr); | ||
3394 | |||
3395 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, | ||
3396 | &sta_id); | ||
3397 | if (ret) { | ||
3398 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | ||
3399 | sta->addr, ret); | ||
3400 | /* Should we return success if return code is EEXIST ? */ | ||
3401 | return ret; | ||
3402 | } | ||
3403 | |||
3404 | sta_priv->common.sta_id = sta_id; | ||
3405 | |||
3406 | /* Initialize rate scaling */ | ||
3407 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | ||
3408 | sta->addr); | ||
3409 | iwl3945_rs_rate_init(priv, sta, sta_id); | ||
3410 | |||
3411 | return 0; | ||
3412 | } | ||
3395 | /***************************************************************************** | 3413 | /***************************************************************************** |
3396 | * | 3414 | * |
3397 | * sysfs attributes | 3415 | * sysfs attributes |
@@ -3591,7 +3609,7 @@ static ssize_t store_measurement(struct device *d, | |||
3591 | struct iwl_priv *priv = dev_get_drvdata(d); | 3609 | struct iwl_priv *priv = dev_get_drvdata(d); |
3592 | struct ieee80211_measurement_params params = { | 3610 | struct ieee80211_measurement_params params = { |
3593 | .channel = le16_to_cpu(priv->active_rxon.channel), | 3611 | .channel = le16_to_cpu(priv->active_rxon.channel), |
3594 | .start_time = cpu_to_le64(priv->last_tsf), | 3612 | .start_time = cpu_to_le64(priv->_3945.last_tsf), |
3595 | .duration = cpu_to_le16(1), | 3613 | .duration = cpu_to_le16(1), |
3596 | }; | 3614 | }; |
3597 | u8 type = IWL_MEASURE_BASIC; | 3615 | u8 type = IWL_MEASURE_BASIC; |
@@ -3655,44 +3673,6 @@ static ssize_t show_channels(struct device *d, | |||
3655 | 3673 | ||
3656 | static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); | 3674 | static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); |
3657 | 3675 | ||
3658 | static ssize_t show_statistics(struct device *d, | ||
3659 | struct device_attribute *attr, char *buf) | ||
3660 | { | ||
3661 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3662 | u32 size = sizeof(struct iwl3945_notif_statistics); | ||
3663 | u32 len = 0, ofs = 0; | ||
3664 | u8 *data = (u8 *)&priv->statistics_39; | ||
3665 | int rc = 0; | ||
3666 | |||
3667 | if (!iwl_is_alive(priv)) | ||
3668 | return -EAGAIN; | ||
3669 | |||
3670 | mutex_lock(&priv->mutex); | ||
3671 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
3672 | mutex_unlock(&priv->mutex); | ||
3673 | |||
3674 | if (rc) { | ||
3675 | len = sprintf(buf, | ||
3676 | "Error sending statistics request: 0x%08X\n", rc); | ||
3677 | return len; | ||
3678 | } | ||
3679 | |||
3680 | while (size && (PAGE_SIZE - len)) { | ||
3681 | hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, | ||
3682 | PAGE_SIZE - len, 1); | ||
3683 | len = strlen(buf); | ||
3684 | if (PAGE_SIZE - len) | ||
3685 | buf[len++] = '\n'; | ||
3686 | |||
3687 | ofs += 16; | ||
3688 | size -= min(size, 16U); | ||
3689 | } | ||
3690 | |||
3691 | return len; | ||
3692 | } | ||
3693 | |||
3694 | static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); | ||
3695 | |||
3696 | static ssize_t show_antenna(struct device *d, | 3676 | static ssize_t show_antenna(struct device *d, |
3697 | struct device_attribute *attr, char *buf) | 3677 | struct device_attribute *attr, char *buf) |
3698 | { | 3678 | { |
@@ -3774,14 +3754,21 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3774 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | 3754 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); |
3775 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | 3755 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); |
3776 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | 3756 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); |
3777 | INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll); | 3757 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); |
3778 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 3758 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); |
3779 | INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); | ||
3780 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 3759 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); |
3760 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | ||
3781 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 3761 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
3782 | 3762 | ||
3783 | iwl3945_hw_setup_deferred_work(priv); | 3763 | iwl3945_hw_setup_deferred_work(priv); |
3784 | 3764 | ||
3765 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
3766 | init_timer(&priv->monitor_recover); | ||
3767 | priv->monitor_recover.data = (unsigned long)priv; | ||
3768 | priv->monitor_recover.function = | ||
3769 | priv->cfg->ops->lib->recover_from_tx_stall; | ||
3770 | } | ||
3771 | |||
3785 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3772 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3786 | iwl3945_irq_tasklet, (unsigned long)priv); | 3773 | iwl3945_irq_tasklet, (unsigned long)priv); |
3787 | } | 3774 | } |
@@ -3793,7 +3780,10 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) | |||
3793 | cancel_delayed_work_sync(&priv->init_alive_start); | 3780 | cancel_delayed_work_sync(&priv->init_alive_start); |
3794 | cancel_delayed_work(&priv->scan_check); | 3781 | cancel_delayed_work(&priv->scan_check); |
3795 | cancel_delayed_work(&priv->alive_start); | 3782 | cancel_delayed_work(&priv->alive_start); |
3783 | cancel_work_sync(&priv->start_internal_scan); | ||
3796 | cancel_work_sync(&priv->beacon_update); | 3784 | cancel_work_sync(&priv->beacon_update); |
3785 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
3786 | del_timer_sync(&priv->monitor_recover); | ||
3797 | } | 3787 | } |
3798 | 3788 | ||
3799 | static struct attribute *iwl3945_sysfs_entries[] = { | 3789 | static struct attribute *iwl3945_sysfs_entries[] = { |
@@ -3804,7 +3794,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
3804 | &dev_attr_filter_flags.attr, | 3794 | &dev_attr_filter_flags.attr, |
3805 | &dev_attr_measurement.attr, | 3795 | &dev_attr_measurement.attr, |
3806 | &dev_attr_retry_rate.attr, | 3796 | &dev_attr_retry_rate.attr, |
3807 | &dev_attr_statistics.attr, | ||
3808 | &dev_attr_status.attr, | 3797 | &dev_attr_status.attr, |
3809 | &dev_attr_temperature.attr, | 3798 | &dev_attr_temperature.attr, |
3810 | &dev_attr_tx_power.attr, | 3799 | &dev_attr_tx_power.attr, |
@@ -3831,7 +3820,9 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
3831 | .conf_tx = iwl_mac_conf_tx, | 3820 | .conf_tx = iwl_mac_conf_tx, |
3832 | .reset_tsf = iwl_mac_reset_tsf, | 3821 | .reset_tsf = iwl_mac_reset_tsf, |
3833 | .bss_info_changed = iwl_bss_info_changed, | 3822 | .bss_info_changed = iwl_bss_info_changed, |
3834 | .hw_scan = iwl_mac_hw_scan | 3823 | .hw_scan = iwl_mac_hw_scan, |
3824 | .sta_add = iwl3945_mac_sta_add, | ||
3825 | .sta_remove = iwl_mac_sta_remove, | ||
3835 | }; | 3826 | }; |
3836 | 3827 | ||
3837 | static int iwl3945_init_drv(struct iwl_priv *priv) | 3828 | static int iwl3945_init_drv(struct iwl_priv *priv) |
@@ -3850,9 +3841,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3850 | mutex_init(&priv->mutex); | 3841 | mutex_init(&priv->mutex); |
3851 | mutex_init(&priv->sync_cmd_mutex); | 3842 | mutex_init(&priv->sync_cmd_mutex); |
3852 | 3843 | ||
3853 | /* Clear the driver's (not device's) station table */ | ||
3854 | iwl_clear_stations_table(priv); | ||
3855 | |||
3856 | priv->ieee_channels = NULL; | 3844 | priv->ieee_channels = NULL; |
3857 | priv->ieee_rates = NULL; | 3845 | priv->ieee_rates = NULL; |
3858 | priv->band = IEEE80211_BAND_2GHZ; | 3846 | priv->band = IEEE80211_BAND_2GHZ; |
@@ -3860,12 +3848,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3860 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3848 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3861 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3849 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3862 | 3850 | ||
3863 | iwl_reset_qos(priv); | ||
3864 | |||
3865 | priv->qos_data.qos_active = 0; | ||
3866 | priv->qos_data.qos_cap.val = 0; | ||
3867 | |||
3868 | priv->rates_mask = IWL_RATES_MASK; | ||
3869 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; | 3851 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; |
3870 | 3852 | ||
3871 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { | 3853 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { |
@@ -3901,6 +3883,8 @@ err: | |||
3901 | return ret; | 3883 | return ret; |
3902 | } | 3884 | } |
3903 | 3885 | ||
3886 | #define IWL3945_MAX_PROBE_REQUEST 200 | ||
3887 | |||
3904 | static int iwl3945_setup_mac(struct iwl_priv *priv) | 3888 | static int iwl3945_setup_mac(struct iwl_priv *priv) |
3905 | { | 3889 | { |
3906 | int ret; | 3890 | int ret; |
@@ -3908,10 +3892,10 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3908 | 3892 | ||
3909 | hw->rate_control_algorithm = "iwl-3945-rs"; | 3893 | hw->rate_control_algorithm = "iwl-3945-rs"; |
3910 | hw->sta_data_size = sizeof(struct iwl3945_sta_priv); | 3894 | hw->sta_data_size = sizeof(struct iwl3945_sta_priv); |
3895 | hw->vif_data_size = sizeof(struct iwl_vif_priv); | ||
3911 | 3896 | ||
3912 | /* Tell mac80211 our characteristics */ | 3897 | /* Tell mac80211 our characteristics */ |
3913 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 3898 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
3914 | IEEE80211_HW_NOISE_DBM | | ||
3915 | IEEE80211_HW_SPECTRUM_MGMT; | 3899 | IEEE80211_HW_SPECTRUM_MGMT; |
3916 | 3900 | ||
3917 | if (!priv->cfg->broken_powersave) | 3901 | if (!priv->cfg->broken_powersave) |
@@ -3927,7 +3911,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3927 | 3911 | ||
3928 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; | 3912 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; |
3929 | /* we create the 802.11 header and a zero-length SSID element */ | 3913 | /* we create the 802.11 header and a zero-length SSID element */ |
3930 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | 3914 | hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2; |
3931 | 3915 | ||
3932 | /* Default value; 4 EDCA QOS priorities */ | 3916 | /* Default value; 4 EDCA QOS priorities */ |
3933 | hw->queues = 4; | 3917 | hw->queues = 4; |
@@ -4130,7 +4114,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4130 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | 4114 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); |
4131 | 4115 | ||
4132 | /* Start monitoring the killswitch */ | 4116 | /* Start monitoring the killswitch */ |
4133 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 4117 | queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll, |
4134 | 2 * HZ); | 4118 | 2 * HZ); |
4135 | 4119 | ||
4136 | return 0; | 4120 | return 0; |
@@ -4204,7 +4188,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4204 | 4188 | ||
4205 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 4189 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
4206 | 4190 | ||
4207 | cancel_delayed_work_sync(&priv->rfkill_poll); | 4191 | cancel_delayed_work_sync(&priv->_3945.rfkill_poll); |
4208 | 4192 | ||
4209 | iwl3945_dealloc_ucode_pci(priv); | 4193 | iwl3945_dealloc_ucode_pci(priv); |
4210 | 4194 | ||
@@ -4213,7 +4197,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4213 | iwl3945_hw_txq_ctx_free(priv); | 4197 | iwl3945_hw_txq_ctx_free(priv); |
4214 | 4198 | ||
4215 | iwl3945_unset_hw_params(priv); | 4199 | iwl3945_unset_hw_params(priv); |
4216 | iwl_clear_stations_table(priv); | ||
4217 | 4200 | ||
4218 | /*netif_stop_queue(dev); */ | 4201 | /*netif_stop_queue(dev); */ |
4219 | flush_workqueue(priv->workqueue); | 4202 | flush_workqueue(priv->workqueue); |
@@ -4235,7 +4218,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4235 | 4218 | ||
4236 | iwl_free_channel_map(priv); | 4219 | iwl_free_channel_map(priv); |
4237 | iwlcore_free_geos(priv); | 4220 | iwlcore_free_geos(priv); |
4238 | kfree(priv->scan); | 4221 | kfree(priv->scan_cmd); |
4239 | if (priv->ibss_beacon) | 4222 | if (priv->ibss_beacon) |
4240 | dev_kfree_skb(priv->ibss_beacon); | 4223 | dev_kfree_skb(priv->ibss_beacon); |
4241 | 4224 | ||