Commit 3688c18b authored by Felix Fietkau's avatar Felix Fietkau
Browse files

wifi: mt76: mt7915: retry mcu messages

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: default avatarFelix Fietkau <nbd@nbd.name>
parent 8351a4a4
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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,
+2 −5
Original line number Diff line number Diff line
@@ -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,
	};