diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-02-27 14:36:55 +0100 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-04-13 09:35:54 +0300 |
commit | ea68f46070c7bae608c619ae048f0ad995db74c3 (patch) | |
tree | 2e9afdb0c460fad91981dd6f46ba087dfd19571e /drivers/net/wireless/iwlwifi/pcie/tx.c | |
parent | 42646ba046e99d185bbf02373b733e9c5009eac5 (diff) | |
download | linux-ea68f46070c7bae608c619ae048f0ad995db74c3.tar.bz2 |
iwlwifi: pcie: clarify TX queue need_update handling
Similar to the recent RX queue patch, this changes the need_update
handling for the TX queues to be clearer and only done when needed.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 6c7dca1013b6..78a6ff215c04 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -287,14 +287,14 @@ static void iwl_pcie_txq_inval_byte_cnt_tbl(struct iwl_trans *trans, /* * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware */ -void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) +static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, + struct iwl_txq *txq) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 reg = 0; int txq_id = txq->q.id; - if (!txq->need_update) - return; + lockdep_assert_held(&txq->lock); /* * explicitly wake up the NIC if: @@ -317,6 +317,7 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) txq_id, reg); iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + txq->need_update = true; return; } } @@ -327,8 +328,23 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) */ IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr); iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); +} - txq->need_update = false; +void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int i; + + for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { + struct iwl_txq *txq = &trans_pcie->txq[i]; + + spin_lock(&txq->lock); + if (trans_pcie->txq[i].need_update) { + iwl_pcie_txq_inc_wr_ptr(trans, txq); + trans_pcie->txq[i].need_update = false; + } + spin_unlock(&txq->lock); + } } static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) @@ -1393,8 +1409,6 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, kfree(txq->entries[idx].free_buf); txq->entries[idx].free_buf = dup_buf; - txq->need_update = true; - trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); /* start timer if queue currently empty */ @@ -1664,7 +1678,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, dma_addr_t tb0_phys, tb1_phys, scratch_phys; void *tb1_addr; u16 len, tb1_len, tb2_len; - bool wait_write_ptr = false; + bool wait_write_ptr; __le16 fc = hdr->frame_control; u8 hdr_len = ieee80211_hdrlen(fc); u16 wifi_seq; @@ -1765,12 +1779,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, trace_iwlwifi_dev_tx_data(trans->dev, skb, skb->data + hdr_len, tb2_len); - if (!ieee80211_has_morefrags(fc)) { - txq->need_update = true; - } else { - wait_write_ptr = true; - txq->need_update = false; - } + wait_write_ptr = ieee80211_has_morefrags(fc); /* start timer if queue currently empty */ if (txq->need_update && q->read_ptr == q->write_ptr && @@ -1779,19 +1788,18 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl_pcie_txq_inc_wr_ptr(trans, txq); + if (!wait_write_ptr) + iwl_pcie_txq_inc_wr_ptr(trans, txq); /* * At this point the frame is "transmitted" successfully * and we will get a TX status notification eventually. */ if (iwl_queue_space(q) < q->high_mark) { - if (wait_write_ptr) { - txq->need_update = true; + if (wait_write_ptr) iwl_pcie_txq_inc_wr_ptr(trans, txq); - } else { + else iwl_stop_queue(trans, txq); - } } spin_unlock(&txq->lock); return 0; |