aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2008-05-04 22:22:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-14 16:29:46 -0400
commit1053d35f4ed6876ad9d3a14cdae363db0a7e9b0a (patch)
tree64c30d5add3bd5be8857803c06c2aedf71182c72 /drivers/net/wireless
parent5a676bbeaf9e534b75286f2294ec57a4c544f1d2 (diff)
iwlwifi: move NIC init and Tx queues init to iwlcore
This patch does the following: 1 - change hw_nic_init from a handler to a function 2 - move hw_nic_init function to iwlcore 3 - open a new file - iwl-tx.c 4 - move all Tx queues initialization (part of NIC init) to iwl-tx.c 5 - move iwl_rx_init, previously as part of the NIC init, to iwl-rx.c 6 - iwl4965_tfd_frame rename to iwl_tfd_frame Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c339
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c95
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c52
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c374
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c177
9 files changed, 550 insertions, 526 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 0211a7f7147d..85c8bf62d595 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,6 +1,6 @@
1obj-$(CONFIG_IWLCORE) += iwlcore.o 1obj-$(CONFIG_IWLCORE) += iwlcore.o
2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o 2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
3iwlcore-objs += iwl-rx.o 3iwlcore-objs += iwl-rx.o iwl-tx.o
4iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o 4iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
5iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o 5iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
6iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o 6iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index 29749e2a8ff0..ee55b283226b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -829,7 +829,7 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
829#define IWL49_NUM_QUEUES 16 829#define IWL49_NUM_QUEUES 16
830 830
831/** 831/**
832 * struct iwl4965_tfd_frame_data 832 * struct iwl_tfd_frame_data
833 * 833 *
834 * Describes up to 2 buffers containing (contiguous) portions of a Tx frame. 834 * Describes up to 2 buffers containing (contiguous) portions of a Tx frame.
835 * Each buffer must be on dword boundary. 835 * Each buffer must be on dword boundary.
@@ -848,7 +848,7 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
848 * 31-20: Tx buffer 2 length (bytes) 848 * 31-20: Tx buffer 2 length (bytes)
849 * 19- 0: Tx buffer 2 address bits [35:16] 849 * 19- 0: Tx buffer 2 address bits [35:16]
850 */ 850 */
851struct iwl4965_tfd_frame_data { 851struct iwl_tfd_frame_data {
852 __le32 tb1_addr; 852 __le32 tb1_addr;
853 853
854 __le32 val1; 854 __le32 val1;
@@ -878,7 +878,7 @@ struct iwl4965_tfd_frame_data {
878 878
879 879
880/** 880/**
881 * struct iwl4965_tfd_frame 881 * struct iwl_tfd_frame
882 * 882 *
883 * Transmit Frame Descriptor (TFD) 883 * Transmit Frame Descriptor (TFD)
884 * 884 *
@@ -905,7 +905,7 @@ struct iwl4965_tfd_frame_data {
905 * 905 *
906 * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. 906 * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
907 */ 907 */
908struct iwl4965_tfd_frame { 908struct iwl_tfd_frame {
909 __le32 val0; 909 __le32 val0;
910 /* __le32 rsvd1:24; */ 910 /* __le32 rsvd1:24; */
911 /* __le32 num_tbs:5; */ 911 /* __le32 num_tbs:5; */
@@ -914,7 +914,7 @@ struct iwl4965_tfd_frame {
914#define IWL_num_tbs_SYM val0 914#define IWL_num_tbs_SYM val0
915 /* __le32 rsvd2:1; */ 915 /* __le32 rsvd2:1; */
916 /* __le32 padding:2; */ 916 /* __le32 padding:2; */
917 struct iwl4965_tfd_frame_data pa[10]; 917 struct iwl_tfd_frame_data pa[10];
918 __le32 reserved; 918 __le32 reserved;
919} __attribute__ ((packed)); 919} __attribute__ ((packed));
920 920
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 9e6f3e33ab66..319ffe747a70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -53,8 +53,6 @@ static struct iwl_mod_params iwl4965_mod_params = {
53 /* the rest are 0 by default */ 53 /* the rest are 0 by default */
54}; 54};
55 55
56static void iwl4965_hw_card_show_info(struct iwl_priv *priv);
57
58#ifdef CONFIG_IWL4965_HT 56#ifdef CONFIG_IWL4965_HT
59 57
60static const u16 default_tid_to_tx_fifo[] = { 58static const u16 default_tid_to_tx_fifo[] = {
@@ -372,104 +370,6 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
372 return ret; 370 return ret;
373} 371}
374 372
375static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
376{
377 int ret;
378 unsigned long flags;
379 unsigned int rb_size;
380
381 spin_lock_irqsave(&priv->lock, flags);
382 ret = iwl_grab_nic_access(priv);
383 if (ret) {
384 spin_unlock_irqrestore(&priv->lock, flags);
385 return ret;
386 }
387
388 if (priv->cfg->mod_params->amsdu_size_8K)
389 rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
390 else
391 rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
392
393 /* Stop Rx DMA */
394 iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
395
396 /* Reset driver's Rx queue write index */
397 iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
398
399 /* Tell device where to find RBD circular buffer in DRAM */
400 iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
401 rxq->dma_addr >> 8);
402
403 /* Tell device where in DRAM to update its Rx status */
404 iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
405 (priv->shared_phys +
406 offsetof(struct iwl4965_shared, rb_closed)) >> 4);
407
408 /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
409 iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
410 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
411 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
412 rb_size |
413 /* 0x10 << 4 | */
414 (RX_QUEUE_SIZE_LOG <<
415 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
416
417 /*
418 * iwl_write32(priv,CSR_INT_COAL_REG,0);
419 */
420
421 iwl_release_nic_access(priv);
422 spin_unlock_irqrestore(&priv->lock, flags);
423
424 return 0;
425}
426
427/* Tell 4965 where to find the "keep warm" buffer */
428static int iwl4965_kw_init(struct iwl_priv *priv)
429{
430 unsigned long flags;
431 int rc;
432
433 spin_lock_irqsave(&priv->lock, flags);
434 rc = iwl_grab_nic_access(priv);
435 if (rc)
436 goto out;
437
438 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
439 priv->kw.dma_addr >> 4);
440 iwl_release_nic_access(priv);
441out:
442 spin_unlock_irqrestore(&priv->lock, flags);
443 return rc;
444}
445
446static int iwl4965_kw_alloc(struct iwl_priv *priv)
447{
448 struct pci_dev *dev = priv->pci_dev;
449 struct iwl4965_kw *kw = &priv->kw;
450
451 kw->size = IWL4965_KW_SIZE; /* TBW need set somewhere else */
452 kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
453 if (!kw->v_addr)
454 return -ENOMEM;
455
456 return 0;
457}
458
459/**
460 * iwl4965_kw_free - Free the "keep warm" buffer
461 */
462static void iwl4965_kw_free(struct iwl_priv *priv)
463{
464 struct pci_dev *dev = priv->pci_dev;
465 struct iwl4965_kw *kw = &priv->kw;
466
467 if (kw->v_addr) {
468 pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
469 memset(kw, 0, sizeof(*kw));
470 }
471}
472
473static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) 373static int iwl4965_disable_tx_fifo(struct iwl_priv *priv)
474{ 374{
475 unsigned long flags; 375 unsigned long flags;
@@ -491,65 +391,6 @@ static int iwl4965_disable_tx_fifo(struct iwl_priv *priv)
491 return 0; 391 return 0;
492} 392}
493 393
494/**
495 * iwl4965_txq_ctx_reset - Reset TX queue context
496 * Destroys all DMA structures and initialise them again
497 *
498 * @param priv
499 * @return error code
500 */
501static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
502{
503 int rc = 0;
504 int txq_id, slots_num;
505
506 iwl4965_kw_free(priv);
507
508 /* Free all tx/cmd queues and keep-warm buffer */
509 iwl4965_hw_txq_ctx_free(priv);
510
511 /* Alloc keep-warm buffer */
512 rc = iwl4965_kw_alloc(priv);
513 if (rc) {
514 IWL_ERROR("Keep Warm allocation failed");
515 goto error_kw;
516 }
517
518 /* Turn off all Tx DMA fifos */
519 rc = priv->cfg->ops->lib->disable_tx_fifo(priv);
520 if (unlikely(rc))
521 goto error_reset;
522
523 /* Tell 4965 where to find the keep-warm buffer */
524 rc = iwl4965_kw_init(priv);
525 if (rc) {
526 IWL_ERROR("kw_init failed\n");
527 goto error_reset;
528 }
529
530 /* Alloc and init all (default 16) Tx queues,
531 * including the command queue (#4) */
532 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
533 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
534 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
535 rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
536 txq_id);
537 if (rc) {
538 IWL_ERROR("Tx %d queue init failed\n", txq_id);
539 goto error;
540 }
541 }
542
543 return rc;
544
545 error:
546 iwl4965_hw_txq_ctx_free(priv);
547 error_reset:
548 iwl4965_kw_free(priv);
549 error_kw:
550 return rc;
551}
552
553static int iwl4965_apm_init(struct iwl_priv *priv) 394static int iwl4965_apm_init(struct iwl_priv *priv)
554{ 395{
555 unsigned long flags; 396 unsigned long flags;
@@ -633,58 +474,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
633 spin_unlock_irqrestore(&priv->lock, flags); 474 spin_unlock_irqrestore(&priv->lock, flags);
634} 475}
635 476
636int iwl4965_hw_nic_init(struct iwl_priv *priv)
637{
638 unsigned long flags;
639 struct iwl_rx_queue *rxq = &priv->rxq;
640 int ret;
641
642 /* nic_init */
643 priv->cfg->ops->lib->apm_ops.init(priv);
644
645 spin_lock_irqsave(&priv->lock, flags);
646 iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
647 spin_unlock_irqrestore(&priv->lock, flags);
648
649 ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
650
651 priv->cfg->ops->lib->apm_ops.config(priv);
652
653 iwl4965_hw_card_show_info(priv);
654
655 /* end nic_init */
656
657 /* Allocate the RX queue, or reset if it is already allocated */
658 if (!rxq->bd) {
659 ret = iwl_rx_queue_alloc(priv);
660 if (ret) {
661 IWL_ERROR("Unable to initialize Rx queue\n");
662 return -ENOMEM;
663 }
664 } else
665 iwl_rx_queue_reset(priv, rxq);
666
667 iwl_rx_replenish(priv);
668
669 iwl4965_rx_init(priv, rxq);
670
671 spin_lock_irqsave(&priv->lock, flags);
672
673 rxq->need_update = 1;
674 iwl_rx_queue_update_write_ptr(priv, rxq);
675
676 spin_unlock_irqrestore(&priv->lock, flags);
677
678 /* Allocate and init all Tx and Command queues */
679 ret = iwl4965_txq_ctx_reset(priv);
680 if (ret)
681 return ret;
682
683 set_bit(STATUS_INIT, &priv->status);
684
685 return 0;
686}
687
688int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) 477int iwl4965_hw_nic_stop_master(struct iwl_priv *priv)
689{ 478{
690 int rc = 0; 479 int rc = 0;
@@ -745,7 +534,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
745 } 534 }
746 535
747 /* Deallocate memory for all Tx queues */ 536 /* Deallocate memory for all Tx queues */
748 iwl4965_hw_txq_ctx_free(priv); 537 iwl_hw_txq_ctx_free(priv);
749} 538}
750 539
751int iwl4965_hw_nic_reset(struct iwl_priv *priv) 540int iwl4965_hw_nic_reset(struct iwl_priv *priv)
@@ -1199,82 +988,6 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
1199 return 0; 988 return 0;
1200} 989}
1201 990
1202/**
1203 * iwl4965_hw_txq_ctx_free - Free TXQ Context
1204 *
1205 * Destroy all TX DMA queues and structures
1206 */
1207void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
1208{
1209 int txq_id;
1210
1211 /* Tx queues */
1212 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
1213 iwl4965_tx_queue_free(priv, &priv->txq[txq_id]);
1214
1215 /* Keep-warm buffer */
1216 iwl4965_kw_free(priv);
1217}
1218
1219/**
1220 * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
1221 *
1222 * Does NOT advance any TFD circular buffer read/write indexes
1223 * Does NOT free the TFD itself (which is within circular buffer)
1224 */
1225int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
1226{
1227 struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0];
1228 struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
1229 struct pci_dev *dev = priv->pci_dev;
1230 int i;
1231 int counter = 0;
1232 int index, is_odd;
1233
1234 /* Host command buffers stay mapped in memory, nothing to clean */
1235 if (txq->q.id == IWL_CMD_QUEUE_NUM)
1236 return 0;
1237
1238 /* Sanity check on number of chunks */
1239 counter = IWL_GET_BITS(*bd, num_tbs);
1240 if (counter > MAX_NUM_OF_TBS) {
1241 IWL_ERROR("Too many chunks: %i\n", counter);
1242 /* @todo issue fatal error, it is quite serious situation */
1243 return 0;
1244 }
1245
1246 /* Unmap chunks, if any.
1247 * TFD info for odd chunks is different format than for even chunks. */
1248 for (i = 0; i < counter; i++) {
1249 index = i / 2;
1250 is_odd = i & 0x1;
1251
1252 if (is_odd)
1253 pci_unmap_single(
1254 dev,
1255 IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
1256 (IWL_GET_BITS(bd->pa[index],
1257 tb2_addr_hi20) << 16),
1258 IWL_GET_BITS(bd->pa[index], tb2_len),
1259 PCI_DMA_TODEVICE);
1260
1261 else if (i > 0)
1262 pci_unmap_single(dev,
1263 le32_to_cpu(bd->pa[index].tb1_addr),
1264 IWL_GET_BITS(bd->pa[index], tb1_len),
1265 PCI_DMA_TODEVICE);
1266
1267 /* Free SKB, if any, for this chunk */
1268 if (txq->txb[txq->q.read_ptr].skb[i]) {
1269 struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
1270
1271 dev_kfree_skb(skb);
1272 txq->txb[txq->q.read_ptr].skb[i] = NULL;
1273 }
1274 }
1275 return 0;
1276}
1277
1278/* set card power command */ 991/* set card power command */
1279static int iwl4965_set_power(struct iwl_priv *priv, 992static int iwl4965_set_power(struct iwl_priv *priv,
1280 void *cmd) 993 void *cmd)
@@ -2240,46 +1953,11 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
2240 return (sizeof(*tx_beacon_cmd) + frame_size); 1953 return (sizeof(*tx_beacon_cmd) + frame_size);
2241} 1954}
2242 1955
2243/*
2244 * Tell 4965 where to find circular buffer of Tx Frame Descriptors for
2245 * given Tx queue, and enable the DMA channel used for that queue.
2246 *
2247 * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
2248 * channels supported in hardware.
2249 */
2250int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
2251{
2252 int rc;
2253 unsigned long flags;
2254 int txq_id = txq->q.id;
2255
2256 spin_lock_irqsave(&priv->lock, flags);
2257 rc = iwl_grab_nic_access(priv);
2258 if (rc) {
2259 spin_unlock_irqrestore(&priv->lock, flags);
2260 return rc;
2261 }
2262
2263 /* Circular buffer (TFD queue in DRAM) physical base address */
2264 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
2265 txq->q.dma_addr >> 8);
2266
2267 /* Enable DMA channel, using same id as for TFD queue */
2268 iwl_write_direct32(
2269 priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
2270 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
2271 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
2272 iwl_release_nic_access(priv);
2273 spin_unlock_irqrestore(&priv->lock, flags);
2274
2275 return 0;
2276}
2277
2278int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, 1956int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
2279 dma_addr_t addr, u16 len) 1957 dma_addr_t addr, u16 len)
2280{ 1958{
2281 int index, is_odd; 1959 int index, is_odd;
2282 struct iwl4965_tfd_frame *tfd = ptr; 1960 struct iwl_tfd_frame *tfd = ptr;
2283 u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs); 1961 u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
2284 1962
2285 /* Each TFD can point to a maximum 20 Tx buffers */ 1963 /* Each TFD can point to a maximum 20 Tx buffers */
@@ -2309,18 +1987,6 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
2309 return 0; 1987 return 0;
2310} 1988}
2311 1989
2312static void iwl4965_hw_card_show_info(struct iwl_priv *priv)
2313{
2314 u16 hw_version = iwl_eeprom_query16(priv, EEPROM_4965_BOARD_REVISION);
2315
2316 IWL_DEBUG_INFO("4965ABGN HW Version %u.%u.%u\n",
2317 ((hw_version >> 8) & 0x0F),
2318 ((hw_version >> 8) >> 4), (hw_version & 0x00FF));
2319
2320 IWL_DEBUG_INFO("4965ABGN PBA Number %.16s\n",
2321 &priv->eeprom[EEPROM_4965_BOARD_PBA]);
2322}
2323
2324static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) 1990static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
2325{ 1991{
2326 priv->shared_virt = pci_alloc_consistent(priv->pci_dev, 1992 priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
@@ -4054,7 +3720,6 @@ static struct iwl_lib_ops iwl4965_lib = {
4054 .alloc_shared_mem = iwl4965_alloc_shared_mem, 3720 .alloc_shared_mem = iwl4965_alloc_shared_mem,
4055 .free_shared_mem = iwl4965_free_shared_mem, 3721 .free_shared_mem = iwl4965_free_shared_mem,
4056 .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, 3722 .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
4057 .hw_nic_init = iwl4965_hw_nic_init,
4058 .disable_tx_fifo = iwl4965_disable_tx_fifo, 3723 .disable_tx_fifo = iwl4965_disable_tx_fifo,
4059 .rx_handler_setup = iwl4965_rx_handler_setup, 3724 .rx_handler_setup = iwl4965_rx_handler_setup,
4060 .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, 3725 .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 2ff27a01cf66..4ba860741f81 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -121,6 +121,101 @@ void iwl_hw_detect(struct iwl_priv *priv)
121} 121}
122EXPORT_SYMBOL(iwl_hw_detect); 122EXPORT_SYMBOL(iwl_hw_detect);
123 123
124/* Tell nic where to find the "keep warm" buffer */
125int iwl_kw_init(struct iwl_priv *priv)
126{
127 unsigned long flags;
128 int ret;
129
130 spin_lock_irqsave(&priv->lock, flags);
131 ret = iwl_grab_nic_access(priv);
132 if (ret)
133 goto out;
134
135 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
136 priv->kw.dma_addr >> 4);
137 iwl_release_nic_access(priv);
138out:
139 spin_unlock_irqrestore(&priv->lock, flags);
140 return ret;
141}
142
143int iwl_kw_alloc(struct iwl_priv *priv)
144{
145 struct pci_dev *dev = priv->pci_dev;
146 struct iwl4965_kw *kw = &priv->kw;
147
148 kw->size = IWL4965_KW_SIZE; /* TBW need set somewhere else */
149 kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
150 if (!kw->v_addr)
151 return -ENOMEM;
152
153 return 0;
154}
155
156/**
157 * iwl_kw_free - Free the "keep warm" buffer
158 */
159void iwl_kw_free(struct iwl_priv *priv)
160{
161 struct pci_dev *dev = priv->pci_dev;
162 struct iwl4965_kw *kw = &priv->kw;
163
164 if (kw->v_addr) {
165 pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
166 memset(kw, 0, sizeof(*kw));
167 }
168}
169
170int iwl_hw_nic_init(struct iwl_priv *priv)
171{
172 unsigned long flags;
173 struct iwl_rx_queue *rxq = &priv->rxq;
174 int ret;
175
176 /* nic_init */
177 priv->cfg->ops->lib->apm_ops.init(priv);
178
179 spin_lock_irqsave(&priv->lock, flags);
180 iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
181 spin_unlock_irqrestore(&priv->lock, flags);
182
183 ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
184
185 priv->cfg->ops->lib->apm_ops.config(priv);
186
187 /* Allocate the RX queue, or reset if it is already allocated */
188 if (!rxq->bd) {
189 ret = iwl_rx_queue_alloc(priv);
190 if (ret) {
191 IWL_ERROR("Unable to initialize Rx queue\n");
192 return -ENOMEM;
193 }
194 } else
195 iwl_rx_queue_reset(priv, rxq);
196
197 iwl_rx_replenish(priv);
198
199 iwl_rx_init(priv, rxq);
200
201 spin_lock_irqsave(&priv->lock, flags);
202
203 rxq->need_update = 1;
204 iwl_rx_queue_update_write_ptr(priv, rxq);
205
206 spin_unlock_irqrestore(&priv->lock, flags);
207
208 /* Allocate and init all Tx and Command queues */
209 ret = iwl_txq_ctx_reset(priv);
210 if (ret)
211 return ret;
212
213 set_bit(STATUS_INIT, &priv->status);
214
215 return 0;
216}
217EXPORT_SYMBOL(iwl_hw_nic_init);
218
124/** 219/**
125 * iwlcore_clear_stations_table - Clear the driver's station table 220 * iwlcore_clear_stations_table - Clear the driver's station table
126 * 221 *
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index c29f8b347129..3a75dc6e35a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -108,8 +108,6 @@ struct iwl_lib_ops {
108 u16 byte_cnt); 108 u16 byte_cnt);
109 /* setup Rx handler */ 109 /* setup Rx handler */
110 void (*rx_handler_setup)(struct iwl_priv *priv); 110 void (*rx_handler_setup)(struct iwl_priv *priv);
111 /* nic init */
112 int (*hw_nic_init)(struct iwl_priv *priv);
113 /* nic Tx fifo handling */ 111 /* nic Tx fifo handling */
114 int (*disable_tx_fifo)(struct iwl_priv *priv); 112 int (*disable_tx_fifo)(struct iwl_priv *priv);
115 /* alive notification */ 113 /* alive notification */
@@ -178,6 +176,12 @@ int iwl_setup(struct iwl_priv *priv);
178void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); 176void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
179u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, 177u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
180 struct ieee80211_ht_info *sta_ht_inf); 178 struct ieee80211_ht_info *sta_ht_inf);
179int iwl_hw_nic_init(struct iwl_priv *priv);
180
181/* "keep warm" functions */
182int iwl_kw_init(struct iwl_priv *priv);
183int iwl_kw_alloc(struct iwl_priv *priv);
184void iwl_kw_free(struct iwl_priv *priv);
181 185
182/***************************************************** 186/*****************************************************
183* RX 187* RX
@@ -189,12 +193,21 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
189 struct iwl_rx_queue *q); 193 struct iwl_rx_queue *q);
190void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); 194void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
191void iwl_rx_replenish(struct iwl_priv *priv); 195void iwl_rx_replenish(struct iwl_priv *priv);
196int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
192/* FIXME: remove when TX is moved to iwl core */ 197/* FIXME: remove when TX is moved to iwl core */
193int iwl_rx_queue_restock(struct iwl_priv *priv); 198int iwl_rx_queue_restock(struct iwl_priv *priv);
194int iwl_rx_queue_space(const struct iwl_rx_queue *q); 199int iwl_rx_queue_space(const struct iwl_rx_queue *q);
195void iwl_rx_allocate(struct iwl_priv *priv); 200void iwl_rx_allocate(struct iwl_priv *priv);
196 201
197/***************************************************** 202/*****************************************************
203* TX
204******************************************************/
205int iwl_txq_ctx_reset(struct iwl_priv *priv);
206/* FIXME: remove when free Tx is fully merged into iwlcore */
207int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
208void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
209
210/*****************************************************
198 * S e n d i n g H o s t C o m m a n d s * 211 * S e n d i n g H o s t C o m m a n d s *
199 *****************************************************/ 212 *****************************************************/
200 213
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 23cae4c13459..e730583d88cc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -138,7 +138,7 @@ struct iwl4965_tx_info {
138 */ 138 */
139struct iwl4965_tx_queue { 139struct iwl4965_tx_queue {
140 struct iwl4965_queue q; 140 struct iwl4965_queue q;
141 struct iwl4965_tfd_frame *bd; 141 struct iwl_tfd_frame *bd;
142 struct iwl_cmd *cmd; 142 struct iwl_cmd *cmd;
143 dma_addr_t dma_addr_cmd; 143 dma_addr_t dma_addr_cmd;
144 struct iwl4965_tx_info *txb; 144 struct iwl4965_tx_info *txb;
@@ -649,9 +649,6 @@ extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv,
649 struct ieee80211_hdr *header); 649 struct ieee80211_hdr *header);
650extern int iwl4965_calc_db_from_ratio(int sig_ratio); 650extern int iwl4965_calc_db_from_ratio(int sig_ratio);
651extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm); 651extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
652extern int iwl4965_tx_queue_init(struct iwl_priv *priv,
653 struct iwl4965_tx_queue *txq, int count, u32 id);
654extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
655extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, 652extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
656 struct ieee80211_hdr *hdr, 653 struct ieee80211_hdr *hdr,
657 const u8 *dest, int left); 654 const u8 *dest, int left);
@@ -692,17 +689,12 @@ extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
692extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); 689extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
693extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); 690extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
694extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv); 691extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
695extern int iwl4965_hw_nic_init(struct iwl_priv *priv);
696extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); 692extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
697extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
698extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv); 693extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
699extern int iwl4965_hw_nic_reset(struct iwl_priv *priv); 694extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
700extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, 695extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
701 dma_addr_t addr, u16 len); 696 dma_addr_t addr, u16 len);
702extern int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
703extern int iwl4965_hw_get_temperature(struct iwl_priv *priv); 697extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
704extern int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
705 struct iwl4965_tx_queue *txq);
706extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, 698extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
707 struct iwl4965_frame *frame, u8 rate); 699 struct iwl4965_frame *frame, u8 rate);
708extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv); 700extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 667b592e6ade..171751e417d5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -369,3 +369,55 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
369} 369}
370EXPORT_SYMBOL(iwl_rx_queue_reset); 370EXPORT_SYMBOL(iwl_rx_queue_reset);
371 371
372int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
373{
374 int ret;
375 unsigned long flags;
376 unsigned int rb_size;
377
378 spin_lock_irqsave(&priv->lock, flags);
379 ret = iwl_grab_nic_access(priv);
380 if (ret) {
381 spin_unlock_irqrestore(&priv->lock, flags);
382 return ret;
383 }
384
385 if (priv->cfg->mod_params->amsdu_size_8K)
386 rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
387 else
388 rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
389
390 /* Stop Rx DMA */
391 iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
392
393 /* Reset driver's Rx queue write index */
394 iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
395
396 /* Tell device where to find RBD circular buffer in DRAM */
397 iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
398 rxq->dma_addr >> 8);
399
400 /* Tell device where in DRAM to update its Rx status */
401 iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
402 (priv->shared_phys +
403 offsetof(struct iwl4965_shared, rb_closed)) >> 4);
404
405 /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
406 iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
407 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
408 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
409 rb_size |
410 /* 0x10 << 4 | */
411 (RX_QUEUE_SIZE_LOG <<
412 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
413
414 /*
415 * iwl_write32(priv,CSR_INT_COAL_REG,0);
416 */
417
418 iwl_release_nic_access(priv);
419 spin_unlock_irqrestore(&priv->lock, flags);
420
421 return 0;
422}
423
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
new file mode 100644
index 000000000000..ade247e63106
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -0,0 +1,374 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
4 *
5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 *
21 * The full GNU General Public License is included in this distribution in the
22 * file called LICENSE.
23 *
24 * Contact Information:
25 * James P. Ketrenos <ipw2100-admin@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 *****************************************************************************/
29
30#include <net/mac80211.h>
31#include "iwl-eeprom.h"
32#include "iwl-dev.h"
33#include "iwl-core.h"
34#include "iwl-sta.h"
35#include "iwl-io.h"
36#include "iwl-helpers.h"
37
38/**
39 * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
40 *
41 * Does NOT advance any TFD circular buffer read/write indexes
42 * Does NOT free the TFD itself (which is within circular buffer)
43 */
44int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
45{
46 struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
47 struct iwl_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
48 struct pci_dev *dev = priv->pci_dev;
49 int i;
50 int counter = 0;
51 int index, is_odd;
52
53 /* Host command buffers stay mapped in memory, nothing to clean */
54 if (txq->q.id == IWL_CMD_QUEUE_NUM)
55 return 0;
56
57 /* Sanity check on number of chunks */
58 counter = IWL_GET_BITS(*bd, num_tbs);
59 if (counter > MAX_NUM_OF_TBS) {
60 IWL_ERROR("Too many chunks: %i\n", counter);
61 /* @todo issue fatal error, it is quite serious situation */
62 return 0;
63 }
64
65 /* Unmap chunks, if any.
66 * TFD info for odd chunks is different format than for even chunks. */
67 for (i = 0; i < counter; i++) {
68 index = i / 2;
69 is_odd = i & 0x1;
70
71 if (is_odd)
72 pci_unmap_single(
73 dev,
74 IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
75 (IWL_GET_BITS(bd->pa[index],
76 tb2_addr_hi20) << 16),
77 IWL_GET_BITS(bd->pa[index], tb2_len),
78 PCI_DMA_TODEVICE);
79
80 else if (i > 0)
81 pci_unmap_single(dev,
82 le32_to_cpu(bd->pa[index].tb1_addr),
83 IWL_GET_BITS(bd->pa[index], tb1_len),
84 PCI_DMA_TODEVICE);
85
86 /* Free SKB, if any, for this chunk */
87 if (txq->txb[txq->q.read_ptr].skb[i]) {
88 struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
89
90 dev_kfree_skb(skb);
91 txq->txb[txq->q.read_ptr].skb[i] = NULL;
92 }
93 }
94 return 0;
95}
96EXPORT_SYMBOL(iwl_hw_txq_free_tfd);
97
98/**
99 * iwl_tx_queue_free - Deallocate DMA queue.
100 * @txq: Transmit queue to deallocate.
101 *
102 * Empty queue by removing and destroying all BD's.
103 * Free all buffers.
104 * 0-fill, but do not free "txq" descriptor structure.
105 */
106static void iwl_tx_queue_free(struct iwl_priv *priv,
107 struct iwl4965_tx_queue *txq)
108{
109 struct iwl4965_queue *q = &txq->q;
110 struct pci_dev *dev = priv->pci_dev;
111 int len;
112
113 if (q->n_bd == 0)
114 return;
115
116 /* first, empty all BD's */
117 for (; q->write_ptr != q->read_ptr;
118 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
119 iwl_hw_txq_free_tfd(priv, txq);
120
121 len = sizeof(struct iwl_cmd) * q->n_window;
122 if (q->id == IWL_CMD_QUEUE_NUM)
123 len += IWL_MAX_SCAN_SIZE;
124
125 /* De-alloc array of command/tx buffers */
126 pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
127
128 /* De-alloc circular buffer of TFDs */
129 if (txq->q.n_bd)
130 pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
131 txq->q.n_bd, txq->bd, txq->q.dma_addr);
132
133 /* De-alloc array of per-TFD driver data */
134 kfree(txq->txb);
135 txq->txb = NULL;
136
137 /* 0-fill queue descriptor structure */
138 memset(txq, 0, sizeof(*txq));
139}
140
141/**
142 * iwl_hw_txq_ctx_free - Free TXQ Context
143 *
144 * Destroy all TX DMA queues and structures
145 */
146void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
147{
148 int txq_id;
149
150 /* Tx queues */
151 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
152 iwl_tx_queue_free(priv, &priv->txq[txq_id]);
153
154 /* Keep-warm buffer */
155 iwl_kw_free(priv);
156}
157EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
158
159/**
160 * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
161 */
162static int iwl_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
163 int count, int slots_num, u32 id)
164{
165 q->n_bd = count;
166 q->n_window = slots_num;
167 q->id = id;
168
169 /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
170 * and iwl_queue_dec_wrap are broken. */
171 BUG_ON(!is_power_of_2(count));
172
173 /* slots_num must be power-of-two size, otherwise
174 * get_cmd_index is broken. */
175 BUG_ON(!is_power_of_2(slots_num));
176
177 q->low_mark = q->n_window / 4;
178 if (q->low_mark < 4)
179 q->low_mark = 4;
180
181 q->high_mark = q->n_window / 8;
182 if (q->high_mark < 2)
183 q->high_mark = 2;
184
185 q->write_ptr = q->read_ptr = 0;
186
187 return 0;
188}
189
190/**
191 * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
192 */
193static int iwl_tx_queue_alloc(struct iwl_priv *priv,
194 struct iwl4965_tx_queue *txq, u32 id)
195{
196 struct pci_dev *dev = priv->pci_dev;
197
198 /* Driver private data, only for Tx (not command) queues,
199 * not shared with device. */
200 if (id != IWL_CMD_QUEUE_NUM) {
201 txq->txb = kmalloc(sizeof(txq->txb[0]) *
202 TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
203 if (!txq->txb) {
204 IWL_ERROR("kmalloc for auxiliary BD "
205 "structures failed\n");
206 goto error;
207 }
208 } else
209 txq->txb = NULL;
210
211 /* Circular buffer of transmit frame descriptors (TFDs),
212 * shared with device */
213 txq->bd = pci_alloc_consistent(dev,
214 sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
215 &txq->q.dma_addr);
216
217 if (!txq->bd) {
218 IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
219 sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
220 goto error;
221 }
222 txq->q.id = id;
223
224 return 0;
225
226 error:
227 kfree(txq->txb);
228 txq->txb = NULL;
229
230 return -ENOMEM;
231}
232
233/*
234 * Tell nic where to find circular buffer of Tx Frame Descriptors for
235 * given Tx queue, and enable the DMA channel used for that queue.
236 *
237 * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
238 * channels supported in hardware.
239 */
240static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
241 struct iwl4965_tx_queue *txq)
242{
243 int rc;
244 unsigned long flags;
245 int txq_id = txq->q.id;
246
247 spin_lock_irqsave(&priv->lock, flags);
248 rc = iwl_grab_nic_access(priv);
249 if (rc) {
250 spin_unlock_irqrestore(&priv->lock, flags);
251 return rc;
252 }
253
254 /* Circular buffer (TFD queue in DRAM) physical base address */
255 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
256 txq->q.dma_addr >> 8);
257
258 /* Enable DMA channel, using same id as for TFD queue */
259 iwl_write_direct32(
260 priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
261 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
262 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
263 iwl_release_nic_access(priv);
264 spin_unlock_irqrestore(&priv->lock, flags);
265
266 return 0;
267}
268
269/**
270 * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue
271 */
272static int iwl_tx_queue_init(struct iwl_priv *priv,
273 struct iwl4965_tx_queue *txq,
274 int slots_num, u32 txq_id)
275{
276 struct pci_dev *dev = priv->pci_dev;
277 int len;
278 int rc = 0;
279
280 /*
281 * Alloc buffer array for commands (Tx or other types of commands).
282 * For the command queue (#4), allocate command space + one big
283 * command for scan, since scan command is very huge; the system will
284 * not have two scans at the same time, so only one is needed.
285 * For normal Tx queues (all other queues), no super-size command
286 * space is needed.
287 */
288 len = sizeof(struct iwl_cmd) * slots_num;
289 if (txq_id == IWL_CMD_QUEUE_NUM)
290 len += IWL_MAX_SCAN_SIZE;
291 txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
292 if (!txq->cmd)
293 return -ENOMEM;
294
295 /* Alloc driver data array and TFD circular buffer */
296 rc = iwl_tx_queue_alloc(priv, txq, txq_id);
297 if (rc) {
298 pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
299
300 return -ENOMEM;
301 }
302 txq->need_update = 0;
303
304 /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
305 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
306 BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
307
308 /* Initialize queue's high/low-water marks, and head/tail indexes */
309 iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
310
311 /* Tell device where to find queue */
312 iwl_hw_tx_queue_init(priv, txq);
313
314 return 0;
315}
316
317/**
318 * iwl_txq_ctx_reset - Reset TX queue context
319 * Destroys all DMA structures and initialise them again
320 *
321 * @param priv
322 * @return error code
323 */
324int iwl_txq_ctx_reset(struct iwl_priv *priv)
325{
326 int ret = 0;
327 int txq_id, slots_num;
328
329 iwl_kw_free(priv);
330
331 /* Free all tx/cmd queues and keep-warm buffer */
332 iwl_hw_txq_ctx_free(priv);
333
334 /* Alloc keep-warm buffer */
335 ret = iwl_kw_alloc(priv);
336 if (ret) {
337 IWL_ERROR("Keep Warm allocation failed");
338 goto error_kw;
339 }
340
341 /* Turn off all Tx DMA fifos */
342 ret = priv->cfg->ops->lib->disable_tx_fifo(priv);
343 if (unlikely(ret))
344 goto error_reset;
345
346 /* Tell nic where to find the keep-warm buffer */
347 ret = iwl_kw_init(priv);
348 if (ret) {
349 IWL_ERROR("kw_init failed\n");
350 goto error_reset;
351 }
352
353 /* Alloc and init all (default 16) Tx queues,
354 * including the command queue (#4) */
355 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
356 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
357 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
358 ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
359 txq_id);
360 if (ret) {
361 IWL_ERROR("Tx %d queue init failed\n", txq_id);
362 goto error;
363 }
364 }
365
366 return ret;
367
368 error:
369 iwl_hw_txq_ctx_free(priv);
370 error_reset:
371 iwl_kw_free(priv);
372 error_kw:
373 return ret;
374}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index ad45249454f0..8d06cf1a3193 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -207,173 +207,6 @@ static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
207 return index & (q->n_window - 1); 207 return index & (q->n_window - 1);
208} 208}
209 209
210/**
211 * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
212 */
213static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
214 int count, int slots_num, u32 id)
215{
216 q->n_bd = count;
217 q->n_window = slots_num;
218 q->id = id;
219
220 /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
221 * and iwl_queue_dec_wrap are broken. */
222 BUG_ON(!is_power_of_2(count));
223
224 /* slots_num must be power-of-two size, otherwise
225 * get_cmd_index is broken. */
226 BUG_ON(!is_power_of_2(slots_num));
227
228 q->low_mark = q->n_window / 4;
229 if (q->low_mark < 4)
230 q->low_mark = 4;
231
232 q->high_mark = q->n_window / 8;
233 if (q->high_mark < 2)
234 q->high_mark = 2;
235
236 q->write_ptr = q->read_ptr = 0;
237
238 return 0;
239}
240
241/**
242 * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
243 */
244static int iwl4965_tx_queue_alloc(struct iwl_priv *priv,
245 struct iwl4965_tx_queue *txq, u32 id)
246{
247 struct pci_dev *dev = priv->pci_dev;
248
249 /* Driver private data, only for Tx (not command) queues,
250 * not shared with device. */
251 if (id != IWL_CMD_QUEUE_NUM) {
252 txq->txb = kmalloc(sizeof(txq->txb[0]) *
253 TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
254 if (!txq->txb) {
255 IWL_ERROR("kmalloc for auxiliary BD "
256 "structures failed\n");
257 goto error;
258 }
259 } else
260 txq->txb = NULL;
261
262 /* Circular buffer of transmit frame descriptors (TFDs),
263 * shared with device */
264 txq->bd = pci_alloc_consistent(dev,
265 sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
266 &txq->q.dma_addr);
267
268 if (!txq->bd) {
269 IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
270 sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
271 goto error;
272 }
273 txq->q.id = id;
274
275 return 0;
276
277 error:
278 if (txq->txb) {
279 kfree(txq->txb);
280 txq->txb = NULL;
281 }
282
283 return -ENOMEM;
284}
285
286/**
287 * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
288 */
289int iwl4965_tx_queue_init(struct iwl_priv *priv,
290 struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
291{
292 struct pci_dev *dev = priv->pci_dev;
293 int len;
294 int rc = 0;
295
296 /*
297 * Alloc buffer array for commands (Tx or other types of commands).
298 * For the command queue (#4), allocate command space + one big
299 * command for scan, since scan command is very huge; the system will
300 * not have two scans at the same time, so only one is needed.
301 * For normal Tx queues (all other queues), no super-size command
302 * space is needed.
303 */
304 len = sizeof(struct iwl_cmd) * slots_num;
305 if (txq_id == IWL_CMD_QUEUE_NUM)
306 len += IWL_MAX_SCAN_SIZE;
307 txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
308 if (!txq->cmd)
309 return -ENOMEM;
310
311 /* Alloc driver data array and TFD circular buffer */
312 rc = iwl4965_tx_queue_alloc(priv, txq, txq_id);
313 if (rc) {
314 pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
315
316 return -ENOMEM;
317 }
318 txq->need_update = 0;
319
320 /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
321 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
322 BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
323
324 /* Initialize queue's high/low-water marks, and head/tail indexes */
325 iwl4965_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
326
327 /* Tell device where to find queue */
328 iwl4965_hw_tx_queue_init(priv, txq);
329
330 return 0;
331}
332
333/**
334 * iwl4965_tx_queue_free - Deallocate DMA queue.
335 * @txq: Transmit queue to deallocate.
336 *
337 * Empty queue by removing and destroying all BD's.
338 * Free all buffers.
339 * 0-fill, but do not free "txq" descriptor structure.
340 */
341void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
342{
343 struct iwl4965_queue *q = &txq->q;
344 struct pci_dev *dev = priv->pci_dev;
345 int len;
346
347 if (q->n_bd == 0)
348 return;
349
350 /* first, empty all BD's */
351 for (; q->write_ptr != q->read_ptr;
352 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
353 iwl4965_hw_txq_free_tfd(priv, txq);
354
355 len = sizeof(struct iwl_cmd) * q->n_window;
356 if (q->id == IWL_CMD_QUEUE_NUM)
357 len += IWL_MAX_SCAN_SIZE;
358
359 /* De-alloc array of command/tx buffers */
360 pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
361
362 /* De-alloc circular buffer of TFDs */
363 if (txq->q.n_bd)
364 pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) *
365 txq->q.n_bd, txq->bd, txq->q.dma_addr);
366
367 /* De-alloc array of per-TFD driver data */
368 if (txq->txb) {
369 kfree(txq->txb);
370 txq->txb = NULL;
371 }
372
373 /* 0-fill queue descriptor structure */
374 memset(txq, 0, sizeof(*txq));
375}
376
377const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 210const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
378 211
379/*************** STATION TABLE MANAGEMENT **** 212/*************** STATION TABLE MANAGEMENT ****
@@ -516,7 +349,7 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
516{ 349{
517 struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; 350 struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
518 struct iwl4965_queue *q = &txq->q; 351 struct iwl4965_queue *q = &txq->q;
519 struct iwl4965_tfd_frame *tfd; 352 struct iwl_tfd_frame *tfd;
520 u32 *control_flags; 353 u32 *control_flags;
521 struct iwl_cmd *out_cmd; 354 struct iwl_cmd *out_cmd;
522 u32 idx; 355 u32 idx;
@@ -1931,7 +1764,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv,
1931 struct sk_buff *skb, struct ieee80211_tx_control *ctl) 1764 struct sk_buff *skb, struct ieee80211_tx_control *ctl)
1932{ 1765{
1933 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1766 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1934 struct iwl4965_tfd_frame *tfd; 1767 struct iwl_tfd_frame *tfd;
1935 u32 *control_flags; 1768 u32 *control_flags;
1936 int txq_id = ctl->queue; 1769 int txq_id = ctl->queue;
1937 struct iwl4965_tx_queue *txq = NULL; 1770 struct iwl4965_tx_queue *txq = NULL;
@@ -2515,7 +2348,7 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
2515 if (txq_id != IWL_CMD_QUEUE_NUM) { 2348 if (txq_id != IWL_CMD_QUEUE_NUM) {
2516 iwl4965_txstatus_to_ieee(priv, 2349 iwl4965_txstatus_to_ieee(priv,
2517 &(txq->txb[txq->q.read_ptr])); 2350 &(txq->txb[txq->q.read_ptr]));
2518 iwl4965_hw_txq_free_tfd(priv, txq); 2351 iwl_hw_txq_free_tfd(priv, txq);
2519 } else if (nfreed > 1) { 2352 } else if (nfreed > 1) {
2520 IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, 2353 IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
2521 q->write_ptr, q->read_ptr); 2354 q->write_ptr, q->read_ptr);
@@ -4677,7 +4510,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
4677 return ret; 4510 return ret;
4678 } 4511 }
4679 4512
4680 ret = priv->cfg->ops->lib->hw_nic_init(priv); 4513 ret = iwl_hw_nic_init(priv);
4681 if (ret) { 4514 if (ret) {
4682 IWL_ERROR("Unable to init nic\n"); 4515 IWL_ERROR("Unable to init nic\n");
4683 return ret; 4516 return ret;
@@ -6940,7 +6773,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
6940 6773
6941 if (priv->rxq.bd) 6774 if (priv->rxq.bd)
6942 iwl_rx_queue_free(priv, &priv->rxq); 6775 iwl_rx_queue_free(priv, &priv->rxq);
6943 iwl4965_hw_txq_ctx_free(priv); 6776 iwl_hw_txq_ctx_free(priv);
6944 6777
6945 iwlcore_clear_stations_table(priv); 6778 iwlcore_clear_stations_table(priv);
6946 iwl_eeprom_free(priv); 6779 iwl_eeprom_free(priv);