|
@@ -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)
|
|
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) &&
|
|
|
|
- (mvmvif->bcast_sta.tfd_queue_msk &
|
|
|
|
- BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)))
|
|
|
|
|
|
+ if (vif->type == NL80211_IFTYPE_AP)
|
|
queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
|
queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
|
- else if ((vif->type == NL80211_IFTYPE_P2P_DEVICE) &&
|
|
|
|
- (mvmvif->bcast_sta.tfd_queue_msk &
|
|
|
|
- BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)))
|
|
|
|
|
|
+ else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
|
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)
|
|
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,
|
|
|
|
- mvmvif->id, mvmvif->color);
|
|
|
|
|
|
+ ret = iwl_mvm_add_int_sta_common(mvm, bsta, baddr,
|
|
|
|
+ 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)
|
|
|
|
|
|
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)
|
|
|
|
|
|
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,
|