aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-07-08 11:46:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-11 15:02:01 -0400
commitc170b867cc119fb9f6e9cac3a8245a3347bc718c (patch)
tree98addc1663a07a9c5173335d3d58dde9229f17c7 /drivers
parentc2c52e8bed1a186d060166ec57228e2a123cab2e (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.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c33
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c56
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c17
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 */
857void 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,
217void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, 217void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
218 struct iwl_rx_mem_buffer *rxb); 218 struct iwl_rx_mem_buffer *rxb);
219int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); 219int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
220void iwlagn_txq_ctx_stop(struct iwl_priv *priv);
221 220
222static inline u32 iwl_tx_status_to_mac80211(u32 status) 221static 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);
384void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); 384void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
385int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, 385int 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);
387void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
388void iwl_setup_watchdog(struct iwl_priv *priv); 387void 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 ****************************************************************************/
695extern void iwl_update_chain_flags(struct iwl_priv *priv); 695extern void iwl_update_chain_flags(struct iwl_priv *priv);
696extern const u8 iwl_bcast_addr[ETH_ALEN]; 696extern const u8 iwl_bcast_addr[ETH_ALEN];
697extern int iwl_rxq_stop(struct iwl_priv *priv);
698extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
699extern int iwl_queue_space(const struct iwl_queue *q); 697extern int iwl_queue_space(const struct iwl_queue *q);
700static inline int iwl_queue_used(const struct iwl_queue *q, int i) 698static 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 */
1239struct iwl_trans_ops { 1238struct 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 */
333static 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 */
521static 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
500static const struct iwl_trans_ops trans_ops = { 555static 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 */
227void 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 *