rtw88: move adaptivity mechanism to firmware
authorChin-Yen Lee <timlee@realtek.com>
Mon, 30 Aug 2021 07:20:14 +0000 (15:20 +0800)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 21 Sep 2021 14:51:57 +0000 (17:51 +0300)
Current adaptivity mechanism is achieved in driver, by periodically
referencing the IGI value and then updating related registers.
But we find that this way may halt TX activity too long if huge
and temporary energy is detected frequently. So we move the mechanism
to firmware for immediately reacting this case to recover TX rapidly.

Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
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@codeaurora.org>
Link: https://lore.kernel.org/r/20210830072014.12250-5-pkshih@realtek.com
drivers/net/wireless/realtek/rtw88/debug.h
drivers/net/wireless/realtek/rtw88/fw.c
drivers/net/wireless/realtek/rtw88/fw.h
drivers/net/wireless/realtek/rtw88/phy.c
drivers/net/wireless/realtek/rtw88/reg.h

index 0dd3f9a88c8d97ee0aadf63f15511ca3ce432e79..47c57f395f52f3f1dc519433609d3ed6cbe56b3d 100644 (file)
@@ -21,6 +21,7 @@ enum rtw_debug_mask {
        RTW_DBG_WOW             = 0x00001000,
        RTW_DBG_CFO             = 0x00002000,
        RTW_DBG_PATH_DIV        = 0x00004000,
+       RTW_DBG_ADAPTIVITY      = 0x00008000,
 
        RTW_DBG_ALL             = 0xffffffff
 };
index e6399519584bd9be645f2dec4dfe2be496bc2006..ccd8221ab264f6a5a40890bdeae9a5444c0bec64 100644 (file)
@@ -183,6 +183,28 @@ static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload,
                dm_info->scan_density);
 }
 
+static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload,
+                                    u8 length)
+{
+       struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
+       struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload;
+
+       rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY,
+               "Adaptivity: density %x igi %x l2h_th_init %x l2h %x h2l %x option %x\n",
+               result->density, result->igi, result->l2h_th_init, result->l2h,
+               result->h2l, result->option);
+
+       rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "Reg Setting: L2H %x H2L %x\n",
+               rtw_read32_mask(rtwdev, edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr,
+                               edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask),
+               rtw_read32_mask(rtwdev, edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr,
+                               edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask));
+
+       rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "EDCCA Flag %s\n",
+               rtw_read32_mask(rtwdev, REG_EDCCA_REPORT, BIT_EDCCA_FLAG) ?
+               "Set" : "Unset");
+}
+
 void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
 {
        struct rtw_c2h_cmd *c2h;
@@ -252,6 +274,10 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
                rtw_fw_scan_result(rtwdev, c2h->payload, len);
                dev_kfree_skb_any(skb);
                break;
+       case C2H_ADAPTIVITY:
+               rtw_fw_adaptivity_result(rtwdev, c2h->payload, len);
+               dev_kfree_skb_any(skb);
+               break;
        default:
                /* pass offset for further operation */
                *((u32 *)skb->cb) = pkt_offset;
@@ -1722,6 +1748,27 @@ void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable)
        rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 }
 
+void rtw_fw_adaptivity(struct rtw_dev *rtwdev)
+{
+       struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+       u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+       if (!rtw_edcca_enabled) {
+               dm_info->edcca_mode = RTW_EDCCA_NORMAL;
+               rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY,
+                       "EDCCA disabled by debugfs\n");
+       }
+
+       SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_ADAPTIVITY);
+       SET_ADAPTIVITY_MODE(h2c_pkt, dm_info->edcca_mode);
+       SET_ADAPTIVITY_OPTION(h2c_pkt, 2);
+       SET_ADAPTIVITY_IGI(h2c_pkt, dm_info->igi_history[0]);
+       SET_ADAPTIVITY_L2H(h2c_pkt, dm_info->l2h_th_ini);
+       SET_ADAPTIVITY_DENSITY(h2c_pkt, dm_info->scan_density);
+
+       rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
 void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
 {
        u8 h2c_pkt[H2C_PKT_SIZE] = {0};
index 64dcde35a021a031d82fa2b89bd062680ffdb0d3..09c7afb99e6318c6ea2c288acfcd7cc59d3a1dc5 100644 (file)
@@ -41,6 +41,7 @@ enum rtw_c2h_cmd_id {
        C2H_WLAN_INFO = 0x27,
        C2H_WLAN_RFON = 0x32,
        C2H_BCN_FILTER_NOTIFY = 0x36,
+       C2H_ADAPTIVITY = 0x37,
        C2H_SCAN_RESULT = 0x38,
        C2H_HW_FEATURE_DUMP = 0xfd,
        C2H_HALMAC = 0xff,
@@ -56,6 +57,15 @@ struct rtw_c2h_cmd {
        u8 payload[];
 } __packed;
 
+struct rtw_c2h_adaptivity {
+       u8 density;
+       u8 igi;
+       u8 l2h_th_init;
+       u8 l2h;
+       u8 h2l;
+       u8 option;
+} __packed;
+
 enum rtw_rsvd_packet_type {
        RSVD_BEACON,
        RSVD_DUMMY,
@@ -90,6 +100,7 @@ enum rtw_fw_feature {
        FW_FEATURE_PG = BIT(3),
        FW_FEATURE_BCN_FILTER = BIT(5),
        FW_FEATURE_NOTIFY_SCAN = BIT(6),
+       FW_FEATURE_ADAPTIVITY = BIT(7),
        FW_FEATURE_MAX = BIT(31),
 };
 
@@ -375,6 +386,7 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
 #define H2C_CMD_BCN_FILTER_OFFLOAD_P1  0x57
 #define H2C_CMD_WL_PHY_INFO            0x58
 #define H2C_CMD_SCAN                   0x59
+#define H2C_CMD_ADAPTIVITY             0x5A
 
 #define H2C_CMD_COEX_TDMA_TYPE         0x60
 #define H2C_CMD_QUERY_BT_INFO          0x61
@@ -428,6 +440,17 @@ static inline void rtw_h2c_pkt_set_header(u8 *h2c_pkt, u8 sub_id)
 #define SET_SCAN_START(h2c_pkt, value)                                        \
        le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
 
+#define SET_ADAPTIVITY_MODE(h2c_pkt, value)                                   \
+       le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(11, 8))
+#define SET_ADAPTIVITY_OPTION(h2c_pkt, value)                                 \
+       le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 12))
+#define SET_ADAPTIVITY_IGI(h2c_pkt, value)                                    \
+       le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define SET_ADAPTIVITY_L2H(h2c_pkt, value)                                    \
+       le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+#define SET_ADAPTIVITY_DENSITY(h2c_pkt, value)                                \
+       le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 0))
+
 #define SET_PWR_MODE_SET_MODE(h2c_pkt, value)                                  \
        le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8))
 #define SET_PWR_MODE_SET_RLBM(h2c_pkt, value)                                  \
@@ -662,4 +685,5 @@ void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev);
 int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
                     u32 *buffer);
 void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
+void rtw_fw_adaptivity(struct rtw_dev *rtwdev);
 #endif
index e0daf12d2484e48a92bc8615d67b27acca3d5129..bfddfcbe63f5598334e92e7e80bda7a76474bf50 100644 (file)
@@ -770,7 +770,11 @@ void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev)
        rtw_phy_cfo_track(rtwdev);
        rtw_phy_dpk_track(rtwdev);
        rtw_phy_pwr_track(rtwdev);
-       rtw_phy_adaptivity(rtwdev);
+
+       if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_ADAPTIVITY))
+               rtw_fw_adaptivity(rtwdev);
+       else
+               rtw_phy_adaptivity(rtwdev);
 }
 
 #define FRAC_BITS 3
index 8adac30ee08e25042b562d2834f4e9a9cc053ab9..abb7b490d8faf40d708c5d2c306de4c04495323b 100644 (file)
 
 #define REG_HRCV_MSG   0x1cf
 
+#define REG_EDCCA_REPORT       0x2d38
+#define BIT_EDCCA_FLAG         BIT(24)
+
 #define REG_IGN_GNTBT4 0x4160
 
 #define RF_MODE                0x00