diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
23 files changed, 726 insertions, 593 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 9a56ce546715..19150398a248 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -14,6 +14,7 @@ iwlagn-objs += iwl-6000.o | |||
14 | iwlagn-objs += iwl-1000.o | 14 | iwlagn-objs += iwl-1000.o |
15 | iwlagn-objs += iwl-2000.o | 15 | iwlagn-objs += iwl-2000.o |
16 | iwlagn-objs += iwl-pci.o | 16 | iwlagn-objs += iwl-pci.o |
17 | iwlagn-objs += iwl-trans.o | ||
17 | 18 | ||
18 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 19 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
19 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 20 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index e57fad9f1f09..cf1449df4f0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -138,7 +138,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
138 | 138 | ||
139 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 139 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
140 | BIT(IEEE80211_BAND_5GHZ); | 140 | BIT(IEEE80211_BAND_5GHZ); |
141 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
142 | 141 | ||
143 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | 142 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
144 | if (priv->cfg->rx_with_siso_diversity) | 143 | if (priv->cfg->rx_with_siso_diversity) |
@@ -197,7 +196,6 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
197 | 196 | ||
198 | static const struct iwl_ops iwl1000_ops = { | 197 | static const struct iwl_ops iwl1000_ops = { |
199 | .lib = &iwl1000_lib, | 198 | .lib = &iwl1000_lib, |
200 | .hcmd = &iwlagn_hcmd, | ||
201 | .utils = &iwlagn_hcmd_utils, | 199 | .utils = &iwlagn_hcmd_utils, |
202 | }; | 200 | }; |
203 | 201 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 64ed1f247df0..a401113c065a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -50,11 +50,13 @@ | |||
50 | #define IWL2030_UCODE_API_MAX 5 | 50 | #define IWL2030_UCODE_API_MAX 5 |
51 | #define IWL2000_UCODE_API_MAX 5 | 51 | #define IWL2000_UCODE_API_MAX 5 |
52 | #define IWL105_UCODE_API_MAX 5 | 52 | #define IWL105_UCODE_API_MAX 5 |
53 | #define IWL135_UCODE_API_MAX 5 | ||
53 | 54 | ||
54 | /* Lowest firmware API version supported */ | 55 | /* Lowest firmware API version supported */ |
55 | #define IWL2030_UCODE_API_MIN 5 | 56 | #define IWL2030_UCODE_API_MIN 5 |
56 | #define IWL2000_UCODE_API_MIN 5 | 57 | #define IWL2000_UCODE_API_MIN 5 |
57 | #define IWL105_UCODE_API_MIN 5 | 58 | #define IWL105_UCODE_API_MIN 5 |
59 | #define IWL135_UCODE_API_MIN 5 | ||
58 | 60 | ||
59 | #define IWL2030_FW_PRE "iwlwifi-2030-" | 61 | #define IWL2030_FW_PRE "iwlwifi-2030-" |
60 | #define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode" | 62 | #define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode" |
@@ -65,6 +67,9 @@ | |||
65 | #define IWL105_FW_PRE "iwlwifi-105-" | 67 | #define IWL105_FW_PRE "iwlwifi-105-" |
66 | #define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" | 68 | #define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" |
67 | 69 | ||
70 | #define IWL135_FW_PRE "iwlwifi-135-" | ||
71 | #define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode" | ||
72 | |||
68 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | 73 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) |
69 | { | 74 | { |
70 | /* want Celsius */ | 75 | /* want Celsius */ |
@@ -131,7 +136,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |||
131 | 136 | ||
132 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 137 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
133 | BIT(IEEE80211_BAND_5GHZ); | 138 | BIT(IEEE80211_BAND_5GHZ); |
134 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
135 | 139 | ||
136 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | 140 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
137 | if (priv->cfg->rx_with_siso_diversity) | 141 | if (priv->cfg->rx_with_siso_diversity) |
@@ -193,25 +197,21 @@ static struct iwl_lib_ops iwl2000_lib = { | |||
193 | 197 | ||
194 | static const struct iwl_ops iwl2000_ops = { | 198 | static const struct iwl_ops iwl2000_ops = { |
195 | .lib = &iwl2000_lib, | 199 | .lib = &iwl2000_lib, |
196 | .hcmd = &iwlagn_hcmd, | ||
197 | .utils = &iwlagn_hcmd_utils, | 200 | .utils = &iwlagn_hcmd_utils, |
198 | }; | 201 | }; |
199 | 202 | ||
200 | static const struct iwl_ops iwl2030_ops = { | 203 | static const struct iwl_ops iwl2030_ops = { |
201 | .lib = &iwl2000_lib, | 204 | .lib = &iwl2000_lib, |
202 | .hcmd = &iwlagn_bt_hcmd, | ||
203 | .utils = &iwlagn_hcmd_utils, | 205 | .utils = &iwlagn_hcmd_utils, |
204 | }; | 206 | }; |
205 | 207 | ||
206 | static const struct iwl_ops iwl105_ops = { | 208 | static const struct iwl_ops iwl105_ops = { |
207 | .lib = &iwl2000_lib, | 209 | .lib = &iwl2000_lib, |
208 | .hcmd = &iwlagn_hcmd, | ||
209 | .utils = &iwlagn_hcmd_utils, | 210 | .utils = &iwlagn_hcmd_utils, |
210 | }; | 211 | }; |
211 | 212 | ||
212 | static const struct iwl_ops iwl135_ops = { | 213 | static const struct iwl_ops iwl135_ops = { |
213 | .lib = &iwl2000_lib, | 214 | .lib = &iwl2000_lib, |
214 | .hcmd = &iwlagn_bt_hcmd, | ||
215 | .utils = &iwlagn_hcmd_utils, | 215 | .utils = &iwlagn_hcmd_utils, |
216 | }; | 216 | }; |
217 | 217 | ||
@@ -344,9 +344,9 @@ struct iwl_cfg iwl105_bgn_cfg = { | |||
344 | }; | 344 | }; |
345 | 345 | ||
346 | #define IWL_DEVICE_135 \ | 346 | #define IWL_DEVICE_135 \ |
347 | .fw_name_pre = IWL105_FW_PRE, \ | 347 | .fw_name_pre = IWL135_FW_PRE, \ |
348 | .ucode_api_max = IWL105_UCODE_API_MAX, \ | 348 | .ucode_api_max = IWL135_UCODE_API_MAX, \ |
349 | .ucode_api_min = IWL105_UCODE_API_MIN, \ | 349 | .ucode_api_min = IWL135_UCODE_API_MIN, \ |
350 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | 350 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ |
351 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | 351 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ |
352 | .ops = &iwl135_ops, \ | 352 | .ops = &iwl135_ops, \ |
@@ -359,12 +359,12 @@ struct iwl_cfg iwl105_bgn_cfg = { | |||
359 | .rx_with_siso_diversity = true \ | 359 | .rx_with_siso_diversity = true \ |
360 | 360 | ||
361 | struct iwl_cfg iwl135_bg_cfg = { | 361 | struct iwl_cfg iwl135_bg_cfg = { |
362 | .name = "105 Series 1x1 BG/BT", | 362 | .name = "135 Series 1x1 BG/BT", |
363 | IWL_DEVICE_135, | 363 | IWL_DEVICE_135, |
364 | }; | 364 | }; |
365 | 365 | ||
366 | struct iwl_cfg iwl135_bgn_cfg = { | 366 | struct iwl_cfg iwl135_bgn_cfg = { |
367 | .name = "105 Series 1x1 BGN/BT", | 367 | .name = "135 Series 1x1 BGN/BT", |
368 | IWL_DEVICE_135, | 368 | IWL_DEVICE_135, |
369 | .ht_params = &iwl2000_ht_params, | 369 | .ht_params = &iwl2000_ht_params, |
370 | }; | 370 | }; |
@@ -372,3 +372,4 @@ struct iwl_cfg iwl135_bgn_cfg = { | |||
372 | MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX)); | 372 | MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX)); |
373 | MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX)); | 373 | MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX)); |
374 | MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX)); | 374 | MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX)); |
375 | MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 269dfdb9fe1a..c55cec853f50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -169,7 +169,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
169 | 169 | ||
170 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 170 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
171 | BIT(IEEE80211_BAND_5GHZ); | 171 | BIT(IEEE80211_BAND_5GHZ); |
172 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
173 | 172 | ||
174 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | 173 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
175 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | 174 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); |
@@ -214,7 +213,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |||
214 | 213 | ||
215 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 214 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
216 | BIT(IEEE80211_BAND_5GHZ); | 215 | BIT(IEEE80211_BAND_5GHZ); |
217 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
218 | 216 | ||
219 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | 217 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
220 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | 218 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); |
@@ -379,13 +377,11 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
379 | 377 | ||
380 | static const struct iwl_ops iwl5000_ops = { | 378 | static const struct iwl_ops iwl5000_ops = { |
381 | .lib = &iwl5000_lib, | 379 | .lib = &iwl5000_lib, |
382 | .hcmd = &iwlagn_hcmd, | ||
383 | .utils = &iwlagn_hcmd_utils, | 380 | .utils = &iwlagn_hcmd_utils, |
384 | }; | 381 | }; |
385 | 382 | ||
386 | static const struct iwl_ops iwl5150_ops = { | 383 | static const struct iwl_ops iwl5150_ops = { |
387 | .lib = &iwl5150_lib, | 384 | .lib = &iwl5150_lib, |
388 | .hcmd = &iwlagn_hcmd, | ||
389 | .utils = &iwlagn_hcmd_utils, | 385 | .utils = &iwlagn_hcmd_utils, |
390 | }; | 386 | }; |
391 | 387 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f1c1db76b9da..965d010794b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -157,7 +157,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
157 | 157 | ||
158 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 158 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
159 | BIT(IEEE80211_BAND_5GHZ); | 159 | BIT(IEEE80211_BAND_5GHZ); |
160 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
161 | 160 | ||
162 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | 161 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
163 | if (priv->cfg->rx_with_siso_diversity) | 162 | if (priv->cfg->rx_with_siso_diversity) |
@@ -328,27 +327,23 @@ static struct iwl_nic_ops iwl6150_nic_ops = { | |||
328 | 327 | ||
329 | static const struct iwl_ops iwl6000_ops = { | 328 | static const struct iwl_ops iwl6000_ops = { |
330 | .lib = &iwl6000_lib, | 329 | .lib = &iwl6000_lib, |
331 | .hcmd = &iwlagn_hcmd, | ||
332 | .utils = &iwlagn_hcmd_utils, | 330 | .utils = &iwlagn_hcmd_utils, |
333 | }; | 331 | }; |
334 | 332 | ||
335 | static const struct iwl_ops iwl6050_ops = { | 333 | static const struct iwl_ops iwl6050_ops = { |
336 | .lib = &iwl6000_lib, | 334 | .lib = &iwl6000_lib, |
337 | .hcmd = &iwlagn_hcmd, | ||
338 | .utils = &iwlagn_hcmd_utils, | 335 | .utils = &iwlagn_hcmd_utils, |
339 | .nic = &iwl6050_nic_ops, | 336 | .nic = &iwl6050_nic_ops, |
340 | }; | 337 | }; |
341 | 338 | ||
342 | static const struct iwl_ops iwl6150_ops = { | 339 | static const struct iwl_ops iwl6150_ops = { |
343 | .lib = &iwl6000_lib, | 340 | .lib = &iwl6000_lib, |
344 | .hcmd = &iwlagn_hcmd, | ||
345 | .utils = &iwlagn_hcmd_utils, | 341 | .utils = &iwlagn_hcmd_utils, |
346 | .nic = &iwl6150_nic_ops, | 342 | .nic = &iwl6150_nic_ops, |
347 | }; | 343 | }; |
348 | 344 | ||
349 | static const struct iwl_ops iwl6030_ops = { | 345 | static const struct iwl_ops iwl6030_ops = { |
350 | .lib = &iwl6030_lib, | 346 | .lib = &iwl6030_lib, |
351 | .hcmd = &iwlagn_bt_hcmd, | ||
352 | .utils = &iwlagn_hcmd_utils, | 347 | .utils = &iwlagn_hcmd_utils, |
353 | }; | 348 | }; |
354 | 349 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index ba7ed9157c92..ce7d4b56d9b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -205,7 +205,7 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
205 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | 205 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; |
206 | } | 206 | } |
207 | 207 | ||
208 | static int iwlagn_set_pan_params(struct iwl_priv *priv) | 208 | int iwlagn_set_pan_params(struct iwl_priv *priv) |
209 | { | 209 | { |
210 | struct iwl_wipan_params_cmd cmd; | 210 | struct iwl_wipan_params_cmd cmd; |
211 | struct iwl_rxon_context *ctx_bss, *ctx_pan; | 211 | struct iwl_rxon_context *ctx_bss, *ctx_pan; |
@@ -297,20 +297,6 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
297 | return ret; | 297 | return ret; |
298 | } | 298 | } |
299 | 299 | ||
300 | struct iwl_hcmd_ops iwlagn_hcmd = { | ||
301 | .set_rxon_chain = iwlagn_set_rxon_chain, | ||
302 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
303 | .send_bt_config = iwl_send_bt_config, | ||
304 | .set_pan_params = iwlagn_set_pan_params, | ||
305 | }; | ||
306 | |||
307 | struct iwl_hcmd_ops iwlagn_bt_hcmd = { | ||
308 | .set_rxon_chain = iwlagn_set_rxon_chain, | ||
309 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
310 | .send_bt_config = iwlagn_send_advance_bt_config, | ||
311 | .set_pan_params = iwlagn_set_pan_params, | ||
312 | }; | ||
313 | |||
314 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | 300 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { |
315 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | 301 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, |
316 | .gain_computation = iwlagn_gain_computation, | 302 | .gain_computation = iwlagn_gain_computation, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index efdab6506ae7..90d366e15d2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -628,38 +628,6 @@ struct iwl_mod_params iwlagn_mod_params = { | |||
628 | /* the rest are 0 by default */ | 628 | /* the rest are 0 by default */ |
629 | }; | 629 | }; |
630 | 630 | ||
631 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
632 | { | ||
633 | unsigned long flags; | ||
634 | int i; | ||
635 | spin_lock_irqsave(&rxq->lock, flags); | ||
636 | INIT_LIST_HEAD(&rxq->rx_free); | ||
637 | INIT_LIST_HEAD(&rxq->rx_used); | ||
638 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
639 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
640 | /* In the reset function, these buffers may have been allocated | ||
641 | * to an SKB, so we need to unmap and free potential storage */ | ||
642 | if (rxq->pool[i].page != NULL) { | ||
643 | dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma, | ||
644 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
645 | DMA_FROM_DEVICE); | ||
646 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
647 | rxq->pool[i].page = NULL; | ||
648 | } | ||
649 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
650 | } | ||
651 | |||
652 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
653 | rxq->queue[i] = NULL; | ||
654 | |||
655 | /* Set us so that we have processed and used all buffers, but have | ||
656 | * not restocked the Rx queue with fresh buffers */ | ||
657 | rxq->read = rxq->write = 0; | ||
658 | rxq->write_actual = 0; | ||
659 | rxq->free_count = 0; | ||
660 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
661 | } | ||
662 | |||
663 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | 631 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) |
664 | { | 632 | { |
665 | u32 rb_size; | 633 | u32 rb_size; |
@@ -731,7 +699,6 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) | |||
731 | { | 699 | { |
732 | unsigned long flags; | 700 | unsigned long flags; |
733 | struct iwl_rx_queue *rxq = &priv->rxq; | 701 | struct iwl_rx_queue *rxq = &priv->rxq; |
734 | int ret; | ||
735 | 702 | ||
736 | /* nic_init */ | 703 | /* nic_init */ |
737 | spin_lock_irqsave(&priv->lock, flags); | 704 | spin_lock_irqsave(&priv->lock, flags); |
@@ -747,14 +714,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) | |||
747 | priv->cfg->ops->lib->apm_ops.config(priv); | 714 | priv->cfg->ops->lib->apm_ops.config(priv); |
748 | 715 | ||
749 | /* Allocate the RX queue, or reset if it is already allocated */ | 716 | /* Allocate the RX queue, or reset if it is already allocated */ |
750 | if (!rxq->bd) { | 717 | priv->trans.ops->rx_init(priv); |
751 | ret = iwl_rx_queue_alloc(priv); | ||
752 | if (ret) { | ||
753 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
754 | return -ENOMEM; | ||
755 | } | ||
756 | } else | ||
757 | iwlagn_rx_queue_reset(priv, rxq); | ||
758 | 718 | ||
759 | iwlagn_rx_replenish(priv); | 719 | iwlagn_rx_replenish(priv); |
760 | 720 | ||
@@ -768,12 +728,8 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) | |||
768 | spin_unlock_irqrestore(&priv->lock, flags); | 728 | spin_unlock_irqrestore(&priv->lock, flags); |
769 | 729 | ||
770 | /* Allocate or reset and init all Tx and Command queues */ | 730 | /* Allocate or reset and init all Tx and Command queues */ |
771 | if (!priv->txq) { | 731 | if (priv->trans.ops->tx_init(priv)) |
772 | ret = iwlagn_txq_ctx_alloc(priv); | 732 | return -ENOMEM; |
773 | if (ret) | ||
774 | return ret; | ||
775 | } else | ||
776 | iwlagn_txq_ctx_reset(priv); | ||
777 | 733 | ||
778 | if (priv->cfg->base_params->shadow_reg_enable) { | 734 | if (priv->cfg->base_params->shadow_reg_enable) { |
779 | /* enable shadow regs in HW */ | 735 | /* enable shadow regs in HW */ |
@@ -949,33 +905,6 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv) | |||
949 | iwlagn_rx_queue_restock(priv); | 905 | iwlagn_rx_queue_restock(priv); |
950 | } | 906 | } |
951 | 907 | ||
952 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
953 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
954 | * This free routine walks the list of POOL entries and if SKB is set to | ||
955 | * non NULL it is unmapped and freed | ||
956 | */ | ||
957 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
958 | { | ||
959 | int i; | ||
960 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
961 | if (rxq->pool[i].page != NULL) { | ||
962 | dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma, | ||
963 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
964 | DMA_FROM_DEVICE); | ||
965 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
966 | rxq->pool[i].page = NULL; | ||
967 | } | ||
968 | } | ||
969 | |||
970 | dma_free_coherent(priv->bus.dev, 4 * RX_QUEUE_SIZE, | ||
971 | rxq->bd, rxq->bd_dma); | ||
972 | dma_free_coherent(priv->bus.dev, | ||
973 | sizeof(struct iwl_rb_status), | ||
974 | rxq->rb_stts, rxq->rb_stts_dma); | ||
975 | rxq->bd = NULL; | ||
976 | rxq->rb_stts = NULL; | ||
977 | } | ||
978 | |||
979 | int iwlagn_rxq_stop(struct iwl_priv *priv) | 908 | int iwlagn_rxq_stop(struct iwl_priv *priv) |
980 | { | 909 | { |
981 | 910 | ||
@@ -1437,17 +1366,14 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1437 | /* set scan bit here for PAN params */ | 1366 | /* set scan bit here for PAN params */ |
1438 | set_bit(STATUS_SCAN_HW, &priv->status); | 1367 | set_bit(STATUS_SCAN_HW, &priv->status); |
1439 | 1368 | ||
1440 | if (priv->cfg->ops->hcmd->set_pan_params) { | 1369 | ret = iwlagn_set_pan_params(priv); |
1441 | ret = priv->cfg->ops->hcmd->set_pan_params(priv); | 1370 | if (ret) |
1442 | if (ret) | 1371 | return ret; |
1443 | return ret; | ||
1444 | } | ||
1445 | 1372 | ||
1446 | ret = iwl_send_cmd_sync(priv, &cmd); | 1373 | ret = iwl_send_cmd_sync(priv, &cmd); |
1447 | if (ret) { | 1374 | if (ret) { |
1448 | clear_bit(STATUS_SCAN_HW, &priv->status); | 1375 | clear_bit(STATUS_SCAN_HW, &priv->status); |
1449 | if (priv->cfg->ops->hcmd->set_pan_params) | 1376 | iwlagn_set_pan_params(priv); |
1450 | priv->cfg->ops->hcmd->set_pan_params(priv); | ||
1451 | } | 1377 | } |
1452 | 1378 | ||
1453 | return ret; | 1379 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 8fa43d427811..c6bb73a66d9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -436,11 +436,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
436 | if (ret) | 436 | if (ret) |
437 | return ret; | 437 | return ret; |
438 | 438 | ||
439 | if (priv->cfg->ops->hcmd->set_pan_params) { | 439 | ret = iwlagn_set_pan_params(priv); |
440 | ret = priv->cfg->ops->hcmd->set_pan_params(priv); | 440 | if (ret) |
441 | if (ret) | 441 | return ret; |
442 | return ret; | ||
443 | } | ||
444 | 442 | ||
445 | if (new_assoc) | 443 | if (new_assoc) |
446 | return iwlagn_rxon_connect(priv, ctx); | 444 | return iwlagn_rxon_connect(priv, ctx); |
@@ -483,9 +481,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
483 | * set up the SM PS mode to OFF if an HT channel is | 481 | * set up the SM PS mode to OFF if an HT channel is |
484 | * configured. | 482 | * configured. |
485 | */ | 483 | */ |
486 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 484 | for_each_context(priv, ctx) |
487 | for_each_context(priv, ctx) | 485 | iwlagn_set_rxon_chain(priv, ctx); |
488 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
489 | } | 486 | } |
490 | 487 | ||
491 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 488 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
@@ -741,8 +738,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
741 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | 738 | iwl_set_rxon_ht(priv, &priv->current_ht_config); |
742 | } | 739 | } |
743 | 740 | ||
744 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 741 | iwlagn_set_rxon_chain(priv, ctx); |
745 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
746 | 742 | ||
747 | if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) | 743 | if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) |
748 | ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; | 744 | ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; |
@@ -821,6 +817,5 @@ void iwlagn_post_scan(struct iwl_priv *priv) | |||
821 | if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) | 817 | if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) |
822 | iwlagn_commit_rxon(priv, ctx); | 818 | iwlagn_commit_rxon(priv, ctx); |
823 | 819 | ||
824 | if (priv->cfg->ops->hcmd->set_pan_params) | 820 | iwlagn_set_pan_params(priv); |
825 | priv->cfg->ops->hcmd->set_pan_params(priv); | ||
826 | } | 821 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index d0ac090399e9..c05a8d9fbd2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -878,96 +878,6 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | |||
878 | } | 878 | } |
879 | 879 | ||
880 | /** | 880 | /** |
881 | * iwlagn_txq_ctx_alloc - allocate TX queue context | ||
882 | * Allocate all Tx DMA structures and initialize them | ||
883 | * | ||
884 | * @param priv | ||
885 | * @return error code | ||
886 | */ | ||
887 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) | ||
888 | { | ||
889 | int ret; | ||
890 | int txq_id, slots_num; | ||
891 | unsigned long flags; | ||
892 | |||
893 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
894 | iwlagn_hw_txq_ctx_free(priv); | ||
895 | |||
896 | ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
897 | priv->hw_params.scd_bc_tbls_size); | ||
898 | if (ret) { | ||
899 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
900 | goto error_bc_tbls; | ||
901 | } | ||
902 | /* Alloc keep-warm buffer */ | ||
903 | ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
904 | if (ret) { | ||
905 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
906 | goto error_kw; | ||
907 | } | ||
908 | |||
909 | /* allocate tx queue structure */ | ||
910 | ret = iwl_alloc_txq_mem(priv); | ||
911 | if (ret) | ||
912 | goto error; | ||
913 | |||
914 | spin_lock_irqsave(&priv->lock, flags); | ||
915 | |||
916 | /* Turn off all Tx DMA fifos */ | ||
917 | iwlagn_txq_set_sched(priv, 0); | ||
918 | |||
919 | /* Tell NIC where to find the "keep warm" buffer */ | ||
920 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
921 | |||
922 | spin_unlock_irqrestore(&priv->lock, flags); | ||
923 | |||
924 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
925 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
926 | slots_num = (txq_id == priv->cmd_queue) ? | ||
927 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
928 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
929 | txq_id); | ||
930 | if (ret) { | ||
931 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
932 | goto error; | ||
933 | } | ||
934 | } | ||
935 | |||
936 | return ret; | ||
937 | |||
938 | error: | ||
939 | iwlagn_hw_txq_ctx_free(priv); | ||
940 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
941 | error_kw: | ||
942 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
943 | error_bc_tbls: | ||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | ||
948 | { | ||
949 | int txq_id, slots_num; | ||
950 | unsigned long flags; | ||
951 | |||
952 | spin_lock_irqsave(&priv->lock, flags); | ||
953 | |||
954 | /* Turn off all Tx DMA fifos */ | ||
955 | iwlagn_txq_set_sched(priv, 0); | ||
956 | |||
957 | /* Tell NIC where to find the "keep warm" buffer */ | ||
958 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
959 | |||
960 | spin_unlock_irqrestore(&priv->lock, flags); | ||
961 | |||
962 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
963 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
964 | slots_num = txq_id == priv->cmd_queue ? | ||
965 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
966 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | /** | ||
971 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | 881 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels |
972 | */ | 882 | */ |
973 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | 883 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index de8277e32253..2043c8b3139b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -386,11 +386,13 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) | |||
386 | spin_lock_irqsave(&priv->lock, flags); | 386 | spin_lock_irqsave(&priv->lock, flags); |
387 | 387 | ||
388 | priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); | 388 | priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); |
389 | a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET; | 389 | a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND; |
390 | for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET; | 390 | /* reset conext data memory */ |
391 | for (; a < priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND; | ||
391 | a += 4) | 392 | a += 4) |
392 | iwl_write_targ_mem(priv, a, 0); | 393 | iwl_write_targ_mem(priv, a, 0); |
393 | for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET; | 394 | /* reset tx status memory */ |
395 | for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND; | ||
394 | a += 4) | 396 | a += 4) |
395 | iwl_write_targ_mem(priv, a, 0); | 397 | iwl_write_targ_mem(priv, a, 0); |
396 | for (; a < priv->scd_base_addr + | 398 | for (; a < priv->scd_base_addr + |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e2f6b2ab0d45..7e6c463abbdf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #include "iwl-agn-calib.h" | 56 | #include "iwl-agn-calib.h" |
57 | #include "iwl-agn.h" | 57 | #include "iwl-agn.h" |
58 | #include "iwl-pci.h" | 58 | #include "iwl-pci.h" |
59 | 59 | #include "iwl-trans.h" | |
60 | 60 | ||
61 | /****************************************************************************** | 61 | /****************************************************************************** |
62 | * | 62 | * |
@@ -90,12 +90,10 @@ void iwl_update_chain_flags(struct iwl_priv *priv) | |||
90 | { | 90 | { |
91 | struct iwl_rxon_context *ctx; | 91 | struct iwl_rxon_context *ctx; |
92 | 92 | ||
93 | if (priv->cfg->ops->hcmd->set_rxon_chain) { | 93 | for_each_context(priv, ctx) { |
94 | for_each_context(priv, ctx) { | 94 | iwlagn_set_rxon_chain(priv, ctx); |
95 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | 95 | if (ctx->active.rx_chain != ctx->staging.rx_chain) |
96 | if (ctx->active.rx_chain != ctx->staging.rx_chain) | 96 | iwlagn_commit_rxon(priv, ctx); |
97 | iwlagn_commit_rxon(priv, ctx); | ||
98 | } | ||
99 | } | 97 | } |
100 | } | 98 | } |
101 | 99 | ||
@@ -260,7 +258,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work) | |||
260 | /* dont send host command if rf-kill is on */ | 258 | /* dont send host command if rf-kill is on */ |
261 | if (!iwl_is_ready_rf(priv)) | 259 | if (!iwl_is_ready_rf(priv)) |
262 | return; | 260 | return; |
263 | priv->cfg->ops->hcmd->send_bt_config(priv); | 261 | iwlagn_send_advance_bt_config(priv); |
264 | } | 262 | } |
265 | 263 | ||
266 | static void iwl_bg_bt_full_concurrency(struct work_struct *work) | 264 | static void iwl_bg_bt_full_concurrency(struct work_struct *work) |
@@ -287,12 +285,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work) | |||
287 | * to avoid 3-wire collisions | 285 | * to avoid 3-wire collisions |
288 | */ | 286 | */ |
289 | for_each_context(priv, ctx) { | 287 | for_each_context(priv, ctx) { |
290 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 288 | iwlagn_set_rxon_chain(priv, ctx); |
291 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
292 | iwlagn_commit_rxon(priv, ctx); | 289 | iwlagn_commit_rxon(priv, ctx); |
293 | } | 290 | } |
294 | 291 | ||
295 | priv->cfg->ops->hcmd->send_bt_config(priv); | 292 | iwlagn_send_advance_bt_config(priv); |
296 | out: | 293 | out: |
297 | mutex_unlock(&priv->mutex); | 294 | mutex_unlock(&priv->mutex); |
298 | } | 295 | } |
@@ -2017,7 +2014,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
2017 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; | 2014 | priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; |
2018 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; | 2015 | priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; |
2019 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; | 2016 | priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; |
2020 | priv->cfg->ops->hcmd->send_bt_config(priv); | 2017 | iwlagn_send_advance_bt_config(priv); |
2021 | priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; | 2018 | priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; |
2022 | iwlagn_send_prio_tbl(priv); | 2019 | iwlagn_send_prio_tbl(priv); |
2023 | 2020 | ||
@@ -2030,7 +2027,13 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
2030 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | 2027 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); |
2031 | if (ret) | 2028 | if (ret) |
2032 | return ret; | 2029 | return ret; |
2030 | } else { | ||
2031 | /* | ||
2032 | * default is 2-wire BT coexexistence support | ||
2033 | */ | ||
2034 | iwl_send_bt_config(priv); | ||
2033 | } | 2035 | } |
2036 | |||
2034 | if (priv->hw_params.calib_rt_cfg) | 2037 | if (priv->hw_params.calib_rt_cfg) |
2035 | iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); | 2038 | iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); |
2036 | 2039 | ||
@@ -2039,8 +2042,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
2039 | priv->active_rate = IWL_RATES_MASK; | 2042 | priv->active_rate = IWL_RATES_MASK; |
2040 | 2043 | ||
2041 | /* Configure Tx antenna selection based on H/W config */ | 2044 | /* Configure Tx antenna selection based on H/W config */ |
2042 | if (priv->cfg->ops->hcmd->set_tx_ant) | 2045 | iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant); |
2043 | priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); | ||
2044 | 2046 | ||
2045 | if (iwl_is_associated_ctx(ctx)) { | 2047 | if (iwl_is_associated_ctx(ctx)) { |
2046 | struct iwl_rxon_cmd *active_rxon = | 2048 | struct iwl_rxon_cmd *active_rxon = |
@@ -2054,16 +2056,7 @@ int iwl_alive_start(struct iwl_priv *priv) | |||
2054 | for_each_context(priv, tmp) | 2056 | for_each_context(priv, tmp) |
2055 | iwl_connection_init_rx_config(priv, tmp); | 2057 | iwl_connection_init_rx_config(priv, tmp); |
2056 | 2058 | ||
2057 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2059 | iwlagn_set_rxon_chain(priv, ctx); |
2058 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
2059 | } | ||
2060 | |||
2061 | if (!priv->cfg->bt_params || (priv->cfg->bt_params && | ||
2062 | !priv->cfg->bt_params->advanced_bt_coexist)) { | ||
2063 | /* | ||
2064 | * default is 2-wire BT coexexistence support | ||
2065 | */ | ||
2066 | priv->cfg->ops->hcmd->send_bt_config(priv); | ||
2067 | } | 2060 | } |
2068 | 2061 | ||
2069 | iwl_reset_run_time_calib(priv); | 2062 | iwl_reset_run_time_calib(priv); |
@@ -3288,9 +3281,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3288 | priv->rx_statistics_jiffies = jiffies; | 3281 | priv->rx_statistics_jiffies = jiffies; |
3289 | 3282 | ||
3290 | /* Choose which receivers/antennas to use */ | 3283 | /* Choose which receivers/antennas to use */ |
3291 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3284 | iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]); |
3292 | priv->cfg->ops->hcmd->set_rxon_chain(priv, | ||
3293 | &priv->contexts[IWL_RXON_CTX_BSS]); | ||
3294 | 3285 | ||
3295 | iwl_init_scan_params(priv); | 3286 | iwl_init_scan_params(priv); |
3296 | 3287 | ||
@@ -3517,6 +3508,8 @@ int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, | |||
3517 | priv->bus.ops->set_drv_data(&priv->bus, priv); | 3508 | priv->bus.ops->set_drv_data(&priv->bus, priv); |
3518 | priv->bus.dev = priv->bus.ops->get_dev(&priv->bus); | 3509 | priv->bus.dev = priv->bus.ops->get_dev(&priv->bus); |
3519 | 3510 | ||
3511 | iwl_trans_register(&priv->trans); | ||
3512 | |||
3520 | /* At this point both hw and priv are allocated. */ | 3513 | /* At this point both hw and priv are allocated. */ |
3521 | 3514 | ||
3522 | SET_IEEE80211_DEV(hw, priv->bus.dev); | 3515 | SET_IEEE80211_DEV(hw, priv->bus.dev); |
@@ -3716,8 +3709,7 @@ void __devexit iwl_remove(struct iwl_priv * priv) | |||
3716 | 3709 | ||
3717 | iwl_dealloc_ucode(priv); | 3710 | iwl_dealloc_ucode(priv); |
3718 | 3711 | ||
3719 | if (priv->rxq.bd) | 3712 | priv->trans.ops->rx_free(priv); |
3720 | iwlagn_rx_queue_free(priv, &priv->rxq); | ||
3721 | iwlagn_hw_txq_ctx_free(priv); | 3713 | iwlagn_hw_txq_ctx_free(priv); |
3722 | 3714 | ||
3723 | iwl_eeprom_free(priv); | 3715 | iwl_eeprom_free(priv); |
@@ -3820,6 +3812,10 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); | |||
3820 | module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); | 3812 | module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); |
3821 | MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); | 3813 | MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); |
3822 | 3814 | ||
3815 | module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO); | ||
3816 | MODULE_PARM_DESC(wd_disable, | ||
3817 | "Disable stuck queue watchdog timer (default: 0 [enabled])"); | ||
3818 | |||
3823 | /* | 3819 | /* |
3824 | * set bt_coex_active to true, uCode will do kill/defer | 3820 | * set bt_coex_active to true, uCode will do kill/defer |
3825 | * every time the priority line is asserted (BT is sending signals on the | 3821 | * every time the priority line is asserted (BT is sending signals on the |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index dcdf2259520f..4351151e2a91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -182,7 +182,6 @@ void iwlagn_temperature(struct iwl_priv *priv); | |||
182 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); | 182 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); |
183 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | 183 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, |
184 | size_t offset); | 184 | size_t offset); |
185 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
186 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 185 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
187 | int iwlagn_hw_nic_init(struct iwl_priv *priv); | 186 | int iwlagn_hw_nic_init(struct iwl_priv *priv); |
188 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); | 187 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); |
@@ -194,7 +193,6 @@ void iwlagn_rx_queue_restock(struct iwl_priv *priv); | |||
194 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); | 193 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); |
195 | void iwlagn_rx_replenish(struct iwl_priv *priv); | 194 | void iwlagn_rx_replenish(struct iwl_priv *priv); |
196 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); | 195 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); |
197 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
198 | int iwlagn_rxq_stop(struct iwl_priv *priv); | 196 | int iwlagn_rxq_stop(struct iwl_priv *priv); |
199 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | 197 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); |
200 | void iwl_setup_rx_handlers(struct iwl_priv *priv); | 198 | void iwl_setup_rx_handlers(struct iwl_priv *priv); |
@@ -220,8 +218,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
220 | struct iwl_rx_mem_buffer *rxb); | 218 | struct iwl_rx_mem_buffer *rxb); |
221 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | 219 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); |
222 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); | 220 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); |
223 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); | ||
224 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv); | ||
225 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); | 221 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); |
226 | 222 | ||
227 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | 223 | static inline u32 iwl_tx_status_to_mac80211(u32 status) |
@@ -260,6 +256,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
260 | /* hcmd */ | 256 | /* hcmd */ |
261 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); | 257 | int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant); |
262 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 258 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
259 | int iwlagn_set_pan_params(struct iwl_priv *priv); | ||
263 | 260 | ||
264 | /* bt coex */ | 261 | /* bt coex */ |
265 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); | 262 | void iwlagn_send_advance_bt_config(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7f16d1203057..f91e306c2498 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -585,8 +585,7 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv, | |||
585 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; | 585 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; |
586 | } | 586 | } |
587 | 587 | ||
588 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 588 | iwlagn_set_rxon_chain(priv, ctx); |
589 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
590 | 589 | ||
591 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " | 590 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " |
592 | "extension channel offset 0x%x\n", | 591 | "extension channel offset 0x%x\n", |
@@ -1216,8 +1215,7 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
1216 | { | 1215 | { |
1217 | iwl_connection_init_rx_config(priv, ctx); | 1216 | iwl_connection_init_rx_config(priv, ctx); |
1218 | 1217 | ||
1219 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1218 | iwlagn_set_rxon_chain(priv, ctx); |
1220 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | ||
1221 | 1219 | ||
1222 | return iwlagn_commit_rxon(priv, ctx); | 1220 | return iwlagn_commit_rxon(priv, ctx); |
1223 | } | 1221 | } |
@@ -1372,20 +1370,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
1372 | 1370 | ||
1373 | } | 1371 | } |
1374 | 1372 | ||
1375 | int iwl_alloc_txq_mem(struct iwl_priv *priv) | ||
1376 | { | ||
1377 | if (!priv->txq) | ||
1378 | priv->txq = kzalloc( | ||
1379 | sizeof(struct iwl_tx_queue) * | ||
1380 | priv->cfg->base_params->num_of_queues, | ||
1381 | GFP_KERNEL); | ||
1382 | if (!priv->txq) { | ||
1383 | IWL_ERR(priv, "Not enough memory for txq\n"); | ||
1384 | return -ENOMEM; | ||
1385 | } | ||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1389 | void iwl_free_txq_mem(struct iwl_priv *priv) | 1373 | void iwl_free_txq_mem(struct iwl_priv *priv) |
1390 | { | 1374 | { |
1391 | kfree(priv->txq); | 1375 | kfree(priv->txq); |
@@ -1853,7 +1837,7 @@ void iwl_setup_watchdog(struct iwl_priv *priv) | |||
1853 | { | 1837 | { |
1854 | unsigned int timeout = priv->cfg->base_params->wd_timeout; | 1838 | unsigned int timeout = priv->cfg->base_params->wd_timeout; |
1855 | 1839 | ||
1856 | if (timeout) | 1840 | if (timeout && !iwlagn_mod_params.wd_disable) |
1857 | mod_timer(&priv->watchdog, | 1841 | mod_timer(&priv->watchdog, |
1858 | jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); | 1842 | jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); |
1859 | else | 1843 | else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f881678be762..6c21de9f5b60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -80,14 +80,6 @@ struct iwl_cmd; | |||
80 | 80 | ||
81 | #define IWL_CMD(x) case x: return #x | 81 | #define IWL_CMD(x) case x: return #x |
82 | 82 | ||
83 | struct iwl_hcmd_ops { | ||
84 | void (*set_rxon_chain)(struct iwl_priv *priv, | ||
85 | struct iwl_rxon_context *ctx); | ||
86 | int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); | ||
87 | void (*send_bt_config)(struct iwl_priv *priv); | ||
88 | int (*set_pan_params)(struct iwl_priv *priv); | ||
89 | }; | ||
90 | |||
91 | struct iwl_hcmd_utils_ops { | 83 | struct iwl_hcmd_utils_ops { |
92 | u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); | 84 | u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); |
93 | void (*gain_computation)(struct iwl_priv *priv, | 85 | void (*gain_computation)(struct iwl_priv *priv, |
@@ -146,7 +138,6 @@ struct iwl_nic_ops { | |||
146 | 138 | ||
147 | struct iwl_ops { | 139 | struct iwl_ops { |
148 | const struct iwl_lib_ops *lib; | 140 | const struct iwl_lib_ops *lib; |
149 | const struct iwl_hcmd_ops *hcmd; | ||
150 | const struct iwl_hcmd_utils_ops *utils; | 141 | const struct iwl_hcmd_utils_ops *utils; |
151 | const struct iwl_nic_ops *nic; | 142 | const struct iwl_nic_ops *nic; |
152 | }; | 143 | }; |
@@ -160,6 +151,7 @@ struct iwl_mod_params { | |||
160 | int restart_fw; /* def: 1 = restart firmware */ | 151 | int restart_fw; /* def: 1 = restart firmware */ |
161 | bool plcp_check; /* def: true = enable plcp health check */ | 152 | bool plcp_check; /* def: true = enable plcp health check */ |
162 | bool ack_check; /* def: false = disable ack health check */ | 153 | bool ack_check; /* def: false = disable ack health check */ |
154 | bool wd_disable; /* def: false = enable stuck queue check */ | ||
163 | bool bt_coex_active; /* def: true = enable bt coex */ | 155 | bool bt_coex_active; /* def: true = enable bt coex */ |
164 | int led_mode; /* def: 0 = system default */ | 156 | int led_mode; /* def: 0 = system default */ |
165 | bool no_sleep_autoadjust; /* def: true = disable autoadjust */ | 157 | bool no_sleep_autoadjust; /* def: true = disable autoadjust */ |
@@ -336,7 +328,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
336 | int iwl_mac_change_interface(struct ieee80211_hw *hw, | 328 | int iwl_mac_change_interface(struct ieee80211_hw *hw, |
337 | struct ieee80211_vif *vif, | 329 | struct ieee80211_vif *vif, |
338 | enum nl80211_iftype newtype, bool newp2p); | 330 | enum nl80211_iftype newtype, bool newp2p); |
339 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | ||
340 | void iwl_free_txq_mem(struct iwl_priv *priv); | 331 | void iwl_free_txq_mem(struct iwl_priv *priv); |
341 | 332 | ||
342 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 333 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -382,7 +373,6 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, | |||
382 | ******************************************************/ | 373 | ******************************************************/ |
383 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 374 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
384 | void iwl_cmd_queue_unmap(struct iwl_priv *priv); | 375 | void iwl_cmd_queue_unmap(struct iwl_priv *priv); |
385 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | ||
386 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 376 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
387 | struct iwl_rx_queue *q); | 377 | struct iwl_rx_queue *q); |
388 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 378 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
@@ -396,11 +386,9 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); | |||
396 | * TX | 386 | * TX |
397 | ******************************************************/ | 387 | ******************************************************/ |
398 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 388 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
399 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
400 | int slots_num, u32 txq_id); | ||
401 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
402 | int slots_num, u32 txq_id); | ||
403 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 389 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
390 | int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | ||
391 | int count, int slots_num, u32 id); | ||
404 | void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id); | 392 | void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id); |
405 | void iwl_setup_watchdog(struct iwl_priv *priv); | 393 | void iwl_setup_watchdog(struct iwl_priv *priv); |
406 | /***************************************************** | 394 | /***************************************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f1b1128ee1c4..c6560e97a62b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -666,7 +666,6 @@ struct iwl_hw_params { | |||
666 | u16 max_rxq_size; | 666 | u16 max_rxq_size; |
667 | u16 max_rxq_log; | 667 | u16 max_rxq_log; |
668 | u32 rx_page_order; | 668 | u32 rx_page_order; |
669 | u32 rx_wrt_ptr_reg; | ||
670 | u8 max_stations; | 669 | u8 max_stations; |
671 | u8 ht40_channel; | 670 | u8 ht40_channel; |
672 | u8 max_beacon_itrvl; /* in 1024 ms */ | 671 | u8 max_beacon_itrvl; /* in 1024 ms */ |
@@ -1228,6 +1227,25 @@ struct iwl_bus { | |||
1228 | unsigned int irq; | 1227 | unsigned int irq; |
1229 | }; | 1228 | }; |
1230 | 1229 | ||
1230 | struct iwl_trans; | ||
1231 | |||
1232 | /** | ||
1233 | * struct iwl_trans_ops - transport specific operations | ||
1234 | |||
1235 | * @rx_init: inits the rx memory, allocate it if needed | ||
1236 | * @rx_free: frees the rx memory | ||
1237 | * @tx_init:inits the tx memory, allocate if needed | ||
1238 | */ | ||
1239 | struct iwl_trans_ops { | ||
1240 | int (*rx_init)(struct iwl_priv *priv); | ||
1241 | void (*rx_free)(struct iwl_priv *priv); | ||
1242 | int (*tx_init)(struct iwl_priv *priv); | ||
1243 | }; | ||
1244 | |||
1245 | struct iwl_trans { | ||
1246 | const struct iwl_trans_ops *ops; | ||
1247 | }; | ||
1248 | |||
1231 | struct iwl_priv { | 1249 | struct iwl_priv { |
1232 | 1250 | ||
1233 | /* ieee device used by generic ieee processing code */ | 1251 | /* ieee device used by generic ieee processing code */ |
@@ -1296,13 +1314,13 @@ struct iwl_priv { | |||
1296 | struct mutex mutex; | 1314 | struct mutex mutex; |
1297 | 1315 | ||
1298 | struct iwl_bus bus; /* bus specific data */ | 1316 | struct iwl_bus bus; /* bus specific data */ |
1317 | struct iwl_trans trans; | ||
1299 | 1318 | ||
1300 | /* microcode/device supports multiple contexts */ | 1319 | /* microcode/device supports multiple contexts */ |
1301 | u8 valid_contexts; | 1320 | u8 valid_contexts; |
1302 | 1321 | ||
1303 | /* command queue number */ | 1322 | /* command queue number */ |
1304 | u8 cmd_queue; | 1323 | u8 cmd_queue; |
1305 | u8 last_sync_cmd_id; | ||
1306 | 1324 | ||
1307 | /* max number of station keys */ | 1325 | /* max number of station keys */ |
1308 | u8 sta_key_max_num; | 1326 | u8 sta_key_max_num; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index e3e5fb614178..107b38e2ee93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -171,6 +171,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
171 | int cmd_idx; | 171 | int cmd_idx; |
172 | int ret; | 172 | int ret; |
173 | 173 | ||
174 | lockdep_assert_held(&priv->mutex); | ||
175 | |||
174 | if (WARN_ON(cmd->flags & CMD_ASYNC)) | 176 | if (WARN_ON(cmd->flags & CMD_ASYNC)) |
175 | return -EINVAL; | 177 | return -EINVAL; |
176 | 178 | ||
@@ -181,16 +183,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
181 | IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", | 183 | IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", |
182 | get_cmd_string(cmd->id)); | 184 | get_cmd_string(cmd->id)); |
183 | 185 | ||
184 | if (test_and_set_bit(STATUS_HCMD_ACTIVE, &priv->status)) { | 186 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); |
185 | IWL_ERR(priv, "STATUS_HCMD_ACTIVE already set while sending %s" | ||
186 | ". Previous SYNC cmdn is %s\n", | ||
187 | get_cmd_string(cmd->id), | ||
188 | get_cmd_string(priv->last_sync_cmd_id)); | ||
189 | WARN_ON(1); | ||
190 | } else { | ||
191 | priv->last_sync_cmd_id = cmd->id; | ||
192 | } | ||
193 | |||
194 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", | 187 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", |
195 | get_cmd_string(cmd->id)); | 188 | get_cmd_string(cmd->id)); |
196 | 189 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index 3b5844b60e7c..74911348a2ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include "iwl-agn.h" | 67 | #include "iwl-agn.h" |
68 | #include "iwl-core.h" | 68 | #include "iwl-core.h" |
69 | #include "iwl-io.h" | 69 | #include "iwl-io.h" |
70 | #include "iwl-trans.h" | ||
70 | 71 | ||
71 | /* PCI registers */ | 72 | /* PCI registers */ |
72 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | 73 | #define PCI_CFG_RETRY_TIMEOUT 0x041 |
@@ -93,7 +94,7 @@ static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) | |||
93 | u16 pci_lnk_ctl; | 94 | u16 pci_lnk_ctl; |
94 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); | 95 | struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); |
95 | 96 | ||
96 | pos = pci_find_capability(pci_dev, PCI_CAP_ID_EXP); | 97 | pos = pci_pcie_cap(pci_dev); |
97 | pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); | 98 | pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); |
98 | return pci_lnk_ctl; | 99 | return pci_lnk_ctl; |
99 | } | 100 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index f00d188b2cfc..1cc0ed1f488c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -168,6 +168,7 @@ | |||
168 | * the scheduler (especially for queue #4/#9, the command queue, otherwise | 168 | * the scheduler (especially for queue #4/#9, the command queue, otherwise |
169 | * the driver can't issue commands!): | 169 | * the driver can't issue commands!): |
170 | */ | 170 | */ |
171 | #define SCD_MEM_LOWER_BOUND (0x0000) | ||
171 | 172 | ||
172 | /** | 173 | /** |
173 | * Max Tx window size is the max number of contiguous TFDs that the scheduler | 174 | * Max Tx window size is the max number of contiguous TFDs that the scheduler |
@@ -197,15 +198,23 @@ | |||
197 | #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) | 198 | #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) |
198 | #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) | 199 | #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) |
199 | 200 | ||
200 | #define IWLAGN_SCD_CONTEXT_DATA_OFFSET (0x600) | 201 | /* Context Data */ |
201 | #define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET (0x7B1) | 202 | #define IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x600) |
202 | #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET (0x7E0) | 203 | #define IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) |
204 | |||
205 | /* Tx status */ | ||
206 | #define IWLAGN_SCD_TX_STTS_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x6A0) | ||
207 | #define IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) | ||
208 | |||
209 | /* Translation Data */ | ||
210 | #define IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND (SCD_MEM_LOWER_BOUND + 0x7E0) | ||
211 | #define IWLAGN_SCD_TRANS_TBL_MEM_UPPER_BOUND (SCD_MEM_LOWER_BOUND + 0x808) | ||
203 | 212 | ||
204 | #define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ | 213 | #define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ |
205 | (IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) | 214 | (IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) |
206 | 215 | ||
207 | #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ | 216 | #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ |
208 | ((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) | 217 | ((IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) |
209 | 218 | ||
210 | #define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \ | 219 | #define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv) \ |
211 | (((1<<(priv)->hw_params.max_txq_num) - 1) &\ | 220 | (((1<<(priv)->hw_params.max_txq_num) - 1) &\ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 3efa7066e987..87148bb3f628 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -134,7 +134,6 @@ int iwl_rx_queue_space(const struct iwl_rx_queue *q) | |||
134 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | 134 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) |
135 | { | 135 | { |
136 | unsigned long flags; | 136 | unsigned long flags; |
137 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; | ||
138 | u32 reg; | 137 | u32 reg; |
139 | 138 | ||
140 | spin_lock_irqsave(&q->lock, flags); | 139 | spin_lock_irqsave(&q->lock, flags); |
@@ -146,7 +145,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
146 | /* shadow register enabled */ | 145 | /* shadow register enabled */ |
147 | /* Device expects a multiple of 8 */ | 146 | /* Device expects a multiple of 8 */ |
148 | q->write_actual = (q->write & ~0x7); | 147 | q->write_actual = (q->write & ~0x7); |
149 | iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); | 148 | iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual); |
150 | } else { | 149 | } else { |
151 | /* If power-saving is in use, make sure device is awake */ | 150 | /* If power-saving is in use, make sure device is awake */ |
152 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 151 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { |
@@ -162,14 +161,14 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
162 | } | 161 | } |
163 | 162 | ||
164 | q->write_actual = (q->write & ~0x7); | 163 | q->write_actual = (q->write & ~0x7); |
165 | iwl_write_direct32(priv, rx_wrt_ptr_reg, | 164 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, |
166 | q->write_actual); | 165 | q->write_actual); |
167 | 166 | ||
168 | /* Else device is assumed to be awake */ | 167 | /* Else device is assumed to be awake */ |
169 | } else { | 168 | } else { |
170 | /* Device expects a multiple of 8 */ | 169 | /* Device expects a multiple of 8 */ |
171 | q->write_actual = (q->write & ~0x7); | 170 | q->write_actual = (q->write & ~0x7); |
172 | iwl_write_direct32(priv, rx_wrt_ptr_reg, | 171 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, |
173 | q->write_actual); | 172 | q->write_actual); |
174 | } | 173 | } |
175 | } | 174 | } |
@@ -179,46 +178,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
179 | spin_unlock_irqrestore(&q->lock, flags); | 178 | spin_unlock_irqrestore(&q->lock, flags); |
180 | } | 179 | } |
181 | 180 | ||
182 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | ||
183 | { | ||
184 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
185 | struct device *dev = priv->bus.dev; | ||
186 | int i; | ||
187 | |||
188 | spin_lock_init(&rxq->lock); | ||
189 | INIT_LIST_HEAD(&rxq->rx_free); | ||
190 | INIT_LIST_HEAD(&rxq->rx_used); | ||
191 | |||
192 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | ||
193 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, | ||
194 | GFP_KERNEL); | ||
195 | if (!rxq->bd) | ||
196 | goto err_bd; | ||
197 | |||
198 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), | ||
199 | &rxq->rb_stts_dma, GFP_KERNEL); | ||
200 | if (!rxq->rb_stts) | ||
201 | goto err_rb; | ||
202 | |||
203 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
204 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) | ||
205 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
206 | |||
207 | /* Set us so that we have processed and used all buffers, but have | ||
208 | * not restocked the Rx queue with fresh buffers */ | ||
209 | rxq->read = rxq->write = 0; | ||
210 | rxq->write_actual = 0; | ||
211 | rxq->free_count = 0; | ||
212 | rxq->need_update = 0; | ||
213 | return 0; | ||
214 | |||
215 | err_rb: | ||
216 | dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
217 | rxq->bd_dma); | ||
218 | err_bd: | ||
219 | return -ENOMEM; | ||
220 | } | ||
221 | |||
222 | /****************************************************************************** | 181 | /****************************************************************************** |
223 | * | 182 | * |
224 | * Generic RX handler implementations | 183 | * Generic RX handler implementations |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 160911a3716a..d825188e5215 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h | |||
@@ -66,116 +66,144 @@ | |||
66 | #include <linux/types.h> | 66 | #include <linux/types.h> |
67 | 67 | ||
68 | 68 | ||
69 | /* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and | 69 | /* |
70 | * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and | ||
70 | * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX). | 71 | * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX). |
71 | * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of | 72 | * The command ID is carried with IWL_TM_ATTR_COMMAND. |
72 | * of command from user space and two types of command from kernel space. | 73 | * |
73 | * See below. | 74 | * @IWL_TM_CMD_APP2DEV_UCODE: |
75 | * commands from user application to the uCode, | ||
76 | * the actual uCode host command ID is carried with | ||
77 | * IWL_TM_ATTR_UCODE_CMD_ID | ||
78 | * | ||
79 | * @IWL_TM_CMD_APP2DEV_REG_READ32: | ||
80 | * @IWL_TM_CMD_APP2DEV_REG_WRITE32: | ||
81 | * @IWL_TM_CMD_APP2DEV_REG_WRITE8: | ||
82 | * commands from user applicaiton to access register | ||
83 | * | ||
84 | * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name | ||
85 | * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image | ||
86 | * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration | ||
87 | * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image | ||
88 | * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data | ||
89 | * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS | ||
90 | * commands fom user space for pure driver level operations | ||
91 | * | ||
92 | * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE: | ||
93 | * @IWL_TM_CMD_APP2DEV_END_TRACE: | ||
94 | * @IWL_TM_CMD_APP2DEV_READ_TRACE: | ||
95 | * commands fom user space for uCode trace operations | ||
96 | * | ||
97 | * @IWL_TM_CMD_DEV2APP_SYNC_RSP: | ||
98 | * commands from kernel space to carry the synchronous response | ||
99 | * to user application | ||
100 | * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT: | ||
101 | * commands from kernel space to multicast the spontaneous messages | ||
102 | * to user application | ||
103 | * @IWL_TM_CMD_DEV2APP_EEPROM_RSP: | ||
104 | * commands from kernel space to carry the eeprom response | ||
105 | * to user application | ||
74 | */ | 106 | */ |
75 | enum iwl_tm_cmd_t { | 107 | enum iwl_tm_cmd_t { |
76 | /* commands from user application to the uCode, | 108 | IWL_TM_CMD_APP2DEV_UCODE = 1, |
77 | * the actual uCode host command ID is carried with | 109 | IWL_TM_CMD_APP2DEV_REG_READ32 = 2, |
78 | * IWL_TM_ATTR_UCODE_CMD_ID */ | 110 | IWL_TM_CMD_APP2DEV_REG_WRITE32 = 3, |
79 | IWL_TM_CMD_APP2DEV_UCODE = 1, | 111 | IWL_TM_CMD_APP2DEV_REG_WRITE8 = 4, |
80 | 112 | IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5, | |
81 | /* commands from user applicaiton to access register */ | 113 | IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6, |
82 | IWL_TM_CMD_APP2DEV_REG_READ32, | 114 | IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7, |
83 | IWL_TM_CMD_APP2DEV_REG_WRITE32, | 115 | IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW = 8, |
84 | IWL_TM_CMD_APP2DEV_REG_WRITE8, | 116 | IWL_TM_CMD_APP2DEV_GET_EEPROM = 9, |
85 | 117 | IWL_TM_CMD_APP2DEV_FIXRATE_REQ = 10, | |
86 | /* commands fom user space for pure driver level operations */ | 118 | IWL_TM_CMD_APP2DEV_BEGIN_TRACE = 11, |
87 | IWL_TM_CMD_APP2DEV_GET_DEVICENAME, | 119 | IWL_TM_CMD_APP2DEV_END_TRACE = 12, |
88 | IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, | 120 | IWL_TM_CMD_APP2DEV_READ_TRACE = 13, |
89 | IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, | 121 | IWL_TM_CMD_DEV2APP_SYNC_RSP = 14, |
90 | IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, | 122 | IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15, |
91 | IWL_TM_CMD_APP2DEV_GET_EEPROM, | 123 | IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16, |
92 | IWL_TM_CMD_APP2DEV_FIXRATE_REQ, | 124 | IWL_TM_CMD_MAX = 17, |
93 | /* if there is other new command for the driver layer operation, | ||
94 | * append them here */ | ||
95 | |||
96 | /* commands fom user space for uCode trace operations */ | ||
97 | IWL_TM_CMD_APP2DEV_BEGIN_TRACE, | ||
98 | IWL_TM_CMD_APP2DEV_END_TRACE, | ||
99 | IWL_TM_CMD_APP2DEV_READ_TRACE, | ||
100 | |||
101 | /* commands from kernel space to carry the synchronous response | ||
102 | * to user application */ | ||
103 | IWL_TM_CMD_DEV2APP_SYNC_RSP, | ||
104 | |||
105 | /* commands from kernel space to multicast the spontaneous messages | ||
106 | * to user application */ | ||
107 | IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, | ||
108 | |||
109 | /* commands from kernel space to carry the eeprom response | ||
110 | * to user application */ | ||
111 | IWL_TM_CMD_DEV2APP_EEPROM_RSP, | ||
112 | |||
113 | IWL_TM_CMD_MAX, | ||
114 | }; | 125 | }; |
115 | 126 | ||
127 | /* | ||
128 | * Atrribute filed in testmode command | ||
129 | * See enum iwl_tm_cmd_t. | ||
130 | * | ||
131 | * @IWL_TM_ATTR_NOT_APPLICABLE: | ||
132 | * The attribute is not applicable or invalid | ||
133 | * @IWL_TM_ATTR_COMMAND: | ||
134 | * From user space to kernel space: | ||
135 | * the command either destines to ucode, driver, or register; | ||
136 | * From kernel space to user space: | ||
137 | * the command either carries synchronous response, | ||
138 | * or the spontaneous message multicast from the device; | ||
139 | * | ||
140 | * @IWL_TM_ATTR_UCODE_CMD_ID: | ||
141 | * @IWL_TM_ATTR_UCODE_CMD_DATA: | ||
142 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, | ||
143 | * The mandatory fields are : | ||
144 | * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; | ||
145 | * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands; | ||
146 | * The optional fields are: | ||
147 | * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload | ||
148 | * to the ucode | ||
149 | * | ||
150 | * @IWL_TM_ATTR_REG_OFFSET: | ||
151 | * @IWL_TM_ATTR_REG_VALUE8: | ||
152 | * @IWL_TM_ATTR_REG_VALUE32: | ||
153 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, | ||
154 | * The mandatory fields are: | ||
155 | * IWL_TM_ATTR_REG_OFFSET for the offset of the target register; | ||
156 | * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value | ||
157 | * | ||
158 | * @IWL_TM_ATTR_SYNC_RSP: | ||
159 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, | ||
160 | * The mandatory fields are: | ||
161 | * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user | ||
162 | * application command | ||
163 | * | ||
164 | * @IWL_TM_ATTR_UCODE_RX_PKT: | ||
165 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, | ||
166 | * The mandatory fields are: | ||
167 | * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user | ||
168 | * application | ||
169 | * | ||
170 | * @IWL_TM_ATTR_EEPROM: | ||
171 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, | ||
172 | * The mandatory fields are: | ||
173 | * IWL_TM_ATTR_EEPROM for the data content responging to the user | ||
174 | * application | ||
175 | * | ||
176 | * @IWL_TM_ATTR_TRACE_ADDR: | ||
177 | * @IWL_TM_ATTR_TRACE_SIZE: | ||
178 | * @IWL_TM_ATTR_TRACE_DUMP: | ||
179 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, | ||
180 | * The mandatory fields are: | ||
181 | * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address | ||
182 | * IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size | ||
183 | * IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump | ||
184 | * | ||
185 | * @IWL_TM_ATTR_FIXRATE: | ||
186 | * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, | ||
187 | * The mandatory fields are: | ||
188 | * IWL_TM_ATTR_FIXRATE for the fixed rate | ||
189 | * | ||
190 | */ | ||
116 | enum iwl_tm_attr_t { | 191 | enum iwl_tm_attr_t { |
117 | IWL_TM_ATTR_NOT_APPLICABLE = 0, | 192 | IWL_TM_ATTR_NOT_APPLICABLE = 0, |
118 | 193 | IWL_TM_ATTR_COMMAND = 1, | |
119 | /* From user space to kernel space: | 194 | IWL_TM_ATTR_UCODE_CMD_ID = 2, |
120 | * the command either destines to ucode, driver, or register; | 195 | IWL_TM_ATTR_UCODE_CMD_DATA = 3, |
121 | * See enum iwl_tm_cmd_t. | 196 | IWL_TM_ATTR_REG_OFFSET = 4, |
122 | * | 197 | IWL_TM_ATTR_REG_VALUE8 = 5, |
123 | * From kernel space to user space: | 198 | IWL_TM_ATTR_REG_VALUE32 = 6, |
124 | * the command either carries synchronous response, | 199 | IWL_TM_ATTR_SYNC_RSP = 7, |
125 | * or the spontaneous message multicast from the device; | 200 | IWL_TM_ATTR_UCODE_RX_PKT = 8, |
126 | * See enum iwl_tm_cmd_t. */ | 201 | IWL_TM_ATTR_EEPROM = 9, |
127 | IWL_TM_ATTR_COMMAND, | 202 | IWL_TM_ATTR_TRACE_ADDR = 10, |
128 | 203 | IWL_TM_ATTR_TRACE_SIZE = 11, | |
129 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, | 204 | IWL_TM_ATTR_TRACE_DUMP = 12, |
130 | * The mandatory fields are : | 205 | IWL_TM_ATTR_FIXRATE = 13, |
131 | * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; | 206 | IWL_TM_ATTR_MAX = 14, |
132 | * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands; | ||
133 | * The optional fields are: | ||
134 | * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload | ||
135 | * to the ucode */ | ||
136 | IWL_TM_ATTR_UCODE_CMD_ID, | ||
137 | IWL_TM_ATTR_UCODE_CMD_DATA, | ||
138 | |||
139 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, | ||
140 | * The mandatory fields are: | ||
141 | * IWL_TM_ATTR_REG_OFFSET for the offset of the target register; | ||
142 | * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */ | ||
143 | IWL_TM_ATTR_REG_OFFSET, | ||
144 | IWL_TM_ATTR_REG_VALUE8, | ||
145 | IWL_TM_ATTR_REG_VALUE32, | ||
146 | |||
147 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, | ||
148 | * The mandatory fields are: | ||
149 | * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user | ||
150 | * application command */ | ||
151 | IWL_TM_ATTR_SYNC_RSP, | ||
152 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, | ||
153 | * The mandatory fields are: | ||
154 | * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user | ||
155 | * application */ | ||
156 | IWL_TM_ATTR_UCODE_RX_PKT, | ||
157 | |||
158 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, | ||
159 | * The mandatory fields are: | ||
160 | * IWL_TM_ATTR_EEPROM for the data content responging to the user | ||
161 | * application */ | ||
162 | IWL_TM_ATTR_EEPROM, | ||
163 | |||
164 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, | ||
165 | * The mandatory fields are: | ||
166 | * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address | ||
167 | */ | ||
168 | IWL_TM_ATTR_TRACE_ADDR, | ||
169 | IWL_TM_ATTR_TRACE_SIZE, | ||
170 | IWL_TM_ATTR_TRACE_DUMP, | ||
171 | |||
172 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, | ||
173 | * The mandatory fields are: | ||
174 | * IWL_TM_ATTR_FIXRATE for the fixed rate | ||
175 | */ | ||
176 | IWL_TM_ATTR_FIXRATE, | ||
177 | |||
178 | IWL_TM_ATTR_MAX, | ||
179 | }; | 207 | }; |
180 | 208 | ||
181 | /* uCode trace buffer */ | 209 | /* uCode trace buffer */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c new file mode 100644 index 000000000000..7b7b97d8c2e1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #include "iwl-dev.h" | ||
64 | #include "iwl-trans.h" | ||
65 | #include "iwl-core.h" | ||
66 | #include "iwl-helpers.h" | ||
67 | /*TODO remove uneeded includes when the transport layer tx_free will be here */ | ||
68 | #include "iwl-agn.h" | ||
69 | |||
70 | static int iwl_trans_rx_alloc(struct iwl_priv *priv) | ||
71 | { | ||
72 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
73 | struct device *dev = priv->bus.dev; | ||
74 | |||
75 | memset(&priv->rxq, 0, sizeof(priv->rxq)); | ||
76 | |||
77 | spin_lock_init(&rxq->lock); | ||
78 | INIT_LIST_HEAD(&rxq->rx_free); | ||
79 | INIT_LIST_HEAD(&rxq->rx_used); | ||
80 | |||
81 | if (WARN_ON(rxq->bd || rxq->rb_stts)) | ||
82 | return -EINVAL; | ||
83 | |||
84 | /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ | ||
85 | rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
86 | &rxq->bd_dma, GFP_KERNEL); | ||
87 | if (!rxq->bd) | ||
88 | goto err_bd; | ||
89 | memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE); | ||
90 | |||
91 | /*Allocate the driver's pointer to receive buffer status */ | ||
92 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts), | ||
93 | &rxq->rb_stts_dma, GFP_KERNEL); | ||
94 | if (!rxq->rb_stts) | ||
95 | goto err_rb_stts; | ||
96 | memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); | ||
97 | |||
98 | return 0; | ||
99 | |||
100 | err_rb_stts: | ||
101 | dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
102 | rxq->bd, rxq->bd_dma); | ||
103 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | ||
104 | rxq->bd = NULL; | ||
105 | err_bd: | ||
106 | return -ENOMEM; | ||
107 | } | ||
108 | |||
109 | static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) | ||
110 | { | ||
111 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
112 | int i; | ||
113 | |||
114 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
115 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
116 | /* In the reset function, these buffers may have been allocated | ||
117 | * to an SKB, so we need to unmap and free potential storage */ | ||
118 | if (rxq->pool[i].page != NULL) { | ||
119 | dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma, | ||
120 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
121 | DMA_FROM_DEVICE); | ||
122 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
123 | rxq->pool[i].page = NULL; | ||
124 | } | ||
125 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static int iwl_trans_rx_init(struct iwl_priv *priv) | ||
130 | { | ||
131 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
132 | int i, err; | ||
133 | unsigned long flags; | ||
134 | |||
135 | if (!rxq->bd) { | ||
136 | err = iwl_trans_rx_alloc(priv); | ||
137 | if (err) | ||
138 | return err; | ||
139 | } | ||
140 | |||
141 | spin_lock_irqsave(&rxq->lock, flags); | ||
142 | INIT_LIST_HEAD(&rxq->rx_free); | ||
143 | INIT_LIST_HEAD(&rxq->rx_used); | ||
144 | |||
145 | iwl_trans_rxq_free_rx_bufs(priv); | ||
146 | |||
147 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
148 | rxq->queue[i] = NULL; | ||
149 | |||
150 | /* Set us so that we have processed and used all buffers, but have | ||
151 | * not restocked the Rx queue with fresh buffers */ | ||
152 | rxq->read = rxq->write = 0; | ||
153 | rxq->write_actual = 0; | ||
154 | rxq->free_count = 0; | ||
155 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void iwl_trans_rx_free(struct iwl_priv *priv) | ||
161 | { | ||
162 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
163 | unsigned long flags; | ||
164 | |||
165 | /*if rxq->bd is NULL, it means that nothing has been allocated, | ||
166 | * exit now */ | ||
167 | if (!rxq->bd) { | ||
168 | IWL_DEBUG_INFO(priv, "Free NULL rx context\n"); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | spin_lock_irqsave(&rxq->lock, flags); | ||
173 | iwl_trans_rxq_free_rx_bufs(priv); | ||
174 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
175 | |||
176 | dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE, | ||
177 | rxq->bd, rxq->bd_dma); | ||
178 | memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); | ||
179 | rxq->bd = NULL; | ||
180 | |||
181 | if (rxq->rb_stts) | ||
182 | dma_free_coherent(priv->bus.dev, | ||
183 | sizeof(struct iwl_rb_status), | ||
184 | rxq->rb_stts, rxq->rb_stts_dma); | ||
185 | else | ||
186 | IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n"); | ||
187 | memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); | ||
188 | rxq->rb_stts = NULL; | ||
189 | } | ||
190 | |||
191 | /* TODO:remove this code duplication */ | ||
192 | static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, | ||
193 | struct iwl_dma_ptr *ptr, size_t size) | ||
194 | { | ||
195 | if (WARN_ON(ptr->addr)) | ||
196 | return -EINVAL; | ||
197 | |||
198 | ptr->addr = dma_alloc_coherent(priv->bus.dev, size, | ||
199 | &ptr->dma, GFP_KERNEL); | ||
200 | if (!ptr->addr) | ||
201 | return -ENOMEM; | ||
202 | ptr->size = size; | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
207 | int slots_num, u32 txq_id) | ||
208 | { | ||
209 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; | ||
210 | int i; | ||
211 | |||
212 | if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) | ||
213 | return -EINVAL; | ||
214 | |||
215 | txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num, | ||
216 | GFP_KERNEL); | ||
217 | txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num, | ||
218 | GFP_KERNEL); | ||
219 | |||
220 | if (!txq->meta || !txq->cmd) | ||
221 | goto error; | ||
222 | |||
223 | for (i = 0; i < slots_num; i++) { | ||
224 | txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), | ||
225 | GFP_KERNEL); | ||
226 | if (!txq->cmd[i]) | ||
227 | goto error; | ||
228 | } | ||
229 | |||
230 | /* Alloc driver data array and TFD circular buffer */ | ||
231 | /* Driver private data, only for Tx (not command) queues, | ||
232 | * not shared with device. */ | ||
233 | if (txq_id != priv->cmd_queue) { | ||
234 | txq->txb = kzalloc(sizeof(txq->txb[0]) * | ||
235 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | ||
236 | if (!txq->txb) { | ||
237 | IWL_ERR(priv, "kmalloc for auxiliary BD " | ||
238 | "structures failed\n"); | ||
239 | goto error; | ||
240 | } | ||
241 | } else { | ||
242 | txq->txb = NULL; | ||
243 | } | ||
244 | |||
245 | /* Circular buffer of transmit frame descriptors (TFDs), | ||
246 | * shared with device */ | ||
247 | txq->tfds = dma_alloc_coherent(priv->bus.dev, tfd_sz, &txq->q.dma_addr, | ||
248 | GFP_KERNEL); | ||
249 | if (!txq->tfds) { | ||
250 | IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | ||
251 | goto error; | ||
252 | } | ||
253 | txq->q.id = txq_id; | ||
254 | |||
255 | return 0; | ||
256 | error: | ||
257 | kfree(txq->txb); | ||
258 | txq->txb = NULL; | ||
259 | /* since txq->cmd has been zeroed, | ||
260 | * all non allocated cmd[i] will be NULL */ | ||
261 | if (txq->cmd) | ||
262 | for (i = 0; i < slots_num; i++) | ||
263 | kfree(txq->cmd[i]); | ||
264 | kfree(txq->meta); | ||
265 | kfree(txq->cmd); | ||
266 | txq->meta = NULL; | ||
267 | txq->cmd = NULL; | ||
268 | |||
269 | return -ENOMEM; | ||
270 | |||
271 | } | ||
272 | |||
273 | static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
274 | int slots_num, u32 txq_id) | ||
275 | { | ||
276 | int ret; | ||
277 | |||
278 | txq->need_update = 0; | ||
279 | memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num); | ||
280 | |||
281 | /* | ||
282 | * For the default queues 0-3, set up the swq_id | ||
283 | * already -- all others need to get one later | ||
284 | * (if they need one at all). | ||
285 | */ | ||
286 | if (txq_id < 4) | ||
287 | iwl_set_swq_id(txq, txq_id, txq_id); | ||
288 | |||
289 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | ||
290 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | ||
291 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | ||
292 | |||
293 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
294 | ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, | ||
295 | txq_id); | ||
296 | if (ret) | ||
297 | return ret; | ||
298 | |||
299 | /* | ||
300 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
301 | * given Tx queue, and enable the DMA channel used for that queue. | ||
302 | * Circular buffer (TFD queue in DRAM) physical base address */ | ||
303 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
304 | txq->q.dma_addr >> 8); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * iwl_trans_tx_alloc - allocate TX context | ||
311 | * Allocate all Tx DMA structures and initialize them | ||
312 | * | ||
313 | * @param priv | ||
314 | * @return error code | ||
315 | */ | ||
316 | static int iwl_trans_tx_alloc(struct iwl_priv *priv) | ||
317 | { | ||
318 | int ret; | ||
319 | int txq_id, slots_num; | ||
320 | |||
321 | /*It is not allowed to alloc twice, so warn when this happens. | ||
322 | * We cannot rely on the previous allocation, so free and fail */ | ||
323 | if (WARN_ON(priv->txq)) { | ||
324 | ret = -EINVAL; | ||
325 | goto error; | ||
326 | } | ||
327 | |||
328 | ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
329 | priv->hw_params.scd_bc_tbls_size); | ||
330 | if (ret) { | ||
331 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
332 | goto error; | ||
333 | } | ||
334 | |||
335 | /* Alloc keep-warm buffer */ | ||
336 | ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
337 | if (ret) { | ||
338 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
339 | goto error; | ||
340 | } | ||
341 | |||
342 | priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * | ||
343 | priv->cfg->base_params->num_of_queues, GFP_KERNEL); | ||
344 | if (!priv->txq) { | ||
345 | IWL_ERR(priv, "Not enough memory for txq\n"); | ||
346 | ret = ENOMEM; | ||
347 | goto error; | ||
348 | } | ||
349 | |||
350 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
351 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
352 | slots_num = (txq_id == priv->cmd_queue) ? | ||
353 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
354 | ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, | ||
355 | txq_id); | ||
356 | if (ret) { | ||
357 | IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id); | ||
358 | goto error; | ||
359 | } | ||
360 | } | ||
361 | |||
362 | return 0; | ||
363 | |||
364 | error: | ||
365 | iwlagn_hw_txq_ctx_free(priv); | ||
366 | |||
367 | return ret; | ||
368 | } | ||
369 | static int iwl_trans_tx_init(struct iwl_priv *priv) | ||
370 | { | ||
371 | int ret; | ||
372 | int txq_id, slots_num; | ||
373 | unsigned long flags; | ||
374 | bool alloc = false; | ||
375 | |||
376 | if (!priv->txq) { | ||
377 | ret = iwl_trans_tx_alloc(priv); | ||
378 | if (ret) | ||
379 | goto error; | ||
380 | alloc = true; | ||
381 | } | ||
382 | |||
383 | spin_lock_irqsave(&priv->lock, flags); | ||
384 | |||
385 | /* Turn off all Tx DMA fifos */ | ||
386 | iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 0); | ||
387 | |||
388 | /* Tell NIC where to find the "keep warm" buffer */ | ||
389 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
390 | |||
391 | spin_unlock_irqrestore(&priv->lock, flags); | ||
392 | |||
393 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ | ||
394 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
395 | slots_num = (txq_id == priv->cmd_queue) ? | ||
396 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
397 | ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, | ||
398 | txq_id); | ||
399 | if (ret) { | ||
400 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
401 | goto error; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | return 0; | ||
406 | error: | ||
407 | /*Upon error, free only if we allocated something */ | ||
408 | if (alloc) | ||
409 | iwlagn_hw_txq_ctx_free(priv); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | static const struct iwl_trans_ops trans_ops = { | ||
414 | .rx_init = iwl_trans_rx_init, | ||
415 | .rx_free = iwl_trans_rx_free, | ||
416 | |||
417 | .tx_init = iwl_trans_tx_init, | ||
418 | }; | ||
419 | |||
420 | void iwl_trans_register(struct iwl_trans *trans) | ||
421 | { | ||
422 | trans->ops = &trans_ops; | ||
423 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h new file mode 100644 index 000000000000..bec494c5a979 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | void iwl_trans_register(struct iwl_trans *trans); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index e72d2279fc5d..db5abaa2ff7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -220,24 +220,6 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
220 | return 0; | 220 | return 0; |
221 | } | 221 | } |
222 | 222 | ||
223 | /* | ||
224 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
225 | * given Tx queue, and enable the DMA channel used for that queue. | ||
226 | * | ||
227 | * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA | ||
228 | * channels supported in hardware. | ||
229 | */ | ||
230 | static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
231 | { | ||
232 | int txq_id = txq->q.id; | ||
233 | |||
234 | /* Circular buffer (TFD queue in DRAM) physical base address */ | ||
235 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
236 | txq->q.dma_addr >> 8); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | /** | 223 | /** |
242 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | 224 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's |
243 | */ | 225 | */ |
@@ -392,11 +374,10 @@ int iwl_queue_space(const struct iwl_queue *q) | |||
392 | return s; | 374 | return s; |
393 | } | 375 | } |
394 | 376 | ||
395 | |||
396 | /** | 377 | /** |
397 | * iwl_queue_init - Initialize queue's high/low-water and read/write indexes | 378 | * iwl_queue_init - Initialize queue's high/low-water and read/write indexes |
398 | */ | 379 | */ |
399 | static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | 380 | int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, |
400 | int count, int slots_num, u32 id) | 381 | int count, int slots_num, u32 id) |
401 | { | 382 | { |
402 | q->n_bd = count; | 383 | q->n_bd = count; |
@@ -426,124 +407,6 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | |||
426 | return 0; | 407 | return 0; |
427 | } | 408 | } |
428 | 409 | ||
429 | /** | ||
430 | * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue | ||
431 | */ | ||
432 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, | ||
433 | struct iwl_tx_queue *txq, u32 id) | ||
434 | { | ||
435 | struct device *dev = priv->bus.dev; | ||
436 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; | ||
437 | |||
438 | /* Driver private data, only for Tx (not command) queues, | ||
439 | * not shared with device. */ | ||
440 | if (id != priv->cmd_queue) { | ||
441 | txq->txb = kzalloc(sizeof(txq->txb[0]) * | ||
442 | TFD_QUEUE_SIZE_MAX, GFP_KERNEL); | ||
443 | if (!txq->txb) { | ||
444 | IWL_ERR(priv, "kmalloc for auxiliary BD " | ||
445 | "structures failed\n"); | ||
446 | goto error; | ||
447 | } | ||
448 | } else { | ||
449 | txq->txb = NULL; | ||
450 | } | ||
451 | |||
452 | /* Circular buffer of transmit frame descriptors (TFDs), | ||
453 | * shared with device */ | ||
454 | txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, | ||
455 | GFP_KERNEL); | ||
456 | if (!txq->tfds) { | ||
457 | IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | ||
458 | goto error; | ||
459 | } | ||
460 | txq->q.id = id; | ||
461 | |||
462 | return 0; | ||
463 | |||
464 | error: | ||
465 | kfree(txq->txb); | ||
466 | txq->txb = NULL; | ||
467 | |||
468 | return -ENOMEM; | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue | ||
473 | */ | ||
474 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
475 | int slots_num, u32 txq_id) | ||
476 | { | ||
477 | int i, len; | ||
478 | int ret; | ||
479 | |||
480 | txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num, | ||
481 | GFP_KERNEL); | ||
482 | txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num, | ||
483 | GFP_KERNEL); | ||
484 | |||
485 | if (!txq->meta || !txq->cmd) | ||
486 | goto out_free_arrays; | ||
487 | |||
488 | len = sizeof(struct iwl_device_cmd); | ||
489 | for (i = 0; i < slots_num; i++) { | ||
490 | txq->cmd[i] = kmalloc(len, GFP_KERNEL); | ||
491 | if (!txq->cmd[i]) | ||
492 | goto err; | ||
493 | } | ||
494 | |||
495 | /* Alloc driver data array and TFD circular buffer */ | ||
496 | ret = iwl_tx_queue_alloc(priv, txq, txq_id); | ||
497 | if (ret) | ||
498 | goto err; | ||
499 | |||
500 | txq->need_update = 0; | ||
501 | |||
502 | /* | ||
503 | * For the default queues 0-3, set up the swq_id | ||
504 | * already -- all others need to get one later | ||
505 | * (if they need one at all). | ||
506 | */ | ||
507 | if (txq_id < 4) | ||
508 | iwl_set_swq_id(txq, txq_id, txq_id); | ||
509 | |||
510 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | ||
511 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | ||
512 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | ||
513 | |||
514 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
515 | ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
516 | if (ret) | ||
517 | return ret; | ||
518 | |||
519 | /* Tell device where to find queue */ | ||
520 | iwlagn_tx_queue_init(priv, txq); | ||
521 | |||
522 | return 0; | ||
523 | err: | ||
524 | for (i = 0; i < slots_num; i++) | ||
525 | kfree(txq->cmd[i]); | ||
526 | out_free_arrays: | ||
527 | kfree(txq->meta); | ||
528 | kfree(txq->cmd); | ||
529 | |||
530 | return -ENOMEM; | ||
531 | } | ||
532 | |||
533 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
534 | int slots_num, u32 txq_id) | ||
535 | { | ||
536 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * slots_num); | ||
537 | |||
538 | txq->need_update = 0; | ||
539 | |||
540 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
541 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
542 | |||
543 | /* Tell device where to find queue */ | ||
544 | iwlagn_tx_queue_init(priv, txq); | ||
545 | } | ||
546 | |||
547 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 410 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
548 | 411 | ||
549 | /** | 412 | /** |