aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c59
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c88
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c2
8 files changed, 88 insertions, 104 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index c5864903f5ef..fe731918c2f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -468,25 +468,13 @@ int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
468 return ret; 468 return ret;
469} 469}
470 470
471static int iwl4965_disable_tx_fifo(struct iwl_priv *priv) 471/*
472 * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
473 * must be called under priv->lock and mac access
474 */
475static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
472{ 476{
473 unsigned long flags; 477 iwl_write_prph(priv, IWL49_SCD_TXFACT, mask);
474 int ret;
475
476 spin_lock_irqsave(&priv->lock, flags);
477
478 ret = iwl_grab_nic_access(priv);
479 if (unlikely(ret)) {
480 IWL_ERROR("Tx fifo reset failed");
481 spin_unlock_irqrestore(&priv->lock, flags);
482 return ret;
483 }
484
485 iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
486 iwl_release_nic_access(priv);
487 spin_unlock_irqrestore(&priv->lock, flags);
488
489 return 0;
490} 478}
491 479
492static int iwl4965_apm_init(struct iwl_priv *priv) 480static int iwl4965_apm_init(struct iwl_priv *priv)
@@ -579,36 +567,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
579 spin_unlock_irqrestore(&priv->lock, flags); 567 spin_unlock_irqrestore(&priv->lock, flags);
580} 568}
581 569
582/**
583 * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
584 */
585void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
586{
587
588 int txq_id;
589 unsigned long flags;
590
591 /* Stop each Tx DMA channel, and wait for it to be idle */
592 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
593 spin_lock_irqsave(&priv->lock, flags);
594 if (iwl_grab_nic_access(priv)) {
595 spin_unlock_irqrestore(&priv->lock, flags);
596 continue;
597 }
598
599 iwl_write_direct32(priv,
600 FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
601 iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
602 FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
603 (txq_id), 200);
604 iwl_release_nic_access(priv);
605 spin_unlock_irqrestore(&priv->lock, flags);
606 }
607
608 /* Deallocate memory for all Tx queues */
609 iwl_hw_txq_ctx_free(priv);
610}
611
612static int iwl4965_apm_stop_master(struct iwl_priv *priv) 570static int iwl4965_apm_stop_master(struct iwl_priv *priv)
613{ 571{
614 int ret = 0; 572 int ret = 0;
@@ -995,8 +953,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
995 (1 << priv->hw_params.max_txq_num) - 1); 953 (1 << priv->hw_params.max_txq_num) - 1);
996 954
997 /* Activate all Tx DMA/FIFO channels */ 955 /* Activate all Tx DMA/FIFO channels */
998 iwl_write_prph(priv, IWL49_SCD_TXFACT, 956 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
999 SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
1000 957
1001 iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); 958 iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
1002 959
@@ -3622,7 +3579,7 @@ static struct iwl_lib_ops iwl4965_lib = {
3622 .free_shared_mem = iwl4965_free_shared_mem, 3579 .free_shared_mem = iwl4965_free_shared_mem,
3623 .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx, 3580 .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx,
3624 .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, 3581 .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
3625 .disable_tx_fifo = iwl4965_disable_tx_fifo, 3582 .txq_set_sched = iwl4965_txq_set_sched,
3626 .rx_handler_setup = iwl4965_rx_handler_setup, 3583 .rx_handler_setup = iwl4965_rx_handler_setup,
3627 .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, 3584 .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
3628 .alive_notify = iwl4965_alive_notify, 3585 .alive_notify = iwl4965_alive_notify,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index d6074522c446..a94cd362fef5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -662,10 +662,10 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
662 } 662 }
663 663
664 iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, 664 iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK,
665 (1 << priv->hw_params.max_txq_num) - 1); 665 IWL_MASK(0, priv->hw_params.max_txq_num));
666 666
667 iwl_write_prph(priv, IWL50_SCD_TXFACT, 667 /* Activate all Tx DMA/FIFO channels */
668 SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); 668 priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
669 669
670 iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); 670 iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
671 /* map qos queues to fifos one-to-one */ 671 /* map qos queues to fifos one-to-one */
@@ -839,25 +839,13 @@ static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
839} 839}
840 840
841 841
842static int iwl5000_disable_tx_fifo(struct iwl_priv *priv) 842/*
843 * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
844 * must be called under priv->lock and mac access
845 */
846static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
843{ 847{
844 unsigned long flags; 848 iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
845 int ret;
846
847 spin_lock_irqsave(&priv->lock, flags);
848
849 ret = iwl_grab_nic_access(priv);
850 if (unlikely(ret)) {
851 IWL_ERROR("Tx fifo reset failed");
852 spin_unlock_irqrestore(&priv->lock, flags);
853 return ret;
854 }
855
856 iwl_write_prph(priv, IWL50_SCD_TXFACT, 0);
857 iwl_release_nic_access(priv);
858 spin_unlock_irqrestore(&priv->lock, flags);
859
860 return 0;
861} 849}
862 850
863/* Currently 5000 is the supperset of everything */ 851/* Currently 5000 is the supperset of everything */
@@ -894,7 +882,7 @@ static struct iwl_lib_ops iwl5000_lib = {
894 .free_shared_mem = iwl5000_free_shared_mem, 882 .free_shared_mem = iwl5000_free_shared_mem,
895 .shared_mem_rx_idx = iwl5000_shared_mem_rx_idx, 883 .shared_mem_rx_idx = iwl5000_shared_mem_rx_idx,
896 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, 884 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
897 .disable_tx_fifo = iwl5000_disable_tx_fifo, 885 .txq_set_sched = iwl5000_txq_set_sched,
898 .rx_handler_setup = iwl5000_rx_handler_setup, 886 .rx_handler_setup = iwl5000_rx_handler_setup,
899 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, 887 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
900 .load_ucode = iwl5000_load_ucode, 888 .load_ucode = iwl5000_load_ucode,
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index d6e6985181cf..d67b53cf7d5b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -110,7 +110,7 @@ struct iwl_lib_ops {
110 /* setup Rx handler */ 110 /* setup Rx handler */
111 void (*rx_handler_setup)(struct iwl_priv *priv); 111 void (*rx_handler_setup)(struct iwl_priv *priv);
112 /* nic Tx fifo handling */ 112 /* nic Tx fifo handling */
113 int (*disable_tx_fifo)(struct iwl_priv *priv); 113 void (*txq_set_sched)(struct iwl_priv *priv, u32 mask);
114 /* alive notification after init uCode load */ 114 /* alive notification after init uCode load */
115 void (*init_alive_start)(struct iwl_priv *priv); 115 void (*init_alive_start)(struct iwl_priv *priv);
116 /* alive notification */ 116 /* alive notification */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 44bd827a8bc3..3cefaaf95b22 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -686,7 +686,7 @@ extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
686extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); 686extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
687extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); 687extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
688extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv); 688extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
689extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv); 689extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
690extern int iwl4965_hw_get_temperature(struct iwl_priv *priv); 690extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
691extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, 691extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
692 struct iwl_frame *frame, u8 rate); 692 struct iwl_frame *frame, u8 rate);
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index e4c3f84f530a..dedefa06ad8f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -136,6 +136,8 @@ static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val)
136 136
137#define KELVIN_TO_CELSIUS(x) ((x)-273) 137#define KELVIN_TO_CELSIUS(x) ((x)-273)
138#define CELSIUS_TO_KELVIN(x) ((x)+273) 138#define CELSIUS_TO_KELVIN(x) ((x)+273)
139#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
140
139 141
140#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010 142#define IEEE80211_CHAN_W_RADAR_DETECT 0x00000010
141 143
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index d6a04f65f359..15cb7ff4f7aa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -358,11 +358,6 @@
358 * 7- 0: Enable (1), disable (0), one bit for each channel 0-7 358 * 7- 0: Enable (1), disable (0), one bit for each channel 0-7
359 */ 359 */
360#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c) 360#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c)
361
362/* Mask to enable contiguous Tx DMA/FIFO channels between "lo" and "hi". */
363#define SCD_TXFACT_REG_TXFIFO_MASK(lo, hi) \
364 ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
365
366/* 361/*
367 * Queue (x) Write Pointers (indexes, really!), one for each Tx queue. 362 * Queue (x) Write Pointers (indexes, really!), one for each Tx queue.
368 * Initialized and updated by driver as new TFDs are added to queue. 363 * Initialized and updated by driver as new TFDs are added to queue.
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 0ebab967d5e7..0b822b5ab523 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -263,24 +263,6 @@ EXPORT_SYMBOL(iwl_queue_space);
263 263
264 264
265/** 265/**
266 * iwl_hw_txq_ctx_free - Free TXQ Context
267 *
268 * Destroy all TX DMA queues and structures
269 */
270void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
271{
272 int txq_id;
273
274 /* Tx queues */
275 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
276 iwl_tx_queue_free(priv, &priv->txq[txq_id]);
277
278 /* Keep-warm buffer */
279 iwl_kw_free(priv);
280}
281EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
282
283/**
284 * iwl_queue_init - Initialize queue's high/low-water and read/write indexes 266 * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
285 */ 267 */
286static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, 268static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
@@ -437,6 +419,24 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
437 419
438 return 0; 420 return 0;
439} 421}
422/**
423 * iwl_hw_txq_ctx_free - Free TXQ Context
424 *
425 * Destroy all TX DMA queues and structures
426 */
427void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
428{
429 int txq_id;
430
431 /* Tx queues */
432 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
433 iwl_tx_queue_free(priv, &priv->txq[txq_id]);
434
435 /* Keep-warm buffer */
436 iwl_kw_free(priv);
437}
438EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
439
440 440
441/** 441/**
442 * iwl_txq_ctx_reset - Reset TX queue context 442 * iwl_txq_ctx_reset - Reset TX queue context
@@ -449,6 +449,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
449{ 449{
450 int ret = 0; 450 int ret = 0;
451 int txq_id, slots_num; 451 int txq_id, slots_num;
452 unsigned long flags;
452 453
453 iwl_kw_free(priv); 454 iwl_kw_free(priv);
454 455
@@ -461,11 +462,19 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
461 IWL_ERROR("Keep Warm allocation failed"); 462 IWL_ERROR("Keep Warm allocation failed");
462 goto error_kw; 463 goto error_kw;
463 } 464 }
465 spin_lock_irqsave(&priv->lock, flags);
466 ret = iwl_grab_nic_access(priv);
467 if (unlikely(ret)) {
468 spin_unlock_irqrestore(&priv->lock, flags);
469 goto error_reset;
470 }
464 471
465 /* Turn off all Tx DMA fifos */ 472 /* Turn off all Tx DMA fifos */
466 ret = priv->cfg->ops->lib->disable_tx_fifo(priv); 473 priv->cfg->ops->lib->txq_set_sched(priv, 0);
467 if (unlikely(ret)) 474
468 goto error_reset; 475 iwl_release_nic_access(priv);
476 spin_unlock_irqrestore(&priv->lock, flags);
477
469 478
470 /* Tell nic where to find the keep-warm buffer */ 479 /* Tell nic where to find the keep-warm buffer */
471 ret = iwl_kw_init(priv); 480 ret = iwl_kw_init(priv);
@@ -474,8 +483,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
474 goto error_reset; 483 goto error_reset;
475 } 484 }
476 485
477 /* Alloc and init all (default 16) Tx queues, 486 /* Alloc and init all Tx queues, including the command queue (#4) */
478 * including the command queue (#4) */
479 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { 487 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
480 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? 488 slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
481 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; 489 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
@@ -496,6 +504,40 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
496 error_kw: 504 error_kw:
497 return ret; 505 return ret;
498} 506}
507/**
508 * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
509 */
510void iwl_txq_ctx_stop(struct iwl_priv *priv)
511{
512
513 int txq_id;
514 unsigned long flags;
515
516
517 /* Turn off all Tx DMA fifos */
518 spin_lock_irqsave(&priv->lock, flags);
519 if (iwl_grab_nic_access(priv)) {
520 spin_unlock_irqrestore(&priv->lock, flags);
521 return;
522 }
523
524 priv->cfg->ops->lib->txq_set_sched(priv, 0);
525
526 /* Stop each Tx DMA channel, and wait for it to be idle */
527 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
528 iwl_write_direct32(priv,
529 FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
530 iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
531 FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
532 (txq_id), 200);
533 }
534 iwl_release_nic_access(priv);
535 spin_unlock_irqrestore(&priv->lock, flags);
536
537 /* Deallocate memory for all Tx queues */
538 iwl_hw_txq_ctx_free(priv);
539}
540EXPORT_SYMBOL(iwl_txq_ctx_stop);
499 541
500/* 542/*
501 * handle build REPLY_TX command notification. 543 * handle build REPLY_TX command notification.
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index af0ffd3aeb43..2652f5ff5103 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -3404,7 +3404,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
3404 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 3404 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
3405 spin_unlock_irqrestore(&priv->lock, flags); 3405 spin_unlock_irqrestore(&priv->lock, flags);
3406 3406
3407 iwl4965_hw_txq_ctx_stop(priv); 3407 iwl_txq_ctx_stop(priv);
3408 iwl4965_hw_rxq_stop(priv); 3408 iwl4965_hw_rxq_stop(priv);
3409 3409
3410 spin_lock_irqsave(&priv->lock, flags); 3410 spin_lock_irqsave(&priv->lock, flags);