CHROMIUM: rtw88: throw a warning when skb headroom is not enough

The driver does report hw->extra_tx_headroom to the mac80211 stack,
but after dequeue from the mac80211 TXQ some of the skbs don't have
the headroom the driver asked for.

Warn once if the problem is seen on dequeue and allocate sufficient
headroom to avoid the subsequent crash.

Note: This code will still crash if the skb is completely corrupted.

BUG=b:162617454
TEST=Run on affected systems

Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
Change-Id: I34b0d5b18ac025c1c4edfe66570586c58eced3ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2478103
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 7f8f683..0fe1938 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -519,12 +519,33 @@
 static struct sk_buff *rtw_txq_dequeue(struct rtw_dev *rtwdev,
 				       struct rtw_txq *rtwtxq)
 {
+	struct rtw_chip_info *chip = rtwdev->chip;
 	struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
 	struct sk_buff *skb;
+	int headroom_needed;
 
-	skb = ieee80211_tx_dequeue(rtwdev->hw, txq);
-	if (!skb)
-		return NULL;
+	do {
+		skb = ieee80211_tx_dequeue(rtwdev->hw, txq);
+		if (!skb)
+			return NULL;
+
+		headroom_needed = chip->tx_pkt_desc_sz - skb_headroom(skb);
+		if (WARN_ONCE(headroom_needed > 0,
+			      "Insufficient headroom (%d bytes, need %d)\n",
+			      skb_headroom(skb), chip->tx_pkt_desc_sz)) {
+			if (skb_cloned(skb)) {
+				netdev_warn(skb->dev, "skb is cloned\n");
+				skb = skb_unshare(skb, GFP_ATOMIC);
+				if (!skb)
+					continue;
+				headroom_needed = chip->tx_pkt_desc_sz - skb_headroom(skb);
+			}
+			if (pskb_expand_head(skb, headroom_needed, 0, GFP_ATOMIC) < 0) {
+				kfree_skb(skb);
+				continue;
+			}
+		}
+	} while (!skb);
 
 	return skb;
 }