Skip to content

Commit cfbc6c4

Browse files
sara-slucacoelho
authored andcommitted
iwlwifi: mvm: support mac80211 TXQs model
Move to use the new mac80211 TXQs implementation. This has quite a few benefits for us. We can get rid of the awkward mapping of DQA to mac80211 queues. We can stop buffering traffic while waiting for the queue to be allocated. We can also use mac80211 AMSDUs instead of building it ourselves. The usage is pretty simple: Each ieee80211_txq contains iwl_mvm_txq. There is such a queue for each TID, and one for management frames. We keep having static AP queues for probes and non-bufferable MMPDUs, along with broadcast and multicast queues. Those are being used from the "old" TX invocation path - iwl_mvm_mac_tx. When there is a new frame in a TXQ, iwl_mvm_mac_wake_tx is being called, and either invokes the TX path, or allocates the queue if it does not exist. Most of the TX path is left untouched, although we can consider cleaning it up some more, for example get rid of the duplication of txq_id in both iwl_mvm_txq and iwl_mvm_dqa_txq_info. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
1 parent c281f13 commit cfbc6c4

File tree

9 files changed

+331
-443
lines changed

9 files changed

+331
-443
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/d3.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2125,7 +2125,6 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
21252125

21262126
file->private_data = inode->i_private;
21272127

2128-
ieee80211_stop_queues(mvm->hw);
21292128
synchronize_net();
21302129

21312130
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
@@ -2140,10 +2139,9 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
21402139
rtnl_unlock();
21412140
if (err > 0)
21422141
err = -EINVAL;
2143-
if (err) {
2144-
ieee80211_wake_queues(mvm->hw);
2142+
if (err)
21452143
return err;
2146-
}
2144+
21472145
mvm->d3_test_active = true;
21482146
mvm->keep_vif = NULL;
21492147
return 0;
@@ -2223,8 +2221,6 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
22232221
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
22242222
iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif);
22252223

2226-
ieee80211_wake_queues(mvm->hw);
2227-
22282224
return 0;
22292225
}
22302226

drivers/net/wireless/intel/iwlwifi/mvm/fw.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
295295
struct iwl_notification_wait alive_wait;
296296
struct iwl_mvm_alive_data alive_data;
297297
const struct fw_img *fw;
298-
int ret, i;
298+
int ret;
299299
enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
300300
static const u16 alive_cmd[] = { MVM_ALIVE };
301301

@@ -373,9 +373,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
373373
mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].tid_bitmap =
374374
BIT(IWL_MAX_TID_COUNT + 2);
375375

376-
for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
377-
atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
378-
379376
set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
380377
#ifdef CONFIG_IWLWIFI_DEBUGFS
381378
iwl_fw_set_dbg_rec_on(&mvm->fwrt);

drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c

Lines changed: 1 addition & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ struct iwl_mvm_mac_iface_iterator_data {
9797
bool found_vif;
9898
};
9999

100-
struct iwl_mvm_hw_queues_iface_iterator_data {
101-
struct ieee80211_vif *exclude_vif;
102-
unsigned long used_hw_queues;
103-
};
104-
105100
static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
106101
struct ieee80211_vif *vif)
107102
{
@@ -208,61 +203,6 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
208203
data->preferred_tsf = NUM_TSF_IDS;
209204
}
210205

211-
/*
212-
* Get the mask of the queues used by the vif
213-
*/
214-
u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif)
215-
{
216-
u32 qmask = 0, ac;
217-
218-
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
219-
return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
220-
221-
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
222-
if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
223-
qmask |= BIT(vif->hw_queue[ac]);
224-
}
225-
226-
if (vif->type == NL80211_IFTYPE_AP ||
227-
vif->type == NL80211_IFTYPE_ADHOC)
228-
qmask |= BIT(vif->cab_queue);
229-
230-
return qmask;
231-
}
232-
233-
static void iwl_mvm_iface_hw_queues_iter(void *_data, u8 *mac,
234-
struct ieee80211_vif *vif)
235-
{
236-
struct iwl_mvm_hw_queues_iface_iterator_data *data = _data;
237-
238-
/* exclude the given vif */
239-
if (vif == data->exclude_vif)
240-
return;
241-
242-
data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif);
243-
}
244-
245-
unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
246-
struct ieee80211_vif *exclude_vif)
247-
{
248-
struct iwl_mvm_hw_queues_iface_iterator_data data = {
249-
.exclude_vif = exclude_vif,
250-
.used_hw_queues =
251-
BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
252-
BIT(mvm->aux_queue) |
253-
BIT(IWL_MVM_DQA_GCAST_QUEUE),
254-
};
255-
256-
lockdep_assert_held(&mvm->mutex);
257-
258-
/* mark all VIF used hw queues */
259-
ieee80211_iterate_active_interfaces_atomic(
260-
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
261-
iwl_mvm_iface_hw_queues_iter, &data);
262-
263-
return data.used_hw_queues;
264-
}
265-
266206
static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
267207
struct ieee80211_vif *vif)
268208
{
@@ -360,8 +300,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
360300
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
361301
iwl_mvm_mac_iface_iterator, &data);
362302

363-
used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, vif);
364-
365303
/*
366304
* In the case we're getting here during resume, it's similar to
367305
* firmware restart, and with RESUME_ALL the iterator will find
@@ -416,9 +354,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
416354
* the ones here - no real limit
417355
*/
418356
queue_limit = IEEE80211_MAX_QUEUES;
419-
BUILD_BUG_ON(IEEE80211_MAX_QUEUES >
420-
BITS_PER_BYTE *
421-
sizeof(mvm->hw_queue_to_mac80211[0]));
422357

423358
/*
424359
* Find available queues, and allocate them to the ACs. When in
@@ -446,9 +381,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
446381
* queue value (when queue is enabled).
447382
*/
448383
mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
449-
vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
450-
} else {
451-
vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
452384
}
453385

454386
mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA;
@@ -462,8 +394,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
462394

463395
exit_fail:
464396
memset(mvmvif, 0, sizeof(struct iwl_mvm_vif));
465-
memset(vif->hw_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(vif->hw_queue));
466-
vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
467397
return ret;
468398
}
469399

@@ -1185,7 +1115,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
11851115

11861116
if (!fw_has_api(&mvm->fw->ucode_capa,
11871117
IWL_UCODE_TLV_API_STA_TYPE))
1188-
ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
1118+
ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue);
11891119

11901120
/*
11911121
* Only set the beacon time when the MAC is being added, when we

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 80 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
425425
ieee80211_hw_set(hw, SIGNAL_DBM);
426426
ieee80211_hw_set(hw, SPECTRUM_MGMT);
427427
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
428-
ieee80211_hw_set(hw, QUEUE_CONTROL);
429428
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
430429
ieee80211_hw_set(hw, SUPPORTS_PS);
431430
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
@@ -439,6 +438,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
439438
ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
440439
ieee80211_hw_set(hw, DEAUTH_NEED_MGD_TX_PREP);
441440
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
441+
ieee80211_hw_set(hw, BUFF_MMPDU_TXQ);
442+
ieee80211_hw_set(hw, STA_MMPDU_TXQ);
442443

443444
if (iwl_mvm_has_tlc_offload(mvm)) {
444445
ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW);
@@ -549,6 +550,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
549550
hw->sta_data_size = sizeof(struct iwl_mvm_sta);
550551
hw->vif_data_size = sizeof(struct iwl_mvm_vif);
551552
hw->chanctx_data_size = sizeof(u16);
553+
hw->txq_data_size = sizeof(struct iwl_mvm_txq);
552554

553555
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
554556
BIT(NL80211_IFTYPE_P2P_CLIENT) |
@@ -798,7 +800,6 @@ static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm,
798800
goto out;
799801

800802
__skb_queue_tail(&mvm->d0i3_tx, skb);
801-
ieee80211_stop_queues(mvm->hw);
802803

803804
/* trigger wakeup */
804805
iwl_mvm_ref(mvm, IWL_MVM_REF_TX);
@@ -818,13 +819,15 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
818819
struct ieee80211_sta *sta = control->sta;
819820
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
820821
struct ieee80211_hdr *hdr = (void *)skb->data;
822+
bool offchannel = IEEE80211_SKB_CB(skb)->flags &
823+
IEEE80211_TX_CTL_TX_OFFCHAN;
821824

822825
if (iwl_mvm_is_radio_killed(mvm)) {
823826
IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n");
824827
goto drop;
825828
}
826829

827-
if (info->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
830+
if (offchannel &&
828831
!test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
829832
!test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
830833
goto drop;
@@ -837,8 +840,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
837840
sta = NULL;
838841

839842
/* If there is no sta, and it's not offchannel - send through AP */
840-
if (info->control.vif->type == NL80211_IFTYPE_STATION &&
841-
info->hw_queue != IWL_MVM_OFFCHANNEL_QUEUE && !sta) {
843+
if (!sta && info->control.vif->type == NL80211_IFTYPE_STATION &&
844+
!offchannel) {
842845
struct iwl_mvm_vif *mvmvif =
843846
iwl_mvm_vif_from_mac80211(info->control.vif);
844847
u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id);
@@ -866,6 +869,77 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
866869
ieee80211_free_txskb(hw, skb);
867870
}
868871

872+
void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
873+
{
874+
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
875+
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
876+
struct sk_buff *skb = NULL;
877+
878+
spin_lock(&mvmtxq->tx_path_lock);
879+
880+
rcu_read_lock();
881+
while (likely(!mvmtxq->stopped &&
882+
(mvm->trans->system_pm_mode ==
883+
IWL_PLAT_PM_MODE_DISABLED))) {
884+
skb = ieee80211_tx_dequeue(hw, txq);
885+
886+
if (!skb)
887+
break;
888+
889+
if (!txq->sta)
890+
iwl_mvm_tx_skb_non_sta(mvm, skb);
891+
else
892+
iwl_mvm_tx_skb(mvm, skb, txq->sta);
893+
}
894+
rcu_read_unlock();
895+
896+
spin_unlock(&mvmtxq->tx_path_lock);
897+
}
898+
899+
static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
900+
struct ieee80211_txq *txq)
901+
{
902+
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
903+
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
904+
905+
/*
906+
* Please note that racing is handled very carefully here:
907+
* mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
908+
* deleted afterwards.
909+
* This means that if:
910+
* mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
911+
* queue is allocated and we can TX.
912+
* mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
913+
* a race, should defer the frame.
914+
* mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
915+
* need to allocate the queue and defer the frame.
916+
* mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
917+
* queue is already scheduled for allocation, no need to allocate,
918+
* should defer the frame.
919+
*/
920+
921+
/* If the queue is allocated TX and return. */
922+
if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
923+
/*
924+
* Check that list is empty to avoid a race where txq_id is
925+
* already updated, but the queue allocation work wasn't
926+
* finished
927+
*/
928+
if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
929+
return;
930+
931+
iwl_mvm_mac_itxq_xmit(hw, txq);
932+
return;
933+
}
934+
935+
/* The list is being deleted only after the queue is fully allocated. */
936+
if (!list_empty(&mvmtxq->list))
937+
return;
938+
939+
list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
940+
schedule_work(&mvm->add_stream_wk);
941+
}
942+
869943
static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg)
870944
{
871945
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG)
@@ -1107,7 +1181,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
11071181

11081182
iwl_mvm_reset_phy_ctxts(mvm);
11091183
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
1110-
memset(mvm->sta_deferred_frames, 0, sizeof(mvm->sta_deferred_frames));
11111184
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
11121185
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
11131186

@@ -2883,32 +2956,6 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
28832956
peer_addr, action);
28842957
}
28852958

2886-
static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,
2887-
struct iwl_mvm_sta *mvm_sta)
2888-
{
2889-
struct iwl_mvm_tid_data *tid_data;
2890-
struct sk_buff *skb;
2891-
int i;
2892-
2893-
spin_lock_bh(&mvm_sta->lock);
2894-
for (i = 0; i <= IWL_MAX_TID_COUNT; i++) {
2895-
tid_data = &mvm_sta->tid_data[i];
2896-
2897-
while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) {
2898-
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
2899-
2900-
/*
2901-
* The first deferred frame should've stopped the MAC
2902-
* queues, so we should never get a second deferred
2903-
* frame for the RA/TID.
2904-
*/
2905-
iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue));
2906-
ieee80211_free_txskb(mvm->hw, skb);
2907-
}
2908-
}
2909-
spin_unlock_bh(&mvm_sta->lock);
2910-
}
2911-
29122959
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
29132960
struct ieee80211_vif *vif,
29142961
struct ieee80211_sta *sta,
@@ -2942,7 +2989,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
29422989
*/
29432990
if (old_state == IEEE80211_STA_NONE &&
29442991
new_state == IEEE80211_STA_NOTEXIST) {
2945-
iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta);
29462992
flush_work(&mvm->add_stream_wk);
29472993

29482994
/*
@@ -4680,6 +4726,7 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw)
46804726

46814727
const struct ieee80211_ops iwl_mvm_hw_ops = {
46824728
.tx = iwl_mvm_mac_tx,
4729+
.wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
46834730
.ampdu_action = iwl_mvm_mac_ampdu_action,
46844731
.start = iwl_mvm_mac_start,
46854732
.reconfig_complete = iwl_mvm_mac_reconfig_complete,

0 commit comments

Comments
 (0)