]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Jul 2021 13:09:50 +0000 (15:09 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Jul 2021 13:09:50 +0000 (15:09 +0200)
added patches:
mt76-dma-export-mt76_dma_rx_cleanup-routine.patch
mt76-dma-introduce-mt76_dma_queue_reset-routine.patch
mt76-mt7921-abort-uncompleted-scan-by-wifi-reset.patch
mt76-mt7921-add-wifi-reset-support.patch
mt76-mt7921-check-mcu-returned-values-in-mt7921_start.patch
mt76-mt7921-get-rid-of-mcu_reset-function-pointer.patch
mt76-mt7921-introduce-__mt7921_start-utility-routine.patch
mt76-mt7921-introduce-mt7921_run_firmware-utility-routine.patch

queue-5.12/mt76-dma-export-mt76_dma_rx_cleanup-routine.patch [new file with mode: 0644]
queue-5.12/mt76-dma-introduce-mt76_dma_queue_reset-routine.patch [new file with mode: 0644]
queue-5.12/mt76-mt7921-abort-uncompleted-scan-by-wifi-reset.patch [new file with mode: 0644]
queue-5.12/mt76-mt7921-add-wifi-reset-support.patch [new file with mode: 0644]
queue-5.12/mt76-mt7921-check-mcu-returned-values-in-mt7921_start.patch [new file with mode: 0644]
queue-5.12/mt76-mt7921-get-rid-of-mcu_reset-function-pointer.patch [new file with mode: 0644]
queue-5.12/mt76-mt7921-introduce-__mt7921_start-utility-routine.patch [new file with mode: 0644]
queue-5.12/mt76-mt7921-introduce-mt7921_run_firmware-utility-routine.patch [new file with mode: 0644]
queue-5.12/series

diff --git a/queue-5.12/mt76-dma-export-mt76_dma_rx_cleanup-routine.patch b/queue-5.12/mt76-dma-export-mt76_dma_rx_cleanup-routine.patch
new file mode 100644 (file)
index 0000000..117649d
--- /dev/null
@@ -0,0 +1,55 @@
+From c001df978e4cb88975147ddd2c829c9e12a55076 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sun, 7 Mar 2021 19:20:50 +0100
+Subject: mt76: dma: export mt76_dma_rx_cleanup routine
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit c001df978e4cb88975147ddd2c829c9e12a55076 upstream.
+
+Export mt76_dma_rx_cleanup routine in mt76_queue_ops data structure.
+This is a preliminary patch to introduce mt7921 chip reset support.
+
+Co-developed-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/dma.c  |    1 +
+ drivers/net/wireless/mediatek/mt76/mt76.h |    5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/dma.c
+@@ -653,6 +653,7 @@ static const struct mt76_queue_ops mt76_
+       .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
+       .tx_queue_skb = mt76_dma_tx_queue_skb,
+       .tx_cleanup = mt76_dma_tx_cleanup,
++      .rx_cleanup = mt76_dma_rx_cleanup,
+       .rx_reset = mt76_dma_rx_reset,
+       .kick = mt76_dma_kick_queue,
+ };
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -190,6 +190,8 @@ struct mt76_queue_ops {
+       void (*tx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q,
+                          bool flush);
++      void (*rx_cleanup)(struct mt76_dev *dev, struct mt76_queue *q);
++
+       void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
+       void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
+@@ -786,7 +788,8 @@ static inline u16 mt76_rev(struct mt76_d
+ #define mt76_tx_queue_skb_raw(dev, ...)       (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_tx_queue_skb(dev, ...)   (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
+-#define mt76_queue_tx_cleanup(dev, ...)        (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
++#define mt76_queue_tx_cleanup(dev, ...)       (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
++#define mt76_queue_rx_cleanup(dev, ...)       (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_queue_kick(dev, ...)     (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_queue_reset(dev, ...)    (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__)
diff --git a/queue-5.12/mt76-dma-introduce-mt76_dma_queue_reset-routine.patch b/queue-5.12/mt76-dma-introduce-mt76_dma_queue_reset-routine.patch
new file mode 100644 (file)
index 0000000..8ad6c39
--- /dev/null
@@ -0,0 +1,126 @@
+From 3990465db6829c91e8ebfde51ba2d98885020249 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sun, 7 Mar 2021 19:20:49 +0100
+Subject: mt76: dma: introduce mt76_dma_queue_reset routine
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit 3990465db6829c91e8ebfde51ba2d98885020249 upstream.
+
+Introduce mt76_dma_queue_reset utility routine to reset a given hw
+queue. This is a preliminary patch to introduce mt7921 chip reset
+support.
+
+Co-developed-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/dma.c  |   46 ++++++++++++++++++------------
+ drivers/net/wireless/mediatek/mt76/mt76.h |    3 +
+ 2 files changed, 31 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/dma.c
+@@ -79,13 +79,38 @@ mt76_free_pending_txwi(struct mt76_dev *
+       local_bh_enable();
+ }
++static void
++mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
++{
++      writel(q->desc_dma, &q->regs->desc_base);
++      writel(q->ndesc, &q->regs->ring_size);
++      q->head = readl(&q->regs->dma_idx);
++      q->tail = q->head;
++}
++
++static void
++mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
++{
++      int i;
++
++      if (!q)
++              return;
++
++      /* clear descriptors */
++      for (i = 0; i < q->ndesc; i++)
++              q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
++
++      writel(0, &q->regs->cpu_idx);
++      writel(0, &q->regs->dma_idx);
++      mt76_dma_sync_idx(dev, q);
++}
++
+ static int
+ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+                    int idx, int n_desc, int bufsize,
+                    u32 ring_base)
+ {
+       int size;
+-      int i;
+       spin_lock_init(&q->lock);
+       spin_lock_init(&q->cleanup_lock);
+@@ -105,14 +130,7 @@ mt76_dma_alloc_queue(struct mt76_dev *de
+       if (!q->entry)
+               return -ENOMEM;
+-      /* clear descriptors */
+-      for (i = 0; i < q->ndesc; i++)
+-              q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
+-
+-      writel(q->desc_dma, &q->regs->desc_base);
+-      writel(0, &q->regs->cpu_idx);
+-      writel(0, &q->regs->dma_idx);
+-      writel(q->ndesc, &q->regs->ring_size);
++      mt76_dma_queue_reset(dev, q);
+       return 0;
+ }
+@@ -202,15 +220,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev
+ }
+ static void
+-mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
+-{
+-      writel(q->desc_dma, &q->regs->desc_base);
+-      writel(q->ndesc, &q->regs->ring_size);
+-      q->head = readl(&q->regs->dma_idx);
+-      q->tail = q->head;
+-}
+-
+-static void
+ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
+ {
+       wmb();
+@@ -640,6 +649,7 @@ mt76_dma_init(struct mt76_dev *dev)
+ static const struct mt76_queue_ops mt76_dma_ops = {
+       .init = mt76_dma_init,
+       .alloc = mt76_dma_alloc_queue,
++      .reset_q = mt76_dma_queue_reset,
+       .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw,
+       .tx_queue_skb = mt76_dma_tx_queue_skb,
+       .tx_cleanup = mt76_dma_tx_cleanup,
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -191,6 +191,8 @@ struct mt76_queue_ops {
+                          bool flush);
+       void (*kick)(struct mt76_dev *dev, struct mt76_queue *q);
++
++      void (*reset_q)(struct mt76_dev *dev, struct mt76_queue *q);
+ };
+ enum mt76_wcid_flags {
+@@ -786,6 +788,7 @@ static inline u16 mt76_rev(struct mt76_d
+ #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_queue_tx_cleanup(dev, ...)        (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_queue_kick(dev, ...)     (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
++#define mt76_queue_reset(dev, ...)    (dev)->mt76.queue_ops->reset_q(&((dev)->mt76), __VA_ARGS__)
+ #define mt76_for_each_q_rx(dev, i)    \
+       for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \
diff --git a/queue-5.12/mt76-mt7921-abort-uncompleted-scan-by-wifi-reset.patch b/queue-5.12/mt76-mt7921-abort-uncompleted-scan-by-wifi-reset.patch
new file mode 100644 (file)
index 0000000..e97be70
--- /dev/null
@@ -0,0 +1,41 @@
+From e513ae49088bbb0d00299a9f996f88f08cca7dc6 Mon Sep 17 00:00:00 2001
+From: Sean Wang <sean.wang@mediatek.com>
+Date: Fri, 16 Apr 2021 23:30:36 +0800
+Subject: mt76: mt7921: abort uncompleted scan by wifi reset
+
+From: Sean Wang <sean.wang@mediatek.com>
+
+commit e513ae49088bbb0d00299a9f996f88f08cca7dc6 upstream.
+
+Scan abort should be required for the uncompleted hardware scan
+interrupted by wifi reset. Otherwise, it is possible that the scan
+request after wifi reset gets error code -EBUSY from mac80211 and
+then blocks the reconnectting to the access point.
+
+Fixes: 0c1ce9884607 ("mt76: mt7921: add wifi reset support")
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mac.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -1386,6 +1386,14 @@ void mt7921_mac_reset_work(struct work_s
+       if (i == 10)
+               dev_err(dev->mt76.dev, "chip reset failed\n");
++      if (test_and_clear_bit(MT76_HW_SCANNING, &dev->mphy.state)) {
++              struct cfg80211_scan_info info = {
++                      .aborted = true,
++              };
++
++              ieee80211_scan_completed(dev->mphy.hw, &info);
++      }
++
+       ieee80211_wake_queues(hw);
+       ieee80211_iterate_active_interfaces(hw,
+                                           IEEE80211_IFACE_ITER_RESUME_ALL,
diff --git a/queue-5.12/mt76-mt7921-add-wifi-reset-support.patch b/queue-5.12/mt76-mt7921-add-wifi-reset-support.patch
new file mode 100644 (file)
index 0000000..13de452
--- /dev/null
@@ -0,0 +1,381 @@
+From 0c1ce988460765ece1ba8eacd00533eefb6e666a Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sun, 7 Mar 2021 19:20:51 +0100
+Subject: mt76: mt7921: add wifi reset support
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit 0c1ce988460765ece1ba8eacd00533eefb6e666a upstream.
+
+Introduce wifi chip reset support for mt7921 device to recover mcu
+hangs.
+
+Co-developed-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/init.c   |    3 
+ drivers/net/wireless/mediatek/mt76/mt7921/mac.c    |  203 +++++++++++++++------
+ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c    |    3 
+ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |    4 
+ drivers/net/wireless/mediatek/mt76/mt7921/regs.h   |    4 
+ 5 files changed, 156 insertions(+), 61 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+@@ -142,7 +142,7 @@ mt7921_mac_init_band(struct mt7921_dev *
+       mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
+ }
+-static void mt7921_mac_init(struct mt7921_dev *dev)
++void mt7921_mac_init(struct mt7921_dev *dev)
+ {
+       int i;
+@@ -232,7 +232,6 @@ int mt7921_register_device(struct mt7921
+       INIT_LIST_HEAD(&dev->sta_poll_list);
+       spin_lock_init(&dev->sta_poll_lock);
+-      init_waitqueue_head(&dev->reset_wait);
+       INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
+       ret = mt7921_init_hardware(dev);
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+@@ -1184,43 +1184,77 @@ void mt7921_update_channel(struct mt76_d
+       mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
+ }
+-static bool
+-mt7921_wait_reset_state(struct mt7921_dev *dev, u32 state)
++static int
++mt7921_wfsys_reset(struct mt7921_dev *dev)
+ {
+-      bool ret;
++      mt76_set(dev, 0x70002600, BIT(0));
++      msleep(200);
++      mt76_clear(dev, 0x70002600, BIT(0));
+-      ret = wait_event_timeout(dev->reset_wait,
+-                               (READ_ONCE(dev->reset_state) & state),
+-                               MT7921_RESET_TIMEOUT);
+-
+-      WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
+-      return ret;
++      return __mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B,
++                              WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500);
+ }
+ static void
+-mt7921_dma_reset(struct mt7921_phy *phy)
++mt7921_dma_reset(struct mt7921_dev *dev)
+ {
+-      struct mt7921_dev *dev = phy->dev;
+       int i;
+-      mt76_clear(dev, MT_WFDMA0_GLO_CFG,
+-                 MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++      /* reset */
++      mt76_clear(dev, MT_WFDMA0_RST,
++                 MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST);
++
++      mt76_set(dev, MT_WFDMA0_RST,
++               MT_WFDMA0_RST_DMASHDL_ALL_RST | MT_WFDMA0_RST_LOGIC_RST);
+-      usleep_range(1000, 2000);
++      /* disable WFDMA0 */
++      mt76_clear(dev, MT_WFDMA0_GLO_CFG,
++                 MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN |
++                 MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
++                 MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++                 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
++                 MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++
++      mt76_poll(dev, MT_WFDMA0_GLO_CFG,
++                MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
++                MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
+-      mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true);
++      /* reset hw queues */
+       for (i = 0; i < __MT_TXQ_MAX; i++)
+-              mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true);
++              mt76_queue_reset(dev, dev->mphy.q_tx[i]);
+-      mt76_for_each_q_rx(&dev->mt76, i) {
+-              mt76_queue_rx_reset(dev, i);
+-      }
++      for (i = 0; i < __MT_MCUQ_MAX; i++)
++              mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
+-      /* re-init prefetch settings after reset */
++      mt76_for_each_q_rx(&dev->mt76, i)
++              mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
++
++      /* configure perfetch settings */
+       mt7921_dma_prefetch(dev);
++      /* reset dma idx */
++      mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
++
++      /* configure delay interrupt */
++      mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
++
++      mt76_set(dev, MT_WFDMA0_GLO_CFG,
++               MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
++               MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
++               MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
++               MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++               MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
++               MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++
+       mt76_set(dev, MT_WFDMA0_GLO_CFG,
+                MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++
++      mt76_set(dev, 0x54000120, BIT(1));
++
++      /* enable interrupts for TX/RX rings */
++      mt7921_irq_enable(dev,
++                        MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
++                        MT_INT_MCU_CMD);
+ }
+ void mt7921_tx_token_put(struct mt7921_dev *dev)
+@@ -1244,71 +1278,125 @@ void mt7921_tx_token_put(struct mt7921_d
+       idr_destroy(&dev->token);
+ }
+-/* system error recovery */
+-void mt7921_mac_reset_work(struct work_struct *work)
++static void
++mt7921_vif_connect_iter(void *priv, u8 *mac,
++                      struct ieee80211_vif *vif)
+ {
+-      struct mt7921_dev *dev;
++      struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
++      struct mt7921_dev *dev = mvif->phy->dev;
+-      dev = container_of(work, struct mt7921_dev, reset_work);
++      ieee80211_disconnect(vif, true);
+-      if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
+-              return;
++      mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, true);
++      mt7921_mcu_set_tx(dev, vif);
++}
++
++static int
++mt7921_mac_reset(struct mt7921_dev *dev)
++{
++      int i, err;
+-      ieee80211_stop_queues(mt76_hw(dev));
++      mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
++
++      mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
++      mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
+-      set_bit(MT76_RESET, &dev->mphy.state);
+       set_bit(MT76_MCU_RESET, &dev->mphy.state);
+       wake_up(&dev->mt76.mcu.wait);
+-      cancel_delayed_work_sync(&dev->mphy.mac_work);
++      skb_queue_purge(&dev->mt76.mcu.res_q);
+-      /* lock/unlock all queues to ensure that no tx is pending */
+       mt76_txq_schedule_all(&dev->mphy);
+       mt76_worker_disable(&dev->mt76.tx_worker);
+-      napi_disable(&dev->mt76.napi[0]);
+-      napi_disable(&dev->mt76.napi[1]);
+-      napi_disable(&dev->mt76.napi[2]);
++      napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
++      napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
++      napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
+       napi_disable(&dev->mt76.tx_napi);
+-      mt7921_mutex_acquire(dev);
+-
+-      mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
+-
+       mt7921_tx_token_put(dev);
+       idr_init(&dev->token);
+-      if (mt7921_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
+-              mt7921_dma_reset(&dev->phy);
++      /* clean up hw queues */
++      for (i = 0; i < ARRAY_SIZE(dev->mt76.phy.q_tx); i++)
++              mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
+-              mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT);
+-              mt7921_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE);
+-      }
++      for (i = 0; i < ARRAY_SIZE(dev->mt76.q_mcu); i++)
++              mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
+-      clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+-      clear_bit(MT76_RESET, &dev->mphy.state);
++      mt76_for_each_q_rx(&dev->mt76, i)
++              mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
++
++      mt7921_wfsys_reset(dev);
++      mt7921_dma_reset(dev);
++
++      mt76_for_each_q_rx(&dev->mt76, i) {
++              mt76_queue_rx_reset(dev, i);
++              napi_enable(&dev->mt76.napi[i]);
++              napi_schedule(&dev->mt76.napi[i]);
++      }
+-      mt76_worker_enable(&dev->mt76.tx_worker);
+       napi_enable(&dev->mt76.tx_napi);
+       napi_schedule(&dev->mt76.tx_napi);
++      mt76_worker_enable(&dev->mt76.tx_worker);
+-      napi_enable(&dev->mt76.napi[0]);
+-      napi_schedule(&dev->mt76.napi[0]);
++      clear_bit(MT76_MCU_RESET, &dev->mphy.state);
+-      napi_enable(&dev->mt76.napi[1]);
+-      napi_schedule(&dev->mt76.napi[1]);
++      mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
++      mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
++      mt7921_irq_enable(dev,
++                        MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
++                        MT_INT_MCU_CMD);
+-      napi_enable(&dev->mt76.napi[2]);
+-      napi_schedule(&dev->mt76.napi[2]);
++      err = mt7921_run_firmware(dev);
++      if (err)
++              return err;
+-      ieee80211_wake_queues(mt76_hw(dev));
++      err = mt7921_mcu_set_eeprom(dev);
++      if (err)
++              return err;
+-      mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE);
+-      mt7921_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
++      mt7921_mac_init(dev);
++      return __mt7921_start(&dev->phy);
++}
+-      mt7921_mutex_release(dev);
++/* system error recovery */
++void mt7921_mac_reset_work(struct work_struct *work)
++{
++      struct ieee80211_hw *hw;
++      struct mt7921_dev *dev;
++      int i;
+-      ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
+-                                   MT7921_WATCHDOG_TIME);
++      dev = container_of(work, struct mt7921_dev, reset_work);
++      hw = mt76_hw(dev);
++
++      dev_err(dev->mt76.dev, "chip reset\n");
++      ieee80211_stop_queues(hw);
++
++      cancel_delayed_work_sync(&dev->mphy.mac_work);
++      cancel_delayed_work_sync(&dev->pm.ps_work);
++      cancel_work_sync(&dev->pm.wake_work);
++
++      mutex_lock(&dev->mt76.mutex);
++      for (i = 0; i < 10; i++) {
++              if (!mt7921_mac_reset(dev))
++                      break;
++      }
++      mutex_unlock(&dev->mt76.mutex);
++
++      if (i == 10)
++              dev_err(dev->mt76.dev, "chip reset failed\n");
++
++      ieee80211_wake_queues(hw);
++      ieee80211_iterate_active_interfaces(hw,
++                                          IEEE80211_IFACE_ITER_RESUME_ALL,
++                                          mt7921_vif_connect_iter, 0);
++}
++
++void mt7921_reset(struct mt76_dev *mdev)
++{
++      struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
++
++      queue_work(dev->mt76.wq, &dev->reset_work);
+ }
+ static void
+@@ -1505,4 +1593,5 @@ void mt7921_coredump_work(struct work_st
+       }
+       dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
+                     GFP_KERNEL);
++      mt7921_reset(&dev->mt76);
+ }
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+@@ -952,6 +952,7 @@ int mt7921_mcu_init(struct mt7921_dev *d
+               .mcu_skb_send_msg = mt7921_mcu_send_message,
+               .mcu_parse_response = mt7921_mcu_parse_response,
+               .mcu_restart = mt7921_mcu_restart,
++              .mcu_reset = mt7921_reset,
+       };
+       dev->mt76.mcu_ops = &mt7921_mcu_ops;
+@@ -1269,6 +1270,7 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_
+       if (i == MT7921_DRV_OWN_RETRY_COUNT) {
+               dev_err(dev->mt76.dev, "driver own failed\n");
++              mt7921_reset(&dev->mt76);
+               return -EIO;
+       }
+@@ -1295,6 +1297,7 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_d
+       if (i == MT7921_DRV_OWN_RETRY_COUNT) {
+               dev_err(dev->mt76.dev, "firmware own failed\n");
++              mt7921_reset(&dev->mt76);
+               return -EIO;
+       }
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+@@ -151,8 +151,6 @@ struct mt7921_dev {
+       struct work_struct init_work;
+       struct work_struct reset_work;
+-      wait_queue_head_t reset_wait;
+-      u32 reset_state;
+       struct list_head sta_poll_list;
+       spinlock_t sta_poll_lock;
+@@ -283,6 +281,7 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u3
+ #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
+ #define mt7921_l1_clear(dev, addr, val)       mt7921_l1_rmw(dev, addr, val, 0)
++void mt7921_mac_init(struct mt7921_dev *dev);
+ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
+ void mt7921_mac_reset_counters(struct mt7921_phy *phy);
+ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
+@@ -298,6 +297,7 @@ void mt7921_mac_sta_remove(struct mt76_d
+                          struct ieee80211_sta *sta);
+ void mt7921_mac_work(struct work_struct *work);
+ void mt7921_mac_reset_work(struct work_struct *work);
++void mt7921_reset(struct mt76_dev *mdev);
+ int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+                         enum mt76_txq_id qid, struct mt76_wcid *wcid,
+                         struct ieee80211_sta *sta,
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h
+@@ -418,6 +418,10 @@
+ #define PCIE_LPCR_HOST_CLR_OWN                BIT(1)
+ #define PCIE_LPCR_HOST_SET_OWN                BIT(0)
++#define MT_WFSYS_SW_RST_B             0x18000140
++#define WFSYS_SW_RST_B                        BIT(0)
++#define WFSYS_SW_INIT_DONE            BIT(4)
++
+ #define MT_CONN_ON_MISC                       0x7c0600f0
+ #define MT_TOP_MISC2_FW_N9_RDY                GENMASK(1, 0)
diff --git a/queue-5.12/mt76-mt7921-check-mcu-returned-values-in-mt7921_start.patch b/queue-5.12/mt76-mt7921-check-mcu-returned-values-in-mt7921_start.patch
new file mode 100644 (file)
index 0000000..cce256b
--- /dev/null
@@ -0,0 +1,60 @@
+From f92f81d35ac26f8a519866f1b561743fe70e33a5 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 26 Feb 2021 12:17:23 +0100
+Subject: mt76: mt7921: check mcu returned values in mt7921_start
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit f92f81d35ac26f8a519866f1b561743fe70e33a5 upstream.
+
+Properly check returned values from mcu utility routines in
+mt7921_start.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/main.c |   19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+@@ -172,22 +172,31 @@ static int mt7921_start(struct ieee80211
+ {
+       struct mt7921_dev *dev = mt7921_hw_dev(hw);
+       struct mt7921_phy *phy = mt7921_hw_phy(hw);
++      int err;
+       mt7921_mutex_acquire(dev);
+-      mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
+-      mt76_connac_mcu_set_channel_domain(phy->mt76);
++      err = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
++      if (err)
++              goto out;
++
++      err = mt76_connac_mcu_set_channel_domain(phy->mt76);
++      if (err)
++              goto out;
++
++      err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
++      if (err)
++              goto out;
+-      mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
+       mt7921_mac_reset_counters(phy);
+       set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+       ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+                                    MT7921_WATCHDOG_TIME);
+-
++out:
+       mt7921_mutex_release(dev);
+-      return 0;
++      return err;
+ }
+ static void mt7921_stop(struct ieee80211_hw *hw)
diff --git a/queue-5.12/mt76-mt7921-get-rid-of-mcu_reset-function-pointer.patch b/queue-5.12/mt76-mt7921-get-rid-of-mcu_reset-function-pointer.patch
new file mode 100644 (file)
index 0000000..662a2af
--- /dev/null
@@ -0,0 +1,48 @@
+From d43b3257621dfe57c71d875afd3f624b9a042fc5 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Wed, 21 Apr 2021 12:28:33 +0200
+Subject: mt76: mt7921: get rid of mcu_reset function pointer
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit d43b3257621dfe57c71d875afd3f624b9a042fc5 upstream.
+
+since mcu_reset it used only by mt7921, move the reset callback to
+mt7921_mcu_parse_response routine and get rid of the function pointer.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Link: https://lore.kernel.org/linux-wireless/364293ec8609dd254067d8173c1599526ffd662c.1619000828.git.lorenzo@kernel.org/
+Signed-off-by: Deren Wu <deren.wu@mediatek.com>
+Cc: <stable@vger.kernel.org> # 5.12: f92f81d35ac2 mt76: mt7921: check mcu returned values in mt7921_start
+Cc: <stable@vger.kernel.org> # 5.12: d32464e68ffc mt76: mt7921: introduce mt7921_run_firmware utility routine.
+Cc: <stable@vger.kernel.org> # 5.12: 1f7396acfef4 mt76: mt7921: introduce __mt7921_start utility routine
+Cc: <stable@vger.kernel.org> # 5.12: 3990465db682 mt76: dma: introduce mt76_dma_queue_reset routine
+Cc: <stable@vger.kernel.org> # 5.12: c001df978e4c mt76: dma: export mt76_dma_rx_cleanup routine
+Cc: <stable@vger.kernel.org> # 5.12: 0c1ce9884607 mt76: mt7921: add wifi reset support
+Cc: <stable@vger.kernel.org> # 5.12: e513ae49088b mt76: mt7921: abort uncompleted scan by wifi reset
+Cc: <stable@vger.kernel.org> # 5.12
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+@@ -161,6 +161,8 @@ mt7921_mcu_parse_response(struct mt76_de
+       if (!skb) {
+               dev_err(mdev->dev, "Message %d (seq %d) timeout\n",
+                       cmd, seq);
++              mt7921_reset(mdev);
++
+               return -ETIMEDOUT;
+       }
+@@ -952,7 +954,6 @@ int mt7921_mcu_init(struct mt7921_dev *d
+               .mcu_skb_send_msg = mt7921_mcu_send_message,
+               .mcu_parse_response = mt7921_mcu_parse_response,
+               .mcu_restart = mt7921_mcu_restart,
+-              .mcu_reset = mt7921_reset,
+       };
+       dev->mt76.mcu_ops = &mt7921_mcu_ops;
diff --git a/queue-5.12/mt76-mt7921-introduce-__mt7921_start-utility-routine.patch b/queue-5.12/mt76-mt7921-introduce-__mt7921_start-utility-routine.patch
new file mode 100644 (file)
index 0000000..1f0fd0c
--- /dev/null
@@ -0,0 +1,90 @@
+From 1f7396acfef4691b8cf4a3e631fd3f59d779c0f2 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sun, 7 Mar 2021 19:20:48 +0100
+Subject: mt76: mt7921: introduce __mt7921_start utility routine
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit 1f7396acfef4691b8cf4a3e631fd3f59d779c0f2 upstream.
+
+This is a preliminary patch to introduce mt7921 chip reset support.
+
+Co-developed-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/main.c   |   35 ++++++++++++---------
+ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |    1 
+ 2 files changed, 22 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+@@ -168,33 +168,40 @@ void mt7921_set_stream_he_caps(struct mt
+       }
+ }
+-static int mt7921_start(struct ieee80211_hw *hw)
++int __mt7921_start(struct mt7921_phy *phy)
+ {
+-      struct mt7921_dev *dev = mt7921_hw_dev(hw);
+-      struct mt7921_phy *phy = mt7921_hw_phy(hw);
++      struct mt76_phy *mphy = phy->mt76;
+       int err;
+-      mt7921_mutex_acquire(dev);
+-
+-      err = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
++      err = mt76_connac_mcu_set_mac_enable(mphy->dev, 0, true, false);
+       if (err)
+-              goto out;
++              return err;
+-      err = mt76_connac_mcu_set_channel_domain(phy->mt76);
++      err = mt76_connac_mcu_set_channel_domain(mphy);
+       if (err)
+-              goto out;
++              return err;
+       err = mt7921_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
+       if (err)
+-              goto out;
++              return err;
+       mt7921_mac_reset_counters(phy);
+-      set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
++      set_bit(MT76_STATE_RUNNING, &mphy->state);
+-      ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
++      ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
+                                    MT7921_WATCHDOG_TIME);
+-out:
+-      mt7921_mutex_release(dev);
++
++      return 0;
++}
++
++static int mt7921_start(struct ieee80211_hw *hw)
++{
++      struct mt7921_phy *phy = mt7921_hw_phy(hw);
++      int err;
++
++      mt7921_mutex_acquire(phy->dev);
++      err = __mt7921_start(phy);
++      mt7921_mutex_release(phy->dev);
+       return err;
+ }
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+@@ -209,6 +209,7 @@ extern struct pci_driver mt7921_pci_driv
+ u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
++int __mt7921_start(struct mt7921_phy *phy);
+ int mt7921_register_device(struct mt7921_dev *dev);
+ void mt7921_unregister_device(struct mt7921_dev *dev);
+ int mt7921_eeprom_init(struct mt7921_dev *dev);
diff --git a/queue-5.12/mt76-mt7921-introduce-mt7921_run_firmware-utility-routine.patch b/queue-5.12/mt76-mt7921-introduce-mt7921_run_firmware-utility-routine.patch
new file mode 100644 (file)
index 0000000..d4991d0
--- /dev/null
@@ -0,0 +1,84 @@
+From d32464e68ffc9cbec4960cd06f05bf48b3b3703f Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sun, 7 Mar 2021 19:20:47 +0100
+Subject: mt76: mt7921: introduce mt7921_run_firmware utility routine.
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+commit d32464e68ffc9cbec4960cd06f05bf48b3b3703f upstream.
+
+This is a preliminary patch to introduce chip reset for mt7921 devices.
+
+Co-developed-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Sean Wang <sean.wang@mediatek.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Cc: Deren Wu <Deren.Wu@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/mt7921/mcu.c    |   32 ++++++++++++---------
+ drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |    1 
+ 2 files changed, 20 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+@@ -927,6 +927,24 @@ int mt7921_mcu_fw_log_2_host(struct mt79
+                                sizeof(data), false);
+ }
++int mt7921_run_firmware(struct mt7921_dev *dev)
++{
++      int err;
++
++      err = mt7921_driver_own(dev);
++      if (err)
++              return err;
++
++      err = mt7921_load_firmware(dev);
++      if (err)
++              return err;
++
++      set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
++      mt7921_mcu_fw_log_2_host(dev, 1);
++
++      return 0;
++}
++
+ int mt7921_mcu_init(struct mt7921_dev *dev)
+ {
+       static const struct mt76_mcu_ops mt7921_mcu_ops = {
+@@ -935,22 +953,10 @@ int mt7921_mcu_init(struct mt7921_dev *d
+               .mcu_parse_response = mt7921_mcu_parse_response,
+               .mcu_restart = mt7921_mcu_restart,
+       };
+-      int ret;
+       dev->mt76.mcu_ops = &mt7921_mcu_ops;
+-      ret = mt7921_driver_own(dev);
+-      if (ret)
+-              return ret;
+-
+-      ret = mt7921_load_firmware(dev);
+-      if (ret)
+-              return ret;
+-
+-      set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
+-      mt7921_mcu_fw_log_2_host(dev, 1);
+-
+-      return 0;
++      return mt7921_run_firmware(dev);
+ }
+ void mt7921_mcu_exit(struct mt7921_dev *dev)
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+@@ -220,6 +220,7 @@ void mt7921_eeprom_init_sku(struct mt792
+ int mt7921_dma_init(struct mt7921_dev *dev);
+ void mt7921_dma_prefetch(struct mt7921_dev *dev);
+ void mt7921_dma_cleanup(struct mt7921_dev *dev);
++int mt7921_run_firmware(struct mt7921_dev *dev);
+ int mt7921_mcu_init(struct mt7921_dev *dev);
+ int mt7921_mcu_add_bss_info(struct mt7921_phy *phy,
+                           struct ieee80211_vif *vif, int enable);
index fb1985523c51ffeba39f917e21d8c6f084d3409c..b2e244d666034bc1d95d5961752be961f3c81046 100644 (file)
@@ -1,3 +1,11 @@
 hexagon-fix-build-errors.patch
 hexagon-add-target-builtins-to-kernel.patch
 hexagon-change-jumps-to-must-extend-in-futex_atomic_.patch
+mt76-mt7921-check-mcu-returned-values-in-mt7921_start.patch
+mt76-mt7921-introduce-mt7921_run_firmware-utility-routine.patch
+mt76-mt7921-introduce-__mt7921_start-utility-routine.patch
+mt76-dma-introduce-mt76_dma_queue_reset-routine.patch
+mt76-dma-export-mt76_dma_rx_cleanup-routine.patch
+mt76-mt7921-add-wifi-reset-support.patch
+mt76-mt7921-abort-uncompleted-scan-by-wifi-reset.patch
+mt76-mt7921-get-rid-of-mcu_reset-function-pointer.patch