]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mt76: do not increase mcu skb refcount if retry is not supported
authorFelix Fietkau <nbd@nbd.name>
Tue, 17 Sep 2024 11:09:42 +0000 (13:09 +0200)
committerKalle Valo <kvalo@kernel.org>
Wed, 18 Sep 2024 13:34:00 +0000 (16:34 +0300)
If mcu_skb_prepare_msg is not implemented, incrementing skb refcount does not
work for mcu message retry. In some cases (e.g. on SDIO), shared skbs can trigger
a BUG_ON, crashing the system.
Fix this by only incrementing refcount if retry is actually supported.

Fixes: 3688c18b65ae ("wifi: mt76: mt7915: retry mcu messages")
Closes: https://lore.kernel.org/r/d907b13a-f8be-4cb8-a0bb-560a21278041@notapiano/
Reported-by: NĂ­colas F. R. A. Prado <nfraprado@collabora.com> #KernelCI
Tested-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://patch.msgid.link/20240917110942.22077-1-nbd@nbd.name
drivers/net/wireless/mediatek/mt76/mcu.c

index 98da82b74094ddd09397cb6644464a2e75bebdb8..3353012e8542984a081c863707cccb915d4a1504 100644 (file)
@@ -84,13 +84,16 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
        mutex_lock(&dev->mcu.mutex);
 
        if (dev->mcu_ops->mcu_skb_prepare_msg) {
+               orig_skb = skb;
                ret = dev->mcu_ops->mcu_skb_prepare_msg(dev, skb, cmd, &seq);
                if (ret < 0)
                        goto out;
        }
 
 retry:
-       orig_skb = skb_get(skb);
+       /* orig skb might be needed for retry, mcu_skb_send_msg consumes it */
+       if (orig_skb)
+               skb_get(orig_skb);
        ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);
        if (ret < 0)
                goto out;
@@ -105,7 +108,7 @@ retry:
        do {
                skb = mt76_mcu_get_response(dev, expires);
                if (!skb && !test_bit(MT76_MCU_RESET, &dev->phy.state) &&
-                   retry++ < dev->mcu_ops->max_retry) {
+                   orig_skb && retry++ < dev->mcu_ops->max_retry) {
                        dev_err(dev->dev, "Retry message %08x (seq %d)\n",
                                cmd, seq);
                        skb = orig_skb;