Commit df88c08d authored by Liad Kaufman's avatar Liad Kaufman Committed by Luca Coelho

iwlwifi: mvm: release static queues on bcast release

A few of the static queues are enabled along with the bcast
STA. Make sure they are removed along with it, rather than
waiting for the mac ctxt release.

This is needed because we sometimes have a STA being removed
and then added again (either with the same sta_id or a
different one). If we wait for the mac ctxt release we will
try to allocate the queues again (as this is currently done
in the STA allocation and not in the MAC init) although
they weren't freed, and even if the sta_id of the STA has
changed.
Signed-off-by: default avatarLiad Kaufman <liad.kaufman@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 05e5a7e5
...@@ -531,38 +531,26 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -531,38 +531,26 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
/*
* If DQA is supported - queues were already disabled, since in
* DQA-mode the queues are a property of the STA and not of the
* vif, and at this point the STA was already deleted
*/
if (iwl_mvm_is_dqa_supported(mvm))
return;
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
if (!iwl_mvm_is_dqa_supported(mvm)) iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, IWL_MVM_OFFCHANNEL_QUEUE,
IWL_MVM_OFFCHANNEL_QUEUE, IWL_MAX_TID_COUNT, 0);
IWL_MAX_TID_COUNT, 0);
else
iwl_mvm_disable_txq(mvm,
IWL_MVM_DQA_P2P_DEVICE_QUEUE,
vif->hw_queue[0], IWL_MAX_TID_COUNT,
0);
break; break;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue, iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
IWL_MAX_TID_COUNT, 0); IWL_MAX_TID_COUNT, 0);
if (iwl_mvm_is_dqa_supported(mvm))
iwl_mvm_disable_txq(mvm,
IWL_MVM_DQA_AP_PROBE_RESP_QUEUE,
vif->hw_queue[0], IWL_MAX_TID_COUNT,
0);
/* fall through */ /* fall through */
default: default:
/*
* If DQA is supported - queues were already disabled, since in
* DQA-mode the queues are a property of the STA and not of the
* vif, and at this point the STA was already deleted
*/
if (iwl_mvm_is_dqa_supported(mvm))
break;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], iwl_mvm_disable_txq(mvm, vif->hw_queue[ac],
vif->hw_queue[ac], vif->hw_queue[ac],
......
...@@ -2104,22 +2104,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, ...@@ -2104,22 +2104,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (ret) if (ret)
goto out_unbind; goto out_unbind;
/* enable the multicast queue, now that we have a station for it */
if (iwl_mvm_is_dqa_supported(mvm)) {
unsigned int wdg_timeout =
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = IWL_MVM_TX_FIFO_MCAST,
.sta_id = mvmvif->bcast_sta.sta_id,
.tid = IWL_MAX_TID_COUNT,
.aggregate = false,
.frame_limit = IWL_FRAME_LIMIT,
};
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
&cfg, wdg_timeout);
}
/* must be set before quota calculations */ /* must be set before quota calculations */
mvmvif->ap_ibss_active = true; mvmvif->ap_ibss_active = true;
......
...@@ -1780,6 +1780,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1780,6 +1780,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta; struct iwl_mvm_int_sta *bsta = &mvmvif->bcast_sta;
static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const u8 *baddr = _baddr; const u8 *baddr = _baddr;
int ret;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -1795,19 +1796,16 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1795,19 +1796,16 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_get_wd_timeout(mvm, vif, false, false); iwl_mvm_get_wd_timeout(mvm, vif, false, false);
int queue; int queue;
if ((vif->type == NL80211_IFTYPE_AP) && if (vif->type == NL80211_IFTYPE_AP)
(mvmvif->bcast_sta.tfd_queue_msk &
BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)))
queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE; queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
else if ((vif->type == NL80211_IFTYPE_P2P_DEVICE) && else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
(mvmvif->bcast_sta.tfd_queue_msk &
BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)))
queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE; queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
else if (WARN(1, "Missed required TXQ for adding bcast STA\n")) else if (WARN(1, "Missing required TXQ for adding bcast STA\n"))
return -EINVAL; return -EINVAL;
iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0, &cfg, iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0, &cfg,
wdg_timeout); wdg_timeout);
bsta->tfd_queue_msk |= BIT(queue);
} }
if (vif->type == NL80211_IFTYPE_ADHOC) if (vif->type == NL80211_IFTYPE_ADHOC)
...@@ -1816,8 +1814,67 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1816,8 +1814,67 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT)) if (WARN_ON_ONCE(bsta->sta_id == IWL_MVM_STATION_COUNT))
return -ENOSPC; return -ENOSPC;
return iwl_mvm_add_int_sta_common(mvm, bsta, baddr, ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
mvmvif->id, mvmvif->color); mvmvif->id, mvmvif->color);
if (ret)
return ret;
/*
* In AP vif type, we also need to enable the cab_queue. However, we
* have to enable it after the ADD_STA command is sent, otherwise the
* FW will throw an assert once we send the ADD_STA command (it'll
* detect a mismatch in the tfd_queue_msk, as we can't add the
* enabled-cab_queue to the mask)
*/
if (iwl_mvm_is_dqa_supported(mvm) &&
vif->type == NL80211_IFTYPE_AP) {
struct iwl_trans_txq_scd_cfg cfg = {
.fifo = IWL_MVM_TX_FIFO_MCAST,
.sta_id = mvmvif->bcast_sta.sta_id,
.tid = IWL_MAX_TID_COUNT,
.aggregate = false,
.frame_limit = IWL_FRAME_LIMIT,
};
unsigned int wdg_timeout =
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue,
0, &cfg, wdg_timeout);
}
return 0;
}
static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
lockdep_assert_held(&mvm->mutex);
if (vif->type == NL80211_IFTYPE_AP)
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
IWL_MAX_TID_COUNT, 0);
if (mvmvif->bcast_sta.tfd_queue_msk &
BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)) {
iwl_mvm_disable_txq(mvm,
IWL_MVM_DQA_AP_PROBE_RESP_QUEUE,
vif->hw_queue[0], IWL_MAX_TID_COUNT,
0);
mvmvif->bcast_sta.tfd_queue_msk &=
~BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE);
}
if (mvmvif->bcast_sta.tfd_queue_msk &
BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)) {
iwl_mvm_disable_txq(mvm,
IWL_MVM_DQA_P2P_DEVICE_QUEUE,
vif->hw_queue[0], IWL_MAX_TID_COUNT,
0);
mvmvif->bcast_sta.tfd_queue_msk &=
~BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE);
}
} }
/* Send the FW a request to remove the station from it's internal data /* Send the FW a request to remove the station from it's internal data
...@@ -1829,6 +1886,9 @@ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1829,6 +1886,9 @@ int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (iwl_mvm_is_dqa_supported(mvm))
iwl_mvm_free_bcast_sta_queues(mvm, vif);
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->bcast_sta.sta_id); ret = iwl_mvm_rm_sta_common(mvm, mvmvif->bcast_sta.sta_id);
if (ret) if (ret)
IWL_WARN(mvm, "Failed sending remove station\n"); IWL_WARN(mvm, "Failed sending remove station\n");
...@@ -1842,22 +1902,16 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1842,22 +1902,16 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (!iwl_mvm_is_dqa_supported(mvm)) if (!iwl_mvm_is_dqa_supported(mvm)) {
qmask = iwl_mvm_mac_get_queues_mask(vif); qmask = iwl_mvm_mac_get_queues_mask(vif);
if (vif->type == NL80211_IFTYPE_AP) {
/* /*
* The firmware defines the TFD queue mask to only be relevant * The firmware defines the TFD queue mask to only be relevant
* for *unicast* queues, so the multicast (CAB) queue shouldn't * for *unicast* queues, so the multicast (CAB) queue shouldn't
* be included. * be included. This only happens in NL80211_IFTYPE_AP vif type,
* so the next line will only have an effect there.
*/ */
qmask &= ~BIT(vif->cab_queue); qmask &= ~BIT(vif->cab_queue);
if (iwl_mvm_is_dqa_supported(mvm))
qmask |= BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE);
} else if (iwl_mvm_is_dqa_supported(mvm) &&
vif->type == NL80211_IFTYPE_P2P_DEVICE) {
qmask |= BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE);
} }
return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, qmask, return iwl_mvm_allocate_int_sta(mvm, &mvmvif->bcast_sta, qmask,
......
...@@ -655,8 +655,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, ...@@ -655,8 +655,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
/* Make sure this TID isn't already enabled */ /* Make sure this TID isn't already enabled */
if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) { if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) {
spin_unlock_bh(&mvm->queue_info_lock); spin_unlock_bh(&mvm->queue_info_lock);
IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n", IWL_ERR(mvm, "Trying to enable TXQ %d with existing TID %d\n",
cfg->tid); queue, cfg->tid);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment