diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 53 |
1 files changed, 20 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 4c03b8288c5..ba2a78c150b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -892,39 +892,45 @@ static inline void iwl_pcie_txq_progress(struct iwl_trans_pcie *trans_pcie, } /* Frees buffers until index _not_ inclusive */ -static int iwl_pcie_txq_reclaim(struct iwl_trans *trans, int txq_id, int index, - struct sk_buff_head *skbs) +void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, + struct sk_buff_head *skbs) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq = &trans_pcie->txq[txq_id]; + /* n_bd is usually 256 => n_bd - 1 = 0xff */ + int tfd_num = ssn & (txq->q.n_bd - 1); struct iwl_queue *q = &txq->q; int last_to_free; - int freed = 0; /* This function is not meant to release cmd queue*/ if (WARN_ON(txq_id == trans_pcie->cmd_queue)) - return 0; + return; - lockdep_assert_held(&txq->lock); + spin_lock(&txq->lock); + + if (txq->q.read_ptr == tfd_num) + goto out; + + IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", + txq_id, txq->q.read_ptr, tfd_num, ssn); /*Since we free until index _not_ inclusive, the one before index is * the last we will free. This one must be used */ - last_to_free = iwl_queue_dec_wrap(index, q->n_bd); + last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd); - if ((index >= q->n_bd) || - (iwl_queue_used(q, last_to_free) == 0)) { + if (iwl_queue_used(q, last_to_free) == 0) { IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", __func__, txq_id, last_to_free, q->n_bd, q->write_ptr, q->read_ptr); - return 0; + goto out; } if (WARN_ON(!skb_queue_empty(skbs))) - return 0; + goto out; for (; - q->read_ptr != index; + q->read_ptr != tfd_num; q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL)) @@ -937,32 +943,13 @@ static int iwl_pcie_txq_reclaim(struct iwl_trans *trans, int txq_id, int index, iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE); - freed++; } iwl_pcie_txq_progress(trans_pcie, txq); - return freed; -} - -void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, - struct sk_buff_head *skbs) -{ - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_txq *txq = &trans_pcie->txq[txq_id]; - /* n_bd is usually 256 => n_bd - 1 = 0xff */ - int tfd_num = ssn & (txq->q.n_bd - 1); - - spin_lock(&txq->lock); - - if (txq->q.read_ptr != tfd_num) { - IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", - txq_id, txq->q.read_ptr, tfd_num, ssn); - iwl_pcie_txq_reclaim(trans, txq_id, tfd_num, skbs); - if (iwl_queue_space(&txq->q) > txq->q.low_mark) - iwl_wake_queue(trans, txq); - } - + if (iwl_queue_space(&txq->q) > txq->q.low_mark) + iwl_wake_queue(trans, txq); +out: spin_unlock(&txq->lock); } |