aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-trans.c
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/net/wireless/iwlwifi/iwl-trans.c
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/net/wireless/iwlwifi/iwl-trans.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index c4cd363d81f..81716fdd593 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