Skip to content

Commit 88046b2

Browse files
committed
mt76: add support for reporting tx status with skb
MT76x2/MT76x0 has somewhat unreliable tx status reporting, and for that reason the driver currently does not report per-skb tx ack status at all. This breaks things like client idle polling, which relies on the tx ack status of a transmitted nullfunc frame. This patch adds code to report skb-attached tx status if requested by mac80211 or the rate control module. Since tx status is polled from a simple FIFO register, the code needs to account for the possibility of tx status events getting lost. The code keeps a list of skbs for which tx status is required and passes them to mac80211 once tx status has been filled in and the DMA queue is done with it. If a tx status event is not received after one second, the status rates are cleared, and a succesful ACK is indicated to avoid spurious disassoc during assoc or client polling. Signed-off-by: Felix Fietkau <[email protected]>
1 parent 59b55d0 commit 88046b2

File tree

11 files changed

+231
-95
lines changed

11 files changed

+231
-95
lines changed

drivers/net/wireless/mediatek/mt76/dma.c

+1
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
258258
return -ENOMEM;
259259
}
260260

261+
skb->prev = skb->next = NULL;
261262
dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi),
262263
DMA_TO_DEVICE);
263264
ret = dev->drv->tx_prepare_skb(dev, &t->txwi, skb, q, wcid, sta,

drivers/net/wireless/mediatek/mt76/mac80211.c

+3
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops)
285285
spin_lock_init(&dev->cc_lock);
286286
mutex_init(&dev->mutex);
287287
init_waitqueue_head(&dev->tx_wait);
288+
skb_queue_head_init(&dev->status_list);
288289

289290
return dev;
290291
}
@@ -326,6 +327,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
326327
ieee80211_hw_set(hw, TX_FRAG_LIST);
327328
ieee80211_hw_set(hw, MFP_CAPABLE);
328329
ieee80211_hw_set(hw, AP_LINK_PS);
330+
ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
329331

330332
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
331333

@@ -357,6 +359,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
357359
{
358360
struct ieee80211_hw *hw = dev->hw;
359361

362+
mt76_tx_status_flush(dev, NULL);
360363
ieee80211_unregister_hw(hw);
361364
mt76_tx_free(dev);
362365
}

drivers/net/wireless/mediatek/mt76/mt76.h

+48
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ struct mt76_wcid {
195195
u8 tx_rate_nss;
196196
s8 max_txpwr_adj;
197197
bool sw_iv;
198+
199+
u8 packet_id;
198200
};
199201

200202
struct mt76_txq {
@@ -233,6 +235,22 @@ struct mt76_rx_tid {
233235
struct sk_buff *reorder_buf[];
234236
};
235237

238+
#define MT_TX_CB_DMA_DONE BIT(0)
239+
#define MT_TX_CB_TXS_DONE BIT(1)
240+
#define MT_TX_CB_TXS_FAILED BIT(2)
241+
242+
#define MT_PACKET_ID_MASK GENMASK(7, 0)
243+
#define MT_PACKET_ID_NO_ACK MT_PACKET_ID_MASK
244+
245+
#define MT_TX_STATUS_SKB_TIMEOUT HZ
246+
247+
struct mt76_tx_cb {
248+
unsigned long jiffies;
249+
u8 wcid;
250+
u8 pktid;
251+
u8 flags;
252+
};
253+
236254
enum {
237255
MT76_STATE_INITIALIZED,
238256
MT76_STATE_RUNNING,
@@ -400,6 +418,7 @@ struct mt76_dev {
400418
const struct mt76_queue_ops *queue_ops;
401419

402420
wait_queue_head_t tx_wait;
421+
struct sk_buff_head status_list;
403422

404423
unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG];
405424

@@ -594,6 +613,13 @@ wcid_to_sta(struct mt76_wcid *wcid)
594613
return container_of(ptr, struct ieee80211_sta, drv_priv);
595614
}
596615

616+
static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb)
617+
{
618+
BUILD_BUG_ON(sizeof(struct mt76_tx_cb) >
619+
sizeof(IEEE80211_SKB_CB(skb)->status.status_driver_data));
620+
return ((void *) IEEE80211_SKB_CB(skb)->status.status_driver_data);
621+
}
622+
597623
int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
598624
struct sk_buff *skb, struct mt76_wcid *wcid,
599625
struct ieee80211_sta *sta);
@@ -624,6 +650,28 @@ void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid);
624650

625651
void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
626652
struct ieee80211_key_conf *key);
653+
int mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
654+
struct sk_buff *skb);
655+
struct sk_buff *mt76_tx_status_skb_get(struct mt76_dev *dev,
656+
struct mt76_wcid *wcid, int pktid);
657+
void mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb);
658+
void mt76_tx_complete_skb(struct mt76_dev *dev, struct sk_buff *skb);
659+
660+
static inline void
661+
mt76_tx_status_check(struct mt76_dev *dev)
662+
{
663+
spin_lock_bh(&dev->status_list.lock);
664+
mt76_tx_status_skb_get(dev, NULL, 0);
665+
spin_unlock_bh(&dev->status_list.lock);
666+
}
667+
668+
static inline void
669+
mt76_tx_status_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
670+
{
671+
spin_lock_bh(&dev->status_list.lock);
672+
mt76_tx_status_skb_get(dev, wcid, -1);
673+
spin_unlock_bh(&dev->status_list.lock);
674+
}
627675

628676
struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
629677

drivers/net/wireless/mediatek/mt76/mt76x02.h

-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
139139
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
140140
int mt76x02_insert_hdr_pad(struct sk_buff *skb);
141141
void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
142-
void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb);
143142
bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
144143
void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
145144
struct sk_buff *skb);

drivers/net/wireless/mediatek/mt76/mt76x02_mac.c

+40-34
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,6 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
324324
else
325325
txwi->wcid = 0xff;
326326

327-
txwi->pktid = 1;
328-
329327
if (wcid && wcid->sw_iv && key) {
330328
u64 pn = atomic64_inc_return(&key->tx_pn);
331329
ccmp_pn[0] = pn;
@@ -371,8 +369,6 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
371369
txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ;
372370
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
373371
txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ;
374-
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
375-
txwi->pktid |= MT_TXWI_PKTID_PROBE;
376372
if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) {
377373
u8 ba_size = IEEE80211_MIN_AMPDU_BUF;
378374

@@ -425,9 +421,6 @@ mt76x02_mac_fill_tx_status(struct mt76x02_dev *dev,
425421
info->status.ampdu_len = n_frames;
426422
info->status.ampdu_ack_len = st->success ? n_frames : 0;
427423

428-
if (st->pktid & MT_TXWI_PKTID_PROBE)
429-
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
430-
431424
if (st->aggr)
432425
info->flags |= IEEE80211_TX_CTL_AMPDU |
433426
IEEE80211_TX_STAT_AMPDU;
@@ -442,23 +435,39 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
442435
struct mt76x02_tx_status *stat, u8 *update)
443436
{
444437
struct ieee80211_tx_info info = {};
445-
struct ieee80211_sta *sta = NULL;
438+
struct ieee80211_tx_status status = {
439+
.info = &info
440+
};
446441
struct mt76_wcid *wcid = NULL;
447442
struct mt76x02_sta *msta = NULL;
443+
struct mt76_dev *mdev = &dev->mt76;
444+
445+
if (stat->pktid == MT_PACKET_ID_NO_ACK)
446+
return;
448447

449448
rcu_read_lock();
449+
spin_lock_bh(&mdev->status_list.lock);
450+
450451
if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid))
451452
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
452453

453454
if (wcid && wcid->sta) {
454455
void *priv;
455456

456457
priv = msta = container_of(wcid, struct mt76x02_sta, wcid);
457-
sta = container_of(priv, struct ieee80211_sta,
458-
drv_priv);
458+
status.sta = container_of(priv, struct ieee80211_sta,
459+
drv_priv);
460+
}
461+
462+
if (wcid) {
463+
if (stat->pktid)
464+
status.skb = mt76_tx_status_skb_get(mdev, wcid,
465+
stat->pktid);
466+
if (status.skb)
467+
status.info = IEEE80211_SKB_CB(status.skb);
459468
}
460469

461-
if (msta && stat->aggr) {
470+
if (msta && stat->aggr && !status.skb) {
462471
u32 stat_val, stat_cache;
463472

464473
stat_val = stat->rate;
@@ -472,20 +481,24 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
472481
goto out;
473482
}
474483

475-
mt76x02_mac_fill_tx_status(dev, &info, &msta->status,
484+
mt76x02_mac_fill_tx_status(dev, status.info, &msta->status,
476485
msta->n_frames);
477486

478487
msta->status = *stat;
479488
msta->n_frames = 1;
480489
*update = 0;
481490
} else {
482-
mt76x02_mac_fill_tx_status(dev, &info, stat, 1);
491+
mt76x02_mac_fill_tx_status(dev, status.info, stat, 1);
483492
*update = 1;
484493
}
485494

486-
ieee80211_tx_status_noskb(dev->mt76.hw, sta, &info);
495+
if (status.skb)
496+
mt76_tx_status_skb_done(mdev, status.skb);
497+
else
498+
ieee80211_tx_status_ext(mt76_hw(dev), &status);
487499

488500
out:
501+
spin_unlock_bh(&mdev->status_list.lock);
489502
rcu_read_unlock();
490503
}
491504

@@ -707,32 +720,23 @@ void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq)
707720
}
708721
}
709722

710-
static void
711-
mt76x02_mac_queue_txdone(struct mt76x02_dev *dev, struct sk_buff *skb,
712-
void *txwi_ptr)
713-
{
714-
struct mt76x02_tx_info *txi = mt76x02_skb_tx_info(skb);
715-
struct mt76x02_txwi *txwi = txwi_ptr;
716-
717-
mt76x02_mac_poll_tx_status(dev, false);
718-
719-
txi->tries = 0;
720-
txi->jiffies = jiffies;
721-
txi->wcid = txwi->wcid;
722-
txi->pktid = txwi->pktid;
723-
trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid);
724-
mt76x02_tx_complete(&dev->mt76, skb);
725-
}
726-
727723
void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
728724
struct mt76_queue_entry *e, bool flush)
729725
{
730726
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
727+
struct mt76x02_txwi *txwi;
731728

732-
if (e->txwi)
733-
mt76x02_mac_queue_txdone(dev, e->skb, &e->txwi->txwi);
734-
else
729+
if (!e->txwi) {
735730
dev_kfree_skb_any(e->skb);
731+
return;
732+
}
733+
734+
mt76x02_mac_poll_tx_status(dev, false);
735+
736+
txwi = (struct mt76x02_txwi *) &e->txwi->txwi;
737+
trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid);
738+
739+
mt76_tx_complete_skb(mdev, e->skb);
736740
}
737741
EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb);
738742

@@ -817,6 +821,8 @@ void mt76x02_mac_work(struct work_struct *work)
817821
if (!dev->beacon_mask)
818822
mt76x02_check_mac_err(dev);
819823

824+
mt76_tx_status_check(&dev->mt76);
825+
820826
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
821827
MT_CALIBRATE_INTERVAL);
822828
}

drivers/net/wireless/mediatek/mt76/mt76x02_mac.h

-19
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,6 @@ struct mt76x02_vif {
4242
struct mt76_wcid group_wcid;
4343
};
4444

45-
struct mt76x02_tx_info {
46-
unsigned long jiffies;
47-
u8 tries;
48-
49-
u8 wcid;
50-
u8 pktid;
51-
u8 retry;
52-
};
53-
5445
DECLARE_EWMA(signal, 10, 8);
5546

5647
struct mt76x02_sta {
@@ -153,8 +144,6 @@ enum mt76x2_phy_bandwidth {
153144
#define MT_TXWI_ACK_CTL_NSEQ BIT(1)
154145
#define MT_TXWI_ACK_CTL_BA_WINDOW GENMASK(7, 2)
155146

156-
#define MT_TXWI_PKTID_PROBE BIT(7)
157-
158147
struct mt76x02_txwi {
159148
__le16 flags;
160149
__le16 rate;
@@ -190,14 +179,6 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev *dev)
190179
return false;
191180
}
192181

193-
static inline struct mt76x02_tx_info *
194-
mt76x02_skb_tx_info(struct sk_buff *skb)
195-
{
196-
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
197-
198-
return (void *)info->status.status_driver_data;
199-
}
200-
201182
void mt76x02_txq_init(struct mt76x02_dev *dev, struct ieee80211_txq *txq);
202183

203184
void mt76x02_mac_set_short_preamble(struct mt76x02_dev *dev, bool enable);

drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c

+7-18
Original file line numberDiff line numberDiff line change
@@ -140,21 +140,6 @@ void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr)
140140
}
141141
EXPORT_SYMBOL_GPL(mt76x02_tx_set_txpwr_auto);
142142

143-
void mt76x02_tx_complete(struct mt76_dev *dev, struct sk_buff *skb)
144-
{
145-
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
146-
147-
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
148-
ieee80211_free_txskb(dev->hw, skb);
149-
} else {
150-
ieee80211_tx_info_clear_status(info);
151-
info->status.rates[0].idx = -1;
152-
info->flags |= IEEE80211_TX_STAT_ACK;
153-
ieee80211_tx_status(dev->hw, skb);
154-
}
155-
}
156-
EXPORT_SYMBOL_GPL(mt76x02_tx_complete);
157-
158143
bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update)
159144
{
160145
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
@@ -169,26 +154,30 @@ bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update)
169154
}
170155
EXPORT_SYMBOL_GPL(mt76x02_tx_status_data);
171156

172-
int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
157+
int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
173158
struct sk_buff *skb, struct mt76_queue *q,
174159
struct mt76_wcid *wcid, struct ieee80211_sta *sta,
175160
u32 *tx_info)
176161
{
177162
struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76);
178-
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
163+
struct mt76x02_txwi *txwi = txwi_ptr;
179164
int qsel = MT_QSEL_EDCA;
165+
int pid;
180166
int ret;
181167

182168
if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128)
183169
mt76x02_mac_wcid_set_drop(dev, wcid->idx, false);
184170

185171
mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, skb->len);
186172

173+
pid = mt76_tx_status_skb_add(mdev, wcid, skb);
174+
txwi->pktid = pid;
175+
187176
ret = mt76x02_insert_hdr_pad(skb);
188177
if (ret < 0)
189178
return ret;
190179

191-
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
180+
if (pid && pid != MT_PACKET_ID_NO_ACK)
192181
qsel = MT_QSEL_MGMT;
193182

194183
*tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) |

0 commit comments

Comments
 (0)