net: ethernet: mtk_wed: add reset/reset_complete callbacks
authorLorenzo Bianconi <lorenzo@kernel.org>
Sat, 14 Jan 2023 17:01:32 +0000 (18:01 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 17 Jan 2023 10:36:45 +0000 (11:36 +0100)
Introduce reset and reset_complete wlan callback to schedule WLAN driver
reset when ethernet/wed driver is resetting.

Tested-by: Daniel Golle <daniel@makrotopia.org>
Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_wed.c
drivers/net/ethernet/mediatek/mtk_wed.h
include/linux/soc/mediatek/mtk_wed.h

index 5d398595ead0660c65a6f762748a3728b4e3ccc1..75bbb1e7766c151e53770070d80b8480e873743a 100644 (file)
@@ -3970,6 +3970,11 @@ static void mtk_pending_work(struct work_struct *work)
        set_bit(MTK_RESETTING, &eth->state);
 
        mtk_prepare_for_reset(eth);
+       mtk_wed_fe_reset();
+       /* Run again reset preliminary configuration in order to avoid any
+        * possible race during FE reset since it can run releasing RTNL lock.
+        */
+       mtk_prepare_for_reset(eth);
 
        /* stop all devices to make sure that dma is properly shut down */
        for (i = 0; i < MTK_MAC_COUNT; i++) {
@@ -4007,6 +4012,8 @@ static void mtk_pending_work(struct work_struct *work)
 
        clear_bit(MTK_RESETTING, &eth->state);
 
+       mtk_wed_fe_reset_complete();
+
        rtnl_unlock();
 }
 
index a6271449617fcf57152a58a20c07b7f30e191de6..95ac4f71d2b24c1f1645653699b9fa56cfdd6b47 100644 (file)
@@ -206,6 +206,48 @@ mtk_wed_wo_reset(struct mtk_wed_device *dev)
        iounmap(reg);
 }
 
+void mtk_wed_fe_reset(void)
+{
+       int i;
+
+       mutex_lock(&hw_lock);
+
+       for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+               struct mtk_wed_hw *hw = hw_list[i];
+               struct mtk_wed_device *dev = hw->wed_dev;
+               int err;
+
+               if (!dev || !dev->wlan.reset)
+                       continue;
+
+               /* reset callback blocks until WLAN reset is completed */
+               err = dev->wlan.reset(dev);
+               if (err)
+                       dev_err(dev->dev, "wlan reset failed: %d\n", err);
+       }
+
+       mutex_unlock(&hw_lock);
+}
+
+void mtk_wed_fe_reset_complete(void)
+{
+       int i;
+
+       mutex_lock(&hw_lock);
+
+       for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+               struct mtk_wed_hw *hw = hw_list[i];
+               struct mtk_wed_device *dev = hw->wed_dev;
+
+               if (!dev || !dev->wlan.reset_complete)
+                       continue;
+
+               dev->wlan.reset_complete(dev);
+       }
+
+       mutex_unlock(&hw_lock);
+}
+
 static struct mtk_wed_hw *
 mtk_wed_assign(struct mtk_wed_device *dev)
 {
index e012b8a821336f878bc5f8a76928765c5e8e2925..43ab77eaf6837b198f916cbaf293c8b8e742b1d2 100644 (file)
@@ -128,6 +128,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
 void mtk_wed_exit(void);
 int mtk_wed_flow_add(int index);
 void mtk_wed_flow_remove(int index);
+void mtk_wed_fe_reset(void);
+void mtk_wed_fe_reset_complete(void);
 #else
 static inline void
 mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
@@ -147,6 +149,13 @@ static inline void mtk_wed_flow_remove(int index)
 {
 }
 
+static inline void mtk_wed_fe_reset(void)
+{
+}
+
+static inline void mtk_wed_fe_reset_complete(void)
+{
+}
 #endif
 
 #ifdef CONFIG_DEBUG_FS
index a0746d4aec204dde9437a45f14d7be69a8962bd0..b939bd2750a0569c4132e9db293bcded2248408f 100644 (file)
@@ -151,6 +151,8 @@ struct mtk_wed_device {
                void (*release_rx_buf)(struct mtk_wed_device *wed);
                void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
                                           struct mtk_wed_wo_rx_stats *stats);
+               int (*reset)(struct mtk_wed_device *wed);
+               void (*reset_complete)(struct mtk_wed_device *wed);
        } wlan;
 #endif
 };