diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
51 files changed, 7331 insertions, 4369 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 99310c033253..dc8ed1527666 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -1,23 +1,7 @@ | |||
1 | config IWLWIFI | 1 | config IWLWIFI |
2 | tristate "Intel Wireless Wifi" | 2 | tristate "Intel Wireless Wifi" |
3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on PCI && MAC80211 |
4 | select LIB80211 | ||
5 | select FW_LOADER | 4 | select FW_LOADER |
6 | select MAC80211_LEDS if IWLWIFI_LEDS | ||
7 | select LEDS_CLASS if IWLWIFI_LEDS | ||
8 | |||
9 | config IWLWIFI_LEDS | ||
10 | bool "Enable LED support in iwlagn and iwl3945 drivers" | ||
11 | depends on IWLWIFI | ||
12 | default y | ||
13 | ---help--- | ||
14 | Select this if you want LED support. | ||
15 | |||
16 | config IWLWIFI_SPECTRUM_MEASUREMENT | ||
17 | bool "Enable Spectrum Measurement in iwlagn driver" | ||
18 | depends on IWLWIFI | ||
19 | ---help--- | ||
20 | This option will enable spectrum measurement for the iwlagn driver. | ||
21 | 5 | ||
22 | config IWLWIFI_DEBUG | 6 | config IWLWIFI_DEBUG |
23 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" | 7 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" |
@@ -50,6 +34,24 @@ config IWLWIFI_DEBUGFS | |||
50 | ---help--- | 34 | ---help--- |
51 | Enable creation of debugfs files for the iwlwifi drivers. | 35 | Enable creation of debugfs files for the iwlwifi drivers. |
52 | 36 | ||
37 | config IWLWIFI_DEVICE_TRACING | ||
38 | bool "iwlwifi device access tracing" | ||
39 | depends on IWLWIFI | ||
40 | depends on EVENT_TRACING | ||
41 | help | ||
42 | Say Y here to trace all commands, including TX frames and IO | ||
43 | accesses, sent to the device. If you say yes, iwlwifi will | ||
44 | register with the ftrace framework for event tracing and dump | ||
45 | all this information to the ringbuffer, you may need to | ||
46 | increase the ringbuffer size. See the ftrace documentation | ||
47 | for more information. | ||
48 | |||
49 | When tracing is not enabled, this option still has some | ||
50 | (though rather small) overhead. | ||
51 | |||
52 | If unsure, say Y so we can help you better when problems | ||
53 | occur. | ||
54 | |||
53 | config IWLAGN | 55 | config IWLAGN |
54 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" | 56 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" |
55 | depends on IWLWIFI | 57 | depends on IWLWIFI |
@@ -112,9 +114,3 @@ config IWL3945 | |||
112 | inserted in and removed from the running kernel whenever you want), | 114 | inserted in and removed from the running kernel whenever you want), |
113 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 115 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
114 | module will be called iwl3945. | 116 | module will be called iwl3945. |
115 | |||
116 | config IWL3945_SPECTRUM_MEASUREMENT | ||
117 | bool "Enable Spectrum Measurement in iwl3945 driver" | ||
118 | depends on IWL3945 | ||
119 | ---help--- | ||
120 | This option will enable spectrum measurement for the iwl3945 driver. | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 1d4e0a226fd4..4e378faee650 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,20 +1,23 @@ | |||
1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o | 1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o |
2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o | 2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o |
3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o | 3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o |
4 | iwlcore-objs += iwl-scan.o | 4 | iwlcore-objs += iwl-scan.o iwl-led.o |
5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
6 | iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o | 6 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
7 | iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o | ||
8 | 7 | ||
8 | CFLAGS_iwl-devtrace.o := -I$(src) | ||
9 | |||
10 | # AGN | ||
9 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 11 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
10 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o |
11 | 13 | ||
12 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 14 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
13 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 15 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
14 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o | 16 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o |
15 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | 17 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o |
16 | 18 | ||
19 | # 3945 | ||
17 | obj-$(CONFIG_IWL3945) += iwl3945.o | 20 | obj-$(CONFIG_IWL3945) += iwl3945.o |
18 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o | 21 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o |
19 | 22 | ||
20 | 23 | ccflags-y += -D__CHECK_ENDIAN__ | |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 950267ab556a..3bf2e6e9b2d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -44,6 +44,7 @@ | |||
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | #include "iwl-agn-led.h" | ||
47 | 48 | ||
48 | /* Highest firmware API version supported */ | 49 | /* Highest firmware API version supported */ |
49 | #define IWL1000_UCODE_API_MAX 3 | 50 | #define IWL1000_UCODE_API_MAX 3 |
@@ -76,7 +77,10 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |||
76 | /* NIC configuration for 1000 series */ | 77 | /* NIC configuration for 1000 series */ |
77 | static void iwl1000_nic_config(struct iwl_priv *priv) | 78 | static void iwl1000_nic_config(struct iwl_priv *priv) |
78 | { | 79 | { |
79 | iwl5000_nic_config(priv); | 80 | /* set CSR_HW_CONFIG_REG for uCode use */ |
81 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
82 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
83 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
80 | 84 | ||
81 | /* Setting digital SVR for 1000 card to 1.32V */ | 85 | /* Setting digital SVR for 1000 card to 1.32V */ |
82 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | 86 | /* locking is acquired in iwl_set_bits_mask_prph() function */ |
@@ -85,8 +89,78 @@ static void iwl1000_nic_config(struct iwl_priv *priv) | |||
85 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | 89 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); |
86 | } | 90 | } |
87 | 91 | ||
92 | static struct iwl_sensitivity_ranges iwl1000_sensitivity = { | ||
93 | .min_nrg_cck = 95, | ||
94 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
95 | .auto_corr_min_ofdm = 90, | ||
96 | .auto_corr_min_ofdm_mrc = 170, | ||
97 | .auto_corr_min_ofdm_x1 = 120, | ||
98 | .auto_corr_min_ofdm_mrc_x1 = 240, | ||
99 | |||
100 | .auto_corr_max_ofdm = 120, | ||
101 | .auto_corr_max_ofdm_mrc = 210, | ||
102 | .auto_corr_max_ofdm_x1 = 155, | ||
103 | .auto_corr_max_ofdm_mrc_x1 = 290, | ||
104 | |||
105 | .auto_corr_min_cck = 125, | ||
106 | .auto_corr_max_cck = 200, | ||
107 | .auto_corr_min_cck_mrc = 170, | ||
108 | .auto_corr_max_cck_mrc = 400, | ||
109 | .nrg_th_cck = 95, | ||
110 | .nrg_th_ofdm = 95, | ||
111 | |||
112 | .barker_corr_th_min = 190, | ||
113 | .barker_corr_th_min_mrc = 390, | ||
114 | .nrg_th_cca = 62, | ||
115 | }; | ||
116 | |||
117 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | ||
118 | { | ||
119 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
120 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | ||
121 | priv->cfg->num_of_queues = | ||
122 | priv->cfg->mod_params->num_of_queues; | ||
123 | |||
124 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | ||
125 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | ||
126 | priv->hw_params.scd_bc_tbls_size = | ||
127 | priv->cfg->num_of_queues * | ||
128 | sizeof(struct iwl5000_scd_bc_tbl); | ||
129 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
130 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | ||
131 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | ||
132 | |||
133 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | ||
134 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | ||
135 | |||
136 | priv->hw_params.max_bsm_size = 0; | ||
137 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
138 | BIT(IEEE80211_BAND_5GHZ); | ||
139 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
140 | |||
141 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | ||
142 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | ||
143 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
144 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
145 | |||
146 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | ||
147 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | ||
148 | |||
149 | /* Set initial sensitivity parameters */ | ||
150 | /* Set initial calibration set */ | ||
151 | priv->hw_params.sens = &iwl1000_sensitivity; | ||
152 | priv->hw_params.calib_init_cfg = | ||
153 | BIT(IWL_CALIB_XTAL) | | ||
154 | BIT(IWL_CALIB_LO) | | ||
155 | BIT(IWL_CALIB_TX_IQ) | | ||
156 | BIT(IWL_CALIB_TX_IQ_PERD) | | ||
157 | BIT(IWL_CALIB_BASE_BAND); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
88 | static struct iwl_lib_ops iwl1000_lib = { | 162 | static struct iwl_lib_ops iwl1000_lib = { |
89 | .set_hw_params = iwl5000_hw_set_hw_params, | 163 | .set_hw_params = iwl1000_hw_set_hw_params, |
90 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 164 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
91 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 165 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, |
92 | .txq_set_sched = iwl5000_txq_set_sched, | 166 | .txq_set_sched = iwl5000_txq_set_sched, |
@@ -101,14 +175,15 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
101 | .load_ucode = iwl5000_load_ucode, | 175 | .load_ucode = iwl5000_load_ucode, |
102 | .dump_nic_event_log = iwl_dump_nic_event_log, | 176 | .dump_nic_event_log = iwl_dump_nic_event_log, |
103 | .dump_nic_error_log = iwl_dump_nic_error_log, | 177 | .dump_nic_error_log = iwl_dump_nic_error_log, |
178 | .dump_csr = iwl_dump_csr, | ||
179 | .dump_fh = iwl_dump_fh, | ||
104 | .init_alive_start = iwl5000_init_alive_start, | 180 | .init_alive_start = iwl5000_init_alive_start, |
105 | .alive_notify = iwl5000_alive_notify, | 181 | .alive_notify = iwl5000_alive_notify, |
106 | .send_tx_power = iwl5000_send_tx_power, | 182 | .send_tx_power = iwl5000_send_tx_power, |
107 | .update_chain_flags = iwl_update_chain_flags, | 183 | .update_chain_flags = iwl_update_chain_flags, |
108 | .apm_ops = { | 184 | .apm_ops = { |
109 | .init = iwl5000_apm_init, | 185 | .init = iwl_apm_init, |
110 | .reset = iwl5000_apm_reset, | 186 | .stop = iwl_apm_stop, |
111 | .stop = iwl5000_apm_stop, | ||
112 | .config = iwl1000_nic_config, | 187 | .config = iwl1000_nic_config, |
113 | .set_pwr_src = iwl_set_pwr_src, | 188 | .set_pwr_src = iwl_set_pwr_src, |
114 | }, | 189 | }, |
@@ -135,13 +210,15 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
135 | .temperature = iwl5000_temperature, | 210 | .temperature = iwl5000_temperature, |
136 | .set_ct_kill = iwl1000_set_ct_threshold, | 211 | .set_ct_kill = iwl1000_set_ct_threshold, |
137 | }, | 212 | }, |
213 | .add_bcast_station = iwl_add_bcast_station, | ||
138 | }; | 214 | }; |
139 | 215 | ||
140 | static struct iwl_ops iwl1000_ops = { | 216 | static const struct iwl_ops iwl1000_ops = { |
141 | .ucode = &iwl5000_ucode, | 217 | .ucode = &iwl5000_ucode, |
142 | .lib = &iwl1000_lib, | 218 | .lib = &iwl1000_lib, |
143 | .hcmd = &iwl5000_hcmd, | 219 | .hcmd = &iwl5000_hcmd, |
144 | .utils = &iwl5000_hcmd_utils, | 220 | .utils = &iwl5000_hcmd_utils, |
221 | .led = &iwlagn_led_ops, | ||
145 | }; | 222 | }; |
146 | 223 | ||
147 | struct iwl_cfg iwl1000_bgn_cfg = { | 224 | struct iwl_cfg iwl1000_bgn_cfg = { |
@@ -152,15 +229,53 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
152 | .sku = IWL_SKU_G|IWL_SKU_N, | 229 | .sku = IWL_SKU_G|IWL_SKU_N, |
153 | .ops = &iwl1000_ops, | 230 | .ops = &iwl1000_ops, |
154 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 231 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
155 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 232 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
156 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 233 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
234 | .num_of_queues = IWL50_NUM_QUEUES, | ||
235 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
157 | .mod_params = &iwl50_mod_params, | 236 | .mod_params = &iwl50_mod_params, |
158 | .valid_tx_ant = ANT_A, | 237 | .valid_tx_ant = ANT_A, |
159 | .valid_rx_ant = ANT_AB, | 238 | .valid_rx_ant = ANT_AB, |
160 | .need_pll_cfg = true, | 239 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
240 | .set_l0s = true, | ||
241 | .use_bsm = false, | ||
161 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 242 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
162 | .shadow_ram_support = false, | 243 | .shadow_ram_support = false, |
163 | .ht_greenfield_support = true, | 244 | .ht_greenfield_support = true, |
245 | .led_compensation = 51, | ||
164 | .use_rts_for_ht = true, /* use rts/cts protection */ | 246 | .use_rts_for_ht = true, /* use rts/cts protection */ |
247 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
248 | .support_ct_kill_exit = true, | ||
249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||
250 | .chain_noise_scale = 1000, | ||
251 | }; | ||
252 | |||
253 | struct iwl_cfg iwl1000_bg_cfg = { | ||
254 | .name = "1000 Series BG", | ||
255 | .fw_name_pre = IWL1000_FW_PRE, | ||
256 | .ucode_api_max = IWL1000_UCODE_API_MAX, | ||
257 | .ucode_api_min = IWL1000_UCODE_API_MIN, | ||
258 | .sku = IWL_SKU_G, | ||
259 | .ops = &iwl1000_ops, | ||
260 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
261 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | ||
262 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
263 | .num_of_queues = IWL50_NUM_QUEUES, | ||
264 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
265 | .mod_params = &iwl50_mod_params, | ||
266 | .valid_tx_ant = ANT_A, | ||
267 | .valid_rx_ant = ANT_AB, | ||
268 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
269 | .set_l0s = true, | ||
270 | .use_bsm = false, | ||
271 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | ||
272 | .shadow_ram_support = false, | ||
273 | .ht_greenfield_support = true, | ||
274 | .led_compensation = 51, | ||
275 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
276 | .support_ct_kill_exit = true, | ||
277 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||
278 | .chain_noise_scale = 1000, | ||
165 | }; | 279 | }; |
166 | 280 | ||
281 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h index 08ce259a0e60..042f6bc0df13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 16772780c5b0..3a876a8ece38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -71,12 +71,6 @@ | |||
71 | 71 | ||
72 | #include "iwl-eeprom.h" | 72 | #include "iwl-eeprom.h" |
73 | 73 | ||
74 | /* | ||
75 | * uCode queue management definitions ... | ||
76 | * Queue #4 is the command queue for 3945 and 4965. | ||
77 | */ | ||
78 | #define IWL_CMD_QUEUE_NUM 4 | ||
79 | |||
80 | /* Time constants */ | 74 | /* Time constants */ |
81 | #define SHORT_SLOT_TIME 9 | 75 | #define SHORT_SLOT_TIME 9 |
82 | #define LONG_SLOT_TIME 20 | 76 | #define LONG_SLOT_TIME 20 |
@@ -254,12 +248,6 @@ struct iwl3945_eeprom { | |||
254 | #define TFD_CTL_PAD_SET(n) (n << 28) | 248 | #define TFD_CTL_PAD_SET(n) (n << 28) |
255 | #define TFD_CTL_PAD_GET(ctl) (ctl >> 28) | 249 | #define TFD_CTL_PAD_GET(ctl) (ctl >> 28) |
256 | 250 | ||
257 | /* | ||
258 | * RX related structures and functions | ||
259 | */ | ||
260 | #define RX_FREE_BUFFERS 64 | ||
261 | #define RX_LOW_WATERMARK 8 | ||
262 | |||
263 | /* Sizes and addresses for instruction and data memory (SRAM) in | 251 | /* Sizes and addresses for instruction and data memory (SRAM) in |
264 | * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | 252 | * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ |
265 | #define IWL39_RTC_INST_LOWER_BOUND (0x000000) | 253 | #define IWL39_RTC_INST_LOWER_BOUND (0x000000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 8c29ded7d02c..abe2b739c4dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -24,8 +24,6 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #ifdef CONFIG_IWLWIFI_LEDS | ||
28 | |||
29 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
31 | #include <linux/init.h> | 29 | #include <linux/init.h> |
@@ -43,388 +41,51 @@ | |||
43 | #include "iwl-3945.h" | 41 | #include "iwl-3945.h" |
44 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
45 | #include "iwl-dev.h" | 43 | #include "iwl-dev.h" |
44 | #include "iwl-3945-led.h" | ||
46 | 45 | ||
47 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
48 | static const char *led_type_str[] = { | ||
49 | __stringify(IWL_LED_TRG_TX), | ||
50 | __stringify(IWL_LED_TRG_RX), | ||
51 | __stringify(IWL_LED_TRG_ASSOC), | ||
52 | __stringify(IWL_LED_TRG_RADIO), | ||
53 | NULL | ||
54 | }; | ||
55 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
56 | |||
57 | static const struct { | ||
58 | u16 brightness; | ||
59 | u8 on_time; | ||
60 | u8 off_time; | ||
61 | } blink_tbl[] = | ||
62 | { | ||
63 | {300, 25, 25}, | ||
64 | {200, 40, 40}, | ||
65 | {100, 55, 55}, | ||
66 | {70, 65, 65}, | ||
67 | {50, 75, 75}, | ||
68 | {20, 85, 85}, | ||
69 | {15, 95, 95 }, | ||
70 | {10, 110, 110}, | ||
71 | {5, 130, 130}, | ||
72 | {0, 167, 167}, | ||
73 | /* SOLID_ON */ | ||
74 | {-1, IWL_LED_SOLID, 0} | ||
75 | }; | ||
76 | |||
77 | #define IWL_1MB_RATE (128 * 1024) | ||
78 | #define IWL_LED_THRESHOLD (16) | ||
79 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ | ||
80 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | ||
81 | |||
82 | static void iwl3945_led_cmd_callback(struct iwl_priv *priv, | ||
83 | struct iwl_device_cmd *cmd, | ||
84 | struct sk_buff *skb) | ||
85 | { | ||
86 | } | ||
87 | |||
88 | static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) | ||
89 | { | ||
90 | return fls(0x000000FF & (u32)brightness); | ||
91 | } | ||
92 | 46 | ||
93 | /* Send led command */ | 47 | /* Send led command */ |
94 | static int iwl_send_led_cmd(struct iwl_priv *priv, | 48 | static int iwl3945_send_led_cmd(struct iwl_priv *priv, |
95 | struct iwl_led_cmd *led_cmd) | 49 | struct iwl_led_cmd *led_cmd) |
96 | { | 50 | { |
97 | struct iwl_host_cmd cmd = { | 51 | struct iwl_host_cmd cmd = { |
98 | .id = REPLY_LEDS_CMD, | 52 | .id = REPLY_LEDS_CMD, |
99 | .len = sizeof(struct iwl_led_cmd), | 53 | .len = sizeof(struct iwl_led_cmd), |
100 | .data = led_cmd, | 54 | .data = led_cmd, |
101 | .flags = CMD_ASYNC, | 55 | .flags = CMD_ASYNC, |
102 | .callback = iwl3945_led_cmd_callback, | 56 | .callback = NULL, |
103 | }; | 57 | }; |
104 | 58 | ||
105 | return iwl_send_cmd(priv, &cmd); | 59 | return iwl_send_cmd(priv, &cmd); |
106 | } | 60 | } |
107 | 61 | ||
108 | |||
109 | |||
110 | /* Set led on command */ | ||
111 | static int iwl3945_led_pattern(struct iwl_priv *priv, int led_id, | ||
112 | unsigned int idx) | ||
113 | { | ||
114 | struct iwl_led_cmd led_cmd = { | ||
115 | .id = led_id, | ||
116 | .interval = IWL_DEF_LED_INTRVL | ||
117 | }; | ||
118 | |||
119 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | ||
120 | |||
121 | led_cmd.on = blink_tbl[idx].on_time; | ||
122 | led_cmd.off = blink_tbl[idx].off_time; | ||
123 | |||
124 | return iwl_send_led_cmd(priv, &led_cmd); | ||
125 | } | ||
126 | |||
127 | |||
128 | /* Set led on command */ | 62 | /* Set led on command */ |
129 | static int iwl3945_led_on(struct iwl_priv *priv, int led_id) | 63 | static int iwl3945_led_on(struct iwl_priv *priv) |
130 | { | 64 | { |
131 | struct iwl_led_cmd led_cmd = { | 65 | struct iwl_led_cmd led_cmd = { |
132 | .id = led_id, | 66 | .id = IWL_LED_LINK, |
133 | .on = IWL_LED_SOLID, | 67 | .on = IWL_LED_SOLID, |
134 | .off = 0, | 68 | .off = 0, |
135 | .interval = IWL_DEF_LED_INTRVL | 69 | .interval = IWL_DEF_LED_INTRVL |
136 | }; | 70 | }; |
137 | return iwl_send_led_cmd(priv, &led_cmd); | 71 | return iwl3945_send_led_cmd(priv, &led_cmd); |
138 | } | 72 | } |
139 | 73 | ||
140 | /* Set led off command */ | 74 | /* Set led off command */ |
141 | static int iwl3945_led_off(struct iwl_priv *priv, int led_id) | 75 | static int iwl3945_led_off(struct iwl_priv *priv) |
142 | { | 76 | { |
143 | struct iwl_led_cmd led_cmd = { | 77 | struct iwl_led_cmd led_cmd = { |
144 | .id = led_id, | 78 | .id = IWL_LED_LINK, |
145 | .on = 0, | 79 | .on = 0, |
146 | .off = 0, | 80 | .off = 0, |
147 | .interval = IWL_DEF_LED_INTRVL | 81 | .interval = IWL_DEF_LED_INTRVL |
148 | }; | 82 | }; |
149 | IWL_DEBUG_LED(priv, "led off %d\n", led_id); | 83 | IWL_DEBUG_LED(priv, "led off\n"); |
150 | return iwl_send_led_cmd(priv, &led_cmd); | 84 | return iwl3945_send_led_cmd(priv, &led_cmd); |
151 | } | 85 | } |
152 | 86 | ||
153 | /* | 87 | const struct iwl_led_ops iwl3945_led_ops = { |
154 | * Set led on in case of association | 88 | .cmd = iwl3945_send_led_cmd, |
155 | * */ | 89 | .on = iwl3945_led_on, |
156 | static int iwl3945_led_associate(struct iwl_priv *priv, int led_id) | 90 | .off = iwl3945_led_off, |
157 | { | 91 | }; |
158 | IWL_DEBUG_LED(priv, "Associated\n"); | ||
159 | |||
160 | priv->allow_blinking = 1; | ||
161 | return iwl3945_led_on(priv, led_id); | ||
162 | } | ||
163 | /* Set Led off in case of disassociation */ | ||
164 | static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id) | ||
165 | { | ||
166 | IWL_DEBUG_LED(priv, "Disassociated\n"); | ||
167 | |||
168 | priv->allow_blinking = 0; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * brightness call back function for Tx/Rx LED | ||
175 | */ | ||
176 | static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) | ||
177 | { | ||
178 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | ||
179 | !test_bit(STATUS_READY, &priv->status)) | ||
180 | return 0; | ||
181 | |||
182 | |||
183 | /* start counting Tx/Rx bytes */ | ||
184 | if (!priv->last_blink_time && priv->allow_blinking) | ||
185 | priv->last_blink_time = jiffies; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * brightness call back for association and radio | ||
191 | */ | ||
192 | static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, | ||
193 | enum led_brightness brightness) | ||
194 | { | ||
195 | struct iwl_led *led = container_of(led_cdev, | ||
196 | struct iwl_led, led_dev); | ||
197 | struct iwl_priv *priv = led->priv; | ||
198 | |||
199 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
200 | return; | ||
201 | |||
202 | IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", | ||
203 | led_type_str[led->type], brightness); | ||
204 | |||
205 | switch (brightness) { | ||
206 | case LED_FULL: | ||
207 | if (led->led_on) | ||
208 | led->led_on(priv, IWL_LED_LINK); | ||
209 | break; | ||
210 | case LED_OFF: | ||
211 | if (led->led_off) | ||
212 | led->led_off(priv, IWL_LED_LINK); | ||
213 | break; | ||
214 | default: | ||
215 | if (led->led_pattern) { | ||
216 | int idx = iwl3945_brightness_to_idx(brightness); | ||
217 | led->led_pattern(priv, IWL_LED_LINK, idx); | ||
218 | } | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Register led class with the system | ||
225 | */ | ||
226 | static int iwl3945_led_register_led(struct iwl_priv *priv, | ||
227 | struct iwl_led *led, | ||
228 | enum led_type type, u8 set_led, | ||
229 | char *trigger) | ||
230 | { | ||
231 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
232 | int ret; | ||
233 | |||
234 | led->led_dev.name = led->name; | ||
235 | led->led_dev.brightness_set = iwl3945_led_brightness_set; | ||
236 | led->led_dev.default_trigger = trigger; | ||
237 | |||
238 | led->priv = priv; | ||
239 | led->type = type; | ||
240 | |||
241 | ret = led_classdev_register(device, &led->led_dev); | ||
242 | if (ret) { | ||
243 | IWL_ERR(priv, "Error: failed to register led handler.\n"); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | led->registered = 1; | ||
248 | |||
249 | if (set_led && led->led_on) | ||
250 | led->led_on(priv, IWL_LED_LINK); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | |||
255 | /* | ||
256 | * calculate blink rate according to last 2 sec Tx/Rx activities | ||
257 | */ | ||
258 | static inline u8 get_blink_rate(struct iwl_priv *priv) | ||
259 | { | ||
260 | int index; | ||
261 | s64 tpt = priv->rxtxpackets; | ||
262 | |||
263 | if (tpt < 0) | ||
264 | tpt = -tpt; | ||
265 | |||
266 | IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt); | ||
267 | |||
268 | if (!priv->allow_blinking) | ||
269 | index = IWL_MAX_BLINK_TBL; | ||
270 | else | ||
271 | for (index = 0; index < IWL_MAX_BLINK_TBL; index++) | ||
272 | if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) | ||
273 | break; | ||
274 | |||
275 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index); | ||
276 | return index; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * this function called from handler. Since setting Led command can | ||
281 | * happen very frequent we postpone led command to be called from | ||
282 | * REPLY handler so we know ucode is up | ||
283 | */ | ||
284 | void iwl3945_led_background(struct iwl_priv *priv) | ||
285 | { | ||
286 | u8 blink_idx; | ||
287 | |||
288 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
289 | priv->last_blink_time = 0; | ||
290 | return; | ||
291 | } | ||
292 | if (iwl_is_rfkill(priv)) { | ||
293 | priv->last_blink_time = 0; | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | if (!priv->allow_blinking) { | ||
298 | priv->last_blink_time = 0; | ||
299 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { | ||
300 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; | ||
301 | iwl3945_led_pattern(priv, IWL_LED_LINK, | ||
302 | IWL_SOLID_BLINK_IDX); | ||
303 | } | ||
304 | return; | ||
305 | } | ||
306 | if (!priv->last_blink_time || | ||
307 | !time_after(jiffies, priv->last_blink_time + | ||
308 | msecs_to_jiffies(1000))) | ||
309 | return; | ||
310 | |||
311 | blink_idx = get_blink_rate(priv); | ||
312 | |||
313 | /* call only if blink rate change */ | ||
314 | if (blink_idx != priv->last_blink_rate) | ||
315 | iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx); | ||
316 | |||
317 | priv->last_blink_time = jiffies; | ||
318 | priv->last_blink_rate = blink_idx; | ||
319 | priv->rxtxpackets = 0; | ||
320 | } | ||
321 | |||
322 | |||
323 | /* Register all led handler */ | ||
324 | int iwl3945_led_register(struct iwl_priv *priv) | ||
325 | { | ||
326 | char *trigger; | ||
327 | int ret; | ||
328 | |||
329 | priv->last_blink_rate = 0; | ||
330 | priv->rxtxpackets = 0; | ||
331 | priv->led_tpt = 0; | ||
332 | priv->last_blink_time = 0; | ||
333 | priv->allow_blinking = 0; | ||
334 | |||
335 | trigger = ieee80211_get_radio_led_name(priv->hw); | ||
336 | snprintf(priv->led[IWL_LED_TRG_RADIO].name, | ||
337 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", | ||
338 | wiphy_name(priv->hw->wiphy)); | ||
339 | |||
340 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; | ||
341 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; | ||
342 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | ||
343 | |||
344 | ret = iwl3945_led_register_led(priv, | ||
345 | &priv->led[IWL_LED_TRG_RADIO], | ||
346 | IWL_LED_TRG_RADIO, 1, trigger); | ||
347 | |||
348 | if (ret) | ||
349 | goto exit_fail; | ||
350 | |||
351 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
352 | snprintf(priv->led[IWL_LED_TRG_ASSOC].name, | ||
353 | sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", | ||
354 | wiphy_name(priv->hw->wiphy)); | ||
355 | |||
356 | ret = iwl3945_led_register_led(priv, | ||
357 | &priv->led[IWL_LED_TRG_ASSOC], | ||
358 | IWL_LED_TRG_ASSOC, 0, trigger); | ||
359 | |||
360 | /* for assoc always turn led on */ | ||
361 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate; | ||
362 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate; | ||
363 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; | ||
364 | |||
365 | if (ret) | ||
366 | goto exit_fail; | ||
367 | |||
368 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
369 | snprintf(priv->led[IWL_LED_TRG_RX].name, | ||
370 | sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", | ||
371 | wiphy_name(priv->hw->wiphy)); | ||
372 | |||
373 | ret = iwl3945_led_register_led(priv, | ||
374 | &priv->led[IWL_LED_TRG_RX], | ||
375 | IWL_LED_TRG_RX, 0, trigger); | ||
376 | |||
377 | priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; | ||
378 | priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; | ||
379 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; | ||
380 | |||
381 | if (ret) | ||
382 | goto exit_fail; | ||
383 | |||
384 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
385 | snprintf(priv->led[IWL_LED_TRG_TX].name, | ||
386 | sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", | ||
387 | wiphy_name(priv->hw->wiphy)); | ||
388 | |||
389 | ret = iwl3945_led_register_led(priv, | ||
390 | &priv->led[IWL_LED_TRG_TX], | ||
391 | IWL_LED_TRG_TX, 0, trigger); | ||
392 | |||
393 | priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; | ||
394 | priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; | ||
395 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; | ||
396 | |||
397 | if (ret) | ||
398 | goto exit_fail; | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | exit_fail: | ||
403 | iwl3945_led_unregister(priv); | ||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | |||
408 | /* unregister led class */ | ||
409 | static void iwl3945_led_unregister_led(struct iwl_led *led, u8 set_led) | ||
410 | { | ||
411 | if (!led->registered) | ||
412 | return; | ||
413 | |||
414 | led_classdev_unregister(&led->led_dev); | ||
415 | |||
416 | if (set_led) | ||
417 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
418 | led->registered = 0; | ||
419 | } | ||
420 | |||
421 | /* Unregister all led handlers */ | ||
422 | void iwl3945_led_unregister(struct iwl_priv *priv) | ||
423 | { | ||
424 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); | ||
425 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); | ||
426 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); | ||
427 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); | ||
428 | } | ||
429 | |||
430 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 3b65642258ca..ce990adc51e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -24,23 +24,9 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #ifndef IWL3945_LEDS_H | 27 | #ifndef __iwl_3945_led_h__ |
28 | #define IWL3945_LEDS_H | 28 | #define __iwl_3945_led_h__ |
29 | 29 | ||
30 | struct iwl_priv; | 30 | extern const struct iwl_led_ops iwl3945_led_ops; |
31 | 31 | ||
32 | #ifdef CONFIG_IWLWIFI_LEDS | 32 | #endif /* __iwl_3945_led_h__ */ |
33 | |||
34 | #include "iwl-led.h" | ||
35 | |||
36 | extern int iwl3945_led_register(struct iwl_priv *priv); | ||
37 | extern void iwl3945_led_unregister(struct iwl_priv *priv); | ||
38 | extern void iwl3945_led_background(struct iwl_priv *priv); | ||
39 | |||
40 | #else | ||
41 | static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } | ||
42 | static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} | ||
43 | static inline void iwl3945_led_background(struct iwl_priv *priv) {} | ||
44 | |||
45 | #endif /* IWLWIFI_LEDS*/ | ||
46 | #endif /* IWL3945_LEDS_H */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index cbb0585083a9..902c4d4293e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/wireless.h> | 31 | #include <linux/wireless.h> |
31 | #include <net/mac80211.h> | 32 | #include <net/mac80211.h> |
32 | 33 | ||
@@ -42,38 +43,6 @@ | |||
42 | 43 | ||
43 | #define RS_NAME "iwl-3945-rs" | 44 | #define RS_NAME "iwl-3945-rs" |
44 | 45 | ||
45 | struct iwl3945_rate_scale_data { | ||
46 | u64 data; | ||
47 | s32 success_counter; | ||
48 | s32 success_ratio; | ||
49 | s32 counter; | ||
50 | s32 average_tpt; | ||
51 | unsigned long stamp; | ||
52 | }; | ||
53 | |||
54 | struct iwl3945_rs_sta { | ||
55 | spinlock_t lock; | ||
56 | struct iwl_priv *priv; | ||
57 | s32 *expected_tpt; | ||
58 | unsigned long last_partial_flush; | ||
59 | unsigned long last_flush; | ||
60 | u32 flush_time; | ||
61 | u32 last_tx_packets; | ||
62 | u32 tx_packets; | ||
63 | u8 tgg; | ||
64 | u8 flush_pending; | ||
65 | u8 start_rate; | ||
66 | u8 ibss_sta_added; | ||
67 | struct timer_list rate_scale_flush; | ||
68 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; | ||
69 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
70 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
71 | #endif | ||
72 | |||
73 | /* used to be in sta_info */ | ||
74 | int last_txrate_idx; | ||
75 | }; | ||
76 | |||
77 | static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = { | 46 | static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = { |
78 | 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 | 47 | 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 |
79 | }; | 48 | }; |
@@ -370,6 +339,28 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
370 | 339 | ||
371 | IWL_DEBUG_RATE(priv, "enter\n"); | 340 | IWL_DEBUG_RATE(priv, "enter\n"); |
372 | 341 | ||
342 | spin_lock_init(&rs_sta->lock); | ||
343 | |||
344 | rs_sta->priv = priv; | ||
345 | |||
346 | rs_sta->start_rate = IWL_RATE_INVALID; | ||
347 | |||
348 | /* default to just 802.11b */ | ||
349 | rs_sta->expected_tpt = iwl3945_expected_tpt_b; | ||
350 | |||
351 | rs_sta->last_partial_flush = jiffies; | ||
352 | rs_sta->last_flush = jiffies; | ||
353 | rs_sta->flush_time = IWL_RATE_FLUSH; | ||
354 | rs_sta->last_tx_packets = 0; | ||
355 | rs_sta->ibss_sta_added = 0; | ||
356 | |||
357 | init_timer(&rs_sta->rate_scale_flush); | ||
358 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; | ||
359 | rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush; | ||
360 | |||
361 | for (i = 0; i < IWL_RATE_COUNT_3945; i++) | ||
362 | iwl3945_clear_window(&rs_sta->win[i]); | ||
363 | |||
373 | /* TODO: what is a good starting rate for STA? About middle? Maybe not | 364 | /* TODO: what is a good starting rate for STA? About middle? Maybe not |
374 | * the lowest or the highest rate.. Could consider using RSSI from | 365 | * the lowest or the highest rate.. Could consider using RSSI from |
375 | * previous packets? Need to have IEEE 802.1X auth succeed immediately | 366 | * previous packets? Need to have IEEE 802.1X auth succeed immediately |
@@ -409,45 +400,11 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) | |||
409 | { | 400 | { |
410 | struct iwl3945_rs_sta *rs_sta; | 401 | struct iwl3945_rs_sta *rs_sta; |
411 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | 402 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; |
412 | struct iwl_priv *priv = iwl_priv; | 403 | struct iwl_priv *priv __maybe_unused = iwl_priv; |
413 | int i; | ||
414 | |||
415 | /* | ||
416 | * XXX: If it's using sta->drv_priv anyway, it might | ||
417 | * as well just put all the information there. | ||
418 | */ | ||
419 | 404 | ||
420 | IWL_DEBUG_RATE(priv, "enter\n"); | 405 | IWL_DEBUG_RATE(priv, "enter\n"); |
421 | 406 | ||
422 | rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); | 407 | rs_sta = &psta->rs_sta; |
423 | if (!rs_sta) { | ||
424 | IWL_DEBUG_RATE(priv, "leave: ENOMEM\n"); | ||
425 | return NULL; | ||
426 | } | ||
427 | |||
428 | psta->rs_sta = rs_sta; | ||
429 | |||
430 | spin_lock_init(&rs_sta->lock); | ||
431 | |||
432 | rs_sta->priv = priv; | ||
433 | |||
434 | rs_sta->start_rate = IWL_RATE_INVALID; | ||
435 | |||
436 | /* default to just 802.11b */ | ||
437 | rs_sta->expected_tpt = iwl3945_expected_tpt_b; | ||
438 | |||
439 | rs_sta->last_partial_flush = jiffies; | ||
440 | rs_sta->last_flush = jiffies; | ||
441 | rs_sta->flush_time = IWL_RATE_FLUSH; | ||
442 | rs_sta->last_tx_packets = 0; | ||
443 | rs_sta->ibss_sta_added = 0; | ||
444 | |||
445 | init_timer(&rs_sta->rate_scale_flush); | ||
446 | rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; | ||
447 | rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; | ||
448 | |||
449 | for (i = 0; i < IWL_RATE_COUNT_3945; i++) | ||
450 | iwl3945_clear_window(&rs_sta->win[i]); | ||
451 | 408 | ||
452 | IWL_DEBUG_RATE(priv, "leave\n"); | 409 | IWL_DEBUG_RATE(priv, "leave\n"); |
453 | 410 | ||
@@ -458,14 +415,11 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, | |||
458 | void *priv_sta) | 415 | void *priv_sta) |
459 | { | 416 | { |
460 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; | 417 | struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; |
461 | struct iwl3945_rs_sta *rs_sta = priv_sta; | 418 | struct iwl3945_rs_sta *rs_sta = &psta->rs_sta; |
462 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; | 419 | struct iwl_priv *priv __maybe_unused = rs_sta->priv; |
463 | 420 | ||
464 | psta->rs_sta = NULL; | ||
465 | |||
466 | IWL_DEBUG_RATE(priv, "enter\n"); | 421 | IWL_DEBUG_RATE(priv, "enter\n"); |
467 | del_timer_sync(&rs_sta->rate_scale_flush); | 422 | del_timer_sync(&rs_sta->rate_scale_flush); |
468 | kfree(rs_sta); | ||
469 | IWL_DEBUG_RATE(priv, "leave\n"); | 423 | IWL_DEBUG_RATE(priv, "leave\n"); |
470 | } | 424 | } |
471 | 425 | ||
@@ -960,14 +914,15 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | |||
960 | 914 | ||
961 | rcu_read_lock(); | 915 | rcu_read_lock(); |
962 | 916 | ||
963 | sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); | 917 | sta = ieee80211_find_sta(priv->vif, |
918 | priv->stations[sta_id].sta.sta.addr); | ||
964 | if (!sta) { | 919 | if (!sta) { |
965 | rcu_read_unlock(); | 920 | rcu_read_unlock(); |
966 | return; | 921 | return; |
967 | } | 922 | } |
968 | 923 | ||
969 | psta = (void *) sta->drv_priv; | 924 | psta = (void *) sta->drv_priv; |
970 | rs_sta = psta->rs_sta; | 925 | rs_sta = &psta->rs_sta; |
971 | 926 | ||
972 | spin_lock_irqsave(&rs_sta->lock, flags); | 927 | spin_lock_irqsave(&rs_sta->lock, flags); |
973 | 928 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f059b49dc691..0728054a22d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
31 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
32 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
@@ -45,9 +46,10 @@ | |||
45 | #include "iwl-sta.h" | 46 | #include "iwl-sta.h" |
46 | #include "iwl-3945.h" | 47 | #include "iwl-3945.h" |
47 | #include "iwl-eeprom.h" | 48 | #include "iwl-eeprom.h" |
48 | #include "iwl-helpers.h" | ||
49 | #include "iwl-core.h" | 49 | #include "iwl-core.h" |
50 | #include "iwl-agn-rs.h" | 50 | #include "iwl-helpers.h" |
51 | #include "iwl-led.h" | ||
52 | #include "iwl-3945-led.h" | ||
51 | 53 | ||
52 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ | 54 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ |
53 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 55 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
@@ -183,7 +185,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) | |||
183 | { | 185 | { |
184 | int idx; | 186 | int idx; |
185 | 187 | ||
186 | for (idx = 0; idx < IWL_RATE_COUNT; idx++) | 188 | for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++) |
187 | if (iwl3945_rates[idx].plcp == plcp) | 189 | if (iwl3945_rates[idx].plcp == plcp) |
188 | return idx; | 190 | return idx; |
189 | return -1; | 191 | return -1; |
@@ -293,7 +295,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | |||
293 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | 295 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, |
294 | struct iwl_rx_mem_buffer *rxb) | 296 | struct iwl_rx_mem_buffer *rxb) |
295 | { | 297 | { |
296 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 298 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
297 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 299 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
298 | int txq_id = SEQ_TO_QUEUE(sequence); | 300 | int txq_id = SEQ_TO_QUEUE(sequence); |
299 | int index = SEQ_TO_INDEX(sequence); | 301 | int index = SEQ_TO_INDEX(sequence); |
@@ -353,16 +355,12 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
353 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 355 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
354 | struct iwl_rx_mem_buffer *rxb) | 356 | struct iwl_rx_mem_buffer *rxb) |
355 | { | 357 | { |
356 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 358 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
357 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 359 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
358 | (int)sizeof(struct iwl3945_notif_statistics), | 360 | (int)sizeof(struct iwl3945_notif_statistics), |
359 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 361 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
360 | 362 | ||
361 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 363 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); |
362 | |||
363 | iwl3945_led_background(priv); | ||
364 | |||
365 | priv->last_statistics_time = jiffies; | ||
366 | } | 364 | } |
367 | 365 | ||
368 | /****************************************************************************** | 366 | /****************************************************************************** |
@@ -545,14 +543,18 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
545 | struct iwl_rx_mem_buffer *rxb, | 543 | struct iwl_rx_mem_buffer *rxb, |
546 | struct ieee80211_rx_status *stats) | 544 | struct ieee80211_rx_status *stats) |
547 | { | 545 | { |
548 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 546 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
549 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 547 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
550 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 548 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
551 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 549 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
552 | short len = le16_to_cpu(rx_hdr->len); | 550 | u16 len = le16_to_cpu(rx_hdr->len); |
551 | struct sk_buff *skb; | ||
552 | int ret; | ||
553 | __le16 fc = hdr->frame_control; | ||
553 | 554 | ||
554 | /* We received data from the HW, so stop the watchdog */ | 555 | /* We received data from the HW, so stop the watchdog */ |
555 | if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { | 556 | if (unlikely(len + IWL39_RX_FRAME_SIZE > |
557 | PAGE_SIZE << priv->hw_params.rx_page_order)) { | ||
556 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); | 558 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); |
557 | return; | 559 | return; |
558 | } | 560 | } |
@@ -564,24 +566,50 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
564 | return; | 566 | return; |
565 | } | 567 | } |
566 | 568 | ||
567 | skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt); | 569 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); |
568 | /* Set the size of the skb to the size of the frame */ | 570 | if (!skb) { |
569 | skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); | 571 | IWL_ERR(priv, "alloc_skb failed\n"); |
572 | return; | ||
573 | } | ||
570 | 574 | ||
571 | if (!iwl3945_mod_params.sw_crypto) | 575 | if (!iwl3945_mod_params.sw_crypto) |
572 | iwl_set_decrypted_flag(priv, | 576 | iwl_set_decrypted_flag(priv, |
573 | (struct ieee80211_hdr *)rxb->skb->data, | 577 | (struct ieee80211_hdr *)rxb_addr(rxb), |
574 | le32_to_cpu(rx_end->status), stats); | 578 | le32_to_cpu(rx_end->status), stats); |
575 | 579 | ||
576 | #ifdef CONFIG_IWLWIFI_LEDS | 580 | skb_reserve(skb, IWL_LINK_HDR_MAX); |
577 | if (ieee80211_is_data(hdr->frame_control)) | 581 | skb_add_rx_frag(skb, 0, rxb->page, |
578 | priv->rxtxpackets += len; | 582 | (void *)rx_hdr->payload - (void *)pkt, len); |
579 | #endif | 583 | |
580 | iwl_update_stats(priv, false, hdr->frame_control, len); | 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); | ||
607 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
581 | 608 | ||
582 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 609 | ieee80211_rx(priv->hw, skb); |
583 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); | 610 | out: |
584 | rxb->skb = NULL; | 611 | priv->alloc_rxb_page--; |
612 | rxb->page = NULL; | ||
585 | } | 613 | } |
586 | 614 | ||
587 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | 615 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) |
@@ -591,7 +619,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
591 | { | 619 | { |
592 | struct ieee80211_hdr *header; | 620 | struct ieee80211_hdr *header; |
593 | struct ieee80211_rx_status rx_status; | 621 | struct ieee80211_rx_status rx_status; |
594 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 622 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
595 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 623 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
596 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 624 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
597 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 625 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
@@ -654,19 +682,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
654 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | 682 | snr = rx_stats_sig_avg / rx_stats_noise_diff; |
655 | rx_status.noise = rx_status.signal - | 683 | rx_status.noise = rx_status.signal - |
656 | iwl3945_calc_db_from_ratio(snr); | 684 | iwl3945_calc_db_from_ratio(snr); |
657 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, | ||
658 | rx_status.noise); | ||
659 | |||
660 | /* If noise info not available, calculate signal quality indicator (%) | ||
661 | * using just the dBm signal level. */ | ||
662 | } else { | 685 | } else { |
663 | rx_status.noise = priv->last_rx_noise; | 686 | rx_status.noise = priv->last_rx_noise; |
664 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); | ||
665 | } | 687 | } |
666 | 688 | ||
667 | 689 | ||
668 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", | 690 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", |
669 | rx_status.signal, rx_status.noise, rx_status.qual, | 691 | rx_status.signal, rx_status.noise, |
670 | rx_stats_sig_avg, rx_stats_noise_diff); | 692 | rx_stats_sig_avg, rx_stats_noise_diff); |
671 | 693 | ||
672 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 694 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
@@ -784,36 +806,38 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
784 | int sta_id, int tx_id) | 806 | int sta_id, int tx_id) |
785 | { | 807 | { |
786 | u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; | 808 | u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; |
787 | u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); | 809 | u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945); |
788 | u16 rate_mask; | 810 | u16 rate_mask; |
789 | int rate; | 811 | int rate; |
790 | u8 rts_retry_limit; | 812 | u8 rts_retry_limit; |
791 | u8 data_retry_limit; | 813 | u8 data_retry_limit; |
792 | __le32 tx_flags; | 814 | __le32 tx_flags; |
793 | __le16 fc = hdr->frame_control; | 815 | __le16 fc = hdr->frame_control; |
794 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 816 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
795 | 817 | ||
796 | rate = iwl3945_rates[rate_index].plcp; | 818 | rate = iwl3945_rates[rate_index].plcp; |
797 | tx_flags = tx->tx_flags; | 819 | tx_flags = tx_cmd->tx_flags; |
798 | 820 | ||
799 | /* We need to figure out how to get the sta->supp_rates while | 821 | /* We need to figure out how to get the sta->supp_rates while |
800 | * in this running context */ | 822 | * in this running context */ |
801 | rate_mask = IWL_RATES_MASK; | 823 | rate_mask = IWL_RATES_MASK; |
802 | 824 | ||
825 | |||
826 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
827 | if (ieee80211_is_probe_resp(fc)) | ||
828 | data_retry_limit = 3; | ||
829 | else | ||
830 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
831 | tx_cmd->data_retry_limit = data_retry_limit; | ||
832 | |||
803 | if (tx_id >= IWL_CMD_QUEUE_NUM) | 833 | if (tx_id >= IWL_CMD_QUEUE_NUM) |
804 | rts_retry_limit = 3; | 834 | rts_retry_limit = 3; |
805 | else | 835 | else |
806 | rts_retry_limit = 7; | 836 | rts_retry_limit = 7; |
807 | 837 | ||
808 | if (ieee80211_is_probe_resp(fc)) { | 838 | if (data_retry_limit < rts_retry_limit) |
809 | data_retry_limit = 3; | 839 | rts_retry_limit = data_retry_limit; |
810 | if (data_retry_limit < rts_retry_limit) | 840 | tx_cmd->rts_retry_limit = rts_retry_limit; |
811 | rts_retry_limit = data_retry_limit; | ||
812 | } else | ||
813 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
814 | |||
815 | if (priv->data_retry_limit != -1) | ||
816 | data_retry_limit = priv->data_retry_limit; | ||
817 | 841 | ||
818 | if (ieee80211_is_mgmt(fc)) { | 842 | if (ieee80211_is_mgmt(fc)) { |
819 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | 843 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { |
@@ -831,22 +855,20 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
831 | } | 855 | } |
832 | } | 856 | } |
833 | 857 | ||
834 | tx->rts_retry_limit = rts_retry_limit; | 858 | tx_cmd->rate = rate; |
835 | tx->data_retry_limit = data_retry_limit; | 859 | tx_cmd->tx_flags = tx_flags; |
836 | tx->rate = rate; | ||
837 | tx->tx_flags = tx_flags; | ||
838 | 860 | ||
839 | /* OFDM */ | 861 | /* OFDM */ |
840 | tx->supp_rates[0] = | 862 | tx_cmd->supp_rates[0] = |
841 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; | 863 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; |
842 | 864 | ||
843 | /* CCK */ | 865 | /* CCK */ |
844 | tx->supp_rates[1] = (rate_mask & 0xF); | 866 | tx_cmd->supp_rates[1] = (rate_mask & 0xF); |
845 | 867 | ||
846 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " | 868 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " |
847 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, | 869 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, |
848 | tx->rate, le32_to_cpu(tx->tx_flags), | 870 | tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags), |
849 | tx->supp_rates[1], tx->supp_rates[0]); | 871 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
850 | } | 872 | } |
851 | 873 | ||
852 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) | 874 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) |
@@ -962,6 +984,11 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
962 | 984 | ||
963 | iwl3945_hw_txq_ctx_free(priv); | 985 | iwl3945_hw_txq_ctx_free(priv); |
964 | 986 | ||
987 | /* allocate tx queue structure */ | ||
988 | rc = iwl_alloc_txq_mem(priv); | ||
989 | if (rc) | ||
990 | return rc; | ||
991 | |||
965 | /* Tx CMD queue */ | 992 | /* Tx CMD queue */ |
966 | rc = iwl3945_tx_reset(priv); | 993 | rc = iwl3945_tx_reset(priv); |
967 | if (rc) | 994 | if (rc) |
@@ -986,41 +1013,25 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
986 | return rc; | 1013 | return rc; |
987 | } | 1014 | } |
988 | 1015 | ||
1016 | |||
1017 | /* | ||
1018 | * Start up 3945's basic functionality after it has been reset | ||
1019 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
1020 | * NOTE: This does not load uCode nor start the embedded processor | ||
1021 | */ | ||
989 | static int iwl3945_apm_init(struct iwl_priv *priv) | 1022 | static int iwl3945_apm_init(struct iwl_priv *priv) |
990 | { | 1023 | { |
991 | int ret; | 1024 | int ret = iwl_apm_init(priv); |
992 | |||
993 | iwl_power_initialize(priv); | ||
994 | |||
995 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
996 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
997 | 1025 | ||
998 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | 1026 | /* Clear APMG (NIC's internal power management) interrupts */ |
999 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | 1027 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); |
1000 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | 1028 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); |
1001 | |||
1002 | /* set "initialization complete" bit to move adapter | ||
1003 | * D0U* --> D0A* state */ | ||
1004 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1005 | |||
1006 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
1007 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1008 | if (ret < 0) { | ||
1009 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
1010 | goto out; | ||
1011 | } | ||
1012 | |||
1013 | /* enable DMA */ | ||
1014 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
1015 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1016 | |||
1017 | udelay(20); | ||
1018 | 1029 | ||
1019 | /* disable L1-Active */ | 1030 | /* Reset radio chip */ |
1020 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | 1031 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); |
1021 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1032 | udelay(5); |
1033 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); | ||
1022 | 1034 | ||
1023 | out: | ||
1024 | return ret; | 1035 | return ret; |
1025 | } | 1036 | } |
1026 | 1037 | ||
@@ -1145,12 +1156,16 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) | |||
1145 | int txq_id; | 1156 | int txq_id; |
1146 | 1157 | ||
1147 | /* Tx queues */ | 1158 | /* Tx queues */ |
1148 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 1159 | if (priv->txq) |
1149 | if (txq_id == IWL_CMD_QUEUE_NUM) | 1160 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; |
1150 | iwl_cmd_queue_free(priv); | 1161 | txq_id++) |
1151 | else | 1162 | if (txq_id == IWL_CMD_QUEUE_NUM) |
1152 | iwl_tx_queue_free(priv, txq_id); | 1163 | iwl_cmd_queue_free(priv); |
1164 | else | ||
1165 | iwl_tx_queue_free(priv, txq_id); | ||
1153 | 1166 | ||
1167 | /* free tx queue structure */ | ||
1168 | iwl_free_txq_mem(priv); | ||
1154 | } | 1169 | } |
1155 | 1170 | ||
1156 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | 1171 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) |
@@ -1159,6 +1174,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1159 | 1174 | ||
1160 | /* stop SCD */ | 1175 | /* stop SCD */ |
1161 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); | 1176 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); |
1177 | iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0); | ||
1162 | 1178 | ||
1163 | /* reset TFD queues */ | 1179 | /* reset TFD queues */ |
1164 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 1180 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
@@ -1171,85 +1187,6 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1171 | iwl3945_hw_txq_ctx_free(priv); | 1187 | iwl3945_hw_txq_ctx_free(priv); |
1172 | } | 1188 | } |
1173 | 1189 | ||
1174 | static int iwl3945_apm_stop_master(struct iwl_priv *priv) | ||
1175 | { | ||
1176 | int ret = 0; | ||
1177 | unsigned long flags; | ||
1178 | |||
1179 | spin_lock_irqsave(&priv->lock, flags); | ||
1180 | |||
1181 | /* set stop master bit */ | ||
1182 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
1183 | |||
1184 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
1185 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
1186 | |||
1187 | if (ret < 0) | ||
1188 | goto out; | ||
1189 | |||
1190 | out: | ||
1191 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1192 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
1193 | |||
1194 | return ret; | ||
1195 | } | ||
1196 | |||
1197 | static void iwl3945_apm_stop(struct iwl_priv *priv) | ||
1198 | { | ||
1199 | unsigned long flags; | ||
1200 | |||
1201 | iwl3945_apm_stop_master(priv); | ||
1202 | |||
1203 | spin_lock_irqsave(&priv->lock, flags); | ||
1204 | |||
1205 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1206 | |||
1207 | udelay(10); | ||
1208 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
1209 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1210 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1211 | } | ||
1212 | |||
1213 | static int iwl3945_apm_reset(struct iwl_priv *priv) | ||
1214 | { | ||
1215 | iwl3945_apm_stop_master(priv); | ||
1216 | |||
1217 | |||
1218 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1219 | udelay(10); | ||
1220 | |||
1221 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1222 | |||
1223 | iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
1224 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1225 | |||
1226 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, | ||
1227 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1228 | |||
1229 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); | ||
1230 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, | ||
1231 | 0xFFFFFFFF); | ||
1232 | |||
1233 | /* enable DMA */ | ||
1234 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1235 | APMG_CLK_VAL_DMA_CLK_RQT | | ||
1236 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1237 | udelay(10); | ||
1238 | |||
1239 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, | ||
1240 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
1241 | udelay(5); | ||
1242 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, | ||
1243 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
1244 | |||
1245 | /* Clear the 'host command active' bit... */ | ||
1246 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
1247 | |||
1248 | wake_up_interruptible(&priv->wait_command_queue); | ||
1249 | |||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | /** | 1190 | /** |
1254 | * iwl3945_hw_reg_adjust_power_by_temp | 1191 | * iwl3945_hw_reg_adjust_power_by_temp |
1255 | * return index delta into power gain settings table | 1192 | * return index delta into power gain settings table |
@@ -1858,7 +1795,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) | |||
1858 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | 1795 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) |
1859 | { | 1796 | { |
1860 | int rc = 0; | 1797 | int rc = 0; |
1861 | struct iwl_rx_packet *res = NULL; | 1798 | struct iwl_rx_packet *pkt; |
1862 | struct iwl3945_rxon_assoc_cmd rxon_assoc; | 1799 | struct iwl3945_rxon_assoc_cmd rxon_assoc; |
1863 | struct iwl_host_cmd cmd = { | 1800 | struct iwl_host_cmd cmd = { |
1864 | .id = REPLY_RXON_ASSOC, | 1801 | .id = REPLY_RXON_ASSOC, |
@@ -1887,14 +1824,13 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | |||
1887 | if (rc) | 1824 | if (rc) |
1888 | return rc; | 1825 | return rc; |
1889 | 1826 | ||
1890 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 1827 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
1891 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 1828 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
1892 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); | 1829 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); |
1893 | rc = -EIO; | 1830 | rc = -EIO; |
1894 | } | 1831 | } |
1895 | 1832 | ||
1896 | priv->alloc_rxb_skb--; | 1833 | iwl_free_pages(priv, cmd.reply_page); |
1897 | dev_kfree_skb_any(cmd.reply_skb); | ||
1898 | 1834 | ||
1899 | return rc; | 1835 | return rc; |
1900 | } | 1836 | } |
@@ -2016,11 +1952,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
2016 | } | 1952 | } |
2017 | 1953 | ||
2018 | /* Add the broadcast address so we can send broadcast frames */ | 1954 | /* Add the broadcast address so we can send broadcast frames */ |
2019 | if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) == | 1955 | priv->cfg->ops->lib->add_bcast_station(priv); |
2020 | IWL_INVALID_STATION) { | ||
2021 | IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); | ||
2022 | return -EIO; | ||
2023 | } | ||
2024 | 1956 | ||
2025 | /* If we have set the ASSOC_MSK and we are in BSS mode then | 1957 | /* If we have set the ASSOC_MSK and we are in BSS mode then |
2026 | * add the IWL_AP_ID to the station rate table */ | 1958 | * add the IWL_AP_ID to the station rate table */ |
@@ -2042,12 +1974,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
2042 | return 0; | 1974 | return 0; |
2043 | } | 1975 | } |
2044 | 1976 | ||
2045 | /* will add 3945 channel switch cmd handling later */ | ||
2046 | int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
2047 | { | ||
2048 | return 0; | ||
2049 | } | ||
2050 | |||
2051 | /** | 1977 | /** |
2052 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. | 1978 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. |
2053 | * | 1979 | * |
@@ -2221,7 +2147,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) | |||
2221 | 2147 | ||
2222 | /* fill in channel group's nominal powers for each rate */ | 2148 | /* fill in channel group's nominal powers for each rate */ |
2223 | for (rate_index = 0; | 2149 | for (rate_index = 0; |
2224 | rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { | 2150 | rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) { |
2225 | switch (rate_index) { | 2151 | switch (rate_index) { |
2226 | case IWL_RATE_36M_INDEX_TABLE: | 2152 | case IWL_RATE_36M_INDEX_TABLE: |
2227 | if (i == 0) /* B/G */ | 2153 | if (i == 0) /* B/G */ |
@@ -2545,11 +2471,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2545 | memset((void *)&priv->hw_params, 0, | 2471 | memset((void *)&priv->hw_params, 0, |
2546 | sizeof(struct iwl_hw_params)); | 2472 | sizeof(struct iwl_hw_params)); |
2547 | 2473 | ||
2548 | priv->shared_virt = | 2474 | priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, |
2549 | pci_alloc_consistent(priv->pci_dev, | 2475 | sizeof(struct iwl3945_shared), |
2550 | sizeof(struct iwl3945_shared), | 2476 | &priv->shared_phys, GFP_KERNEL); |
2551 | &priv->shared_phys); | ||
2552 | |||
2553 | if (!priv->shared_virt) { | 2477 | if (!priv->shared_virt) { |
2554 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 2478 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
2555 | mutex_unlock(&priv->mutex); | 2479 | mutex_unlock(&priv->mutex); |
@@ -2557,11 +2481,10 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2557 | } | 2481 | } |
2558 | 2482 | ||
2559 | /* Assign number of Usable TX queues */ | 2483 | /* Assign number of Usable TX queues */ |
2560 | priv->hw_params.max_txq_num = IWL39_NUM_QUEUES; | 2484 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
2561 | 2485 | ||
2562 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | 2486 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); |
2563 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; | 2487 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K); |
2564 | priv->hw_params.max_pkt_size = 2342; | ||
2565 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 2488 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
2566 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 2489 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
2567 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; | 2490 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; |
@@ -2844,8 +2767,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2844 | .dump_nic_error_log = iwl3945_dump_nic_error_log, | 2767 | .dump_nic_error_log = iwl3945_dump_nic_error_log, |
2845 | .apm_ops = { | 2768 | .apm_ops = { |
2846 | .init = iwl3945_apm_init, | 2769 | .init = iwl3945_apm_init, |
2847 | .reset = iwl3945_apm_reset, | 2770 | .stop = iwl_apm_stop, |
2848 | .stop = iwl3945_apm_stop, | ||
2849 | .config = iwl3945_nic_config, | 2771 | .config = iwl3945_nic_config, |
2850 | .set_pwr_src = iwl3945_set_pwr_src, | 2772 | .set_pwr_src = iwl3945_set_pwr_src, |
2851 | }, | 2773 | }, |
@@ -2869,18 +2791,21 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2869 | .post_associate = iwl3945_post_associate, | 2791 | .post_associate = iwl3945_post_associate, |
2870 | .isr = iwl_isr_legacy, | 2792 | .isr = iwl_isr_legacy, |
2871 | .config_ap = iwl3945_config_ap, | 2793 | .config_ap = iwl3945_config_ap, |
2794 | .add_bcast_station = iwl3945_add_bcast_station, | ||
2872 | }; | 2795 | }; |
2873 | 2796 | ||
2874 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2797 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { |
2875 | .get_hcmd_size = iwl3945_get_hcmd_size, | 2798 | .get_hcmd_size = iwl3945_get_hcmd_size, |
2876 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, | 2799 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, |
2800 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | ||
2877 | }; | 2801 | }; |
2878 | 2802 | ||
2879 | static struct iwl_ops iwl3945_ops = { | 2803 | static const struct iwl_ops iwl3945_ops = { |
2880 | .ucode = &iwl3945_ucode, | 2804 | .ucode = &iwl3945_ucode, |
2881 | .lib = &iwl3945_lib, | 2805 | .lib = &iwl3945_lib, |
2882 | .hcmd = &iwl3945_hcmd, | 2806 | .hcmd = &iwl3945_hcmd, |
2883 | .utils = &iwl3945_hcmd_utils, | 2807 | .utils = &iwl3945_hcmd_utils, |
2808 | .led = &iwl3945_led_ops, | ||
2884 | }; | 2809 | }; |
2885 | 2810 | ||
2886 | static struct iwl_cfg iwl3945_bg_cfg = { | 2811 | static struct iwl_cfg iwl3945_bg_cfg = { |
@@ -2892,9 +2817,16 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2892 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2817 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2893 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2818 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2894 | .ops = &iwl3945_ops, | 2819 | .ops = &iwl3945_ops, |
2820 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2895 | .mod_params = &iwl3945_mod_params, | 2821 | .mod_params = &iwl3945_mod_params, |
2822 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2823 | .set_l0s = false, | ||
2824 | .use_bsm = true, | ||
2896 | .use_isr_legacy = true, | 2825 | .use_isr_legacy = true, |
2897 | .ht_greenfield_support = false, | 2826 | .ht_greenfield_support = false, |
2827 | .led_compensation = 64, | ||
2828 | .broken_powersave = true, | ||
2829 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2898 | }; | 2830 | }; |
2899 | 2831 | ||
2900 | static struct iwl_cfg iwl3945_abg_cfg = { | 2832 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2906,12 +2838,16 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2906 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2838 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2907 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2839 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2908 | .ops = &iwl3945_ops, | 2840 | .ops = &iwl3945_ops, |
2841 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2909 | .mod_params = &iwl3945_mod_params, | 2842 | .mod_params = &iwl3945_mod_params, |
2910 | .use_isr_legacy = true, | 2843 | .use_isr_legacy = true, |
2911 | .ht_greenfield_support = false, | 2844 | .ht_greenfield_support = false, |
2845 | .led_compensation = 64, | ||
2846 | .broken_powersave = true, | ||
2847 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2912 | }; | 2848 | }; |
2913 | 2849 | ||
2914 | struct pci_device_id iwl3945_hw_card_ids[] = { | 2850 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |
2915 | {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, | 2851 | {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, |
2916 | {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, | 2852 | {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, |
2917 | {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, | 2853 | {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 21679bf3a1aa..452dfd5456c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -37,7 +37,7 @@ | |||
37 | #include <net/ieee80211_radiotap.h> | 37 | #include <net/ieee80211_radiotap.h> |
38 | 38 | ||
39 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | 39 | /* Hardware specific file defines the PCI IDs table for that hardware module */ |
40 | extern struct pci_device_id iwl3945_hw_card_ids[]; | 40 | extern const struct pci_device_id iwl3945_hw_card_ids[]; |
41 | 41 | ||
42 | #include "iwl-csr.h" | 42 | #include "iwl-csr.h" |
43 | #include "iwl-prph.h" | 43 | #include "iwl-prph.h" |
@@ -46,7 +46,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; | |||
46 | #include "iwl-debug.h" | 46 | #include "iwl-debug.h" |
47 | #include "iwl-power.h" | 47 | #include "iwl-power.h" |
48 | #include "iwl-dev.h" | 48 | #include "iwl-dev.h" |
49 | #include "iwl-3945-led.h" | 49 | #include "iwl-led.h" |
50 | 50 | ||
51 | /* Highest firmware API version supported */ | 51 | /* Highest firmware API version supported */ |
52 | #define IWL3945_UCODE_API_MAX 2 | 52 | #define IWL3945_UCODE_API_MAX 2 |
@@ -74,8 +74,41 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; | |||
74 | /* Module parameters accessible from iwl-*.c */ | 74 | /* Module parameters accessible from iwl-*.c */ |
75 | extern struct iwl_mod_params iwl3945_mod_params; | 75 | extern struct iwl_mod_params iwl3945_mod_params; |
76 | 76 | ||
77 | struct iwl3945_rate_scale_data { | ||
78 | u64 data; | ||
79 | s32 success_counter; | ||
80 | s32 success_ratio; | ||
81 | s32 counter; | ||
82 | s32 average_tpt; | ||
83 | unsigned long stamp; | ||
84 | }; | ||
85 | |||
86 | struct iwl3945_rs_sta { | ||
87 | spinlock_t lock; | ||
88 | struct iwl_priv *priv; | ||
89 | s32 *expected_tpt; | ||
90 | unsigned long last_partial_flush; | ||
91 | unsigned long last_flush; | ||
92 | u32 flush_time; | ||
93 | u32 last_tx_packets; | ||
94 | u32 tx_packets; | ||
95 | u8 tgg; | ||
96 | u8 flush_pending; | ||
97 | u8 start_rate; | ||
98 | u8 ibss_sta_added; | ||
99 | struct timer_list rate_scale_flush; | ||
100 | struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; | ||
101 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
102 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
103 | #endif | ||
104 | |||
105 | /* used to be in sta_info */ | ||
106 | int last_txrate_idx; | ||
107 | }; | ||
108 | |||
109 | |||
77 | struct iwl3945_sta_priv { | 110 | struct iwl3945_sta_priv { |
78 | struct iwl3945_rs_sta *rs_sta; | 111 | struct iwl3945_rs_sta rs_sta; |
79 | }; | 112 | }; |
80 | 113 | ||
81 | enum iwl3945_antenna { | 114 | enum iwl3945_antenna { |
@@ -130,12 +163,6 @@ struct iwl3945_frame { | |||
130 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | 163 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) |
131 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | 164 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) |
132 | 165 | ||
133 | /* | ||
134 | * RX related structures and functions | ||
135 | */ | ||
136 | #define RX_FREE_BUFFERS 64 | ||
137 | #define RX_LOW_WATERMARK 8 | ||
138 | |||
139 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | 166 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 |
140 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | 167 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 |
141 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | 168 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 |
@@ -144,24 +171,6 @@ struct iwl3945_frame { | |||
144 | 171 | ||
145 | #define SCAN_INTERVAL 100 | 172 | #define SCAN_INTERVAL 100 |
146 | 173 | ||
147 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | ||
148 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | ||
149 | #define STATUS_INT_ENABLED 2 | ||
150 | #define STATUS_RF_KILL_HW 3 | ||
151 | #define STATUS_INIT 5 | ||
152 | #define STATUS_ALIVE 6 | ||
153 | #define STATUS_READY 7 | ||
154 | #define STATUS_TEMPERATURE 8 | ||
155 | #define STATUS_GEO_CONFIGURED 9 | ||
156 | #define STATUS_EXIT_PENDING 10 | ||
157 | #define STATUS_STATISTICS 12 | ||
158 | #define STATUS_SCANNING 13 | ||
159 | #define STATUS_SCAN_ABORTING 14 | ||
160 | #define STATUS_SCAN_HW 15 | ||
161 | #define STATUS_POWER_PMI 16 | ||
162 | #define STATUS_FW_ERROR 17 | ||
163 | #define STATUS_CONF_PENDING 18 | ||
164 | |||
165 | #define MAX_TID_COUNT 9 | 174 | #define MAX_TID_COUNT 9 |
166 | 175 | ||
167 | #define IWL_INVALID_RATE 0xFF | 176 | #define IWL_INVALID_RATE 0xFF |
@@ -194,22 +203,13 @@ struct iwl3945_ibss_seq { | |||
194 | * for use by iwl-*.c | 203 | * for use by iwl-*.c |
195 | * | 204 | * |
196 | *****************************************************************************/ | 205 | *****************************************************************************/ |
197 | extern int iwl3945_power_init_handle(struct iwl_priv *priv); | ||
198 | extern int iwl3945_eeprom_init(struct iwl_priv *priv); | ||
199 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); | 206 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); |
200 | extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); | ||
201 | extern int iwl3945_tx_queue_init(struct iwl_priv *priv, | ||
202 | struct iwl_tx_queue *txq, int count, u32 id); | ||
203 | extern void iwl3945_rx_replenish(void *data); | 207 | extern void iwl3945_rx_replenish(void *data); |
204 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 208 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
205 | extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
206 | extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, | ||
207 | const void *data); | ||
208 | extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, | ||
209 | struct iwl_host_cmd *cmd); | ||
210 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 209 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
211 | struct ieee80211_hdr *hdr,int left); | 210 | struct ieee80211_hdr *hdr,int left); |
212 | extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv); | 211 | extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
212 | char **buf, bool display); | ||
213 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | 213 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); |
214 | 214 | ||
215 | /* | 215 | /* |
@@ -280,8 +280,6 @@ extern void iwl3945_config_ap(struct iwl_priv *priv); | |||
280 | */ | 280 | */ |
281 | extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); | 281 | extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); |
282 | 282 | ||
283 | extern int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel); | ||
284 | |||
285 | /* | 283 | /* |
286 | * Forward declare iwl-3945.c functions for iwl-base.c | 284 | * Forward declare iwl-3945.c functions for iwl-base.c |
287 | */ | 285 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index b34322a32458..67ef562e8db1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -76,12 +76,9 @@ | |||
76 | 76 | ||
77 | /* | 77 | /* |
78 | * uCode queue management definitions ... | 78 | * uCode queue management definitions ... |
79 | * Queue #4 is the command queue for 3945 and 4965; map it to Tx FIFO chnl 4. | ||
80 | * The first queue used for block-ack aggregation is #7 (4965 only). | 79 | * The first queue used for block-ack aggregation is #7 (4965 only). |
81 | * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. | 80 | * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. |
82 | */ | 81 | */ |
83 | #define IWL_CMD_QUEUE_NUM 4 | ||
84 | #define IWL_CMD_FIFO_NUM 4 | ||
85 | #define IWL49_FIRST_AMPDU_QUEUE 7 | 82 | #define IWL49_FIRST_AMPDU_QUEUE 7 |
86 | 83 | ||
87 | /* Time constants */ | 84 | /* Time constants */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6f703a041847..8972166386cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -45,6 +45,7 @@ | |||
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
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 | 49 | ||
49 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 50 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
50 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 51 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); |
@@ -62,8 +63,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | |||
62 | 63 | ||
63 | /* module parameters */ | 64 | /* module parameters */ |
64 | static struct iwl_mod_params iwl4965_mod_params = { | 65 | static struct iwl_mod_params iwl4965_mod_params = { |
65 | .num_of_queues = IWL49_NUM_QUEUES, | ||
66 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
67 | .amsdu_size_8K = 1, | 66 | .amsdu_size_8K = 1, |
68 | .restart_fw = 1, | 67 | .restart_fw = 1, |
69 | /* the rest are 0 by default */ | 68 | /* the rest are 0 by default */ |
@@ -319,63 +318,13 @@ static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask) | |||
319 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); | 318 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); |
320 | } | 319 | } |
321 | 320 | ||
322 | static int iwl4965_apm_init(struct iwl_priv *priv) | ||
323 | { | ||
324 | int ret = 0; | ||
325 | |||
326 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
327 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
328 | |||
329 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
330 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
331 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
332 | |||
333 | /* set "initialization complete" bit to move adapter | ||
334 | * D0U* --> D0A* state */ | ||
335 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
336 | |||
337 | /* wait for clock stabilization */ | ||
338 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
339 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
340 | if (ret < 0) { | ||
341 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
342 | goto out; | ||
343 | } | ||
344 | |||
345 | /* enable DMA */ | ||
346 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
347 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
348 | |||
349 | udelay(20); | ||
350 | |||
351 | /* disable L1-Active */ | ||
352 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
353 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
354 | |||
355 | out: | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | |||
360 | static void iwl4965_nic_config(struct iwl_priv *priv) | 321 | static void iwl4965_nic_config(struct iwl_priv *priv) |
361 | { | 322 | { |
362 | unsigned long flags; | 323 | unsigned long flags; |
363 | u16 radio_cfg; | 324 | u16 radio_cfg; |
364 | u16 lctl; | ||
365 | 325 | ||
366 | spin_lock_irqsave(&priv->lock, flags); | 326 | spin_lock_irqsave(&priv->lock, flags); |
367 | 327 | ||
368 | lctl = iwl_pcie_link_ctl(priv); | ||
369 | |||
370 | /* HW bug W/A - negligible power consumption */ | ||
371 | /* L1-ASPM is enabled by BIOS */ | ||
372 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) | ||
373 | /* L1-ASPM enabled: disable L0S */ | ||
374 | iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
375 | else | ||
376 | /* L1-ASPM disabled: enable L0S */ | ||
377 | iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
378 | |||
379 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 328 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
380 | 329 | ||
381 | /* write radio config values to register */ | 330 | /* write radio config values to register */ |
@@ -396,79 +345,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
396 | spin_unlock_irqrestore(&priv->lock, flags); | 345 | spin_unlock_irqrestore(&priv->lock, flags); |
397 | } | 346 | } |
398 | 347 | ||
399 | static int iwl4965_apm_stop_master(struct iwl_priv *priv) | ||
400 | { | ||
401 | unsigned long flags; | ||
402 | |||
403 | spin_lock_irqsave(&priv->lock, flags); | ||
404 | |||
405 | /* set stop master bit */ | ||
406 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
407 | |||
408 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
409 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
410 | |||
411 | spin_unlock_irqrestore(&priv->lock, flags); | ||
412 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static void iwl4965_apm_stop(struct iwl_priv *priv) | ||
418 | { | ||
419 | unsigned long flags; | ||
420 | |||
421 | iwl4965_apm_stop_master(priv); | ||
422 | |||
423 | spin_lock_irqsave(&priv->lock, flags); | ||
424 | |||
425 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
426 | |||
427 | udelay(10); | ||
428 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
429 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
430 | spin_unlock_irqrestore(&priv->lock, flags); | ||
431 | } | ||
432 | |||
433 | static int iwl4965_apm_reset(struct iwl_priv *priv) | ||
434 | { | ||
435 | int ret = 0; | ||
436 | |||
437 | iwl4965_apm_stop_master(priv); | ||
438 | |||
439 | |||
440 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
441 | |||
442 | udelay(10); | ||
443 | |||
444 | /* FIXME: put here L1A -L0S w/a */ | ||
445 | |||
446 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
447 | |||
448 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
449 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
450 | if (ret < 0) | ||
451 | goto out; | ||
452 | |||
453 | udelay(10); | ||
454 | |||
455 | /* Enable DMA and BSM Clock */ | ||
456 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
457 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
458 | |||
459 | udelay(10); | ||
460 | |||
461 | /* disable L1A */ | ||
462 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
463 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
464 | |||
465 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
466 | wake_up_interruptible(&priv->wait_command_queue); | ||
467 | |||
468 | out: | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. | 348 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. |
473 | * Called after every association, but this runs only once! | 349 | * Called after every association, but this runs only once! |
474 | * ... once chain noise is calibrated the first time, it's good forever. */ | 350 | * ... once chain noise is calibrated the first time, it's good forever. */ |
@@ -496,14 +372,15 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) | |||
496 | static void iwl4965_gain_computation(struct iwl_priv *priv, | 372 | static void iwl4965_gain_computation(struct iwl_priv *priv, |
497 | u32 *average_noise, | 373 | u32 *average_noise, |
498 | u16 min_average_noise_antenna_i, | 374 | u16 min_average_noise_antenna_i, |
499 | u32 min_average_noise) | 375 | u32 min_average_noise, |
376 | u8 default_chain) | ||
500 | { | 377 | { |
501 | int i, ret; | 378 | int i, ret; |
502 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 379 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
503 | 380 | ||
504 | data->delta_gain_code[min_average_noise_antenna_i] = 0; | 381 | data->delta_gain_code[min_average_noise_antenna_i] = 0; |
505 | 382 | ||
506 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 383 | for (i = default_chain; i < NUM_RX_CHAINS; i++) { |
507 | s32 delta_g = 0; | 384 | s32 delta_g = 0; |
508 | 385 | ||
509 | if (!(data->disconn_array[i]) && | 386 | if (!(data->disconn_array[i]) && |
@@ -557,18 +434,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
557 | data->beacon_count = 0; | 434 | data->beacon_count = 0; |
558 | } | 435 | } |
559 | 436 | ||
560 | static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
561 | __le32 *tx_flags) | ||
562 | { | ||
563 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
564 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
565 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
566 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
567 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
568 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 437 | static void iwl4965_bg_txpower_work(struct work_struct *work) |
573 | { | 438 | { |
574 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 439 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
@@ -663,7 +528,8 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
663 | iwl_write_targ_mem(priv, a, 0); | 528 | iwl_write_targ_mem(priv, a, 0); |
664 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) | 529 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) |
665 | iwl_write_targ_mem(priv, a, 0); | 530 | iwl_write_targ_mem(priv, a, 0); |
666 | for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) | 531 | for (; a < priv->scd_base_addr + |
532 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
667 | iwl_write_targ_mem(priv, a, 0); | 533 | iwl_write_targ_mem(priv, a, 0); |
668 | 534 | ||
669 | /* Tel 4965 where to find Tx byte count tables */ | 535 | /* Tel 4965 where to find Tx byte count tables */ |
@@ -715,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
715 | 581 | ||
716 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 582 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
717 | 583 | ||
584 | /* make sure all queue are not stopped */ | ||
585 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
586 | for (i = 0; i < 4; i++) | ||
587 | atomic_set(&priv->queue_stop_count[i], 0); | ||
588 | |||
589 | /* reset to 0 to enable all the queue first */ | ||
590 | priv->txq_ctx_active_msk = 0; | ||
718 | /* Map each Tx/cmd queue to its corresponding fifo */ | 591 | /* Map each Tx/cmd queue to its corresponding fifo */ |
719 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 592 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
720 | int ac = default_queue_to_tx_fifo[i]; | 593 | int ac = default_queue_to_tx_fifo[i]; |
@@ -748,6 +621,10 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = { | |||
748 | 621 | ||
749 | .nrg_th_cck = 100, | 622 | .nrg_th_cck = 100, |
750 | .nrg_th_ofdm = 100, | 623 | .nrg_th_ofdm = 100, |
624 | |||
625 | .barker_corr_th_min = 190, | ||
626 | .barker_corr_th_min_mrc = 390, | ||
627 | .nrg_th_cca = 62, | ||
751 | }; | 628 | }; |
752 | 629 | ||
753 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | 630 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) |
@@ -764,19 +641,16 @@ static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | |||
764 | */ | 641 | */ |
765 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | 642 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) |
766 | { | 643 | { |
644 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
645 | priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES) | ||
646 | priv->cfg->num_of_queues = | ||
647 | priv->cfg->mod_params->num_of_queues; | ||
767 | 648 | ||
768 | if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || | 649 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
769 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | ||
770 | IWL_ERR(priv, | ||
771 | "invalid queues_num, should be between %d and %d\n", | ||
772 | IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES); | ||
773 | return -EINVAL; | ||
774 | } | ||
775 | |||
776 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | ||
777 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | 650 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; |
778 | priv->hw_params.scd_bc_tbls_size = | 651 | priv->hw_params.scd_bc_tbls_size = |
779 | IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); | 652 | priv->cfg->num_of_queues * |
653 | sizeof(struct iwl4965_scd_bc_tbl); | ||
780 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 654 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
781 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 655 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
782 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; | 656 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
@@ -787,10 +661,10 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
787 | 661 | ||
788 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | 662 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; |
789 | 663 | ||
790 | priv->hw_params.tx_chains_num = 2; | 664 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
791 | priv->hw_params.rx_chains_num = 2; | 665 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); |
792 | priv->hw_params.valid_tx_ant = ANT_A | ANT_B; | 666 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; |
793 | priv->hw_params.valid_rx_ant = ANT_A | ANT_B; | 667 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; |
794 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | 668 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) |
795 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | 669 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); |
796 | 670 | ||
@@ -1337,7 +1211,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, | |||
1337 | iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); | 1211 | iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); |
1338 | 1212 | ||
1339 | /* calculate tx gain adjustment based on power supply voltage */ | 1213 | /* calculate tx gain adjustment based on power supply voltage */ |
1340 | voltage = priv->calib_info->voltage; | 1214 | voltage = le16_to_cpu(priv->calib_info->voltage); |
1341 | init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); | 1215 | init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); |
1342 | voltage_compensation = | 1216 | voltage_compensation = |
1343 | iwl4965_get_voltage_compensation(voltage, init_voltage); | 1217 | iwl4965_get_voltage_compensation(voltage, init_voltage); |
@@ -1567,14 +1441,13 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | |||
1567 | return ret; | 1441 | return ret; |
1568 | } | 1442 | } |
1569 | 1443 | ||
1570 | #ifdef IEEE80211_CONF_CHANNEL_SWITCH | ||
1571 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 1444 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
1572 | { | 1445 | { |
1573 | int rc; | 1446 | int rc; |
1574 | u8 band = 0; | 1447 | u8 band = 0; |
1575 | bool is_ht40 = false; | 1448 | bool is_ht40 = false; |
1576 | u8 ctrl_chan_high = 0; | 1449 | u8 ctrl_chan_high = 0; |
1577 | struct iwl4965_channel_switch_cmd cmd = { 0 }; | 1450 | struct iwl4965_channel_switch_cmd cmd; |
1578 | const struct iwl_channel_info *ch_info; | 1451 | const struct iwl_channel_info *ch_info; |
1579 | 1452 | ||
1580 | band = priv->band == IEEE80211_BAND_2GHZ; | 1453 | band = priv->band == IEEE80211_BAND_2GHZ; |
@@ -1584,19 +1457,22 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1584 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); | 1457 | is_ht40 = is_ht40_channel(priv->staging_rxon.flags); |
1585 | 1458 | ||
1586 | if (is_ht40 && | 1459 | if (is_ht40 && |
1587 | (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) | 1460 | (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) |
1588 | ctrl_chan_high = 1; | 1461 | ctrl_chan_high = 1; |
1589 | 1462 | ||
1590 | cmd.band = band; | 1463 | cmd.band = band; |
1591 | cmd.expect_beacon = 0; | 1464 | cmd.expect_beacon = 0; |
1592 | cmd.channel = cpu_to_le16(channel); | 1465 | cmd.channel = cpu_to_le16(channel); |
1593 | cmd.rxon_flags = priv->active_rxon.flags; | 1466 | cmd.rxon_flags = priv->staging_rxon.flags; |
1594 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | 1467 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
1595 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1468 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); |
1596 | if (ch_info) | 1469 | if (ch_info) |
1597 | cmd.expect_beacon = is_channel_radar(ch_info); | 1470 | cmd.expect_beacon = is_channel_radar(ch_info); |
1598 | else | 1471 | else { |
1599 | cmd.expect_beacon = 1; | 1472 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
1473 | priv->active_rxon.channel, channel); | ||
1474 | return -EFAULT; | ||
1475 | } | ||
1600 | 1476 | ||
1601 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, | 1477 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, |
1602 | ctrl_chan_high, &cmd.tx_power); | 1478 | ctrl_chan_high, &cmd.tx_power); |
@@ -1605,10 +1481,11 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1605 | return rc; | 1481 | return rc; |
1606 | } | 1482 | } |
1607 | 1483 | ||
1608 | rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | 1484 | priv->switch_rxon.channel = cpu_to_le16(channel); |
1609 | return rc; | 1485 | priv->switch_rxon.switch_in_progress = true; |
1486 | |||
1487 | return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | ||
1610 | } | 1488 | } |
1611 | #endif | ||
1612 | 1489 | ||
1613 | /** | 1490 | /** |
1614 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 1491 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
@@ -1805,11 +1682,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1805 | u16 ssn_idx, u8 tx_fifo) | 1682 | u16 ssn_idx, u8 tx_fifo) |
1806 | { | 1683 | { |
1807 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1684 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1808 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { | 1685 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
1686 | <= txq_id)) { | ||
1809 | IWL_WARN(priv, | 1687 | IWL_WARN(priv, |
1810 | "queue number out of range: %d, must be %d to %d\n", | 1688 | "queue number out of range: %d, must be %d to %d\n", |
1811 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1689 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1812 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | 1690 | IWL49_FIRST_AMPDU_QUEUE + |
1691 | priv->cfg->num_of_ampdu_queues - 1); | ||
1813 | return -EINVAL; | 1692 | return -EINVAL; |
1814 | } | 1693 | } |
1815 | 1694 | ||
@@ -1870,11 +1749,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1870 | u16 ra_tid; | 1749 | u16 ra_tid; |
1871 | 1750 | ||
1872 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1751 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1873 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { | 1752 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
1753 | <= txq_id)) { | ||
1874 | IWL_WARN(priv, | 1754 | IWL_WARN(priv, |
1875 | "queue number out of range: %d, must be %d to %d\n", | 1755 | "queue number out of range: %d, must be %d to %d\n", |
1876 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1756 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1877 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | 1757 | IWL49_FIRST_AMPDU_QUEUE + |
1758 | priv->cfg->num_of_ampdu_queues - 1); | ||
1878 | return -EINVAL; | 1759 | return -EINVAL; |
1879 | } | 1760 | } |
1880 | 1761 | ||
@@ -1944,8 +1825,9 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
1944 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; | 1825 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; |
1945 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; | 1826 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; |
1946 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; | 1827 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; |
1828 | addsta->sleep_tx_count = cmd->sleep_tx_count; | ||
1947 | addsta->reserved1 = cpu_to_le16(0); | 1829 | addsta->reserved1 = cpu_to_le16(0); |
1948 | addsta->reserved2 = cpu_to_le32(0); | 1830 | addsta->reserved2 = cpu_to_le16(0); |
1949 | 1831 | ||
1950 | return (u16)sizeof(struct iwl4965_addsta_cmd); | 1832 | return (u16)sizeof(struct iwl4965_addsta_cmd); |
1951 | } | 1833 | } |
@@ -1991,8 +1873,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1991 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 1873 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
1992 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1874 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1993 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1875 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1994 | info->flags |= iwl_is_tx_success(status) ? | 1876 | info->flags |= iwl_tx_status_to_mac80211(status); |
1995 | IEEE80211_TX_STAT_ACK : 0; | ||
1996 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1877 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
1997 | /* FIXME: code repetition end */ | 1878 | /* FIXME: code repetition end */ |
1998 | 1879 | ||
@@ -2078,7 +1959,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
2078 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | 1959 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, |
2079 | struct iwl_rx_mem_buffer *rxb) | 1960 | struct iwl_rx_mem_buffer *rxb) |
2080 | { | 1961 | { |
2081 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1962 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2082 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1963 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
2083 | int txq_id = SEQ_TO_QUEUE(sequence); | 1964 | int txq_id = SEQ_TO_QUEUE(sequence); |
2084 | int index = SEQ_TO_INDEX(sequence); | 1965 | int index = SEQ_TO_INDEX(sequence); |
@@ -2087,7 +1968,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2087 | struct ieee80211_tx_info *info; | 1968 | struct ieee80211_tx_info *info; |
2088 | struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | 1969 | struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; |
2089 | u32 status = le32_to_cpu(tx_resp->u.status); | 1970 | u32 status = le32_to_cpu(tx_resp->u.status); |
2090 | int tid = MAX_TID_COUNT; | 1971 | int uninitialized_var(tid); |
2091 | int sta_id; | 1972 | int sta_id; |
2092 | int freed; | 1973 | int freed; |
2093 | u8 *qc = NULL; | 1974 | u8 *qc = NULL; |
@@ -2134,7 +2015,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2134 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2015 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
2135 | "%d index %d\n", scd_ssn , index); | 2016 | "%d index %d\n", scd_ssn , index); |
2136 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2017 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
2137 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 2018 | if (qc) |
2019 | iwl_free_tfds_in_queue(priv, sta_id, | ||
2020 | tid, freed); | ||
2138 | 2021 | ||
2139 | if (priv->mac80211_registered && | 2022 | if (priv->mac80211_registered && |
2140 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | 2023 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && |
@@ -2147,8 +2030,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2147 | } | 2030 | } |
2148 | } else { | 2031 | } else { |
2149 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2032 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2150 | info->flags |= iwl_is_tx_success(status) ? | 2033 | info->flags |= iwl_tx_status_to_mac80211(status); |
2151 | IEEE80211_TX_STAT_ACK : 0; | ||
2152 | iwl_hwrate_to_tx_control(priv, | 2034 | iwl_hwrate_to_tx_control(priv, |
2153 | le32_to_cpu(tx_resp->rate_n_flags), | 2035 | le32_to_cpu(tx_resp->rate_n_flags), |
2154 | info); | 2036 | info); |
@@ -2162,13 +2044,14 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2162 | 2044 | ||
2163 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2045 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
2164 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2046 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2165 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 2047 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
2048 | else if (sta_id == IWL_INVALID_STATION) | ||
2049 | IWL_DEBUG_TX_REPLY(priv, "Station not known\n"); | ||
2166 | 2050 | ||
2167 | if (priv->mac80211_registered && | 2051 | if (priv->mac80211_registered && |
2168 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | 2052 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) |
2169 | iwl_wake_queue(priv, txq_id); | 2053 | iwl_wake_queue(priv, txq_id); |
2170 | } | 2054 | } |
2171 | |||
2172 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2055 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2173 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2056 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); |
2174 | 2057 | ||
@@ -2279,7 +2162,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2279 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2162 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
2280 | .chain_noise_reset = iwl4965_chain_noise_reset, | 2163 | .chain_noise_reset = iwl4965_chain_noise_reset, |
2281 | .gain_computation = iwl4965_gain_computation, | 2164 | .gain_computation = iwl4965_gain_computation, |
2282 | .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, | 2165 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2283 | .calc_rssi = iwl4965_calc_rssi, | 2166 | .calc_rssi = iwl4965_calc_rssi, |
2284 | }; | 2167 | }; |
2285 | 2168 | ||
@@ -2301,10 +2184,10 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2301 | .load_ucode = iwl4965_load_bsm, | 2184 | .load_ucode = iwl4965_load_bsm, |
2302 | .dump_nic_event_log = iwl_dump_nic_event_log, | 2185 | .dump_nic_event_log = iwl_dump_nic_event_log, |
2303 | .dump_nic_error_log = iwl_dump_nic_error_log, | 2186 | .dump_nic_error_log = iwl_dump_nic_error_log, |
2187 | .set_channel_switch = iwl4965_hw_channel_switch, | ||
2304 | .apm_ops = { | 2188 | .apm_ops = { |
2305 | .init = iwl4965_apm_init, | 2189 | .init = iwl_apm_init, |
2306 | .reset = iwl4965_apm_reset, | 2190 | .stop = iwl_apm_stop, |
2307 | .stop = iwl4965_apm_stop, | ||
2308 | .config = iwl4965_nic_config, | 2191 | .config = iwl4965_nic_config, |
2309 | .set_pwr_src = iwl_set_pwr_src, | 2192 | .set_pwr_src = iwl_set_pwr_src, |
2310 | }, | 2193 | }, |
@@ -2333,13 +2216,15 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2333 | .temperature = iwl4965_temperature_calib, | 2216 | .temperature = iwl4965_temperature_calib, |
2334 | .set_ct_kill = iwl4965_set_ct_threshold, | 2217 | .set_ct_kill = iwl4965_set_ct_threshold, |
2335 | }, | 2218 | }, |
2219 | .add_bcast_station = iwl_add_bcast_station, | ||
2336 | }; | 2220 | }; |
2337 | 2221 | ||
2338 | static struct iwl_ops iwl4965_ops = { | 2222 | static const struct iwl_ops iwl4965_ops = { |
2339 | .ucode = &iwl4965_ucode, | 2223 | .ucode = &iwl4965_ucode, |
2340 | .lib = &iwl4965_lib, | 2224 | .lib = &iwl4965_lib, |
2341 | .hcmd = &iwl4965_hcmd, | 2225 | .hcmd = &iwl4965_hcmd, |
2342 | .utils = &iwl4965_hcmd_utils, | 2226 | .utils = &iwl4965_hcmd_utils, |
2227 | .led = &iwlagn_led_ops, | ||
2343 | }; | 2228 | }; |
2344 | 2229 | ||
2345 | struct iwl_cfg iwl4965_agn_cfg = { | 2230 | struct iwl_cfg iwl4965_agn_cfg = { |
@@ -2352,30 +2237,41 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2352 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | 2237 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, |
2353 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | 2238 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, |
2354 | .ops = &iwl4965_ops, | 2239 | .ops = &iwl4965_ops, |
2240 | .num_of_queues = IWL49_NUM_QUEUES, | ||
2241 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
2355 | .mod_params = &iwl4965_mod_params, | 2242 | .mod_params = &iwl4965_mod_params, |
2243 | .valid_tx_ant = ANT_AB, | ||
2244 | .valid_rx_ant = ANT_ABC, | ||
2245 | .pll_cfg_val = 0, | ||
2246 | .set_l0s = true, | ||
2247 | .use_bsm = true, | ||
2356 | .use_isr_legacy = true, | 2248 | .use_isr_legacy = true, |
2357 | .ht_greenfield_support = false, | 2249 | .ht_greenfield_support = false, |
2358 | .broken_powersave = true, | 2250 | .broken_powersave = true, |
2251 | .led_compensation = 61, | ||
2252 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | ||
2253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
2359 | }; | 2254 | }; |
2360 | 2255 | ||
2361 | /* Module firmware */ | 2256 | /* Module firmware */ |
2362 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | 2257 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2363 | 2258 | ||
2364 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 2259 | module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); |
2365 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2260 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
2366 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); | 2261 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); |
2367 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | 2262 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); |
2368 | module_param_named( | 2263 | module_param_named( |
2369 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); | 2264 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); |
2370 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 2265 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
2371 | 2266 | ||
2372 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); | 2267 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); |
2373 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | 2268 | MODULE_PARM_DESC(queues_num, "number of hw queues."); |
2374 | /* 11n */ | 2269 | /* 11n */ |
2375 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444); | 2270 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); |
2376 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | 2271 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); |
2377 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); | 2272 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, |
2273 | int, S_IRUGO); | ||
2378 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | 2274 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); |
2379 | 2275 | ||
2380 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444); | 2276 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); |
2381 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | 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 4ef6804a455a..714e032f6217 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -92,11 +92,15 @@ | |||
92 | 92 | ||
93 | static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | 93 | static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) |
94 | { | 94 | { |
95 | u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, | 95 | u16 temperature, voltage; |
96 | EEPROM_5000_TEMPERATURE); | 96 | __le16 *temp_calib = |
97 | /* offset = temperature - voltage / coef */ | 97 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); |
98 | s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | 98 | |
99 | return offset; | 99 | temperature = le16_to_cpu(temp_calib[0]); |
100 | voltage = le16_to_cpu(temp_calib[1]); | ||
101 | |||
102 | /* offset = temp - volt / coeff */ | ||
103 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | ||
100 | } | 104 | } |
101 | 105 | ||
102 | /* Fixed (non-configurable) rx data from phy */ | 106 | /* Fixed (non-configurable) rx data from phy */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6e6f516ba404..e476acb53aa7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -43,6 +43,7 @@ | |||
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-agn-led.h" | ||
46 | #include "iwl-5000-hw.h" | 47 | #include "iwl-5000-hw.h" |
47 | #include "iwl-6000-hw.h" | 48 | #include "iwl-6000-hw.h" |
48 | 49 | ||
@@ -72,157 +73,18 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = { | |||
72 | IWL_TX_FIFO_HCCA_2 | 73 | IWL_TX_FIFO_HCCA_2 |
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* FIXME: same implementation as 4965 */ | 76 | /* NIC configuration for 5000 series */ |
76 | static int iwl5000_apm_stop_master(struct iwl_priv *priv) | ||
77 | { | ||
78 | unsigned long flags; | ||
79 | |||
80 | spin_lock_irqsave(&priv->lock, flags); | ||
81 | |||
82 | /* set stop master bit */ | ||
83 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
84 | |||
85 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
86 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
87 | |||
88 | spin_unlock_irqrestore(&priv->lock, flags); | ||
89 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | |||
95 | int iwl5000_apm_init(struct iwl_priv *priv) | ||
96 | { | ||
97 | int ret = 0; | ||
98 | |||
99 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
100 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
101 | |||
102 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
103 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
104 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
105 | |||
106 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
107 | iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
108 | |||
109 | /* enable HAP INTA to move device L1a -> L0s */ | ||
110 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
111 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
112 | |||
113 | if (priv->cfg->need_pll_cfg) | ||
114 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | ||
115 | |||
116 | /* set "initialization complete" bit to move adapter | ||
117 | * D0U* --> D0A* state */ | ||
118 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
119 | |||
120 | /* wait for clock stabilization */ | ||
121 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
122 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
123 | if (ret < 0) { | ||
124 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | /* enable DMA */ | ||
129 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
130 | |||
131 | udelay(20); | ||
132 | |||
133 | /* disable L1-Active */ | ||
134 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
135 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | /* FIXME: this is identical to 4965 */ | ||
141 | void iwl5000_apm_stop(struct iwl_priv *priv) | ||
142 | { | ||
143 | unsigned long flags; | ||
144 | |||
145 | iwl5000_apm_stop_master(priv); | ||
146 | |||
147 | spin_lock_irqsave(&priv->lock, flags); | ||
148 | |||
149 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
150 | |||
151 | udelay(10); | ||
152 | |||
153 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
154 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
155 | |||
156 | spin_unlock_irqrestore(&priv->lock, flags); | ||
157 | } | ||
158 | |||
159 | |||
160 | int iwl5000_apm_reset(struct iwl_priv *priv) | ||
161 | { | ||
162 | int ret = 0; | ||
163 | |||
164 | iwl5000_apm_stop_master(priv); | ||
165 | |||
166 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
167 | |||
168 | udelay(10); | ||
169 | |||
170 | |||
171 | /* FIXME: put here L1A -L0S w/a */ | ||
172 | |||
173 | if (priv->cfg->need_pll_cfg) | ||
174 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | ||
175 | |||
176 | /* set "initialization complete" bit to move adapter | ||
177 | * D0U* --> D0A* state */ | ||
178 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
179 | |||
180 | /* wait for clock stabilization */ | ||
181 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | ||
182 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
183 | if (ret < 0) { | ||
184 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
185 | goto out; | ||
186 | } | ||
187 | |||
188 | /* enable DMA */ | ||
189 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
190 | |||
191 | udelay(20); | ||
192 | |||
193 | /* disable L1-Active */ | ||
194 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
195 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
196 | out: | ||
197 | |||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | |||
202 | /* NIC configuration for 5000 series and up */ | ||
203 | void iwl5000_nic_config(struct iwl_priv *priv) | 77 | void iwl5000_nic_config(struct iwl_priv *priv) |
204 | { | 78 | { |
205 | unsigned long flags; | 79 | unsigned long flags; |
206 | u16 radio_cfg; | 80 | u16 radio_cfg; |
207 | u16 lctl; | ||
208 | 81 | ||
209 | spin_lock_irqsave(&priv->lock, flags); | 82 | spin_lock_irqsave(&priv->lock, flags); |
210 | 83 | ||
211 | lctl = iwl_pcie_link_ctl(priv); | ||
212 | |||
213 | /* HW bug W/A */ | ||
214 | /* L1-ASPM is enabled by BIOS */ | ||
215 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) | ||
216 | /* L1-APSM enabled: disable L0S */ | ||
217 | iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
218 | else | ||
219 | /* L1-ASPM disabled: enable L0S */ | ||
220 | iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
221 | |||
222 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 84 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
223 | 85 | ||
224 | /* write radio config values to register */ | 86 | /* write radio config values to register */ |
225 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_5000_RF_CFG_TYPE_MAX) | 87 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX) |
226 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 88 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
227 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | 89 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | |
228 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | 90 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | |
@@ -302,26 +164,39 @@ u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) | |||
302 | static void iwl5000_gain_computation(struct iwl_priv *priv, | 164 | static void iwl5000_gain_computation(struct iwl_priv *priv, |
303 | u32 average_noise[NUM_RX_CHAINS], | 165 | u32 average_noise[NUM_RX_CHAINS], |
304 | u16 min_average_noise_antenna_i, | 166 | u16 min_average_noise_antenna_i, |
305 | u32 min_average_noise) | 167 | u32 min_average_noise, |
168 | u8 default_chain) | ||
306 | { | 169 | { |
307 | int i; | 170 | int i; |
308 | s32 delta_g; | 171 | s32 delta_g; |
309 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 172 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
310 | 173 | ||
311 | /* Find Gain Code for the antennas B and C */ | 174 | /* |
312 | for (i = 1; i < NUM_RX_CHAINS; i++) { | 175 | * Find Gain Code for the chains based on "default chain" |
176 | */ | ||
177 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
313 | if ((data->disconn_array[i])) { | 178 | if ((data->disconn_array[i])) { |
314 | data->delta_gain_code[i] = 0; | 179 | data->delta_gain_code[i] = 0; |
315 | continue; | 180 | continue; |
316 | } | 181 | } |
317 | delta_g = (1000 * ((s32)average_noise[0] - | 182 | |
183 | delta_g = (priv->cfg->chain_noise_scale * | ||
184 | ((s32)average_noise[default_chain] - | ||
318 | (s32)average_noise[i])) / 1500; | 185 | (s32)average_noise[i])) / 1500; |
186 | |||
319 | /* bound gain by 2 bits value max, 3rd bit is sign */ | 187 | /* bound gain by 2 bits value max, 3rd bit is sign */ |
320 | data->delta_gain_code[i] = | 188 | data->delta_gain_code[i] = |
321 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | 189 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); |
322 | 190 | ||
323 | if (delta_g < 0) | 191 | if (delta_g < 0) |
324 | /* set negative sign */ | 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 | */ | ||
325 | data->delta_gain_code[i] |= (1 << 2); | 200 | data->delta_gain_code[i] |= (1 << 2); |
326 | } | 201 | } |
327 | 202 | ||
@@ -398,8 +273,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | |||
398 | 273 | ||
399 | .auto_corr_max_ofdm = 120, | 274 | .auto_corr_max_ofdm = 120, |
400 | .auto_corr_max_ofdm_mrc = 210, | 275 | .auto_corr_max_ofdm_mrc = 210, |
401 | .auto_corr_max_ofdm_x1 = 155, | 276 | .auto_corr_max_ofdm_x1 = 120, |
402 | .auto_corr_max_ofdm_mrc_x1 = 290, | 277 | .auto_corr_max_ofdm_mrc_x1 = 240, |
403 | 278 | ||
404 | .auto_corr_min_cck = 125, | 279 | .auto_corr_min_cck = 125, |
405 | .auto_corr_max_cck = 200, | 280 | .auto_corr_max_cck = 200, |
@@ -407,6 +282,10 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | |||
407 | .auto_corr_max_cck_mrc = 400, | 282 | .auto_corr_max_cck_mrc = 400, |
408 | .nrg_th_cck = 95, | 283 | .nrg_th_cck = 95, |
409 | .nrg_th_ofdm = 95, | 284 | .nrg_th_ofdm = 95, |
285 | |||
286 | .barker_corr_th_min = 190, | ||
287 | .barker_corr_th_min_mrc = 390, | ||
288 | .nrg_th_cca = 62, | ||
410 | }; | 289 | }; |
411 | 290 | ||
412 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | 291 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { |
@@ -429,6 +308,10 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
429 | .auto_corr_max_cck_mrc = 400, | 308 | .auto_corr_max_cck_mrc = 400, |
430 | .nrg_th_cck = 95, | 309 | .nrg_th_cck = 95, |
431 | .nrg_th_ofdm = 95, | 310 | .nrg_th_ofdm = 95, |
311 | |||
312 | .barker_corr_th_min = 190, | ||
313 | .barker_corr_th_min_mrc = 390, | ||
314 | .nrg_th_cca = 62, | ||
432 | }; | 315 | }; |
433 | 316 | ||
434 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | 317 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, |
@@ -460,14 +343,15 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |||
460 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) | 343 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) |
461 | { | 344 | { |
462 | struct iwl_calib_xtal_freq_cmd cmd; | 345 | struct iwl_calib_xtal_freq_cmd cmd; |
463 | u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | 346 | __le16 *xtal_calib = |
347 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | ||
464 | 348 | ||
465 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | 349 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; |
466 | cmd.hdr.first_group = 0; | 350 | cmd.hdr.first_group = 0; |
467 | cmd.hdr.groups_num = 1; | 351 | cmd.hdr.groups_num = 1; |
468 | cmd.hdr.data_valid = 1; | 352 | cmd.hdr.data_valid = 1; |
469 | cmd.cap_pin1 = (u8)xtal_calib[0]; | 353 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); |
470 | cmd.cap_pin2 = (u8)xtal_calib[1]; | 354 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); |
471 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | 355 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], |
472 | (u8 *)&cmd, sizeof(cmd)); | 356 | (u8 *)&cmd, sizeof(cmd)); |
473 | } | 357 | } |
@@ -493,7 +377,7 @@ static int iwl5000_send_calib_cfg(struct iwl_priv *priv) | |||
493 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, | 377 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, |
494 | struct iwl_rx_mem_buffer *rxb) | 378 | struct iwl_rx_mem_buffer *rxb) |
495 | { | 379 | { |
496 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 380 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
497 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | 381 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; |
498 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 382 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
499 | int index; | 383 | int index; |
@@ -538,12 +422,14 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv, | |||
538 | /* | 422 | /* |
539 | * ucode | 423 | * ucode |
540 | */ | 424 | */ |
541 | static int iwl5000_load_section(struct iwl_priv *priv, | 425 | static int iwl5000_load_section(struct iwl_priv *priv, const char *name, |
542 | struct fw_desc *image, | 426 | struct fw_desc *image, u32 dst_addr) |
543 | u32 dst_addr) | ||
544 | { | 427 | { |
545 | dma_addr_t phy_addr = image->p_addr; | 428 | dma_addr_t phy_addr = image->p_addr; |
546 | u32 byte_cnt = image->len; | 429 | u32 byte_cnt = image->len; |
430 | int ret; | ||
431 | |||
432 | priv->ucode_write_complete = 0; | ||
547 | 433 | ||
548 | iwl_write_direct32(priv, | 434 | iwl_write_direct32(priv, |
549 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | 435 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), |
@@ -573,57 +459,36 @@ static int iwl5000_load_section(struct iwl_priv *priv, | |||
573 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | 459 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | |
574 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | 460 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); |
575 | 461 | ||
576 | return 0; | 462 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); |
577 | } | ||
578 | |||
579 | static int iwl5000_load_given_ucode(struct iwl_priv *priv, | ||
580 | struct fw_desc *inst_image, | ||
581 | struct fw_desc *data_image) | ||
582 | { | ||
583 | int ret = 0; | ||
584 | |||
585 | ret = iwl5000_load_section(priv, inst_image, | ||
586 | IWL50_RTC_INST_LOWER_BOUND); | ||
587 | if (ret) | ||
588 | return ret; | ||
589 | |||
590 | IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n"); | ||
591 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 463 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, |
592 | priv->ucode_write_complete, 5 * HZ); | 464 | priv->ucode_write_complete, 5 * HZ); |
593 | if (ret == -ERESTARTSYS) { | 465 | if (ret == -ERESTARTSYS) { |
594 | IWL_ERR(priv, "Could not load the INST uCode section due " | 466 | IWL_ERR(priv, "Could not load the %s uCode section due " |
595 | "to interrupt\n"); | 467 | "to interrupt\n", name); |
596 | return ret; | 468 | return ret; |
597 | } | 469 | } |
598 | if (!ret) { | 470 | if (!ret) { |
599 | IWL_ERR(priv, "Could not load the INST uCode section\n"); | 471 | IWL_ERR(priv, "Could not load the %s uCode section\n", |
472 | name); | ||
600 | return -ETIMEDOUT; | 473 | return -ETIMEDOUT; |
601 | } | 474 | } |
602 | 475 | ||
603 | priv->ucode_write_complete = 0; | 476 | return 0; |
604 | 477 | } | |
605 | ret = iwl5000_load_section( | ||
606 | priv, data_image, IWL50_RTC_DATA_LOWER_BOUND); | ||
607 | if (ret) | ||
608 | return ret; | ||
609 | 478 | ||
610 | IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n"); | 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; | ||
611 | 484 | ||
612 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 485 | ret = iwl5000_load_section(priv, "INST", inst_image, |
613 | priv->ucode_write_complete, 5 * HZ); | 486 | IWL50_RTC_INST_LOWER_BOUND); |
614 | if (ret == -ERESTARTSYS) { | 487 | if (ret) |
615 | IWL_ERR(priv, "Could not load the INST uCode section due " | ||
616 | "to interrupt\n"); | ||
617 | return ret; | 488 | return ret; |
618 | } else if (!ret) { | ||
619 | IWL_ERR(priv, "Could not load the DATA uCode section\n"); | ||
620 | return -ETIMEDOUT; | ||
621 | } else | ||
622 | ret = 0; | ||
623 | |||
624 | priv->ucode_write_complete = 0; | ||
625 | 489 | ||
626 | return ret; | 490 | return iwl5000_load_section(priv, "DATA", data_image, |
491 | IWL50_RTC_DATA_LOWER_BOUND); | ||
627 | } | 492 | } |
628 | 493 | ||
629 | int iwl5000_load_ucode(struct iwl_priv *priv) | 494 | int iwl5000_load_ucode(struct iwl_priv *priv) |
@@ -719,16 +584,6 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, | |||
719 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); | 584 | scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); |
720 | } | 585 | } |
721 | 586 | ||
722 | static int iwl5000_send_wimax_coex(struct iwl_priv *priv) | ||
723 | { | ||
724 | struct iwl_wimax_coex_cmd coex_cmd; | ||
725 | |||
726 | memset(&coex_cmd, 0, sizeof(coex_cmd)); | ||
727 | |||
728 | return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, | ||
729 | sizeof(coex_cmd), &coex_cmd); | ||
730 | } | ||
731 | |||
732 | int iwl5000_alive_notify(struct iwl_priv *priv) | 587 | int iwl5000_alive_notify(struct iwl_priv *priv) |
733 | { | 588 | { |
734 | u32 a; | 589 | u32 a; |
@@ -746,7 +601,8 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
746 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | 601 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; |
747 | a += 4) | 602 | a += 4) |
748 | iwl_write_targ_mem(priv, a, 0); | 603 | iwl_write_targ_mem(priv, a, 0); |
749 | for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) | 604 | for (; a < priv->scd_base_addr + |
605 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
750 | iwl_write_targ_mem(priv, a, 0); | 606 | iwl_write_targ_mem(priv, a, 0); |
751 | 607 | ||
752 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | 608 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, |
@@ -792,15 +648,26 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
792 | 648 | ||
793 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 649 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
794 | 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; | ||
795 | /* map qos queues to fifos one-to-one */ | 658 | /* map qos queues to fifos one-to-one */ |
796 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { | 659 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { |
797 | int ac = iwl5000_default_queue_to_tx_fifo[i]; | 660 | int ac = iwl5000_default_queue_to_tx_fifo[i]; |
798 | iwl_txq_ctx_activate(priv, i); | 661 | iwl_txq_ctx_activate(priv, i); |
799 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | 662 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); |
800 | } | 663 | } |
801 | /* TODO - need to initialize those FIFOs inside the loop above, | 664 | |
802 | * not only mark them as active */ | 665 | /* |
803 | iwl_txq_ctx_activate(priv, 4); | 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 | */ | ||
804 | iwl_txq_ctx_activate(priv, 7); | 671 | iwl_txq_ctx_activate(priv, 7); |
805 | iwl_txq_ctx_activate(priv, 8); | 672 | iwl_txq_ctx_activate(priv, 8); |
806 | iwl_txq_ctx_activate(priv, 9); | 673 | iwl_txq_ctx_activate(priv, 9); |
@@ -808,7 +675,7 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
808 | spin_unlock_irqrestore(&priv->lock, flags); | 675 | spin_unlock_irqrestore(&priv->lock, flags); |
809 | 676 | ||
810 | 677 | ||
811 | iwl5000_send_wimax_coex(priv); | 678 | iwl_send_wimax_coex(priv); |
812 | 679 | ||
813 | iwl5000_set_Xtal_calib(priv); | 680 | iwl5000_set_Xtal_calib(priv); |
814 | iwl_send_calib_results(priv); | 681 | iwl_send_calib_results(priv); |
@@ -818,32 +685,22 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
818 | 685 | ||
819 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | 686 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
820 | { | 687 | { |
821 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || | 688 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
822 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | 689 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) |
823 | IWL_ERR(priv, | 690 | priv->cfg->num_of_queues = |
824 | "invalid queues_num, should be between %d and %d\n", | 691 | priv->cfg->mod_params->num_of_queues; |
825 | IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); | ||
826 | return -EINVAL; | ||
827 | } | ||
828 | 692 | ||
829 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 693 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
830 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 694 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
831 | priv->hw_params.scd_bc_tbls_size = | 695 | priv->hw_params.scd_bc_tbls_size = |
832 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | 696 | priv->cfg->num_of_queues * |
697 | sizeof(struct iwl5000_scd_bc_tbl); | ||
833 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 698 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
834 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 699 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
835 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 700 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
836 | 701 | ||
837 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 702 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; |
838 | case CSR_HW_REV_TYPE_6x00: | 703 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; |
839 | case CSR_HW_REV_TYPE_6x50: | ||
840 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | ||
841 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | ||
842 | break; | ||
843 | default: | ||
844 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | ||
845 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | ||
846 | } | ||
847 | 704 | ||
848 | priv->hw_params.max_bsm_size = 0; | 705 | priv->hw_params.max_bsm_size = 0; |
849 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 706 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -922,7 +779,7 @@ void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
922 | 779 | ||
923 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | 780 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; |
924 | 781 | ||
925 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 782 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) |
926 | scd_bc_tbl[txq_id]. | 783 | scd_bc_tbl[txq_id]. |
927 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | 784 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; |
928 | } | 785 | } |
@@ -941,12 +798,12 @@ void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | |||
941 | if (txq_id != IWL_CMD_QUEUE_NUM) | 798 | if (txq_id != IWL_CMD_QUEUE_NUM) |
942 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | 799 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; |
943 | 800 | ||
944 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | 801 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); |
945 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | 802 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; |
946 | 803 | ||
947 | if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) | 804 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) |
948 | scd_bc_tbl[txq_id]. | 805 | scd_bc_tbl[txq_id]. |
949 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | 806 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; |
950 | } | 807 | } |
951 | 808 | ||
952 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | 809 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, |
@@ -989,11 +846,13 @@ int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
989 | u16 ra_tid; | 846 | u16 ra_tid; |
990 | 847 | ||
991 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | 848 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || |
992 | (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { | 849 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
850 | <= txq_id)) { | ||
993 | IWL_WARN(priv, | 851 | IWL_WARN(priv, |
994 | "queue number out of range: %d, must be %d to %d\n", | 852 | "queue number out of range: %d, must be %d to %d\n", |
995 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | 853 | txq_id, IWL50_FIRST_AMPDU_QUEUE, |
996 | IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); | 854 | IWL50_FIRST_AMPDU_QUEUE + |
855 | priv->cfg->num_of_ampdu_queues - 1); | ||
997 | return -EINVAL; | 856 | return -EINVAL; |
998 | } | 857 | } |
999 | 858 | ||
@@ -1047,11 +906,13 @@ int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1047 | u16 ssn_idx, u8 tx_fifo) | 906 | u16 ssn_idx, u8 tx_fifo) |
1048 | { | 907 | { |
1049 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | 908 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || |
1050 | (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { | 909 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
910 | <= txq_id)) { | ||
1051 | IWL_ERR(priv, | 911 | IWL_ERR(priv, |
1052 | "queue number out of range: %d, must be %d to %d\n", | 912 | "queue number out of range: %d, must be %d to %d\n", |
1053 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | 913 | txq_id, IWL50_FIRST_AMPDU_QUEUE, |
1054 | IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); | 914 | IWL50_FIRST_AMPDU_QUEUE + |
915 | priv->cfg->num_of_ampdu_queues - 1); | ||
1055 | return -EINVAL; | 916 | return -EINVAL; |
1056 | } | 917 | } |
1057 | 918 | ||
@@ -1132,8 +993,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
1132 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 993 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
1133 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 994 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1134 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 995 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1135 | info->flags |= iwl_is_tx_success(status) ? | 996 | info->flags |= iwl_tx_status_to_mac80211(status); |
1136 | IEEE80211_TX_STAT_ACK : 0; | ||
1137 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 997 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
1138 | 998 | ||
1139 | /* FIXME: code repetition end */ | 999 | /* FIXME: code repetition end */ |
@@ -1218,7 +1078,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
1218 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | 1078 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, |
1219 | struct iwl_rx_mem_buffer *rxb) | 1079 | struct iwl_rx_mem_buffer *rxb) |
1220 | { | 1080 | { |
1221 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1081 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1222 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1082 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
1223 | int txq_id = SEQ_TO_QUEUE(sequence); | 1083 | int txq_id = SEQ_TO_QUEUE(sequence); |
1224 | int index = SEQ_TO_INDEX(sequence); | 1084 | int index = SEQ_TO_INDEX(sequence); |
@@ -1263,7 +1123,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | |||
1263 | scd_ssn , index, txq_id, txq->swq_id); | 1123 | scd_ssn , index, txq_id, txq->swq_id); |
1264 | 1124 | ||
1265 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 1125 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
1266 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 1126 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
1267 | 1127 | ||
1268 | if (priv->mac80211_registered && | 1128 | if (priv->mac80211_registered && |
1269 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | 1129 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && |
@@ -1278,8 +1138,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | |||
1278 | BUG_ON(txq_id != txq->swq_id); | 1138 | BUG_ON(txq_id != txq->swq_id); |
1279 | 1139 | ||
1280 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1140 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1281 | info->flags |= iwl_is_tx_success(status) ? | 1141 | info->flags |= iwl_tx_status_to_mac80211(status); |
1282 | IEEE80211_TX_STAT_ACK : 0; | ||
1283 | iwl_hwrate_to_tx_control(priv, | 1142 | iwl_hwrate_to_tx_control(priv, |
1284 | le32_to_cpu(tx_resp->rate_n_flags), | 1143 | le32_to_cpu(tx_resp->rate_n_flags), |
1285 | info); | 1144 | info); |
@@ -1292,16 +1151,14 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | |||
1292 | tx_resp->failure_frame); | 1151 | tx_resp->failure_frame); |
1293 | 1152 | ||
1294 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 1153 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); |
1295 | if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) | 1154 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
1296 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
1297 | 1155 | ||
1298 | if (priv->mac80211_registered && | 1156 | if (priv->mac80211_registered && |
1299 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | 1157 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) |
1300 | iwl_wake_queue(priv, txq_id); | 1158 | iwl_wake_queue(priv, txq_id); |
1301 | } | 1159 | } |
1302 | 1160 | ||
1303 | if (ieee80211_is_data_qos(tx_resp->frame_ctrl)) | 1161 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); |
1304 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | ||
1305 | 1162 | ||
1306 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | 1163 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) |
1307 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | 1164 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); |
@@ -1389,6 +1246,22 @@ int iwl5000_send_tx_power(struct iwl_priv *priv) | |||
1389 | 1246 | ||
1390 | /* half dBm need to multiply */ | 1247 | /* half dBm need to multiply */ |
1391 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 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 | } | ||
1392 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | 1265 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; |
1393 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | 1266 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; |
1394 | 1267 | ||
@@ -1459,6 +1332,24 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, | |||
1459 | return max_rssi - agc - IWL49_RSSI_OFFSET; | 1332 | return max_rssi - agc - IWL49_RSSI_OFFSET; |
1460 | } | 1333 | } |
1461 | 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 | |||
1462 | #define IWL5000_UCODE_GET(item) \ | 1353 | #define IWL5000_UCODE_GET(item) \ |
1463 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | 1354 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ |
1464 | u32 api_ver) \ | 1355 | u32 api_ver) \ |
@@ -1497,10 +1388,43 @@ IWL5000_UCODE_GET(init_size); | |||
1497 | IWL5000_UCODE_GET(init_data_size); | 1388 | IWL5000_UCODE_GET(init_data_size); |
1498 | IWL5000_UCODE_GET(boot_size); | 1389 | IWL5000_UCODE_GET(boot_size); |
1499 | 1390 | ||
1391 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
1392 | { | ||
1393 | struct iwl5000_channel_switch_cmd cmd; | ||
1394 | const struct iwl_channel_info *ch_info; | ||
1395 | struct iwl_host_cmd hcmd = { | ||
1396 | .id = REPLY_CHANNEL_SWITCH, | ||
1397 | .len = sizeof(cmd), | ||
1398 | .flags = CMD_SIZE_HUGE, | ||
1399 | .data = &cmd, | ||
1400 | }; | ||
1401 | |||
1402 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
1403 | priv->active_rxon.channel, channel); | ||
1404 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
1405 | cmd.channel = cpu_to_le16(channel); | ||
1406 | cmd.rxon_flags = priv->staging_rxon.flags; | ||
1407 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | ||
1408 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
1409 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
1410 | if (ch_info) | ||
1411 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
1412 | else { | ||
1413 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
1414 | priv->active_rxon.channel, channel); | ||
1415 | return -EFAULT; | ||
1416 | } | ||
1417 | priv->switch_rxon.channel = cpu_to_le16(channel); | ||
1418 | priv->switch_rxon.switch_in_progress = true; | ||
1419 | |||
1420 | return iwl_send_cmd_sync(priv, &hcmd); | ||
1421 | } | ||
1422 | |||
1500 | struct iwl_hcmd_ops iwl5000_hcmd = { | 1423 | struct iwl_hcmd_ops iwl5000_hcmd = { |
1501 | .rxon_assoc = iwl5000_send_rxon_assoc, | 1424 | .rxon_assoc = iwl5000_send_rxon_assoc, |
1502 | .commit_rxon = iwl_commit_rxon, | 1425 | .commit_rxon = iwl_commit_rxon, |
1503 | .set_rxon_chain = iwl_set_rxon_chain, | 1426 | .set_rxon_chain = iwl_set_rxon_chain, |
1427 | .set_tx_ant = iwl5000_send_tx_ant_config, | ||
1504 | }; | 1428 | }; |
1505 | 1429 | ||
1506 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | 1430 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { |
@@ -1538,15 +1462,17 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1538 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1462 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
1539 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1463 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1540 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1464 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1465 | .dump_csr = iwl_dump_csr, | ||
1466 | .dump_fh = iwl_dump_fh, | ||
1541 | .load_ucode = iwl5000_load_ucode, | 1467 | .load_ucode = iwl5000_load_ucode, |
1542 | .init_alive_start = iwl5000_init_alive_start, | 1468 | .init_alive_start = iwl5000_init_alive_start, |
1543 | .alive_notify = iwl5000_alive_notify, | 1469 | .alive_notify = iwl5000_alive_notify, |
1544 | .send_tx_power = iwl5000_send_tx_power, | 1470 | .send_tx_power = iwl5000_send_tx_power, |
1545 | .update_chain_flags = iwl_update_chain_flags, | 1471 | .update_chain_flags = iwl_update_chain_flags, |
1472 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
1546 | .apm_ops = { | 1473 | .apm_ops = { |
1547 | .init = iwl5000_apm_init, | 1474 | .init = iwl_apm_init, |
1548 | .reset = iwl5000_apm_reset, | 1475 | .stop = iwl_apm_stop, |
1549 | .stop = iwl5000_apm_stop, | ||
1550 | .config = iwl5000_nic_config, | 1476 | .config = iwl5000_nic_config, |
1551 | .set_pwr_src = iwl_set_pwr_src, | 1477 | .set_pwr_src = iwl_set_pwr_src, |
1552 | }, | 1478 | }, |
@@ -1573,6 +1499,7 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1573 | .temperature = iwl5000_temperature, | 1499 | .temperature = iwl5000_temperature, |
1574 | .set_ct_kill = iwl5000_set_ct_threshold, | 1500 | .set_ct_kill = iwl5000_set_ct_threshold, |
1575 | }, | 1501 | }, |
1502 | .add_bcast_station = iwl_add_bcast_station, | ||
1576 | }; | 1503 | }; |
1577 | 1504 | ||
1578 | static struct iwl_lib_ops iwl5150_lib = { | 1505 | static struct iwl_lib_ops iwl5150_lib = { |
@@ -1590,15 +1517,16 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1590 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1517 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
1591 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1518 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1592 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1519 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1520 | .dump_csr = iwl_dump_csr, | ||
1593 | .load_ucode = iwl5000_load_ucode, | 1521 | .load_ucode = iwl5000_load_ucode, |
1594 | .init_alive_start = iwl5000_init_alive_start, | 1522 | .init_alive_start = iwl5000_init_alive_start, |
1595 | .alive_notify = iwl5000_alive_notify, | 1523 | .alive_notify = iwl5000_alive_notify, |
1596 | .send_tx_power = iwl5000_send_tx_power, | 1524 | .send_tx_power = iwl5000_send_tx_power, |
1597 | .update_chain_flags = iwl_update_chain_flags, | 1525 | .update_chain_flags = iwl_update_chain_flags, |
1526 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
1598 | .apm_ops = { | 1527 | .apm_ops = { |
1599 | .init = iwl5000_apm_init, | 1528 | .init = iwl_apm_init, |
1600 | .reset = iwl5000_apm_reset, | 1529 | .stop = iwl_apm_stop, |
1601 | .stop = iwl5000_apm_stop, | ||
1602 | .config = iwl5000_nic_config, | 1530 | .config = iwl5000_nic_config, |
1603 | .set_pwr_src = iwl_set_pwr_src, | 1531 | .set_pwr_src = iwl_set_pwr_src, |
1604 | }, | 1532 | }, |
@@ -1625,25 +1553,26 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1625 | .temperature = iwl5150_temperature, | 1553 | .temperature = iwl5150_temperature, |
1626 | .set_ct_kill = iwl5150_set_ct_threshold, | 1554 | .set_ct_kill = iwl5150_set_ct_threshold, |
1627 | }, | 1555 | }, |
1556 | .add_bcast_station = iwl_add_bcast_station, | ||
1628 | }; | 1557 | }; |
1629 | 1558 | ||
1630 | struct iwl_ops iwl5000_ops = { | 1559 | static const struct iwl_ops iwl5000_ops = { |
1631 | .ucode = &iwl5000_ucode, | 1560 | .ucode = &iwl5000_ucode, |
1632 | .lib = &iwl5000_lib, | 1561 | .lib = &iwl5000_lib, |
1633 | .hcmd = &iwl5000_hcmd, | 1562 | .hcmd = &iwl5000_hcmd, |
1634 | .utils = &iwl5000_hcmd_utils, | 1563 | .utils = &iwl5000_hcmd_utils, |
1564 | .led = &iwlagn_led_ops, | ||
1635 | }; | 1565 | }; |
1636 | 1566 | ||
1637 | static struct iwl_ops iwl5150_ops = { | 1567 | static const struct iwl_ops iwl5150_ops = { |
1638 | .ucode = &iwl5000_ucode, | 1568 | .ucode = &iwl5000_ucode, |
1639 | .lib = &iwl5150_lib, | 1569 | .lib = &iwl5150_lib, |
1640 | .hcmd = &iwl5000_hcmd, | 1570 | .hcmd = &iwl5000_hcmd, |
1641 | .utils = &iwl5000_hcmd_utils, | 1571 | .utils = &iwl5000_hcmd_utils, |
1572 | .led = &iwlagn_led_ops, | ||
1642 | }; | 1573 | }; |
1643 | 1574 | ||
1644 | struct iwl_mod_params iwl50_mod_params = { | 1575 | struct iwl_mod_params iwl50_mod_params = { |
1645 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1646 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1647 | .amsdu_size_8K = 1, | 1576 | .amsdu_size_8K = 1, |
1648 | .restart_fw = 1, | 1577 | .restart_fw = 1, |
1649 | /* the rest are 0 by default */ | 1578 | /* the rest are 0 by default */ |
@@ -1660,28 +1589,46 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1660 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1589 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1661 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1590 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1662 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1591 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1592 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1593 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1663 | .mod_params = &iwl50_mod_params, | 1594 | .mod_params = &iwl50_mod_params, |
1664 | .valid_tx_ant = ANT_ABC, | 1595 | .valid_tx_ant = ANT_ABC, |
1665 | .valid_rx_ant = ANT_ABC, | 1596 | .valid_rx_ant = ANT_ABC, |
1666 | .need_pll_cfg = true, | 1597 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1598 | .set_l0s = true, | ||
1599 | .use_bsm = false, | ||
1667 | .ht_greenfield_support = true, | 1600 | .ht_greenfield_support = true, |
1601 | .led_compensation = 51, | ||
1602 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
1603 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1604 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1605 | .chain_noise_scale = 1000, | ||
1668 | }; | 1606 | }; |
1669 | 1607 | ||
1670 | struct iwl_cfg iwl5100_bg_cfg = { | 1608 | struct iwl_cfg iwl5100_bgn_cfg = { |
1671 | .name = "5100BG", | 1609 | .name = "5100BGN", |
1672 | .fw_name_pre = IWL5000_FW_PRE, | 1610 | .fw_name_pre = IWL5000_FW_PRE, |
1673 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 1611 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1674 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 1612 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1675 | .sku = IWL_SKU_G, | 1613 | .sku = IWL_SKU_G|IWL_SKU_N, |
1676 | .ops = &iwl5000_ops, | 1614 | .ops = &iwl5000_ops, |
1677 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1615 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1678 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1616 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1679 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1617 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1618 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1619 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1680 | .mod_params = &iwl50_mod_params, | 1620 | .mod_params = &iwl50_mod_params, |
1681 | .valid_tx_ant = ANT_B, | 1621 | .valid_tx_ant = ANT_B, |
1682 | .valid_rx_ant = ANT_AB, | 1622 | .valid_rx_ant = ANT_AB, |
1683 | .need_pll_cfg = true, | 1623 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1624 | .set_l0s = true, | ||
1625 | .use_bsm = false, | ||
1684 | .ht_greenfield_support = true, | 1626 | .ht_greenfield_support = true, |
1627 | .led_compensation = 51, | ||
1628 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
1629 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1630 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1631 | .chain_noise_scale = 1000, | ||
1685 | }; | 1632 | }; |
1686 | 1633 | ||
1687 | struct iwl_cfg iwl5100_abg_cfg = { | 1634 | struct iwl_cfg iwl5100_abg_cfg = { |
@@ -1694,11 +1641,18 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1694 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1641 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1695 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1642 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1696 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1643 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1644 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1645 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1697 | .mod_params = &iwl50_mod_params, | 1646 | .mod_params = &iwl50_mod_params, |
1698 | .valid_tx_ant = ANT_B, | 1647 | .valid_tx_ant = ANT_B, |
1699 | .valid_rx_ant = ANT_AB, | 1648 | .valid_rx_ant = ANT_AB, |
1700 | .need_pll_cfg = true, | 1649 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1701 | .ht_greenfield_support = true, | 1650 | .set_l0s = true, |
1651 | .use_bsm = false, | ||
1652 | .led_compensation = 51, | ||
1653 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1654 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1655 | .chain_noise_scale = 1000, | ||
1702 | }; | 1656 | }; |
1703 | 1657 | ||
1704 | struct iwl_cfg iwl5100_agn_cfg = { | 1658 | struct iwl_cfg iwl5100_agn_cfg = { |
@@ -1711,11 +1665,20 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1711 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1665 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1712 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1666 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1713 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1667 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1668 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1669 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1714 | .mod_params = &iwl50_mod_params, | 1670 | .mod_params = &iwl50_mod_params, |
1715 | .valid_tx_ant = ANT_B, | 1671 | .valid_tx_ant = ANT_B, |
1716 | .valid_rx_ant = ANT_AB, | 1672 | .valid_rx_ant = ANT_AB, |
1717 | .need_pll_cfg = true, | 1673 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1674 | .set_l0s = true, | ||
1675 | .use_bsm = false, | ||
1718 | .ht_greenfield_support = true, | 1676 | .ht_greenfield_support = true, |
1677 | .led_compensation = 51, | ||
1678 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
1679 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1680 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1681 | .chain_noise_scale = 1000, | ||
1719 | }; | 1682 | }; |
1720 | 1683 | ||
1721 | struct iwl_cfg iwl5350_agn_cfg = { | 1684 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1728,11 +1691,20 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1728 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1691 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1729 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 1692 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1730 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 1693 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1694 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1695 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1731 | .mod_params = &iwl50_mod_params, | 1696 | .mod_params = &iwl50_mod_params, |
1732 | .valid_tx_ant = ANT_ABC, | 1697 | .valid_tx_ant = ANT_ABC, |
1733 | .valid_rx_ant = ANT_ABC, | 1698 | .valid_rx_ant = ANT_ABC, |
1734 | .need_pll_cfg = true, | 1699 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1700 | .set_l0s = true, | ||
1701 | .use_bsm = false, | ||
1735 | .ht_greenfield_support = true, | 1702 | .ht_greenfield_support = true, |
1703 | .led_compensation = 51, | ||
1704 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
1705 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1706 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1707 | .chain_noise_scale = 1000, | ||
1736 | }; | 1708 | }; |
1737 | 1709 | ||
1738 | struct iwl_cfg iwl5150_agn_cfg = { | 1710 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1745,24 +1717,58 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1745 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1717 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1746 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 1718 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1747 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 1719 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1720 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1721 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1748 | .mod_params = &iwl50_mod_params, | 1722 | .mod_params = &iwl50_mod_params, |
1749 | .valid_tx_ant = ANT_A, | 1723 | .valid_tx_ant = ANT_A, |
1750 | .valid_rx_ant = ANT_AB, | 1724 | .valid_rx_ant = ANT_AB, |
1751 | .need_pll_cfg = true, | 1725 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1726 | .set_l0s = true, | ||
1727 | .use_bsm = false, | ||
1752 | .ht_greenfield_support = true, | 1728 | .ht_greenfield_support = true, |
1729 | .led_compensation = 51, | ||
1730 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
1731 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1732 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1733 | .chain_noise_scale = 1000, | ||
1734 | }; | ||
1735 | |||
1736 | struct iwl_cfg iwl5150_abg_cfg = { | ||
1737 | .name = "5150ABG", | ||
1738 | .fw_name_pre = IWL5150_FW_PRE, | ||
1739 | .ucode_api_max = IWL5150_UCODE_API_MAX, | ||
1740 | .ucode_api_min = IWL5150_UCODE_API_MIN, | ||
1741 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
1742 | .ops = &iwl5150_ops, | ||
1743 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | ||
1744 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | ||
1745 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | ||
1746 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1747 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1748 | .mod_params = &iwl50_mod_params, | ||
1749 | .valid_tx_ant = ANT_A, | ||
1750 | .valid_rx_ant = ANT_AB, | ||
1751 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
1752 | .set_l0s = true, | ||
1753 | .use_bsm = false, | ||
1754 | .led_compensation = 51, | ||
1755 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1756 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||
1757 | .chain_noise_scale = 1000, | ||
1753 | }; | 1758 | }; |
1754 | 1759 | ||
1755 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 1760 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1756 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | 1761 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); |
1757 | 1762 | ||
1758 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); | 1763 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO); |
1759 | MODULE_PARM_DESC(swcrypto50, | 1764 | MODULE_PARM_DESC(swcrypto50, |
1760 | "using software crypto engine (default 0 [hardware])\n"); | 1765 | "using software crypto engine (default 0 [hardware])\n"); |
1761 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); | 1766 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO); |
1762 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | 1767 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); |
1763 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); | 1768 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO); |
1764 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); | 1769 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); |
1765 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444); | 1770 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, |
1771 | int, S_IRUGO); | ||
1766 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | 1772 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); |
1767 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444); | 1773 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO); |
1768 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); | 1774 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h index 90185777d98b..ddba39999997 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 1473452ba22f..92b3e64fc14d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -44,14 +44,16 @@ | |||
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | #include "iwl-6000-hw.h" | ||
48 | #include "iwl-agn-led.h" | ||
47 | 49 | ||
48 | /* Highest firmware API version supported */ | 50 | /* Highest firmware API version supported */ |
49 | #define IWL6000_UCODE_API_MAX 4 | 51 | #define IWL6000_UCODE_API_MAX 4 |
50 | #define IWL6050_UCODE_API_MAX 4 | 52 | #define IWL6050_UCODE_API_MAX 4 |
51 | 53 | ||
52 | /* Lowest firmware API version supported */ | 54 | /* Lowest firmware API version supported */ |
53 | #define IWL6000_UCODE_API_MIN 1 | 55 | #define IWL6000_UCODE_API_MIN 4 |
54 | #define IWL6050_UCODE_API_MIN 1 | 56 | #define IWL6050_UCODE_API_MIN 4 |
55 | 57 | ||
56 | #define IWL6000_FW_PRE "iwlwifi-6000-" | 58 | #define IWL6000_FW_PRE "iwlwifi-6000-" |
57 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" | 59 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" |
@@ -68,26 +70,161 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
68 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | 70 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; |
69 | } | 71 | } |
70 | 72 | ||
73 | /* Indicate calibration version to uCode. */ | ||
74 | static void iwl6050_set_calib_version(struct iwl_priv *priv) | ||
75 | { | ||
76 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) | ||
77 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | ||
78 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
79 | } | ||
80 | |||
71 | /* NIC configuration for 6000 series */ | 81 | /* NIC configuration for 6000 series */ |
72 | static void iwl6000_nic_config(struct iwl_priv *priv) | 82 | static void iwl6000_nic_config(struct iwl_priv *priv) |
73 | { | 83 | { |
74 | iwl5000_nic_config(priv); | 84 | u16 radio_cfg; |
85 | |||
86 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
87 | |||
88 | /* write radio config values to register */ | ||
89 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) | ||
90 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
91 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | ||
92 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | ||
93 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
94 | |||
95 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
96 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
97 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
98 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
75 | 99 | ||
76 | /* no locking required for register write */ | 100 | /* no locking required for register write */ |
77 | if (priv->cfg->pa_type == IWL_PA_HYBRID) { | 101 | if (priv->cfg->pa_type == IWL_PA_INTERNAL) { |
78 | /* 2x2 hybrid phy type */ | ||
79 | iwl_write32(priv, CSR_GP_DRIVER_REG, | ||
80 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB); | ||
81 | } else if (priv->cfg->pa_type == IWL_PA_INTERNAL) { | ||
82 | /* 2x2 IPA phy type */ | 102 | /* 2x2 IPA phy type */ |
83 | iwl_write32(priv, CSR_GP_DRIVER_REG, | 103 | iwl_write32(priv, CSR_GP_DRIVER_REG, |
84 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | 104 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
85 | } | 105 | } |
86 | /* else do nothing, uCode configured */ | 106 | /* else do nothing, uCode configured */ |
107 | if (priv->cfg->ops->lib->temp_ops.set_calib_version) | ||
108 | priv->cfg->ops->lib->temp_ops.set_calib_version(priv); | ||
109 | } | ||
110 | |||
111 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | ||
112 | .min_nrg_cck = 97, | ||
113 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
114 | .auto_corr_min_ofdm = 80, | ||
115 | .auto_corr_min_ofdm_mrc = 128, | ||
116 | .auto_corr_min_ofdm_x1 = 105, | ||
117 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
118 | |||
119 | .auto_corr_max_ofdm = 145, | ||
120 | .auto_corr_max_ofdm_mrc = 232, | ||
121 | .auto_corr_max_ofdm_x1 = 110, | ||
122 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
123 | |||
124 | .auto_corr_min_cck = 125, | ||
125 | .auto_corr_max_cck = 175, | ||
126 | .auto_corr_min_cck_mrc = 160, | ||
127 | .auto_corr_max_cck_mrc = 310, | ||
128 | .nrg_th_cck = 97, | ||
129 | .nrg_th_ofdm = 100, | ||
130 | |||
131 | .barker_corr_th_min = 190, | ||
132 | .barker_corr_th_min_mrc = 390, | ||
133 | .nrg_th_cca = 62, | ||
134 | }; | ||
135 | |||
136 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | ||
137 | { | ||
138 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
139 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | ||
140 | priv->cfg->num_of_queues = | ||
141 | priv->cfg->mod_params->num_of_queues; | ||
142 | |||
143 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; | ||
144 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | ||
145 | priv->hw_params.scd_bc_tbls_size = | ||
146 | priv->cfg->num_of_queues * | ||
147 | sizeof(struct iwl5000_scd_bc_tbl); | ||
148 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
149 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | ||
150 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | ||
151 | |||
152 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | ||
153 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | ||
154 | |||
155 | priv->hw_params.max_bsm_size = 0; | ||
156 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
157 | BIT(IEEE80211_BAND_5GHZ); | ||
158 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
159 | |||
160 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | ||
161 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | ||
162 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
163 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
164 | |||
165 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | ||
166 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | ||
167 | |||
168 | /* Set initial sensitivity parameters */ | ||
169 | /* Set initial calibration set */ | ||
170 | priv->hw_params.sens = &iwl6000_sensitivity; | ||
171 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | ||
172 | case CSR_HW_REV_TYPE_6x50: | ||
173 | priv->hw_params.calib_init_cfg = | ||
174 | BIT(IWL_CALIB_XTAL) | | ||
175 | BIT(IWL_CALIB_DC) | | ||
176 | BIT(IWL_CALIB_LO) | | ||
177 | BIT(IWL_CALIB_TX_IQ) | | ||
178 | BIT(IWL_CALIB_BASE_BAND); | ||
179 | |||
180 | break; | ||
181 | default: | ||
182 | priv->hw_params.calib_init_cfg = | ||
183 | BIT(IWL_CALIB_XTAL) | | ||
184 | BIT(IWL_CALIB_LO) | | ||
185 | BIT(IWL_CALIB_TX_IQ) | | ||
186 | BIT(IWL_CALIB_BASE_BAND); | ||
187 | break; | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
194 | { | ||
195 | struct iwl6000_channel_switch_cmd cmd; | ||
196 | const struct iwl_channel_info *ch_info; | ||
197 | struct iwl_host_cmd hcmd = { | ||
198 | .id = REPLY_CHANNEL_SWITCH, | ||
199 | .len = sizeof(cmd), | ||
200 | .flags = CMD_SIZE_HUGE, | ||
201 | .data = &cmd, | ||
202 | }; | ||
203 | |||
204 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
205 | priv->active_rxon.channel, channel); | ||
206 | |||
207 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
208 | cmd.channel = cpu_to_le16(channel); | ||
209 | cmd.rxon_flags = priv->staging_rxon.flags; | ||
210 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | ||
211 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
212 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
213 | if (ch_info) | ||
214 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
215 | else { | ||
216 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
217 | priv->active_rxon.channel, channel); | ||
218 | return -EFAULT; | ||
219 | } | ||
220 | priv->switch_rxon.channel = cpu_to_le16(channel); | ||
221 | priv->switch_rxon.switch_in_progress = true; | ||
222 | |||
223 | return iwl_send_cmd_sync(priv, &hcmd); | ||
87 | } | 224 | } |
88 | 225 | ||
89 | static struct iwl_lib_ops iwl6000_lib = { | 226 | static struct iwl_lib_ops iwl6000_lib = { |
90 | .set_hw_params = iwl5000_hw_set_hw_params, | 227 | .set_hw_params = iwl6000_hw_set_hw_params, |
91 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 228 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
92 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 229 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, |
93 | .txq_set_sched = iwl5000_txq_set_sched, | 230 | .txq_set_sched = iwl5000_txq_set_sched, |
@@ -102,14 +239,16 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
102 | .load_ucode = iwl5000_load_ucode, | 239 | .load_ucode = iwl5000_load_ucode, |
103 | .dump_nic_event_log = iwl_dump_nic_event_log, | 240 | .dump_nic_event_log = iwl_dump_nic_event_log, |
104 | .dump_nic_error_log = iwl_dump_nic_error_log, | 241 | .dump_nic_error_log = iwl_dump_nic_error_log, |
242 | .dump_csr = iwl_dump_csr, | ||
243 | .dump_fh = iwl_dump_fh, | ||
105 | .init_alive_start = iwl5000_init_alive_start, | 244 | .init_alive_start = iwl5000_init_alive_start, |
106 | .alive_notify = iwl5000_alive_notify, | 245 | .alive_notify = iwl5000_alive_notify, |
107 | .send_tx_power = iwl5000_send_tx_power, | 246 | .send_tx_power = iwl5000_send_tx_power, |
108 | .update_chain_flags = iwl_update_chain_flags, | 247 | .update_chain_flags = iwl_update_chain_flags, |
248 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
109 | .apm_ops = { | 249 | .apm_ops = { |
110 | .init = iwl5000_apm_init, | 250 | .init = iwl_apm_init, |
111 | .reset = iwl5000_apm_reset, | 251 | .stop = iwl_apm_stop, |
112 | .stop = iwl5000_apm_stop, | ||
113 | .config = iwl6000_nic_config, | 252 | .config = iwl6000_nic_config, |
114 | .set_pwr_src = iwl_set_pwr_src, | 253 | .set_pwr_src = iwl_set_pwr_src, |
115 | }, | 254 | }, |
@@ -120,7 +259,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
120 | EEPROM_5000_REG_BAND_3_CHANNELS, | 259 | EEPROM_5000_REG_BAND_3_CHANNELS, |
121 | EEPROM_5000_REG_BAND_4_CHANNELS, | 260 | EEPROM_5000_REG_BAND_4_CHANNELS, |
122 | EEPROM_5000_REG_BAND_5_CHANNELS, | 261 | EEPROM_5000_REG_BAND_5_CHANNELS, |
123 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 262 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, |
124 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 263 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS |
125 | }, | 264 | }, |
126 | .verify_signature = iwlcore_eeprom_verify_signature, | 265 | .verify_signature = iwlcore_eeprom_verify_signature, |
@@ -137,27 +276,86 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
137 | .temperature = iwl5000_temperature, | 276 | .temperature = iwl5000_temperature, |
138 | .set_ct_kill = iwl6000_set_ct_threshold, | 277 | .set_ct_kill = iwl6000_set_ct_threshold, |
139 | }, | 278 | }, |
279 | .add_bcast_station = iwl_add_bcast_station, | ||
140 | }; | 280 | }; |
141 | 281 | ||
142 | static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { | 282 | static const struct iwl_ops iwl6000_ops = { |
143 | .get_hcmd_size = iwl5000_get_hcmd_size, | ||
144 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | ||
145 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
146 | .calc_rssi = iwl5000_calc_rssi, | ||
147 | }; | ||
148 | |||
149 | static struct iwl_ops iwl6000_ops = { | ||
150 | .ucode = &iwl5000_ucode, | 283 | .ucode = &iwl5000_ucode, |
151 | .lib = &iwl6000_lib, | 284 | .lib = &iwl6000_lib, |
152 | .hcmd = &iwl5000_hcmd, | 285 | .hcmd = &iwl5000_hcmd, |
153 | .utils = &iwl6000_hcmd_utils, | 286 | .utils = &iwl5000_hcmd_utils, |
287 | .led = &iwlagn_led_ops, | ||
288 | }; | ||
289 | |||
290 | static struct iwl_lib_ops iwl6050_lib = { | ||
291 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
292 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | ||
293 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | ||
294 | .txq_set_sched = iwl5000_txq_set_sched, | ||
295 | .txq_agg_enable = iwl5000_txq_agg_enable, | ||
296 | .txq_agg_disable = iwl5000_txq_agg_disable, | ||
297 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
298 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
299 | .txq_init = iwl_hw_tx_queue_init, | ||
300 | .rx_handler_setup = iwl5000_rx_handler_setup, | ||
301 | .setup_deferred_work = iwl5000_setup_deferred_work, | ||
302 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | ||
303 | .load_ucode = iwl5000_load_ucode, | ||
304 | .dump_nic_event_log = iwl_dump_nic_event_log, | ||
305 | .dump_nic_error_log = iwl_dump_nic_error_log, | ||
306 | .dump_csr = iwl_dump_csr, | ||
307 | .dump_fh = iwl_dump_fh, | ||
308 | .init_alive_start = iwl5000_init_alive_start, | ||
309 | .alive_notify = iwl5000_alive_notify, | ||
310 | .send_tx_power = iwl5000_send_tx_power, | ||
311 | .update_chain_flags = iwl_update_chain_flags, | ||
312 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
313 | .apm_ops = { | ||
314 | .init = iwl_apm_init, | ||
315 | .stop = iwl_apm_stop, | ||
316 | .config = iwl6000_nic_config, | ||
317 | .set_pwr_src = iwl_set_pwr_src, | ||
318 | }, | ||
319 | .eeprom_ops = { | ||
320 | .regulatory_bands = { | ||
321 | EEPROM_5000_REG_BAND_1_CHANNELS, | ||
322 | EEPROM_5000_REG_BAND_2_CHANNELS, | ||
323 | EEPROM_5000_REG_BAND_3_CHANNELS, | ||
324 | EEPROM_5000_REG_BAND_4_CHANNELS, | ||
325 | EEPROM_5000_REG_BAND_5_CHANNELS, | ||
326 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
327 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | ||
328 | }, | ||
329 | .verify_signature = iwlcore_eeprom_verify_signature, | ||
330 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | ||
331 | .release_semaphore = iwlcore_eeprom_release_semaphore, | ||
332 | .calib_version = iwl5000_eeprom_calib_version, | ||
333 | .query_addr = iwl5000_eeprom_query_addr, | ||
334 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | ||
335 | }, | ||
336 | .post_associate = iwl_post_associate, | ||
337 | .isr = iwl_isr_ict, | ||
338 | .config_ap = iwl_config_ap, | ||
339 | .temp_ops = { | ||
340 | .temperature = iwl5000_temperature, | ||
341 | .set_ct_kill = iwl6000_set_ct_threshold, | ||
342 | .set_calib_version = iwl6050_set_calib_version, | ||
343 | }, | ||
344 | .add_bcast_station = iwl_add_bcast_station, | ||
154 | }; | 345 | }; |
155 | 346 | ||
347 | static const struct iwl_ops iwl6050_ops = { | ||
348 | .ucode = &iwl5000_ucode, | ||
349 | .lib = &iwl6050_lib, | ||
350 | .hcmd = &iwl5000_hcmd, | ||
351 | .utils = &iwl5000_hcmd_utils, | ||
352 | .led = &iwlagn_led_ops, | ||
353 | }; | ||
156 | 354 | ||
157 | /* | 355 | /* |
158 | * "h": Hybrid configuration, use both internal and external Power Amplifier | 356 | * "i": Internal configuration, use internal Power Amplifier |
159 | */ | 357 | */ |
160 | struct iwl_cfg iwl6000h_2agn_cfg = { | 358 | struct iwl_cfg iwl6000i_2agn_cfg = { |
161 | .name = "6000 Series 2x2 AGN", | 359 | .name = "6000 Series 2x2 AGN", |
162 | .fw_name_pre = IWL6000_FW_PRE, | 360 | .fw_name_pre = IWL6000_FW_PRE, |
163 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 361 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
@@ -165,41 +363,90 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
165 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 363 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
166 | .ops = &iwl6000_ops, | 364 | .ops = &iwl6000_ops, |
167 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 365 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
168 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 366 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
169 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 367 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
368 | .num_of_queues = IWL50_NUM_QUEUES, | ||
369 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
170 | .mod_params = &iwl50_mod_params, | 370 | .mod_params = &iwl50_mod_params, |
171 | .valid_tx_ant = ANT_AB, | 371 | .valid_tx_ant = ANT_BC, |
172 | .valid_rx_ant = ANT_AB, | 372 | .valid_rx_ant = ANT_BC, |
173 | .need_pll_cfg = false, | 373 | .pll_cfg_val = 0, |
174 | .pa_type = IWL_PA_HYBRID, | 374 | .set_l0s = true, |
375 | .use_bsm = false, | ||
376 | .pa_type = IWL_PA_INTERNAL, | ||
175 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 377 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
176 | .shadow_ram_support = true, | 378 | .shadow_ram_support = true, |
177 | .ht_greenfield_support = true, | 379 | .ht_greenfield_support = true, |
380 | .led_compensation = 51, | ||
178 | .use_rts_for_ht = true, /* use rts/cts protection */ | 381 | .use_rts_for_ht = true, /* use rts/cts protection */ |
382 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
383 | .supports_idle = true, | ||
384 | .adv_thermal_throttle = true, | ||
385 | .support_ct_kill_exit = true, | ||
386 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
387 | .chain_noise_scale = 1000, | ||
179 | }; | 388 | }; |
180 | 389 | ||
181 | /* | 390 | struct iwl_cfg iwl6000i_2abg_cfg = { |
182 | * "i": Internal configuration, use internal Power Amplifier | 391 | .name = "6000 Series 2x2 ABG", |
183 | */ | ||
184 | struct iwl_cfg iwl6000i_2agn_cfg = { | ||
185 | .name = "6000 Series 2x2 AGN", | ||
186 | .fw_name_pre = IWL6000_FW_PRE, | 392 | .fw_name_pre = IWL6000_FW_PRE, |
187 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 393 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
188 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 394 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
189 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 395 | .sku = IWL_SKU_A|IWL_SKU_G, |
190 | .ops = &iwl6000_ops, | 396 | .ops = &iwl6000_ops, |
191 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 397 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
192 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 398 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
193 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 399 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
400 | .num_of_queues = IWL50_NUM_QUEUES, | ||
401 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
194 | .mod_params = &iwl50_mod_params, | 402 | .mod_params = &iwl50_mod_params, |
195 | .valid_tx_ant = ANT_BC, | 403 | .valid_tx_ant = ANT_BC, |
196 | .valid_rx_ant = ANT_BC, | 404 | .valid_rx_ant = ANT_BC, |
197 | .need_pll_cfg = false, | 405 | .pll_cfg_val = 0, |
406 | .set_l0s = true, | ||
407 | .use_bsm = false, | ||
198 | .pa_type = IWL_PA_INTERNAL, | 408 | .pa_type = IWL_PA_INTERNAL, |
199 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 409 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
200 | .shadow_ram_support = true, | 410 | .shadow_ram_support = true, |
201 | .ht_greenfield_support = true, | 411 | .ht_greenfield_support = true, |
202 | .use_rts_for_ht = true, /* use rts/cts protection */ | 412 | .led_compensation = 51, |
413 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
414 | .supports_idle = true, | ||
415 | .adv_thermal_throttle = true, | ||
416 | .support_ct_kill_exit = true, | ||
417 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
418 | .chain_noise_scale = 1000, | ||
419 | }; | ||
420 | |||
421 | struct iwl_cfg iwl6000i_2bg_cfg = { | ||
422 | .name = "6000 Series 2x2 BG", | ||
423 | .fw_name_pre = IWL6000_FW_PRE, | ||
424 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
425 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
426 | .sku = IWL_SKU_G, | ||
427 | .ops = &iwl6000_ops, | ||
428 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
429 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
430 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
431 | .num_of_queues = IWL50_NUM_QUEUES, | ||
432 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
433 | .mod_params = &iwl50_mod_params, | ||
434 | .valid_tx_ant = ANT_BC, | ||
435 | .valid_rx_ant = ANT_BC, | ||
436 | .pll_cfg_val = 0, | ||
437 | .set_l0s = true, | ||
438 | .use_bsm = false, | ||
439 | .pa_type = IWL_PA_INTERNAL, | ||
440 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
441 | .shadow_ram_support = true, | ||
442 | .ht_greenfield_support = true, | ||
443 | .led_compensation = 51, | ||
444 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
445 | .supports_idle = true, | ||
446 | .adv_thermal_throttle = true, | ||
447 | .support_ct_kill_exit = true, | ||
448 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
449 | .chain_noise_scale = 1000, | ||
203 | }; | 450 | }; |
204 | 451 | ||
205 | struct iwl_cfg iwl6050_2agn_cfg = { | 452 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -208,61 +455,93 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
208 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 455 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
209 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 456 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
210 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 457 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
211 | .ops = &iwl6000_ops, | 458 | .ops = &iwl6050_ops, |
212 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 459 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
213 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 460 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
214 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 461 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
462 | .num_of_queues = IWL50_NUM_QUEUES, | ||
463 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
215 | .mod_params = &iwl50_mod_params, | 464 | .mod_params = &iwl50_mod_params, |
216 | .valid_tx_ant = ANT_AB, | 465 | .valid_tx_ant = ANT_AB, |
217 | .valid_rx_ant = ANT_AB, | 466 | .valid_rx_ant = ANT_AB, |
218 | .need_pll_cfg = false, | 467 | .pll_cfg_val = 0, |
468 | .set_l0s = true, | ||
469 | .use_bsm = false, | ||
219 | .pa_type = IWL_PA_SYSTEM, | 470 | .pa_type = IWL_PA_SYSTEM, |
220 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 471 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
221 | .shadow_ram_support = true, | 472 | .shadow_ram_support = true, |
222 | .ht_greenfield_support = true, | 473 | .ht_greenfield_support = true, |
474 | .led_compensation = 51, | ||
223 | .use_rts_for_ht = true, /* use rts/cts protection */ | 475 | .use_rts_for_ht = true, /* use rts/cts protection */ |
476 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
477 | .supports_idle = true, | ||
478 | .adv_thermal_throttle = true, | ||
479 | .support_ct_kill_exit = true, | ||
480 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
481 | .chain_noise_scale = 1500, | ||
224 | }; | 482 | }; |
225 | 483 | ||
226 | struct iwl_cfg iwl6000_3agn_cfg = { | 484 | struct iwl_cfg iwl6050_2abg_cfg = { |
227 | .name = "6000 Series 3x3 AGN", | 485 | .name = "6050 Series 2x2 ABG", |
228 | .fw_name_pre = IWL6000_FW_PRE, | 486 | .fw_name_pre = IWL6050_FW_PRE, |
229 | .ucode_api_max = IWL6000_UCODE_API_MAX, | 487 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
230 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 488 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
231 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 489 | .sku = IWL_SKU_A|IWL_SKU_G, |
232 | .ops = &iwl6000_ops, | 490 | .ops = &iwl6050_ops, |
233 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 491 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
234 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 492 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
235 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 493 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
494 | .num_of_queues = IWL50_NUM_QUEUES, | ||
495 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
236 | .mod_params = &iwl50_mod_params, | 496 | .mod_params = &iwl50_mod_params, |
237 | .valid_tx_ant = ANT_ABC, | 497 | .valid_tx_ant = ANT_AB, |
238 | .valid_rx_ant = ANT_ABC, | 498 | .valid_rx_ant = ANT_AB, |
239 | .need_pll_cfg = false, | 499 | .pll_cfg_val = 0, |
500 | .set_l0s = true, | ||
501 | .use_bsm = false, | ||
240 | .pa_type = IWL_PA_SYSTEM, | 502 | .pa_type = IWL_PA_SYSTEM, |
241 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 503 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
242 | .shadow_ram_support = true, | 504 | .shadow_ram_support = true, |
243 | .ht_greenfield_support = true, | 505 | .ht_greenfield_support = true, |
244 | .use_rts_for_ht = true, /* use rts/cts protection */ | 506 | .led_compensation = 51, |
507 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
508 | .supports_idle = true, | ||
509 | .adv_thermal_throttle = true, | ||
510 | .support_ct_kill_exit = true, | ||
511 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
512 | .chain_noise_scale = 1500, | ||
245 | }; | 513 | }; |
246 | 514 | ||
247 | struct iwl_cfg iwl6050_3agn_cfg = { | 515 | struct iwl_cfg iwl6000_3agn_cfg = { |
248 | .name = "6050 Series 3x3 AGN", | 516 | .name = "6000 Series 3x3 AGN", |
249 | .fw_name_pre = IWL6050_FW_PRE, | 517 | .fw_name_pre = IWL6000_FW_PRE, |
250 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 518 | .ucode_api_max = IWL6000_UCODE_API_MAX, |
251 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 519 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
252 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 520 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
253 | .ops = &iwl6000_ops, | 521 | .ops = &iwl6000_ops, |
254 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 522 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
255 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 523 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
256 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 524 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
525 | .num_of_queues = IWL50_NUM_QUEUES, | ||
526 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
257 | .mod_params = &iwl50_mod_params, | 527 | .mod_params = &iwl50_mod_params, |
258 | .valid_tx_ant = ANT_ABC, | 528 | .valid_tx_ant = ANT_ABC, |
259 | .valid_rx_ant = ANT_ABC, | 529 | .valid_rx_ant = ANT_ABC, |
260 | .need_pll_cfg = false, | 530 | .pll_cfg_val = 0, |
531 | .set_l0s = true, | ||
532 | .use_bsm = false, | ||
261 | .pa_type = IWL_PA_SYSTEM, | 533 | .pa_type = IWL_PA_SYSTEM, |
262 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 534 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
263 | .shadow_ram_support = true, | 535 | .shadow_ram_support = true, |
264 | .ht_greenfield_support = true, | 536 | .ht_greenfield_support = true, |
537 | .led_compensation = 51, | ||
265 | .use_rts_for_ht = true, /* use rts/cts protection */ | 538 | .use_rts_for_ht = true, /* use rts/cts protection */ |
539 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
540 | .supports_idle = true, | ||
541 | .adv_thermal_throttle = true, | ||
542 | .support_ct_kill_exit = true, | ||
543 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
544 | .chain_noise_scale = 1000, | ||
266 | }; | 545 | }; |
267 | 546 | ||
268 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 547 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c new file mode 100644 index 000000000000..1a24946bc203 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/wireless.h> | ||
36 | #include <net/mac80211.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <asm/unaligned.h> | ||
39 | |||
40 | #include "iwl-commands.h" | ||
41 | #include "iwl-dev.h" | ||
42 | #include "iwl-core.h" | ||
43 | #include "iwl-io.h" | ||
44 | #include "iwl-agn-led.h" | ||
45 | |||
46 | /* Send led command */ | ||
47 | static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | ||
48 | { | ||
49 | struct iwl_host_cmd cmd = { | ||
50 | .id = REPLY_LEDS_CMD, | ||
51 | .len = sizeof(struct iwl_led_cmd), | ||
52 | .data = led_cmd, | ||
53 | .flags = CMD_ASYNC, | ||
54 | .callback = NULL, | ||
55 | }; | ||
56 | u32 reg; | ||
57 | |||
58 | reg = iwl_read32(priv, CSR_LED_REG); | ||
59 | if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) | ||
60 | iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); | ||
61 | |||
62 | return iwl_send_cmd(priv, &cmd); | ||
63 | } | ||
64 | |||
65 | /* Set led register off */ | ||
66 | static int iwl_led_on_reg(struct iwl_priv *priv) | ||
67 | { | ||
68 | IWL_DEBUG_LED(priv, "led on\n"); | ||
69 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /* Set led register off */ | ||
74 | static int iwl_led_off_reg(struct iwl_priv *priv) | ||
75 | { | ||
76 | IWL_DEBUG_LED(priv, "LED Reg off\n"); | ||
77 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | const struct iwl_led_ops iwlagn_led_ops = { | ||
82 | .cmd = iwl_send_led_cmd, | ||
83 | .on = iwl_led_on_reg, | ||
84 | .off = iwl_led_off_reg, | ||
85 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h new file mode 100644 index 000000000000..a594e4fdc6b8 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #ifndef __iwl_agn_led_h__ | ||
28 | #define __iwl_agn_led_h__ | ||
29 | |||
30 | extern const struct iwl_led_ops iwlagn_led_ops; | ||
31 | |||
32 | #endif /* __iwl_agn_led_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 81726ee32858..1460116d329f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/skbuff.h> | 28 | #include <linux/skbuff.h> |
29 | #include <linux/slab.h> | ||
29 | #include <linux/wireless.h> | 30 | #include <linux/wireless.h> |
30 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
31 | 32 | ||
@@ -75,104 +76,6 @@ static const u8 ant_toggle_lookup[] = { | |||
75 | /*ANT_ABC -> */ ANT_ABC, | 76 | /*ANT_ABC -> */ ANT_ABC, |
76 | }; | 77 | }; |
77 | 78 | ||
78 | /** | ||
79 | * struct iwl_rate_scale_data -- tx success history for one rate | ||
80 | */ | ||
81 | struct iwl_rate_scale_data { | ||
82 | u64 data; /* bitmap of successful frames */ | ||
83 | s32 success_counter; /* number of frames successful */ | ||
84 | s32 success_ratio; /* per-cent * 128 */ | ||
85 | s32 counter; /* number of frames attempted */ | ||
86 | s32 average_tpt; /* success ratio * expected throughput */ | ||
87 | unsigned long stamp; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | ||
92 | * | ||
93 | * There are two of these in struct iwl_lq_sta, | ||
94 | * one for "active", and one for "search". | ||
95 | */ | ||
96 | struct iwl_scale_tbl_info { | ||
97 | enum iwl_table_type lq_type; | ||
98 | u8 ant_type; | ||
99 | u8 is_SGI; /* 1 = short guard interval */ | ||
100 | u8 is_ht40; /* 1 = 40 MHz channel width */ | ||
101 | u8 is_dup; /* 1 = duplicated data streams */ | ||
102 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | ||
103 | u8 max_search; /* maximun number of tables we can search */ | ||
104 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | ||
105 | u32 current_rate; /* rate_n_flags, uCode API format */ | ||
106 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | ||
107 | }; | ||
108 | |||
109 | struct iwl_traffic_load { | ||
110 | unsigned long time_stamp; /* age of the oldest statistics */ | ||
111 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time | ||
112 | * slice */ | ||
113 | u32 total; /* total num of packets during the | ||
114 | * last TID_MAX_TIME_DIFF */ | ||
115 | u8 queue_count; /* number of queues that has | ||
116 | * been used since the last cleanup */ | ||
117 | u8 head; /* start of the circular buffer */ | ||
118 | }; | ||
119 | |||
120 | /** | ||
121 | * struct iwl_lq_sta -- driver's rate scaling private structure | ||
122 | * | ||
123 | * Pointer to this gets passed back and forth between driver and mac80211. | ||
124 | */ | ||
125 | struct iwl_lq_sta { | ||
126 | u8 active_tbl; /* index of active table, range 0-1 */ | ||
127 | u8 enable_counter; /* indicates HT mode */ | ||
128 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ | ||
129 | u8 search_better_tbl; /* 1: currently trying alternate mode */ | ||
130 | s32 last_tpt; | ||
131 | |||
132 | /* The following determine when to search for a new mode */ | ||
133 | u32 table_count_limit; | ||
134 | u32 max_failure_limit; /* # failed frames before new search */ | ||
135 | u32 max_success_limit; /* # successful frames before new search */ | ||
136 | u32 table_count; | ||
137 | u32 total_failed; /* total failed frames, any/all rates */ | ||
138 | u32 total_success; /* total successful frames, any/all rates */ | ||
139 | u64 flush_timer; /* time staying in mode before new search */ | ||
140 | |||
141 | u8 action_counter; /* # mode-switch actions tried */ | ||
142 | u8 is_green; | ||
143 | u8 is_dup; | ||
144 | enum ieee80211_band band; | ||
145 | u8 ibss_sta_added; | ||
146 | |||
147 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | ||
148 | u32 supp_rates; | ||
149 | u16 active_legacy_rate; | ||
150 | u16 active_siso_rate; | ||
151 | u16 active_mimo2_rate; | ||
152 | u16 active_mimo3_rate; | ||
153 | u16 active_rate_basic; | ||
154 | s8 max_rate_idx; /* Max rate set by user */ | ||
155 | u8 missed_rate_counter; | ||
156 | |||
157 | struct iwl_link_quality_cmd lq; | ||
158 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | ||
159 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | ||
160 | u8 tx_agg_tid_en; | ||
161 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
162 | struct dentry *rs_sta_dbgfs_scale_table_file; | ||
163 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
164 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
165 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | ||
166 | u32 dbg_fixed_rate; | ||
167 | #endif | ||
168 | struct iwl_priv *drv; | ||
169 | |||
170 | /* used to be in sta_info */ | ||
171 | int last_txrate_idx; | ||
172 | /* last tx rate_n_flags */ | ||
173 | u32 last_rate_n_flags; | ||
174 | }; | ||
175 | |||
176 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 79 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
177 | struct sk_buff *skb, | 80 | struct sk_buff *skb, |
178 | struct ieee80211_sta *sta, | 81 | struct ieee80211_sta *sta, |
@@ -190,84 +93,78 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
190 | {} | 93 | {} |
191 | #endif | 94 | #endif |
192 | 95 | ||
193 | /* | 96 | /** |
194 | * Expected throughput metrics for following rates: | 97 | * The following tables contain the expected throughput metrics for all rates |
195 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits | 98 | * |
196 | * "G" is the only table that supports CCK (the first 4 rates). | 99 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits |
100 | * | ||
101 | * where invalid entries are zeros. | ||
102 | * | ||
103 | * CCK rates are only valid in legacy table and will only be used in G | ||
104 | * (2.4 GHz) band. | ||
197 | */ | 105 | */ |
198 | 106 | ||
199 | static s32 expected_tpt_A[IWL_RATE_COUNT] = { | 107 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { |
200 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 | 108 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0 |
201 | }; | ||
202 | |||
203 | static s32 expected_tpt_G[IWL_RATE_COUNT] = { | ||
204 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186 | ||
205 | }; | ||
206 | |||
207 | static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = { | ||
208 | 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202 | ||
209 | }; | ||
210 | |||
211 | static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { | ||
212 | 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 | ||
213 | }; | ||
214 | |||
215 | static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = { | ||
216 | 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 | ||
217 | }; | ||
218 | |||
219 | static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = { | ||
220 | 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 | ||
221 | }; | ||
222 | |||
223 | static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { | ||
224 | 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 | ||
225 | }; | ||
226 | |||
227 | static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { | ||
228 | 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 | ||
229 | }; | 109 | }; |
230 | 110 | ||
231 | static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { | 111 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { |
232 | 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 | 112 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */ |
113 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */ | ||
114 | {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */ | ||
115 | {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */ | ||
233 | }; | 116 | }; |
234 | 117 | ||
235 | static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { | 118 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { |
236 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 | 119 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ |
120 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ | ||
121 | {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */ | ||
122 | {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */ | ||
237 | }; | 123 | }; |
238 | 124 | ||
239 | /* Expected throughput metric MIMO3 */ | 125 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { |
240 | static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { | 126 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */ |
241 | 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 | 127 | {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */ |
128 | {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */ | ||
129 | {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/ | ||
242 | }; | 130 | }; |
243 | 131 | ||
244 | static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { | 132 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { |
245 | 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 | 133 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ |
134 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ | ||
135 | {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */ | ||
136 | {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */ | ||
246 | }; | 137 | }; |
247 | 138 | ||
248 | static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { | 139 | static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { |
249 | 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 | 140 | {0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */ |
141 | {0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */ | ||
142 | {0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */ | ||
143 | {0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */ | ||
250 | }; | 144 | }; |
251 | 145 | ||
252 | static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { | 146 | static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { |
253 | 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 | 147 | {0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */ |
148 | {0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */ | ||
149 | {0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */ | ||
150 | {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */ | ||
254 | }; | 151 | }; |
255 | 152 | ||
256 | /* mbps, mcs */ | 153 | /* mbps, mcs */ |
257 | const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 154 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { |
258 | {"1", ""}, | 155 | { "1", "BPSK DSSS"}, |
259 | {"2", ""}, | 156 | { "2", "QPSK DSSS"}, |
260 | {"5.5", ""}, | 157 | {"5.5", "BPSK CCK"}, |
261 | {"11", ""}, | 158 | { "11", "QPSK CCK"}, |
262 | {"6", "BPSK 1/2"}, | 159 | { "6", "BPSK 1/2"}, |
263 | {"9", "BPSK 1/2"}, | 160 | { "9", "BPSK 1/2"}, |
264 | {"12", "QPSK 1/2"}, | 161 | { "12", "QPSK 1/2"}, |
265 | {"18", "QPSK 3/4"}, | 162 | { "18", "QPSK 3/4"}, |
266 | {"24", "16QAM 1/2"}, | 163 | { "24", "16QAM 1/2"}, |
267 | {"36", "16QAM 3/4"}, | 164 | { "36", "16QAM 3/4"}, |
268 | {"48", "64QAM 2/3"}, | 165 | { "48", "64QAM 2/3"}, |
269 | {"54", "64QAM 3/4"}, | 166 | { "54", "64QAM 3/4"}, |
270 | {"60", "64QAM 5/6"} | 167 | { "60", "64QAM 5/6"}, |
271 | }; | 168 | }; |
272 | 169 | ||
273 | #define MCS_INDEX_PER_STREAM (8) | 170 | #define MCS_INDEX_PER_STREAM (8) |
@@ -402,10 +299,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
402 | struct iwl_lq_sta *lq_data, u8 tid, | 299 | struct iwl_lq_sta *lq_data, u8 tid, |
403 | struct ieee80211_sta *sta) | 300 | struct ieee80211_sta *sta) |
404 | { | 301 | { |
302 | int ret; | ||
303 | |||
405 | 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) { |
406 | 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", |
407 | sta->addr, tid); | 306 | sta->addr, tid); |
408 | ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); | 307 | ret = ieee80211_start_tx_ba_session(sta, tid); |
308 | if (ret == -EAGAIN) { | ||
309 | /* | ||
310 | * driver and mac80211 is out of sync | ||
311 | * this might be cause by reloading firmware | ||
312 | * stop the tx ba session here | ||
313 | */ | ||
314 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | ||
315 | tid); | ||
316 | ret = ieee80211_stop_tx_ba_session(sta, tid, | ||
317 | WLAN_BACK_INITIATOR); | ||
318 | } | ||
409 | } | 319 | } |
410 | } | 320 | } |
411 | 321 | ||
@@ -436,6 +346,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
436 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); | 346 | !!(rate_n_flags & RATE_MCS_ANT_C_MSK); |
437 | } | 347 | } |
438 | 348 | ||
349 | /* | ||
350 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
351 | * that wraps a NULL pointer check | ||
352 | */ | ||
353 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
354 | { | ||
355 | if (tbl->expected_tpt) | ||
356 | return tbl->expected_tpt[rs_index]; | ||
357 | return 0; | ||
358 | } | ||
359 | |||
439 | /** | 360 | /** |
440 | * rs_collect_tx_data - Update the success/failure sliding window | 361 | * rs_collect_tx_data - Update the success/failure sliding window |
441 | * | 362 | * |
@@ -443,19 +364,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
443 | * at this rate. window->data contains the bitmask of successful | 364 | * at this rate. window->data contains the bitmask of successful |
444 | * packets. | 365 | * packets. |
445 | */ | 366 | */ |
446 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 367 | static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl, |
447 | int scale_index, s32 tpt, int retries, | 368 | int scale_index, int attempts, int successes) |
448 | int successes) | ||
449 | { | 369 | { |
450 | struct iwl_rate_scale_data *window = NULL; | 370 | struct iwl_rate_scale_data *window = NULL; |
451 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); | 371 | static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); |
452 | s32 fail_count; | 372 | s32 fail_count, tpt; |
453 | 373 | ||
454 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 374 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
455 | return -EINVAL; | 375 | return -EINVAL; |
456 | 376 | ||
457 | /* Select data for current tx bit rate */ | 377 | /* Select window for current tx bit rate */ |
458 | window = &(windows[scale_index]); | 378 | window = &(tbl->win[scale_index]); |
379 | |||
380 | /* Get expected throughput */ | ||
381 | tpt = get_expected_tpt(tbl, scale_index); | ||
459 | 382 | ||
460 | /* | 383 | /* |
461 | * Keep track of only the latest 62 tx frame attempts in this rate's | 384 | * Keep track of only the latest 62 tx frame attempts in this rate's |
@@ -465,7 +388,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | |||
465 | * subtract "1" from the success counter (this is the main reason | 388 | * subtract "1" from the success counter (this is the main reason |
466 | * we keep these bitmaps!). | 389 | * we keep these bitmaps!). |
467 | */ | 390 | */ |
468 | while (retries > 0) { | 391 | while (attempts > 0) { |
469 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | 392 | if (window->counter >= IWL_RATE_MAX_WINDOW) { |
470 | 393 | ||
471 | /* remove earliest */ | 394 | /* remove earliest */ |
@@ -480,17 +403,17 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | |||
480 | /* Increment frames-attempted counter */ | 403 | /* Increment frames-attempted counter */ |
481 | window->counter++; | 404 | window->counter++; |
482 | 405 | ||
483 | /* Shift bitmap by one frame (throw away oldest history), | 406 | /* Shift bitmap by one frame to throw away oldest history */ |
484 | * OR in "1", and increment "success" if this | ||
485 | * frame was successful. */ | ||
486 | window->data <<= 1; | 407 | window->data <<= 1; |
408 | |||
409 | /* Mark the most recent #successes attempts as successful */ | ||
487 | if (successes > 0) { | 410 | if (successes > 0) { |
488 | window->success_counter++; | 411 | window->success_counter++; |
489 | window->data |= 0x1; | 412 | window->data |= 0x1; |
490 | successes--; | 413 | successes--; |
491 | } | 414 | } |
492 | 415 | ||
493 | retries--; | 416 | attempts--; |
494 | } | 417 | } |
495 | 418 | ||
496 | /* Calculate current success ratio, avoid divide-by-0! */ | 419 | /* Calculate current success ratio, avoid divide-by-0! */ |
@@ -671,7 +594,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
671 | * there are no non-GF stations present in the BSS. | 594 | * there are no non-GF stations present in the BSS. |
672 | */ | 595 | */ |
673 | static inline u8 rs_use_green(struct ieee80211_sta *sta, | 596 | static inline u8 rs_use_green(struct ieee80211_sta *sta, |
674 | struct iwl_ht_info *ht_conf) | 597 | struct iwl_ht_config *ht_conf) |
675 | { | 598 | { |
676 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 599 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
677 | !(ht_conf->non_GF_STA_present); | 600 | !(ht_conf->non_GF_STA_present); |
@@ -821,28 +744,34 @@ out: | |||
821 | } | 744 | } |
822 | 745 | ||
823 | /* | 746 | /* |
747 | * Simple function to compare two rate scale table types | ||
748 | */ | ||
749 | static bool table_type_matches(struct iwl_scale_tbl_info *a, | ||
750 | struct iwl_scale_tbl_info *b) | ||
751 | { | ||
752 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | ||
753 | (a->is_SGI == b->is_SGI); | ||
754 | } | ||
755 | |||
756 | /* | ||
824 | * mac80211 sends us Tx status | 757 | * mac80211 sends us Tx status |
825 | */ | 758 | */ |
826 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | 759 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, |
827 | struct ieee80211_sta *sta, void *priv_sta, | 760 | struct ieee80211_sta *sta, void *priv_sta, |
828 | struct sk_buff *skb) | 761 | struct sk_buff *skb) |
829 | { | 762 | { |
830 | int status; | 763 | int legacy_success; |
831 | u8 retries; | 764 | int retries; |
832 | int rs_index, mac_index, index = 0; | 765 | int rs_index, mac_index, i; |
833 | struct iwl_lq_sta *lq_sta = priv_sta; | 766 | struct iwl_lq_sta *lq_sta = priv_sta; |
834 | struct iwl_link_quality_cmd *table; | 767 | struct iwl_link_quality_cmd *table; |
835 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 768 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
836 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 769 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
837 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 770 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
838 | struct iwl_rate_scale_data *window = NULL; | ||
839 | struct iwl_rate_scale_data *search_win = NULL; | ||
840 | enum mac80211_rate_control_flags mac_flags; | 771 | enum mac80211_rate_control_flags mac_flags; |
841 | u32 tx_rate; | 772 | u32 tx_rate; |
842 | struct iwl_scale_tbl_info tbl_type; | 773 | struct iwl_scale_tbl_info tbl_type; |
843 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; | 774 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; |
844 | u8 active_index = 0; | ||
845 | s32 tpt = 0; | ||
846 | 775 | ||
847 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 776 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
848 | 777 | ||
@@ -850,30 +779,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
850 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 779 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
851 | return; | 780 | return; |
852 | 781 | ||
853 | /* This packet was aggregated but doesn't carry rate scale info */ | 782 | /* This packet was aggregated but doesn't carry status info */ |
854 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 783 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
855 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 784 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
856 | return; | 785 | return; |
857 | 786 | ||
858 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
859 | retries = 0; | ||
860 | else | ||
861 | retries = info->status.rates[0].count - 1; | ||
862 | |||
863 | if (retries > 15) | ||
864 | retries = 15; | ||
865 | |||
866 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 787 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
867 | !lq_sta->ibss_sta_added) | 788 | !lq_sta->ibss_sta_added) |
868 | goto out; | 789 | return; |
869 | |||
870 | table = &lq_sta->lq; | ||
871 | active_index = lq_sta->active_tbl; | ||
872 | |||
873 | curr_tbl = &(lq_sta->lq_info[active_index]); | ||
874 | search_tbl = &(lq_sta->lq_info[(1 - active_index)]); | ||
875 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
876 | search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); | ||
877 | 790 | ||
878 | /* | 791 | /* |
879 | * Ignore this Tx frame response if its initial rate doesn't match | 792 | * Ignore this Tx frame response if its initial rate doesn't match |
@@ -883,6 +796,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
883 | * to check "search" mode, or a prior "search" mode after we've moved | 796 | * to check "search" mode, or a prior "search" mode after we've moved |
884 | * to a new "search" mode (which might become the new "active" mode). | 797 | * to a new "search" mode (which might become the new "active" mode). |
885 | */ | 798 | */ |
799 | table = &lq_sta->lq; | ||
886 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 800 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
887 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 801 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); |
888 | if (priv->band == IEEE80211_BAND_5GHZ) | 802 | if (priv->band == IEEE80211_BAND_5GHZ) |
@@ -901,7 +815,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
901 | if (priv->band == IEEE80211_BAND_2GHZ) | 815 | if (priv->band == IEEE80211_BAND_2GHZ) |
902 | mac_index += IWL_FIRST_OFDM_RATE; | 816 | mac_index += IWL_FIRST_OFDM_RATE; |
903 | } | 817 | } |
904 | 818 | /* Here we actually compare this rate to the latest LQ command */ | |
905 | if ((mac_index < 0) || | 819 | if ((mac_index < 0) || |
906 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 820 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
907 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 821 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || |
@@ -911,124 +825,98 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
911 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 825 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
912 | (rs_index != mac_index)) { | 826 | (rs_index != mac_index)) { |
913 | IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); | 827 | IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); |
914 | /* the last LQ command could failed so the LQ in ucode not | 828 | /* |
915 | * the same in driver sync up | 829 | * Since rates mis-match, the last LQ command may have failed. |
830 | * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with | ||
831 | * ... driver. | ||
916 | */ | 832 | */ |
917 | lq_sta->missed_rate_counter++; | 833 | lq_sta->missed_rate_counter++; |
918 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 834 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
919 | lq_sta->missed_rate_counter = 0; | 835 | lq_sta->missed_rate_counter = 0; |
920 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 836 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
921 | } | 837 | } |
922 | goto out; | 838 | /* Regardless, ignore this status info for outdated rate */ |
923 | } | 839 | return; |
924 | 840 | } else | |
925 | lq_sta->missed_rate_counter = 0; | 841 | /* Rate did match, so reset the missed_rate_counter */ |
926 | /* Update frame history window with "failure" for each Tx retry. */ | 842 | lq_sta->missed_rate_counter = 0; |
927 | while (retries) { | 843 | |
928 | /* Look up the rate and other info used for each tx attempt. | 844 | /* Figure out if rate scale algorithm is in active or search table */ |
929 | * Each tx attempt steps one entry deeper in the rate table. */ | 845 | if (table_type_matches(&tbl_type, |
930 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 846 | &(lq_sta->lq_info[lq_sta->active_tbl]))) { |
931 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | 847 | curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
932 | &tbl_type, &rs_index); | 848 | other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
933 | 849 | } else if (table_type_matches(&tbl_type, | |
934 | /* If type matches "search" table, | 850 | &lq_sta->lq_info[1 - lq_sta->active_tbl])) { |
935 | * add failure to "search" history */ | 851 | curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); |
936 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 852 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
937 | (tbl_type.ant_type == search_tbl->ant_type) && | 853 | } else { |
938 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 854 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
939 | if (search_tbl->expected_tpt) | 855 | return; |
940 | tpt = search_tbl->expected_tpt[rs_index]; | ||
941 | else | ||
942 | tpt = 0; | ||
943 | rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); | ||
944 | |||
945 | /* Else if type matches "current/active" table, | ||
946 | * add failure to "current/active" history */ | ||
947 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | ||
948 | (tbl_type.ant_type == curr_tbl->ant_type) && | ||
949 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | ||
950 | if (curr_tbl->expected_tpt) | ||
951 | tpt = curr_tbl->expected_tpt[rs_index]; | ||
952 | else | ||
953 | tpt = 0; | ||
954 | rs_collect_tx_data(window, rs_index, tpt, 1, 0); | ||
955 | } | ||
956 | |||
957 | /* If not searching for a new mode, increment failed counter | ||
958 | * ... this helps determine when to start searching again */ | ||
959 | if (lq_sta->stay_in_tbl) | ||
960 | lq_sta->total_failed++; | ||
961 | --retries; | ||
962 | index++; | ||
963 | |||
964 | } | 856 | } |
965 | 857 | ||
966 | /* | 858 | /* |
967 | * Find (by rate) the history window to update with final Tx attempt; | 859 | * Updating the frame history depends on whether packets were |
968 | * if Tx was successful first try, use original rate, | 860 | * aggregated. |
969 | * else look up the rate that was, finally, successful. | 861 | * |
862 | * For aggregation, all packets were transmitted at the same rate, the | ||
863 | * first index into rate scale table. | ||
970 | */ | 864 | */ |
971 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 865 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
972 | lq_sta->last_rate_n_flags = tx_rate; | 866 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
973 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 867 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
974 | 868 | &rs_index); | |
975 | /* Update frame history window with "success" if Tx got ACKed ... */ | 869 | rs_collect_tx_data(curr_tbl, rs_index, |
976 | status = !!(info->flags & IEEE80211_TX_STAT_ACK); | 870 | info->status.ampdu_ack_len, |
977 | 871 | info->status.ampdu_ack_map); | |
978 | /* If type matches "search" table, | 872 | |
979 | * add final tx status to "search" history */ | 873 | /* Update success/fail counts if not searching for new mode */ |
980 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 874 | if (lq_sta->stay_in_tbl) { |
981 | (tbl_type.ant_type == search_tbl->ant_type) && | ||
982 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | ||
983 | if (search_tbl->expected_tpt) | ||
984 | tpt = search_tbl->expected_tpt[rs_index]; | ||
985 | else | ||
986 | tpt = 0; | ||
987 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
988 | rs_collect_tx_data(search_win, rs_index, tpt, | ||
989 | info->status.ampdu_ack_len, | ||
990 | info->status.ampdu_ack_map); | ||
991 | else | ||
992 | rs_collect_tx_data(search_win, rs_index, tpt, | ||
993 | 1, status); | ||
994 | /* Else if type matches "current/active" table, | ||
995 | * add final tx status to "current/active" history */ | ||
996 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | ||
997 | (tbl_type.ant_type == curr_tbl->ant_type) && | ||
998 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | ||
999 | if (curr_tbl->expected_tpt) | ||
1000 | tpt = curr_tbl->expected_tpt[rs_index]; | ||
1001 | else | ||
1002 | tpt = 0; | ||
1003 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
1004 | rs_collect_tx_data(window, rs_index, tpt, | ||
1005 | info->status.ampdu_ack_len, | ||
1006 | info->status.ampdu_ack_map); | ||
1007 | else | ||
1008 | rs_collect_tx_data(window, rs_index, tpt, | ||
1009 | 1, status); | ||
1010 | } | ||
1011 | |||
1012 | /* If not searching for new mode, increment success/failed counter | ||
1013 | * ... these help determine when to start searching again */ | ||
1014 | if (lq_sta->stay_in_tbl) { | ||
1015 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | ||
1016 | lq_sta->total_success += info->status.ampdu_ack_map; | 875 | lq_sta->total_success += info->status.ampdu_ack_map; |
1017 | lq_sta->total_failed += | 876 | lq_sta->total_failed += (info->status.ampdu_ack_len - |
1018 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); | 877 | info->status.ampdu_ack_map); |
1019 | } else { | 878 | } |
1020 | if (status) | 879 | } else { |
1021 | lq_sta->total_success++; | 880 | /* |
881 | * For legacy, update frame history with for each Tx retry. | ||
882 | */ | ||
883 | retries = info->status.rates[0].count - 1; | ||
884 | /* HW doesn't send more than 15 retries */ | ||
885 | retries = min(retries, 15); | ||
886 | |||
887 | /* The last transmission may have been successful */ | ||
888 | legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); | ||
889 | /* Collect data for each rate used during failed TX attempts */ | ||
890 | for (i = 0; i <= retries; ++i) { | ||
891 | tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags); | ||
892 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | ||
893 | &tbl_type, &rs_index); | ||
894 | /* | ||
895 | * Only collect stats if retried rate is in the same RS | ||
896 | * table as active/search. | ||
897 | */ | ||
898 | if (table_type_matches(&tbl_type, curr_tbl)) | ||
899 | tmp_tbl = curr_tbl; | ||
900 | else if (table_type_matches(&tbl_type, other_tbl)) | ||
901 | tmp_tbl = other_tbl; | ||
1022 | else | 902 | else |
1023 | lq_sta->total_failed++; | 903 | continue; |
904 | rs_collect_tx_data(tmp_tbl, rs_index, 1, | ||
905 | i < retries ? 0 : legacy_success); | ||
906 | } | ||
907 | |||
908 | /* Update success/fail counts if not searching for new mode */ | ||
909 | if (lq_sta->stay_in_tbl) { | ||
910 | lq_sta->total_success += legacy_success; | ||
911 | lq_sta->total_failed += retries + (1 - legacy_success); | ||
1024 | } | 912 | } |
1025 | } | 913 | } |
914 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | ||
915 | lq_sta->last_rate_n_flags = tx_rate; | ||
1026 | 916 | ||
1027 | /* See if there's a better rate or modulation mode to try. */ | 917 | /* See if there's a better rate or modulation mode to try. */ |
1028 | if (sta && sta->supp_rates[sband->band]) | 918 | if (sta && sta->supp_rates[sband->band]) |
1029 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 919 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
1030 | out: | ||
1031 | return; | ||
1032 | } | 920 | } |
1033 | 921 | ||
1034 | /* | 922 | /* |
@@ -1066,43 +954,45 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, | |||
1066 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | 954 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, |
1067 | struct iwl_scale_tbl_info *tbl) | 955 | struct iwl_scale_tbl_info *tbl) |
1068 | { | 956 | { |
957 | /* Used to choose among HT tables */ | ||
958 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; | ||
959 | |||
960 | /* Check for invalid LQ type */ | ||
961 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) { | ||
962 | tbl->expected_tpt = expected_tpt_legacy; | ||
963 | return; | ||
964 | } | ||
965 | |||
966 | /* Legacy rates have only one table */ | ||
1069 | if (is_legacy(tbl->lq_type)) { | 967 | if (is_legacy(tbl->lq_type)) { |
1070 | if (!is_a_band(tbl->lq_type)) | 968 | tbl->expected_tpt = expected_tpt_legacy; |
1071 | tbl->expected_tpt = expected_tpt_G; | 969 | return; |
1072 | else | 970 | } |
1073 | tbl->expected_tpt = expected_tpt_A; | 971 | |
1074 | } else if (is_siso(tbl->lq_type)) { | 972 | /* Choose among many HT tables depending on number of streams |
1075 | if (tbl->is_ht40 && !lq_sta->is_dup) | 973 | * (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation |
1076 | if (tbl->is_SGI) | 974 | * status */ |
1077 | tbl->expected_tpt = expected_tpt_siso40MHzSGI; | 975 | if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1078 | else | 976 | ht_tbl_pointer = expected_tpt_siso20MHz; |
1079 | tbl->expected_tpt = expected_tpt_siso40MHz; | 977 | else if (is_siso(tbl->lq_type)) |
1080 | else if (tbl->is_SGI) | 978 | ht_tbl_pointer = expected_tpt_siso40MHz; |
1081 | tbl->expected_tpt = expected_tpt_siso20MHzSGI; | 979 | else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1082 | else | 980 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; |
1083 | tbl->expected_tpt = expected_tpt_siso20MHz; | 981 | else if (is_mimo2(tbl->lq_type)) |
1084 | } else if (is_mimo2(tbl->lq_type)) { | 982 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; |
1085 | if (tbl->is_ht40 && !lq_sta->is_dup) | 983 | else if (is_mimo3(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1086 | if (tbl->is_SGI) | 984 | ht_tbl_pointer = expected_tpt_mimo3_20MHz; |
1087 | tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; | 985 | else /* if (is_mimo3(tbl->lq_type)) <-- must be true */ |
1088 | else | 986 | ht_tbl_pointer = expected_tpt_mimo3_40MHz; |
1089 | tbl->expected_tpt = expected_tpt_mimo2_40MHz; | 987 | |
1090 | else if (tbl->is_SGI) | 988 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ |
1091 | tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; | 989 | tbl->expected_tpt = ht_tbl_pointer[0]; |
1092 | else | 990 | else if (tbl->is_SGI && !lq_sta->is_agg) /* SGI */ |
1093 | tbl->expected_tpt = expected_tpt_mimo2_20MHz; | 991 | tbl->expected_tpt = ht_tbl_pointer[1]; |
1094 | } else if (is_mimo3(tbl->lq_type)) { | 992 | else if (!tbl->is_SGI && lq_sta->is_agg) /* AGG */ |
1095 | if (tbl->is_ht40 && !lq_sta->is_dup) | 993 | tbl->expected_tpt = ht_tbl_pointer[2]; |
1096 | if (tbl->is_SGI) | 994 | else /* AGG+SGI */ |
1097 | tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; | 995 | tbl->expected_tpt = ht_tbl_pointer[3]; |
1098 | else | ||
1099 | tbl->expected_tpt = expected_tpt_mimo3_40MHz; | ||
1100 | else if (tbl->is_SGI) | ||
1101 | tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI; | ||
1102 | else | ||
1103 | tbl->expected_tpt = expected_tpt_mimo3_20MHz; | ||
1104 | } else | ||
1105 | tbl->expected_tpt = expected_tpt_G; | ||
1106 | } | 996 | } |
1107 | 997 | ||
1108 | /* | 998 | /* |
@@ -2077,6 +1967,14 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2077 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; | 1967 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; |
2078 | 1968 | ||
2079 | tid = rs_tl_add_packet(lq_sta, hdr); | 1969 | tid = rs_tl_add_packet(lq_sta, hdr); |
1970 | if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { | ||
1971 | tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; | ||
1972 | if (tid_data->agg.state == IWL_AGG_OFF) | ||
1973 | lq_sta->is_agg = 0; | ||
1974 | else | ||
1975 | lq_sta->is_agg = 1; | ||
1976 | } else | ||
1977 | lq_sta->is_agg = 0; | ||
2080 | 1978 | ||
2081 | /* | 1979 | /* |
2082 | * Select rate-scale / modulation-mode table to work with in | 1980 | * Select rate-scale / modulation-mode table to work with in |
@@ -2177,10 +2075,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2177 | 2075 | ||
2178 | goto out; | 2076 | goto out; |
2179 | } | 2077 | } |
2180 | |||
2181 | /* Else we have enough samples; calculate estimate of | 2078 | /* Else we have enough samples; calculate estimate of |
2182 | * actual average throughput */ | 2079 | * actual average throughput */ |
2183 | 2080 | ||
2081 | /* Sanity-check TPT calculations */ | ||
2184 | BUG_ON(window->average_tpt != ((window->success_ratio * | 2082 | BUG_ON(window->average_tpt != ((window->success_ratio * |
2185 | tbl->expected_tpt[index] + 64) / 128)); | 2083 | tbl->expected_tpt[index] + 64) / 128)); |
2186 | 2084 | ||
@@ -2584,22 +2482,13 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | |||
2584 | gfp_t gfp) | 2482 | gfp_t gfp) |
2585 | { | 2483 | { |
2586 | struct iwl_lq_sta *lq_sta; | 2484 | struct iwl_lq_sta *lq_sta; |
2485 | struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; | ||
2587 | struct iwl_priv *priv; | 2486 | struct iwl_priv *priv; |
2588 | int i, j; | ||
2589 | 2487 | ||
2590 | priv = (struct iwl_priv *)priv_rate; | 2488 | priv = (struct iwl_priv *)priv_rate; |
2591 | IWL_DEBUG_RATE(priv, "create station rate scale window\n"); | 2489 | IWL_DEBUG_RATE(priv, "create station rate scale window\n"); |
2592 | 2490 | ||
2593 | lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); | 2491 | lq_sta = &sta_priv->lq_sta; |
2594 | |||
2595 | if (lq_sta == NULL) | ||
2596 | return NULL; | ||
2597 | lq_sta->lq.sta_id = 0xff; | ||
2598 | |||
2599 | |||
2600 | for (j = 0; j < LQ_SIZE; j++) | ||
2601 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
2602 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2603 | 2492 | ||
2604 | return lq_sta; | 2493 | return lq_sta; |
2605 | } | 2494 | } |
@@ -2613,6 +2502,12 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2613 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 2502 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
2614 | struct iwl_lq_sta *lq_sta = priv_sta; | 2503 | struct iwl_lq_sta *lq_sta = priv_sta; |
2615 | 2504 | ||
2505 | lq_sta->lq.sta_id = 0xff; | ||
2506 | |||
2507 | for (j = 0; j < LQ_SIZE; j++) | ||
2508 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
2509 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | ||
2510 | |||
2616 | lq_sta->flush_timer = 0; | 2511 | lq_sta->flush_timer = 0; |
2617 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | 2512 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
2618 | for (j = 0; j < LQ_SIZE; j++) | 2513 | for (j = 0; j < LQ_SIZE; j++) |
@@ -2690,6 +2585,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2690 | lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); | 2585 | lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); |
2691 | if (sband->band == IEEE80211_BAND_5GHZ) | 2586 | if (sband->band == IEEE80211_BAND_5GHZ) |
2692 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 2587 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
2588 | lq_sta->is_agg = 0; | ||
2693 | 2589 | ||
2694 | rs_initialize_lq(priv, conf, sta, lq_sta); | 2590 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2695 | } | 2591 | } |
@@ -2808,7 +2704,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2808 | repeat_rate--; | 2704 | repeat_rate--; |
2809 | } | 2705 | } |
2810 | 2706 | ||
2811 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX; | 2707 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
2812 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 2708 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
2813 | lq_cmd->agg_params.agg_time_limit = | 2709 | lq_cmd->agg_params.agg_time_limit = |
2814 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2710 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
@@ -2827,11 +2723,9 @@ static void rs_free(void *priv_rate) | |||
2827 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, | 2723 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, |
2828 | void *priv_sta) | 2724 | void *priv_sta) |
2829 | { | 2725 | { |
2830 | struct iwl_lq_sta *lq_sta = priv_sta; | ||
2831 | struct iwl_priv *priv __maybe_unused = priv_r; | 2726 | struct iwl_priv *priv __maybe_unused = priv_r; |
2832 | 2727 | ||
2833 | IWL_DEBUG_RATE(priv, "enter\n"); | 2728 | IWL_DEBUG_RATE(priv, "enter\n"); |
2834 | kfree(lq_sta); | ||
2835 | IWL_DEBUG_RATE(priv, "leave\n"); | 2729 | IWL_DEBUG_RATE(priv, "leave\n"); |
2836 | } | 2730 | } |
2837 | 2731 | ||
@@ -2942,8 +2836,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2942 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); | 2836 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); |
2943 | desc += sprintf(buff+desc, " %s", | 2837 | desc += sprintf(buff+desc, " %s", |
2944 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 2838 | (tbl->is_ht40) ? "40MHz" : "20MHz"); |
2945 | desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", | 2839 | desc += sprintf(buff+desc, " %s %s %s\n", (tbl->is_SGI) ? "SGI" : "", |
2946 | (lq_sta->is_green) ? "GF enabled" : ""); | 2840 | (lq_sta->is_green) ? "GF enabled" : "", |
2841 | (lq_sta->is_agg) ? "AGG on" : ""); | ||
2947 | } | 2842 | } |
2948 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 2843 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
2949 | lq_sta->last_rate_n_flags); | 2844 | lq_sta->last_rate_n_flags); |
@@ -3076,16 +2971,16 @@ static void rs_add_debugfs(void *priv, void *priv_sta, | |||
3076 | { | 2971 | { |
3077 | struct iwl_lq_sta *lq_sta = priv_sta; | 2972 | struct iwl_lq_sta *lq_sta = priv_sta; |
3078 | lq_sta->rs_sta_dbgfs_scale_table_file = | 2973 | lq_sta->rs_sta_dbgfs_scale_table_file = |
3079 | debugfs_create_file("rate_scale_table", 0600, dir, | 2974 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, |
3080 | lq_sta, &rs_sta_dbgfs_scale_table_ops); | 2975 | lq_sta, &rs_sta_dbgfs_scale_table_ops); |
3081 | lq_sta->rs_sta_dbgfs_stats_table_file = | 2976 | lq_sta->rs_sta_dbgfs_stats_table_file = |
3082 | debugfs_create_file("rate_stats_table", 0600, dir, | 2977 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
3083 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 2978 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
3084 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = | 2979 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = |
3085 | debugfs_create_file("rate_scale_data", 0600, dir, | 2980 | debugfs_create_file("rate_scale_data", S_IRUSR, dir, |
3086 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); | 2981 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); |
3087 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 2982 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
3088 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, | 2983 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, |
3089 | &lq_sta->tx_agg_tid_en); | 2984 | &lq_sta->tx_agg_tid_en); |
3090 | 2985 | ||
3091 | } | 2986 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 9fac530cfb7e..e71923961e69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -54,6 +54,7 @@ struct iwl3945_rate_info { | |||
54 | u8 prev_table_rs; /* prev in rate table cmd */ | 54 | u8 prev_table_rs; /* prev in rate table cmd */ |
55 | }; | 55 | }; |
56 | 56 | ||
57 | |||
57 | /* | 58 | /* |
58 | * These serve as indexes into | 59 | * These serve as indexes into |
59 | * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; | 60 | * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; |
@@ -190,7 +191,7 @@ enum { | |||
190 | IWL_RATE_2M_MASK) | 191 | IWL_RATE_2M_MASK) |
191 | 192 | ||
192 | #define IWL_CCK_RATES_MASK \ | 193 | #define IWL_CCK_RATES_MASK \ |
193 | (IWL_BASIC_RATES_MASK | \ | 194 | (IWL_CCK_BASIC_RATES_MASK | \ |
194 | IWL_RATE_5M_MASK | \ | 195 | IWL_RATE_5M_MASK | \ |
195 | IWL_RATE_11M_MASK) | 196 | IWL_RATE_11M_MASK) |
196 | 197 | ||
@@ -335,6 +336,106 @@ struct iwl_rate_mcs_info { | |||
335 | char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; | 336 | char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; |
336 | }; | 337 | }; |
337 | 338 | ||
339 | /** | ||
340 | * struct iwl_rate_scale_data -- tx success history for one rate | ||
341 | */ | ||
342 | struct iwl_rate_scale_data { | ||
343 | u64 data; /* bitmap of successful frames */ | ||
344 | s32 success_counter; /* number of frames successful */ | ||
345 | s32 success_ratio; /* per-cent * 128 */ | ||
346 | s32 counter; /* number of frames attempted */ | ||
347 | s32 average_tpt; /* success ratio * expected throughput */ | ||
348 | unsigned long stamp; | ||
349 | }; | ||
350 | |||
351 | /** | ||
352 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | ||
353 | * | ||
354 | * There are two of these in struct iwl_lq_sta, | ||
355 | * one for "active", and one for "search". | ||
356 | */ | ||
357 | struct iwl_scale_tbl_info { | ||
358 | enum iwl_table_type lq_type; | ||
359 | u8 ant_type; | ||
360 | u8 is_SGI; /* 1 = short guard interval */ | ||
361 | u8 is_ht40; /* 1 = 40 MHz channel width */ | ||
362 | u8 is_dup; /* 1 = duplicated data streams */ | ||
363 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | ||
364 | u8 max_search; /* maximun number of tables we can search */ | ||
365 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | ||
366 | u32 current_rate; /* rate_n_flags, uCode API format */ | ||
367 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | ||
368 | }; | ||
369 | |||
370 | struct iwl_traffic_load { | ||
371 | unsigned long time_stamp; /* age of the oldest statistics */ | ||
372 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time | ||
373 | * slice */ | ||
374 | u32 total; /* total num of packets during the | ||
375 | * last TID_MAX_TIME_DIFF */ | ||
376 | u8 queue_count; /* number of queues that has | ||
377 | * been used since the last cleanup */ | ||
378 | u8 head; /* start of the circular buffer */ | ||
379 | }; | ||
380 | |||
381 | /** | ||
382 | * struct iwl_lq_sta -- driver's rate scaling private structure | ||
383 | * | ||
384 | * Pointer to this gets passed back and forth between driver and mac80211. | ||
385 | */ | ||
386 | struct iwl_lq_sta { | ||
387 | u8 active_tbl; /* index of active table, range 0-1 */ | ||
388 | u8 enable_counter; /* indicates HT mode */ | ||
389 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ | ||
390 | u8 search_better_tbl; /* 1: currently trying alternate mode */ | ||
391 | s32 last_tpt; | ||
392 | |||
393 | /* The following determine when to search for a new mode */ | ||
394 | u32 table_count_limit; | ||
395 | u32 max_failure_limit; /* # failed frames before new search */ | ||
396 | u32 max_success_limit; /* # successful frames before new search */ | ||
397 | u32 table_count; | ||
398 | u32 total_failed; /* total failed frames, any/all rates */ | ||
399 | u32 total_success; /* total successful frames, any/all rates */ | ||
400 | u64 flush_timer; /* time staying in mode before new search */ | ||
401 | |||
402 | u8 action_counter; /* # mode-switch actions tried */ | ||
403 | u8 is_green; | ||
404 | u8 is_dup; | ||
405 | enum ieee80211_band band; | ||
406 | u8 ibss_sta_added; | ||
407 | |||
408 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | ||
409 | u32 supp_rates; | ||
410 | u16 active_legacy_rate; | ||
411 | u16 active_siso_rate; | ||
412 | u16 active_mimo2_rate; | ||
413 | u16 active_mimo3_rate; | ||
414 | u16 active_rate_basic; | ||
415 | s8 max_rate_idx; /* Max rate set by user */ | ||
416 | u8 missed_rate_counter; | ||
417 | |||
418 | struct iwl_link_quality_cmd lq; | ||
419 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | ||
420 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | ||
421 | u8 tx_agg_tid_en; | ||
422 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
423 | struct dentry *rs_sta_dbgfs_scale_table_file; | ||
424 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
425 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
426 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | ||
427 | u32 dbg_fixed_rate; | ||
428 | #endif | ||
429 | struct iwl_priv *drv; | ||
430 | |||
431 | /* used to be in sta_info */ | ||
432 | int last_txrate_idx; | ||
433 | /* last tx rate_n_flags */ | ||
434 | u32 last_rate_n_flags; | ||
435 | /* packets destined for this STA are aggregated */ | ||
436 | u8 is_agg; | ||
437 | }; | ||
438 | |||
338 | static inline u8 num_of_ant(u8 mask) | 439 | static inline u8 num_of_ant(u8 mask) |
339 | { | 440 | { |
340 | return !!((mask) & ANT_A) + | 441 | return !!((mask) & ANT_A) + |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 921dc4a26fe2..bdff56583e11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/slab.h> | ||
34 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
35 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
36 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
@@ -73,13 +74,7 @@ | |||
73 | #define VD | 74 | #define VD |
74 | #endif | 75 | #endif |
75 | 76 | ||
76 | #ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT | 77 | #define DRV_VERSION IWLWIFI_VERSION VD |
77 | #define VS "s" | ||
78 | #else | ||
79 | #define VS | ||
80 | #endif | ||
81 | |||
82 | #define DRV_VERSION IWLWIFI_VERSION VD VS | ||
83 | 78 | ||
84 | 79 | ||
85 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 80 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
@@ -123,6 +118,17 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
123 | return -EINVAL; | 118 | return -EINVAL; |
124 | } | 119 | } |
125 | 120 | ||
121 | /* | ||
122 | * receive commit_rxon request | ||
123 | * abort any previous channel switch if still in process | ||
124 | */ | ||
125 | if (priv->switch_rxon.switch_in_progress && | ||
126 | (priv->switch_rxon.channel != priv->staging_rxon.channel)) { | ||
127 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | ||
128 | le16_to_cpu(priv->switch_rxon.channel)); | ||
129 | priv->switch_rxon.switch_in_progress = false; | ||
130 | } | ||
131 | |||
126 | /* If we don't need to send a full RXON, we can use | 132 | /* If we don't need to send a full RXON, we can use |
127 | * iwl_rxon_assoc_cmd which is used to reconfigure filter | 133 | * iwl_rxon_assoc_cmd which is used to reconfigure filter |
128 | * and other flags for the current radio configuration. */ | 134 | * and other flags for the current radio configuration. */ |
@@ -134,6 +140,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
134 | } | 140 | } |
135 | 141 | ||
136 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 142 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
143 | iwl_print_rx_config_cmd(priv); | ||
137 | return 0; | 144 | return 0; |
138 | } | 145 | } |
139 | 146 | ||
@@ -191,11 +198,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
191 | priv->start_calib = 0; | 198 | priv->start_calib = 0; |
192 | 199 | ||
193 | /* Add the broadcast address so we can send broadcast frames */ | 200 | /* Add the broadcast address so we can send broadcast frames */ |
194 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == | 201 | priv->cfg->ops->lib->add_bcast_station(priv); |
195 | IWL_INVALID_STATION) { | 202 | |
196 | IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); | ||
197 | return -EIO; | ||
198 | } | ||
199 | 203 | ||
200 | /* If we have set the ASSOC_MSK and we are in BSS mode then | 204 | /* If we have set the ASSOC_MSK and we are in BSS mode then |
201 | * add the IWL_AP_ID to the station rate table */ | 205 | * add the IWL_AP_ID to the station rate table */ |
@@ -233,6 +237,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
233 | } | 237 | } |
234 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 238 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
235 | } | 239 | } |
240 | iwl_print_rx_config_cmd(priv); | ||
236 | 241 | ||
237 | iwl_init_sensitivity(priv); | 242 | iwl_init_sensitivity(priv); |
238 | 243 | ||
@@ -302,7 +307,7 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) | |||
302 | list_add(&frame->list, &priv->free_frames); | 307 | list_add(&frame->list, &priv->free_frames); |
303 | } | 308 | } |
304 | 309 | ||
305 | static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | 310 | static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, |
306 | struct ieee80211_hdr *hdr, | 311 | struct ieee80211_hdr *hdr, |
307 | int left) | 312 | int left) |
308 | { | 313 | { |
@@ -319,34 +324,74 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | |||
319 | return priv->ibss_beacon->len; | 324 | return priv->ibss_beacon->len; |
320 | } | 325 | } |
321 | 326 | ||
327 | /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ | ||
328 | static void iwl_set_beacon_tim(struct iwl_priv *priv, | ||
329 | struct iwl_tx_beacon_cmd *tx_beacon_cmd, | ||
330 | u8 *beacon, u32 frame_size) | ||
331 | { | ||
332 | u16 tim_idx; | ||
333 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; | ||
334 | |||
335 | /* | ||
336 | * The index is relative to frame start but we start looking at the | ||
337 | * variable-length part of the beacon. | ||
338 | */ | ||
339 | tim_idx = mgmt->u.beacon.variable - beacon; | ||
340 | |||
341 | /* Parse variable-length elements of beacon to find WLAN_EID_TIM */ | ||
342 | while ((tim_idx < (frame_size - 2)) && | ||
343 | (beacon[tim_idx] != WLAN_EID_TIM)) | ||
344 | tim_idx += beacon[tim_idx+1] + 2; | ||
345 | |||
346 | /* If TIM field was found, set variables */ | ||
347 | if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) { | ||
348 | tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx); | ||
349 | tx_beacon_cmd->tim_size = beacon[tim_idx+1]; | ||
350 | } else | ||
351 | IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); | ||
352 | } | ||
353 | |||
322 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | 354 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, |
323 | struct iwl_frame *frame, u8 rate) | 355 | struct iwl_frame *frame) |
324 | { | 356 | { |
325 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 357 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
326 | unsigned int frame_size; | 358 | u32 frame_size; |
359 | u32 rate_flags; | ||
360 | u32 rate; | ||
361 | /* | ||
362 | * We have to set up the TX command, the TX Beacon command, and the | ||
363 | * beacon contents. | ||
364 | */ | ||
327 | 365 | ||
366 | /* Initialize memory */ | ||
328 | tx_beacon_cmd = &frame->u.beacon; | 367 | tx_beacon_cmd = &frame->u.beacon; |
329 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 368 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); |
330 | 369 | ||
331 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | 370 | /* Set up TX beacon contents */ |
332 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
333 | |||
334 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, | 371 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, |
335 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | 372 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); |
373 | if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE)) | ||
374 | return 0; | ||
336 | 375 | ||
337 | BUG_ON(frame_size > MAX_MPDU_SIZE); | 376 | /* Set up TX command fields */ |
338 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 377 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
378 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | ||
379 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
380 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | ||
381 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; | ||
339 | 382 | ||
340 | if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) | 383 | /* Set up TX beacon command fields */ |
341 | tx_beacon_cmd->tx.rate_n_flags = | 384 | iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, |
342 | iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); | 385 | frame_size); |
343 | else | ||
344 | tx_beacon_cmd->tx.rate_n_flags = | ||
345 | iwl_hw_set_rate_n_flags(rate, 0); | ||
346 | 386 | ||
347 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | 387 | /* Set up packet rate and flags */ |
348 | TX_CMD_FLG_TSF_MSK | | 388 | rate = iwl_rate_get_lowest_plcp(priv); |
349 | TX_CMD_FLG_STA_RATE_MSK; | 389 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); |
390 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
391 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) | ||
392 | rate_flags |= RATE_MCS_CCK_MSK; | ||
393 | tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, | ||
394 | rate_flags); | ||
350 | 395 | ||
351 | return sizeof(*tx_beacon_cmd) + frame_size; | 396 | return sizeof(*tx_beacon_cmd) + frame_size; |
352 | } | 397 | } |
@@ -355,19 +400,20 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv) | |||
355 | struct iwl_frame *frame; | 400 | struct iwl_frame *frame; |
356 | unsigned int frame_size; | 401 | unsigned int frame_size; |
357 | int rc; | 402 | int rc; |
358 | u8 rate; | ||
359 | 403 | ||
360 | frame = iwl_get_free_frame(priv); | 404 | frame = iwl_get_free_frame(priv); |
361 | |||
362 | if (!frame) { | 405 | if (!frame) { |
363 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " | 406 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " |
364 | "command.\n"); | 407 | "command.\n"); |
365 | return -ENOMEM; | 408 | return -ENOMEM; |
366 | } | 409 | } |
367 | 410 | ||
368 | rate = iwl_rate_get_lowest_plcp(priv); | 411 | frame_size = iwl_hw_get_beacon_cmd(priv, frame); |
369 | 412 | if (!frame_size) { | |
370 | frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate); | 413 | IWL_ERR(priv, "Error configuring the beacon command\n"); |
414 | iwl_free_frame(priv, frame); | ||
415 | return -EINVAL; | ||
416 | } | ||
371 | 417 | ||
372 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, | 418 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, |
373 | &frame->u.cmd[0]); | 419 | &frame->u.cmd[0]); |
@@ -525,7 +571,7 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv, | |||
525 | static void iwl_rx_reply_alive(struct iwl_priv *priv, | 571 | static void iwl_rx_reply_alive(struct iwl_priv *priv, |
526 | struct iwl_rx_mem_buffer *rxb) | 572 | struct iwl_rx_mem_buffer *rxb) |
527 | { | 573 | { |
528 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 574 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
529 | struct iwl_alive_resp *palive; | 575 | struct iwl_alive_resp *palive; |
530 | struct delayed_work *pwork; | 576 | struct delayed_work *pwork; |
531 | 577 | ||
@@ -604,14 +650,139 @@ static void iwl_bg_statistics_periodic(unsigned long data) | |||
604 | if (!iwl_is_ready_rf(priv)) | 650 | if (!iwl_is_ready_rf(priv)) |
605 | return; | 651 | return; |
606 | 652 | ||
607 | iwl_send_statistics_request(priv, CMD_ASYNC); | 653 | iwl_send_statistics_request(priv, CMD_ASYNC, false); |
654 | } | ||
655 | |||
656 | |||
657 | static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | ||
658 | u32 start_idx, u32 num_events, | ||
659 | u32 mode) | ||
660 | { | ||
661 | u32 i; | ||
662 | u32 ptr; /* SRAM byte address of log data */ | ||
663 | u32 ev, time, data; /* event log data */ | ||
664 | unsigned long reg_flags; | ||
665 | |||
666 | if (mode == 0) | ||
667 | ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32)); | ||
668 | else | ||
669 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); | ||
670 | |||
671 | /* Make sure device is powered up for SRAM reads */ | ||
672 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
673 | if (iwl_grab_nic_access(priv)) { | ||
674 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
675 | return; | ||
676 | } | ||
677 | |||
678 | /* Set starting address; reads will auto-increment */ | ||
679 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
680 | rmb(); | ||
681 | |||
682 | /* | ||
683 | * "time" is actually "data" for mode 0 (no timestamp). | ||
684 | * place event id # at far right for easier visual parsing. | ||
685 | */ | ||
686 | for (i = 0; i < num_events; i++) { | ||
687 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
688 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
689 | if (mode == 0) { | ||
690 | trace_iwlwifi_dev_ucode_cont_event(priv, | ||
691 | 0, time, ev); | ||
692 | } else { | ||
693 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
694 | trace_iwlwifi_dev_ucode_cont_event(priv, | ||
695 | time, data, ev); | ||
696 | } | ||
697 | } | ||
698 | /* Allow device to power down */ | ||
699 | iwl_release_nic_access(priv); | ||
700 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
701 | } | ||
702 | |||
703 | static void iwl_continuous_event_trace(struct iwl_priv *priv) | ||
704 | { | ||
705 | u32 capacity; /* event log capacity in # entries */ | ||
706 | u32 base; /* SRAM byte address of event log header */ | ||
707 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
708 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
709 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
710 | |||
711 | if (priv->ucode_type == UCODE_INIT) | ||
712 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | ||
713 | else | ||
714 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
715 | if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
716 | capacity = iwl_read_targ_mem(priv, base); | ||
717 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | ||
718 | mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); | ||
719 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | ||
720 | } else | ||
721 | return; | ||
722 | |||
723 | if (num_wraps == priv->event_log.num_wraps) { | ||
724 | iwl_print_cont_event_trace(priv, | ||
725 | base, priv->event_log.next_entry, | ||
726 | next_entry - priv->event_log.next_entry, | ||
727 | mode); | ||
728 | priv->event_log.non_wraps_count++; | ||
729 | } else { | ||
730 | if ((num_wraps - priv->event_log.num_wraps) > 1) | ||
731 | priv->event_log.wraps_more_count++; | ||
732 | else | ||
733 | priv->event_log.wraps_once_count++; | ||
734 | trace_iwlwifi_dev_ucode_wrap_event(priv, | ||
735 | num_wraps - priv->event_log.num_wraps, | ||
736 | next_entry, priv->event_log.next_entry); | ||
737 | if (next_entry < priv->event_log.next_entry) { | ||
738 | iwl_print_cont_event_trace(priv, base, | ||
739 | priv->event_log.next_entry, | ||
740 | capacity - priv->event_log.next_entry, | ||
741 | mode); | ||
742 | |||
743 | iwl_print_cont_event_trace(priv, base, 0, | ||
744 | next_entry, mode); | ||
745 | } else { | ||
746 | iwl_print_cont_event_trace(priv, base, | ||
747 | next_entry, capacity - next_entry, | ||
748 | mode); | ||
749 | |||
750 | iwl_print_cont_event_trace(priv, base, 0, | ||
751 | next_entry, mode); | ||
752 | } | ||
753 | } | ||
754 | priv->event_log.num_wraps = num_wraps; | ||
755 | priv->event_log.next_entry = next_entry; | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * iwl_bg_ucode_trace - Timer callback to log ucode event | ||
760 | * | ||
761 | * The timer is continually set to execute every | ||
762 | * UCODE_TRACE_PERIOD milliseconds after the last timer expired | ||
763 | * this function is to perform continuous uCode event logging operation | ||
764 | * if enabled | ||
765 | */ | ||
766 | static void iwl_bg_ucode_trace(unsigned long data) | ||
767 | { | ||
768 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
769 | |||
770 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
771 | return; | ||
772 | |||
773 | if (priv->event_log.ucode_trace) { | ||
774 | iwl_continuous_event_trace(priv); | ||
775 | /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */ | ||
776 | mod_timer(&priv->ucode_trace, | ||
777 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | ||
778 | } | ||
608 | } | 779 | } |
609 | 780 | ||
610 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 781 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
611 | struct iwl_rx_mem_buffer *rxb) | 782 | struct iwl_rx_mem_buffer *rxb) |
612 | { | 783 | { |
613 | #ifdef CONFIG_IWLWIFI_DEBUG | 784 | #ifdef CONFIG_IWLWIFI_DEBUG |
614 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 785 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
615 | struct iwl4965_beacon_notif *beacon = | 786 | struct iwl4965_beacon_notif *beacon = |
616 | (struct iwl4965_beacon_notif *)pkt->u.raw; | 787 | (struct iwl4965_beacon_notif *)pkt->u.raw; |
617 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | 788 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); |
@@ -635,16 +806,18 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
635 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | 806 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, |
636 | struct iwl_rx_mem_buffer *rxb) | 807 | struct iwl_rx_mem_buffer *rxb) |
637 | { | 808 | { |
638 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 809 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
639 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 810 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
640 | unsigned long status = priv->status; | 811 | unsigned long status = priv->status; |
641 | 812 | ||
642 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", | 813 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", |
643 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | 814 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", |
644 | (flags & SW_CARD_DISABLED) ? "Kill" : "On"); | 815 | (flags & SW_CARD_DISABLED) ? "Kill" : "On", |
816 | (flags & CT_CARD_DISABLED) ? | ||
817 | "Reached" : "Not reached"); | ||
645 | 818 | ||
646 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | 819 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | |
647 | RF_CARD_DISABLED)) { | 820 | CT_CARD_DISABLED)) { |
648 | 821 | ||
649 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | 822 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, |
650 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | 823 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); |
@@ -658,10 +831,10 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
658 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | 831 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, |
659 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | 832 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); |
660 | } | 833 | } |
661 | if (flags & RF_CARD_DISABLED) | 834 | if (flags & CT_CARD_DISABLED) |
662 | iwl_tt_enter_ct_kill(priv); | 835 | iwl_tt_enter_ct_kill(priv); |
663 | } | 836 | } |
664 | if (!(flags & RF_CARD_DISABLED)) | 837 | if (!(flags & CT_CARD_DISABLED)) |
665 | iwl_tt_exit_ct_kill(priv); | 838 | iwl_tt_exit_ct_kill(priv); |
666 | 839 | ||
667 | if (flags & HW_CARD_DISABLED) | 840 | if (flags & HW_CARD_DISABLED) |
@@ -711,6 +884,8 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
711 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | 884 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; |
712 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | 885 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; |
713 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | 886 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; |
887 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
888 | iwl_rx_spectrum_measure_notif; | ||
714 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 889 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
715 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | 890 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = |
716 | iwl_rx_pm_debug_statistics_notif; | 891 | iwl_rx_pm_debug_statistics_notif; |
@@ -721,10 +896,9 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
721 | * statistics request from the host as well as for the periodic | 896 | * statistics request from the host as well as for the periodic |
722 | * statistics notifications (after received beacons) from the uCode. | 897 | * statistics notifications (after received beacons) from the uCode. |
723 | */ | 898 | */ |
724 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; | 899 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; |
725 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | 900 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; |
726 | 901 | ||
727 | iwl_setup_spectrum_handlers(priv); | ||
728 | iwl_setup_rx_scan_handlers(priv); | 902 | iwl_setup_rx_scan_handlers(priv); |
729 | 903 | ||
730 | /* status change handler */ | 904 | /* status change handler */ |
@@ -770,7 +944,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
770 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); | 944 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); |
771 | 945 | ||
772 | /* calculate total frames need to be restock after handling RX */ | 946 | /* calculate total frames need to be restock after handling RX */ |
773 | total_empty = r - priv->rxq.write_actual; | 947 | total_empty = r - rxq->write_actual; |
774 | if (total_empty < 0) | 948 | if (total_empty < 0) |
775 | total_empty += RX_QUEUE_SIZE; | 949 | total_empty += RX_QUEUE_SIZE; |
776 | 950 | ||
@@ -787,10 +961,13 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
787 | 961 | ||
788 | rxq->queue[i] = NULL; | 962 | rxq->queue[i] = NULL; |
789 | 963 | ||
790 | pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, | 964 | pci_unmap_page(priv->pci_dev, rxb->page_dma, |
791 | priv->hw_params.rx_buf_size + 256, | 965 | PAGE_SIZE << priv->hw_params.rx_page_order, |
792 | PCI_DMA_FROMDEVICE); | 966 | PCI_DMA_FROMDEVICE); |
793 | pkt = (struct iwl_rx_packet *)rxb->skb->data; | 967 | pkt = rxb_addr(rxb); |
968 | |||
969 | trace_iwlwifi_dev_rx(priv, pkt, | ||
970 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
794 | 971 | ||
795 | /* Reclaim a command buffer only if this packet is a response | 972 | /* Reclaim a command buffer only if this packet is a response |
796 | * to a (driver-originated) command. | 973 | * to a (driver-originated) command. |
@@ -812,8 +989,8 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
812 | if (priv->rx_handlers[pkt->hdr.cmd]) { | 989 | if (priv->rx_handlers[pkt->hdr.cmd]) { |
813 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, | 990 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, |
814 | i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 991 | i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); |
815 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
816 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; | 992 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; |
993 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
817 | } else { | 994 | } else { |
818 | /* No handling needed */ | 995 | /* No handling needed */ |
819 | IWL_DEBUG_RX(priv, | 996 | IWL_DEBUG_RX(priv, |
@@ -822,35 +999,45 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
822 | pkt->hdr.cmd); | 999 | pkt->hdr.cmd); |
823 | } | 1000 | } |
824 | 1001 | ||
1002 | /* | ||
1003 | * XXX: After here, we should always check rxb->page | ||
1004 | * against NULL before touching it or its virtual | ||
1005 | * memory (pkt). Because some rx_handler might have | ||
1006 | * already taken or freed the pages. | ||
1007 | */ | ||
1008 | |||
825 | if (reclaim) { | 1009 | if (reclaim) { |
826 | /* Invoke any callbacks, transfer the skb to caller, and | 1010 | /* Invoke any callbacks, transfer the buffer to caller, |
827 | * fire off the (possibly) blocking iwl_send_cmd() | 1011 | * and fire off the (possibly) blocking iwl_send_cmd() |
828 | * as we reclaim the driver command queue */ | 1012 | * as we reclaim the driver command queue */ |
829 | if (rxb && rxb->skb) | 1013 | if (rxb->page) |
830 | iwl_tx_cmd_complete(priv, rxb); | 1014 | iwl_tx_cmd_complete(priv, rxb); |
831 | else | 1015 | else |
832 | IWL_WARN(priv, "Claim null rxb?\n"); | 1016 | IWL_WARN(priv, "Claim null rxb?\n"); |
833 | } | 1017 | } |
834 | 1018 | ||
835 | /* For now we just don't re-use anything. We can tweak this | 1019 | /* Reuse the page if possible. For notification packets and |
836 | * later to try and re-use notification packets and SKBs that | 1020 | * SKBs that fail to Rx correctly, add them back into the |
837 | * fail to Rx correctly */ | 1021 | * rx_free list for reuse later. */ |
838 | if (rxb->skb != NULL) { | ||
839 | priv->alloc_rxb_skb--; | ||
840 | dev_kfree_skb_any(rxb->skb); | ||
841 | rxb->skb = NULL; | ||
842 | } | ||
843 | |||
844 | spin_lock_irqsave(&rxq->lock, flags); | 1022 | spin_lock_irqsave(&rxq->lock, flags); |
845 | list_add_tail(&rxb->list, &priv->rxq.rx_used); | 1023 | if (rxb->page != NULL) { |
1024 | rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page, | ||
1025 | 0, PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1026 | PCI_DMA_FROMDEVICE); | ||
1027 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
1028 | rxq->free_count++; | ||
1029 | } else | ||
1030 | list_add_tail(&rxb->list, &rxq->rx_used); | ||
1031 | |||
846 | spin_unlock_irqrestore(&rxq->lock, flags); | 1032 | spin_unlock_irqrestore(&rxq->lock, flags); |
1033 | |||
847 | i = (i + 1) & RX_QUEUE_MASK; | 1034 | i = (i + 1) & RX_QUEUE_MASK; |
848 | /* If there are a lot of unused frames, | 1035 | /* If there are a lot of unused frames, |
849 | * restock the Rx queue so ucode wont assert. */ | 1036 | * restock the Rx queue so ucode wont assert. */ |
850 | if (fill_rx) { | 1037 | if (fill_rx) { |
851 | count++; | 1038 | count++; |
852 | if (count >= 8) { | 1039 | if (count >= 8) { |
853 | priv->rxq.read = i; | 1040 | rxq->read = i; |
854 | iwl_rx_replenish_now(priv); | 1041 | iwl_rx_replenish_now(priv); |
855 | count = 0; | 1042 | count = 0; |
856 | } | 1043 | } |
@@ -858,7 +1045,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
858 | } | 1045 | } |
859 | 1046 | ||
860 | /* Backtrack one entry */ | 1047 | /* Backtrack one entry */ |
861 | priv->rxq.read = i; | 1048 | rxq->read = i; |
862 | if (fill_rx) | 1049 | if (fill_rx) |
863 | iwl_rx_replenish_now(priv); | 1050 | iwl_rx_replenish_now(priv); |
864 | else | 1051 | else |
@@ -878,6 +1065,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
878 | u32 inta, handled = 0; | 1065 | u32 inta, handled = 0; |
879 | u32 inta_fh; | 1066 | u32 inta_fh; |
880 | unsigned long flags; | 1067 | unsigned long flags; |
1068 | u32 i; | ||
881 | #ifdef CONFIG_IWLWIFI_DEBUG | 1069 | #ifdef CONFIG_IWLWIFI_DEBUG |
882 | u32 inta_mask; | 1070 | u32 inta_mask; |
883 | #endif | 1071 | #endif |
@@ -905,6 +1093,8 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
905 | } | 1093 | } |
906 | #endif | 1094 | #endif |
907 | 1095 | ||
1096 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1097 | |||
908 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not | 1098 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not |
909 | * atomic, make sure that inta covers all the interrupts that | 1099 | * atomic, make sure that inta covers all the interrupts that |
910 | * we've discovered, even if FH interrupt came in just after | 1100 | * we've discovered, even if FH interrupt came in just after |
@@ -926,8 +1116,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
926 | 1116 | ||
927 | handled |= CSR_INT_BIT_HW_ERR; | 1117 | handled |= CSR_INT_BIT_HW_ERR; |
928 | 1118 | ||
929 | spin_unlock_irqrestore(&priv->lock, flags); | ||
930 | |||
931 | return; | 1119 | return; |
932 | } | 1120 | } |
933 | 1121 | ||
@@ -995,19 +1183,17 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
995 | handled |= CSR_INT_BIT_SW_ERR; | 1183 | handled |= CSR_INT_BIT_SW_ERR; |
996 | } | 1184 | } |
997 | 1185 | ||
998 | /* uCode wakes up after power-down sleep */ | 1186 | /* |
1187 | * uCode wakes up after power-down sleep. | ||
1188 | * Tell device about any new tx or host commands enqueued, | ||
1189 | * and about any Rx buffers made available while asleep. | ||
1190 | */ | ||
999 | if (inta & CSR_INT_BIT_WAKEUP) { | 1191 | if (inta & CSR_INT_BIT_WAKEUP) { |
1000 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); | 1192 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); |
1001 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); | 1193 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); |
1002 | iwl_txq_update_write_ptr(priv, &priv->txq[0]); | 1194 | for (i = 0; i < priv->hw_params.max_txq_num; i++) |
1003 | iwl_txq_update_write_ptr(priv, &priv->txq[1]); | 1195 | iwl_txq_update_write_ptr(priv, &priv->txq[i]); |
1004 | iwl_txq_update_write_ptr(priv, &priv->txq[2]); | ||
1005 | iwl_txq_update_write_ptr(priv, &priv->txq[3]); | ||
1006 | iwl_txq_update_write_ptr(priv, &priv->txq[4]); | ||
1007 | iwl_txq_update_write_ptr(priv, &priv->txq[5]); | ||
1008 | |||
1009 | priv->isr_stats.wakeup++; | 1196 | priv->isr_stats.wakeup++; |
1010 | |||
1011 | handled |= CSR_INT_BIT_WAKEUP; | 1197 | handled |= CSR_INT_BIT_WAKEUP; |
1012 | } | 1198 | } |
1013 | 1199 | ||
@@ -1020,11 +1206,12 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1020 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 1206 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
1021 | } | 1207 | } |
1022 | 1208 | ||
1209 | /* This "Tx" DMA channel is used only for loading uCode */ | ||
1023 | if (inta & CSR_INT_BIT_FH_TX) { | 1210 | if (inta & CSR_INT_BIT_FH_TX) { |
1024 | IWL_DEBUG_ISR(priv, "Tx interrupt\n"); | 1211 | IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); |
1025 | priv->isr_stats.tx++; | 1212 | priv->isr_stats.tx++; |
1026 | handled |= CSR_INT_BIT_FH_TX; | 1213 | handled |= CSR_INT_BIT_FH_TX; |
1027 | /* FH finished to write, send event */ | 1214 | /* Wake up uCode load routine, now that load is complete */ |
1028 | priv->ucode_write_complete = 1; | 1215 | priv->ucode_write_complete = 1; |
1029 | wake_up_interruptible(&priv->wait_command_queue); | 1216 | wake_up_interruptible(&priv->wait_command_queue); |
1030 | } | 1217 | } |
@@ -1054,7 +1241,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1054 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); | 1241 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); |
1055 | } | 1242 | } |
1056 | #endif | 1243 | #endif |
1057 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1058 | } | 1244 | } |
1059 | 1245 | ||
1060 | /* tasklet for iwlagn interrupt */ | 1246 | /* tasklet for iwlagn interrupt */ |
@@ -1063,6 +1249,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1063 | u32 inta = 0; | 1249 | u32 inta = 0; |
1064 | u32 handled = 0; | 1250 | u32 handled = 0; |
1065 | unsigned long flags; | 1251 | unsigned long flags; |
1252 | u32 i; | ||
1066 | #ifdef CONFIG_IWLWIFI_DEBUG | 1253 | #ifdef CONFIG_IWLWIFI_DEBUG |
1067 | u32 inta_mask; | 1254 | u32 inta_mask; |
1068 | #endif | 1255 | #endif |
@@ -1072,7 +1259,15 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1072 | /* Ack/clear/reset pending uCode interrupts. | 1259 | /* Ack/clear/reset pending uCode interrupts. |
1073 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, | 1260 | * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, |
1074 | */ | 1261 | */ |
1075 | iwl_write32(priv, CSR_INT, priv->inta); | 1262 | /* There is a hardware bug in the interrupt mask function that some |
1263 | * interrupts (i.e. CSR_INT_BIT_SCD) can still be generated even if | ||
1264 | * they are disabled in the CSR_INT_MASK register. Furthermore the | ||
1265 | * ICT interrupt handling mechanism has another bug that might cause | ||
1266 | * these unmasked interrupts fail to be detected. We workaround the | ||
1267 | * hardware bugs here by ACKing all the possible interrupts so that | ||
1268 | * interrupt coalescing can still be achieved. | ||
1269 | */ | ||
1270 | iwl_write32(priv, CSR_INT, priv->inta | ~priv->inta_mask); | ||
1076 | 1271 | ||
1077 | inta = priv->inta; | 1272 | inta = priv->inta; |
1078 | 1273 | ||
@@ -1084,6 +1279,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1084 | inta, inta_mask); | 1279 | inta, inta_mask); |
1085 | } | 1280 | } |
1086 | #endif | 1281 | #endif |
1282 | |||
1283 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1284 | |||
1087 | /* saved interrupt in inta variable now we can reset priv->inta */ | 1285 | /* saved interrupt in inta variable now we can reset priv->inta */ |
1088 | priv->inta = 0; | 1286 | priv->inta = 0; |
1089 | 1287 | ||
@@ -1099,8 +1297,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1099 | 1297 | ||
1100 | handled |= CSR_INT_BIT_HW_ERR; | 1298 | handled |= CSR_INT_BIT_HW_ERR; |
1101 | 1299 | ||
1102 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1103 | |||
1104 | return; | 1300 | return; |
1105 | } | 1301 | } |
1106 | 1302 | ||
@@ -1172,12 +1368,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1172 | if (inta & CSR_INT_BIT_WAKEUP) { | 1368 | if (inta & CSR_INT_BIT_WAKEUP) { |
1173 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); | 1369 | IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); |
1174 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); | 1370 | iwl_rx_queue_update_write_ptr(priv, &priv->rxq); |
1175 | iwl_txq_update_write_ptr(priv, &priv->txq[0]); | 1371 | for (i = 0; i < priv->hw_params.max_txq_num; i++) |
1176 | iwl_txq_update_write_ptr(priv, &priv->txq[1]); | 1372 | iwl_txq_update_write_ptr(priv, &priv->txq[i]); |
1177 | iwl_txq_update_write_ptr(priv, &priv->txq[2]); | ||
1178 | iwl_txq_update_write_ptr(priv, &priv->txq[3]); | ||
1179 | iwl_txq_update_write_ptr(priv, &priv->txq[4]); | ||
1180 | iwl_txq_update_write_ptr(priv, &priv->txq[5]); | ||
1181 | 1373 | ||
1182 | priv->isr_stats.wakeup++; | 1374 | priv->isr_stats.wakeup++; |
1183 | 1375 | ||
@@ -1206,26 +1398,36 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1206 | * 3- update RX shared data to indicate last write index. | 1398 | * 3- update RX shared data to indicate last write index. |
1207 | * 4- send interrupt. | 1399 | * 4- send interrupt. |
1208 | * This could lead to RX race, driver could receive RX interrupt | 1400 | * This could lead to RX race, driver could receive RX interrupt |
1209 | * but the shared data changes does not reflect this. | 1401 | * but the shared data changes does not reflect this; |
1210 | * this could lead to RX race, RX periodic will solve this race | 1402 | * periodic interrupt will detect any dangling Rx activity. |
1211 | */ | 1403 | */ |
1212 | iwl_write32(priv, CSR_INT_PERIODIC_REG, | 1404 | |
1405 | /* Disable periodic interrupt; we use it as just a one-shot. */ | ||
1406 | iwl_write8(priv, CSR_INT_PERIODIC_REG, | ||
1213 | CSR_INT_PERIODIC_DIS); | 1407 | CSR_INT_PERIODIC_DIS); |
1214 | iwl_rx_handle(priv); | 1408 | iwl_rx_handle(priv); |
1215 | /* Only set RX periodic if real RX is received. */ | 1409 | |
1410 | /* | ||
1411 | * Enable periodic interrupt in 8 msec only if we received | ||
1412 | * real RX interrupt (instead of just periodic int), to catch | ||
1413 | * any dangling Rx interrupt. If it was just the periodic | ||
1414 | * interrupt, there was no dangling Rx activity, and no need | ||
1415 | * to extend the periodic interrupt; one-shot is enough. | ||
1416 | */ | ||
1216 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) | 1417 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) |
1217 | iwl_write32(priv, CSR_INT_PERIODIC_REG, | 1418 | iwl_write8(priv, CSR_INT_PERIODIC_REG, |
1218 | CSR_INT_PERIODIC_ENA); | 1419 | CSR_INT_PERIODIC_ENA); |
1219 | 1420 | ||
1220 | priv->isr_stats.rx++; | 1421 | priv->isr_stats.rx++; |
1221 | } | 1422 | } |
1222 | 1423 | ||
1424 | /* This "Tx" DMA channel is used only for loading uCode */ | ||
1223 | if (inta & CSR_INT_BIT_FH_TX) { | 1425 | if (inta & CSR_INT_BIT_FH_TX) { |
1224 | iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); | 1426 | iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); |
1225 | IWL_DEBUG_ISR(priv, "Tx interrupt\n"); | 1427 | IWL_DEBUG_ISR(priv, "uCode load interrupt\n"); |
1226 | priv->isr_stats.tx++; | 1428 | priv->isr_stats.tx++; |
1227 | handled |= CSR_INT_BIT_FH_TX; | 1429 | handled |= CSR_INT_BIT_FH_TX; |
1228 | /* FH finished to write, send event */ | 1430 | /* Wake up uCode load routine, now that load is complete */ |
1229 | priv->ucode_write_complete = 1; | 1431 | priv->ucode_write_complete = 1; |
1230 | wake_up_interruptible(&priv->wait_command_queue); | 1432 | wake_up_interruptible(&priv->wait_command_queue); |
1231 | } | 1433 | } |
@@ -1240,14 +1442,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1240 | inta & ~priv->inta_mask); | 1442 | inta & ~priv->inta_mask); |
1241 | } | 1443 | } |
1242 | 1444 | ||
1243 | |||
1244 | /* Re-enable all interrupts */ | 1445 | /* Re-enable all interrupts */ |
1245 | /* only Re-enable if diabled by irq */ | 1446 | /* only Re-enable if diabled by irq */ |
1246 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1447 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1247 | iwl_enable_interrupts(priv); | 1448 | iwl_enable_interrupts(priv); |
1248 | |||
1249 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1250 | |||
1251 | } | 1449 | } |
1252 | 1450 | ||
1253 | 1451 | ||
@@ -1274,59 +1472,66 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
1274 | } | 1472 | } |
1275 | 1473 | ||
1276 | 1474 | ||
1475 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | ||
1476 | static int iwl_mac_setup_register(struct iwl_priv *priv); | ||
1477 | |||
1478 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | ||
1479 | { | ||
1480 | const char *name_pre = priv->cfg->fw_name_pre; | ||
1481 | |||
1482 | if (first) | ||
1483 | priv->fw_index = priv->cfg->ucode_api_max; | ||
1484 | else | ||
1485 | priv->fw_index--; | ||
1486 | |||
1487 | if (priv->fw_index < priv->cfg->ucode_api_min) { | ||
1488 | IWL_ERR(priv, "no suitable firmware found!\n"); | ||
1489 | return -ENOENT; | ||
1490 | } | ||
1491 | |||
1492 | sprintf(priv->firmware_name, "%s%d%s", | ||
1493 | name_pre, priv->fw_index, ".ucode"); | ||
1494 | |||
1495 | IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", | ||
1496 | priv->firmware_name); | ||
1497 | |||
1498 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, | ||
1499 | &priv->pci_dev->dev, GFP_KERNEL, priv, | ||
1500 | iwl_ucode_callback); | ||
1501 | } | ||
1502 | |||
1277 | /** | 1503 | /** |
1278 | * iwl_read_ucode - Read uCode images from disk file. | 1504 | * iwl_ucode_callback - callback when firmware was loaded |
1279 | * | 1505 | * |
1280 | * Copy into buffers for card to fetch via bus-mastering | 1506 | * If loaded successfully, copies the firmware into buffers |
1507 | * for the card to fetch (via DMA). | ||
1281 | */ | 1508 | */ |
1282 | static int iwl_read_ucode(struct iwl_priv *priv) | 1509 | static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) |
1283 | { | 1510 | { |
1511 | struct iwl_priv *priv = context; | ||
1284 | struct iwl_ucode_header *ucode; | 1512 | struct iwl_ucode_header *ucode; |
1285 | int ret = -EINVAL, index; | ||
1286 | const struct firmware *ucode_raw; | ||
1287 | const char *name_pre = priv->cfg->fw_name_pre; | ||
1288 | const unsigned int api_max = priv->cfg->ucode_api_max; | 1513 | const unsigned int api_max = priv->cfg->ucode_api_max; |
1289 | const unsigned int api_min = priv->cfg->ucode_api_min; | 1514 | const unsigned int api_min = priv->cfg->ucode_api_min; |
1290 | char buf[25]; | ||
1291 | u8 *src; | 1515 | u8 *src; |
1292 | size_t len; | 1516 | size_t len; |
1293 | u32 api_ver, build; | 1517 | u32 api_ver, build; |
1294 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | 1518 | u32 inst_size, data_size, init_size, init_data_size, boot_size; |
1519 | int err; | ||
1295 | u16 eeprom_ver; | 1520 | u16 eeprom_ver; |
1296 | 1521 | ||
1297 | /* Ask kernel firmware_class module to get the boot firmware off disk. | 1522 | if (!ucode_raw) { |
1298 | * request_firmware() is synchronous, file is in memory on return. */ | 1523 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", |
1299 | for (index = api_max; index >= api_min; index--) { | 1524 | priv->firmware_name); |
1300 | sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); | 1525 | goto try_again; |
1301 | ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); | ||
1302 | if (ret < 0) { | ||
1303 | IWL_ERR(priv, "%s firmware file req failed: %d\n", | ||
1304 | buf, ret); | ||
1305 | if (ret == -ENOENT) | ||
1306 | continue; | ||
1307 | else | ||
1308 | goto error; | ||
1309 | } else { | ||
1310 | if (index < api_max) | ||
1311 | IWL_ERR(priv, "Loaded firmware %s, " | ||
1312 | "which is deprecated. " | ||
1313 | "Please use API v%u instead.\n", | ||
1314 | buf, api_max); | ||
1315 | |||
1316 | IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n", | ||
1317 | buf, ucode_raw->size); | ||
1318 | break; | ||
1319 | } | ||
1320 | } | 1526 | } |
1321 | 1527 | ||
1322 | if (ret < 0) | 1528 | IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", |
1323 | goto error; | 1529 | priv->firmware_name, ucode_raw->size); |
1324 | 1530 | ||
1325 | /* Make sure that we got at least the v1 header! */ | 1531 | /* Make sure that we got at least the v1 header! */ |
1326 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { | 1532 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { |
1327 | IWL_ERR(priv, "File size way too small!\n"); | 1533 | IWL_ERR(priv, "File size way too small!\n"); |
1328 | ret = -EINVAL; | 1534 | goto try_again; |
1329 | goto err_release; | ||
1330 | } | 1535 | } |
1331 | 1536 | ||
1332 | /* Data from ucode file: header followed by uCode images */ | 1537 | /* Data from ucode file: header followed by uCode images */ |
@@ -1351,10 +1556,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1351 | IWL_ERR(priv, "Driver unable to support your firmware API. " | 1556 | IWL_ERR(priv, "Driver unable to support your firmware API. " |
1352 | "Driver supports v%u, firmware is v%u.\n", | 1557 | "Driver supports v%u, firmware is v%u.\n", |
1353 | api_max, api_ver); | 1558 | api_max, api_ver); |
1354 | priv->ucode_ver = 0; | 1559 | goto try_again; |
1355 | ret = -EINVAL; | ||
1356 | goto err_release; | ||
1357 | } | 1560 | } |
1561 | |||
1358 | if (api_ver != api_max) | 1562 | if (api_ver != api_max) |
1359 | IWL_ERR(priv, "Firmware has old API version. Expected v%u, " | 1563 | IWL_ERR(priv, "Firmware has old API version. Expected v%u, " |
1360 | "got v%u. New firmware can be obtained " | 1564 | "got v%u. New firmware can be obtained " |
@@ -1367,6 +1571,14 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1367 | IWL_UCODE_API(priv->ucode_ver), | 1571 | IWL_UCODE_API(priv->ucode_ver), |
1368 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1572 | IWL_UCODE_SERIAL(priv->ucode_ver)); |
1369 | 1573 | ||
1574 | snprintf(priv->hw->wiphy->fw_version, | ||
1575 | sizeof(priv->hw->wiphy->fw_version), | ||
1576 | "%u.%u.%u.%u", | ||
1577 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
1578 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
1579 | IWL_UCODE_API(priv->ucode_ver), | ||
1580 | IWL_UCODE_SERIAL(priv->ucode_ver)); | ||
1581 | |||
1370 | if (build) | 1582 | if (build) |
1371 | IWL_DEBUG_INFO(priv, "Build %u\n", build); | 1583 | IWL_DEBUG_INFO(priv, "Build %u\n", build); |
1372 | 1584 | ||
@@ -1388,6 +1600,12 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1388 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", | 1600 | IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", |
1389 | boot_size); | 1601 | boot_size); |
1390 | 1602 | ||
1603 | /* | ||
1604 | * For any of the failures below (before allocating pci memory) | ||
1605 | * we will try to load a version with a smaller API -- maybe the | ||
1606 | * user just got a corrupted version of the latest API. | ||
1607 | */ | ||
1608 | |||
1391 | /* Verify size of file vs. image size info in file's header */ | 1609 | /* Verify size of file vs. image size info in file's header */ |
1392 | if (ucode_raw->size != | 1610 | if (ucode_raw->size != |
1393 | priv->cfg->ops->ucode->get_header_size(api_ver) + | 1611 | priv->cfg->ops->ucode->get_header_size(api_ver) + |
@@ -1397,41 +1615,35 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1397 | IWL_DEBUG_INFO(priv, | 1615 | IWL_DEBUG_INFO(priv, |
1398 | "uCode file size %d does not match expected size\n", | 1616 | "uCode file size %d does not match expected size\n", |
1399 | (int)ucode_raw->size); | 1617 | (int)ucode_raw->size); |
1400 | ret = -EINVAL; | 1618 | goto try_again; |
1401 | goto err_release; | ||
1402 | } | 1619 | } |
1403 | 1620 | ||
1404 | /* Verify that uCode images will fit in card's SRAM */ | 1621 | /* Verify that uCode images will fit in card's SRAM */ |
1405 | if (inst_size > priv->hw_params.max_inst_size) { | 1622 | if (inst_size > priv->hw_params.max_inst_size) { |
1406 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", | 1623 | IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", |
1407 | inst_size); | 1624 | inst_size); |
1408 | ret = -EINVAL; | 1625 | goto try_again; |
1409 | goto err_release; | ||
1410 | } | 1626 | } |
1411 | 1627 | ||
1412 | if (data_size > priv->hw_params.max_data_size) { | 1628 | if (data_size > priv->hw_params.max_data_size) { |
1413 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", | 1629 | IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", |
1414 | data_size); | 1630 | data_size); |
1415 | ret = -EINVAL; | 1631 | goto try_again; |
1416 | goto err_release; | ||
1417 | } | 1632 | } |
1418 | if (init_size > priv->hw_params.max_inst_size) { | 1633 | if (init_size > priv->hw_params.max_inst_size) { |
1419 | IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", | 1634 | IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", |
1420 | init_size); | 1635 | init_size); |
1421 | ret = -EINVAL; | 1636 | goto try_again; |
1422 | goto err_release; | ||
1423 | } | 1637 | } |
1424 | if (init_data_size > priv->hw_params.max_data_size) { | 1638 | if (init_data_size > priv->hw_params.max_data_size) { |
1425 | IWL_INFO(priv, "uCode init data len %d too large to fit in\n", | 1639 | IWL_INFO(priv, "uCode init data len %d too large to fit in\n", |
1426 | init_data_size); | 1640 | init_data_size); |
1427 | ret = -EINVAL; | 1641 | goto try_again; |
1428 | goto err_release; | ||
1429 | } | 1642 | } |
1430 | if (boot_size > priv->hw_params.max_bsm_size) { | 1643 | if (boot_size > priv->hw_params.max_bsm_size) { |
1431 | IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", | 1644 | IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", |
1432 | boot_size); | 1645 | boot_size); |
1433 | ret = -EINVAL; | 1646 | goto try_again; |
1434 | goto err_release; | ||
1435 | } | 1647 | } |
1436 | 1648 | ||
1437 | /* Allocate ucode buffers for card's bus-master loading ... */ | 1649 | /* Allocate ucode buffers for card's bus-master loading ... */ |
@@ -1515,23 +1727,38 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1515 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); | 1727 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); |
1516 | memcpy(priv->ucode_boot.v_addr, src, len); | 1728 | memcpy(priv->ucode_boot.v_addr, src, len); |
1517 | 1729 | ||
1730 | /************************************************** | ||
1731 | * This is still part of probe() in a sense... | ||
1732 | * | ||
1733 | * 9. Setup and register with mac80211 and debugfs | ||
1734 | **************************************************/ | ||
1735 | err = iwl_mac_setup_register(priv); | ||
1736 | if (err) | ||
1737 | goto out_unbind; | ||
1738 | |||
1739 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
1740 | if (err) | ||
1741 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
1742 | |||
1518 | /* We have our copies now, allow OS release its copies */ | 1743 | /* We have our copies now, allow OS release its copies */ |
1519 | release_firmware(ucode_raw); | 1744 | release_firmware(ucode_raw); |
1520 | return 0; | 1745 | return; |
1746 | |||
1747 | try_again: | ||
1748 | /* try next, if any */ | ||
1749 | if (iwl_request_firmware(priv, false)) | ||
1750 | goto out_unbind; | ||
1751 | release_firmware(ucode_raw); | ||
1752 | return; | ||
1521 | 1753 | ||
1522 | err_pci_alloc: | 1754 | err_pci_alloc: |
1523 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 1755 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
1524 | ret = -ENOMEM; | ||
1525 | iwl_dealloc_ucode_pci(priv); | 1756 | iwl_dealloc_ucode_pci(priv); |
1526 | 1757 | out_unbind: | |
1527 | err_release: | 1758 | device_release_driver(&priv->pci_dev->dev); |
1528 | release_firmware(ucode_raw); | 1759 | release_firmware(ucode_raw); |
1529 | |||
1530 | error: | ||
1531 | return ret; | ||
1532 | } | 1760 | } |
1533 | 1761 | ||
1534 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1535 | static const char *desc_lookup_text[] = { | 1762 | static const char *desc_lookup_text[] = { |
1536 | "OK", | 1763 | "OK", |
1537 | "FAIL", | 1764 | "FAIL", |
@@ -1561,7 +1788,7 @@ static const char *desc_lookup_text[] = { | |||
1561 | "DEBUG_1", | 1788 | "DEBUG_1", |
1562 | "DEBUG_2", | 1789 | "DEBUG_2", |
1563 | "DEBUG_3", | 1790 | "DEBUG_3", |
1564 | "UNKNOWN" | 1791 | "ADVANCED SYSASSERT" |
1565 | }; | 1792 | }; |
1566 | 1793 | ||
1567 | static const char *desc_lookup(int i) | 1794 | static const char *desc_lookup(int i) |
@@ -1589,7 +1816,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1589 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | 1816 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); |
1590 | 1817 | ||
1591 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 1818 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
1592 | IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); | 1819 | IWL_ERR(priv, |
1820 | "Not valid error log pointer 0x%08X for %s uCode\n", | ||
1821 | base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); | ||
1593 | return; | 1822 | return; |
1594 | } | 1823 | } |
1595 | 1824 | ||
@@ -1611,6 +1840,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1611 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | 1840 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); |
1612 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | 1841 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); |
1613 | 1842 | ||
1843 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, | ||
1844 | blink1, blink2, ilink1, ilink2); | ||
1845 | |||
1614 | IWL_ERR(priv, "Desc Time " | 1846 | IWL_ERR(priv, "Desc Time " |
1615 | "data1 data2 line\n"); | 1847 | "data1 data2 line\n"); |
1616 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | 1848 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", |
@@ -1627,17 +1859,19 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1627 | * iwl_print_event_log - Dump error event log to syslog | 1859 | * iwl_print_event_log - Dump error event log to syslog |
1628 | * | 1860 | * |
1629 | */ | 1861 | */ |
1630 | static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1862 | static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1631 | u32 num_events, u32 mode) | 1863 | u32 num_events, u32 mode, |
1864 | int pos, char **buf, size_t bufsz) | ||
1632 | { | 1865 | { |
1633 | u32 i; | 1866 | u32 i; |
1634 | u32 base; /* SRAM byte address of event log header */ | 1867 | u32 base; /* SRAM byte address of event log header */ |
1635 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | 1868 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ |
1636 | u32 ptr; /* SRAM byte address of log data */ | 1869 | u32 ptr; /* SRAM byte address of log data */ |
1637 | u32 ev, time, data; /* event log data */ | 1870 | u32 ev, time, data; /* event log data */ |
1871 | unsigned long reg_flags; | ||
1638 | 1872 | ||
1639 | if (num_events == 0) | 1873 | if (num_events == 0) |
1640 | return; | 1874 | return pos; |
1641 | if (priv->ucode_type == UCODE_INIT) | 1875 | if (priv->ucode_type == UCODE_INIT) |
1642 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 1876 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
1643 | else | 1877 | else |
@@ -1650,26 +1884,95 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1650 | 1884 | ||
1651 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | 1885 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); |
1652 | 1886 | ||
1887 | /* Make sure device is powered up for SRAM reads */ | ||
1888 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
1889 | iwl_grab_nic_access(priv); | ||
1890 | |||
1891 | /* Set starting address; reads will auto-increment */ | ||
1892 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
1893 | rmb(); | ||
1894 | |||
1653 | /* "time" is actually "data" for mode 0 (no timestamp). | 1895 | /* "time" is actually "data" for mode 0 (no timestamp). |
1654 | * place event id # at far right for easier visual parsing. */ | 1896 | * place event id # at far right for easier visual parsing. */ |
1655 | for (i = 0; i < num_events; i++) { | 1897 | for (i = 0; i < num_events; i++) { |
1656 | ev = iwl_read_targ_mem(priv, ptr); | 1898 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1657 | ptr += sizeof(u32); | 1899 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1658 | time = iwl_read_targ_mem(priv, ptr); | ||
1659 | ptr += sizeof(u32); | ||
1660 | if (mode == 0) { | 1900 | if (mode == 0) { |
1661 | /* data, ev */ | 1901 | /* data, ev */ |
1662 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | 1902 | if (bufsz) { |
1903 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1904 | "EVT_LOG:0x%08x:%04u\n", | ||
1905 | time, ev); | ||
1906 | } else { | ||
1907 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1908 | time, ev); | ||
1909 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", | ||
1910 | time, ev); | ||
1911 | } | ||
1663 | } else { | 1912 | } else { |
1664 | data = iwl_read_targ_mem(priv, ptr); | 1913 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1665 | ptr += sizeof(u32); | 1914 | if (bufsz) { |
1666 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | 1915 | pos += scnprintf(*buf + pos, bufsz - pos, |
1916 | "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1917 | time, data, ev); | ||
1918 | } else { | ||
1919 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1667 | time, data, ev); | 1920 | time, data, ev); |
1921 | trace_iwlwifi_dev_ucode_event(priv, time, | ||
1922 | data, ev); | ||
1923 | } | ||
1924 | } | ||
1925 | } | ||
1926 | |||
1927 | /* Allow device to power down */ | ||
1928 | iwl_release_nic_access(priv); | ||
1929 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
1930 | return pos; | ||
1931 | } | ||
1932 | |||
1933 | /** | ||
1934 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | ||
1935 | */ | ||
1936 | static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1937 | u32 num_wraps, u32 next_entry, | ||
1938 | u32 size, u32 mode, | ||
1939 | int pos, char **buf, size_t bufsz) | ||
1940 | { | ||
1941 | /* | ||
1942 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1943 | * i.e the entries just before the next ont that uCode would fill. | ||
1944 | */ | ||
1945 | if (num_wraps) { | ||
1946 | if (next_entry < size) { | ||
1947 | pos = iwl_print_event_log(priv, | ||
1948 | capacity - (size - next_entry), | ||
1949 | size - next_entry, mode, | ||
1950 | pos, buf, bufsz); | ||
1951 | pos = iwl_print_event_log(priv, 0, | ||
1952 | next_entry, mode, | ||
1953 | pos, buf, bufsz); | ||
1954 | } else | ||
1955 | pos = iwl_print_event_log(priv, next_entry - size, | ||
1956 | size, mode, pos, buf, bufsz); | ||
1957 | } else { | ||
1958 | if (next_entry < size) { | ||
1959 | pos = iwl_print_event_log(priv, 0, next_entry, | ||
1960 | mode, pos, buf, bufsz); | ||
1961 | } else { | ||
1962 | pos = iwl_print_event_log(priv, next_entry - size, | ||
1963 | size, mode, pos, buf, bufsz); | ||
1668 | } | 1964 | } |
1669 | } | 1965 | } |
1966 | return pos; | ||
1670 | } | 1967 | } |
1671 | 1968 | ||
1672 | void iwl_dump_nic_event_log(struct iwl_priv *priv) | 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) | ||
1973 | |||
1974 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | ||
1975 | char **buf, bool display) | ||
1673 | { | 1976 | { |
1674 | u32 base; /* SRAM byte address of event log header */ | 1977 | u32 base; /* SRAM byte address of event log header */ |
1675 | u32 capacity; /* event log capacity in # entries */ | 1978 | u32 capacity; /* event log capacity in # entries */ |
@@ -1677,6 +1980,8 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
1677 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1980 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1678 | u32 next_entry; /* index of next entry to be written by uCode */ | 1981 | u32 next_entry; /* index of next entry to be written by uCode */ |
1679 | u32 size; /* # entries that we'll print */ | 1982 | u32 size; /* # entries that we'll print */ |
1983 | int pos = 0; | ||
1984 | size_t bufsz = 0; | ||
1680 | 1985 | ||
1681 | if (priv->ucode_type == UCODE_INIT) | 1986 | if (priv->ucode_type == UCODE_INIT) |
1682 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 1987 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
@@ -1684,8 +1989,10 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
1684 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1989 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1685 | 1990 | ||
1686 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | 1991 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
1687 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | 1992 | IWL_ERR(priv, |
1688 | return; | 1993 | "Invalid event log pointer 0x%08X for %s uCode\n", |
1994 | base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); | ||
1995 | return -EINVAL; | ||
1689 | } | 1996 | } |
1690 | 1997 | ||
1691 | /* event log header */ | 1998 | /* event log header */ |
@@ -1694,27 +2001,71 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
1694 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2001 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1695 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2002 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1696 | 2003 | ||
2004 | if (capacity > MAX_EVENT_LOG_SIZE) { | ||
2005 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | ||
2006 | capacity, MAX_EVENT_LOG_SIZE); | ||
2007 | capacity = MAX_EVENT_LOG_SIZE; | ||
2008 | } | ||
2009 | |||
2010 | if (next_entry > MAX_EVENT_LOG_SIZE) { | ||
2011 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | ||
2012 | next_entry, MAX_EVENT_LOG_SIZE); | ||
2013 | next_entry = MAX_EVENT_LOG_SIZE; | ||
2014 | } | ||
2015 | |||
1697 | size = num_wraps ? capacity : next_entry; | 2016 | size = num_wraps ? capacity : next_entry; |
1698 | 2017 | ||
1699 | /* bail out if nothing in log */ | 2018 | /* bail out if nothing in log */ |
1700 | if (size == 0) { | 2019 | if (size == 0) { |
1701 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 2020 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1702 | return; | 2021 | return pos; |
1703 | } | 2022 | } |
1704 | 2023 | ||
1705 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | 2024 | #ifdef CONFIG_IWLWIFI_DEBUG |
1706 | size, num_wraps); | 2025 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) |
1707 | 2026 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | |
1708 | /* if uCode has wrapped back to top of log, start at the oldest entry, | 2027 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
1709 | * i.e the next one that uCode would fill. */ | 2028 | #else |
1710 | if (num_wraps) | 2029 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) |
1711 | iwl_print_event_log(priv, next_entry, | 2030 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
1712 | capacity - next_entry, mode); | 2031 | #endif |
1713 | /* (then/else) start at top of log */ | 2032 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", |
1714 | iwl_print_event_log(priv, 0, next_entry, mode); | 2033 | size); |
1715 | 2034 | ||
1716 | } | 2035 | #ifdef CONFIG_IWLWIFI_DEBUG |
2036 | if (display) { | ||
2037 | if (full_log) | ||
2038 | bufsz = capacity * 48; | ||
2039 | else | ||
2040 | bufsz = size * 48; | ||
2041 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
2042 | if (!*buf) | ||
2043 | return -ENOMEM; | ||
2044 | } | ||
2045 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | ||
2046 | /* | ||
2047 | * if uCode has wrapped back to top of log, | ||
2048 | * start at the oldest entry, | ||
2049 | * i.e the next one that uCode would fill. | ||
2050 | */ | ||
2051 | if (num_wraps) | ||
2052 | pos = iwl_print_event_log(priv, next_entry, | ||
2053 | capacity - next_entry, mode, | ||
2054 | pos, buf, bufsz); | ||
2055 | /* (then/else) start at top of log */ | ||
2056 | pos = iwl_print_event_log(priv, 0, | ||
2057 | next_entry, mode, pos, buf, bufsz); | ||
2058 | } else | ||
2059 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
2060 | next_entry, size, mode, | ||
2061 | pos, buf, bufsz); | ||
2062 | #else | ||
2063 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
2064 | next_entry, size, mode, | ||
2065 | pos, buf, bufsz); | ||
1717 | #endif | 2066 | #endif |
2067 | return pos; | ||
2068 | } | ||
1718 | 2069 | ||
1719 | /** | 2070 | /** |
1720 | * iwl_alive_start - called after REPLY_ALIVE notification received | 2071 | * iwl_alive_start - called after REPLY_ALIVE notification received |
@@ -1763,6 +2114,10 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
1763 | priv->active_rate = priv->rates_mask; | 2114 | priv->active_rate = priv->rates_mask; |
1764 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | 2115 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; |
1765 | 2116 | ||
2117 | /* Configure Tx antenna selection based on H/W config */ | ||
2118 | if (priv->cfg->ops->hcmd->set_tx_ant) | ||
2119 | priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); | ||
2120 | |||
1766 | if (iwl_is_associated(priv)) { | 2121 | if (iwl_is_associated(priv)) { |
1767 | struct iwl_rxon_cmd *active_rxon = | 2122 | struct iwl_rxon_cmd *active_rxon = |
1768 | (struct iwl_rxon_cmd *)&priv->active_rxon; | 2123 | (struct iwl_rxon_cmd *)&priv->active_rxon; |
@@ -1790,7 +2145,7 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
1790 | /* At this point, the NIC is initialized and operational */ | 2145 | /* At this point, the NIC is initialized and operational */ |
1791 | iwl_rf_kill_ct_config(priv); | 2146 | iwl_rf_kill_ct_config(priv); |
1792 | 2147 | ||
1793 | iwl_leds_register(priv); | 2148 | iwl_leds_init(priv); |
1794 | 2149 | ||
1795 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2150 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
1796 | set_bit(STATUS_READY, &priv->status); | 2151 | set_bit(STATUS_READY, &priv->status); |
@@ -1828,8 +2183,6 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1828 | if (!exit_pending) | 2183 | if (!exit_pending) |
1829 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2184 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
1830 | 2185 | ||
1831 | iwl_leds_unregister(priv); | ||
1832 | |||
1833 | iwl_clear_stations_table(priv); | 2186 | iwl_clear_stations_table(priv); |
1834 | 2187 | ||
1835 | /* Unblock any waiting calls */ | 2188 | /* Unblock any waiting calls */ |
@@ -1877,24 +2230,20 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1877 | 2230 | ||
1878 | /* device going down, Stop using ICT table */ | 2231 | /* device going down, Stop using ICT table */ |
1879 | iwl_disable_ict(priv); | 2232 | iwl_disable_ict(priv); |
1880 | spin_lock_irqsave(&priv->lock, flags); | ||
1881 | iwl_clear_bit(priv, CSR_GP_CNTRL, | ||
1882 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
1883 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1884 | 2233 | ||
1885 | iwl_txq_ctx_stop(priv); | 2234 | iwl_txq_ctx_stop(priv); |
1886 | iwl_rxq_stop(priv); | 2235 | iwl_rxq_stop(priv); |
1887 | 2236 | ||
1888 | iwl_write_prph(priv, APMG_CLK_DIS_REG, | 2237 | /* Power-down device's busmaster DMA clocks */ |
1889 | APMG_CLK_VAL_DMA_CLK_RQT); | 2238 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
1890 | |||
1891 | udelay(5); | 2239 | udelay(5); |
1892 | 2240 | ||
1893 | /* FIXME: apm_ops.suspend(priv) */ | 2241 | /* Make sure (redundant) we've released our request to stay awake */ |
1894 | if (exit_pending) | 2242 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
1895 | priv->cfg->ops->lib->apm_ops.stop(priv); | 2243 | |
1896 | else | 2244 | /* Stop the device, and put it in low power state */ |
1897 | priv->cfg->ops->lib->apm_ops.reset(priv); | 2245 | priv->cfg->ops->lib->apm_ops.stop(priv); |
2246 | |||
1898 | exit: | 2247 | exit: |
1899 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); | 2248 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); |
1900 | 2249 | ||
@@ -2121,18 +2470,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
2121 | return; | 2470 | return; |
2122 | } | 2471 | } |
2123 | 2472 | ||
2124 | static void iwl_bg_up(struct work_struct *data) | ||
2125 | { | ||
2126 | struct iwl_priv *priv = container_of(data, struct iwl_priv, up); | ||
2127 | |||
2128 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2129 | return; | ||
2130 | |||
2131 | mutex_lock(&priv->mutex); | ||
2132 | __iwl_up(priv); | ||
2133 | mutex_unlock(&priv->mutex); | ||
2134 | } | ||
2135 | |||
2136 | static void iwl_bg_restart(struct work_struct *data) | 2473 | static void iwl_bg_restart(struct work_struct *data) |
2137 | { | 2474 | { |
2138 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); | 2475 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); |
@@ -2149,7 +2486,13 @@ static void iwl_bg_restart(struct work_struct *data) | |||
2149 | ieee80211_restart_hw(priv->hw); | 2486 | ieee80211_restart_hw(priv->hw); |
2150 | } else { | 2487 | } else { |
2151 | iwl_down(priv); | 2488 | iwl_down(priv); |
2152 | queue_work(priv->workqueue, &priv->up); | 2489 | |
2490 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2491 | return; | ||
2492 | |||
2493 | mutex_lock(&priv->mutex); | ||
2494 | __iwl_up(priv); | ||
2495 | mutex_unlock(&priv->mutex); | ||
2153 | } | 2496 | } |
2154 | } | 2497 | } |
2155 | 2498 | ||
@@ -2281,6 +2624,71 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2281 | 2624 | ||
2282 | #define UCODE_READY_TIMEOUT (4 * HZ) | 2625 | #define UCODE_READY_TIMEOUT (4 * HZ) |
2283 | 2626 | ||
2627 | /* | ||
2628 | * Not a mac80211 entry point function, but it fits in with all the | ||
2629 | * other mac80211 functions grouped here. | ||
2630 | */ | ||
2631 | static int iwl_mac_setup_register(struct iwl_priv *priv) | ||
2632 | { | ||
2633 | int ret; | ||
2634 | struct ieee80211_hw *hw = priv->hw; | ||
2635 | hw->rate_control_algorithm = "iwl-agn-rs"; | ||
2636 | |||
2637 | /* Tell mac80211 our characteristics */ | ||
2638 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
2639 | IEEE80211_HW_NOISE_DBM | | ||
2640 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
2641 | IEEE80211_HW_SPECTRUM_MGMT; | ||
2642 | |||
2643 | if (!priv->cfg->broken_powersave) | ||
2644 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
2645 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
2646 | |||
2647 | if (priv->cfg->sku & IWL_SKU_N) | ||
2648 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2649 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | ||
2650 | |||
2651 | hw->sta_data_size = sizeof(struct iwl_station_priv); | ||
2652 | hw->wiphy->interface_modes = | ||
2653 | BIT(NL80211_IFTYPE_STATION) | | ||
2654 | BIT(NL80211_IFTYPE_ADHOC); | ||
2655 | |||
2656 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | ||
2657 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | ||
2658 | |||
2659 | /* | ||
2660 | * For now, disable PS by default because it affects | ||
2661 | * RX performance significantly. | ||
2662 | */ | ||
2663 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
2664 | |||
2665 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | ||
2666 | /* 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; | ||
2668 | |||
2669 | /* Default value; 4 EDCA QOS priorities */ | ||
2670 | hw->queues = 4; | ||
2671 | |||
2672 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||
2673 | |||
2674 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
2675 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
2676 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
2677 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
2678 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
2679 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
2680 | |||
2681 | ret = ieee80211_register_hw(priv->hw); | ||
2682 | if (ret) { | ||
2683 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
2684 | return ret; | ||
2685 | } | ||
2686 | priv->mac80211_registered = 1; | ||
2687 | |||
2688 | return 0; | ||
2689 | } | ||
2690 | |||
2691 | |||
2284 | static int iwl_mac_start(struct ieee80211_hw *hw) | 2692 | static int iwl_mac_start(struct ieee80211_hw *hw) |
2285 | { | 2693 | { |
2286 | struct iwl_priv *priv = hw->priv; | 2694 | struct iwl_priv *priv = hw->priv; |
@@ -2290,21 +2698,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) | |||
2290 | 2698 | ||
2291 | /* we should be verifying the device is ready to be opened */ | 2699 | /* we should be verifying the device is ready to be opened */ |
2292 | mutex_lock(&priv->mutex); | 2700 | mutex_lock(&priv->mutex); |
2293 | |||
2294 | /* fetch ucode file from disk, alloc and copy to bus-master buffers ... | ||
2295 | * ucode filename and max sizes are card-specific. */ | ||
2296 | |||
2297 | if (!priv->ucode_code.len) { | ||
2298 | ret = iwl_read_ucode(priv); | ||
2299 | if (ret) { | ||
2300 | IWL_ERR(priv, "Could not read microcode: %d\n", ret); | ||
2301 | mutex_unlock(&priv->mutex); | ||
2302 | return ret; | ||
2303 | } | ||
2304 | } | ||
2305 | |||
2306 | ret = __iwl_up(priv); | 2701 | ret = __iwl_up(priv); |
2307 | |||
2308 | mutex_unlock(&priv->mutex); | 2702 | mutex_unlock(&priv->mutex); |
2309 | 2703 | ||
2310 | if (ret) | 2704 | if (ret) |
@@ -2328,6 +2722,8 @@ static int iwl_mac_start(struct ieee80211_hw *hw) | |||
2328 | } | 2722 | } |
2329 | } | 2723 | } |
2330 | 2724 | ||
2725 | iwl_led_start(priv); | ||
2726 | |||
2331 | out: | 2727 | out: |
2332 | priv->is_open = 1; | 2728 | priv->is_open = 1; |
2333 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2729 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2404,6 +2800,10 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2404 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 2800 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
2405 | "Attempting to continue.\n"); | 2801 | "Attempting to continue.\n"); |
2406 | 2802 | ||
2803 | /* AP has all antennas */ | ||
2804 | priv->chain_noise_data.active_chains = | ||
2805 | priv->hw_params.valid_rx_ant; | ||
2806 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
2407 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2807 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2408 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2808 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2409 | 2809 | ||
@@ -2432,10 +2832,11 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2432 | /* restore RXON assoc */ | 2832 | /* restore RXON assoc */ |
2433 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2833 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2434 | iwlcore_commit_rxon(priv); | 2834 | iwlcore_commit_rxon(priv); |
2835 | iwl_reset_qos(priv); | ||
2435 | spin_lock_irqsave(&priv->lock, flags); | 2836 | spin_lock_irqsave(&priv->lock, flags); |
2436 | iwl_activate_qos(priv, 1); | 2837 | iwl_activate_qos(priv, 1); |
2437 | spin_unlock_irqrestore(&priv->lock, flags); | 2838 | spin_unlock_irqrestore(&priv->lock, flags); |
2438 | iwl_rxon_add_station(priv, iwl_bcast_addr, 0); | 2839 | iwl_add_bcast_station(priv); |
2439 | } | 2840 | } |
2440 | iwl_send_beacon_cmd(priv); | 2841 | iwl_send_beacon_cmd(priv); |
2441 | 2842 | ||
@@ -2445,14 +2846,18 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2445 | } | 2846 | } |
2446 | 2847 | ||
2447 | static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | 2848 | static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, |
2448 | struct ieee80211_key_conf *keyconf, const u8 *addr, | 2849 | struct ieee80211_vif *vif, |
2449 | u32 iv32, u16 *phase1key) | 2850 | struct ieee80211_key_conf *keyconf, |
2851 | struct ieee80211_sta *sta, | ||
2852 | u32 iv32, u16 *phase1key) | ||
2450 | { | 2853 | { |
2451 | 2854 | ||
2452 | struct iwl_priv *priv = hw->priv; | 2855 | struct iwl_priv *priv = hw->priv; |
2453 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2856 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2454 | 2857 | ||
2455 | iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key); | 2858 | iwl_update_tkip_key(priv, keyconf, |
2859 | sta ? sta->addr : iwl_bcast_addr, | ||
2860 | iv32, phase1key); | ||
2456 | 2861 | ||
2457 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2862 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2458 | } | 2863 | } |
@@ -2527,6 +2932,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2527 | } | 2932 | } |
2528 | 2933 | ||
2529 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 2934 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
2935 | struct ieee80211_vif *vif, | ||
2530 | enum ieee80211_ampdu_mlme_action action, | 2936 | enum ieee80211_ampdu_mlme_action action, |
2531 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2937 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2532 | { | 2938 | { |
@@ -2560,6 +2966,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2560 | return 0; | 2966 | return 0; |
2561 | else | 2967 | else |
2562 | return ret; | 2968 | return ret; |
2969 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2970 | /* do nothing */ | ||
2971 | return -EOPNOTSUPP; | ||
2563 | default: | 2972 | default: |
2564 | IWL_DEBUG_HT(priv, "unknown\n"); | 2973 | IWL_DEBUG_HT(priv, "unknown\n"); |
2565 | return -EINVAL; | 2974 | return -EINVAL; |
@@ -2580,6 +2989,47 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, | |||
2580 | return 0; | 2989 | return 0; |
2581 | } | 2990 | } |
2582 | 2991 | ||
2992 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | ||
2993 | struct ieee80211_vif *vif, | ||
2994 | enum sta_notify_cmd cmd, | ||
2995 | struct ieee80211_sta *sta) | ||
2996 | { | ||
2997 | struct iwl_priv *priv = hw->priv; | ||
2998 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
2999 | int sta_id; | ||
3000 | |||
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) { | ||
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: | ||
3014 | WARN_ON(!sta_priv->client); | ||
3015 | sta_priv->asleep = true; | ||
3016 | if (atomic_read(&sta_priv->pending_frames) > 0) | ||
3017 | ieee80211_sta_block_awake(hw, sta, true); | ||
3018 | break; | ||
3019 | case STA_NOTIFY_AWAKE: | ||
3020 | WARN_ON(!sta_priv->client); | ||
3021 | if (!sta_priv->asleep) | ||
3022 | break; | ||
3023 | sta_priv->asleep = false; | ||
3024 | sta_id = iwl_find_station(priv, sta->addr); | ||
3025 | if (sta_id != IWL_INVALID_STATION) | ||
3026 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
3027 | break; | ||
3028 | default: | ||
3029 | break; | ||
3030 | } | ||
3031 | } | ||
3032 | |||
2583 | /***************************************************************************** | 3033 | /***************************************************************************** |
2584 | * | 3034 | * |
2585 | * sysfs attributes | 3035 | * sysfs attributes |
@@ -2774,7 +3224,7 @@ static ssize_t show_statistics(struct device *d, | |||
2774 | return -EAGAIN; | 3224 | return -EAGAIN; |
2775 | 3225 | ||
2776 | mutex_lock(&priv->mutex); | 3226 | mutex_lock(&priv->mutex); |
2777 | rc = iwl_send_statistics_request(priv, 0); | 3227 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); |
2778 | mutex_unlock(&priv->mutex); | 3228 | mutex_unlock(&priv->mutex); |
2779 | 3229 | ||
2780 | if (rc) { | 3230 | if (rc) { |
@@ -2799,6 +3249,40 @@ static ssize_t show_statistics(struct device *d, | |||
2799 | 3249 | ||
2800 | static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); | 3250 | static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); |
2801 | 3251 | ||
3252 | static ssize_t show_rts_ht_protection(struct device *d, | ||
3253 | struct device_attribute *attr, char *buf) | ||
3254 | { | ||
3255 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3256 | |||
3257 | return sprintf(buf, "%s\n", | ||
3258 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | ||
3259 | } | ||
3260 | |||
3261 | static ssize_t store_rts_ht_protection(struct device *d, | ||
3262 | struct device_attribute *attr, | ||
3263 | const char *buf, size_t count) | ||
3264 | { | ||
3265 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
3266 | unsigned long val; | ||
3267 | int ret; | ||
3268 | |||
3269 | ret = strict_strtoul(buf, 10, &val); | ||
3270 | if (ret) | ||
3271 | IWL_INFO(priv, "Input is not in decimal form.\n"); | ||
3272 | else { | ||
3273 | if (!iwl_is_associated(priv)) | ||
3274 | priv->cfg->use_rts_for_ht = val ? true : false; | ||
3275 | else | ||
3276 | IWL_ERR(priv, "Sta associated with AP - " | ||
3277 | "Change protection mechanism is not allowed\n"); | ||
3278 | ret = count; | ||
3279 | } | ||
3280 | return ret; | ||
3281 | } | ||
3282 | |||
3283 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
3284 | show_rts_ht_protection, store_rts_ht_protection); | ||
3285 | |||
2802 | 3286 | ||
2803 | /***************************************************************************** | 3287 | /***************************************************************************** |
2804 | * | 3288 | * |
@@ -2812,7 +3296,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
2812 | 3296 | ||
2813 | init_waitqueue_head(&priv->wait_command_queue); | 3297 | init_waitqueue_head(&priv->wait_command_queue); |
2814 | 3298 | ||
2815 | INIT_WORK(&priv->up, iwl_bg_up); | ||
2816 | INIT_WORK(&priv->restart, iwl_bg_restart); | 3299 | INIT_WORK(&priv->restart, iwl_bg_restart); |
2817 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); | 3300 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); |
2818 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); | 3301 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); |
@@ -2829,6 +3312,10 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
2829 | priv->statistics_periodic.data = (unsigned long)priv; | 3312 | priv->statistics_periodic.data = (unsigned long)priv; |
2830 | priv->statistics_periodic.function = iwl_bg_statistics_periodic; | 3313 | priv->statistics_periodic.function = iwl_bg_statistics_periodic; |
2831 | 3314 | ||
3315 | init_timer(&priv->ucode_trace); | ||
3316 | priv->ucode_trace.data = (unsigned long)priv; | ||
3317 | priv->ucode_trace.function = iwl_bg_ucode_trace; | ||
3318 | |||
2832 | if (!priv->cfg->use_isr_legacy) | 3319 | if (!priv->cfg->use_isr_legacy) |
2833 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3320 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
2834 | iwl_irq_tasklet, (unsigned long)priv); | 3321 | iwl_irq_tasklet, (unsigned long)priv); |
@@ -2844,9 +3331,109 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
2844 | 3331 | ||
2845 | cancel_delayed_work_sync(&priv->init_alive_start); | 3332 | cancel_delayed_work_sync(&priv->init_alive_start); |
2846 | cancel_delayed_work(&priv->scan_check); | 3333 | cancel_delayed_work(&priv->scan_check); |
3334 | cancel_work_sync(&priv->start_internal_scan); | ||
2847 | cancel_delayed_work(&priv->alive_start); | 3335 | cancel_delayed_work(&priv->alive_start); |
2848 | cancel_work_sync(&priv->beacon_update); | 3336 | cancel_work_sync(&priv->beacon_update); |
2849 | del_timer_sync(&priv->statistics_periodic); | 3337 | del_timer_sync(&priv->statistics_periodic); |
3338 | del_timer_sync(&priv->ucode_trace); | ||
3339 | } | ||
3340 | |||
3341 | static void iwl_init_hw_rates(struct iwl_priv *priv, | ||
3342 | struct ieee80211_rate *rates) | ||
3343 | { | ||
3344 | int i; | ||
3345 | |||
3346 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { | ||
3347 | rates[i].bitrate = iwl_rates[i].ieee * 5; | ||
3348 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | ||
3349 | rates[i].hw_value_short = i; | ||
3350 | rates[i].flags = 0; | ||
3351 | if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { | ||
3352 | /* | ||
3353 | * If CCK != 1M then set short preamble rate flag. | ||
3354 | */ | ||
3355 | rates[i].flags |= | ||
3356 | (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? | ||
3357 | 0 : IEEE80211_RATE_SHORT_PREAMBLE; | ||
3358 | } | ||
3359 | } | ||
3360 | } | ||
3361 | |||
3362 | static int iwl_init_drv(struct iwl_priv *priv) | ||
3363 | { | ||
3364 | int ret; | ||
3365 | |||
3366 | priv->ibss_beacon = NULL; | ||
3367 | |||
3368 | spin_lock_init(&priv->sta_lock); | ||
3369 | spin_lock_init(&priv->hcmd_lock); | ||
3370 | |||
3371 | INIT_LIST_HEAD(&priv->free_frames); | ||
3372 | |||
3373 | mutex_init(&priv->mutex); | ||
3374 | mutex_init(&priv->sync_cmd_mutex); | ||
3375 | |||
3376 | /* Clear the driver's (not device's) station table */ | ||
3377 | iwl_clear_stations_table(priv); | ||
3378 | |||
3379 | priv->ieee_channels = NULL; | ||
3380 | priv->ieee_rates = NULL; | ||
3381 | priv->band = IEEE80211_BAND_2GHZ; | ||
3382 | |||
3383 | priv->iw_mode = NL80211_IFTYPE_STATION; | ||
3384 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | ||
3385 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
3386 | |||
3387 | /* initialize force reset */ | ||
3388 | priv->force_reset[IWL_RF_RESET].reset_duration = | ||
3389 | IWL_DELAY_NEXT_FORCE_RF_RESET; | ||
3390 | priv->force_reset[IWL_FW_RESET].reset_duration = | ||
3391 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; | ||
3392 | |||
3393 | /* Choose which receivers/antennas to use */ | ||
3394 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
3395 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
3396 | |||
3397 | iwl_init_scan_params(priv); | ||
3398 | |||
3399 | iwl_reset_qos(priv); | ||
3400 | |||
3401 | priv->qos_data.qos_active = 0; | ||
3402 | priv->qos_data.qos_cap.val = 0; | ||
3403 | |||
3404 | priv->rates_mask = IWL_RATES_MASK; | ||
3405 | /* Set the tx_power_user_lmt to the lowest power level | ||
3406 | * this value will get overwritten by channel max power avg | ||
3407 | * from eeprom */ | ||
3408 | priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; | ||
3409 | |||
3410 | ret = iwl_init_channel_map(priv); | ||
3411 | if (ret) { | ||
3412 | IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); | ||
3413 | goto err; | ||
3414 | } | ||
3415 | |||
3416 | ret = iwlcore_init_geos(priv); | ||
3417 | if (ret) { | ||
3418 | IWL_ERR(priv, "initializing geos failed: %d\n", ret); | ||
3419 | goto err_free_channel_map; | ||
3420 | } | ||
3421 | iwl_init_hw_rates(priv, priv->ieee_rates); | ||
3422 | |||
3423 | return 0; | ||
3424 | |||
3425 | err_free_channel_map: | ||
3426 | iwl_free_channel_map(priv); | ||
3427 | err: | ||
3428 | return ret; | ||
3429 | } | ||
3430 | |||
3431 | static void iwl_uninit_drv(struct iwl_priv *priv) | ||
3432 | { | ||
3433 | iwl_calib_free_results(priv); | ||
3434 | iwlcore_free_geos(priv); | ||
3435 | iwl_free_channel_map(priv); | ||
3436 | kfree(priv->scan); | ||
2850 | } | 3437 | } |
2851 | 3438 | ||
2852 | static struct attribute *iwl_sysfs_entries[] = { | 3439 | static struct attribute *iwl_sysfs_entries[] = { |
@@ -2855,6 +3442,7 @@ static struct attribute *iwl_sysfs_entries[] = { | |||
2855 | &dev_attr_statistics.attr, | 3442 | &dev_attr_statistics.attr, |
2856 | &dev_attr_temperature.attr, | 3443 | &dev_attr_temperature.attr, |
2857 | &dev_attr_tx_power.attr, | 3444 | &dev_attr_tx_power.attr, |
3445 | &dev_attr_rts_ht_protection.attr, | ||
2858 | #ifdef CONFIG_IWLWIFI_DEBUG | 3446 | #ifdef CONFIG_IWLWIFI_DEBUG |
2859 | &dev_attr_debug_level.attr, | 3447 | &dev_attr_debug_level.attr, |
2860 | #endif | 3448 | #endif |
@@ -2877,12 +3465,12 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
2877 | .set_key = iwl_mac_set_key, | 3465 | .set_key = iwl_mac_set_key, |
2878 | .update_tkip_key = iwl_mac_update_tkip_key, | 3466 | .update_tkip_key = iwl_mac_update_tkip_key, |
2879 | .get_stats = iwl_mac_get_stats, | 3467 | .get_stats = iwl_mac_get_stats, |
2880 | .get_tx_stats = iwl_mac_get_tx_stats, | ||
2881 | .conf_tx = iwl_mac_conf_tx, | 3468 | .conf_tx = iwl_mac_conf_tx, |
2882 | .reset_tsf = iwl_mac_reset_tsf, | 3469 | .reset_tsf = iwl_mac_reset_tsf, |
2883 | .bss_info_changed = iwl_bss_info_changed, | 3470 | .bss_info_changed = iwl_bss_info_changed, |
2884 | .ampdu_action = iwl_mac_ampdu_action, | 3471 | .ampdu_action = iwl_mac_ampdu_action, |
2885 | .hw_scan = iwl_mac_hw_scan | 3472 | .hw_scan = iwl_mac_hw_scan, |
3473 | .sta_notify = iwl_mac_sta_notify, | ||
2886 | }; | 3474 | }; |
2887 | 3475 | ||
2888 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3476 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -2972,10 +3560,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2972 | (unsigned long long) pci_resource_len(pdev, 0)); | 3560 | (unsigned long long) pci_resource_len(pdev, 0)); |
2973 | IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); | 3561 | IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); |
2974 | 3562 | ||
2975 | /* this spin lock will be used in apm_ops.init and EEPROM access | 3563 | /* these spin locks will be used in apm_ops.init and EEPROM access |
2976 | * we should init now | 3564 | * we should init now |
2977 | */ | 3565 | */ |
2978 | spin_lock_init(&priv->reg_lock); | 3566 | spin_lock_init(&priv->reg_lock); |
3567 | spin_lock_init(&priv->lock); | ||
3568 | |||
3569 | /* | ||
3570 | * stop and reset the on-board processor just in case it is in a | ||
3571 | * strange state ... like being left stranded by a primary kernel | ||
3572 | * and this is now the kdump kernel trying to start up | ||
3573 | */ | ||
3574 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
3575 | |||
2979 | iwl_hw_detect(priv); | 3576 | iwl_hw_detect(priv); |
2980 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", | 3577 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", |
2981 | priv->cfg->name, priv->hw_rev); | 3578 | priv->cfg->name, priv->hw_rev); |
@@ -2990,12 +3587,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2990 | goto out_iounmap; | 3587 | goto out_iounmap; |
2991 | } | 3588 | } |
2992 | 3589 | ||
2993 | /* amp init */ | ||
2994 | err = priv->cfg->ops->lib->apm_ops.init(priv); | ||
2995 | if (err < 0) { | ||
2996 | IWL_ERR(priv, "Failed to init APMG\n"); | ||
2997 | goto out_iounmap; | ||
2998 | } | ||
2999 | /***************** | 3590 | /***************** |
3000 | * 4. Read EEPROM | 3591 | * 4. Read EEPROM |
3001 | *****************/ | 3592 | *****************/ |
@@ -3056,9 +3647,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3056 | iwl_setup_deferred_work(priv); | 3647 | iwl_setup_deferred_work(priv); |
3057 | iwl_setup_rx_handlers(priv); | 3648 | iwl_setup_rx_handlers(priv); |
3058 | 3649 | ||
3059 | /********************************** | 3650 | /********************************************* |
3060 | * 8. Setup and register mac80211 | 3651 | * 8. Enable interrupts and read RFKILL state |
3061 | **********************************/ | 3652 | *********************************************/ |
3062 | 3653 | ||
3063 | /* enable interrupts if needed: hw bug w/a */ | 3654 | /* enable interrupts if needed: hw bug w/a */ |
3064 | pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); | 3655 | pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); |
@@ -3069,14 +3660,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3069 | 3660 | ||
3070 | iwl_enable_interrupts(priv); | 3661 | iwl_enable_interrupts(priv); |
3071 | 3662 | ||
3072 | err = iwl_setup_mac(priv); | ||
3073 | if (err) | ||
3074 | goto out_remove_sysfs; | ||
3075 | |||
3076 | err = iwl_dbgfs_register(priv, DRV_NAME); | ||
3077 | if (err) | ||
3078 | IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); | ||
3079 | |||
3080 | /* If platform's RF_KILL switch is NOT set to KILL */ | 3663 | /* If platform's RF_KILL switch is NOT set to KILL */ |
3081 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | 3664 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) |
3082 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 3665 | clear_bit(STATUS_RF_KILL_HW, &priv->status); |
@@ -3088,6 +3671,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3088 | 3671 | ||
3089 | iwl_power_initialize(priv); | 3672 | iwl_power_initialize(priv); |
3090 | iwl_tt_initialize(priv); | 3673 | iwl_tt_initialize(priv); |
3674 | |||
3675 | err = iwl_request_firmware(priv, true); | ||
3676 | if (err) | ||
3677 | goto out_remove_sysfs; | ||
3678 | |||
3091 | return 0; | 3679 | return 0; |
3092 | 3680 | ||
3093 | out_remove_sysfs: | 3681 | out_remove_sysfs: |
@@ -3141,6 +3729,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3141 | iwl_down(priv); | 3729 | iwl_down(priv); |
3142 | } | 3730 | } |
3143 | 3731 | ||
3732 | /* | ||
3733 | * Make sure device is reset to low power before unloading driver. | ||
3734 | * This may be redundant with iwl_down(), but there are paths to | ||
3735 | * run iwl_down() without calling apm_ops.stop(), and there are | ||
3736 | * paths to avoid running iwl_down() at all before leaving driver. | ||
3737 | * This (inexpensive) call *makes sure* device is reset. | ||
3738 | */ | ||
3739 | priv->cfg->ops->lib->apm_ops.stop(priv); | ||
3740 | |||
3144 | iwl_tt_exit(priv); | 3741 | iwl_tt_exit(priv); |
3145 | 3742 | ||
3146 | /* make sure we flush any pending irq or | 3743 | /* make sure we flush any pending irq or |
@@ -3197,43 +3794,103 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3197 | *****************************************************************************/ | 3794 | *****************************************************************************/ |
3198 | 3795 | ||
3199 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | 3796 | /* Hardware specific file defines the PCI IDs table for that hardware module */ |
3200 | static struct pci_device_id iwl_hw_card_ids[] = { | 3797 | static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { |
3201 | #ifdef CONFIG_IWL4965 | 3798 | #ifdef CONFIG_IWL4965 |
3202 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, | 3799 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, |
3203 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | 3800 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, |
3204 | #endif /* CONFIG_IWL4965 */ | 3801 | #endif /* CONFIG_IWL4965 */ |
3205 | #ifdef CONFIG_IWL5000 | 3802 | #ifdef CONFIG_IWL5000 |
3206 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, | 3803 | /* 5100 Series WiFi */ |
3207 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, | 3804 | {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ |
3208 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, | 3805 | {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3209 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, | 3806 | {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ |
3210 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, | 3807 | {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3211 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, | 3808 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */ |
3212 | {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, | 3809 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3213 | {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, | 3810 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */ |
3214 | {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, | 3811 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3215 | {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, | 3812 | {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */ |
3216 | /* 5350 WiFi/WiMax */ | 3813 | {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3217 | {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, | 3814 | {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */ |
3218 | {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, | 3815 | {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3219 | {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, | 3816 | {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */ |
3220 | /* 5150 Wifi/WiMax */ | 3817 | {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3221 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3818 | {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */ |
3222 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3819 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3223 | /* 6000/6050 Series */ | 3820 | {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */ |
3224 | {IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)}, | 3821 | {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3225 | {IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)}, | 3822 | {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */ |
3226 | {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)}, | 3823 | {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3227 | {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)}, | 3824 | {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */ |
3228 | {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)}, | 3825 | {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3229 | {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)}, | 3826 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */ |
3230 | {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3827 | {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3231 | {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3828 | |
3232 | {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3829 | /* 5300 Series WiFi */ |
3233 | {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3830 | {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */ |
3831 | {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3832 | {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3833 | {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3834 | {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3835 | {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3836 | {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3837 | {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3838 | {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3839 | {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3840 | {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3841 | {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3842 | |||
3843 | /* 5350 Series WiFi/WiMax */ | ||
3844 | {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3845 | {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3846 | {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3847 | |||
3848 | /* 5150 Series Wifi/WiMax */ | ||
3849 | {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3850 | {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3851 | {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */ | ||
3852 | {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ | ||
3853 | {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3854 | {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3855 | |||
3856 | {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3857 | {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3858 | {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */ | ||
3859 | {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */ | ||
3860 | |||
3861 | /* 6x00 Series */ | ||
3862 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, | ||
3863 | {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, | ||
3864 | {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, | ||
3865 | {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)}, | ||
3866 | {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)}, | ||
3867 | {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)}, | ||
3868 | {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)}, | ||
3869 | {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, | ||
3870 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | ||
3871 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | ||
3872 | |||
3873 | /* 6x50 WiFi/WiMax Series */ | ||
3874 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | ||
3875 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, | ||
3876 | {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, | ||
3877 | {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, | ||
3878 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, | ||
3879 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, | ||
3880 | |||
3234 | /* 1000 Series WiFi */ | 3881 | /* 1000 Series WiFi */ |
3235 | {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl1000_bgn_cfg)}, | 3882 | {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, |
3236 | {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl1000_bgn_cfg)}, | 3883 | {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)}, |
3884 | {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)}, | ||
3885 | {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)}, | ||
3886 | {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)}, | ||
3887 | {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)}, | ||
3888 | {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)}, | ||
3889 | {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)}, | ||
3890 | {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)}, | ||
3891 | {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)}, | ||
3892 | {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)}, | ||
3893 | {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)}, | ||
3237 | #endif /* CONFIG_IWL5000 */ | 3894 | #endif /* CONFIG_IWL5000 */ |
3238 | 3895 | ||
3239 | {0} | 3896 | {0} |
@@ -3288,9 +3945,9 @@ module_exit(iwl_exit); | |||
3288 | module_init(iwl_init); | 3945 | module_init(iwl_init); |
3289 | 3946 | ||
3290 | #ifdef CONFIG_IWLWIFI_DEBUG | 3947 | #ifdef CONFIG_IWLWIFI_DEBUG |
3291 | module_param_named(debug50, iwl_debug_level, uint, 0444); | 3948 | module_param_named(debug50, iwl_debug_level, uint, S_IRUGO); |
3292 | MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); | 3949 | MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); |
3293 | module_param_named(debug, iwl_debug_level, uint, 0644); | 3950 | module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); |
3294 | MODULE_PARM_DESC(debug, "debug output mask"); | 3951 | MODULE_PARM_DESC(debug, "debug output mask"); |
3295 | #endif | 3952 | #endif |
3296 | 3953 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index c4b565a2de94..8b516c5ff0bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -60,6 +60,7 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | *****************************************************************************/ | 61 | *****************************************************************************/ |
62 | 62 | ||
63 | #include <linux/slab.h> | ||
63 | #include <net/mac80211.h> | 64 | #include <net/mac80211.h> |
64 | 65 | ||
65 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
@@ -132,6 +133,7 @@ void iwl_calib_free_results(struct iwl_priv *priv) | |||
132 | priv->calib_results[i].buf_len = 0; | 133 | priv->calib_results[i].buf_len = 0; |
133 | } | 134 | } |
134 | } | 135 | } |
136 | EXPORT_SYMBOL(iwl_calib_free_results); | ||
135 | 137 | ||
136 | /***************************************************************************** | 138 | /***************************************************************************** |
137 | * RUNTIME calibrations framework | 139 | * RUNTIME calibrations framework |
@@ -413,7 +415,6 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, | |||
413 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ | 415 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ |
414 | static int iwl_sensitivity_write(struct iwl_priv *priv) | 416 | static int iwl_sensitivity_write(struct iwl_priv *priv) |
415 | { | 417 | { |
416 | int ret = 0; | ||
417 | struct iwl_sensitivity_cmd cmd ; | 418 | struct iwl_sensitivity_cmd cmd ; |
418 | struct iwl_sensitivity_data *data = NULL; | 419 | struct iwl_sensitivity_data *data = NULL; |
419 | struct iwl_host_cmd cmd_out = { | 420 | struct iwl_host_cmd cmd_out = { |
@@ -447,11 +448,11 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
447 | cpu_to_le16((u16)data->nrg_th_ofdm); | 448 | cpu_to_le16((u16)data->nrg_th_ofdm); |
448 | 449 | ||
449 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = | 450 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = |
450 | cpu_to_le16(190); | 451 | cpu_to_le16(data->barker_corr_th_min); |
451 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = | 452 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = |
452 | cpu_to_le16(390); | 453 | cpu_to_le16(data->barker_corr_th_min_mrc); |
453 | cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = | 454 | cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = |
454 | cpu_to_le16(62); | 455 | cpu_to_le16(data->nrg_th_cca); |
455 | 456 | ||
456 | IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", | 457 | IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", |
457 | data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, | 458 | data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, |
@@ -476,11 +477,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
476 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), | 477 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), |
477 | sizeof(u16)*HD_TABLE_SIZE); | 478 | sizeof(u16)*HD_TABLE_SIZE); |
478 | 479 | ||
479 | ret = iwl_send_cmd(priv, &cmd_out); | 480 | return iwl_send_cmd(priv, &cmd_out); |
480 | if (ret) | ||
481 | IWL_ERR(priv, "SENSITIVITY_CMD failed\n"); | ||
482 | |||
483 | return ret; | ||
484 | } | 481 | } |
485 | 482 | ||
486 | void iwl_init_sensitivity(struct iwl_priv *priv) | 483 | void iwl_init_sensitivity(struct iwl_priv *priv) |
@@ -516,7 +513,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
516 | for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) | 513 | for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) |
517 | data->nrg_silence_rssi[i] = 0; | 514 | data->nrg_silence_rssi[i] = 0; |
518 | 515 | ||
519 | data->auto_corr_ofdm = 90; | 516 | data->auto_corr_ofdm = ranges->auto_corr_min_ofdm; |
520 | data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc; | 517 | data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc; |
521 | data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1; | 518 | data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1; |
522 | data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1; | 519 | data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1; |
@@ -524,6 +521,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
524 | data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc; | 521 | data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc; |
525 | data->nrg_th_cck = ranges->nrg_th_cck; | 522 | data->nrg_th_cck = ranges->nrg_th_cck; |
526 | data->nrg_th_ofdm = ranges->nrg_th_ofdm; | 523 | data->nrg_th_ofdm = ranges->nrg_th_ofdm; |
524 | data->barker_corr_th_min = ranges->barker_corr_th_min; | ||
525 | data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc; | ||
526 | data->nrg_th_cca = ranges->nrg_th_cca; | ||
527 | 527 | ||
528 | data->last_bad_plcp_cnt_ofdm = 0; | 528 | data->last_bad_plcp_cnt_ofdm = 0; |
529 | data->last_fa_cnt_ofdm = 0; | 529 | data->last_fa_cnt_ofdm = 0; |
@@ -643,6 +643,15 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
643 | } | 643 | } |
644 | EXPORT_SYMBOL(iwl_sensitivity_calibration); | 644 | EXPORT_SYMBOL(iwl_sensitivity_calibration); |
645 | 645 | ||
646 | static inline u8 find_first_chain(u8 mask) | ||
647 | { | ||
648 | if (mask & ANT_A) | ||
649 | return CHAIN_A; | ||
650 | if (mask & ANT_B) | ||
651 | return CHAIN_B; | ||
652 | return CHAIN_C; | ||
653 | } | ||
654 | |||
646 | /* | 655 | /* |
647 | * Accumulate 20 beacons of signal and noise statistics for each of | 656 | * Accumulate 20 beacons of signal and noise statistics for each of |
648 | * 3 receivers/antennas/rx-chains, then figure out: | 657 | * 3 receivers/antennas/rx-chains, then figure out: |
@@ -675,14 +684,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
675 | u8 num_tx_chains; | 684 | u8 num_tx_chains; |
676 | unsigned long flags; | 685 | unsigned long flags; |
677 | struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); | 686 | struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); |
687 | u8 first_chain; | ||
678 | 688 | ||
679 | if (priv->disable_chain_noise_cal) | 689 | if (priv->disable_chain_noise_cal) |
680 | return; | 690 | return; |
681 | 691 | ||
682 | data = &(priv->chain_noise_data); | 692 | data = &(priv->chain_noise_data); |
683 | 693 | ||
684 | /* Accumulate just the first 20 beacons after the first association, | 694 | /* |
685 | * then we're done forever. */ | 695 | * Accumulate just the first "chain_noise_num_beacons" after |
696 | * the first association, then we're done forever. | ||
697 | */ | ||
686 | if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) { | 698 | if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) { |
687 | if (data->state == IWL_CHAIN_NOISE_ALIVE) | 699 | if (data->state == IWL_CHAIN_NOISE_ALIVE) |
688 | IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n"); | 700 | IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n"); |
@@ -710,7 +722,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
710 | return; | 722 | return; |
711 | } | 723 | } |
712 | 724 | ||
713 | /* Accumulate beacon statistics values across 20 beacons */ | 725 | /* |
726 | * Accumulate beacon statistics values across | ||
727 | * "chain_noise_num_beacons" | ||
728 | */ | ||
714 | chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & | 729 | chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & |
715 | IN_BAND_FILTER; | 730 | IN_BAND_FILTER; |
716 | chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & | 731 | chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & |
@@ -741,16 +756,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
741 | IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n", | 756 | IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n", |
742 | chain_noise_a, chain_noise_b, chain_noise_c); | 757 | chain_noise_a, chain_noise_b, chain_noise_c); |
743 | 758 | ||
744 | /* If this is the 20th beacon, determine: | 759 | /* If this is the "chain_noise_num_beacons", determine: |
745 | * 1) Disconnected antennas (using signal strengths) | 760 | * 1) Disconnected antennas (using signal strengths) |
746 | * 2) Differential gain (using silence noise) to balance receivers */ | 761 | * 2) Differential gain (using silence noise) to balance receivers */ |
747 | if (data->beacon_count != CAL_NUM_OF_BEACONS) | 762 | if (data->beacon_count != priv->cfg->chain_noise_num_beacons) |
748 | return; | 763 | return; |
749 | 764 | ||
750 | /* Analyze signal for disconnected antenna */ | 765 | /* Analyze signal for disconnected antenna */ |
751 | average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS; | 766 | average_sig[0] = |
752 | average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS; | 767 | (data->chain_signal_a) / priv->cfg->chain_noise_num_beacons; |
753 | average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS; | 768 | average_sig[1] = |
769 | (data->chain_signal_b) / priv->cfg->chain_noise_num_beacons; | ||
770 | average_sig[2] = | ||
771 | (data->chain_signal_c) / priv->cfg->chain_noise_num_beacons; | ||
754 | 772 | ||
755 | if (average_sig[0] >= average_sig[1]) { | 773 | if (average_sig[0] >= average_sig[1]) { |
756 | max_average_sig = average_sig[0]; | 774 | max_average_sig = average_sig[0]; |
@@ -790,6 +808,18 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
790 | } | 808 | } |
791 | } | 809 | } |
792 | 810 | ||
811 | /* | ||
812 | * The above algorithm sometimes fails when the ucode | ||
813 | * reports 0 for all chains. It's not clear why that | ||
814 | * happens to start with, but it is then causing trouble | ||
815 | * because this can make us enable more chains than the | ||
816 | * hardware really has. | ||
817 | * | ||
818 | * To be safe, simply mask out any chains that we know | ||
819 | * are not on the device. | ||
820 | */ | ||
821 | active_chains &= priv->hw_params.valid_rx_ant; | ||
822 | |||
793 | num_tx_chains = 0; | 823 | num_tx_chains = 0; |
794 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 824 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
795 | /* loops on all the bits of | 825 | /* loops on all the bits of |
@@ -803,13 +833,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
803 | /* there is a Tx antenna connected */ | 833 | /* there is a Tx antenna connected */ |
804 | break; | 834 | break; |
805 | if (num_tx_chains == priv->hw_params.tx_chains_num && | 835 | if (num_tx_chains == priv->hw_params.tx_chains_num && |
806 | data->disconn_array[i]) { | 836 | data->disconn_array[i]) { |
807 | /* This is the last TX antenna and is also | 837 | /* |
808 | * disconnected connect it anyway */ | 838 | * If all chains are disconnected |
809 | data->disconn_array[i] = 0; | 839 | * connect the first valid tx chain |
810 | active_chains |= ant_msk; | 840 | */ |
811 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - " | 841 | first_chain = |
812 | "declare %d as connected\n", i); | 842 | find_first_chain(priv->cfg->valid_tx_ant); |
843 | data->disconn_array[first_chain] = 0; | ||
844 | active_chains |= BIT(first_chain); | ||
845 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n", | ||
846 | first_chain); | ||
813 | break; | 847 | break; |
814 | } | 848 | } |
815 | } | 849 | } |
@@ -820,9 +854,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
820 | active_chains); | 854 | active_chains); |
821 | 855 | ||
822 | /* Analyze noise for rx balance */ | 856 | /* Analyze noise for rx balance */ |
823 | average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS); | 857 | average_noise[0] = |
824 | average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS); | 858 | ((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons); |
825 | average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS); | 859 | average_noise[1] = |
860 | ((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons); | ||
861 | average_noise[2] = | ||
862 | ((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons); | ||
826 | 863 | ||
827 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 864 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
828 | if (!(data->disconn_array[i]) && | 865 | if (!(data->disconn_array[i]) && |
@@ -843,7 +880,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
843 | 880 | ||
844 | if (priv->cfg->ops->utils->gain_computation) | 881 | if (priv->cfg->ops->utils->gain_computation) |
845 | priv->cfg->ops->utils->gain_computation(priv, average_noise, | 882 | priv->cfg->ops->utils->gain_computation(priv, average_noise, |
846 | min_average_noise_antenna_i, min_average_noise); | 883 | min_average_noise_antenna_i, min_average_noise, |
884 | find_first_chain(priv->cfg->valid_rx_ant)); | ||
847 | 885 | ||
848 | /* Some power changes may have been made during the calibration. | 886 | /* Some power changes may have been made during the calibration. |
849 | * Update and commit the RXON | 887 | * Update and commit the RXON |
@@ -870,7 +908,7 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv) | |||
870 | 908 | ||
871 | /* Ask for statistics now, the uCode will send notification | 909 | /* Ask for statistics now, the uCode will send notification |
872 | * periodically after association */ | 910 | * periodically after association */ |
873 | iwl_send_statistics_request(priv, CMD_ASYNC); | 911 | iwl_send_statistics_request(priv, CMD_ASYNC, true); |
874 | } | 912 | } |
875 | EXPORT_SYMBOL(iwl_reset_run_time_calib); | 913 | EXPORT_SYMBOL(iwl_reset_run_time_calib); |
876 | 914 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index b6cef989a796..2b7b1df83ba0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 4afaf773aeac..f4e59ae07f8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -109,17 +109,17 @@ enum { | |||
109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ | 109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ |
110 | 110 | ||
111 | /* WiMAX coexistence */ | 111 | /* WiMAX coexistence */ |
112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /*5000 only */ | 112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ |
113 | COEX_MEDIUM_NOTIFICATION = 0x5b, | 113 | COEX_MEDIUM_NOTIFICATION = 0x5b, |
114 | COEX_EVENT_CMD = 0x5c, | 114 | COEX_EVENT_CMD = 0x5c, |
115 | 115 | ||
116 | /* Calibration */ | 116 | /* Calibration */ |
117 | TEMPERATURE_NOTIFICATION = 0x62, | ||
117 | CALIBRATION_CFG_CMD = 0x65, | 118 | CALIBRATION_CFG_CMD = 0x65, |
118 | CALIBRATION_RES_NOTIFICATION = 0x66, | 119 | CALIBRATION_RES_NOTIFICATION = 0x66, |
119 | CALIBRATION_COMPLETE_NOTIFICATION = 0x67, | 120 | CALIBRATION_COMPLETE_NOTIFICATION = 0x67, |
120 | 121 | ||
121 | /* 802.11h related */ | 122 | /* 802.11h related */ |
122 | RADAR_NOTIFICATION = 0x70, /* not used */ | ||
123 | REPLY_QUIET_CMD = 0x71, /* not used */ | 123 | REPLY_QUIET_CMD = 0x71, /* not used */ |
124 | REPLY_CHANNEL_SWITCH = 0x72, | 124 | REPLY_CHANNEL_SWITCH = 0x72, |
125 | CHANNEL_SWITCH_NOTIFICATION = 0x73, | 125 | CHANNEL_SWITCH_NOTIFICATION = 0x73, |
@@ -148,7 +148,7 @@ enum { | |||
148 | QUIET_NOTIFICATION = 0x96, /* not used */ | 148 | QUIET_NOTIFICATION = 0x96, /* not used */ |
149 | REPLY_TX_PWR_TABLE_CMD = 0x97, | 149 | REPLY_TX_PWR_TABLE_CMD = 0x97, |
150 | REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */ | 150 | REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */ |
151 | TX_ANT_CONFIGURATION_CMD = 0x98, /* not used */ | 151 | TX_ANT_CONFIGURATION_CMD = 0x98, |
152 | MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ | 152 | MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ |
153 | 153 | ||
154 | /* Bluetooth device coexistence config command */ | 154 | /* Bluetooth device coexistence config command */ |
@@ -353,6 +353,9 @@ struct iwl3945_power_per_rate { | |||
353 | #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 | 353 | #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 |
354 | #define POWER_TABLE_CCK_ENTRY 32 | 354 | #define POWER_TABLE_CCK_ENTRY 32 |
355 | 355 | ||
356 | #define IWL_PWR_NUM_HT_OFDM_ENTRIES 24 | ||
357 | #define IWL_PWR_CCK_ENTRIES 2 | ||
358 | |||
356 | /** | 359 | /** |
357 | * union iwl4965_tx_power_dual_stream | 360 | * union iwl4965_tx_power_dual_stream |
358 | * | 361 | * |
@@ -411,6 +414,16 @@ struct iwl5000_tx_power_dbm_cmd { | |||
411 | u8 reserved; | 414 | u8 reserved; |
412 | } __attribute__ ((packed)); | 415 | } __attribute__ ((packed)); |
413 | 416 | ||
417 | /** | ||
418 | * Command TX_ANT_CONFIGURATION_CMD = 0x98 | ||
419 | * This command is used to configure valid Tx antenna. | ||
420 | * By default uCode concludes the valid antenna according to the radio flavor. | ||
421 | * This command enables the driver to override/modify this conclusion. | ||
422 | */ | ||
423 | struct iwl_tx_ant_config_cmd { | ||
424 | __le32 valid; | ||
425 | } __attribute__ ((packed)); | ||
426 | |||
414 | /****************************************************************************** | 427 | /****************************************************************************** |
415 | * (0a) | 428 | * (0a) |
416 | * Alive and Error Commands & Responses: | 429 | * Alive and Error Commands & Responses: |
@@ -793,7 +806,7 @@ struct iwl3945_channel_switch_cmd { | |||
793 | struct iwl3945_power_per_rate power[IWL_MAX_RATES]; | 806 | struct iwl3945_power_per_rate power[IWL_MAX_RATES]; |
794 | } __attribute__ ((packed)); | 807 | } __attribute__ ((packed)); |
795 | 808 | ||
796 | struct iwl_channel_switch_cmd { | 809 | struct iwl4965_channel_switch_cmd { |
797 | u8 band; | 810 | u8 band; |
798 | u8 expect_beacon; | 811 | u8 expect_beacon; |
799 | __le16 channel; | 812 | __le16 channel; |
@@ -803,6 +816,48 @@ struct iwl_channel_switch_cmd { | |||
803 | struct iwl4965_tx_power_db tx_power; | 816 | struct iwl4965_tx_power_db tx_power; |
804 | } __attribute__ ((packed)); | 817 | } __attribute__ ((packed)); |
805 | 818 | ||
819 | /** | ||
820 | * struct iwl5000_channel_switch_cmd | ||
821 | * @band: 0- 5.2GHz, 1- 2.4GHz | ||
822 | * @expect_beacon: 0- resume transmits after channel switch | ||
823 | * 1- wait for beacon to resume transmits | ||
824 | * @channel: new channel number | ||
825 | * @rxon_flags: Rx on flags | ||
826 | * @rxon_filter_flags: filtering parameters | ||
827 | * @switch_time: switch time in extended beacon format | ||
828 | * @reserved: reserved bytes | ||
829 | */ | ||
830 | struct iwl5000_channel_switch_cmd { | ||
831 | u8 band; | ||
832 | u8 expect_beacon; | ||
833 | __le16 channel; | ||
834 | __le32 rxon_flags; | ||
835 | __le32 rxon_filter_flags; | ||
836 | __le32 switch_time; | ||
837 | __le32 reserved[2][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES]; | ||
838 | } __attribute__ ((packed)); | ||
839 | |||
840 | /** | ||
841 | * struct iwl6000_channel_switch_cmd | ||
842 | * @band: 0- 5.2GHz, 1- 2.4GHz | ||
843 | * @expect_beacon: 0- resume transmits after channel switch | ||
844 | * 1- wait for beacon to resume transmits | ||
845 | * @channel: new channel number | ||
846 | * @rxon_flags: Rx on flags | ||
847 | * @rxon_filter_flags: filtering parameters | ||
848 | * @switch_time: switch time in extended beacon format | ||
849 | * @reserved: reserved bytes | ||
850 | */ | ||
851 | struct iwl6000_channel_switch_cmd { | ||
852 | u8 band; | ||
853 | u8 expect_beacon; | ||
854 | __le16 channel; | ||
855 | __le32 rxon_flags; | ||
856 | __le32 rxon_filter_flags; | ||
857 | __le32 switch_time; | ||
858 | __le32 reserved[3][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES]; | ||
859 | } __attribute__ ((packed)); | ||
860 | |||
806 | /* | 861 | /* |
807 | * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) | 862 | * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) |
808 | */ | 863 | */ |
@@ -921,6 +976,7 @@ struct iwl_qosparam_cmd { | |||
921 | #define STA_MODIFY_TX_RATE_MSK 0x04 | 976 | #define STA_MODIFY_TX_RATE_MSK 0x04 |
922 | #define STA_MODIFY_ADDBA_TID_MSK 0x08 | 977 | #define STA_MODIFY_ADDBA_TID_MSK 0x08 |
923 | #define STA_MODIFY_DELBA_TID_MSK 0x10 | 978 | #define STA_MODIFY_DELBA_TID_MSK 0x10 |
979 | #define STA_MODIFY_SLEEP_TX_COUNT_MSK 0x20 | ||
924 | 980 | ||
925 | /* Receiver address (actually, Rx station's index into station table), | 981 | /* Receiver address (actually, Rx station's index into station table), |
926 | * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ | 982 | * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ |
@@ -1051,7 +1107,14 @@ struct iwl4965_addsta_cmd { | |||
1051 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ | 1107 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ |
1052 | __le16 add_immediate_ba_ssn; | 1108 | __le16 add_immediate_ba_ssn; |
1053 | 1109 | ||
1054 | __le32 reserved2; | 1110 | /* |
1111 | * Number of packets OK to transmit to station even though | ||
1112 | * it is asleep -- used to synchronise PS-poll and u-APSD | ||
1113 | * responses while ucode keeps track of STA sleep state. | ||
1114 | */ | ||
1115 | __le16 sleep_tx_count; | ||
1116 | |||
1117 | __le16 reserved2; | ||
1055 | } __attribute__ ((packed)); | 1118 | } __attribute__ ((packed)); |
1056 | 1119 | ||
1057 | /* 5000 */ | 1120 | /* 5000 */ |
@@ -1082,7 +1145,14 @@ struct iwl_addsta_cmd { | |||
1082 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ | 1145 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ |
1083 | __le16 add_immediate_ba_ssn; | 1146 | __le16 add_immediate_ba_ssn; |
1084 | 1147 | ||
1085 | __le32 reserved2; | 1148 | /* |
1149 | * Number of packets OK to transmit to station even though | ||
1150 | * it is asleep -- used to synchronise PS-poll and u-APSD | ||
1151 | * responses while ucode keeps track of STA sleep state. | ||
1152 | */ | ||
1153 | __le16 sleep_tx_count; | ||
1154 | |||
1155 | __le16 reserved2; | ||
1086 | } __attribute__ ((packed)); | 1156 | } __attribute__ ((packed)); |
1087 | 1157 | ||
1088 | 1158 | ||
@@ -1634,6 +1704,21 @@ enum { | |||
1634 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ | 1704 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ |
1635 | }; | 1705 | }; |
1636 | 1706 | ||
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 | |||
1637 | static inline bool iwl_is_tx_success(u32 status) | 1722 | static inline bool iwl_is_tx_success(u32 status) |
1638 | { | 1723 | { |
1639 | status &= TX_STATUS_MSK; | 1724 | status &= TX_STATUS_MSK; |
@@ -2163,6 +2248,31 @@ struct iwl_link_quality_cmd { | |||
2163 | } __attribute__ ((packed)); | 2248 | } __attribute__ ((packed)); |
2164 | 2249 | ||
2165 | /* | 2250 | /* |
2251 | * BT configuration enable flags: | ||
2252 | * bit 0 - 1: BT channel announcement enabled | ||
2253 | * 0: disable | ||
2254 | * bit 1 - 1: priority of BT device enabled | ||
2255 | * 0: disable | ||
2256 | * bit 2 - 1: BT 2 wire support enabled | ||
2257 | * 0: disable | ||
2258 | */ | ||
2259 | #define BT_COEX_DISABLE (0x0) | ||
2260 | #define BT_ENABLE_CHANNEL_ANNOUNCE BIT(0) | ||
2261 | #define BT_ENABLE_PRIORITY BIT(1) | ||
2262 | #define BT_ENABLE_2_WIRE BIT(2) | ||
2263 | |||
2264 | #define BT_COEX_DISABLE (0x0) | ||
2265 | #define BT_COEX_ENABLE (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY) | ||
2266 | |||
2267 | #define BT_LEAD_TIME_MIN (0x0) | ||
2268 | #define BT_LEAD_TIME_DEF (0x1E) | ||
2269 | #define BT_LEAD_TIME_MAX (0xFF) | ||
2270 | |||
2271 | #define BT_MAX_KILL_MIN (0x1) | ||
2272 | #define BT_MAX_KILL_DEF (0x5) | ||
2273 | #define BT_MAX_KILL_MAX (0xFF) | ||
2274 | |||
2275 | /* | ||
2166 | * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) | 2276 | * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) |
2167 | * | 2277 | * |
2168 | * 3945 and 4965 support hardware handshake with Bluetooth device on | 2278 | * 3945 and 4965 support hardware handshake with Bluetooth device on |
@@ -2411,7 +2521,7 @@ struct iwl_card_state_notif { | |||
2411 | 2521 | ||
2412 | #define HW_CARD_DISABLED 0x01 | 2522 | #define HW_CARD_DISABLED 0x01 |
2413 | #define SW_CARD_DISABLED 0x02 | 2523 | #define SW_CARD_DISABLED 0x02 |
2414 | #define RF_CARD_DISABLED 0x04 | 2524 | #define CT_CARD_DISABLED 0x04 |
2415 | #define RXON_CARD_DISABLED 0x10 | 2525 | #define RXON_CARD_DISABLED 0x10 |
2416 | 2526 | ||
2417 | struct iwl_ct_kill_config { | 2527 | struct iwl_ct_kill_config { |
@@ -2497,9 +2607,10 @@ struct iwl_scan_channel { | |||
2497 | /** | 2607 | /** |
2498 | * struct iwl_ssid_ie - directed scan network information element | 2608 | * struct iwl_ssid_ie - directed scan network information element |
2499 | * | 2609 | * |
2500 | * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field | 2610 | * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in |
2501 | * in struct iwl_scan_channel; each channel may select different ssids from | 2611 | * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel; |
2502 | * among the 4 entries. SSID IEs get transmitted in reverse order of entry. | 2612 | * each channel may select different ssids from among the 20 (4) entries. |
2613 | * SSID IEs get transmitted in reverse order of entry. | ||
2503 | */ | 2614 | */ |
2504 | struct iwl_ssid_ie { | 2615 | struct iwl_ssid_ie { |
2505 | u8 id; | 2616 | u8 id; |
@@ -2510,8 +2621,11 @@ struct iwl_ssid_ie { | |||
2510 | #define PROBE_OPTION_MAX_3945 4 | 2621 | #define PROBE_OPTION_MAX_3945 4 |
2511 | #define PROBE_OPTION_MAX 20 | 2622 | #define PROBE_OPTION_MAX 20 |
2512 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) | 2623 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) |
2513 | #define IWL_GOOD_CRC_TH cpu_to_le16(1) | 2624 | #define IWL_GOOD_CRC_TH_DISABLED 0 |
2625 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) | ||
2626 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) | ||
2514 | #define IWL_MAX_SCAN_SIZE 1024 | 2627 | #define IWL_MAX_SCAN_SIZE 1024 |
2628 | #define IWL_MAX_CMD_SIZE 4096 | ||
2515 | #define IWL_MAX_PROBE_REQUEST 200 | 2629 | #define IWL_MAX_PROBE_REQUEST 200 |
2516 | 2630 | ||
2517 | /* | 2631 | /* |
@@ -2884,7 +2998,7 @@ struct statistics_rx_ht_phy { | |||
2884 | __le32 agg_crc32_good; | 2998 | __le32 agg_crc32_good; |
2885 | __le32 agg_mpdu_cnt; | 2999 | __le32 agg_mpdu_cnt; |
2886 | __le32 agg_cnt; | 3000 | __le32 agg_cnt; |
2887 | __le32 reserved2; | 3001 | __le32 unsupport_mcs; |
2888 | } __attribute__ ((packed)); | 3002 | } __attribute__ ((packed)); |
2889 | 3003 | ||
2890 | #define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) | 3004 | #define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) |
@@ -2987,8 +3101,8 @@ struct statistics_div { | |||
2987 | } __attribute__ ((packed)); | 3101 | } __attribute__ ((packed)); |
2988 | 3102 | ||
2989 | struct statistics_general { | 3103 | struct statistics_general { |
2990 | __le32 temperature; | 3104 | __le32 temperature; /* radio temperature */ |
2991 | __le32 temperature_m; | 3105 | __le32 temperature_m; /* for 5000 and up, this is radio voltage */ |
2992 | struct statistics_dbg dbg; | 3106 | struct statistics_dbg dbg; |
2993 | __le32 sleep_time; | 3107 | __le32 sleep_time; |
2994 | __le32 slots_out; | 3108 | __le32 slots_out; |
@@ -2996,11 +3110,20 @@ struct statistics_general { | |||
2996 | __le32 ttl_timestamp; | 3110 | __le32 ttl_timestamp; |
2997 | struct statistics_div div; | 3111 | struct statistics_div div; |
2998 | __le32 rx_enable_counter; | 3112 | __le32 rx_enable_counter; |
2999 | __le32 reserved1; | 3113 | /* |
3114 | * num_of_sos_states: | ||
3115 | * count the number of times we have to re-tune | ||
3116 | * in order to get out of bad PHY status | ||
3117 | */ | ||
3118 | __le32 num_of_sos_states; | ||
3000 | __le32 reserved2; | 3119 | __le32 reserved2; |
3001 | __le32 reserved3; | 3120 | __le32 reserved3; |
3002 | } __attribute__ ((packed)); | 3121 | } __attribute__ ((packed)); |
3003 | 3122 | ||
3123 | #define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0) | ||
3124 | #define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1) | ||
3125 | #define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2) | ||
3126 | |||
3004 | /* | 3127 | /* |
3005 | * REPLY_STATISTICS_CMD = 0x9c, | 3128 | * REPLY_STATISTICS_CMD = 0x9c, |
3006 | * 3945 and 4965 identical. | 3129 | * 3945 and 4965 identical. |
@@ -3057,13 +3180,30 @@ struct iwl_notif_statistics { | |||
3057 | 3180 | ||
3058 | /* | 3181 | /* |
3059 | * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) | 3182 | * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) |
3183 | * | ||
3184 | * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed | ||
3185 | * in regardless of how many missed beacons, which mean when driver receive the | ||
3186 | * notification, inside the command, it can find all the beacons information | ||
3187 | * which include number of total missed beacons, number of consecutive missed | ||
3188 | * beacons, number of beacons received and number of beacons expected to | ||
3189 | * receive. | ||
3190 | * | ||
3191 | * If uCode detected consecutive_missed_beacons > 5, it will reset the radio | ||
3192 | * in order to bring the radio/PHY back to working state; which has no relation | ||
3193 | * to when driver will perform sensitivity calibration. | ||
3194 | * | ||
3195 | * Driver should set it own missed_beacon_threshold to decide when to perform | ||
3196 | * sensitivity calibration based on number of consecutive missed beacons in | ||
3197 | * order to improve overall performance, especially in noisy environment. | ||
3198 | * | ||
3060 | */ | 3199 | */ |
3061 | /* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, | 3200 | |
3062 | * then this notification will be sent. */ | 3201 | #define IWL_MISSED_BEACON_THRESHOLD_MIN (1) |
3063 | #define CONSECUTIVE_MISSED_BCONS_TH 20 | 3202 | #define IWL_MISSED_BEACON_THRESHOLD_DEF (5) |
3203 | #define IWL_MISSED_BEACON_THRESHOLD_MAX IWL_MISSED_BEACON_THRESHOLD_DEF | ||
3064 | 3204 | ||
3065 | struct iwl_missed_beacon_notif { | 3205 | struct iwl_missed_beacon_notif { |
3066 | __le32 consequtive_missed_beacons; | 3206 | __le32 consecutive_missed_beacons; |
3067 | __le32 total_missed_becons; | 3207 | __le32 total_missed_becons; |
3068 | __le32 num_expected_beacons; | 3208 | __le32 num_expected_beacons; |
3069 | __le32 num_recvd_beacons; | 3209 | __le32 num_recvd_beacons; |
@@ -3237,12 +3377,6 @@ struct iwl_missed_beacon_notif { | |||
3237 | * Lower values mean higher energy; this means making sure that the value | 3377 | * Lower values mean higher energy; this means making sure that the value |
3238 | * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". | 3378 | * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". |
3239 | * | 3379 | * |
3240 | * Driver should set the following entries to fixed values: | ||
3241 | * | ||
3242 | * HD_MIN_ENERGY_OFDM_DET_INDEX 100 | ||
3243 | * HD_BARKER_CORR_TH_ADD_MIN_INDEX 190 | ||
3244 | * HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390 | ||
3245 | * HD_OFDM_ENERGY_TH_IN_INDEX 62 | ||
3246 | */ | 3380 | */ |
3247 | 3381 | ||
3248 | /* | 3382 | /* |
@@ -3339,11 +3473,7 @@ enum { | |||
3339 | IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, | 3473 | IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, |
3340 | IWL_PHY_CALIBRATE_DC_CMD = 8, | 3474 | IWL_PHY_CALIBRATE_DC_CMD = 8, |
3341 | IWL_PHY_CALIBRATE_LO_CMD = 9, | 3475 | IWL_PHY_CALIBRATE_LO_CMD = 9, |
3342 | IWL_PHY_CALIBRATE_RX_BB_CMD = 10, | ||
3343 | IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, | 3476 | IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, |
3344 | IWL_PHY_CALIBRATE_RX_IQ_CMD = 12, | ||
3345 | IWL_PHY_CALIBRATION_NOISE_CMD = 13, | ||
3346 | IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14, | ||
3347 | IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, | 3477 | IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, |
3348 | IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, | 3478 | IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, |
3349 | IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, | 3479 | IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, |
@@ -3440,30 +3570,134 @@ struct iwl_led_cmd { | |||
3440 | } __attribute__ ((packed)); | 3570 | } __attribute__ ((packed)); |
3441 | 3571 | ||
3442 | /* | 3572 | /* |
3443 | * Coexistence WIFI/WIMAX Command | 3573 | * station priority table entries |
3444 | * COEX_PRIORITY_TABLE_CMD = 0x5a | 3574 | * also used as potential "events" value for both |
3445 | * | 3575 | * COEX_MEDIUM_NOTIFICATION and COEX_EVENT_CMD |
3576 | */ | ||
3577 | |||
3578 | /* | ||
3579 | * COEX events entry flag masks | ||
3580 | * RP - Requested Priority | ||
3581 | * WP - Win Medium Priority: priority assigned when the contention has been won | ||
3582 | */ | ||
3583 | #define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG (0x1) | ||
3584 | #define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG (0x2) | ||
3585 | #define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG (0x4) | ||
3586 | |||
3587 | #define COEX_CU_UNASSOC_IDLE_RP 4 | ||
3588 | #define COEX_CU_UNASSOC_MANUAL_SCAN_RP 4 | ||
3589 | #define COEX_CU_UNASSOC_AUTO_SCAN_RP 4 | ||
3590 | #define COEX_CU_CALIBRATION_RP 4 | ||
3591 | #define COEX_CU_PERIODIC_CALIBRATION_RP 4 | ||
3592 | #define COEX_CU_CONNECTION_ESTAB_RP 4 | ||
3593 | #define COEX_CU_ASSOCIATED_IDLE_RP 4 | ||
3594 | #define COEX_CU_ASSOC_MANUAL_SCAN_RP 4 | ||
3595 | #define COEX_CU_ASSOC_AUTO_SCAN_RP 4 | ||
3596 | #define COEX_CU_ASSOC_ACTIVE_LEVEL_RP 4 | ||
3597 | #define COEX_CU_RF_ON_RP 6 | ||
3598 | #define COEX_CU_RF_OFF_RP 4 | ||
3599 | #define COEX_CU_STAND_ALONE_DEBUG_RP 6 | ||
3600 | #define COEX_CU_IPAN_ASSOC_LEVEL_RP 4 | ||
3601 | #define COEX_CU_RSRVD1_RP 4 | ||
3602 | #define COEX_CU_RSRVD2_RP 4 | ||
3603 | |||
3604 | #define COEX_CU_UNASSOC_IDLE_WP 3 | ||
3605 | #define COEX_CU_UNASSOC_MANUAL_SCAN_WP 3 | ||
3606 | #define COEX_CU_UNASSOC_AUTO_SCAN_WP 3 | ||
3607 | #define COEX_CU_CALIBRATION_WP 3 | ||
3608 | #define COEX_CU_PERIODIC_CALIBRATION_WP 3 | ||
3609 | #define COEX_CU_CONNECTION_ESTAB_WP 3 | ||
3610 | #define COEX_CU_ASSOCIATED_IDLE_WP 3 | ||
3611 | #define COEX_CU_ASSOC_MANUAL_SCAN_WP 3 | ||
3612 | #define COEX_CU_ASSOC_AUTO_SCAN_WP 3 | ||
3613 | #define COEX_CU_ASSOC_ACTIVE_LEVEL_WP 3 | ||
3614 | #define COEX_CU_RF_ON_WP 3 | ||
3615 | #define COEX_CU_RF_OFF_WP 3 | ||
3616 | #define COEX_CU_STAND_ALONE_DEBUG_WP 6 | ||
3617 | #define COEX_CU_IPAN_ASSOC_LEVEL_WP 3 | ||
3618 | #define COEX_CU_RSRVD1_WP 3 | ||
3619 | #define COEX_CU_RSRVD2_WP 3 | ||
3620 | |||
3621 | #define COEX_UNASSOC_IDLE_FLAGS 0 | ||
3622 | #define COEX_UNASSOC_MANUAL_SCAN_FLAGS \ | ||
3623 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3624 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) | ||
3625 | #define COEX_UNASSOC_AUTO_SCAN_FLAGS \ | ||
3626 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3627 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) | ||
3628 | #define COEX_CALIBRATION_FLAGS \ | ||
3629 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3630 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) | ||
3631 | #define COEX_PERIODIC_CALIBRATION_FLAGS 0 | ||
3632 | /* | ||
3633 | * COEX_CONNECTION_ESTAB: | ||
3634 | * we need DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. | ||
3635 | */ | ||
3636 | #define COEX_CONNECTION_ESTAB_FLAGS \ | ||
3637 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3638 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \ | ||
3639 | COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG) | ||
3640 | #define COEX_ASSOCIATED_IDLE_FLAGS 0 | ||
3641 | #define COEX_ASSOC_MANUAL_SCAN_FLAGS \ | ||
3642 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3643 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) | ||
3644 | #define COEX_ASSOC_AUTO_SCAN_FLAGS \ | ||
3645 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3646 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) | ||
3647 | #define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0 | ||
3648 | #define COEX_RF_ON_FLAGS 0 | ||
3649 | #define COEX_RF_OFF_FLAGS 0 | ||
3650 | #define COEX_STAND_ALONE_DEBUG_FLAGS \ | ||
3651 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3652 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG) | ||
3653 | #define COEX_IPAN_ASSOC_LEVEL_FLAGS \ | ||
3654 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3655 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \ | ||
3656 | COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG) | ||
3657 | #define COEX_RSRVD1_FLAGS 0 | ||
3658 | #define COEX_RSRVD2_FLAGS 0 | ||
3659 | /* | ||
3660 | * COEX_CU_RF_ON is the event wrapping all radio ownership. | ||
3661 | * We need DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. | ||
3446 | */ | 3662 | */ |
3663 | #define COEX_CU_RF_ON_FLAGS \ | ||
3664 | (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \ | ||
3665 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \ | ||
3666 | COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG) | ||
3667 | |||
3668 | |||
3447 | enum { | 3669 | enum { |
3670 | /* un-association part */ | ||
3448 | COEX_UNASSOC_IDLE = 0, | 3671 | COEX_UNASSOC_IDLE = 0, |
3449 | COEX_UNASSOC_MANUAL_SCAN = 1, | 3672 | COEX_UNASSOC_MANUAL_SCAN = 1, |
3450 | COEX_UNASSOC_AUTO_SCAN = 2, | 3673 | COEX_UNASSOC_AUTO_SCAN = 2, |
3674 | /* calibration */ | ||
3451 | COEX_CALIBRATION = 3, | 3675 | COEX_CALIBRATION = 3, |
3452 | COEX_PERIODIC_CALIBRATION = 4, | 3676 | COEX_PERIODIC_CALIBRATION = 4, |
3677 | /* connection */ | ||
3453 | COEX_CONNECTION_ESTAB = 5, | 3678 | COEX_CONNECTION_ESTAB = 5, |
3679 | /* association part */ | ||
3454 | COEX_ASSOCIATED_IDLE = 6, | 3680 | COEX_ASSOCIATED_IDLE = 6, |
3455 | COEX_ASSOC_MANUAL_SCAN = 7, | 3681 | COEX_ASSOC_MANUAL_SCAN = 7, |
3456 | COEX_ASSOC_AUTO_SCAN = 8, | 3682 | COEX_ASSOC_AUTO_SCAN = 8, |
3457 | COEX_ASSOC_ACTIVE_LEVEL = 9, | 3683 | COEX_ASSOC_ACTIVE_LEVEL = 9, |
3684 | /* RF ON/OFF */ | ||
3458 | COEX_RF_ON = 10, | 3685 | COEX_RF_ON = 10, |
3459 | COEX_RF_OFF = 11, | 3686 | COEX_RF_OFF = 11, |
3460 | COEX_STAND_ALONE_DEBUG = 12, | 3687 | COEX_STAND_ALONE_DEBUG = 12, |
3688 | /* IPAN */ | ||
3461 | COEX_IPAN_ASSOC_LEVEL = 13, | 3689 | COEX_IPAN_ASSOC_LEVEL = 13, |
3690 | /* reserved */ | ||
3462 | COEX_RSRVD1 = 14, | 3691 | COEX_RSRVD1 = 14, |
3463 | COEX_RSRVD2 = 15, | 3692 | COEX_RSRVD2 = 15, |
3464 | COEX_NUM_OF_EVENTS = 16 | 3693 | COEX_NUM_OF_EVENTS = 16 |
3465 | }; | 3694 | }; |
3466 | 3695 | ||
3696 | /* | ||
3697 | * Coexistence WIFI/WIMAX Command | ||
3698 | * COEX_PRIORITY_TABLE_CMD = 0x5a | ||
3699 | * | ||
3700 | */ | ||
3467 | struct iwl_wimax_coex_event_entry { | 3701 | struct iwl_wimax_coex_event_entry { |
3468 | u8 request_prio; | 3702 | u8 request_prio; |
3469 | u8 win_medium_prio; | 3703 | u8 win_medium_prio; |
@@ -3488,6 +3722,55 @@ struct iwl_wimax_coex_cmd { | |||
3488 | struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS]; | 3722 | struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS]; |
3489 | } __attribute__ ((packed)); | 3723 | } __attribute__ ((packed)); |
3490 | 3724 | ||
3725 | /* | ||
3726 | * Coexistence MEDIUM NOTIFICATION | ||
3727 | * COEX_MEDIUM_NOTIFICATION = 0x5b | ||
3728 | * | ||
3729 | * notification from uCode to host to indicate medium changes | ||
3730 | * | ||
3731 | */ | ||
3732 | /* | ||
3733 | * status field | ||
3734 | * bit 0 - 2: medium status | ||
3735 | * bit 3: medium change indication | ||
3736 | * bit 4 - 31: reserved | ||
3737 | */ | ||
3738 | /* status option values, (0 - 2 bits) */ | ||
3739 | #define COEX_MEDIUM_BUSY (0x0) /* radio belongs to WiMAX */ | ||
3740 | #define COEX_MEDIUM_ACTIVE (0x1) /* radio belongs to WiFi */ | ||
3741 | #define COEX_MEDIUM_PRE_RELEASE (0x2) /* received radio release */ | ||
3742 | #define COEX_MEDIUM_MSK (0x7) | ||
3743 | |||
3744 | /* send notification status (1 bit) */ | ||
3745 | #define COEX_MEDIUM_CHANGED (0x8) | ||
3746 | #define COEX_MEDIUM_CHANGED_MSK (0x8) | ||
3747 | #define COEX_MEDIUM_SHIFT (3) | ||
3748 | |||
3749 | struct iwl_coex_medium_notification { | ||
3750 | __le32 status; | ||
3751 | __le32 events; | ||
3752 | } __attribute__ ((packed)); | ||
3753 | |||
3754 | /* | ||
3755 | * Coexistence EVENT Command | ||
3756 | * COEX_EVENT_CMD = 0x5c | ||
3757 | * | ||
3758 | * send from host to uCode for coex event request. | ||
3759 | */ | ||
3760 | /* flags options */ | ||
3761 | #define COEX_EVENT_REQUEST_MSK (0x1) | ||
3762 | |||
3763 | struct iwl_coex_event_cmd { | ||
3764 | u8 flags; | ||
3765 | u8 event; | ||
3766 | __le16 reserved; | ||
3767 | } __attribute__ ((packed)); | ||
3768 | |||
3769 | struct iwl_coex_event_resp { | ||
3770 | __le32 status; | ||
3771 | } __attribute__ ((packed)); | ||
3772 | |||
3773 | |||
3491 | /****************************************************************************** | 3774 | /****************************************************************************** |
3492 | * (13) | 3775 | * (13) |
3493 | * Union of all expected notifications/responses: | 3776 | * Union of all expected notifications/responses: |
@@ -3495,6 +3778,16 @@ struct iwl_wimax_coex_cmd { | |||
3495 | *****************************************************************************/ | 3778 | *****************************************************************************/ |
3496 | 3779 | ||
3497 | struct iwl_rx_packet { | 3780 | struct iwl_rx_packet { |
3781 | /* | ||
3782 | * The first 4 bytes of the RX frame header contain both the RX frame | ||
3783 | * size and some flags. | ||
3784 | * Bit fields: | ||
3785 | * 31: flag flush RB request | ||
3786 | * 30: flag ignore TC (terminal counter) request | ||
3787 | * 29: flag fast IRQ request | ||
3788 | * 28-14: Reserved | ||
3789 | * 13-00: RX frame size | ||
3790 | */ | ||
3498 | __le32 len_n_flags; | 3791 | __le32 len_n_flags; |
3499 | struct iwl_cmd_header hdr; | 3792 | struct iwl_cmd_header hdr; |
3500 | union { | 3793 | union { |
@@ -3514,6 +3807,8 @@ struct iwl_rx_packet { | |||
3514 | struct iwl_notif_statistics stats; | 3807 | struct iwl_notif_statistics stats; |
3515 | struct iwl_compressed_ba_resp compressed_ba; | 3808 | struct iwl_compressed_ba_resp compressed_ba; |
3516 | struct iwl_missed_beacon_notif missed_beacon; | 3809 | struct iwl_missed_beacon_notif missed_beacon; |
3810 | struct iwl_coex_medium_notification coex_medium_notif; | ||
3811 | struct iwl_coex_event_resp coex_event; | ||
3517 | __le32 status; | 3812 | __le32 status; |
3518 | u8 raw[0]; | 3813 | u8 raw[0]; |
3519 | } u; | 3814 | } u; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2dc928755454..049b652bcb5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/slab.h> | ||
33 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
34 | 35 | ||
35 | #include "iwl-eeprom.h" | 36 | #include "iwl-eeprom.h" |
@@ -47,6 +48,57 @@ MODULE_VERSION(IWLWIFI_VERSION); | |||
47 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | 48 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); |
48 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
49 | 50 | ||
51 | /* | ||
52 | * set bt_coex_active to true, uCode will do kill/defer | ||
53 | * every time the priority line is asserted (BT is sending signals on the | ||
54 | * priority line in the PCIx). | ||
55 | * set bt_coex_active to false, uCode will ignore the BT activity and | ||
56 | * perform the normal operation | ||
57 | * | ||
58 | * User might experience transmit issue on some platform due to WiFi/BT | ||
59 | * co-exist problem. The possible behaviors are: | ||
60 | * Able to scan and finding all the available AP | ||
61 | * Not able to associate with any AP | ||
62 | * On those platforms, WiFi communication can be restored by set | ||
63 | * "bt_coex_active" module parameter to "false" | ||
64 | * | ||
65 | * default: bt_coex_active = true (BT_COEX_ENABLE) | ||
66 | */ | ||
67 | static bool bt_coex_active = true; | ||
68 | module_param(bt_coex_active, bool, S_IRUGO); | ||
69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); | ||
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 | |||
50 | #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ | 102 | #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ |
51 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 103 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
52 | IWL_RATE_SISO_##s##M_PLCP, \ | 104 | IWL_RATE_SISO_##s##M_PLCP, \ |
@@ -178,6 +230,7 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | |||
178 | } | 230 | } |
179 | return ant; | 231 | return ant; |
180 | } | 232 | } |
233 | EXPORT_SYMBOL(iwl_toggle_tx_ant); | ||
181 | 234 | ||
182 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 235 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
183 | EXPORT_SYMBOL(iwl_bcast_addr); | 236 | EXPORT_SYMBOL(iwl_bcast_addr); |
@@ -224,7 +277,10 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
224 | /* nic_init */ | 277 | /* nic_init */ |
225 | spin_lock_irqsave(&priv->lock, flags); | 278 | spin_lock_irqsave(&priv->lock, flags); |
226 | priv->cfg->ops->lib->apm_ops.init(priv); | 279 | priv->cfg->ops->lib->apm_ops.init(priv); |
227 | iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); | 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 | |||
228 | spin_unlock_irqrestore(&priv->lock, flags); | 284 | spin_unlock_irqrestore(&priv->lock, flags); |
229 | 285 | ||
230 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | 286 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); |
@@ -252,10 +308,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
252 | 308 | ||
253 | spin_unlock_irqrestore(&priv->lock, flags); | 309 | spin_unlock_irqrestore(&priv->lock, flags); |
254 | 310 | ||
255 | /* Allocate and init all Tx and Command queues */ | 311 | /* Allocate or reset and init all Tx and Command queues */ |
256 | ret = iwl_txq_ctx_reset(priv); | 312 | if (!priv->txq) { |
257 | if (ret) | 313 | ret = iwl_txq_ctx_alloc(priv); |
258 | return ret; | 314 | if (ret) |
315 | return ret; | ||
316 | } else | ||
317 | iwl_txq_ctx_reset(priv); | ||
259 | 318 | ||
260 | set_bit(STATUS_INIT, &priv->status); | 319 | set_bit(STATUS_INIT, &priv->status); |
261 | 320 | ||
@@ -415,9 +474,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
415 | if (priv->cfg->ht_greenfield_support) | 474 | if (priv->cfg->ht_greenfield_support) |
416 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 475 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |
417 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 476 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
418 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & | ||
419 | (WLAN_HT_CAP_SM_PS_DISABLED << 2)); | ||
420 | |||
421 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | 477 | max_bit_rate = MAX_BIT_RATE_20_MHZ; |
422 | if (priv->hw_params.ht40_channel & BIT(band)) { | 478 | if (priv->hw_params.ht40_channel & BIT(band)) { |
423 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 479 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -452,28 +508,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
452 | } | 508 | } |
453 | } | 509 | } |
454 | 510 | ||
455 | static void iwlcore_init_hw_rates(struct iwl_priv *priv, | ||
456 | struct ieee80211_rate *rates) | ||
457 | { | ||
458 | int i; | ||
459 | |||
460 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { | ||
461 | rates[i].bitrate = iwl_rates[i].ieee * 5; | ||
462 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | ||
463 | rates[i].hw_value_short = i; | ||
464 | rates[i].flags = 0; | ||
465 | if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { | ||
466 | /* | ||
467 | * If CCK != 1M then set short preamble rate flag. | ||
468 | */ | ||
469 | rates[i].flags |= | ||
470 | (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? | ||
471 | 0 : IEEE80211_RATE_SHORT_PREAMBLE; | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | |||
476 | |||
477 | /** | 511 | /** |
478 | * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom | 512 | * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom |
479 | */ | 513 | */ |
@@ -605,11 +639,27 @@ void iwlcore_free_geos(struct iwl_priv *priv) | |||
605 | } | 639 | } |
606 | EXPORT_SYMBOL(iwlcore_free_geos); | 640 | EXPORT_SYMBOL(iwlcore_free_geos); |
607 | 641 | ||
642 | /* | ||
643 | * iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this | ||
644 | * function. | ||
645 | */ | ||
646 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
647 | __le32 *tx_flags) | ||
648 | { | ||
649 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
650 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
651 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
652 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
653 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
654 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
655 | } | ||
656 | } | ||
657 | EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); | ||
658 | |||
608 | static bool is_single_rx_stream(struct iwl_priv *priv) | 659 | static bool is_single_rx_stream(struct iwl_priv *priv) |
609 | { | 660 | { |
610 | return !priv->current_ht_config.is_ht || | 661 | return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || |
611 | ((priv->current_ht_config.mcs.rx_mask[1] == 0) && | 662 | priv->current_ht_config.single_chain_sufficient; |
612 | (priv->current_ht_config.mcs.rx_mask[2] == 0)); | ||
613 | } | 663 | } |
614 | 664 | ||
615 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, | 665 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, |
@@ -635,10 +685,9 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, | |||
635 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 685 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
636 | struct ieee80211_sta_ht_cap *sta_ht_inf) | 686 | struct ieee80211_sta_ht_cap *sta_ht_inf) |
637 | { | 687 | { |
638 | struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; | 688 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
639 | 689 | ||
640 | if ((!iwl_ht_conf->is_ht) || | 690 | if (!ht_conf->is_ht || !ht_conf->is_40mhz) |
641 | (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ)) | ||
642 | return 0; | 691 | return 0; |
643 | 692 | ||
644 | /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 693 | /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@@ -654,7 +703,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
654 | #endif | 703 | #endif |
655 | return iwl_is_channel_extension(priv, priv->band, | 704 | return iwl_is_channel_extension(priv, priv->band, |
656 | le16_to_cpu(priv->staging_rxon.channel), | 705 | le16_to_cpu(priv->staging_rxon.channel), |
657 | iwl_ht_conf->extension_chan_offset); | 706 | ht_conf->extension_chan_offset); |
658 | } | 707 | } |
659 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); | 708 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); |
660 | 709 | ||
@@ -878,11 +927,11 @@ u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) | |||
878 | } | 927 | } |
879 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); | 928 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); |
880 | 929 | ||
881 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | 930 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) |
882 | { | 931 | { |
883 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 932 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
884 | 933 | ||
885 | if (!ht_info->is_ht) { | 934 | if (!ht_conf->is_ht) { |
886 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | 935 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | |
887 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | 936 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | |
888 | RXON_FLG_HT40_PROT_MSK | | 937 | RXON_FLG_HT40_PROT_MSK | |
@@ -893,7 +942,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
893 | /* FIXME: if the definition of ht_protection changed, the "translation" | 942 | /* FIXME: if the definition of ht_protection changed, the "translation" |
894 | * will be needed for rxon->flags | 943 | * will be needed for rxon->flags |
895 | */ | 944 | */ |
896 | rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); | 945 | rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); |
897 | 946 | ||
898 | /* Set up channel bandwidth: | 947 | /* Set up channel bandwidth: |
899 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | 948 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ |
@@ -902,10 +951,10 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
902 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 951 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
903 | if (iwl_is_ht40_tx_allowed(priv, NULL)) { | 952 | if (iwl_is_ht40_tx_allowed(priv, NULL)) { |
904 | /* pure ht40 */ | 953 | /* pure ht40 */ |
905 | if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | 954 | if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { |
906 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | 955 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; |
907 | /* Note: control channel is opposite of extension channel */ | 956 | /* Note: control channel is opposite of extension channel */ |
908 | switch (ht_info->extension_chan_offset) { | 957 | switch (ht_conf->extension_chan_offset) { |
909 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 958 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
910 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | 959 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; |
911 | break; | 960 | break; |
@@ -915,7 +964,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
915 | } | 964 | } |
916 | } else { | 965 | } else { |
917 | /* Note: control channel is opposite of extension channel */ | 966 | /* Note: control channel is opposite of extension channel */ |
918 | switch (ht_info->extension_chan_offset) { | 967 | switch (ht_conf->extension_chan_offset) { |
919 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 968 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
920 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 969 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
921 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | 970 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; |
@@ -938,14 +987,10 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
938 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 987 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
939 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 988 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
940 | 989 | ||
941 | IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X " | 990 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " |
942 | "rxon flags 0x%X operation mode :0x%X " | ||
943 | "extension channel offset 0x%x\n", | 991 | "extension channel offset 0x%x\n", |
944 | ht_info->mcs.rx_mask[0], | 992 | le32_to_cpu(rxon->flags), ht_conf->ht_protection, |
945 | ht_info->mcs.rx_mask[1], | 993 | ht_conf->extension_chan_offset); |
946 | ht_info->mcs.rx_mask[2], | ||
947 | le32_to_cpu(rxon->flags), ht_info->ht_protection, | ||
948 | ht_info->extension_chan_offset); | ||
949 | return; | 994 | return; |
950 | } | 995 | } |
951 | EXPORT_SYMBOL(iwl_set_rxon_ht); | 996 | EXPORT_SYMBOL(iwl_set_rxon_ht); |
@@ -955,47 +1000,43 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); | |||
955 | #define IWL_NUM_IDLE_CHAINS_DUAL 2 | 1000 | #define IWL_NUM_IDLE_CHAINS_DUAL 2 |
956 | #define IWL_NUM_IDLE_CHAINS_SINGLE 1 | 1001 | #define IWL_NUM_IDLE_CHAINS_SINGLE 1 |
957 | 1002 | ||
958 | /* Determine how many receiver/antenna chains to use. | 1003 | /* |
959 | * More provides better reception via diversity. Fewer saves power. | 1004 | * Determine how many receiver/antenna chains to use. |
1005 | * | ||
1006 | * More provides better reception via diversity. Fewer saves power | ||
1007 | * at the expense of throughput, but only when not in powersave to | ||
1008 | * start with. | ||
1009 | * | ||
960 | * MIMO (dual stream) requires at least 2, but works better with 3. | 1010 | * MIMO (dual stream) requires at least 2, but works better with 3. |
961 | * This does not determine *which* chains to use, just how many. | 1011 | * This does not determine *which* chains to use, just how many. |
962 | */ | 1012 | */ |
963 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | 1013 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) |
964 | { | 1014 | { |
965 | bool is_single = is_single_rx_stream(priv); | ||
966 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | ||
967 | |||
968 | /* # of Rx chains to use when expecting MIMO. */ | 1015 | /* # of Rx chains to use when expecting MIMO. */ |
969 | if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == | 1016 | if (is_single_rx_stream(priv)) |
970 | WLAN_HT_CAP_SM_PS_STATIC))) | ||
971 | return IWL_NUM_RX_CHAINS_SINGLE; | 1017 | return IWL_NUM_RX_CHAINS_SINGLE; |
972 | else | 1018 | else |
973 | return IWL_NUM_RX_CHAINS_MULTIPLE; | 1019 | return IWL_NUM_RX_CHAINS_MULTIPLE; |
974 | } | 1020 | } |
975 | 1021 | ||
1022 | /* | ||
1023 | * When we are in power saving mode, unless device support spatial | ||
1024 | * multiplexing power save, use the active count for rx chain count. | ||
1025 | */ | ||
976 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | 1026 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) |
977 | { | 1027 | { |
978 | int idle_cnt; | 1028 | /* # Rx chains when idling, depending on SMPS mode */ |
979 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | 1029 | switch (priv->current_ht_config.smps) { |
980 | /* # Rx chains when idling and maybe trying to save power */ | 1030 | case IEEE80211_SMPS_STATIC: |
981 | switch (priv->current_ht_config.sm_ps) { | 1031 | case IEEE80211_SMPS_DYNAMIC: |
982 | case WLAN_HT_CAP_SM_PS_STATIC: | 1032 | return IWL_NUM_IDLE_CHAINS_SINGLE; |
983 | case WLAN_HT_CAP_SM_PS_DYNAMIC: | 1033 | case IEEE80211_SMPS_OFF: |
984 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : | 1034 | return active_cnt; |
985 | IWL_NUM_IDLE_CHAINS_SINGLE; | ||
986 | break; | ||
987 | case WLAN_HT_CAP_SM_PS_DISABLED: | ||
988 | idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; | ||
989 | break; | ||
990 | case WLAN_HT_CAP_SM_PS_INVALID: | ||
991 | default: | 1035 | default: |
992 | IWL_ERR(priv, "invalid mimo ps mode %d\n", | 1036 | WARN(1, "invalid SMPS mode %d", |
993 | priv->current_ht_config.sm_ps); | 1037 | priv->current_ht_config.smps); |
994 | WARN_ON(1); | 1038 | return active_cnt; |
995 | idle_cnt = -1; | ||
996 | break; | ||
997 | } | 1039 | } |
998 | return idle_cnt; | ||
999 | } | 1040 | } |
1000 | 1041 | ||
1001 | /* up to 4 chains */ | 1042 | /* up to 4 chains */ |
@@ -1005,7 +1046,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) | |||
1005 | res = (chain_bitmap & BIT(0)) >> 0; | 1046 | res = (chain_bitmap & BIT(0)) >> 0; |
1006 | res += (chain_bitmap & BIT(1)) >> 1; | 1047 | res += (chain_bitmap & BIT(1)) >> 1; |
1007 | res += (chain_bitmap & BIT(2)) >> 2; | 1048 | res += (chain_bitmap & BIT(2)) >> 2; |
1008 | res += (chain_bitmap & BIT(4)) >> 4; | 1049 | res += (chain_bitmap & BIT(3)) >> 3; |
1009 | return res; | 1050 | return res; |
1010 | } | 1051 | } |
1011 | 1052 | ||
@@ -1281,18 +1322,28 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1281 | 1322 | ||
1282 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1323 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1283 | { | 1324 | { |
1284 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1325 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1285 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; | 1326 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; |
1286 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | 1327 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); |
1287 | IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n", | 1328 | |
1288 | le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); | 1329 | if (priv->switch_rxon.switch_in_progress) { |
1289 | rxon->channel = csa->channel; | 1330 | if (!le32_to_cpu(csa->status) && |
1290 | priv->staging_rxon.channel = csa->channel; | 1331 | (csa->channel == priv->switch_rxon.channel)) { |
1332 | rxon->channel = csa->channel; | ||
1333 | priv->staging_rxon.channel = csa->channel; | ||
1334 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | ||
1335 | le16_to_cpu(csa->channel)); | ||
1336 | } else | ||
1337 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | ||
1338 | le16_to_cpu(csa->channel)); | ||
1339 | |||
1340 | priv->switch_rxon.switch_in_progress = false; | ||
1341 | } | ||
1291 | } | 1342 | } |
1292 | EXPORT_SYMBOL(iwl_rx_csa); | 1343 | EXPORT_SYMBOL(iwl_rx_csa); |
1293 | 1344 | ||
1294 | #ifdef CONFIG_IWLWIFI_DEBUG | 1345 | #ifdef CONFIG_IWLWIFI_DEBUG |
1295 | static void iwl_print_rx_config_cmd(struct iwl_priv *priv) | 1346 | void iwl_print_rx_config_cmd(struct iwl_priv *priv) |
1296 | { | 1347 | { |
1297 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 1348 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
1298 | 1349 | ||
@@ -1310,6 +1361,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) | |||
1310 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); | 1361 | IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); |
1311 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); | 1362 | IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); |
1312 | } | 1363 | } |
1364 | EXPORT_SYMBOL(iwl_print_rx_config_cmd); | ||
1313 | #endif | 1365 | #endif |
1314 | /** | 1366 | /** |
1315 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | 1367 | * iwl_irq_handle_error - called for HW or SW error interrupt from card |
@@ -1322,12 +1374,15 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1322 | /* Cancel currently queued command. */ | 1374 | /* Cancel currently queued command. */ |
1323 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1375 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1324 | 1376 | ||
1377 | priv->cfg->ops->lib->dump_nic_error_log(priv); | ||
1378 | if (priv->cfg->ops->lib->dump_csr) | ||
1379 | priv->cfg->ops->lib->dump_csr(priv); | ||
1380 | if (priv->cfg->ops->lib->dump_fh) | ||
1381 | priv->cfg->ops->lib->dump_fh(priv, NULL, false); | ||
1382 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); | ||
1325 | #ifdef CONFIG_IWLWIFI_DEBUG | 1383 | #ifdef CONFIG_IWLWIFI_DEBUG |
1326 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) { | 1384 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) |
1327 | priv->cfg->ops->lib->dump_nic_error_log(priv); | ||
1328 | priv->cfg->ops->lib->dump_nic_event_log(priv); | ||
1329 | iwl_print_rx_config_cmd(priv); | 1385 | iwl_print_rx_config_cmd(priv); |
1330 | } | ||
1331 | #endif | 1386 | #endif |
1332 | 1387 | ||
1333 | wake_up_interruptible(&priv->wait_command_queue); | 1388 | wake_up_interruptible(&priv->wait_command_queue); |
@@ -1346,6 +1401,160 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1346 | } | 1401 | } |
1347 | EXPORT_SYMBOL(iwl_irq_handle_error); | 1402 | EXPORT_SYMBOL(iwl_irq_handle_error); |
1348 | 1403 | ||
1404 | int iwl_apm_stop_master(struct iwl_priv *priv) | ||
1405 | { | ||
1406 | int ret = 0; | ||
1407 | |||
1408 | /* stop device's busmaster DMA activity */ | ||
1409 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
1410 | |||
1411 | ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, | ||
1412 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
1413 | if (ret) | ||
1414 | IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n"); | ||
1415 | |||
1416 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
1417 | |||
1418 | return ret; | ||
1419 | } | ||
1420 | EXPORT_SYMBOL(iwl_apm_stop_master); | ||
1421 | |||
1422 | void iwl_apm_stop(struct iwl_priv *priv) | ||
1423 | { | ||
1424 | IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); | ||
1425 | |||
1426 | /* Stop device's DMA activity */ | ||
1427 | iwl_apm_stop_master(priv); | ||
1428 | |||
1429 | /* Reset the entire device */ | ||
1430 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1431 | |||
1432 | udelay(10); | ||
1433 | |||
1434 | /* | ||
1435 | * Clear "initialization complete" bit to move adapter from | ||
1436 | * D0A* (powered-up Active) --> D0U* (Uninitialized) state. | ||
1437 | */ | ||
1438 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1439 | } | ||
1440 | EXPORT_SYMBOL(iwl_apm_stop); | ||
1441 | |||
1442 | |||
1443 | /* | ||
1444 | * Start up NIC's basic functionality after it has been reset | ||
1445 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
1446 | * NOTE: This does not load uCode nor start the embedded processor | ||
1447 | */ | ||
1448 | int iwl_apm_init(struct iwl_priv *priv) | ||
1449 | { | ||
1450 | int ret = 0; | ||
1451 | u16 lctl; | ||
1452 | |||
1453 | IWL_DEBUG_INFO(priv, "Init card's basic functions\n"); | ||
1454 | |||
1455 | /* | ||
1456 | * Use "set_bit" below rather than "write", to preserve any hardware | ||
1457 | * bits already set by default after reset. | ||
1458 | */ | ||
1459 | |||
1460 | /* Disable L0S exit timer (platform NMI Work/Around) */ | ||
1461 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
1462 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
1463 | |||
1464 | /* | ||
1465 | * Disable L0s without affecting L1; | ||
1466 | * don't wait for ICH L0s (ICH bug W/A) | ||
1467 | */ | ||
1468 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
1469 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
1470 | |||
1471 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
1472 | iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
1473 | |||
1474 | /* | ||
1475 | * Enable HAP INTA (interrupt from management bus) to | ||
1476 | * wake device's PCI Express link L1a -> L0s | ||
1477 | * NOTE: This is no-op for 3945 (non-existant bit) | ||
1478 | */ | ||
1479 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
1480 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
1481 | |||
1482 | /* | ||
1483 | * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition. | ||
1484 | * Check if BIOS (or OS) enabled L1-ASPM on this device. | ||
1485 | * If so (likely), disable L0S, so device moves directly L0->L1; | ||
1486 | * costs negligible amount of power savings. | ||
1487 | * If not (unlikely), enable L0S, so there is at least some | ||
1488 | * power savings, even without L1. | ||
1489 | */ | ||
1490 | if (priv->cfg->set_l0s) { | ||
1491 | lctl = iwl_pcie_link_ctl(priv); | ||
1492 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | ||
1493 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | ||
1494 | /* L1-ASPM enabled; disable(!) L0S */ | ||
1495 | iwl_set_bit(priv, CSR_GIO_REG, | ||
1496 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
1497 | IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); | ||
1498 | } else { | ||
1499 | /* L1-ASPM disabled; enable(!) L0S */ | ||
1500 | iwl_clear_bit(priv, CSR_GIO_REG, | ||
1501 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
1502 | IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | /* Configure analog phase-lock-loop before activating to D0A */ | ||
1507 | if (priv->cfg->pll_cfg_val) | ||
1508 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->pll_cfg_val); | ||
1509 | |||
1510 | /* | ||
1511 | * Set "initialization complete" bit to move adapter from | ||
1512 | * D0U* --> D0A* (powered-up active) state. | ||
1513 | */ | ||
1514 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1515 | |||
1516 | /* | ||
1517 | * Wait for clock stabilization; once stabilized, access to | ||
1518 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
1519 | * and accesses to uCode SRAM. | ||
1520 | */ | ||
1521 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
1522 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
1523 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1524 | if (ret < 0) { | ||
1525 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
1526 | goto out; | ||
1527 | } | ||
1528 | |||
1529 | /* | ||
1530 | * Enable DMA and BSM (if used) clocks, wait for them to stabilize. | ||
1531 | * BSM (Boostrap State Machine) is only in 3945 and 4965; | ||
1532 | * later devices (i.e. 5000 and later) have non-volatile SRAM, | ||
1533 | * and don't need BSM to restore data after power-saving sleep. | ||
1534 | * | ||
1535 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits | ||
1536 | * do not disable clocks. This preserves any hardware bits already | ||
1537 | * set by default in "CLK_CTRL_REG" after reset. | ||
1538 | */ | ||
1539 | if (priv->cfg->use_bsm) | ||
1540 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1541 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1542 | else | ||
1543 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1544 | APMG_CLK_VAL_DMA_CLK_RQT); | ||
1545 | udelay(20); | ||
1546 | |||
1547 | /* Disable L1-Active */ | ||
1548 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
1549 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
1550 | |||
1551 | out: | ||
1552 | return ret; | ||
1553 | } | ||
1554 | EXPORT_SYMBOL(iwl_apm_init); | ||
1555 | |||
1556 | |||
1557 | |||
1349 | void iwl_configure_filter(struct ieee80211_hw *hw, | 1558 | void iwl_configure_filter(struct ieee80211_hw *hw, |
1350 | unsigned int changed_flags, | 1559 | unsigned int changed_flags, |
1351 | unsigned int *total_flags, | 1560 | unsigned int *total_flags, |
@@ -1393,73 +1602,14 @@ void iwl_configure_filter(struct ieee80211_hw *hw, | |||
1393 | } | 1602 | } |
1394 | EXPORT_SYMBOL(iwl_configure_filter); | 1603 | EXPORT_SYMBOL(iwl_configure_filter); |
1395 | 1604 | ||
1396 | int iwl_setup_mac(struct iwl_priv *priv) | ||
1397 | { | ||
1398 | int ret; | ||
1399 | struct ieee80211_hw *hw = priv->hw; | ||
1400 | hw->rate_control_algorithm = "iwl-agn-rs"; | ||
1401 | |||
1402 | /* Tell mac80211 our characteristics */ | ||
1403 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
1404 | IEEE80211_HW_NOISE_DBM | | ||
1405 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
1406 | IEEE80211_HW_SPECTRUM_MGMT; | ||
1407 | |||
1408 | if (!priv->cfg->broken_powersave) | ||
1409 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
1410 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
1411 | |||
1412 | hw->wiphy->interface_modes = | ||
1413 | BIT(NL80211_IFTYPE_STATION) | | ||
1414 | BIT(NL80211_IFTYPE_ADHOC); | ||
1415 | |||
1416 | hw->wiphy->custom_regulatory = true; | ||
1417 | |||
1418 | /* Firmware does not support this */ | ||
1419 | hw->wiphy->disable_beacon_hints = true; | ||
1420 | |||
1421 | /* | ||
1422 | * For now, disable PS by default because it affects | ||
1423 | * RX performance significantly. | ||
1424 | */ | ||
1425 | hw->wiphy->ps_default = false; | ||
1426 | |||
1427 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | ||
1428 | /* we create the 802.11 header and a zero-length SSID element */ | ||
1429 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | ||
1430 | |||
1431 | /* Default value; 4 EDCA QOS priorities */ | ||
1432 | hw->queues = 4; | ||
1433 | |||
1434 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||
1435 | |||
1436 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
1437 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1438 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1439 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
1440 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1441 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1442 | |||
1443 | ret = ieee80211_register_hw(priv->hw); | ||
1444 | if (ret) { | ||
1445 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
1446 | return ret; | ||
1447 | } | ||
1448 | priv->mac80211_registered = 1; | ||
1449 | |||
1450 | return 0; | ||
1451 | } | ||
1452 | EXPORT_SYMBOL(iwl_setup_mac); | ||
1453 | |||
1454 | int iwl_set_hw_params(struct iwl_priv *priv) | 1605 | int iwl_set_hw_params(struct iwl_priv *priv) |
1455 | { | 1606 | { |
1456 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 1607 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
1457 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 1608 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
1458 | if (priv->cfg->mod_params->amsdu_size_8K) | 1609 | if (priv->cfg->mod_params->amsdu_size_8K) |
1459 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; | 1610 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); |
1460 | else | 1611 | else |
1461 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; | 1612 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); |
1462 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; | ||
1463 | 1613 | ||
1464 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; | 1614 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; |
1465 | 1615 | ||
@@ -1471,71 +1621,6 @@ int iwl_set_hw_params(struct iwl_priv *priv) | |||
1471 | } | 1621 | } |
1472 | EXPORT_SYMBOL(iwl_set_hw_params); | 1622 | EXPORT_SYMBOL(iwl_set_hw_params); |
1473 | 1623 | ||
1474 | int iwl_init_drv(struct iwl_priv *priv) | ||
1475 | { | ||
1476 | int ret; | ||
1477 | |||
1478 | priv->ibss_beacon = NULL; | ||
1479 | |||
1480 | spin_lock_init(&priv->lock); | ||
1481 | spin_lock_init(&priv->sta_lock); | ||
1482 | spin_lock_init(&priv->hcmd_lock); | ||
1483 | |||
1484 | INIT_LIST_HEAD(&priv->free_frames); | ||
1485 | |||
1486 | mutex_init(&priv->mutex); | ||
1487 | |||
1488 | /* Clear the driver's (not device's) station table */ | ||
1489 | iwl_clear_stations_table(priv); | ||
1490 | |||
1491 | priv->data_retry_limit = -1; | ||
1492 | priv->ieee_channels = NULL; | ||
1493 | priv->ieee_rates = NULL; | ||
1494 | priv->band = IEEE80211_BAND_2GHZ; | ||
1495 | |||
1496 | priv->iw_mode = NL80211_IFTYPE_STATION; | ||
1497 | |||
1498 | priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; | ||
1499 | |||
1500 | /* Choose which receivers/antennas to use */ | ||
1501 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
1502 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
1503 | |||
1504 | iwl_init_scan_params(priv); | ||
1505 | |||
1506 | iwl_reset_qos(priv); | ||
1507 | |||
1508 | priv->qos_data.qos_active = 0; | ||
1509 | priv->qos_data.qos_cap.val = 0; | ||
1510 | |||
1511 | priv->rates_mask = IWL_RATES_MASK; | ||
1512 | /* Set the tx_power_user_lmt to the lowest power level | ||
1513 | * this value will get overwritten by channel max power avg | ||
1514 | * from eeprom */ | ||
1515 | priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; | ||
1516 | |||
1517 | ret = iwl_init_channel_map(priv); | ||
1518 | if (ret) { | ||
1519 | IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); | ||
1520 | goto err; | ||
1521 | } | ||
1522 | |||
1523 | ret = iwlcore_init_geos(priv); | ||
1524 | if (ret) { | ||
1525 | IWL_ERR(priv, "initializing geos failed: %d\n", ret); | ||
1526 | goto err_free_channel_map; | ||
1527 | } | ||
1528 | iwlcore_init_hw_rates(priv, priv->ieee_rates); | ||
1529 | |||
1530 | return 0; | ||
1531 | |||
1532 | err_free_channel_map: | ||
1533 | iwl_free_channel_map(priv); | ||
1534 | err: | ||
1535 | return ret; | ||
1536 | } | ||
1537 | EXPORT_SYMBOL(iwl_init_drv); | ||
1538 | |||
1539 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | 1624 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) |
1540 | { | 1625 | { |
1541 | int ret = 0; | 1626 | int ret = 0; |
@@ -1583,24 +1668,15 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1583 | } | 1668 | } |
1584 | EXPORT_SYMBOL(iwl_set_tx_power); | 1669 | EXPORT_SYMBOL(iwl_set_tx_power); |
1585 | 1670 | ||
1586 | void iwl_uninit_drv(struct iwl_priv *priv) | ||
1587 | { | ||
1588 | iwl_calib_free_results(priv); | ||
1589 | iwlcore_free_geos(priv); | ||
1590 | iwl_free_channel_map(priv); | ||
1591 | kfree(priv->scan); | ||
1592 | } | ||
1593 | EXPORT_SYMBOL(iwl_uninit_drv); | ||
1594 | |||
1595 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | 1671 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) |
1596 | 1672 | ||
1597 | /* Free dram table */ | 1673 | /* Free dram table */ |
1598 | void iwl_free_isr_ict(struct iwl_priv *priv) | 1674 | void iwl_free_isr_ict(struct iwl_priv *priv) |
1599 | { | 1675 | { |
1600 | if (priv->ict_tbl_vir) { | 1676 | if (priv->ict_tbl_vir) { |
1601 | pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) + | 1677 | dma_free_coherent(&priv->pci_dev->dev, |
1602 | PAGE_SIZE, priv->ict_tbl_vir, | 1678 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
1603 | priv->ict_tbl_dma); | 1679 | priv->ict_tbl_vir, priv->ict_tbl_dma); |
1604 | priv->ict_tbl_vir = NULL; | 1680 | priv->ict_tbl_vir = NULL; |
1605 | } | 1681 | } |
1606 | } | 1682 | } |
@@ -1616,9 +1692,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) | |||
1616 | if (priv->cfg->use_isr_legacy) | 1692 | if (priv->cfg->use_isr_legacy) |
1617 | return 0; | 1693 | return 0; |
1618 | /* allocate shrared data table */ | 1694 | /* allocate shrared data table */ |
1619 | priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) * | 1695 | priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, |
1620 | ICT_COUNT) + PAGE_SIZE, | 1696 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
1621 | &priv->ict_tbl_dma); | 1697 | &priv->ict_tbl_dma, GFP_KERNEL); |
1622 | if (!priv->ict_tbl_vir) | 1698 | if (!priv->ict_tbl_vir) |
1623 | return -ENOMEM; | 1699 | return -ENOMEM; |
1624 | 1700 | ||
@@ -1753,6 +1829,16 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
1753 | if (val == 0xffffffff) | 1829 | if (val == 0xffffffff) |
1754 | val = 0; | 1830 | val = 0; |
1755 | 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 | |||
1756 | inta = (0xff & val) | ((0xff00 & val) << 16); | 1842 | inta = (0xff & val) | ((0xff00 & val) << 16); |
1757 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", | 1843 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", |
1758 | inta, inta_mask, val); | 1844 | inta, inta_mask, val); |
@@ -1915,28 +2001,40 @@ EXPORT_SYMBOL(iwl_isr_legacy); | |||
1915 | int iwl_send_bt_config(struct iwl_priv *priv) | 2001 | int iwl_send_bt_config(struct iwl_priv *priv) |
1916 | { | 2002 | { |
1917 | struct iwl_bt_cmd bt_cmd = { | 2003 | struct iwl_bt_cmd bt_cmd = { |
1918 | .flags = 3, | 2004 | .lead_time = BT_LEAD_TIME_DEF, |
1919 | .lead_time = 0xAA, | 2005 | .max_kill = BT_MAX_KILL_DEF, |
1920 | .max_kill = 1, | ||
1921 | .kill_ack_mask = 0, | 2006 | .kill_ack_mask = 0, |
1922 | .kill_cts_mask = 0, | 2007 | .kill_cts_mask = 0, |
1923 | }; | 2008 | }; |
1924 | 2009 | ||
2010 | if (!bt_coex_active) | ||
2011 | bt_cmd.flags = BT_COEX_DISABLE; | ||
2012 | else | ||
2013 | bt_cmd.flags = BT_COEX_ENABLE; | ||
2014 | |||
2015 | IWL_DEBUG_INFO(priv, "BT coex %s\n", | ||
2016 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); | ||
2017 | |||
1925 | return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, | 2018 | return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, |
1926 | sizeof(struct iwl_bt_cmd), &bt_cmd); | 2019 | sizeof(struct iwl_bt_cmd), &bt_cmd); |
1927 | } | 2020 | } |
1928 | EXPORT_SYMBOL(iwl_send_bt_config); | 2021 | EXPORT_SYMBOL(iwl_send_bt_config); |
1929 | 2022 | ||
1930 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) | 2023 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) |
1931 | { | 2024 | { |
1932 | u32 stat_flags = 0; | 2025 | struct iwl_statistics_cmd statistics_cmd = { |
1933 | struct iwl_host_cmd cmd = { | 2026 | .configuration_flags = |
1934 | .id = REPLY_STATISTICS_CMD, | 2027 | clear ? IWL_STATS_CONF_CLEAR_STATS : 0, |
1935 | .flags = flags, | ||
1936 | .len = sizeof(stat_flags), | ||
1937 | .data = (u8 *) &stat_flags, | ||
1938 | }; | 2028 | }; |
1939 | return iwl_send_cmd(priv, &cmd); | 2029 | |
2030 | if (flags & CMD_ASYNC) | ||
2031 | return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD, | ||
2032 | sizeof(struct iwl_statistics_cmd), | ||
2033 | &statistics_cmd, NULL); | ||
2034 | else | ||
2035 | return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
2036 | sizeof(struct iwl_statistics_cmd), | ||
2037 | &statistics_cmd); | ||
1940 | } | 2038 | } |
1941 | EXPORT_SYMBOL(iwl_send_statistics_request); | 2039 | EXPORT_SYMBOL(iwl_send_statistics_request); |
1942 | 2040 | ||
@@ -2077,10 +2175,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2077 | spin_unlock_irqrestore(&priv->lock, flags); | 2175 | spin_unlock_irqrestore(&priv->lock, flags); |
2078 | priv->thermal_throttle.ct_kill_toggle = false; | 2176 | priv->thermal_throttle.ct_kill_toggle = false; |
2079 | 2177 | ||
2080 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 2178 | if (priv->cfg->support_ct_kill_exit) { |
2081 | case CSR_HW_REV_TYPE_1000: | ||
2082 | case CSR_HW_REV_TYPE_6x00: | ||
2083 | case CSR_HW_REV_TYPE_6x50: | ||
2084 | adv_cmd.critical_temperature_enter = | 2179 | adv_cmd.critical_temperature_enter = |
2085 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | 2180 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
2086 | adv_cmd.critical_temperature_exit = | 2181 | adv_cmd.critical_temperature_exit = |
@@ -2097,8 +2192,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2097 | "exit is %d\n", | 2192 | "exit is %d\n", |
2098 | priv->hw_params.ct_kill_threshold, | 2193 | priv->hw_params.ct_kill_threshold, |
2099 | priv->hw_params.ct_kill_exit_threshold); | 2194 | priv->hw_params.ct_kill_exit_threshold); |
2100 | break; | 2195 | } else { |
2101 | default: | ||
2102 | cmd.critical_temperature_R = | 2196 | cmd.critical_temperature_R = |
2103 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | 2197 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
2104 | 2198 | ||
@@ -2111,7 +2205,6 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2111 | "succeeded, " | 2205 | "succeeded, " |
2112 | "critical temperature is %d\n", | 2206 | "critical temperature is %d\n", |
2113 | priv->hw_params.ct_kill_threshold); | 2207 | priv->hw_params.ct_kill_threshold); |
2114 | break; | ||
2115 | } | 2208 | } |
2116 | } | 2209 | } |
2117 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); | 2210 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); |
@@ -2143,7 +2236,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | |||
2143 | struct iwl_rx_mem_buffer *rxb) | 2236 | struct iwl_rx_mem_buffer *rxb) |
2144 | { | 2237 | { |
2145 | #ifdef CONFIG_IWLWIFI_DEBUG | 2238 | #ifdef CONFIG_IWLWIFI_DEBUG |
2146 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2239 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2147 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); | 2240 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); |
2148 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | 2241 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", |
2149 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | 2242 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); |
@@ -2154,7 +2247,7 @@ EXPORT_SYMBOL(iwl_rx_pm_sleep_notif); | |||
2154 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | 2247 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, |
2155 | struct iwl_rx_mem_buffer *rxb) | 2248 | struct iwl_rx_mem_buffer *rxb) |
2156 | { | 2249 | { |
2157 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2250 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2158 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 2251 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
2159 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | 2252 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " |
2160 | "notification for %s:\n", len, | 2253 | "notification for %s:\n", len, |
@@ -2166,7 +2259,7 @@ EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); | |||
2166 | void iwl_rx_reply_error(struct iwl_priv *priv, | 2259 | void iwl_rx_reply_error(struct iwl_priv *priv, |
2167 | struct iwl_rx_mem_buffer *rxb) | 2260 | struct iwl_rx_mem_buffer *rxb) |
2168 | { | 2261 | { |
2169 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2262 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2170 | 2263 | ||
2171 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " | 2264 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " |
2172 | "seq 0x%04X ser 0x%08X\n", | 2265 | "seq 0x%04X ser 0x%08X\n", |
@@ -2228,46 +2321,77 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2228 | EXPORT_SYMBOL(iwl_mac_conf_tx); | 2321 | EXPORT_SYMBOL(iwl_mac_conf_tx); |
2229 | 2322 | ||
2230 | static void iwl_ht_conf(struct iwl_priv *priv, | 2323 | static void iwl_ht_conf(struct iwl_priv *priv, |
2231 | struct ieee80211_bss_conf *bss_conf) | 2324 | struct ieee80211_bss_conf *bss_conf) |
2232 | { | 2325 | { |
2233 | struct ieee80211_sta_ht_cap *ht_conf; | 2326 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2234 | struct iwl_ht_info *iwl_conf = &priv->current_ht_config; | ||
2235 | struct ieee80211_sta *sta; | 2327 | struct ieee80211_sta *sta; |
2236 | 2328 | ||
2237 | IWL_DEBUG_MAC80211(priv, "enter: \n"); | 2329 | IWL_DEBUG_MAC80211(priv, "enter: \n"); |
2238 | 2330 | ||
2239 | if (!iwl_conf->is_ht) | 2331 | if (!ht_conf->is_ht) |
2240 | return; | 2332 | return; |
2241 | 2333 | ||
2334 | ht_conf->ht_protection = | ||
2335 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
2336 | ht_conf->non_GF_STA_present = | ||
2337 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
2242 | 2338 | ||
2243 | /* | 2339 | ht_conf->single_chain_sufficient = false; |
2244 | * It is totally wrong to base global information on something | ||
2245 | * that is valid only when associated, alas, this driver works | ||
2246 | * that way and I don't know how to fix it. | ||
2247 | */ | ||
2248 | 2340 | ||
2249 | rcu_read_lock(); | 2341 | switch (priv->iw_mode) { |
2250 | sta = ieee80211_find_sta(priv->hw, priv->bssid); | 2342 | case NL80211_IFTYPE_STATION: |
2251 | if (!sta) { | 2343 | rcu_read_lock(); |
2344 | sta = ieee80211_find_sta(priv->vif, priv->bssid); | ||
2345 | if (sta) { | ||
2346 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2347 | int maxstreams; | ||
2348 | |||
2349 | maxstreams = (ht_cap->mcs.tx_params & | ||
2350 | IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | ||
2351 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
2352 | maxstreams += 1; | ||
2353 | |||
2354 | if ((ht_cap->mcs.rx_mask[1] == 0) && | ||
2355 | (ht_cap->mcs.rx_mask[2] == 0)) | ||
2356 | ht_conf->single_chain_sufficient = true; | ||
2357 | if (maxstreams <= 1) | ||
2358 | ht_conf->single_chain_sufficient = true; | ||
2359 | } else { | ||
2360 | /* | ||
2361 | * If at all, this can only happen through a race | ||
2362 | * when the AP disconnects us while we're still | ||
2363 | * setting up the connection, in that case mac80211 | ||
2364 | * will soon tell us about that. | ||
2365 | */ | ||
2366 | ht_conf->single_chain_sufficient = true; | ||
2367 | } | ||
2252 | rcu_read_unlock(); | 2368 | rcu_read_unlock(); |
2253 | return; | 2369 | break; |
2370 | case NL80211_IFTYPE_ADHOC: | ||
2371 | ht_conf->single_chain_sufficient = true; | ||
2372 | break; | ||
2373 | default: | ||
2374 | break; | ||
2254 | } | 2375 | } |
2255 | ht_conf = &sta->ht_cap; | ||
2256 | |||
2257 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); | ||
2258 | |||
2259 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); | ||
2260 | |||
2261 | iwl_conf->ht_protection = | ||
2262 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
2263 | iwl_conf->non_GF_STA_present = | ||
2264 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
2265 | |||
2266 | rcu_read_unlock(); | ||
2267 | 2376 | ||
2268 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2377 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2269 | } | 2378 | } |
2270 | 2379 | ||
2380 | static inline void iwl_set_no_assoc(struct iwl_priv *priv) | ||
2381 | { | ||
2382 | priv->assoc_id = 0; | ||
2383 | iwl_led_disassociate(priv); | ||
2384 | /* | ||
2385 | * inform the ucode that there is no longer an | ||
2386 | * association and that no more packets should be | ||
2387 | * sent | ||
2388 | */ | ||
2389 | priv->staging_rxon.filter_flags &= | ||
2390 | ~RXON_FILTER_ASSOC_MSK; | ||
2391 | priv->staging_rxon.assoc_id = 0; | ||
2392 | iwlcore_commit_rxon(priv); | ||
2393 | } | ||
2394 | |||
2271 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | 2395 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) |
2272 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | 2396 | void iwl_bss_info_changed(struct ieee80211_hw *hw, |
2273 | struct ieee80211_vif *vif, | 2397 | struct ieee80211_vif *vif, |
@@ -2387,6 +2511,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2387 | priv->timestamp = bss_conf->timestamp; | 2511 | priv->timestamp = bss_conf->timestamp; |
2388 | priv->assoc_capability = bss_conf->assoc_capability; | 2512 | priv->assoc_capability = bss_conf->assoc_capability; |
2389 | 2513 | ||
2514 | iwl_led_associate(priv); | ||
2515 | |||
2390 | /* | 2516 | /* |
2391 | * We have just associated, don't start scan too early | 2517 | * We have just associated, don't start scan too early |
2392 | * leave time for EAPOL exchange to complete. | 2518 | * leave time for EAPOL exchange to complete. |
@@ -2398,8 +2524,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2398 | if (!iwl_is_rfkill(priv)) | 2524 | if (!iwl_is_rfkill(priv)) |
2399 | priv->cfg->ops->lib->post_associate(priv); | 2525 | priv->cfg->ops->lib->post_associate(priv); |
2400 | } else | 2526 | } else |
2401 | priv->assoc_id = 0; | 2527 | iwl_set_no_assoc(priv); |
2402 | |||
2403 | } | 2528 | } |
2404 | 2529 | ||
2405 | if (changes && iwl_is_associated(priv) && priv->assoc_id) { | 2530 | if (changes && iwl_is_associated(priv) && priv->assoc_id) { |
@@ -2414,6 +2539,16 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2414 | } | 2539 | } |
2415 | } | 2540 | } |
2416 | 2541 | ||
2542 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
2543 | if (vif->bss_conf.enable_beacon) { | ||
2544 | memcpy(priv->staging_rxon.bssid_addr, | ||
2545 | bss_conf->bssid, ETH_ALEN); | ||
2546 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | ||
2547 | iwlcore_config_ap(priv); | ||
2548 | } else | ||
2549 | iwl_set_no_assoc(priv); | ||
2550 | } | ||
2551 | |||
2417 | mutex_unlock(&priv->mutex); | 2552 | mutex_unlock(&priv->mutex); |
2418 | 2553 | ||
2419 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2554 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2497,44 +2632,43 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) | |||
2497 | EXPORT_SYMBOL(iwl_set_mode); | 2632 | EXPORT_SYMBOL(iwl_set_mode); |
2498 | 2633 | ||
2499 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 2634 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
2500 | struct ieee80211_if_init_conf *conf) | 2635 | struct ieee80211_vif *vif) |
2501 | { | 2636 | { |
2502 | struct iwl_priv *priv = hw->priv; | 2637 | struct iwl_priv *priv = hw->priv; |
2503 | unsigned long flags; | 2638 | int err = 0; |
2639 | |||
2640 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); | ||
2504 | 2641 | ||
2505 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); | 2642 | mutex_lock(&priv->mutex); |
2506 | 2643 | ||
2507 | if (priv->vif) { | 2644 | if (priv->vif) { |
2508 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 2645 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); |
2509 | return -EOPNOTSUPP; | 2646 | err = -EOPNOTSUPP; |
2647 | goto out; | ||
2510 | } | 2648 | } |
2511 | 2649 | ||
2512 | spin_lock_irqsave(&priv->lock, flags); | 2650 | priv->vif = vif; |
2513 | priv->vif = conf->vif; | 2651 | priv->iw_mode = vif->type; |
2514 | priv->iw_mode = conf->type; | ||
2515 | 2652 | ||
2516 | spin_unlock_irqrestore(&priv->lock, flags); | 2653 | if (vif->addr) { |
2517 | 2654 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); | |
2518 | mutex_lock(&priv->mutex); | 2655 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
2519 | |||
2520 | if (conf->mac_addr) { | ||
2521 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); | ||
2522 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | ||
2523 | } | 2656 | } |
2524 | 2657 | ||
2525 | if (iwl_set_mode(priv, conf->type) == -EAGAIN) | 2658 | if (iwl_set_mode(priv, vif->type) == -EAGAIN) |
2526 | /* we are not ready, will run again when ready */ | 2659 | /* we are not ready, will run again when ready */ |
2527 | set_bit(STATUS_MODE_PENDING, &priv->status); | 2660 | set_bit(STATUS_MODE_PENDING, &priv->status); |
2528 | 2661 | ||
2662 | out: | ||
2529 | mutex_unlock(&priv->mutex); | 2663 | mutex_unlock(&priv->mutex); |
2530 | 2664 | ||
2531 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2665 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2532 | return 0; | 2666 | return err; |
2533 | } | 2667 | } |
2534 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2668 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2535 | 2669 | ||
2536 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 2670 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
2537 | struct ieee80211_if_init_conf *conf) | 2671 | struct ieee80211_vif *vif) |
2538 | { | 2672 | { |
2539 | struct iwl_priv *priv = hw->priv; | 2673 | struct iwl_priv *priv = hw->priv; |
2540 | 2674 | ||
@@ -2547,7 +2681,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2547 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2681 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2548 | iwlcore_commit_rxon(priv); | 2682 | iwlcore_commit_rxon(priv); |
2549 | } | 2683 | } |
2550 | if (priv->vif == conf->vif) { | 2684 | if (priv->vif == vif) { |
2551 | priv->vif = NULL; | 2685 | priv->vif = NULL; |
2552 | memset(priv->bssid, 0, ETH_ALEN); | 2686 | memset(priv->bssid, 0, ETH_ALEN); |
2553 | } | 2687 | } |
@@ -2570,7 +2704,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2570 | struct iwl_priv *priv = hw->priv; | 2704 | struct iwl_priv *priv = hw->priv; |
2571 | const struct iwl_channel_info *ch_info; | 2705 | const struct iwl_channel_info *ch_info; |
2572 | struct ieee80211_conf *conf = &hw->conf; | 2706 | struct ieee80211_conf *conf = &hw->conf; |
2573 | struct iwl_ht_info *ht_conf = &priv->current_ht_config; | 2707 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2574 | unsigned long flags = 0; | 2708 | unsigned long flags = 0; |
2575 | int ret = 0; | 2709 | int ret = 0; |
2576 | u16 ch; | 2710 | u16 ch; |
@@ -2587,6 +2721,21 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2587 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); | 2721 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); |
2588 | } | 2722 | } |
2589 | 2723 | ||
2724 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | | ||
2725 | IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
2726 | /* mac80211 uses static for non-HT which is what we want */ | ||
2727 | priv->current_ht_config.smps = conf->smps_mode; | ||
2728 | |||
2729 | /* | ||
2730 | * Recalculate chain counts. | ||
2731 | * | ||
2732 | * If monitor mode is enabled then mac80211 will | ||
2733 | * set up the SM PS mode to OFF if an HT channel is | ||
2734 | * configured. | ||
2735 | */ | ||
2736 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2737 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
2738 | } | ||
2590 | 2739 | ||
2591 | /* during scanning mac80211 will delay channel setting until | 2740 | /* during scanning mac80211 will delay channel setting until |
2592 | * scan finish with changed = 0 | 2741 | * scan finish with changed = 0 |
@@ -2620,21 +2769,18 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2620 | if (conf_is_ht40_minus(conf)) { | 2769 | if (conf_is_ht40_minus(conf)) { |
2621 | ht_conf->extension_chan_offset = | 2770 | ht_conf->extension_chan_offset = |
2622 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 2771 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
2623 | ht_conf->supported_chan_width = | 2772 | ht_conf->is_40mhz = true; |
2624 | IWL_CHANNEL_WIDTH_40MHZ; | ||
2625 | } else if (conf_is_ht40_plus(conf)) { | 2773 | } else if (conf_is_ht40_plus(conf)) { |
2626 | ht_conf->extension_chan_offset = | 2774 | ht_conf->extension_chan_offset = |
2627 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 2775 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
2628 | ht_conf->supported_chan_width = | 2776 | ht_conf->is_40mhz = true; |
2629 | IWL_CHANNEL_WIDTH_40MHZ; | ||
2630 | } else { | 2777 | } else { |
2631 | ht_conf->extension_chan_offset = | 2778 | ht_conf->extension_chan_offset = |
2632 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | 2779 | IEEE80211_HT_PARAM_CHA_SEC_NONE; |
2633 | ht_conf->supported_chan_width = | 2780 | ht_conf->is_40mhz = false; |
2634 | IWL_CHANNEL_WIDTH_20MHZ; | ||
2635 | } | 2781 | } |
2636 | } else | 2782 | } else |
2637 | ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ; | 2783 | ht_conf->is_40mhz = false; |
2638 | /* Default to no protection. Protection mode will later be set | 2784 | /* Default to no protection. Protection mode will later be set |
2639 | * from BSS config in iwl_ht_conf */ | 2785 | * from BSS config in iwl_ht_conf */ |
2640 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 2786 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
@@ -2646,9 +2792,26 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2646 | priv->staging_rxon.flags = 0; | 2792 | priv->staging_rxon.flags = 0; |
2647 | 2793 | ||
2648 | iwl_set_rxon_channel(priv, conf->channel); | 2794 | iwl_set_rxon_channel(priv, conf->channel); |
2795 | iwl_set_rxon_ht(priv, ht_conf); | ||
2649 | 2796 | ||
2650 | iwl_set_flags_for_band(priv, conf->channel->band); | 2797 | iwl_set_flags_for_band(priv, conf->channel->band); |
2651 | spin_unlock_irqrestore(&priv->lock, flags); | 2798 | spin_unlock_irqrestore(&priv->lock, flags); |
2799 | if (iwl_is_associated(priv) && | ||
2800 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | ||
2801 | priv->cfg->ops->lib->set_channel_switch) { | ||
2802 | iwl_set_rate(priv); | ||
2803 | /* | ||
2804 | * at this point, staging_rxon has the | ||
2805 | * configuration for channel switch | ||
2806 | */ | ||
2807 | ret = priv->cfg->ops->lib->set_channel_switch(priv, | ||
2808 | ch); | ||
2809 | if (!ret) { | ||
2810 | iwl_print_rx_config_cmd(priv); | ||
2811 | goto out; | ||
2812 | } | ||
2813 | priv->switch_rxon.switch_in_progress = false; | ||
2814 | } | ||
2652 | set_ch_out: | 2815 | set_ch_out: |
2653 | /* The list of supported rates and rate mask can be different | 2816 | /* The list of supported rates and rate mask can be different |
2654 | * for each band; since the band may have changed, reset | 2817 | * for each band; since the band may have changed, reset |
@@ -2656,7 +2819,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2656 | iwl_set_rate(priv); | 2819 | iwl_set_rate(priv); |
2657 | } | 2820 | } |
2658 | 2821 | ||
2659 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 2822 | if (changed & (IEEE80211_CONF_CHANGE_PS | |
2823 | IEEE80211_CONF_CHANGE_IDLE)) { | ||
2660 | ret = iwl_power_update_mode(priv, false); | 2824 | ret = iwl_power_update_mode(priv, false); |
2661 | if (ret) | 2825 | if (ret) |
2662 | IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); | 2826 | IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); |
@@ -2669,10 +2833,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2669 | iwl_set_tx_power(priv, conf->power_level, false); | 2833 | iwl_set_tx_power(priv, conf->power_level, false); |
2670 | } | 2834 | } |
2671 | 2835 | ||
2672 | /* call to ensure that 4965 rx_chain is set properly in monitor mode */ | ||
2673 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2674 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
2675 | |||
2676 | if (!iwl_is_ready(priv)) { | 2836 | if (!iwl_is_ready(priv)) { |
2677 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2837 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2678 | goto out; | 2838 | goto out; |
@@ -2695,42 +2855,6 @@ out: | |||
2695 | } | 2855 | } |
2696 | EXPORT_SYMBOL(iwl_mac_config); | 2856 | EXPORT_SYMBOL(iwl_mac_config); |
2697 | 2857 | ||
2698 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | ||
2699 | struct ieee80211_tx_queue_stats *stats) | ||
2700 | { | ||
2701 | struct iwl_priv *priv = hw->priv; | ||
2702 | int i, avail; | ||
2703 | struct iwl_tx_queue *txq; | ||
2704 | struct iwl_queue *q; | ||
2705 | unsigned long flags; | ||
2706 | |||
2707 | IWL_DEBUG_MAC80211(priv, "enter\n"); | ||
2708 | |||
2709 | if (!iwl_is_ready_rf(priv)) { | ||
2710 | IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); | ||
2711 | return -EIO; | ||
2712 | } | ||
2713 | |||
2714 | spin_lock_irqsave(&priv->lock, flags); | ||
2715 | |||
2716 | for (i = 0; i < AC_NUM; i++) { | ||
2717 | txq = &priv->txq[i]; | ||
2718 | q = &txq->q; | ||
2719 | avail = iwl_queue_space(q); | ||
2720 | |||
2721 | stats[i].len = q->n_window - avail; | ||
2722 | stats[i].limit = q->n_window - q->high_mark; | ||
2723 | stats[i].count = q->n_window; | ||
2724 | |||
2725 | } | ||
2726 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2727 | |||
2728 | IWL_DEBUG_MAC80211(priv, "leave\n"); | ||
2729 | |||
2730 | return 0; | ||
2731 | } | ||
2732 | EXPORT_SYMBOL(iwl_mac_get_tx_stats); | ||
2733 | |||
2734 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | 2858 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw) |
2735 | { | 2859 | { |
2736 | struct iwl_priv *priv = hw->priv; | 2860 | struct iwl_priv *priv = hw->priv; |
@@ -2740,7 +2864,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2740 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2864 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2741 | 2865 | ||
2742 | spin_lock_irqsave(&priv->lock, flags); | 2866 | spin_lock_irqsave(&priv->lock, flags); |
2743 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); | 2867 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); |
2744 | spin_unlock_irqrestore(&priv->lock, flags); | 2868 | spin_unlock_irqrestore(&priv->lock, flags); |
2745 | 2869 | ||
2746 | iwl_reset_qos(priv); | 2870 | iwl_reset_qos(priv); |
@@ -2792,6 +2916,55 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2792 | } | 2916 | } |
2793 | EXPORT_SYMBOL(iwl_mac_reset_tsf); | 2917 | EXPORT_SYMBOL(iwl_mac_reset_tsf); |
2794 | 2918 | ||
2919 | int iwl_alloc_txq_mem(struct iwl_priv *priv) | ||
2920 | { | ||
2921 | if (!priv->txq) | ||
2922 | priv->txq = kzalloc( | ||
2923 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, | ||
2924 | GFP_KERNEL); | ||
2925 | if (!priv->txq) { | ||
2926 | IWL_ERR(priv, "Not enough memory for txq \n"); | ||
2927 | return -ENOMEM; | ||
2928 | } | ||
2929 | return 0; | ||
2930 | } | ||
2931 | EXPORT_SYMBOL(iwl_alloc_txq_mem); | ||
2932 | |||
2933 | void iwl_free_txq_mem(struct iwl_priv *priv) | ||
2934 | { | ||
2935 | kfree(priv->txq); | ||
2936 | priv->txq = NULL; | ||
2937 | } | ||
2938 | EXPORT_SYMBOL(iwl_free_txq_mem); | ||
2939 | |||
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 | |||
2795 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 2968 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
2796 | 2969 | ||
2797 | #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) | 2970 | #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) |
@@ -2929,15 +3102,11 @@ const char *get_ctrl_string(int cmd) | |||
2929 | } | 3102 | } |
2930 | } | 3103 | } |
2931 | 3104 | ||
2932 | void iwl_clear_tx_stats(struct iwl_priv *priv) | 3105 | void iwl_clear_traffic_stats(struct iwl_priv *priv) |
2933 | { | 3106 | { |
2934 | memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); | 3107 | memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); |
2935 | |||
2936 | } | ||
2937 | |||
2938 | void iwl_clear_rx_stats(struct iwl_priv *priv) | ||
2939 | { | ||
2940 | memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); | 3108 | memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); |
3109 | priv->led_tpt = 0; | ||
2941 | } | 3110 | } |
2942 | 3111 | ||
2943 | /* | 3112 | /* |
@@ -3030,10 +3199,211 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
3030 | stats->data_cnt++; | 3199 | stats->data_cnt++; |
3031 | stats->data_bytes += len; | 3200 | stats->data_bytes += len; |
3032 | } | 3201 | } |
3202 | iwl_leds_background(priv); | ||
3033 | } | 3203 | } |
3034 | EXPORT_SYMBOL(iwl_update_stats); | 3204 | EXPORT_SYMBOL(iwl_update_stats); |
3035 | #endif | 3205 | #endif |
3036 | 3206 | ||
3207 | const static char *get_csr_string(int cmd) | ||
3208 | { | ||
3209 | switch (cmd) { | ||
3210 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | ||
3211 | IWL_CMD(CSR_INT_COALESCING); | ||
3212 | IWL_CMD(CSR_INT); | ||
3213 | IWL_CMD(CSR_INT_MASK); | ||
3214 | IWL_CMD(CSR_FH_INT_STATUS); | ||
3215 | IWL_CMD(CSR_GPIO_IN); | ||
3216 | IWL_CMD(CSR_RESET); | ||
3217 | IWL_CMD(CSR_GP_CNTRL); | ||
3218 | IWL_CMD(CSR_HW_REV); | ||
3219 | IWL_CMD(CSR_EEPROM_REG); | ||
3220 | IWL_CMD(CSR_EEPROM_GP); | ||
3221 | IWL_CMD(CSR_OTP_GP_REG); | ||
3222 | IWL_CMD(CSR_GIO_REG); | ||
3223 | IWL_CMD(CSR_GP_UCODE_REG); | ||
3224 | IWL_CMD(CSR_GP_DRIVER_REG); | ||
3225 | IWL_CMD(CSR_UCODE_DRV_GP1); | ||
3226 | IWL_CMD(CSR_UCODE_DRV_GP2); | ||
3227 | IWL_CMD(CSR_LED_REG); | ||
3228 | IWL_CMD(CSR_DRAM_INT_TBL_REG); | ||
3229 | IWL_CMD(CSR_GIO_CHICKEN_BITS); | ||
3230 | IWL_CMD(CSR_ANA_PLL_CFG); | ||
3231 | IWL_CMD(CSR_HW_REV_WA_REG); | ||
3232 | IWL_CMD(CSR_DBG_HPET_MEM_REG); | ||
3233 | default: | ||
3234 | return "UNKNOWN"; | ||
3235 | |||
3236 | } | ||
3237 | } | ||
3238 | |||
3239 | void iwl_dump_csr(struct iwl_priv *priv) | ||
3240 | { | ||
3241 | int i; | ||
3242 | u32 csr_tbl[] = { | ||
3243 | CSR_HW_IF_CONFIG_REG, | ||
3244 | CSR_INT_COALESCING, | ||
3245 | CSR_INT, | ||
3246 | CSR_INT_MASK, | ||
3247 | CSR_FH_INT_STATUS, | ||
3248 | CSR_GPIO_IN, | ||
3249 | CSR_RESET, | ||
3250 | CSR_GP_CNTRL, | ||
3251 | CSR_HW_REV, | ||
3252 | CSR_EEPROM_REG, | ||
3253 | CSR_EEPROM_GP, | ||
3254 | CSR_OTP_GP_REG, | ||
3255 | CSR_GIO_REG, | ||
3256 | CSR_GP_UCODE_REG, | ||
3257 | CSR_GP_DRIVER_REG, | ||
3258 | CSR_UCODE_DRV_GP1, | ||
3259 | CSR_UCODE_DRV_GP2, | ||
3260 | CSR_LED_REG, | ||
3261 | CSR_DRAM_INT_TBL_REG, | ||
3262 | CSR_GIO_CHICKEN_BITS, | ||
3263 | CSR_ANA_PLL_CFG, | ||
3264 | CSR_HW_REV_WA_REG, | ||
3265 | CSR_DBG_HPET_MEM_REG | ||
3266 | }; | ||
3267 | IWL_ERR(priv, "CSR values:\n"); | ||
3268 | IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " | ||
3269 | "CSR_INT_PERIODIC_REG)\n"); | ||
3270 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { | ||
3271 | IWL_ERR(priv, " %25s: 0X%08x\n", | ||
3272 | get_csr_string(csr_tbl[i]), | ||
3273 | iwl_read32(priv, csr_tbl[i])); | ||
3274 | } | ||
3275 | } | ||
3276 | EXPORT_SYMBOL(iwl_dump_csr); | ||
3277 | |||
3278 | const static char *get_fh_string(int cmd) | ||
3279 | { | ||
3280 | switch (cmd) { | ||
3281 | IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); | ||
3282 | IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); | ||
3283 | IWL_CMD(FH_RSCSR_CHNL0_WPTR); | ||
3284 | IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); | ||
3285 | IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); | ||
3286 | IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); | ||
3287 | IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); | ||
3288 | IWL_CMD(FH_TSSR_TX_STATUS_REG); | ||
3289 | IWL_CMD(FH_TSSR_TX_ERROR_REG); | ||
3290 | default: | ||
3291 | return "UNKNOWN"; | ||
3292 | |||
3293 | } | ||
3294 | } | ||
3295 | |||
3296 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) | ||
3297 | { | ||
3298 | int i; | ||
3299 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3300 | int pos = 0; | ||
3301 | size_t bufsz = 0; | ||
3302 | #endif | ||
3303 | u32 fh_tbl[] = { | ||
3304 | FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
3305 | FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
3306 | FH_RSCSR_CHNL0_WPTR, | ||
3307 | FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
3308 | FH_MEM_RSSR_SHARED_CTRL_REG, | ||
3309 | FH_MEM_RSSR_RX_STATUS_REG, | ||
3310 | FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, | ||
3311 | FH_TSSR_TX_STATUS_REG, | ||
3312 | FH_TSSR_TX_ERROR_REG | ||
3313 | }; | ||
3314 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3315 | if (display) { | ||
3316 | bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; | ||
3317 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
3318 | if (!*buf) | ||
3319 | return -ENOMEM; | ||
3320 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
3321 | "FH register values:\n"); | ||
3322 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
3323 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
3324 | " %34s: 0X%08x\n", | ||
3325 | get_fh_string(fh_tbl[i]), | ||
3326 | iwl_read_direct32(priv, fh_tbl[i])); | ||
3327 | } | ||
3328 | return pos; | ||
3329 | } | ||
3330 | #endif | ||
3331 | IWL_ERR(priv, "FH register values:\n"); | ||
3332 | for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { | ||
3333 | IWL_ERR(priv, " %34s: 0X%08x\n", | ||
3334 | get_fh_string(fh_tbl[i]), | ||
3335 | iwl_read_direct32(priv, fh_tbl[i])); | ||
3336 | } | ||
3337 | return 0; | ||
3338 | } | ||
3339 | EXPORT_SYMBOL(iwl_dump_fh); | ||
3340 | |||
3341 | static void iwl_force_rf_reset(struct iwl_priv *priv) | ||
3342 | { | ||
3343 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3344 | return; | ||
3345 | |||
3346 | if (!iwl_is_associated(priv)) { | ||
3347 | IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); | ||
3348 | return; | ||
3349 | } | ||
3350 | /* | ||
3351 | * There is no easy and better way to force reset the radio, | ||
3352 | * the only known method is switching channel which will force to | ||
3353 | * reset and tune the radio. | ||
3354 | * Use internal short scan (single channel) operation to should | ||
3355 | * achieve this objective. | ||
3356 | * Driver should reset the radio when number of consecutive missed | ||
3357 | * beacon, or any other uCode error condition detected. | ||
3358 | */ | ||
3359 | IWL_DEBUG_INFO(priv, "perform radio reset.\n"); | ||
3360 | iwl_internal_short_hw_scan(priv); | ||
3361 | } | ||
3362 | |||
3363 | |||
3364 | int iwl_force_reset(struct iwl_priv *priv, int mode) | ||
3365 | { | ||
3366 | struct iwl_force_reset *force_reset; | ||
3367 | |||
3368 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3369 | return -EINVAL; | ||
3370 | |||
3371 | if (mode >= IWL_MAX_FORCE_RESET) { | ||
3372 | IWL_DEBUG_INFO(priv, "invalid reset request.\n"); | ||
3373 | return -EINVAL; | ||
3374 | } | ||
3375 | force_reset = &priv->force_reset[mode]; | ||
3376 | force_reset->reset_request_count++; | ||
3377 | if (force_reset->last_force_reset_jiffies && | ||
3378 | time_after(force_reset->last_force_reset_jiffies + | ||
3379 | force_reset->reset_duration, jiffies)) { | ||
3380 | IWL_DEBUG_INFO(priv, "force reset rejected\n"); | ||
3381 | force_reset->reset_reject_count++; | ||
3382 | return -EAGAIN; | ||
3383 | } | ||
3384 | force_reset->reset_success_count++; | ||
3385 | force_reset->last_force_reset_jiffies = jiffies; | ||
3386 | IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); | ||
3387 | switch (mode) { | ||
3388 | case IWL_RF_RESET: | ||
3389 | iwl_force_rf_reset(priv); | ||
3390 | break; | ||
3391 | case IWL_FW_RESET: | ||
3392 | IWL_ERR(priv, "On demand firmware reload\n"); | ||
3393 | /* Set the FW error flag -- cleared on iwl_down */ | ||
3394 | set_bit(STATUS_FW_ERROR, &priv->status); | ||
3395 | wake_up_interruptible(&priv->wait_command_queue); | ||
3396 | /* | ||
3397 | * Keep the restart process from trying to send host | ||
3398 | * commands by clearing the INIT status bit | ||
3399 | */ | ||
3400 | clear_bit(STATUS_READY, &priv->status); | ||
3401 | queue_work(priv->workqueue, &priv->restart); | ||
3402 | break; | ||
3403 | } | ||
3404 | return 0; | ||
3405 | } | ||
3406 | |||
3037 | #ifdef CONFIG_PM | 3407 | #ifdef CONFIG_PM |
3038 | 3408 | ||
3039 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 3409 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7754538c2194..36940a9ec6b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -70,8 +70,8 @@ struct iwl_host_cmd; | |||
70 | struct iwl_cmd; | 70 | struct iwl_cmd; |
71 | 71 | ||
72 | 72 | ||
73 | #define IWLWIFI_VERSION "1.3.27k" | 73 | #define IWLWIFI_VERSION "in-tree:" |
74 | #define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" | 74 | #define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" |
75 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 75 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
76 | 76 | ||
77 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 77 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
@@ -89,6 +89,7 @@ struct iwl_hcmd_ops { | |||
89 | int (*rxon_assoc)(struct iwl_priv *priv); | 89 | int (*rxon_assoc)(struct iwl_priv *priv); |
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 | }; | 93 | }; |
93 | 94 | ||
94 | struct iwl_hcmd_utils_ops { | 95 | struct iwl_hcmd_utils_ops { |
@@ -97,7 +98,8 @@ struct iwl_hcmd_utils_ops { | |||
97 | void (*gain_computation)(struct iwl_priv *priv, | 98 | void (*gain_computation)(struct iwl_priv *priv, |
98 | u32 *average_noise, | 99 | u32 *average_noise, |
99 | u16 min_average_noise_antennat_i, | 100 | u16 min_average_noise_antennat_i, |
100 | u32 min_average_noise); | 101 | u32 min_average_noise, |
102 | u8 default_chain); | ||
101 | void (*chain_noise_reset)(struct iwl_priv *priv); | 103 | void (*chain_noise_reset)(struct iwl_priv *priv); |
102 | void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, | 104 | void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, |
103 | __le32 *tx_flags); | 105 | __le32 *tx_flags); |
@@ -107,7 +109,6 @@ struct iwl_hcmd_utils_ops { | |||
107 | 109 | ||
108 | struct iwl_apm_ops { | 110 | struct iwl_apm_ops { |
109 | int (*init)(struct iwl_priv *priv); | 111 | int (*init)(struct iwl_priv *priv); |
110 | int (*reset)(struct iwl_priv *priv); | ||
111 | void (*stop)(struct iwl_priv *priv); | 112 | void (*stop)(struct iwl_priv *priv); |
112 | void (*config)(struct iwl_priv *priv); | 113 | void (*config)(struct iwl_priv *priv); |
113 | int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); | 114 | int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); |
@@ -116,6 +117,7 @@ struct iwl_apm_ops { | |||
116 | struct iwl_temp_ops { | 117 | struct iwl_temp_ops { |
117 | void (*temperature)(struct iwl_priv *priv); | 118 | void (*temperature)(struct iwl_priv *priv); |
118 | void (*set_ct_kill)(struct iwl_priv *priv); | 119 | void (*set_ct_kill)(struct iwl_priv *priv); |
120 | void (*set_calib_version)(struct iwl_priv *priv); | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | struct iwl_ucode_ops { | 123 | struct iwl_ucode_ops { |
@@ -166,8 +168,12 @@ struct iwl_lib_ops { | |||
166 | int (*is_valid_rtc_data_addr)(u32 addr); | 168 | int (*is_valid_rtc_data_addr)(u32 addr); |
167 | /* 1st ucode load */ | 169 | /* 1st ucode load */ |
168 | int (*load_ucode)(struct iwl_priv *priv); | 170 | int (*load_ucode)(struct iwl_priv *priv); |
169 | void (*dump_nic_event_log)(struct iwl_priv *priv); | 171 | int (*dump_nic_event_log)(struct iwl_priv *priv, |
172 | bool full_log, char **buf, bool display); | ||
170 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 173 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
174 | void (*dump_csr)(struct iwl_priv *priv); | ||
175 | int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); | ||
176 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | ||
171 | /* power management */ | 177 | /* power management */ |
172 | struct iwl_apm_ops apm_ops; | 178 | struct iwl_apm_ops apm_ops; |
173 | 179 | ||
@@ -183,6 +189,14 @@ struct iwl_lib_ops { | |||
183 | 189 | ||
184 | /* temperature */ | 190 | /* temperature */ |
185 | struct iwl_temp_ops temp_ops; | 191 | struct iwl_temp_ops temp_ops; |
192 | /* station management */ | ||
193 | void (*add_bcast_station)(struct iwl_priv *priv); | ||
194 | }; | ||
195 | |||
196 | struct iwl_led_ops { | ||
197 | int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); | ||
198 | int (*on)(struct iwl_priv *priv); | ||
199 | int (*off)(struct iwl_priv *priv); | ||
186 | }; | 200 | }; |
187 | 201 | ||
188 | struct iwl_ops { | 202 | struct iwl_ops { |
@@ -190,13 +204,13 @@ struct iwl_ops { | |||
190 | const struct iwl_lib_ops *lib; | 204 | const struct iwl_lib_ops *lib; |
191 | const struct iwl_hcmd_ops *hcmd; | 205 | const struct iwl_hcmd_ops *hcmd; |
192 | const struct iwl_hcmd_utils_ops *utils; | 206 | const struct iwl_hcmd_utils_ops *utils; |
207 | const struct iwl_led_ops *led; | ||
193 | }; | 208 | }; |
194 | 209 | ||
195 | struct iwl_mod_params { | 210 | struct iwl_mod_params { |
196 | int sw_crypto; /* def: 0 = using hardware encryption */ | 211 | int sw_crypto; /* def: 0 = using hardware encryption */ |
197 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 212 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
198 | int num_of_queues; /* def: HW dependent */ | 213 | int num_of_queues; /* def: HW dependent */ |
199 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
200 | int disable_11n; /* def: 0 = 11n capabilities enabled */ | 214 | int disable_11n; /* def: 0 = 11n capabilities enabled */ |
201 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ | 215 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ |
202 | int antenna; /* def: 0 = both antennas (use diversity) */ | 216 | int antenna; /* def: 0 = both antennas (use diversity) */ |
@@ -213,7 +227,16 @@ struct iwl_mod_params { | |||
213 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier | 227 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier |
214 | * @max_ll_items: max number of OTP blocks | 228 | * @max_ll_items: max number of OTP blocks |
215 | * @shadow_ram_support: shadow support for OTP memory | 229 | * @shadow_ram_support: shadow support for OTP memory |
230 | * @led_compensation: compensate on the led on/off time per HW according | ||
231 | * to the deviation to achieve the desired led frequency. | ||
232 | * The detail algorithm is described in iwl-led.c | ||
216 | * @use_rts_for_ht: use rts/cts protection for HT traffic | 233 | * @use_rts_for_ht: use rts/cts protection for HT traffic |
234 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | ||
235 | * @adv_thermal_throttle: support advance thermal throttle | ||
236 | * @support_ct_kill_exit: support ct kill exit condition | ||
237 | * @support_wimax_coexist: support wimax/wifi co-exist | ||
238 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | ||
239 | * radio tuning when there is a high receiving plcp error rate | ||
217 | * | 240 | * |
218 | * We enable the driver to be backward compatible wrt API version. The | 241 | * We enable the driver to be backward compatible wrt API version. The |
219 | * driver specifies which APIs it supports (with @ucode_api_max being the | 242 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -245,18 +268,33 @@ struct iwl_cfg { | |||
245 | int eeprom_size; | 268 | int eeprom_size; |
246 | u16 eeprom_ver; | 269 | u16 eeprom_ver; |
247 | u16 eeprom_calib_ver; | 270 | u16 eeprom_calib_ver; |
271 | int num_of_queues; /* def: HW dependent */ | ||
272 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
248 | const struct iwl_ops *ops; | 273 | const struct iwl_ops *ops; |
249 | const struct iwl_mod_params *mod_params; | 274 | const struct iwl_mod_params *mod_params; |
250 | u8 valid_tx_ant; | 275 | u8 valid_tx_ant; |
251 | u8 valid_rx_ant; | 276 | u8 valid_rx_ant; |
252 | bool need_pll_cfg; | 277 | |
278 | /* for iwl_apm_init() */ | ||
279 | u32 pll_cfg_val; | ||
280 | bool set_l0s; | ||
281 | bool use_bsm; | ||
282 | |||
253 | bool use_isr_legacy; | 283 | bool use_isr_legacy; |
254 | enum iwl_pa_type pa_type; | 284 | enum iwl_pa_type pa_type; |
255 | const u16 max_ll_items; | 285 | const u16 max_ll_items; |
256 | const bool shadow_ram_support; | 286 | const bool shadow_ram_support; |
257 | const bool ht_greenfield_support; | 287 | const bool ht_greenfield_support; |
288 | u16 led_compensation; | ||
258 | const bool broken_powersave; | 289 | const bool broken_powersave; |
259 | bool use_rts_for_ht; | 290 | bool use_rts_for_ht; |
291 | int chain_noise_num_beacons; | ||
292 | const bool supports_idle; | ||
293 | bool adv_thermal_throttle; | ||
294 | bool support_ct_kill_exit; | ||
295 | const bool support_wimax_coexist; | ||
296 | u8 plcp_delta_threshold; | ||
297 | s32 chain_noise_scale; | ||
260 | }; | 298 | }; |
261 | 299 | ||
262 | /*************************** | 300 | /*************************** |
@@ -275,7 +313,7 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv); | |||
275 | int iwl_full_rxon_required(struct iwl_priv *priv); | 313 | int iwl_full_rxon_required(struct iwl_priv *priv); |
276 | void iwl_set_rxon_chain(struct iwl_priv *priv); | 314 | void iwl_set_rxon_chain(struct iwl_priv *priv); |
277 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); | 315 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); |
278 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); | 316 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); |
279 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 317 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
280 | struct ieee80211_sta_ht_cap *sta_ht_inf); | 318 | struct ieee80211_sta_ht_cap *sta_ht_inf); |
281 | void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); | 319 | void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); |
@@ -289,10 +327,7 @@ void iwl_configure_filter(struct ieee80211_hw *hw, | |||
289 | unsigned int changed_flags, | 327 | unsigned int changed_flags, |
290 | unsigned int *total_flags, u64 multicast); | 328 | unsigned int *total_flags, u64 multicast); |
291 | int iwl_hw_nic_init(struct iwl_priv *priv); | 329 | int iwl_hw_nic_init(struct iwl_priv *priv); |
292 | int iwl_setup_mac(struct iwl_priv *priv); | ||
293 | int iwl_set_hw_params(struct iwl_priv *priv); | 330 | int iwl_set_hw_params(struct iwl_priv *priv); |
294 | int iwl_init_drv(struct iwl_priv *priv); | ||
295 | void iwl_uninit_drv(struct iwl_priv *priv); | ||
296 | bool iwl_is_monitor_mode(struct iwl_priv *priv); | 331 | bool iwl_is_monitor_mode(struct iwl_priv *priv); |
297 | void iwl_post_associate(struct iwl_priv *priv); | 332 | void iwl_post_associate(struct iwl_priv *priv); |
298 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | 333 | void iwl_bss_info_changed(struct ieee80211_hw *hw, |
@@ -303,14 +338,17 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
303 | int iwl_commit_rxon(struct iwl_priv *priv); | 338 | int iwl_commit_rxon(struct iwl_priv *priv); |
304 | int iwl_set_mode(struct iwl_priv *priv, int mode); | 339 | int iwl_set_mode(struct iwl_priv *priv, int mode); |
305 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 340 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
306 | struct ieee80211_if_init_conf *conf); | 341 | struct ieee80211_vif *vif); |
307 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 342 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
308 | struct ieee80211_if_init_conf *conf); | 343 | struct ieee80211_vif *vif); |
309 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); | 344 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); |
310 | void iwl_config_ap(struct iwl_priv *priv); | 345 | void iwl_config_ap(struct iwl_priv *priv); |
311 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | ||
312 | struct ieee80211_tx_queue_stats *stats); | ||
313 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); | 346 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); |
347 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | ||
348 | void iwl_free_txq_mem(struct iwl_priv *priv); | ||
349 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
350 | __le32 *tx_flags); | ||
351 | int iwl_send_wimax_coex(struct iwl_priv *priv); | ||
314 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 352 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
315 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); | 353 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); |
316 | void iwl_free_traffic_mem(struct iwl_priv *priv); | 354 | void iwl_free_traffic_mem(struct iwl_priv *priv); |
@@ -321,8 +359,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, | |||
321 | u16 length, struct ieee80211_hdr *header); | 359 | u16 length, struct ieee80211_hdr *header); |
322 | const char *get_mgmt_string(int cmd); | 360 | const char *get_mgmt_string(int cmd); |
323 | const char *get_ctrl_string(int cmd); | 361 | const char *get_ctrl_string(int cmd); |
324 | void iwl_clear_tx_stats(struct iwl_priv *priv); | 362 | void iwl_clear_traffic_stats(struct iwl_priv *priv); |
325 | void iwl_clear_rx_stats(struct iwl_priv *priv); | ||
326 | void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, | 363 | void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, |
327 | u16 len); | 364 | u16 len); |
328 | #else | 365 | #else |
@@ -358,6 +395,7 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, | |||
358 | /* data */ | 395 | /* data */ |
359 | stats->data_bytes += len; | 396 | stats->data_bytes += len; |
360 | } | 397 | } |
398 | iwl_leds_background(priv); | ||
361 | } | 399 | } |
362 | #endif | 400 | #endif |
363 | /***************************************************** | 401 | /***************************************************** |
@@ -377,13 +415,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | |||
377 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 415 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
378 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 416 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
379 | void iwl_rx_handle(struct iwl_priv *priv); | 417 | void iwl_rx_handle(struct iwl_priv *priv); |
380 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 418 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
381 | struct iwl_rx_queue *q); | 419 | struct iwl_rx_queue *q); |
382 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 420 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
383 | void iwl_rx_replenish(struct iwl_priv *priv); | 421 | void iwl_rx_replenish(struct iwl_priv *priv); |
384 | void iwl_rx_replenish_now(struct iwl_priv *priv); | 422 | void iwl_rx_replenish_now(struct iwl_priv *priv); |
385 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 423 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
386 | int iwl_rx_queue_restock(struct iwl_priv *priv); | 424 | void iwl_rx_queue_restock(struct iwl_priv *priv); |
387 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 425 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
388 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); | 426 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); |
389 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 427 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
@@ -391,8 +429,12 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | |||
391 | /* Handlers */ | 429 | /* Handlers */ |
392 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 430 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
393 | struct iwl_rx_mem_buffer *rxb); | 431 | struct iwl_rx_mem_buffer *rxb); |
432 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
433 | struct iwl_rx_mem_buffer *rxb); | ||
394 | void iwl_rx_statistics(struct iwl_priv *priv, | 434 | void iwl_rx_statistics(struct iwl_priv *priv, |
395 | struct iwl_rx_mem_buffer *rxb); | 435 | struct iwl_rx_mem_buffer *rxb); |
436 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
437 | struct iwl_rx_mem_buffer *rxb); | ||
396 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 438 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
397 | 439 | ||
398 | /* TX helpers */ | 440 | /* TX helpers */ |
@@ -400,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
400 | /***************************************************** | 442 | /***************************************************** |
401 | * TX | 443 | * TX |
402 | ******************************************************/ | 444 | ******************************************************/ |
403 | int iwl_txq_ctx_reset(struct iwl_priv *priv); | 445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); |
446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
404 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
405 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 448 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
406 | struct iwl_tx_queue *txq, | 449 | struct iwl_tx_queue *txq, |
@@ -409,9 +452,13 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | |||
409 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | 452 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); |
410 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 453 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
411 | struct iwl_tx_queue *txq); | 454 | struct iwl_tx_queue *txq); |
412 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 455 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
456 | int sta_id, int tid, int freed); | ||
457 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
413 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 458 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
414 | int slots_num, u32 txq_id); | 459 | int slots_num, u32 txq_id); |
460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
461 | int slots_num, u32 txq_id); | ||
415 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
416 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
417 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 464 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); |
@@ -459,6 +506,8 @@ void iwl_init_scan_params(struct iwl_priv *priv); | |||
459 | int iwl_scan_cancel(struct iwl_priv *priv); | 506 | int iwl_scan_cancel(struct iwl_priv *priv); |
460 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 507 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
461 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); | 508 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); |
509 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | ||
510 | int iwl_force_reset(struct iwl_priv *priv, int mode); | ||
462 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 511 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
463 | const u8 *ie, int ie_len, int left); | 512 | const u8 *ie, int ie_len, int left); |
464 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 513 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
@@ -489,14 +538,6 @@ int iwl_send_calib_results(struct iwl_priv *priv); | |||
489 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); | 538 | int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); |
490 | void iwl_calib_free_results(struct iwl_priv *priv); | 539 | void iwl_calib_free_results(struct iwl_priv *priv); |
491 | 540 | ||
492 | /******************************************************************************* | ||
493 | * Spectrum Measureemtns in iwl-spectrum.c | ||
494 | ******************************************************************************/ | ||
495 | #ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT | ||
496 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv); | ||
497 | #else | ||
498 | static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {} | ||
499 | #endif | ||
500 | /***************************************************** | 541 | /***************************************************** |
501 | * S e n d i n g H o s t C o m m a n d s * | 542 | * S e n d i n g H o s t C o m m a n d s * |
502 | *****************************************************/ | 543 | *****************************************************/ |
@@ -511,7 +552,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, | |||
511 | const void *data, | 552 | const void *data, |
512 | void (*callback)(struct iwl_priv *priv, | 553 | void (*callback)(struct iwl_priv *priv, |
513 | struct iwl_device_cmd *cmd, | 554 | struct iwl_device_cmd *cmd, |
514 | struct sk_buff *skb)); | 555 | struct iwl_rx_packet *pkt)); |
515 | 556 | ||
516 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); | 557 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); |
517 | 558 | ||
@@ -544,15 +585,15 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
544 | /***************************************************** | 585 | /***************************************************** |
545 | * Error Handling Debugging | 586 | * Error Handling Debugging |
546 | ******************************************************/ | 587 | ******************************************************/ |
547 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
548 | void iwl_dump_nic_event_log(struct iwl_priv *priv); | ||
549 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 588 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
589 | int iwl_dump_nic_event_log(struct iwl_priv *priv, | ||
590 | bool full_log, char **buf, bool display); | ||
591 | void iwl_dump_csr(struct iwl_priv *priv); | ||
592 | int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); | ||
593 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
594 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | ||
550 | #else | 595 | #else |
551 | static inline void iwl_dump_nic_event_log(struct iwl_priv *priv) | 596 | static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv) |
552 | { | ||
553 | } | ||
554 | |||
555 | static inline void iwl_dump_nic_error_log(struct iwl_priv *priv) | ||
556 | { | 597 | { |
557 | } | 598 | } |
558 | #endif | 599 | #endif |
@@ -568,9 +609,10 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
568 | /*************** DRIVER STATUS FUNCTIONS *****/ | 609 | /*************** DRIVER STATUS FUNCTIONS *****/ |
569 | 610 | ||
570 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | 611 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ |
571 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | 612 | /* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ |
572 | #define STATUS_INT_ENABLED 2 | 613 | #define STATUS_INT_ENABLED 2 |
573 | #define STATUS_RF_KILL_HW 3 | 614 | #define STATUS_RF_KILL_HW 3 |
615 | #define STATUS_CT_KILL 4 | ||
574 | #define STATUS_INIT 5 | 616 | #define STATUS_INIT 5 |
575 | #define STATUS_ALIVE 6 | 617 | #define STATUS_ALIVE 6 |
576 | #define STATUS_READY 7 | 618 | #define STATUS_READY 7 |
@@ -615,6 +657,11 @@ static inline int iwl_is_rfkill(struct iwl_priv *priv) | |||
615 | return iwl_is_rfkill_hw(priv); | 657 | return iwl_is_rfkill_hw(priv); |
616 | } | 658 | } |
617 | 659 | ||
660 | static inline int iwl_is_ctkill(struct iwl_priv *priv) | ||
661 | { | ||
662 | return test_bit(STATUS_CT_KILL, &priv->status); | ||
663 | } | ||
664 | |||
618 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) | 665 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) |
619 | { | 666 | { |
620 | 667 | ||
@@ -626,7 +673,8 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) | |||
626 | 673 | ||
627 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | 674 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); |
628 | extern int iwl_send_bt_config(struct iwl_priv *priv); | 675 | extern int iwl_send_bt_config(struct iwl_priv *priv); |
629 | extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); | 676 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
677 | u8 flags, bool clear); | ||
630 | extern int iwl_verify_ucode(struct iwl_priv *priv); | 678 | extern int iwl_verify_ucode(struct iwl_priv *priv); |
631 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 679 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
632 | struct iwl_link_quality_cmd *lq, u8 flags); | 680 | struct iwl_link_quality_cmd *lq, u8 flags); |
@@ -636,6 +684,9 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | |||
636 | struct iwl_rx_mem_buffer *rxb); | 684 | struct iwl_rx_mem_buffer *rxb); |
637 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | 685 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, |
638 | struct iwl_rx_mem_buffer *rxb); | 686 | struct iwl_rx_mem_buffer *rxb); |
687 | 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); | ||
639 | 690 | ||
640 | void iwl_setup_rxon_timing(struct iwl_priv *priv); | 691 | void iwl_setup_rxon_timing(struct iwl_priv *priv); |
641 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 692 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
@@ -655,5 +706,4 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | |||
655 | { | 706 | { |
656 | return priv->hw->wiphy->bands[band]; | 707 | return priv->hw->wiphy->bands[band]; |
657 | } | 708 | } |
658 | |||
659 | #endif /* __iwl_core_h__ */ | 709 | #endif /* __iwl_core_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 06437d13e73e..808b7146bead 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -62,11 +62,28 @@ | |||
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #ifndef __iwl_csr_h__ | 63 | #ifndef __iwl_csr_h__ |
64 | #define __iwl_csr_h__ | 64 | #define __iwl_csr_h__ |
65 | /*=== CSR (control and status registers) ===*/ | 65 | /* |
66 | * CSR (control and status registers) | ||
67 | * | ||
68 | * CSR registers are mapped directly into PCI bus space, and are accessible | ||
69 | * whenever platform supplies power to device, even when device is in | ||
70 | * low power states due to driver-invoked device resets | ||
71 | * (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes. | ||
72 | * | ||
73 | * Use iwl_write32() and iwl_read32() family to access these registers; | ||
74 | * these provide simple PCI bus access, without waking up the MAC. | ||
75 | * Do not use iwl_write_direct32() family for these registers; | ||
76 | * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ. | ||
77 | * The MAC (uCode processor, etc.) does not need to be powered up for accessing | ||
78 | * the CSR registers. | ||
79 | * | ||
80 | * NOTE: Device does need to be awake in order to read this memory | ||
81 | * via CSR_EEPROM and CSR_OTP registers | ||
82 | */ | ||
66 | #define CSR_BASE (0x000) | 83 | #define CSR_BASE (0x000) |
67 | 84 | ||
68 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ | 85 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ |
69 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ | 86 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ |
70 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ | 87 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ |
71 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ | 88 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ |
72 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ | 89 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ |
@@ -74,43 +91,66 @@ | |||
74 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ | 91 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ |
75 | #define CSR_GP_CNTRL (CSR_BASE+0x024) | 92 | #define CSR_GP_CNTRL (CSR_BASE+0x024) |
76 | 93 | ||
94 | /* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */ | ||
95 | #define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) | ||
96 | |||
77 | /* | 97 | /* |
78 | * Hardware revision info | 98 | * Hardware revision info |
79 | * Bit fields: | 99 | * Bit fields: |
80 | * 31-8: Reserved | 100 | * 31-8: Reserved |
81 | * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 | 101 | * 7-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions |
82 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | 102 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D |
83 | * 1-0: "Dash" value, as in A-1, etc. | 103 | * 1-0: "Dash" (-) value, as in A-1, etc. |
84 | * | 104 | * |
85 | * NOTE: Revision step affects calculation of CCK txpower for 4965. | 105 | * NOTE: Revision step affects calculation of CCK txpower for 4965. |
106 | * NOTE: See also CSR_HW_REV_WA_REG (work-around for bug in 4965). | ||
86 | */ | 107 | */ |
87 | #define CSR_HW_REV (CSR_BASE+0x028) | 108 | #define CSR_HW_REV (CSR_BASE+0x028) |
88 | 109 | ||
89 | /* EEPROM reads */ | 110 | /* |
111 | * EEPROM and OTP (one-time-programmable) memory reads | ||
112 | * | ||
113 | * NOTE: Device must be awake, initialized via apm_ops.init(), | ||
114 | * in order to read. | ||
115 | */ | ||
90 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) | 116 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) |
91 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | 117 | #define CSR_EEPROM_GP (CSR_BASE+0x030) |
92 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) | 118 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) |
119 | |||
93 | #define CSR_GIO_REG (CSR_BASE+0x03C) | 120 | #define CSR_GIO_REG (CSR_BASE+0x03C) |
94 | #define CSR_GP_UCODE_REG (CSR_BASE+0x048) | 121 | #define CSR_GP_UCODE_REG (CSR_BASE+0x048) |
95 | #define CSR_GP_DRIVER_REG (CSR_BASE+0x050) | 122 | #define CSR_GP_DRIVER_REG (CSR_BASE+0x050) |
123 | |||
124 | /* | ||
125 | * UCODE-DRIVER GP (general purpose) mailbox registers. | ||
126 | * SET/CLR registers set/clear bit(s) if "1" is written. | ||
127 | */ | ||
96 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | 128 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) |
97 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) | 129 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) |
98 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) | 130 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) |
99 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) | 131 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) |
132 | |||
100 | #define CSR_LED_REG (CSR_BASE+0x094) | 133 | #define CSR_LED_REG (CSR_BASE+0x094) |
101 | #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) | 134 | #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) |
135 | |||
136 | /* GIO Chicken Bits (PCI Express bus link power management) */ | ||
102 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) | 137 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) |
103 | 138 | ||
104 | #define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) | ||
105 | /* Analog phase-lock-loop configuration */ | 139 | /* Analog phase-lock-loop configuration */ |
106 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) | 140 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) |
141 | |||
107 | /* | 142 | /* |
108 | * Indicates hardware rev, to determine CCK backoff for txpower calculation. | 143 | * CSR Hardware Revision Workaround Register. Indicates hardware rev; |
144 | * "step" determines CCK backoff for txpower calculation. Used for 4965 only. | ||
145 | * See also CSR_HW_REV register. | ||
109 | * Bit fields: | 146 | * Bit fields: |
110 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step | 147 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step |
148 | * 1-0: "Dash" (-) value, as in C-1, etc. | ||
111 | */ | 149 | */ |
112 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) | 150 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) |
113 | #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) | 151 | |
152 | #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) | ||
153 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) | ||
114 | 154 | ||
115 | /* Bits for CSR_HW_IF_CONFIG_REG */ | 155 | /* Bits for CSR_HW_IF_CONFIG_REG */ |
116 | #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) | 156 | #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) |
@@ -125,14 +165,14 @@ | |||
125 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) | 165 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) |
126 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) | 166 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) |
127 | 167 | ||
128 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) | 168 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) |
129 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | 169 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) |
130 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) | 170 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ |
131 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) | 171 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */ |
132 | #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) | 172 | #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */ |
133 | 173 | ||
134 | #define CSR_INT_PERIODIC_DIS (0x00) | 174 | #define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/ |
135 | #define CSR_INT_PERIODIC_ENA (0xFF) | 175 | #define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/ |
136 | 176 | ||
137 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), | 177 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), |
138 | * acknowledged (reset) by host writing "1" to flagged bits. */ | 178 | * acknowledged (reset) by host writing "1" to flagged bits. */ |
@@ -195,8 +235,46 @@ | |||
195 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) | 235 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) |
196 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) | 236 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) |
197 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) | 237 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) |
238 | #define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000) | ||
198 | 239 | ||
199 | /* GP (general purpose) CONTROL */ | 240 | /* |
241 | * GP (general purpose) CONTROL REGISTER | ||
242 | * Bit fields: | ||
243 | * 27: HW_RF_KILL_SW | ||
244 | * Indicates state of (platform's) hardware RF-Kill switch | ||
245 | * 26-24: POWER_SAVE_TYPE | ||
246 | * Indicates current power-saving mode: | ||
247 | * 000 -- No power saving | ||
248 | * 001 -- MAC power-down | ||
249 | * 010 -- PHY (radio) power-down | ||
250 | * 011 -- Error | ||
251 | * 9-6: SYS_CONFIG | ||
252 | * Indicates current system configuration, reflecting pins on chip | ||
253 | * as forced high/low by device circuit board. | ||
254 | * 4: GOING_TO_SLEEP | ||
255 | * Indicates MAC is entering a power-saving sleep power-down. | ||
256 | * Not a good time to access device-internal resources. | ||
257 | * 3: MAC_ACCESS_REQ | ||
258 | * Host sets this to request and maintain MAC wakeup, to allow host | ||
259 | * access to device-internal resources. Host must wait for | ||
260 | * MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR | ||
261 | * device registers. | ||
262 | * 2: INIT_DONE | ||
263 | * Host sets this to put device into fully operational D0 power mode. | ||
264 | * Host resets this after SW_RESET to put device into low power mode. | ||
265 | * 0: MAC_CLOCK_READY | ||
266 | * Indicates MAC (ucode processor, etc.) is powered up and can run. | ||
267 | * Internal resources are accessible. | ||
268 | * NOTE: This does not indicate that the processor is actually running. | ||
269 | * NOTE: This does not indicate that 4965 or 3945 has completed | ||
270 | * init or post-power-down restore of internal SRAM memory. | ||
271 | * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that | ||
272 | * SRAM is restored and uCode is in normal operation mode. | ||
273 | * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and | ||
274 | * do not need to save/restore it. | ||
275 | * NOTE: After device reset, this bit remains "0" until host sets | ||
276 | * INIT_DONE | ||
277 | */ | ||
200 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) | 278 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) |
201 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) | 279 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) |
202 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) | 280 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) |
@@ -229,18 +307,58 @@ | |||
229 | #define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000) | 307 | #define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000) |
230 | 308 | ||
231 | /* EEPROM GP */ | 309 | /* EEPROM GP */ |
232 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) | 310 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) /* signature */ |
233 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) | ||
234 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | 311 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) |
312 | #define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000) | ||
313 | #define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001) | ||
314 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002) | ||
315 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004) | ||
316 | |||
317 | /* One-time-programmable memory general purpose reg */ | ||
235 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ | 318 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ |
236 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ | 319 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ |
237 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ | 320 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ |
238 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ | 321 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ |
239 | 322 | ||
323 | /* GP REG */ | ||
324 | #define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */ | ||
325 | #define CSR_GP_REG_NO_POWER_SAVE (0x00000000) | ||
326 | #define CSR_GP_REG_MAC_POWER_SAVE (0x01000000) | ||
327 | #define CSR_GP_REG_PHY_POWER_SAVE (0x02000000) | ||
328 | #define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000) | ||
329 | |||
330 | |||
240 | /* CSR GIO */ | 331 | /* CSR GIO */ |
241 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) | 332 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) |
242 | 333 | ||
243 | /* UCODE DRV GP */ | 334 | /* |
335 | * UCODE-DRIVER GP (general purpose) mailbox register 1 | ||
336 | * Host driver and uCode write and/or read this register to communicate with | ||
337 | * each other. | ||
338 | * Bit fields: | ||
339 | * 4: UCODE_DISABLE | ||
340 | * Host sets this to request permanent halt of uCode, same as | ||
341 | * sending CARD_STATE command with "halt" bit set. | ||
342 | * 3: CT_KILL_EXIT | ||
343 | * Host sets this to request exit from CT_KILL state, i.e. host thinks | ||
344 | * device temperature is low enough to continue normal operation. | ||
345 | * 2: CMD_BLOCKED | ||
346 | * Host sets this during RF KILL power-down sequence (HW, SW, CT KILL) | ||
347 | * to release uCode to clear all Tx and command queues, enter | ||
348 | * unassociated mode, and power down. | ||
349 | * NOTE: Some devices also use HBUS_TARG_MBX_C register for this bit. | ||
350 | * 1: SW_BIT_RFKILL | ||
351 | * Host sets this when issuing CARD_STATE command to request | ||
352 | * device sleep. | ||
353 | * 0: MAC_SLEEP | ||
354 | * uCode sets this when preparing a power-saving power-down. | ||
355 | * uCode resets this when power-up is complete and SRAM is sane. | ||
356 | * NOTE: 3945/4965 saves internal SRAM data to host when powering down, | ||
357 | * and must restore this data after powering back up. | ||
358 | * MAC_SLEEP is the best indication that restore is complete. | ||
359 | * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and | ||
360 | * do not need to save/restore it. | ||
361 | */ | ||
244 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) | 362 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) |
245 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) | 363 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) |
246 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) | 364 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) |
@@ -251,9 +369,9 @@ | |||
251 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) | 369 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) |
252 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) | 370 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) |
253 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) | 371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) |
372 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) | ||
254 | 373 | ||
255 | 374 | /* GIO Chicken Bits (PCI Express bus link power management) */ | |
256 | /* GI Chicken Bits */ | ||
257 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 375 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
258 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | 376 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) |
259 | 377 | ||
@@ -273,8 +391,23 @@ | |||
273 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) | 391 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) |
274 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) | 392 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) |
275 | 393 | ||
276 | /*=== HBUS (Host-side Bus) ===*/ | 394 | /* |
395 | * HBUS (Host-side Bus) | ||
396 | * | ||
397 | * HBUS registers are mapped directly into PCI bus space, but are used | ||
398 | * to indirectly access device's internal memory or registers that | ||
399 | * may be powered-down. | ||
400 | * | ||
401 | * Use iwl_write_direct32()/iwl_read_direct32() family for these registers; | ||
402 | * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ | ||
403 | * to make sure the MAC (uCode processor, etc.) is powered up for accessing | ||
404 | * internal resources. | ||
405 | * | ||
406 | * Do not use iwl_write32()/iwl_read32() family to access these registers; | ||
407 | * these provide only simple PCI bus access, without waking up the MAC. | ||
408 | */ | ||
277 | #define HBUS_BASE (0x400) | 409 | #define HBUS_BASE (0x400) |
410 | |||
278 | /* | 411 | /* |
279 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM | 412 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM |
280 | * structures, error log, event log, verifying uCode load). | 413 | * structures, error log, event log, verifying uCode load). |
@@ -289,6 +422,10 @@ | |||
289 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) | 422 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) |
290 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) | 423 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) |
291 | 424 | ||
425 | /* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */ | ||
426 | #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) | ||
427 | #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) | ||
428 | |||
292 | /* | 429 | /* |
293 | * Registers for accessing device's internal peripheral registers | 430 | * Registers for accessing device's internal peripheral registers |
294 | * (e.g. SCD, BSM, etc.). First write to address register, | 431 | * (e.g. SCD, BSM, etc.). First write to address register, |
@@ -303,16 +440,12 @@ | |||
303 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) | 440 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) |
304 | 441 | ||
305 | /* | 442 | /* |
306 | * Per-Tx-queue write pointer (index, really!) (3945 and 4965). | 443 | * Per-Tx-queue write pointer (index, really!) |
307 | * Indicates index to next TFD that driver will fill (1 past latest filled). | 444 | * Indicates index to next TFD that driver will fill (1 past latest filled). |
308 | * Bit usage: | 445 | * Bit usage: |
309 | * 0-7: queue write index | 446 | * 0-7: queue write index |
310 | * 11-8: queue selector | 447 | * 11-8: queue selector |
311 | */ | 448 | */ |
312 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) | 449 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) |
313 | #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) | ||
314 | |||
315 | #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) | ||
316 | |||
317 | 450 | ||
318 | #endif /* !__iwl_csr_h__ */ | 451 | #endif /* !__iwl_csr_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index cbc62904655d..1c7b53d511c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project. | 5 | * Portions of this file are derived from the ipw3945 project. |
6 | * | 6 | * |
@@ -67,56 +67,6 @@ do { \ | |||
67 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ | 67 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ |
68 | } while (0) | 68 | } while (0) |
69 | 69 | ||
70 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
71 | struct iwl_debugfs { | ||
72 | const char *name; | ||
73 | struct dentry *dir_drv; | ||
74 | struct dentry *dir_data; | ||
75 | struct dentry *dir_debug; | ||
76 | struct dentry *dir_rf; | ||
77 | struct dir_data_files { | ||
78 | struct dentry *file_sram; | ||
79 | struct dentry *file_nvm; | ||
80 | struct dentry *file_stations; | ||
81 | struct dentry *file_log_event; | ||
82 | struct dentry *file_channels; | ||
83 | struct dentry *file_status; | ||
84 | struct dentry *file_interrupt; | ||
85 | struct dentry *file_qos; | ||
86 | struct dentry *file_thermal_throttling; | ||
87 | #ifdef CONFIG_IWLWIFI_LEDS | ||
88 | struct dentry *file_led; | ||
89 | #endif | ||
90 | struct dentry *file_disable_ht40; | ||
91 | struct dentry *file_sleep_level_override; | ||
92 | struct dentry *file_current_sleep_command; | ||
93 | } dbgfs_data_files; | ||
94 | struct dir_rf_files { | ||
95 | struct dentry *file_disable_sensitivity; | ||
96 | struct dentry *file_disable_chain_noise; | ||
97 | struct dentry *file_disable_tx_power; | ||
98 | } dbgfs_rf_files; | ||
99 | struct dir_debug_files { | ||
100 | struct dentry *file_rx_statistics; | ||
101 | struct dentry *file_tx_statistics; | ||
102 | struct dentry *file_traffic_log; | ||
103 | struct dentry *file_rx_queue; | ||
104 | struct dentry *file_tx_queue; | ||
105 | struct dentry *file_ucode_rx_stats; | ||
106 | struct dentry *file_ucode_tx_stats; | ||
107 | struct dentry *file_ucode_general_stats; | ||
108 | struct dentry *file_sensitivity; | ||
109 | struct dentry *file_chain_noise; | ||
110 | struct dentry *file_tx_power; | ||
111 | } dbgfs_debug_files; | ||
112 | u32 sram_offset; | ||
113 | u32 sram_len; | ||
114 | }; | ||
115 | |||
116 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | ||
117 | void iwl_dbgfs_unregister(struct iwl_priv *priv); | ||
118 | #endif | ||
119 | |||
120 | #else | 70 | #else |
121 | #define IWL_DEBUG(__priv, level, fmt, args...) | 71 | #define IWL_DEBUG(__priv, level, fmt, args...) |
122 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) | 72 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) |
@@ -125,9 +75,10 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | |||
125 | {} | 75 | {} |
126 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 76 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
127 | 77 | ||
128 | 78 | #ifdef CONFIG_IWLWIFI_DEBUGFS | |
129 | 79 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); | |
130 | #ifndef CONFIG_IWLWIFI_DEBUGFS | 80 | void iwl_dbgfs_unregister(struct iwl_priv *priv); |
81 | #else | ||
131 | static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 82 | static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) |
132 | { | 83 | { |
133 | return 0; | 84 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a198bcf61022..b6e1b0ebe230 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -26,6 +26,7 @@ | |||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | *****************************************************************************/ | 27 | *****************************************************************************/ |
28 | 28 | ||
29 | #include <linux/slab.h> | ||
29 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
@@ -41,43 +42,28 @@ | |||
41 | #include "iwl-calib.h" | 42 | #include "iwl-calib.h" |
42 | 43 | ||
43 | /* create and remove of files */ | 44 | /* create and remove of files */ |
44 | #define DEBUGFS_ADD_DIR(name, parent) do { \ | 45 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ |
45 | dbgfs->dir_##name = debugfs_create_dir(#name, parent); \ | 46 | if (!debugfs_create_file(#name, mode, parent, priv, \ |
46 | if (!(dbgfs->dir_##name)) \ | 47 | &iwl_dbgfs_##name##_ops)) \ |
47 | goto err; \ | 48 | goto err; \ |
48 | } while (0) | 49 | } while (0) |
49 | 50 | ||
50 | #define DEBUGFS_ADD_FILE(name, parent) do { \ | 51 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ |
51 | dbgfs->dbgfs_##parent##_files.file_##name = \ | 52 | struct dentry *__tmp; \ |
52 | debugfs_create_file(#name, S_IWUSR | S_IRUSR, \ | 53 | __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ |
53 | dbgfs->dir_##parent, priv, \ | 54 | parent, ptr); \ |
54 | &iwl_dbgfs_##name##_ops); \ | 55 | if (IS_ERR(__tmp) || !__tmp) \ |
55 | if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ | 56 | goto err; \ |
56 | goto err; \ | ||
57 | } while (0) | 57 | } while (0) |
58 | 58 | ||
59 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ | 59 | #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ |
60 | dbgfs->dbgfs_##parent##_files.file_##name = \ | 60 | struct dentry *__tmp; \ |
61 | debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ | 61 | __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ |
62 | dbgfs->dir_##parent, ptr); \ | 62 | parent, ptr); \ |
63 | if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ | 63 | if (IS_ERR(__tmp) || !__tmp) \ |
64 | || !dbgfs->dbgfs_##parent##_files.file_##name) \ | 64 | goto err; \ |
65 | goto err; \ | ||
66 | } while (0) | 65 | } while (0) |
67 | 66 | ||
68 | #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ | ||
69 | dbgfs->dbgfs_##parent##_files.file_##name = \ | ||
70 | debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \ | ||
71 | if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ | ||
72 | || !dbgfs->dbgfs_##parent##_files.file_##name) \ | ||
73 | goto err; \ | ||
74 | } while (0) | ||
75 | |||
76 | #define DEBUGFS_REMOVE(name) do { \ | ||
77 | debugfs_remove(name); \ | ||
78 | name = NULL; \ | ||
79 | } while (0); | ||
80 | |||
81 | /* file operation */ | 67 | /* file operation */ |
82 | #define DEBUGFS_READ_FUNC(name) \ | 68 | #define DEBUGFS_READ_FUNC(name) \ |
83 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | 69 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ |
@@ -125,27 +111,28 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | |||
125 | char __user *user_buf, | 111 | char __user *user_buf, |
126 | size_t count, loff_t *ppos) { | 112 | size_t count, loff_t *ppos) { |
127 | 113 | ||
128 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 114 | struct iwl_priv *priv = file->private_data; |
129 | char *buf; | 115 | char *buf; |
130 | int pos = 0; | 116 | int pos = 0; |
131 | 117 | ||
132 | int cnt; | 118 | int cnt; |
133 | ssize_t ret; | 119 | ssize_t ret; |
134 | const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX); | 120 | const size_t bufsz = 100 + |
121 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | ||
135 | buf = kzalloc(bufsz, GFP_KERNEL); | 122 | buf = kzalloc(bufsz, GFP_KERNEL); |
136 | if (!buf) | 123 | if (!buf) |
137 | return -ENOMEM; | 124 | return -ENOMEM; |
138 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 125 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); |
139 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 126 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { |
140 | pos += scnprintf(buf + pos, bufsz - pos, | 127 | pos += scnprintf(buf + pos, bufsz - pos, |
141 | "\t%s\t\t: %u\n", | 128 | "\t%25s\t\t: %u\n", |
142 | get_mgmt_string(cnt), | 129 | get_mgmt_string(cnt), |
143 | priv->tx_stats.mgmt[cnt]); | 130 | priv->tx_stats.mgmt[cnt]); |
144 | } | 131 | } |
145 | pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); | 132 | pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); |
146 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 133 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { |
147 | pos += scnprintf(buf + pos, bufsz - pos, | 134 | pos += scnprintf(buf + pos, bufsz - pos, |
148 | "\t%s\t\t: %u\n", | 135 | "\t%25s\t\t: %u\n", |
149 | get_ctrl_string(cnt), | 136 | get_ctrl_string(cnt), |
150 | priv->tx_stats.ctrl[cnt]); | 137 | priv->tx_stats.ctrl[cnt]); |
151 | } | 138 | } |
@@ -159,7 +146,7 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | |||
159 | return ret; | 146 | return ret; |
160 | } | 147 | } |
161 | 148 | ||
162 | static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file, | 149 | static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file, |
163 | const char __user *user_buf, | 150 | const char __user *user_buf, |
164 | size_t count, loff_t *ppos) | 151 | size_t count, loff_t *ppos) |
165 | { | 152 | { |
@@ -174,8 +161,7 @@ static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file, | |||
174 | return -EFAULT; | 161 | return -EFAULT; |
175 | if (sscanf(buf, "%x", &clear_flag) != 1) | 162 | if (sscanf(buf, "%x", &clear_flag) != 1) |
176 | return -EFAULT; | 163 | return -EFAULT; |
177 | if (clear_flag == 1) | 164 | iwl_clear_traffic_stats(priv); |
178 | iwl_clear_tx_stats(priv); | ||
179 | 165 | ||
180 | return count; | 166 | return count; |
181 | } | 167 | } |
@@ -184,13 +170,13 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
184 | char __user *user_buf, | 170 | char __user *user_buf, |
185 | size_t count, loff_t *ppos) { | 171 | size_t count, loff_t *ppos) { |
186 | 172 | ||
187 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 173 | struct iwl_priv *priv = file->private_data; |
188 | char *buf; | 174 | char *buf; |
189 | int pos = 0; | 175 | int pos = 0; |
190 | int cnt; | 176 | int cnt; |
191 | ssize_t ret; | 177 | ssize_t ret; |
192 | const size_t bufsz = 100 + | 178 | const size_t bufsz = 100 + |
193 | sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX); | 179 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); |
194 | buf = kzalloc(bufsz, GFP_KERNEL); | 180 | buf = kzalloc(bufsz, GFP_KERNEL); |
195 | if (!buf) | 181 | if (!buf) |
196 | return -ENOMEM; | 182 | return -ENOMEM; |
@@ -198,14 +184,14 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
198 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 184 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); |
199 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 185 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { |
200 | pos += scnprintf(buf + pos, bufsz - pos, | 186 | pos += scnprintf(buf + pos, bufsz - pos, |
201 | "\t%s\t\t: %u\n", | 187 | "\t%25s\t\t: %u\n", |
202 | get_mgmt_string(cnt), | 188 | get_mgmt_string(cnt), |
203 | priv->rx_stats.mgmt[cnt]); | 189 | priv->rx_stats.mgmt[cnt]); |
204 | } | 190 | } |
205 | pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); | 191 | pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); |
206 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 192 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { |
207 | pos += scnprintf(buf + pos, bufsz - pos, | 193 | pos += scnprintf(buf + pos, bufsz - pos, |
208 | "\t%s\t\t: %u\n", | 194 | "\t%25s\t\t: %u\n", |
209 | get_ctrl_string(cnt), | 195 | get_ctrl_string(cnt), |
210 | priv->rx_stats.ctrl[cnt]); | 196 | priv->rx_stats.ctrl[cnt]); |
211 | } | 197 | } |
@@ -220,26 +206,6 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
220 | return ret; | 206 | return ret; |
221 | } | 207 | } |
222 | 208 | ||
223 | static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file, | ||
224 | const char __user *user_buf, | ||
225 | size_t count, loff_t *ppos) | ||
226 | { | ||
227 | struct iwl_priv *priv = file->private_data; | ||
228 | u32 clear_flag; | ||
229 | char buf[8]; | ||
230 | int buf_size; | ||
231 | |||
232 | memset(buf, 0, sizeof(buf)); | ||
233 | buf_size = min(count, sizeof(buf) - 1); | ||
234 | if (copy_from_user(buf, user_buf, buf_size)) | ||
235 | return -EFAULT; | ||
236 | if (sscanf(buf, "%x", &clear_flag) != 1) | ||
237 | return -EFAULT; | ||
238 | if (clear_flag == 1) | ||
239 | iwl_clear_rx_stats(priv); | ||
240 | return count; | ||
241 | } | ||
242 | |||
243 | #define BYTE1_MASK 0x000000ff; | 209 | #define BYTE1_MASK 0x000000ff; |
244 | #define BYTE2_MASK 0x0000ffff; | 210 | #define BYTE2_MASK 0x0000ffff; |
245 | #define BYTE3_MASK 0x00ffffff; | 211 | #define BYTE3_MASK 0x00ffffff; |
@@ -248,16 +214,32 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
248 | size_t count, loff_t *ppos) | 214 | size_t count, loff_t *ppos) |
249 | { | 215 | { |
250 | u32 val; | 216 | u32 val; |
251 | char buf[1024]; | 217 | char *buf; |
252 | ssize_t ret; | 218 | ssize_t ret; |
253 | int i; | 219 | int i; |
254 | int pos = 0; | 220 | int pos = 0; |
255 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 221 | struct iwl_priv *priv = file->private_data; |
256 | const size_t bufsz = sizeof(buf); | 222 | size_t bufsz; |
257 | 223 | ||
258 | for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { | 224 | /* default is to dump the entire data segment */ |
259 | val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ | 225 | if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { |
260 | priv->dbgfs->sram_len - i); | 226 | priv->dbgfs_sram_offset = 0x800000; |
227 | if (priv->ucode_type == UCODE_INIT) | ||
228 | priv->dbgfs_sram_len = priv->ucode_init_data.len; | ||
229 | else | ||
230 | priv->dbgfs_sram_len = priv->ucode_data.len; | ||
231 | } | ||
232 | bufsz = 30 + priv->dbgfs_sram_len * sizeof(char) * 10; | ||
233 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
234 | if (!buf) | ||
235 | return -ENOMEM; | ||
236 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", | ||
237 | priv->dbgfs_sram_len); | ||
238 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | ||
239 | priv->dbgfs_sram_offset); | ||
240 | for (i = priv->dbgfs_sram_len; i > 0; i -= 4) { | ||
241 | val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \ | ||
242 | priv->dbgfs_sram_len - i); | ||
261 | if (i < 4) { | 243 | if (i < 4) { |
262 | switch (i) { | 244 | switch (i) { |
263 | case 1: | 245 | case 1: |
@@ -271,11 +253,14 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
271 | break; | 253 | break; |
272 | } | 254 | } |
273 | } | 255 | } |
256 | if (!(i % 16)) | ||
257 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
274 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); | 258 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); |
275 | } | 259 | } |
276 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 260 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
277 | 261 | ||
278 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 262 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
263 | kfree(buf); | ||
279 | return ret; | 264 | return ret; |
280 | } | 265 | } |
281 | 266 | ||
@@ -294,11 +279,11 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, | |||
294 | return -EFAULT; | 279 | return -EFAULT; |
295 | 280 | ||
296 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { | 281 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { |
297 | priv->dbgfs->sram_offset = offset; | 282 | priv->dbgfs_sram_offset = offset; |
298 | priv->dbgfs->sram_len = len; | 283 | priv->dbgfs_sram_len = len; |
299 | } else { | 284 | } else { |
300 | priv->dbgfs->sram_offset = 0; | 285 | priv->dbgfs_sram_offset = 0; |
301 | priv->dbgfs->sram_len = 0; | 286 | priv->dbgfs_sram_len = 0; |
302 | } | 287 | } |
303 | 288 | ||
304 | return count; | 289 | return count; |
@@ -307,7 +292,7 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, | |||
307 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | 292 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, |
308 | size_t count, loff_t *ppos) | 293 | size_t count, loff_t *ppos) |
309 | { | 294 | { |
310 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 295 | struct iwl_priv *priv = file->private_data; |
311 | struct iwl_station_entry *station; | 296 | struct iwl_station_entry *station; |
312 | int max_sta = priv->hw_params.max_stations; | 297 | int max_sta = priv->hw_params.max_stations; |
313 | char *buf; | 298 | char *buf; |
@@ -335,8 +320,6 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
335 | pos += scnprintf(buf + pos, bufsz - pos, | 320 | pos += scnprintf(buf + pos, bufsz - pos, |
336 | "flags: 0x%x\n", | 321 | "flags: 0x%x\n", |
337 | station->sta.station_flags_msk); | 322 | station->sta.station_flags_msk); |
338 | pos += scnprintf(buf + pos, bufsz - pos, | ||
339 | "ps_status: %u\n", station->ps_status); | ||
340 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); | 323 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); |
341 | pos += scnprintf(buf + pos, bufsz - pos, | 324 | pos += scnprintf(buf + pos, bufsz - pos, |
342 | "seq_num\t\ttxq_id"); | 325 | "seq_num\t\ttxq_id"); |
@@ -379,10 +362,11 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
379 | loff_t *ppos) | 362 | loff_t *ppos) |
380 | { | 363 | { |
381 | ssize_t ret; | 364 | ssize_t ret; |
382 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 365 | struct iwl_priv *priv = file->private_data; |
383 | int pos = 0, ofs = 0, buf_size = 0; | 366 | int pos = 0, ofs = 0, buf_size = 0; |
384 | const u8 *ptr; | 367 | const u8 *ptr; |
385 | char *buf; | 368 | char *buf; |
369 | u16 eeprom_ver; | ||
386 | size_t eeprom_len = priv->cfg->eeprom_size; | 370 | size_t eeprom_len = priv->cfg->eeprom_size; |
387 | buf_size = 4 * eeprom_len + 256; | 371 | buf_size = 4 * eeprom_len + 256; |
388 | 372 | ||
@@ -403,9 +387,11 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
403 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 387 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
404 | return -ENOMEM; | 388 | return -ENOMEM; |
405 | } | 389 | } |
406 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n", | 390 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); |
391 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | ||
392 | "version: 0x%x\n", | ||
407 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 393 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
408 | ? "OTP" : "EEPROM"); | 394 | ? "OTP" : "EEPROM", eeprom_ver); |
409 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 395 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
410 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 396 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
411 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 397 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -420,6 +406,24 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
420 | return ret; | 406 | return ret; |
421 | } | 407 | } |
422 | 408 | ||
409 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
410 | char __user *user_buf, | ||
411 | size_t count, loff_t *ppos) | ||
412 | { | ||
413 | struct iwl_priv *priv = file->private_data; | ||
414 | char *buf; | ||
415 | int pos = 0; | ||
416 | ssize_t ret = -ENOMEM; | ||
417 | |||
418 | ret = pos = priv->cfg->ops->lib->dump_nic_event_log( | ||
419 | priv, true, &buf, true); | ||
420 | if (buf) { | ||
421 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
422 | kfree(buf); | ||
423 | } | ||
424 | return ret; | ||
425 | } | ||
426 | |||
423 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | 427 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, |
424 | const char __user *user_buf, | 428 | const char __user *user_buf, |
425 | size_t count, loff_t *ppos) | 429 | size_t count, loff_t *ppos) |
@@ -436,7 +440,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
436 | if (sscanf(buf, "%d", &event_log_flag) != 1) | 440 | if (sscanf(buf, "%d", &event_log_flag) != 1) |
437 | return -EFAULT; | 441 | return -EFAULT; |
438 | if (event_log_flag == 1) | 442 | if (event_log_flag == 1) |
439 | priv->cfg->ops->lib->dump_nic_event_log(priv); | 443 | priv->cfg->ops->lib->dump_nic_event_log(priv, true, |
444 | NULL, false); | ||
440 | 445 | ||
441 | return count; | 446 | return count; |
442 | } | 447 | } |
@@ -446,7 +451,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
446 | static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | 451 | static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, |
447 | size_t count, loff_t *ppos) | 452 | size_t count, loff_t *ppos) |
448 | { | 453 | { |
449 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 454 | struct iwl_priv *priv = file->private_data; |
450 | struct ieee80211_channel *channels = NULL; | 455 | struct ieee80211_channel *channels = NULL; |
451 | const struct ieee80211_supported_band *supp_band = NULL; | 456 | const struct ieee80211_supported_band *supp_band = NULL; |
452 | int pos = 0, i, bufsz = PAGE_SIZE; | 457 | int pos = 0, i, bufsz = PAGE_SIZE; |
@@ -519,19 +524,19 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
519 | char __user *user_buf, | 524 | char __user *user_buf, |
520 | size_t count, loff_t *ppos) { | 525 | size_t count, loff_t *ppos) { |
521 | 526 | ||
522 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 527 | struct iwl_priv *priv = file->private_data; |
523 | char buf[512]; | 528 | char buf[512]; |
524 | int pos = 0; | 529 | int pos = 0; |
525 | const size_t bufsz = sizeof(buf); | 530 | const size_t bufsz = sizeof(buf); |
526 | 531 | ||
527 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", | 532 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", |
528 | test_bit(STATUS_HCMD_ACTIVE, &priv->status)); | 533 | test_bit(STATUS_HCMD_ACTIVE, &priv->status)); |
529 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", | ||
530 | test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); | ||
531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", | 534 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", |
532 | test_bit(STATUS_INT_ENABLED, &priv->status)); | 535 | test_bit(STATUS_INT_ENABLED, &priv->status)); |
533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 536 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", |
534 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 537 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
538 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", | ||
539 | test_bit(STATUS_CT_KILL, &priv->status)); | ||
535 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", | 540 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", |
536 | test_bit(STATUS_INIT, &priv->status)); | 541 | test_bit(STATUS_INIT, &priv->status)); |
537 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", | 542 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", |
@@ -565,7 +570,7 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | |||
565 | char __user *user_buf, | 570 | char __user *user_buf, |
566 | size_t count, loff_t *ppos) { | 571 | size_t count, loff_t *ppos) { |
567 | 572 | ||
568 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 573 | struct iwl_priv *priv = file->private_data; |
569 | int pos = 0; | 574 | int pos = 0; |
570 | int cnt = 0; | 575 | int cnt = 0; |
571 | char *buf; | 576 | char *buf; |
@@ -652,7 +657,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | |||
652 | static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | 657 | static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, |
653 | size_t count, loff_t *ppos) | 658 | size_t count, loff_t *ppos) |
654 | { | 659 | { |
655 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 660 | struct iwl_priv *priv = file->private_data; |
656 | int pos = 0, i; | 661 | int pos = 0, i; |
657 | char buf[256]; | 662 | char buf[256]; |
658 | const size_t bufsz = sizeof(buf); | 663 | const size_t bufsz = sizeof(buf); |
@@ -672,11 +677,10 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
672 | return ret; | 677 | return ret; |
673 | } | 678 | } |
674 | 679 | ||
675 | #ifdef CONFIG_IWLWIFI_LEDS | ||
676 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | 680 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, |
677 | size_t count, loff_t *ppos) | 681 | size_t count, loff_t *ppos) |
678 | { | 682 | { |
679 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 683 | struct iwl_priv *priv = file->private_data; |
680 | int pos = 0; | 684 | int pos = 0; |
681 | char buf[256]; | 685 | char buf[256]; |
682 | const size_t bufsz = sizeof(buf); | 686 | const size_t bufsz = sizeof(buf); |
@@ -697,13 +701,12 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | |||
697 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 701 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
698 | return ret; | 702 | return ret; |
699 | } | 703 | } |
700 | #endif | ||
701 | 704 | ||
702 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 705 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, |
703 | char __user *user_buf, | 706 | char __user *user_buf, |
704 | size_t count, loff_t *ppos) | 707 | size_t count, loff_t *ppos) |
705 | { | 708 | { |
706 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 709 | struct iwl_priv *priv = file->private_data; |
707 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 710 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
708 | struct iwl_tt_restriction *restriction; | 711 | struct iwl_tt_restriction *restriction; |
709 | char buf[100]; | 712 | char buf[100]; |
@@ -763,7 +766,7 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, | |||
763 | char __user *user_buf, | 766 | char __user *user_buf, |
764 | size_t count, loff_t *ppos) | 767 | size_t count, loff_t *ppos) |
765 | { | 768 | { |
766 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 769 | struct iwl_priv *priv = file->private_data; |
767 | char buf[100]; | 770 | char buf[100]; |
768 | int pos = 0; | 771 | int pos = 0; |
769 | const size_t bufsz = sizeof(buf); | 772 | const size_t bufsz = sizeof(buf); |
@@ -798,15 +801,22 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | |||
798 | * valid here. However, let's not confuse them and present | 801 | * valid here. However, let's not confuse them and present |
799 | * IWL_POWER_INDEX_1 as "1", not "0". | 802 | * IWL_POWER_INDEX_1 as "1", not "0". |
800 | */ | 803 | */ |
801 | if (value > 0) | 804 | if (value == 0) |
805 | return -EINVAL; | ||
806 | else if (value > 0) | ||
802 | value -= 1; | 807 | value -= 1; |
803 | 808 | ||
804 | if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) | 809 | if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) |
805 | return -EINVAL; | 810 | return -EINVAL; |
806 | 811 | ||
812 | if (!iwl_is_ready_rf(priv)) | ||
813 | return -EAGAIN; | ||
814 | |||
807 | priv->power_data.debug_sleep_level_override = value; | 815 | priv->power_data.debug_sleep_level_override = value; |
808 | 816 | ||
809 | iwl_power_update_mode(priv, false); | 817 | mutex_lock(&priv->mutex); |
818 | iwl_power_update_mode(priv, true); | ||
819 | mutex_unlock(&priv->mutex); | ||
810 | 820 | ||
811 | return count; | 821 | return count; |
812 | } | 822 | } |
@@ -815,7 +825,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, | |||
815 | char __user *user_buf, | 825 | char __user *user_buf, |
816 | size_t count, loff_t *ppos) | 826 | size_t count, loff_t *ppos) |
817 | { | 827 | { |
818 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 828 | struct iwl_priv *priv = file->private_data; |
819 | char buf[10]; | 829 | char buf[10]; |
820 | int pos, value; | 830 | int pos, value; |
821 | const size_t bufsz = sizeof(buf); | 831 | const size_t bufsz = sizeof(buf); |
@@ -833,7 +843,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | |||
833 | char __user *user_buf, | 843 | char __user *user_buf, |
834 | size_t count, loff_t *ppos) | 844 | size_t count, loff_t *ppos) |
835 | { | 845 | { |
836 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 846 | struct iwl_priv *priv = file->private_data; |
837 | char buf[200]; | 847 | char buf[200]; |
838 | int pos = 0, i; | 848 | int pos = 0, i; |
839 | const size_t bufsz = sizeof(buf); | 849 | const size_t bufsz = sizeof(buf); |
@@ -854,16 +864,14 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | |||
854 | } | 864 | } |
855 | 865 | ||
856 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 866 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
857 | DEBUGFS_WRITE_FILE_OPS(log_event); | 867 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); |
858 | DEBUGFS_READ_FILE_OPS(nvm); | 868 | DEBUGFS_READ_FILE_OPS(nvm); |
859 | DEBUGFS_READ_FILE_OPS(stations); | 869 | DEBUGFS_READ_FILE_OPS(stations); |
860 | DEBUGFS_READ_FILE_OPS(channels); | 870 | DEBUGFS_READ_FILE_OPS(channels); |
861 | DEBUGFS_READ_FILE_OPS(status); | 871 | DEBUGFS_READ_FILE_OPS(status); |
862 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 872 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
863 | DEBUGFS_READ_FILE_OPS(qos); | 873 | DEBUGFS_READ_FILE_OPS(qos); |
864 | #ifdef CONFIG_IWLWIFI_LEDS | ||
865 | DEBUGFS_READ_FILE_OPS(led); | 874 | DEBUGFS_READ_FILE_OPS(led); |
866 | #endif | ||
867 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 875 | DEBUGFS_READ_FILE_OPS(thermal_throttling); |
868 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 876 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); |
869 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 877 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); |
@@ -881,10 +889,14 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | |||
881 | struct iwl_rx_queue *rxq = &priv->rxq; | 889 | struct iwl_rx_queue *rxq = &priv->rxq; |
882 | char *buf; | 890 | char *buf; |
883 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | 891 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + |
884 | (IWL_MAX_NUM_QUEUES * 32 * 8) + 400; | 892 | (priv->cfg->num_of_queues * 32 * 8) + 400; |
885 | const u8 *ptr; | 893 | const u8 *ptr; |
886 | ssize_t ret; | 894 | ssize_t ret; |
887 | 895 | ||
896 | if (!priv->txq) { | ||
897 | IWL_ERR(priv, "txq not ready\n"); | ||
898 | return -EAGAIN; | ||
899 | } | ||
888 | buf = kzalloc(bufsz, GFP_KERNEL); | 900 | buf = kzalloc(bufsz, GFP_KERNEL); |
889 | if (!buf) { | 901 | if (!buf) { |
890 | IWL_ERR(priv, "Can not allocate buffer\n"); | 902 | IWL_ERR(priv, "Can not allocate buffer\n"); |
@@ -969,15 +981,19 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
969 | char __user *user_buf, | 981 | char __user *user_buf, |
970 | size_t count, loff_t *ppos) { | 982 | size_t count, loff_t *ppos) { |
971 | 983 | ||
972 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 984 | struct iwl_priv *priv = file->private_data; |
973 | struct iwl_tx_queue *txq; | 985 | struct iwl_tx_queue *txq; |
974 | struct iwl_queue *q; | 986 | struct iwl_queue *q; |
975 | char *buf; | 987 | char *buf; |
976 | int pos = 0; | 988 | int pos = 0; |
977 | int cnt; | 989 | int cnt; |
978 | int ret; | 990 | int ret; |
979 | const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES; | 991 | const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues; |
980 | 992 | ||
993 | if (!priv->txq) { | ||
994 | IWL_ERR(priv, "txq not ready\n"); | ||
995 | return -EAGAIN; | ||
996 | } | ||
981 | buf = kzalloc(bufsz, GFP_KERNEL); | 997 | buf = kzalloc(bufsz, GFP_KERNEL); |
982 | if (!buf) | 998 | if (!buf) |
983 | return -ENOMEM; | 999 | return -ENOMEM; |
@@ -1011,7 +1027,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1011 | char __user *user_buf, | 1027 | char __user *user_buf, |
1012 | size_t count, loff_t *ppos) { | 1028 | size_t count, loff_t *ppos) { |
1013 | 1029 | ||
1014 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1030 | struct iwl_priv *priv = file->private_data; |
1015 | struct iwl_rx_queue *rxq = &priv->rxq; | 1031 | struct iwl_rx_queue *rxq = &priv->rxq; |
1016 | char buf[256]; | 1032 | char buf[256]; |
1017 | int pos = 0; | 1033 | int pos = 0; |
@@ -1028,10 +1044,6 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1028 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1044 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1029 | } | 1045 | } |
1030 | 1046 | ||
1031 | #define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0) | ||
1032 | #define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1) | ||
1033 | #define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2) | ||
1034 | |||
1035 | static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, | 1047 | static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, |
1036 | int bufsz) | 1048 | int bufsz) |
1037 | { | 1049 | { |
@@ -1056,36 +1068,33 @@ static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, | |||
1056 | return p; | 1068 | return p; |
1057 | } | 1069 | } |
1058 | 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"; | ||
1059 | 1077 | ||
1060 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | 1078 | static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, |
1061 | char __user *user_buf, | 1079 | char __user *user_buf, |
1062 | size_t count, loff_t *ppos) | 1080 | size_t count, loff_t *ppos) |
1063 | { | 1081 | { |
1064 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1082 | struct iwl_priv *priv = file->private_data; |
1065 | int pos = 0; | 1083 | int pos = 0; |
1066 | char *buf; | 1084 | char *buf; |
1067 | int bufsz = sizeof(struct statistics_rx_phy) * 20 + | 1085 | int bufsz = sizeof(struct statistics_rx_phy) * 40 + |
1068 | sizeof(struct statistics_rx_non_phy) * 20 + | 1086 | sizeof(struct statistics_rx_non_phy) * 40 + |
1069 | sizeof(struct statistics_rx_ht_phy) * 20 + 400; | 1087 | sizeof(struct statistics_rx_ht_phy) * 40 + 400; |
1070 | ssize_t ret; | 1088 | ssize_t ret; |
1071 | struct statistics_rx_phy *ofdm; | 1089 | struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; |
1072 | struct statistics_rx_phy *cck; | 1090 | struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; |
1073 | struct statistics_rx_non_phy *general; | 1091 | struct statistics_rx_non_phy *general, *accum_general; |
1074 | struct statistics_rx_ht_phy *ht; | 1092 | struct statistics_rx_non_phy *delta_general, *max_general; |
1093 | struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; | ||
1075 | 1094 | ||
1076 | if (!iwl_is_alive(priv)) | 1095 | if (!iwl_is_alive(priv)) |
1077 | return -EAGAIN; | 1096 | return -EAGAIN; |
1078 | 1097 | ||
1079 | /* make request to uCode to retrieve statistics information */ | ||
1080 | mutex_lock(&priv->mutex); | ||
1081 | ret = iwl_send_statistics_request(priv, 0); | ||
1082 | mutex_unlock(&priv->mutex); | ||
1083 | |||
1084 | if (ret) { | ||
1085 | IWL_ERR(priv, | ||
1086 | "Error sending statistics request: %zd\n", ret); | ||
1087 | return -EAGAIN; | ||
1088 | } | ||
1089 | buf = kzalloc(bufsz, GFP_KERNEL); | 1098 | buf = kzalloc(bufsz, GFP_KERNEL); |
1090 | if (!buf) { | 1099 | if (!buf) { |
1091 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 1100 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
@@ -1100,155 +1109,405 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
1100 | cck = &priv->statistics.rx.cck; | 1109 | cck = &priv->statistics.rx.cck; |
1101 | general = &priv->statistics.rx.general; | 1110 | general = &priv->statistics.rx.general; |
1102 | ht = &priv->statistics.rx.ofdm_ht; | 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 | |||
1103 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1125 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1104 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); | 1126 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1105 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n", | 1127 | "Statistics_Rx - OFDM:"); |
1106 | le32_to_cpu(ofdm->ina_cnt)); | 1128 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1107 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n", | 1129 | "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), |
1108 | le32_to_cpu(ofdm->fina_cnt)); | 1130 | accum_ofdm->ina_cnt, |
1109 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", | 1131 | delta_ofdm->ina_cnt, max_ofdm->ina_cnt); |
1110 | le32_to_cpu(ofdm->plcp_err)); | 1132 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1111 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", | 1133 | "fina_cnt:", |
1112 | le32_to_cpu(ofdm->crc32_err)); | 1134 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, |
1113 | pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", | 1135 | delta_ofdm->fina_cnt, max_ofdm->fina_cnt); |
1114 | le32_to_cpu(ofdm->overrun_err)); | 1136 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1115 | pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", | 1137 | "plcp_err:", |
1116 | le32_to_cpu(ofdm->early_overrun_err)); | 1138 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, |
1117 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", | 1139 | delta_ofdm->plcp_err, max_ofdm->plcp_err); |
1118 | le32_to_cpu(ofdm->crc32_good)); | 1140 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1119 | pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n", | 1141 | "crc32_err:", |
1120 | le32_to_cpu(ofdm->false_alarm_cnt)); | 1142 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, |
1121 | pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n", | 1143 | delta_ofdm->crc32_err, max_ofdm->crc32_err); |
1122 | le32_to_cpu(ofdm->fina_sync_err_cnt)); | 1144 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1123 | pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n", | 1145 | "overrun_err:", |
1124 | le32_to_cpu(ofdm->sfd_timeout)); | 1146 | le32_to_cpu(ofdm->overrun_err), |
1125 | pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n", | 1147 | accum_ofdm->overrun_err, |
1126 | le32_to_cpu(ofdm->fina_timeout)); | 1148 | delta_ofdm->overrun_err, max_ofdm->overrun_err); |
1127 | pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n", | 1149 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1128 | le32_to_cpu(ofdm->unresponded_rts)); | 1150 | "early_overrun_err:", |
1129 | pos += scnprintf(buf + pos, bufsz - pos, | 1151 | le32_to_cpu(ofdm->early_overrun_err), |
1130 | "rxe_frame_limit_overrun: %u\n", | 1152 | accum_ofdm->early_overrun_err, |
1131 | le32_to_cpu(ofdm->rxe_frame_limit_overrun)); | 1153 | delta_ofdm->early_overrun_err, |
1132 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n", | 1154 | max_ofdm->early_overrun_err); |
1133 | le32_to_cpu(ofdm->sent_ack_cnt)); | 1155 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1134 | pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n", | 1156 | "crc32_good:", |
1135 | le32_to_cpu(ofdm->sent_cts_cnt)); | 1157 | le32_to_cpu(ofdm->crc32_good), |
1136 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n", | 1158 | accum_ofdm->crc32_good, |
1137 | le32_to_cpu(ofdm->sent_ba_rsp_cnt)); | 1159 | delta_ofdm->crc32_good, max_ofdm->crc32_good); |
1138 | pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n", | 1160 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1139 | le32_to_cpu(ofdm->dsp_self_kill)); | 1161 | "false_alarm_cnt:", |
1140 | pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", | 1162 | le32_to_cpu(ofdm->false_alarm_cnt), |
1141 | le32_to_cpu(ofdm->mh_format_err)); | 1163 | accum_ofdm->false_alarm_cnt, |
1142 | pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n", | 1164 | delta_ofdm->false_alarm_cnt, |
1143 | le32_to_cpu(ofdm->re_acq_main_rssi_sum)); | 1165 | max_ofdm->false_alarm_cnt); |
1144 | 1166 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | |
1145 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); | 1167 | "fina_sync_err_cnt:", |
1146 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n", | 1168 | le32_to_cpu(ofdm->fina_sync_err_cnt), |
1147 | le32_to_cpu(cck->ina_cnt)); | 1169 | accum_ofdm->fina_sync_err_cnt, |
1148 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n", | 1170 | delta_ofdm->fina_sync_err_cnt, |
1149 | le32_to_cpu(cck->fina_cnt)); | 1171 | max_ofdm->fina_sync_err_cnt); |
1150 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", | 1172 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1151 | le32_to_cpu(cck->plcp_err)); | 1173 | "sfd_timeout:", |
1152 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", | 1174 | le32_to_cpu(ofdm->sfd_timeout), |
1153 | le32_to_cpu(cck->crc32_err)); | 1175 | accum_ofdm->sfd_timeout, |
1154 | pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", | 1176 | delta_ofdm->sfd_timeout, |
1155 | le32_to_cpu(cck->overrun_err)); | 1177 | max_ofdm->sfd_timeout); |
1156 | pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", | 1178 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1157 | le32_to_cpu(cck->early_overrun_err)); | 1179 | "fina_timeout:", |
1158 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", | 1180 | le32_to_cpu(ofdm->fina_timeout), |
1159 | le32_to_cpu(cck->crc32_good)); | 1181 | accum_ofdm->fina_timeout, |
1160 | pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n", | 1182 | delta_ofdm->fina_timeout, |
1161 | le32_to_cpu(cck->false_alarm_cnt)); | 1183 | max_ofdm->fina_timeout); |
1162 | pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n", | 1184 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1163 | le32_to_cpu(cck->fina_sync_err_cnt)); | 1185 | "unresponded_rts:", |
1164 | pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n", | 1186 | le32_to_cpu(ofdm->unresponded_rts), |
1165 | le32_to_cpu(cck->sfd_timeout)); | 1187 | accum_ofdm->unresponded_rts, |
1166 | pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n", | 1188 | delta_ofdm->unresponded_rts, |
1167 | le32_to_cpu(cck->fina_timeout)); | 1189 | max_ofdm->unresponded_rts); |
1168 | pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n", | 1190 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1169 | le32_to_cpu(cck->unresponded_rts)); | 1191 | "rxe_frame_lmt_ovrun:", |
1170 | pos += scnprintf(buf + pos, bufsz - pos, | 1192 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), |
1171 | "rxe_frame_limit_overrun: %u\n", | 1193 | accum_ofdm->rxe_frame_limit_overrun, |
1172 | le32_to_cpu(cck->rxe_frame_limit_overrun)); | 1194 | delta_ofdm->rxe_frame_limit_overrun, |
1173 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n", | 1195 | max_ofdm->rxe_frame_limit_overrun); |
1174 | le32_to_cpu(cck->sent_ack_cnt)); | 1196 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1175 | pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n", | 1197 | "sent_ack_cnt:", |
1176 | le32_to_cpu(cck->sent_cts_cnt)); | 1198 | le32_to_cpu(ofdm->sent_ack_cnt), |
1177 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n", | 1199 | accum_ofdm->sent_ack_cnt, |
1178 | le32_to_cpu(cck->sent_ba_rsp_cnt)); | 1200 | delta_ofdm->sent_ack_cnt, |
1179 | pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n", | 1201 | max_ofdm->sent_ack_cnt); |
1180 | le32_to_cpu(cck->dsp_self_kill)); | 1202 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1181 | pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", | 1203 | "sent_cts_cnt:", |
1182 | le32_to_cpu(cck->mh_format_err)); | 1204 | le32_to_cpu(ofdm->sent_cts_cnt), |
1183 | pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n", | 1205 | accum_ofdm->sent_cts_cnt, |
1184 | le32_to_cpu(cck->re_acq_main_rssi_sum)); | 1206 | delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); |
1185 | 1207 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, | |
1186 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); | 1208 | "sent_ba_rsp_cnt:", |
1187 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n", | 1209 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), |
1188 | le32_to_cpu(general->bogus_cts)); | 1210 | accum_ofdm->sent_ba_rsp_cnt, |
1189 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n", | 1211 | delta_ofdm->sent_ba_rsp_cnt, |
1190 | le32_to_cpu(general->bogus_ack)); | 1212 | max_ofdm->sent_ba_rsp_cnt); |
1191 | pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n", | 1213 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1192 | le32_to_cpu(general->non_bssid_frames)); | 1214 | "dsp_self_kill:", |
1193 | pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n", | 1215 | le32_to_cpu(ofdm->dsp_self_kill), |
1194 | le32_to_cpu(general->filtered_frames)); | 1216 | accum_ofdm->dsp_self_kill, |
1195 | pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n", | 1217 | delta_ofdm->dsp_self_kill, |
1196 | le32_to_cpu(general->non_channel_beacons)); | 1218 | max_ofdm->dsp_self_kill); |
1197 | pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n", | 1219 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1198 | le32_to_cpu(general->channel_beacons)); | 1220 | "mh_format_err:", |
1199 | pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n", | 1221 | le32_to_cpu(ofdm->mh_format_err), |
1200 | le32_to_cpu(general->num_missed_bcon)); | 1222 | accum_ofdm->mh_format_err, |
1201 | pos += scnprintf(buf + pos, bufsz - pos, | 1223 | delta_ofdm->mh_format_err, |
1202 | "adc_rx_saturation_time: %u\n", | 1224 | max_ofdm->mh_format_err); |
1203 | le32_to_cpu(general->adc_rx_saturation_time)); | 1225 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1204 | pos += scnprintf(buf + pos, bufsz - pos, | 1226 | "re_acq_main_rssi_sum:", |
1205 | "ina_detection_search_time: %u\n", | 1227 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), |
1206 | le32_to_cpu(general->ina_detection_search_time)); | 1228 | accum_ofdm->re_acq_main_rssi_sum, |
1207 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n", | 1229 | delta_ofdm->re_acq_main_rssi_sum, |
1208 | le32_to_cpu(general->beacon_silence_rssi_a)); | 1230 | max_ofdm->re_acq_main_rssi_sum); |
1209 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n", | 1231 | |
1210 | le32_to_cpu(general->beacon_silence_rssi_b)); | 1232 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1211 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n", | 1233 | "Statistics_Rx - CCK:"); |
1212 | le32_to_cpu(general->beacon_silence_rssi_c)); | 1234 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1213 | pos += scnprintf(buf + pos, bufsz - pos, | 1235 | "ina_cnt:", |
1214 | "interference_data_flag: %u\n", | 1236 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, |
1215 | le32_to_cpu(general->interference_data_flag)); | 1237 | delta_cck->ina_cnt, max_cck->ina_cnt); |
1216 | pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n", | 1238 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1217 | le32_to_cpu(general->channel_load)); | 1239 | "fina_cnt:", |
1218 | pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n", | 1240 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, |
1219 | le32_to_cpu(general->dsp_false_alarms)); | 1241 | delta_cck->fina_cnt, max_cck->fina_cnt); |
1220 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n", | 1242 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1221 | le32_to_cpu(general->beacon_rssi_a)); | 1243 | "plcp_err:", |
1222 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n", | 1244 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, |
1223 | le32_to_cpu(general->beacon_rssi_b)); | 1245 | delta_cck->plcp_err, max_cck->plcp_err); |
1224 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n", | 1246 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1225 | le32_to_cpu(general->beacon_rssi_c)); | 1247 | "crc32_err:", |
1226 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n", | 1248 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, |
1227 | le32_to_cpu(general->beacon_energy_a)); | 1249 | delta_cck->crc32_err, max_cck->crc32_err); |
1228 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n", | 1250 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1229 | le32_to_cpu(general->beacon_energy_b)); | 1251 | "overrun_err:", |
1230 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n", | 1252 | le32_to_cpu(cck->overrun_err), |
1231 | le32_to_cpu(general->beacon_energy_c)); | 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); | ||
1232 | 1461 | ||
1233 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); | 1462 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); |
1234 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", | 1463 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1235 | le32_to_cpu(ht->plcp_err)); | 1464 | "Statistics_Rx - OFDM_HT:"); |
1236 | pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", | 1465 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1237 | le32_to_cpu(ht->overrun_err)); | 1466 | "plcp_err:", |
1238 | pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", | 1467 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, |
1239 | le32_to_cpu(ht->early_overrun_err)); | 1468 | delta_ht->plcp_err, max_ht->plcp_err); |
1240 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", | 1469 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1241 | le32_to_cpu(ht->crc32_good)); | 1470 | "overrun_err:", |
1242 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", | 1471 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, |
1243 | le32_to_cpu(ht->crc32_err)); | 1472 | delta_ht->overrun_err, max_ht->overrun_err); |
1244 | pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", | 1473 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1245 | le32_to_cpu(ht->mh_format_err)); | 1474 | "early_overrun_err:", |
1246 | pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n", | 1475 | le32_to_cpu(ht->early_overrun_err), |
1247 | le32_to_cpu(ht->agg_crc32_good)); | 1476 | accum_ht->early_overrun_err, |
1248 | pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n", | 1477 | delta_ht->early_overrun_err, |
1249 | le32_to_cpu(ht->agg_mpdu_cnt)); | 1478 | max_ht->early_overrun_err); |
1250 | pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n", | 1479 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1251 | le32_to_cpu(ht->agg_cnt)); | 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); | ||
1252 | 1511 | ||
1253 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1512 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1254 | kfree(buf); | 1513 | kfree(buf); |
@@ -1259,26 +1518,16 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1259 | char __user *user_buf, | 1518 | char __user *user_buf, |
1260 | size_t count, loff_t *ppos) | 1519 | size_t count, loff_t *ppos) |
1261 | { | 1520 | { |
1262 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1521 | struct iwl_priv *priv = file->private_data; |
1263 | int pos = 0; | 1522 | int pos = 0; |
1264 | char *buf; | 1523 | char *buf; |
1265 | int bufsz = (sizeof(struct statistics_tx) * 24) + 250; | 1524 | int bufsz = (sizeof(struct statistics_tx) * 48) + 250; |
1266 | ssize_t ret; | 1525 | ssize_t ret; |
1267 | struct statistics_tx *tx; | 1526 | struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; |
1268 | 1527 | ||
1269 | if (!iwl_is_alive(priv)) | 1528 | if (!iwl_is_alive(priv)) |
1270 | return -EAGAIN; | 1529 | return -EAGAIN; |
1271 | 1530 | ||
1272 | /* make request to uCode to retrieve statistics information */ | ||
1273 | mutex_lock(&priv->mutex); | ||
1274 | ret = iwl_send_statistics_request(priv, 0); | ||
1275 | mutex_unlock(&priv->mutex); | ||
1276 | |||
1277 | if (ret) { | ||
1278 | IWL_ERR(priv, | ||
1279 | "Error sending statistics request: %zd\n", ret); | ||
1280 | return -EAGAIN; | ||
1281 | } | ||
1282 | buf = kzalloc(bufsz, GFP_KERNEL); | 1531 | buf = kzalloc(bufsz, GFP_KERNEL); |
1283 | if (!buf) { | 1532 | if (!buf) { |
1284 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 1533 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
@@ -1290,62 +1539,149 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1290 | * might not reflect the current uCode activity | 1539 | * might not reflect the current uCode activity |
1291 | */ | 1540 | */ |
1292 | tx = &priv->statistics.tx; | 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; | ||
1293 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1545 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1294 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); | 1546 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1295 | pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n", | 1547 | "Statistics_Tx:"); |
1296 | le32_to_cpu(tx->preamble_cnt)); | 1548 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1297 | pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n", | 1549 | "preamble:", |
1298 | le32_to_cpu(tx->rx_detected_cnt)); | 1550 | le32_to_cpu(tx->preamble_cnt), |
1299 | pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n", | 1551 | accum_tx->preamble_cnt, |
1300 | le32_to_cpu(tx->bt_prio_defer_cnt)); | 1552 | delta_tx->preamble_cnt, max_tx->preamble_cnt); |
1301 | pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n", | 1553 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1302 | le32_to_cpu(tx->bt_prio_kill_cnt)); | 1554 | "rx_detected_cnt:", |
1303 | pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n", | 1555 | le32_to_cpu(tx->rx_detected_cnt), |
1304 | le32_to_cpu(tx->few_bytes_cnt)); | 1556 | accum_tx->rx_detected_cnt, |
1305 | pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n", | 1557 | delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); |
1306 | le32_to_cpu(tx->cts_timeout)); | 1558 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1307 | pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n", | 1559 | "bt_prio_defer_cnt:", |
1308 | le32_to_cpu(tx->ack_timeout)); | 1560 | le32_to_cpu(tx->bt_prio_defer_cnt), |
1309 | pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n", | 1561 | accum_tx->bt_prio_defer_cnt, |
1310 | le32_to_cpu(tx->expected_ack_cnt)); | 1562 | delta_tx->bt_prio_defer_cnt, |
1311 | pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n", | 1563 | max_tx->bt_prio_defer_cnt); |
1312 | le32_to_cpu(tx->actual_ack_cnt)); | 1564 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1313 | pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n", | 1565 | "bt_prio_kill_cnt:", |
1314 | le32_to_cpu(tx->dump_msdu_cnt)); | 1566 | le32_to_cpu(tx->bt_prio_kill_cnt), |
1315 | pos += scnprintf(buf + pos, bufsz - pos, | 1567 | accum_tx->bt_prio_kill_cnt, |
1316 | "burst_abort_next_frame_mismatch_cnt: %u\n", | 1568 | delta_tx->bt_prio_kill_cnt, |
1317 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt)); | 1569 | max_tx->bt_prio_kill_cnt); |
1318 | pos += scnprintf(buf + pos, bufsz - pos, | 1570 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1319 | "burst_abort_missing_next_frame_cnt: %u\n", | 1571 | "few_bytes_cnt:", |
1320 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt)); | 1572 | le32_to_cpu(tx->few_bytes_cnt), |
1321 | pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n", | 1573 | accum_tx->few_bytes_cnt, |
1322 | le32_to_cpu(tx->cts_timeout_collision)); | 1574 | delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); |
1323 | pos += scnprintf(buf + pos, bufsz - pos, | 1575 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1324 | "ack_or_ba_timeout_collision: %u\n", | 1576 | "cts_timeout:", |
1325 | le32_to_cpu(tx->ack_or_ba_timeout_collision)); | 1577 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, |
1326 | pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n", | 1578 | delta_tx->cts_timeout, max_tx->cts_timeout); |
1327 | le32_to_cpu(tx->agg.ba_timeout)); | 1579 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1328 | pos += scnprintf(buf + pos, bufsz - pos, | 1580 | "ack_timeout:", |
1329 | "agg ba_reschedule_frames: %u\n", | 1581 | le32_to_cpu(tx->ack_timeout), |
1330 | le32_to_cpu(tx->agg.ba_reschedule_frames)); | 1582 | accum_tx->ack_timeout, |
1331 | pos += scnprintf(buf + pos, bufsz - pos, | 1583 | delta_tx->ack_timeout, max_tx->ack_timeout); |
1332 | "agg scd_query_agg_frame_cnt: %u\n", | 1584 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1333 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt)); | 1585 | "expected_ack_cnt:", |
1334 | pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n", | 1586 | le32_to_cpu(tx->expected_ack_cnt), |
1335 | le32_to_cpu(tx->agg.scd_query_no_agg)); | 1587 | accum_tx->expected_ack_cnt, |
1336 | pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n", | 1588 | delta_tx->expected_ack_cnt, |
1337 | le32_to_cpu(tx->agg.scd_query_agg)); | 1589 | max_tx->expected_ack_cnt); |
1338 | pos += scnprintf(buf + pos, bufsz - pos, | 1590 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1339 | "agg scd_query_mismatch: %u\n", | 1591 | "actual_ack_cnt:", |
1340 | le32_to_cpu(tx->agg.scd_query_mismatch)); | 1592 | le32_to_cpu(tx->actual_ack_cnt), |
1341 | pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n", | 1593 | accum_tx->actual_ack_cnt, |
1342 | le32_to_cpu(tx->agg.frame_not_ready)); | 1594 | delta_tx->actual_ack_cnt, |
1343 | pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n", | 1595 | max_tx->actual_ack_cnt); |
1344 | le32_to_cpu(tx->agg.underrun)); | 1596 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1345 | pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n", | 1597 | "dump_msdu_cnt:", |
1346 | le32_to_cpu(tx->agg.bt_prio_kill)); | 1598 | le32_to_cpu(tx->dump_msdu_cnt), |
1347 | pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n", | 1599 | accum_tx->dump_msdu_cnt, |
1348 | le32_to_cpu(tx->agg.rx_ba_rsp_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); | ||
1349 | 1685 | ||
1350 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1686 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1351 | kfree(buf); | 1687 | kfree(buf); |
@@ -1356,28 +1692,19 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1356 | char __user *user_buf, | 1692 | char __user *user_buf, |
1357 | size_t count, loff_t *ppos) | 1693 | size_t count, loff_t *ppos) |
1358 | { | 1694 | { |
1359 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1695 | struct iwl_priv *priv = file->private_data; |
1360 | int pos = 0; | 1696 | int pos = 0; |
1361 | char *buf; | 1697 | char *buf; |
1362 | int bufsz = sizeof(struct statistics_general) * 4 + 250; | 1698 | int bufsz = sizeof(struct statistics_general) * 10 + 300; |
1363 | ssize_t ret; | 1699 | ssize_t ret; |
1364 | struct statistics_general *general; | 1700 | struct statistics_general *general, *accum_general; |
1365 | struct statistics_dbg *dbg; | 1701 | struct statistics_general *delta_general, *max_general; |
1366 | struct statistics_div *div; | 1702 | struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; |
1703 | struct statistics_div *div, *accum_div, *delta_div, *max_div; | ||
1367 | 1704 | ||
1368 | if (!iwl_is_alive(priv)) | 1705 | if (!iwl_is_alive(priv)) |
1369 | return -EAGAIN; | 1706 | return -EAGAIN; |
1370 | 1707 | ||
1371 | /* make request to uCode to retrieve statistics information */ | ||
1372 | mutex_lock(&priv->mutex); | ||
1373 | ret = iwl_send_statistics_request(priv, 0); | ||
1374 | mutex_unlock(&priv->mutex); | ||
1375 | |||
1376 | if (ret) { | ||
1377 | IWL_ERR(priv, | ||
1378 | "Error sending statistics request: %zd\n", ret); | ||
1379 | return -EAGAIN; | ||
1380 | } | ||
1381 | buf = kzalloc(bufsz, GFP_KERNEL); | 1708 | buf = kzalloc(bufsz, GFP_KERNEL); |
1382 | if (!buf) { | 1709 | if (!buf) { |
1383 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 1710 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
@@ -1391,34 +1718,79 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1391 | general = &priv->statistics.general; | 1718 | general = &priv->statistics.general; |
1392 | dbg = &priv->statistics.general.dbg; | 1719 | dbg = &priv->statistics.general.dbg; |
1393 | div = &priv->statistics.general.div; | 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; | ||
1394 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1730 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1395 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); | 1731 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, |
1396 | pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n", | 1732 | "Statistics_General:"); |
1733 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, | ||
1734 | "temperature:", | ||
1397 | le32_to_cpu(general->temperature)); | 1735 | le32_to_cpu(general->temperature)); |
1398 | pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n", | 1736 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, |
1737 | "temperature_m:", | ||
1399 | le32_to_cpu(general->temperature_m)); | 1738 | le32_to_cpu(general->temperature_m)); |
1400 | pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n", | 1739 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1401 | le32_to_cpu(dbg->burst_check)); | 1740 | "burst_check:", |
1402 | pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n", | 1741 | le32_to_cpu(dbg->burst_check), |
1403 | le32_to_cpu(dbg->burst_count)); | 1742 | accum_dbg->burst_check, |
1404 | pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n", | 1743 | delta_dbg->burst_check, max_dbg->burst_check); |
1405 | le32_to_cpu(general->sleep_time)); | 1744 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1406 | pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n", | 1745 | "burst_count:", |
1407 | le32_to_cpu(general->slots_out)); | 1746 | le32_to_cpu(dbg->burst_count), |
1408 | pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n", | 1747 | accum_dbg->burst_count, |
1409 | le32_to_cpu(general->slots_idle)); | 1748 | delta_dbg->burst_count, max_dbg->burst_count); |
1410 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n", | 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", | ||
1411 | le32_to_cpu(general->ttl_timestamp)); | 1765 | le32_to_cpu(general->ttl_timestamp)); |
1412 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n", | 1766 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1413 | le32_to_cpu(div->tx_on_a)); | 1767 | "tx_on_a:", |
1414 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n", | 1768 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, |
1415 | le32_to_cpu(div->tx_on_b)); | 1769 | delta_div->tx_on_a, max_div->tx_on_a); |
1416 | pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n", | 1770 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1417 | le32_to_cpu(div->exec_time)); | 1771 | "tx_on_b:", |
1418 | pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n", | 1772 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, |
1419 | le32_to_cpu(div->probe_time)); | 1773 | delta_div->tx_on_b, max_div->tx_on_b); |
1420 | pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n", | 1774 | pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, |
1421 | le32_to_cpu(general->rx_enable_counter)); | 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); | ||
1422 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1794 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1423 | kfree(buf); | 1795 | kfree(buf); |
1424 | return ret; | 1796 | return ret; |
@@ -1428,7 +1800,7 @@ static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, | |||
1428 | char __user *user_buf, | 1800 | char __user *user_buf, |
1429 | size_t count, loff_t *ppos) { | 1801 | size_t count, loff_t *ppos) { |
1430 | 1802 | ||
1431 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1803 | struct iwl_priv *priv = file->private_data; |
1432 | int pos = 0; | 1804 | int pos = 0; |
1433 | int cnt = 0; | 1805 | int cnt = 0; |
1434 | char *buf; | 1806 | char *buf; |
@@ -1509,7 +1881,7 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, | |||
1509 | char __user *user_buf, | 1881 | char __user *user_buf, |
1510 | size_t count, loff_t *ppos) { | 1882 | size_t count, loff_t *ppos) { |
1511 | 1883 | ||
1512 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1884 | struct iwl_priv *priv = file->private_data; |
1513 | int pos = 0; | 1885 | int pos = 0; |
1514 | int cnt = 0; | 1886 | int cnt = 0; |
1515 | char *buf; | 1887 | char *buf; |
@@ -1567,26 +1939,15 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, | |||
1567 | char __user *user_buf, | 1939 | char __user *user_buf, |
1568 | size_t count, loff_t *ppos) { | 1940 | size_t count, loff_t *ppos) { |
1569 | 1941 | ||
1570 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 1942 | struct iwl_priv *priv = file->private_data; |
1571 | char buf[128]; | 1943 | char buf[128]; |
1572 | int pos = 0; | 1944 | int pos = 0; |
1573 | ssize_t ret; | ||
1574 | const size_t bufsz = sizeof(buf); | 1945 | const size_t bufsz = sizeof(buf); |
1575 | struct statistics_tx *tx; | 1946 | struct statistics_tx *tx; |
1576 | 1947 | ||
1577 | if (!iwl_is_alive(priv)) | 1948 | if (!iwl_is_alive(priv)) |
1578 | pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); | 1949 | pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); |
1579 | else { | 1950 | else { |
1580 | /* make request to uCode to retrieve statistics information */ | ||
1581 | mutex_lock(&priv->mutex); | ||
1582 | ret = iwl_send_statistics_request(priv, 0); | ||
1583 | mutex_unlock(&priv->mutex); | ||
1584 | |||
1585 | if (ret) { | ||
1586 | IWL_ERR(priv, "Error sending statistics request: %zd\n", | ||
1587 | ret); | ||
1588 | return -EAGAIN; | ||
1589 | } | ||
1590 | tx = &priv->statistics.tx; | 1951 | tx = &priv->statistics.tx; |
1591 | if (tx->tx_power.ant_a || | 1952 | if (tx->tx_power.ant_a || |
1592 | tx->tx_power.ant_b || | 1953 | tx->tx_power.ant_b || |
@@ -1614,8 +1975,311 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, | |||
1614 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1975 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1615 | } | 1976 | } |
1616 | 1977 | ||
1617 | DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics); | 1978 | static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, |
1618 | DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics); | 1979 | char __user *user_buf, |
1980 | size_t count, loff_t *ppos) | ||
1981 | { | ||
1982 | struct iwl_priv *priv = file->private_data; | ||
1983 | char buf[60]; | ||
1984 | int pos = 0; | ||
1985 | const size_t bufsz = sizeof(buf); | ||
1986 | u32 pwrsave_status; | ||
1987 | |||
1988 | pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & | ||
1989 | CSR_GP_REG_POWER_SAVE_STATUS_MSK; | ||
1990 | |||
1991 | pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); | ||
1992 | pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | ||
1993 | (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : | ||
1994 | (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : | ||
1995 | (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : | ||
1996 | "error"); | ||
1997 | |||
1998 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1999 | } | ||
2000 | |||
2001 | static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, | ||
2002 | const char __user *user_buf, | ||
2003 | size_t count, loff_t *ppos) | ||
2004 | { | ||
2005 | struct iwl_priv *priv = file->private_data; | ||
2006 | char buf[8]; | ||
2007 | int buf_size; | ||
2008 | int clear; | ||
2009 | |||
2010 | memset(buf, 0, sizeof(buf)); | ||
2011 | buf_size = min(count, sizeof(buf) - 1); | ||
2012 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2013 | return -EFAULT; | ||
2014 | if (sscanf(buf, "%d", &clear) != 1) | ||
2015 | return -EFAULT; | ||
2016 | |||
2017 | /* make request to uCode to retrieve statistics information */ | ||
2018 | mutex_lock(&priv->mutex); | ||
2019 | iwl_send_statistics_request(priv, CMD_SYNC, true); | ||
2020 | mutex_unlock(&priv->mutex); | ||
2021 | |||
2022 | return count; | ||
2023 | } | ||
2024 | |||
2025 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | ||
2026 | const char __user *user_buf, | ||
2027 | size_t count, loff_t *ppos) | ||
2028 | { | ||
2029 | struct iwl_priv *priv = file->private_data; | ||
2030 | char buf[8]; | ||
2031 | int buf_size; | ||
2032 | int csr; | ||
2033 | |||
2034 | memset(buf, 0, sizeof(buf)); | ||
2035 | buf_size = min(count, sizeof(buf) - 1); | ||
2036 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2037 | return -EFAULT; | ||
2038 | if (sscanf(buf, "%d", &csr) != 1) | ||
2039 | return -EFAULT; | ||
2040 | |||
2041 | if (priv->cfg->ops->lib->dump_csr) | ||
2042 | priv->cfg->ops->lib->dump_csr(priv); | ||
2043 | |||
2044 | return count; | ||
2045 | } | ||
2046 | |||
2047 | static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | ||
2048 | char __user *user_buf, | ||
2049 | size_t count, loff_t *ppos) { | ||
2050 | |||
2051 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2052 | int pos = 0; | ||
2053 | char buf[128]; | ||
2054 | const size_t bufsz = sizeof(buf); | ||
2055 | ssize_t ret; | ||
2056 | |||
2057 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | ||
2058 | priv->event_log.ucode_trace ? "On" : "Off"); | ||
2059 | pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", | ||
2060 | priv->event_log.non_wraps_count); | ||
2061 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", | ||
2062 | priv->event_log.wraps_once_count); | ||
2063 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | ||
2064 | priv->event_log.wraps_more_count); | ||
2065 | |||
2066 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2067 | return ret; | ||
2068 | } | ||
2069 | |||
2070 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | ||
2071 | const char __user *user_buf, | ||
2072 | size_t count, loff_t *ppos) | ||
2073 | { | ||
2074 | struct iwl_priv *priv = file->private_data; | ||
2075 | char buf[8]; | ||
2076 | int buf_size; | ||
2077 | int trace; | ||
2078 | |||
2079 | memset(buf, 0, sizeof(buf)); | ||
2080 | buf_size = min(count, sizeof(buf) - 1); | ||
2081 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2082 | return -EFAULT; | ||
2083 | if (sscanf(buf, "%d", &trace) != 1) | ||
2084 | return -EFAULT; | ||
2085 | |||
2086 | if (trace) { | ||
2087 | priv->event_log.ucode_trace = true; | ||
2088 | /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ | ||
2089 | mod_timer(&priv->ucode_trace, | ||
2090 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | ||
2091 | } else { | ||
2092 | priv->event_log.ucode_trace = false; | ||
2093 | del_timer_sync(&priv->ucode_trace); | ||
2094 | } | ||
2095 | |||
2096 | return count; | ||
2097 | } | ||
2098 | |||
2099 | static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | ||
2100 | char __user *user_buf, | ||
2101 | size_t count, loff_t *ppos) | ||
2102 | { | ||
2103 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2104 | char *buf; | ||
2105 | int pos = 0; | ||
2106 | ssize_t ret = -EFAULT; | ||
2107 | |||
2108 | if (priv->cfg->ops->lib->dump_fh) { | ||
2109 | ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); | ||
2110 | if (buf) { | ||
2111 | ret = simple_read_from_buffer(user_buf, | ||
2112 | count, ppos, buf, pos); | ||
2113 | kfree(buf); | ||
2114 | } | ||
2115 | } | ||
2116 | |||
2117 | return ret; | ||
2118 | } | ||
2119 | |||
2120 | static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, | ||
2121 | char __user *user_buf, | ||
2122 | size_t count, loff_t *ppos) { | ||
2123 | |||
2124 | struct iwl_priv *priv = file->private_data; | ||
2125 | int pos = 0; | ||
2126 | char buf[12]; | ||
2127 | const size_t bufsz = sizeof(buf); | ||
2128 | ssize_t ret; | ||
2129 | |||
2130 | pos += scnprintf(buf + pos, bufsz - pos, "%d\n", | ||
2131 | priv->missed_beacon_threshold); | ||
2132 | |||
2133 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2134 | return ret; | ||
2135 | } | ||
2136 | |||
2137 | static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, | ||
2138 | const char __user *user_buf, | ||
2139 | size_t count, loff_t *ppos) | ||
2140 | { | ||
2141 | struct iwl_priv *priv = file->private_data; | ||
2142 | char buf[8]; | ||
2143 | int buf_size; | ||
2144 | int missed; | ||
2145 | |||
2146 | memset(buf, 0, sizeof(buf)); | ||
2147 | buf_size = min(count, sizeof(buf) - 1); | ||
2148 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2149 | return -EFAULT; | ||
2150 | if (sscanf(buf, "%d", &missed) != 1) | ||
2151 | return -EINVAL; | ||
2152 | |||
2153 | if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || | ||
2154 | missed > IWL_MISSED_BEACON_THRESHOLD_MAX) | ||
2155 | priv->missed_beacon_threshold = | ||
2156 | IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
2157 | else | ||
2158 | priv->missed_beacon_threshold = missed; | ||
2159 | |||
2160 | return count; | ||
2161 | } | ||
2162 | |||
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, | ||
2185 | char __user *user_buf, | ||
2186 | size_t count, loff_t *ppos) { | ||
2187 | |||
2188 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
2189 | int pos = 0; | ||
2190 | char buf[12]; | ||
2191 | const size_t bufsz = sizeof(buf); | ||
2192 | ssize_t ret; | ||
2193 | |||
2194 | pos += scnprintf(buf + pos, bufsz - pos, "%u\n", | ||
2195 | priv->cfg->plcp_delta_threshold); | ||
2196 | |||
2197 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2198 | return ret; | ||
2199 | } | ||
2200 | |||
2201 | static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | ||
2202 | const char __user *user_buf, | ||
2203 | size_t count, loff_t *ppos) { | ||
2204 | |||
2205 | struct iwl_priv *priv = file->private_data; | ||
2206 | char buf[8]; | ||
2207 | int buf_size; | ||
2208 | int plcp; | ||
2209 | |||
2210 | memset(buf, 0, sizeof(buf)); | ||
2211 | buf_size = min(count, sizeof(buf) - 1); | ||
2212 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2213 | return -EFAULT; | ||
2214 | if (sscanf(buf, "%d", &plcp) != 1) | ||
2215 | return -EINVAL; | ||
2216 | if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || | ||
2217 | (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) | ||
2218 | priv->cfg->plcp_delta_threshold = | ||
2219 | IWL_MAX_PLCP_ERR_THRESHOLD_DEF; | ||
2220 | else | ||
2221 | priv->cfg->plcp_delta_threshold = plcp; | ||
2222 | return count; | ||
2223 | } | ||
2224 | |||
2225 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | ||
2226 | char __user *user_buf, | ||
2227 | size_t count, loff_t *ppos) { | ||
2228 | |||
2229 | struct iwl_priv *priv = file->private_data; | ||
2230 | int i, pos = 0; | ||
2231 | char buf[300]; | ||
2232 | const size_t bufsz = sizeof(buf); | ||
2233 | struct iwl_force_reset *force_reset; | ||
2234 | |||
2235 | for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { | ||
2236 | force_reset = &priv->force_reset[i]; | ||
2237 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2238 | "Force reset method %d\n", i); | ||
2239 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2240 | "\tnumber of reset request: %d\n", | ||
2241 | force_reset->reset_request_count); | ||
2242 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2243 | "\tnumber of reset request success: %d\n", | ||
2244 | force_reset->reset_success_count); | ||
2245 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2246 | "\tnumber of reset request reject: %d\n", | ||
2247 | force_reset->reset_reject_count); | ||
2248 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2249 | "\treset duration: %lu\n", | ||
2250 | force_reset->reset_duration); | ||
2251 | } | ||
2252 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2253 | } | ||
2254 | |||
2255 | static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | ||
2256 | const char __user *user_buf, | ||
2257 | size_t count, loff_t *ppos) { | ||
2258 | |||
2259 | struct iwl_priv *priv = file->private_data; | ||
2260 | char buf[8]; | ||
2261 | int buf_size; | ||
2262 | int reset, ret; | ||
2263 | |||
2264 | memset(buf, 0, sizeof(buf)); | ||
2265 | buf_size = min(count, sizeof(buf) - 1); | ||
2266 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2267 | return -EFAULT; | ||
2268 | if (sscanf(buf, "%d", &reset) != 1) | ||
2269 | return -EINVAL; | ||
2270 | switch (reset) { | ||
2271 | case IWL_RF_RESET: | ||
2272 | case IWL_FW_RESET: | ||
2273 | ret = iwl_force_reset(priv, reset); | ||
2274 | break; | ||
2275 | default: | ||
2276 | return -EINVAL; | ||
2277 | } | ||
2278 | return ret ? ret : count; | ||
2279 | } | ||
2280 | |||
2281 | DEBUGFS_READ_FILE_OPS(rx_statistics); | ||
2282 | DEBUGFS_READ_FILE_OPS(tx_statistics); | ||
1619 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2283 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
1620 | DEBUGFS_READ_FILE_OPS(rx_queue); | 2284 | DEBUGFS_READ_FILE_OPS(rx_queue); |
1621 | DEBUGFS_READ_FILE_OPS(tx_queue); | 2285 | DEBUGFS_READ_FILE_OPS(tx_queue); |
@@ -1625,6 +2289,16 @@ DEBUGFS_READ_FILE_OPS(ucode_general_stats); | |||
1625 | DEBUGFS_READ_FILE_OPS(sensitivity); | 2289 | DEBUGFS_READ_FILE_OPS(sensitivity); |
1626 | DEBUGFS_READ_FILE_OPS(chain_noise); | 2290 | DEBUGFS_READ_FILE_OPS(chain_noise); |
1627 | DEBUGFS_READ_FILE_OPS(tx_power); | 2291 | DEBUGFS_READ_FILE_OPS(tx_power); |
2292 | DEBUGFS_READ_FILE_OPS(power_save_status); | ||
2293 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | ||
2294 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | ||
2295 | DEBUGFS_WRITE_FILE_OPS(csr); | ||
2296 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | ||
2297 | DEBUGFS_READ_FILE_OPS(fh_reg); | ||
2298 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | ||
2299 | DEBUGFS_WRITE_FILE_OPS(internal_scan); | ||
2300 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | ||
2301 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | ||
1628 | 2302 | ||
1629 | /* | 2303 | /* |
1630 | * Create the debugfs files and directories | 2304 | * Create the debugfs files and directories |
@@ -1632,68 +2306,74 @@ DEBUGFS_READ_FILE_OPS(tx_power); | |||
1632 | */ | 2306 | */ |
1633 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | 2307 | int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) |
1634 | { | 2308 | { |
1635 | struct iwl_debugfs *dbgfs; | ||
1636 | struct dentry *phyd = priv->hw->wiphy->debugfsdir; | 2309 | struct dentry *phyd = priv->hw->wiphy->debugfsdir; |
1637 | int ret = 0; | 2310 | struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; |
1638 | 2311 | ||
1639 | dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); | 2312 | dir_drv = debugfs_create_dir(name, phyd); |
1640 | if (!dbgfs) { | 2313 | if (!dir_drv) |
1641 | ret = -ENOMEM; | 2314 | return -ENOMEM; |
1642 | goto err; | 2315 | |
1643 | } | 2316 | priv->debugfs_dir = dir_drv; |
1644 | 2317 | ||
1645 | priv->dbgfs = dbgfs; | 2318 | dir_data = debugfs_create_dir("data", dir_drv); |
1646 | dbgfs->name = name; | 2319 | if (!dir_data) |
1647 | dbgfs->dir_drv = debugfs_create_dir(name, phyd); | 2320 | goto err; |
1648 | if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { | 2321 | dir_rf = debugfs_create_dir("rf", dir_drv); |
1649 | ret = -ENOENT; | 2322 | if (!dir_rf) |
2323 | goto err; | ||
2324 | dir_debug = debugfs_create_dir("debug", dir_drv); | ||
2325 | if (!dir_debug) | ||
1650 | goto err; | 2326 | goto err; |
1651 | } | ||
1652 | 2327 | ||
1653 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); | 2328 | DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); |
1654 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); | 2329 | DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); |
1655 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); | 2330 | DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); |
1656 | DEBUGFS_ADD_FILE(nvm, data); | 2331 | DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); |
1657 | DEBUGFS_ADD_FILE(sram, data); | 2332 | DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); |
1658 | DEBUGFS_ADD_FILE(log_event, data); | 2333 | DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); |
1659 | DEBUGFS_ADD_FILE(stations, data); | 2334 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); |
1660 | DEBUGFS_ADD_FILE(channels, data); | 2335 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); |
1661 | DEBUGFS_ADD_FILE(status, data); | 2336 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); |
1662 | DEBUGFS_ADD_FILE(interrupt, data); | 2337 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); |
1663 | DEBUGFS_ADD_FILE(qos, data); | 2338 | DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); |
1664 | #ifdef CONFIG_IWLWIFI_LEDS | 2339 | DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); |
1665 | DEBUGFS_ADD_FILE(led, data); | 2340 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); |
1666 | #endif | 2341 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); |
1667 | DEBUGFS_ADD_FILE(sleep_level_override, data); | 2342 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); |
1668 | DEBUGFS_ADD_FILE(current_sleep_command, data); | 2343 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); |
1669 | DEBUGFS_ADD_FILE(thermal_throttling, data); | 2344 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); |
1670 | DEBUGFS_ADD_FILE(disable_ht40, data); | 2345 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); |
1671 | DEBUGFS_ADD_FILE(rx_statistics, debug); | 2346 | DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR); |
1672 | DEBUGFS_ADD_FILE(tx_statistics, debug); | 2347 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); |
1673 | DEBUGFS_ADD_FILE(traffic_log, debug); | 2348 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); |
1674 | DEBUGFS_ADD_FILE(rx_queue, debug); | 2349 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); |
1675 | DEBUGFS_ADD_FILE(tx_queue, debug); | 2350 | DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); |
1676 | DEBUGFS_ADD_FILE(tx_power, debug); | 2351 | DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); |
2352 | 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); | ||
2355 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | ||
1677 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2356 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1678 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug); | 2357 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); |
1679 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug); | 2358 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
1680 | DEBUGFS_ADD_FILE(ucode_general_stats, debug); | 2359 | DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); |
1681 | DEBUGFS_ADD_FILE(sensitivity, debug); | 2360 | DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); |
1682 | DEBUGFS_ADD_FILE(chain_noise, debug); | 2361 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
2362 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | ||
1683 | } | 2363 | } |
1684 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 2364 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); |
1685 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 2365 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
1686 | &priv->disable_chain_noise_cal); | 2366 | &priv->disable_chain_noise_cal); |
1687 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || | 2367 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || |
1688 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) | 2368 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) |
1689 | DEBUGFS_ADD_BOOL(disable_tx_power, rf, | 2369 | DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, |
1690 | &priv->disable_tx_power_cal); | 2370 | &priv->disable_tx_power_cal); |
1691 | return 0; | 2371 | return 0; |
1692 | 2372 | ||
1693 | err: | 2373 | err: |
1694 | IWL_ERR(priv, "Can't open the debugfs directory\n"); | 2374 | IWL_ERR(priv, "Can't create the debugfs directory\n"); |
1695 | iwl_dbgfs_unregister(priv); | 2375 | iwl_dbgfs_unregister(priv); |
1696 | return ret; | 2376 | return -ENOMEM; |
1697 | } | 2377 | } |
1698 | EXPORT_SYMBOL(iwl_dbgfs_register); | 2378 | EXPORT_SYMBOL(iwl_dbgfs_register); |
1699 | 2379 | ||
@@ -1703,53 +2383,11 @@ EXPORT_SYMBOL(iwl_dbgfs_register); | |||
1703 | */ | 2383 | */ |
1704 | void iwl_dbgfs_unregister(struct iwl_priv *priv) | 2384 | void iwl_dbgfs_unregister(struct iwl_priv *priv) |
1705 | { | 2385 | { |
1706 | if (!priv->dbgfs) | 2386 | if (!priv->debugfs_dir) |
1707 | return; | 2387 | return; |
1708 | 2388 | ||
1709 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override); | 2389 | debugfs_remove_recursive(priv->debugfs_dir); |
1710 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command); | 2390 | priv->debugfs_dir = NULL; |
1711 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); | ||
1712 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); | ||
1713 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); | ||
1714 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); | ||
1715 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); | ||
1716 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); | ||
1717 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); | ||
1718 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); | ||
1719 | #ifdef CONFIG_IWLWIFI_LEDS | ||
1720 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); | ||
1721 | #endif | ||
1722 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); | ||
1723 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); | ||
1724 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); | ||
1725 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics); | ||
1726 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics); | ||
1727 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log); | ||
1728 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue); | ||
1729 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); | ||
1730 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); | ||
1731 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | ||
1732 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1733 | file_ucode_rx_stats); | ||
1734 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1735 | file_ucode_tx_stats); | ||
1736 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1737 | file_ucode_general_stats); | ||
1738 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1739 | file_sensitivity); | ||
1740 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1741 | file_chain_noise); | ||
1742 | } | ||
1743 | DEBUGFS_REMOVE(priv->dbgfs->dir_debug); | ||
1744 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); | ||
1745 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); | ||
1746 | if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || | ||
1747 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) | ||
1748 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power); | ||
1749 | DEBUGFS_REMOVE(priv->dbgfs->dir_rf); | ||
1750 | DEBUGFS_REMOVE(priv->dbgfs->dir_drv); | ||
1751 | kfree(priv->dbgfs); | ||
1752 | priv->dbgfs = NULL; | ||
1753 | } | 2391 | } |
1754 | EXPORT_SYMBOL(iwl_dbgfs_unregister); | 2392 | EXPORT_SYMBOL(iwl_dbgfs_unregister); |
1755 | 2393 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 028d50599550..ef1720a852e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -43,7 +43,6 @@ | |||
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-3945-led.h" | ||
47 | #include "iwl-led.h" | 46 | #include "iwl-led.h" |
48 | #include "iwl-power.h" | 47 | #include "iwl-power.h" |
49 | #include "iwl-agn-rs.h" | 48 | #include "iwl-agn-rs.h" |
@@ -53,21 +52,23 @@ extern struct iwl_cfg iwl4965_agn_cfg; | |||
53 | extern struct iwl_cfg iwl5300_agn_cfg; | 52 | extern struct iwl_cfg iwl5300_agn_cfg; |
54 | extern struct iwl_cfg iwl5100_agn_cfg; | 53 | extern struct iwl_cfg iwl5100_agn_cfg; |
55 | extern struct iwl_cfg iwl5350_agn_cfg; | 54 | extern struct iwl_cfg iwl5350_agn_cfg; |
56 | extern struct iwl_cfg iwl5100_bg_cfg; | 55 | extern struct iwl_cfg iwl5100_bgn_cfg; |
57 | extern struct iwl_cfg iwl5100_abg_cfg; | 56 | extern struct iwl_cfg iwl5100_abg_cfg; |
58 | extern struct iwl_cfg iwl5150_agn_cfg; | 57 | extern struct iwl_cfg iwl5150_agn_cfg; |
59 | extern struct iwl_cfg iwl6000h_2agn_cfg; | 58 | extern struct iwl_cfg iwl5150_abg_cfg; |
60 | extern struct iwl_cfg iwl6000i_2agn_cfg; | 59 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
60 | extern struct iwl_cfg iwl6000i_2abg_cfg; | ||
61 | extern struct iwl_cfg iwl6000i_2bg_cfg; | ||
61 | extern struct iwl_cfg iwl6000_3agn_cfg; | 62 | extern struct iwl_cfg iwl6000_3agn_cfg; |
62 | extern struct iwl_cfg iwl6050_2agn_cfg; | 63 | extern struct iwl_cfg iwl6050_2agn_cfg; |
63 | extern struct iwl_cfg iwl6050_3agn_cfg; | 64 | extern struct iwl_cfg iwl6050_2abg_cfg; |
64 | extern struct iwl_cfg iwl1000_bgn_cfg; | 65 | extern struct iwl_cfg iwl1000_bgn_cfg; |
66 | extern struct iwl_cfg iwl1000_bg_cfg; | ||
65 | 67 | ||
66 | struct iwl_tx_queue; | 68 | struct iwl_tx_queue; |
67 | 69 | ||
68 | /* shared structures from iwl-5000.c */ | 70 | /* shared structures from iwl-5000.c */ |
69 | extern struct iwl_mod_params iwl50_mod_params; | 71 | extern struct iwl_mod_params iwl50_mod_params; |
70 | extern struct iwl_ops iwl5000_ops; | ||
71 | extern struct iwl_ucode_ops iwl5000_ucode; | 72 | extern struct iwl_ucode_ops iwl5000_ucode; |
72 | extern struct iwl_lib_ops iwl5000_lib; | 73 | extern struct iwl_lib_ops iwl5000_lib; |
73 | extern struct iwl_hcmd_ops iwl5000_hcmd; | 74 | extern struct iwl_hcmd_ops iwl5000_hcmd; |
@@ -81,9 +82,6 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | |||
81 | __le32 *tx_flags); | 82 | __le32 *tx_flags); |
82 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, | 83 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, |
83 | struct iwl_rx_phy_res *rx_resp); | 84 | struct iwl_rx_phy_res *rx_resp); |
84 | extern int iwl5000_apm_init(struct iwl_priv *priv); | ||
85 | extern void iwl5000_apm_stop(struct iwl_priv *priv); | ||
86 | extern int iwl5000_apm_reset(struct iwl_priv *priv); | ||
87 | extern void iwl5000_nic_config(struct iwl_priv *priv); | 85 | extern void iwl5000_nic_config(struct iwl_priv *priv); |
88 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); | 86 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); |
89 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | 87 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, |
@@ -144,12 +142,13 @@ extern void iwl5000_temperature(struct iwl_priv *priv); | |||
144 | #define DEFAULT_LONG_RETRY_LIMIT 4U | 142 | #define DEFAULT_LONG_RETRY_LIMIT 4U |
145 | 143 | ||
146 | struct iwl_rx_mem_buffer { | 144 | struct iwl_rx_mem_buffer { |
147 | dma_addr_t real_dma_addr; | 145 | dma_addr_t page_dma; |
148 | dma_addr_t aligned_dma_addr; | 146 | struct page *page; |
149 | struct sk_buff *skb; | ||
150 | struct list_head list; | 147 | struct list_head list; |
151 | }; | 148 | }; |
152 | 149 | ||
150 | #define rxb_addr(r) page_address(r->page) | ||
151 | |||
153 | /* defined below */ | 152 | /* defined below */ |
154 | struct iwl_device_cmd; | 153 | struct iwl_device_cmd; |
155 | 154 | ||
@@ -165,7 +164,7 @@ struct iwl_cmd_meta { | |||
165 | */ | 164 | */ |
166 | void (*callback)(struct iwl_priv *priv, | 165 | void (*callback)(struct iwl_priv *priv, |
167 | struct iwl_device_cmd *cmd, | 166 | struct iwl_device_cmd *cmd, |
168 | struct sk_buff *skb); | 167 | struct iwl_rx_packet *pkt); |
169 | 168 | ||
170 | /* The CMD_SIZE_HUGE flag bit indicates that the command | 169 | /* The CMD_SIZE_HUGE flag bit indicates that the command |
171 | * structure is stored at the end of the shared queue memory. */ | 170 | * structure is stored at the end of the shared queue memory. */ |
@@ -293,9 +292,6 @@ struct iwl_channel_info { | |||
293 | 292 | ||
294 | /* HT40 channel info */ | 293 | /* HT40 channel info */ |
295 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | 294 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ |
296 | s8 ht40_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ | ||
297 | s8 ht40_min_power; /* always 0 */ | ||
298 | s8 ht40_scan_power; /* (dBm) eeprom, direct scans, any rate */ | ||
299 | u8 ht40_flags; /* flags copied from EEPROM */ | 295 | u8 ht40_flags; /* flags copied from EEPROM */ |
300 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ | 296 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ |
301 | 297 | ||
@@ -321,6 +317,13 @@ struct iwl_channel_info { | |||
321 | * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ | 317 | * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ |
322 | #define IWL_MIN_NUM_QUEUES 10 | 318 | #define IWL_MIN_NUM_QUEUES 10 |
323 | 319 | ||
320 | /* | ||
321 | * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00, | ||
322 | * the driver maps it into the appropriate device FIFO for the | ||
323 | * uCode. | ||
324 | */ | ||
325 | #define IWL_CMD_QUEUE_NUM 4 | ||
326 | |||
324 | /* Power management (not Tx power) structures */ | 327 | /* Power management (not Tx power) structures */ |
325 | 328 | ||
326 | enum iwl_pwr_src { | 329 | enum iwl_pwr_src { |
@@ -356,7 +359,14 @@ enum { | |||
356 | CMD_WANT_SKB = (1 << 2), | 359 | CMD_WANT_SKB = (1 << 2), |
357 | }; | 360 | }; |
358 | 361 | ||
359 | #define IWL_CMD_MAX_PAYLOAD 320 | 362 | #define DEF_CMD_PAYLOAD_SIZE 320 |
363 | |||
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 | ||
360 | 370 | ||
361 | /** | 371 | /** |
362 | * struct iwl_device_cmd | 372 | * struct iwl_device_cmd |
@@ -373,7 +383,8 @@ struct iwl_device_cmd { | |||
373 | u16 val16; | 383 | u16 val16; |
374 | u32 val32; | 384 | u32 val32; |
375 | struct iwl_tx_cmd tx; | 385 | struct iwl_tx_cmd tx; |
376 | u8 payload[IWL_CMD_MAX_PAYLOAD]; | 386 | struct iwl6000_channel_switch_cmd chswitch; |
387 | u8 payload[DEF_CMD_PAYLOAD_SIZE]; | ||
377 | } __attribute__ ((packed)) cmd; | 388 | } __attribute__ ((packed)) cmd; |
378 | } __attribute__ ((packed)); | 389 | } __attribute__ ((packed)); |
379 | 390 | ||
@@ -382,21 +393,15 @@ struct iwl_device_cmd { | |||
382 | 393 | ||
383 | struct iwl_host_cmd { | 394 | struct iwl_host_cmd { |
384 | const void *data; | 395 | const void *data; |
385 | struct sk_buff *reply_skb; | 396 | unsigned long reply_page; |
386 | void (*callback)(struct iwl_priv *priv, | 397 | void (*callback)(struct iwl_priv *priv, |
387 | struct iwl_device_cmd *cmd, | 398 | struct iwl_device_cmd *cmd, |
388 | struct sk_buff *skb); | 399 | struct iwl_rx_packet *pkt); |
389 | u32 flags; | 400 | u32 flags; |
390 | u16 len; | 401 | u16 len; |
391 | u8 id; | 402 | u8 id; |
392 | }; | 403 | }; |
393 | 404 | ||
394 | /* | ||
395 | * RX related structures and functions | ||
396 | */ | ||
397 | #define RX_FREE_BUFFERS 64 | ||
398 | #define RX_LOW_WATERMARK 8 | ||
399 | |||
400 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | 405 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 |
401 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | 406 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 |
402 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | 407 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 |
@@ -502,12 +507,12 @@ union iwl_ht_rate_supp { | |||
502 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | 507 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) |
503 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | 508 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC |
504 | 509 | ||
505 | struct iwl_ht_info { | 510 | struct iwl_ht_config { |
506 | /* self configuration data */ | 511 | /* self configuration data */ |
507 | u8 is_ht; | 512 | bool is_ht; |
508 | u8 supported_chan_width; | 513 | bool is_40mhz; |
509 | u8 sm_ps; | 514 | bool single_chain_sufficient; |
510 | struct ieee80211_mcs_info mcs; | 515 | enum ieee80211_smps_mode smps; /* current smps mode */ |
511 | /* BSS related data */ | 516 | /* BSS related data */ |
512 | u8 extension_chan_offset; | 517 | u8 extension_chan_offset; |
513 | u8 ht_protection; | 518 | u8 ht_protection; |
@@ -541,26 +546,27 @@ struct iwl_qos_info { | |||
541 | struct iwl_qosparam_cmd def_qos_parm; | 546 | struct iwl_qosparam_cmd def_qos_parm; |
542 | }; | 547 | }; |
543 | 548 | ||
544 | #define STA_PS_STATUS_WAKE 0 | ||
545 | #define STA_PS_STATUS_SLEEP 1 | ||
546 | |||
547 | |||
548 | struct iwl3945_station_entry { | ||
549 | struct iwl3945_addsta_cmd sta; | ||
550 | struct iwl_tid_data tid[MAX_TID_COUNT]; | ||
551 | u8 used; | ||
552 | u8 ps_status; | ||
553 | struct iwl_hw_key keyinfo; | ||
554 | }; | ||
555 | |||
556 | struct iwl_station_entry { | 549 | struct iwl_station_entry { |
557 | struct iwl_addsta_cmd sta; | 550 | struct iwl_addsta_cmd sta; |
558 | struct iwl_tid_data tid[MAX_TID_COUNT]; | 551 | struct iwl_tid_data tid[MAX_TID_COUNT]; |
559 | u8 used; | 552 | u8 used; |
560 | u8 ps_status; | ||
561 | struct iwl_hw_key keyinfo; | 553 | struct iwl_hw_key keyinfo; |
562 | }; | 554 | }; |
563 | 555 | ||
556 | /* | ||
557 | * iwl_station_priv: Driver's private station information | ||
558 | * | ||
559 | * 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 | ||
561 | * space. | ||
562 | */ | ||
563 | struct iwl_station_priv { | ||
564 | struct iwl_lq_sta lq_sta; | ||
565 | atomic_t pending_frames; | ||
566 | bool client; | ||
567 | bool asleep; | ||
568 | }; | ||
569 | |||
564 | /* one for each uCode image (inst/data, boot/init/runtime) */ | 570 | /* one for each uCode image (inst/data, boot/init/runtime) */ |
565 | struct fw_desc { | 571 | struct fw_desc { |
566 | void *v_addr; /* access by driver */ | 572 | void *v_addr; /* access by driver */ |
@@ -622,6 +628,10 @@ struct iwl_sensitivity_ranges { | |||
622 | u16 auto_corr_max_cck_mrc; | 628 | u16 auto_corr_max_cck_mrc; |
623 | u16 auto_corr_min_cck; | 629 | u16 auto_corr_min_cck; |
624 | u16 auto_corr_min_cck_mrc; | 630 | u16 auto_corr_min_cck_mrc; |
631 | |||
632 | u16 barker_corr_th_min; | ||
633 | u16 barker_corr_th_min_mrc; | ||
634 | u16 nrg_th_cca; | ||
625 | }; | 635 | }; |
626 | 636 | ||
627 | 637 | ||
@@ -639,7 +649,7 @@ struct iwl_sensitivity_ranges { | |||
639 | * @valid_tx/rx_ant: usable antennas | 649 | * @valid_tx/rx_ant: usable antennas |
640 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) | 650 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) |
641 | * @max_rxq_log: Log-base-2 of max_rxq_size | 651 | * @max_rxq_log: Log-base-2 of max_rxq_size |
642 | * @rx_buf_size: Rx buffer size | 652 | * @rx_page_order: Rx buffer page order |
643 | * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR | 653 | * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR |
644 | * @max_stations: | 654 | * @max_stations: |
645 | * @bcast_sta_id: | 655 | * @bcast_sta_id: |
@@ -662,9 +672,8 @@ struct iwl_hw_params { | |||
662 | u8 valid_rx_ant; | 672 | u8 valid_rx_ant; |
663 | u16 max_rxq_size; | 673 | u16 max_rxq_size; |
664 | u16 max_rxq_log; | 674 | u16 max_rxq_log; |
665 | u32 rx_buf_size; | 675 | u32 rx_page_order; |
666 | u32 rx_wrt_ptr_reg; | 676 | u32 rx_wrt_ptr_reg; |
667 | u32 max_pkt_size; | ||
668 | u8 max_stations; | 677 | u8 max_stations; |
669 | u8 bcast_sta_id; | 678 | u8 bcast_sta_id; |
670 | u8 ht40_channel; | 679 | u8 ht40_channel; |
@@ -703,7 +712,7 @@ extern void iwl_txq_ctx_stop(struct iwl_priv *priv); | |||
703 | extern int iwl_queue_space(const struct iwl_queue *q); | 712 | extern int iwl_queue_space(const struct iwl_queue *q); |
704 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) | 713 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) |
705 | { | 714 | { |
706 | return q->write_ptr > q->read_ptr ? | 715 | return q->write_ptr >= q->read_ptr ? |
707 | (i >= q->read_ptr && i < q->write_ptr) : | 716 | (i >= q->read_ptr && i < q->write_ptr) : |
708 | !(i < q->read_ptr && i >= q->write_ptr); | 717 | !(i < q->read_ptr && i >= q->write_ptr); |
709 | } | 718 | } |
@@ -711,7 +720,11 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i) | |||
711 | 720 | ||
712 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | 721 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) |
713 | { | 722 | { |
714 | /* This is for scan command, the big buffer at end of command array */ | 723 | /* |
724 | * This is for init calibration result and scan command which | ||
725 | * required buffer > TFD_MAX_PAYLOAD_SIZE, | ||
726 | * the big buffer at end of command array | ||
727 | */ | ||
715 | if (is_huge) | 728 | if (is_huge) |
716 | return q->n_window; /* must be power of 2 */ | 729 | return q->n_window; /* must be power of 2 */ |
717 | 730 | ||
@@ -726,9 +739,6 @@ struct iwl_dma_ptr { | |||
726 | size_t size; | 739 | size_t size; |
727 | }; | 740 | }; |
728 | 741 | ||
729 | #define IWL_CHANNEL_WIDTH_20MHZ 0 | ||
730 | #define IWL_CHANNEL_WIDTH_40MHZ 1 | ||
731 | |||
732 | #define IWL_OPERATION_MODE_AUTO 0 | 742 | #define IWL_OPERATION_MODE_AUTO 0 |
733 | #define IWL_OPERATION_MODE_HT_ONLY 1 | 743 | #define IWL_OPERATION_MODE_HT_ONLY 1 |
734 | #define IWL_OPERATION_MODE_MIXED 2 | 744 | #define IWL_OPERATION_MODE_MIXED 2 |
@@ -741,7 +751,8 @@ struct iwl_dma_ptr { | |||
741 | 751 | ||
742 | /* Sensitivity and chain noise calibration */ | 752 | /* Sensitivity and chain noise calibration */ |
743 | #define INITIALIZATION_VALUE 0xFFFF | 753 | #define INITIALIZATION_VALUE 0xFFFF |
744 | #define CAL_NUM_OF_BEACONS 20 | 754 | #define IWL4965_CAL_NUM_BEACONS 20 |
755 | #define IWL_CAL_NUM_BEACONS 16 | ||
745 | #define MAXIMUM_ALLOWED_PATHLOSS 15 | 756 | #define MAXIMUM_ALLOWED_PATHLOSS 15 |
746 | 757 | ||
747 | #define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3 | 758 | #define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3 |
@@ -845,6 +856,10 @@ struct iwl_sensitivity_data { | |||
845 | s32 nrg_auto_corr_silence_diff; | 856 | s32 nrg_auto_corr_silence_diff; |
846 | u32 num_in_cck_no_fa; | 857 | u32 num_in_cck_no_fa; |
847 | u32 nrg_th_ofdm; | 858 | u32 nrg_th_ofdm; |
859 | |||
860 | u16 barker_corr_th_min; | ||
861 | u16 barker_corr_th_min_mrc; | ||
862 | u16 nrg_th_cca; | ||
848 | }; | 863 | }; |
849 | 864 | ||
850 | /* Chain noise (differential Rx gain) calib data */ | 865 | /* Chain noise (differential Rx gain) calib data */ |
@@ -894,13 +909,11 @@ enum iwl_access_mode { | |||
894 | /** | 909 | /** |
895 | * enum iwl_pa_type - Power Amplifier type | 910 | * enum iwl_pa_type - Power Amplifier type |
896 | * @IWL_PA_SYSTEM: based on uCode configuration | 911 | * @IWL_PA_SYSTEM: based on uCode configuration |
897 | * @IWL_PA_HYBRID: use both Internal and external PA | ||
898 | * @IWL_PA_INTERNAL: use Internal only | 912 | * @IWL_PA_INTERNAL: use Internal only |
899 | */ | 913 | */ |
900 | enum iwl_pa_type { | 914 | enum iwl_pa_type { |
901 | IWL_PA_SYSTEM = 0, | 915 | IWL_PA_SYSTEM = 0, |
902 | IWL_PA_HYBRID = 1, | 916 | IWL_PA_INTERNAL = 1, |
903 | IWL_PA_INTERNAL = 2, | ||
904 | }; | 917 | }; |
905 | 918 | ||
906 | /* interrupt statistics */ | 919 | /* interrupt statistics */ |
@@ -961,7 +974,84 @@ struct traffic_stats { | |||
961 | }; | 974 | }; |
962 | #endif | 975 | #endif |
963 | 976 | ||
964 | #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ | 977 | /* |
978 | * iwl_switch_rxon: "channel switch" structure | ||
979 | * | ||
980 | * @ switch_in_progress: channel switch in progress | ||
981 | * @ channel: new channel | ||
982 | */ | ||
983 | struct iwl_switch_rxon { | ||
984 | bool switch_in_progress; | ||
985 | __le16 channel; | ||
986 | }; | ||
987 | |||
988 | /* | ||
989 | * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds | ||
990 | * to perform continuous uCode event logging operation if enabled | ||
991 | */ | ||
992 | #define UCODE_TRACE_PERIOD (100) | ||
993 | |||
994 | /* | ||
995 | * iwl_event_log: current uCode event log position | ||
996 | * | ||
997 | * @ucode_trace: enable/disable ucode continuous trace timer | ||
998 | * @num_wraps: how many times the event buffer wraps | ||
999 | * @next_entry: the entry just before the next one that uCode would fill | ||
1000 | * @non_wraps_count: counter for no wrap detected when dump ucode events | ||
1001 | * @wraps_once_count: counter for wrap once detected when dump ucode events | ||
1002 | * @wraps_more_count: counter for wrap more than once detected | ||
1003 | * when dump ucode events | ||
1004 | */ | ||
1005 | struct iwl_event_log { | ||
1006 | bool ucode_trace; | ||
1007 | u32 num_wraps; | ||
1008 | u32 next_entry; | ||
1009 | int non_wraps_count; | ||
1010 | int wraps_once_count; | ||
1011 | int wraps_more_count; | ||
1012 | }; | ||
1013 | |||
1014 | /* | ||
1015 | * host interrupt timeout value | ||
1016 | * used with setting interrupt coalescing timer | ||
1017 | * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit | ||
1018 | * | ||
1019 | * default interrupt coalescing timer is 64 x 32 = 2048 usecs | ||
1020 | * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs | ||
1021 | */ | ||
1022 | #define IWL_HOST_INT_TIMEOUT_MAX (0xFF) | ||
1023 | #define IWL_HOST_INT_TIMEOUT_DEF (0x40) | ||
1024 | #define IWL_HOST_INT_TIMEOUT_MIN (0x0) | ||
1025 | #define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) | ||
1026 | #define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) | ||
1027 | #define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) | ||
1028 | |||
1029 | /* | ||
1030 | * This is the threshold value of plcp error rate per 100mSecs. It is | ||
1031 | * used to set and check for the validity of plcp_delta. | ||
1032 | */ | ||
1033 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) | ||
1034 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) | ||
1035 | #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) | ||
1036 | #define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200) | ||
1037 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) | ||
1038 | |||
1039 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) | ||
1040 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) | ||
1041 | |||
1042 | enum iwl_reset { | ||
1043 | IWL_RF_RESET = 0, | ||
1044 | IWL_FW_RESET, | ||
1045 | IWL_MAX_FORCE_RESET, | ||
1046 | }; | ||
1047 | |||
1048 | struct iwl_force_reset { | ||
1049 | int reset_request_count; | ||
1050 | int reset_success_count; | ||
1051 | int reset_reject_count; | ||
1052 | unsigned long reset_duration; | ||
1053 | unsigned long last_force_reset_jiffies; | ||
1054 | }; | ||
965 | 1055 | ||
966 | struct iwl_priv { | 1056 | struct iwl_priv { |
967 | 1057 | ||
@@ -976,20 +1066,26 @@ struct iwl_priv { | |||
976 | int frames_count; | 1066 | int frames_count; |
977 | 1067 | ||
978 | enum ieee80211_band band; | 1068 | enum ieee80211_band band; |
979 | int alloc_rxb_skb; | 1069 | int alloc_rxb_page; |
980 | 1070 | ||
981 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, | 1071 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, |
982 | struct iwl_rx_mem_buffer *rxb); | 1072 | struct iwl_rx_mem_buffer *rxb); |
983 | 1073 | ||
984 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 1074 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
985 | 1075 | ||
986 | #if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT) | ||
987 | /* spectrum measurement report caching */ | 1076 | /* spectrum measurement report caching */ |
988 | struct iwl_spectrum_notification measure_report; | 1077 | struct iwl_spectrum_notification measure_report; |
989 | u8 measurement_status; | 1078 | u8 measurement_status; |
990 | #endif | 1079 | |
991 | /* ucode beacon time */ | 1080 | /* ucode beacon time */ |
992 | u32 ucode_beacon_time; | 1081 | u32 ucode_beacon_time; |
1082 | int missed_beacon_threshold; | ||
1083 | |||
1084 | /* storing the jiffies when the plcp error rate is received */ | ||
1085 | unsigned long plcp_jiffies; | ||
1086 | |||
1087 | /* force reset */ | ||
1088 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | ||
993 | 1089 | ||
994 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. | 1090 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. |
995 | * Access via channel # using indirect index array */ | 1091 | * Access via channel # using indirect index array */ |
@@ -1008,7 +1104,6 @@ struct iwl_priv { | |||
1008 | struct iwl_calib_result calib_results[IWL_CALIB_MAX]; | 1104 | struct iwl_calib_result calib_results[IWL_CALIB_MAX]; |
1009 | 1105 | ||
1010 | /* Scan related variables */ | 1106 | /* Scan related variables */ |
1011 | unsigned long last_scan_jiffies; | ||
1012 | unsigned long next_scan_jiffies; | 1107 | unsigned long next_scan_jiffies; |
1013 | unsigned long scan_start; | 1108 | unsigned long scan_start; |
1014 | unsigned long scan_pass_start; | 1109 | unsigned long scan_pass_start; |
@@ -1016,6 +1111,7 @@ struct iwl_priv { | |||
1016 | void *scan; | 1111 | void *scan; |
1017 | int scan_bands; | 1112 | int scan_bands; |
1018 | struct cfg80211_scan_request *scan_request; | 1113 | struct cfg80211_scan_request *scan_request; |
1114 | bool is_internal_short_scan; | ||
1019 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; | 1115 | u8 scan_tx_ant[IEEE80211_NUM_BANDS]; |
1020 | u8 mgmt_tx_ant; | 1116 | u8 mgmt_tx_ant; |
1021 | 1117 | ||
@@ -1024,6 +1120,7 @@ struct iwl_priv { | |||
1024 | spinlock_t hcmd_lock; /* protect hcmd */ | 1120 | spinlock_t hcmd_lock; /* protect hcmd */ |
1025 | spinlock_t reg_lock; /* protect hw register access */ | 1121 | spinlock_t reg_lock; /* protect hw register access */ |
1026 | struct mutex mutex; | 1122 | struct mutex mutex; |
1123 | struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ | ||
1027 | 1124 | ||
1028 | /* basic pci-network driver stuff */ | 1125 | /* basic pci-network driver stuff */ |
1029 | struct pci_dev *pci_dev; | 1126 | struct pci_dev *pci_dev; |
@@ -1035,6 +1132,7 @@ struct iwl_priv { | |||
1035 | u8 rev_id; | 1132 | u8 rev_id; |
1036 | 1133 | ||
1037 | /* uCode images, save to reload in case of failure */ | 1134 | /* uCode images, save to reload in case of failure */ |
1135 | int fw_index; /* firmware we're trying to load */ | ||
1038 | u32 ucode_ver; /* version of ucode, copy of | 1136 | u32 ucode_ver; /* version of ucode, copy of |
1039 | iwl_ucode.ver */ | 1137 | iwl_ucode.ver */ |
1040 | struct fw_desc ucode_code; /* runtime inst */ | 1138 | struct fw_desc ucode_code; /* runtime inst */ |
@@ -1045,6 +1143,7 @@ struct iwl_priv { | |||
1045 | struct fw_desc ucode_boot; /* bootstrap inst */ | 1143 | struct fw_desc ucode_boot; /* bootstrap inst */ |
1046 | enum ucode_type ucode_type; | 1144 | enum ucode_type ucode_type; |
1047 | u8 ucode_write_complete; /* the image write is complete */ | 1145 | u8 ucode_write_complete; /* the image write is complete */ |
1146 | char firmware_name[25]; | ||
1048 | 1147 | ||
1049 | 1148 | ||
1050 | struct iwl_rxon_time_cmd rxon_timing; | 1149 | struct iwl_rxon_time_cmd rxon_timing; |
@@ -1056,21 +1155,18 @@ struct iwl_priv { | |||
1056 | const struct iwl_rxon_cmd active_rxon; | 1155 | const struct iwl_rxon_cmd active_rxon; |
1057 | struct iwl_rxon_cmd staging_rxon; | 1156 | struct iwl_rxon_cmd staging_rxon; |
1058 | 1157 | ||
1059 | struct iwl_rxon_cmd recovery_rxon; | 1158 | struct iwl_switch_rxon switch_rxon; |
1060 | 1159 | ||
1061 | /* 1st responses from initialize and runtime uCode images. | 1160 | /* 1st responses from initialize and runtime uCode images. |
1062 | * 4965's initialize alive response contains some calibration data. */ | 1161 | * 4965's initialize alive response contains some calibration data. */ |
1063 | struct iwl_init_alive_resp card_alive_init; | 1162 | struct iwl_init_alive_resp card_alive_init; |
1064 | struct iwl_alive_resp card_alive; | 1163 | struct iwl_alive_resp card_alive; |
1065 | 1164 | ||
1066 | #ifdef CONFIG_IWLWIFI_LEDS | ||
1067 | unsigned long last_blink_time; | 1165 | unsigned long last_blink_time; |
1068 | u8 last_blink_rate; | 1166 | u8 last_blink_rate; |
1069 | u8 allow_blinking; | 1167 | u8 allow_blinking; |
1070 | u64 led_tpt; | 1168 | u64 led_tpt; |
1071 | struct iwl_led led[IWL_LED_TRG_MAX]; | 1169 | |
1072 | unsigned int rxtxpackets; | ||
1073 | #endif | ||
1074 | u16 active_rate; | 1170 | u16 active_rate; |
1075 | u16 active_rate_basic; | 1171 | u16 active_rate_basic; |
1076 | 1172 | ||
@@ -1080,11 +1176,10 @@ struct iwl_priv { | |||
1080 | struct iwl_chain_noise_data chain_noise_data; | 1176 | struct iwl_chain_noise_data chain_noise_data; |
1081 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; | 1177 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; |
1082 | 1178 | ||
1083 | struct iwl_ht_info current_ht_config; | 1179 | struct iwl_ht_config current_ht_config; |
1084 | u8 last_phy_res[100]; | 1180 | u8 last_phy_res[100]; |
1085 | 1181 | ||
1086 | /* Rate scaling data */ | 1182 | /* Rate scaling data */ |
1087 | s8 data_retry_limit; | ||
1088 | u8 retry_rate; | 1183 | u8 retry_rate; |
1089 | 1184 | ||
1090 | wait_queue_head_t wait_command_queue; | 1185 | wait_queue_head_t wait_command_queue; |
@@ -1093,7 +1188,7 @@ struct iwl_priv { | |||
1093 | 1188 | ||
1094 | /* Rx and Tx DMA processing queues */ | 1189 | /* Rx and Tx DMA processing queues */ |
1095 | struct iwl_rx_queue rxq; | 1190 | struct iwl_rx_queue rxq; |
1096 | struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES]; | 1191 | struct iwl_tx_queue *txq; |
1097 | unsigned long txq_ctx_active_msk; | 1192 | unsigned long txq_ctx_active_msk; |
1098 | struct iwl_dma_ptr kw; /* keep warm address */ | 1193 | struct iwl_dma_ptr kw; /* keep warm address */ |
1099 | struct iwl_dma_ptr scd_bc_tbls; | 1194 | struct iwl_dma_ptr scd_bc_tbls; |
@@ -1116,7 +1211,11 @@ struct iwl_priv { | |||
1116 | struct iwl_tt_mgmt thermal_throttle; | 1211 | struct iwl_tt_mgmt thermal_throttle; |
1117 | 1212 | ||
1118 | struct iwl_notif_statistics statistics; | 1213 | struct iwl_notif_statistics statistics; |
1119 | unsigned long last_statistics_time; | 1214 | #ifdef CONFIG_IWLWIFI_DEBUG |
1215 | struct iwl_notif_statistics accum_statistics; | ||
1216 | struct iwl_notif_statistics delta_statistics; | ||
1217 | struct iwl_notif_statistics max_delta; | ||
1218 | #endif | ||
1120 | 1219 | ||
1121 | /* context information */ | 1220 | /* context information */ |
1122 | u16 rates_mask; | 1221 | u16 rates_mask; |
@@ -1149,7 +1248,7 @@ struct iwl_priv { | |||
1149 | u32 last_beacon_time; | 1248 | u32 last_beacon_time; |
1150 | u64 last_tsf; | 1249 | u64 last_tsf; |
1151 | 1250 | ||
1152 | /* eeprom */ | 1251 | /* eeprom -- this is in the card's little endian byte order */ |
1153 | u8 *eeprom; | 1252 | u8 *eeprom; |
1154 | int nvm_device_type; | 1253 | int nvm_device_type; |
1155 | struct iwl_eeprom_calib_info *calib_info; | 1254 | struct iwl_eeprom_calib_info *calib_info; |
@@ -1188,20 +1287,16 @@ struct iwl_priv { | |||
1188 | 1287 | ||
1189 | struct workqueue_struct *workqueue; | 1288 | struct workqueue_struct *workqueue; |
1190 | 1289 | ||
1191 | struct work_struct up; | ||
1192 | struct work_struct restart; | 1290 | struct work_struct restart; |
1193 | struct work_struct calibrated_work; | ||
1194 | struct work_struct scan_completed; | 1291 | struct work_struct scan_completed; |
1195 | struct work_struct rx_replenish; | 1292 | struct work_struct rx_replenish; |
1196 | struct work_struct abort_scan; | 1293 | struct work_struct abort_scan; |
1197 | struct work_struct update_link_led; | ||
1198 | struct work_struct auth_work; | ||
1199 | struct work_struct report_work; | ||
1200 | struct work_struct request_scan; | 1294 | struct work_struct request_scan; |
1201 | struct work_struct beacon_update; | 1295 | struct work_struct beacon_update; |
1202 | struct work_struct tt_work; | 1296 | struct work_struct tt_work; |
1203 | struct work_struct ct_enter; | 1297 | struct work_struct ct_enter; |
1204 | struct work_struct ct_exit; | 1298 | struct work_struct ct_exit; |
1299 | struct work_struct start_internal_scan; | ||
1205 | 1300 | ||
1206 | struct tasklet_struct irq_tasklet; | 1301 | struct tasklet_struct irq_tasklet; |
1207 | 1302 | ||
@@ -1216,6 +1311,7 @@ struct iwl_priv { | |||
1216 | /* TX Power */ | 1311 | /* TX Power */ |
1217 | s8 tx_power_user_lmt; | 1312 | s8 tx_power_user_lmt; |
1218 | s8 tx_power_device_lmt; | 1313 | s8 tx_power_device_lmt; |
1314 | s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ | ||
1219 | 1315 | ||
1220 | 1316 | ||
1221 | #ifdef CONFIG_IWLWIFI_DEBUG | 1317 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1231,7 +1327,8 @@ struct iwl_priv { | |||
1231 | u16 rx_traffic_idx; | 1327 | u16 rx_traffic_idx; |
1232 | u8 *tx_traffic; | 1328 | u8 *tx_traffic; |
1233 | u8 *rx_traffic; | 1329 | u8 *rx_traffic; |
1234 | struct iwl_debugfs *dbgfs; | 1330 | struct dentry *debugfs_dir; |
1331 | u32 dbgfs_sram_offset, dbgfs_sram_len; | ||
1235 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 1332 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
1236 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 1333 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
1237 | 1334 | ||
@@ -1241,6 +1338,7 @@ struct iwl_priv { | |||
1241 | u32 disable_tx_power_cal; | 1338 | u32 disable_tx_power_cal; |
1242 | struct work_struct run_time_calib_work; | 1339 | struct work_struct run_time_calib_work; |
1243 | struct timer_list statistics_periodic; | 1340 | struct timer_list statistics_periodic; |
1341 | struct timer_list ucode_trace; | ||
1244 | bool hw_ready; | 1342 | bool hw_ready; |
1245 | /*For 3945*/ | 1343 | /*For 3945*/ |
1246 | #define IWL_DEFAULT_TX_POWER 0x0F | 1344 | #define IWL_DEFAULT_TX_POWER 0x0F |
@@ -1248,6 +1346,8 @@ struct iwl_priv { | |||
1248 | struct iwl3945_notif_statistics statistics_39; | 1346 | struct iwl3945_notif_statistics statistics_39; |
1249 | 1347 | ||
1250 | u32 sta_supp_rates; | 1348 | u32 sta_supp_rates; |
1349 | |||
1350 | struct iwl_event_log event_log; | ||
1251 | }; /*iwl_priv */ | 1351 | }; /*iwl_priv */ |
1252 | 1352 | ||
1253 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) | 1353 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) |
@@ -1333,4 +1433,15 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) | |||
1333 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; | 1433 | return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; |
1334 | } | 1434 | } |
1335 | 1435 | ||
1436 | static inline void __iwl_free_pages(struct iwl_priv *priv, struct page *page) | ||
1437 | { | ||
1438 | __free_pages(page, priv->hw_params.rx_page_order); | ||
1439 | priv->alloc_rxb_page--; | ||
1440 | } | ||
1441 | |||
1442 | static inline void iwl_free_pages(struct iwl_priv *priv, unsigned long page) | ||
1443 | { | ||
1444 | free_pages(page, priv->hw_params.rx_page_order); | ||
1445 | priv->alloc_rxb_page--; | ||
1446 | } | ||
1336 | #endif /* __iwl_dev_h__ */ | 1447 | #endif /* __iwl_dev_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c new file mode 100644 index 000000000000..2ffc2edbf4f0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | |||
29 | /* sparse doesn't like tracepoint macros */ | ||
30 | #ifndef __CHECKER__ | ||
31 | #include "iwl-dev.h" | ||
32 | |||
33 | #define CREATE_TRACE_POINTS | ||
34 | #include "iwl-devtrace.h" | ||
35 | |||
36 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8); | ||
37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); | ||
38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | ||
39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | ||
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | ||
41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | ||
42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | ||
43 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); | ||
44 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h new file mode 100644 index 000000000000..ae7319bb3a99 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -0,0 +1,266 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
28 | #define __IWLWIFI_DEVICE_TRACE | ||
29 | |||
30 | #include <linux/tracepoint.h> | ||
31 | |||
32 | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) | ||
33 | #undef TRACE_EVENT | ||
34 | #define TRACE_EVENT(name, proto, ...) \ | ||
35 | static inline void trace_ ## name(proto) {} | ||
36 | #endif | ||
37 | |||
38 | #define PRIV_ENTRY __field(struct iwl_priv *, priv) | ||
39 | #define PRIV_ASSIGN __entry->priv = priv | ||
40 | |||
41 | #undef TRACE_SYSTEM | ||
42 | #define TRACE_SYSTEM iwlwifi_io | ||
43 | |||
44 | TRACE_EVENT(iwlwifi_dev_ioread32, | ||
45 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), | ||
46 | TP_ARGS(priv, offs, val), | ||
47 | TP_STRUCT__entry( | ||
48 | PRIV_ENTRY | ||
49 | __field(u32, offs) | ||
50 | __field(u32, val) | ||
51 | ), | ||
52 | TP_fast_assign( | ||
53 | PRIV_ASSIGN; | ||
54 | __entry->offs = offs; | ||
55 | __entry->val = val; | ||
56 | ), | ||
57 | TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val) | ||
58 | ); | ||
59 | |||
60 | TRACE_EVENT(iwlwifi_dev_iowrite8, | ||
61 | TP_PROTO(struct iwl_priv *priv, u32 offs, u8 val), | ||
62 | TP_ARGS(priv, offs, val), | ||
63 | TP_STRUCT__entry( | ||
64 | PRIV_ENTRY | ||
65 | __field(u32, offs) | ||
66 | __field(u8, val) | ||
67 | ), | ||
68 | TP_fast_assign( | ||
69 | PRIV_ASSIGN; | ||
70 | __entry->offs = offs; | ||
71 | __entry->val = val; | ||
72 | ), | ||
73 | TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) | ||
74 | ); | ||
75 | |||
76 | TRACE_EVENT(iwlwifi_dev_iowrite32, | ||
77 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), | ||
78 | TP_ARGS(priv, offs, val), | ||
79 | TP_STRUCT__entry( | ||
80 | PRIV_ENTRY | ||
81 | __field(u32, offs) | ||
82 | __field(u32, val) | ||
83 | ), | ||
84 | TP_fast_assign( | ||
85 | PRIV_ASSIGN; | ||
86 | __entry->offs = offs; | ||
87 | __entry->val = val; | ||
88 | ), | ||
89 | TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) | ||
90 | ); | ||
91 | |||
92 | #undef TRACE_SYSTEM | ||
93 | #define TRACE_SYSTEM iwlwifi_ucode | ||
94 | |||
95 | TRACE_EVENT(iwlwifi_dev_ucode_cont_event, | ||
96 | TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), | ||
97 | TP_ARGS(priv, time, data, ev), | ||
98 | TP_STRUCT__entry( | ||
99 | PRIV_ENTRY | ||
100 | |||
101 | __field(u32, time) | ||
102 | __field(u32, data) | ||
103 | __field(u32, ev) | ||
104 | ), | ||
105 | TP_fast_assign( | ||
106 | PRIV_ASSIGN; | ||
107 | __entry->time = time; | ||
108 | __entry->data = data; | ||
109 | __entry->ev = ev; | ||
110 | ), | ||
111 | TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", | ||
112 | __entry->priv, __entry->time, __entry->data, __entry->ev) | ||
113 | ); | ||
114 | |||
115 | TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, | ||
116 | TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry), | ||
117 | TP_ARGS(priv, wraps, n_entry, p_entry), | ||
118 | TP_STRUCT__entry( | ||
119 | PRIV_ENTRY | ||
120 | |||
121 | __field(u32, wraps) | ||
122 | __field(u32, n_entry) | ||
123 | __field(u32, p_entry) | ||
124 | ), | ||
125 | TP_fast_assign( | ||
126 | PRIV_ASSIGN; | ||
127 | __entry->wraps = wraps; | ||
128 | __entry->n_entry = n_entry; | ||
129 | __entry->p_entry = p_entry; | ||
130 | ), | ||
131 | TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", | ||
132 | __entry->priv, __entry->wraps, __entry->n_entry, | ||
133 | __entry->p_entry) | ||
134 | ); | ||
135 | |||
136 | #undef TRACE_SYSTEM | ||
137 | #define TRACE_SYSTEM iwlwifi | ||
138 | |||
139 | TRACE_EVENT(iwlwifi_dev_hcmd, | ||
140 | TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), | ||
141 | TP_ARGS(priv, hcmd, len, flags), | ||
142 | TP_STRUCT__entry( | ||
143 | PRIV_ENTRY | ||
144 | __dynamic_array(u8, hcmd, len) | ||
145 | __field(u32, flags) | ||
146 | ), | ||
147 | TP_fast_assign( | ||
148 | PRIV_ASSIGN; | ||
149 | memcpy(__get_dynamic_array(hcmd), hcmd, len); | ||
150 | __entry->flags = flags; | ||
151 | ), | ||
152 | TP_printk("[%p] hcmd %#.2x (%ssync)", | ||
153 | __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0], | ||
154 | __entry->flags & CMD_ASYNC ? "a" : "") | ||
155 | ); | ||
156 | |||
157 | TRACE_EVENT(iwlwifi_dev_rx, | ||
158 | TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len), | ||
159 | TP_ARGS(priv, rxbuf, len), | ||
160 | TP_STRUCT__entry( | ||
161 | PRIV_ENTRY | ||
162 | __dynamic_array(u8, rxbuf, len) | ||
163 | ), | ||
164 | TP_fast_assign( | ||
165 | PRIV_ASSIGN; | ||
166 | memcpy(__get_dynamic_array(rxbuf), rxbuf, len); | ||
167 | ), | ||
168 | TP_printk("[%p] RX cmd %#.2x", | ||
169 | __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4]) | ||
170 | ); | ||
171 | |||
172 | TRACE_EVENT(iwlwifi_dev_tx, | ||
173 | TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen, | ||
174 | void *buf0, size_t buf0_len, | ||
175 | void *buf1, size_t buf1_len), | ||
176 | TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), | ||
177 | TP_STRUCT__entry( | ||
178 | PRIV_ENTRY | ||
179 | |||
180 | __field(size_t, framelen) | ||
181 | __dynamic_array(u8, tfd, tfdlen) | ||
182 | |||
183 | /* | ||
184 | * Do not insert between or below these items, | ||
185 | * we want to keep the frame together (except | ||
186 | * for the possible padding). | ||
187 | */ | ||
188 | __dynamic_array(u8, buf0, buf0_len) | ||
189 | __dynamic_array(u8, buf1, buf1_len) | ||
190 | ), | ||
191 | TP_fast_assign( | ||
192 | PRIV_ASSIGN; | ||
193 | __entry->framelen = buf0_len + buf1_len; | ||
194 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); | ||
195 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); | ||
196 | memcpy(__get_dynamic_array(buf1), buf1, buf0_len); | ||
197 | ), | ||
198 | TP_printk("[%p] TX %.2x (%zu bytes)", | ||
199 | __entry->priv, | ||
200 | ((u8 *)__get_dynamic_array(buf0))[0], | ||
201 | __entry->framelen) | ||
202 | ); | ||
203 | |||
204 | TRACE_EVENT(iwlwifi_dev_ucode_error, | ||
205 | TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time, | ||
206 | u32 data1, u32 data2, u32 line, u32 blink1, | ||
207 | u32 blink2, u32 ilink1, u32 ilink2), | ||
208 | TP_ARGS(priv, desc, time, data1, data2, line, | ||
209 | blink1, blink2, ilink1, ilink2), | ||
210 | TP_STRUCT__entry( | ||
211 | PRIV_ENTRY | ||
212 | __field(u32, desc) | ||
213 | __field(u32, time) | ||
214 | __field(u32, data1) | ||
215 | __field(u32, data2) | ||
216 | __field(u32, line) | ||
217 | __field(u32, blink1) | ||
218 | __field(u32, blink2) | ||
219 | __field(u32, ilink1) | ||
220 | __field(u32, ilink2) | ||
221 | ), | ||
222 | TP_fast_assign( | ||
223 | PRIV_ASSIGN; | ||
224 | __entry->desc = desc; | ||
225 | __entry->time = time; | ||
226 | __entry->data1 = data1; | ||
227 | __entry->data2 = data2; | ||
228 | __entry->line = line; | ||
229 | __entry->blink1 = blink1; | ||
230 | __entry->blink2 = blink2; | ||
231 | __entry->ilink1 = ilink1; | ||
232 | __entry->ilink2 = ilink2; | ||
233 | ), | ||
234 | TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, " | ||
235 | "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X", | ||
236 | __entry->priv, __entry->desc, __entry->time, __entry->data1, | ||
237 | __entry->data2, __entry->line, __entry->blink1, | ||
238 | __entry->blink2, __entry->ilink1, __entry->ilink2) | ||
239 | ); | ||
240 | |||
241 | TRACE_EVENT(iwlwifi_dev_ucode_event, | ||
242 | TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), | ||
243 | TP_ARGS(priv, time, data, ev), | ||
244 | TP_STRUCT__entry( | ||
245 | PRIV_ENTRY | ||
246 | |||
247 | __field(u32, time) | ||
248 | __field(u32, data) | ||
249 | __field(u32, ev) | ||
250 | ), | ||
251 | TP_fast_assign( | ||
252 | PRIV_ASSIGN; | ||
253 | __entry->time = time; | ||
254 | __entry->data = data; | ||
255 | __entry->ev = ev; | ||
256 | ), | ||
257 | TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", | ||
258 | __entry->priv, __entry->time, __entry->data, __entry->ev) | ||
259 | ); | ||
260 | #endif /* __IWLWIFI_DEVICE_TRACE */ | ||
261 | |||
262 | #undef TRACE_INCLUDE_PATH | ||
263 | #define TRACE_INCLUDE_PATH . | ||
264 | #undef TRACE_INCLUDE_FILE | ||
265 | #define TRACE_INCLUDE_FILE iwl-devtrace | ||
266 | #include <trace/define_trace.h> | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index e14c9952a935..fb5bb487f3bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -63,6 +63,7 @@ | |||
63 | 63 | ||
64 | #include <linux/kernel.h> | 64 | #include <linux/kernel.h> |
65 | #include <linux/module.h> | 65 | #include <linux/module.h> |
66 | #include <linux/slab.h> | ||
66 | #include <linux/init.h> | 67 | #include <linux/init.h> |
67 | 68 | ||
68 | #include <net/mac80211.h> | 69 | #include <net/mac80211.h> |
@@ -215,12 +216,35 @@ static const struct iwl_txpwr_section enhinfo[] = { | |||
215 | 216 | ||
216 | int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) | 217 | int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) |
217 | { | 218 | { |
218 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP); | 219 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; |
219 | if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { | 220 | int ret = 0; |
220 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | 221 | |
221 | return -ENOENT; | 222 | IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp); |
223 | switch (gp) { | ||
224 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
225 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { | ||
226 | IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n", | ||
227 | gp); | ||
228 | ret = -ENOENT; | ||
229 | } | ||
230 | break; | ||
231 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
232 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
233 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { | ||
234 | IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp); | ||
235 | ret = -ENOENT; | ||
236 | } | ||
237 | break; | ||
238 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
239 | default: | ||
240 | IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, " | ||
241 | "EEPROM_GP=0x%08x\n", | ||
242 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
243 | ? "OTP" : "EEPROM", gp); | ||
244 | ret = -ENOENT; | ||
245 | break; | ||
222 | } | 246 | } |
223 | return 0; | 247 | return ret; |
224 | } | 248 | } |
225 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); | 249 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); |
226 | 250 | ||
@@ -283,7 +307,8 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) | |||
283 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | 307 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); |
284 | 308 | ||
285 | /* See if we got it */ | 309 | /* See if we got it */ |
286 | ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG, | 310 | ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, |
311 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
287 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | 312 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, |
288 | EEPROM_SEM_TIMEOUT); | 313 | EEPROM_SEM_TIMEOUT); |
289 | if (ret >= 0) { | 314 | if (ret >= 0) { |
@@ -322,7 +347,8 @@ static int iwl_init_otp_access(struct iwl_priv *priv) | |||
322 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 347 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
323 | 348 | ||
324 | /* wait for clock to be ready */ | 349 | /* wait for clock to be ready */ |
325 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 350 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
351 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
326 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | 352 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
327 | 25000); | 353 | 25000); |
328 | if (ret < 0) | 354 | if (ret < 0) |
@@ -333,11 +359,19 @@ static int iwl_init_otp_access(struct iwl_priv *priv) | |||
333 | udelay(5); | 359 | udelay(5); |
334 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, | 360 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, |
335 | APMG_PS_CTRL_VAL_RESET_REQ); | 361 | APMG_PS_CTRL_VAL_RESET_REQ); |
362 | |||
363 | /* | ||
364 | * CSR auto clock gate disable bit - | ||
365 | * this is only applicable for HW with OTP shadow RAM | ||
366 | */ | ||
367 | if (priv->cfg->shadow_ram_support) | ||
368 | iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, | ||
369 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
336 | } | 370 | } |
337 | return ret; | 371 | return ret; |
338 | } | 372 | } |
339 | 373 | ||
340 | static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) | 374 | static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data) |
341 | { | 375 | { |
342 | int ret = 0; | 376 | int ret = 0; |
343 | u32 r; | 377 | u32 r; |
@@ -345,7 +379,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) | |||
345 | 379 | ||
346 | _iwl_write32(priv, CSR_EEPROM_REG, | 380 | _iwl_write32(priv, CSR_EEPROM_REG, |
347 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 381 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
348 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | 382 | ret = iwl_poll_bit(priv, CSR_EEPROM_REG, |
383 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
349 | CSR_EEPROM_REG_READ_VALID_MSK, | 384 | CSR_EEPROM_REG_READ_VALID_MSK, |
350 | IWL_EEPROM_ACCESS_TIMEOUT); | 385 | IWL_EEPROM_ACCESS_TIMEOUT); |
351 | if (ret < 0) { | 386 | if (ret < 0) { |
@@ -370,7 +405,7 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) | |||
370 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | 405 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); |
371 | IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); | 406 | IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); |
372 | } | 407 | } |
373 | *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); | 408 | *eeprom_data = cpu_to_le16(r >> 16); |
374 | return 0; | 409 | return 0; |
375 | } | 410 | } |
376 | 411 | ||
@@ -379,7 +414,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) | |||
379 | */ | 414 | */ |
380 | static bool iwl_is_otp_empty(struct iwl_priv *priv) | 415 | static bool iwl_is_otp_empty(struct iwl_priv *priv) |
381 | { | 416 | { |
382 | u16 next_link_addr = 0, link_value; | 417 | u16 next_link_addr = 0; |
418 | __le16 link_value; | ||
383 | bool is_empty = false; | 419 | bool is_empty = false; |
384 | 420 | ||
385 | /* locate the beginning of OTP link list */ | 421 | /* locate the beginning of OTP link list */ |
@@ -409,7 +445,8 @@ static bool iwl_is_otp_empty(struct iwl_priv *priv) | |||
409 | static int iwl_find_otp_image(struct iwl_priv *priv, | 445 | static int iwl_find_otp_image(struct iwl_priv *priv, |
410 | u16 *validblockaddr) | 446 | u16 *validblockaddr) |
411 | { | 447 | { |
412 | u16 next_link_addr = 0, link_value = 0, valid_addr; | 448 | u16 next_link_addr = 0, valid_addr; |
449 | __le16 link_value = 0; | ||
413 | int usedblocks = 0; | 450 | int usedblocks = 0; |
414 | 451 | ||
415 | /* set addressing mode to absolute to traverse the link list */ | 452 | /* set addressing mode to absolute to traverse the link list */ |
@@ -429,7 +466,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, | |||
429 | * check for more block on the link list | 466 | * check for more block on the link list |
430 | */ | 467 | */ |
431 | valid_addr = next_link_addr; | 468 | valid_addr = next_link_addr; |
432 | next_link_addr = link_value * sizeof(u16); | 469 | next_link_addr = le16_to_cpu(link_value) * sizeof(u16); |
433 | IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", | 470 | IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", |
434 | usedblocks, next_link_addr); | 471 | usedblocks, next_link_addr); |
435 | if (iwl_read_otp_word(priv, next_link_addr, &link_value)) | 472 | if (iwl_read_otp_word(priv, next_link_addr, &link_value)) |
@@ -463,7 +500,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv, | |||
463 | */ | 500 | */ |
464 | int iwl_eeprom_init(struct iwl_priv *priv) | 501 | int iwl_eeprom_init(struct iwl_priv *priv) |
465 | { | 502 | { |
466 | u16 *e; | 503 | __le16 *e; |
467 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP); | 504 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP); |
468 | int sz; | 505 | int sz; |
469 | int ret; | 506 | int ret; |
@@ -482,7 +519,9 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
482 | ret = -ENOMEM; | 519 | ret = -ENOMEM; |
483 | goto alloc_err; | 520 | goto alloc_err; |
484 | } | 521 | } |
485 | e = (u16 *)priv->eeprom; | 522 | e = (__le16 *)priv->eeprom; |
523 | |||
524 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
486 | 525 | ||
487 | ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); | 526 | ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); |
488 | if (ret < 0) { | 527 | if (ret < 0) { |
@@ -498,7 +537,9 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
498 | ret = -ENOENT; | 537 | ret = -ENOENT; |
499 | goto err; | 538 | goto err; |
500 | } | 539 | } |
540 | |||
501 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | 541 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { |
542 | |||
502 | ret = iwl_init_otp_access(priv); | 543 | ret = iwl_init_otp_access(priv); |
503 | if (ret) { | 544 | if (ret) { |
504 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); | 545 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); |
@@ -521,7 +562,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
521 | } | 562 | } |
522 | for (addr = validblockaddr; addr < validblockaddr + sz; | 563 | for (addr = validblockaddr; addr < validblockaddr + sz; |
523 | addr += sizeof(u16)) { | 564 | addr += sizeof(u16)) { |
524 | u16 eeprom_data; | 565 | __le16 eeprom_data; |
525 | 566 | ||
526 | ret = iwl_read_otp_word(priv, addr, &eeprom_data); | 567 | ret = iwl_read_otp_word(priv, addr, &eeprom_data); |
527 | if (ret) | 568 | if (ret) |
@@ -537,7 +578,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
537 | _iwl_write32(priv, CSR_EEPROM_REG, | 578 | _iwl_write32(priv, CSR_EEPROM_REG, |
538 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 579 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
539 | 580 | ||
540 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | 581 | ret = iwl_poll_bit(priv, CSR_EEPROM_REG, |
582 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
541 | CSR_EEPROM_REG_READ_VALID_MSK, | 583 | CSR_EEPROM_REG_READ_VALID_MSK, |
542 | IWL_EEPROM_ACCESS_TIMEOUT); | 584 | IWL_EEPROM_ACCESS_TIMEOUT); |
543 | if (ret < 0) { | 585 | if (ret < 0) { |
@@ -545,7 +587,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
545 | goto done; | 587 | goto done; |
546 | } | 588 | } |
547 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); | 589 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); |
548 | e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); | 590 | e[addr / 2] = cpu_to_le16(r >> 16); |
549 | } | 591 | } |
550 | } | 592 | } |
551 | ret = 0; | 593 | ret = 0; |
@@ -554,6 +596,8 @@ done: | |||
554 | err: | 596 | err: |
555 | if (ret) | 597 | if (ret) |
556 | iwl_eeprom_free(priv); | 598 | iwl_eeprom_free(priv); |
599 | /* Reset chip to save power until we load uCode during "up". */ | ||
600 | priv->cfg->ops->lib->apm_ops.stop(priv); | ||
557 | alloc_err: | 601 | alloc_err: |
558 | return ret; | 602 | return ret; |
559 | } | 603 | } |
@@ -705,11 +749,9 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | |||
705 | 749 | ||
706 | ch_info->ht40_eeprom = *eeprom_ch; | 750 | ch_info->ht40_eeprom = *eeprom_ch; |
707 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; | 751 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; |
708 | ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg; | ||
709 | ch_info->ht40_min_power = 0; | ||
710 | ch_info->ht40_scan_power = eeprom_ch->max_power_avg; | ||
711 | ch_info->ht40_flags = eeprom_ch->flags; | 752 | ch_info->ht40_flags = eeprom_ch->flags; |
712 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; | 753 | if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) |
754 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; | ||
713 | 755 | ||
714 | return 0; | 756 | return 0; |
715 | } | 757 | } |
@@ -719,7 +761,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | |||
719 | * find the highest tx power from all chains for the channel | 761 | * find the highest tx power from all chains for the channel |
720 | */ | 762 | */ |
721 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | 763 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, |
722 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element) | 764 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
765 | int element, s8 *max_txpower_in_half_dbm) | ||
723 | { | 766 | { |
724 | s8 max_txpower_avg = 0; /* (dBm) */ | 767 | s8 max_txpower_avg = 0; /* (dBm) */ |
725 | 768 | ||
@@ -751,10 +794,14 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | |||
751 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | 794 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) |
752 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | 795 | max_txpower_avg = enhanced_txpower[element].mimo3_max; |
753 | 796 | ||
754 | /* max. tx power in EEPROM is in 1/2 dBm format | 797 | /* |
755 | * convert from 1/2 dBm to dBm | 798 | * max. tx power in EEPROM is in 1/2 dBm format |
799 | * convert from 1/2 dBm to dBm (round-up convert) | ||
800 | * but we also do not want to loss 1/2 dBm resolution which | ||
801 | * will impact performance | ||
756 | */ | 802 | */ |
757 | return max_txpower_avg >> 1; | 803 | *max_txpower_in_half_dbm = max_txpower_avg; |
804 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
758 | } | 805 | } |
759 | 806 | ||
760 | /** | 807 | /** |
@@ -763,7 +810,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | |||
763 | */ | 810 | */ |
764 | static s8 iwl_update_common_txpower(struct iwl_priv *priv, | 811 | static s8 iwl_update_common_txpower(struct iwl_priv *priv, |
765 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | 812 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
766 | int section, int element) | 813 | int section, int element, s8 *max_txpower_in_half_dbm) |
767 | { | 814 | { |
768 | struct iwl_channel_info *ch_info; | 815 | struct iwl_channel_info *ch_info; |
769 | int ch; | 816 | int ch; |
@@ -777,25 +824,25 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv, | |||
777 | if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) | 824 | if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) |
778 | is_ht40 = true; | 825 | is_ht40 = true; |
779 | max_txpower_avg = | 826 | max_txpower_avg = |
780 | iwl_get_max_txpower_avg(priv, enhanced_txpower, element); | 827 | iwl_get_max_txpower_avg(priv, enhanced_txpower, |
828 | element, max_txpower_in_half_dbm); | ||
829 | |||
781 | ch_info = priv->channel_info; | 830 | ch_info = priv->channel_info; |
782 | 831 | ||
783 | for (ch = 0; ch < priv->channel_count; ch++) { | 832 | for (ch = 0; ch < priv->channel_count; ch++) { |
784 | /* find matching band and update tx power if needed */ | 833 | /* find matching band and update tx power if needed */ |
785 | if ((ch_info->band == enhinfo[section].band) && | 834 | if ((ch_info->band == enhinfo[section].band) && |
786 | (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) { | 835 | (ch_info->max_power_avg < max_txpower_avg) && |
836 | (!is_ht40)) { | ||
787 | /* Update regulatory-based run-time data */ | 837 | /* Update regulatory-based run-time data */ |
788 | ch_info->max_power_avg = ch_info->curr_txpow = | 838 | ch_info->max_power_avg = ch_info->curr_txpow = |
789 | max_txpower_avg; | 839 | max_txpower_avg; |
790 | ch_info->scan_power = max_txpower_avg; | 840 | ch_info->scan_power = max_txpower_avg; |
791 | } | 841 | } |
792 | if ((ch_info->band == enhinfo[section].band) && is_ht40 && | 842 | if ((ch_info->band == enhinfo[section].band) && is_ht40 && |
793 | ch_info->ht40_max_power_avg && | ||
794 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | 843 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { |
795 | /* Update regulatory-based run-time data */ | 844 | /* Update regulatory-based run-time data */ |
796 | ch_info->ht40_max_power_avg = max_txpower_avg; | 845 | ch_info->ht40_max_power_avg = max_txpower_avg; |
797 | ch_info->ht40_curr_txpow = max_txpower_avg; | ||
798 | ch_info->ht40_scan_power = max_txpower_avg; | ||
799 | } | 846 | } |
800 | ch_info++; | 847 | ch_info++; |
801 | } | 848 | } |
@@ -808,7 +855,7 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv, | |||
808 | */ | 855 | */ |
809 | static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | 856 | static s8 iwl_update_channel_txpower(struct iwl_priv *priv, |
810 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | 857 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
811 | int section, int element) | 858 | int section, int element, s8 *max_txpower_in_half_dbm) |
812 | { | 859 | { |
813 | struct iwl_channel_info *ch_info; | 860 | struct iwl_channel_info *ch_info; |
814 | int ch; | 861 | int ch; |
@@ -817,7 +864,8 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | |||
817 | 864 | ||
818 | channel = enhinfo[section].iwl_eeprom_section_channel[element]; | 865 | channel = enhinfo[section].iwl_eeprom_section_channel[element]; |
819 | max_txpower_avg = | 866 | max_txpower_avg = |
820 | iwl_get_max_txpower_avg(priv, enhanced_txpower, element); | 867 | iwl_get_max_txpower_avg(priv, enhanced_txpower, |
868 | element, max_txpower_in_half_dbm); | ||
821 | 869 | ||
822 | ch_info = priv->channel_info; | 870 | ch_info = priv->channel_info; |
823 | for (ch = 0; ch < priv->channel_count; ch++) { | 871 | for (ch = 0; ch < priv->channel_count; ch++) { |
@@ -831,12 +879,9 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | |||
831 | ch_info->scan_power = max_txpower_avg; | 879 | ch_info->scan_power = max_txpower_avg; |
832 | } | 880 | } |
833 | if ((enhinfo[section].is_ht40) && | 881 | if ((enhinfo[section].is_ht40) && |
834 | (ch_info->ht40_max_power_avg) && | ||
835 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | 882 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { |
836 | /* Update regulatory-based run-time data */ | 883 | /* Update regulatory-based run-time data */ |
837 | ch_info->ht40_max_power_avg = max_txpower_avg; | 884 | ch_info->ht40_max_power_avg = max_txpower_avg; |
838 | ch_info->ht40_curr_txpow = max_txpower_avg; | ||
839 | ch_info->ht40_scan_power = max_txpower_avg; | ||
840 | } | 885 | } |
841 | break; | 886 | break; |
842 | } | 887 | } |
@@ -855,6 +900,7 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
855 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; | 900 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; |
856 | u32 offset; | 901 | u32 offset; |
857 | s8 max_txpower_avg; /* (dBm) */ | 902 | s8 max_txpower_avg; /* (dBm) */ |
903 | s8 max_txpower_in_half_dbm; /* (half-dBm) */ | ||
858 | 904 | ||
859 | /* Loop through all the sections | 905 | /* Loop through all the sections |
860 | * adjust bands and channel's max tx power | 906 | * adjust bands and channel's max tx power |
@@ -867,20 +913,43 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
867 | enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) | 913 | enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) |
868 | iwl_eeprom_query_addr(priv, offset); | 914 | iwl_eeprom_query_addr(priv, offset); |
869 | 915 | ||
916 | /* | ||
917 | * check for valid entry - | ||
918 | * different version of EEPROM might contain different set | ||
919 | * of enhanced tx power table | ||
920 | * always check for valid entry before process | ||
921 | * the information | ||
922 | */ | ||
923 | if (!enhanced_txpower->common || enhanced_txpower->reserved) | ||
924 | continue; | ||
925 | |||
870 | for (element = 0; element < eeprom_section_count; element++) { | 926 | for (element = 0; element < eeprom_section_count; element++) { |
871 | if (enhinfo[section].is_common) | 927 | if (enhinfo[section].is_common) |
872 | max_txpower_avg = | 928 | max_txpower_avg = |
873 | iwl_update_common_txpower(priv, | 929 | iwl_update_common_txpower(priv, |
874 | enhanced_txpower, section, element); | 930 | enhanced_txpower, section, |
931 | element, | ||
932 | &max_txpower_in_half_dbm); | ||
875 | else | 933 | else |
876 | max_txpower_avg = | 934 | max_txpower_avg = |
877 | iwl_update_channel_txpower(priv, | 935 | iwl_update_channel_txpower(priv, |
878 | enhanced_txpower, section, element); | 936 | enhanced_txpower, section, |
937 | element, | ||
938 | &max_txpower_in_half_dbm); | ||
879 | 939 | ||
880 | /* Update the tx_power_user_lmt to the highest power | 940 | /* Update the tx_power_user_lmt to the highest power |
881 | * supported by any channel */ | 941 | * supported by any channel */ |
882 | if (max_txpower_avg > priv->tx_power_user_lmt) | 942 | if (max_txpower_avg > priv->tx_power_user_lmt) |
883 | priv->tx_power_user_lmt = max_txpower_avg; | 943 | priv->tx_power_user_lmt = max_txpower_avg; |
944 | |||
945 | /* | ||
946 | * Update the tx_power_lmt_in_half_dbm to | ||
947 | * the highest power supported by any channel | ||
948 | */ | ||
949 | if (max_txpower_in_half_dbm > | ||
950 | priv->tx_power_lmt_in_half_dbm) | ||
951 | priv->tx_power_lmt_in_half_dbm = | ||
952 | max_txpower_in_half_dbm; | ||
884 | } | 953 | } |
885 | } | 954 | } |
886 | } | 955 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 80b9e45d9b9c..8171c701e4e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -63,6 +63,8 @@ | |||
63 | #ifndef __iwl_eeprom_h__ | 63 | #ifndef __iwl_eeprom_h__ |
64 | #define __iwl_eeprom_h__ | 64 | #define __iwl_eeprom_h__ |
65 | 65 | ||
66 | #include <net/mac80211.h> | ||
67 | |||
66 | struct iwl_priv; | 68 | struct iwl_priv; |
67 | 69 | ||
68 | /* | 70 | /* |
@@ -125,19 +127,21 @@ struct iwl_eeprom_channel { | |||
125 | * Enhanced regulatory tx power portion of eeprom image can be broken down | 127 | * Enhanced regulatory tx power portion of eeprom image can be broken down |
126 | * into individual structures; each one is 8 bytes in size and contain the | 128 | * into individual structures; each one is 8 bytes in size and contain the |
127 | * following information | 129 | * following information |
130 | * @common: (desc + channel) not used by driver, should _NOT_ be "zero" | ||
128 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | 131 | * @chain_a_max_pwr: chain a max power in 1/2 dBm |
129 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | 132 | * @chain_b_max_pwr: chain b max power in 1/2 dBm |
130 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | 133 | * @chain_c_max_pwr: chain c max power in 1/2 dBm |
134 | * @reserved: not used, should be "zero" | ||
131 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | 135 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm |
132 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | 136 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm |
133 | * | 137 | * |
134 | */ | 138 | */ |
135 | struct iwl_eeprom_enhanced_txpwr { | 139 | struct iwl_eeprom_enhanced_txpwr { |
136 | u16 reserved; | 140 | __le16 common; |
137 | s8 chain_a_max; | 141 | s8 chain_a_max; |
138 | s8 chain_b_max; | 142 | s8 chain_b_max; |
139 | s8 chain_c_max; | 143 | s8 chain_c_max; |
140 | s8 reserved1; | 144 | s8 reserved; |
141 | s8 mimo2_max; | 145 | s8 mimo2_max; |
142 | s8 mimo3_max; | 146 | s8 mimo3_max; |
143 | } __attribute__ ((packed)); | 147 | } __attribute__ ((packed)); |
@@ -199,6 +203,10 @@ struct iwl_eeprom_enhanced_txpwr { | |||
199 | #define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ | 203 | #define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ |
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
201 | 205 | ||
206 | /* 6000 regulatory - indirect access */ | ||
207 | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\ | ||
208 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | ||
209 | |||
202 | /* 6000 and up regulatory tx power - indirect access */ | 210 | /* 6000 and up regulatory tx power - indirect access */ |
203 | /* max. elements per section */ | 211 | /* max. elements per section */ |
204 | #define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) | 212 | #define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) |
@@ -256,6 +264,15 @@ struct iwl_eeprom_enhanced_txpwr { | |||
256 | #define EEPROM_5050_TX_POWER_VERSION (4) | 264 | #define EEPROM_5050_TX_POWER_VERSION (4) |
257 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 265 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
258 | 266 | ||
267 | /* 1000 Specific */ | ||
268 | #define EEPROM_1000_EEPROM_VERSION (0x15C) | ||
269 | |||
270 | /* 6x00 Specific */ | ||
271 | #define EEPROM_6000_EEPROM_VERSION (0x434) | ||
272 | |||
273 | /* 6x50 Specific */ | ||
274 | #define EEPROM_6050_EEPROM_VERSION (0x532) | ||
275 | |||
259 | /* OTP */ | 276 | /* OTP */ |
260 | /* lower blocks contain EEPROM image and calibration data */ | 277 | /* lower blocks contain EEPROM image and calibration data */ |
261 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ | 278 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ |
@@ -347,7 +364,7 @@ struct iwl_eeprom_calib_subband_info { | |||
347 | struct iwl_eeprom_calib_info { | 364 | struct iwl_eeprom_calib_info { |
348 | u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ | 365 | u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ |
349 | u8 saturation_power52; /* half-dBm */ | 366 | u8 saturation_power52; /* half-dBm */ |
350 | s16 voltage; /* signed */ | 367 | __le16 voltage; /* signed */ |
351 | struct iwl_eeprom_calib_subband_info | 368 | struct iwl_eeprom_calib_subband_info |
352 | band_info[EEPROM_TX_POWER_BANDS]; | 369 | band_info[EEPROM_TX_POWER_BANDS]; |
353 | } __attribute__ ((packed)); | 370 | } __attribute__ ((packed)); |
@@ -370,12 +387,10 @@ struct iwl_eeprom_calib_info { | |||
370 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | 387 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ |
371 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | 388 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ |
372 | #define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ | 389 | #define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ |
373 | #define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ | ||
374 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | 390 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ |
375 | #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ | 391 | #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ |
376 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | 392 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ |
377 | #define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ | 393 | #define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ |
378 | #define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ | ||
379 | 394 | ||
380 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ | 395 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ |
381 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | 396 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ |
@@ -387,7 +402,12 @@ struct iwl_eeprom_calib_info { | |||
387 | 402 | ||
388 | #define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 | 403 | #define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 |
389 | #define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 | 404 | #define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 |
390 | #define EEPROM_5000_RF_CFG_TYPE_MAX 0x3 | 405 | |
406 | /* Radio Config for 5000 and up */ | ||
407 | #define EEPROM_RF_CONFIG_TYPE_R3x3 0x0 | ||
408 | #define EEPROM_RF_CONFIG_TYPE_R2x2 0x1 | ||
409 | #define EEPROM_RF_CONFIG_TYPE_R1x2 0x2 | ||
410 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 | ||
391 | 411 | ||
392 | /* | 412 | /* |
393 | * Per-channel regulatory data. | 413 | * Per-channel regulatory data. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 65fa8a69fd5a..113c3669b9ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -379,6 +379,25 @@ | |||
379 | 379 | ||
380 | #define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) | 380 | #define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) |
381 | 381 | ||
382 | /** | ||
383 | * Bit fields for TSSR(Tx Shared Status & Control) error status register: | ||
384 | * 31: Indicates an address error when accessed to internal memory | ||
385 | * uCode/driver must write "1" in order to clear this flag | ||
386 | * 30: Indicates that Host did not send the expected number of dwords to FH | ||
387 | * uCode/driver must write "1" in order to clear this flag | ||
388 | * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA | ||
389 | * command was received from the scheduler while the TRB was already full | ||
390 | * with previous command | ||
391 | * uCode/driver must write "1" in order to clear this flag | ||
392 | * 7-0: Each status bit indicates a channel's TxCredit error. When an error | ||
393 | * bit is set, it indicates that the FH has received a full indication | ||
394 | * from the RTC TxFIFO and the current value of the TxCredit counter was | ||
395 | * not equal to zero. This mean that the credit mechanism was not | ||
396 | * synchronized to the TxFIFO status | ||
397 | * uCode/driver must write "1" in order to clear this flag | ||
398 | */ | ||
399 | #define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018) | ||
400 | |||
382 | #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) | 401 | #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) |
383 | #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) | 402 | #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) |
384 | 403 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index a6856daf14cb..73681c4fefe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -56,7 +56,8 @@ const char *get_cmd_string(u8 cmd) | |||
56 | IWL_CMD(REPLY_LEDS_CMD); | 56 | IWL_CMD(REPLY_LEDS_CMD); |
57 | IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); | 57 | IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); |
58 | IWL_CMD(COEX_PRIORITY_TABLE_CMD); | 58 | IWL_CMD(COEX_PRIORITY_TABLE_CMD); |
59 | IWL_CMD(RADAR_NOTIFICATION); | 59 | IWL_CMD(COEX_MEDIUM_NOTIFICATION); |
60 | IWL_CMD(COEX_EVENT_CMD); | ||
60 | IWL_CMD(REPLY_QUIET_CMD); | 61 | IWL_CMD(REPLY_QUIET_CMD); |
61 | IWL_CMD(REPLY_CHANNEL_SWITCH); | 62 | IWL_CMD(REPLY_CHANNEL_SWITCH); |
62 | IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); | 63 | IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); |
@@ -93,6 +94,8 @@ const char *get_cmd_string(u8 cmd) | |||
93 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); | 94 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); |
94 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); | 95 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); |
95 | IWL_CMD(REPLY_TX_POWER_DBM_CMD); | 96 | IWL_CMD(REPLY_TX_POWER_DBM_CMD); |
97 | IWL_CMD(TEMPERATURE_NOTIFICATION); | ||
98 | IWL_CMD(TX_ANT_CONFIGURATION_CMD); | ||
96 | default: | 99 | default: |
97 | return "UNKNOWN"; | 100 | return "UNKNOWN"; |
98 | 101 | ||
@@ -104,17 +107,8 @@ EXPORT_SYMBOL(get_cmd_string); | |||
104 | 107 | ||
105 | static void iwl_generic_cmd_callback(struct iwl_priv *priv, | 108 | static void iwl_generic_cmd_callback(struct iwl_priv *priv, |
106 | struct iwl_device_cmd *cmd, | 109 | struct iwl_device_cmd *cmd, |
107 | struct sk_buff *skb) | 110 | struct iwl_rx_packet *pkt) |
108 | { | 111 | { |
109 | struct iwl_rx_packet *pkt = NULL; | ||
110 | |||
111 | if (!skb) { | ||
112 | IWL_ERR(priv, "Error: Response NULL in %s.\n", | ||
113 | get_cmd_string(cmd->hdr.cmd)); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | pkt = (struct iwl_rx_packet *)skb->data; | ||
118 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | 112 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
119 | IWL_ERR(priv, "Bad return from %s (0x%08X)\n", | 113 | IWL_ERR(priv, "Bad return from %s (0x%08X)\n", |
120 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); | 114 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); |
@@ -170,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
170 | /* A synchronous command can not have a callback set. */ | 164 | /* A synchronous command can not have a callback set. */ |
171 | BUG_ON(cmd->callback); | 165 | BUG_ON(cmd->callback); |
172 | 166 | ||
173 | if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { | 167 | IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", |
174 | IWL_ERR(priv, | ||
175 | "Error sending %s: Already sending a host command\n", | ||
176 | get_cmd_string(cmd->id)); | 168 | get_cmd_string(cmd->id)); |
177 | ret = -EBUSY; | 169 | mutex_lock(&priv->sync_cmd_mutex); |
178 | goto out; | ||
179 | } | ||
180 | 170 | ||
181 | 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", | ||
173 | get_cmd_string(cmd->id)); | ||
182 | 174 | ||
183 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); | 175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); |
184 | if (cmd_idx < 0) { | 176 | if (cmd_idx < 0) { |
@@ -199,24 +191,26 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
199 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
200 | 192 | ||
201 | 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", | ||
195 | get_cmd_string(cmd->id)); | ||
202 | ret = -ETIMEDOUT; | 196 | ret = -ETIMEDOUT; |
203 | goto cancel; | 197 | goto cancel; |
204 | } | 198 | } |
205 | } | 199 | } |
206 | 200 | ||
207 | if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { | 201 | if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { |
208 | IWL_DEBUG_INFO(priv, "Command %s aborted: RF KILL Switch\n", | 202 | IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n", |
209 | get_cmd_string(cmd->id)); | 203 | get_cmd_string(cmd->id)); |
210 | ret = -ECANCELED; | 204 | ret = -ECANCELED; |
211 | goto fail; | 205 | goto fail; |
212 | } | 206 | } |
213 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { | 207 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { |
214 | IWL_DEBUG_INFO(priv, "Command %s failed: FW Error\n", | 208 | IWL_ERR(priv, "Command %s failed: FW Error\n", |
215 | get_cmd_string(cmd->id)); | 209 | get_cmd_string(cmd->id)); |
216 | ret = -EIO; | 210 | ret = -EIO; |
217 | goto fail; | 211 | goto fail; |
218 | } | 212 | } |
219 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) { | 213 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { |
220 | IWL_ERR(priv, "Error: Response NULL in '%s'\n", | 214 | IWL_ERR(priv, "Error: Response NULL in '%s'\n", |
221 | get_cmd_string(cmd->id)); | 215 | get_cmd_string(cmd->id)); |
222 | ret = -EIO; | 216 | ret = -EIO; |
@@ -238,12 +232,12 @@ cancel: | |||
238 | ~CMD_WANT_SKB; | 232 | ~CMD_WANT_SKB; |
239 | } | 233 | } |
240 | fail: | 234 | fail: |
241 | if (cmd->reply_skb) { | 235 | if (cmd->reply_page) { |
242 | dev_kfree_skb_any(cmd->reply_skb); | 236 | iwl_free_pages(priv, cmd->reply_page); |
243 | cmd->reply_skb = NULL; | 237 | cmd->reply_page = 0; |
244 | } | 238 | } |
245 | out: | 239 | out: |
246 | clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); | 240 | mutex_unlock(&priv->sync_cmd_mutex); |
247 | return ret; | 241 | return ret; |
248 | } | 242 | } |
249 | EXPORT_SYMBOL(iwl_send_cmd_sync); | 243 | EXPORT_SYMBOL(iwl_send_cmd_sync); |
@@ -273,7 +267,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, | |||
273 | u8 id, u16 len, const void *data, | 267 | u8 id, u16 len, const void *data, |
274 | void (*callback)(struct iwl_priv *priv, | 268 | void (*callback)(struct iwl_priv *priv, |
275 | struct iwl_device_cmd *cmd, | 269 | struct iwl_device_cmd *cmd, |
276 | struct sk_buff *skb)) | 270 | struct iwl_rx_packet *pkt)) |
277 | { | 271 | { |
278 | struct iwl_host_cmd cmd = { | 272 | struct iwl_host_cmd cmd = { |
279 | .id = id, | 273 | .id = id, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index bd0b12efb5c7..51a67fb2e185 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
80 | struct fw_desc *desc) | 80 | struct fw_desc *desc) |
81 | { | 81 | { |
82 | if (desc->v_addr) | 82 | if (desc->v_addr) |
83 | pci_free_consistent(pci_dev, desc->len, | 83 | dma_free_coherent(&pci_dev->dev, desc->len, |
84 | desc->v_addr, desc->p_addr); | 84 | desc->v_addr, desc->p_addr); |
85 | desc->v_addr = NULL; | 85 | desc->v_addr = NULL; |
86 | desc->len = 0; | 86 | desc->len = 0; |
87 | } | 87 | } |
@@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
89 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, | 89 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, |
90 | struct fw_desc *desc) | 90 | struct fw_desc *desc) |
91 | { | 91 | { |
92 | desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); | 92 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, |
93 | &desc->p_addr, GFP_KERNEL); | ||
93 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | 94 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; |
94 | } | 95 | } |
95 | 96 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index d30cb0275d19..16eb3ced9b30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project. | 5 | * Portions of this file are derived from the ipw3945 project. |
6 | * | 6 | * |
@@ -31,7 +31,9 @@ | |||
31 | 31 | ||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | 33 | ||
34 | #include "iwl-dev.h" | ||
34 | #include "iwl-debug.h" | 35 | #include "iwl-debug.h" |
36 | #include "iwl-devtrace.h" | ||
35 | 37 | ||
36 | /* | 38 | /* |
37 | * IO, register, and NIC memory access functions | 39 | * IO, register, and NIC memory access functions |
@@ -61,7 +63,32 @@ | |||
61 | * | 63 | * |
62 | */ | 64 | */ |
63 | 65 | ||
64 | #define _iwl_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) | 66 | static inline void _iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) |
67 | { | ||
68 | trace_iwlwifi_dev_iowrite8(priv, ofs, val); | ||
69 | iowrite8(val, priv->hw_base + ofs); | ||
70 | } | ||
71 | |||
72 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
73 | static inline void __iwl_write8(const char *f, u32 l, struct iwl_priv *priv, | ||
74 | u32 ofs, u8 val) | ||
75 | { | ||
76 | IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l); | ||
77 | _iwl_write8(priv, ofs, val); | ||
78 | } | ||
79 | #define iwl_write8(priv, ofs, val) \ | ||
80 | __iwl_write8(__FILE__, __LINE__, priv, ofs, val) | ||
81 | #else | ||
82 | #define iwl_write8(priv, ofs, val) _iwl_write8(priv, ofs, val) | ||
83 | #endif | ||
84 | |||
85 | |||
86 | static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) | ||
87 | { | ||
88 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); | ||
89 | iowrite32(val, priv->hw_base + ofs); | ||
90 | } | ||
91 | |||
65 | #ifdef CONFIG_IWLWIFI_DEBUG | 92 | #ifdef CONFIG_IWLWIFI_DEBUG |
66 | static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, | 93 | static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, |
67 | u32 ofs, u32 val) | 94 | u32 ofs, u32 val) |
@@ -75,7 +102,13 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, | |||
75 | #define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) | 102 | #define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) |
76 | #endif | 103 | #endif |
77 | 104 | ||
78 | #define _iwl_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) | 105 | static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs) |
106 | { | ||
107 | u32 val = ioread32(priv->hw_base + ofs); | ||
108 | trace_iwlwifi_dev_ioread32(priv, ofs, val); | ||
109 | return val; | ||
110 | } | ||
111 | |||
79 | #ifdef CONFIG_IWLWIFI_DEBUG | 112 | #ifdef CONFIG_IWLWIFI_DEBUG |
80 | static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) | 113 | static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) |
81 | { | 114 | { |
@@ -188,6 +221,26 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv) | |||
188 | 221 | ||
189 | /* this bit wakes up the NIC */ | 222 | /* this bit wakes up the NIC */ |
190 | _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 223 | _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
224 | |||
225 | /* | ||
226 | * These bits say the device is running, and should keep running for | ||
227 | * at least a short while (at least as long as MAC_ACCESS_REQ stays 1), | ||
228 | * but they do not indicate that embedded SRAM is restored yet; | ||
229 | * 3945 and 4965 have volatile SRAM, and must save/restore contents | ||
230 | * to/from host DRAM when sleeping/waking for power-saving. | ||
231 | * Each direction takes approximately 1/4 millisecond; with this | ||
232 | * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a | ||
233 | * series of register accesses are expected (e.g. reading Event Log), | ||
234 | * to keep device from sleeping. | ||
235 | * | ||
236 | * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that | ||
237 | * SRAM is okay/restored. We don't check that here because this call | ||
238 | * is just for hardware register access; but GP1 MAC_SLEEP check is a | ||
239 | * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log). | ||
240 | * | ||
241 | * 5000 series and later (including 1000 series) have non-volatile SRAM, | ||
242 | * and do not save/restore SRAM when power cycling. | ||
243 | */ | ||
191 | ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, | 244 | ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, |
192 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, | 245 | CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, |
193 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | | 246 | (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index f420c99e7240..a6f9c918aabc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -42,15 +42,11 @@ | |||
42 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | 44 | ||
45 | #ifdef CONFIG_IWLWIFI_DEBUG | 45 | /* default: IWL_LED_BLINK(0) using blinking index table */ |
46 | static const char *led_type_str[] = { | 46 | static int led_mode; |
47 | __stringify(IWL_LED_TRG_TX), | 47 | module_param(led_mode, int, S_IRUGO); |
48 | __stringify(IWL_LED_TRG_RX), | 48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " |
49 | __stringify(IWL_LED_TRG_ASSOC), | 49 | "(default 0)\n"); |
50 | __stringify(IWL_LED_TRG_RADIO), | ||
51 | NULL | ||
52 | }; | ||
53 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
54 | 50 | ||
55 | 51 | ||
56 | static const struct { | 52 | static const struct { |
@@ -65,11 +61,11 @@ static const struct { | |||
65 | {70, 65, 65}, | 61 | {70, 65, 65}, |
66 | {50, 75, 75}, | 62 | {50, 75, 75}, |
67 | {20, 85, 85}, | 63 | {20, 85, 85}, |
68 | {15, 95, 95 }, | 64 | {10, 95, 95}, |
69 | {10, 110, 110}, | 65 | {5, 110, 110}, |
70 | {5, 130, 130}, | 66 | {1, 130, 130}, |
71 | {0, 167, 167}, | 67 | {0, 167, 167}, |
72 | /* SOLID_ON */ | 68 | /* SOLID_ON */ |
73 | {-1, IWL_LED_SOLID, 0} | 69 | {-1, IWL_LED_SOLID, 0} |
74 | }; | 70 | }; |
75 | 71 | ||
@@ -78,191 +74,74 @@ static const struct { | |||
78 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ | 74 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ |
79 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | 75 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) |
80 | 76 | ||
81 | /* [0-256] -> [0..8] FIXME: we need [0..10] */ | 77 | /* |
82 | static inline int iwl_brightness_to_idx(enum led_brightness brightness) | 78 | * Adjust led blink rate to compensate on a MAC Clock difference on every HW |
83 | { | 79 | * Led blink rate analysis showed an average deviation of 0% on 3945, |
84 | return fls(0x000000FF & (u32)brightness); | 80 | * 5% on 4965 HW and 20% on 5000 series and up. |
85 | } | 81 | * Need to compensate on the led on/off time per HW according to the deviation |
86 | 82 | * to achieve the desired led frequency | |
87 | /* Send led command */ | 83 | * The calculation is: (100-averageDeviation)/100 * blinkTime |
88 | static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | 84 | * For code efficiency the calculation will be: |
85 | * compensation = (100 - averageDeviation) * 64 / 100 | ||
86 | * NewBlinkTime = (compensation * BlinkTime) / 64 | ||
87 | */ | ||
88 | static inline u8 iwl_blink_compensation(struct iwl_priv *priv, | ||
89 | u8 time, u16 compensation) | ||
89 | { | 90 | { |
90 | struct iwl_host_cmd cmd = { | 91 | if (!compensation) { |
91 | .id = REPLY_LEDS_CMD, | 92 | IWL_ERR(priv, "undefined blink compensation: " |
92 | .len = sizeof(struct iwl_led_cmd), | 93 | "use pre-defined blinking time\n"); |
93 | .data = led_cmd, | 94 | return time; |
94 | .flags = CMD_ASYNC, | 95 | } |
95 | .callback = NULL, | ||
96 | }; | ||
97 | u32 reg; | ||
98 | |||
99 | reg = iwl_read32(priv, CSR_LED_REG); | ||
100 | if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) | ||
101 | iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); | ||
102 | 96 | ||
103 | return iwl_send_cmd(priv, &cmd); | 97 | return (u8)((time * compensation) >> 6); |
104 | } | 98 | } |
105 | 99 | ||
106 | /* Set led pattern command */ | 100 | /* Set led pattern command */ |
107 | static int iwl_led_pattern(struct iwl_priv *priv, int led_id, | 101 | static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx) |
108 | unsigned int idx) | ||
109 | { | 102 | { |
110 | struct iwl_led_cmd led_cmd = { | 103 | struct iwl_led_cmd led_cmd = { |
111 | .id = led_id, | 104 | .id = IWL_LED_LINK, |
112 | .interval = IWL_DEF_LED_INTRVL | 105 | .interval = IWL_DEF_LED_INTRVL |
113 | }; | 106 | }; |
114 | 107 | ||
115 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | 108 | BUG_ON(idx > IWL_MAX_BLINK_TBL); |
116 | 109 | ||
117 | led_cmd.on = blink_tbl[idx].on_time; | 110 | IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n", |
118 | led_cmd.off = blink_tbl[idx].off_time; | 111 | priv->cfg->led_compensation); |
119 | 112 | led_cmd.on = | |
120 | return iwl_send_led_cmd(priv, &led_cmd); | 113 | iwl_blink_compensation(priv, blink_tbl[idx].on_time, |
121 | } | 114 | priv->cfg->led_compensation); |
122 | 115 | led_cmd.off = | |
123 | /* Set led register off */ | 116 | iwl_blink_compensation(priv, blink_tbl[idx].off_time, |
124 | static int iwl_led_on_reg(struct iwl_priv *priv, int led_id) | 117 | priv->cfg->led_compensation); |
125 | { | ||
126 | IWL_DEBUG_LED(priv, "led on %d\n", led_id); | ||
127 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | ||
128 | return 0; | ||
129 | } | ||
130 | 118 | ||
131 | #if 0 | 119 | return priv->cfg->ops->led->cmd(priv, &led_cmd); |
132 | /* Set led on command */ | ||
133 | static int iwl_led_on(struct iwl_priv *priv, int led_id) | ||
134 | { | ||
135 | struct iwl_led_cmd led_cmd = { | ||
136 | .id = led_id, | ||
137 | .on = IWL_LED_SOLID, | ||
138 | .off = 0, | ||
139 | .interval = IWL_DEF_LED_INTRVL | ||
140 | }; | ||
141 | return iwl_send_led_cmd(priv, &led_cmd); | ||
142 | } | 120 | } |
143 | 121 | ||
144 | /* Set led off command */ | 122 | int iwl_led_start(struct iwl_priv *priv) |
145 | int iwl_led_off(struct iwl_priv *priv, int led_id) | ||
146 | { | 123 | { |
147 | struct iwl_led_cmd led_cmd = { | 124 | return priv->cfg->ops->led->on(priv); |
148 | .id = led_id, | ||
149 | .on = 0, | ||
150 | .off = 0, | ||
151 | .interval = IWL_DEF_LED_INTRVL | ||
152 | }; | ||
153 | IWL_DEBUG_LED(priv, "led off %d\n", led_id); | ||
154 | return iwl_send_led_cmd(priv, &led_cmd); | ||
155 | } | 125 | } |
156 | #endif | 126 | EXPORT_SYMBOL(iwl_led_start); |
157 | |||
158 | 127 | ||
159 | /* Set led register off */ | 128 | int iwl_led_associate(struct iwl_priv *priv) |
160 | static int iwl_led_off_reg(struct iwl_priv *priv, int led_id) | ||
161 | { | ||
162 | IWL_DEBUG_LED(priv, "LED Reg off\n"); | ||
163 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Set led register in case of disassociation according to rfkill state | ||
169 | */ | ||
170 | static int iwl_led_associate(struct iwl_priv *priv, int led_id) | ||
171 | { | 129 | { |
172 | IWL_DEBUG_LED(priv, "Associated\n"); | 130 | IWL_DEBUG_LED(priv, "Associated\n"); |
173 | priv->allow_blinking = 1; | 131 | if (led_mode == IWL_LED_BLINK) |
174 | return iwl_led_on_reg(priv, led_id); | 132 | priv->allow_blinking = 1; |
175 | } | 133 | priv->last_blink_time = jiffies; |
176 | static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) | ||
177 | { | ||
178 | priv->allow_blinking = 0; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * brightness call back function for Tx/Rx LED | ||
185 | */ | ||
186 | static int iwl_led_associated(struct iwl_priv *priv, int led_id) | ||
187 | { | ||
188 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | ||
189 | !test_bit(STATUS_READY, &priv->status)) | ||
190 | return 0; | ||
191 | |||
192 | 134 | ||
193 | /* start counting Tx/Rx bytes */ | ||
194 | if (!priv->last_blink_time && priv->allow_blinking) | ||
195 | priv->last_blink_time = jiffies; | ||
196 | return 0; | 135 | return 0; |
197 | } | 136 | } |
198 | 137 | ||
199 | /* | 138 | int iwl_led_disassociate(struct iwl_priv *priv) |
200 | * brightness call back for association and radio | ||
201 | */ | ||
202 | static void iwl_led_brightness_set(struct led_classdev *led_cdev, | ||
203 | enum led_brightness brightness) | ||
204 | { | 139 | { |
205 | struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev); | 140 | priv->allow_blinking = 0; |
206 | struct iwl_priv *priv = led->priv; | ||
207 | |||
208 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
209 | return; | ||
210 | |||
211 | |||
212 | IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", | ||
213 | led_type_str[led->type], brightness); | ||
214 | switch (brightness) { | ||
215 | case LED_FULL: | ||
216 | if (led->led_on) | ||
217 | led->led_on(priv, IWL_LED_LINK); | ||
218 | break; | ||
219 | case LED_OFF: | ||
220 | if (led->led_off) | ||
221 | led->led_off(priv, IWL_LED_LINK); | ||
222 | break; | ||
223 | default: | ||
224 | if (led->led_pattern) { | ||
225 | int idx = iwl_brightness_to_idx(brightness); | ||
226 | led->led_pattern(priv, IWL_LED_LINK, idx); | ||
227 | } | ||
228 | break; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | |||
234 | /* | ||
235 | * Register led class with the system | ||
236 | */ | ||
237 | static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, | ||
238 | enum led_type type, u8 set_led, | ||
239 | char *trigger) | ||
240 | { | ||
241 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
242 | int ret; | ||
243 | |||
244 | led->led_dev.name = led->name; | ||
245 | led->led_dev.brightness_set = iwl_led_brightness_set; | ||
246 | led->led_dev.default_trigger = trigger; | ||
247 | |||
248 | led->priv = priv; | ||
249 | led->type = type; | ||
250 | |||
251 | ret = led_classdev_register(device, &led->led_dev); | ||
252 | if (ret) { | ||
253 | IWL_ERR(priv, "Error: failed to register led handler.\n"); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | led->registered = 1; | ||
258 | |||
259 | if (set_led && led->led_on) | ||
260 | led->led_on(priv, IWL_LED_LINK); | ||
261 | 141 | ||
262 | return 0; | 142 | return 0; |
263 | } | 143 | } |
264 | 144 | ||
265 | |||
266 | /* | 145 | /* |
267 | * calculate blink rate according to last second Tx/Rx activities | 146 | * calculate blink rate according to last second Tx/Rx activities |
268 | */ | 147 | */ |
@@ -288,7 +167,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) | |||
288 | i = IWL_MAX_BLINK_TBL; | 167 | i = IWL_MAX_BLINK_TBL; |
289 | else | 168 | else |
290 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) | 169 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) |
291 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) | 170 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) |
292 | break; | 171 | break; |
293 | 172 | ||
294 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); | 173 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); |
@@ -317,8 +196,7 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
317 | priv->last_blink_time = 0; | 196 | priv->last_blink_time = 0; |
318 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { | 197 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { |
319 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; | 198 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; |
320 | iwl_led_pattern(priv, IWL_LED_LINK, | 199 | iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX); |
321 | IWL_SOLID_BLINK_IDX); | ||
322 | } | 200 | } |
323 | return; | 201 | return; |
324 | } | 202 | } |
@@ -331,111 +209,17 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
331 | 209 | ||
332 | /* call only if blink rate change */ | 210 | /* call only if blink rate change */ |
333 | if (blink_idx != priv->last_blink_rate) | 211 | if (blink_idx != priv->last_blink_rate) |
334 | iwl_led_pattern(priv, IWL_LED_LINK, blink_idx); | 212 | iwl_led_pattern(priv, blink_idx); |
335 | 213 | ||
336 | priv->last_blink_time = jiffies; | 214 | priv->last_blink_time = jiffies; |
337 | priv->last_blink_rate = blink_idx; | 215 | priv->last_blink_rate = blink_idx; |
338 | } | 216 | } |
217 | EXPORT_SYMBOL(iwl_leds_background); | ||
339 | 218 | ||
340 | /* Register all led handler */ | 219 | void iwl_leds_init(struct iwl_priv *priv) |
341 | int iwl_leds_register(struct iwl_priv *priv) | ||
342 | { | 220 | { |
343 | char *trigger; | ||
344 | int ret; | ||
345 | |||
346 | priv->last_blink_rate = 0; | 221 | priv->last_blink_rate = 0; |
347 | priv->led_tpt = 0; | ||
348 | priv->last_blink_time = 0; | 222 | priv->last_blink_time = 0; |
349 | priv->allow_blinking = 0; | 223 | priv->allow_blinking = 0; |
350 | |||
351 | trigger = ieee80211_get_radio_led_name(priv->hw); | ||
352 | snprintf(priv->led[IWL_LED_TRG_RADIO].name, | ||
353 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", | ||
354 | wiphy_name(priv->hw->wiphy)); | ||
355 | |||
356 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg; | ||
357 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg; | ||
358 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | ||
359 | |||
360 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], | ||
361 | IWL_LED_TRG_RADIO, 1, trigger); | ||
362 | if (ret) | ||
363 | goto exit_fail; | ||
364 | |||
365 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
366 | snprintf(priv->led[IWL_LED_TRG_ASSOC].name, | ||
367 | sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", | ||
368 | wiphy_name(priv->hw->wiphy)); | ||
369 | |||
370 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], | ||
371 | IWL_LED_TRG_ASSOC, 0, trigger); | ||
372 | |||
373 | /* for assoc always turn led on */ | ||
374 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate; | ||
375 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate; | ||
376 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; | ||
377 | |||
378 | if (ret) | ||
379 | goto exit_fail; | ||
380 | |||
381 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
382 | snprintf(priv->led[IWL_LED_TRG_RX].name, | ||
383 | sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", | ||
384 | wiphy_name(priv->hw->wiphy)); | ||
385 | |||
386 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], | ||
387 | IWL_LED_TRG_RX, 0, trigger); | ||
388 | |||
389 | priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; | ||
390 | priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; | ||
391 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern; | ||
392 | |||
393 | if (ret) | ||
394 | goto exit_fail; | ||
395 | |||
396 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
397 | snprintf(priv->led[IWL_LED_TRG_TX].name, | ||
398 | sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", | ||
399 | wiphy_name(priv->hw->wiphy)); | ||
400 | |||
401 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], | ||
402 | IWL_LED_TRG_TX, 0, trigger); | ||
403 | |||
404 | priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; | ||
405 | priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; | ||
406 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern; | ||
407 | |||
408 | if (ret) | ||
409 | goto exit_fail; | ||
410 | |||
411 | return 0; | ||
412 | |||
413 | exit_fail: | ||
414 | iwl_leds_unregister(priv); | ||
415 | return ret; | ||
416 | } | 224 | } |
417 | EXPORT_SYMBOL(iwl_leds_register); | 225 | EXPORT_SYMBOL(iwl_leds_init); |
418 | |||
419 | /* unregister led class */ | ||
420 | static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led) | ||
421 | { | ||
422 | if (!led->registered) | ||
423 | return; | ||
424 | |||
425 | led_classdev_unregister(&led->led_dev); | ||
426 | |||
427 | if (set_led) | ||
428 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
429 | led->registered = 0; | ||
430 | } | ||
431 | |||
432 | /* Unregister all led handlers */ | ||
433 | void iwl_leds_unregister(struct iwl_priv *priv) | ||
434 | { | ||
435 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); | ||
436 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); | ||
437 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); | ||
438 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); | ||
439 | } | ||
440 | EXPORT_SYMBOL(iwl_leds_unregister); | ||
441 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index ef9b174c37ff..49a70baa3fb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of version 2 of the GNU General Public License as | 6 | * under the terms of version 2 of the GNU General Public License as |
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | struct iwl_priv; | 31 | struct iwl_priv; |
32 | 32 | ||
33 | #ifdef CONFIG_IWLWIFI_LEDS | ||
34 | #include <linux/leds.h> | ||
35 | |||
36 | #define IWL_LED_SOLID 11 | 33 | #define IWL_LED_SOLID 11 |
37 | #define IWL_LED_NAME_LEN 31 | 34 | #define IWL_LED_NAME_LEN 31 |
38 | #define IWL_DEF_LED_INTRVL cpu_to_le32(1000) | 35 | #define IWL_DEF_LED_INTRVL cpu_to_le32(1000) |
@@ -47,38 +44,23 @@ enum led_type { | |||
47 | IWL_LED_TRG_RADIO, | 44 | IWL_LED_TRG_RADIO, |
48 | IWL_LED_TRG_MAX, | 45 | IWL_LED_TRG_MAX, |
49 | }; | 46 | }; |
50 | #endif | ||
51 | |||
52 | #ifdef CONFIG_IWLWIFI_LEDS | ||
53 | |||
54 | struct iwl_led { | ||
55 | struct iwl_priv *priv; | ||
56 | struct led_classdev led_dev; | ||
57 | char name[32]; | ||
58 | 47 | ||
59 | int (*led_on) (struct iwl_priv *priv, int led_id); | 48 | /* |
60 | int (*led_off) (struct iwl_priv *priv, int led_id); | 49 | * LED mode |
61 | int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); | 50 | * IWL_LED_BLINK: adjust led blink rate based on blink table |
62 | 51 | * IWL_LED_RF_STATE: turn LED on/off based on RF state | |
63 | enum led_type type; | 52 | * LED ON = RF ON |
64 | unsigned int registered; | 53 | * LED OFF = RF OFF |
54 | */ | ||
55 | enum iwl_led_mode { | ||
56 | IWL_LED_BLINK, | ||
57 | IWL_LED_RF_STATE, | ||
65 | }; | 58 | }; |
66 | 59 | ||
67 | int iwl_leds_register(struct iwl_priv *priv); | 60 | void iwl_leds_init(struct iwl_priv *priv); |
68 | void iwl_leds_unregister(struct iwl_priv *priv); | ||
69 | void iwl_leds_background(struct iwl_priv *priv); | 61 | void iwl_leds_background(struct iwl_priv *priv); |
62 | int iwl_led_start(struct iwl_priv *priv); | ||
63 | int iwl_led_associate(struct iwl_priv *priv); | ||
64 | int iwl_led_disassociate(struct iwl_priv *priv); | ||
70 | 65 | ||
71 | #else | ||
72 | static inline int iwl_leds_register(struct iwl_priv *priv) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
76 | static inline void iwl_leds_unregister(struct iwl_priv *priv) | ||
77 | { | ||
78 | } | ||
79 | static inline void iwl_leds_background(struct iwl_priv *priv) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | #endif /* CONFIG_IWLWIFI_LEDS */ | ||
84 | #endif /* __iwl_leds_h__ */ | 66 | #endif /* __iwl_leds_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 60be976afff8..548dac2f6a96 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/slab.h> | ||
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | 34 | ||
34 | #include <net/mac80211.h> | 35 | #include <net/mac80211.h> |
@@ -66,7 +67,7 @@ MODULE_PARM_DESC(no_sleep_autoadjust, | |||
66 | 67 | ||
67 | struct iwl_power_vec_entry { | 68 | struct iwl_power_vec_entry { |
68 | struct iwl_powertable_cmd cmd; | 69 | struct iwl_powertable_cmd cmd; |
69 | u8 no_dtim; | 70 | u8 no_dtim; /* number of skip dtim */ |
70 | }; | 71 | }; |
71 | 72 | ||
72 | #define IWL_DTIM_RANGE_0_MAX 2 | 73 | #define IWL_DTIM_RANGE_0_MAX 2 |
@@ -83,8 +84,9 @@ struct iwl_power_vec_entry { | |||
83 | cpu_to_le32(X4)} | 84 | cpu_to_le32(X4)} |
84 | /* default power management (not Tx power) table values */ | 85 | /* default power management (not Tx power) table values */ |
85 | /* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ | 86 | /* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ |
87 | /* DTIM 0 - 2 */ | ||
86 | static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { | 88 | static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { |
87 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, | 89 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0}, |
88 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, | 90 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, |
89 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, | 91 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, |
90 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, | 92 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, |
@@ -93,15 +95,17 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { | |||
93 | 95 | ||
94 | 96 | ||
95 | /* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ | 97 | /* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ |
98 | /* DTIM 3 - 10 */ | ||
96 | static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { | 99 | static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { |
97 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, | 100 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, |
98 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, | 101 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, |
99 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, | 102 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, |
100 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, | 103 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, |
101 | {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} | 104 | {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2} |
102 | }; | 105 | }; |
103 | 106 | ||
104 | /* for DTIM period > IWL_DTIM_RANGE_1_MAX */ | 107 | /* for DTIM period > IWL_DTIM_RANGE_1_MAX */ |
108 | /* DTIM 11 - */ | ||
105 | static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { | 109 | static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { |
106 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, | 110 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, |
107 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, | 111 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, |
@@ -115,13 +119,15 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
115 | enum iwl_power_level lvl, int period) | 119 | enum iwl_power_level lvl, int period) |
116 | { | 120 | { |
117 | const struct iwl_power_vec_entry *table; | 121 | const struct iwl_power_vec_entry *table; |
118 | int max_sleep, i; | 122 | int max_sleep[IWL_POWER_VEC_SIZE] = { 0 }; |
119 | bool skip; | 123 | int i; |
124 | u8 skip; | ||
125 | u32 slp_itrvl; | ||
120 | 126 | ||
121 | table = range_2; | 127 | table = range_2; |
122 | if (period < IWL_DTIM_RANGE_1_MAX) | 128 | if (period <= IWL_DTIM_RANGE_1_MAX) |
123 | table = range_1; | 129 | table = range_1; |
124 | if (period < IWL_DTIM_RANGE_0_MAX) | 130 | if (period <= IWL_DTIM_RANGE_0_MAX) |
125 | table = range_0; | 131 | table = range_0; |
126 | 132 | ||
127 | BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); | 133 | BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); |
@@ -129,34 +135,60 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
129 | *cmd = table[lvl].cmd; | 135 | *cmd = table[lvl].cmd; |
130 | 136 | ||
131 | if (period == 0) { | 137 | if (period == 0) { |
132 | skip = false; | 138 | skip = 0; |
133 | period = 1; | 139 | period = 1; |
140 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | ||
141 | max_sleep[i] = 1; | ||
142 | |||
134 | } else { | 143 | } else { |
135 | skip = !!table[lvl].no_dtim; | 144 | skip = table[lvl].no_dtim; |
145 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | ||
146 | max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]); | ||
147 | max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1; | ||
136 | } | 148 | } |
137 | 149 | ||
138 | if (skip) { | 150 | slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); |
139 | __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; | 151 | /* figure out the listen interval based on dtim period and skip */ |
140 | max_sleep = le32_to_cpu(slp_itrvl); | 152 | if (slp_itrvl == 0xFF) |
141 | if (max_sleep == 0xFF) | 153 | cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = |
142 | max_sleep = period * (skip + 1); | 154 | cpu_to_le32(period * (skip + 1)); |
143 | else if (max_sleep > period) | 155 | |
144 | max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; | 156 | slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); |
157 | if (slp_itrvl > period) | ||
158 | cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = | ||
159 | cpu_to_le32((slp_itrvl / period) * period); | ||
160 | |||
161 | if (skip) | ||
145 | cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; | 162 | cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; |
146 | } else { | 163 | else |
147 | max_sleep = period; | ||
148 | cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; | 164 | cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; |
149 | } | ||
150 | 165 | ||
151 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | 166 | slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); |
152 | if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) | 167 | if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL) |
153 | cmd->sleep_interval[i] = cpu_to_le32(max_sleep); | 168 | cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = |
169 | cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL); | ||
170 | |||
171 | /* enforce max sleep interval */ | ||
172 | for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) { | ||
173 | if (le32_to_cpu(cmd->sleep_interval[i]) > | ||
174 | (max_sleep[i] * period)) | ||
175 | cmd->sleep_interval[i] = | ||
176 | cpu_to_le32(max_sleep[i] * period); | ||
177 | if (i != (IWL_POWER_VEC_SIZE - 1)) { | ||
178 | if (le32_to_cpu(cmd->sleep_interval[i]) > | ||
179 | le32_to_cpu(cmd->sleep_interval[i+1])) | ||
180 | cmd->sleep_interval[i] = | ||
181 | cmd->sleep_interval[i+1]; | ||
182 | } | ||
183 | } | ||
154 | 184 | ||
155 | if (priv->power_data.pci_pm) | 185 | if (priv->power_data.pci_pm) |
156 | cmd->flags |= IWL_POWER_PCI_PM_MSK; | 186 | cmd->flags |= IWL_POWER_PCI_PM_MSK; |
157 | else | 187 | else |
158 | cmd->flags &= ~IWL_POWER_PCI_PM_MSK; | 188 | cmd->flags &= ~IWL_POWER_PCI_PM_MSK; |
159 | 189 | ||
190 | IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", | ||
191 | skip, period); | ||
160 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); | 192 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); |
161 | } | 193 | } |
162 | 194 | ||
@@ -165,26 +197,26 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
165 | *============================================================================= | 197 | *============================================================================= |
166 | * Condition Nxt State Condition Nxt State Condition Nxt State | 198 | * Condition Nxt State Condition Nxt State Condition Nxt State |
167 | *----------------------------------------------------------------------------- | 199 | *----------------------------------------------------------------------------- |
168 | * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A | 200 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A |
169 | * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 | 201 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 |
170 | * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 | 202 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 |
171 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | 203 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 |
172 | *============================================================================= | 204 | *============================================================================= |
173 | */ | 205 | */ |
174 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | 206 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { |
175 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, | 207 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, |
176 | {IWL_TI_1, 105, CT_KILL_THRESHOLD}, | 208 | {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, |
177 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | 209 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} |
178 | }; | 210 | }; |
179 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | 211 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { |
180 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, | 212 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, |
181 | {IWL_TI_2, 110, CT_KILL_THRESHOLD}, | 213 | {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, |
182 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | 214 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} |
183 | }; | 215 | }; |
184 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | 216 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { |
185 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, | 217 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, |
186 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, | 218 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, |
187 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | 219 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} |
188 | }; | 220 | }; |
189 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | 221 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { |
190 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, | 222 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, |
@@ -272,13 +304,12 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) | |||
272 | sizeof(struct iwl_powertable_cmd), cmd); | 304 | sizeof(struct iwl_powertable_cmd), cmd); |
273 | } | 305 | } |
274 | 306 | ||
275 | 307 | /* priv->mutex must be held */ | |
276 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) | 308 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) |
277 | { | 309 | { |
278 | int ret = 0; | 310 | int ret = 0; |
279 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 311 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
280 | bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && | 312 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; |
281 | (priv->hw->conf.flags & IEEE80211_CONF_PS); | ||
282 | bool update_chains; | 313 | bool update_chains; |
283 | struct iwl_powertable_cmd cmd; | 314 | struct iwl_powertable_cmd cmd; |
284 | int dtimper; | 315 | int dtimper; |
@@ -288,12 +319,15 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
288 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; | 319 | priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; |
289 | 320 | ||
290 | if (priv->vif) | 321 | if (priv->vif) |
291 | dtimper = priv->vif->bss_conf.dtim_period; | 322 | dtimper = priv->hw->conf.ps_dtim_period; |
292 | else | 323 | else |
293 | dtimper = 1; | 324 | dtimper = 1; |
294 | 325 | ||
295 | if (priv->cfg->broken_powersave) | 326 | if (priv->cfg->broken_powersave) |
296 | iwl_power_sleep_cam_cmd(priv, &cmd); | 327 | iwl_power_sleep_cam_cmd(priv, &cmd); |
328 | else if (priv->cfg->supports_idle && | ||
329 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | ||
330 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); | ||
297 | else if (tt->state >= IWL_TI_1) | 331 | else if (tt->state >= IWL_TI_1) |
298 | iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); | 332 | iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); |
299 | else if (!enabled) | 333 | else if (!enabled) |
@@ -348,6 +382,23 @@ bool iwl_ht_enabled(struct iwl_priv *priv) | |||
348 | } | 382 | } |
349 | EXPORT_SYMBOL(iwl_ht_enabled); | 383 | EXPORT_SYMBOL(iwl_ht_enabled); |
350 | 384 | ||
385 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | ||
386 | { | ||
387 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | ||
388 | bool within_margin = false; | ||
389 | |||
390 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | ||
391 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
392 | |||
393 | if (!priv->thermal_throttle.advanced_tt) | ||
394 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
395 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | ||
396 | else | ||
397 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
398 | CT_KILL_THRESHOLD) ? true : false; | ||
399 | return within_margin; | ||
400 | } | ||
401 | |||
351 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | 402 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) |
352 | { | 403 | { |
353 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 404 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
@@ -372,6 +423,7 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) | |||
372 | } | 423 | } |
373 | 424 | ||
374 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ | 425 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ |
426 | #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ | ||
375 | 427 | ||
376 | /* | 428 | /* |
377 | * toggle the bit to wake up uCode and check the temperature | 429 | * toggle the bit to wake up uCode and check the temperature |
@@ -409,6 +461,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) | |||
409 | /* Reschedule the ct_kill timer to occur in | 461 | /* Reschedule the ct_kill timer to occur in |
410 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | 462 | * CT_KILL_EXIT_DURATION seconds to ensure we get a |
411 | * thermal update */ | 463 | * thermal update */ |
464 | IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); | ||
412 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + | 465 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + |
413 | CT_KILL_EXIT_DURATION * HZ); | 466 | CT_KILL_EXIT_DURATION * HZ); |
414 | } | 467 | } |
@@ -432,6 +485,33 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | |||
432 | } | 485 | } |
433 | } | 486 | } |
434 | 487 | ||
488 | static void iwl_tt_ready_for_ct_kill(unsigned long data) | ||
489 | { | ||
490 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
491 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
492 | |||
493 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
494 | return; | ||
495 | |||
496 | /* temperature timer expired, ready to go into CT_KILL state */ | ||
497 | if (tt->state != IWL_TI_CT_KILL) { | ||
498 | IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); | ||
499 | tt->state = IWL_TI_CT_KILL; | ||
500 | set_bit(STATUS_CT_KILL, &priv->status); | ||
501 | iwl_perform_ct_kill_task(priv, true); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | ||
506 | { | ||
507 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | ||
508 | /* make request to retrieve statistics information */ | ||
509 | iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
510 | /* Reschedule the ct_kill wait timer */ | ||
511 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | ||
512 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | ||
513 | } | ||
514 | |||
435 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) | 515 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) |
436 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) | 516 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) |
437 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) | 517 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) |
@@ -445,7 +525,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | |||
445 | * Throttle early enough to lower the power consumption before | 525 | * Throttle early enough to lower the power consumption before |
446 | * drastic steps are needed | 526 | * drastic steps are needed |
447 | */ | 527 | */ |
448 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | 528 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) |
449 | { | 529 | { |
450 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 530 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
451 | enum iwl_tt_state old_state; | 531 | enum iwl_tt_state old_state; |
@@ -474,6 +554,8 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | |||
474 | #ifdef CONFIG_IWLWIFI_DEBUG | 554 | #ifdef CONFIG_IWLWIFI_DEBUG |
475 | tt->tt_previous_temp = temp; | 555 | tt->tt_previous_temp = temp; |
476 | #endif | 556 | #endif |
557 | /* stop ct_kill_waiting_tm timer */ | ||
558 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
477 | if (tt->state != old_state) { | 559 | if (tt->state != old_state) { |
478 | switch (tt->state) { | 560 | switch (tt->state) { |
479 | case IWL_TI_0: | 561 | case IWL_TI_0: |
@@ -494,17 +576,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | |||
494 | break; | 576 | break; |
495 | } | 577 | } |
496 | mutex_lock(&priv->mutex); | 578 | mutex_lock(&priv->mutex); |
497 | if (iwl_power_update_mode(priv, true)) { | 579 | if (old_state == IWL_TI_CT_KILL) |
580 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
581 | if (tt->state != IWL_TI_CT_KILL && | ||
582 | iwl_power_update_mode(priv, true)) { | ||
498 | /* TT state not updated | 583 | /* TT state not updated |
499 | * try again during next temperature read | 584 | * try again during next temperature read |
500 | */ | 585 | */ |
586 | if (old_state == IWL_TI_CT_KILL) | ||
587 | set_bit(STATUS_CT_KILL, &priv->status); | ||
501 | tt->state = old_state; | 588 | tt->state = old_state; |
502 | IWL_ERR(priv, "Cannot update power mode, " | 589 | IWL_ERR(priv, "Cannot update power mode, " |
503 | "TT state not updated\n"); | 590 | "TT state not updated\n"); |
504 | } else { | 591 | } else { |
505 | if (tt->state == IWL_TI_CT_KILL) | 592 | if (tt->state == IWL_TI_CT_KILL) { |
506 | iwl_perform_ct_kill_task(priv, true); | 593 | if (force) { |
507 | else if (old_state == IWL_TI_CT_KILL && | 594 | set_bit(STATUS_CT_KILL, &priv->status); |
595 | iwl_perform_ct_kill_task(priv, true); | ||
596 | } else { | ||
597 | iwl_prepare_ct_kill_task(priv); | ||
598 | tt->state = old_state; | ||
599 | } | ||
600 | } else if (old_state == IWL_TI_CT_KILL && | ||
508 | tt->state != IWL_TI_CT_KILL) | 601 | tt->state != IWL_TI_CT_KILL) |
509 | iwl_perform_ct_kill_task(priv, false); | 602 | iwl_perform_ct_kill_task(priv, false); |
510 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", | 603 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", |
@@ -531,13 +624,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | |||
531 | *============================================================================= | 624 | *============================================================================= |
532 | * Condition Nxt State Condition Nxt State Condition Nxt State | 625 | * Condition Nxt State Condition Nxt State Condition Nxt State |
533 | *----------------------------------------------------------------------------- | 626 | *----------------------------------------------------------------------------- |
534 | * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A | 627 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A |
535 | * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 | 628 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 |
536 | * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 | 629 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 |
537 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | 630 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 |
538 | *============================================================================= | 631 | *============================================================================= |
539 | */ | 632 | */ |
540 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | 633 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) |
541 | { | 634 | { |
542 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 635 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
543 | int i; | 636 | int i; |
@@ -582,6 +675,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | |||
582 | break; | 675 | break; |
583 | } | 676 | } |
584 | } | 677 | } |
678 | /* stop ct_kill_waiting_tm timer */ | ||
679 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
585 | if (changed) { | 680 | if (changed) { |
586 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 681 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
587 | 682 | ||
@@ -613,12 +708,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | |||
613 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | 708 | iwl_set_rxon_ht(priv, &priv->current_ht_config); |
614 | } | 709 | } |
615 | mutex_lock(&priv->mutex); | 710 | mutex_lock(&priv->mutex); |
616 | if (iwl_power_update_mode(priv, true)) { | 711 | if (old_state == IWL_TI_CT_KILL) |
712 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
713 | if (tt->state != IWL_TI_CT_KILL && | ||
714 | iwl_power_update_mode(priv, true)) { | ||
617 | /* TT state not updated | 715 | /* TT state not updated |
618 | * try again during next temperature read | 716 | * try again during next temperature read |
619 | */ | 717 | */ |
620 | IWL_ERR(priv, "Cannot update power mode, " | 718 | IWL_ERR(priv, "Cannot update power mode, " |
621 | "TT state not updated\n"); | 719 | "TT state not updated\n"); |
720 | if (old_state == IWL_TI_CT_KILL) | ||
721 | set_bit(STATUS_CT_KILL, &priv->status); | ||
622 | tt->state = old_state; | 722 | tt->state = old_state; |
623 | } else { | 723 | } else { |
624 | IWL_DEBUG_POWER(priv, | 724 | IWL_DEBUG_POWER(priv, |
@@ -626,9 +726,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | |||
626 | tt->state); | 726 | tt->state); |
627 | if (old_state != IWL_TI_CT_KILL && | 727 | if (old_state != IWL_TI_CT_KILL && |
628 | tt->state == IWL_TI_CT_KILL) { | 728 | tt->state == IWL_TI_CT_KILL) { |
629 | IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n"); | 729 | if (force) { |
630 | iwl_perform_ct_kill_task(priv, true); | 730 | IWL_DEBUG_POWER(priv, |
631 | 731 | "Enter IWL_TI_CT_KILL\n"); | |
732 | set_bit(STATUS_CT_KILL, &priv->status); | ||
733 | iwl_perform_ct_kill_task(priv, true); | ||
734 | } else { | ||
735 | iwl_prepare_ct_kill_task(priv); | ||
736 | tt->state = old_state; | ||
737 | } | ||
632 | } else if (old_state == IWL_TI_CT_KILL && | 738 | } else if (old_state == IWL_TI_CT_KILL && |
633 | tt->state != IWL_TI_CT_KILL) { | 739 | tt->state != IWL_TI_CT_KILL) { |
634 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); | 740 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); |
@@ -665,10 +771,11 @@ static void iwl_bg_ct_enter(struct work_struct *work) | |||
665 | "- ucode going to sleep!\n"); | 771 | "- ucode going to sleep!\n"); |
666 | if (!priv->thermal_throttle.advanced_tt) | 772 | if (!priv->thermal_throttle.advanced_tt) |
667 | iwl_legacy_tt_handler(priv, | 773 | iwl_legacy_tt_handler(priv, |
668 | IWL_MINIMAL_POWER_THRESHOLD); | 774 | IWL_MINIMAL_POWER_THRESHOLD, |
775 | true); | ||
669 | else | 776 | else |
670 | iwl_advance_tt_handler(priv, | 777 | iwl_advance_tt_handler(priv, |
671 | CT_KILL_THRESHOLD + 1); | 778 | CT_KILL_THRESHOLD + 1, true); |
672 | } | 779 | } |
673 | } | 780 | } |
674 | 781 | ||
@@ -695,11 +802,18 @@ static void iwl_bg_ct_exit(struct work_struct *work) | |||
695 | IWL_ERR(priv, | 802 | IWL_ERR(priv, |
696 | "Device temperature below critical" | 803 | "Device temperature below critical" |
697 | "- ucode awake!\n"); | 804 | "- ucode awake!\n"); |
805 | /* | ||
806 | * exit from CT_KILL state | ||
807 | * reset the current temperature reading | ||
808 | */ | ||
809 | priv->temperature = 0; | ||
698 | if (!priv->thermal_throttle.advanced_tt) | 810 | if (!priv->thermal_throttle.advanced_tt) |
699 | iwl_legacy_tt_handler(priv, | 811 | iwl_legacy_tt_handler(priv, |
700 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2); | 812 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2, |
813 | true); | ||
701 | else | 814 | else |
702 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); | 815 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, |
816 | true); | ||
703 | } | 817 | } |
704 | } | 818 | } |
705 | 819 | ||
@@ -735,9 +849,9 @@ static void iwl_bg_tt_work(struct work_struct *work) | |||
735 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 849 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
736 | 850 | ||
737 | if (!priv->thermal_throttle.advanced_tt) | 851 | if (!priv->thermal_throttle.advanced_tt) |
738 | iwl_legacy_tt_handler(priv, temp); | 852 | iwl_legacy_tt_handler(priv, temp, false); |
739 | else | 853 | else |
740 | iwl_advance_tt_handler(priv, temp); | 854 | iwl_advance_tt_handler(priv, temp, false); |
741 | } | 855 | } |
742 | 856 | ||
743 | void iwl_tt_handler(struct iwl_priv *priv) | 857 | void iwl_tt_handler(struct iwl_priv *priv) |
@@ -768,16 +882,18 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
768 | tt->state = IWL_TI_0; | 882 | tt->state = IWL_TI_0; |
769 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); | 883 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); |
770 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; | 884 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; |
771 | priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; | 885 | priv->thermal_throttle.ct_kill_exit_tm.function = |
772 | 886 | iwl_tt_check_exit_ct_kill; | |
887 | init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
888 | priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; | ||
889 | priv->thermal_throttle.ct_kill_waiting_tm.function = | ||
890 | iwl_tt_ready_for_ct_kill; | ||
773 | /* setup deferred ct kill work */ | 891 | /* setup deferred ct kill work */ |
774 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); | 892 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); |
775 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | 893 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); |
776 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | 894 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); |
777 | 895 | ||
778 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 896 | if (priv->cfg->adv_thermal_throttle) { |
779 | case CSR_HW_REV_TYPE_6x00: | ||
780 | case CSR_HW_REV_TYPE_6x50: | ||
781 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | 897 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); |
782 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | 898 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * |
783 | IWL_TI_STATE_MAX, GFP_KERNEL); | 899 | IWL_TI_STATE_MAX, GFP_KERNEL); |
@@ -810,11 +926,9 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
810 | &restriction_range[0], size); | 926 | &restriction_range[0], size); |
811 | priv->thermal_throttle.advanced_tt = true; | 927 | priv->thermal_throttle.advanced_tt = true; |
812 | } | 928 | } |
813 | break; | 929 | } else { |
814 | default: | ||
815 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); | 930 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); |
816 | priv->thermal_throttle.advanced_tt = false; | 931 | priv->thermal_throttle.advanced_tt = false; |
817 | break; | ||
818 | } | 932 | } |
819 | } | 933 | } |
820 | EXPORT_SYMBOL(iwl_tt_initialize); | 934 | EXPORT_SYMBOL(iwl_tt_initialize); |
@@ -826,6 +940,8 @@ void iwl_tt_exit(struct iwl_priv *priv) | |||
826 | 940 | ||
827 | /* stop ct_kill_exit_tm timer if activated */ | 941 | /* stop ct_kill_exit_tm timer if activated */ |
828 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | 942 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); |
943 | /* stop ct_kill_waiting_tm timer if activated */ | ||
944 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
829 | cancel_work_sync(&priv->tt_work); | 945 | cancel_work_sync(&priv->tt_work); |
830 | cancel_work_sync(&priv->ct_enter); | 946 | cancel_work_sync(&priv->ct_enter); |
831 | cancel_work_sync(&priv->ct_exit); | 947 | cancel_work_sync(&priv->ct_exit); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index df6f6a49712b..5db91c10dcc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -33,6 +33,7 @@ | |||
33 | #define IWL_ABSOLUTE_ZERO 0 | 33 | #define IWL_ABSOLUTE_ZERO 0 |
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | 34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF |
35 | #define IWL_TT_INCREASE_MARGIN 5 | 35 | #define IWL_TT_INCREASE_MARGIN 5 |
36 | #define IWL_TT_CT_KILL_MARGIN 3 | ||
36 | 37 | ||
37 | enum iwl_antenna_ok { | 38 | enum iwl_antenna_ok { |
38 | IWL_ANT_OK_NONE, | 39 | IWL_ANT_OK_NONE, |
@@ -110,6 +111,7 @@ struct iwl_tt_mgmt { | |||
110 | struct iwl_tt_restriction *restriction; | 111 | struct iwl_tt_restriction *restriction; |
111 | struct iwl_tt_trans *transaction; | 112 | struct iwl_tt_trans *transaction; |
112 | struct timer_list ct_kill_exit_tm; | 113 | struct timer_list ct_kill_exit_tm; |
114 | struct timer_list ct_kill_waiting_tm; | ||
113 | }; | 115 | }; |
114 | 116 | ||
115 | enum iwl_power_level { | 117 | enum iwl_power_level { |
@@ -129,6 +131,7 @@ struct iwl_power_mgr { | |||
129 | 131 | ||
130 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); | 132 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); |
131 | bool iwl_ht_enabled(struct iwl_priv *priv); | 133 | bool iwl_ht_enabled(struct iwl_priv *priv); |
134 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv); | ||
132 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | 135 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); |
133 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | 136 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); |
134 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | 137 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index d393e8f02102..d2d2a9174900 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 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 | 11 | * it under the terms of version 2 of the GNU General Public License as |
@@ -30,7 +30,7 @@ | |||
30 | * | 30 | * |
31 | * BSD LICENSE | 31 | * BSD LICENSE |
32 | * | 32 | * |
33 | * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. | 33 | * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. |
34 | * All rights reserved. | 34 | * All rights reserved. |
35 | * | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without |
@@ -254,7 +254,8 @@ | |||
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 channels have dedicated purposes. For 4965, they are used as follows |
258 | * (cf. default_queue_to_tx_fifo in iwl-4965.c): | ||
258 | * | 259 | * |
259 | * 0 -- EDCA BK (background) frames, lowest priority | 260 | * 0 -- EDCA BK (background) frames, lowest priority |
260 | * 1 -- EDCA BE (best effort) frames, normal priority | 261 | * 1 -- EDCA BE (best effort) frames, normal priority |
@@ -265,9 +266,21 @@ | |||
265 | * 6 -- HCCA long frames | 266 | * 6 -- HCCA long frames |
266 | * 7 -- not used by driver (device-internal only) | 267 | * 7 -- not used by driver (device-internal only) |
267 | * | 268 | * |
269 | * For 5000 series and up, they are used slightly differently | ||
270 | * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c): | ||
271 | * | ||
272 | * 0 -- EDCA BK (background) frames, lowest priority | ||
273 | * 1 -- EDCA BE (best effort) frames, normal priority | ||
274 | * 2 -- EDCA VI (video) frames, higher priority | ||
275 | * 3 -- EDCA VO (voice) and management frames, highest priority | ||
276 | * 4 -- (TBD) | ||
277 | * 5 -- HCCA short frames | ||
278 | * 6 -- HCCA long frames | ||
279 | * 7 -- Commands | ||
280 | * | ||
268 | * 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. |
269 | * In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to | 282 | * In addition, driver can map the remaining queues to Tx DMA/FIFO |
270 | * support 11n aggregation via EDCA DMA channels. | 283 | * channels 0-3 to support 11n aggregation via EDCA DMA channels. |
271 | * | 284 | * |
272 | * The driver sets up each queue to work in one of two modes: | 285 | * The driver sets up each queue to work in one of two modes: |
273 | * | 286 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 493626bcd3ec..e5eb339107dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -28,6 +28,7 @@ | |||
28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
29 | 29 | ||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/slab.h> | ||
31 | #include <net/mac80211.h> | 32 | #include <net/mac80211.h> |
32 | #include <asm/unaligned.h> | 33 | #include <asm/unaligned.h> |
33 | #include "iwl-eeprom.h" | 34 | #include "iwl-eeprom.h" |
@@ -123,12 +124,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space); | |||
123 | /** | 124 | /** |
124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | 125 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue |
125 | */ | 126 | */ |
126 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | 127 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) |
127 | { | 128 | { |
128 | unsigned long flags; | 129 | unsigned long flags; |
129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; | 130 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; |
130 | u32 reg; | 131 | u32 reg; |
131 | int ret = 0; | ||
132 | 132 | ||
133 | spin_lock_irqsave(&q->lock, flags); | 133 | spin_lock_irqsave(&q->lock, flags); |
134 | 134 | ||
@@ -140,6 +140,8 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | |||
140 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | 140 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); |
141 | 141 | ||
142 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 142 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
143 | IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n", | ||
144 | reg); | ||
143 | iwl_set_bit(priv, CSR_GP_CNTRL, | 145 | iwl_set_bit(priv, CSR_GP_CNTRL, |
144 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 146 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
145 | goto exit_unlock; | 147 | goto exit_unlock; |
@@ -159,7 +161,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | |||
159 | 161 | ||
160 | exit_unlock: | 162 | exit_unlock: |
161 | spin_unlock_irqrestore(&q->lock, flags); | 163 | spin_unlock_irqrestore(&q->lock, flags); |
162 | return ret; | ||
163 | } | 164 | } |
164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 165 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
165 | /** | 166 | /** |
@@ -182,14 +183,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
182 | * also updates the memory address in the firmware to reference the new | 183 | * also updates the memory address in the firmware to reference the new |
183 | * target buffer. | 184 | * target buffer. |
184 | */ | 185 | */ |
185 | int iwl_rx_queue_restock(struct iwl_priv *priv) | 186 | void iwl_rx_queue_restock(struct iwl_priv *priv) |
186 | { | 187 | { |
187 | struct iwl_rx_queue *rxq = &priv->rxq; | 188 | struct iwl_rx_queue *rxq = &priv->rxq; |
188 | struct list_head *element; | 189 | struct list_head *element; |
189 | struct iwl_rx_mem_buffer *rxb; | 190 | struct iwl_rx_mem_buffer *rxb; |
190 | unsigned long flags; | 191 | unsigned long flags; |
191 | int write; | 192 | int write; |
192 | int ret = 0; | ||
193 | 193 | ||
194 | spin_lock_irqsave(&rxq->lock, flags); | 194 | spin_lock_irqsave(&rxq->lock, flags); |
195 | write = rxq->write & ~0x7; | 195 | write = rxq->write & ~0x7; |
@@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
200 | list_del(element); | 200 | list_del(element); |
201 | 201 | ||
202 | /* Point to Rx buffer via next RBD in circular buffer */ | 202 | /* Point to Rx buffer via next RBD in circular buffer */ |
203 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr); | 203 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma); |
204 | rxq->queue[rxq->write] = rxb; | 204 | rxq->queue[rxq->write] = rxb; |
205 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 205 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
206 | rxq->free_count--; | 206 | rxq->free_count--; |
@@ -218,10 +218,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
218 | spin_lock_irqsave(&rxq->lock, flags); | 218 | spin_lock_irqsave(&rxq->lock, flags); |
219 | rxq->need_update = 1; | 219 | rxq->need_update = 1; |
220 | spin_unlock_irqrestore(&rxq->lock, flags); | 220 | spin_unlock_irqrestore(&rxq->lock, flags); |
221 | ret = iwl_rx_queue_update_write_ptr(priv, rxq); | 221 | iwl_rx_queue_update_write_ptr(priv, rxq); |
222 | } | 222 | } |
223 | |||
224 | return ret; | ||
225 | } | 223 | } |
226 | EXPORT_SYMBOL(iwl_rx_queue_restock); | 224 | EXPORT_SYMBOL(iwl_rx_queue_restock); |
227 | 225 | ||
@@ -239,8 +237,9 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
239 | struct iwl_rx_queue *rxq = &priv->rxq; | 237 | struct iwl_rx_queue *rxq = &priv->rxq; |
240 | struct list_head *element; | 238 | struct list_head *element; |
241 | struct iwl_rx_mem_buffer *rxb; | 239 | struct iwl_rx_mem_buffer *rxb; |
242 | struct sk_buff *skb; | 240 | struct page *page; |
243 | unsigned long flags; | 241 | unsigned long flags; |
242 | gfp_t gfp_mask = priority; | ||
244 | 243 | ||
245 | while (1) { | 244 | while (1) { |
246 | spin_lock_irqsave(&rxq->lock, flags); | 245 | spin_lock_irqsave(&rxq->lock, flags); |
@@ -251,30 +250,35 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
251 | spin_unlock_irqrestore(&rxq->lock, flags); | 250 | spin_unlock_irqrestore(&rxq->lock, flags); |
252 | 251 | ||
253 | if (rxq->free_count > RX_LOW_WATERMARK) | 252 | if (rxq->free_count > RX_LOW_WATERMARK) |
254 | priority |= __GFP_NOWARN; | 253 | gfp_mask |= __GFP_NOWARN; |
255 | /* Alloc a new receive buffer */ | 254 | |
256 | skb = alloc_skb(priv->hw_params.rx_buf_size + 256, | 255 | if (priv->hw_params.rx_page_order > 0) |
257 | priority); | 256 | gfp_mask |= __GFP_COMP; |
258 | 257 | ||
259 | if (!skb) { | 258 | /* Alloc a new receive buffer */ |
259 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
260 | if (!page) { | ||
260 | if (net_ratelimit()) | 261 | if (net_ratelimit()) |
261 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | 262 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " |
263 | "order: %d\n", | ||
264 | priv->hw_params.rx_page_order); | ||
265 | |||
262 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | 266 | if ((rxq->free_count <= RX_LOW_WATERMARK) && |
263 | net_ratelimit()) | 267 | net_ratelimit()) |
264 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | 268 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", |
265 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | 269 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", |
266 | rxq->free_count); | 270 | rxq->free_count); |
267 | /* We don't reschedule replenish work here -- we will | 271 | /* We don't reschedule replenish work here -- we will |
268 | * call the restock method and if it still needs | 272 | * call the restock method and if it still needs |
269 | * more buffers it will schedule replenish */ | 273 | * more buffers it will schedule replenish */ |
270 | break; | 274 | return; |
271 | } | 275 | } |
272 | 276 | ||
273 | spin_lock_irqsave(&rxq->lock, flags); | 277 | spin_lock_irqsave(&rxq->lock, flags); |
274 | 278 | ||
275 | if (list_empty(&rxq->rx_used)) { | 279 | if (list_empty(&rxq->rx_used)) { |
276 | spin_unlock_irqrestore(&rxq->lock, flags); | 280 | spin_unlock_irqrestore(&rxq->lock, flags); |
277 | dev_kfree_skb_any(skb); | 281 | __free_pages(page, priv->hw_params.rx_page_order); |
278 | return; | 282 | return; |
279 | } | 283 | } |
280 | element = rxq->rx_used.next; | 284 | element = rxq->rx_used.next; |
@@ -283,24 +287,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
283 | 287 | ||
284 | spin_unlock_irqrestore(&rxq->lock, flags); | 288 | spin_unlock_irqrestore(&rxq->lock, flags); |
285 | 289 | ||
286 | rxb->skb = skb; | 290 | rxb->page = page; |
287 | /* Get physical address of RB/SKB */ | 291 | /* Get physical address of the RB */ |
288 | rxb->real_dma_addr = pci_map_single( | 292 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, |
289 | priv->pci_dev, | 293 | PAGE_SIZE << priv->hw_params.rx_page_order, |
290 | rxb->skb->data, | 294 | PCI_DMA_FROMDEVICE); |
291 | priv->hw_params.rx_buf_size + 256, | ||
292 | PCI_DMA_FROMDEVICE); | ||
293 | /* dma address must be no more than 36 bits */ | 295 | /* dma address must be no more than 36 bits */ |
294 | BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36)); | 296 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); |
295 | /* and also 256 byte aligned! */ | 297 | /* and also 256 byte aligned! */ |
296 | rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); | 298 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); |
297 | skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); | ||
298 | 299 | ||
299 | spin_lock_irqsave(&rxq->lock, flags); | 300 | spin_lock_irqsave(&rxq->lock, flags); |
300 | 301 | ||
301 | list_add_tail(&rxb->list, &rxq->rx_free); | 302 | list_add_tail(&rxb->list, &rxq->rx_free); |
302 | rxq->free_count++; | 303 | rxq->free_count++; |
303 | priv->alloc_rxb_skb++; | 304 | priv->alloc_rxb_page++; |
304 | 305 | ||
305 | spin_unlock_irqrestore(&rxq->lock, flags); | 306 | spin_unlock_irqrestore(&rxq->lock, flags); |
306 | } | 307 | } |
@@ -336,19 +337,19 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
336 | { | 337 | { |
337 | int i; | 338 | int i; |
338 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | 339 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { |
339 | if (rxq->pool[i].skb != NULL) { | 340 | if (rxq->pool[i].page != NULL) { |
340 | pci_unmap_single(priv->pci_dev, | 341 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
341 | rxq->pool[i].real_dma_addr, | 342 | PAGE_SIZE << priv->hw_params.rx_page_order, |
342 | priv->hw_params.rx_buf_size + 256, | 343 | PCI_DMA_FROMDEVICE); |
343 | PCI_DMA_FROMDEVICE); | 344 | __iwl_free_pages(priv, rxq->pool[i].page); |
344 | dev_kfree_skb(rxq->pool[i].skb); | 345 | rxq->pool[i].page = NULL; |
345 | } | 346 | } |
346 | } | 347 | } |
347 | 348 | ||
348 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 349 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
349 | rxq->dma_addr); | 350 | rxq->dma_addr); |
350 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 351 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
351 | rxq->rb_stts, rxq->rb_stts_dma); | 352 | rxq->rb_stts, rxq->rb_stts_dma); |
352 | rxq->bd = NULL; | 353 | rxq->bd = NULL; |
353 | rxq->rb_stts = NULL; | 354 | rxq->rb_stts = NULL; |
354 | } | 355 | } |
@@ -357,7 +358,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free); | |||
357 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 358 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
358 | { | 359 | { |
359 | struct iwl_rx_queue *rxq = &priv->rxq; | 360 | struct iwl_rx_queue *rxq = &priv->rxq; |
360 | struct pci_dev *dev = priv->pci_dev; | 361 | struct device *dev = &priv->pci_dev->dev; |
361 | int i; | 362 | int i; |
362 | 363 | ||
363 | spin_lock_init(&rxq->lock); | 364 | spin_lock_init(&rxq->lock); |
@@ -365,12 +366,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
365 | INIT_LIST_HEAD(&rxq->rx_used); | 366 | INIT_LIST_HEAD(&rxq->rx_used); |
366 | 367 | ||
367 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 368 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
368 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); | 369 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, |
370 | GFP_KERNEL); | ||
369 | if (!rxq->bd) | 371 | if (!rxq->bd) |
370 | goto err_bd; | 372 | goto err_bd; |
371 | 373 | ||
372 | rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), | 374 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), |
373 | &rxq->rb_stts_dma); | 375 | &rxq->rb_stts_dma, GFP_KERNEL); |
374 | if (!rxq->rb_stts) | 376 | if (!rxq->rb_stts) |
375 | goto err_rb; | 377 | goto err_rb; |
376 | 378 | ||
@@ -387,8 +389,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
387 | return 0; | 389 | return 0; |
388 | 390 | ||
389 | err_rb: | 391 | err_rb: |
390 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 392 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
391 | rxq->dma_addr); | 393 | rxq->dma_addr); |
392 | err_bd: | 394 | err_bd: |
393 | return -ENOMEM; | 395 | return -ENOMEM; |
394 | } | 396 | } |
@@ -405,14 +407,12 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
405 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | 407 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { |
406 | /* In the reset function, these buffers may have been allocated | 408 | /* In the reset function, these buffers may have been allocated |
407 | * to an SKB, so we need to unmap and free potential storage */ | 409 | * to an SKB, so we need to unmap and free potential storage */ |
408 | if (rxq->pool[i].skb != NULL) { | 410 | if (rxq->pool[i].page != NULL) { |
409 | pci_unmap_single(priv->pci_dev, | 411 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
410 | rxq->pool[i].real_dma_addr, | 412 | PAGE_SIZE << priv->hw_params.rx_page_order, |
411 | priv->hw_params.rx_buf_size + 256, | 413 | PCI_DMA_FROMDEVICE); |
412 | PCI_DMA_FROMDEVICE); | 414 | __iwl_free_pages(priv, rxq->pool[i].page); |
413 | priv->alloc_rxb_skb--; | 415 | rxq->pool[i].page = NULL; |
414 | dev_kfree_skb(rxq->pool[i].skb); | ||
415 | rxq->pool[i].skb = NULL; | ||
416 | } | 416 | } |
417 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | 417 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); |
418 | } | 418 | } |
@@ -470,7 +470,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
470 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | 470 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| |
471 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | 471 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); |
472 | 472 | ||
473 | iwl_write32(priv, CSR_INT_COALESCING, 0x40); | 473 | /* Set interrupt coalescing timer to default (2048 usecs) */ |
474 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
474 | 475 | ||
475 | return 0; | 476 | return 0; |
476 | } | 477 | } |
@@ -491,13 +492,14 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
491 | struct iwl_rx_mem_buffer *rxb) | 492 | struct iwl_rx_mem_buffer *rxb) |
492 | 493 | ||
493 | { | 494 | { |
494 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 495 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
495 | struct iwl_missed_beacon_notif *missed_beacon; | 496 | struct iwl_missed_beacon_notif *missed_beacon; |
496 | 497 | ||
497 | missed_beacon = &pkt->u.missed_beacon; | 498 | missed_beacon = &pkt->u.missed_beacon; |
498 | if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { | 499 | if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) > |
500 | priv->missed_beacon_threshold) { | ||
499 | IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", | 501 | IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", |
500 | le32_to_cpu(missed_beacon->consequtive_missed_beacons), | 502 | le32_to_cpu(missed_beacon->consecutive_missed_beacons), |
501 | le32_to_cpu(missed_beacon->total_missed_becons), | 503 | le32_to_cpu(missed_beacon->total_missed_becons), |
502 | le32_to_cpu(missed_beacon->num_recvd_beacons), | 504 | le32_to_cpu(missed_beacon->num_recvd_beacons), |
503 | le32_to_cpu(missed_beacon->num_expected_beacons)); | 505 | le32_to_cpu(missed_beacon->num_expected_beacons)); |
@@ -507,6 +509,24 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
507 | } | 509 | } |
508 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); | 510 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); |
509 | 511 | ||
512 | void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
513 | struct iwl_rx_mem_buffer *rxb) | ||
514 | { | ||
515 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
516 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | ||
517 | |||
518 | if (!report->state) { | ||
519 | IWL_DEBUG_11H(priv, | ||
520 | "Spectrum Measure Notification: Start\n"); | ||
521 | return; | ||
522 | } | ||
523 | |||
524 | memcpy(&priv->measure_report, report, sizeof(*report)); | ||
525 | priv->measurement_status |= MEASUREMENT_READY; | ||
526 | } | ||
527 | EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); | ||
528 | |||
529 | |||
510 | 530 | ||
511 | /* Calculate noise level, based on measurements during network silence just | 531 | /* Calculate noise level, based on measurements during network silence just |
512 | * before arriving beacon. This measurement can be done only if we know | 532 | * before arriving beacon. This measurement can be done only if we know |
@@ -548,13 +568,64 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
548 | priv->last_rx_noise); | 568 | priv->last_rx_noise); |
549 | } | 569 | } |
550 | 570 | ||
571 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
572 | /* | ||
573 | * based on the assumption of all statistics counter are in DWORD | ||
574 | * FIXME: This function is for debugging, do not deal with | ||
575 | * the case of counters roll-over. | ||
576 | */ | ||
577 | static void iwl_accumulative_statistics(struct iwl_priv *priv, | ||
578 | __le32 *stats) | ||
579 | { | ||
580 | int i; | ||
581 | __le32 *prev_stats; | ||
582 | u32 *accum_stats; | ||
583 | u32 *delta, *max_delta; | ||
584 | |||
585 | prev_stats = (__le32 *)&priv->statistics; | ||
586 | accum_stats = (u32 *)&priv->accum_statistics; | ||
587 | delta = (u32 *)&priv->delta_statistics; | ||
588 | max_delta = (u32 *)&priv->max_delta; | ||
589 | |||
590 | for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); | ||
591 | i += sizeof(__le32), stats++, prev_stats++, delta++, | ||
592 | max_delta++, accum_stats++) { | ||
593 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { | ||
594 | *delta = (le32_to_cpu(*stats) - | ||
595 | le32_to_cpu(*prev_stats)); | ||
596 | *accum_stats += *delta; | ||
597 | if (*delta > *max_delta) | ||
598 | *max_delta = *delta; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | /* reset accumulative statistics for "no-counter" type statistics */ | ||
603 | priv->accum_statistics.general.temperature = | ||
604 | priv->statistics.general.temperature; | ||
605 | priv->accum_statistics.general.temperature_m = | ||
606 | priv->statistics.general.temperature_m; | ||
607 | priv->accum_statistics.general.ttl_timestamp = | ||
608 | priv->statistics.general.ttl_timestamp; | ||
609 | priv->accum_statistics.tx.tx_power.ant_a = | ||
610 | priv->statistics.tx.tx_power.ant_a; | ||
611 | priv->accum_statistics.tx.tx_power.ant_b = | ||
612 | priv->statistics.tx.tx_power.ant_b; | ||
613 | priv->accum_statistics.tx.tx_power.ant_c = | ||
614 | priv->statistics.tx.tx_power.ant_c; | ||
615 | } | ||
616 | #endif | ||
617 | |||
551 | #define REG_RECALIB_PERIOD (60) | 618 | #define REG_RECALIB_PERIOD (60) |
552 | 619 | ||
620 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | ||
553 | void iwl_rx_statistics(struct iwl_priv *priv, | 621 | void iwl_rx_statistics(struct iwl_priv *priv, |
554 | struct iwl_rx_mem_buffer *rxb) | 622 | struct iwl_rx_mem_buffer *rxb) |
555 | { | 623 | { |
556 | int change; | 624 | int change; |
557 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 625 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
626 | int combined_plcp_delta; | ||
627 | unsigned int plcp_msec; | ||
628 | unsigned long plcp_received_jiffies; | ||
558 | 629 | ||
559 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 630 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
560 | (int)sizeof(priv->statistics), | 631 | (int)sizeof(priv->statistics), |
@@ -566,6 +637,59 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
566 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 637 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
567 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 638 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
568 | 639 | ||
640 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
641 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
642 | #endif | ||
643 | /* | ||
644 | * check for plcp_err and trigger radio reset if it exceeds | ||
645 | * the plcp error threshold plcp_delta. | ||
646 | */ | ||
647 | plcp_received_jiffies = jiffies; | ||
648 | plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - | ||
649 | (long) priv->plcp_jiffies); | ||
650 | priv->plcp_jiffies = plcp_received_jiffies; | ||
651 | /* | ||
652 | * check to make sure plcp_msec is not 0 to prevent division | ||
653 | * by zero. | ||
654 | */ | ||
655 | if (plcp_msec) { | ||
656 | combined_plcp_delta = | ||
657 | (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - | ||
658 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) + | ||
659 | (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - | ||
660 | le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); | ||
661 | |||
662 | if ((combined_plcp_delta > 0) && | ||
663 | ((combined_plcp_delta * 100) / plcp_msec) > | ||
664 | priv->cfg->plcp_delta_threshold) { | ||
665 | /* | ||
666 | * if plcp_err exceed the threshold, the following | ||
667 | * data is printed in csv format: | ||
668 | * Text: plcp_err exceeded %d, | ||
669 | * Received ofdm.plcp_err, | ||
670 | * Current ofdm.plcp_err, | ||
671 | * Received ofdm_ht.plcp_err, | ||
672 | * Current ofdm_ht.plcp_err, | ||
673 | * combined_plcp_delta, | ||
674 | * plcp_msec | ||
675 | */ | ||
676 | IWL_DEBUG_RADIO(priv, PLCP_MSG, | ||
677 | priv->cfg->plcp_delta_threshold, | ||
678 | le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), | ||
679 | le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), | ||
680 | le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), | ||
681 | le32_to_cpu( | ||
682 | priv->statistics.rx.ofdm_ht.plcp_err), | ||
683 | combined_plcp_delta, plcp_msec); | ||
684 | |||
685 | /* | ||
686 | * Reset the RF radio due to the high plcp | ||
687 | * error rate | ||
688 | */ | ||
689 | iwl_force_reset(priv, IWL_RF_RESET); | ||
690 | } | ||
691 | } | ||
692 | |||
569 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | 693 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); |
570 | 694 | ||
571 | set_bit(STATUS_STATISTICS, &priv->status); | 695 | set_bit(STATUS_STATISTICS, &priv->status); |
@@ -582,54 +706,30 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
582 | iwl_rx_calc_noise(priv); | 706 | iwl_rx_calc_noise(priv); |
583 | queue_work(priv->workqueue, &priv->run_time_calib_work); | 707 | queue_work(priv->workqueue, &priv->run_time_calib_work); |
584 | } | 708 | } |
585 | |||
586 | iwl_leds_background(priv); | ||
587 | |||
588 | if (priv->cfg->ops->lib->temp_ops.temperature && change) | 709 | if (priv->cfg->ops->lib->temp_ops.temperature && change) |
589 | priv->cfg->ops->lib->temp_ops.temperature(priv); | 710 | priv->cfg->ops->lib->temp_ops.temperature(priv); |
590 | } | 711 | } |
591 | EXPORT_SYMBOL(iwl_rx_statistics); | 712 | EXPORT_SYMBOL(iwl_rx_statistics); |
592 | 713 | ||
593 | #define PERFECT_RSSI (-20) /* dBm */ | 714 | void iwl_reply_statistics(struct iwl_priv *priv, |
594 | #define WORST_RSSI (-95) /* dBm */ | 715 | struct iwl_rx_mem_buffer *rxb) |
595 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
596 | |||
597 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
598 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
599 | * about formulas used below. */ | ||
600 | static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
601 | { | 716 | { |
602 | int sig_qual; | 717 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
603 | int degradation = PERFECT_RSSI - rssi_dbm; | 718 | |
604 | 719 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { | |
605 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | 720 | #ifdef CONFIG_IWLWIFI_DEBUG |
606 | * as indicator; formula is (signal dbm - noise dbm). | 721 | memset(&priv->accum_statistics, 0, |
607 | * SNR at or above 40 is a great signal (100%). | 722 | sizeof(struct iwl_notif_statistics)); |
608 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | 723 | memset(&priv->delta_statistics, 0, |
609 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | 724 | sizeof(struct iwl_notif_statistics)); |
610 | if (noise_dbm) { | 725 | memset(&priv->max_delta, 0, |
611 | if (rssi_dbm - noise_dbm >= 40) | 726 | sizeof(struct iwl_notif_statistics)); |
612 | return 100; | 727 | #endif |
613 | else if (rssi_dbm < noise_dbm) | 728 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); |
614 | return 0; | 729 | } |
615 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | 730 | iwl_rx_statistics(priv, rxb); |
616 | |||
617 | /* Else use just the signal level. | ||
618 | * This formula is a least squares fit of data points collected and | ||
619 | * compared with a reference system that had a percentage (%) display | ||
620 | * for signal quality. */ | ||
621 | } else | ||
622 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
623 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
624 | (RSSI_RANGE * RSSI_RANGE); | ||
625 | |||
626 | if (sig_qual > 100) | ||
627 | sig_qual = 100; | ||
628 | else if (sig_qual < 1) | ||
629 | sig_qual = 0; | ||
630 | |||
631 | return sig_qual; | ||
632 | } | 731 | } |
732 | EXPORT_SYMBOL(iwl_reply_statistics); | ||
633 | 733 | ||
634 | /* Calc max signal level (dBm) among 3 possible receivers */ | 734 | /* Calc max signal level (dBm) among 3 possible receivers */ |
635 | static inline int iwl_calc_rssi(struct iwl_priv *priv, | 735 | static inline int iwl_calc_rssi(struct iwl_priv *priv, |
@@ -878,6 +978,10 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
878 | struct iwl_rx_mem_buffer *rxb, | 978 | struct iwl_rx_mem_buffer *rxb, |
879 | struct ieee80211_rx_status *stats) | 979 | struct ieee80211_rx_status *stats) |
880 | { | 980 | { |
981 | struct sk_buff *skb; | ||
982 | int ret = 0; | ||
983 | __le16 fc = hdr->frame_control; | ||
984 | |||
881 | /* We only process data packets if the interface is open */ | 985 | /* We only process data packets if the interface is open */ |
882 | if (unlikely(!priv->is_open)) { | 986 | if (unlikely(!priv->is_open)) { |
883 | IWL_DEBUG_DROP_LIMIT(priv, | 987 | IWL_DEBUG_DROP_LIMIT(priv, |
@@ -890,15 +994,47 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
890 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | 994 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) |
891 | return; | 995 | return; |
892 | 996 | ||
893 | /* Resize SKB from mac header to end of packet */ | 997 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); |
894 | skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data); | 998 | if (!skb) { |
895 | skb_put(rxb->skb, len); | 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 | } | ||
896 | 1025 | ||
897 | iwl_update_stats(priv, false, hdr->frame_control, len); | 1026 | /* |
898 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 1027 | * XXX: We cannot touch the page and its virtual memory (hdr) after |
899 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); | 1028 | * here. It might have already been freed by the above skb change. |
900 | priv->alloc_rxb_skb--; | 1029 | */ |
901 | rxb->skb = NULL; | 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; | ||
902 | } | 1038 | } |
903 | 1039 | ||
904 | /* This is necessary only for a number of statistics, see the caller. */ | 1040 | /* This is necessary only for a number of statistics, see the caller. */ |
@@ -926,13 +1062,12 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
926 | { | 1062 | { |
927 | struct ieee80211_hdr *header; | 1063 | struct ieee80211_hdr *header; |
928 | struct ieee80211_rx_status rx_status; | 1064 | struct ieee80211_rx_status rx_status; |
929 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1065 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
930 | struct iwl_rx_phy_res *phy_res; | 1066 | struct iwl_rx_phy_res *phy_res; |
931 | __le32 rx_pkt_status; | 1067 | __le32 rx_pkt_status; |
932 | struct iwl4965_rx_mpdu_res_start *amsdu; | 1068 | struct iwl4965_rx_mpdu_res_start *amsdu; |
933 | u32 len; | 1069 | u32 len; |
934 | u32 ampdu_status; | 1070 | u32 ampdu_status; |
935 | u16 fc; | ||
936 | u32 rate_n_flags; | 1071 | u32 rate_n_flags; |
937 | 1072 | ||
938 | /** | 1073 | /** |
@@ -1009,11 +1144,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1009 | if (iwl_is_associated(priv) && | 1144 | if (iwl_is_associated(priv) && |
1010 | !test_bit(STATUS_SCANNING, &priv->status)) { | 1145 | !test_bit(STATUS_SCANNING, &priv->status)) { |
1011 | rx_status.noise = priv->last_rx_noise; | 1146 | rx_status.noise = priv->last_rx_noise; |
1012 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, | ||
1013 | rx_status.noise); | ||
1014 | } else { | 1147 | } else { |
1015 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 1148 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
1016 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0); | ||
1017 | } | 1149 | } |
1018 | 1150 | ||
1019 | /* Reset beacon noise level if not associated. */ | 1151 | /* Reset beacon noise level if not associated. */ |
@@ -1026,8 +1158,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1026 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); | 1158 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); |
1027 | #endif | 1159 | #endif |
1028 | iwl_dbg_log_rx_data_frame(priv, len, header); | 1160 | iwl_dbg_log_rx_data_frame(priv, len, header); |
1029 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", | 1161 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", |
1030 | rx_status.signal, rx_status.noise, rx_status.qual, | 1162 | rx_status.signal, rx_status.noise, |
1031 | (unsigned long long)rx_status.mactime); | 1163 | (unsigned long long)rx_status.mactime); |
1032 | 1164 | ||
1033 | /* | 1165 | /* |
@@ -1065,20 +1197,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1065 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); | 1197 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); |
1066 | } | 1198 | } |
1067 | 1199 | ||
1068 | fc = le16_to_cpu(header->frame_control); | 1200 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1069 | switch (fc & IEEE80211_FCTL_FTYPE) { | 1201 | rxb, &rx_status); |
1070 | case IEEE80211_FTYPE_MGMT: | ||
1071 | case IEEE80211_FTYPE_DATA: | ||
1072 | if (priv->iw_mode == NL80211_IFTYPE_AP) | ||
1073 | iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
1074 | header->addr2); | ||
1075 | /* fall through */ | ||
1076 | default: | ||
1077 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1078 | rxb, &rx_status); | ||
1079 | break; | ||
1080 | |||
1081 | } | ||
1082 | } | 1202 | } |
1083 | EXPORT_SYMBOL(iwl_rx_reply_rx); | 1203 | EXPORT_SYMBOL(iwl_rx_reply_rx); |
1084 | 1204 | ||
@@ -1087,7 +1207,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx); | |||
1087 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | 1207 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, |
1088 | struct iwl_rx_mem_buffer *rxb) | 1208 | struct iwl_rx_mem_buffer *rxb) |
1089 | { | 1209 | { |
1090 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1210 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1091 | priv->last_phy_res[0] = 1; | 1211 | priv->last_phy_res[0] = 1; |
1092 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | 1212 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), |
1093 | sizeof(struct iwl_rx_phy_res)); | 1213 | sizeof(struct iwl_rx_phy_res)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 4f3a108fa990..741e65ec8301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * GPL LICENSE SUMMARY | 3 | * GPL LICENSE SUMMARY |
4 | * | 4 | * |
5 | * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of version 2 of the GNU General Public License as |
@@ -25,9 +25,9 @@ | |||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | 25 | * Intel Linux Wireless <ilw@linux.intel.com> |
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | *****************************************************************************/ | 27 | *****************************************************************************/ |
28 | #include <linux/slab.h> | ||
28 | #include <linux/types.h> | 29 | #include <linux/types.h> |
29 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
30 | #include <net/lib80211.h> | ||
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | 32 | ||
33 | #include "iwl-eeprom.h" | 33 | #include "iwl-eeprom.h" |
@@ -112,7 +112,7 @@ EXPORT_SYMBOL(iwl_scan_cancel_timeout); | |||
112 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 112 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
113 | { | 113 | { |
114 | int ret = 0; | 114 | int ret = 0; |
115 | struct iwl_rx_packet *res; | 115 | struct iwl_rx_packet *pkt; |
116 | struct iwl_host_cmd cmd = { | 116 | struct iwl_host_cmd cmd = { |
117 | .id = REPLY_SCAN_ABORT_CMD, | 117 | .id = REPLY_SCAN_ABORT_CMD, |
118 | .flags = CMD_WANT_SKB, | 118 | .flags = CMD_WANT_SKB, |
@@ -132,21 +132,20 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
132 | return ret; | 132 | return ret; |
133 | } | 133 | } |
134 | 134 | ||
135 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 135 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
136 | if (res->u.status != CAN_ABORT_STATUS) { | 136 | if (pkt->u.status != CAN_ABORT_STATUS) { |
137 | /* The scan abort will return 1 for success or | 137 | /* The scan abort will return 1 for success or |
138 | * 2 for "failure". A failure condition can be | 138 | * 2 for "failure". A failure condition can be |
139 | * due to simply not being in an active scan which | 139 | * due to simply not being in an active scan which |
140 | * can occur if we send the scan abort before we | 140 | * can occur if we send the scan abort before we |
141 | * the microcode has notified us that a scan is | 141 | * the microcode has notified us that a scan is |
142 | * completed. */ | 142 | * completed. */ |
143 | IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status); | 143 | IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status); |
144 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | 144 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); |
145 | clear_bit(STATUS_SCAN_HW, &priv->status); | 145 | clear_bit(STATUS_SCAN_HW, &priv->status); |
146 | } | 146 | } |
147 | 147 | ||
148 | priv->alloc_rxb_skb--; | 148 | iwl_free_pages(priv, cmd.reply_page); |
149 | dev_kfree_skb_any(cmd.reply_skb); | ||
150 | 149 | ||
151 | return ret; | 150 | return ret; |
152 | } | 151 | } |
@@ -156,7 +155,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
156 | struct iwl_rx_mem_buffer *rxb) | 155 | struct iwl_rx_mem_buffer *rxb) |
157 | { | 156 | { |
158 | #ifdef CONFIG_IWLWIFI_DEBUG | 157 | #ifdef CONFIG_IWLWIFI_DEBUG |
159 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 158 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
160 | struct iwl_scanreq_notification *notif = | 159 | struct iwl_scanreq_notification *notif = |
161 | (struct iwl_scanreq_notification *)pkt->u.raw; | 160 | (struct iwl_scanreq_notification *)pkt->u.raw; |
162 | 161 | ||
@@ -168,7 +167,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
168 | static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | 167 | static void iwl_rx_scan_start_notif(struct iwl_priv *priv, |
169 | struct iwl_rx_mem_buffer *rxb) | 168 | struct iwl_rx_mem_buffer *rxb) |
170 | { | 169 | { |
171 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 170 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
172 | struct iwl_scanstart_notification *notif = | 171 | struct iwl_scanstart_notification *notif = |
173 | (struct iwl_scanstart_notification *)pkt->u.raw; | 172 | (struct iwl_scanstart_notification *)pkt->u.raw; |
174 | priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); | 173 | priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); |
@@ -187,26 +186,24 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, | |||
187 | struct iwl_rx_mem_buffer *rxb) | 186 | struct iwl_rx_mem_buffer *rxb) |
188 | { | 187 | { |
189 | #ifdef CONFIG_IWLWIFI_DEBUG | 188 | #ifdef CONFIG_IWLWIFI_DEBUG |
190 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 189 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
191 | struct iwl_scanresults_notification *notif = | 190 | struct iwl_scanresults_notification *notif = |
192 | (struct iwl_scanresults_notification *)pkt->u.raw; | 191 | (struct iwl_scanresults_notification *)pkt->u.raw; |
193 | 192 | ||
194 | IWL_DEBUG_SCAN(priv, "Scan ch.res: " | 193 | IWL_DEBUG_SCAN(priv, "Scan ch.res: " |
195 | "%d [802.11%s] " | 194 | "%d [802.11%s] " |
196 | "(TSF: 0x%08X:%08X) - %d " | 195 | "(TSF: 0x%08X:%08X) - %d " |
197 | "elapsed=%lu usec (%dms since last)\n", | 196 | "elapsed=%lu usec\n", |
198 | notif->channel, | 197 | notif->channel, |
199 | notif->band ? "bg" : "a", | 198 | notif->band ? "bg" : "a", |
200 | le32_to_cpu(notif->tsf_high), | 199 | le32_to_cpu(notif->tsf_high), |
201 | le32_to_cpu(notif->tsf_low), | 200 | le32_to_cpu(notif->tsf_low), |
202 | le32_to_cpu(notif->statistics[0]), | 201 | le32_to_cpu(notif->statistics[0]), |
203 | le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf, | 202 | le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); |
204 | jiffies_to_msecs(elapsed_jiffies | ||
205 | (priv->last_scan_jiffies, jiffies))); | ||
206 | #endif | 203 | #endif |
207 | 204 | ||
208 | priv->last_scan_jiffies = jiffies; | 205 | if (!priv->is_internal_short_scan) |
209 | priv->next_scan_jiffies = 0; | 206 | priv->next_scan_jiffies = 0; |
210 | } | 207 | } |
211 | 208 | ||
212 | /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ | 209 | /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ |
@@ -214,7 +211,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
214 | struct iwl_rx_mem_buffer *rxb) | 211 | struct iwl_rx_mem_buffer *rxb) |
215 | { | 212 | { |
216 | #ifdef CONFIG_IWLWIFI_DEBUG | 213 | #ifdef CONFIG_IWLWIFI_DEBUG |
217 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 214 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
218 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; | 215 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; |
219 | 216 | ||
220 | IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", | 217 | IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", |
@@ -252,8 +249,9 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
252 | goto reschedule; | 249 | goto reschedule; |
253 | } | 250 | } |
254 | 251 | ||
255 | priv->last_scan_jiffies = jiffies; | 252 | if (!priv->is_internal_short_scan) |
256 | priv->next_scan_jiffies = 0; | 253 | priv->next_scan_jiffies = 0; |
254 | |||
257 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); | 255 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); |
258 | 256 | ||
259 | clear_bit(STATUS_SCANNING, &priv->status); | 257 | clear_bit(STATUS_SCANNING, &priv->status); |
@@ -316,6 +314,72 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
316 | } | 314 | } |
317 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); | 315 | EXPORT_SYMBOL(iwl_get_passive_dwell_time); |
318 | 316 | ||
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 | |||
319 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | 383 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, |
320 | enum ieee80211_band band, | 384 | enum ieee80211_band band, |
321 | u8 is_active, u8 n_probes, | 385 | u8 is_active, u8 n_probes, |
@@ -402,26 +466,15 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
402 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 466 | if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) |
403 | priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; | 467 | priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; |
404 | } | 468 | } |
469 | EXPORT_SYMBOL(iwl_init_scan_params); | ||
405 | 470 | ||
406 | static int iwl_scan_initiate(struct iwl_priv *priv) | 471 | static int iwl_scan_initiate(struct iwl_priv *priv) |
407 | { | 472 | { |
408 | if (!iwl_is_ready_rf(priv)) { | 473 | WARN_ON(!mutex_is_locked(&priv->mutex)); |
409 | IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n"); | ||
410 | return -EIO; | ||
411 | } | ||
412 | |||
413 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
414 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
415 | return -EAGAIN; | ||
416 | } | ||
417 | |||
418 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
419 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
420 | return -EAGAIN; | ||
421 | } | ||
422 | 474 | ||
423 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 475 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); |
424 | set_bit(STATUS_SCANNING, &priv->status); | 476 | set_bit(STATUS_SCANNING, &priv->status); |
477 | priv->is_internal_short_scan = false; | ||
425 | priv->scan_start = jiffies; | 478 | priv->scan_start = jiffies; |
426 | priv->scan_pass_start = priv->scan_start; | 479 | priv->scan_pass_start = priv->scan_start; |
427 | 480 | ||
@@ -450,6 +503,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
450 | goto out_unlock; | 503 | goto out_unlock; |
451 | } | 504 | } |
452 | 505 | ||
506 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
507 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
508 | ret = -EAGAIN; | ||
509 | goto out_unlock; | ||
510 | } | ||
511 | |||
512 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
513 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
514 | ret = -EAGAIN; | ||
515 | goto out_unlock; | ||
516 | } | ||
517 | |||
453 | /* We don't schedule scan within next_scan_jiffies period. | 518 | /* We don't schedule scan within next_scan_jiffies period. |
454 | * Avoid scanning during possible EAPOL exchange, return | 519 | * Avoid scanning during possible EAPOL exchange, return |
455 | * success immediately. | 520 | * success immediately. |
@@ -462,15 +527,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
462 | goto out_unlock; | 527 | goto out_unlock; |
463 | } | 528 | } |
464 | 529 | ||
465 | /* if we just finished scan ask for delay */ | ||
466 | if (iwl_is_associated(priv) && priv->last_scan_jiffies && | ||
467 | time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { | ||
468 | IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n"); | ||
469 | queue_work(priv->workqueue, &priv->scan_completed); | ||
470 | ret = 0; | ||
471 | goto out_unlock; | ||
472 | } | ||
473 | |||
474 | priv->scan_bands = 0; | 530 | priv->scan_bands = 0; |
475 | for (i = 0; i < req->n_channels; i++) | 531 | for (i = 0; i < req->n_channels; i++) |
476 | priv->scan_bands |= BIT(req->channels[i]->band); | 532 | priv->scan_bands |= BIT(req->channels[i]->band); |
@@ -489,6 +545,52 @@ out_unlock: | |||
489 | } | 545 | } |
490 | EXPORT_SYMBOL(iwl_mac_hw_scan); | 546 | EXPORT_SYMBOL(iwl_mac_hw_scan); |
491 | 547 | ||
548 | /* | ||
549 | * internal short scan, this function should only been called while associated. | ||
550 | * It will reset and tune the radio to prevent possible RF related problem | ||
551 | */ | ||
552 | void iwl_internal_short_hw_scan(struct iwl_priv *priv) | ||
553 | { | ||
554 | queue_work(priv->workqueue, &priv->start_internal_scan); | ||
555 | } | ||
556 | |||
557 | static void iwl_bg_start_internal_scan(struct work_struct *work) | ||
558 | { | ||
559 | struct iwl_priv *priv = | ||
560 | container_of(work, struct iwl_priv, start_internal_scan); | ||
561 | |||
562 | mutex_lock(&priv->mutex); | ||
563 | |||
564 | if (!iwl_is_ready_rf(priv)) { | ||
565 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | ||
566 | goto unlock; | ||
567 | } | ||
568 | |||
569 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
570 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
571 | goto unlock; | ||
572 | } | ||
573 | |||
574 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
575 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
576 | goto unlock; | ||
577 | } | ||
578 | |||
579 | priv->scan_bands = 0; | ||
580 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
581 | priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); | ||
582 | else | ||
583 | priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); | ||
584 | |||
585 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); | ||
586 | set_bit(STATUS_SCANNING, &priv->status); | ||
587 | priv->is_internal_short_scan = true; | ||
588 | queue_work(priv->workqueue, &priv->request_scan); | ||
589 | unlock: | ||
590 | mutex_unlock(&priv->mutex); | ||
591 | } | ||
592 | EXPORT_SYMBOL(iwl_internal_short_hw_scan); | ||
593 | |||
492 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) | 594 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) |
493 | 595 | ||
494 | void iwl_bg_scan_check(struct work_struct *data) | 596 | void iwl_bg_scan_check(struct work_struct *data) |
@@ -552,7 +654,8 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
552 | if (WARN_ON(left < ie_len)) | 654 | if (WARN_ON(left < ie_len)) |
553 | return len; | 655 | return len; |
554 | 656 | ||
555 | memcpy(pos, ies, ie_len); | 657 | if (ies) |
658 | memcpy(pos, ies, ie_len); | ||
556 | len += ie_len; | 659 | len += ie_len; |
557 | left -= ie_len; | 660 | left -= ie_len; |
558 | 661 | ||
@@ -581,6 +684,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
581 | u8 rate; | 684 | u8 rate; |
582 | bool is_active = false; | 685 | bool is_active = false; |
583 | int chan_mod; | 686 | int chan_mod; |
687 | u8 active_chains; | ||
584 | 688 | ||
585 | conf = ieee80211_get_hw_conf(priv->hw); | 689 | conf = ieee80211_get_hw_conf(priv->hw); |
586 | 690 | ||
@@ -654,7 +758,6 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
654 | unsigned long flags; | 758 | unsigned long flags; |
655 | 759 | ||
656 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 760 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
657 | |||
658 | spin_lock_irqsave(&priv->lock, flags); | 761 | spin_lock_irqsave(&priv->lock, flags); |
659 | interval = priv->beacon_int; | 762 | interval = priv->beacon_int; |
660 | spin_unlock_irqrestore(&priv->lock, flags); | 763 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -672,7 +775,9 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
672 | scan_suspend_time, interval); | 775 | scan_suspend_time, interval); |
673 | } | 776 | } |
674 | 777 | ||
675 | if (priv->scan_request->n_ssids) { | 778 | if (priv->is_internal_short_scan) { |
779 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
780 | } else if (priv->scan_request->n_ssids) { | ||
676 | int i, p = 0; | 781 | int i, p = 0; |
677 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 782 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
678 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 783 | for (i = 0; i < priv->scan_request->n_ssids; i++) { |
@@ -708,16 +813,29 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
708 | rate = IWL_RATE_1M_PLCP; | 813 | rate = IWL_RATE_1M_PLCP; |
709 | rate_flags = RATE_MCS_CCK_MSK; | 814 | rate_flags = RATE_MCS_CCK_MSK; |
710 | } | 815 | } |
711 | scan->good_CRC_th = 0; | 816 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; |
712 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { | 817 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { |
713 | band = IEEE80211_BAND_5GHZ; | 818 | band = IEEE80211_BAND_5GHZ; |
714 | rate = IWL_RATE_6M_PLCP; | 819 | rate = IWL_RATE_6M_PLCP; |
715 | /* | 820 | /* |
716 | * If active scaning is requested but a certain channel | 821 | * If active scanning is requested but a certain channel is |
717 | * is marked passive, we can do active scanning if we | 822 | * marked passive, we can do active scanning if we detect |
718 | * detect transmissions. | 823 | * transmissions. |
824 | * | ||
825 | * There is an issue with some firmware versions that triggers | ||
826 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
827 | * on a radar channel even though this means that we should NOT | ||
828 | * send probes. | ||
829 | * | ||
830 | * The "good CRC threshold" is the number of frames that we | ||
831 | * need to receive during our dwell time on a channel before | ||
832 | * sending out probes -- setting this to a huge value will | ||
833 | * mean we never reach it, but at the same time work around | ||
834 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
835 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
719 | */ | 836 | */ |
720 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 837 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
838 | IWL_GOOD_CRC_TH_NEVER; | ||
721 | 839 | ||
722 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | 840 | /* Force use of chains B and C (0x6) for scan Rx for 4965 |
723 | * Avoid A (0x1) because of its off-channel reception on A-band. | 841 | * Avoid A (0x1) because of its off-channel reception on A-band. |
@@ -734,30 +852,57 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
734 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | 852 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); |
735 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | 853 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); |
736 | 854 | ||
855 | /* In power save mode use one chain, otherwise use all chains */ | ||
856 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
857 | /* rx_ant has been set to all valid chains previously */ | ||
858 | active_chains = rx_ant & | ||
859 | ((u8)(priv->chain_noise_data.active_chains)); | ||
860 | if (!active_chains) | ||
861 | active_chains = rx_ant; | ||
862 | |||
863 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
864 | priv->chain_noise_data.active_chains); | ||
865 | |||
866 | rx_ant = first_antenna(active_chains); | ||
867 | } | ||
737 | /* MIMO is not used here, but value is required */ | 868 | /* MIMO is not used here, but value is required */ |
738 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS; | 869 | rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; |
739 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 870 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
740 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 871 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; |
741 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 872 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; |
742 | scan->rx_chain = cpu_to_le16(rx_chain); | 873 | scan->rx_chain = cpu_to_le16(rx_chain); |
743 | cmd_len = iwl_fill_probe_req(priv, | 874 | if (!priv->is_internal_short_scan) { |
744 | (struct ieee80211_mgmt *)scan->data, | 875 | cmd_len = iwl_fill_probe_req(priv, |
745 | priv->scan_request->ie, | 876 | (struct ieee80211_mgmt *)scan->data, |
746 | priv->scan_request->ie_len, | 877 | priv->scan_request->ie, |
747 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 878 | priv->scan_request->ie_len, |
879 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
880 | } else { | ||
881 | cmd_len = iwl_fill_probe_req(priv, | ||
882 | (struct ieee80211_mgmt *)scan->data, | ||
883 | NULL, 0, | ||
884 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
748 | 885 | ||
886 | } | ||
749 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | 887 | scan->tx_cmd.len = cpu_to_le16(cmd_len); |
750 | |||
751 | if (iwl_is_monitor_mode(priv)) | 888 | if (iwl_is_monitor_mode(priv)) |
752 | scan->filter_flags = RXON_FILTER_PROMISC_MSK; | 889 | scan->filter_flags = RXON_FILTER_PROMISC_MSK; |
753 | 890 | ||
754 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | 891 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | |
755 | RXON_FILTER_BCON_AWARE_MSK); | 892 | RXON_FILTER_BCON_AWARE_MSK); |
756 | 893 | ||
757 | scan->channel_count = | 894 | if (priv->is_internal_short_scan) { |
758 | iwl_get_channels_for_scan(priv, band, is_active, n_probes, | 895 | scan->channel_count = |
759 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | 896 | iwl_get_single_channel_for_scan(priv, band, |
760 | 897 | (void *)&scan->data[le16_to_cpu( | |
898 | scan->tx_cmd.len)]); | ||
899 | } else { | ||
900 | scan->channel_count = | ||
901 | iwl_get_channels_for_scan(priv, band, | ||
902 | is_active, n_probes, | ||
903 | (void *)&scan->data[le16_to_cpu( | ||
904 | scan->tx_cmd.len)]); | ||
905 | } | ||
761 | if (scan->channel_count == 0) { | 906 | if (scan->channel_count == 0) { |
762 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | 907 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); |
763 | goto done; | 908 | goto done; |
@@ -818,7 +963,12 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
818 | 963 | ||
819 | cancel_delayed_work(&priv->scan_check); | 964 | cancel_delayed_work(&priv->scan_check); |
820 | 965 | ||
821 | ieee80211_scan_completed(priv->hw, false); | 966 | if (!priv->is_internal_short_scan) |
967 | ieee80211_scan_completed(priv->hw, false); | ||
968 | else { | ||
969 | priv->is_internal_short_scan = false; | ||
970 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | ||
971 | } | ||
822 | 972 | ||
823 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 973 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
824 | return; | 974 | return; |
@@ -836,6 +986,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | |||
836 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 986 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); |
837 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); | 987 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); |
838 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 988 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); |
989 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | ||
839 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 990 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
840 | } | 991 | } |
841 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); | 992 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c deleted file mode 100644 index 022bcf115731..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ /dev/null | |||
@@ -1,198 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
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/pci.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/netdevice.h> | ||
37 | #include <linux/wireless.h> | ||
38 | |||
39 | #include <net/mac80211.h> | ||
40 | |||
41 | #include "iwl-eeprom.h" | ||
42 | #include "iwl-dev.h" | ||
43 | #include "iwl-core.h" | ||
44 | #include "iwl-io.h" | ||
45 | #include "iwl-spectrum.h" | ||
46 | |||
47 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | ||
48 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | ||
49 | #define TIME_UNIT 1024 | ||
50 | |||
51 | /* | ||
52 | * extended beacon time format | ||
53 | * time in usec will be changed into a 32-bit value in 8:24 format | ||
54 | * the high 1 byte is the beacon counts | ||
55 | * the lower 3 bytes is the time in usec within one beacon interval | ||
56 | */ | ||
57 | |||
58 | /* TOOD: was used in sysfs debug interface need to add to mac */ | ||
59 | #if 0 | ||
60 | static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval) | ||
61 | { | ||
62 | u32 quot; | ||
63 | u32 rem; | ||
64 | u32 interval = beacon_interval * 1024; | ||
65 | |||
66 | if (!interval || !usec) | ||
67 | return 0; | ||
68 | |||
69 | quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); | ||
70 | rem = (usec % interval) & BEACON_TIME_MASK_LOW; | ||
71 | |||
72 | return (quot << 24) + rem; | ||
73 | } | ||
74 | |||
75 | /* base is usually what we get from ucode with each received frame, | ||
76 | * the same as HW timer counter counting down | ||
77 | */ | ||
78 | |||
79 | static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) | ||
80 | { | ||
81 | u32 base_low = base & BEACON_TIME_MASK_LOW; | ||
82 | u32 addon_low = addon & BEACON_TIME_MASK_LOW; | ||
83 | u32 interval = beacon_interval * TIME_UNIT; | ||
84 | u32 res = (base & BEACON_TIME_MASK_HIGH) + | ||
85 | (addon & BEACON_TIME_MASK_HIGH); | ||
86 | |||
87 | if (base_low > addon_low) | ||
88 | res += base_low - addon_low; | ||
89 | else if (base_low < addon_low) { | ||
90 | res += interval + base_low - addon_low; | ||
91 | res += (1 << 24); | ||
92 | } else | ||
93 | res += (1 << 24); | ||
94 | |||
95 | return cpu_to_le32(res); | ||
96 | } | ||
97 | static int iwl_get_measurement(struct iwl_priv *priv, | ||
98 | struct ieee80211_measurement_params *params, | ||
99 | u8 type) | ||
100 | { | ||
101 | struct iwl4965_spectrum_cmd spectrum; | ||
102 | struct iwl_rx_packet *res; | ||
103 | struct iwl_host_cmd cmd = { | ||
104 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, | ||
105 | .data = (void *)&spectrum, | ||
106 | .meta.flags = CMD_WANT_SKB, | ||
107 | }; | ||
108 | u32 add_time = le64_to_cpu(params->start_time); | ||
109 | int rc; | ||
110 | int spectrum_resp_status; | ||
111 | int duration = le16_to_cpu(params->duration); | ||
112 | |||
113 | if (iwl_is_associated(priv)) | ||
114 | add_time = | ||
115 | iwl_usecs_to_beacons( | ||
116 | le64_to_cpu(params->start_time) - priv->last_tsf, | ||
117 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | ||
118 | |||
119 | memset(&spectrum, 0, sizeof(spectrum)); | ||
120 | |||
121 | spectrum.channel_count = cpu_to_le16(1); | ||
122 | spectrum.flags = | ||
123 | RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; | ||
124 | spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; | ||
125 | cmd.len = sizeof(spectrum); | ||
126 | spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); | ||
127 | |||
128 | if (iwl_is_associated(priv)) | ||
129 | spectrum.start_time = | ||
130 | iwl_add_beacon_time(priv->last_beacon_time, | ||
131 | add_time, | ||
132 | le16_to_cpu(priv->rxon_timing.beacon_interval)); | ||
133 | else | ||
134 | spectrum.start_time = 0; | ||
135 | |||
136 | spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); | ||
137 | spectrum.channels[0].channel = params->channel; | ||
138 | spectrum.channels[0].type = type; | ||
139 | if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) | ||
140 | spectrum.flags |= RXON_FLG_BAND_24G_MSK | | ||
141 | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; | ||
142 | |||
143 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
144 | if (rc) | ||
145 | return rc; | ||
146 | |||
147 | res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; | ||
148 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
149 | IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); | ||
150 | rc = -EIO; | ||
151 | } | ||
152 | |||
153 | spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); | ||
154 | switch (spectrum_resp_status) { | ||
155 | case 0: /* Command will be handled */ | ||
156 | if (res->u.spectrum.id != 0xff) { | ||
157 | IWL_DEBUG_INFO(priv, | ||
158 | "Replaced existing measurement: %d\n", | ||
159 | res->u.spectrum.id); | ||
160 | priv->measurement_status &= ~MEASUREMENT_READY; | ||
161 | } | ||
162 | priv->measurement_status |= MEASUREMENT_ACTIVE; | ||
163 | rc = 0; | ||
164 | break; | ||
165 | |||
166 | case 1: /* Command will not be handled */ | ||
167 | rc = -EAGAIN; | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | dev_kfree_skb_any(cmd.meta.u.skb); | ||
172 | |||
173 | return rc; | ||
174 | } | ||
175 | #endif | ||
176 | |||
177 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | ||
178 | struct iwl_rx_mem_buffer *rxb) | ||
179 | { | ||
180 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
181 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | ||
182 | |||
183 | if (!report->state) { | ||
184 | IWL_DEBUG_11H(priv, | ||
185 | "Spectrum Measure Notification: Start\n"); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | memcpy(&priv->measure_report, report, sizeof(*report)); | ||
190 | priv->measurement_status |= MEASUREMENT_READY; | ||
191 | } | ||
192 | |||
193 | void iwl_setup_spectrum_handlers(struct iwl_priv *priv) | ||
194 | { | ||
195 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
196 | iwl_rx_spectrum_measure_notif; | ||
197 | } | ||
198 | EXPORT_SYMBOL(iwl_setup_spectrum_handlers); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index a77c1e619062..af6babee2891 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ieee80211 subsystem header files. | 5 | * Portions of this file are derived from the ieee80211 subsystem header files. |
6 | * | 6 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c6633fec8216..4a6686fa6b36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -80,59 +80,109 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
80 | } | 80 | } |
81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | 81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); |
82 | 82 | ||
83 | /* priv->sta_lock must be held */ | ||
83 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 84 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) |
84 | { | 85 | { |
85 | unsigned long flags; | ||
86 | |||
87 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
88 | 86 | ||
89 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) | 87 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) |
90 | IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", | 88 | IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n", |
91 | sta_id); | 89 | sta_id, priv->stations[sta_id].sta.sta.addr); |
92 | |||
93 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | ||
94 | IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n", | ||
95 | priv->stations[sta_id].sta.sta.addr); | ||
96 | 90 | ||
97 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 91 | if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) { |
92 | IWL_DEBUG_ASSOC(priv, | ||
93 | "STA id %u addr %pM already present in uCode (according to driver)\n", | ||
94 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
95 | } else { | ||
96 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | ||
97 | IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", | ||
98 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
99 | } | ||
98 | } | 100 | } |
99 | 101 | ||
100 | static void iwl_add_sta_callback(struct iwl_priv *priv, | 102 | static void iwl_process_add_sta_resp(struct iwl_priv *priv, |
101 | struct iwl_device_cmd *cmd, | 103 | struct iwl_addsta_cmd *addsta, |
102 | struct sk_buff *skb) | 104 | struct iwl_rx_packet *pkt, |
105 | bool sync) | ||
103 | { | 106 | { |
104 | struct iwl_rx_packet *res = NULL; | ||
105 | struct iwl_addsta_cmd *addsta = | ||
106 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | ||
107 | u8 sta_id = addsta->sta.sta_id; | 107 | u8 sta_id = addsta->sta.sta_id; |
108 | unsigned long flags; | ||
108 | 109 | ||
109 | if (!skb) { | 110 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
110 | IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | res = (struct iwl_rx_packet *)skb->data; | ||
115 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
116 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | 111 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", |
117 | res->hdr.flags); | 112 | pkt->hdr.flags); |
118 | return; | 113 | return; |
119 | } | 114 | } |
120 | 115 | ||
121 | switch (res->u.add_sta.status) { | 116 | IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", |
117 | sta_id); | ||
118 | |||
119 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
120 | |||
121 | switch (pkt->u.add_sta.status) { | ||
122 | case ADD_STA_SUCCESS_MSK: | 122 | case ADD_STA_SUCCESS_MSK: |
123 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | ||
123 | iwl_sta_ucode_activate(priv, sta_id); | 124 | iwl_sta_ucode_activate(priv, sta_id); |
124 | /* fall through */ | 125 | break; |
126 | case ADD_STA_NO_ROOM_IN_TABLE: | ||
127 | IWL_ERR(priv, "Adding station %d failed, no room in table.\n", | ||
128 | sta_id); | ||
129 | break; | ||
130 | case ADD_STA_NO_BLOCK_ACK_RESOURCE: | ||
131 | IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n", | ||
132 | sta_id); | ||
133 | break; | ||
134 | case ADD_STA_MODIFY_NON_EXIST_STA: | ||
135 | IWL_ERR(priv, "Attempting to modify non-existing station %d \n", | ||
136 | sta_id); | ||
137 | break; | ||
125 | default: | 138 | default: |
126 | IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", | 139 | IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", |
127 | res->u.add_sta.status); | 140 | pkt->u.add_sta.status); |
128 | break; | 141 | break; |
129 | } | 142 | } |
143 | |||
144 | IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n", | ||
145 | priv->stations[sta_id].sta.mode == | ||
146 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | ||
147 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
148 | |||
149 | /* | ||
150 | * XXX: The MAC address in the command buffer is often changed from | ||
151 | * the original sent to the device. That is, the MAC address | ||
152 | * written to the command buffer often is not the same MAC adress | ||
153 | * read from the command buffer when the command returns. This | ||
154 | * issue has not yet been resolved and this debugging is left to | ||
155 | * observe the problem. | ||
156 | */ | ||
157 | IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n", | ||
158 | priv->stations[sta_id].sta.mode == | ||
159 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | ||
160 | 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); | ||
169 | } | ||
170 | |||
171 | static void iwl_add_sta_callback(struct iwl_priv *priv, | ||
172 | struct iwl_device_cmd *cmd, | ||
173 | struct iwl_rx_packet *pkt) | ||
174 | { | ||
175 | struct iwl_addsta_cmd *addsta = | ||
176 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | ||
177 | |||
178 | iwl_process_add_sta_resp(priv, addsta, pkt, false); | ||
179 | |||
130 | } | 180 | } |
131 | 181 | ||
132 | int iwl_send_add_sta(struct iwl_priv *priv, | 182 | int iwl_send_add_sta(struct iwl_priv *priv, |
133 | struct iwl_addsta_cmd *sta, u8 flags) | 183 | struct iwl_addsta_cmd *sta, u8 flags) |
134 | { | 184 | { |
135 | struct iwl_rx_packet *res = NULL; | 185 | struct iwl_rx_packet *pkt = NULL; |
136 | int ret = 0; | 186 | int ret = 0; |
137 | u8 data[sizeof(*sta)]; | 187 | u8 data[sizeof(*sta)]; |
138 | struct iwl_host_cmd cmd = { | 188 | struct iwl_host_cmd cmd = { |
@@ -152,28 +202,11 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
152 | if (ret || (flags & CMD_ASYNC)) | 202 | if (ret || (flags & CMD_ASYNC)) |
153 | return ret; | 203 | return ret; |
154 | 204 | ||
155 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | ||
156 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
157 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | ||
158 | res->hdr.flags); | ||
159 | ret = -EIO; | ||
160 | } | ||
161 | |||
162 | if (ret == 0) { | 205 | if (ret == 0) { |
163 | switch (res->u.add_sta.status) { | 206 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
164 | case ADD_STA_SUCCESS_MSK: | 207 | iwl_process_add_sta_resp(priv, sta, pkt, true); |
165 | iwl_sta_ucode_activate(priv, sta->sta.sta_id); | ||
166 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | ||
167 | break; | ||
168 | default: | ||
169 | ret = -EIO; | ||
170 | IWL_WARN(priv, "REPLY_ADD_STA failed\n"); | ||
171 | break; | ||
172 | } | ||
173 | } | 208 | } |
174 | 209 | iwl_free_pages(priv, cmd.reply_page); | |
175 | priv->alloc_rxb_skb--; | ||
176 | dev_kfree_skb_any(cmd.reply_skb); | ||
177 | 210 | ||
178 | return ret; | 211 | return ret; |
179 | } | 212 | } |
@@ -189,6 +222,11 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | |||
189 | goto done; | 222 | goto done; |
190 | 223 | ||
191 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; | 224 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; |
225 | IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n", | ||
226 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? | ||
227 | "static" : | ||
228 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? | ||
229 | "dynamic" : "disabled"); | ||
192 | 230 | ||
193 | sta_flags = priv->stations[index].sta.station_flags; | 231 | sta_flags = priv->stations[index].sta.station_flags; |
194 | 232 | ||
@@ -301,7 +339,7 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
301 | } | 339 | } |
302 | EXPORT_SYMBOL(iwl_add_station); | 340 | EXPORT_SYMBOL(iwl_add_station); |
303 | 341 | ||
304 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) | 342 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr) |
305 | { | 343 | { |
306 | unsigned long flags; | 344 | unsigned long flags; |
307 | u8 sta_id = iwl_find_station(priv, addr); | 345 | u8 sta_id = iwl_find_station(priv, addr); |
@@ -324,26 +362,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) | |||
324 | 362 | ||
325 | static void iwl_remove_sta_callback(struct iwl_priv *priv, | 363 | static void iwl_remove_sta_callback(struct iwl_priv *priv, |
326 | struct iwl_device_cmd *cmd, | 364 | struct iwl_device_cmd *cmd, |
327 | struct sk_buff *skb) | 365 | struct iwl_rx_packet *pkt) |
328 | { | 366 | { |
329 | struct iwl_rx_packet *res = NULL; | ||
330 | struct iwl_rem_sta_cmd *rm_sta = | 367 | struct iwl_rem_sta_cmd *rm_sta = |
331 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; | 368 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; |
332 | const char *addr = rm_sta->addr; | 369 | const u8 *addr = rm_sta->addr; |
333 | |||
334 | if (!skb) { | ||
335 | IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n"); | ||
336 | return; | ||
337 | } | ||
338 | 370 | ||
339 | res = (struct iwl_rx_packet *)skb->data; | 371 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
340 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
341 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 372 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", |
342 | res->hdr.flags); | 373 | pkt->hdr.flags); |
343 | return; | 374 | return; |
344 | } | 375 | } |
345 | 376 | ||
346 | switch (res->u.rem_sta.status) { | 377 | switch (pkt->u.rem_sta.status) { |
347 | case REM_STA_SUCCESS_MSK: | 378 | case REM_STA_SUCCESS_MSK: |
348 | iwl_sta_ucode_deactivate(priv, addr); | 379 | iwl_sta_ucode_deactivate(priv, addr); |
349 | break; | 380 | break; |
@@ -356,7 +387,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv, | |||
356 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | 387 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, |
357 | u8 flags) | 388 | u8 flags) |
358 | { | 389 | { |
359 | struct iwl_rx_packet *res = NULL; | 390 | struct iwl_rx_packet *pkt; |
360 | int ret; | 391 | int ret; |
361 | 392 | ||
362 | struct iwl_rem_sta_cmd rm_sta_cmd; | 393 | struct iwl_rem_sta_cmd rm_sta_cmd; |
@@ -381,15 +412,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
381 | if (ret || (flags & CMD_ASYNC)) | 412 | if (ret || (flags & CMD_ASYNC)) |
382 | return ret; | 413 | return ret; |
383 | 414 | ||
384 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 415 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
385 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 416 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
386 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 417 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", |
387 | res->hdr.flags); | 418 | pkt->hdr.flags); |
388 | ret = -EIO; | 419 | ret = -EIO; |
389 | } | 420 | } |
390 | 421 | ||
391 | if (!ret) { | 422 | if (!ret) { |
392 | switch (res->u.rem_sta.status) { | 423 | switch (pkt->u.rem_sta.status) { |
393 | case REM_STA_SUCCESS_MSK: | 424 | case REM_STA_SUCCESS_MSK: |
394 | iwl_sta_ucode_deactivate(priv, addr); | 425 | iwl_sta_ucode_deactivate(priv, addr); |
395 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 426 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
@@ -400,9 +431,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
400 | break; | 431 | break; |
401 | } | 432 | } |
402 | } | 433 | } |
403 | 434 | iwl_free_pages(priv, cmd.reply_page); | |
404 | priv->alloc_rxb_skb--; | ||
405 | dev_kfree_skb_any(cmd.reply_skb); | ||
406 | 435 | ||
407 | return ret; | 436 | return ret; |
408 | } | 437 | } |
@@ -1016,24 +1045,19 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
1016 | struct ieee80211_sta_ht_cap *cur_ht_config = NULL; | 1045 | struct ieee80211_sta_ht_cap *cur_ht_config = NULL; |
1017 | u8 sta_id; | 1046 | u8 sta_id; |
1018 | 1047 | ||
1019 | /* Add station to device's station table */ | ||
1020 | |||
1021 | /* | 1048 | /* |
1022 | * XXX: This check is definitely not correct, if we're an AP | 1049 | * Set HT capabilities. It is ok to set this struct even if not using |
1023 | * it'll always be false which is not what we want, but | 1050 | * HT config: the priv->current_ht_config.is_ht flag will just be false |
1024 | * it doesn't look like iwlagn is prepared to be an HT | ||
1025 | * AP anyway. | ||
1026 | */ | 1051 | */ |
1027 | if (priv->current_ht_config.is_ht) { | 1052 | rcu_read_lock(); |
1028 | rcu_read_lock(); | 1053 | sta = ieee80211_find_sta(priv->vif, addr); |
1029 | sta = ieee80211_find_sta(priv->hw, addr); | 1054 | if (sta) { |
1030 | if (sta) { | 1055 | memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); |
1031 | memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); | 1056 | cur_ht_config = &ht_config; |
1032 | cur_ht_config = &ht_config; | ||
1033 | } | ||
1034 | rcu_read_unlock(); | ||
1035 | } | 1057 | } |
1058 | rcu_read_unlock(); | ||
1036 | 1059 | ||
1060 | /* Add station to device's station table */ | ||
1037 | sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); | 1061 | sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); |
1038 | 1062 | ||
1039 | /* Set up default rate scaling table in device's station table */ | 1063 | /* Set up default rate scaling table in device's station table */ |
@@ -1044,6 +1068,79 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
1044 | EXPORT_SYMBOL(iwl_rxon_add_station); | 1068 | EXPORT_SYMBOL(iwl_rxon_add_station); |
1045 | 1069 | ||
1046 | /** | 1070 | /** |
1071 | * iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table | ||
1072 | * | ||
1073 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
1074 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
1075 | * which requires station table entry to exist). | ||
1076 | */ | ||
1077 | static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) | ||
1078 | { | ||
1079 | int i, r; | ||
1080 | struct iwl_link_quality_cmd link_cmd = { | ||
1081 | .reserved1 = 0, | ||
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 | |||
1097 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | ||
1098 | RATE_MCS_ANT_POS; | ||
1099 | |||
1100 | link_cmd.rs_table[i].rate_n_flags = | ||
1101 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
1102 | r = iwl_get_prev_ieee_rate(r); | ||
1103 | } | ||
1104 | |||
1105 | link_cmd.general_params.single_stream_ant_msk = | ||
1106 | first_antenna(priv->hw_params.valid_tx_ant); | ||
1107 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
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 | |||
1120 | /** | ||
1121 | * iwl_add_bcast_station - add broadcast station into station table. | ||
1122 | */ | ||
1123 | void iwl_add_bcast_station(struct iwl_priv *priv) | ||
1124 | { | ||
1125 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | ||
1126 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | ||
1127 | |||
1128 | /* Set up default rate scaling table in device's station table */ | ||
1129 | iwl_sta_init_bcast_lq(priv); | ||
1130 | } | ||
1131 | EXPORT_SYMBOL(iwl_add_bcast_station); | ||
1132 | |||
1133 | /** | ||
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 | } | ||
1141 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | ||
1142 | |||
1143 | /** | ||
1047 | * iwl_get_sta_id - Find station's index within station table | 1144 | * iwl_get_sta_id - Find station's index within station table |
1048 | * | 1145 | * |
1049 | * If new IBSS station, create new entry in station table | 1146 | * If new IBSS station, create new entry in station table |
@@ -1163,7 +1260,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | |||
1163 | } | 1260 | } |
1164 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | 1261 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); |
1165 | 1262 | ||
1166 | static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | 1263 | void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) |
1167 | { | 1264 | { |
1168 | unsigned long flags; | 1265 | unsigned long flags; |
1169 | 1266 | ||
@@ -1171,27 +1268,26 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1171 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | 1268 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; |
1172 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | 1269 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; |
1173 | priv->stations[sta_id].sta.sta.modify_mask = 0; | 1270 | priv->stations[sta_id].sta.sta.modify_mask = 0; |
1271 | priv->stations[sta_id].sta.sleep_tx_count = 0; | ||
1174 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1272 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1175 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1273 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1176 | 1274 | ||
1177 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1275 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1178 | } | 1276 | } |
1277 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); | ||
1179 | 1278 | ||
1180 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | 1279 | void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) |
1181 | { | 1280 | { |
1182 | /* FIXME: need locking over ps_status ??? */ | 1281 | unsigned long flags; |
1183 | u8 sta_id = iwl_find_station(priv, addr); | ||
1184 | 1282 | ||
1185 | if (sta_id != IWL_INVALID_STATION) { | 1283 | spin_lock_irqsave(&priv->sta_lock, flags); |
1186 | u8 sta_awake = priv->stations[sta_id]. | 1284 | priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; |
1187 | ps_status == STA_PS_STATUS_WAKE; | 1285 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; |
1286 | priv->stations[sta_id].sta.sta.modify_mask = | ||
1287 | STA_MODIFY_SLEEP_TX_COUNT_MSK; | ||
1288 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); | ||
1289 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1290 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1188 | 1291 | ||
1189 | if (sta_awake && ps_bit) | 1292 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1190 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
1191 | else if (!sta_awake && !ps_bit) { | ||
1192 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
1193 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
1194 | } | ||
1195 | } | ||
1196 | } | 1293 | } |
1197 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 6deebade6361..2dc35fe28f56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -52,6 +52,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
52 | const u8 *addr, u32 iv32, u16 *phase1key); | 52 | const u8 *addr, u32 iv32, u16 *phase1key); |
53 | 53 | ||
54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); |
55 | void iwl_add_bcast_station(struct iwl_priv *priv); | ||
56 | void iwl3945_add_bcast_station(struct iwl_priv *priv); | ||
55 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); | 57 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); |
56 | void iwl_clear_stations_table(struct iwl_priv *priv); | 58 | void iwl_clear_stations_table(struct iwl_priv *priv); |
57 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | 59 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); |
@@ -65,5 +67,6 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); | |||
65 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | 67 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, |
66 | const u8 *addr, int tid, u16 ssn); | 68 | const u8 *addr, int tid, u16 ssn); |
67 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); | 69 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); |
68 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr); | 70 | 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); | ||
69 | #endif /* __iwl_sta_h__ */ | 72 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index b7e196e3c8d3..8dd0c036d547 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
32 | #include <linux/slab.h> | ||
32 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
33 | #include "iwl-eeprom.h" | 34 | #include "iwl-eeprom.h" |
34 | #include "iwl-dev.h" | 35 | #include "iwl-dev.h" |
@@ -60,7 +61,8 @@ static const u16 default_tid_to_tx_fifo[] = { | |||
60 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | 61 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, |
61 | struct iwl_dma_ptr *ptr, size_t size) | 62 | struct iwl_dma_ptr *ptr, size_t size) |
62 | { | 63 | { |
63 | ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); | 64 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, |
65 | GFP_KERNEL); | ||
64 | if (!ptr->addr) | 66 | if (!ptr->addr) |
65 | return -ENOMEM; | 67 | return -ENOMEM; |
66 | ptr->size = size; | 68 | ptr->size = size; |
@@ -73,21 +75,20 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | |||
73 | if (unlikely(!ptr->addr)) | 75 | if (unlikely(!ptr->addr)) |
74 | return; | 76 | return; |
75 | 77 | ||
76 | pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); | 78 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); |
77 | memset(ptr, 0, sizeof(*ptr)); | 79 | memset(ptr, 0, sizeof(*ptr)); |
78 | } | 80 | } |
79 | 81 | ||
80 | /** | 82 | /** |
81 | * iwl_txq_update_write_ptr - Send new write index to hardware | 83 | * iwl_txq_update_write_ptr - Send new write index to hardware |
82 | */ | 84 | */ |
83 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | 85 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) |
84 | { | 86 | { |
85 | u32 reg = 0; | 87 | u32 reg = 0; |
86 | int ret = 0; | ||
87 | int txq_id = txq->q.id; | 88 | int txq_id = txq->q.id; |
88 | 89 | ||
89 | if (txq->need_update == 0) | 90 | if (txq->need_update == 0) |
90 | return ret; | 91 | return; |
91 | 92 | ||
92 | /* if we're trying to save power */ | 93 | /* if we're trying to save power */ |
93 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 94 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { |
@@ -97,10 +98,11 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
97 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); | 98 | reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); |
98 | 99 | ||
99 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 100 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
100 | IWL_DEBUG_INFO(priv, "Requesting wakeup, GP1 = 0x%x\n", reg); | 101 | IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", |
102 | txq_id, reg); | ||
101 | iwl_set_bit(priv, CSR_GP_CNTRL, | 103 | iwl_set_bit(priv, CSR_GP_CNTRL, |
102 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 104 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
103 | return ret; | 105 | return; |
104 | } | 106 | } |
105 | 107 | ||
106 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | 108 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, |
@@ -113,12 +115,24 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
113 | txq->q.write_ptr | (txq_id << 8)); | 115 | txq->q.write_ptr | (txq_id << 8)); |
114 | 116 | ||
115 | txq->need_update = 0; | 117 | txq->need_update = 0; |
116 | |||
117 | return ret; | ||
118 | } | 118 | } |
119 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | 119 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); |
120 | 120 | ||
121 | 121 | ||
122 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | ||
123 | int sta_id, int tid, int freed) | ||
124 | { | ||
125 | if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) | ||
126 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | ||
127 | else { | ||
128 | IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", | ||
129 | priv->stations[sta_id].tid[tid].tfds_in_queue, | ||
130 | freed); | ||
131 | priv->stations[sta_id].tid[tid].tfds_in_queue = 0; | ||
132 | } | ||
133 | } | ||
134 | EXPORT_SYMBOL(iwl_free_tfds_in_queue); | ||
135 | |||
122 | /** | 136 | /** |
123 | * iwl_tx_queue_free - Deallocate DMA queue. | 137 | * iwl_tx_queue_free - Deallocate DMA queue. |
124 | * @txq: Transmit queue to deallocate. | 138 | * @txq: Transmit queue to deallocate. |
@@ -131,8 +145,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
131 | { | 145 | { |
132 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 146 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
133 | struct iwl_queue *q = &txq->q; | 147 | struct iwl_queue *q = &txq->q; |
134 | struct pci_dev *dev = priv->pci_dev; | 148 | struct device *dev = &priv->pci_dev->dev; |
135 | int i, len; | 149 | int i; |
136 | 150 | ||
137 | if (q->n_bd == 0) | 151 | if (q->n_bd == 0) |
138 | return; | 152 | return; |
@@ -142,16 +156,14 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
142 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) | 156 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) |
143 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 157 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); |
144 | 158 | ||
145 | len = sizeof(struct iwl_device_cmd) * q->n_window; | ||
146 | |||
147 | /* De-alloc array of command/tx buffers */ | 159 | /* De-alloc array of command/tx buffers */ |
148 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) | 160 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) |
149 | kfree(txq->cmd[i]); | 161 | kfree(txq->cmd[i]); |
150 | 162 | ||
151 | /* De-alloc circular buffer of TFDs */ | 163 | /* De-alloc circular buffer of TFDs */ |
152 | if (txq->q.n_bd) | 164 | if (txq->q.n_bd) |
153 | pci_free_consistent(dev, priv->hw_params.tfd_size * | 165 | dma_free_coherent(dev, priv->hw_params.tfd_size * |
154 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 166 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
155 | 167 | ||
156 | /* De-alloc array of per-TFD driver data */ | 168 | /* De-alloc array of per-TFD driver data */ |
157 | kfree(txq->txb); | 169 | kfree(txq->txb); |
@@ -180,14 +192,35 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
180 | { | 192 | { |
181 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | 193 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; |
182 | struct iwl_queue *q = &txq->q; | 194 | struct iwl_queue *q = &txq->q; |
183 | struct pci_dev *dev = priv->pci_dev; | 195 | struct device *dev = &priv->pci_dev->dev; |
184 | int i, len; | 196 | int i; |
197 | bool huge = false; | ||
185 | 198 | ||
186 | if (q->n_bd == 0) | 199 | if (q->n_bd == 0) |
187 | return; | 200 | return; |
188 | 201 | ||
189 | len = sizeof(struct iwl_device_cmd) * q->n_window; | 202 | for (; q->read_ptr != q->write_ptr; |
190 | len += IWL_MAX_SCAN_SIZE; | 203 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
204 | /* we have no way to tell if it is a huge cmd ATM */ | ||
205 | i = get_cmd_index(q, q->read_ptr, 0); | ||
206 | |||
207 | if (txq->meta[i].flags & CMD_SIZE_HUGE) { | ||
208 | huge = true; | ||
209 | continue; | ||
210 | } | ||
211 | |||
212 | pci_unmap_single(priv->pci_dev, | ||
213 | pci_unmap_addr(&txq->meta[i], mapping), | ||
214 | pci_unmap_len(&txq->meta[i], len), | ||
215 | PCI_DMA_BIDIRECTIONAL); | ||
216 | } | ||
217 | if (huge) { | ||
218 | i = q->n_window; | ||
219 | pci_unmap_single(priv->pci_dev, | ||
220 | pci_unmap_addr(&txq->meta[i], mapping), | ||
221 | pci_unmap_len(&txq->meta[i], len), | ||
222 | PCI_DMA_BIDIRECTIONAL); | ||
223 | } | ||
191 | 224 | ||
192 | /* De-alloc array of command/tx buffers */ | 225 | /* De-alloc array of command/tx buffers */ |
193 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 226 | for (i = 0; i <= TFD_CMD_SLOTS; i++) |
@@ -195,8 +228,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
195 | 228 | ||
196 | /* De-alloc circular buffer of TFDs */ | 229 | /* De-alloc circular buffer of TFDs */ |
197 | if (txq->q.n_bd) | 230 | if (txq->q.n_bd) |
198 | pci_free_consistent(dev, priv->hw_params.tfd_size * | 231 | dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, |
199 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 232 | txq->tfds, txq->q.dma_addr); |
200 | 233 | ||
201 | /* deallocate arrays */ | 234 | /* deallocate arrays */ |
202 | kfree(txq->cmd); | 235 | kfree(txq->cmd); |
@@ -287,7 +320,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | |||
287 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, | 320 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, |
288 | struct iwl_tx_queue *txq, u32 id) | 321 | struct iwl_tx_queue *txq, u32 id) |
289 | { | 322 | { |
290 | struct pci_dev *dev = priv->pci_dev; | 323 | struct device *dev = &priv->pci_dev->dev; |
291 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; | 324 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; |
292 | 325 | ||
293 | /* Driver private data, only for Tx (not command) queues, | 326 | /* Driver private data, only for Tx (not command) queues, |
@@ -306,8 +339,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
306 | 339 | ||
307 | /* Circular buffer of transmit frame descriptors (TFDs), | 340 | /* Circular buffer of transmit frame descriptors (TFDs), |
308 | * shared with device */ | 341 | * shared with device */ |
309 | txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr); | 342 | txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, |
310 | 343 | GFP_KERNEL); | |
311 | if (!txq->tfds) { | 344 | if (!txq->tfds) { |
312 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); | 345 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); |
313 | goto error; | 346 | goto error; |
@@ -356,7 +389,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
356 | for (i = 0; i < actual_slots; i++) { | 389 | for (i = 0; i < actual_slots; i++) { |
357 | /* only happens for cmd queue */ | 390 | /* only happens for cmd queue */ |
358 | if (i == slots_num) | 391 | if (i == slots_num) |
359 | len += IWL_MAX_SCAN_SIZE; | 392 | len = IWL_MAX_CMD_SIZE; |
360 | 393 | ||
361 | txq->cmd[i] = kmalloc(len, GFP_KERNEL); | 394 | txq->cmd[i] = kmalloc(len, GFP_KERNEL); |
362 | if (!txq->cmd[i]) | 395 | if (!txq->cmd[i]) |
@@ -370,8 +403,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
370 | 403 | ||
371 | txq->need_update = 0; | 404 | txq->need_update = 0; |
372 | 405 | ||
373 | /* aggregation TX queues will get their ID when aggregation begins */ | 406 | /* |
374 | if (txq_id <= IWL_TX_FIFO_AC3) | 407 | * Aggregation TX queues will get their ID when aggregation begins; |
408 | * they overwrite the setting done here. The command FIFO doesn't | ||
409 | * need an swq_id so don't set one to catch errors, all others can | ||
410 | * be set up to the identity mapping. | ||
411 | */ | ||
412 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
375 | txq->swq_id = txq_id; | 413 | txq->swq_id = txq_id; |
376 | 414 | ||
377 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | 415 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise |
@@ -396,6 +434,26 @@ out_free_arrays: | |||
396 | } | 434 | } |
397 | EXPORT_SYMBOL(iwl_tx_queue_init); | 435 | EXPORT_SYMBOL(iwl_tx_queue_init); |
398 | 436 | ||
437 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
438 | int slots_num, u32 txq_id) | ||
439 | { | ||
440 | int actual_slots = slots_num; | ||
441 | |||
442 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
443 | actual_slots++; | ||
444 | |||
445 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); | ||
446 | |||
447 | txq->need_update = 0; | ||
448 | |||
449 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
450 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
451 | |||
452 | /* Tell device where to find queue */ | ||
453 | priv->cfg->ops->lib->txq_init(priv, txq); | ||
454 | } | ||
455 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
456 | |||
399 | /** | 457 | /** |
400 | * iwl_hw_txq_ctx_free - Free TXQ Context | 458 | * iwl_hw_txq_ctx_free - Free TXQ Context |
401 | * | 459 | * |
@@ -406,28 +464,32 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
406 | int txq_id; | 464 | int txq_id; |
407 | 465 | ||
408 | /* Tx queues */ | 466 | /* Tx queues */ |
409 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 467 | if (priv->txq) { |
410 | if (txq_id == IWL_CMD_QUEUE_NUM) | 468 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
411 | iwl_cmd_queue_free(priv); | 469 | if (txq_id == IWL_CMD_QUEUE_NUM) |
412 | else | 470 | iwl_cmd_queue_free(priv); |
413 | iwl_tx_queue_free(priv, txq_id); | 471 | else |
414 | 472 | iwl_tx_queue_free(priv, txq_id); | |
473 | } | ||
415 | iwl_free_dma_ptr(priv, &priv->kw); | 474 | iwl_free_dma_ptr(priv, &priv->kw); |
416 | 475 | ||
417 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | 476 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); |
477 | |||
478 | /* free tx queue structure */ | ||
479 | iwl_free_txq_mem(priv); | ||
418 | } | 480 | } |
419 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 481 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
420 | 482 | ||
421 | /** | 483 | /** |
422 | * iwl_txq_ctx_reset - Reset TX queue context | 484 | * iwl_txq_ctx_alloc - allocate TX queue context |
423 | * Destroys all DMA structures and initialize them again | 485 | * Allocate all Tx DMA structures and initialize them |
424 | * | 486 | * |
425 | * @param priv | 487 | * @param priv |
426 | * @return error code | 488 | * @return error code |
427 | */ | 489 | */ |
428 | int iwl_txq_ctx_reset(struct iwl_priv *priv) | 490 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) |
429 | { | 491 | { |
430 | int ret = 0; | 492 | int ret; |
431 | int txq_id, slots_num; | 493 | int txq_id, slots_num; |
432 | unsigned long flags; | 494 | unsigned long flags; |
433 | 495 | ||
@@ -446,6 +508,12 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
446 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | 508 | IWL_ERR(priv, "Keep Warm allocation failed\n"); |
447 | goto error_kw; | 509 | goto error_kw; |
448 | } | 510 | } |
511 | |||
512 | /* allocate tx queue structure */ | ||
513 | ret = iwl_alloc_txq_mem(priv); | ||
514 | if (ret) | ||
515 | goto error; | ||
516 | |||
449 | spin_lock_irqsave(&priv->lock, flags); | 517 | spin_lock_irqsave(&priv->lock, flags); |
450 | 518 | ||
451 | /* Turn off all Tx DMA fifos */ | 519 | /* Turn off all Tx DMA fifos */ |
@@ -479,8 +547,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
479 | return ret; | 547 | return ret; |
480 | } | 548 | } |
481 | 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 | |||
482 | /** | 573 | /** |
483 | * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | 574 | * iwl_txq_ctx_stop - Stop all Tx DMA channels |
484 | */ | 575 | */ |
485 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 576 | void iwl_txq_ctx_stop(struct iwl_priv *priv) |
486 | { | 577 | { |
@@ -500,9 +591,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv) | |||
500 | 1000); | 591 | 1000); |
501 | } | 592 | } |
502 | spin_unlock_irqrestore(&priv->lock, flags); | 593 | spin_unlock_irqrestore(&priv->lock, flags); |
503 | |||
504 | /* Deallocate memory for all Tx queues */ | ||
505 | iwl_hw_txq_ctx_free(priv); | ||
506 | } | 594 | } |
507 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | 595 | EXPORT_SYMBOL(iwl_txq_ctx_stop); |
508 | 596 | ||
@@ -582,9 +670,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, | |||
582 | u8 rate_plcp; | 670 | u8 rate_plcp; |
583 | 671 | ||
584 | /* Set retry limit on DATA packets and Probe Responses*/ | 672 | /* Set retry limit on DATA packets and Probe Responses*/ |
585 | if (priv->data_retry_limit != -1) | 673 | if (ieee80211_is_probe_resp(fc)) |
586 | data_retry_limit = priv->data_retry_limit; | ||
587 | else if (ieee80211_is_probe_resp(fc)) | ||
588 | data_retry_limit = 3; | 674 | data_retry_limit = 3; |
589 | else | 675 | else |
590 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | 676 | data_retry_limit = IWL_DEFAULT_TX_RETRY; |
@@ -701,6 +787,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
701 | { | 787 | { |
702 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 788 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
703 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 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; | ||
704 | struct iwl_tx_queue *txq; | 792 | struct iwl_tx_queue *txq; |
705 | struct iwl_queue *q; | 793 | struct iwl_queue *q; |
706 | struct iwl_device_cmd *out_cmd; | 794 | struct iwl_device_cmd *out_cmd; |
@@ -710,7 +798,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
710 | dma_addr_t phys_addr; | 798 | dma_addr_t phys_addr; |
711 | dma_addr_t txcmd_phys; | 799 | dma_addr_t txcmd_phys; |
712 | dma_addr_t scratch_phys; | 800 | dma_addr_t scratch_phys; |
713 | u16 len, len_org; | 801 | u16 len, len_org, firstlen, secondlen; |
714 | u16 seq_number = 0; | 802 | u16 seq_number = 0; |
715 | __le16 fc; | 803 | __le16 fc; |
716 | u8 hdr_len; | 804 | u8 hdr_len; |
@@ -719,7 +807,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
719 | u8 tid = 0; | 807 | u8 tid = 0; |
720 | u8 *qc = NULL; | 808 | u8 *qc = NULL; |
721 | unsigned long flags; | 809 | unsigned long flags; |
722 | int ret; | ||
723 | 810 | ||
724 | spin_lock_irqsave(&priv->lock, flags); | 811 | spin_lock_irqsave(&priv->lock, flags); |
725 | if (iwl_is_rfkill(priv)) { | 812 | if (iwl_is_rfkill(priv)) { |
@@ -763,6 +850,24 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
763 | 850 | ||
764 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | 851 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); |
765 | 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 | |||
766 | txq_id = skb_get_queue_mapping(skb); | 871 | txq_id = skb_get_queue_mapping(skb); |
767 | if (ieee80211_is_data_qos(fc)) { | 872 | if (ieee80211_is_data_qos(fc)) { |
768 | qc = ieee80211_get_qos_ctl(hdr); | 873 | qc = ieee80211_get_qos_ctl(hdr); |
@@ -776,8 +881,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
776 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | 881 | hdr->seq_ctrl |= cpu_to_le16(seq_number); |
777 | seq_number += 0x10; | 882 | seq_number += 0x10; |
778 | /* aggregation is on for this <sta,tid> */ | 883 | /* aggregation is on for this <sta,tid> */ |
779 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 884 | if (info->flags & IEEE80211_TX_CTL_AMPDU && |
885 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
780 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | 886 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; |
887 | } | ||
781 | } | 888 | } |
782 | 889 | ||
783 | txq = &priv->txq[txq_id]; | 890 | txq = &priv->txq[txq_id]; |
@@ -843,7 +950,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
843 | sizeof(struct iwl_cmd_header) + hdr_len; | 950 | sizeof(struct iwl_cmd_header) + hdr_len; |
844 | 951 | ||
845 | len_org = len; | 952 | len_org = len; |
846 | len = (len + 3) & ~3; | 953 | firstlen = len = (len + 3) & ~3; |
847 | 954 | ||
848 | if (len_org != len) | 955 | if (len_org != len) |
849 | len_org = 1; | 956 | len_org = 1; |
@@ -877,7 +984,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
877 | 984 | ||
878 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 985 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
879 | * if any (802.11 null frames have no payload). */ | 986 | * if any (802.11 null frames have no payload). */ |
880 | len = skb->len - hdr_len; | 987 | secondlen = len = skb->len - hdr_len; |
881 | if (len) { | 988 | if (len) { |
882 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | 989 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, |
883 | len, PCI_DMA_TODEVICE); | 990 | len, PCI_DMA_TODEVICE); |
@@ -911,13 +1018,27 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
911 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | 1018 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, |
912 | len, PCI_DMA_BIDIRECTIONAL); | 1019 | len, PCI_DMA_BIDIRECTIONAL); |
913 | 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 | |||
914 | /* Tell device the write index *just past* this latest filled TFD */ | 1027 | /* Tell device the write index *just past* this latest filled TFD */ |
915 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1028 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
916 | ret = iwl_txq_update_write_ptr(priv, txq); | 1029 | iwl_txq_update_write_ptr(priv, txq); |
917 | spin_unlock_irqrestore(&priv->lock, flags); | 1030 | spin_unlock_irqrestore(&priv->lock, flags); |
918 | 1031 | ||
919 | if (ret) | 1032 | /* |
920 | return ret; | 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); | ||
921 | 1042 | ||
922 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | 1043 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { |
923 | if (wait_write_ptr) { | 1044 | if (wait_write_ptr) { |
@@ -957,7 +1078,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
957 | struct iwl_cmd_meta *out_meta; | 1078 | struct iwl_cmd_meta *out_meta; |
958 | dma_addr_t phys_addr; | 1079 | dma_addr_t phys_addr; |
959 | unsigned long flags; | 1080 | unsigned long flags; |
960 | int len, ret; | 1081 | int len; |
961 | u32 idx; | 1082 | u32 idx; |
962 | u16 fix_size; | 1083 | u16 fix_size; |
963 | 1084 | ||
@@ -966,22 +1087,40 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
966 | 1087 | ||
967 | /* If any of the command structures end up being larger than | 1088 | /* If any of the command structures end up being larger than |
968 | * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then | 1089 | * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then |
969 | * we will need to increase the size of the TFD entries */ | 1090 | * we will need to increase the size of the TFD entries |
1091 | * Also, check to see if command buffer should not exceed the size | ||
1092 | * of device_cmd and max_cmd_size. */ | ||
970 | BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && | 1093 | BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && |
971 | !(cmd->flags & CMD_SIZE_HUGE)); | 1094 | !(cmd->flags & CMD_SIZE_HUGE)); |
1095 | BUG_ON(fix_size > IWL_MAX_CMD_SIZE); | ||
972 | 1096 | ||
973 | if (iwl_is_rfkill(priv)) { | 1097 | if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { |
974 | IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); | 1098 | IWL_WARN(priv, "Not sending command - %s KILL\n", |
1099 | iwl_is_rfkill(priv) ? "RF" : "CT"); | ||
975 | return -EIO; | 1100 | return -EIO; |
976 | } | 1101 | } |
977 | 1102 | ||
978 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { | 1103 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { |
979 | IWL_ERR(priv, "No space for Tx\n"); | 1104 | IWL_ERR(priv, "No space in command queue\n"); |
1105 | if (iwl_within_ct_kill_margin(priv)) | ||
1106 | iwl_tt_enter_ct_kill(priv); | ||
1107 | else { | ||
1108 | IWL_ERR(priv, "Restarting adapter due to queue full\n"); | ||
1109 | queue_work(priv->workqueue, &priv->restart); | ||
1110 | } | ||
980 | return -ENOSPC; | 1111 | return -ENOSPC; |
981 | } | 1112 | } |
982 | 1113 | ||
983 | spin_lock_irqsave(&priv->hcmd_lock, flags); | 1114 | spin_lock_irqsave(&priv->hcmd_lock, flags); |
984 | 1115 | ||
1116 | /* If this is a huge cmd, mark the huge flag also on the meta.flags | ||
1117 | * of the _original_ cmd. This is used for DMA mapping clean up. | ||
1118 | */ | ||
1119 | if (cmd->flags & CMD_SIZE_HUGE) { | ||
1120 | idx = get_cmd_index(q, q->write_ptr, 0); | ||
1121 | txq->meta[idx].flags = CMD_SIZE_HUGE; | ||
1122 | } | ||
1123 | |||
985 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); | 1124 | idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); |
986 | out_cmd = txq->cmd[idx]; | 1125 | out_cmd = txq->cmd[idx]; |
987 | out_meta = &txq->meta[idx]; | 1126 | out_meta = &txq->meta[idx]; |
@@ -1005,8 +1144,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1005 | if (cmd->flags & CMD_SIZE_HUGE) | 1144 | if (cmd->flags & CMD_SIZE_HUGE) |
1006 | out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; | 1145 | out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; |
1007 | len = sizeof(struct iwl_device_cmd); | 1146 | len = sizeof(struct iwl_device_cmd); |
1008 | len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0; | 1147 | if (idx == TFD_CMD_SLOTS) |
1009 | 1148 | len = IWL_MAX_CMD_SIZE; | |
1010 | 1149 | ||
1011 | #ifdef CONFIG_IWLWIFI_DEBUG | 1150 | #ifdef CONFIG_IWLWIFI_DEBUG |
1012 | switch (out_cmd->hdr.cmd) { | 1151 | switch (out_cmd->hdr.cmd) { |
@@ -1039,16 +1178,36 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1039 | pci_unmap_addr_set(out_meta, mapping, phys_addr); | 1178 | pci_unmap_addr_set(out_meta, mapping, phys_addr); |
1040 | pci_unmap_len_set(out_meta, len, fix_size); | 1179 | pci_unmap_len_set(out_meta, len, fix_size); |
1041 | 1180 | ||
1181 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | ||
1182 | |||
1042 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 1183 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
1043 | phys_addr, fix_size, 1, | 1184 | phys_addr, fix_size, 1, |
1044 | U32_PAD(cmd->len)); | 1185 | U32_PAD(cmd->len)); |
1045 | 1186 | ||
1046 | /* Increment and update queue's write index */ | 1187 | /* Increment and update queue's write index */ |
1047 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1188 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
1048 | ret = iwl_txq_update_write_ptr(priv, txq); | 1189 | iwl_txq_update_write_ptr(priv, txq); |
1049 | 1190 | ||
1050 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 1191 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
1051 | return ret ? ret : idx; | 1192 | return idx; |
1193 | } | ||
1194 | |||
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); | ||
1052 | } | 1211 | } |
1053 | 1212 | ||
1054 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | 1213 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) |
@@ -1057,6 +1216,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1057 | struct iwl_queue *q = &txq->q; | 1216 | struct iwl_queue *q = &txq->q; |
1058 | struct iwl_tx_info *tx_info; | 1217 | struct iwl_tx_info *tx_info; |
1059 | int nfreed = 0; | 1218 | int nfreed = 0; |
1219 | struct ieee80211_hdr *hdr; | ||
1060 | 1220 | ||
1061 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | 1221 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { |
1062 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | 1222 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " |
@@ -1070,14 +1230,17 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1070 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1230 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1071 | 1231 | ||
1072 | tx_info = &txq->txb[txq->q.read_ptr]; | 1232 | tx_info = &txq->txb[txq->q.read_ptr]; |
1073 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); | 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++; | ||
1074 | tx_info->skb[0] = NULL; | 1238 | tx_info->skb[0] = NULL; |
1075 | 1239 | ||
1076 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | 1240 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) |
1077 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | 1241 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); |
1078 | 1242 | ||
1079 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 1243 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); |
1080 | nfreed++; | ||
1081 | } | 1244 | } |
1082 | return nfreed; | 1245 | return nfreed; |
1083 | } | 1246 | } |
@@ -1105,11 +1268,6 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, | |||
1105 | return; | 1268 | return; |
1106 | } | 1269 | } |
1107 | 1270 | ||
1108 | pci_unmap_single(priv->pci_dev, | ||
1109 | pci_unmap_addr(&txq->meta[cmd_idx], mapping), | ||
1110 | pci_unmap_len(&txq->meta[cmd_idx], len), | ||
1111 | PCI_DMA_BIDIRECTIONAL); | ||
1112 | |||
1113 | for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; | 1271 | for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; |
1114 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1272 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1115 | 1273 | ||
@@ -1132,7 +1290,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, | |||
1132 | */ | 1290 | */ |
1133 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1291 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1134 | { | 1292 | { |
1135 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1293 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1136 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1294 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
1137 | int txq_id = SEQ_TO_QUEUE(sequence); | 1295 | int txq_id = SEQ_TO_QUEUE(sequence); |
1138 | int index = SEQ_TO_INDEX(sequence); | 1296 | int index = SEQ_TO_INDEX(sequence); |
@@ -1140,6 +1298,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1140 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); | 1298 | bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); |
1141 | struct iwl_device_cmd *cmd; | 1299 | struct iwl_device_cmd *cmd; |
1142 | struct iwl_cmd_meta *meta; | 1300 | struct iwl_cmd_meta *meta; |
1301 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | ||
1143 | 1302 | ||
1144 | /* If a Tx command is being handled and it isn't in the actual | 1303 | /* If a Tx command is being handled and it isn't in the actual |
1145 | * command queue then there a command routing bug has been introduced | 1304 | * command queue then there a command routing bug has been introduced |
@@ -1153,23 +1312,39 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1153 | return; | 1312 | return; |
1154 | } | 1313 | } |
1155 | 1314 | ||
1156 | cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); | 1315 | /* If this is a huge cmd, clear the huge flag on the meta.flags |
1157 | cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; | 1316 | * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap |
1158 | meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; | 1317 | * the DMA buffer for the scan (huge) command. |
1318 | */ | ||
1319 | if (huge) { | ||
1320 | cmd_index = get_cmd_index(&txq->q, index, 0); | ||
1321 | txq->meta[cmd_index].flags = 0; | ||
1322 | } | ||
1323 | cmd_index = get_cmd_index(&txq->q, index, huge); | ||
1324 | cmd = txq->cmd[cmd_index]; | ||
1325 | meta = &txq->meta[cmd_index]; | ||
1326 | |||
1327 | pci_unmap_single(priv->pci_dev, | ||
1328 | pci_unmap_addr(meta, mapping), | ||
1329 | pci_unmap_len(meta, len), | ||
1330 | PCI_DMA_BIDIRECTIONAL); | ||
1159 | 1331 | ||
1160 | /* Input error checking is done when commands are added to queue. */ | 1332 | /* Input error checking is done when commands are added to queue. */ |
1161 | if (meta->flags & CMD_WANT_SKB) { | 1333 | if (meta->flags & CMD_WANT_SKB) { |
1162 | meta->source->reply_skb = rxb->skb; | 1334 | meta->source->reply_page = (unsigned long)rxb_addr(rxb); |
1163 | rxb->skb = NULL; | 1335 | rxb->page = NULL; |
1164 | } else if (meta->callback) | 1336 | } else if (meta->callback) |
1165 | meta->callback(priv, cmd, rxb->skb); | 1337 | meta->callback(priv, cmd, pkt); |
1166 | 1338 | ||
1167 | iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); | 1339 | iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); |
1168 | 1340 | ||
1169 | if (!(meta->flags & CMD_ASYNC)) { | 1341 | if (!(meta->flags & CMD_ASYNC)) { |
1170 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1342 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1343 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | ||
1344 | get_cmd_string(cmd->hdr.cmd)); | ||
1171 | wake_up_interruptible(&priv->wait_command_queue); | 1345 | wake_up_interruptible(&priv->wait_command_queue); |
1172 | } | 1346 | } |
1347 | meta->flags = 0; | ||
1173 | } | 1348 | } |
1174 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 1349 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
1175 | 1350 | ||
@@ -1240,7 +1415,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | |||
1240 | if (tid_data->tfds_in_queue == 0) { | 1415 | if (tid_data->tfds_in_queue == 0) { |
1241 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1416 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1242 | tid_data->agg.state = IWL_AGG_ON; | 1417 | tid_data->agg.state = IWL_AGG_ON; |
1243 | ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); | 1418 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1244 | } else { | 1419 | } else { |
1245 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | 1420 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", |
1246 | tid_data->tfds_in_queue); | 1421 | tid_data->tfds_in_queue); |
@@ -1254,7 +1429,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1254 | { | 1429 | { |
1255 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | 1430 | int tx_fifo_id, txq_id, sta_id, ssn = -1; |
1256 | struct iwl_tid_data *tid_data; | 1431 | struct iwl_tid_data *tid_data; |
1257 | int ret, write_ptr, read_ptr; | 1432 | int write_ptr, read_ptr; |
1258 | unsigned long flags; | 1433 | unsigned long flags; |
1259 | 1434 | ||
1260 | if (!ra) { | 1435 | if (!ra) { |
@@ -1280,7 +1455,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1280 | if (priv->stations[sta_id].tid[tid].agg.state == | 1455 | if (priv->stations[sta_id].tid[tid].agg.state == |
1281 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | 1456 | IWL_EMPTYING_HW_QUEUE_ADDBA) { |
1282 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | 1457 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); |
1283 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); | 1458 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1284 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1459 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1285 | return 0; | 1460 | return 0; |
1286 | } | 1461 | } |
@@ -1306,14 +1481,18 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1306 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1481 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1307 | 1482 | ||
1308 | spin_lock_irqsave(&priv->lock, flags); | 1483 | spin_lock_irqsave(&priv->lock, flags); |
1309 | ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | 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, | ||
1310 | tx_fifo_id); | 1492 | tx_fifo_id); |
1311 | spin_unlock_irqrestore(&priv->lock, flags); | 1493 | spin_unlock_irqrestore(&priv->lock, flags); |
1312 | 1494 | ||
1313 | if (ret) | 1495 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1314 | return ret; | ||
1315 | |||
1316 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); | ||
1317 | 1496 | ||
1318 | return 0; | 1497 | return 0; |
1319 | } | 1498 | } |
@@ -1337,7 +1516,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | |||
1337 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | 1516 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, |
1338 | ssn, tx_fifo); | 1517 | ssn, tx_fifo); |
1339 | tid_data->agg.state = IWL_AGG_OFF; | 1518 | tid_data->agg.state = IWL_AGG_OFF; |
1340 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); | 1519 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); |
1341 | } | 1520 | } |
1342 | break; | 1521 | break; |
1343 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 1522 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -1345,7 +1524,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | |||
1345 | if (tid_data->tfds_in_queue == 0) { | 1524 | if (tid_data->tfds_in_queue == 0) { |
1346 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | 1525 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); |
1347 | tid_data->agg.state = IWL_AGG_ON; | 1526 | tid_data->agg.state = IWL_AGG_ON; |
1348 | ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); | 1527 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); |
1349 | } | 1528 | } |
1350 | break; | 1529 | break; |
1351 | } | 1530 | } |
@@ -1409,7 +1588,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1409 | 1588 | ||
1410 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | 1589 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); |
1411 | memset(&info->status, 0, sizeof(info->status)); | 1590 | memset(&info->status, 0, sizeof(info->status)); |
1412 | info->flags = IEEE80211_TX_STAT_ACK; | 1591 | info->flags |= IEEE80211_TX_STAT_ACK; |
1413 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 1592 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
1414 | info->status.ampdu_ack_map = successes; | 1593 | info->status.ampdu_ack_map = successes; |
1415 | info->status.ampdu_ack_len = agg->frame_count; | 1594 | info->status.ampdu_ack_len = agg->frame_count; |
@@ -1429,7 +1608,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1429 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | 1608 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, |
1430 | struct iwl_rx_mem_buffer *rxb) | 1609 | struct iwl_rx_mem_buffer *rxb) |
1431 | { | 1610 | { |
1432 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1611 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1433 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | 1612 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; |
1434 | struct iwl_tx_queue *txq = NULL; | 1613 | struct iwl_tx_queue *txq = NULL; |
1435 | struct iwl_ht_agg *agg; | 1614 | struct iwl_ht_agg *agg; |
@@ -1485,7 +1664,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1485 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | 1664 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { |
1486 | /* calculate mac80211 ampdu sw queue to wake */ | 1665 | /* calculate mac80211 ampdu sw queue to wake */ |
1487 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); | 1666 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); |
1488 | priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; | 1667 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
1489 | 1668 | ||
1490 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | 1669 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && |
1491 | priv->mac80211_registered && | 1670 | priv->mac80211_registered && |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d00a80334095..b74a56c48d26 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/slab.h> | ||
34 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
35 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
36 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
@@ -42,7 +43,6 @@ | |||
42 | #include <linux/if_arp.h> | 43 | #include <linux/if_arp.h> |
43 | 44 | ||
44 | #include <net/ieee80211_radiotap.h> | 45 | #include <net/ieee80211_radiotap.h> |
45 | #include <net/lib80211.h> | ||
46 | #include <net/mac80211.h> | 46 | #include <net/mac80211.h> |
47 | 47 | ||
48 | #include <asm/div64.h> | 48 | #include <asm/div64.h> |
@@ -54,9 +54,10 @@ | |||
54 | #include "iwl-commands.h" | 54 | #include "iwl-commands.h" |
55 | #include "iwl-sta.h" | 55 | #include "iwl-sta.h" |
56 | #include "iwl-3945.h" | 56 | #include "iwl-3945.h" |
57 | #include "iwl-helpers.h" | ||
58 | #include "iwl-core.h" | 57 | #include "iwl-core.h" |
58 | #include "iwl-helpers.h" | ||
59 | #include "iwl-dev.h" | 59 | #include "iwl-dev.h" |
60 | #include "iwl-spectrum.h" | ||
60 | 61 | ||
61 | /* | 62 | /* |
62 | * module name, copyright, version, etc. | 63 | * module name, copyright, version, etc. |
@@ -71,17 +72,14 @@ | |||
71 | #define VD | 72 | #define VD |
72 | #endif | 73 | #endif |
73 | 74 | ||
74 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | 75 | /* |
75 | #define VS "s" | 76 | * add "s" to indicate spectrum measurement included. |
76 | #else | 77 | * we add it here to be consistent with previous releases in which |
77 | #define VS | 78 | * this was configurable. |
78 | #endif | 79 | */ |
79 | 80 | #define DRV_VERSION IWLWIFI_VERSION VD "s" | |
80 | #define IWL39_VERSION "1.2.26k" VD VS | 81 | #define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" |
81 | #define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" | ||
82 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 82 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
83 | #define DRV_VERSION IWL39_VERSION | ||
84 | |||
85 | 83 | ||
86 | MODULE_DESCRIPTION(DRV_DESCRIPTION); | 84 | MODULE_DESCRIPTION(DRV_DESCRIPTION); |
87 | MODULE_VERSION(DRV_VERSION); | 85 | MODULE_VERSION(DRV_VERSION); |
@@ -90,7 +88,6 @@ MODULE_LICENSE("GPL"); | |||
90 | 88 | ||
91 | /* module parameters */ | 89 | /* module parameters */ |
92 | struct iwl_mod_params iwl3945_mod_params = { | 90 | struct iwl_mod_params iwl3945_mod_params = { |
93 | .num_of_queues = IWL39_NUM_QUEUES, /* Not used */ | ||
94 | .sw_crypto = 1, | 91 | .sw_crypto = 1, |
95 | .restart_fw = 1, | 92 | .restart_fw = 1, |
96 | /* the rest are 0 by default */ | 93 | /* the rest are 0 by default */ |
@@ -356,10 +353,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) | |||
356 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) | 353 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) |
357 | { | 354 | { |
358 | if (priv->shared_virt) | 355 | if (priv->shared_virt) |
359 | pci_free_consistent(priv->pci_dev, | 356 | dma_free_coherent(&priv->pci_dev->dev, |
360 | sizeof(struct iwl3945_shared), | 357 | sizeof(struct iwl3945_shared), |
361 | priv->shared_virt, | 358 | priv->shared_virt, |
362 | priv->shared_phys); | 359 | priv->shared_phys); |
363 | } | 360 | } |
364 | 361 | ||
365 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | 362 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, |
@@ -368,13 +365,13 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
368 | struct sk_buff *skb_frag, | 365 | struct sk_buff *skb_frag, |
369 | int sta_id) | 366 | int sta_id) |
370 | { | 367 | { |
371 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 368 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
372 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | 369 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
373 | 370 | ||
374 | switch (keyinfo->alg) { | 371 | switch (keyinfo->alg) { |
375 | case ALG_CCMP: | 372 | case ALG_CCMP: |
376 | tx->sec_ctl = TX_CMD_SEC_CCM; | 373 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; |
377 | memcpy(tx->key, keyinfo->key, keyinfo->keylen); | 374 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); |
378 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | 375 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); |
379 | break; | 376 | break; |
380 | 377 | ||
@@ -382,13 +379,13 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
382 | break; | 379 | break; |
383 | 380 | ||
384 | case ALG_WEP: | 381 | case ALG_WEP: |
385 | tx->sec_ctl = TX_CMD_SEC_WEP | | 382 | tx_cmd->sec_ctl = TX_CMD_SEC_WEP | |
386 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 383 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; |
387 | 384 | ||
388 | if (keyinfo->keylen == 13) | 385 | if (keyinfo->keylen == 13) |
389 | tx->sec_ctl |= TX_CMD_SEC_KEY128; | 386 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; |
390 | 387 | ||
391 | memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen); | 388 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); |
392 | 389 | ||
393 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | 390 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " |
394 | "with key %d\n", info->control.hw_key->hw_key_idx); | 391 | "with key %d\n", info->control.hw_key->hw_key_idx); |
@@ -408,12 +405,11 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
408 | struct ieee80211_tx_info *info, | 405 | struct ieee80211_tx_info *info, |
409 | struct ieee80211_hdr *hdr, u8 std_id) | 406 | struct ieee80211_hdr *hdr, u8 std_id) |
410 | { | 407 | { |
411 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 408 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
412 | __le32 tx_flags = tx->tx_flags; | 409 | __le32 tx_flags = tx_cmd->tx_flags; |
413 | __le16 fc = hdr->frame_control; | 410 | __le16 fc = hdr->frame_control; |
414 | u8 rc_flags = info->control.rates[0].flags; | ||
415 | 411 | ||
416 | tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 412 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
417 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 413 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
418 | tx_flags |= TX_CMD_FLG_ACK_MSK; | 414 | tx_flags |= TX_CMD_FLG_ACK_MSK; |
419 | if (ieee80211_is_mgmt(fc)) | 415 | if (ieee80211_is_mgmt(fc)) |
@@ -426,25 +422,19 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
426 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 422 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
427 | } | 423 | } |
428 | 424 | ||
429 | tx->sta_id = std_id; | 425 | tx_cmd->sta_id = std_id; |
430 | if (ieee80211_has_morefrags(fc)) | 426 | if (ieee80211_has_morefrags(fc)) |
431 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | 427 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; |
432 | 428 | ||
433 | if (ieee80211_is_data_qos(fc)) { | 429 | if (ieee80211_is_data_qos(fc)) { |
434 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 430 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
435 | tx->tid_tspec = qc[0] & 0xf; | 431 | tx_cmd->tid_tspec = qc[0] & 0xf; |
436 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | 432 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; |
437 | } else { | 433 | } else { |
438 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 434 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
439 | } | 435 | } |
440 | 436 | ||
441 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 437 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); |
442 | tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
443 | tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
444 | } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
445 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
446 | tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
447 | } | ||
448 | 438 | ||
449 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | 439 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) |
450 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | 440 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; |
@@ -452,19 +442,16 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
452 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | 442 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); |
453 | if (ieee80211_is_mgmt(fc)) { | 443 | if (ieee80211_is_mgmt(fc)) { |
454 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | 444 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) |
455 | tx->timeout.pm_frame_timeout = cpu_to_le16(3); | 445 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); |
456 | else | 446 | else |
457 | tx->timeout.pm_frame_timeout = cpu_to_le16(2); | 447 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); |
458 | } else { | 448 | } else { |
459 | tx->timeout.pm_frame_timeout = 0; | 449 | tx_cmd->timeout.pm_frame_timeout = 0; |
460 | #ifdef CONFIG_IWLWIFI_LEDS | ||
461 | priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); | ||
462 | #endif | ||
463 | } | 450 | } |
464 | 451 | ||
465 | tx->driver_txop = 0; | 452 | tx_cmd->driver_txop = 0; |
466 | tx->tx_flags = tx_flags; | 453 | tx_cmd->tx_flags = tx_flags; |
467 | tx->next_frame_len = 0; | 454 | tx_cmd->next_frame_len = 0; |
468 | } | 455 | } |
469 | 456 | ||
470 | /* | 457 | /* |
@@ -474,7 +461,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
474 | { | 461 | { |
475 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 462 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
476 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 463 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
477 | struct iwl3945_tx_cmd *tx; | 464 | struct iwl3945_tx_cmd *tx_cmd; |
478 | struct iwl_tx_queue *txq = NULL; | 465 | struct iwl_tx_queue *txq = NULL; |
479 | struct iwl_queue *q = NULL; | 466 | struct iwl_queue *q = NULL; |
480 | struct iwl_device_cmd *out_cmd; | 467 | struct iwl_device_cmd *out_cmd; |
@@ -492,7 +479,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
492 | u8 wait_write_ptr = 0; | 479 | u8 wait_write_ptr = 0; |
493 | u8 *qc = NULL; | 480 | u8 *qc = NULL; |
494 | unsigned long flags; | 481 | unsigned long flags; |
495 | int rc; | ||
496 | 482 | ||
497 | spin_lock_irqsave(&priv->lock, flags); | 483 | spin_lock_irqsave(&priv->lock, flags); |
498 | if (iwl_is_rfkill(priv)) { | 484 | if (iwl_is_rfkill(priv)) { |
@@ -562,6 +548,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
562 | txq = &priv->txq[txq_id]; | 548 | txq = &priv->txq[txq_id]; |
563 | q = &txq->q; | 549 | q = &txq->q; |
564 | 550 | ||
551 | if ((iwl_queue_space(q) < q->high_mark)) | ||
552 | goto drop; | ||
553 | |||
565 | spin_lock_irqsave(&priv->lock, flags); | 554 | spin_lock_irqsave(&priv->lock, flags); |
566 | 555 | ||
567 | idx = get_cmd_index(q, q->write_ptr, 0); | 556 | idx = get_cmd_index(q, q->write_ptr, 0); |
@@ -573,9 +562,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
573 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | 562 | /* Init first empty entry in queue's array of Tx/cmd buffers */ |
574 | out_cmd = txq->cmd[idx]; | 563 | out_cmd = txq->cmd[idx]; |
575 | out_meta = &txq->meta[idx]; | 564 | out_meta = &txq->meta[idx]; |
576 | tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; | 565 | tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; |
577 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | 566 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); |
578 | memset(tx, 0, sizeof(*tx)); | 567 | memset(tx_cmd, 0, sizeof(*tx_cmd)); |
579 | 568 | ||
580 | /* | 569 | /* |
581 | * Set up the Tx-command (not MAC!) header. | 570 | * Set up the Tx-command (not MAC!) header. |
@@ -588,7 +577,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
588 | INDEX_TO_SEQ(q->write_ptr))); | 577 | INDEX_TO_SEQ(q->write_ptr))); |
589 | 578 | ||
590 | /* Copy MAC header from skb into command buffer */ | 579 | /* Copy MAC header from skb into command buffer */ |
591 | memcpy(tx->hdr, hdr, hdr_len); | 580 | memcpy(tx_cmd->hdr, hdr, hdr_len); |
592 | 581 | ||
593 | 582 | ||
594 | if (info->control.hw_key) | 583 | if (info->control.hw_key) |
@@ -602,12 +591,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
602 | 591 | ||
603 | /* Total # bytes to be transmitted */ | 592 | /* Total # bytes to be transmitted */ |
604 | len = (u16)skb->len; | 593 | len = (u16)skb->len; |
605 | tx->len = cpu_to_le16(len); | 594 | tx_cmd->len = cpu_to_le16(len); |
606 | 595 | ||
607 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | 596 | iwl_dbg_log_tx_data_frame(priv, len, hdr); |
608 | iwl_update_stats(priv, true, fc, len); | 597 | iwl_update_stats(priv, true, fc, len); |
609 | tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; | 598 | tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; |
610 | tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; | 599 | tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; |
611 | 600 | ||
612 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 601 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
613 | txq->need_update = 1; | 602 | txq->need_update = 1; |
@@ -620,9 +609,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
620 | 609 | ||
621 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 610 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", |
622 | le16_to_cpu(out_cmd->hdr.sequence)); | 611 | le16_to_cpu(out_cmd->hdr.sequence)); |
623 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); | 612 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); |
624 | iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx)); | 613 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); |
625 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr, | 614 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, |
626 | ieee80211_hdrlen(fc)); | 615 | ieee80211_hdrlen(fc)); |
627 | 616 | ||
628 | /* | 617 | /* |
@@ -674,12 +663,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
674 | 663 | ||
675 | /* Tell device the write index *just past* this latest filled TFD */ | 664 | /* Tell device the write index *just past* this latest filled TFD */ |
676 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 665 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
677 | rc = iwl_txq_update_write_ptr(priv, txq); | 666 | iwl_txq_update_write_ptr(priv, txq); |
678 | spin_unlock_irqrestore(&priv->lock, flags); | 667 | spin_unlock_irqrestore(&priv->lock, flags); |
679 | 668 | ||
680 | if (rc) | ||
681 | return rc; | ||
682 | |||
683 | if ((iwl_queue_space(q) < q->high_mark) | 669 | if ((iwl_queue_space(q) < q->high_mark) |
684 | && priv->mac80211_registered) { | 670 | && priv->mac80211_registered) { |
685 | if (wait_write_ptr) { | 671 | if (wait_write_ptr) { |
@@ -700,10 +686,6 @@ drop: | |||
700 | return -1; | 686 | return -1; |
701 | } | 687 | } |
702 | 688 | ||
703 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | ||
704 | |||
705 | #include "iwl-spectrum.h" | ||
706 | |||
707 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF | 689 | #define BEACON_TIME_MASK_LOW 0x00FFFFFF |
708 | #define BEACON_TIME_MASK_HIGH 0xFF000000 | 690 | #define BEACON_TIME_MASK_HIGH 0xFF000000 |
709 | #define TIME_UNIT 1024 | 691 | #define TIME_UNIT 1024 |
@@ -758,7 +740,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
758 | u8 type) | 740 | u8 type) |
759 | { | 741 | { |
760 | struct iwl_spectrum_cmd spectrum; | 742 | struct iwl_spectrum_cmd spectrum; |
761 | struct iwl_rx_packet *res; | 743 | struct iwl_rx_packet *pkt; |
762 | struct iwl_host_cmd cmd = { | 744 | struct iwl_host_cmd cmd = { |
763 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, | 745 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, |
764 | .data = (void *)&spectrum, | 746 | .data = (void *)&spectrum, |
@@ -803,18 +785,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
803 | if (rc) | 785 | if (rc) |
804 | return rc; | 786 | return rc; |
805 | 787 | ||
806 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 788 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
807 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 789 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
808 | IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); | 790 | IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); |
809 | rc = -EIO; | 791 | rc = -EIO; |
810 | } | 792 | } |
811 | 793 | ||
812 | spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); | 794 | spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status); |
813 | switch (spectrum_resp_status) { | 795 | switch (spectrum_resp_status) { |
814 | case 0: /* Command will be handled */ | 796 | case 0: /* Command will be handled */ |
815 | if (res->u.spectrum.id != 0xff) { | 797 | if (pkt->u.spectrum.id != 0xff) { |
816 | IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", | 798 | IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", |
817 | res->u.spectrum.id); | 799 | pkt->u.spectrum.id); |
818 | priv->measurement_status &= ~MEASUREMENT_READY; | 800 | priv->measurement_status &= ~MEASUREMENT_READY; |
819 | } | 801 | } |
820 | priv->measurement_status |= MEASUREMENT_ACTIVE; | 802 | priv->measurement_status |= MEASUREMENT_ACTIVE; |
@@ -826,16 +808,15 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
826 | break; | 808 | break; |
827 | } | 809 | } |
828 | 810 | ||
829 | dev_kfree_skb_any(cmd.reply_skb); | 811 | iwl_free_pages(priv, cmd.reply_page); |
830 | 812 | ||
831 | return rc; | 813 | return rc; |
832 | } | 814 | } |
833 | #endif | ||
834 | 815 | ||
835 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, | 816 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, |
836 | struct iwl_rx_mem_buffer *rxb) | 817 | struct iwl_rx_mem_buffer *rxb) |
837 | { | 818 | { |
838 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 819 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
839 | struct iwl_alive_resp *palive; | 820 | struct iwl_alive_resp *palive; |
840 | struct delayed_work *pwork; | 821 | struct delayed_work *pwork; |
841 | 822 | ||
@@ -872,7 +853,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, | |||
872 | struct iwl_rx_mem_buffer *rxb) | 853 | struct iwl_rx_mem_buffer *rxb) |
873 | { | 854 | { |
874 | #ifdef CONFIG_IWLWIFI_DEBUG | 855 | #ifdef CONFIG_IWLWIFI_DEBUG |
875 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 856 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
876 | #endif | 857 | #endif |
877 | 858 | ||
878 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); | 859 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); |
@@ -908,7 +889,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | |||
908 | struct iwl_rx_mem_buffer *rxb) | 889 | struct iwl_rx_mem_buffer *rxb) |
909 | { | 890 | { |
910 | #ifdef CONFIG_IWLWIFI_DEBUG | 891 | #ifdef CONFIG_IWLWIFI_DEBUG |
911 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 892 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
912 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); | 893 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); |
913 | u8 rate = beacon->beacon_notify_hdr.rate; | 894 | u8 rate = beacon->beacon_notify_hdr.rate; |
914 | 895 | ||
@@ -931,7 +912,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | |||
931 | static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, | 912 | static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, |
932 | struct iwl_rx_mem_buffer *rxb) | 913 | struct iwl_rx_mem_buffer *rxb) |
933 | { | 914 | { |
934 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 915 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
935 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 916 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
936 | unsigned long status = priv->status; | 917 | unsigned long status = priv->status; |
937 | 918 | ||
@@ -973,6 +954,8 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | |||
973 | priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; | 954 | priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; |
974 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; | 955 | priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; |
975 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; | 956 | priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; |
957 | priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = | ||
958 | iwl_rx_spectrum_measure_notif; | ||
976 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 959 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
977 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | 960 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = |
978 | iwl_rx_pm_debug_statistics_notif; | 961 | iwl_rx_pm_debug_statistics_notif; |
@@ -986,7 +969,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) | |||
986 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; | 969 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; |
987 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; | 970 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; |
988 | 971 | ||
989 | iwl_setup_spectrum_handlers(priv); | ||
990 | iwl_setup_rx_scan_handlers(priv); | 972 | iwl_setup_rx_scan_handlers(priv); |
991 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; | 973 | priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; |
992 | 974 | ||
@@ -1078,13 +1060,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
1078 | * also updates the memory address in the firmware to reference the new | 1060 | * also updates the memory address in the firmware to reference the new |
1079 | * target buffer. | 1061 | * target buffer. |
1080 | */ | 1062 | */ |
1081 | static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | 1063 | static void iwl3945_rx_queue_restock(struct iwl_priv *priv) |
1082 | { | 1064 | { |
1083 | struct iwl_rx_queue *rxq = &priv->rxq; | 1065 | struct iwl_rx_queue *rxq = &priv->rxq; |
1084 | struct list_head *element; | 1066 | struct list_head *element; |
1085 | struct iwl_rx_mem_buffer *rxb; | 1067 | struct iwl_rx_mem_buffer *rxb; |
1086 | unsigned long flags; | 1068 | unsigned long flags; |
1087 | int write, rc; | 1069 | int write; |
1088 | 1070 | ||
1089 | spin_lock_irqsave(&rxq->lock, flags); | 1071 | spin_lock_irqsave(&rxq->lock, flags); |
1090 | write = rxq->write & ~0x7; | 1072 | write = rxq->write & ~0x7; |
@@ -1095,7 +1077,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1095 | list_del(element); | 1077 | list_del(element); |
1096 | 1078 | ||
1097 | /* Point to Rx buffer via next RBD in circular buffer */ | 1079 | /* Point to Rx buffer via next RBD in circular buffer */ |
1098 | rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr); | 1080 | rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma); |
1099 | rxq->queue[rxq->write] = rxb; | 1081 | rxq->queue[rxq->write] = rxb; |
1100 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 1082 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
1101 | rxq->free_count--; | 1083 | rxq->free_count--; |
@@ -1114,12 +1096,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1114 | spin_lock_irqsave(&rxq->lock, flags); | 1096 | spin_lock_irqsave(&rxq->lock, flags); |
1115 | rxq->need_update = 1; | 1097 | rxq->need_update = 1; |
1116 | spin_unlock_irqrestore(&rxq->lock, flags); | 1098 | spin_unlock_irqrestore(&rxq->lock, flags); |
1117 | rc = iwl_rx_queue_update_write_ptr(priv, rxq); | 1099 | iwl_rx_queue_update_write_ptr(priv, rxq); |
1118 | if (rc) | ||
1119 | return rc; | ||
1120 | } | 1100 | } |
1121 | |||
1122 | return 0; | ||
1123 | } | 1101 | } |
1124 | 1102 | ||
1125 | /** | 1103 | /** |
@@ -1135,8 +1113,9 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1135 | struct iwl_rx_queue *rxq = &priv->rxq; | 1113 | struct iwl_rx_queue *rxq = &priv->rxq; |
1136 | struct list_head *element; | 1114 | struct list_head *element; |
1137 | struct iwl_rx_mem_buffer *rxb; | 1115 | struct iwl_rx_mem_buffer *rxb; |
1138 | struct sk_buff *skb; | 1116 | struct page *page; |
1139 | unsigned long flags; | 1117 | unsigned long flags; |
1118 | gfp_t gfp_mask = priority; | ||
1140 | 1119 | ||
1141 | while (1) { | 1120 | while (1) { |
1142 | spin_lock_irqsave(&rxq->lock, flags); | 1121 | spin_lock_irqsave(&rxq->lock, flags); |
@@ -1148,10 +1127,14 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1148 | spin_unlock_irqrestore(&rxq->lock, flags); | 1127 | spin_unlock_irqrestore(&rxq->lock, flags); |
1149 | 1128 | ||
1150 | if (rxq->free_count > RX_LOW_WATERMARK) | 1129 | if (rxq->free_count > RX_LOW_WATERMARK) |
1151 | priority |= __GFP_NOWARN; | 1130 | gfp_mask |= __GFP_NOWARN; |
1131 | |||
1132 | if (priv->hw_params.rx_page_order > 0) | ||
1133 | gfp_mask |= __GFP_COMP; | ||
1134 | |||
1152 | /* Alloc a new receive buffer */ | 1135 | /* Alloc a new receive buffer */ |
1153 | skb = alloc_skb(priv->hw_params.rx_buf_size, priority); | 1136 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); |
1154 | if (!skb) { | 1137 | if (!page) { |
1155 | if (net_ratelimit()) | 1138 | if (net_ratelimit()) |
1156 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | 1139 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); |
1157 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | 1140 | if ((rxq->free_count <= RX_LOW_WATERMARK) && |
@@ -1168,7 +1151,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1168 | spin_lock_irqsave(&rxq->lock, flags); | 1151 | spin_lock_irqsave(&rxq->lock, flags); |
1169 | if (list_empty(&rxq->rx_used)) { | 1152 | if (list_empty(&rxq->rx_used)) { |
1170 | spin_unlock_irqrestore(&rxq->lock, flags); | 1153 | spin_unlock_irqrestore(&rxq->lock, flags); |
1171 | dev_kfree_skb_any(skb); | 1154 | __free_pages(page, priv->hw_params.rx_page_order); |
1172 | return; | 1155 | return; |
1173 | } | 1156 | } |
1174 | element = rxq->rx_used.next; | 1157 | element = rxq->rx_used.next; |
@@ -1176,26 +1159,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1176 | list_del(element); | 1159 | list_del(element); |
1177 | spin_unlock_irqrestore(&rxq->lock, flags); | 1160 | spin_unlock_irqrestore(&rxq->lock, flags); |
1178 | 1161 | ||
1179 | rxb->skb = skb; | 1162 | rxb->page = page; |
1180 | |||
1181 | /* If radiotap head is required, reserve some headroom here. | ||
1182 | * The physical head count is a variable rx_stats->phy_count. | ||
1183 | * We reserve 4 bytes here. Plus these extra bytes, the | ||
1184 | * headroom of the physical head should be enough for the | ||
1185 | * radiotap head that iwl3945 supported. See iwl3945_rt. | ||
1186 | */ | ||
1187 | skb_reserve(rxb->skb, 4); | ||
1188 | |||
1189 | /* Get physical address of RB/SKB */ | 1163 | /* Get physical address of RB/SKB */ |
1190 | rxb->real_dma_addr = pci_map_single(priv->pci_dev, | 1164 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, |
1191 | rxb->skb->data, | 1165 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1192 | priv->hw_params.rx_buf_size, | 1166 | PCI_DMA_FROMDEVICE); |
1193 | PCI_DMA_FROMDEVICE); | ||
1194 | 1167 | ||
1195 | spin_lock_irqsave(&rxq->lock, flags); | 1168 | spin_lock_irqsave(&rxq->lock, flags); |
1169 | |||
1196 | list_add_tail(&rxb->list, &rxq->rx_free); | 1170 | list_add_tail(&rxb->list, &rxq->rx_free); |
1197 | priv->alloc_rxb_skb++; | ||
1198 | rxq->free_count++; | 1171 | rxq->free_count++; |
1172 | priv->alloc_rxb_page++; | ||
1173 | |||
1199 | spin_unlock_irqrestore(&rxq->lock, flags); | 1174 | spin_unlock_irqrestore(&rxq->lock, flags); |
1200 | } | 1175 | } |
1201 | } | 1176 | } |
@@ -1211,14 +1186,12 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
1211 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | 1186 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { |
1212 | /* In the reset function, these buffers may have been allocated | 1187 | /* In the reset function, these buffers may have been allocated |
1213 | * to an SKB, so we need to unmap and free potential storage */ | 1188 | * to an SKB, so we need to unmap and free potential storage */ |
1214 | if (rxq->pool[i].skb != NULL) { | 1189 | if (rxq->pool[i].page != NULL) { |
1215 | pci_unmap_single(priv->pci_dev, | 1190 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
1216 | rxq->pool[i].real_dma_addr, | 1191 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1217 | priv->hw_params.rx_buf_size, | 1192 | PCI_DMA_FROMDEVICE); |
1218 | PCI_DMA_FROMDEVICE); | 1193 | __iwl_free_pages(priv, rxq->pool[i].page); |
1219 | priv->alloc_rxb_skb--; | 1194 | rxq->pool[i].page = NULL; |
1220 | dev_kfree_skb(rxq->pool[i].skb); | ||
1221 | rxq->pool[i].skb = NULL; | ||
1222 | } | 1195 | } |
1223 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | 1196 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); |
1224 | } | 1197 | } |
@@ -1226,8 +1199,8 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
1226 | /* Set us so that we have processed and used all buffers, but have | 1199 | /* Set us so that we have processed and used all buffers, but have |
1227 | * not restocked the Rx queue with fresh buffers */ | 1200 | * not restocked the Rx queue with fresh buffers */ |
1228 | rxq->read = rxq->write = 0; | 1201 | rxq->read = rxq->write = 0; |
1229 | rxq->free_count = 0; | ||
1230 | rxq->write_actual = 0; | 1202 | rxq->write_actual = 0; |
1203 | rxq->free_count = 0; | ||
1231 | spin_unlock_irqrestore(&rxq->lock, flags); | 1204 | spin_unlock_irqrestore(&rxq->lock, flags); |
1232 | } | 1205 | } |
1233 | 1206 | ||
@@ -1260,19 +1233,19 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx | |||
1260 | { | 1233 | { |
1261 | int i; | 1234 | int i; |
1262 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | 1235 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { |
1263 | if (rxq->pool[i].skb != NULL) { | 1236 | if (rxq->pool[i].page != NULL) { |
1264 | pci_unmap_single(priv->pci_dev, | 1237 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
1265 | rxq->pool[i].real_dma_addr, | 1238 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1266 | priv->hw_params.rx_buf_size, | 1239 | PCI_DMA_FROMDEVICE); |
1267 | PCI_DMA_FROMDEVICE); | 1240 | __iwl_free_pages(priv, rxq->pool[i].page); |
1268 | dev_kfree_skb(rxq->pool[i].skb); | 1241 | rxq->pool[i].page = NULL; |
1269 | } | 1242 | } |
1270 | } | 1243 | } |
1271 | 1244 | ||
1272 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 1245 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
1273 | rxq->dma_addr); | 1246 | rxq->dma_addr); |
1274 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 1247 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
1275 | rxq->rb_stts, rxq->rb_stts_dma); | 1248 | rxq->rb_stts, rxq->rb_stts_dma); |
1276 | rxq->bd = NULL; | 1249 | rxq->bd = NULL; |
1277 | rxq->rb_stts = NULL; | 1250 | rxq->rb_stts = NULL; |
1278 | } | 1251 | } |
@@ -1315,47 +1288,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio) | |||
1315 | return (int)ratio2dB[sig_ratio]; | 1288 | return (int)ratio2dB[sig_ratio]; |
1316 | } | 1289 | } |
1317 | 1290 | ||
1318 | #define PERFECT_RSSI (-20) /* dBm */ | ||
1319 | #define WORST_RSSI (-95) /* dBm */ | ||
1320 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
1321 | |||
1322 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
1323 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
1324 | * about formulas used below. */ | ||
1325 | int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
1326 | { | ||
1327 | int sig_qual; | ||
1328 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
1329 | |||
1330 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
1331 | * as indicator; formula is (signal dbm - noise dbm). | ||
1332 | * SNR at or above 40 is a great signal (100%). | ||
1333 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
1334 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
1335 | if (noise_dbm) { | ||
1336 | if (rssi_dbm - noise_dbm >= 40) | ||
1337 | return 100; | ||
1338 | else if (rssi_dbm < noise_dbm) | ||
1339 | return 0; | ||
1340 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
1341 | |||
1342 | /* Else use just the signal level. | ||
1343 | * This formula is a least squares fit of data points collected and | ||
1344 | * compared with a reference system that had a percentage (%) display | ||
1345 | * for signal quality. */ | ||
1346 | } else | ||
1347 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
1348 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
1349 | (RSSI_RANGE * RSSI_RANGE); | ||
1350 | |||
1351 | if (sig_qual > 100) | ||
1352 | sig_qual = 100; | ||
1353 | else if (sig_qual < 1) | ||
1354 | sig_qual = 0; | ||
1355 | |||
1356 | return sig_qual; | ||
1357 | } | ||
1358 | |||
1359 | /** | 1291 | /** |
1360 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode | 1292 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode |
1361 | * | 1293 | * |
@@ -1381,7 +1313,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1381 | i = rxq->read; | 1313 | i = rxq->read; |
1382 | 1314 | ||
1383 | /* calculate total frames need to be restock after handling RX */ | 1315 | /* calculate total frames need to be restock after handling RX */ |
1384 | total_empty = r - priv->rxq.write_actual; | 1316 | total_empty = r - rxq->write_actual; |
1385 | if (total_empty < 0) | 1317 | if (total_empty < 0) |
1386 | total_empty += RX_QUEUE_SIZE; | 1318 | total_empty += RX_QUEUE_SIZE; |
1387 | 1319 | ||
@@ -1401,10 +1333,13 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1401 | 1333 | ||
1402 | rxq->queue[i] = NULL; | 1334 | rxq->queue[i] = NULL; |
1403 | 1335 | ||
1404 | pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, | 1336 | pci_unmap_page(priv->pci_dev, rxb->page_dma, |
1405 | priv->hw_params.rx_buf_size, | 1337 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1406 | PCI_DMA_FROMDEVICE); | 1338 | PCI_DMA_FROMDEVICE); |
1407 | pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1339 | pkt = rxb_addr(rxb); |
1340 | |||
1341 | trace_iwlwifi_dev_rx(priv, pkt, | ||
1342 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
1408 | 1343 | ||
1409 | /* Reclaim a command buffer only if this packet is a response | 1344 | /* Reclaim a command buffer only if this packet is a response |
1410 | * to a (driver-originated) command. | 1345 | * to a (driver-originated) command. |
@@ -1422,44 +1357,55 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1422 | if (priv->rx_handlers[pkt->hdr.cmd]) { | 1357 | if (priv->rx_handlers[pkt->hdr.cmd]) { |
1423 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, | 1358 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, |
1424 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 1359 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); |
1425 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
1426 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; | 1360 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; |
1361 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
1427 | } else { | 1362 | } else { |
1428 | /* No handling needed */ | 1363 | /* No handling needed */ |
1429 | IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n", | 1364 | IWL_DEBUG_RX(priv, |
1365 | "r %d i %d No handler needed for %s, 0x%02x\n", | ||
1430 | r, i, get_cmd_string(pkt->hdr.cmd), | 1366 | r, i, get_cmd_string(pkt->hdr.cmd), |
1431 | pkt->hdr.cmd); | 1367 | pkt->hdr.cmd); |
1432 | } | 1368 | } |
1433 | 1369 | ||
1370 | /* | ||
1371 | * XXX: After here, we should always check rxb->page | ||
1372 | * against NULL before touching it or its virtual | ||
1373 | * memory (pkt). Because some rx_handler might have | ||
1374 | * already taken or freed the pages. | ||
1375 | */ | ||
1376 | |||
1434 | if (reclaim) { | 1377 | if (reclaim) { |
1435 | /* Invoke any callbacks, transfer the skb to caller, and | 1378 | /* Invoke any callbacks, transfer the buffer to caller, |
1436 | * fire off the (possibly) blocking iwl_send_cmd() | 1379 | * and fire off the (possibly) blocking iwl_send_cmd() |
1437 | * as we reclaim the driver command queue */ | 1380 | * as we reclaim the driver command queue */ |
1438 | if (rxb && rxb->skb) | 1381 | if (rxb->page) |
1439 | iwl_tx_cmd_complete(priv, rxb); | 1382 | iwl_tx_cmd_complete(priv, rxb); |
1440 | else | 1383 | else |
1441 | IWL_WARN(priv, "Claim null rxb?\n"); | 1384 | IWL_WARN(priv, "Claim null rxb?\n"); |
1442 | } | 1385 | } |
1443 | 1386 | ||
1444 | /* For now we just don't re-use anything. We can tweak this | 1387 | /* Reuse the page if possible. For notification packets and |
1445 | * later to try and re-use notification packets and SKBs that | 1388 | * SKBs that fail to Rx correctly, add them back into the |
1446 | * fail to Rx correctly */ | 1389 | * rx_free list for reuse later. */ |
1447 | if (rxb->skb != NULL) { | ||
1448 | priv->alloc_rxb_skb--; | ||
1449 | dev_kfree_skb_any(rxb->skb); | ||
1450 | rxb->skb = NULL; | ||
1451 | } | ||
1452 | |||
1453 | spin_lock_irqsave(&rxq->lock, flags); | 1390 | spin_lock_irqsave(&rxq->lock, flags); |
1454 | list_add_tail(&rxb->list, &priv->rxq.rx_used); | 1391 | if (rxb->page != NULL) { |
1392 | rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page, | ||
1393 | 0, PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1394 | PCI_DMA_FROMDEVICE); | ||
1395 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
1396 | rxq->free_count++; | ||
1397 | } else | ||
1398 | list_add_tail(&rxb->list, &rxq->rx_used); | ||
1399 | |||
1455 | spin_unlock_irqrestore(&rxq->lock, flags); | 1400 | spin_unlock_irqrestore(&rxq->lock, flags); |
1401 | |||
1456 | i = (i + 1) & RX_QUEUE_MASK; | 1402 | i = (i + 1) & RX_QUEUE_MASK; |
1457 | /* If there are a lot of unused frames, | 1403 | /* If there are a lot of unused frames, |
1458 | * restock the Rx queue so ucode won't assert. */ | 1404 | * restock the Rx queue so ucode won't assert. */ |
1459 | if (fill_rx) { | 1405 | if (fill_rx) { |
1460 | count++; | 1406 | count++; |
1461 | if (count >= 8) { | 1407 | if (count >= 8) { |
1462 | priv->rxq.read = i; | 1408 | rxq->read = i; |
1463 | iwl3945_rx_replenish_now(priv); | 1409 | iwl3945_rx_replenish_now(priv); |
1464 | count = 0; | 1410 | count = 0; |
1465 | } | 1411 | } |
@@ -1467,7 +1413,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1467 | } | 1413 | } |
1468 | 1414 | ||
1469 | /* Backtrack one entry */ | 1415 | /* Backtrack one entry */ |
1470 | priv->rxq.read = i; | 1416 | rxq->read = i; |
1471 | if (fill_rx) | 1417 | if (fill_rx) |
1472 | iwl3945_rx_replenish_now(priv); | 1418 | iwl3945_rx_replenish_now(priv); |
1473 | else | 1419 | else |
@@ -1482,7 +1428,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) | |||
1482 | tasklet_kill(&priv->irq_tasklet); | 1428 | tasklet_kill(&priv->irq_tasklet); |
1483 | } | 1429 | } |
1484 | 1430 | ||
1485 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1486 | static const char *desc_lookup(int i) | 1431 | static const char *desc_lookup(int i) |
1487 | { | 1432 | { |
1488 | switch (i) { | 1433 | switch (i) { |
@@ -1551,8 +1496,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1551 | "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", | 1496 | "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", |
1552 | desc_lookup(desc), desc, time, blink1, blink2, | 1497 | desc_lookup(desc), desc, time, blink1, blink2, |
1553 | ilink1, ilink2, data1); | 1498 | ilink1, ilink2, data1); |
1499 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0, | ||
1500 | 0, blink1, blink2, ilink1, ilink2); | ||
1554 | } | 1501 | } |
1555 | |||
1556 | } | 1502 | } |
1557 | 1503 | ||
1558 | #define EVENT_START_OFFSET (6 * sizeof(u32)) | 1504 | #define EVENT_START_OFFSET (6 * sizeof(u32)) |
@@ -1561,17 +1507,19 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1561 | * iwl3945_print_event_log - Dump error event log to syslog | 1507 | * iwl3945_print_event_log - Dump error event log to syslog |
1562 | * | 1508 | * |
1563 | */ | 1509 | */ |
1564 | static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1510 | static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1565 | u32 num_events, u32 mode) | 1511 | u32 num_events, u32 mode, |
1512 | int pos, char **buf, size_t bufsz) | ||
1566 | { | 1513 | { |
1567 | u32 i; | 1514 | u32 i; |
1568 | u32 base; /* SRAM byte address of event log header */ | 1515 | u32 base; /* SRAM byte address of event log header */ |
1569 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | 1516 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ |
1570 | u32 ptr; /* SRAM byte address of log data */ | 1517 | u32 ptr; /* SRAM byte address of log data */ |
1571 | u32 ev, time, data; /* event log data */ | 1518 | u32 ev, time, data; /* event log data */ |
1519 | unsigned long reg_flags; | ||
1572 | 1520 | ||
1573 | if (num_events == 0) | 1521 | if (num_events == 0) |
1574 | return; | 1522 | return pos; |
1575 | 1523 | ||
1576 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1524 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1577 | 1525 | ||
@@ -1582,25 +1530,96 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1582 | 1530 | ||
1583 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | 1531 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); |
1584 | 1532 | ||
1533 | /* Make sure device is powered up for SRAM reads */ | ||
1534 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
1535 | iwl_grab_nic_access(priv); | ||
1536 | |||
1537 | /* Set starting address; reads will auto-increment */ | ||
1538 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
1539 | rmb(); | ||
1540 | |||
1585 | /* "time" is actually "data" for mode 0 (no timestamp). | 1541 | /* "time" is actually "data" for mode 0 (no timestamp). |
1586 | * place event id # at far right for easier visual parsing. */ | 1542 | * place event id # at far right for easier visual parsing. */ |
1587 | for (i = 0; i < num_events; i++) { | 1543 | for (i = 0; i < num_events; i++) { |
1588 | ev = iwl_read_targ_mem(priv, ptr); | 1544 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1589 | ptr += sizeof(u32); | 1545 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1590 | time = iwl_read_targ_mem(priv, ptr); | ||
1591 | ptr += sizeof(u32); | ||
1592 | if (mode == 0) { | 1546 | if (mode == 0) { |
1593 | /* data, ev */ | 1547 | /* data, ev */ |
1594 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | 1548 | if (bufsz) { |
1549 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1550 | "0x%08x:%04u\n", | ||
1551 | time, ev); | ||
1552 | } else { | ||
1553 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | ||
1554 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1555 | time, ev); | ||
1556 | } | ||
1595 | } else { | 1557 | } else { |
1596 | data = iwl_read_targ_mem(priv, ptr); | 1558 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1597 | ptr += sizeof(u32); | 1559 | if (bufsz) { |
1598 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); | 1560 | pos += scnprintf(*buf + pos, bufsz - pos, |
1561 | "%010u:0x%08x:%04u\n", | ||
1562 | time, data, ev); | ||
1563 | } else { | ||
1564 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", | ||
1565 | time, data, ev); | ||
1566 | trace_iwlwifi_dev_ucode_event(priv, time, | ||
1567 | data, ev); | ||
1568 | } | ||
1599 | } | 1569 | } |
1600 | } | 1570 | } |
1571 | |||
1572 | /* Allow device to power down */ | ||
1573 | iwl_release_nic_access(priv); | ||
1574 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
1575 | return pos; | ||
1601 | } | 1576 | } |
1602 | 1577 | ||
1603 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | 1578 | /** |
1579 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog | ||
1580 | */ | ||
1581 | static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1582 | u32 num_wraps, u32 next_entry, | ||
1583 | u32 size, u32 mode, | ||
1584 | int pos, char **buf, size_t bufsz) | ||
1585 | { | ||
1586 | /* | ||
1587 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1588 | * i.e the entries just before the next ont that uCode would fill. | ||
1589 | */ | ||
1590 | if (num_wraps) { | ||
1591 | if (next_entry < size) { | ||
1592 | pos = iwl3945_print_event_log(priv, | ||
1593 | capacity - (size - next_entry), | ||
1594 | size - next_entry, mode, | ||
1595 | pos, buf, bufsz); | ||
1596 | pos = iwl3945_print_event_log(priv, 0, | ||
1597 | next_entry, mode, | ||
1598 | pos, buf, bufsz); | ||
1599 | } else | ||
1600 | pos = iwl3945_print_event_log(priv, next_entry - size, | ||
1601 | size, mode, | ||
1602 | pos, buf, bufsz); | ||
1603 | } else { | ||
1604 | if (next_entry < size) | ||
1605 | pos = iwl3945_print_event_log(priv, 0, | ||
1606 | next_entry, mode, | ||
1607 | pos, buf, bufsz); | ||
1608 | else | ||
1609 | pos = iwl3945_print_event_log(priv, next_entry - size, | ||
1610 | size, mode, | ||
1611 | pos, buf, bufsz); | ||
1612 | } | ||
1613 | return pos; | ||
1614 | } | ||
1615 | |||
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) | ||
1620 | |||
1621 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | ||
1622 | char **buf, bool display) | ||
1604 | { | 1623 | { |
1605 | u32 base; /* SRAM byte address of event log header */ | 1624 | u32 base; /* SRAM byte address of event log header */ |
1606 | u32 capacity; /* event log capacity in # entries */ | 1625 | u32 capacity; /* event log capacity in # entries */ |
@@ -1608,11 +1627,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | |||
1608 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1627 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1609 | u32 next_entry; /* index of next entry to be written by uCode */ | 1628 | u32 next_entry; /* index of next entry to be written by uCode */ |
1610 | u32 size; /* # entries that we'll print */ | 1629 | u32 size; /* # entries that we'll print */ |
1630 | int pos = 0; | ||
1631 | size_t bufsz = 0; | ||
1611 | 1632 | ||
1612 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1633 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1613 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | 1634 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { |
1614 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | 1635 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); |
1615 | return; | 1636 | return -EINVAL; |
1616 | } | 1637 | } |
1617 | 1638 | ||
1618 | /* event log header */ | 1639 | /* event log header */ |
@@ -1621,37 +1642,72 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | |||
1621 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 1642 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1622 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 1643 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1623 | 1644 | ||
1645 | if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) { | ||
1646 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | ||
1647 | capacity, IWL3945_MAX_EVENT_LOG_SIZE); | ||
1648 | capacity = IWL3945_MAX_EVENT_LOG_SIZE; | ||
1649 | } | ||
1650 | |||
1651 | if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) { | ||
1652 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | ||
1653 | next_entry, IWL3945_MAX_EVENT_LOG_SIZE); | ||
1654 | next_entry = IWL3945_MAX_EVENT_LOG_SIZE; | ||
1655 | } | ||
1656 | |||
1624 | size = num_wraps ? capacity : next_entry; | 1657 | size = num_wraps ? capacity : next_entry; |
1625 | 1658 | ||
1626 | /* bail out if nothing in log */ | 1659 | /* bail out if nothing in log */ |
1627 | if (size == 0) { | 1660 | if (size == 0) { |
1628 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 1661 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1629 | return; | 1662 | return pos; |
1630 | } | 1663 | } |
1631 | 1664 | ||
1632 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | 1665 | #ifdef CONFIG_IWLWIFI_DEBUG |
1633 | size, num_wraps); | 1666 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) |
1634 | 1667 | size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) | |
1635 | /* if uCode has wrapped back to top of log, start at the oldest entry, | 1668 | ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; |
1636 | * i.e the next one that uCode would fill. */ | ||
1637 | if (num_wraps) | ||
1638 | iwl3945_print_event_log(priv, next_entry, | ||
1639 | capacity - next_entry, mode); | ||
1640 | |||
1641 | /* (then/else) start at top of log */ | ||
1642 | iwl3945_print_event_log(priv, 0, next_entry, mode); | ||
1643 | |||
1644 | } | ||
1645 | #else | 1669 | #else |
1646 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | 1670 | size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) |
1647 | { | 1671 | ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; |
1648 | } | 1672 | #endif |
1649 | 1673 | ||
1650 | void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | 1674 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n", |
1651 | { | 1675 | size); |
1652 | } | ||
1653 | 1676 | ||
1677 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1678 | if (display) { | ||
1679 | if (full_log) | ||
1680 | bufsz = capacity * 48; | ||
1681 | else | ||
1682 | bufsz = size * 48; | ||
1683 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1684 | if (!*buf) | ||
1685 | return -ENOMEM; | ||
1686 | } | ||
1687 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | ||
1688 | /* if uCode has wrapped back to top of log, | ||
1689 | * start at the oldest entry, | ||
1690 | * i.e the next one that uCode would fill. | ||
1691 | */ | ||
1692 | if (num_wraps) | ||
1693 | pos = iwl3945_print_event_log(priv, next_entry, | ||
1694 | capacity - next_entry, mode, | ||
1695 | pos, buf, bufsz); | ||
1696 | |||
1697 | /* (then/else) start at top of log */ | ||
1698 | pos = iwl3945_print_event_log(priv, 0, next_entry, mode, | ||
1699 | pos, buf, bufsz); | ||
1700 | } else | ||
1701 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, | ||
1702 | next_entry, size, mode, | ||
1703 | pos, buf, bufsz); | ||
1704 | #else | ||
1705 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, | ||
1706 | next_entry, size, mode, | ||
1707 | pos, buf, bufsz); | ||
1654 | #endif | 1708 | #endif |
1709 | return pos; | ||
1710 | } | ||
1655 | 1711 | ||
1656 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1712 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) |
1657 | { | 1713 | { |
@@ -1685,6 +1741,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1685 | } | 1741 | } |
1686 | #endif | 1742 | #endif |
1687 | 1743 | ||
1744 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1745 | |||
1688 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not | 1746 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not |
1689 | * atomic, make sure that inta covers all the interrupts that | 1747 | * atomic, make sure that inta covers all the interrupts that |
1690 | * we've discovered, even if FH interrupt came in just after | 1748 | * we've discovered, even if FH interrupt came in just after |
@@ -1706,8 +1764,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1706 | 1764 | ||
1707 | handled |= CSR_INT_BIT_HW_ERR; | 1765 | handled |= CSR_INT_BIT_HW_ERR; |
1708 | 1766 | ||
1709 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1710 | |||
1711 | return; | 1767 | return; |
1712 | } | 1768 | } |
1713 | 1769 | ||
@@ -1799,7 +1855,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1799 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); | 1855 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); |
1800 | } | 1856 | } |
1801 | #endif | 1857 | #endif |
1802 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1803 | } | 1858 | } |
1804 | 1859 | ||
1805 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | 1860 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, |
@@ -1901,7 +1956,7 @@ static void iwl3945_init_hw_rates(struct iwl_priv *priv, | |||
1901 | { | 1956 | { |
1902 | int i; | 1957 | int i; |
1903 | 1958 | ||
1904 | for (i = 0; i < IWL_RATE_COUNT; i++) { | 1959 | for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { |
1905 | rates[i].bitrate = iwl3945_rates[i].ieee * 5; | 1960 | rates[i].bitrate = iwl3945_rates[i].ieee * 5; |
1906 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ | 1961 | rates[i].hw_value = i; /* Rate scaling will work on indexes */ |
1907 | rates[i].hw_value_short = i; | 1962 | rates[i].hw_value_short = i; |
@@ -2158,6 +2213,14 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2158 | IWL_UCODE_API(priv->ucode_ver), | 2213 | IWL_UCODE_API(priv->ucode_ver), |
2159 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 2214 | IWL_UCODE_SERIAL(priv->ucode_ver)); |
2160 | 2215 | ||
2216 | snprintf(priv->hw->wiphy->fw_version, | ||
2217 | sizeof(priv->hw->wiphy->fw_version), | ||
2218 | "%u.%u.%u.%u", | ||
2219 | IWL_UCODE_MAJOR(priv->ucode_ver), | ||
2220 | IWL_UCODE_MINOR(priv->ucode_ver), | ||
2221 | IWL_UCODE_API(priv->ucode_ver), | ||
2222 | IWL_UCODE_SERIAL(priv->ucode_ver)); | ||
2223 | |||
2161 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | 2224 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", |
2162 | priv->ucode_ver); | 2225 | priv->ucode_ver); |
2163 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | 2226 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", |
@@ -2458,7 +2521,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2458 | priv->active_rate = priv->rates_mask; | 2521 | priv->active_rate = priv->rates_mask; |
2459 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | 2522 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; |
2460 | 2523 | ||
2461 | iwl_power_update_mode(priv, false); | 2524 | iwl_power_update_mode(priv, true); |
2462 | 2525 | ||
2463 | if (iwl_is_associated(priv)) { | 2526 | if (iwl_is_associated(priv)) { |
2464 | struct iwl3945_rxon_cmd *active_rxon = | 2527 | struct iwl3945_rxon_cmd *active_rxon = |
@@ -2479,7 +2542,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2479 | 2542 | ||
2480 | iwl3945_reg_txpower_periodic(priv); | 2543 | iwl3945_reg_txpower_periodic(priv); |
2481 | 2544 | ||
2482 | iwl3945_led_register(priv); | 2545 | iwl_leds_init(priv); |
2483 | 2546 | ||
2484 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2547 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
2485 | set_bit(STATUS_READY, &priv->status); | 2548 | set_bit(STATUS_READY, &priv->status); |
@@ -2517,7 +2580,6 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2517 | if (!exit_pending) | 2580 | if (!exit_pending) |
2518 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2581 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2519 | 2582 | ||
2520 | iwl3945_led_unregister(priv); | ||
2521 | iwl_clear_stations_table(priv); | 2583 | iwl_clear_stations_table(priv); |
2522 | 2584 | ||
2523 | /* Unblock any waiting calls */ | 2585 | /* Unblock any waiting calls */ |
@@ -2563,23 +2625,15 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2563 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | 2625 | test_bit(STATUS_EXIT_PENDING, &priv->status) << |
2564 | STATUS_EXIT_PENDING; | 2626 | STATUS_EXIT_PENDING; |
2565 | 2627 | ||
2566 | priv->cfg->ops->lib->apm_ops.reset(priv); | ||
2567 | spin_lock_irqsave(&priv->lock, flags); | ||
2568 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
2569 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2570 | |||
2571 | iwl3945_hw_txq_ctx_stop(priv); | 2628 | iwl3945_hw_txq_ctx_stop(priv); |
2572 | iwl3945_hw_rxq_stop(priv); | 2629 | iwl3945_hw_rxq_stop(priv); |
2573 | 2630 | ||
2574 | iwl_write_prph(priv, APMG_CLK_DIS_REG, | 2631 | /* Power-down device's busmaster DMA clocks */ |
2575 | APMG_CLK_VAL_DMA_CLK_RQT); | 2632 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
2576 | |||
2577 | udelay(5); | 2633 | udelay(5); |
2578 | 2634 | ||
2579 | if (exit_pending) | 2635 | /* Stop the device, and put it in low power state */ |
2580 | priv->cfg->ops->lib->apm_ops.stop(priv); | 2636 | priv->cfg->ops->lib->apm_ops.stop(priv); |
2581 | else | ||
2582 | priv->cfg->ops->lib->apm_ops.reset(priv); | ||
2583 | 2637 | ||
2584 | exit: | 2638 | exit: |
2585 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); | 2639 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); |
@@ -2724,19 +2778,34 @@ static void iwl3945_bg_alive_start(struct work_struct *data) | |||
2724 | mutex_unlock(&priv->mutex); | 2778 | mutex_unlock(&priv->mutex); |
2725 | } | 2779 | } |
2726 | 2780 | ||
2781 | /* | ||
2782 | * 3945 cannot interrupt driver when hardware rf kill switch toggles; | ||
2783 | * driver must poll CSR_GP_CNTRL_REG register for change. This register | ||
2784 | * *is* readable even when device has been SW_RESET into low power mode | ||
2785 | * (e.g. during RF KILL). | ||
2786 | */ | ||
2727 | static void iwl3945_rfkill_poll(struct work_struct *data) | 2787 | static void iwl3945_rfkill_poll(struct work_struct *data) |
2728 | { | 2788 | { |
2729 | struct iwl_priv *priv = | 2789 | struct iwl_priv *priv = |
2730 | container_of(data, struct iwl_priv, rfkill_poll.work); | 2790 | container_of(data, struct iwl_priv, rfkill_poll.work); |
2791 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2792 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) | ||
2793 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | ||
2731 | 2794 | ||
2732 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | 2795 | if (new_rfkill != old_rfkill) { |
2733 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 2796 | if (new_rfkill) |
2734 | else | 2797 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
2735 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 2798 | else |
2799 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2736 | 2800 | ||
2737 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | 2801 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill); |
2738 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | ||
2739 | 2802 | ||
2803 | IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", | ||
2804 | new_rfkill ? "disable radio" : "enable radio"); | ||
2805 | } | ||
2806 | |||
2807 | /* Keep this running, even if radio now enabled. This will be | ||
2808 | * cancelled in mac_start() if system decides to start again */ | ||
2740 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 2809 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, |
2741 | round_jiffies_relative(2 * HZ)); | 2810 | round_jiffies_relative(2 * HZ)); |
2742 | 2811 | ||
@@ -2898,7 +2967,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2898 | * is marked passive, we can do active scanning if we | 2967 | * is marked passive, we can do active scanning if we |
2899 | * detect transmissions. | 2968 | * detect transmissions. |
2900 | */ | 2969 | */ |
2901 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 2970 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
2971 | IWL_GOOD_CRC_TH_DISABLED; | ||
2902 | band = IEEE80211_BAND_5GHZ; | 2972 | band = IEEE80211_BAND_5GHZ; |
2903 | } else { | 2973 | } else { |
2904 | IWL_WARN(priv, "Invalid scan band count\n"); | 2974 | IWL_WARN(priv, "Invalid scan band count\n"); |
@@ -2957,18 +3027,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
2957 | mutex_unlock(&priv->mutex); | 3027 | mutex_unlock(&priv->mutex); |
2958 | } | 3028 | } |
2959 | 3029 | ||
2960 | static void iwl3945_bg_up(struct work_struct *data) | ||
2961 | { | ||
2962 | struct iwl_priv *priv = container_of(data, struct iwl_priv, up); | ||
2963 | |||
2964 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2965 | return; | ||
2966 | |||
2967 | mutex_lock(&priv->mutex); | ||
2968 | __iwl3945_up(priv); | ||
2969 | mutex_unlock(&priv->mutex); | ||
2970 | } | ||
2971 | |||
2972 | static void iwl3945_bg_restart(struct work_struct *data) | 3030 | static void iwl3945_bg_restart(struct work_struct *data) |
2973 | { | 3031 | { |
2974 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); | 3032 | struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); |
@@ -2985,7 +3043,13 @@ static void iwl3945_bg_restart(struct work_struct *data) | |||
2985 | ieee80211_restart_hw(priv->hw); | 3043 | ieee80211_restart_hw(priv->hw); |
2986 | } else { | 3044 | } else { |
2987 | iwl3945_down(priv); | 3045 | iwl3945_down(priv); |
2988 | queue_work(priv->workqueue, &priv->up); | 3046 | |
3047 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3048 | return; | ||
3049 | |||
3050 | mutex_lock(&priv->mutex); | ||
3051 | __iwl3945_up(priv); | ||
3052 | mutex_unlock(&priv->mutex); | ||
2989 | } | 3053 | } |
2990 | } | 3054 | } |
2991 | 3055 | ||
@@ -3152,6 +3216,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
3152 | * no need to poll the killswitch state anymore */ | 3216 | * no need to poll the killswitch state anymore */ |
3153 | cancel_delayed_work(&priv->rfkill_poll); | 3217 | cancel_delayed_work(&priv->rfkill_poll); |
3154 | 3218 | ||
3219 | iwl_led_start(priv); | ||
3220 | |||
3155 | priv->is_open = 1; | 3221 | priv->is_open = 1; |
3156 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3222 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3157 | return 0; | 3223 | return 0; |
@@ -3487,8 +3553,6 @@ static ssize_t store_filter_flags(struct device *d, | |||
3487 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, | 3553 | static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, |
3488 | store_filter_flags); | 3554 | store_filter_flags); |
3489 | 3555 | ||
3490 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | ||
3491 | |||
3492 | static ssize_t show_measurement(struct device *d, | 3556 | static ssize_t show_measurement(struct device *d, |
3493 | struct device_attribute *attr, char *buf) | 3557 | struct device_attribute *attr, char *buf) |
3494 | { | 3558 | { |
@@ -3558,7 +3622,6 @@ static ssize_t store_measurement(struct device *d, | |||
3558 | 3622 | ||
3559 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, | 3623 | static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, |
3560 | show_measurement, store_measurement); | 3624 | show_measurement, store_measurement); |
3561 | #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ | ||
3562 | 3625 | ||
3563 | static ssize_t store_retry_rate(struct device *d, | 3626 | static ssize_t store_retry_rate(struct device *d, |
3564 | struct device_attribute *attr, | 3627 | struct device_attribute *attr, |
@@ -3606,7 +3669,7 @@ static ssize_t show_statistics(struct device *d, | |||
3606 | return -EAGAIN; | 3669 | return -EAGAIN; |
3607 | 3670 | ||
3608 | mutex_lock(&priv->mutex); | 3671 | mutex_lock(&priv->mutex); |
3609 | rc = iwl_send_statistics_request(priv, 0); | 3672 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); |
3610 | mutex_unlock(&priv->mutex); | 3673 | mutex_unlock(&priv->mutex); |
3611 | 3674 | ||
3612 | if (rc) { | 3675 | if (rc) { |
@@ -3707,7 +3770,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3707 | 3770 | ||
3708 | init_waitqueue_head(&priv->wait_command_queue); | 3771 | init_waitqueue_head(&priv->wait_command_queue); |
3709 | 3772 | ||
3710 | INIT_WORK(&priv->up, iwl3945_bg_up); | ||
3711 | INIT_WORK(&priv->restart, iwl3945_bg_restart); | 3773 | INIT_WORK(&priv->restart, iwl3945_bg_restart); |
3712 | INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); | 3774 | INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); |
3713 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | 3775 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); |
@@ -3741,9 +3803,7 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
3741 | &dev_attr_dump_errors.attr, | 3803 | &dev_attr_dump_errors.attr, |
3742 | &dev_attr_flags.attr, | 3804 | &dev_attr_flags.attr, |
3743 | &dev_attr_filter_flags.attr, | 3805 | &dev_attr_filter_flags.attr, |
3744 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | ||
3745 | &dev_attr_measurement.attr, | 3806 | &dev_attr_measurement.attr, |
3746 | #endif | ||
3747 | &dev_attr_retry_rate.attr, | 3807 | &dev_attr_retry_rate.attr, |
3748 | &dev_attr_statistics.attr, | 3808 | &dev_attr_statistics.attr, |
3749 | &dev_attr_status.attr, | 3809 | &dev_attr_status.attr, |
@@ -3769,7 +3829,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
3769 | .config = iwl_mac_config, | 3829 | .config = iwl_mac_config, |
3770 | .configure_filter = iwl_configure_filter, | 3830 | .configure_filter = iwl_configure_filter, |
3771 | .set_key = iwl3945_mac_set_key, | 3831 | .set_key = iwl3945_mac_set_key, |
3772 | .get_tx_stats = iwl_mac_get_tx_stats, | ||
3773 | .conf_tx = iwl_mac_conf_tx, | 3832 | .conf_tx = iwl_mac_conf_tx, |
3774 | .reset_tsf = iwl_mac_reset_tsf, | 3833 | .reset_tsf = iwl_mac_reset_tsf, |
3775 | .bss_info_changed = iwl_bss_info_changed, | 3834 | .bss_info_changed = iwl_bss_info_changed, |
@@ -3784,23 +3843,23 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3784 | priv->retry_rate = 1; | 3843 | priv->retry_rate = 1; |
3785 | priv->ibss_beacon = NULL; | 3844 | priv->ibss_beacon = NULL; |
3786 | 3845 | ||
3787 | spin_lock_init(&priv->lock); | ||
3788 | spin_lock_init(&priv->sta_lock); | 3846 | spin_lock_init(&priv->sta_lock); |
3789 | spin_lock_init(&priv->hcmd_lock); | 3847 | spin_lock_init(&priv->hcmd_lock); |
3790 | 3848 | ||
3791 | INIT_LIST_HEAD(&priv->free_frames); | 3849 | INIT_LIST_HEAD(&priv->free_frames); |
3792 | 3850 | ||
3793 | mutex_init(&priv->mutex); | 3851 | mutex_init(&priv->mutex); |
3852 | mutex_init(&priv->sync_cmd_mutex); | ||
3794 | 3853 | ||
3795 | /* Clear the driver's (not device's) station table */ | 3854 | /* Clear the driver's (not device's) station table */ |
3796 | iwl_clear_stations_table(priv); | 3855 | iwl_clear_stations_table(priv); |
3797 | 3856 | ||
3798 | priv->data_retry_limit = -1; | ||
3799 | priv->ieee_channels = NULL; | 3857 | priv->ieee_channels = NULL; |
3800 | priv->ieee_rates = NULL; | 3858 | priv->ieee_rates = NULL; |
3801 | priv->band = IEEE80211_BAND_2GHZ; | 3859 | priv->band = IEEE80211_BAND_2GHZ; |
3802 | 3860 | ||
3803 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3861 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3862 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | ||
3804 | 3863 | ||
3805 | iwl_reset_qos(priv); | 3864 | iwl_reset_qos(priv); |
3806 | 3865 | ||
@@ -3854,18 +3913,18 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3854 | /* Tell mac80211 our characteristics */ | 3913 | /* Tell mac80211 our characteristics */ |
3855 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 3914 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
3856 | IEEE80211_HW_NOISE_DBM | | 3915 | IEEE80211_HW_NOISE_DBM | |
3857 | IEEE80211_HW_SPECTRUM_MGMT | | 3916 | IEEE80211_HW_SPECTRUM_MGMT; |
3858 | IEEE80211_HW_SUPPORTS_PS | | 3917 | |
3859 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 3918 | if (!priv->cfg->broken_powersave) |
3919 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
3920 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
3860 | 3921 | ||
3861 | hw->wiphy->interface_modes = | 3922 | hw->wiphy->interface_modes = |
3862 | BIT(NL80211_IFTYPE_STATION) | | 3923 | BIT(NL80211_IFTYPE_STATION) | |
3863 | BIT(NL80211_IFTYPE_ADHOC); | 3924 | BIT(NL80211_IFTYPE_ADHOC); |
3864 | 3925 | ||
3865 | hw->wiphy->custom_regulatory = true; | 3926 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
3866 | 3927 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | |
3867 | /* Firmware does not support this */ | ||
3868 | hw->wiphy->disable_beacon_hints = true; | ||
3869 | 3928 | ||
3870 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; | 3929 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; |
3871 | /* we create the 802.11 header and a zero-length SSID element */ | 3930 | /* we create the 802.11 header and a zero-length SSID element */ |
@@ -3977,17 +4036,18 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
3977 | * PCI Tx retries from interfering with C3 CPU state */ | 4036 | * PCI Tx retries from interfering with C3 CPU state */ |
3978 | pci_write_config_byte(pdev, 0x41, 0x00); | 4037 | pci_write_config_byte(pdev, 0x41, 0x00); |
3979 | 4038 | ||
3980 | /* this spin lock will be used in apm_ops.init and EEPROM access | 4039 | /* these spin locks will be used in apm_ops.init and EEPROM access |
3981 | * we should init now | 4040 | * we should init now |
3982 | */ | 4041 | */ |
3983 | spin_lock_init(&priv->reg_lock); | 4042 | spin_lock_init(&priv->reg_lock); |
4043 | spin_lock_init(&priv->lock); | ||
3984 | 4044 | ||
3985 | /* amp init */ | 4045 | /* |
3986 | err = priv->cfg->ops->lib->apm_ops.init(priv); | 4046 | * stop and reset the on-board processor just in case it is in a |
3987 | if (err < 0) { | 4047 | * strange state ... like being left stranded by a primary kernel |
3988 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | 4048 | * and this is now the kdump kernel trying to start up |
3989 | goto out_iounmap; | 4049 | */ |
3990 | } | 4050 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); |
3991 | 4051 | ||
3992 | /*********************** | 4052 | /*********************** |
3993 | * 4. Read EEPROM | 4053 | * 4. Read EEPROM |
@@ -4054,6 +4114,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4054 | &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); | 4114 | &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); |
4055 | iwl3945_setup_deferred_work(priv); | 4115 | iwl3945_setup_deferred_work(priv); |
4056 | iwl3945_setup_rx_handlers(priv); | 4116 | iwl3945_setup_rx_handlers(priv); |
4117 | iwl_power_initialize(priv); | ||
4057 | 4118 | ||
4058 | /********************************* | 4119 | /********************************* |
4059 | * 8. Setup and Register mac80211 | 4120 | * 8. Setup and Register mac80211 |
@@ -4124,6 +4185,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4124 | iwl3945_down(priv); | 4185 | iwl3945_down(priv); |
4125 | } | 4186 | } |
4126 | 4187 | ||
4188 | /* | ||
4189 | * Make sure device is reset to low power before unloading driver. | ||
4190 | * This may be redundant with iwl_down(), but there are paths to | ||
4191 | * run iwl_down() without calling apm_ops.stop(), and there are | ||
4192 | * paths to avoid running iwl_down() at all before leaving driver. | ||
4193 | * This (inexpensive) call *makes sure* device is reset. | ||
4194 | */ | ||
4195 | priv->cfg->ops->lib->apm_ops.stop(priv); | ||
4196 | |||
4127 | /* make sure we flush any pending irq or | 4197 | /* make sure we flush any pending irq or |
4128 | * tasklet for the driver | 4198 | * tasklet for the driver |
4129 | */ | 4199 | */ |
@@ -4226,18 +4296,19 @@ static void __exit iwl3945_exit(void) | |||
4226 | 4296 | ||
4227 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); | 4297 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); |
4228 | 4298 | ||
4229 | module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); | 4299 | module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO); |
4230 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 4300 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
4231 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); | 4301 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO); |
4232 | MODULE_PARM_DESC(swcrypto, | 4302 | MODULE_PARM_DESC(swcrypto, |
4233 | "using software crypto (default 1 [software])\n"); | 4303 | "using software crypto (default 1 [software])\n"); |
4234 | #ifdef CONFIG_IWLWIFI_DEBUG | 4304 | #ifdef CONFIG_IWLWIFI_DEBUG |
4235 | module_param_named(debug, iwl_debug_level, uint, 0644); | 4305 | module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); |
4236 | MODULE_PARM_DESC(debug, "debug output mask"); | 4306 | MODULE_PARM_DESC(debug, "debug output mask"); |
4237 | #endif | 4307 | #endif |
4238 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); | 4308 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, |
4309 | int, S_IRUGO); | ||
4239 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4310 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
4240 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); | 4311 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); |
4241 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); | 4312 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); |
4242 | 4313 | ||
4243 | module_exit(iwl3945_exit); | 4314 | module_exit(iwl3945_exit); |