wifi: mt76: mt7915: retry mcu messages
authorFelix Fietkau <nbd@nbd.name>
Tue, 27 Aug 2024 09:30:01 +0000 (11:30 +0200)
committerFelix Fietkau <nbd@nbd.name>
Fri, 6 Sep 2024 12:23:06 +0000 (14:23 +0200)
In some cases MCU messages can get lost. Instead of failing completely,
attempt to recover by re-sending them.

Link: https://patch.msgid.link/20240827093011.18621-14-nbd@nbd.name
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mcu.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c

index a8cafa39a56ddab5df94f1017426047bc81691c1..98da82b74094ddd09397cb6644464a2e75bebdb8 100644 (file)
@@ -73,6 +73,8 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
                                  int cmd, bool wait_resp,
                                  struct sk_buff **ret_skb)
 {
+       unsigned int retry = 0;
+       struct sk_buff *orig_skb = NULL;
        unsigned long expires;
        int ret, seq;
 
@@ -81,6 +83,14 @@ 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) {
+               ret = dev->mcu_ops->mcu_skb_prepare_msg(dev, skb, cmd, &seq);
+               if (ret < 0)
+                       goto out;
+       }
+
+retry:
+       orig_skb = skb_get(skb);
        ret = dev->mcu_ops->mcu_skb_send_msg(dev, skb, cmd, &seq);
        if (ret < 0)
                goto out;
@@ -94,6 +104,14 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
 
        do {
                skb = mt76_mcu_get_response(dev, expires);
+               if (!skb && !test_bit(MT76_MCU_RESET, &dev->phy.state) &&
+                   retry++ < dev->mcu_ops->max_retry) {
+                       dev_err(dev->dev, "Retry message %08x (seq %d)\n",
+                               cmd, seq);
+                       skb = orig_skb;
+                       goto retry;
+               }
+
                ret = dev->mcu_ops->mcu_parse_response(dev, cmd, skb, seq);
                if (!ret && ret_skb)
                        *ret_skb = skb;
@@ -101,7 +119,9 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
                        dev_kfree_skb(skb);
        } while (ret == -EAGAIN);
 
+
 out:
+       dev_kfree_skb(orig_skb);
        mutex_unlock(&dev->mcu.mutex);
 
        return ret;
index 43e743b510ba6cabca86db821517e1eb9228d8b4..794cd33be68bd64c1759f9faf9f3e2f259fc278a 100644 (file)
@@ -230,11 +230,14 @@ struct mt76_queue {
 };
 
 struct mt76_mcu_ops {
+       unsigned int max_retry;
        u32 headroom;
        u32 tailroom;
 
        int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data,
                            int len, bool wait_resp);
+       int (*mcu_skb_prepare_msg)(struct mt76_dev *dev, struct sk_buff *skb,
+                                  int cmd, int *seq);
        int (*mcu_skb_send_msg)(struct mt76_dev *dev, struct sk_buff *skb,
                                int cmd, int *seq);
        int (*mcu_parse_response)(struct mt76_dev *dev, int cmd,
index 2ef8d90132ddae2660e944076bf89c8087e6ef07..0cde1b3c7d41636f9f8073b81a2c36de8fda563f 100644 (file)
@@ -191,11 +191,6 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
 {
        struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
        enum mt76_mcuq_id qid;
-       int ret;
-
-       ret = mt76_connac2_mcu_fill_message(mdev, skb, cmd, wait_seq);
-       if (ret)
-               return ret;
 
        if (cmd == MCU_CMD(FW_SCATTER))
                qid = MT_MCUQ_FWDL;
@@ -2382,7 +2377,9 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
 int mt7915_mcu_init(struct mt7915_dev *dev)
 {
        static const struct mt76_mcu_ops mt7915_mcu_ops = {
+               .max_retry = 3,
                .headroom = sizeof(struct mt76_connac2_mcu_txd),
+               .mcu_skb_prepare_msg = mt76_connac2_mcu_fill_message,
                .mcu_skb_send_msg = mt7915_mcu_send_message,
                .mcu_parse_response = mt7915_mcu_parse_response,
        };