Introduce mt7915_mmio_wed_reset_complete and mt7915_mmio_wed_reset_complete callbacks and the related wait queues in order to wait for wed reset completion during wlan reset. Tested-by: Daniel Golle <daniel@xxxxxxxxxxxxxx> Co-developed-by: Sujuan Chen <sujuan.chen@xxxxxxxxxxxx> Signed-off-by: Sujuan Chen <sujuan.chen@xxxxxxxxxxxx> Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- drivers/net/wireless/mediatek/mt76/dma.c | 2 + drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++ .../net/wireless/mediatek/mt76/mt7915/dma.c | 15 +++++++ .../net/wireless/mediatek/mt76/mt7915/mmio.c | 40 +++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 93c42082f1c2..714becbbefea 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -922,6 +922,8 @@ mt76_dma_init(struct mt76_dev *dev, snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s", wiphy_name(dev->hw->wiphy)); dev->napi_dev.threaded = 1; + init_completion(&dev->mmio.wed_reset); + init_completion(&dev->mmio.wed_reset_complete); mt76_for_each_q_rx(dev, i) { netif_napi_add(&dev->napi_dev, &dev->napi[i], poll); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 9037780f9e88..8abc6ecd7b68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -413,6 +413,7 @@ enum { MT76_STATE_SUSPEND, MT76_STATE_ROC, MT76_STATE_PM, + MT76_STATE_WED_RESET, }; struct mt76_hw_cap { @@ -591,6 +592,8 @@ struct mt76_mmio { u32 irqmask; struct mtk_wed_device wed; + struct completion wed_reset; + struct completion wed_reset_complete; }; struct mt76_rx_status { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index e3fa064918bf..a956e2a0be4f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -559,6 +559,20 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) return 0; } +static void mt7915_dma_wed_reset(struct mt7915_dev *dev) +{ + struct mt76_dev *mdev = &dev->mt76; + + if (!test_bit(MT76_STATE_WED_RESET, &dev->mphy.state)) + return; + + complete(&mdev->mmio.wed_reset); + + if (!wait_for_completion_timeout(&dev->mt76.mmio.wed_reset_complete, + 3 * HZ)) + dev_err(dev->mt76.dev, "wed reset complete timeout\n"); +} + int mt7915_dma_reset(struct mt7915_dev *dev, bool force) { struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1]; @@ -582,6 +596,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force) mt7915_wfsys_reset(dev); mt7915_dma_disable(dev, force); + mt7915_dma_wed_reset(dev); /* reset hw queues */ for (i = 0; i < __MT_TXQ_MAX; i++) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 3ab2e5bf7d45..24f1af7992d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -4,10 +4,12 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/rtnetlink.h> #include <linux/pci.h> #include "mt7915.h" #include "mac.h" +#include "mcu.h" #include "../trace.h" #include "../dma.h" @@ -695,6 +697,42 @@ static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed, rcu_read_unlock(); } + +static int mt7915_mmio_wed_reset(struct mtk_wed_device *wed) +{ + struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed); + struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt76_phy *mphy = &dev->mphy; + int ret; + + ASSERT_RTNL(); + + if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state)) + return -EBUSY; + + ret = mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L1, + mphy->band_idx); + if (ret) + goto out; + + rtnl_unlock(); + if (!wait_for_completion_timeout(&mdev->mmio.wed_reset, 20 * HZ)) { + dev_err(mdev->dev, "wed reset timeout\n"); + ret = -ETIMEDOUT; + } + rtnl_lock(); +out: + clear_bit(MT76_STATE_WED_RESET, &mphy->state); + + return ret; +} + +static void mt7915_mmio_wed_reset_complete(struct mtk_wed_device *wed) +{ + struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed); + + complete(&dev->mmio.wed_reset_complete); +} #endif int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, @@ -777,6 +815,8 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.init_rx_buf = mt7915_mmio_wed_init_rx_buf; wed->wlan.release_rx_buf = mt7915_mmio_wed_release_rx_buf; wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats; + wed->wlan.reset = mt7915_mmio_wed_reset; + wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete; dev->mt76.rx_token_size = wed->wlan.rx_npkt; -- 2.39.0