wifi: rtw89: add drop tx packet function
authorChih-Kang Chang <gary.chang@realtek.com>
Thu, 27 Oct 2022 05:27:04 +0000 (13:27 +0800)
committerKalle Valo <kvalo@kernel.org>
Tue, 1 Nov 2022 09:26:13 +0000 (11:26 +0200)
When entering WoWLAN mode, we need to drop all transmit packets,
including those in mac buffer, to avoid memory leakage, so implement
the drop_tx function.

Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: Chin-Yen Lee <timlee@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/20221027052707.14605-5-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac.h
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8852a.c
drivers/net/wireless/realtek/rtw89/rtw8852c.c

index 10ccb04..6b6bb32 100644 (file)
@@ -2624,6 +2624,8 @@ struct rtw89_chip_info {
        u32 rsvd_ple_ofst;
        const struct rtw89_hfc_param_ini *hfc_param_ini;
        const struct rtw89_dle_mem *dle_mem;
+       u8 wde_qempty_acq_num;
+       u8 wde_qempty_mgq_sel;
        u32 rf_base_addr[2];
        u8 support_chanctx_num;
        u8 support_bands;
@@ -2949,6 +2951,7 @@ struct rtw89_pkt_drop_params {
        u8 port;
        u8 mbssid;
        bool tf_trs;
+       u32 macid_band_sel[4];
 };
 
 struct rtw89_pkt_stat {
index 8b82ea6..cd2c84b 100644 (file)
@@ -2900,6 +2900,7 @@ int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
        case RTW89_PKT_DROP_SEL_MACID_BK_ONCE:
        case RTW89_PKT_DROP_SEL_MACID_VI_ONCE:
        case RTW89_PKT_DROP_SEL_MACID_VO_ONCE:
+       case RTW89_PKT_DROP_SEL_BAND_ONCE:
                break;
        default:
                rtw89_debug(rtwdev, RTW89_DBG_FW,
@@ -2915,6 +2916,14 @@ int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
        RTW89_SET_FWCMD_PKT_DROP_PORT(skb->data, params->port);
        RTW89_SET_FWCMD_PKT_DROP_MBSSID(skb->data, params->mbssid);
        RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(skb->data, params->tf_trs);
+       RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_0(skb->data,
+                                                 params->macid_band_sel[0]);
+       RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_1(skb->data,
+                                                 params->macid_band_sel[1]);
+       RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_2(skb->data,
+                                                 params->macid_band_sel[2]);
+       RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_3(skb->data,
+                                                 params->macid_band_sel[3]);
 
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
                              H2C_CAT_MAC,
index 8563efa..3845581 100644 (file)
@@ -1873,6 +1873,26 @@ static inline void RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(void *cmd, u32 va
        le32p_replace_bits((__le32 *)cmd + 1, val, GENMASK(15, 8));
 }
 
+static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_0(void *cmd, u32 val)
+{
+       le32p_replace_bits((__le32 *)cmd + 2, val, GENMASK(31, 0));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_1(void *cmd, u32 val)
+{
+       le32p_replace_bits((__le32 *)cmd + 3, val, GENMASK(31, 0));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_2(void *cmd, u32 val)
+{
+       le32p_replace_bits((__le32 *)cmd + 4, val, GENMASK(31, 0));
+}
+
+static inline void RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_3(void *cmd, u32 val)
+{
+       le32p_replace_bits((__le32 *)cmd + 5, val, GENMASK(31, 0));
+}
+
 enum rtw89_btc_btf_h2c_class {
        BTFC_SET = 0x10,
        BTFC_GET = 0x11,
index 061244a..5b70661 100644 (file)
@@ -1335,6 +1335,60 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
        return cfg;
 }
 
+static bool mac_is_txq_empty(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_mac_dle_dfi_qempty qempty;
+       u32 qnum, qtmp, val32, msk32;
+       int i, j, ret;
+
+       qnum = rtwdev->chip->wde_qempty_acq_num;
+       qempty.dle_type = DLE_CTRL_TYPE_WDE;
+
+       for (i = 0; i < qnum; i++) {
+               qempty.grpsel = i;
+               ret = dle_dfi_qempty(rtwdev, &qempty);
+               if (ret) {
+                       rtw89_warn(rtwdev, "dle dfi acq empty %d\n", ret);
+                       return false;
+               }
+               qtmp = qempty.qempty;
+               for (j = 0 ; j < QEMP_ACQ_GRP_MACID_NUM; j++) {
+                       val32 = FIELD_GET(QEMP_ACQ_GRP_QSEL_MASK, qtmp);
+                       if (val32 != QEMP_ACQ_GRP_QSEL_MASK)
+                               return false;
+                       qtmp >>= QEMP_ACQ_GRP_QSEL_SH;
+               }
+       }
+
+       qempty.grpsel = rtwdev->chip->wde_qempty_mgq_sel;
+       ret = dle_dfi_qempty(rtwdev, &qempty);
+       if (ret) {
+               rtw89_warn(rtwdev, "dle dfi mgq empty %d\n", ret);
+               return false;
+       }
+       msk32 = B_CMAC0_MGQ_NORMAL | B_CMAC0_MGQ_NO_PWRSAV | B_CMAC0_CPUMGQ;
+       if ((qempty.qempty & msk32) != msk32)
+               return false;
+
+       if (rtwdev->dbcc_en) {
+               msk32 |= B_CMAC1_MGQ_NORMAL | B_CMAC1_MGQ_NO_PWRSAV | B_CMAC1_CPUMGQ;
+               if ((qempty.qempty & msk32) != msk32)
+                       return false;
+       }
+
+       msk32 = B_AX_WDE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_WDE_EMPTY_QTA_DMAC_DATA_CPU |
+               B_AX_PLE_EMPTY_QTA_DMAC_WLAN_CPU | B_AX_PLE_EMPTY_QTA_DMAC_H2C |
+               B_AX_WDE_EMPTY_QUE_OTHERS | B_AX_PLE_EMPTY_QUE_DMAC_MPDU_TX |
+               B_AX_WDE_EMPTY_QTA_DMAC_CPUIO | B_AX_PLE_EMPTY_QTA_DMAC_CPUIO |
+               B_AX_WDE_EMPTY_QUE_DMAC_PKTIN | B_AX_WDE_EMPTY_QTA_DMAC_HIF |
+               B_AX_PLE_EMPTY_QUE_DMAC_SEC_TX | B_AX_WDE_EMPTY_QTA_DMAC_PKTIN |
+               B_AX_PLE_EMPTY_QTA_DMAC_B0_TXPL | B_AX_PLE_EMPTY_QTA_DMAC_B1_TXPL |
+               B_AX_PLE_EMPTY_QTA_DMAC_MPDU_TX;
+       val32 = rtw89_read32(rtwdev, R_AX_DLE_EMPTY0);
+
+       return (val32 & msk32) == msk32;
+}
+
 static inline u32 dle_used_size(const struct rtw89_dle_size *wde,
                                const struct rtw89_dle_size *ple)
 {
@@ -4893,3 +4947,24 @@ void rtw89_mac_pkt_drop_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
                                          rtw89_mac_pkt_drop_vif_iter,
                                          rtwvif);
 }
+
+int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
+                                       enum rtw89_mac_idx band)
+{
+       struct rtw89_pkt_drop_params params = {0};
+       bool empty;
+       int i, ret = 0, try_cnt = 3;
+
+       params.mac_band = band;
+       params.sel = RTW89_PKT_DROP_SEL_BAND_ONCE;
+
+       for (i = 0; i < try_cnt; i++) {
+               ret = read_poll_timeout(mac_is_txq_empty, empty, empty, 50,
+                                       50000, false, rtwdev);
+               if (ret)
+                       rtw89_fw_h2c_pkt_drop(rtwdev, &params);
+               else
+                       return 0;
+       }
+       return ret;
+}
index 20211c4..e3b4c78 100644 (file)
@@ -420,6 +420,17 @@ enum rtw89_mac_bf_rrsc_rate {
 #define S_AX_PLE_PAGE_SEL_128  1
 #define S_AX_PLE_PAGE_SEL_256  2
 
+#define B_CMAC0_MGQ_NORMAL     BIT(2)
+#define B_CMAC0_MGQ_NO_PWRSAV  BIT(3)
+#define B_CMAC0_CPUMGQ         BIT(4)
+#define B_CMAC1_MGQ_NORMAL     BIT(10)
+#define B_CMAC1_MGQ_NO_PWRSAV  BIT(11)
+#define B_CMAC1_CPUMGQ         BIT(12)
+
+#define QEMP_ACQ_GRP_MACID_NUM 8
+#define QEMP_ACQ_GRP_QSEL_SH   4
+#define QEMP_ACQ_GRP_QSEL_MASK 0xF
+
 #define SDIO_LOCAL_BASE_ADDR    0x80000000
 
 #define        PWR_CMD_WRITE           0
@@ -1028,5 +1039,7 @@ u16 rtw89_mac_dle_buf_req(struct rtw89_dev *rtwdev, u16 buf_len, bool wd);
 int rtw89_mac_set_cpuio(struct rtw89_dev *rtwdev,
                        struct rtw89_cpuio_ctrl *ctrl_para, bool wd);
 int rtw89_mac_resize_ple_rx_quota(struct rtw89_dev *rtwdev, bool wow);
+int rtw89_mac_ptk_drop_by_band_and_wait(struct rtw89_dev *rtwdev,
+                                       enum rtw89_mac_idx band);
 
 #endif
index 2b938d1..33f2b67 100644 (file)
 #define B_AX_WDE_EMPTY_QUE_CMAC0_MBH BIT(1)
 #define B_AX_WDE_EMPTY_QUE_CMAC0_ALL_AC BIT(0)
 
+#define R_AX_DLE_EMPTY1 0x8434
+#define B_AX_PLE_EMPTY_QTA_DMAC_WDRLS BIT(20)
+#define B_AX_PLE_EMPTY_QTA_CMAC1_DMA_BBRPT BIT(19)
+#define B_AX_PLE_EMPTY_QTA_CMAC1_DMA_RX BIT(18)
+#define B_AX_PLE_EMPTY_QTA_CMAC0_DMA_RX BIT(17)
+#define B_AX_PLE_EMPTY_QTA_DMAC_C2H BIT(16)
+#define B_AX_PLE_EMPTY_QUE_DMAC_PLRLS BIT(5)
+#define B_AX_PLE_EMPTY_QUE_DMAC_CPUIO BIT(4)
+#define B_AX_PLE_EMPTY_QUE_DMAC_SEC_RX BIT(3)
+#define B_AX_PLE_EMPTY_QUE_DMAC_MPDU_RX BIT(2)
+#define B_AX_PLE_EMPTY_QUE_DMAC_HDP BIT(1)
+#define B_AX_WDE_EMPTY_QUE_DMAC_WDRLS BIT(0)
+
 #define R_AX_DMAC_ERR_IMR 0x8520
 #define B_AX_DLE_CPUIO_ERR_INT_EN BIT(10)
 #define B_AX_APB_BRIDGE_ERR_INT_EN BIT(9)
index 375e84f..7995d72 100644 (file)
@@ -2049,6 +2049,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
        .rsvd_ple_ofst          = 0x6f800,
        .hfc_param_ini          = rtw8852a_hfc_param_ini_pcie,
        .dle_mem                = rtw8852a_dle_mem_pcie,
+       .wde_qempty_acq_num     = 16,
+       .wde_qempty_mgq_sel     = 16,
        .rf_base_addr           = {0xc000, 0xd000},
        .pwr_on_seq             = pwr_on_seq_8852a,
        .pwr_off_seq            = pwr_off_seq_8852a,
index 7e208a8..93332fe 100644 (file)
@@ -2855,6 +2855,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
        .rsvd_ple_ofst          = 0x6f800,
        .hfc_param_ini          = rtw8852c_hfc_param_ini_pcie,
        .dle_mem                = rtw8852c_dle_mem_pcie,
+       .wde_qempty_acq_num     = 16,
+       .wde_qempty_mgq_sel     = 16,
        .rf_base_addr           = {0xe000, 0xf000},
        .pwr_on_seq             = NULL,
        .pwr_off_seq            = NULL,