* [PATCH 1/2] wifi: mt76: mt7615: fix lost first mcu event on mt7622
2026-10-25 12:32 [PATCH 0/2] wifi: mt76: mt7615: fix mt7622 wmac init Francesco Palmarini via B4 Relay
@ 2026-10-25 12:32 ` Francesco Palmarini via B4 Relay
2026-10-25 12:32 ` [PATCH 2/2] wifi: mt76: mt7615: release patch semaphore on timeout Francesco Palmarini via B4 Relay
1 sibling, 0 replies; 3+ messages in thread
From: Francesco Palmarini via B4 Relay @ 2026-10-25 12:32 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee
Cc: Shayne Chen, Sean Wang, linux-wireless, linux-mediatek,
Francesco Palmarini
From: Francesco Palmarini <palmarini@unive.it>
On MT7622 the 2.4 GHz wmac fails to initialize on most boots:
mt7622-wmac 18000000.wmac: Message 00000010 (seq 1) timeout
mt7622-wmac 18000000.wmac: Failed to get patch semaphore
The rom actually replies to the first PATCH_SEM_CONTROL command and
grants the semaphore, but the event shows up on the data ring with an
extra zero dword in front of it:
00000000 e000001c 00000000 00000000
00000000 e000000c 00000104 00000002
Since RXD0 is zero, mt7615_rx_check() handles it as tx status and the
event is dropped. The command times out and all the retries in
mt7615_pci_init_work() fail because the semaphore is already taken.
Detect the shifted event while the mcu is not running yet and strip the
extra dword.
Tested on Xiaomi AX3200 (same hw as Redmi AX6S).
Signed-off-by: Francesco Palmarini <palmarini@unive.it>
---
drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
index aad232c5a..54c70a427 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -1590,6 +1590,21 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
mt76_worker_schedule(&dev->mt76.tx_worker);
}
+static bool
+mt7615_mac_rx_shifted_event(struct mt7615_dev *dev, __le32 *rxd, int len)
+{
+ /* mt7622 rom can report the first mcu event on the data ring,
+ * with an extra dword in front of it
+ */
+ if (!is_mt7622(&dev->mt76) ||
+ test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
+ return false;
+
+ return len >= 8 && !rxd[0] &&
+ le32_get_bits(rxd[1], MT_RXD0_PKT_TYPE) == PKT_TYPE_RX_EVENT &&
+ le32_get_bits(rxd[1], MT_RXD0_LENGTH) == len - 4;
+}
+
bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
@@ -1597,6 +1612,9 @@ bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len)
__le32 *end = (__le32 *)&rxd[len / 4];
enum rx_pkt_type type;
+ if (mt7615_mac_rx_shifted_event(dev, rxd, len))
+ return true;
+
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
switch (type) {
@@ -1624,6 +1642,11 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
enum rx_pkt_type type;
u16 flag;
+ if (mt7615_mac_rx_shifted_event(dev, rxd, skb->len)) {
+ skb_pull(skb, 4);
+ rxd = (__le32 *)skb->data;
+ }
+
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);
if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
--
2.39.5
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 2/2] wifi: mt76: mt7615: release patch semaphore on timeout
2026-10-25 12:32 [PATCH 0/2] wifi: mt76: mt7615: fix mt7622 wmac init Francesco Palmarini via B4 Relay
2026-10-25 12:32 ` [PATCH 1/2] wifi: mt76: mt7615: fix lost first mcu event on mt7622 Francesco Palmarini via B4 Relay
@ 2026-10-25 12:32 ` Francesco Palmarini via B4 Relay
1 sibling, 0 replies; 3+ messages in thread
From: Francesco Palmarini via B4 Relay @ 2026-10-25 12:32 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee
Cc: Shayne Chen, Sean Wang, linux-wireless, linux-mediatek,
Francesco Palmarini
From: Francesco Palmarini <palmarini@unive.it>
If the PATCH_SEM_CONTROL reply gets lost, the rom may still have granted
the semaphore and every following attempt fails with
PATCH_NOT_DL_SEM_FAIL. Release it on timeout so the next retry can get
it again.
Signed-off-by: Francesco Palmarini <palmarini@unive.it>
---
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index aab4303fe..5f5e29f49 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -1259,6 +1259,10 @@ static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)
goto release_fw;
case PATCH_NOT_DL_SEM_SUCCESS:
break;
+ case -ETIMEDOUT:
+ /* rom might have granted the semaphore anyway */
+ mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
+ fallthrough;
default:
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
ret = -EAGAIN;
--
2.39.5
^ permalink raw reply related [flat|nested] 3+ messages in thread