diff options
author | Lorenzo Bianconi <lorenzo@kernel.org> | 2021-09-13 12:25:02 +0300 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2021-10-20 11:36:47 +0300 |
commit | bd1e3e7b693c17a04e7d2bd9119daa482b7c7720 (patch) | |
tree | c28515b327e460349744ff182f9adef7a6db0552 /drivers/net/wireless/mediatek/mt76/tx.c | |
parent | 50ac15a511e3a03d5ade7fad976973560c3d453e (diff) | |
download | linux-bd1e3e7b693c17a04e7d2bd9119daa482b7c7720.tar.xz |
mt76: introduce packet_id idr
Introduce per-wcid idr to manage packet id for txs. This allow fast idr
lookup and skb queueing at the same time.
Tested-by: mrkiko.rs@gmail.com
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/tx.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/tx.c | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 6f302acb6e69..15916f6d9f1b 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -92,8 +92,6 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags, if ((flags & done) != done) return; - __skb_unlink(skb, &dev->status_list); - /* Tx status can be unreliable. if it fails, mark the frame as ACKed */ if (flags & MT_TX_CB_TXS_FAILED) { info->status.rates[0].count = 0; @@ -120,6 +118,8 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); int pid; + memset(cb, 0, sizeof(*cb)); + if (!wcid) return MT_PACKET_ID_NO_ACK; @@ -132,13 +132,21 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, spin_lock_bh(&dev->status_list.lock); - memset(cb, 0, sizeof(*cb)); - pid = mt76_get_next_pkt_id(wcid); + pid = idr_alloc(&wcid->pktid, skb, MT_PACKET_ID_FIRST, + MT_PACKET_ID_MASK, GFP_ATOMIC); + if (pid < 0) { + pid = MT_PACKET_ID_NO_SKB; + goto out; + } + cb->wcid = wcid->idx; cb->pktid = pid; cb->jiffies = jiffies; - __skb_queue_tail(&dev->status_list, skb); + if (list_empty(&wcid->list)) + list_add_tail(&wcid->list, &dev->wcid_list); + +out: spin_unlock_bh(&dev->status_list.lock); return pid; @@ -149,26 +157,38 @@ struct sk_buff * mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, struct sk_buff_head *list) { - struct sk_buff *skb, *tmp; + struct sk_buff *skb; + int id; - skb_queue_walk_safe(&dev->status_list, skb, tmp) { - struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); + lockdep_assert_held(&dev->status_list.lock); - if (wcid && cb->wcid != wcid->idx) - continue; + skb = idr_remove(&wcid->pktid, pktid); + if (skb) + goto out; - if (cb->pktid == pktid) - return skb; + /* look for stale entries in the wcid idr queue */ + idr_for_each_entry(&wcid->pktid, skb, id) { + struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); - if (pktid >= 0 && !time_after(jiffies, cb->jiffies + - MT_TX_STATUS_SKB_TIMEOUT)) - continue; + if (pktid >= 0) { + if (!(cb->flags & MT_TX_CB_DMA_DONE)) + continue; + + if (!time_is_after_jiffies(cb->jiffies + + MT_TX_STATUS_SKB_TIMEOUT)) + continue; + } + idr_remove(&wcid->pktid, cb->pktid); __mt76_tx_status_skb_done(dev, skb, MT_TX_CB_TXS_FAILED | MT_TX_CB_TXS_DONE, list); } - return NULL; +out: + if (idr_is_empty(&wcid->pktid)) + list_del_init(&wcid->list); + + return skb; } EXPORT_SYMBOL_GPL(mt76_tx_status_skb_get); @@ -176,9 +196,11 @@ void mt76_tx_status_check(struct mt76_dev *dev, struct mt76_wcid *wcid, bool flush) { struct sk_buff_head list; + struct mt76_wcid *tmp; mt76_tx_status_lock(dev, &list); - mt76_tx_status_skb_get(dev, wcid, flush ? -1 : 0, &list); + list_for_each_entry_safe(wcid, tmp, &dev->wcid_list, list) + mt76_tx_status_skb_get(dev, wcid, flush ? -1 : 0, &list); mt76_tx_status_unlock(dev, &list); } EXPORT_SYMBOL_GPL(mt76_tx_status_check); @@ -201,6 +223,7 @@ mt76_tx_check_non_aql(struct mt76_dev *dev, struct mt76_wcid *wcid, void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *skb, struct list_head *free_list) { + struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); struct ieee80211_tx_status status = { .skb = skb, .free_list = free_list, @@ -230,7 +253,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff * } #endif - if (!skb->prev) { + if (cb->pktid < MT_PACKET_ID_FIRST) { hw = mt76_tx_status_get_hw(dev, skb); status.sta = wcid_to_sta(wcid); ieee80211_tx_status_ext(hw, &status); |