All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] mt76: fix rx amsdu subframe processing
@ 2021-04-07  8:13 Felix Fietkau
  0 siblings, 0 replies; only message in thread
From: Felix Fietkau @ 2021-04-07  8:13 UTC (permalink / raw)
  To: linux-wireless

When receiving an A-MSDU containing only a single subframe, status->last_amsdu
is set, but no previous head is present in the rx A-MSDU queue.
In this case, the A-MSDU subframe will be held until the next one is received,
potentially causing significant extra latency.
Rework the code to make it easier to read and less convoluted, and release the
newly created head if status->last_amsdu is set.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/mediatek/mt76/mac80211.c | 47 ++++++++-----------
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 7684a8cf00fb..ef31026ac9d7 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -508,44 +508,37 @@ void mt76_free_device(struct mt76_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt76_free_device);
 
+static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
+{
+	struct sk_buff *skb = phy->rx_amsdu[q].head;
+	struct mt76_dev *dev = phy->dev;
+
+	phy->rx_amsdu[q].head = NULL;
+	phy->rx_amsdu[q].tail = NULL;
+	__skb_queue_tail(&dev->rx_skb[q], skb);
+}
+
 static void mt76_rx_release_burst(struct mt76_phy *phy, enum mt76_rxq_id q,
 				  struct sk_buff *skb)
 {
 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
-	struct sk_buff *nskb = phy->rx_amsdu[q].head;
-	struct mt76_dev *dev = phy->dev;
 
-	/* first amsdu subframe */
-	if (status->amsdu && !phy->rx_amsdu[q].head) {
+	if (phy->rx_amsdu[q].head &&
+	    (!status->amsdu || status->first_amsdu ||
+	     status->seqno != phy->rx_amsdu[q].seqno))
+		mt76_rx_release_amsdu(phy, q);
+
+	if (!phy->rx_amsdu[q].head) {
 		phy->rx_amsdu[q].tail = &skb_shinfo(skb)->frag_list;
 		phy->rx_amsdu[q].seqno = status->seqno;
 		phy->rx_amsdu[q].head = skb;
-		goto enqueue;
-	}
-
-	/* ampdu or out-of-order amsdu subframes */
-	if (!status->amsdu || status->seqno != phy->rx_amsdu[q].seqno) {
-		/* release pending frames */
-		if (phy->rx_amsdu[q].head)
-			__skb_queue_tail(&dev->rx_skb[q],
-					 phy->rx_amsdu[q].head);
-		nskb = skb;
-		goto reset_burst;
-	}
-
-	/* trailing amsdu subframes */
-	*phy->rx_amsdu[q].tail = skb;
-	if (!status->last_amsdu) {
+	} else {
+		*phy->rx_amsdu[q].tail = skb;
 		phy->rx_amsdu[q].tail = &skb->next;
-		return;
 	}
 
-reset_burst:
-	phy->rx_amsdu[q].head = NULL;
-	phy->rx_amsdu[q].tail = NULL;
-enqueue:
-	if (nskb)
-		__skb_queue_tail(&dev->rx_skb[q], nskb);
+	if (!status->amsdu || status->last_amsdu)
+		mt76_rx_release_amsdu(phy, q);
 }
 
 void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
-- 
2.30.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2021-04-07  8:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-07  8:13 [PATCH v2] mt76: fix rx amsdu subframe processing Felix Fietkau

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.