mt76: mt7921e: process txfree and txstatus without allocating skbs
authorLorenzo Bianconi <lorenzo@kernel.org>
Tue, 28 Dec 2021 12:01:19 +0000 (13:01 +0100)
committerFelix Fietkau <nbd@nbd.name>
Thu, 3 Feb 2022 12:57:58 +0000 (13:57 +0100)
Similar to mt7915 driver, process txfree and txstatus without allocating
skbs in order to reduce pressure on the memory allocator

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7921/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
drivers/net/wireless/mediatek/mt76/mt7921/pci.c
drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c

index b2b8813..defef34 100644 (file)
@@ -1195,6 +1195,7 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
 out:
        rcu_read_unlock();
 }
+EXPORT_SYMBOL_GPL(mt7921_mac_add_txs);
 
 void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
                         struct sk_buff *skb)
index fd93317..8b674e0 100644 (file)
@@ -434,6 +434,7 @@ int mt7921_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
 int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd,
                              struct sk_buff *skb, int seq);
 
+bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len);
 void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
                          struct sk_buff *skb);
 int mt7921e_driver_own(struct mt7921_dev *dev);
index 9dae2f5..1ae0d58 100644 (file)
@@ -134,6 +134,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
                .token_size = MT7921_TOKEN_SIZE,
                .tx_prepare_skb = mt7921e_tx_prepare_skb,
                .tx_complete_skb = mt7921e_tx_complete_skb,
+               .rx_check = mt7921e_rx_check,
                .rx_skb = mt7921e_queue_rx_skb,
                .rx_poll_complete = mt7921_rx_poll_complete,
                .sta_ps = mt7921_sta_ps,
index a63ef5d..8ca5829 100644 (file)
@@ -148,14 +148,15 @@ out:
 }
 
 static void
-mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb)
+mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
 {
-       struct mt7921_tx_free *free = (struct mt7921_tx_free *)skb->data;
+       struct mt7921_tx_free *free = (struct mt7921_tx_free *)data;
        struct mt76_dev *mdev = &dev->mt76;
        struct mt76_txwi_cache *txwi;
        struct ieee80211_sta *sta = NULL;
+       struct sk_buff *skb, *tmp;
+       void *end = data + len;
        LIST_HEAD(free_list);
-       struct sk_buff *tmp;
        bool wake = false;
        u8 i, count;
 
@@ -168,6 +169,9 @@ mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb)
         * Should avoid accessing WTBL to get Tx airtime, and use it instead.
         */
        count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl));
+       if (WARN_ON_ONCE((void *)&free->info[count] > end))
+               return;
+
        for (i = 0; i < count; i++) {
                u32 msdu, info = le32_to_cpu(free->info[i]);
                u8 stat;
@@ -208,8 +212,6 @@ mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb)
        if (wake)
                mt76_set_tx_blocked(&dev->mt76, false);
 
-       napi_consume_skb(skb, 1);
-
        list_for_each_entry_safe(skb, tmp, &free_list, list) {
                skb_list_del_init(skb);
                napi_consume_skb(skb, 1);
@@ -222,6 +224,27 @@ mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb)
        mt76_worker_schedule(&dev->mt76.tx_worker);
 }
 
+bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len)
+{
+       struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
+       __le32 *rxd = (__le32 *)data;
+       __le32 *end = (__le32 *)&rxd[len / 4];
+       enum rx_pkt_type type;
+
+       type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
+       switch (type) {
+       case PKT_TYPE_TXRX_NOTIFY:
+               mt7921e_mac_tx_free(dev, data, len);
+               return false;
+       case PKT_TYPE_TXS:
+               for (rxd += 2; rxd + 8 <= end; rxd += 8)
+                       mt7921_mac_add_txs(dev, rxd);
+               return false;
+       default:
+               return true;
+       }
+}
+
 void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
                          struct sk_buff *skb)
 {
@@ -233,7 +256,8 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
 
        switch (type) {
        case PKT_TYPE_TXRX_NOTIFY:
-               mt7921_mac_tx_free(dev, skb);
+               mt7921e_mac_tx_free(dev, skb->data, skb->len);
+               napi_consume_skb(skb, 1);
                break;
        default:
                mt7921_queue_rx_skb(mdev, q, skb);