diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2011-07-08 11:46:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-07-11 15:02:01 -0400 |
commit | c170b867cc119fb9f6e9cac3a8245a3347bc718c (patch) | |
tree | 98addc1663a07a9c5173335d3d58dde9229f17c7 /drivers | |
parent | c2c52e8bed1a186d060166ec57228e2a123cab2e (diff) |
iwlagn: add an API for TX stop
Tx stop moves to transport layer.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 17 |
7 files changed, 59 insertions, 55 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 25a592a656a4..a926142f470f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -2310,7 +2310,7 @@ void iwlagn_stop_device(struct iwl_priv *priv) | |||
2310 | * already dead. | 2310 | * already dead. |
2311 | */ | 2311 | */ |
2312 | if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { | 2312 | if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { |
2313 | iwlagn_txq_ctx_stop(priv); | 2313 | priv->trans.ops->tx_stop(priv); |
2314 | priv->trans.ops->rx_stop(priv); | 2314 | priv->trans.ops->rx_stop(priv); |
2315 | 2315 | ||
2316 | /* Power-down device's busmaster DMA clocks */ | 2316 | /* Power-down device's busmaster DMA clocks */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c90c78a081dd..f29b31d73be6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -851,39 +851,6 @@ static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, | |||
851 | memset(ptr, 0, sizeof(*ptr)); | 851 | memset(ptr, 0, sizeof(*ptr)); |
852 | } | 852 | } |
853 | 853 | ||
854 | /** | ||
855 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
856 | */ | ||
857 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | ||
858 | { | ||
859 | int ch, txq_id; | ||
860 | unsigned long flags; | ||
861 | |||
862 | /* Turn off all Tx DMA fifos */ | ||
863 | spin_lock_irqsave(&priv->lock, flags); | ||
864 | |||
865 | iwlagn_txq_set_sched(priv, 0); | ||
866 | |||
867 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
868 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
869 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
870 | if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
871 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
872 | 1000)) | ||
873 | IWL_ERR(priv, "Failing on timeout while stopping" | ||
874 | " DMA channel %d [0x%08x]", ch, | ||
875 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); | ||
876 | } | ||
877 | spin_unlock_irqrestore(&priv->lock, flags); | ||
878 | |||
879 | if (!priv->txq) | ||
880 | return; | ||
881 | |||
882 | /* Unmap DMA from host system and free skb's */ | ||
883 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
884 | iwl_tx_queue_unmap(priv, txq_id); | ||
885 | } | ||
886 | |||
887 | /* | 854 | /* |
888 | * Find first available (lowest unused) Tx Queue, mark it "active". | 855 | * Find first available (lowest unused) Tx Queue, mark it "active". |
889 | * Called only when finding queue for aggregation. | 856 | * Called only when finding queue for aggregation. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 0fa379b4f46b..ff0b2ed71237 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -217,7 +217,6 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
217 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | 217 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, |
218 | struct iwl_rx_mem_buffer *rxb); | 218 | struct iwl_rx_mem_buffer *rxb); |
219 | 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); |
220 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); | ||
221 | 220 | ||
222 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | 221 | static inline u32 iwl_tx_status_to_mac80211(u32 status) |
223 | { | 222 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7d8be6b26acd..76f65350ebc3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -384,7 +384,6 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); | |||
384 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 384 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
385 | int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | 385 | int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, |
386 | int count, int slots_num, u32 id); | 386 | int count, int slots_num, u32 id); |
387 | void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id); | ||
388 | void iwl_setup_watchdog(struct iwl_priv *priv); | 387 | void iwl_setup_watchdog(struct iwl_priv *priv); |
389 | /***************************************************** | 388 | /***************************************************** |
390 | * TX power | 389 | * TX power |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8611cf0e5556..85e4fa350371 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -694,8 +694,6 @@ struct iwl_hw_params { | |||
694 | ****************************************************************************/ | 694 | ****************************************************************************/ |
695 | extern void iwl_update_chain_flags(struct iwl_priv *priv); | 695 | extern void iwl_update_chain_flags(struct iwl_priv *priv); |
696 | extern const u8 iwl_bcast_addr[ETH_ALEN]; | 696 | extern const u8 iwl_bcast_addr[ETH_ALEN]; |
697 | extern int iwl_rxq_stop(struct iwl_priv *priv); | ||
698 | extern void iwl_txq_ctx_stop(struct iwl_priv *priv); | ||
699 | extern int iwl_queue_space(const struct iwl_queue *q); | 697 | extern int iwl_queue_space(const struct iwl_queue *q); |
700 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) | 698 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) |
701 | { | 699 | { |
@@ -1234,6 +1232,7 @@ struct iwl_trans; | |||
1234 | * @rx_stop: stop the rx | 1232 | * @rx_stop: stop the rx |
1235 | * @rx_free: frees the rx memory | 1233 | * @rx_free: frees the rx memory |
1236 | * @tx_init:inits the tx memory, allocate if needed | 1234 | * @tx_init:inits the tx memory, allocate if needed |
1235 | * @tx_stop: stop the tx | ||
1237 | * @tx_free: frees the tx memory | 1236 | * @tx_free: frees the tx memory |
1238 | */ | 1237 | */ |
1239 | struct iwl_trans_ops { | 1238 | struct iwl_trans_ops { |
@@ -1242,6 +1241,7 @@ struct iwl_trans_ops { | |||
1242 | void (*rx_free)(struct iwl_priv *priv); | 1241 | void (*rx_free)(struct iwl_priv *priv); |
1243 | 1242 | ||
1244 | int (*tx_init)(struct iwl_priv *priv); | 1243 | int (*tx_init)(struct iwl_priv *priv); |
1244 | int (*tx_stop)(struct iwl_priv *priv); | ||
1245 | void (*tx_free)(struct iwl_priv *priv); | 1245 | void (*tx_free)(struct iwl_priv *priv); |
1246 | }; | 1246 | }; |
1247 | 1247 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index c4cd363d81f2..81716fdd593a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -328,6 +328,24 @@ static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
328 | } | 328 | } |
329 | 329 | ||
330 | /** | 330 | /** |
331 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | ||
332 | */ | ||
333 | static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) | ||
334 | { | ||
335 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
336 | struct iwl_queue *q = &txq->q; | ||
337 | |||
338 | if (!q->n_bd) | ||
339 | return; | ||
340 | |||
341 | while (q->write_ptr != q->read_ptr) { | ||
342 | /* The read_ptr needs to bound by q->n_window */ | ||
343 | iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr)); | ||
344 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | ||
345 | } | ||
346 | } | ||
347 | |||
348 | /** | ||
331 | * iwl_tx_queue_free - Deallocate DMA queue. | 349 | * iwl_tx_queue_free - Deallocate DMA queue. |
332 | * @txq: Transmit queue to deallocate. | 350 | * @txq: Transmit queue to deallocate. |
333 | * | 351 | * |
@@ -497,12 +515,50 @@ error: | |||
497 | return ret; | 515 | return ret; |
498 | } | 516 | } |
499 | 517 | ||
518 | /** | ||
519 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
520 | */ | ||
521 | static int iwl_trans_tx_stop(struct iwl_priv *priv) | ||
522 | { | ||
523 | int ch, txq_id; | ||
524 | unsigned long flags; | ||
525 | |||
526 | /* Turn off all Tx DMA fifos */ | ||
527 | spin_lock_irqsave(&priv->lock, flags); | ||
528 | |||
529 | iwlagn_txq_set_sched(priv, 0); | ||
530 | |||
531 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
532 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
533 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
534 | if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
535 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
536 | 1000)) | ||
537 | IWL_ERR(priv, "Failing on timeout while stopping" | ||
538 | " DMA channel %d [0x%08x]", ch, | ||
539 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); | ||
540 | } | ||
541 | spin_unlock_irqrestore(&priv->lock, flags); | ||
542 | |||
543 | if (!priv->txq) { | ||
544 | IWL_WARN(priv, "Stopping tx queues that aren't allocated..."); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /* Unmap DMA from host system and free skb's */ | ||
549 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
550 | iwl_tx_queue_unmap(priv, txq_id); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
500 | static const struct iwl_trans_ops trans_ops = { | 555 | static const struct iwl_trans_ops trans_ops = { |
501 | .rx_init = iwl_trans_rx_init, | 556 | .rx_init = iwl_trans_rx_init, |
502 | .rx_stop = iwl_trans_rx_stop, | 557 | .rx_stop = iwl_trans_rx_stop, |
503 | .rx_free = iwl_trans_rx_free, | 558 | .rx_free = iwl_trans_rx_free, |
504 | 559 | ||
505 | .tx_init = iwl_trans_tx_init, | 560 | .tx_init = iwl_trans_tx_init, |
561 | .tx_stop = iwl_trans_tx_stop, | ||
506 | .tx_free = iwl_trans_tx_free, | 562 | .tx_free = iwl_trans_tx_free, |
507 | }; | 563 | }; |
508 | 564 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 36b643a385be..b62d03235b8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -221,23 +221,6 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, | |||
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | 223 | ||
224 | /** | ||
225 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | ||
226 | */ | ||
227 | void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) | ||
228 | { | ||
229 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
230 | struct iwl_queue *q = &txq->q; | ||
231 | |||
232 | if (q->n_bd == 0) | ||
233 | return; | ||
234 | |||
235 | while (q->write_ptr != q->read_ptr) { | ||
236 | iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr)); | ||
237 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** | 224 | /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** |
242 | * DMA services | 225 | * DMA services |
243 | * | 226 | * |