wifi: rtw89: mac: implement MRC C2H event handling
authorZong-Zhe Yang <kevin_yang@realtek.com>
Tue, 13 Feb 2024 07:35:11 +0000 (15:35 +0800)
committerKalle Valo <kvalo@kernel.org>
Thu, 15 Feb 2024 11:09:48 +0000 (13:09 +0200)
Add handling of MRC (multiple role concurrent) C2H events including
TSF report and status report. Parse report data and then complete the
corresponding H2C commands, which will be implemented in the following.

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://msgid.link/20240213073514.23796-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac.h

index e3913efedc288a772485b85059c909dc6632ac2a..6269ae2539b2114ddb3f8de993f14923423b58fc 100644 (file)
@@ -3918,7 +3918,7 @@ enum rtw89_host_rpr_mode {
        RTW89_RPR_MODE_STF
 };
 
-#define RTW89_COMPLETION_BUF_SIZE 24
+#define RTW89_COMPLETION_BUF_SIZE 40
 #define RTW89_WAIT_COND_IDLE UINT_MAX
 
 struct rtw89_completion_data {
index 409f62cea0d7a74d351cd0e7ef14748d41191dd2..d44df3897dd21744e14f34eb3669371ddb079adc 100644 (file)
@@ -3474,6 +3474,8 @@ struct rtw89_h2c_mrc_del {
 #define RTW89_H2C_MRC_DEL_W0_STOP_SLOT_IDX GENMASK(15, 8)
 #define RTW89_H2C_MRC_DEL_W0_SPECIFIC_ROLE_MACID GENMASK(31, 16)
 
+#define RTW89_MAC_MRC_MAX_REQ_TSF_NUM 2
+
 struct rtw89_h2c_mrc_req_tsf {
        u8 req_tsf_num;
        u8 infos[] __counted_by(req_tsf_num);
@@ -3710,6 +3712,13 @@ static_assert(sizeof(struct rtw89_mac_mcc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE)
 #define RTW89_GET_MAC_C2H_MCC_STATUS_RPT_TSF_HIGH(c2h) \
        le32_get_bits(*((const __le32 *)(c2h) + 4), GENMASK(31, 0))
 
+struct rtw89_mac_mrc_tsf_rpt {
+       unsigned int num;
+       u64 tsfs[RTW89_MAC_MRC_MAX_REQ_TSF_NUM];
+};
+
+static_assert(sizeof(struct rtw89_mac_mrc_tsf_rpt) <= RTW89_COMPLETION_BUF_SIZE);
+
 struct rtw89_c2h_mrc_tsf_rpt_info {
        __le32 tsf_low;
        __le32 tsf_high;
@@ -4129,8 +4138,17 @@ enum rtw89_mrc_h2c_func {
        H2C_FUNC_MRC_SYNC               = 0x4,
        H2C_FUNC_MRC_UPD_DURATION       = 0x5,
        H2C_FUNC_MRC_UPD_BITMAP         = 0x6,
+
+       NUM_OF_RTW89_MRC_H2C_FUNC,
 };
 
+/* can consider MRC's sch_idx as MCC's group */
+#define RTW89_MRC_WAIT_COND(sch_idx, func) \
+       ((sch_idx) * NUM_OF_RTW89_MRC_H2C_FUNC + (func))
+
+#define RTW89_MRC_WAIT_COND_REQ_TSF \
+       RTW89_MRC_WAIT_COND(0 /* don't care */, H2C_FUNC_MRC_REQ_TSF)
+
 #define H2C_CAT_OUTSRC                 0x2
 
 #define H2C_CL_OUTSRC_RA               0x1
index 3ea50d49e12f79e8d1302369b0ab8d0cb60aac15..908245ac46bd54ec08e3fce8176a469829476a24 100644 (file)
@@ -5099,6 +5099,84 @@ rtw89_mac_c2h_mcc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32
        rtw89_complete_cond(&rtwdev->mcc.wait, cond, &data);
 }
 
+static void
+rtw89_mac_c2h_mrc_tsf_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+       struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
+       const struct rtw89_c2h_mrc_tsf_rpt *c2h_rpt;
+       struct rtw89_completion_data data = {};
+       struct rtw89_mac_mrc_tsf_rpt *rpt;
+       unsigned int i;
+
+       c2h_rpt = (const struct rtw89_c2h_mrc_tsf_rpt *)c2h->data;
+       rpt = (struct rtw89_mac_mrc_tsf_rpt *)data.buf;
+       rpt->num = min_t(u8, RTW89_MAC_MRC_MAX_REQ_TSF_NUM,
+                        le32_get_bits(c2h_rpt->w2,
+                                      RTW89_C2H_MRC_TSF_RPT_W2_REQ_TSF_NUM));
+
+       for (i = 0; i < rpt->num; i++) {
+               u32 tsf_high = le32_to_cpu(c2h_rpt->infos[i].tsf_high);
+               u32 tsf_low = le32_to_cpu(c2h_rpt->infos[i].tsf_low);
+
+               rpt->tsfs[i] = (u64)tsf_high << 32 | tsf_low;
+
+               rtw89_debug(rtwdev, RTW89_DBG_CHAN,
+                           "MRC C2H TSF RPT: index %u> %llu\n",
+                           i, rpt->tsfs[i]);
+       }
+
+       rtw89_complete_cond(wait, RTW89_MRC_WAIT_COND_REQ_TSF, &data);
+}
+
+static void
+rtw89_mac_c2h_mrc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+       struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
+       const struct rtw89_c2h_mrc_status_rpt *c2h_rpt;
+       struct rtw89_completion_data data = {};
+       enum rtw89_mac_mrc_status status;
+       unsigned int cond;
+       bool next = false;
+       u32 tsf_high;
+       u32 tsf_low;
+       u8 sch_idx;
+       u8 func;
+
+       c2h_rpt = (const struct rtw89_c2h_mrc_status_rpt *)c2h->data;
+       sch_idx = le32_get_bits(c2h_rpt->w2, RTW89_C2H_MRC_STATUS_RPT_W2_SCH_IDX);
+       status = le32_get_bits(c2h_rpt->w2, RTW89_C2H_MRC_STATUS_RPT_W2_STATUS);
+       tsf_high = le32_to_cpu(c2h_rpt->tsf_high);
+       tsf_low = le32_to_cpu(c2h_rpt->tsf_low);
+
+       switch (status) {
+       case RTW89_MAC_MRC_START_SCH_OK:
+               func = H2C_FUNC_START_MRC;
+               break;
+       case RTW89_MAC_MRC_STOP_SCH_OK:
+               /* H2C_FUNC_DEL_MRC without STOP_ONLY, so wait for DEL_SCH_OK */
+               func = H2C_FUNC_DEL_MRC;
+               next = true;
+               break;
+       case RTW89_MAC_MRC_DEL_SCH_OK:
+               func = H2C_FUNC_DEL_MRC;
+               break;
+       default:
+               rtw89_debug(rtwdev, RTW89_DBG_CHAN,
+                           "invalid MRC C2H STS RPT: status %d\n", status);
+               return;
+       }
+
+       rtw89_debug(rtwdev, RTW89_DBG_CHAN,
+                   "MRC C2H STS RPT: sch_idx %d, status %d, tsf %llu\n",
+                   sch_idx, status, (u64)tsf_high << 32 | tsf_low);
+
+       if (next)
+               return;
+
+       cond = RTW89_MRC_WAIT_COND(sch_idx, func);
+       rtw89_complete_cond(wait, cond, &data);
+}
+
 static
 void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
                                            struct sk_buff *c2h, u32 len) = {
@@ -5130,6 +5208,13 @@ void (* const rtw89_mac_c2h_mcc_handler[])(struct rtw89_dev *rtwdev,
        [RTW89_MAC_C2H_FUNC_MCC_STATUS_RPT] = rtw89_mac_c2h_mcc_status_rpt,
 };
 
+static
+void (* const rtw89_mac_c2h_mrc_handler[])(struct rtw89_dev *rtwdev,
+                                          struct sk_buff *c2h, u32 len) = {
+       [RTW89_MAC_C2H_FUNC_MRC_TSF_RPT] = rtw89_mac_c2h_mrc_tsf_rpt,
+       [RTW89_MAC_C2H_FUNC_MRC_STATUS_RPT] = rtw89_mac_c2h_mrc_status_rpt,
+};
+
 static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev,
                                              struct sk_buff *skb)
 {
@@ -5180,6 +5265,8 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
                }
        case RTW89_MAC_C2H_CLASS_MCC:
                return true;
+       case RTW89_MAC_C2H_CLASS_MRC:
+               return true;
        }
 }
 
@@ -5202,6 +5289,10 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
                if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MCC)
                        handler = rtw89_mac_c2h_mcc_handler[func];
                break;
+       case RTW89_MAC_C2H_CLASS_MRC:
+               if (func < NUM_OF_RTW89_MAC_C2H_FUNC_MRC)
+                       handler = rtw89_mac_c2h_mrc_handler[func];
+               break;
        case RTW89_MAC_C2H_CLASS_FWDBG:
                return;
        default:
index 12318d8504752af3c837ddd2a79410c80ce9fec3..db95509fad2f3aaf6fa04389f3b124bd4e11cef9 100644 (file)
@@ -409,6 +409,8 @@ enum rtw89_mac_c2h_mcc_func {
 enum rtw89_mac_c2h_mrc_func {
        RTW89_MAC_C2H_FUNC_MRC_TSF_RPT = 0,
        RTW89_MAC_C2H_FUNC_MRC_STATUS_RPT = 1,
+
+       NUM_OF_RTW89_MAC_C2H_FUNC_MRC,
 };
 
 enum rtw89_mac_c2h_class {