diff options
author | Liad Kaufman <liad.kaufman@intel.com> | 2015-07-14 13:36:18 +0300 |
---|---|---|
committer | Luca Coelho <luciano.coelho@intel.com> | 2015-10-05 14:33:27 +0300 |
commit | 4ecafae9e56802575c3b0c45ecf3dedecd3fd9e3 (patch) | |
tree | 3fabf1863843c5de3fe11bfc8385037eed7bc320 /drivers/net/wireless/iwlwifi/mvm/utils.c | |
parent | 56882e6cab432508c79b350d7842af3abac9c7d3 (diff) | |
download | lwn-4ecafae9e56802575c3b0c45ecf3dedecd3fd9e3.tar.gz lwn-4ecafae9e56802575c3b0c45ecf3dedecd3fd9e3.zip |
iwlwifi: mvm: support using multiple ACs on single HW queue
"DQA" is shorthand for "dynamic queue allocation", with the
idea of allocating queues per-RA/TID on-demand rather than
using shared queues statically allocated per vif. The goal
of this is to enable future features (like GO PM) and to
improve performance measurements of TX traffic.
When RA/TID streams can't be neatly sorted into different AC
queues, DQA allows sharing queues for the same RA. This means
that DQA allows different ACs may reach the same HW queue.
Update the code to allow such queue sharing by having a mapping
between the HW queue and the mac80211 queues using it (as this
could be more than one queue).
Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/utils.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 142 |
1 files changed, 126 insertions, 16 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 06cba97418b3..ad0f16909e2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 Intel Deutschland GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -657,34 +658,143 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) if (mvm->support_umac_log) iwl_mvm_dump_umac_error_log(mvm); } -void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, - const struct iwl_trans_txq_scd_cfg *cfg, + +int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq) +{ + int i; + + lockdep_assert_held(&mvm->queue_info_lock); + + for (i = minq; i <= maxq; i++) + if (mvm->queue_info[i].hw_queue_refcount == 0 && + !mvm->queue_info[i].setup_reserved) + return i; + + return -ENOSPC; +} + +void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, unsigned int wdg_timeout) { - struct iwl_scd_txq_cfg_cmd cmd = { - .scd_queue = queue, - .enable = 1, - .window = cfg->frame_limit, - .sta_id = cfg->sta_id, - .ssn = cpu_to_le16(ssn), - .tx_fifo = cfg->fifo, - .aggregate = cfg->aggregate, - .tid = cfg->tid, - }; + bool enable_queue = true; + + spin_lock_bh(&mvm->queue_info_lock); + + /* Make sure this TID isn't already enabled */ + if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) { + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n", + cfg->tid); + return; + } - iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout); - WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), - "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); + /* Update mappings and refcounts */ + mvm->queue_info[queue].hw_queue_to_mac80211 |= BIT(mac80211_queue); + mvm->queue_info[queue].hw_queue_refcount++; + if (mvm->queue_info[queue].hw_queue_refcount > 1) + enable_queue = false; + mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid); + + IWL_DEBUG_TX_QUEUES(mvm, + "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", + queue, mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211); + + spin_unlock_bh(&mvm->queue_info_lock); + + /* Send the enabling command if we need to */ + if (enable_queue) { + struct iwl_scd_txq_cfg_cmd cmd = { + .scd_queue = queue, + .enable = 1, + .window = cfg->frame_limit, + .sta_id = cfg->sta_id, + .ssn = cpu_to_le16(ssn), + .tx_fifo = cfg->fifo, + .aggregate = cfg->aggregate, + .tid = cfg->tid, + }; + + iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, + wdg_timeout); + WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), + &cmd), + "Failed to configure queue %d on FIFO %d\n", queue, + cfg->fifo); + } } -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags) +void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u8 tid, u8 flags) { struct iwl_scd_txq_cfg_cmd cmd = { .scd_queue = queue, .enable = 0, }; + bool remove_mac_queue = true; int ret; + spin_lock_bh(&mvm->queue_info_lock); + + if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { + spin_unlock_bh(&mvm->queue_info_lock); + return; + } + + mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); + + /* + * If there is another TID with the same AC - don't remove the MAC queue + * from the mapping + */ + if (tid < IWL_MAX_TID_COUNT) { + unsigned long tid_bitmap = + mvm->queue_info[queue].tid_bitmap; + int ac = tid_to_mac80211_ac[tid]; + int i; + + for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { + if (tid_to_mac80211_ac[i] == ac) + remove_mac_queue = false; + } + } + + if (remove_mac_queue) + mvm->queue_info[queue].hw_queue_to_mac80211 &= + ~BIT(mac80211_queue); + mvm->queue_info[queue].hw_queue_refcount--; + + cmd.enable = mvm->queue_info[queue].hw_queue_refcount ? 1 : 0; + + IWL_DEBUG_TX_QUEUES(mvm, + "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", + queue, + mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211); + + /* If the queue is still enabled - nothing left to do in this func */ + if (cmd.enable) { + spin_unlock_bh(&mvm->queue_info_lock); + return; + } + + /* Make sure queue info is correct even though we overwrite it */ + WARN(mvm->queue_info[queue].hw_queue_refcount || + mvm->queue_info[queue].tid_bitmap || + mvm->queue_info[queue].hw_queue_to_mac80211, + "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n", + queue, mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211, + mvm->queue_info[queue].tid_bitmap); + + /* If we are here - the queue is freed and we can zero out these vals */ + mvm->queue_info[queue].hw_queue_refcount = 0; + mvm->queue_info[queue].tid_bitmap = 0; + mvm->queue_info[queue].hw_queue_to_mac80211 = 0; + + spin_unlock_bh(&mvm->queue_info_lock); + iwl_trans_txq_disable(mvm->trans, queue, false); ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, sizeof(cmd), &cmd); |