mt76: introduce packet_id idr
authorLorenzo Bianconi <lorenzo@kernel.org>
Mon, 13 Sep 2021 09:25:02 +0000 (11:25 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 20 Oct 2021 08:36:47 +0000 (10:36 +0200)
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>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/main.c
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt76x02_util.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/tx.c

index 4ca2c154e046270b81e38369aba922cc43614660..ddc692d7b59e10264d1987f27d3ee9777cecf9ff 100644 (file)
@@ -566,6 +566,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
        spin_lock_init(&dev->token_lock);
        idr_init(&dev->token);
 
+       INIT_LIST_HEAD(&dev->wcid_list);
+
        INIT_LIST_HEAD(&dev->txwi_cache);
 
        for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
@@ -1237,6 +1239,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif,
        wcid->ext_phy = ext_phy;
        rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
 
+       mt76_packet_id_init(wcid);
 out:
        mutex_unlock(&dev->mutex);
 
@@ -1255,7 +1258,8 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
        if (dev->drv->sta_remove)
                dev->drv->sta_remove(dev, vif, sta);
 
-       mt76_tx_status_check(dev, wcid, true);
+       mt76_packet_id_flush(dev, wcid);
+
        mt76_wcid_mask_clear(dev->wcid_mask, idx);
        mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
 }
index aa38ac93b7c37ddd8ac8f16067f34f5a06f1aac9..7bd82cfbf0b550b6d072663993da51627ee875d2 100644 (file)
@@ -261,7 +261,8 @@ struct mt76_wcid {
        u32 tx_info;
        bool sw_iv;
 
-       u8 packet_id;
+       struct list_head list;
+       struct idr pktid;
 };
 
 struct mt76_txq {
@@ -701,6 +702,7 @@ struct mt76_dev {
 
        struct mt76_wcid global_wcid;
        struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
+       struct list_head wcid_list;
 
        u32 rev;
 
@@ -1311,14 +1313,22 @@ mt76_token_put(struct mt76_dev *dev, int token)
        return txwi;
 }
 
-static inline int
-mt76_get_next_pkt_id(struct mt76_wcid *wcid)
+static inline void mt76_packet_id_init(struct mt76_wcid *wcid)
+{
+       INIT_LIST_HEAD(&wcid->list);
+       idr_init(&wcid->pktid);
+}
+
+static inline void
+mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
 {
-       wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK;
-       if (wcid->packet_id == MT_PACKET_ID_NO_ACK ||
-           wcid->packet_id == MT_PACKET_ID_NO_SKB)
-               wcid->packet_id = MT_PACKET_ID_FIRST;
+       struct sk_buff_head list;
 
-       return wcid->packet_id;
+       mt76_tx_status_lock(dev, &list);
+       mt76_tx_status_skb_get(dev, wcid, -1, &list);
+       mt76_tx_status_unlock(dev, &list);
+
+       idr_destroy(&wcid->pktid);
 }
+
 #endif
index 8edea1e7a602f7e0c4a0944672ef01a9fa4e98b2..7ac4cd247a730c23582f76bcea475c846e38ec38 100644 (file)
@@ -69,6 +69,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        INIT_LIST_HEAD(&mvif->sta.poll_list);
        mvif->sta.wcid.idx = idx;
        mvif->sta.wcid.hw_key_idx = -1;
+       mt76_packet_id_init(&mvif->sta.wcid);
 
        eth_broadcast_addr(bc_addr);
        mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
@@ -107,6 +108,8 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        mutex_lock(&dev->mt76.mutex);
        dev->mt76.vif_mask &= ~BIT(mvif->idx);
        mutex_unlock(&dev->mt76.mutex);
+
+       mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
 }
 
 void mt7603_init_edcca(struct mt7603_dev *dev)
index 457e50255250a12d312bd1311456bac141328e18..d5bcffef7122f0d89eac3d218fbacaf187864eb5 100644 (file)
@@ -231,6 +231,8 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
        mvif->sta.wcid.idx = idx;
        mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
        mvif->sta.wcid.hw_key_idx = -1;
+       mt76_packet_id_init(&mvif->sta.wcid);
+
        mt7615_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
@@ -281,6 +283,8 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
        if (!list_empty(&msta->poll_list))
                list_del_init(&msta->poll_list);
        spin_unlock_bh(&dev->sta_poll_lock);
+
+       mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
 }
 
 static void mt7615_init_dfs_state(struct mt7615_phy *phy)
index ccdbab34127146f6860f9146390c078186c24ffc..1f17d86ff755e4508eb602d75f34c6e2b114f7fd 100644 (file)
@@ -287,6 +287,8 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
        mvif->idx = idx;
        mvif->group_wcid.idx = MT_VIF_WCID(idx);
        mvif->group_wcid.hw_key_idx = -1;
+       mt76_packet_id_init(&mvif->group_wcid);
+
        mtxq = (struct mt76_txq *)vif->txq->drv_priv;
        mtxq->wcid = &mvif->group_wcid;
 }
@@ -341,6 +343,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
        struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
 
        dev->mt76.vif_mask &= ~BIT(mvif->idx);
+       mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
 }
 EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
 
index cca94b3b372f9ed822b55466ff3577486bab3156..bdd5f525e621f898316b5cebbc5f41cd35adf86e 100644 (file)
@@ -236,6 +236,8 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
        mvif->sta.wcid.ext_phy = mvif->band_idx;
        mvif->sta.wcid.hw_key_idx = -1;
        mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
+       mt76_packet_id_init(&mvif->sta.wcid);
+
        mt7915_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
@@ -290,6 +292,8 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
        if (!list_empty(&msta->poll_list))
                list_del_init(&msta->poll_list);
        spin_unlock_bh(&dev->sta_poll_lock);
+
+       mt76_packet_id_flush(&dev->mt76, &msta->wcid);
 }
 
 static void mt7915_init_dfs_state(struct mt7915_phy *phy)
index cd3974b6ba8fc9baf19a92de19920b01d5ca73c8..c51266e40cb445fa4529bb580bcb23722036b029 100644 (file)
@@ -304,6 +304,8 @@ static int mt7921_add_interface(struct ieee80211_hw *hw,
        mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
        mvif->sta.wcid.hw_key_idx = -1;
        mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
+       mt76_packet_id_init(&mvif->sta.wcid);
+
        mt7921_mac_wtbl_update(dev, idx,
                               MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
 
@@ -350,6 +352,8 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
        if (!list_empty(&msta->poll_list))
                list_del_init(&msta->poll_list);
        spin_unlock_bh(&dev->sta_poll_lock);
+
+       mt76_packet_id_flush(&dev->mt76, &msta->wcid);
 }
 
 static int mt7921_set_channel(struct mt7921_phy *phy)
index 6f302acb6e691ce6379afec70041d31b8c3fca23..15916f6d9f1b6dd0aa19cc685b3fea7314cb23a6 100644 (file)
@@ -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);