wifi: rtw89: pci: stop/start DMA for level 1 recovery according to chip gen
authorZong-Zhe Yang <kevin_yang@realtek.com>
Fri, 10 Nov 2023 01:23:14 +0000 (09:23 +0800)
committerKalle Valo <kvalo@kernel.org>
Tue, 14 Nov 2023 10:22:42 +0000 (12:22 +0200)
Level 1 recovery is to recover TX/RX rings, so it needs PCI to stop/start
DMA. But, different chip gen have different implementations, either
register address/mask or function flow. So, configure callback of
stop/start DMA by chip gen.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20231110012319.12727-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/pci.c
drivers/net/wireless/realtek/rtw89/pci.h
drivers/net/wireless/realtek/rtw89/pci_be.c
drivers/net/wireless/realtek/rtw89/ser.c

index bac9ec2236da53feb2909250064eb2a884557270..822b914cf935e47d942e7d7831639ff7a4981812 100644 (file)
@@ -1755,7 +1755,7 @@ static void rtw89_pci_ctrl_dma_io(struct rtw89_dev *rtwdev, bool enable)
                rtw89_write32_set(rtwdev, reg->addr, reg->mask);
 }
 
-static void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable)
+void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable)
 {
        rtw89_pci_ctrl_dma_io(rtwdev, enable);
        rtw89_pci_ctrl_dma_trx(rtwdev, enable);
@@ -3640,7 +3640,7 @@ static void rtw89_pci_l1ss_cfg(struct rtw89_dev *rtwdev)
                rtw89_pci_l1ss_set(rtwdev, true);
 }
 
-static int rtw89_pci_poll_io_idle(struct rtw89_dev *rtwdev)
+static int rtw89_pci_poll_io_idle_ax(struct rtw89_dev *rtwdev)
 {
        int ret = 0;
        u32 sts;
@@ -3657,7 +3657,7 @@ static int rtw89_pci_poll_io_idle(struct rtw89_dev *rtwdev)
        return ret;
 }
 
-static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
+static int rtw89_pci_lv1rst_stop_dma_ax(struct rtw89_dev *rtwdev)
 {
        u32 val;
        int ret;
@@ -3666,7 +3666,7 @@ static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
                return 0;
 
        rtw89_pci_ctrl_dma_all(rtwdev, false);
-       ret = rtw89_pci_poll_io_idle(rtwdev);
+       ret = rtw89_pci_poll_io_idle_ax(rtwdev);
        if (ret) {
                val = rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG);
                rtw89_debug(rtwdev, RTW89_DBG_HCI,
@@ -3677,7 +3677,7 @@ static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
                if (val & B_AX_RX_STUCK)
                        rtw89_mac_ctrl_hci_dma_rx(rtwdev, false);
                rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
-               ret = rtw89_pci_poll_io_idle(rtwdev);
+               ret = rtw89_pci_poll_io_idle_ax(rtwdev);
                val = rtw89_read32(rtwdev, R_AX_DBG_ERR_FLAG);
                rtw89_debug(rtwdev, RTW89_DBG_HCI,
                            "[PCIe] poll_io_idle fail, after 0x%08x: 0x%08x\n",
@@ -3687,7 +3687,7 @@ static int rtw89_pci_lv1rst_stop_dma(struct rtw89_dev *rtwdev)
        return ret;
 }
 
-static int rtw89_pci_lv1rst_start_dma(struct rtw89_dev *rtwdev)
+static int rtw89_pci_lv1rst_start_dma_ax(struct rtw89_dev *rtwdev)
 {
        u32 ret;
 
@@ -3709,18 +3709,20 @@ static int rtw89_pci_lv1rst_start_dma(struct rtw89_dev *rtwdev)
 static int rtw89_pci_ops_mac_lv1_recovery(struct rtw89_dev *rtwdev,
                                          enum rtw89_lv1_rcvy_step step)
 {
+       const struct rtw89_pci_info *info = rtwdev->pci_info;
+       const struct rtw89_pci_gen_def *gen_def = info->gen_def;
        int ret;
 
        switch (step) {
        case RTW89_LV1_RCVY_STEP_1:
-               ret = rtw89_pci_lv1rst_stop_dma(rtwdev);
+               ret = gen_def->lv1rst_stop_dma(rtwdev);
                if (ret)
                        rtw89_err(rtwdev, "lv1 rcvy pci stop dma fail\n");
 
                break;
 
        case RTW89_LV1_RCVY_STEP_2:
-               ret = rtw89_pci_lv1rst_start_dma(rtwdev);
+               ret = gen_def->lv1rst_start_dma(rtwdev);
                if (ret)
                        rtw89_err(rtwdev, "lv1 rcvy pci start dma fail\n");
                break;
@@ -3839,6 +3841,9 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
 
        .clr_idx_all = rtw89_pci_clr_idx_all_ax,
        .rst_bdram = rtw89_pci_rst_bdram_ax,
+
+       .lv1rst_stop_dma = rtw89_pci_lv1rst_stop_dma_ax,
+       .lv1rst_start_dma = rtw89_pci_lv1rst_start_dma_ax,
 };
 EXPORT_SYMBOL(rtw89_pci_gen_ax);
 
index e3a4a61196603834878eda4b94125b972ff7835b..30ab9d41e0eeb57b4ae390b7ca51496340b1b90c 100644 (file)
@@ -1042,6 +1042,9 @@ struct rtw89_pci_gen_def {
 
        void (*clr_idx_all)(struct rtw89_dev *rtwdev);
        int (*rst_bdram)(struct rtw89_dev *rtwdev);
+
+       int (*lv1rst_stop_dma)(struct rtw89_dev *rtwdev);
+       int (*lv1rst_start_dma)(struct rtw89_dev *rtwdev);
 };
 
 struct rtw89_pci_info {
@@ -1369,6 +1372,7 @@ u32 rtw89_pci_fill_txaddr_info(struct rtw89_dev *rtwdev,
 u32 rtw89_pci_fill_txaddr_info_v1(struct rtw89_dev *rtwdev,
                                  void *txaddr_info_addr, u32 total_len,
                                  dma_addr_t dma, u8 *add_info_nr);
+void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable);
 void rtw89_pci_config_intr_mask(struct rtw89_dev *rtwdev);
 void rtw89_pci_config_intr_mask_v1(struct rtw89_dev *rtwdev);
 void rtw89_pci_enable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci);
index 7d552b1a2d5e9fda0659e6e5a5876a096f6e3157..01d72cde48a3fc3701979c7fb9714c30db1aa047 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/pci.h>
 
+#include "mac.h"
 #include "pci.h"
 #include "reg.h"
 
@@ -420,11 +421,65 @@ static int rtw89_pci_ops_mac_post_init_be(struct rtw89_dev *rtwdev)
        return 0;
 }
 
+static int rtw89_pci_poll_io_idle_be(struct rtw89_dev *rtwdev)
+{
+       u32 sts;
+       int ret;
+
+       ret = read_poll_timeout_atomic(rtw89_read32, sts,
+                                      !(sts & B_BE_HAXI_MST_BUSY),
+                                      10, 1000, false, rtwdev,
+                                      R_BE_HAXI_DMA_BUSY1);
+       if (ret) {
+               rtw89_err(rtwdev, "pci dmach busy1 0x%X\n", sts);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rtw89_pci_lv1rst_stop_dma_be(struct rtw89_dev *rtwdev)
+{
+       int ret;
+
+       rtw89_pci_ctrl_dma_all(rtwdev, false);
+       ret = rtw89_pci_poll_io_idle_be(rtwdev);
+       if (!ret)
+               return 0;
+
+       rtw89_debug(rtwdev, RTW89_DBG_HCI,
+                   "[PCIe] poll_io_idle fail; reset hci dma trx\n");
+
+       rtw89_mac_ctrl_hci_dma_trx(rtwdev, false);
+       rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
+
+       return rtw89_pci_poll_io_idle_be(rtwdev);
+}
+
+static int rtw89_pci_lv1rst_start_dma_be(struct rtw89_dev *rtwdev)
+{
+       int ret;
+
+       rtw89_mac_ctrl_hci_dma_trx(rtwdev, false);
+       rtw89_mac_ctrl_hci_dma_trx(rtwdev, true);
+       rtw89_pci_clr_idx_all(rtwdev);
+
+       ret = rtw89_pci_rst_bdram_be(rtwdev);
+       if (ret)
+               return ret;
+
+       rtw89_pci_ctrl_dma_all(rtwdev, true);
+       return 0;
+}
+
 const struct rtw89_pci_gen_def rtw89_pci_gen_be = {
        .mac_pre_init = rtw89_pci_ops_mac_pre_init_be,
        .mac_post_init = rtw89_pci_ops_mac_post_init_be,
 
        .clr_idx_all = rtw89_pci_clr_idx_all_be,
        .rst_bdram = rtw89_pci_rst_bdram_be,
+
+       .lv1rst_stop_dma = rtw89_pci_lv1rst_stop_dma_be,
+       .lv1rst_start_dma = rtw89_pci_lv1rst_start_dma_be,
 };
 EXPORT_SYMBOL(rtw89_pci_gen_be);
index c1644353053f01af99a214ec446427961ae571a2..1e4a79a3b814adeba84d5450198d02458ff1f421 100644 (file)
@@ -361,6 +361,9 @@ static int hal_enable_dma(struct rtw89_ser *ser)
        ret = rtwdev->hci.ops->mac_lv1_rcvy(rtwdev, RTW89_LV1_RCVY_STEP_2);
        if (!ret)
                clear_bit(RTW89_SER_HAL_STOP_DMA, ser->flags);
+       else
+               rtw89_debug(rtwdev, RTW89_DBG_SER,
+                           "lv1 rcvy fail to start dma: %d\n", ret);
 
        return ret;
 }
@@ -376,6 +379,9 @@ static int hal_stop_dma(struct rtw89_ser *ser)
        ret = rtwdev->hci.ops->mac_lv1_rcvy(rtwdev, RTW89_LV1_RCVY_STEP_1);
        if (!ret)
                set_bit(RTW89_SER_HAL_STOP_DMA, ser->flags);
+       else
+               rtw89_debug(rtwdev, RTW89_DBG_SER,
+                           "lv1 rcvy fail to stop dma: %d\n", ret);
 
        return ret;
 }