mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-18 16:44:27 +08:00
iwlwifi: mvm: support dqa-mode scd queue redirection
Make sure that in DQA mode, the SCD's configuration of a queue is redirected to the lower AC of the streams of the queue. Make sure that this queue is redirected to the lowest AC when adding a new RA/TID to an existing queue. If it isn't - redirect the queue. Also, as redirection revealed a bug in the marking of a shared queue, this patch contains a small fix to make sure a shared queue maintains the appropriate "shared queue marking". Signed-off-by: Liad Kaufman <liad.kaufman@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
e3118ad74d
commit
58f2cc57dc
@ -513,6 +513,101 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm,
|
||||
return queue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a given queue has a higher AC than the TID stream that is being added to
|
||||
* it, the queue needs to be redirected to the lower AC. This function does that
|
||||
* in such a case, otherwise - if no redirection required - it does nothing,
|
||||
* unless the %force param is true.
|
||||
*/
|
||||
static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid,
|
||||
int ac, int ssn, unsigned int wdg_timeout,
|
||||
bool force)
|
||||
{
|
||||
struct iwl_scd_txq_cfg_cmd cmd = {
|
||||
.scd_queue = queue,
|
||||
.enable = 0,
|
||||
};
|
||||
bool shared_queue;
|
||||
unsigned long mq;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If the AC is lower than current one - FIFO needs to be redirected to
|
||||
* the lowest one of the streams in the queue. Check if this is needed
|
||||
* here.
|
||||
* Notice that the enum ieee80211_ac_numbers is "flipped", so BK is with
|
||||
* value 3 and VO with value 0, so to check if ac X is lower than ac Y
|
||||
* we need to check if the numerical value of X is LARGER than of Y.
|
||||
*/
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
if (ac <= mvm->queue_info[queue].mac80211_ac && !force) {
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
IWL_DEBUG_TX_QUEUES(mvm,
|
||||
"No redirection needed on TXQ #%d\n",
|
||||
queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
|
||||
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[mvm->queue_info[queue].mac80211_ac];
|
||||
mq = mvm->queue_info[queue].hw_queue_to_mac80211;
|
||||
shared_queue = (mvm->queue_info[queue].hw_queue_refcount > 1);
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
IWL_DEBUG_TX_QUEUES(mvm, "Redirecting shared TXQ #%d to FIFO #%d\n",
|
||||
queue, iwl_mvm_ac_to_tx_fifo[ac]);
|
||||
|
||||
/* Stop MAC queues and wait for this queue to empty */
|
||||
iwl_mvm_stop_mac_queues(mvm, mq);
|
||||
ret = iwl_trans_wait_tx_queue_empty(mvm->trans, BIT(queue));
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Error draining queue %d before reconfig\n",
|
||||
queue);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Before redirecting the queue we need to de-activate it */
|
||||
iwl_trans_txq_disable(mvm->trans, queue, false);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed SCD disable TXQ %d (ret=%d)\n", queue,
|
||||
ret);
|
||||
|
||||
/* Make sure the SCD wrptr is correctly set before reconfiguring */
|
||||
iwl_trans_txq_enable(mvm->trans, queue, iwl_mvm_ac_to_tx_fifo[ac],
|
||||
cmd.sta_id, tid, LINK_QUAL_AGG_FRAME_LIMIT_DEF,
|
||||
ssn, wdg_timeout);
|
||||
|
||||
/* TODO: Work-around SCD bug when moving back by multiples of 0x40 */
|
||||
|
||||
/* Redirect to lower AC */
|
||||
iwl_mvm_reconfig_scd(mvm, queue, iwl_mvm_ac_to_tx_fifo[ac],
|
||||
cmd.sta_id, tid, LINK_QUAL_AGG_FRAME_LIMIT_DEF,
|
||||
ssn);
|
||||
|
||||
/* Update AC marking of the queue */
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
mvm->queue_info[queue].mac80211_ac = ac;
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
/*
|
||||
* Mark queue as shared in transport if shared
|
||||
* Note this has to be done after queue enablement because enablement
|
||||
* can also set this value, and there is no indication there to shared
|
||||
* queues
|
||||
*/
|
||||
if (shared_queue)
|
||||
iwl_trans_txq_set_shared_mode(mvm->trans, queue, true);
|
||||
|
||||
out:
|
||||
/* Continue using the MAC queues */
|
||||
iwl_mvm_start_mac_queues(mvm, mq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta, u8 ac, int tid,
|
||||
struct ieee80211_hdr *hdr)
|
||||
@ -680,17 +775,21 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
iwl_mvm_invalidate_sta_queue(mvm, queue,
|
||||
disable_agg_tids, false);
|
||||
}
|
||||
|
||||
/* Mark queue as shared in transport */
|
||||
iwl_trans_txq_set_shared_mode(mvm->trans, queue, true);
|
||||
|
||||
/* TODO: a redirection may be required - DQA phase 2 */
|
||||
}
|
||||
|
||||
ssn = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl));
|
||||
iwl_mvm_enable_txq(mvm, queue, mac_queue, ssn, &cfg,
|
||||
wdg_timeout);
|
||||
|
||||
/*
|
||||
* Mark queue as shared in transport if shared
|
||||
* Note this has to be done after queue enablement because enablement
|
||||
* can also set this value, and there is no indication there to shared
|
||||
* queues
|
||||
*/
|
||||
if (shared_queue)
|
||||
iwl_trans_txq_set_shared_mode(mvm->trans, queue, true);
|
||||
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
mvmsta->tid_data[tid].txq_id = queue;
|
||||
mvmsta->tid_data[tid].is_tid_active = true;
|
||||
@ -712,6 +811,12 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
if (ret)
|
||||
goto out_err;
|
||||
}
|
||||
} else {
|
||||
/* Redirect queue, if needed */
|
||||
ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid, ac, ssn,
|
||||
wdg_timeout, false);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user