diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c index 581d6d4154d33..f1e758a5f32b2 100644 --- a/drivers/net/wireless/realtek/rtw89/acpi.c +++ b/drivers/net/wireless/realtek/rtw89/acpi.c @@ -236,6 +236,50 @@ int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev, return 0; } +static bool chk_acpi_policy_6ghz_vlp_sig(const struct rtw89_acpi_policy_6ghz_vlp *p) +{ + return p->signature[0] == 0x52 && + p->signature[1] == 0x54 && + p->signature[2] == 0x4B && + p->signature[3] == 0x0B; +} + +static +int rtw89_acpi_dsm_get_policy_6ghz_vlp(struct rtw89_dev *rtwdev, + union acpi_object *obj, + struct rtw89_acpi_policy_6ghz_vlp **policy) +{ + const struct rtw89_acpi_policy_6ghz_vlp *ptr; + u32 buf_len; + + if (obj->type != ACPI_TYPE_BUFFER) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, + "acpi: expect buffer but type: %d\n", obj->type); + return -EINVAL; + } + + buf_len = obj->buffer.length; + if (buf_len < sizeof(*ptr)) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n", + __func__, buf_len); + return -EINVAL; + } + + ptr = (typeof(ptr))obj->buffer.pointer; + if (!chk_acpi_policy_6ghz_vlp_sig(ptr)) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__); + return -EINVAL; + } + + *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL); + if (!*policy) + return -ENOMEM; + + rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_vlp: ", *policy, + sizeof(*ptr)); + return 0; +} + static bool chk_acpi_policy_tas_sig(const struct rtw89_acpi_policy_tas *p) { return p->signature[0] == 0x52 && @@ -279,6 +323,51 @@ static int rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev *rtwdev, return 0; } +static +bool chk_acpi_policy_reg_rules_sig(const struct rtw89_acpi_policy_reg_rules *p) +{ + return p->signature[0] == 0x52 && + p->signature[1] == 0x54 && + p->signature[2] == 0x4B && + p->signature[3] == 0x0A; +} + +static +int rtw89_acpi_dsm_get_policy_reg_rules(struct rtw89_dev *rtwdev, + union acpi_object *obj, + struct rtw89_acpi_policy_reg_rules **policy) +{ + const struct rtw89_acpi_policy_reg_rules *ptr; + u32 buf_len; + + if (obj->type != ACPI_TYPE_BUFFER) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, + "acpi: expect buffer but type: %d\n", obj->type); + return -EINVAL; + } + + buf_len = obj->buffer.length; + if (buf_len < sizeof(*ptr)) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n", + __func__, buf_len); + return -EINVAL; + } + + ptr = (typeof(ptr))obj->buffer.pointer; + if (!chk_acpi_policy_reg_rules_sig(ptr)) { + rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__); + return -EINVAL; + } + + *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL); + if (!*policy) + return -ENOMEM; + + rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_reg_rules: ", *policy, + sizeof(*ptr)); + return 0; +} + int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, enum rtw89_acpi_dsm_func func, struct rtw89_acpi_dsm_result *res) @@ -300,8 +389,14 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP) ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj, &res->u.policy_6ghz_sp); + else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP) + ret = rtw89_acpi_dsm_get_policy_6ghz_vlp(rtwdev, obj, + &res->u.policy_6ghz_vlp); else if (func == RTW89_ACPI_DSM_FUNC_TAS_EN) ret = rtw89_acpi_dsm_get_policy_tas(rtwdev, obj, &res->u.policy_tas); + else if (func == RTW89_ACPI_DSM_FUNC_REG_RULES_EN) + ret = rtw89_acpi_dsm_get_policy_reg_rules(rtwdev, obj, + &res->u.policy_reg_rules); else ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value); diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h index 8c918ee02d2ed..48a46f2005b19 100644 --- a/drivers/net/wireless/realtek/rtw89/acpi.h +++ b/drivers/net/wireless/realtek/rtw89/acpi.h @@ -19,11 +19,13 @@ enum rtw89_acpi_dsm_func { RTW89_ACPI_DSM_FUNC_TAS_EN = 5, RTW89_ACPI_DSM_FUNC_UNII4_SUP = 6, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP = 7, + RTW89_ACPI_DSM_FUNC_REG_RULES_EN = 10, + RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP = 11, }; enum rtw89_acpi_conf_unii4 { - RTW89_ACPI_CONF_UNII4_FCC = BIT(0), - RTW89_ACPI_CONF_UNII4_IC = BIT(1), + RTW89_ACPI_CONF_UNII4_US = BIT(0), + RTW89_ACPI_CONF_UNII4_CA = BIT(1), }; enum rtw89_acpi_policy_mode { @@ -56,6 +58,7 @@ struct rtw89_acpi_policy_6ghz { enum rtw89_acpi_conf_6ghz_sp { RTW89_ACPI_CONF_6GHZ_SP_US = BIT(0), + RTW89_ACPI_CONF_6GHZ_SP_CA = BIT(1), }; struct rtw89_acpi_policy_6ghz_sp { @@ -66,6 +69,19 @@ struct rtw89_acpi_policy_6ghz_sp { u8 rsvd; } __packed; +enum rtw89_acpi_conf_6ghz_vlp { + RTW89_ACPI_CONF_6GHZ_VLP_US = BIT(0), + RTW89_ACPI_CONF_6GHZ_VLP_CA = BIT(1), +}; + +struct rtw89_acpi_policy_6ghz_vlp { + u8 signature[4]; + u8 revision; + u8 override; + u8 conf; + u8 rsvd; +} __packed; + struct rtw89_acpi_policy_tas { u8 signature[4]; u8 revision; @@ -74,13 +90,26 @@ struct rtw89_acpi_policy_tas { u8 rsvd[3]; } __packed; +enum rtw89_acpi_conf_reg_rules { + RTW89_ACPI_CONF_REG_RULE_REGD_UK = BIT(0), +}; + +struct rtw89_acpi_policy_reg_rules { + u8 signature[4]; + u8 revision; + u8 conf; + u8 rsvd[3]; +} __packed; + struct rtw89_acpi_dsm_result { union { u8 value; /* caller needs to free it after using */ struct rtw89_acpi_policy_6ghz *policy_6ghz; struct rtw89_acpi_policy_6ghz_sp *policy_6ghz_sp; + struct rtw89_acpi_policy_6ghz_vlp *policy_6ghz_vlp; struct rtw89_acpi_policy_tas *policy_tas; + struct rtw89_acpi_policy_reg_rules *policy_reg_rules; } u; }; diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c index 385a238fe5cc2..9f63d67777faf 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.c +++ b/drivers/net/wireless/realtek/rtw89/cam.c @@ -236,7 +236,8 @@ static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev, if (ret) rtw89_err(rtwdev, "failed to update dctl cam del key: %d\n", ret); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_INFO_CHANGE); if (ret) rtw89_err(rtwdev, "failed to update cam del key: %d\n", ret); } @@ -276,7 +277,8 @@ static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev, ret); return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_INFO_CHANGE); if (ret) { rtw89_err(rtwdev, "failed to update addr cam sec entry: %d\n", ret); @@ -760,7 +762,8 @@ int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, u8 *cmd) + struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_addr_cam_v0 *h2c) { struct rtw89_bssid_cam_entry *bssid_cam = rtw89_get_bssid_cam_of(rtwvif_link, rtwsta_link); @@ -780,20 +783,19 @@ int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, rcu_read_unlock(); - FWCMD_SET_ADDR_BSSID_IDX(cmd, bssid_cam->bssid_cam_idx); - FWCMD_SET_ADDR_BSSID_OFFSET(cmd, bssid_cam->offset); - FWCMD_SET_ADDR_BSSID_LEN(cmd, bssid_cam->len); - FWCMD_SET_ADDR_BSSID_VALID(cmd, bssid_cam->valid); - FWCMD_SET_ADDR_BSSID_MASK(cmd, bss_mask); - FWCMD_SET_ADDR_BSSID_BB_SEL(cmd, bssid_cam->phy_idx); - FWCMD_SET_ADDR_BSSID_BSS_COLOR(cmd, bss_color); - - FWCMD_SET_ADDR_BSSID_BSSID0(cmd, bssid_cam->bssid[0]); - FWCMD_SET_ADDR_BSSID_BSSID1(cmd, bssid_cam->bssid[1]); - FWCMD_SET_ADDR_BSSID_BSSID2(cmd, bssid_cam->bssid[2]); - FWCMD_SET_ADDR_BSSID_BSSID3(cmd, bssid_cam->bssid[3]); - FWCMD_SET_ADDR_BSSID_BSSID4(cmd, bssid_cam->bssid[4]); - FWCMD_SET_ADDR_BSSID_BSSID5(cmd, bssid_cam->bssid[5]); + h2c->w12 = le32_encode_bits(bssid_cam->bssid_cam_idx, ADDR_CAM_W12_BSSID_IDX) | + le32_encode_bits(bssid_cam->offset, ADDR_CAM_W12_BSSID_OFFSET) | + le32_encode_bits(bssid_cam->len, ADDR_CAM_W12_BSSID_LEN); + h2c->w13 = le32_encode_bits(bssid_cam->valid, ADDR_CAM_W13_BSSID_VALID) | + le32_encode_bits(bss_mask, ADDR_CAM_W13_BSSID_MASK) | + le32_encode_bits(bssid_cam->phy_idx, ADDR_CAM_W13_BSSID_BB_SEL) | + le32_encode_bits(bss_color, ADDR_CAM_W13_BSSID_BSS_COLOR) | + le32_encode_bits(bssid_cam->bssid[0], ADDR_CAM_W13_BSSID_BSSID0) | + le32_encode_bits(bssid_cam->bssid[1], ADDR_CAM_W13_BSSID_BSSID1); + h2c->w14 = le32_encode_bits(bssid_cam->bssid[2], ADDR_CAM_W14_BSSID_BSSID2) | + le32_encode_bits(bssid_cam->bssid[3], ADDR_CAM_W14_BSSID_BSSID3) | + le32_encode_bits(bssid_cam->bssid[4], ADDR_CAM_W14_BSSID_BSSID4) | + le32_encode_bits(bssid_cam->bssid[5], ADDR_CAM_W14_BSSID_BSSID5); return 0; } @@ -813,18 +815,21 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, - u8 *cmd) + struct rtw89_h2c_addr_cam_v0 *h2c) { struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_addr_cam_entry *addr_cam = rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link); + const struct rtw89_chip_info *chip = rtwdev->chip; struct ieee80211_link_sta *link_sta; const u8 *sma = scan_mac_addr ? scan_mac_addr : rtwvif_link->mac_addr; u8 sma_hash, tma_hash, addr_msk_start; + u8 ver = chip->addrcam_ver; u8 sma_start = 0; u8 tma_start = 0; const u8 *tma; + u8 mac_id; rcu_read_lock(); @@ -845,69 +850,79 @@ void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, sma_hash = rtw89_cam_addr_hash(sma_start, sma); tma_hash = rtw89_cam_addr_hash(tma_start, tma); - FWCMD_SET_ADDR_IDX(cmd, addr_cam->addr_cam_idx); - FWCMD_SET_ADDR_OFFSET(cmd, addr_cam->offset); - FWCMD_SET_ADDR_LEN(cmd, addr_cam->len); - - FWCMD_SET_ADDR_VALID(cmd, addr_cam->valid); - FWCMD_SET_ADDR_NET_TYPE(cmd, rtwvif_link->net_type); - FWCMD_SET_ADDR_BCN_HIT_COND(cmd, rtwvif_link->bcn_hit_cond); - FWCMD_SET_ADDR_HIT_RULE(cmd, rtwvif_link->hit_rule); - FWCMD_SET_ADDR_BB_SEL(cmd, rtwvif_link->phy_idx); - FWCMD_SET_ADDR_ADDR_MASK(cmd, addr_cam->addr_mask); - FWCMD_SET_ADDR_MASK_SEL(cmd, addr_cam->mask_sel); - FWCMD_SET_ADDR_SMA_HASH(cmd, sma_hash); - FWCMD_SET_ADDR_TMA_HASH(cmd, tma_hash); - - FWCMD_SET_ADDR_BSSID_CAM_IDX(cmd, addr_cam->bssid_cam_idx); - - FWCMD_SET_ADDR_SMA0(cmd, sma[0]); - FWCMD_SET_ADDR_SMA1(cmd, sma[1]); - FWCMD_SET_ADDR_SMA2(cmd, sma[2]); - FWCMD_SET_ADDR_SMA3(cmd, sma[3]); - FWCMD_SET_ADDR_SMA4(cmd, sma[4]); - FWCMD_SET_ADDR_SMA5(cmd, sma[5]); - - FWCMD_SET_ADDR_TMA0(cmd, tma[0]); - FWCMD_SET_ADDR_TMA1(cmd, tma[1]); - FWCMD_SET_ADDR_TMA2(cmd, tma[2]); - FWCMD_SET_ADDR_TMA3(cmd, tma[3]); - FWCMD_SET_ADDR_TMA4(cmd, tma[4]); - FWCMD_SET_ADDR_TMA5(cmd, tma[5]); - - FWCMD_SET_ADDR_PORT_INT(cmd, rtwvif_link->port); - FWCMD_SET_ADDR_TSF_SYNC(cmd, rtwvif_link->port); - FWCMD_SET_ADDR_TF_TRS(cmd, rtwvif_link->trigger); - FWCMD_SET_ADDR_LSIG_TXOP(cmd, rtwvif_link->lsig_txop); - FWCMD_SET_ADDR_TGT_IND(cmd, rtwvif_link->tgt_ind); - FWCMD_SET_ADDR_FRM_TGT_IND(cmd, rtwvif_link->frm_tgt_ind); - FWCMD_SET_ADDR_MACID(cmd, rtwsta_link ? rtwsta_link->mac_id : - rtwvif_link->mac_id); + mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + + if (ver == 0) + h2c->w1 = le32_encode_bits(addr_cam->addr_cam_idx, ADDR_CAM_W1_IDX) | + le32_encode_bits(addr_cam->offset, ADDR_CAM_W1_OFFSET) | + le32_encode_bits(addr_cam->len, ADDR_CAM_W1_LEN); + else + h2c->w1 = le32_encode_bits(addr_cam->addr_cam_idx, ADDR_CAM_W1_V1_IDX) | + le32_encode_bits(addr_cam->offset, ADDR_CAM_W1_V1_OFFSET) | + le32_encode_bits(addr_cam->len, ADDR_CAM_W1_V1_LEN); + + h2c->w2 = le32_encode_bits(addr_cam->valid, ADDR_CAM_W2_VALID) | + le32_encode_bits(rtwvif_link->net_type, ADDR_CAM_W2_NET_TYPE) | + le32_encode_bits(rtwvif_link->bcn_hit_cond, ADDR_CAM_W2_BCN_HIT_COND) | + le32_encode_bits(rtwvif_link->hit_rule, ADDR_CAM_W2_HIT_RULE) | + le32_encode_bits(rtwvif_link->phy_idx, ADDR_CAM_W2_BB_SEL) | + le32_encode_bits(addr_cam->addr_mask, ADDR_CAM_W2_ADDR_MASK) | + le32_encode_bits(addr_cam->mask_sel, ADDR_CAM_W2_MASK_SEL) | + le32_encode_bits(sma_hash, ADDR_CAM_W2_SMA_HASH) | + le32_encode_bits(tma_hash, ADDR_CAM_W2_TMA_HASH); + h2c->w3 = le32_encode_bits(addr_cam->bssid_cam_idx, ADDR_CAM_W3_BSSID_CAM_IDX); + h2c->w4 = le32_encode_bits(sma[0], ADDR_CAM_W4_SMA0) | + le32_encode_bits(sma[1], ADDR_CAM_W4_SMA1) | + le32_encode_bits(sma[2], ADDR_CAM_W4_SMA2) | + le32_encode_bits(sma[3], ADDR_CAM_W4_SMA3); + h2c->w5 = le32_encode_bits(sma[4], ADDR_CAM_W5_SMA4) | + le32_encode_bits(sma[5], ADDR_CAM_W5_SMA5) | + le32_encode_bits(tma[0], ADDR_CAM_W5_TMA0) | + le32_encode_bits(tma[1], ADDR_CAM_W5_TMA1); + h2c->w6 = le32_encode_bits(tma[2], ADDR_CAM_W6_TMA2) | + le32_encode_bits(tma[3], ADDR_CAM_W6_TMA3) | + le32_encode_bits(tma[4], ADDR_CAM_W6_TMA4) | + le32_encode_bits(tma[5], ADDR_CAM_W6_TMA5); + if (ver == 0) + h2c->w8 = le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_PORT_INT) | + le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_TSF_SYNC) | + le32_encode_bits(rtwvif_link->trigger, ADDR_CAM_W8_TF_TRS) | + le32_encode_bits(rtwvif_link->lsig_txop, ADDR_CAM_W8_LSIG_TXOP) | + le32_encode_bits(rtwvif_link->tgt_ind, ADDR_CAM_W8_TGT_IND) | + le32_encode_bits(rtwvif_link->frm_tgt_ind, ADDR_CAM_W8_FRM_TGT_IND) | + le32_encode_bits(mac_id, ADDR_CAM_W8_MACID); + else + h2c->w8 = le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_V1_PORT_INT) | + le32_encode_bits(rtwvif_link->port, ADDR_CAM_W8_V1_TSF_SYNC) | + le32_encode_bits(rtwvif_link->trigger, ADDR_CAM_W8_V1_TF_TRS) | + le32_encode_bits(rtwvif_link->lsig_txop, ADDR_CAM_W8_V1_LSIG_TXOP) | + le32_encode_bits(mac_id, ADDR_CAM_W8_V1_MACID); + if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) - FWCMD_SET_ADDR_AID12(cmd, vif->cfg.aid & 0xfff); + h2c->w9 = le32_encode_bits(vif->cfg.aid & 0xfff, ADDR_CAM_W9_AID12); else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) - FWCMD_SET_ADDR_AID12(cmd, sta ? sta->aid & 0xfff : 0); - FWCMD_SET_ADDR_WOL_PATTERN(cmd, rtwvif_link->wowlan_pattern); - FWCMD_SET_ADDR_WOL_UC(cmd, rtwvif_link->wowlan_uc); - FWCMD_SET_ADDR_WOL_MAGIC(cmd, rtwvif_link->wowlan_magic); - FWCMD_SET_ADDR_WAPI(cmd, addr_cam->wapi); - FWCMD_SET_ADDR_SEC_ENT_MODE(cmd, addr_cam->sec_ent_mode); - FWCMD_SET_ADDR_SEC_ENT0_KEYID(cmd, addr_cam->sec_ent_keyid[0]); - FWCMD_SET_ADDR_SEC_ENT1_KEYID(cmd, addr_cam->sec_ent_keyid[1]); - FWCMD_SET_ADDR_SEC_ENT2_KEYID(cmd, addr_cam->sec_ent_keyid[2]); - FWCMD_SET_ADDR_SEC_ENT3_KEYID(cmd, addr_cam->sec_ent_keyid[3]); - FWCMD_SET_ADDR_SEC_ENT4_KEYID(cmd, addr_cam->sec_ent_keyid[4]); - FWCMD_SET_ADDR_SEC_ENT5_KEYID(cmd, addr_cam->sec_ent_keyid[5]); - FWCMD_SET_ADDR_SEC_ENT6_KEYID(cmd, addr_cam->sec_ent_keyid[6]); - - FWCMD_SET_ADDR_SEC_ENT_VALID(cmd, addr_cam->sec_cam_map[0] & 0xff); - FWCMD_SET_ADDR_SEC_ENT0(cmd, addr_cam->sec_ent[0]); - FWCMD_SET_ADDR_SEC_ENT1(cmd, addr_cam->sec_ent[1]); - FWCMD_SET_ADDR_SEC_ENT2(cmd, addr_cam->sec_ent[2]); - FWCMD_SET_ADDR_SEC_ENT3(cmd, addr_cam->sec_ent[3]); - FWCMD_SET_ADDR_SEC_ENT4(cmd, addr_cam->sec_ent[4]); - FWCMD_SET_ADDR_SEC_ENT5(cmd, addr_cam->sec_ent[5]); - FWCMD_SET_ADDR_SEC_ENT6(cmd, addr_cam->sec_ent[6]); + h2c->w9 = le32_encode_bits(sta ? sta->aid & 0xfff : 0, ADDR_CAM_W9_AID12); + + h2c->w9 |= le32_encode_bits(rtwvif_link->wowlan_pattern, ADDR_CAM_W9_WOL_PATTERN) | + le32_encode_bits(rtwvif_link->wowlan_uc, ADDR_CAM_W9_WOL_UC) | + le32_encode_bits(rtwvif_link->wowlan_magic, ADDR_CAM_W9_WOL_MAGIC) | + le32_encode_bits(addr_cam->wapi, ADDR_CAM_W9_WAPI) | + le32_encode_bits(addr_cam->sec_ent_mode, ADDR_CAM_W9_SEC_ENT_MODE) | + le32_encode_bits(addr_cam->sec_ent_keyid[0], ADDR_CAM_W9_SEC_ENT0_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[1], ADDR_CAM_W9_SEC_ENT1_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[2], ADDR_CAM_W9_SEC_ENT2_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[3], ADDR_CAM_W9_SEC_ENT3_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[4], ADDR_CAM_W9_SEC_ENT4_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[5], ADDR_CAM_W9_SEC_ENT5_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[6], ADDR_CAM_W9_SEC_ENT6_KEYID); + h2c->w10 = le32_encode_bits(addr_cam->sec_cam_map[0] & 0xff, ADDR_CAM_W10_SEC_ENT_VALID) | + le32_encode_bits(addr_cam->sec_ent[0], ADDR_CAM_W10_SEC_ENT0) | + le32_encode_bits(addr_cam->sec_ent[1], ADDR_CAM_W10_SEC_ENT1) | + le32_encode_bits(addr_cam->sec_ent[2], ADDR_CAM_W10_SEC_ENT2); + h2c->w11 = le32_encode_bits(addr_cam->sec_ent[3], ADDR_CAM_W11_SEC_ENT3) | + le32_encode_bits(addr_cam->sec_ent[4], ADDR_CAM_W11_SEC_ENT4) | + le32_encode_bits(addr_cam->sec_ent[5], ADDR_CAM_W11_SEC_ENT5) | + le32_encode_bits(addr_cam->sec_ent[6], ADDR_CAM_W11_SEC_ENT6); rcu_read_unlock(); } @@ -1125,3 +1140,137 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, le32_encode_bits(mld_bssid[5], DCTLINFO_V2_W12_MLD_BSSID_5); h2c->m12 = cpu_to_le32(DCTLINFO_V2_W12_ALL); } + +void rtw89_cam_fill_dctl_sec_cam_info_v3(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_dctlinfo_ud_v3 *h2c) +{ + struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link); + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link->rtwvif); + struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; + struct rtw89_addr_cam_entry *addr_cam = + rtw89_get_addr_cam_of(rtwvif_link, rtwsta_link); + bool is_mld = sta ? sta->mlo : ieee80211_vif_is_mld(vif); + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + u8 *ptk_tx_iv = rtw_wow->key_info.ptk_tx_iv; + u8 *mld_sma, *mld_tma, *mld_bssid; + + h2c->c0 = le32_encode_bits(rtwsta_link ? rtwsta_link->mac_id : + rtwvif_link->mac_id, + DCTLINFO_V3_C0_MACID) | + le32_encode_bits(1, DCTLINFO_V3_C0_OP); + + h2c->w2 = le32_encode_bits(is_mld, DCTLINFO_V3_W2_IS_MLD); + h2c->m2 = cpu_to_le32(DCTLINFO_V3_W2_IS_MLD); + + h2c->w4 = le32_encode_bits(addr_cam->sec_ent_keyid[0], + DCTLINFO_V3_W4_SEC_ENT0_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[1], + DCTLINFO_V3_W4_SEC_ENT1_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[2], + DCTLINFO_V3_W4_SEC_ENT2_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[3], + DCTLINFO_V3_W4_SEC_ENT3_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[4], + DCTLINFO_V3_W4_SEC_ENT4_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[5], + DCTLINFO_V3_W4_SEC_ENT5_KEYID) | + le32_encode_bits(addr_cam->sec_ent_keyid[6], + DCTLINFO_V3_W4_SEC_ENT6_KEYID); + h2c->m4 = cpu_to_le32(DCTLINFO_V3_W4_SEC_ENT0_KEYID | + DCTLINFO_V3_W4_SEC_ENT1_KEYID | + DCTLINFO_V3_W4_SEC_ENT2_KEYID | + DCTLINFO_V3_W4_SEC_ENT3_KEYID | + DCTLINFO_V3_W4_SEC_ENT4_KEYID | + DCTLINFO_V3_W4_SEC_ENT5_KEYID | + DCTLINFO_V3_W4_SEC_ENT6_KEYID); + + h2c->w5 = le32_encode_bits(addr_cam->sec_cam_map[0], + DCTLINFO_V3_W5_SEC_ENT_VALID_V1); + h2c->m5 = cpu_to_le32(DCTLINFO_V3_W5_SEC_ENT_VALID_V1); + + h2c->w6 = le32_encode_bits(addr_cam->sec_ent[0], + DCTLINFO_V3_W6_SEC_ENT0_V2) | + le32_encode_bits(addr_cam->sec_ent[1], + DCTLINFO_V3_W6_SEC_ENT1_V2) | + le32_encode_bits(addr_cam->sec_ent[2], + DCTLINFO_V3_W6_SEC_ENT2_V2); + h2c->m6 = cpu_to_le32(DCTLINFO_V3_W6_SEC_ENT0_V2 | + DCTLINFO_V3_W6_SEC_ENT1_V2 | + DCTLINFO_V3_W6_SEC_ENT2_V2); + + h2c->w7 = le32_encode_bits(addr_cam->sec_ent[3], + DCTLINFO_V3_W7_SEC_ENT3_V2) | + le32_encode_bits(addr_cam->sec_ent[4], + DCTLINFO_V3_W7_SEC_ENT4_V2) | + le32_encode_bits(addr_cam->sec_ent[5], + DCTLINFO_V3_W7_SEC_ENT5_V2); + h2c->m7 = cpu_to_le32(DCTLINFO_V3_W7_SEC_ENT3_V2 | + DCTLINFO_V3_W7_SEC_ENT4_V2 | + DCTLINFO_V3_W7_SEC_ENT5_V2); + + h2c->w8 = le32_encode_bits(addr_cam->sec_ent[6], + DCTLINFO_V3_W8_SEC_ENT6_V2); + h2c->m8 = cpu_to_le32(DCTLINFO_V3_W8_SEC_ENT6_V2); + + if (rtw_wow->ptk_alg) { + h2c->w0 = le32_encode_bits(ptk_tx_iv[0] | ptk_tx_iv[1] << 8, + DCTLINFO_V3_W0_AES_IV_L); + h2c->m0 = cpu_to_le32(DCTLINFO_V3_W0_AES_IV_L); + + h2c->w1 = le32_encode_bits(ptk_tx_iv[4] | + ptk_tx_iv[5] << 8 | + ptk_tx_iv[6] << 16 | + ptk_tx_iv[7] << 24, + DCTLINFO_V3_W1_AES_IV_H); + h2c->m1 = cpu_to_le32(DCTLINFO_V3_W1_AES_IV_H); + + h2c->w4 |= le32_encode_bits(rtw_wow->ptk_keyidx, + DCTLINFO_V3_W4_SEC_KEY_ID); + h2c->m4 |= cpu_to_le32(DCTLINFO_V3_W4_SEC_KEY_ID); + } + + if (!is_mld) + return; + + if (rtwvif_link->net_type == RTW89_NET_TYPE_INFRA) { + mld_sma = rtwvif->mac_addr; + mld_tma = vif->cfg.ap_addr; + mld_bssid = vif->cfg.ap_addr; + } else if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE && sta) { + mld_sma = rtwvif->mac_addr; + mld_tma = sta->addr; + mld_bssid = rtwvif->mac_addr; + } else { + return; + } + + h2c->w9 = le32_encode_bits(mld_sma[0], DCTLINFO_V3_W9_MLD_SMA_0_V2) | + le32_encode_bits(mld_sma[1], DCTLINFO_V3_W9_MLD_SMA_1_V2) | + le32_encode_bits(mld_sma[2], DCTLINFO_V3_W9_MLD_SMA_2_V2) | + le32_encode_bits(mld_sma[3], DCTLINFO_V3_W9_MLD_SMA_3_V2); + h2c->m9 = cpu_to_le32(DCTLINFO_V3_W9_ALL); + + h2c->w10 = le32_encode_bits(mld_sma[4], DCTLINFO_V3_W10_MLD_SMA_4_V2) | + le32_encode_bits(mld_sma[5], DCTLINFO_V3_W10_MLD_SMA_5_V2) | + le32_encode_bits(mld_tma[0], DCTLINFO_V3_W10_MLD_TMA_0_V2) | + le32_encode_bits(mld_tma[1], DCTLINFO_V3_W10_MLD_TMA_1_V2); + h2c->m10 = cpu_to_le32(DCTLINFO_V3_W10_ALL); + + h2c->w11 = le32_encode_bits(mld_tma[2], DCTLINFO_V3_W11_MLD_TMA_2_V2) | + le32_encode_bits(mld_tma[3], DCTLINFO_V3_W11_MLD_TMA_3_V2) | + le32_encode_bits(mld_tma[4], DCTLINFO_V3_W11_MLD_TMA_4_V2) | + le32_encode_bits(mld_tma[5], DCTLINFO_V3_W11_MLD_TMA_5_V2); + h2c->m11 = cpu_to_le32(DCTLINFO_V3_W11_ALL); + + h2c->w12 = le32_encode_bits(mld_bssid[0], DCTLINFO_V3_W12_MLD_TA_BSSID_0_V2) | + le32_encode_bits(mld_bssid[1], DCTLINFO_V3_W12_MLD_TA_BSSID_1_V2) | + le32_encode_bits(mld_bssid[2], DCTLINFO_V3_W12_MLD_TA_BSSID_2_V2) | + le32_encode_bits(mld_bssid[3], DCTLINFO_V3_W12_MLD_TA_BSSID_3_V2); + h2c->m12 = cpu_to_le32(DCTLINFO_V3_W12_ALL); + + h2c->w13 = le32_encode_bits(mld_bssid[4], DCTLINFO_V3_W13_MLD_TA_BSSID_4_V2) | + le32_encode_bits(mld_bssid[5], DCTLINFO_V3_W13_MLD_TA_BSSID_5_V2); + h2c->m13 = cpu_to_le32(DCTLINFO_V3_W13_ALL); +} diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h index 8fd2d776408ea..22868f2622430 100644 --- a/drivers/net/wireless/realtek/rtw89/cam.h +++ b/drivers/net/wireless/realtek/rtw89/cam.h @@ -12,345 +12,109 @@ #define RTW89_BSSID_MATCH_ALL GENMASK(5, 0) #define RTW89_BSSID_MATCH_5_BYTES GENMASK(4, 0) -static inline void FWCMD_SET_ADDR_IDX(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_OFFSET(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_LEN(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 1, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_VALID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, BIT(0)); -} - -static inline void FWCMD_SET_ADDR_NET_TYPE(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(2, 1)); -} - -static inline void FWCMD_SET_ADDR_BCN_HIT_COND(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(4, 3)); -} - -static inline void FWCMD_SET_ADDR_HIT_RULE(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(6, 5)); -} - -static inline void FWCMD_SET_ADDR_BB_SEL(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, BIT(7)); -} - -static inline void FWCMD_SET_ADDR_ADDR_MASK(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(13, 8)); -} - -static inline void FWCMD_SET_ADDR_MASK_SEL(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(15, 14)); -} - -static inline void FWCMD_SET_ADDR_SMA_HASH(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_TMA_HASH(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 2, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_BSSID_CAM_IDX(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 3, value, GENMASK(5, 0)); -} - -static inline void FWCMD_SET_ADDR_SMA0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SMA1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_SMA2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_SMA3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 4, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_SMA4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SMA5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_TMA0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_TMA1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 5, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_TMA2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_TMA3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_TMA4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_TMA5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 6, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_MACID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_PORT_INT(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(10, 8)); -} - -static inline void FWCMD_SET_ADDR_TSF_SYNC(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(13, 11)); -} - -static inline void FWCMD_SET_ADDR_TF_TRS(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, BIT(14)); -} - -static inline void FWCMD_SET_ADDR_LSIG_TXOP(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, BIT(15)); -} - -static inline void FWCMD_SET_ADDR_TGT_IND(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(26, 24)); -} - -static inline void FWCMD_SET_ADDR_FRM_TGT_IND(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 8, value, GENMASK(29, 27)); -} - -static inline void FWCMD_SET_ADDR_AID12(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(11, 0)); -} - -static inline void FWCMD_SET_ADDR_AID12_0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_AID12_1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(11, 8)); -} - -static inline void FWCMD_SET_ADDR_WOL_PATTERN(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(12)); -} - -static inline void FWCMD_SET_ADDR_WOL_UC(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(13)); -} - -static inline void FWCMD_SET_ADDR_WOL_MAGIC(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(14)); -} - -static inline void FWCMD_SET_ADDR_WAPI(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, BIT(15)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT_MODE(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(17, 16)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT0_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(19, 18)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT1_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(21, 20)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT2_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(23, 22)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT3_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(25, 24)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT4_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(27, 26)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT5_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(29, 28)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT6_KEYID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 9, value, GENMASK(31, 30)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT_VALID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 10, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_SEC_ENT6(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 11, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_BSSID_IDX(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 12, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_BSSID_OFFSET(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 12, value, GENMASK(15, 8)); -} - -static inline void FWCMD_SET_ADDR_BSSID_LEN(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 12, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_BSSID_VALID(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(0)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BB_SEL(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, BIT(1)); -} - -static inline void FWCMD_SET_ADDR_BSSID_MASK(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(7, 2)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSS_COLOR(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(13, 8)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID0(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(23, 16)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID1(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 13, value, GENMASK(31, 24)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID2(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(7, 0)); -} - -static inline void FWCMD_SET_ADDR_BSSID_BSSID3(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(15, 8)); -} +struct rtw89_h2c_addr_cam_v0 { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; + __le32 w12; + __le32 w13; + __le32 w14; +} __packed; -static inline void FWCMD_SET_ADDR_BSSID_BSSID4(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(23, 16)); -} +struct rtw89_h2c_addr_cam { + struct rtw89_h2c_addr_cam_v0 v0; + __le32 w15; +} __packed; -static inline void FWCMD_SET_ADDR_BSSID_BSSID5(void *cmd, u32 value) -{ - le32p_replace_bits((__le32 *)(cmd) + 14, value, GENMASK(31, 24)); -} +#define ADDR_CAM_W1_IDX GENMASK(7, 0) +#define ADDR_CAM_W1_OFFSET GENMASK(15, 8) +#define ADDR_CAM_W1_LEN GENMASK(23, 16) +#define ADDR_CAM_W1_V1_IDX GENMASK(9, 0) +#define ADDR_CAM_W1_V1_OFFSET GENMASK(23, 16) +#define ADDR_CAM_W1_V1_LEN GENMASK(31, 24) +#define ADDR_CAM_W2_VALID BIT(0) +#define ADDR_CAM_W2_NET_TYPE GENMASK(2, 1) +#define ADDR_CAM_W2_BCN_HIT_COND GENMASK(4, 3) +#define ADDR_CAM_W2_HIT_RULE GENMASK(6, 5) +#define ADDR_CAM_W2_BB_SEL BIT(7) +#define ADDR_CAM_W2_ADDR_MASK GENMASK(13, 8) +#define ADDR_CAM_W2_MASK_SEL GENMASK(15, 14) +#define ADDR_CAM_W2_SMA_HASH GENMASK(23, 16) +#define ADDR_CAM_W2_TMA_HASH GENMASK(31, 24) +#define ADDR_CAM_W3_BSSID_CAM_IDX GENMASK(5, 0) +#define ADDR_CAM_W4_SMA0 GENMASK(7, 0) +#define ADDR_CAM_W4_SMA1 GENMASK(15, 8) +#define ADDR_CAM_W4_SMA2 GENMASK(23, 16) +#define ADDR_CAM_W4_SMA3 GENMASK(31, 24) +#define ADDR_CAM_W5_SMA4 GENMASK(7, 0) +#define ADDR_CAM_W5_SMA5 GENMASK(15, 8) +#define ADDR_CAM_W5_TMA0 GENMASK(23, 16) +#define ADDR_CAM_W5_TMA1 GENMASK(31, 24) +#define ADDR_CAM_W6_TMA2 GENMASK(7, 0) +#define ADDR_CAM_W6_TMA3 GENMASK(15, 8) +#define ADDR_CAM_W6_TMA4 GENMASK(23, 16) +#define ADDR_CAM_W6_TMA5 GENMASK(31, 24) +#define ADDR_CAM_W8_MACID GENMASK(7, 0) +#define ADDR_CAM_W8_PORT_INT GENMASK(10, 8) +#define ADDR_CAM_W8_TSF_SYNC GENMASK(13, 11) +#define ADDR_CAM_W8_TF_TRS BIT(14) +#define ADDR_CAM_W8_LSIG_TXOP BIT(15) +#define ADDR_CAM_W8_TGT_IND GENMASK(26, 24) +#define ADDR_CAM_W8_FRM_TGT_IND GENMASK(29, 27) +#define ADDR_CAM_W8_V1_MACID GENMASK(9, 0) +#define ADDR_CAM_W8_V1_PORT_INT GENMASK(18, 16) +#define ADDR_CAM_W8_V1_TSF_SYNC GENMASK(21, 19) +#define ADDR_CAM_W8_V1_TF_TRS BIT(22) +#define ADDR_CAM_W8_V1_LSIG_TXOP BIT(23) +#define ADDR_CAM_W8_V1_TB_RANGING BIT(24) +#define ADDR_CAM_W8_V1_TB_SENSING BIT(25) +#define ADDR_CAM_W8_V1_SENS_EN BIT(26) +#define ADDR_CAM_W9_AID12 GENMASK(11, 0) +#define ADDR_CAM_W9_AID12_0 GENMASK(7, 0) +#define ADDR_CAM_W9_AID12_1 GENMASK(11, 8) +#define ADDR_CAM_W9_WOL_PATTERN BIT(12) +#define ADDR_CAM_W9_WOL_UC BIT(13) +#define ADDR_CAM_W9_WOL_MAGIC BIT(14) +#define ADDR_CAM_W9_WAPI BIT(15) +#define ADDR_CAM_W9_SEC_ENT_MODE GENMASK(17, 16) +#define ADDR_CAM_W9_SEC_ENT0_KEYID GENMASK(19, 18) +#define ADDR_CAM_W9_SEC_ENT1_KEYID GENMASK(21, 20) +#define ADDR_CAM_W9_SEC_ENT2_KEYID GENMASK(23, 22) +#define ADDR_CAM_W9_SEC_ENT3_KEYID GENMASK(25, 24) +#define ADDR_CAM_W9_SEC_ENT4_KEYID GENMASK(27, 26) +#define ADDR_CAM_W9_SEC_ENT5_KEYID GENMASK(29, 28) +#define ADDR_CAM_W9_SEC_ENT6_KEYID GENMASK(31, 30) +#define ADDR_CAM_W10_SEC_ENT_VALID GENMASK(7, 0) +#define ADDR_CAM_W10_SEC_ENT0 GENMASK(15, 8) +#define ADDR_CAM_W10_SEC_ENT1 GENMASK(23, 16) +#define ADDR_CAM_W10_SEC_ENT2 GENMASK(31, 24) +#define ADDR_CAM_W11_SEC_ENT3 GENMASK(7, 0) +#define ADDR_CAM_W11_SEC_ENT4 GENMASK(15, 8) +#define ADDR_CAM_W11_SEC_ENT5 GENMASK(23, 16) +#define ADDR_CAM_W11_SEC_ENT6 GENMASK(31, 24) +#define ADDR_CAM_W12_BSSID_IDX GENMASK(7, 0) +#define ADDR_CAM_W12_BSSID_OFFSET GENMASK(15, 8) +#define ADDR_CAM_W12_BSSID_LEN GENMASK(23, 16) +#define ADDR_CAM_W13_BSSID_VALID BIT(0) +#define ADDR_CAM_W13_BSSID_BB_SEL BIT(1) +#define ADDR_CAM_W13_BSSID_MASK GENMASK(7, 2) +#define ADDR_CAM_W13_BSSID_BSS_COLOR GENMASK(13, 8) +#define ADDR_CAM_W13_BSSID_BSSID0 GENMASK(23, 16) +#define ADDR_CAM_W13_BSSID_BSSID1 GENMASK(31, 24) +#define ADDR_CAM_W14_BSSID_BSSID2 GENMASK(7, 0) +#define ADDR_CAM_W14_BSSID_BSSID3 GENMASK(15, 8) +#define ADDR_CAM_W14_BSSID_BSSID4 GENMASK(23, 16) +#define ADDR_CAM_W14_BSSID_BSSID5 GENMASK(31, 24) +#define ADDR_CAM_W15_UPD_MODE GENMASK(2, 0) struct rtw89_h2c_dctlinfo_ud_v1 { __le32 c0; @@ -538,6 +302,131 @@ struct rtw89_h2c_dctlinfo_ud_v2 { #define DCTLINFO_V2_W12_MLD_BSSID_5 GENMASK(15, 8) #define DCTLINFO_V2_W12_ALL GENMASK(15, 0) +struct rtw89_h2c_dctlinfo_ud_v3 { + __le32 c0; + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; + __le32 w12; + __le32 w13; + __le32 w14; + __le32 w15; + __le32 m0; + __le32 m1; + __le32 m2; + __le32 m3; + __le32 m4; + __le32 m5; + __le32 m6; + __le32 m7; + __le32 m8; + __le32 m9; + __le32 m10; + __le32 m11; + __le32 m12; + __le32 m13; + __le32 m14; + __le32 m15; +} __packed; + +#define DCTLINFO_V3_C0_MACID GENMASK(15, 0) +#define DCTLINFO_V3_C0_OP BIT(16) + +#define DCTLINFO_V3_W0_QOS_FIELD_H GENMASK(7, 0) +#define DCTLINFO_V3_W0_HW_EXSEQ_MACID GENMASK(14, 8) +#define DCTLINFO_V3_W0_QOS_DATA BIT(15) +#define DCTLINFO_V3_W0_AES_IV_L GENMASK(31, 16) +#define DCTLINFO_V3_W0_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W1_AES_IV_H GENMASK(31, 0) +#define DCTLINFO_V3_W1_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W2_SEQ0 GENMASK(11, 0) +#define DCTLINFO_V3_W2_SEQ1 GENMASK(23, 12) +#define DCTLINFO_V3_W2_AMSDU_MAX_LEN GENMASK(26, 24) +#define DCTLINFO_V3_W2_STA_AMSDU_EN BIT(27) +#define DCTLINFO_V3_W2_CHKSUM_OFLD_EN BIT(28) +#define DCTLINFO_V3_W2_WITH_LLC BIT(29) +#define DCTLINFO_V3_W2_NAT25_EN BIT(30) +#define DCTLINFO_V3_W2_IS_MLD BIT(31) +#define DCTLINFO_V3_W2_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W3_SEQ2 GENMASK(11, 0) +#define DCTLINFO_V3_W3_SEQ3 GENMASK(23, 12) +#define DCTLINFO_V3_W3_TGT_IND GENMASK(27, 24) +#define DCTLINFO_V3_W3_TGT_IND_EN BIT(28) +#define DCTLINFO_V3_W3_HTC_LB GENMASK(31, 29) +#define DCTLINFO_V3_W3_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W4_VLAN_TAG_SEL GENMASK(7, 5) +#define DCTLINFO_V3_W4_HTC_ORDER BIT(8) +#define DCTLINFO_V3_W4_SEC_KEY_ID GENMASK(10, 9) +#define DCTLINFO_V3_W4_VLAN_RX_DYNAMIC_PCP_EN BIT(11) +#define DCTLINFO_V3_W4_VLAN_RX_PKT_DROP BIT(12) +#define DCTLINFO_V3_W4_VLAN_RX_VALID BIT(13) +#define DCTLINFO_V3_W4_VLAN_TX_VALID BIT(14) +#define DCTLINFO_V3_W4_WAPI BIT(15) +#define DCTLINFO_V3_W4_SEC_ENT_MODE GENMASK(17, 16) +#define DCTLINFO_V3_W4_SEC_ENT0_KEYID GENMASK(19, 18) +#define DCTLINFO_V3_W4_SEC_ENT1_KEYID GENMASK(21, 20) +#define DCTLINFO_V3_W4_SEC_ENT2_KEYID GENMASK(23, 22) +#define DCTLINFO_V3_W4_SEC_ENT3_KEYID GENMASK(25, 24) +#define DCTLINFO_V3_W4_SEC_ENT4_KEYID GENMASK(27, 26) +#define DCTLINFO_V3_W4_SEC_ENT5_KEYID GENMASK(29, 28) +#define DCTLINFO_V3_W4_SEC_ENT6_KEYID GENMASK(31, 30) +#define DCTLINFO_V3_W4_ALL GENMASK(31, 5) +#define DCTLINFO_V3_W5_SEC_ENT7_KEYID GENMASK(1, 0) +#define DCTLINFO_V3_W5_SEC_ENT8_KEYID GENMASK(3, 2) +#define DCTLINFO_V3_W5_SEC_ENT_VALID_V1 GENMASK(23, 8) +#define DCTLINFO_V3_W5_ALL (GENMASK(23, 8) | GENMASK(3, 0)) +#define DCTLINFO_V3_W6_SEC_ENT0_V2 GENMASK(8, 0) +#define DCTLINFO_V3_W6_SEC_ENT1_V2 GENMASK(18, 10) +#define DCTLINFO_V3_W6_SEC_ENT2_V2 GENMASK(28, 20) +#define DCTLINFO_V3_W6_ALL GENMASK(28, 0) +#define DCTLINFO_V3_W7_SEC_ENT3_V2 GENMASK(8, 0) +#define DCTLINFO_V3_W7_SEC_ENT4_V2 GENMASK(18, 10) +#define DCTLINFO_V3_W7_SEC_ENT5_V2 GENMASK(28, 20) +#define DCTLINFO_V3_W7_ALL GENMASK(28, 0) +#define DCTLINFO_V3_W8_SEC_ENT6_V2 GENMASK(8, 0) +#define DCTLINFO_V3_W8_SEC_ENT7_V1 GENMASK(18, 10) +#define DCTLINFO_V3_W8_SEC_ENT8_V1 GENMASK(28, 20) +#define DCTLINFO_V3_W8_ALL GENMASK(28, 0) +#define DCTLINFO_V3_W9_MLD_SMA_0_V2 GENMASK(7, 0) +#define DCTLINFO_V3_W9_MLD_SMA_1_V2 GENMASK(15, 8) +#define DCTLINFO_V3_W9_MLD_SMA_2_V2 GENMASK(23, 16) +#define DCTLINFO_V3_W9_MLD_SMA_3_V2 GENMASK(31, 24) +#define DCTLINFO_V3_W9_MLD_SMA_L_V2 GENMASK(31, 0) +#define DCTLINFO_V3_W9_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W10_MLD_SMA_4_V2 GENMASK(7, 0) +#define DCTLINFO_V3_W10_MLD_SMA_5_V2 GENMASK(15, 8) +#define DCTLINFO_V3_W10_MLD_SMA_H_V2 GENMASK(15, 0) +#define DCTLINFO_V3_W10_MLD_TMA_0_V2 GENMASK(23, 16) +#define DCTLINFO_V3_W10_MLD_TMA_1_V2 GENMASK(31, 24) +#define DCTLINFO_V3_W10_MLD_TMA_L_V2 GENMASK(31, 16) +#define DCTLINFO_V3_W10_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W11_MLD_TMA_2_V2 GENMASK(7, 0) +#define DCTLINFO_V3_W11_MLD_TMA_3_V2 GENMASK(15, 8) +#define DCTLINFO_V3_W11_MLD_TMA_4_V2 GENMASK(23, 16) +#define DCTLINFO_V3_W11_MLD_TMA_5_V2 GENMASK(31, 24) +#define DCTLINFO_V3_W11_MLD_TMA_H_V2 GENMASK(31, 0) +#define DCTLINFO_V3_W11_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W12_MLD_TA_BSSID_0_V2 GENMASK(7, 0) +#define DCTLINFO_V3_W12_MLD_TA_BSSID_1_V2 GENMASK(15, 8) +#define DCTLINFO_V3_W12_MLD_TA_BSSID_2_V2 GENMASK(23, 16) +#define DCTLINFO_V3_W12_MLD_TA_BSSID_3_V2 GENMASK(31, 24) +#define DCTLINFO_V3_W12_MLD_TA_BSSID_L_V2 GENMASK(31, 0) +#define DCTLINFO_V3_W12_ALL GENMASK(31, 0) +#define DCTLINFO_V3_W13_MLD_TA_BSSID_4_V2 GENMASK(7, 0) +#define DCTLINFO_V3_W13_MLD_TA_BSSID_5_V2 GENMASK(15, 8) +#define DCTLINFO_V3_W13_MLD_TA_BSSID_H_V2 GENMASK(15, 0) +#define DCTLINFO_V3_W13_HW_EXSEQ_MACID_V1 GENMASK(24, 16) +#define DCTLINFO_V3_W13_ALL GENMASK(24, 0) + int rtw89_cam_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); void rtw89_cam_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif); int rtw89_cam_init_addr_cam(struct rtw89_dev *rtwdev, @@ -552,9 +441,10 @@ int rtw89_cam_init_bssid_cam(struct rtw89_dev *rtwdev, void rtw89_cam_deinit_bssid_cam(struct rtw89_dev *rtwdev, struct rtw89_bssid_cam_entry *bssid_cam); void rtw89_cam_fill_addr_cam_info(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *vif, + struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, - const u8 *scan_mac_addr, u8 *cmd); + const u8 *scan_mac_addr, + struct rtw89_h2c_addr_cam_v0 *h2c); void rtw89_cam_fill_dctl_sec_cam_info_v1(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, @@ -563,9 +453,14 @@ void rtw89_cam_fill_dctl_sec_cam_info_v2(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, struct rtw89_h2c_dctlinfo_ud_v2 *h2c); +void rtw89_cam_fill_dctl_sec_cam_info_v3(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_dctlinfo_ud_v3 *h2c); int rtw89_cam_fill_bssid_cam_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, u8 *cmd); + struct rtw89_sta_link *rtwsta_link, + struct rtw89_h2c_addr_cam_v0 *h2c); int rtw89_cam_sec_key_add(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 6f10235647a17..652a488945ee1 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -7,6 +7,7 @@ #include "debug.h" #include "fw.h" #include "mac.h" +#include "phy.h" #include "ps.h" #include "sar.h" #include "util.h" @@ -59,6 +60,28 @@ static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band, } } +static enum rtw89_tx_comp_band rtw89_get_tx_comp_band(enum rtw89_band band, + u8 center_chan) +{ + switch (band) { + default: + case RTW89_BAND_2G: + return RTW89_TX_COMP_BAND_2GHZ; + case RTW89_BAND_5G: + if (center_chan < 149) + return RTW89_TX_COMP_BAND_5GHZ_L; + else + return RTW89_TX_COMP_BAND_5GHZ_H; + case RTW89_BAND_6G: + if (center_chan < 65) + return RTW89_TX_COMP_BAND_5GHZ_H; + else if (center_chan < 193) + return RTW89_TX_COMP_BAND_6GHZ_M; + else + return RTW89_TX_COMP_BAND_6GHZ_UH; + } +} + static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw, u32 center_freq, u32 primary_freq) @@ -122,12 +145,14 @@ void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan, chan->freq = center_freq; chan->subband_type = rtw89_get_subband_type(band, center_chan); + chan->tx_comp_band = rtw89_get_tx_comp_band(band, center_chan); chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq, primary_freq); chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan, bandwidth); } + bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx idx, const struct rtw89_chan *new) @@ -238,6 +263,7 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; + int i, j; hal->entity_pause = false; bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX); @@ -246,6 +272,13 @@ void rtw89_entity_init(struct rtw89_dev *rtwdev) INIT_LIST_HEAD(&mgnt->active_list); + for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) { + for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++) + mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE; + } + + hal->entity_force_hw = RTW89_PHY_NUM; + rtw89_config_default_chandef(rtwdev); } @@ -298,8 +331,8 @@ static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev, if (unlikely(!rtwvif_link->chanctx_assigned)) return; - cur = rtw89_vif_get_link_inst(rtwvif, 0); - if (!cur || !cur->chanctx_assigned) + cur = rtw89_get_designated_link(rtwvif); + if (unlikely(!cur) || !cur->chanctx_assigned) return; if (cur == rtwvif_link) @@ -310,7 +343,7 @@ static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev, const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, const char *caller_message, - u8 link_index) + u8 link_index, bool nullchk) { struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; @@ -357,6 +390,9 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, return rtw89_chan_get(rtwdev, chanctx_idx); dflt: + if (unlikely(nullchk)) + return NULL; + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s (%s): prefetch NULL on link index %u\n", __func__, caller_message ?: "", link_index); @@ -365,12 +401,43 @@ const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(__rtw89_mgnt_chan_get); +bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + switch (rtwdev->mlo_dbcc_mode) { + case MLO_2_PLUS_0_1RF: + return phy_idx == RTW89_PHY_0; + case MLO_0_PLUS_2_1RF: + return phy_idx == RTW89_PHY_1; + default: + return false; + } +} + +void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + rtwdev->hal.entity_force_hw = phy_idx; + + if (phy_idx != RTW89_PHY_NUM) + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: %d\n", __func__, phy_idx); + else + rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: (none)\n", __func__); +} + static enum rtw89_mlo_dbcc_mode rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws) { if (rtwdev->chip->chip_gen != RTW89_CHIP_BE) return MLO_DBCC_NOT_SUPPORT; + switch (rtwdev->hal.entity_force_hw) { + case RTW89_PHY_0: + return MLO_2_PLUS_0_1RF; + case RTW89_PHY_1: + return MLO_0_PLUS_2_1RF; + default: + break; + } + switch (active_hws) { case BIT(0): return MLO_2_PLUS_0_1RF; @@ -414,8 +481,8 @@ static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev) } /* To be consistent with legacy behavior, expect the first active role - * which uses RTW89_CHANCTX_0 to put at position 0, and make its first - * link instance take RTW89_CHANCTX_0. (normalizing) + * which uses RTW89_CHANCTX_0 to put at position 0 and its designated + * link take RTW89_CHANCTX_0. (normalizing) */ list_for_each_entry(role, &mgnt->active_list, mgnt_entry) { for (i = 0; i < role->links_inst_valid_num; i++) { @@ -999,6 +1066,11 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev, *pattern = *new; memset(&pattern->courtesy, 0, sizeof(pattern->courtesy)); + if (RTW89_MCC_REQ_COURTESY(pattern, aux) && aux->is_gc) + aux->ignore_bcn = true; + else + aux->ignore_bcn = false; + if (RTW89_MCC_REQ_COURTESY(pattern, aux) && rtw89_mcc_can_courtesy(ref, aux)) { crtz = &pattern->courtesy.ref; ref->crtz = crtz; @@ -1013,6 +1085,11 @@ static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev, ref->crtz = NULL; } + if (RTW89_MCC_REQ_COURTESY(pattern, ref) && ref->is_gc) + ref->ignore_bcn = true; + else + ref->ignore_bcn = false; + if (RTW89_MCC_REQ_COURTESY(pattern, ref) && rtw89_mcc_can_courtesy(aux, ref)) { crtz = &pattern->courtesy.aux; aux->crtz = crtz; @@ -1115,7 +1192,7 @@ static int __rtw89_mcc_calc_pattern_strict(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *ref = &mcc->role_ref; struct rtw89_mcc_role *aux = &mcc->role_aux; struct rtw89_mcc_config *config = &mcc->config; - u16 min_tob = RTW89_MCC_EARLY_RX_BCN_TIME; + u16 min_tob = RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_SWITCH_CH_TIME; u16 min_toa = RTW89_MCC_MIN_RX_BCN_TIME; u16 bcn_ofst = config->beacon_offset; s16 upper_toa_ref, lower_toa_ref; @@ -1271,11 +1348,11 @@ static int __rtw89_mcc_calc_pattern_anchor(struct rtw89_dev *rtwdev, u16 bcn_ofst = config->beacon_offset; bool small_bcn_ofst; - if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_TIME) + if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME) small_bcn_ofst = true; else if (bcn_ofst < aux->duration - aux->limit.max_toa) small_bcn_ofst = true; - else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_TIME) + else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME) small_bcn_ofst = false; else return -EPERM; @@ -2170,6 +2247,7 @@ static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable) rtw89_p2p_noa_renew(rtwvif_go); if (enable) { + duration += RTW89_MCC_SWITCH_CH_TIME; noa_desc.start_time = cpu_to_le32(start_time); noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(interval)); noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(duration)); @@ -2253,15 +2331,6 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) else mcc->mode = RTW89_MCC_MODE_GC_STA; - if (rtw89_mcc_ignore_bcn(rtwdev, ref)) { - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false); - } else if (rtw89_mcc_ignore_bcn(rtwdev, aux)) { - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false); - } else { - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true); - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true); - } - rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode); mcc->group = RTW89_MCC_DFLT_GROUP; @@ -2270,6 +2339,15 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) if (ret) return ret; + if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn) { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false); + } else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn) { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false); + } else { + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true); + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true); + } + if (rtw89_concurrent_via_mrc(rtwdev)) ret = __mrc_fw_start(rtwdev, false); else @@ -2281,6 +2359,7 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev) rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START); rtw89_mcc_start_beacon_noa(rtwdev); + rtw89_phy_dig_suspend(rtwdev); rtw89_mcc_prepare(rtwdev, true); return 0; @@ -2333,9 +2412,11 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_mcc_info *mcc = &rtwdev->mcc; struct rtw89_mcc_role *ref = &mcc->role_ref; + struct rtw89_mcc_role *aux = &mcc->role_aux; struct rtw89_mcc_stop_sel sel = { .hint.target = pause ? pause->trigger : NULL, }; + bool rsn_scan; int ret; if (!pause) { @@ -2343,6 +2424,12 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES); } + rsn_scan = pause && pause->rsn == RTW89_CHANCTX_PAUSE_REASON_HW_SCAN; + if (rsn_scan && ref->is_go) + sel.hint.target = ref->rtwvif_link; + else if (rsn_scan && aux->is_go) + sel.hint.target = aux->rtwvif_link; + /* by default, stop at ref */ rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_stop_sel_iterator, &sel); if (!sel.filled) @@ -2371,6 +2458,8 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); rtw89_mcc_stop_beacon_noa(rtwdev); + rtw89_fw_h2c_mcc_dig(rtwdev, RTW89_CHANCTX_0, 0, 0, false); + rtw89_phy_dig_resume(rtwdev, true); rtw89_mcc_prepare(rtwdev, false); } @@ -2378,7 +2467,11 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, static int rtw89_mcc_update(struct rtw89_dev *rtwdev) { struct rtw89_mcc_info *mcc = &rtwdev->mcc; + bool old_ref_ignore_bcn = mcc->role_ref.ignore_bcn; + bool old_aux_ignore_bcn = mcc->role_aux.ignore_bcn; struct rtw89_mcc_config *config = &mcc->config; + struct rtw89_mcc_role *ref = &mcc->role_ref; + struct rtw89_mcc_role *aux = &mcc->role_aux; struct rtw89_mcc_config old_cfg = *config; bool courtesy_changed; bool sync_changed; @@ -2393,6 +2486,11 @@ static int rtw89_mcc_update(struct rtw89_dev *rtwdev) if (ret) return ret; + if (old_ref_ignore_bcn != ref->ignore_bcn) + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, !ref->ignore_bcn); + else if (old_aux_ignore_bcn != aux->ignore_bcn) + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, !aux->ignore_bcn); + if (memcmp(&old_cfg.pattern.courtesy, &config->pattern.courtesy, sizeof(old_cfg.pattern.courtesy)) == 0) courtesy_changed = false; @@ -2428,24 +2526,127 @@ static int rtw89_mcc_update(struct rtw89_dev *rtwdev) return 0; } +static int rtw89_mcc_search_gc_iterator(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *mcc_role, + unsigned int ordered_idx, + void *data) +{ + struct rtw89_mcc_role **role = data; + + if (mcc_role->is_gc) + *role = mcc_role; + + return 0; +} + +static struct rtw89_mcc_role *rtw89_mcc_get_gc_role(struct rtw89_dev *rtwdev) +{ + struct rtw89_mcc_info *mcc = &rtwdev->mcc; + struct rtw89_mcc_role *role = NULL; + + if (mcc->mode != RTW89_MCC_MODE_GC_STA) + return NULL; + + rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_search_gc_iterator, &role); + + return role; +} + +void rtw89_mcc_gc_detect_beacon_work(struct wiphy *wiphy, struct wiphy_work *work) +{ + struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, + mcc_gc_detect_beacon_work.work); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + enum rtw89_entity_mode mode; + struct rtw89_dev *rtwdev; + + lockdep_assert_wiphy(wiphy); + + rtwdev = rtwvif_link->rtwvif->rtwdev; + + mode = rtw89_get_entity_mode(rtwdev); + if (mode != RTW89_ENTITY_MODE_MCC) + return; + + if (READ_ONCE(rtwvif_link->sync_bcn_tsf) > rtwvif_link->last_sync_bcn_tsf) + rtwvif_link->detect_bcn_count = 0; + else + rtwvif_link->detect_bcn_count++; + + if (rtwvif_link->detect_bcn_count < RTW89_MCC_DETECT_BCN_MAX_TRIES) + rtw89_chanctx_proceed(rtwdev, NULL); + else + ieee80211_connection_loss(vif); +} + +bool rtw89_mcc_detect_go_bcn(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); + struct rtw89_chanctx_pause_parm pause_parm = { + .rsn = RTW89_CHANCTX_PAUSE_REASON_GC_BCN_LOSS, + .trigger = rtwvif_link, + }; + struct ieee80211_bss_conf *bss_conf; + struct rtw89_mcc_role *role; + u16 bcn_int; + + if (mode != RTW89_ENTITY_MODE_MCC) + return false; + + role = rtw89_mcc_get_gc_role(rtwdev); + if (!role) + return false; + + if (role->rtwvif_link != rtwvif_link) + return false; + + rtw89_debug(rtwdev, RTW89_DBG_CHAN, + "MCC GC beacon loss, pause MCC to detect GO beacon\n"); + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + bcn_int = bss_conf->beacon_int; + + rcu_read_unlock(); + + rtw89_chanctx_pause(rtwdev, &pause_parm); + rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); + wiphy_delayed_work_queue(rtwdev->hw->wiphy, + &rtwvif_link->mcc_gc_detect_beacon_work, + usecs_to_jiffies(ieee80211_tu_to_usec(bcn_int))); + + return true; +} + static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role) { + struct rtw89_vif_link *rtwvif_link = role->rtwvif_link; struct ieee80211_vif *vif; + bool start_detect; int ret; ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false, RTW89_MCC_PROBE_TIMEOUT); - if (ret) + if (ret && + READ_ONCE(rtwvif_link->sync_bcn_tsf) == rtwvif_link->last_sync_bcn_tsf) role->probe_count++; else role->probe_count = 0; + rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES) return; rtw89_debug(rtwdev, RTW89_DBG_CHAN, - "MCC can not detect AP\n", role->rtwvif_link->mac_id); + "MCC can not detect AP/GO\n", role->rtwvif_link->mac_id); + + start_detect = rtw89_mcc_detect_go_bcn(rtwdev, role->rtwvif_link); + if (start_detect) + return; + vif = rtwvif_link_to_vif(role->rtwvif_link); ieee80211_connection_loss(vif); } @@ -2461,9 +2662,9 @@ static void rtw89_mcc_track(struct rtw89_dev *rtwdev) u16 bcn_ofst; u16 diff; - if (rtw89_mcc_ignore_bcn(rtwdev, ref)) + if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn) rtw89_mcc_detect_connection(rtwdev, aux); - else if (rtw89_mcc_ignore_bcn(rtwdev, aux)) + else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn) rtw89_mcc_detect_connection(rtwdev, ref); if (mcc->mode != RTW89_MCC_MODE_GC_STA) @@ -2622,6 +2823,30 @@ static void rtw89_mcc_update_limit(struct rtw89_dev *rtwdev) rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_lmt_iterator, NULL); } +static int rtw89_mcc_get_links_iterator(struct rtw89_dev *rtwdev, + struct rtw89_mcc_role *mcc_role, + unsigned int ordered_idx, + void *data) +{ + struct rtw89_mcc_links_info *info = data; + + info->links[ordered_idx] = mcc_role->rtwvif_link; + return 0; +} + +void rtw89_mcc_get_links(struct rtw89_dev *rtwdev, struct rtw89_mcc_links_info *info) +{ + enum rtw89_entity_mode mode; + + memset(info, 0, sizeof(*info)); + + mode = rtw89_get_entity_mode(rtwdev); + if (unlikely(mode != RTW89_ENTITY_MODE_MCC)) + return; + + rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_get_links_iterator, info); +} + void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work) { struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, @@ -2690,6 +2915,7 @@ void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, return; case RTW89_ENTITY_MODE_MCC_PREPARE: delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE); + rtw89_phy_dig_suspend(rtwdev); break; case RTW89_ENTITY_MODE_MCC: delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC); @@ -3088,6 +3314,7 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, rtw89_config_entity_chandef(rtwdev, idx, &ctx->def); rtw89_set_channel(rtwdev); } + } int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, @@ -3231,5 +3458,6 @@ int rtw89_chanctx_ops_reassign_vif(struct rtw89_dev *rtwdev, return ret; } + return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h index 57355cb3d765d..c797cda2e7633 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.h +++ b/drivers/net/wireless/realtek/rtw89/chan.h @@ -18,16 +18,22 @@ #define RTW89_MCC_EARLY_RX_BCN_TIME 5 #define RTW89_MCC_MIN_RX_BCN_TIME 10 #define RTW89_MCC_DFLT_BCN_OFST_TIME 40 +#define RTW89_MCC_SWITCH_CH_TIME 3 #define RTW89_MCC_PROBE_TIMEOUT 100 #define RTW89_MCC_PROBE_MAX_TRIES 3 +#define RTW89_MCC_DETECT_BCN_MAX_TRIES 2 + #define RTW89_MCC_MIN_GO_DURATION \ (RTW89_MCC_EARLY_TX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME) #define RTW89_MCC_MIN_STA_DURATION \ (RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME) +#define RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME \ + (RTW89_MCC_MIN_RX_BCN_TIME + RTW89_MCC_SWITCH_CH_TIME) + #define RTW89_MCC_DFLT_GROUP 0 #define RTW89_MCC_NEXT_GROUP(cur) (((cur) + 1) % 4) @@ -90,6 +96,7 @@ struct rtw89_mr_chanctx_info { enum rtw89_chanctx_pause_reasons { RTW89_CHANCTX_PAUSE_REASON_HW_SCAN, RTW89_CHANCTX_PAUSE_REASON_ROC, + RTW89_CHANCTX_PAUSE_REASON_GC_BCN_LOSS, }; struct rtw89_chanctx_pause_parm { @@ -159,6 +166,8 @@ void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev, const struct cfg80211_chan_def *chandef); void rtw89_entity_init(struct rtw89_dev *rtwdev); enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev); +bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work); void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev); void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, @@ -173,12 +182,26 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev, const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, const char *caller_message, - u8 link_index); + u8 link_index, bool nullchk); #define rtw89_mgnt_chan_get(rtwdev, link_index) \ - __rtw89_mgnt_chan_get(rtwdev, __func__, link_index) + __rtw89_mgnt_chan_get(rtwdev, __func__, link_index, false) + +static inline const struct rtw89_chan * +rtw89_mgnt_chan_get_or_null(struct rtw89_dev *rtwdev, u8 link_index) +{ + return __rtw89_mgnt_chan_get(rtwdev, NULL, link_index, true); +} + +struct rtw89_mcc_links_info { + struct rtw89_vif_link *links[NUM_OF_RTW89_MCC_ROLES]; +}; +void rtw89_mcc_get_links(struct rtw89_dev *rtwdev, struct rtw89_mcc_links_info *info); void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work); +void rtw89_mcc_gc_detect_beacon_work(struct wiphy *wiphy, struct wiphy_work *work); +bool rtw89_mcc_detect_go_bcn(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, struct ieee80211_chanctx_conf *ctx); diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index e4e6daf51a1ba..0f7ae572ef915 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -93,7 +93,7 @@ static const struct rtw89_btc_fbtc_slot s_def[] = { [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX), [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO), [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX), - [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0xaaaaaaaa, SLOT_ISO), + [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX), [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX), [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO), [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO), @@ -4153,6 +4153,7 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); + _slot_set_dur(btc, CXST_EBT, dur_2); break; case BTC_CXP_OFFE_DEF2: _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO); @@ -4162,6 +4163,7 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur, s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype); + _slot_set_dur(btc, CXST_EBT, dur_2); break; case BTC_CXP_OFFE_2GBWMIXB: if (a2dp->exist) @@ -4170,6 +4172,7 @@ void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type) _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX); _slot_set_le(btc, CXST_EBT, cpu_to_le16(40), s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); + _slot_set_dur(btc, CXST_EBT, dur_2); break; case BTC_CXP_OFFE_WL: /* for 4-way */ _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX); diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 21fccd6452596..9882afe89e9cf 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ #include +#include #include #include "cam.h" @@ -276,17 +277,18 @@ rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq) return NULL; } -bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate) +bool rtw89_legacy_rate_to_bitrate(struct rtw89_dev *rtwdev, u8 legacy_rate, u16 *bitrate) { - struct ieee80211_rate rate; + const struct ieee80211_rate *rate; - if (unlikely(rpt_rate >= ARRAY_SIZE(rtw89_bitrates))) { - rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "invalid rpt rate %d\n", rpt_rate); + if (unlikely(legacy_rate >= ARRAY_SIZE(rtw89_bitrates))) { + rtw89_debug(rtwdev, RTW89_DBG_UNEXP, + "invalid legacy rate %d\n", legacy_rate); return false; } - rate = rtw89_bitrates[rpt_rate]; - *bitrate = rate.bitrate; + rate = &rtw89_bitrates[legacy_rate]; + *bitrate = rate->bitrate; return true; } @@ -323,15 +325,45 @@ static const struct ieee80211_supported_band rtw89_sband_6ghz = { .n_bitrates = ARRAY_SIZE(rtw89_bitrates) - 4, }; +static const struct rtw89_hw_rate_def { + enum rtw89_hw_rate ht; + enum rtw89_hw_rate vht[RTW89_NSS_NUM]; +} rtw89_hw_rate[RTW89_CHIP_GEN_NUM] = { + [RTW89_CHIP_AX] = { + .ht = RTW89_HW_RATE_MCS0, + .vht = {RTW89_HW_RATE_VHT_NSS1_MCS0, + RTW89_HW_RATE_VHT_NSS2_MCS0, + RTW89_HW_RATE_VHT_NSS3_MCS0, + RTW89_HW_RATE_VHT_NSS4_MCS0}, + }, + [RTW89_CHIP_BE] = { + .ht = RTW89_HW_RATE_V1_MCS0, + .vht = {RTW89_HW_RATE_V1_VHT_NSS1_MCS0, + RTW89_HW_RATE_V1_VHT_NSS2_MCS0, + RTW89_HW_RATE_V1_VHT_NSS3_MCS0, + RTW89_HW_RATE_V1_VHT_NSS4_MCS0}, + }, +}; + +static void __rtw89_traffic_stats_accu(struct rtw89_traffic_stats *stats, + struct sk_buff *skb, bool tx) +{ + if (tx) { + stats->tx_cnt++; + stats->tx_unicast += skb->len; + } else { + stats->rx_cnt++; + stats->rx_unicast += skb->len; + } +} + static void rtw89_traffic_stats_accu(struct rtw89_dev *rtwdev, - struct rtw89_traffic_stats *stats, - struct sk_buff *skb, bool tx) + struct rtw89_vif *rtwvif, + struct sk_buff *skb, + bool accu_dev, bool tx) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - if (tx && ieee80211_is_assoc_req(hdr->frame_control)) - rtw89_wow_parse_akm(rtwdev, skb); - if (!ieee80211_is_data(hdr->frame_control)) return; @@ -339,12 +371,12 @@ static void rtw89_traffic_stats_accu(struct rtw89_dev *rtwdev, is_multicast_ether_addr(hdr->addr1)) return; - if (tx) { - stats->tx_cnt++; - stats->tx_unicast += skb->len; - } else { - stats->rx_cnt++; - stats->rx_unicast += skb->len; + if (accu_dev) + __rtw89_traffic_stats_accu(&rtwdev->stats, skb, tx); + + if (rtwvif) { + __rtw89_traffic_stats_accu(&rtwvif->stats, skb, tx); + __rtw89_traffic_stats_accu(&rtwvif->stats_ps, skb, tx); } } @@ -442,6 +474,48 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) __rtw89_core_set_chip_txpwr(rtwdev, chan, RTW89_PHY_1); } +void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + bool mon = !!rtwdev->pure_monitor_mode_vif; + bool prehdl_link = false; + + if (chip->chip_gen != RTW89_CHIP_AX && + !RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw) && + !mon && !rtw89_entity_check_hw(rtwdev, rtwvif_link->phy_idx)) + prehdl_link = true; + + if (prehdl_link) { + rtw89_entity_force_hw(rtwdev, rtwvif_link->phy_idx); + rtw89_set_channel(rtwdev); + } + + if (chip->ops->rfk_channel) + chip->ops->rfk_channel(rtwdev, rtwvif_link); + + if (prehdl_link) { + rtw89_entity_force_hw(rtwdev, RTW89_PHY_NUM); + rtw89_set_channel(rtwdev); + } +} + +static void rtw89_chip_rfk_channel_for_pure_mon_vif(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + struct rtw89_vif *rtwvif = rtwdev->pure_monitor_mode_vif; + struct rtw89_vif_link *rtwvif_link; + + if (!rtwvif) + return; + + rtwvif_link = rtw89_vif_get_link_inst(rtwvif, phy_idx); + if (!rtwvif_link) + return; + + rtw89_chip_rfk_channel(rtwdev, rtwvif_link); +} + static void __rtw89_set_channel(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_mac_idx mac_idx, @@ -475,6 +549,8 @@ static void __rtw89_set_channel(struct rtw89_dev *rtwdev, } rtw89_set_entity_state(rtwdev, phy_idx, true); + + rtw89_chip_rfk_channel_for_pure_mon_vif(rtwdev, phy_idx); } int rtw89_set_channel(struct rtw89_dev *rtwdev) @@ -507,7 +583,7 @@ rtw89_core_get_tx_type(struct rtw89_dev *rtwdev, struct ieee80211_hdr *hdr = (void *)skb->data; __le16 fc = hdr->frame_control; - if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc)) + if (ieee80211_is_mgmt(fc) || ieee80211_is_any_nullfunc(fc)) return RTW89_CORE_TX_TYPE_MGMT; return RTW89_CORE_TX_TYPE_DATA; @@ -696,6 +772,66 @@ static void rtw89_core_tx_update_llc_hdr(struct rtw89_dev *rtwdev, desc_info->hdr_llc_len >>= 1; /* in unit of 2 bytes */ } +u8 rtw89_core_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel) +{ + switch (qsel) { + default: + rtw89_warn(rtwdev, "Cannot map qsel to dma: %d\n", qsel); + fallthrough; + case RTW89_TX_QSEL_BE_0: + case RTW89_TX_QSEL_BE_1: + case RTW89_TX_QSEL_BE_2: + case RTW89_TX_QSEL_BE_3: + return RTW89_TXCH_ACH0; + case RTW89_TX_QSEL_BK_0: + case RTW89_TX_QSEL_BK_1: + case RTW89_TX_QSEL_BK_2: + case RTW89_TX_QSEL_BK_3: + return RTW89_TXCH_ACH1; + case RTW89_TX_QSEL_VI_0: + case RTW89_TX_QSEL_VI_1: + case RTW89_TX_QSEL_VI_2: + case RTW89_TX_QSEL_VI_3: + return RTW89_TXCH_ACH2; + case RTW89_TX_QSEL_VO_0: + case RTW89_TX_QSEL_VO_1: + case RTW89_TX_QSEL_VO_2: + case RTW89_TX_QSEL_VO_3: + return RTW89_TXCH_ACH3; + case RTW89_TX_QSEL_B0_MGMT: + return RTW89_TXCH_CH8; + case RTW89_TX_QSEL_B0_HI: + return RTW89_TXCH_CH9; + case RTW89_TX_QSEL_B1_MGMT: + return RTW89_TXCH_CH10; + case RTW89_TX_QSEL_B1_HI: + return RTW89_TXCH_CH11; + } +} +EXPORT_SYMBOL(rtw89_core_get_ch_dma); + +u8 rtw89_core_get_ch_dma_v1(struct rtw89_dev *rtwdev, u8 qsel) +{ + switch (qsel) { + default: + rtw89_warn(rtwdev, "Cannot map qsel to dma v1: %d\n", qsel); + fallthrough; + case RTW89_TX_QSEL_BE_0: + case RTW89_TX_QSEL_BK_0: + return RTW89_TXCH_ACH0; + case RTW89_TX_QSEL_VI_0: + case RTW89_TX_QSEL_VO_0: + return RTW89_TXCH_ACH2; + case RTW89_TX_QSEL_B0_MGMT: + case RTW89_TX_QSEL_B0_HI: + return RTW89_TXCH_CH8; + case RTW89_TX_QSEL_B1_MGMT: + case RTW89_TX_QSEL_B1_HI: + return RTW89_TXCH_CH10; + } +} +EXPORT_SYMBOL(rtw89_core_get_ch_dma_v1); + static void rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) @@ -709,10 +845,11 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev, u8 qsel, ch_dma; qsel = rtw89_core_get_qsel_mgmt(rtwdev, tx_req); - ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); + ch_dma = rtw89_chip_get_ch_dma(rtwdev, qsel); desc_info->qsel = qsel; desc_info->ch_dma = ch_dma; + desc_info->sw_mld = true; desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL; @@ -926,11 +1063,12 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev, tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; tid_indicate = rtw89_core_get_tid_indicate(rtwdev, tid); qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : rtw89_core_get_qsel(rtwdev, tid); - ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); + ch_dma = rtw89_chip_get_ch_dma(rtwdev, qsel); desc_info->ch_dma = ch_dma; desc_info->tid_indicate = tid_indicate; desc_info->qsel = qsel; + desc_info->sw_mld = false; desc_info->mac_id = rtw89_core_tx_get_mac_id(rtwdev, tx_req); desc_info->port = desc_info->hiq ? rtwvif_link->port : 0; desc_info->er_cap = rtwsta_link ? rtwsta_link->er_cap : false; @@ -993,16 +1131,66 @@ rtw89_core_tx_wake(struct rtw89_dev *rtwdev, if (!RTW89_CHK_FW_FEATURE(TX_WAKE, &rtwdev->fw)) return; - if (!test_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags)) - return; + switch (chip->chip_id) { + case RTL8852BT: + if (test_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags)) + goto notify; + break; + case RTL8852C: + if (test_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags)) + goto notify; + break; + default: + if (test_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags) && + tx_req->tx_type == RTW89_CORE_TX_TYPE_MGMT) + goto notify; + break; + } - if (chip->chip_id != RTL8852C && - tx_req->tx_type != RTW89_CORE_TX_TYPE_MGMT) - return; + return; +notify: rtw89_mac_notify_wake(rtwdev); } +static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req, + struct ieee80211_tx_info *info) +{ + const struct rtw89_hw_rate_def *hw_rate = &rtw89_hw_rate[rtwdev->chip->chip_gen]; + enum mac80211_rate_control_flags flags = info->control.rates[0].flags; + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + const struct rtw89_chan *chan; + u8 idx = info->control.rates[0].idx; + u8 nss, mcs; + + desc_info->use_rate = true; + desc_info->dis_data_fb = true; + + if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH) + desc_info->data_bw = 3; + else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + desc_info->data_bw = 2; + else if (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + desc_info->data_bw = 1; + + if (flags & IEEE80211_TX_RC_SHORT_GI) + desc_info->gi_ltf = 1; + + if (flags & IEEE80211_TX_RC_VHT_MCS) { + nss = umin(idx >> 4, ARRAY_SIZE(hw_rate->vht) - 1); + mcs = idx & 0xf; + desc_info->data_rate = hw_rate->vht[nss] + mcs; + } else if (flags & IEEE80211_TX_RC_MCS) { + desc_info->data_rate = hw_rate->ht + idx; + } else { + chan = rtw89_chan_get(rtwdev, tx_req->rtwvif_link->chanctx_idx); + + desc_info->data_rate = idx + (chan->band_type == RTW89_BAND_2G ? + RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6); + } +} + static void rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) @@ -1012,32 +1200,35 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; struct rtw89_addr_cam_entry *addr_cam; - enum rtw89_core_tx_type tx_type; enum btc_pkt_type pkt_type; bool upd_wlan_hdr = false; bool is_bmc; u16 seq; + desc_info->pkt_size = skb->len; + + if (unlikely(tx_req->tx_type == RTW89_CORE_TX_TYPE_FWCMD)) { + rtw89_core_tx_update_h2c_info(rtwdev, tx_req); + return; + } + + tx_req->tx_type = rtw89_core_get_tx_type(rtwdev, skb); + if (tx_req->sta) desc_info->mlo = tx_req->sta->mlo; else if (tx_req->vif) desc_info->mlo = ieee80211_vif_is_mld(tx_req->vif); seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - if (tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD) { - tx_type = rtw89_core_get_tx_type(rtwdev, skb); - tx_req->tx_type = tx_type; + addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link, + tx_req->rtwsta_link); + if (addr_cam->valid && desc_info->mlo) + upd_wlan_hdr = true; - addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link, - tx_req->rtwsta_link); - if (addr_cam->valid && desc_info->mlo) - upd_wlan_hdr = true; - } is_bmc = (is_broadcast_ether_addr(hdr->addr1) || is_multicast_ether_addr(hdr->addr1)); desc_info->seq = seq; - desc_info->pkt_size = skb->len; desc_info->is_bmc = is_bmc; desc_info->wd_page = true; desc_info->hiq = info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM; @@ -1054,48 +1245,54 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, rtw89_core_tx_update_ampdu_info(rtwdev, tx_req, pkt_type); rtw89_core_tx_update_llc_hdr(rtwdev, desc_info, skb); break; - case RTW89_CORE_TX_TYPE_FWCMD: - rtw89_core_tx_update_h2c_info(rtwdev, tx_req); + default: break; } + + if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) + rtw89_core_tx_update_injection(rtwdev, tx_req, info); +} + +static void rtw89_tx_wait_work(struct wiphy *wiphy, struct wiphy_work *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + tx_wait_work.work); + + rtw89_tx_wait_list_clear(rtwdev); } void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel) { u8 ch_dma; - ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); + ch_dma = rtw89_chip_get_ch_dma(rtwdev, qsel); rtw89_hci_tx_kick_off(rtwdev, ch_dma); } int rtw89_core_tx_kick_off_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, - int qsel, unsigned int timeout) + struct rtw89_tx_wait_info *wait, int qsel, + unsigned int timeout) { - struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); - struct rtw89_tx_wait_info *wait; unsigned long time_left; int ret = 0; - wait = kzalloc(sizeof(*wait), GFP_KERNEL); - if (!wait) { - rtw89_core_tx_kick_off(rtwdev, qsel); - return 0; - } - - init_completion(&wait->completion); - rcu_assign_pointer(skb_data->wait, wait); + lockdep_assert_wiphy(rtwdev->hw->wiphy); rtw89_core_tx_kick_off(rtwdev, qsel); time_left = wait_for_completion_timeout(&wait->completion, msecs_to_jiffies(timeout)); - if (time_left == 0) - ret = -ETIMEDOUT; - else if (!wait->tx_done) - ret = -EAGAIN; - rcu_assign_pointer(skb_data->wait, NULL); - kfree_rcu(wait, rcu_head); + if (time_left == 0) { + ret = -ETIMEDOUT; + list_add_tail(&wait->list, &rtwdev->tx_waits); + wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->tx_wait_work, + RTW89_TX_WAIT_WORK_TIMEOUT); + } else { + if (!wait->tx_done) + ret = -EAGAIN; + rtw89_tx_wait_release(wait); + } return ret; } @@ -1144,10 +1341,12 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev, static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, - struct sk_buff *skb, int *qsel, bool sw_mld) + struct sk_buff *skb, int *qsel, + struct rtw89_tx_wait_info *wait) { struct ieee80211_sta *sta = rtwsta_link_to_sta_safe(rtwsta_link); struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_core_tx_request tx_req = {}; int ret; @@ -1157,13 +1356,14 @@ static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev, tx_req.sta = sta; tx_req.rtwvif_link = rtwvif_link; tx_req.rtwsta_link = rtwsta_link; - tx_req.desc_info.sw_mld = sw_mld; - rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, true); - rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, true); + rtw89_traffic_stats_accu(rtwdev, rtwvif, skb, true, true); + rtw89_wow_parse_akm(rtwdev, skb); rtw89_core_tx_update_desc_info(rtwdev, &tx_req); rtw89_core_tx_wake(rtwdev, &tx_req); + rcu_assign_pointer(skb_data->wait, wait); + ret = rtw89_hci_tx_write(rtwdev, &tx_req); if (ret) { rtw89_err(rtwdev, "failed to transmit skb to HCI\n"); @@ -1200,7 +1400,7 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, } } - return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel, false); + return rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, qsel, NULL); } static __le32 rtw89_build_txwd_body0(struct rtw89_tx_desc_info *desc_info) @@ -1278,6 +1478,8 @@ static __le32 rtw89_build_txwd_body5(struct rtw89_tx_desc_info *desc_info) static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(RTW89_TXWD_BODY7_USE_RATE_V1, desc_info->use_rate) | + FIELD_PREP(RTW89_TXWD_BODY7_DATA_BW, desc_info->data_bw) | + FIELD_PREP(RTW89_TXWD_BODY7_GI_LTF, desc_info->gi_ltf) | FIELD_PREP(RTW89_TXWD_BODY7_DATA_RATE, desc_info->data_rate); return cpu_to_le32(dword); @@ -1286,6 +1488,8 @@ static __le32 rtw89_build_txwd_body7_v1(struct rtw89_tx_desc_info *desc_info) static __le32 rtw89_build_txwd_info0(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(RTW89_TXWD_INFO0_USE_RATE, desc_info->use_rate) | + FIELD_PREP(RTW89_TXWD_INFO0_DATA_BW, desc_info->data_bw) | + FIELD_PREP(RTW89_TXWD_INFO0_GI_LTF, desc_info->gi_ltf) | FIELD_PREP(RTW89_TXWD_INFO0_DATA_RATE, desc_info->data_rate) | FIELD_PREP(RTW89_TXWD_INFO0_DATA_STBC, desc_info->stbc) | FIELD_PREP(RTW89_TXWD_INFO0_DATA_LDPC, desc_info->ldpc) | @@ -1428,6 +1632,17 @@ static __le32 rtw89_build_txwd_body2_v2(struct rtw89_tx_desc_info *desc_info) return cpu_to_le32(dword); } +static __le32 rtw89_build_txwd_body2_v3(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(BE_TXD_BODY2_TID_IND_V1, desc_info->tid_indicate) | + FIELD_PREP(BE_TXD_BODY2_QSEL_V1, desc_info->qsel) | + FIELD_PREP(BE_TXD_BODY2_TXPKTSIZE, desc_info->pkt_size) | + FIELD_PREP(BE_TXD_BODY2_AGG_EN, desc_info->agg_en) | + FIELD_PREP(BE_TXD_BODY2_MACID_V1, desc_info->mac_id); + + return cpu_to_le32(dword); +} + static __le32 rtw89_build_txwd_body3_v2(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq) | @@ -1437,6 +1652,16 @@ static __le32 rtw89_build_txwd_body3_v2(struct rtw89_tx_desc_info *desc_info) return cpu_to_le32(dword); } +static __le32 rtw89_build_txwd_body3_v3(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(BE_TXD_BODY3_WIFI_SEQ, desc_info->seq) | + FIELD_PREP(BE_TXD_BODY3_MLO_FLAG, desc_info->mlo) | + FIELD_PREP(BE_TXD_BODY3_IS_MLD_SW_EN, desc_info->sw_mld) | + FIELD_PREP(BE_TXD_BODY3_BK_V1, desc_info->bk); + + return cpu_to_le32(dword); +} + static __le32 rtw89_build_txwd_body4_v2(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(BE_TXD_BODY4_SEC_IV_L0, desc_info->sec_seq[0]) | @@ -1465,6 +1690,8 @@ static __le32 rtw89_build_txwd_body6_v2(struct rtw89_tx_desc_info *desc_info) static __le32 rtw89_build_txwd_body7_v2(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(BE_TXD_BODY7_USERATE_SEL, desc_info->use_rate) | + FIELD_PREP(BE_TXD_BODY7_DATA_BW, desc_info->data_bw) | + FIELD_PREP(BE_TXD_BODY7_GI_LTF, desc_info->gi_ltf) | FIELD_PREP(BE_TXD_BODY7_DATA_ER, desc_info->er_cap) | FIELD_PREP(BE_TXD_BODY7_DATA_BW_ER, 0) | FIELD_PREP(BE_TXD_BODY7_DATARATE, desc_info->data_rate); @@ -1501,6 +1728,15 @@ static __le32 rtw89_build_txwd_info2_v2(struct rtw89_tx_desc_info *desc_info) return cpu_to_le32(dword); } +static __le32 rtw89_build_txwd_info2_v3(struct rtw89_tx_desc_info *desc_info) +{ + u32 dword = FIELD_PREP(BE_TXD_INFO2_AMPDU_DENSITY, desc_info->ampdu_density) | + FIELD_PREP(BE_TXD_INFO2_FORCE_KEY_EN_V1, desc_info->sec_en) | + FIELD_PREP(BE_TXD_INFO2_SEC_CAM_IDX_V1, desc_info->sec_cam_idx); + + return cpu_to_le32(dword); +} + static __le32 rtw89_build_txwd_info4_v2(struct rtw89_tx_desc_info *desc_info) { bool rts_en = !desc_info->is_bmc; @@ -1539,6 +1775,35 @@ void rtw89_core_fill_txdesc_v2(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_core_fill_txdesc_v2); +void rtw89_core_fill_txdesc_v3(struct rtw89_dev *rtwdev, + struct rtw89_tx_desc_info *desc_info, + void *txdesc) +{ + struct rtw89_txwd_body_v2 *txwd_body = txdesc; + struct rtw89_txwd_info_v2 *txwd_info; + + txwd_body->dword0 = rtw89_build_txwd_body0_v2(desc_info); + txwd_body->dword1 = rtw89_build_txwd_body1_v2(desc_info); + txwd_body->dword2 = rtw89_build_txwd_body2_v3(desc_info); + txwd_body->dword3 = rtw89_build_txwd_body3_v3(desc_info); + if (desc_info->sec_en) { + txwd_body->dword4 = rtw89_build_txwd_body4_v2(desc_info); + txwd_body->dword5 = rtw89_build_txwd_body5_v2(desc_info); + } + txwd_body->dword6 = rtw89_build_txwd_body6_v2(desc_info); + txwd_body->dword7 = rtw89_build_txwd_body7_v2(desc_info); + + if (!desc_info->en_wd_info) + return; + + txwd_info = (struct rtw89_txwd_info_v2 *)(txwd_body + 1); + txwd_info->dword0 = rtw89_build_txwd_info0_v2(desc_info); + txwd_info->dword1 = rtw89_build_txwd_info1_v2(desc_info); + txwd_info->dword2 = rtw89_build_txwd_info2_v3(desc_info); + txwd_info->dword4 = rtw89_build_txwd_info4_v2(desc_info); +} +EXPORT_SYMBOL(rtw89_core_fill_txdesc_v3); + static __le32 rtw89_build_txwd_fwcmd0_v1(struct rtw89_tx_desc_info *desc_info) { u32 dword = FIELD_PREP(AX_RXD_RPKT_LEN_MASK, desc_info->pkt_size) | @@ -1624,9 +1889,13 @@ static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev, /* For WiFi 7 chips, RXWD.mac_id of PPDU status is not set * by hardware, so update mac_id by rxinfo_user[].mac_id. */ - if (chip_gen == RTW89_CHIP_BE) + if (chip->chip_id == RTL8922A) phy_ppdu->mac_id = le32_get_bits(user->w0, RTW89_RXINFO_USER_MACID); + else if (chip->chip_id == RTL8922D) + phy_ppdu->mac_id = + le32_get_bits(user->w0, RTW89_RXINFO_USER_MACID_V1); + phy_ppdu->has_data = le32_get_bits(user->w0, RTW89_RXINFO_USER_DATA); phy_ppdu->has_bcn = @@ -1822,6 +2091,10 @@ static void rtw89_core_parse_phy_status_ie00(struct rtw89_dev *rtwdev, tmp_rpl = le32_get_bits(ie->w0, RTW89_PHY_STS_IE00_W0_RPL); phy_ppdu->rpl_avg = tmp_rpl >> 1; + + if (!phy_ppdu->hdr_2_en) + phy_ppdu->rx_path_en = + le32_get_bits(ie->w3, RTW89_PHY_STS_IE00_W3_RX_PATH_EN); } static void rtw89_core_parse_phy_status_ie00_v2(struct rtw89_dev *rtwdev, @@ -2208,6 +2481,437 @@ static void rtw89_vif_sync_bcn_tsf(struct rtw89_vif_link *rtwvif_link, WRITE_ONCE(rtwvif_link->sync_bcn_tsf, le64_to_cpu(mgmt->u.beacon.timestamp)); } +static u32 rtw89_bcn_calc_min_tbtt(struct rtw89_dev *rtwdev, u32 tbtt1, u32 tbtt2) +{ + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + u32 close_bcn_intvl_th = bcn_track->close_bcn_intvl_th; + u32 tbtt_diff_th = bcn_track->tbtt_diff_th; + + if (tbtt2 > tbtt1) + swap(tbtt1, tbtt2); + + if (tbtt1 - tbtt2 > tbtt_diff_th) + return tbtt1; + else if (tbtt2 > close_bcn_intvl_th) + return tbtt2; + else if (tbtt1 > close_bcn_intvl_th) + return tbtt1; + else + return tbtt2; +} + +static void rtw89_bcn_cfg_tbtt_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + u32 offset = bcn_track->tbtt_offset; + + if (chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + u32 bcnspc, val; + + bcnspc = rtw89_read32_port_mask(rtwdev, rtwvif_link, + p->bcn_space, B_AX_BCN_SPACE_MASK); + val = bcnspc - (offset / 1024); + val = u32_encode_bits(val, B_AX_TBTT_SHIFT_OFST_MAG) | + B_AX_TBTT_SHIFT_OFST_SIGN; + + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_shift, + B_AX_TBTT_SHIFT_OFST_MASK, val); + + return; + } + + rtw89_fw_h2c_tbtt_tuning(rtwdev, rtwvif_link, offset); +} + +static void rtw89_bcn_update_tbtt_offset(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + u32 *tbtt_us = bcn_stat->tbtt_us; + u32 offset = tbtt_us[0]; + u8 i; + + for (i = 1; i < RTW89_BCN_TRACK_STAT_NR; i++) + offset = rtw89_bcn_calc_min_tbtt(rtwdev, tbtt_us[i], offset); + + if (bcn_track->tbtt_offset == offset) + return; + + bcn_track->tbtt_offset = offset; + rtw89_bcn_cfg_tbtt_offset(rtwdev, rtwvif_link); +} + +static int cmp_u16(const void *a, const void *b) +{ + return *(const u16 *)a - *(const u16 *)b; +} + +static u16 _rtw89_bcn_calc_drift(u16 tbtt, u16 offset, u16 beacon_int) +{ + if (tbtt < offset) + return beacon_int - offset + tbtt; + + return tbtt - offset; +} + +static void rtw89_bcn_calc_drift(struct rtw89_dev *rtwdev) +{ + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + u16 offset_tu = bcn_track->tbtt_offset / 1024; + u16 *tbtt_tu = bcn_stat->tbtt_tu; + u16 *drift = bcn_stat->drift; + u8 i; + + bcn_stat->tbtt_tu_min = U16_MAX; + bcn_stat->tbtt_tu_max = 0; + for (i = 0; i < RTW89_BCN_TRACK_STAT_NR; i++) { + drift[i] = _rtw89_bcn_calc_drift(tbtt_tu[i], offset_tu, + bcn_track->beacon_int); + + bcn_stat->tbtt_tu_min = min(bcn_stat->tbtt_tu_min, tbtt_tu[i]); + bcn_stat->tbtt_tu_max = max(bcn_stat->tbtt_tu_max, tbtt_tu[i]); + } + + sort(drift, RTW89_BCN_TRACK_STAT_NR, sizeof(*drift), cmp_u16, NULL); +} + +static void rtw89_bcn_calc_distribution(struct rtw89_dev *rtwdev) +{ + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_dist *bcn_dist = &bcn_stat->bcn_dist; + u16 lower_bound, upper_bound, outlier_count = 0; + u16 *drift = bcn_stat->drift; + u16 *bins = bcn_dist->bins; + u16 q1, q3, iqr, tmp; + u8 i; + + BUILD_BUG_ON(RTW89_BCN_TRACK_STAT_NR % 4 != 0); + + memset(bcn_dist, 0, sizeof(*bcn_dist)); + + bcn_dist->min = drift[0]; + bcn_dist->max = drift[RTW89_BCN_TRACK_STAT_NR - 1]; + + tmp = RTW89_BCN_TRACK_STAT_NR / 4; + q1 = ((drift[tmp] + drift[tmp - 1]) * RTW89_BCN_TRACK_SCALE_FACTOR) / 2; + + tmp = (RTW89_BCN_TRACK_STAT_NR * 3) / 4; + q3 = ((drift[tmp] + drift[tmp - 1]) * RTW89_BCN_TRACK_SCALE_FACTOR) / 2; + + iqr = q3 - q1; + tmp = (3 * iqr) / 2; + + if (bcn_dist->min <= 5) + lower_bound = bcn_dist->min; + else if (q1 > tmp) + lower_bound = (q1 - tmp) / RTW89_BCN_TRACK_SCALE_FACTOR; + else + lower_bound = 0; + + upper_bound = (q3 + tmp) / RTW89_BCN_TRACK_SCALE_FACTOR; + + for (i = 0; i < RTW89_BCN_TRACK_STAT_NR; i++) { + u16 tbtt = bcn_stat->tbtt_tu[i]; + u16 min = bcn_stat->tbtt_tu_min; + u8 bin_idx; + + /* histogram */ + bin_idx = min((tbtt - min) / RTW89_BCN_TRACK_BIN_WIDTH, + RTW89_BCN_TRACK_MAX_BIN_NUM - 1); + bins[bin_idx]++; + + /* boxplot outlier */ + if (drift[i] < lower_bound || drift[i] > upper_bound) + outlier_count++; + } + + bcn_dist->outlier_count = outlier_count; + bcn_dist->lower_bound = lower_bound; + bcn_dist->upper_bound = upper_bound; +} + +static u8 rtw89_bcn_get_coverage(struct rtw89_dev *rtwdev, u16 threshold) +{ + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + int l = 0, r = RTW89_BCN_TRACK_STAT_NR - 1, m; + u16 *drift = bcn_stat->drift; + int index = -1; + u8 count = 0; + + while (l <= r) { + m = l + (r - l) / 2; + + if (drift[m] <= threshold) { + index = m; + l = m + 1; + } else { + r = m - 1; + } + } + + count = (index == -1) ? 0 : (index + 1); + + return (count * PERCENT) / RTW89_BCN_TRACK_STAT_NR; +} + +static u16 rtw89_bcn_get_histogram_bound(struct rtw89_dev *rtwdev, u8 target) +{ + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_dist *bcn_dist = &bcn_stat->bcn_dist; + u16 tbtt_tu_max = bcn_stat->tbtt_tu_max; + u16 upper, lower = bcn_stat->tbtt_tu_min; + u8 i, count = 0; + + for (i = 0; i < RTW89_BCN_TRACK_MAX_BIN_NUM; i++) { + upper = lower + RTW89_BCN_TRACK_BIN_WIDTH - 1; + if (i == RTW89_BCN_TRACK_MAX_BIN_NUM - 1) + upper = max(upper, tbtt_tu_max); + + count += bcn_dist->bins[i]; + if (count > target) + break; + + lower = upper + 1; + } + + return upper; +} + +static u16 rtw89_bcn_get_rx_time(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ +#define RTW89_SYMBOL_TIME_2GHZ 192 +#define RTW89_SYMBOL_TIME_5GHZ 20 +#define RTW89_SYMBOL_TIME_6GHZ 20 + struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; + u16 bitrate, val; + + if (!rtw89_legacy_rate_to_bitrate(rtwdev, pkt_stat->beacon_rate, &bitrate)) + return 0; + + val = (pkt_stat->beacon_len * 8 * RTW89_BCN_TRACK_SCALE_FACTOR) / bitrate; + + switch (chan->band_type) { + default: + case RTW89_BAND_2G: + val += RTW89_SYMBOL_TIME_2GHZ; + break; + case RTW89_BAND_5G: + val += RTW89_SYMBOL_TIME_5GHZ; + break; + case RTW89_BAND_6G: + val += RTW89_SYMBOL_TIME_6GHZ; + break; + } + + /* convert to millisecond */ + return DIV_ROUND_UP(val, 1000); +} + +static void rtw89_bcn_calc_timeout(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ +#define RTW89_BCN_TRACK_EXTEND_TIMEOUT 5 +#define RTW89_BCN_TRACK_COVERAGE_TH 0 /* unit: TU */ +#define RTW89_BCN_TRACK_STRONG_RSSI 80 + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat; + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + struct rtw89_beacon_dist *bcn_dist = &bcn_stat->bcn_dist; + u16 outlier_high_bcn_th = bcn_track->outlier_high_bcn_th; + u16 outlier_low_bcn_th = bcn_track->outlier_low_bcn_th; + u8 rssi = ewma_rssi_read(&rtwdev->phystat.bcn_rssi); + u16 target_bcn_th = bcn_track->target_bcn_th; + u16 low_bcn_th = bcn_track->low_bcn_th; + u16 med_bcn_th = bcn_track->med_bcn_th; + u16 beacon_int = bcn_track->beacon_int; + u16 bcn_timeout; + + if (pkt_stat->beacon_nr < low_bcn_th) { + bcn_timeout = (RTW89_BCN_TRACK_TARGET_BCN * beacon_int) / PERCENT; + goto out; + } + + if (bcn_dist->outlier_count >= outlier_high_bcn_th) { + bcn_timeout = bcn_dist->max; + goto out; + } + + if (pkt_stat->beacon_nr < med_bcn_th) { + if (bcn_dist->outlier_count > outlier_low_bcn_th) + bcn_timeout = (bcn_dist->max + bcn_dist->upper_bound) / 2; + else + bcn_timeout = bcn_dist->upper_bound + + RTW89_BCN_TRACK_EXTEND_TIMEOUT; + + goto out; + } + + if (rssi >= RTW89_BCN_TRACK_STRONG_RSSI) { + if (rtw89_bcn_get_coverage(rtwdev, RTW89_BCN_TRACK_COVERAGE_TH) >= 90) { + /* ideal case */ + bcn_timeout = 0; + } else { + u16 offset_tu = bcn_track->tbtt_offset / 1024; + u16 upper_bound; + + upper_bound = + rtw89_bcn_get_histogram_bound(rtwdev, target_bcn_th); + bcn_timeout = + _rtw89_bcn_calc_drift(upper_bound, offset_tu, beacon_int); + } + + goto out; + } + + bcn_timeout = bcn_stat->drift[target_bcn_th]; + +out: + bcn_track->bcn_timeout = bcn_timeout + rtw89_bcn_get_rx_time(rtwdev, chan); +} + +static void rtw89_bcn_update_timeout(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + rtw89_bcn_calc_drift(rtwdev); + rtw89_bcn_calc_distribution(rtwdev); + rtw89_bcn_calc_timeout(rtwdev, rtwvif_link); +} + +static void rtw89_core_bcn_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_vif *rtwvif; + unsigned int link_id; + + if (!RTW89_CHK_FW_FEATURE(BEACON_TRACKING, &rtwdev->fw)) + return; + + if (!rtwdev->lps_enabled) + return; + + if (!bcn_track->is_data_ready) + return; + + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + if (!(rtwvif_link->wifi_role == RTW89_WIFI_ROLE_STATION || + rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)) + continue; + + rtw89_bcn_update_tbtt_offset(rtwdev, rtwvif_link); + rtw89_bcn_update_timeout(rtwdev, rtwvif_link); + } + } +} + +static bool rtw89_core_bcn_track_can_lps(struct rtw89_dev *rtwdev) +{ + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + + if (!RTW89_CHK_FW_FEATURE(BEACON_TRACKING, &rtwdev->fw)) + return true; + + return bcn_track->is_data_ready; +} + +static void rtw89_core_bcn_track_assoc(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ +#define RTW89_BCN_TRACK_MED_BCN 70 +#define RTW89_BCN_TRACK_LOW_BCN 30 +#define RTW89_BCN_TRACK_OUTLIER_HIGH_BCN 30 +#define RTW89_BCN_TRACK_OUTLIER_LOW_BCN 20 + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + u32 period = jiffies_to_msecs(RTW89_TRACK_WORK_PERIOD); + struct ieee80211_bss_conf *bss_conf; + u32 beacons_in_period; + u32 bcn_intvl_us; + u16 beacon_int; + u8 dtim; + + rcu_read_lock(); + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + beacon_int = bss_conf->beacon_int ?: 100; + dtim = bss_conf->dtim_period; + rcu_read_unlock(); + + beacons_in_period = period / beacon_int / dtim; + bcn_intvl_us = ieee80211_tu_to_usec(beacon_int); + + bcn_track->low_bcn_th = + (beacons_in_period * RTW89_BCN_TRACK_LOW_BCN) / PERCENT; + bcn_track->med_bcn_th = + (beacons_in_period * RTW89_BCN_TRACK_MED_BCN) / PERCENT; + bcn_track->outlier_low_bcn_th = + (RTW89_BCN_TRACK_STAT_NR * RTW89_BCN_TRACK_OUTLIER_LOW_BCN) / PERCENT; + bcn_track->outlier_high_bcn_th = + (RTW89_BCN_TRACK_STAT_NR * RTW89_BCN_TRACK_OUTLIER_HIGH_BCN) / PERCENT; + bcn_track->target_bcn_th = + (RTW89_BCN_TRACK_STAT_NR * RTW89_BCN_TRACK_TARGET_BCN) / PERCENT; + + bcn_track->close_bcn_intvl_th = ieee80211_tu_to_usec(beacon_int - 3); + bcn_track->tbtt_diff_th = (bcn_intvl_us * 85) / PERCENT; + bcn_track->beacon_int = beacon_int; + bcn_track->dtim = dtim; +} + +static void rtw89_core_bcn_track_reset(struct rtw89_dev *rtwdev) +{ + memset(&rtwdev->phystat.bcn_stat, 0, sizeof(rtwdev->phystat.bcn_stat)); + memset(&rtwdev->bcn_track, 0, sizeof(rtwdev->bcn_track)); +} + +static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev, struct sk_buff *skb) +{ +#define RTW89_APPEND_TSF_2GHZ 384 +#define RTW89_APPEND_TSF_5GHZ 52 +#define RTW89_APPEND_TSF_6GHZ 52 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + u32 bcn_intvl_us = ieee80211_tu_to_usec(bcn_track->beacon_int); + u64 tsf = le64_to_cpu(mgmt->u.beacon.timestamp); + u8 wp, num = bcn_stat->num; + u16 append; + + if (!RTW89_CHK_FW_FEATURE(BEACON_TRACKING, &rtwdev->fw)) + return; + + /* Skip if not yet associated */ + if (!bcn_intvl_us) + return; + + switch (rx_status->band) { + default: + case NL80211_BAND_2GHZ: + append = RTW89_APPEND_TSF_2GHZ; + break; + case NL80211_BAND_5GHZ: + append = RTW89_APPEND_TSF_5GHZ; + break; + case NL80211_BAND_6GHZ: + append = RTW89_APPEND_TSF_6GHZ; + break; + } + + wp = bcn_stat->wp; + div_u64_rem(tsf - append, bcn_intvl_us, &bcn_stat->tbtt_us[wp]); + bcn_stat->tbtt_tu[wp] = bcn_stat->tbtt_us[wp] / 1024; + bcn_stat->wp = (wp + 1) % RTW89_BCN_TRACK_STAT_NR; + bcn_stat->num = umin(num + 1, RTW89_BCN_TRACK_STAT_NR); + bcn_track->is_data_ready = bcn_stat->num == RTW89_BCN_TRACK_STAT_NR; +} + static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { @@ -2224,6 +2928,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, struct ieee80211_bss_conf *bss_conf; struct rtw89_vif_link *rtwvif_link; const u8 *bssid = iter_data->bssid; + const u8 *target_bssid; if (rtwdev->scanning && (ieee80211_is_beacon(hdr->frame_control) || @@ -2245,7 +2950,10 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, goto out; } - if (!ether_addr_equal(bss_conf->bssid, bssid)) + target_bssid = ieee80211_is_beacon(hdr->frame_control) && + bss_conf->nontransmitted ? + bss_conf->transmitter_bssid : bss_conf->bssid; + if (!ether_addr_equal(target_bssid, bssid)) goto out; if (is_mld) { @@ -2259,7 +2967,6 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, rtw89_vif_sync_bcn_tsf(rtwvif_link, hdr, skb->len); rtw89_fw_h2c_rssi_offload(rtwdev, phy_ppdu); } - pkt_stat->beacon_nr++; if (phy_ppdu) { ewma_rssi_add(&rtwdev->phystat.bcn_rssi, phy_ppdu->rssi_avg); @@ -2267,7 +2974,11 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, rtwvif_link->bcn_bw_idx = phy_ppdu->bw_idx; } + pkt_stat->beacon_nr++; pkt_stat->beacon_rate = desc_info->data_rate; + pkt_stat->beacon_len = skb->len; + + rtw89_vif_rx_bcn_stat(rtwdev, skb); } if (!ether_addr_equal(bss_conf->addr, hdr->addr1)) @@ -2276,7 +2987,7 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac, if (desc_info->data_rate < RTW89_HW_RATE_NR) pkt_stat->rx_rate_cnt[desc_info->data_rate]++; - rtw89_traffic_stats_accu(rtwdev, &rtwvif->stats, skb, false); + rtw89_traffic_stats_accu(rtwdev, rtwvif, skb, false, false); out: rcu_read_unlock(); @@ -2289,7 +3000,7 @@ static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev, { struct rtw89_vif_rx_stats_iter_data iter_data; - rtw89_traffic_stats_accu(rtwdev, &rtwdev->stats, skb, false); + rtw89_traffic_stats_accu(rtwdev, NULL, skb, true, false); iter_data.rtwdev = rtwdev; iter_data.phy_ppdu = phy_ppdu; @@ -2754,6 +3465,79 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_core_query_rxdesc_v2); +void rtw89_core_query_rxdesc_v3(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + u8 *data, u32 data_offset) +{ + struct rtw89_rxdesc_phy_rpt_v2 *rxd_rpt; + struct rtw89_rxdesc_short_v3 *rxd_s; + struct rtw89_rxdesc_long_v3 *rxd_l; + u16 shift_len, drv_info_len, phy_rtp_len, hdr_cnv_len; + + rxd_s = (struct rtw89_rxdesc_short_v3 *)(data + data_offset); + + desc_info->pkt_size = le32_get_bits(rxd_s->dword0, BE_RXD_RPKT_LEN_MASK); + desc_info->drv_info_size = le32_get_bits(rxd_s->dword0, BE_RXD_DRV_INFO_SZ_MASK); + desc_info->phy_rpt_size = le32_get_bits(rxd_s->dword0, BE_RXD_PHY_RPT_SZ_MASK); + desc_info->hdr_cnv_size = le32_get_bits(rxd_s->dword0, BE_RXD_HDR_CNV_SZ_MASK); + desc_info->shift = le32_get_bits(rxd_s->dword0, BE_RXD_SHIFT_MASK); + desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, BE_RXD_LONG_RXD); + desc_info->pkt_type = le32_get_bits(rxd_s->dword0, BE_RXD_RPKT_TYPE_MASK); + desc_info->bb_sel = le32_get_bits(rxd_s->dword0, BE_RXD_BB_SEL); + if (desc_info->pkt_type == RTW89_CORE_RX_TYPE_PPDU_STAT) + desc_info->mac_info_valid = true; + + desc_info->frame_type = le32_get_bits(rxd_s->dword2, BE_RXD_TYPE_MASK); + desc_info->mac_id = le32_get_bits(rxd_s->dword2, BE_RXD_MAC_ID_V1); + desc_info->addr_cam_valid = le32_get_bits(rxd_s->dword2, BE_RXD_ADDR_CAM_VLD); + + desc_info->icv_err = le32_get_bits(rxd_s->dword3, BE_RXD_ICV_ERR); + desc_info->crc32_err = le32_get_bits(rxd_s->dword3, BE_RXD_CRC32_ERR); + desc_info->hw_dec = le32_get_bits(rxd_s->dword3, BE_RXD_HW_DEC); + desc_info->sw_dec = le32_get_bits(rxd_s->dword3, BE_RXD_SW_DEC); + desc_info->addr1_match = le32_get_bits(rxd_s->dword3, BE_RXD_A1_MATCH); + + desc_info->bw = le32_get_bits(rxd_s->dword4, BE_RXD_BW_MASK); + desc_info->data_rate = le32_get_bits(rxd_s->dword4, BE_RXD_RX_DATARATE_MASK); + desc_info->gi_ltf = le32_get_bits(rxd_s->dword4, BE_RXD_RX_GI_LTF_MASK); + desc_info->ppdu_cnt = le32_get_bits(rxd_s->dword4, BE_RXD_PPDU_CNT_MASK); + desc_info->ppdu_type = le32_get_bits(rxd_s->dword4, BE_RXD_PPDU_TYPE_MASK); + + desc_info->free_run_cnt = le32_to_cpu(rxd_s->dword5); + + shift_len = desc_info->shift << 1; /* 2-byte unit */ + drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */ + phy_rtp_len = desc_info->phy_rpt_size << 3; /* 8-byte unit */ + hdr_cnv_len = desc_info->hdr_cnv_size << 4; /* 16-byte unit */ + desc_info->offset = data_offset + shift_len + drv_info_len + + phy_rtp_len + hdr_cnv_len; + + if (desc_info->long_rxdesc) + desc_info->rxd_len = sizeof(struct rtw89_rxdesc_long_v3); + else + desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short_v3); + desc_info->ready = true; + + if (phy_rtp_len == sizeof(*rxd_rpt)) { + rxd_rpt = (struct rtw89_rxdesc_phy_rpt_v2 *)(data + data_offset + + desc_info->rxd_len); + desc_info->rssi = le32_get_bits(rxd_rpt->dword0, BE_RXD_PHY_RSSI); + } + + if (!desc_info->long_rxdesc) + return; + + rxd_l = (struct rtw89_rxdesc_long_v3 *)(data + data_offset); + + desc_info->sr_en = le32_get_bits(rxd_l->dword6, BE_RXD_SR_EN); + desc_info->user_id = le32_get_bits(rxd_l->dword6, BE_RXD_USER_ID_MASK); + desc_info->addr_cam_id = le32_get_bits(rxd_l->dword6, BE_RXD_ADDR_CAM_V1); + desc_info->sec_cam_id = le32_get_bits(rxd_l->dword6, BE_RXD_SEC_CAM_IDX_V1); + + desc_info->rx_pl_id = le32_get_bits(rxd_l->dword7, BE_RXD_RX_PL_ID_MASK); +} +EXPORT_SYMBOL(rtw89_core_query_rxdesc_v3); + struct rtw89_core_iter_rx_status { struct rtw89_dev *rtwdev; struct ieee80211_rx_status *rx_status; @@ -3124,12 +3908,10 @@ void rtw89_core_free_sta_pending_roc_tx(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta) { struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); - struct sk_buff *skb, *tmp; + struct sk_buff *skb; - skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { - skb_unlink(skb, &rtwsta->roc_queue); + while ((skb = skb_dequeue(&rtwsta->roc_queue))) dev_kfree_skb_any(skb); - } } static void rtw89_core_stop_tx_ba_session(struct rtw89_dev *rtwdev, @@ -3229,7 +4011,7 @@ static u32 rtw89_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, u8 tid) u8 qsel, ch_dma; qsel = rtw89_core_get_qsel(rtwdev, tid); - ch_dma = rtw89_core_get_ch_dma(rtwdev, qsel); + ch_dma = rtw89_chip_get_ch_dma(rtwdev, qsel); return rtw89_hci_check_and_reclaim_tx_resource(rtwdev, ch_dma); } @@ -3373,8 +4155,8 @@ static void rtw89_core_sta_pending_tx_iter(void *data, struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); struct rtw89_vif_link *target = data; struct rtw89_vif_link *rtwvif_link; - struct sk_buff *skb, *tmp; unsigned int link_id; + struct sk_buff *skb; int qsel, ret; rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) @@ -3387,9 +4169,7 @@ static void rtw89_core_sta_pending_tx_iter(void *data, if (skb_queue_len(&rtwsta->roc_queue) == 0) return; - skb_queue_walk_safe(&rtwsta->roc_queue, skb, tmp) { - skb_unlink(skb, &rtwsta->roc_queue); - + while ((skb = skb_dequeue(&rtwsta->roc_queue))) { ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel); if (ret) { rtw89_warn(rtwdev, "pending tx failed with %d\n", ret); @@ -3414,6 +4194,7 @@ int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1; struct rtw89_sta_link *rtwsta_link; + struct rtw89_tx_wait_info *wait; struct ieee80211_sta *sta; struct ieee80211_hdr *hdr; struct rtw89_sta *rtwsta; @@ -3423,6 +4204,12 @@ int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc) return 0; + wait = kzalloc(sizeof(*wait), GFP_KERNEL); + if (!wait) + return -ENOMEM; + + init_completion(&wait->completion); + rcu_read_lock(); sta = ieee80211_find_sta(vif, vif->cfg.ap_addr); if (!sta) { @@ -3437,6 +4224,8 @@ int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt goto out; } + wait->skb = skb; + hdr = (struct ieee80211_hdr *)skb->data; if (ps) hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); @@ -3448,7 +4237,7 @@ int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt goto out; } - ret = rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, &qsel, true); + ret = rtw89_core_tx_write_link(rtwdev, rtwvif_link, rtwsta_link, skb, &qsel, wait); if (ret) { rtw89_warn(rtwdev, "nullfunc transmit failed: %d\n", ret); dev_kfree_skb_any(skb); @@ -3457,10 +4246,11 @@ int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt rcu_read_unlock(); - return rtw89_core_tx_kick_off_and_wait(rtwdev, skb, qsel, + return rtw89_core_tx_kick_off_and_wait(rtwdev, skb, wait, qsel, timeout); out: rcu_read_unlock(); + kfree(wait); return ret; } @@ -3528,12 +4318,10 @@ void rtw89_roc_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct ieee80211_hw *hw = rtwdev->hw; struct rtw89_roc *roc = &rtwvif->roc; struct rtw89_vif_link *rtwvif_link; struct rtw89_vif *tmp_vif; - u32 reg; int ret; lockdep_assert_wiphy(hw->wiphy); @@ -3550,8 +4338,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) return; } - reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); - rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, rtwvif_link->mac_idx, rtwdev->hal.rx_fltr); roc->state = RTW89_ROC_IDLE; rtw89_config_roc_chandef(rtwdev, rtwvif_link, NULL); @@ -3596,9 +4383,22 @@ void rtw89_roc_work(struct wiphy *wiphy, struct wiphy_work *work) } static enum rtw89_tfc_lv rtw89_get_traffic_level(struct rtw89_dev *rtwdev, - u32 throughput, u64 cnt) + u32 throughput, u64 cnt, + enum rtw89_tfc_interval interval) { - if (cnt < 100) + u64 cnt_level; + + switch (interval) { + default: + case RTW89_TFC_INTERVAL_100MS: + cnt_level = 5; + break; + case RTW89_TFC_INTERVAL_2SEC: + cnt_level = 100; + break; + } + + if (cnt < cnt_level) return RTW89_TFC_IDLE; if (throughput > 50) return RTW89_TFC_HIGH; @@ -3610,13 +4410,14 @@ static enum rtw89_tfc_lv rtw89_get_traffic_level(struct rtw89_dev *rtwdev, } static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, - struct rtw89_traffic_stats *stats) + struct rtw89_traffic_stats *stats, + enum rtw89_tfc_interval interval) { enum rtw89_tfc_lv tx_tfc_lv = stats->tx_tfc_lv; enum rtw89_tfc_lv rx_tfc_lv = stats->rx_tfc_lv; - stats->tx_throughput_raw = (u32)(stats->tx_unicast >> RTW89_TP_SHIFT); - stats->rx_throughput_raw = (u32)(stats->rx_unicast >> RTW89_TP_SHIFT); + stats->tx_throughput_raw = rtw89_bytes_to_mbps(stats->tx_unicast, interval); + stats->rx_throughput_raw = rtw89_bytes_to_mbps(stats->rx_unicast, interval); ewma_tp_add(&stats->tx_ewma_tp, stats->tx_throughput_raw); ewma_tp_add(&stats->rx_ewma_tp, stats->rx_throughput_raw); @@ -3624,9 +4425,9 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp); stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp); stats->tx_tfc_lv = rtw89_get_traffic_level(rtwdev, stats->tx_throughput, - stats->tx_cnt); + stats->tx_cnt, interval); stats->rx_tfc_lv = rtw89_get_traffic_level(rtwdev, stats->rx_throughput, - stats->rx_cnt); + stats->rx_cnt, interval); stats->tx_avg_len = stats->tx_cnt ? DIV_ROUND_DOWN_ULL(stats->tx_unicast, stats->tx_cnt) : 0; stats->rx_avg_len = stats->rx_cnt ? @@ -3652,10 +4453,12 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) unsigned int link_id; bool tfc_changed; - tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats); + tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats, + RTW89_TFC_INTERVAL_2SEC); rtw89_for_each_rtwvif(rtwdev, rtwvif) { - rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats); + rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats, + RTW89_TFC_INTERVAL_2SEC); rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); @@ -3675,8 +4478,8 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) if (rtwvif->offchan) continue; - if (rtwvif->stats.tx_tfc_lv != RTW89_TFC_IDLE || - rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE) + if (rtwvif->stats_ps.tx_tfc_lv >= RTW89_TFC_MID || + rtwvif->stats_ps.rx_tfc_lv >= RTW89_TFC_MID) continue; vif = rtwvif_to_vif(rtwvif); @@ -3685,6 +4488,9 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) vif->type == NL80211_IFTYPE_P2P_CLIENT)) continue; + if (!rtw89_core_bcn_track_can_lps(rtwdev)) + continue; + rtw89_enter_lps(rtwdev, rtwvif, true); } } @@ -3815,6 +4621,34 @@ static void rtw89_core_mlo_track(struct rtw89_dev *rtwdev) } } +static void rtw89_track_ps_work(struct wiphy *wiphy, struct wiphy_work *work) +{ + struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, + track_ps_work.work); + struct rtw89_vif *rtwvif; + + lockdep_assert_wiphy(wiphy); + + if (test_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags)) + return; + + if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) + return; + + wiphy_delayed_work_queue(wiphy, &rtwdev->track_ps_work, + RTW89_TRACK_PS_WORK_PERIOD); + + rtw89_for_each_rtwvif(rtwdev, rtwvif) + rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats_ps, + RTW89_TFC_INTERVAL_100MS); + + if (rtwdev->scanning) + return; + + if (rtwdev->lps_enabled && !rtwdev->btc.lps) + rtw89_enter_lps_track(rtwdev); +} + static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work) { struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, @@ -3843,6 +4677,7 @@ static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work) rtw89_btc_ntfy_wl_sta(rtwdev); } rtw89_mac_bf_monitor_track(rtwdev); + rtw89_core_bcn_track(rtwdev); rtw89_phy_stat_track(rtwdev); rtw89_phy_env_monitor_track(rtwdev); rtw89_phy_dig(rtwdev); @@ -4054,6 +4889,7 @@ int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev, &rtwsta_link->tx_retry); rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, 60); } + rtw89_phy_dig_suspend(rtwdev); } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false); if (ret) { @@ -4088,8 +4924,10 @@ int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev, rtw89_assoc_link_clr(rtwsta_link); - if (vif->type == NL80211_IFTYPE_STATION) + if (vif->type == NL80211_IFTYPE_STATION) { rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false); + rtw89_core_bcn_track_reset(rtwdev); + } if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT) rtw89_p2p_noa_once_deinit(rtwvif_link); @@ -4131,7 +4969,8 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev, } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_CON_DISCONN); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -4205,7 +5044,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, } /* update cam aid mac_id net_type */ - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_CON_DISCONN); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -4230,6 +5070,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, BTC_ROLE_MSTS_STA_CONN_END); rtw89_core_get_no_ul_ofdma_htc(rtwdev, &rtwsta_link->htc_template, chan); rtw89_phy_ul_tb_assoc(rtwdev, rtwvif_link); + rtw89_core_bcn_track_assoc(rtwdev, rtwvif_link); ret = rtw89_fw_h2c_general_pkt(rtwdev, rtwvif_link, rtwsta_link->mac_id); if (ret) { @@ -4242,6 +5083,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev, if (vif->p2p) rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, rtwsta_link->tx_retry); + rtw89_phy_dig_resume(rtwdev, false); } rtw89_assoc_link_set(rtwsta_link); @@ -4388,7 +5230,7 @@ static void rtw89_init_vht_cap(struct rtw89_dev *rtwdev, } vht_cap->vht_supported = true; - vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + vht_cap->cap = chip->max_vht_mpdu_cap | IEEE80211_VHT_CAP_SHORT_GI_80 | IEEE80211_VHT_CAP_RXSTBC_1 | IEEE80211_VHT_CAP_HTC_VHT | @@ -4516,7 +5358,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev, IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) | le16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K, IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) | - le16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + le16_encode_bits(chip->max_vht_mpdu_cap, IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN); iftype_data->he_6ghz_capa.capa = capa; } @@ -4537,7 +5379,7 @@ static void rtw89_init_eht_cap(struct rtw89_dev *rtwdev, u8 val, val_mcs13; int sts = 8; - if (chip->chip_gen == RTW89_CHIP_AX) + if (chip->chip_gen == RTW89_CHIP_AX || hal->no_eht) return; if (hal->no_mcs_12_13) @@ -4554,7 +5396,7 @@ static void rtw89_init_eht_cap(struct rtw89_dev *rtwdev, eht_cap->has_eht = true; eht_cap_elem->mac_cap_info[0] = - u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991, + u8_encode_bits(chip->max_eht_mpdu_cap, IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK); eht_cap_elem->mac_cap_info[1] = 0; @@ -4819,39 +5661,96 @@ void rtw89_core_csa_beacon_work(struct wiphy *wiphy, struct wiphy_work *work) } } -int rtw89_wait_for_cond(struct rtw89_wait_info *wait, unsigned int cond) +struct rtw89_wait_response * +rtw89_wait_for_cond_prep(struct rtw89_wait_info *wait, unsigned int cond) { - struct completion *cmpl = &wait->completion; - unsigned long time_left; + struct rtw89_wait_response *prep; unsigned int cur; + /* use -EPERM _iff_ telling eval side not to make any changes */ + cur = atomic_cmpxchg(&wait->cond, RTW89_WAIT_COND_IDLE, cond); if (cur != RTW89_WAIT_COND_IDLE) - return -EBUSY; + return ERR_PTR(-EPERM); + + prep = kzalloc(sizeof(*prep), GFP_KERNEL); + if (!prep) + return ERR_PTR(-ENOMEM); + + init_completion(&prep->completion); + + rcu_assign_pointer(wait->resp, prep); - time_left = wait_for_completion_timeout(cmpl, RTW89_WAIT_FOR_COND_TIMEOUT); + return prep; +} + +int rtw89_wait_for_cond_eval(struct rtw89_wait_info *wait, + struct rtw89_wait_response *prep, int err) +{ + unsigned long time_left; + + if (IS_ERR(prep)) { + err = err ?: PTR_ERR(prep); + + /* special error case: no permission to reset anything */ + if (PTR_ERR(prep) == -EPERM) + return err; + + goto reset; + } + + if (err) + goto cleanup; + + time_left = wait_for_completion_timeout(&prep->completion, + RTW89_WAIT_FOR_COND_TIMEOUT); if (time_left == 0) { - atomic_set(&wait->cond, RTW89_WAIT_COND_IDLE); - return -ETIMEDOUT; + err = -ETIMEDOUT; + goto cleanup; } + wait->data = prep->data; + +cleanup: + rcu_assign_pointer(wait->resp, NULL); + kfree_rcu(prep, rcu_head); + +reset: + atomic_set(&wait->cond, RTW89_WAIT_COND_IDLE); + + if (err) + return err; + if (wait->data.err) return -EFAULT; return 0; } +static void rtw89_complete_cond_resp(struct rtw89_wait_response *resp, + const struct rtw89_completion_data *data) +{ + resp->data = *data; + complete(&resp->completion); +} + void rtw89_complete_cond(struct rtw89_wait_info *wait, unsigned int cond, const struct rtw89_completion_data *data) { + struct rtw89_wait_response *resp; unsigned int cur; + guard(rcu)(); + + resp = rcu_dereference(wait->resp); + if (!resp) + return; + cur = atomic_cmpxchg(&wait->cond, cond, RTW89_WAIT_COND_IDLE); if (cur != cond) return; - wait->data = *data; - complete(&wait->completion); + rtw89_complete_cond_resp(resp, data); } void rtw89_core_ntfy_btc_event(struct rtw89_dev *rtwdev, enum rtw89_btc_hmsg event) @@ -4896,8 +5795,22 @@ EXPORT_SYMBOL(rtw89_check_quirks); int rtw89_core_start(struct rtw89_dev *rtwdev) { + bool no_bbmcu = !rtwdev->chip->bbmcu_nr; int ret; + ret = rtw89_mac_preinit(rtwdev); + if (ret) { + rtw89_err(rtwdev, "mac preinit fail, ret: %d\n", ret); + return ret; + } + + if (no_bbmcu) + rtw89_chip_bb_preinit(rtwdev); + + rtw89_phy_init_bb_afe(rtwdev); + + /* above do preinit before downloading firmware */ + ret = rtw89_mac_init(rtwdev); if (ret) { rtw89_err(rtwdev, "mac init fail, ret:%d\n", ret); @@ -4921,6 +5834,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_phy_dm_init(rtwdev); + rtw89_mac_set_edcca_mode_bands(rtwdev, true); rtw89_mac_cfg_ppdu_status_bands(rtwdev, true); rtw89_mac_cfg_phy_rpt_bands(rtwdev, true); rtw89_mac_update_rts_threshold(rtwdev); @@ -4933,6 +5847,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->track_work, RTW89_TRACK_WORK_PERIOD); + wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->track_ps_work, + RTW89_TRACK_PS_WORK_PERIOD); set_bit(RTW89_FLAG_RUNNING, rtwdev->flags); @@ -4940,6 +5856,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.log.enable); rtw89_fw_h2c_init_ba_cam(rtwdev); + rtw89_tas_fw_timer_enable(rtwdev, true); + rtwdev->ps_hang_cnt = 0; return 0; } @@ -4955,6 +5873,7 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) return; + rtw89_tas_fw_timer_enable(rtwdev, false); rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_OFF); clear_bit(RTW89_FLAG_RUNNING, rtwdev->flags); @@ -4966,7 +5885,9 @@ void rtw89_core_stop(struct rtw89_dev *rtwdev) wiphy_work_cancel(wiphy, &btc->dhcp_notify_work); wiphy_work_cancel(wiphy, &btc->icmp_notify_work); cancel_delayed_work_sync(&rtwdev->txq_reinvoke_work); + wiphy_delayed_work_cancel(wiphy, &rtwdev->tx_wait_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->track_work); + wiphy_delayed_work_cancel(wiphy, &rtwdev->track_ps_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->chanctx_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_act1_work); wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_bt_devinfo_work); @@ -5180,6 +6101,9 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) struct rtw89_btc *btc = &rtwdev->btc; u8 band; + bitmap_or(rtwdev->quirks, rtwdev->quirks, &rtwdev->chip->default_quirks, + NUM_OF_RTW89_QUIRKS); + INIT_LIST_HEAD(&rtwdev->ba_list); INIT_LIST_HEAD(&rtwdev->forbid_ba_list); INIT_LIST_HEAD(&rtwdev->rtwvifs_list); @@ -5190,16 +6114,19 @@ int rtw89_core_init(struct rtw89_dev *rtwdev) INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]); } INIT_LIST_HEAD(&rtwdev->scan_info.chan_list); + INIT_LIST_HEAD(&rtwdev->tx_waits); INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work); INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work); INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work); wiphy_delayed_work_init(&rtwdev->track_work, rtw89_track_work); + wiphy_delayed_work_init(&rtwdev->track_ps_work, rtw89_track_ps_work); wiphy_delayed_work_init(&rtwdev->chanctx_work, rtw89_chanctx_work); wiphy_delayed_work_init(&rtwdev->coex_act1_work, rtw89_coex_act1_work); wiphy_delayed_work_init(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work); wiphy_delayed_work_init(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); wiphy_delayed_work_init(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work); wiphy_delayed_work_init(&rtwdev->mcc_prepare_done_work, rtw89_mcc_prepare_done_work); + wiphy_delayed_work_init(&rtwdev->tx_wait_work, rtw89_tx_wait_work); INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work); wiphy_delayed_work_init(&rtwdev->antdiv_work, rtw89_phy_antdiv_work); rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); @@ -5285,7 +6212,8 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwv rtw89_phy_config_edcca(rtwdev, bb, true); rtw89_tas_scan(rtwdev, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, mac_addr, + RTW89_ROLE_INFO_CHANGE); } void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, @@ -5305,7 +6233,8 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, rcu_read_unlock(); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, + RTW89_ROLE_INFO_CHANGE); rtw89_chip_rfk_scan(rtwdev, rtwvif_link, false); rtw89_btc_ntfy_scan_finish(rtwdev, rtwvif_link->phy_idx); @@ -5331,7 +6260,9 @@ void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_hal *hal = &rtwdev->hal; int ret; + u8 val2; u8 val; u8 cv; @@ -5343,14 +6274,28 @@ static void rtw89_read_chip_ver(struct rtw89_dev *rtwdev) cv = CHIP_CBV; } - rtwdev->hal.cv = cv; + hal->cv = cv; - if (rtw89_is_rtl885xb(rtwdev)) { + if (rtw89_is_rtl885xb(rtwdev) || chip->chip_gen >= RTW89_CHIP_BE) { ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CV, &val); if (ret) return; - rtwdev->hal.acv = u8_get_bits(val, XTAL_SI_ACV_MASK); + hal->acv = u8_get_bits(val, XTAL_SI_ACV_MASK); + } + + if (chip->chip_gen >= RTW89_CHIP_BE) { + hal->cid = + rtw89_read32_mask(rtwdev, R_BE_SYS_CHIPINFO, B_BE_HW_ID_MASK); + + ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CHIP_ID_L, &val); + if (ret) + return; + ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_CHIP_ID_H, &val2); + if (ret) + return; + + hal->aid = val | val2 << 8; } } @@ -5406,7 +6351,7 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); u16 usable_links = ieee80211_vif_usable_links(vif); u16 active_links = vif->active_links; - struct rtw89_vif_link *target, *cur; + struct rtw89_vif_link *target; int ret; lockdep_assert_wiphy(rtwdev->hw->wiphy); @@ -5432,11 +6377,9 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, ieee80211_stop_queues(rtwdev->hw); flush_work(&rtwdev->txq_work); - cur = rtw89_get_designated_link(rtwvif); - - ret = ieee80211_set_active_links(vif, active_links | BIT(link_id)); + ret = ieee80211_set_active_links(vif, BIT(link_id)); if (ret) { - rtw89_err(rtwdev, "%s: failed to activate link id %u\n", + rtw89_err(rtwdev, "%s: failed to work on link id %u\n", __func__, link_id); goto wake_queue; } @@ -5451,17 +6394,8 @@ int rtw89_core_mlsr_switch(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, goto wake_queue; } - if (likely(cur)) - rtw89_fw_h2c_mlo_link_cfg(rtwdev, cur, false); - - rtw89_fw_h2c_mlo_link_cfg(rtwdev, target, true); - - ret = ieee80211_set_active_links(vif, BIT(link_id)); - if (ret) - rtw89_err(rtwdev, "%s: failed to inactivate links 0x%x\n", - __func__, active_links); - - rtw89_chip_rfk_channel(rtwdev, target); + if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) + rtw89_chip_rfk_channel(rtwdev, target); rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR; @@ -5508,25 +6442,24 @@ static int rtw89_chip_board_info_setup(struct rtw89_dev *rtwdev) static bool rtw89_chip_has_rfkill(struct rtw89_dev *rtwdev) { - return !!rtwdev->chip->rfkill_init.mask; + return !!rtwdev->chip->rfkill_init; } static void rtw89_core_rfkill_init(struct rtw89_dev *rtwdev) { - const struct rtw89_reg3_def reg = rtwdev->chip->rfkill_init; - u16 val; + const struct rtw89_rfkill_regs *regs = rtwdev->chip->rfkill_init; - val = rtw89_read16(rtwdev, reg.addr); - val &= ~reg.mask; - val |= reg.data; - rtw89_write16(rtwdev, reg.addr, val); + rtw89_write16_mask(rtwdev, regs->pinmux.addr, + regs->pinmux.mask, regs->pinmux.data); + rtw89_write16_mask(rtwdev, regs->mode.addr, + regs->mode.mask, regs->mode.data); } static bool rtw89_core_rfkill_get(struct rtw89_dev *rtwdev) { - const struct rtw89_reg_def reg = rtwdev->chip->rfkill_get; + const struct rtw89_reg_def *reg = &rtwdev->chip->rfkill_get; - return !rtw89_read8_mask(rtwdev, reg.addr, reg.mask); + return !rtw89_read8_mask(rtwdev, reg->addr, reg->mask); } static void rtw89_rfkill_polling_init(struct rtw89_dev *rtwdev) @@ -5573,6 +6506,8 @@ void rtw89_core_rfkill_poll(struct rtw89_dev *rtwdev, bool force) int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) { + struct rtw89_efuse *efuse = &rtwdev->efuse; + struct rtw89_hal *hal = &rtwdev->hal; int ret; rtw89_read_chip_ver(rtwdev); @@ -5612,6 +6547,9 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) rtw89_core_setup_rfe_parms(rtwdev); rtwdev->ps_mode = rtw89_update_ps_mode(rtwdev); + rtw89_info(rtwdev, "chip info CID: %x, CV: %x, AID: %x, ACV: %x, RFE: %d\n", + hal->cid, hal->cv, hal->aid, hal->acv, efuse->rfe_type); + out: rtw89_mac_pwr_off(rtwdev); @@ -5650,6 +6588,9 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) int ret; int tx_headroom = IEEE80211_HT_CTL_LEN; + if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + tx_headroom += chip->txwd_body_size + chip->txwd_info_size; + hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n); hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n); hw->txq_data_size = sizeof(struct rtw89_txq); @@ -5659,8 +6600,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev) hw->extra_tx_headroom = tx_headroom; hw->queues = IEEE80211_NUM_ACS; - hw->max_rx_aggregation_subframes = RTW89_MAX_RX_AGG_NUM; - hw->max_tx_aggregation_subframes = RTW89_MAX_TX_AGG_NUM; + hw->max_rx_aggregation_subframes = chip->max_rx_agg_num; + hw->max_tx_aggregation_subframes = chip->max_tx_agg_num; hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL; hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC | @@ -5815,6 +6756,7 @@ int rtw89_core_register(struct rtw89_dev *rtwdev) return ret; } + rtw89_phy_dm_init_data(rtwdev); rtw89_debugfs_init(rtwdev); return 0; @@ -5865,6 +6807,9 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device, ops->cancel_remain_on_channel = NULL; } + if (!chip->support_noise) + ops->get_survey = NULL; + driver_data_size = sizeof(struct rtw89_dev) + bus_data_size; hw = ieee80211_alloc_hw(driver_data_size, ops); if (!hw) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 052da29099ab3..86ea32fc3bcb8 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -102,6 +102,8 @@ static inline u64 roundup_u64(u64 x, u32 y) #define WIPHY_FLAG_DISABLE_WEXT 0 +#define BSS_CHANGED_MLD_VALID_LINKS BIT_ULL(33) + /** * napi_is_scheduled - test if NAPI is scheduled * @n: NAPI context @@ -156,8 +158,10 @@ struct rtw89_efuse_block_cfg; struct rtw89_h2c_rf_tssi; struct rtw89_fw_txpwr_track_cfg; struct rtw89_phy_rfk_log_fmt; +struct rtw89_phy_calc_efuse_gain; struct rtw89_debugfs; struct rtw89_regd_data; +struct rtw89_wow_cam_info; extern const struct ieee80211_ops rtw89_ops; @@ -172,9 +176,13 @@ extern const struct ieee80211_ops rtw89_ops; #define RFREG_MASK 0xfffff #define INV_RF_DATA 0xffffffff #define BYPASS_CR_DATA 0xbabecafe +#define RTW89_R32_EA 0xEAEAEAEA +#define RTW89_R32_DEAD 0xDEADBEEF #define RTW89_TRACK_WORK_PERIOD round_jiffies_relative(HZ * 2) +#define RTW89_TRACK_PS_WORK_PERIOD msecs_to_jiffies(100) #define RTW89_FORBID_BA_TIMER round_jiffies_relative(HZ * 4) +#define RTW89_PS_HANG_MAX_CNT 3 #define CFO_TRACK_MAX_USER 64 #define MAX_RSSI 110 #define RSSI_FACTOR 1 @@ -242,6 +250,16 @@ enum rtw89_subband { RTW89_SUBBAND_2GHZ_5GHZ_NR = RTW89_CH_5G_BAND_4 + 1, }; +enum rtw89_tx_comp_band { + RTW89_TX_COMP_BAND_2GHZ, + RTW89_TX_COMP_BAND_5GHZ_L, + RTW89_TX_COMP_BAND_5GHZ_H, + RTW89_TX_COMP_BAND_6GHZ_M, + RTW89_TX_COMP_BAND_6GHZ_UH, + + RTW89_TX_COMP_BAND_NR, +}; + enum rtw89_gain_offset { RTW89_GAIN_OFFSET_2G_CCK, RTW89_GAIN_OFFSET_2G_OFDM, @@ -264,6 +282,17 @@ enum rtw89_hci_type { RTW89_HCI_TYPE_PCIE, RTW89_HCI_TYPE_USB, RTW89_HCI_TYPE_SDIO, + + RTW89_HCI_TYPE_NUM, +}; + +enum rtw89_hci_dle_type { + RTW89_HCI_DLE_TYPE_PCIE, + RTW89_HCI_DLE_TYPE_USB2, + RTW89_HCI_DLE_TYPE_USB3, + RTW89_HCI_DLE_TYPE_SDIO, + + RTW89_HCI_DLE_TYPE_NUM, }; enum rtw89_core_chip_id { @@ -273,6 +302,18 @@ enum rtw89_core_chip_id { RTL8852C, RTL8851B, RTL8922A, + RTL8922D, +}; + +enum rtw89_core_chip_cid { + RTL8922D_CID7025 = 0x74, + RTL8922D_CID7090 = 0x79, +}; + +enum rtw89_core_chip_aid { + RTL8922D_AID1348 = 0x1348, + RTL8922D_AID7060 = 0x7060, + RTL8922D_AID7102 = 0x7102, }; enum rtw89_chip_gen { @@ -1095,6 +1136,7 @@ struct rtw89_chan { */ u32 freq; enum rtw89_subband subband_type; + enum rtw89_tx_comp_band tx_comp_band; enum rtw89_sc_offset pri_ch_idx; u8 pri_sb_idx; }; @@ -1133,6 +1175,7 @@ struct rtw89_port_reg { u32 ptcl_dbg; u32 ptcl_dbg_info; u32 bcn_drop_all; + u32 bcn_psr_rpt; u32 hiq_win[RTW89_PORT_NUM]; }; @@ -1241,6 +1284,15 @@ struct rtw89_rxdesc_short_v2 { __le32 dword5; } __packed; +struct rtw89_rxdesc_short_v3 { + __le32 dword0; + __le32 dword1; + __le32 dword2; + __le32 dword3; + __le32 dword4; + __le32 dword5; +} __packed; + struct rtw89_rxdesc_long { __le32 dword0; __le32 dword1; @@ -1265,6 +1317,19 @@ struct rtw89_rxdesc_long_v2 { __le32 dword9; } __packed; +struct rtw89_rxdesc_long_v3 { + __le32 dword0; + __le32 dword1; + __le32 dword2; + __le32 dword3; + __le32 dword4; + __le32 dword5; + __le32 dword6; + __le32 dword7; + __le32 dword8; + __le32 dword9; +} __packed; + struct rtw89_rxdesc_phy_rpt_v2 { __le32 dword0; __le32 dword1; @@ -1295,6 +1360,8 @@ struct rtw89_tx_desc_info { u8 sec_seq[6]; u16 data_rate; u16 data_retry_lowest_rate; + u8 data_bw; + u8 gi_ltf; bool fw_dl; u16 seq; bool a_ctrl_bsr; @@ -1515,6 +1582,11 @@ struct rtw89_btc_wl_smap { u32 emlsr: 1; }; +enum rtw89_tfc_interval { + RTW89_TFC_INTERVAL_100MS, + RTW89_TFC_INTERVAL_2SEC, +}; + enum rtw89_tfc_lv { RTW89_TFC_IDLE, RTW89_TFC_ULTRA_LOW, @@ -1523,7 +1595,6 @@ enum rtw89_tfc_lv { RTW89_TFC_HIGH, }; -#define RTW89_TP_SHIFT 18 /* bytes/2s --> Mbps */ DECLARE_EWMA(tp, 10, 2); struct rtw89_traffic_stats { @@ -3491,11 +3562,18 @@ struct rtw89_ra_info { u8 cr_tbl_sel:1; u8 fix_giltf_en:1; u8 fix_giltf:3; - u8 rsvd2:1; + u8 partial_bw_er:1; u8 csi_mcs_ss_idx; u8 csi_mode:2; u8 csi_gi_ltf:3; u8 csi_bw:3; + /* after v1 */ + u8 is_noisy:1; + u8 psra_en:1; + u8 rsvd0:1; + u8 macid_msb:2; + u8 band:2; /* enum rtw89_band */ + u8 is_new_dbgreg:1; }; #define RTW89_PPDU_MAC_INFO_USR_SIZE 4 @@ -3503,9 +3581,6 @@ struct rtw89_ra_info { #define RTW89_PPDU_MAC_RX_CNT_SIZE 96 #define RTW89_PPDU_MAC_RX_CNT_SIZE_V1 128 -#define RTW89_MAX_RX_AGG_NUM 64 -#define RTW89_MAX_TX_AGG_NUM 128 - struct rtw89_ampdu_params { u16 agg_num; bool amsdu; @@ -3614,6 +3689,7 @@ struct rtw89_efuse { u8 addr[ETH_ALEN]; u8 rfe_type; char country_code[2]; + u8 adc_td; }; struct rtw89_phy_rate_pattern { @@ -3623,9 +3699,17 @@ struct rtw89_phy_rate_pattern { bool enable; }; +#define RTW89_TX_DONE 0x0 +#define RTW89_TX_RETRY_LIMIT 0x1 +#define RTW89_TX_LIFE_TIME 0x2 +#define RTW89_TX_MACID_DROP 0x3 + +#define RTW89_TX_WAIT_WORK_TIMEOUT msecs_to_jiffies(500) struct rtw89_tx_wait_info { struct rcu_head rcu_head; + struct list_head list; struct completion completion; + struct sk_buff *skb; bool tx_done; }; @@ -3714,6 +3798,7 @@ struct rtw89_vif_link { u8 hit_rule; u8 last_noa_nr; u64 sync_bcn_tsf; + u64 last_sync_bcn_tsf; bool rand_tsf_done; bool trigger; bool lsig_txop; @@ -3737,6 +3822,8 @@ struct rtw89_vif_link { struct list_head general_pkt_list; struct rtw89_p2p_noa_setter p2p_noa; struct rtw89_ps_noa_once_handler noa_once; + struct wiphy_delayed_work mcc_gc_detect_beacon_work; + u8 detect_bcn_count; }; enum rtw89_lv1_rcvy_step { @@ -3762,6 +3849,8 @@ struct rtw89_hci_ops { void (*write16)(struct rtw89_dev *rtwdev, u32 addr, u16 data); void (*write32)(struct rtw89_dev *rtwdev, u32 addr, u32 data); + u32 (*read32_pci_cfg)(struct rtw89_dev *rtwdev, u32 addr); + int (*mac_pre_init)(struct rtw89_dev *rtwdev); int (*mac_pre_deinit)(struct rtw89_dev *rtwdev); int (*mac_post_init)(struct rtw89_dev *rtwdev); @@ -3793,6 +3882,7 @@ struct rtw89_hci_ops { struct rtw89_hci_info { const struct rtw89_hci_ops *ops; enum rtw89_hci_type type; + enum rtw89_hci_dle_type dle_type; u32 rpwm_addr; u32 cpwm_addr; bool paused; @@ -3861,6 +3951,11 @@ struct rtw89_chip_ops { s8 pw_ofst, enum rtw89_mac_idx mac_idx); void (*digital_pwr_comp)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); + void (*calc_rx_gain_normal)(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_rf_path path, + enum rtw89_phy_idx phy_idx, + struct rtw89_phy_calc_efuse_gain *calc); int (*pwr_on_func)(struct rtw89_dev *rtwdev); int (*pwr_off_func)(struct rtw89_dev *rtwdev); void (*query_rxdesc)(struct rtw89_dev *rtwdev, @@ -3872,6 +3967,7 @@ struct rtw89_chip_ops { void (*fill_txdesc_fwcmd)(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); + u8 (*get_ch_dma)(struct rtw89_dev *rtwdev, u8 qsel); int (*cfg_ctrl_path)(struct rtw89_dev *rtwdev, bool wl); int (*mac_cfg_gnt)(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex_gnt *gnt_cfg); @@ -3892,6 +3988,9 @@ struct rtw89_chip_ops { struct rtw89_sta_link *rtwsta_link); int (*h2c_txtime_cmac_tbl)(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); + int (*h2c_punctured_cmac_tbl)(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 punctured); int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); @@ -3901,6 +4000,8 @@ struct rtw89_chip_ops { struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, bool valid, struct ieee80211_ampdu_params *params); + int (*h2c_wow_cam_update)(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info); void (*btc_set_rfe)(struct rtw89_dev *rtwdev); void (*btc_init_cfg)(struct rtw89_dev *rtwdev); @@ -3976,7 +4077,7 @@ struct rtw89_scan_option { u16 slow_pd; u16 norm_cy; u8 opch_end; - u16 delay; + u16 delay; /* in unit of ms */ u64 prohib_chan; enum rtw89_phy_idx band; enum rtw89_scan_be_operation operation; @@ -4033,6 +4134,11 @@ struct rtw89_hfc_prec_cfg { u8 h2c_full_cond; u8 wp_ch07_full_cond; u8 wp_ch811_full_cond; + /* for WiFi 7 chips after 8922D */ + u16 ch011_full_page; + u16 h2c_full_page; + u16 wp_ch07_full_page; + u16 wp_ch811_full_page; }; struct rtw89_hfc_param { @@ -4057,13 +4163,14 @@ struct rtw89_dle_size { u16 pge_size; u16 lnk_pge_num; u16 unlnk_pge_num; - /* for WiFi 7 chips below */ + /* for WiFi 7 chips below (suffix v1) */ u32 srt_ofst; }; struct rtw89_wde_quota { u16 hif; u16 wcpu; + /* unused dcpu isn't listed */ u16 pkt_in; u16 cpu_io; }; @@ -4081,8 +4188,10 @@ struct rtw89_ple_quota { u16 wd_rel; u16 cpu_io; u16 tx_rpt; - /* for WiFi 7 chips below */ + /* for WiFi 7 chips below (suffix v1) */ u16 h2d; + /* for WiFi 7 chips after 8922D (suffix v2) */ + u16 snrpt; }; struct rtw89_rsvd_quota { @@ -4103,6 +4212,17 @@ struct rtw89_dle_rsvd_size { u32 size; }; +struct rtw89_dle_input { + u32 tx_ampdu_num_b0; + u32 tx_ampdu_num_b1; + u32 tx_amsdu_size; /* unit: KB */ + u32 h2c_max_size; + u32 rx_amsdu_size; /* unit: KB */ + u32 c2h_max_size; + u32 mpdu_info_tbl_b0; + u32 mpdu_info_tbl_b1; +}; + struct rtw89_dle_mem { enum rtw89_qta_mode mode; const struct rtw89_dle_size *wde_size; @@ -4115,6 +4235,8 @@ struct rtw89_dle_mem { const struct rtw89_rsvd_quota *rsvd_qt; const struct rtw89_dle_rsvd_size *rsvd0_size; const struct rtw89_dle_rsvd_size *rsvd1_size; + /* for WiFi 7 chips after 8922D */ + const struct rtw89_dle_input *dle_input; }; struct rtw89_reg_def { @@ -4388,6 +4510,18 @@ struct rtw89_rrsr_cfgs { struct rtw89_reg3_def rsc; }; +struct rtw89_sb_regs { + struct { + u32 cfg; + u32 get; + } n[2]; +}; + +struct rtw89_rfkill_regs { + struct rtw89_reg3_def pinmux; + struct rtw89_reg3_def mode; +}; + struct rtw89_dig_regs { u32 seg0_pd_reg; u32 pd_lower_bound_mask; @@ -4468,6 +4602,9 @@ struct rtw89_chanctx_listener { (struct rtw89_dev *rtwdev, enum rtw89_chanctx_state state); }; +#define RTW89_NHM_TH_NUM 11 +#define RTW89_NHM_RPT_NUM 12 + struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; enum rtw89_chip_gen chip_gen; @@ -4484,10 +4621,14 @@ struct rtw89_chip_info { bool small_fifo_size; u32 dle_scc_rsvd_size; u16 max_amsdu_limit; + u16 max_vht_mpdu_cap; + u16 max_eht_mpdu_cap; + u16 max_tx_agg_num; + u16 max_rx_agg_num; bool dis_2g_40m_ul_ofdma; u32 rsvd_ple_ofst; - const struct rtw89_hfc_param_ini *hfc_param_ini; - const struct rtw89_dle_mem *dle_mem; + const struct rtw89_hfc_param_ini *hfc_param_ini[RTW89_HCI_TYPE_NUM]; + const struct rtw89_dle_mem *dle_mem[RTW89_HCI_DLE_TYPE_NUM]; u8 wde_qempty_acq_grpnum; u8 wde_qempty_mgq_grpsel; u32 rf_base_addr[2]; @@ -4502,6 +4643,7 @@ struct rtw89_chip_info { bool support_ant_gain; bool support_tas; bool support_sar_by_ant; + bool support_noise; bool ul_tb_waveform_ctrl; bool ul_tb_pwr_diff; bool rx_freq_frome_ie; @@ -4518,6 +4660,7 @@ struct rtw89_chip_info { u8 bacam_num; u8 bacam_dynamic_num; enum rtw89_bacam_ver bacam_ver; + u8 addrcam_ver; u8 ppdu_max_usr; u8 sec_ctrl_efuse_size; @@ -4586,18 +4729,22 @@ struct rtw89_chip_info { bool cfo_hw_comp; const struct rtw89_reg_def *dcfo_comp; u8 dcfo_comp_sft; + const struct rtw89_reg_def (*nhm_report)[RTW89_NHM_RPT_NUM]; + const struct rtw89_reg_def (*nhm_th)[RTW89_NHM_TH_NUM]; const struct rtw89_imr_info *imr_info; const struct rtw89_imr_table *imr_dmac_table; const struct rtw89_imr_table *imr_cmac_table; const struct rtw89_rrsr_cfgs *rrsr_cfgs; struct rtw89_reg_def bss_clr_vld; u32 bss_clr_map_reg; - struct rtw89_reg3_def rfkill_init; + const struct rtw89_rfkill_regs *rfkill_init; struct rtw89_reg_def rfkill_get; + struct rtw89_sb_regs btc_sb; u32 dma_ch_mask; const struct rtw89_edcca_regs *edcca_regs; const struct wiphy_wowlan_support *wowlan_stub; const struct rtw89_xtal_info *xtal_info; + unsigned long default_quirks; /* bitmap of rtw89_quirks */ }; struct rtw89_chip_variant { @@ -4627,6 +4774,7 @@ enum rtw89_hcifc_mode { struct rtw89_dle_info { const struct rtw89_rsvd_quota *rsvd_qt; + const struct rtw89_dle_input *dle_input; enum rtw89_qta_mode qta_mode; u16 ple_pg_size; u16 ple_free_pg; @@ -4647,17 +4795,23 @@ struct rtw89_completion_data { u8 buf[RTW89_COMPLETION_BUF_SIZE]; }; +struct rtw89_wait_response { + struct rcu_head rcu_head; + struct completion completion; + struct rtw89_completion_data data; +}; + struct rtw89_wait_info { atomic_t cond; - struct completion completion; struct rtw89_completion_data data; + struct rtw89_wait_response __rcu *resp; }; #define RTW89_WAIT_FOR_COND_TIMEOUT msecs_to_jiffies(100) static inline void rtw89_init_wait(struct rtw89_wait_info *wait) { - init_completion(&wait->completion); + rcu_assign_pointer(wait->resp, NULL); atomic_set(&wait->cond, RTW89_WAIT_COND_IDLE); } @@ -4691,11 +4845,21 @@ enum rtw89_fw_type { RTW89_FW_LOGFMT = 255, }; +#define RTW89_FW_FEATURE_GROUP(_grp, _features...) \ + RTW89_FW_FEATURE_##_grp##_MIN, \ + __RTW89_FW_FEATURE_##_grp##_S = RTW89_FW_FEATURE_##_grp##_MIN - 1, \ + _features \ + __RTW89_FW_FEATURE_##_grp##_E, \ + RTW89_FW_FEATURE_##_grp##_MAX = __RTW89_FW_FEATURE_##_grp##_E - 1 + enum rtw89_fw_feature { RTW89_FW_FEATURE_OLD_HT_RA_FORMAT, RTW89_FW_FEATURE_SCAN_OFFLOAD, RTW89_FW_FEATURE_TX_WAKE, - RTW89_FW_FEATURE_CRASH_TRIGGER, + RTW89_FW_FEATURE_GROUP(CRASH_TRIGGER, + RTW89_FW_FEATURE_CRASH_TRIGGER_TYPE_0, + RTW89_FW_FEATURE_CRASH_TRIGGER_TYPE_1, + ), RTW89_FW_FEATURE_NO_PACKET_DROP, RTW89_FW_FEATURE_NO_DEEP_PS, RTW89_FW_FEATURE_NO_LPS_PG, @@ -4703,8 +4867,17 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_MACID_PAUSE_SLEEP, RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0, RTW89_FW_FEATURE_WOW_REASON_V1, - RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, - RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1, + RTW89_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V2, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V3, + ), + RTW89_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V0, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V1, + RTW89_FW_FEATURE_RFK_PRE_NOTIFY_MCC_V2, + ), RTW89_FW_FEATURE_RFK_RXDCK_V0, RTW89_FW_FEATURE_RFK_IQK_V0, RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX, @@ -4716,6 +4889,14 @@ enum rtw89_fw_feature { RTW89_FW_FEATURE_BEACON_LOSS_COUNT_V1, RTW89_FW_FEATURE_SCAN_OFFLOAD_EXTRA_OP, RTW89_FW_FEATURE_RFK_NTFY_MCC_V0, + RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG, + RTW89_FW_FEATURE_BEACON_TRACKING, + RTW89_FW_FEATURE_ADDR_CAM_V0, + RTW89_FW_FEATURE_SER_L1_BY_EVENT, + RTW89_FW_FEATURE_SIM_SER_L0L1_BY_HALT_H2C, + RTW89_FW_FEATURE_LPS_ML_INFO_V1, + + NUM_OF_RTW89_FW_FEATURES, }; struct rtw89_fw_suit { @@ -4775,6 +4956,9 @@ struct rtw89_fw_elm_info { struct rtw89_fw_txpwr_track_cfg *txpwr_trk; struct rtw89_phy_rfk_log_fmt *rfk_log_fmt; const struct rtw89_regd_data *regd; + const struct rtw89_fw_element_hdr *afe; + const struct rtw89_fw_element_hdr *diag_mac; + const struct rtw89_fw_element_hdr *tx_comp; }; enum rtw89_fw_mss_dev_type { @@ -4805,16 +4989,28 @@ struct rtw89_fw_info { struct rtw89_fw_suit bbmcu0; struct rtw89_fw_suit bbmcu1; struct rtw89_fw_log log; - u32 feature_map; struct rtw89_fw_elm_info elm_info; struct rtw89_fw_secure sec; + + DECLARE_BITMAP(feature_map, NUM_OF_RTW89_FW_FEATURES); }; #define RTW89_CHK_FW_FEATURE(_feat, _fw) \ - (!!((_fw)->feature_map & BIT(RTW89_FW_FEATURE_ ## _feat))) + test_bit(RTW89_FW_FEATURE_ ## _feat, (_fw)->feature_map) + +#define RTW89_CHK_FW_FEATURE_GROUP(_grp, _fw) \ +({ \ + unsigned int bit = find_next_bit((_fw)->feature_map, \ + NUM_OF_RTW89_FW_FEATURES, \ + RTW89_FW_FEATURE_ ## _grp ## _MIN); \ + bit <= RTW89_FW_FEATURE_ ## _grp ## _MAX; \ +}) #define RTW89_SET_FW_FEATURE(_fw_feature, _fw) \ - ((_fw)->feature_map |= BIT(_fw_feature)) + set_bit(_fw_feature, (_fw)->feature_map) + +#define RTW89_CLR_FW_FEATURE(_fw_feature, _fw) \ + clear_bit(_fw_feature, (_fw)->feature_map) struct rtw89_cam_info { DECLARE_BITMAP(addr_cam_map, RTW89_MAX_ADDR_CAM_NUM); @@ -5056,7 +5252,9 @@ enum rtw89_dm_type { struct rtw89_hal { u32 rx_fltr; u8 cv; + u8 cid; /* enum rtw89_core_chip_cid */ u8 acv; + u16 aid; /* enum rtw89_core_chip_aid */ u32 antenna_tx; u32 antenna_rx; u8 tx_nss; @@ -5067,6 +5265,7 @@ struct rtw89_hal { bool support_cckpd; bool support_igi; bool no_mcs_12_13; + bool no_eht; atomic_t roc_chanctx_idx; u8 roc_link_index; @@ -5081,6 +5280,8 @@ struct rtw89_hal { enum rtw89_entity_mode entity_mode; struct rtw89_entity_mgnt entity_mgnt; + enum rtw89_phy_idx entity_force_hw; + u32 disabled_dm_bitmap; /* bitmap of enum rtw89_dm_type */ u8 thermal_prot_th; @@ -5095,6 +5296,8 @@ enum rtw89_flags { RTW89_FLAG_DMAC_FUNC, RTW89_FLAG_CMAC0_FUNC, RTW89_FLAG_CMAC1_FUNC, + RTW89_FLAG_CMAC0_PWR, + RTW89_FLAG_CMAC1_PWR, RTW89_FLAG_FW_RDY, RTW89_FLAG_RUNNING, RTW89_FLAG_PROBE_DONE, @@ -5111,6 +5314,7 @@ enum rtw89_flags { RTW89_FLAG_FORBIDDEN_TRACK_WORK, RTW89_FLAG_CHANGING_INTERFACE, RTW89_FLAG_HW_RFKILL_STATE, + RTW89_FLAG_UNPLUGGED, NUM_OF_RTW89_FLAGS, }; @@ -5130,13 +5334,15 @@ enum rtw89_test_config { }; enum rtw89_custid { - RTW89_CUSTID_NONE, - RTW89_CUSTID_ACER, - RTW89_CUSTID_AMD, - RTW89_CUSTID_ASUS, - RTW89_CUSTID_DELL, - RTW89_CUSTID_HP, - RTW89_CUSTID_LENOVO, + RTW89_CUSTID_NONE = 0, + RTW89_CUSTID_HP = 1, + RTW89_CUSTID_ASUS = 2, + RTW89_CUSTID_ACER = 3, + RTW89_CUSTID_LENOVO = 4, + RTW89_CUSTID_NEC = 5, + RTW89_CUSTID_AMD = 6, + RTW89_CUSTID_FUJITSU = 7, + RTW89_CUSTID_DELL = 8, }; enum rtw89_pkt_drop_sel { @@ -5169,9 +5375,36 @@ struct rtw89_pkt_drop_params { struct rtw89_pkt_stat { u16 beacon_nr; u8 beacon_rate; + u32 beacon_len; u32 rx_rate_cnt[RTW89_HW_RATE_NR]; }; +#define RTW89_BCN_TRACK_STAT_NR 32 +#define RTW89_BCN_TRACK_SCALE_FACTOR 10 +#define RTW89_BCN_TRACK_MAX_BIN_NUM 6 +#define RTW89_BCN_TRACK_BIN_WIDTH 5 +#define RTW89_BCN_TRACK_TARGET_BCN 80 + +struct rtw89_beacon_dist { + u16 min; + u16 max; + u16 outlier_count; + u16 lower_bound; + u16 upper_bound; + u16 bins[RTW89_BCN_TRACK_MAX_BIN_NUM]; +}; + +struct rtw89_beacon_stat { + u8 num; + u8 wp; + u16 tbtt_tu_min; + u16 tbtt_tu_max; + u16 drift[RTW89_BCN_TRACK_STAT_NR]; + u32 tbtt_us[RTW89_BCN_TRACK_STAT_NR]; + u16 tbtt_tu[RTW89_BCN_TRACK_STAT_NR]; + struct rtw89_beacon_dist bcn_dist; +}; + DECLARE_EWMA(thermal, 4, 4); struct rtw89_phy_stat { @@ -5180,6 +5413,7 @@ struct rtw89_phy_stat { struct ewma_rssi bcn_rssi; struct rtw89_pkt_stat cur_pkt_stat; struct rtw89_pkt_stat last_pkt_stat; + struct rtw89_beacon_stat bcn_stat; }; enum rtw89_rfk_report_state { @@ -5223,6 +5457,7 @@ struct rtw89_rfk_mcc_info_data { u8 ch[RTW89_RFK_CHS_NR]; u8 band[RTW89_RFK_CHS_NR]; u8 bw[RTW89_RFK_CHS_NR]; + u32 rf18[RTW89_RFK_CHS_NR]; u8 table_idx; }; @@ -5281,7 +5516,7 @@ struct rtw89_dpk_bkup_para { enum rtw89_band band; enum rtw89_bandwidth bw; u8 ch; - bool path_ok; + u8 path_ok; u8 mdpd_en; u8 txagc_dpk; u8 ther_dpk; @@ -5359,8 +5594,10 @@ struct rtw89_dig_info { s8 tia_gain_a[TIA_GAIN_NUM]; s8 tia_gain_g[TIA_GAIN_NUM]; s8 *tia_gain; + u32 bak_dig; bool is_linked_pre; bool bypass_dig; + bool pause_dig; }; enum rtw89_multi_cfo_mode { @@ -5495,6 +5732,8 @@ struct rtw89_regd_ctrl { struct rtw89_regulatory_info { struct rtw89_regd_ctrl ctrl; const struct rtw89_regd *regd; + bool programmed; + enum rtw89_reg_6ghz_power reg_6ghz_power; struct rtw89_reg_6ghz_tpe reg_6ghz_tpe; bool txpwr_uk_follow_etsi; @@ -5502,6 +5741,7 @@ struct rtw89_regulatory_info { DECLARE_BITMAP(block_unii4, RTW89_REGD_MAX_COUNTRY_NUM); DECLARE_BITMAP(block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM); DECLARE_BITMAP(block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM); + DECLARE_BITMAP(block_6ghz_vlp, RTW89_REGD_MAX_COUNTRY_NUM); }; enum rtw89_ifs_clm_application { @@ -5526,6 +5766,7 @@ enum rtw89_env_racing_lv { struct rtw89_ccx_para_info { enum rtw89_env_racing_lv rac_lv; u16 mntr_time; + bool nhm_incld_cca; u8 nhm_manual_th_ofst; u8 nhm_manual_th0; enum rtw89_ifs_clm_application ifs_clm_app; @@ -5559,9 +5800,13 @@ enum rtw89_ccx_edcca_opt_bw_idx { RTW89_CCX_EDCCA_BW20_7 = 7 }; -#define RTW89_NHM_TH_NUM 11 +struct rtw89_nhm_report { + struct list_head list; + struct ieee80211_channel *channel; + u8 noise; +}; + #define RTW89_FAHM_TH_NUM 11 -#define RTW89_NHM_RPT_NUM 12 #define RTW89_FAHM_RPT_NUM 12 #define RTW89_IFS_CLM_NUM 4 struct rtw89_env_monitor_info { @@ -5582,7 +5827,7 @@ struct rtw89_env_monitor_info { u16 ifs_clm_cckfa; u16 ifs_clm_cckcca_excl_fa; u16 ifs_clm_total_ifs; - u8 ifs_clm_his[RTW89_IFS_CLM_NUM]; + u16 ifs_clm_his[RTW89_IFS_CLM_NUM]; u16 ifs_clm_avg[RTW89_IFS_CLM_NUM]; u16 ifs_clm_cca[RTW89_IFS_CLM_NUM]; u8 ifs_clm_tx_ratio; @@ -5595,6 +5840,13 @@ struct rtw89_env_monitor_info { u16 ifs_clm_ofdm_fa_permil; u32 ifs_clm_ifs_avg[RTW89_IFS_CLM_NUM]; u32 ifs_clm_cca_avg[RTW89_IFS_CLM_NUM]; + bool nhm_include_cca; + u32 nhm_sum; + u32 nhm_mntr_time; + u16 nhm_result[RTW89_NHM_RPT_NUM]; + u8 nhm_th[RTW89_NHM_RPT_NUM]; + struct rtw89_nhm_report *nhm_his[RTW89_BAND_NUM]; + struct list_head nhm_rpt_list; }; enum rtw89_ser_rcvy_step { @@ -5652,7 +5904,9 @@ struct rtw89_early_h2c { struct rtw89_hw_scan_extra_op { bool set; u8 macid; + u8 port; struct rtw89_chan chan; + struct rtw89_vif_link *rtwvif_link; }; struct rtw89_hw_scan_info { @@ -5663,6 +5917,8 @@ struct rtw89_hw_scan_info { struct rtw89_hw_scan_extra_op extra_op; bool connected; bool abort; + u16 delay; /* in unit of ms */ + u8 seq: 2; }; enum rtw89_phy_bb_gain_band { @@ -5772,6 +6028,12 @@ struct rtw89_phy_efuse_gain { s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */ }; +struct rtw89_phy_calc_efuse_gain { + s8 cck_mean_gain_bias; + s8 cck_rpl_ofst; + s8 rssi_ofst; +}; + #define RTW89_MAX_PATTERN_NUM 18 #define RTW89_MAX_PATTERN_MASK_SIZE 4 #define RTW89_MAX_PATTERN_SIZE 128 @@ -5779,7 +6041,7 @@ struct rtw89_phy_efuse_gain { struct rtw89_wow_cam_info { bool r_w; u8 idx; - u32 mask[RTW89_MAX_PATTERN_MASK_SIZE]; + __le32 mask[RTW89_MAX_PATTERN_MASK_SIZE]; u16 crc; bool negative_pattern_match; bool skip_mac_hdr; @@ -5803,8 +6065,8 @@ struct rtw89_wow_gtk_info { u8 kck[32]; u8 kek[32]; u8 tk1[16]; - u8 txmickey[8]; u8 rxmickey[8]; + u8 txmickey[8]; __le32 igtk_keyid; __le64 ipn; u8 igtk[2][32]; @@ -5888,6 +6150,7 @@ struct rtw89_mcc_role { bool is_2ghz; bool is_go; bool is_gc; + bool ignore_bcn; }; struct rtw89_mcc_bt_role { @@ -5961,6 +6224,7 @@ struct rtw89_mcc_info { enum rtw89_mlo_mode { RTW89_MLO_MODE_MLSR = 0, + RTW89_MLO_MODE_EMLSR = 1, NUM_OF_RTW89_MLO_MODE, }; @@ -5969,6 +6233,24 @@ struct rtw89_mlo_info { struct rtw89_wait_info wait; }; +struct rtw89_beacon_track_info { + bool is_data_ready; + u32 tbtt_offset; /* in unit of microsecond */ + u16 bcn_timeout; /* in unit of millisecond */ + + /* The following are constant and set at association. */ + u8 dtim; + u16 beacon_int; + u16 low_bcn_th; + u16 med_bcn_th; + u16 high_bcn_th; + u16 target_bcn_th; + u16 outlier_low_bcn_th; + u16 outlier_high_bcn_th; + u32 close_bcn_intvl_th; + u32 tbtt_diff_th; +}; + struct rtw89_dev { struct ieee80211_hw *hw; struct device *dev; @@ -5983,6 +6265,7 @@ struct rtw89_dev { const struct rtw89_pci_info *pci_info; const struct rtw89_rfe_parms *rfe_parms; struct rtw89_hal hal; + struct rtw89_beacon_track_info bcn_track; struct rtw89_mcc_info mcc; struct rtw89_mlo_info mlo; struct rtw89_mac_info mac; @@ -6012,6 +6295,9 @@ struct rtw89_dev { /* used to protect rpwm */ spinlock_t rpwm_lock; + struct list_head tx_waits; + struct wiphy_delayed_work tx_wait_work; + struct rtw89_cam_info cam_info; struct sk_buff_head c2h_queue; @@ -6065,6 +6351,7 @@ struct rtw89_dev { } bbs[RTW89_PHY_NUM]; struct wiphy_delayed_work track_work; + struct wiphy_delayed_work track_ps_work; struct wiphy_delayed_work chanctx_work; struct wiphy_delayed_work coex_act1_work; struct wiphy_delayed_work coex_bt_devinfo_work; @@ -6085,6 +6372,7 @@ struct rtw89_dev { struct rtw89_btc btc; enum rtw89_ps_mode ps_mode; bool lps_enabled; + u8 ps_hang_cnt; struct rtw89_wow_param wow; @@ -6094,6 +6382,7 @@ struct rtw89_dev { int napi_budget_countdown; struct rtw89_debugfs *debugfs; + struct rtw89_vif *pure_monitor_mode_vif; /* HCI related data, keep last */ u8 priv[] __aligned(sizeof(void *)); @@ -6103,6 +6392,12 @@ struct rtw89_link_conf_container { struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS]; }; +struct rtw89_vif_ml_trans { + u16 mediate_links; + u16 links_to_del; + u16 links_to_add; +}; + #define RTW89_VIF_IDLE_LINK_ID 0 struct rtw89_vif { @@ -6115,6 +6410,7 @@ struct rtw89_vif { __be32 ip_addr; struct rtw89_traffic_stats stats; + struct rtw89_traffic_stats stats_ps; u32 tdls_peer; struct ieee80211_scan_ies *scan_ies; @@ -6124,6 +6420,7 @@ struct rtw89_vif { bool offchan; enum rtw89_mlo_mode mlo_mode; + struct rtw89_vif_ml_trans ml_trans; struct list_head dlink_pool; u8 links_inst_valid_num; @@ -6267,6 +6564,26 @@ rtw89_assoc_link_rcu_dereference(struct rtw89_dev *rtwdev, u8 macid) list_first_entry_or_null(&p->dlink_pool, typeof(*p->links_inst), dlink_schd); \ }) +static inline void rtw89_tx_wait_release(struct rtw89_tx_wait_info *wait) +{ + dev_kfree_skb_any(wait->skb); + kfree_rcu(wait, rcu_head); +} + +static inline void rtw89_tx_wait_list_clear(struct rtw89_dev *rtwdev) +{ + struct rtw89_tx_wait_info *wait, *tmp; + + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + list_for_each_entry_safe(wait, tmp, &rtwdev->tx_waits, list) { + if (!completion_done(&wait->completion)) + continue; + list_del(&wait->list); + rtw89_tx_wait_release(wait); + } +} + static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request *tx_req) { @@ -6276,6 +6593,7 @@ static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, static inline void rtw89_hci_reset(struct rtw89_dev *rtwdev) { rtwdev->hci.ops->reset(rtwdev); + rtw89_tx_wait_list_clear(rtwdev); } static inline int rtw89_hci_start(struct rtw89_dev *rtwdev) @@ -6408,9 +6726,13 @@ static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pde static inline struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb) { + /* + * This should be used by/after rtw89_hci_tx_write() and before doing + * ieee80211_tx_info_clear_status(). + */ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - return (struct rtw89_tx_skb_data *)info->status.status_driver_data; + return (struct rtw89_tx_skb_data *)info->driver_data; } static inline u8 rtw89_read8(struct rtw89_dev *rtwdev, u32 addr) @@ -6600,6 +6922,15 @@ rtw89_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, mutex_unlock(&rtwdev->rf_mutex); } +static inline u32 rtw89_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr) +{ + if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE || + !rtwdev->hci.ops->read32_pci_cfg) + return RTW89_R32_EA; + + return rtwdev->hci.ops->read32_pci_cfg(rtwdev, addr); +} + static inline struct ieee80211_txq *rtw89_txq_to_txq(struct rtw89_txq *rtwtxq) { void *p = rtwtxq; @@ -6964,12 +7295,17 @@ static inline void rtw89_chip_rfk_hw_init(struct rtw89_dev *rtwdev) } static inline -void rtw89_chip_bb_preinit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +void rtw89_chip_bb_preinit(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; - if (chip->ops->bb_preinit) - chip->ops->bb_preinit(rtwdev, phy_idx); + if (!chip->ops->bb_preinit) + return; + + chip->ops->bb_preinit(rtwdev, RTW89_PHY_0); + + if (rtwdev->dbcc_en) + chip->ops->bb_preinit(rtwdev, RTW89_PHY_1); } static inline @@ -7010,15 +7346,6 @@ static inline void rtw89_chip_rfk_init_late(struct rtw89_dev *rtwdev) chip->ops->rfk_init_late(rtwdev); } -static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) -{ - const struct rtw89_chip_info *chip = rtwdev->chip; - - if (chip->ops->rfk_channel) - chip->ops->rfk_channel(rtwdev, rtwvif_link); -} - static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan) @@ -7159,6 +7486,19 @@ static inline void rtw89_chip_digital_pwr_comp(struct rtw89_dev *rtwdev, chip->ops->digital_pwr_comp(rtwdev, phy_idx); } +static inline +void rtw89_chip_calc_rx_gain_normal(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_rf_path path, + enum rtw89_phy_idx phy_idx, + struct rtw89_phy_calc_efuse_gain *calc) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->calc_rx_gain_normal) + chip->ops->calc_rx_gain_normal(rtwdev, chan, path, phy_idx, calc); +} + static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev, const struct rtw89_txpwr_table *tbl) { @@ -7216,6 +7556,14 @@ void rtw89_chip_fill_txdesc_fwcmd(struct rtw89_dev *rtwdev, chip->ops->fill_txdesc_fwcmd(rtwdev, desc_info, txdesc); } +static inline +u8 rtw89_chip_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + return chip->ops->get_ch_dma(rtwdev, qsel); +} + static inline void rtw89_chip_mac_cfg_gnt(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex_gnt *gnt_cfg) @@ -7344,23 +7692,22 @@ static inline struct sk_buff *rtw89_alloc_skb_for_rx(struct rtw89_dev *rtwdev, return dev_alloc_skb(length); } -static inline void rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev, +static inline bool rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev, struct rtw89_tx_skb_data *skb_data, - bool tx_done) + u8 tx_status) { struct rtw89_tx_wait_info *wait; - rcu_read_lock(); + guard(rcu)(); wait = rcu_dereference(skb_data->wait); if (!wait) - goto out; - - wait->tx_done = tx_done; - complete(&wait->completion); + return false; -out: - rcu_read_unlock(); + wait->tx_done = tx_status == RTW89_TX_DONE; + /* Don't access skb anymore after completion */ + complete_all(&wait->completion); + return true; } static inline bool rtw89_is_mlo_1_1(struct rtw89_dev *rtwdev) @@ -7427,13 +7774,25 @@ static inline bool rtw89_is_rtl885xb(struct rtw89_dev *rtwdev) return false; } +static inline u32 rtw89_bytes_to_mbps(u64 bytes, enum rtw89_tfc_interval interval) +{ + switch (interval) { + default: + case RTW89_TFC_INTERVAL_2SEC: + return bytes >> 18; /* bytes/2s --> Mbps */; + case RTW89_TFC_INTERVAL_100MS: + return (bytes * 10) >> 17; /* bytes/100ms --> Mbps */ + } +} + int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct sk_buff *skb, int *qsel); int rtw89_h2c_tx(struct rtw89_dev *rtwdev, struct sk_buff *skb, bool fwdl); void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel); int rtw89_core_tx_kick_off_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, - int qsel, unsigned int timeout); + struct rtw89_tx_wait_info *wait, int qsel, + unsigned int timeout); void rtw89_core_fill_txdesc(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); @@ -7443,12 +7802,17 @@ void rtw89_core_fill_txdesc_v1(struct rtw89_dev *rtwdev, void rtw89_core_fill_txdesc_v2(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); +void rtw89_core_fill_txdesc_v3(struct rtw89_dev *rtwdev, + struct rtw89_tx_desc_info *desc_info, + void *txdesc); void rtw89_core_fill_txdesc_fwcmd_v1(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); void rtw89_core_fill_txdesc_fwcmd_v2(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); +u8 rtw89_core_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel); +u8 rtw89_core_get_ch_dma_v1(struct rtw89_dev *rtwdev, u8 qsel); void rtw89_core_rx(struct rtw89_dev *rtwdev, struct rtw89_rx_desc_info *desc_info, struct sk_buff *skb); @@ -7458,6 +7822,9 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev, void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev, struct rtw89_rx_desc_info *desc_info, u8 *data, u32 data_offset); +void rtw89_core_query_rxdesc_v3(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + u8 *data, u32 data_offset); void rtw89_core_napi_start(struct rtw89_dev *rtwdev); void rtw89_core_napi_stop(struct rtw89_dev *rtwdev); int rtw89_core_napi_init(struct rtw89_dev *rtwdev); @@ -7505,6 +7872,8 @@ struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id); void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev); +void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link); const struct rtw89_6ghz_span * rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq); void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef); @@ -7530,13 +7899,18 @@ void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc); int rtw89_chip_info_setup(struct rtw89_dev *rtwdev); void rtw89_chip_cfg_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); -bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate); +bool rtw89_legacy_rate_to_bitrate(struct rtw89_dev *rtwdev, u8 legacy_rate, u16 *bitrate); int rtw89_regd_setup(struct rtw89_dev *rtwdev); int rtw89_regd_init_hint(struct rtw89_dev *rtwdev); const char *rtw89_regd_get_string(enum rtw89_regulation_type regd); void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, struct rtw89_traffic_stats *stats); -int rtw89_wait_for_cond(struct rtw89_wait_info *wait, unsigned int cond); +struct rtw89_wait_response * +rtw89_wait_for_cond_prep(struct rtw89_wait_info *wait, unsigned int cond) +__acquires(rtw89_wait); +int rtw89_wait_for_cond_eval(struct rtw89_wait_info *wait, + struct rtw89_wait_response *prep, int err) +__releases(rtw89_wait); void rtw89_complete_cond(struct rtw89_wait_info *wait, unsigned int cond, const struct rtw89_completion_data *data); int rtw89_core_start(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 1811111042fd9..5f7146af47304 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -79,6 +79,7 @@ struct rtw89_debugfs { struct rtw89_debugfs_priv send_h2c; struct rtw89_debugfs_priv early_h2c; struct rtw89_debugfs_priv fw_crash; + struct rtw89_debugfs_priv ser_counters; struct rtw89_debugfs_priv btc_info; struct rtw89_debugfs_priv btc_manual; struct rtw89_debugfs_priv fw_log_manual; @@ -87,6 +88,8 @@ struct rtw89_debugfs { struct rtw89_debugfs_priv disable_dm; struct rtw89_debugfs_priv wifi_test_config; struct rtw89_debugfs_priv mlo_mode; + struct rtw89_debugfs_priv beacon_info; + struct rtw89_debugfs_priv diag_mac; }; struct rtw89_debugfs_iter_data { @@ -3514,13 +3517,49 @@ rtw89_debug_priv_early_h2c_set(struct rtw89_dev *rtwdev, return count; } -static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev) +static int rtw89_dbg_trigger_l1_error_by_halt_h2c_ax(struct rtw89_dev *rtwdev) +{ + if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)) + return -EBUSY; + + return rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RESET_FORCE); +} + +static int rtw89_dbg_trigger_l1_error_by_halt_h2c_be(struct rtw89_dev *rtwdev) +{ + if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)) + return -EBUSY; + + rtw89_write32_set(rtwdev, R_BE_FW_TRIGGER_IDCT_ISR, + B_BE_DMAC_FW_TRIG_IDCT | B_BE_DMAC_FW_ERR_IDCT_IMR); + + return 0; +} + +static int rtw89_dbg_trigger_l1_error_by_halt_h2c(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + switch (chip->chip_gen) { + case RTW89_CHIP_AX: + return rtw89_dbg_trigger_l1_error_by_halt_h2c_ax(rtwdev); + case RTW89_CHIP_BE: + return rtw89_dbg_trigger_l1_error_by_halt_h2c_be(rtwdev); + default: + return -EOPNOTSUPP; + } +} + +static int rtw89_dbg_trigger_l1_error(struct rtw89_dev *rtwdev) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; struct rtw89_cpuio_ctrl ctrl_para = {0}; u16 pkt_id; int ret; + if (RTW89_CHK_FW_FEATURE(SIM_SER_L0L1_BY_HALT_H2C, &rtwdev->fw)) + return rtw89_dbg_trigger_l1_error_by_halt_h2c(rtwdev); + rtw89_leave_ps_mode(rtwdev); ret = mac->dle_buf_req(rtwdev, 0x20, true, &pkt_id); @@ -3541,6 +3580,91 @@ static int rtw89_dbg_trigger_ctrl_error(struct rtw89_dev *rtwdev) return 0; } +static int rtw89_dbg_trigger_l0_error_ax(struct rtw89_dev *rtwdev) +{ + u16 val16; + u8 val8; + int ret; + + ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL); + if (ret) + return ret; + + val8 = rtw89_read8(rtwdev, R_AX_CMAC_FUNC_EN); + rtw89_write8(rtwdev, R_AX_CMAC_FUNC_EN, val8 & ~B_AX_TMAC_EN); + mdelay(1); + rtw89_write8(rtwdev, R_AX_CMAC_FUNC_EN, val8); + + val16 = rtw89_read16(rtwdev, R_AX_PTCL_IMR0); + rtw89_write16(rtwdev, R_AX_PTCL_IMR0, val16 | B_AX_F2PCMD_EMPTY_ERR_INT_EN); + rtw89_write16(rtwdev, R_AX_PTCL_IMR0, val16); + + return 0; +} + +static int rtw89_dbg_trigger_l0_error_be(struct rtw89_dev *rtwdev) +{ + u8 val8; + int ret; + + ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_CMAC_SEL); + if (ret) + return ret; + + val8 = rtw89_read8(rtwdev, R_BE_CMAC_FUNC_EN); + rtw89_write8(rtwdev, R_BE_CMAC_FUNC_EN, val8 & ~B_BE_TMAC_EN); + mdelay(1); + rtw89_write8(rtwdev, R_BE_CMAC_FUNC_EN, val8); + + return 0; +} + +static int rtw89_dbg_trigger_l0_error_by_halt_h2c_ax(struct rtw89_dev *rtwdev) +{ + if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)) + return -EBUSY; + + return rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L0_RESET_FORCE); +} + +static int rtw89_dbg_trigger_l0_error_by_halt_h2c_be(struct rtw89_dev *rtwdev) +{ + if (!test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)) + return -EBUSY; + + rtw89_write32_set(rtwdev, R_BE_CMAC_FW_TRIGGER_IDCT_ISR, + B_BE_CMAC_FW_TRIG_IDCT | B_BE_CMAC_FW_ERR_IDCT_IMR); + + return 0; +} + +static int rtw89_dbg_trigger_l0_error(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + int (*sim_l0_by_halt_h2c)(struct rtw89_dev *rtwdev); + int (*sim_l0)(struct rtw89_dev *rtwdev); + + switch (chip->chip_gen) { + case RTW89_CHIP_AX: + sim_l0_by_halt_h2c = rtw89_dbg_trigger_l0_error_by_halt_h2c_ax; + sim_l0 = rtw89_dbg_trigger_l0_error_ax; + break; + case RTW89_CHIP_BE: + sim_l0_by_halt_h2c = rtw89_dbg_trigger_l0_error_by_halt_h2c_be; + sim_l0 = rtw89_dbg_trigger_l0_error_be; + break; + default: + return -EOPNOTSUPP; + } + + if (RTW89_CHK_FW_FEATURE(SIM_SER_L0L1_BY_HALT_H2C, &rtwdev->fw)) + return sim_l0_by_halt_h2c(rtwdev); + + rtw89_leave_ps_mode(rtwdev); + + return sim_l0(rtwdev); +} + static ssize_t rtw89_debug_priv_fw_crash_get(struct rtw89_dev *rtwdev, struct rtw89_debugfs_priv *debugfs_priv, @@ -3555,7 +3679,8 @@ rtw89_debug_priv_fw_crash_get(struct rtw89_dev *rtwdev, enum rtw89_dbg_crash_simulation_type { RTW89_DBG_SIM_CPU_EXCEPTION = 1, - RTW89_DBG_SIM_CTRL_ERROR = 2, + RTW89_DBG_SIM_L1_ERROR = 2, + RTW89_DBG_SIM_L0_ERROR = 3, }; static ssize_t @@ -3564,6 +3689,7 @@ rtw89_debug_priv_fw_crash_set(struct rtw89_dev *rtwdev, const char *buf, size_t count) { int (*sim)(struct rtw89_dev *rtwdev); + bool announce = true; u8 crash_type; int ret; @@ -3575,18 +3701,26 @@ rtw89_debug_priv_fw_crash_set(struct rtw89_dev *rtwdev, switch (crash_type) { case RTW89_DBG_SIM_CPU_EXCEPTION: - if (!RTW89_CHK_FW_FEATURE(CRASH_TRIGGER, &rtwdev->fw)) + if (!RTW89_CHK_FW_FEATURE_GROUP(CRASH_TRIGGER, &rtwdev->fw)) return -EOPNOTSUPP; sim = rtw89_fw_h2c_trigger_cpu_exception; break; - case RTW89_DBG_SIM_CTRL_ERROR: - sim = rtw89_dbg_trigger_ctrl_error; + case RTW89_DBG_SIM_L1_ERROR: + sim = rtw89_dbg_trigger_l1_error; + break; + case RTW89_DBG_SIM_L0_ERROR: + sim = rtw89_dbg_trigger_l0_error; + + /* Driver SER flow won't get involved; only FW will. */ + announce = false; break; default: return -EINVAL; } - set_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags); + if (announce) + set_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags); + ret = sim(rtwdev); if (ret) @@ -3595,6 +3729,60 @@ rtw89_debug_priv_fw_crash_set(struct rtw89_dev *rtwdev, return count; } +struct rtw89_dbg_ser_counters { + unsigned int l0; + unsigned int l1; + unsigned int l0_to_l1; +}; + +static void rtw89_dbg_get_ser_counters_ax(struct rtw89_dev *rtwdev, + struct rtw89_dbg_ser_counters *cnt) +{ + const u32 val = rtw89_read32(rtwdev, R_AX_SER_DBG_INFO); + + cnt->l0 = u32_get_bits(val, B_AX_SER_L0_COUNTER_MASK); + cnt->l1 = u32_get_bits(val, B_AX_SER_L1_COUNTER_MASK); + cnt->l0_to_l1 = u32_get_bits(val, B_AX_L0_TO_L1_EVENT_MASK); +} + +static void rtw89_dbg_get_ser_counters_be(struct rtw89_dev *rtwdev, + struct rtw89_dbg_ser_counters *cnt) +{ + const u32 val = rtw89_read32(rtwdev, R_BE_SER_DBG_INFO); + + cnt->l0 = u32_get_bits(val, B_BE_SER_L0_COUNTER_MASK); + cnt->l1 = u32_get_bits(val, B_BE_SER_L1_COUNTER_MASK); + cnt->l0_to_l1 = u32_get_bits(val, B_BE_SER_L0_PROMOTE_L1_EVENT_MASK); +} + +static ssize_t rtw89_debug_priv_ser_counters_get(struct rtw89_dev *rtwdev, + struct rtw89_debugfs_priv *debugfs_priv, + char *buf, size_t bufsz) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_dbg_ser_counters cnt = {}; + char *p = buf, *end = buf + bufsz; + + rtw89_leave_ps_mode(rtwdev); + + switch (chip->chip_gen) { + case RTW89_CHIP_AX: + rtw89_dbg_get_ser_counters_ax(rtwdev, &cnt); + break; + case RTW89_CHIP_BE: + rtw89_dbg_get_ser_counters_be(rtwdev, &cnt); + break; + default: + return -EOPNOTSUPP; + } + + p += scnprintf(p, end - p, "SER L0 Count: %d\n", cnt.l0); + p += scnprintf(p, end - p, "SER L1 Count: %d\n", cnt.l1); + p += scnprintf(p, end - p, "SER L0 promote event: %d\n", cnt.l0_to_l1); + + return p - buf; +} + static ssize_t rtw89_debug_priv_btc_info_get(struct rtw89_dev *rtwdev, struct rtw89_debugfs_priv *debugfs_priv, char *buf, size_t bufsz) @@ -4277,6 +4465,302 @@ rtw89_debug_priv_mlo_mode_set(struct rtw89_dev *rtwdev, return count; } +enum __diag_mac_cmd { + __CMD_EQUALV, + __CMD_EQUALO, + __CMD_NEQUALV, + __CMD_NEQUALO, + __CMD_SETEQUALV, + __CMD_SETEQUALO, + __CMD_CMPWCR, + __CMD_CMPWWD, + __CMD_NEQ_CMPWCR, + __CMD_NEQ_CMPWWD, + __CMD_INCREMENT, + __CMD_MESSAGE, +}; + +enum __diag_mac_io { + __IO_NORMAL, + __IO_NORMAL_PCIE, + __IO_NORMAL_USB, + __IO_NORMAL_SDIO, + __IO_PCIE_CFG, + __IO_SDIO_CCCR, +}; + +struct __diag_mac_rule_header { + u8 sheet; + u8 cmd; + u8 seq_major; + u8 seq_minor; + u8 io_band; + #define __DIAG_MAC_IO GENMASK(3, 0) + #define __DIAG_MAC_N_BAND BIT(4) + #define __DIAG_MAC_HAS_BAND BIT(5) + u8 len; /* include header. Unit: 4 bytes */ + u8 rsvd[2]; +} __packed; + +struct __diag_mac_rule_equal { + struct __diag_mac_rule_header header; + __le32 addr; + __le32 addr_name_offset; + __le32 mask; + __le32 val; + __le32 msg_offset; + u8 rsvd[4]; +} __packed; + +struct __diag_mac_rule_increment { + struct __diag_mac_rule_header header; + __le32 addr; + __le32 addr_name_offset; + __le32 mask; + __le16 sel; + __le16 delay; + __le32 msg_offset; + u8 rsvd[4]; +} __packed; + +struct __diag_mac_msg_buf { + __le16 len; + char string[]; +} __packed; + +static ssize_t rtw89_mac_diag_do_equalv(struct rtw89_dev *rtwdev, + char *buf, size_t bufsz, + const struct __diag_mac_rule_equal *r, + const void *msg_start, + u64 *positive_bmp) +{ + const struct __diag_mac_msg_buf *name = msg_start + + le32_to_cpu(r->addr_name_offset); + const struct __diag_mac_msg_buf *msg = msg_start + + le32_to_cpu(r->msg_offset); + bool want_eq = r->header.cmd == __CMD_EQUALV; + char *p = buf, *end = buf + bufsz; + bool equal = false; + u32 val; + + *positive_bmp <<= 1; + + if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG) + val = rtw89_read32_pci_cfg(rtwdev, le32_to_cpu(r->addr)); + else + val = rtw89_read32(rtwdev, le32_to_cpu(r->addr)); + + if ((val & le32_to_cpu(r->mask)) == le32_to_cpu(r->val)) + equal = true; + + if (want_eq == equal) { + *positive_bmp |= BIT(0); + return p - buf; + } + + p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s => %x, %.*s\n", + r->header.sheet, r->header.cmd, le16_to_cpu(name->len), + name->string, val, le16_to_cpu(msg->len), msg->string); + + return p - buf; +} + +static ssize_t rtw89_mac_diag_do_increment(struct rtw89_dev *rtwdev, + char *buf, size_t bufsz, + const struct __diag_mac_rule_increment *r, + const void *msg_start, + u64 *positive_bmp) +{ + const struct __diag_mac_msg_buf *name = msg_start + + le32_to_cpu(r->addr_name_offset); + const struct __diag_mac_msg_buf *msg = msg_start + + le32_to_cpu(r->msg_offset); + char *p = buf, *end = buf + bufsz; + u32 addr = le32_to_cpu(r->addr); + u32 mask = le32_to_cpu(r->mask); + u16 sel = le16_to_cpu(r->sel); + u32 val1, val2; + + *positive_bmp <<= 1; + + rtw89_write32(rtwdev, addr, sel); + + if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG) + val1 = rtw89_read32_pci_cfg(rtwdev, addr); + else + val1 = rtw89_read32(rtwdev, addr); + + mdelay(le16_to_cpu(r->delay)); + + if (u8_get_bits(r->header.io_band, __DIAG_MAC_IO) == __IO_PCIE_CFG) + val2 = rtw89_read32_pci_cfg(rtwdev, addr); + else + val2 = rtw89_read32(rtwdev, addr); + + if ((val2 & mask) > (val1 & mask)) { + *positive_bmp |= BIT(0); + return p - buf; + } + + p += scnprintf(p, end - p, "sheet: %d, cmd: %d, Reg: %.*s [%d]=> %x, %.*s\n", + r->header.sheet, r->header.cmd, le16_to_cpu(name->len), + name->string, le16_to_cpu(r->sel), val1, + le16_to_cpu(msg->len), msg->string); + + return p - buf; +} + +static bool rtw89_mac_diag_match_hci(struct rtw89_dev *rtwdev, + const struct __diag_mac_rule_header *rh) +{ + switch (u8_get_bits(rh->io_band, __DIAG_MAC_IO)) { + case __IO_NORMAL: + default: + return true; + case __IO_NORMAL_PCIE: + case __IO_PCIE_CFG: + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + return true; + break; + case __IO_NORMAL_USB: + if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + return true; + break; + case __IO_NORMAL_SDIO: + case __IO_SDIO_CCCR: + if (rtwdev->hci.type == RTW89_HCI_TYPE_SDIO) + return true; + break; + } + + return false; +} + +static bool rtw89_mac_diag_match_band(struct rtw89_dev *rtwdev, + const struct __diag_mac_rule_header *rh) +{ + u8 active_bands; + bool has_band; + u8 band; + + has_band = u8_get_bits(rh->io_band, __DIAG_MAC_HAS_BAND); + if (!has_band) + return true; + + band = u8_get_bits(rh->io_band, __DIAG_MAC_N_BAND); + active_bands = rtw89_get_active_phy_bitmap(rtwdev); + + if (active_bands & BIT(band)) + return true; + + return false; +} + +static ssize_t rtw89_mac_diag_iter_all(struct rtw89_dev *rtwdev, + char *buf, size_t bufsz) +{ + const struct rtw89_fw_element_hdr *elm = rtwdev->fw.elm_info.diag_mac; + u32 n_plains = 0, n_rules = 0, n_positive = 0, n_ignore = 0; + char *p = buf, *end = buf + bufsz, *p_rewind; + const void *rule, *rule_end; + u32 elm_size, rule_size; + const void *msg_start; + u64 positive_bmp = 0; + u8 prev_sheet = 0; + u8 prev_seq = 0; + int limit; + + if (!elm) { + p += scnprintf(p, end - p, "No diag_mac entry\n"); + goto out; + } + + rule_size = le32_to_cpu(elm->u.diag_mac.rule_size); + elm_size = le32_to_cpu(elm->size); + + if (ALIGN(rule_size, 16) > elm_size) { + p += scnprintf(p, end - p, "rule size (%u) exceed elm_size (%u)\n", + ALIGN(rule_size, 16), elm_size); + goto out; + } + + rule = &elm->u.diag_mac.rules_and_msgs[0]; + rule_end = &elm->u.diag_mac.rules_and_msgs[rule_size]; + msg_start = &elm->u.diag_mac.rules_and_msgs[ALIGN(rule_size, 16)]; + + for (limit = 0; limit < 5000 && rule < rule_end; limit++) { + const struct __diag_mac_rule_header *rh = rule; + u8 sheet = rh->sheet; + u8 seq = rh->seq_major; + + if (!rtw89_mac_diag_match_hci(rtwdev, rh) || + !rtw89_mac_diag_match_band(rtwdev, rh)) { + n_ignore++; + goto next; + } + + if (!seq || prev_sheet != sheet || prev_seq != seq) { + if (positive_bmp) { + n_positive++; + /* + * discard output for negative results if one in + * a sequence set is positive. + */ + if (p_rewind) + p = p_rewind; + } + p_rewind = seq ? p : NULL; + positive_bmp = 0; + n_rules++; + } + + switch (rh->cmd) { + case __CMD_EQUALV: + case __CMD_NEQUALV: + p += rtw89_mac_diag_do_equalv(rtwdev, p, end - p, rule, + msg_start, &positive_bmp); + break; + case __CMD_INCREMENT: + p += rtw89_mac_diag_do_increment(rtwdev, p, end - p, rule, + msg_start, &positive_bmp); + break; + default: + p += scnprintf(p, end - p, "unknown rule cmd %u\n", rh->cmd); + break; + } + +next: + n_plains++; + rule += rh->len * 4; + prev_seq = seq; + prev_sheet = sheet; + } + + if (positive_bmp) { + n_positive++; + if (p_rewind) + p = p_rewind; + } + + p += scnprintf(p, end - p, "\nPlain(Ignore)/Rules/Positive: %u(%u)/%u/%u\n", + n_plains, n_ignore, n_rules, n_positive); + +out: + return p - buf; +} + +static ssize_t +rtw89_debug_priv_diag_mac_get(struct rtw89_dev *rtwdev, + struct rtw89_debugfs_priv *debugfs_priv, + char *buf, size_t bufsz) +{ + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + rtw89_leave_lps(rtwdev); + + return rtw89_mac_diag_iter_all(rtwdev, buf, bufsz); +} + static ssize_t rtw89_debug_priv_wifi_test_config_set(struct rtw89_dev *rtwdev, struct rtw89_debugfs_priv *debugfs_priv, @@ -4305,6 +4789,64 @@ rtw89_debug_priv_wifi_test_config_set(struct rtw89_dev *rtwdev, return count; } +static ssize_t +rtw89_debug_priv_beacon_info_get(struct rtw89_dev *rtwdev, + struct rtw89_debugfs_priv *debugfs_priv, + char *buf, size_t bufsz) +{ + struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.last_pkt_stat; + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + struct rtw89_beacon_stat *bcn_stat = &rtwdev->phystat.bcn_stat; + struct rtw89_beacon_dist *bcn_dist = &bcn_stat->bcn_dist; + u16 upper, lower = bcn_stat->tbtt_tu_min; + char *p = buf, *end = buf + bufsz; + u16 *drift = bcn_stat->drift; + u8 bcn_num = bcn_stat->num; + u8 count; + u8 i; + + p += scnprintf(p, end - p, "[Beacon info]\n"); + p += scnprintf(p, end - p, "count: %u\n", pkt_stat->beacon_nr); + p += scnprintf(p, end - p, "interval: %u\n", bcn_track->beacon_int); + p += scnprintf(p, end - p, "dtim: %u\n", bcn_track->dtim); + p += scnprintf(p, end - p, "raw rssi: %lu\n", + ewma_rssi_read(&rtwdev->phystat.bcn_rssi)); + p += scnprintf(p, end - p, "hw rate: %u\n", pkt_stat->beacon_rate); + p += scnprintf(p, end - p, "length: %u\n", pkt_stat->beacon_len); + + p += scnprintf(p, end - p, "\n[Distribution]\n"); + p += scnprintf(p, end - p, "tbtt\n"); + for (i = 0; i < RTW89_BCN_TRACK_MAX_BIN_NUM; i++) { + upper = lower + RTW89_BCN_TRACK_BIN_WIDTH - 1; + if (i == RTW89_BCN_TRACK_MAX_BIN_NUM - 1) + upper = max(upper, bcn_stat->tbtt_tu_max); + + p += scnprintf(p, end - p, "%02u - %02u: %u\n", + lower, upper, bcn_dist->bins[i]); + + lower = upper + 1; + } + + p += scnprintf(p, end - p, "\ndrift\n"); + + for (i = 0; i < bcn_num; i += count) { + count = 1; + while (i + count < bcn_num && drift[i] == drift[i + count]) + count++; + + p += scnprintf(p, end - p, "%u: %u\n", drift[i], count); + } + p += scnprintf(p, end - p, "\nlower bound: %u\n", bcn_dist->lower_bound); + p += scnprintf(p, end - p, "upper bound: %u\n", bcn_dist->upper_bound); + p += scnprintf(p, end - p, "outlier count: %u\n", bcn_dist->outlier_count); + + p += scnprintf(p, end - p, "\n[Tracking]\n"); + p += scnprintf(p, end - p, "tbtt offset: %u\n", bcn_track->tbtt_offset); + p += scnprintf(p, end - p, "bcn timeout: %u\n", bcn_track->bcn_timeout); + + return p - buf; +} + #define rtw89_debug_priv_get(name, opts...) \ { \ .cb_read = rtw89_debug_priv_ ##name## _get, \ @@ -4356,6 +4898,7 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = { .send_h2c = rtw89_debug_priv_set(send_h2c), .early_h2c = rtw89_debug_priv_set_and_get(early_h2c, RWLOCK), .fw_crash = rtw89_debug_priv_set_and_get(fw_crash, WLOCK), + .ser_counters = rtw89_debug_priv_get(ser_counters, RLOCK), .btc_info = rtw89_debug_priv_get(btc_info, RSIZE_12K), .btc_manual = rtw89_debug_priv_set(btc_manual), .fw_log_manual = rtw89_debug_priv_set(fw_log_manual, WLOCK), @@ -4364,6 +4907,8 @@ static const struct rtw89_debugfs rtw89_debugfs_templ = { .disable_dm = rtw89_debug_priv_set_and_get(disable_dm, RWLOCK), .wifi_test_config = rtw89_debug_priv_set(wifi_test_config), .mlo_mode = rtw89_debug_priv_set_and_get(mlo_mode, RWLOCK), + .beacon_info = rtw89_debug_priv_get(beacon_info), + .diag_mac = rtw89_debug_priv_get(diag_mac, RSIZE_16K, RLOCK), }; #define rtw89_debugfs_add(name, mode, fopname, parent) \ @@ -4402,6 +4947,7 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top rtw89_debugfs_add_w(send_h2c); rtw89_debugfs_add_rw(early_h2c); rtw89_debugfs_add_rw(fw_crash); + rtw89_debugfs_add_r(ser_counters); rtw89_debugfs_add_r(btc_info); rtw89_debugfs_add_w(btc_manual); rtw89_debugfs_add_w(fw_log_manual); @@ -4410,6 +4956,8 @@ void rtw89_debugfs_add_sec1(struct rtw89_dev *rtwdev, struct dentry *debugfs_top rtw89_debugfs_add_rw(disable_dm); rtw89_debugfs_add_rw(mlo_mode); rtw89_debugfs_add_w(wifi_test_config); + rtw89_debugfs_add_r(beacon_info); + rtw89_debugfs_add_r(diag_mac); } void rtw89_debugfs_init(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h index fc690f7c55dc7..7cdceb24f52dd 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.h +++ b/drivers/net/wireless/realtek/rtw89/debug.h @@ -31,6 +31,7 @@ enum rtw89_debug_mask { RTW89_DBG_CHAN = BIT(20), RTW89_DBG_ACPI = BIT(21), RTW89_DBG_EDCCA = BIT(22), + RTW89_DBG_PS = BIT(23), RTW89_DBG_UNEXP = BIT(31), }; @@ -56,6 +57,7 @@ static inline void rtw89_debugfs_deinit(struct rtw89_dev *rtwdev) {} #endif #define rtw89_info(rtwdev, a...) dev_info((rtwdev)->dev, ##a) +#define rtw89_info_once(rtwdev, a...) dev_info_once((rtwdev)->dev, ##a) #define rtw89_warn(rtwdev, a...) dev_warn((rtwdev)->dev, ##a) #define rtw89_err(rtwdev, a...) dev_err((rtwdev)->dev, ##a) diff --git a/drivers/net/wireless/realtek/rtw89/drv_ver.c b/drivers/net/wireless/realtek/rtw89/drv_ver.c index 15ce2711d45bb..934eb29664261 100644 --- a/drivers/net/wireless/realtek/rtw89/drv_ver.c +++ b/drivers/net/wireless/realtek/rtw89/drv_ver.c @@ -1,4 +1,4 @@ -#define VERSTR "v6.16-backport-6.6-g722e3d06b" +#define VERSTR "v6.18-backport-6.6-ac17d40858" static char drv_ver[] = VERSTR; #include diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c index 6c6c763510af6..a2757a88d55da 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.c +++ b/drivers/net/wireless/realtek/rtw89/efuse.c @@ -7,10 +7,6 @@ #include "mac.h" #include "reg.h" -#define EF_FV_OFSET 0x5ea -#define EF_CV_MASK GENMASK(7, 4) -#define EF_CV_INV 15 - #define EFUSE_B1_MSSDEVTYPE_MASK GENMASK(3, 0) #define EFUSE_B1_MSSCUSTIDX0_MASK GENMASK(7, 4) #define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0) diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h index a96fc10447910..a14a9dfed8e8f 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.h +++ b/drivers/net/wireless/realtek/rtw89/efuse.h @@ -11,6 +11,11 @@ #define RTW89_EFUSE_BLOCK_SIZE_MASK GENMASK(15, 0) #define RTW89_EFUSE_MAX_BLOCK_SIZE 0x10000 +#define EF_FV_OFSET 0x5EA +#define EF_FV_OFSET_BE_V1 0x17CA +#define EF_CV_MASK GENMASK(7, 4) +#define EF_CV_INV 15 + struct rtw89_efuse_block_cfg { u32 offset; u32 size; @@ -26,5 +31,6 @@ int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv); int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2); int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev); int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev); +int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev); #endif diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c index 64768923b0f0a..70c1b8be662e1 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse_be.c +++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c @@ -512,3 +512,29 @@ int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev) return 0; } + +int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev) +{ + u32 dump_addr; + u8 buff[4]; /* efuse access must 4 bytes align */ + int ret; + u8 ecv; + u8 val; + + dump_addr = ALIGN_DOWN(EF_FV_OFSET_BE_V1, 4); + + ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false); + if (ret) + return ret; + + val = buff[EF_FV_OFSET_BE_V1 & 0x3]; + + ecv = u8_get_bits(val, EF_CV_MASK); + if (ecv == EF_CV_INV) + return -ENOENT; + + rtwdev->hal.cv = ecv; + + return 0; +} +EXPORT_SYMBOL(rtw89_efuse_read_ecv_be); diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index e1ba9c191279d..5e02eca6a046e 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -161,6 +161,11 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_W7_DYN_HDR); info->idmem_share_mode = le32_get_bits(fw_hdr->w7, FW_HDR_W7_IDMEM_SHARE_MODE); + if (chip->chip_gen == RTW89_CHIP_AX) + info->part_size = FWDL_SECTION_PER_PKT_LEN; + else + info->part_size = le32_get_bits(fw_hdr->w7, FW_HDR_W7_PART_SIZE); + if (info->dynamic_hdr_en) { info->hdr_len = le32_get_bits(fw_hdr->w3, FW_HDR_W3_LEN); info->dynamic_hdr_len = info->hdr_len - base_hdr_len; @@ -439,6 +444,7 @@ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le struct rtw89_fw_bin_info *info) { const struct rtw89_fw_hdr_v1 *fw_hdr = (const struct rtw89_fw_hdr_v1 *)fw; + const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_fw_hdr_section_info *section_info; const struct rtw89_fw_dynhdr_hdr *fwdynhdr; const struct rtw89_fw_hdr_section_v1 *section; @@ -455,6 +461,11 @@ static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR); info->idmem_share_mode = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_IDMEM_SHARE_MODE); + if (chip->chip_gen == RTW89_CHIP_AX) + info->part_size = FWDL_SECTION_PER_PKT_LEN; + else + info->part_size = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_PART_SIZE); + if (info->dynamic_hdr_en) { info->hdr_len = le32_get_bits(fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE); info->dynamic_hdr_len = info->hdr_len - base_hdr_len; @@ -801,6 +812,8 @@ struct __fw_feat_cfg { enum rtw89_fw_feature feature; u32 ver_code; bool (*cond)(u32 suit_ver_code, u32 comp_ver_code); + bool disable; + int size; }; #define __CFG_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat) \ @@ -811,51 +824,105 @@ struct __fw_feat_cfg { .cond = __fw_feat_cond_ ## _cond, \ } +#define __S_DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat) \ + { \ + .chip_id = _chip, \ + .feature = RTW89_FW_FEATURE_ ## _feat, \ + .ver_code = RTW89_FW_VER_CODE(_maj, _min, _sub, _idx), \ + .cond = __fw_feat_cond_ ## _cond, \ + .disable = true, \ + .size = 1, \ + } + +#define __G_DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _grp) \ + { \ + .chip_id = _chip, \ + .feature = RTW89_FW_FEATURE_ ## _grp ## _MIN, \ + .ver_code = RTW89_FW_VER_CODE(_maj, _min, _sub, _idx), \ + .cond = __fw_feat_cond_ ## _cond, \ + .disable = true, \ + .size = RTW89_FW_FEATURE_ ## _grp ## _MAX - \ + RTW89_FW_FEATURE_ ## _grp ## _MIN + 1, \ + } + +#define __DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat, _type) \ + __##_type##_DIS_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat) + static const struct __fw_feat_cfg fw_feat_tbl[] = { __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE), __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD), - __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER_TYPE_0), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 127, 0, SER_L1_BY_EVENT), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C), __CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE), - __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER_TYPE_0), __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 37, 0, NO_WOW_CPU_IO_RX), __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 38, 0, NO_PACKET_DROP), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE), - __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER_TYPE_0), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 7, BEACON_FILTER), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 15, BEACON_LOSS_COUNT_V1), __CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 127, 0, LPS_DACK_BY_C2H_REG), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 127, 0, SER_L1_BY_EVENT), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 128, 0, CRASH_TRIGGER_TYPE_1), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 128, 0, SCAN_OFFLOAD_EXTRA_OP), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 128, 0, BEACON_TRACKING), + __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE), - __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER_TYPE_0), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 91, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 110, 0, BEACON_FILTER), - __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 122, 0, BEACON_TRACKING), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, SCAN_OFFLOAD_EXTRA_OP), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, LPS_DACK_BY_C2H_REG), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, CRASH_TRIGGER_TYPE_1), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, SER_L1_BY_EVENT), + __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C), __CFG_FW_FEAT(RTL8852C, ge, 0, 0, 0, 0, RFK_NTFY_MCC_V0), + __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD), - __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER_TYPE_0), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 80, 0, WOW_REASON_V1), __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, BEACON_LOSS_COUNT_V1), - __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER), + __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, LPS_DACK_BY_C2H_REG), + __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, CRASH_TRIGGER_TYPE_1), + __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 129, 1, BEACON_TRACKING), + __CFG_FW_FEAT(RTL8852C, ge, 0, 29, 94, 0, SER_L1_BY_EVENT), + __CFG_FW_FEAT(RTL8852C, ge, 0, 29, 130, 0, SIM_SER_L0L1_BY_HALT_H2C), + __CFG_FW_FEAT(RTL8922A, ge, 0, 0, 0, 0, RFK_PRE_NOTIFY_V0), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 11, 0, MACID_PAUSE_SLEEP), + __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER_TYPE_0), __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD), - __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 21, 0, SCAN_OFFLOAD_BE_V0), + __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD_EXTRA_OP), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 21, 0, SCAN_OFFLOAD_BE_V0), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 28, 0, RFK_IQK_V0), - __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 31, 0, RFK_PRE_NOTIFY_V1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, LPS_CH_INFO), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 46, 0, NOTIFY_AP_INFO), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0), - __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 49, 0, RFK_PRE_NOTIFY_V2), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 49, 0, RFK_PRE_NOTIFY_MCC_V0), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1), __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE), __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 71, 0, BEACON_LOSS_COUNT_V1), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 76, 0, LPS_DACK_BY_C2H_REG), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 79, 0, CRASH_TRIGGER_TYPE_1), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 80, 0, BEACON_TRACKING), + __DIS_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, WITH_RFK_PRE_NOTIFY, G), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 84, 0, RFK_PRE_NOTIFY_MCC_V1), + __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 84, 0, ADDR_CAM_V0), + __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 97, 0, SIM_SER_L0L1_BY_HALT_H2C), }; static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, @@ -870,8 +937,16 @@ static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw, if (chip->chip_id != ent->chip_id) continue; - if (ent->cond(ver_code, ent->ver_code)) + if (!ent->cond(ver_code, ent->ver_code)) + continue; + + if (!ent->disable) { RTW89_SET_FW_FEATURE(ent->feature, fw); + continue; + } + + for (int n = 0; n < ent->size; n++) + RTW89_CLR_FW_FEATURE(ent->feature + n, fw); } } @@ -987,42 +1062,47 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev, const union rtw89_fw_element_arg arg) { struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; - struct rtw89_phy_table *tbl; + struct rtw89_hal *hal = &rtwdev->hal; + struct rtw89_phy_table *tbl, **pp; struct rtw89_reg2_def *regs; - enum rtw89_rf_path rf_path; + bool radio = false; u32 n_regs, i; + u16 aid; u8 idx; - tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); - if (!tbl) - return -ENOMEM; - switch (le32_to_cpu(elm->id)) { case RTW89_FW_ELEMENT_ID_BB_REG: - elm_info->bb_tbl = tbl; + pp = &elm_info->bb_tbl; break; case RTW89_FW_ELEMENT_ID_BB_GAIN: - elm_info->bb_gain = tbl; + pp = &elm_info->bb_gain; break; case RTW89_FW_ELEMENT_ID_RADIO_A: case RTW89_FW_ELEMENT_ID_RADIO_B: case RTW89_FW_ELEMENT_ID_RADIO_C: case RTW89_FW_ELEMENT_ID_RADIO_D: - rf_path = arg.rf_path; idx = elm->u.reg2.idx; + pp = &elm_info->rf_radio[idx]; - elm_info->rf_radio[idx] = tbl; - tbl->rf_path = rf_path; - tbl->config = rtw89_phy_config_rf_reg_v1; + radio = true; break; case RTW89_FW_ELEMENT_ID_RF_NCTL: - elm_info->rf_nctl = tbl; + pp = &elm_info->rf_nctl; break; default: - kfree(tbl); return -ENOENT; } + aid = le16_to_cpu(elm->aid); + if (aid && aid != hal->aid) + return 1; /* ignore if aid not matched */ + else if (*pp) + return 1; /* ignore if an element is existing */ + + tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); + if (!tbl) + return -ENOMEM; + n_regs = le32_to_cpu(elm->size) / sizeof(tbl->regs[0]); regs = kcalloc(n_regs, sizeof(tbl->regs[0]), GFP_KERNEL); if (!regs) @@ -1036,6 +1116,13 @@ int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev, tbl->n_regs = n_regs; tbl->regs = regs; + if (radio) { + tbl->rf_path = arg.rf_path; + tbl->config = rtw89_phy_config_rf_reg_v1; + } + + *pp = tbl; + return 0; out: @@ -1272,6 +1359,50 @@ int rtw89_recognize_regd_from_elm(struct rtw89_dev *rtwdev, return 0; } +static +int rtw89_build_afe_pwr_seq_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const union rtw89_fw_element_arg arg) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + + elm_info->afe = elm; + + return 0; +} + +static +int rtw89_recognize_diag_mac_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const union rtw89_fw_element_arg arg) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + + elm_info->diag_mac = elm; + + return 0; +} + +static +int rtw89_build_tx_comp_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const union rtw89_fw_element_arg arg) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + struct rtw89_hal *hal = &rtwdev->hal; + u16 aid; + + aid = le16_to_cpu(elm->aid); + if (aid && aid != hal->aid) + return 1; /* ignore if aid not matched */ + else if (elm_info->tx_comp) + return 1; /* ignore if an element is existing */ + + elm_info->tx_comp = elm; + + return 0; +} + static const struct rtw89_fw_element_handler __fw_element_handlers[] = { [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm, { .fw_type = RTW89_FW_BBMCU0 }, NULL}, @@ -1357,6 +1488,15 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = { [RTW89_FW_ELEMENT_ID_REGD] = { rtw89_recognize_regd_from_elm, {}, "REGD", }, + [RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ] = { + rtw89_build_afe_pwr_seq_from_elm, {}, "AFE", + }, + [RTW89_FW_ELEMENT_ID_DIAG_MAC] = { + rtw89_recognize_diag_mac_from_elm, {}, NULL, + }, + [RTW89_FW_ELEMENT_ID_TX_COMP] = { + rtw89_build_tx_comp_from_elm, {}, NULL, + }, }; int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) @@ -1425,11 +1565,12 @@ void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len) { + const struct rtw89_chip_info *chip = rtwdev->chip; struct fwcmd_hdr *hdr; hdr = (struct fwcmd_hdr *)skb_push(skb, 8); - if (!(rtwdev->fw.h2c_seq % 4)) + if (chip->chip_gen == RTW89_CHIP_AX && !(rtwdev->fw.h2c_seq % 4)) rack = true; hdr->hdr0 = cpu_to_le32(FIELD_PREP(H2C_HDR_DEL_TYPE, type) | FIELD_PREP(H2C_HDR_CAT, cat) | @@ -1472,8 +1613,7 @@ static u32 __rtw89_fw_download_tweak_hdr_v0(struct rtw89_dev *rtwdev, struct rtw89_fw_hdr_section *section; int i; - le32p_replace_bits(&fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN, - FW_HDR_W7_PART_SIZE); + le32p_replace_bits(&fw_hdr->w7, info->part_size, FW_HDR_W7_PART_SIZE); for (i = 0; i < info->section_num; i++) { section_info = &info->section_info[i]; @@ -1498,8 +1638,7 @@ static u32 __rtw89_fw_download_tweak_hdr_v1(struct rtw89_dev *rtwdev, u8 dst_sec_idx = 0; u8 sec_idx; - le32p_replace_bits(&fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN, - FW_HDR_V1_W7_PART_SIZE); + le32p_replace_bits(&fw_hdr->w7, info->part_size, FW_HDR_V1_W7_PART_SIZE); for (sec_idx = 0; sec_idx < info->section_num; sec_idx++) { section_info = &info->section_info[sec_idx]; @@ -1529,7 +1668,7 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, struct rtw89_fw_hdr *fw_hdr; struct sk_buff *skb; u32 truncated; - u32 ret = 0; + int ret; skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { @@ -1601,7 +1740,8 @@ static int rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, } static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, - struct rtw89_fw_hdr_section_info *info) + struct rtw89_fw_hdr_section_info *info, + u32 part_size) { struct sk_buff *skb; const u8 *section = info->addr; @@ -1622,20 +1762,17 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, } if (info->key_addr && info->key_len) { - if (residue_len > FWDL_SECTION_PER_PKT_LEN || info->len < info->key_len) + if (residue_len > part_size || info->len < info->key_len) rtw89_warn(rtwdev, "ignore to copy key data because of len %d, %d, %d, %d\n", - info->len, FWDL_SECTION_PER_PKT_LEN, + info->len, part_size, info->key_len, residue_len); else copy_key = true; } while (residue_len) { - if (residue_len >= FWDL_SECTION_PER_PKT_LEN) - pkt_len = FWDL_SECTION_PER_PKT_LEN; - else - pkt_len = residue_len; + pkt_len = min(residue_len, part_size); skb = rtw89_fw_h2c_alloc_skb_no_hdr(rtwdev, pkt_len); if (!skb) { @@ -1690,7 +1827,7 @@ static int rtw89_fw_download_main(struct rtw89_dev *rtwdev, int ret; while (section_num--) { - ret = __rtw89_fw_download_main(rtwdev, section_info); + ret = __rtw89_fw_download_main(rtwdev, section_info, info->part_size); if (ret) return ret; section_info++; @@ -2081,28 +2218,48 @@ void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len) } -#define H2C_CAM_LEN 60 int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr) + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, + enum rtw89_upd_mode upd_mode) { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_h2c_addr_cam_v0 *h2c_v0; + struct rtw89_h2c_addr_cam *h2c; + u32 len = sizeof(*h2c); struct sk_buff *skb; + u8 ver = U8_MAX; int ret; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CAM_LEN); + if (RTW89_CHK_FW_FEATURE(ADDR_CAM_V0, &rtwdev->fw) || + chip->chip_gen == RTW89_CHIP_AX) { + len = sizeof(*h2c_v0); + ver = 0; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); return -ENOMEM; } - skb_put(skb, H2C_CAM_LEN); - rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, scan_mac_addr, - skb->data); - rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, skb->data); + skb_put(skb, len); + h2c_v0 = (struct rtw89_h2c_addr_cam_v0 *)skb->data; + + rtw89_cam_fill_addr_cam_info(rtwdev, rtwvif_link, rtwsta_link, + scan_mac_addr, h2c_v0); + rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif_link, rtwsta_link, h2c_v0); + + if (ver == 0) + goto hdr; + + h2c = (struct rtw89_h2c_addr_cam *)skb->data; + h2c->w15 = le32_encode_bits(upd_mode, ADDR_CAM_W15_UPD_MODE); +hdr: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_ADDR_CAM_UPDATE, H2C_FUNC_MAC_ADDR_CAM_UPD, 0, 1, - H2C_CAM_LEN); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { @@ -2195,6 +2352,45 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2); +int rtw89_fw_h2c_dctl_sec_cam_v3(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_h2c_dctlinfo_ud_v3 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for dctl sec cam\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_dctlinfo_ud_v3 *)skb->data; + + rtw89_cam_fill_dctl_sec_cam_info_v3(rtwdev, rtwvif_link, rtwsta_link, h2c); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_DCTLINFO_UD_V3, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v3); + int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link) @@ -2250,6 +2446,62 @@ int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2); +int rtw89_fw_h2c_default_dmac_tbl_v3(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) +{ + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_dctlinfo_ud_v3 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for dctl v2\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_dctlinfo_ud_v3 *)skb->data; + + h2c->c0 = le32_encode_bits(mac_id, DCTLINFO_V3_C0_MACID) | + le32_encode_bits(1, DCTLINFO_V3_C0_OP); + + h2c->m0 = cpu_to_le32(DCTLINFO_V3_W0_ALL); + h2c->m1 = cpu_to_le32(DCTLINFO_V3_W1_ALL); + h2c->m2 = cpu_to_le32(DCTLINFO_V3_W2_ALL); + h2c->m3 = cpu_to_le32(DCTLINFO_V3_W3_ALL); + h2c->m4 = cpu_to_le32(DCTLINFO_V3_W4_ALL); + h2c->m5 = cpu_to_le32(DCTLINFO_V3_W5_ALL); + h2c->m6 = cpu_to_le32(DCTLINFO_V3_W6_ALL); + h2c->m7 = cpu_to_le32(DCTLINFO_V3_W7_ALL); + h2c->m8 = cpu_to_le32(DCTLINFO_V3_W8_ALL); + h2c->m9 = cpu_to_le32(DCTLINFO_V3_W9_ALL); + h2c->m10 = cpu_to_le32(DCTLINFO_V3_W10_ALL); + h2c->m11 = cpu_to_le32(DCTLINFO_V3_W11_ALL); + h2c->m12 = cpu_to_le32(DCTLINFO_V3_W12_ALL); + h2c->m13 = cpu_to_le32(DCTLINFO_V3_W13_ALL); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_DCTLINFO_UD_V3, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v3); + int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, @@ -2824,8 +3076,14 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, struct rtw89_lps_parm *lps_param) { struct sk_buff *skb; + bool done_ack; int ret; + if (RTW89_CHK_FW_FEATURE(LPS_DACK_BY_C2H_REG, &rtwdev->fw)) + done_ack = false; + else + done_ack = !lps_param->psmode; + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LPS_PARM_LEN); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for fw dl\n"); @@ -2847,7 +3105,7 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_PS, - H2C_FUNC_MAC_LPS_PARM, 0, !lps_param->psmode, + H2C_FUNC_MAC_LPS_PARM, 0, done_ack, H2C_LPS_PARM_LEN); ret = rtw89_h2c_tx(rtwdev, skb, false); @@ -3030,6 +3288,161 @@ int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev, return ret; } +void rtw89_bb_lps_cmn_info_rx_gain_fill(struct rtw89_dev *rtwdev, + struct rtw89_bb_link_info_rx_gain *h2c_gain, + const struct rtw89_chan *chan, u8 phy_idx) +{ + const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be; + enum rtw89_bb_link_rx_gain_table_type tab_idx; + struct rtw89_chan chan_bcn; + u8 bw = chan->band_width; + u8 gain_band; + u8 bw_idx; + u8 path; + int i; + + rtw89_chan_create(&chan_bcn, chan->primary_channel, chan->primary_channel, + chan->band_type, RTW89_CHANNEL_WIDTH_20); + + for (tab_idx = RTW89_BB_PS_LINK_RX_GAIN_TAB_BCN_PATH_A; + tab_idx < RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX; tab_idx++) { + struct rtw89_phy_calc_efuse_gain calc = {}; + + path = (tab_idx & BIT(0)) ? (RF_PATH_B) : (RF_PATH_A); + if (tab_idx & BIT(1)) { + rtw89_chip_calc_rx_gain_normal(rtwdev, chan, path, phy_idx, + &calc); + gain_band = rtw89_subband_to_gain_band_be(chan->subband_type); + if (bw > RTW89_CHANNEL_WIDTH_40) + bw_idx = RTW89_BB_BW_80_160_320; + else + bw_idx = RTW89_BB_BW_20_40; + } else { + rtw89_chip_calc_rx_gain_normal(rtwdev, &chan_bcn, path, phy_idx, + &calc); + gain_band = rtw89_subband_to_gain_band_be(chan_bcn.subband_type); + bw_idx = RTW89_BB_BW_20_40; + } + + /* efuse ofst and comp */ + h2c_gain->gain_ofst[tab_idx] = calc.rssi_ofst; + h2c_gain->cck_gain_ofst[tab_idx] = calc.cck_rpl_ofst; + h2c_gain->cck_rpl_bias_comp[tab_idx][0] = calc.cck_mean_gain_bias; + h2c_gain->cck_rpl_bias_comp[tab_idx][1] = calc.cck_mean_gain_bias; + + for (i = 0; i < TIA_GAIN_NUM; i++) { + h2c_gain->gain_err_tia[tab_idx][i] = + cpu_to_le16(gain->tia_gain[gain_band][bw_idx][path][i]); + } + memcpy(h2c_gain->gain_err_lna[tab_idx], + gain->lna_gain[gain_band][bw_idx][path], + LNA_GAIN_NUM); + memcpy(h2c_gain->op1db_lna[tab_idx], + gain->lna_op1db[gain_band][bw_idx][path], + LNA_GAIN_NUM); + memcpy(h2c_gain->op1db_tia[tab_idx], + gain->tia_lna_op1db[gain_band][bw_idx][path], + LNA_GAIN_NUM + 1); + + memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._20M, + gain->rpl_ofst_20[gain_band][path], + RTW89_BW20_SC_20M); + memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._40M, + gain->rpl_ofst_40[gain_band][path], + RTW89_BW20_SC_40M); + memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._80M, + gain->rpl_ofst_80[gain_band][path], + RTW89_BW20_SC_80M); + memcpy(h2c_gain->rpl_bias_comp_bw[tab_idx]._160M, + gain->rpl_ofst_160[gain_band][path], + RTW89_BW20_SC_160M); + } +} + +int rtw89_fw_h2c_lps_ml_cmn_info_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif) +{ + static const u8 bcn_bw_ofst[] = {0, 0, 0, 3, 6, 9, 0, 12}; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_efuse *efuse = &rtwdev->efuse; + struct rtw89_h2c_lps_ml_cmn_info_v1 *h2c; + struct rtw89_vif_link *rtwvif_link; + const struct rtw89_chan *chan; + struct rtw89_bb_ctx *bb; + u32 len = sizeof(*h2c); + unsigned int link_id; + struct sk_buff *skb; + u8 beacon_bw_ofst; + u32 done; + int ret; + + if (chip->chip_gen != RTW89_CHIP_BE) + return 0; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c lps_ml_cmn_info_v1\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_lps_ml_cmn_info_v1 *)skb->data; + + h2c->fmt_id = 0x20; + + h2c->mlo_dbcc_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + h2c->rfe_type = efuse->rfe_type; + h2c->rssi_main = U8_MAX; + + memset(h2c->link_id, 0xfe, RTW89_BB_PS_LINK_BUF_MAX); + + rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { + u8 phy_idx = rtwvif_link->phy_idx; + + bb = rtw89_get_bb_ctx(rtwdev, phy_idx); + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + + h2c->link_id[phy_idx] = phy_idx; + h2c->central_ch[phy_idx] = chan->channel; + h2c->pri_ch[phy_idx] = chan->primary_channel; + h2c->band[phy_idx] = chan->band_type; + h2c->bw[phy_idx] = chan->band_width; + + if (rtwvif_link->bcn_bw_idx < ARRAY_SIZE(bcn_bw_ofst)) { + beacon_bw_ofst = bcn_bw_ofst[rtwvif_link->bcn_bw_idx]; + h2c->dup_bcn_ofst[phy_idx] = beacon_bw_ofst; + } + + if (h2c->rssi_main > bb->ch_info.rssi_min) + h2c->rssi_main = bb->ch_info.rssi_min; + + rtw89_bb_lps_cmn_info_rx_gain_fill(rtwdev, + &h2c->rx_gain[phy_idx], + chan, phy_idx); + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM, + H2C_FUNC_FW_LPS_ML_CMN_INFO, 0, 0, len); + + rtw89_phy_write32_mask(rtwdev, R_CHK_LPS_STAT_BE4, B_CHK_LPS_STAT, 0); + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + ret = read_poll_timeout(rtw89_phy_read32_mask, done, done, 50, 5000, + true, rtwdev, R_CHK_LPS_STAT_BE4, B_CHK_LPS_STAT); + if (ret) + rtw89_warn(rtwdev, "h2c_lps_ml_cmn_info done polling timeout\n"); + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + #define H2C_P2P_ACT_LEN 20 int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, @@ -3238,9 +3651,95 @@ int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7); -static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, - struct ieee80211_link_sta *link_sta, - u8 *pads) +int rtw89_fw_h2c_default_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) +{ + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + bool preld = rtw89_mac_chk_preload_allow(rtwdev); + struct rtw89_h2c_cctlinfo_ud_be *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for default cmac be\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data; + + h2c->c0 = le32_encode_bits(mac_id, BE_CCTL_INFO_C0_V1_MACID) | + le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP); + + h2c->w0 = le32_encode_bits(4, BE_CCTL_INFO_W0_DATARATE); + h2c->m0 = cpu_to_le32(BE_CCTL_INFO_W0_ALL); + + h2c->w1 = le32_encode_bits(4, BE_CCTL_INFO_W1_DATA_RTY_LOWEST_RATE) | + le32_encode_bits(0xa, BE_CCTL_INFO_W1_RTSRATE) | + le32_encode_bits(4, BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE); + h2c->m1 = cpu_to_le32(BE_CCTL_INFO_W1_ALL); + + h2c->w1 = le32_encode_bits(preld, BE_CCTL_INFO_W2_PRELOAD_ENABLE); + h2c->m2 = cpu_to_le32(BE_CCTL_INFO_W2_ALL); + + h2c->m3 = cpu_to_le32(BE_CCTL_INFO_W3_ALL); + + h2c->w4 = le32_encode_bits(0xFFFF, BE_CCTL_INFO_W4_ACT_SUBCH_CBW); + h2c->m4 = cpu_to_le32(BE_CCTL_INFO_W4_ALL); + + h2c->w5 = le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1) | + le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1) | + le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1) | + le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1) | + le32_encode_bits(2, BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1); + h2c->m5 = cpu_to_le32(BE_CCTL_INFO_W5_ALL); + + h2c->w6 = le32_encode_bits(0xb, BE_CCTL_INFO_W6_RESP_REF_RATE); + h2c->m6 = cpu_to_le32(BE_CCTL_INFO_W6_ALL); + + h2c->w7 = le32_encode_bits(1, BE_CCTL_INFO_W7_NC) | + le32_encode_bits(1, BE_CCTL_INFO_W7_NR) | + le32_encode_bits(1, BE_CCTL_INFO_W7_CB) | + le32_encode_bits(0x1, BE_CCTL_INFO_W7_CSI_PARA_EN) | + le32_encode_bits(0xb, BE_CCTL_INFO_W7_CSI_FIX_RATE); + h2c->m7 = cpu_to_le32(BE_CCTL_INFO_W7_ALL); + + h2c->m8 = cpu_to_le32(BE_CCTL_INFO_W8_ALL); + + h2c->w14 = le32_encode_bits(0, BE_CCTL_INFO_W14_VO_CURR_RATE) | + le32_encode_bits(0, BE_CCTL_INFO_W14_VI_CURR_RATE) | + le32_encode_bits(0, BE_CCTL_INFO_W14_BE_CURR_RATE_L); + h2c->m14 = cpu_to_le32(BE_CCTL_INFO_W14_ALL); + + h2c->w15 = le32_encode_bits(0, BE_CCTL_INFO_W15_BE_CURR_RATE_H) | + le32_encode_bits(0, BE_CCTL_INFO_W15_BK_CURR_RATE) | + le32_encode_bits(0, BE_CCTL_INFO_W15_MGNT_CURR_RATE); + h2c->m15 = cpu_to_le32(BE_CCTL_INFO_W15_ALL); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_be); + +static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, + struct ieee80211_link_sta *link_sta, + u8 *pads) { bool ppe_th; u8 ppe16, ppe8; @@ -3570,6 +4069,134 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7); +int rtw89_fw_h2c_assoc_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) +{ + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + u8 mac_id = rtwsta_link ? rtwsta_link->mac_id : rtwvif_link->mac_id; + struct rtw89_h2c_cctlinfo_ud_be *h2c; + struct ieee80211_bss_conf *bss_conf; + struct ieee80211_link_sta *link_sta; + u8 pads[RTW89_PPE_BW_NUM]; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u16 lowest_rate; + int ret; + + memset(pads, 0, sizeof(pads)); + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for assoc cmac be\n"); + return -ENOMEM; + } + + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + + if (rtwsta_link) { + link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true); + + if (link_sta->eht_cap.has_eht) + __get_sta_eht_pkt_padding(rtwdev, link_sta, pads); + else if (link_sta->he_cap.has_he) + __get_sta_he_pkt_padding(rtwdev, link_sta, pads); + } + + if (vif->p2p) + lowest_rate = RTW89_HW_RATE_OFDM6; + else if (chan->band_type == RTW89_BAND_2G) + lowest_rate = RTW89_HW_RATE_CCK1; + else + lowest_rate = RTW89_HW_RATE_OFDM6; + + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data; + + h2c->c0 = le32_encode_bits(mac_id, BE_CCTL_INFO_C0_V1_MACID) | + le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP); + + h2c->w0 = le32_encode_bits(1, BE_CCTL_INFO_W0_DISRTSFB) | + le32_encode_bits(1, BE_CCTL_INFO_W0_DISDATAFB); + h2c->m0 = cpu_to_le32(BE_CCTL_INFO_W0_DISRTSFB | + BE_CCTL_INFO_W0_DISDATAFB); + + h2c->w1 = le32_encode_bits(lowest_rate, BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE); + h2c->m1 = cpu_to_le32(BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE); + + h2c->w2 = le32_encode_bits(0, BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL); + h2c->m2 = cpu_to_le32(BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL); + + h2c->w3 = le32_encode_bits(0, BE_CCTL_INFO_W3_RTS_TXCNT_LMT_SEL); + h2c->m3 = cpu_to_le32(BE_CCTL_INFO_W3_RTS_TXCNT_LMT_SEL); + + h2c->w4 = le32_encode_bits(rtwvif_link->port, BE_CCTL_INFO_W4_MULTI_PORT_ID); + h2c->m4 = cpu_to_le32(BE_CCTL_INFO_W4_MULTI_PORT_ID); + + if (bss_conf->eht_support) { + u16 punct = bss_conf->eht_puncturing; + + h2c->w4 |= le32_encode_bits(~punct, + BE_CCTL_INFO_W4_ACT_SUBCH_CBW); + h2c->m4 |= cpu_to_le32(BE_CCTL_INFO_W4_ACT_SUBCH_CBW); + } + + h2c->w5 = le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_20], + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1) | + le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_40], + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1) | + le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_80], + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1) | + le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_160], + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1) | + le32_encode_bits(pads[RTW89_CHANNEL_WIDTH_320], + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1); + h2c->m5 = cpu_to_le32(BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1 | + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1 | + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1 | + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1 | + BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1); + + if (rtwvif_link->net_type == RTW89_NET_TYPE_AP_MODE) { + h2c->w5 |= le32_encode_bits(0, BE_CCTL_INFO_W5_DATA_DCM_V1); + h2c->m5 |= cpu_to_le32(BE_CCTL_INFO_W5_DATA_DCM_V1); + } + + h2c->w6 = le32_encode_bits(vif->cfg.aid, BE_CCTL_INFO_W6_AID12_PAID) | + le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, + BE_CCTL_INFO_W6_ULDL); + h2c->m6 = cpu_to_le32(BE_CCTL_INFO_W6_AID12_PAID | BE_CCTL_INFO_W6_ULDL); + + if (rtwsta_link) { + h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, + BE_CCTL_INFO_W8_BSR_QUEUE_SIZE_FORMAT_V1); + h2c->m8 = cpu_to_le32(BE_CCTL_INFO_W8_BSR_QUEUE_SIZE_FORMAT_V1); + } + + rcu_read_unlock(); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_be); + int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link) @@ -3636,6 +4263,72 @@ int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7); +int rtw89_fw_h2c_ampdu_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_sta *rtwsta = rtwsta_link->rtwsta; + struct rtw89_h2c_cctlinfo_ud_be *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u16 agg_num = 0; + u8 ba_bmap = 0; + int ret; + u8 tid; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for ampdu cmac be\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data; + + for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS) { + if (agg_num == 0) + agg_num = rtwsta->ampdu_params[tid].agg_num; + else + agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num); + } + + if (agg_num <= 0x20) + ba_bmap = 3; + else if (agg_num > 0x20 && agg_num <= 0x40) + ba_bmap = 0; + else if (agg_num > 0x40 && agg_num <= 0x80) + ba_bmap = 1; + else if (agg_num > 0x80 && agg_num <= 0x100) + ba_bmap = 2; + else if (agg_num > 0x100 && agg_num <= 0x200) + ba_bmap = 4; + else if (agg_num > 0x200 && agg_num <= 0x400) + ba_bmap = 5; + + h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, BE_CCTL_INFO_C0_V1_MACID) | + le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP); + + h2c->w3 = le32_encode_bits(ba_bmap, BE_CCTL_INFO_W3_BA_BMAP); + h2c->m3 = cpu_to_le32(BE_CCTL_INFO_W3_BA_BMAP); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_be); + int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) { @@ -3733,6 +4426,145 @@ int rtw89_fw_h2c_txtime_cmac_tbl_g7(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl_g7); +int rtw89_fw_h2c_txtime_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link) +{ + struct rtw89_h2c_cctlinfo_ud_be *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for txtime_cmac_be\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data; + + h2c->c0 = le32_encode_bits(rtwsta_link->mac_id, BE_CCTL_INFO_C0_V1_MACID) | + le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP); + + if (rtwsta_link->cctl_tx_time) { + h2c->w3 |= le32_encode_bits(1, BE_CCTL_INFO_W3_AMPDU_TIME_SEL); + h2c->m3 |= cpu_to_le32(BE_CCTL_INFO_W3_AMPDU_TIME_SEL); + + h2c->w2 |= le32_encode_bits(rtwsta_link->ampdu_max_time, + BE_CCTL_INFO_W2_AMPDU_MAX_TIME); + h2c->m2 |= cpu_to_le32(BE_CCTL_INFO_W2_AMPDU_MAX_TIME); + } + if (rtwsta_link->cctl_tx_retry_limit) { + h2c->w2 |= le32_encode_bits(1, BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL) | + le32_encode_bits(rtwsta_link->data_tx_cnt_lmt, + BE_CCTL_INFO_W2_DATA_TX_CNT_LMT); + h2c->m2 |= cpu_to_le32(BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL | + BE_CCTL_INFO_W2_DATA_TX_CNT_LMT); + } + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl_be); + +int rtw89_fw_h2c_punctured_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 punctured) +{ + struct rtw89_h2c_cctlinfo_ud_g7 *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for punctured cmac g7\n"); + return -ENOMEM; + } + + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data; + + h2c->c0 = le32_encode_bits(rtwvif_link->mac_id, CCTLINFO_G7_C0_MACID) | + le32_encode_bits(1, CCTLINFO_G7_C0_OP); + + h2c->w4 = le32_encode_bits(~punctured, CCTLINFO_G7_W4_ACT_SUBCH_CBW); + h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_ACT_SUBCH_CBW); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_punctured_cmac_tbl_g7); + +int rtw89_fw_h2c_punctured_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 punctured) +{ + struct rtw89_h2c_cctlinfo_ud_be *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for punctured cmac be\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_cctlinfo_ud_be *)skb->data; + + h2c->c0 = le32_encode_bits(rtwvif_link->mac_id, BE_CCTL_INFO_C0_V1_MACID) | + le32_encode_bits(1, BE_CCTL_INFO_C0_V1_OP); + + h2c->w4 = le32_encode_bits(~punctured, BE_CCTL_INFO_W4_ACT_SUBCH_CBW); + h2c->m4 = cpu_to_le32(BE_CCTL_INFO_W4_ACT_SUBCH_CBW); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG, + H2C_FUNC_MAC_CCTLINFO_UD_G7, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_punctured_cmac_tbl_be); + int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link) { @@ -3935,6 +4767,93 @@ int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be); +int rtw89_fw_h2c_tbtt_tuning(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, u32 offset) +{ + struct rtw89_h2c_tbtt_tuning *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c tbtt tuning\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_tbtt_tuning *)skb->data; + + h2c->w0 = le32_encode_bits(rtwvif_link->phy_idx, RTW89_H2C_TBTT_TUNING_W0_BAND) | + le32_encode_bits(rtwvif_link->port, RTW89_H2C_TBTT_TUNING_W0_PORT); + h2c->w1 = le32_encode_bits(offset, RTW89_H2C_TBTT_TUNING_W1_SHIFT); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_PS, + H2C_FUNC_TBTT_TUNING, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +int rtw89_fw_h2c_pwr_lvl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) +{ +#define RTW89_BCN_TO_VAL_MIN 4 +#define RTW89_BCN_TO_VAL_MAX 64 +#define RTW89_DTIM_TO_VAL_MIN 7 +#define RTW89_DTIM_TO_VAL_MAX 15 + struct rtw89_beacon_track_info *bcn_track = &rtwdev->bcn_track; + struct rtw89_h2c_pwr_lvl *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u8 bcn_to_val; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c pwr lvl\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_pwr_lvl *)skb->data; + + bcn_to_val = clamp_t(u8, bcn_track->bcn_timeout, + RTW89_BCN_TO_VAL_MIN, RTW89_BCN_TO_VAL_MAX); + + h2c->w0 = le32_encode_bits(rtwvif_link->mac_id, RTW89_H2C_PWR_LVL_W0_MACID) | + le32_encode_bits(bcn_to_val, RTW89_H2C_PWR_LVL_W0_BCN_TO_VAL) | + le32_encode_bits(0, RTW89_H2C_PWR_LVL_W0_PS_LVL) | + le32_encode_bits(0, RTW89_H2C_PWR_LVL_W0_TRX_LVL) | + le32_encode_bits(RTW89_DTIM_TO_VAL_MIN, + RTW89_H2C_PWR_LVL_W0_DTIM_TO_VAL); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, H2C_CL_MAC_PS, + H2C_FUNC_PS_POWER_LEVEL, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, @@ -4552,13 +5471,16 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi struct rtw89_h2c_ra_v1 *h2c_v1; struct rtw89_h2c_ra *h2c; u32 len = sizeof(*h2c); - bool format_v1 = false; struct sk_buff *skb; + u8 ver = U8_MAX; int ret; - if (chip->chip_gen == RTW89_CHIP_BE) { + if (chip->chip_gen == RTW89_CHIP_AX) { + len = sizeof(*h2c); + ver = 0; + } else { len = sizeof(*h2c_v1); - format_v1 = true; + ver = 1; } skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); @@ -4590,16 +5512,8 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi h2c->w3 = le32_encode_bits(ra->fix_giltf_en, RTW89_H2C_RA_W3_FIX_GILTF_EN) | le32_encode_bits(ra->fix_giltf, RTW89_H2C_RA_W3_FIX_GILTF); - if (!format_v1) - goto csi; - - h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c; - h2c_v1->w4 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) | - le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT); - -csi: - if (!csi) - goto done; + if (!csi || ver >= 1) + goto next_v1; h2c->w2 |= le32_encode_bits(1, RTW89_H2C_RA_W2_BFEE_CSI_CTL); h2c->w3 |= le32_encode_bits(ra->band_num, RTW89_H2C_RA_W3_BAND_NUM) | @@ -4611,6 +5525,18 @@ int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi le32_encode_bits(ra->csi_gi_ltf, RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF) | le32_encode_bits(ra->csi_bw, RTW89_H2C_RA_W3_FIXED_CSI_BW); +next_v1: + if (ver < 1) + goto done; + + h2c->w3 |= le32_encode_bits(ra->partial_bw_er, + RTW89_H2C_RA_V1_W3_PARTIAL_BW_SU_ER) | + le32_encode_bits(ra->band, RTW89_H2C_RA_V1_W3_BAND); + + h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c; + h2c_v1->w4 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) | + le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT); + done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RA, @@ -5585,7 +6511,6 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num, return 0; } -#define RTW89_SCAN_DELAY_TSF_UNIT 1000000 int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, struct rtw89_scan_option *option, struct rtw89_vif_link *rtwvif_link, @@ -5617,7 +6542,7 @@ int rtw89_fw_h2c_scan_offload_ax(struct rtw89_dev *rtwdev, scan_mode = RTW89_SCAN_IMMEDIATE; } else { scan_mode = RTW89_SCAN_DELAY; - tsf += (u64)option->delay * RTW89_SCAN_DELAY_TSF_UNIT; + tsf += (u64)option->delay * 1000; } } @@ -5703,26 +6628,38 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, { struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + const struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait; struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_h2c_scanofld_be_macc_role *macc_role; + struct rtw89_hw_scan_extra_op scan_op[2] = {}; struct rtw89_chan *op = &scan_info->op_chan; struct rtw89_h2c_scanofld_be_opch *opch; struct rtw89_pktofld_info *pkt_info; struct rtw89_h2c_scanofld_be *h2c; + struct ieee80211_vif *vif; struct sk_buff *skb; u8 macc_role_size = sizeof(*macc_role) * option->num_macc_role; u8 opch_size = sizeof(*opch) * option->num_opch; + enum rtw89_scan_be_opmode opmode; u8 probe_id[NUM_NL80211_BANDS]; u8 scan_offload_ver = U8_MAX; u8 cfg_len = sizeof(*h2c); unsigned int cond; u8 ver = U8_MAX; + u8 policy_val; void *ptr; + u8 txnull; + u8 txbcn; int ret; u32 len; u8 i; + if (option->num_opch > RTW89_MAX_OP_NUM_BE) { + rtw89_err(rtwdev, "num of scan OP chan %d over limit\n", option->num_opch); + return -ENOENT; + } + rtw89_scan_get_6g_disabled_chan(rtwdev, option); if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD_BE_V0, &rtwdev->fw)) { @@ -5783,7 +6720,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, RTW89_H2C_SCANOFLD_BE_W4_PROBE_5G) | le32_encode_bits(probe_id[NL80211_BAND_6GHZ], RTW89_H2C_SCANOFLD_BE_W4_PROBE_6G) | - le32_encode_bits(option->delay, RTW89_H2C_SCANOFLD_BE_W4_DELAY_START); + le32_encode_bits(option->delay / 1000, RTW89_H2C_SCANOFLD_BE_W4_DELAY_START); h2c->w5 = le32_encode_bits(option->mlo_mode, RTW89_H2C_SCANOFLD_BE_W5_MLO_MODE); @@ -5825,29 +6762,53 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, } for (i = 0; i < option->num_opch; i++) { + struct rtw89_vif_link *rtwvif_link_op; + bool is_ap; + + switch (i) { + case 0: + scan_op[0].macid = rtwvif_link->mac_id; + scan_op[0].port = rtwvif_link->port; + scan_op[0].chan = *op; + rtwvif_link_op = rtwvif_link; + break; + case 1: + scan_op[1] = *ext; + rtwvif_link_op = ext->rtwvif_link; + break; + } + + vif = rtwvif_to_vif(rtwvif_link_op->rtwvif); + is_ap = vif->type == NL80211_IFTYPE_AP; + txnull = !is_zero_ether_addr(rtwvif_link_op->bssid) && + vif->type != NL80211_IFTYPE_AP; + opmode = is_ap ? RTW89_SCAN_OPMODE_TBTT : RTW89_SCAN_OPMODE_INTV; + policy_val = is_ap ? 2 : RTW89_OFF_CHAN_TIME / 10; + txbcn = is_ap ? 1 : 0; + opch = ptr; - opch->w0 = le32_encode_bits(rtwvif_link->mac_id, + opch->w0 = le32_encode_bits(scan_op[i].macid, RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID) | le32_encode_bits(option->band, RTW89_H2C_SCANOFLD_BE_OPCH_W0_BAND) | - le32_encode_bits(rtwvif_link->port, + le32_encode_bits(scan_op[i].port, RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) | - le32_encode_bits(RTW89_SCAN_OPMODE_INTV, + le32_encode_bits(opmode, RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) | - le32_encode_bits(true, + le32_encode_bits(txnull, RTW89_H2C_SCANOFLD_BE_OPCH_W0_TXNULL) | - le32_encode_bits(RTW89_OFF_CHAN_TIME / 10, + le32_encode_bits(policy_val, RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY_VAL); - opch->w1 = le32_encode_bits(op->band_type, + opch->w1 = le32_encode_bits(scan_op[i].chan.band_type, RTW89_H2C_SCANOFLD_BE_OPCH_W1_CH_BAND) | - le32_encode_bits(op->band_width, + le32_encode_bits(scan_op[i].chan.band_width, RTW89_H2C_SCANOFLD_BE_OPCH_W1_BW) | le32_encode_bits(0x3, RTW89_H2C_SCANOFLD_BE_OPCH_W1_NOTIFY) | - le32_encode_bits(op->primary_channel, + le32_encode_bits(scan_op[i].chan.primary_channel, RTW89_H2C_SCANOFLD_BE_OPCH_W1_PRI_CH) | - le32_encode_bits(op->channel, + le32_encode_bits(scan_op[i].chan.channel, RTW89_H2C_SCANOFLD_BE_OPCH_W1_CENTRAL_CH); opch->w2 = le32_encode_bits(0, @@ -5855,7 +6816,9 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev, le32_encode_bits(0, RTW89_H2C_SCANOFLD_BE_OPCH_W2_SW_DEF) | le32_encode_bits(rtw89_is_mlo_1_1(rtwdev) ? 1 : 2, - RTW89_H2C_SCANOFLD_BE_OPCH_W2_SS); + RTW89_H2C_SCANOFLD_BE_OPCH_W2_SS) | + le32_encode_bits(txbcn, + RTW89_H2C_SCANOFLD_BE_OPCH_W2_TXBCN); opch->w3 = le32_encode_bits(RTW89_SCANOFLD_PKT_NONE, RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT0) | @@ -5987,6 +6950,59 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev) } EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc); +int rtw89_fw_h2c_mcc_dig(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx chanctx_idx, + u8 mcc_role_idx, u8 pd_val, bool en) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx); + const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs; + struct rtw89_h2c_mcc_dig *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c mcc_dig\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_mcc_dig *)skb->data; + + h2c->w0 = le32_encode_bits(1, RTW89_H2C_MCC_DIG_W0_REG_CNT) | + le32_encode_bits(en, RTW89_H2C_MCC_DIG_W0_DM_EN) | + le32_encode_bits(mcc_role_idx, RTW89_H2C_MCC_DIG_W0_IDX) | + le32_encode_bits(1, RTW89_H2C_MCC_DIG_W0_SET) | + le32_encode_bits(1, RTW89_H2C_MCC_DIG_W0_PHY0_EN) | + le32_encode_bits(chan->channel, RTW89_H2C_MCC_DIG_W0_CENTER_CH) | + le32_encode_bits(chan->band_type, RTW89_H2C_MCC_DIG_W0_BAND_TYPE); + h2c->w1 = le32_encode_bits(dig_regs->seg0_pd_reg, + RTW89_H2C_MCC_DIG_W1_ADDR_LSB) | + le32_encode_bits(dig_regs->seg0_pd_reg >> 8, + RTW89_H2C_MCC_DIG_W1_ADDR_MSB) | + le32_encode_bits(dig_regs->pd_lower_bound_mask, + RTW89_H2C_MCC_DIG_W1_BMASK_LSB) | + le32_encode_bits(dig_regs->pd_lower_bound_mask >> 8, + RTW89_H2C_MCC_DIG_W1_BMASK_MSB); + h2c->w2 = le32_encode_bits(pd_val, RTW89_H2C_MCC_DIG_W2_VAL_LSB); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM, + H2C_FUNC_FW_MCC_DIG, 0, 0, len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -6017,7 +7033,7 @@ int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) path = rtw89_phy_get_syn_sel(rtwdev, rtwvif_link->phy_idx); val = rtw89_chip_chan_to_rf18_val(rtwdev, chan); - if (path >= chip->rf_path_num) { + if (path >= chip->rf_path_num || path >= NUM_OF_RTW89_FW_RFK_PATH) { rtw89_err(rtwdev, "unsupported rf path (%d)\n", path); ret = -ENOENT; goto fail; @@ -6053,6 +7069,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, struct rtw89_fw_h2c_rfk_pre_info_common *common; struct rtw89_fw_h2c_rfk_pre_info_v0 *h2c_v0; struct rtw89_fw_h2c_rfk_pre_info_v1 *h2c_v1; + struct rtw89_fw_h2c_rfk_pre_info_v2 *h2c_v2; struct rtw89_fw_h2c_rfk_pre_info *h2c; u8 tbl_sel[NUM_OF_RTW89_FW_RFK_PATH]; u32 len = sizeof(*h2c); @@ -6062,7 +7079,11 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, u32 val32; int ret; - if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V1, &rtwdev->fw)) { + if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V3, &rtwdev->fw)) { + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V2, &rtwdev->fw)) { + len = sizeof(*h2c_v2); + ver = 2; + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V1, &rtwdev->fw)) { len = sizeof(*h2c_v1); ver = 1; } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V0, &rtwdev->fw)) { @@ -6076,8 +7097,21 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, return -ENOMEM; } skb_put(skb, len); + + if (ver <= 2) + goto old_format; + h2c = (struct rtw89_fw_h2c_rfk_pre_info *)skb->data; - common = &h2c->base_v1.common; + + h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + h2c->phy_idx = cpu_to_le32(phy_idx); + h2c->mlo_1_1 = cpu_to_le32(rtw89_is_mlo_1_1(rtwdev)); + + goto done; + +old_format: + h2c_v2 = (struct rtw89_fw_h2c_rfk_pre_info_v2 *)skb->data; + common = &h2c_v2->base_v1.common; common->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); @@ -6104,7 +7138,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, if (ver <= 1) continue; - h2c->cur_bandwidth[path] = + h2c_v2->cur_bandwidth[path] = cpu_to_le32(rfk_mcc->data[path].bw[tbl_sel[path]]); } @@ -6117,32 +7151,130 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, h2c_v0->cur_bw = cpu_to_le32(rfk_mcc->data[0].bw[tbl_sel[0]]); h2c_v0->cur_center_ch = cpu_to_le32(rfk_mcc->data[0].ch[tbl_sel[0]]); - val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_IQC_V1); - h2c_v0->ktbl_sel0 = cpu_to_le32(val32); - val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_IQC_V1); - h2c_v0->ktbl_sel1 = cpu_to_le32(val32); - val32 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK); - h2c_v0->rfmod0 = cpu_to_le32(val32); - val32 = rtw89_read_rf(rtwdev, RF_PATH_B, RR_CFGCH, RFREG_MASK); - h2c_v0->rfmod1 = cpu_to_le32(val32); + val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_IQC_V1); + h2c_v0->ktbl_sel0 = cpu_to_le32(val32); + val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_IQC_V1); + h2c_v0->ktbl_sel1 = cpu_to_le32(val32); + val32 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_CFGCH, RFREG_MASK); + h2c_v0->rfmod0 = cpu_to_le32(val32); + val32 = rtw89_read_rf(rtwdev, RF_PATH_B, RR_CFGCH, RFREG_MASK); + h2c_v0->rfmod1 = cpu_to_le32(val32); + + if (rtw89_is_mlo_1_1(rtwdev)) + h2c_v0->mlo_1_1 = cpu_to_le32(1); + + h2c_v0->rfe_type = cpu_to_le32(rtwdev->efuse.rfe_type); + + goto done; + } + + if (rtw89_is_mlo_1_1(rtwdev)) { + h2c_v1 = &h2c_v2->base_v1; + h2c_v1->mlo_1_1 = cpu_to_le32(1); + } +done: + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, + H2C_FUNC_RFK_PRE_NOTIFY, 0, 0, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_rfk_mcc_info *rfk_mcc_v0 = &rtwdev->rfk_mcc; + struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 *h2c_v0; + struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 *h2c_v1; + struct rtw89_fw_h2c_rfk_pre_info_mcc *h2c; + struct rtw89_hal *hal = &rtwdev->hal; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u8 ver = U8_MAX; + u8 tbl, path; + u8 tbl_sel; + int ret; + + if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V2, &rtwdev->fw)) { + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V1, &rtwdev->fw)) { + len = sizeof(*h2c_v1); + ver = 1; + } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V0, &rtwdev->fw)) { + len = sizeof(*h2c_v0); + ver = 0; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c rfk_pre_ntfy_mcc\n"); + return -ENOMEM; + } + skb_put(skb, len); + + if (ver != 0) + goto v1; + + h2c_v0 = (struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 *)skb->data; + for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) { + for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) { + h2c_v0->tbl_18[tbl][path] = + cpu_to_le32(rfk_mcc_v0->data[path].rf18[tbl]); + tbl_sel = rfk_mcc_v0->data[path].table_idx; + h2c_v0->cur_18[path] = + cpu_to_le32(rfk_mcc_v0->data[path].rf18[tbl_sel]); + } + } + + h2c_v0->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + goto done; + +v1: + h2c_v1 = (struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 *)skb->data; + + BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR); - if (rtw89_is_mlo_1_1(rtwdev)) - h2c_v0->mlo_1_1 = cpu_to_le32(1); + for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) + h2c_v1->tbl_18[tbl] = cpu_to_le32(rfk_mcc->rf18[tbl]); - h2c_v0->rfe_type = cpu_to_le32(rtwdev->efuse.rfe_type); + BUILD_BUG_ON(ARRAY_SIZE(rtwdev->rfk_mcc.data) < NUM_OF_RTW89_FW_RFK_PATH); - goto done; + /* shared table array, but tbl_sel can be independent by path */ + for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) { + tbl = rfk_mcc[path].table_idx; + h2c_v1->cur_18[path] = cpu_to_le32(rfk_mcc->rf18[tbl]); + + if (path == phy_idx) + h2c_v1->tbl_idx = tbl; } - if (rtw89_is_mlo_1_1(rtwdev)) { - h2c_v1 = &h2c->base_v1; + h2c_v1->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode); + h2c_v1->phy_idx = phy_idx; + + if (rtw89_is_mlo_1_1(rtwdev)) h2c_v1->mlo_1_1 = cpu_to_le32(1); - } + + if (ver == 1) + goto done; + + h2c = (struct rtw89_fw_h2c_rfk_pre_info_mcc *)skb->data; + + h2c->aid = cpu_to_le32(hal->aid); + done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, - H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, - H2C_FUNC_RFK_PRE_NOTIFY, 0, 0, - len); + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY, + H2C_FUNC_OUTSRC_RF_MCC_INFO, 0, 0, len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { @@ -6160,6 +7292,7 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, enum rtw89_tssi_mode tssi_mode) { + const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_h2c_rf_tssi *h2c; @@ -6180,11 +7313,15 @@ int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, h2c->ch = chan->channel; h2c->bw = chan->band_width; h2c->band = chan->band_type; - h2c->hwtx_en = true; h2c->cv = hal->cv; h2c->tssi_mode = tssi_mode; h2c->rfe_type = efuse->rfe_type; + if (chip->chip_id == RTL8922A) + h2c->hwtx_en = true; + else + h2c->hwtx_en = false; + rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(rtwdev, phy_idx, chan, h2c); rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(rtwdev, phy_idx, chan, h2c); @@ -6367,9 +7504,9 @@ int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, skb_put(skb, len); h2c = (struct rtw89_h2c_rf_dack *)skb->data; - h2c->len = cpu_to_le32(len); - h2c->phy = cpu_to_le32(phy_idx); - h2c->type = cpu_to_le32(0); + h2c->len = len; + h2c->phy = phy_idx; + h2c->type = 0; rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, @@ -6444,6 +7581,124 @@ int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, return ret; } +int rtw89_fw_h2c_rf_tas_trigger(struct rtw89_dev *rtwdev, bool enable) +{ + struct rtw89_h2c_rf_tas *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c RF TAS\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_rf_tas *)skb->data; + + h2c->enable = cpu_to_le32(enable); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, + H2C_FUNC_RFK_TAS_OFFLOAD, 0, 0, len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +int rtw89_fw_h2c_rf_txiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan) +{ + struct rtw89_h2c_rf_txiqk *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c RF TXIQK\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_rf_txiqk *)skb->data; + + h2c->len = len; + h2c->phy = phy_idx; + h2c->txiqk_enable = true; + h2c->is_wb_txiqk = true; + h2c->kpath = RF_AB; + h2c->cur_band = chan->band_type; + h2c->cur_bw = chan->band_width; + h2c->cur_ch = chan->channel; + h2c->txiqk_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, + H2C_FUNC_RFK_TXIQK_OFFOAD, 0, 0, len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + +int rtw89_fw_h2c_rf_cim3k(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan) +{ + struct rtw89_h2c_rf_cim3k *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for h2c RF CIM3K\n"); + return -ENOMEM; + } + skb_put(skb, len); + h2c = (struct rtw89_h2c_rf_cim3k *)skb->data; + + h2c->len = len; + h2c->phy = phy_idx; + h2c->kpath = RF_AB; + h2c->cur_band = chan->band_type; + h2c->cur_bw = chan->band_width; + h2c->cur_ch = chan->channel; + h2c->cim3k_dbg_en = rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK, + H2C_FUNC_RFK_CIM3K_OFFOAD, 0, 0, len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} + int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, u8 *buf, u16 len, bool rack, bool dack) @@ -6529,6 +7784,17 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev) __rtw89_fw_free_all_early_h2c(rtwdev); } +void rtw89_fw_c2h_dummy_handler(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ + struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(c2h); + u8 category = attr->category; + u8 class = attr->class; + u8 func = attr->func; + + rtw89_debug(rtwdev, RTW89_DBG_FW, + "C2H cate=%u cls=%u func=%u is dummy\n", category, class, func); +} + static void rtw89_fw_c2h_parse_attr(struct sk_buff *c2h) { const struct rtw89_c2h_hdr *hdr = (const struct rtw89_c2h_hdr *)c2h->data; @@ -6613,16 +7879,57 @@ void rtw89_fw_c2h_work(struct wiphy *wiphy, struct wiphy_work *work) struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, c2h_work); struct sk_buff *skb, *tmp; + struct sk_buff_head c2hq; + unsigned long flags; lockdep_assert_wiphy(rtwdev->hw->wiphy); - skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) { - skb_unlink(skb, &rtwdev->c2h_queue); + __skb_queue_head_init(&c2hq); + + spin_lock_irqsave(&rtwdev->c2h_queue.lock, flags); + skb_queue_splice_init(&rtwdev->c2h_queue, &c2hq); + spin_unlock_irqrestore(&rtwdev->c2h_queue.lock, flags); + + skb_queue_walk_safe(&c2hq, skb, tmp) { rtw89_fw_c2h_cmd_handle(rtwdev, skb); dev_kfree_skb_any(skb); } } +void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev) +{ + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct sk_buff *skb, *tmp; + struct sk_buff_head c2hq; + unsigned long flags; + + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + __skb_queue_head_init(&c2hq); + + spin_lock_irqsave(&rtwdev->c2h_queue.lock, flags); + skb_queue_splice_init(&rtwdev->c2h_queue, &c2hq); + spin_unlock_irqrestore(&rtwdev->c2h_queue.lock, flags); + + skb_queue_walk_safe(&c2hq, skb, tmp) { + struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb); + + if (!attr->is_scan_event || attr->scan_seq == scan_info->seq) + continue; + + rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, + "purge obsoleted scan event with seq=%d (cur=%d)\n", + attr->scan_seq, scan_info->seq); + + __skb_unlink(skb, &c2hq); + dev_kfree_skb_any(skb); + } + + spin_lock_irqsave(&rtwdev->c2h_queue.lock, flags); + skb_queue_splice(&c2hq, &rtwdev->c2h_queue); + spin_unlock_irqrestore(&rtwdev->c2h_queue.lock, flags); +} + static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev, struct rtw89_mac_h2c_info *info) { @@ -6662,8 +7969,9 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev, const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_fw_info *fw_info = &rtwdev->fw; const u32 *c2h_reg = chip->c2h_regs; - u32 ret, timeout; + u32 timeout; u8 i, val; + int ret; info->id = RTW89_FWCMD_C2HREG_FUNC_NULL; @@ -6672,6 +7980,9 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev, else timeout = RTW89_C2H_TIMEOUT; + if (info->timeout) + timeout = info->timeout; + ret = read_poll_timeout_atomic(rtw89_read8, val, val, 1, timeout, false, rtwdev, chip->c2h_ctrl_reg); @@ -6701,7 +8012,7 @@ int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev, struct rtw89_mac_h2c_info *h2c_info, struct rtw89_mac_c2h_info *c2h_info) { - u32 ret; + int ret; if (h2c_info && h2c_info->id != RTW89_FWCMD_H2CREG_FUNC_GET_FEATURE) lockdep_assert_wiphy(rtwdev->hw->wiphy); @@ -6780,6 +8091,7 @@ static void rtw89_hw_scan_cleanup(struct rtw89_dev *rtwdev, scan_info->scanning_vif = NULL; scan_info->abort = false; scan_info->connected = false; + scan_info->delay = 0; } static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev, @@ -6958,7 +8270,6 @@ static void rtw89_pno_scan_add_chan_ax(struct rtw89_dev *rtwdev, struct rtw89_pktofld_info *info; u8 probe_count = 0; - ch_info->notify_action = RTW89_SCANOFLD_DEBUG_MASK; ch_info->dfs_ch = chan_type == RTW89_CHAN_DFS; ch_info->bw = RTW89_SCAN_WIDTH; ch_info->tx_pkt = true; @@ -7012,6 +8323,7 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, struct cfg80211_scan_request *req = rtwvif->scan_req; struct rtw89_chan *op = &rtwdev->scan_info.op_chan; struct rtw89_pktofld_info *info; + struct ieee80211_vif *vif; u8 band, probe_count = 0; int ret; @@ -7064,7 +8376,9 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, ch_info->pri_ch = op->primary_channel; ch_info->ch_band = op->band_type; ch_info->bw = op->band_width; - ch_info->tx_null = true; + vif = rtwvif_link_to_vif(rtwvif_link); + ch_info->tx_null = !is_zero_ether_addr(rtwvif_link->bssid) && + vif->type != NL80211_IFTYPE_AP; ch_info->num_pkt = 0; break; case RTW89_CHAN_DFS: @@ -7082,7 +8396,9 @@ static void rtw89_hw_scan_add_chan_ax(struct rtw89_dev *rtwdev, int chan_type, ch_info->pri_ch = ext->chan.primary_channel; ch_info->ch_band = ext->chan.band_type; ch_info->bw = ext->chan.band_width; - ch_info->tx_null = true; + vif = rtwvif_link_to_vif(ext->rtwvif_link); + ch_info->tx_null = !is_zero_ether_addr(ext->rtwvif_link->bssid) && + vif->type != NL80211_IFTYPE_AP; ch_info->num_pkt = 0; ch_info->macid_tx = true; break; @@ -7099,7 +8415,6 @@ static void rtw89_pno_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type, struct rtw89_pktofld_info *info; u8 probe_count = 0, i; - ch_info->notify_action = RTW89_SCANOFLD_DEBUG_MASK; ch_info->dfs_ch = chan_type == RTW89_CHAN_DFS; ch_info->bw = RTW89_SCAN_WIDTH; ch_info->tx_null = false; @@ -7388,6 +8703,13 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev, INIT_LIST_HEAD(&list); list_for_each_entry_safe(ch_info, tmp, &scan_info->chan_list, list) { + /* The operating channel (tx_null == true) should + * not be last in the list, to avoid breaking + * RTL8851BU and RTL8832BU. + */ + if (list_len + 1 == RTW89_SCAN_LIST_LIMIT_AX && ch_info->tx_null) + break; + list_move_tail(&ch_info->list, &list); list_len++; @@ -7468,15 +8790,23 @@ int rtw89_hw_scan_prep_chan_list_be(struct rtw89_dev *rtwdev, struct ieee80211_channel *channel; struct list_head chan_list; enum rtw89_chan_type type; + bool chan_by_rnr; bool random_seq; int ret; u32 idx; random_seq = !!(req->flags & NL80211_SCAN_FLAG_RANDOM_SN); + chan_by_rnr = rtwdev->chip->support_rnr && + (req->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ); INIT_LIST_HEAD(&chan_list); for (idx = 0; idx < req->n_channels; idx++) { channel = req->channels[idx]; + + if (channel->band == NL80211_BAND_6GHZ && + !cfg80211_channel_is_psc(channel) && chan_by_rnr) + continue; + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); if (!ch_info) { ret = -ENOMEM; @@ -7579,12 +8909,25 @@ static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev, static void rtw89_hw_scan_update_link_beacon_noa(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, - u16 tu) + u16 tu, bool scan) { struct ieee80211_p2p_noa_desc noa_desc = {}; + struct ieee80211_bss_conf *bss_conf; + u16 beacon_int; u64 tsf; int ret; + rcu_read_lock(); + + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + beacon_int = bss_conf->beacon_int; + + rcu_read_unlock(); + + tu += beacon_int * 3; + if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) + rtwdev->scan_info.delay = ieee80211_tu_to_usec(beacon_int * 3) / 1000; + ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); if (ret) { rtw89_warn(rtwdev, "%s: failed to get tsf\n", __func__); @@ -7592,17 +8935,24 @@ static void rtw89_hw_scan_update_link_beacon_noa(struct rtw89_dev *rtwdev, } noa_desc.start_time = cpu_to_le32(tsf); - noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(tu)); - noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(tu)); - noa_desc.count = 1; + if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) { + noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(tu)); + noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(tu)); + noa_desc.count = 1; + } else { + noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(20000)); + noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(20000)); + noa_desc.count = 255; + } rtw89_p2p_noa_renew(rtwvif_link); - rtw89_p2p_noa_append(rtwvif_link, &noa_desc); + if (scan) + rtw89_p2p_noa_append(rtwvif_link, &noa_desc); + rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_link); } -static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, - const struct cfg80211_scan_request *req) +static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, bool scan) { const struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; const struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; @@ -7617,6 +8967,9 @@ static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, lockdep_assert_wiphy(rtwdev->hw->wiphy); + if (!scan) + goto update; + list_for_each_safe(pos, tmp, &scan_info->chan_list) { switch (chip->chip_gen) { case RTW89_CHIP_AX: @@ -7640,6 +8993,7 @@ static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, return; } +update: list_for_each_entry(rtwvif, &mgnt->active_list, mgnt_entry) { unsigned int link_id; @@ -7648,7 +9002,8 @@ static void rtw89_hw_scan_update_beacon_noa(struct rtw89_dev *rtwdev, continue; rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) - rtw89_hw_scan_update_link_beacon_noa(rtwdev, rtwvif_link, tu); + rtw89_hw_scan_update_link_beacon_noa(rtwdev, rtwvif_link, + tu, scan); } } @@ -7672,18 +9027,17 @@ static void rtw89_hw_scan_set_extra_op_info(struct rtw89_dev *rtwdev, if (tmp == scan_rtwvif) continue; - tmp_link = rtw89_vif_get_link_inst(tmp, 0); - if (unlikely(!tmp_link)) { - rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, - "hw scan: no HW-0 link for extra op\n"); + tmp_link = rtw89_get_designated_link(tmp); + if (unlikely(!tmp_link)) continue; - } tmp_chan = rtw89_chan_get(rtwdev, tmp_link->chanctx_idx); *ext = (struct rtw89_hw_scan_extra_op){ .set = true, .macid = tmp_link->mac_id, + .port = tmp_link->port, .chan = *tmp_chan, + .rtwvif_link = tmp_link, }; rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN, @@ -7697,11 +9051,11 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct ieee80211_scan_request *scan_req) { - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); struct cfg80211_scan_request *req = &scan_req->req; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; struct rtw89_chanctx_pause_parm pause_parm = { .rsn = RTW89_CHANCTX_PAUSE_REASON_HW_SCAN, @@ -7709,7 +9063,6 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, }; u32 rx_fltr = rtwdev->hal.rx_fltr; u8 mac_addr[ETH_ALEN]; - u32 reg; int ret; /* clone op and keep it during scan */ @@ -7724,12 +9077,15 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, rtwdev->scan_info.connected = rtw89_is_any_vif_connected_or_connecting(rtwdev); rtwdev->scan_info.scanning_vif = rtwvif_link; rtwdev->scan_info.abort = false; + rtwdev->scan_info.delay = 0; rtwvif->scan_ies = &scan_req->ies; rtwvif->scan_req = req; if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) get_random_mask_addr(mac_addr, req->mac_addr, req->mac_addr_mask); + else if (ieee80211_vif_is_mld(vif)) + ether_addr_copy(mac_addr, vif->addr); else ether_addr_copy(mac_addr, rtwvif_link->mac_addr); @@ -7748,13 +9104,13 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev, rx_fltr &= ~B_AX_A_BC; rx_fltr &= ~B_AX_A_A1_MATCH; - reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); - rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, rtwvif_link->mac_idx, rx_fltr); rtw89_chanctx_pause(rtwdev, &pause_parm); + rtw89_phy_dig_suspend(rtwdev); if (mode == RTW89_ENTITY_MODE_MCC) - rtw89_hw_scan_update_beacon_noa(rtwdev, req); + rtw89_hw_scan_update_beacon_noa(rtwdev, true); return 0; } @@ -7766,29 +9122,30 @@ struct rtw89_hw_scan_complete_cb_data { static int rtw89_hw_scan_complete_cb(struct rtw89_dev *rtwdev, void *data) { - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); struct rtw89_hw_scan_complete_cb_data *cb_data = data; struct rtw89_vif_link *rtwvif_link = cb_data->rtwvif_link; struct cfg80211_scan_info info = { .aborted = cb_data->aborted, }; - u32 reg; - if (!rtwvif_link) return -EINVAL; - reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, rtwvif_link->mac_idx); - rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rtwdev->hal.rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, rtwvif_link->mac_idx, rtwdev->hal.rx_fltr); rtw89_core_scan_complete(rtwdev, rtwvif_link, true); ieee80211_scan_completed(rtwdev->hw, &info); ieee80211_wake_queues(rtwdev->hw); rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true); rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true); + rtw89_phy_dig_resume(rtwdev, true); rtw89_hw_scan_cleanup(rtwdev, rtwvif_link); + if (mode == RTW89_ENTITY_MODE_MCC) + rtw89_hw_scan_update_beacon_noa(rtwdev, false); + return 0; } @@ -7855,6 +9212,8 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, bool enable) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + const struct rtw89_hw_scan_extra_op *ext = &scan_info->extra_op; struct rtw89_scan_option opt = {0}; bool connected; int ret = 0; @@ -7865,6 +9224,7 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, connected = rtwdev->scan_info.connected; opt.enable = enable; opt.target_ch_mode = connected; + opt.delay = rtwdev->scan_info.delay; if (enable) { ret = mac->add_chan_list(rtwdev, rtwvif_link); if (ret) @@ -7878,49 +9238,62 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, opt.num_macc_role = 0; opt.mlo_mode = rtwdev->mlo_dbcc_mode; opt.num_opch = connected ? 1 : 0; + if (connected && ext->set) + opt.num_opch++; + opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID; } - ret = mac->scan_offload(rtwdev, &opt, rtwvif_link, false); + ret = rtw89_mac_scan_offload(rtwdev, &opt, rtwvif_link, false); + out: return ret; } -#define H2C_FW_CPU_EXCEPTION_LEN 4 -#define H2C_FW_CPU_EXCEPTION_TYPE_DEF 0x5566 +#define H2C_FW_CPU_EXCEPTION_TYPE_0 0x5566 +#define H2C_FW_CPU_EXCEPTION_TYPE_1 0x0 int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev) { + struct rtw89_h2c_trig_cpu_except *h2c; + u32 cpu_exception_type_def; + u32 len = sizeof(*h2c); struct sk_buff *skb; int ret; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_FW_CPU_EXCEPTION_LEN); + if (RTW89_CHK_FW_FEATURE(CRASH_TRIGGER_TYPE_1, &rtwdev->fw)) + cpu_exception_type_def = H2C_FW_CPU_EXCEPTION_TYPE_1; + else if (RTW89_CHK_FW_FEATURE(CRASH_TRIGGER_TYPE_0, &rtwdev->fw)) + cpu_exception_type_def = H2C_FW_CPU_EXCEPTION_TYPE_0; + else + return -EOPNOTSUPP; + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for fw cpu exception\n"); return -ENOMEM; } - skb_put(skb, H2C_FW_CPU_EXCEPTION_LEN); - RTW89_SET_FWCMD_CPU_EXCEPTION_TYPE(skb->data, - H2C_FW_CPU_EXCEPTION_TYPE_DEF); + skb_put(skb, len); + h2c = (struct rtw89_h2c_trig_cpu_except *)skb->data; + + h2c->w0 = le32_encode_bits(cpu_exception_type_def, + RTW89_H2C_CPU_EXCEPTION_TYPE); rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_TEST, H2C_CL_FW_STATUS_TEST, H2C_FUNC_CPU_EXCEPTION, 0, 0, - H2C_FW_CPU_EXCEPTION_LEN); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { rtw89_err(rtwdev, "failed to send h2c\n"); - goto fail; + dev_kfree_skb_any(skb); + return ret; } return 0; - -fail: - dev_kfree_skb_any(skb); - return ret; } #define H2C_PKT_DROP_LEN 24 @@ -8276,44 +9649,106 @@ int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, return ret; } -#define H2C_WOW_CAM_UPD_LEN 24 -int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, - struct rtw89_wow_cam_info *cam_info) +int rtw89_fw_h2c_wow_cam_update(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info) { + struct rtw89_h2c_wow_cam_update *h2c; + u32 len = sizeof(*h2c); struct sk_buff *skb; int ret; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_CAM_UPD_LEN); + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { - rtw89_err(rtwdev, "failed to alloc skb for keep alive\n"); + rtw89_err(rtwdev, "failed to alloc skb for wow cam update\n"); return -ENOMEM; } + skb_put(skb, len); + h2c = (struct rtw89_h2c_wow_cam_update *)skb->data; + + h2c->w0 = le32_encode_bits(cam_info->r_w, RTW89_H2C_WOW_CAM_UPD_W0_R_W) | + le32_encode_bits(cam_info->idx, RTW89_H2C_WOW_CAM_UPD_W0_IDX); + + if (!cam_info->valid) + goto fill_valid; + + h2c->wkfm0 = cam_info->mask[0]; + h2c->wkfm1 = cam_info->mask[1]; + h2c->wkfm2 = cam_info->mask[2]; + h2c->wkfm3 = cam_info->mask[3]; + h2c->w5 = le32_encode_bits(cam_info->crc, RTW89_H2C_WOW_CAM_UPD_W5_CRC) | + le32_encode_bits(cam_info->negative_pattern_match, + RTW89_H2C_WOW_CAM_UPD_W5_NEGATIVE_PATTERN_MATCH) | + le32_encode_bits(cam_info->skip_mac_hdr, + RTW89_H2C_WOW_CAM_UPD_W5_SKIP_MAC_HDR) | + le32_encode_bits(cam_info->uc, RTW89_H2C_WOW_CAM_UPD_W5_UC) | + le32_encode_bits(cam_info->mc, RTW89_H2C_WOW_CAM_UPD_W5_MC) | + le32_encode_bits(cam_info->bc, RTW89_H2C_WOW_CAM_UPD_W5_BC); +fill_valid: + h2c->w5 |= le32_encode_bits(cam_info->valid, RTW89_H2C_WOW_CAM_UPD_W5_VALID); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_WOW_CAM_UPD, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; +fail: + dev_kfree_skb_any(skb); + + return ret; +} +EXPORT_SYMBOL(rtw89_fw_h2c_wow_cam_update); - skb_put(skb, H2C_WOW_CAM_UPD_LEN); +int rtw89_fw_h2c_wow_cam_update_v1(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info) +{ + struct rtw89_h2c_wow_payload_cam_update *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + int ret; - RTW89_SET_WOW_CAM_UPD_R_W(skb->data, cam_info->r_w); - RTW89_SET_WOW_CAM_UPD_IDX(skb->data, cam_info->idx); - if (cam_info->valid) { - RTW89_SET_WOW_CAM_UPD_WKFM1(skb->data, cam_info->mask[0]); - RTW89_SET_WOW_CAM_UPD_WKFM2(skb->data, cam_info->mask[1]); - RTW89_SET_WOW_CAM_UPD_WKFM3(skb->data, cam_info->mask[2]); - RTW89_SET_WOW_CAM_UPD_WKFM4(skb->data, cam_info->mask[3]); - RTW89_SET_WOW_CAM_UPD_CRC(skb->data, cam_info->crc); - RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(skb->data, - cam_info->negative_pattern_match); - RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(skb->data, - cam_info->skip_mac_hdr); - RTW89_SET_WOW_CAM_UPD_UC(skb->data, cam_info->uc); - RTW89_SET_WOW_CAM_UPD_MC(skb->data, cam_info->mc); - RTW89_SET_WOW_CAM_UPD_BC(skb->data, cam_info->bc); + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for wow payload cam update\n"); + return -ENOMEM; } - RTW89_SET_WOW_CAM_UPD_VALID(skb->data, cam_info->valid); + skb_put(skb, len); + h2c = (struct rtw89_h2c_wow_payload_cam_update *)skb->data; + + h2c->w0 = le32_encode_bits(cam_info->r_w, RTW89_H2C_WOW_PLD_CAM_UPD_W0_R_W) | + le32_encode_bits(cam_info->idx, RTW89_H2C_WOW_PLD_CAM_UPD_W0_IDX); + h2c->w8 = le32_encode_bits(cam_info->valid, RTW89_H2C_WOW_PLD_CAM_UPD_W8_VALID) | + le32_encode_bits(1, RTW89_H2C_WOW_PLD_CAM_UPD_W8_WOW_PTR); + + if (!cam_info->valid) + goto done; + h2c->wkfm0 = cam_info->mask[0]; + h2c->wkfm1 = cam_info->mask[1]; + h2c->wkfm2 = cam_info->mask[2]; + h2c->wkfm3 = cam_info->mask[3]; + h2c->w5 = le32_encode_bits(cam_info->uc, RTW89_H2C_WOW_PLD_CAM_UPD_W5_UC) | + le32_encode_bits(cam_info->mc, RTW89_H2C_WOW_PLD_CAM_UPD_W5_MC) | + le32_encode_bits(cam_info->bc, RTW89_H2C_WOW_PLD_CAM_UPD_W5_BC) | + le32_encode_bits(cam_info->skip_mac_hdr, + RTW89_H2C_WOW_PLD_CAM_UPD_W5_SKIP_MAC_HDR); + h2c->w6 = le32_encode_bits(cam_info->crc, RTW89_H2C_WOW_PLD_CAM_UPD_W6_CRC); + h2c->w7 = le32_encode_bits(cam_info->negative_pattern_match, + RTW89_H2C_WOW_PLD_CAM_UPD_W7_NEGATIVE_PATTERN_MATCH); + +done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_MAC, H2C_CL_MAC_WOW, - H2C_FUNC_WOW_CAM_UPD, 0, 1, - H2C_WOW_CAM_UPD_LEN); + H2C_FUNC_WOW_PLD_CAM_UPD, 0, 1, + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { @@ -8327,6 +9762,7 @@ int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, return ret; } +EXPORT_SYMBOL(rtw89_fw_h2c_wow_cam_update_v1); int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, @@ -8371,9 +9807,10 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, goto fail; } - /* not support TKIP yet */ h2c->w0 = le32_encode_bits(enable, RTW89_H2C_WOW_GTK_OFLD_W0_EN) | - le32_encode_bits(0, RTW89_H2C_WOW_GTK_OFLD_W0_TKIP_EN) | + le32_encode_bits(!!memchr_inv(gtk_info->txmickey, 0, + sizeof(gtk_info->txmickey)), + RTW89_H2C_WOW_GTK_OFLD_W0_TKIP_EN) | le32_encode_bits(gtk_info->igtk_keyid ? 1 : 0, RTW89_H2C_WOW_GTK_OFLD_W0_IEEE80211W_EN) | le32_encode_bits(macid, RTW89_H2C_WOW_GTK_OFLD_W0_MAC_ID) | @@ -8465,19 +9902,30 @@ int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev) static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct rtw89_wait_info *wait, unsigned int cond) { - int ret; + struct rtw89_wait_response *prep; + int ret = 0; + + lockdep_assert_wiphy(rtwdev->hw->wiphy); + + prep = rtw89_wait_for_cond_prep(wait, cond); + if (IS_ERR(prep)) + goto out; ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { rtw89_err(rtwdev, "failed to send h2c\n"); dev_kfree_skb_any(skb); - return -EBUSY; + ret = -EBUSY; + goto out; } - if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) - return 1; + if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) { + ret = 1; + goto out; + } - return rtw89_wait_for_cond(wait, cond); +out: + return rtw89_wait_for_cond_eval(wait, prep, ret); } #define H2C_ADD_MCC_LEN 16 diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 2b312b2be1157..62cb42e8ec234 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -42,6 +42,10 @@ struct rtw89_c2hreg_phycap { #define RTW89_C2HREG_PHYCAP_W0_BW GENMASK(31, 24) #define RTW89_C2HREG_PHYCAP_W1_TX_NSS GENMASK(7, 0) #define RTW89_C2HREG_PHYCAP_W1_PROT GENMASK(15, 8) +#define RTW89_C2HREG_PHYCAP_W1_PROT_11N 1 +#define RTW89_C2HREG_PHYCAP_W1_PROT_11AC 2 +#define RTW89_C2HREG_PHYCAP_W1_PROT_11AX 3 +#define RTW89_C2HREG_PHYCAP_W1_PROT_11BE 4 #define RTW89_C2HREG_PHYCAP_W1_NIC GENMASK(23, 16) #define RTW89_C2HREG_PHYCAP_W1_WL_FUNC GENMASK(31, 24) #define RTW89_C2HREG_PHYCAP_W2_HW_TYPE GENMASK(7, 0) @@ -87,6 +91,9 @@ struct rtw89_c2hreg_phycap { #define RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_6 GENMASK(7, 0) #define RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_7 GENMASK(15, 8) +#define RTW89_C2HREG_PS_LEAVE_ACK_RET GENMASK(7, 0) +#define RTW89_C2HREG_PS_LEAVE_ACK_MACID GENMASK(31, 16) + struct rtw89_h2creg_hdr { u32 w0; }; @@ -117,6 +124,7 @@ struct rtw89_h2creg_sch_tx_en { struct rtw89_mac_c2h_info { u8 id; u8 content_len; + u32 timeout; union { u32 c2hreg[RTW89_C2HREG_MAX]; struct rtw89_c2hreg_hdr hdr; @@ -156,6 +164,7 @@ enum rtw89_mac_c2h_type { RTW89_FWCMD_C2HREG_FUNC_TX_PAUSE_RPT, RTW89_FWCMD_C2HREG_FUNC_WOW_CPUIO_RX_ACK = 0xA, RTW89_FWCMD_C2HREG_FUNC_PHY_CAP_PART1 = 0xC, + RTW89_FWCMD_C2HREG_FUNC_PS_LEAVE_ACK = 0xD, RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF, }; @@ -293,6 +302,7 @@ struct rtw89_fw_hdr_section_info { struct rtw89_fw_bin_info { u8 section_num; + u32 part_size; u32 hdr_len; bool dynamic_hdr_en; u32 dynamic_hdr_len; @@ -442,6 +452,13 @@ struct rtw89_h2c_ra { #define RTW89_H2C_RA_W3_FIXED_CSI_MODE GENMASK(25, 24) #define RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF GENMASK(28, 26) #define RTW89_H2C_RA_W3_FIXED_CSI_BW GENMASK(31, 29) +#define RTW89_H2C_RA_V1_W3_PARTIAL_BW_SU_ER BIT(15) +#define RTW89_H2C_RA_V1_W3_FIXED_CSI_RATE_L GENMASK(23, 16) +#define RTW89_H2C_RA_V1_W3_IS_NOISY BIT(24) +#define RTW89_H2C_RA_V1_W3_PSRA_EN BIT(25) +#define RTW89_H2C_RA_V1_W3_MACID_MSB GENMASK(28, 27) +#define RTW89_H2C_RA_V1_W3_BAND GENMASK(30, 29) +#define RTW89_H2C_RA_V1_W3_NEW_DBGREG BIT(31) struct rtw89_h2c_ra_v1 { struct rtw89_h2c_ra v0; @@ -1505,6 +1522,153 @@ struct rtw89_h2c_cctlinfo_ud_g7 { #define CCTLINFO_G7_W15_MGNT_CURR_RATE GENMASK(27, 16) #define CCTLINFO_G7_W15_ALL GENMASK(27, 0) +struct rtw89_h2c_cctlinfo_ud_be { + __le32 c0; + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; + __le32 w12; + __le32 w13; + __le32 w14; + __le32 w15; + __le32 m0; + __le32 m1; + __le32 m2; + __le32 m3; + __le32 m4; + __le32 m5; + __le32 m6; + __le32 m7; + __le32 m8; + __le32 m9; + __le32 m10; + __le32 m11; + __le32 m12; + __le32 m13; + __le32 m14; + __le32 m15; +} __packed; + +#define BE_CCTL_INFO_C0_V1_MACID GENMASK(9, 0) +#define BE_CCTL_INFO_C0_V1_OP BIT(10) + +#define BE_CCTL_INFO_W0_DATARATE GENMASK(11, 0) +#define BE_CCTL_INFO_W0_DATA_GI_LTF GENMASK(14, 12) +#define BE_CCTL_INFO_W0_TRYRATE BIT(15) +#define BE_CCTL_INFO_W0_ARFR_CTRL GENMASK(17, 16) +#define BE_CCTL_INFO_W0_DIS_HE1SS_STBC BIT(18) +#define BE_CCTL_INFO_W0_ACQ_RPT_EN BIT(20) +#define BE_CCTL_INFO_W0_MGQ_RPT_EN BIT(21) +#define BE_CCTL_INFO_W0_ULQ_RPT_EN BIT(22) +#define BE_CCTL_INFO_W0_TWTQ_RPT_EN BIT(23) +#define BE_CCTL_INFO_W0_FORCE_TXOP BIT(24) +#define BE_CCTL_INFO_W0_DISRTSFB BIT(25) +#define BE_CCTL_INFO_W0_DISDATAFB BIT(26) +#define BE_CCTL_INFO_W0_NSTR_EN BIT(27) +#define BE_CCTL_INFO_W0_AMPDU_DENSITY GENMASK(31, 28) +#define BE_CCTL_INFO_W0_ALL (GENMASK(31, 20) | GENMASK(18, 0)) +#define BE_CCTL_INFO_W1_DATA_RTY_LOWEST_RATE GENMASK(11, 0) +#define BE_CCTL_INFO_W1_RTS_TXCNT_LMT GENMASK(15, 12) +#define BE_CCTL_INFO_W1_RTSRATE GENMASK(27, 16) +#define BE_CCTL_INFO_W1_RTS_RTY_LOWEST_RATE GENMASK(31, 28) +#define BE_CCTL_INFO_W1_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W2_DATA_TX_CNT_LMT GENMASK(5, 0) +#define BE_CCTL_INFO_W2_DATA_TXCNT_LMT_SEL BIT(6) +#define BE_CCTL_INFO_W2_MAX_AGG_NUM_SEL BIT(7) +#define BE_CCTL_INFO_W2_RTS_EN BIT(8) +#define BE_CCTL_INFO_W2_CTS2SELF_EN BIT(9) +#define BE_CCTL_INFO_W2_CCA_RTS GENMASK(11, 10) +#define BE_CCTL_INFO_W2_HW_RTS_EN BIT(12) +#define BE_CCTL_INFO_W2_RTS_DROP_DATA_MODE GENMASK(14, 13) +#define BE_CCTL_INFO_W2_PRELOAD_ENABLE BIT(15) +#define BE_CCTL_INFO_W2_AMPDU_MAX_LEN GENMASK(26, 16) +#define BE_CCTL_INFO_W2_UL_MU_DIS BIT(27) +#define BE_CCTL_INFO_W2_AMPDU_MAX_TIME GENMASK(31, 28) +#define BE_CCTL_INFO_W2_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W3_MAX_AGG_NUM GENMASK(7, 0) +#define BE_CCTL_INFO_W3_DATA_BW GENMASK(10, 8) +#define BE_CCTL_INFO_W3_DATA_BW_ER BIT(11) +#define BE_CCTL_INFO_W3_BA_BMAP GENMASK(14, 12) +#define BE_CCTL_INFO_W3_VCS_STBC BIT(15) +#define BE_CCTL_INFO_W3_VO_LFTIME_SEL GENMASK(18, 16) +#define BE_CCTL_INFO_W3_VI_LFTIME_SEL GENMASK(21, 19) +#define BE_CCTL_INFO_W3_BE_LFTIME_SEL GENMASK(24, 22) +#define BE_CCTL_INFO_W3_BK_LFTIME_SEL GENMASK(27, 25) +#define BE_CCTL_INFO_W3_AMPDU_TIME_SEL BIT(28) +#define BE_CCTL_INFO_W3_AMPDU_LEN_SEL BIT(29) +#define BE_CCTL_INFO_W3_RTS_TXCNT_LMT_SEL BIT(30) +#define BE_CCTL_INFO_W3_LSIG_TXOP_EN BIT(31) +#define BE_CCTL_INFO_W3_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W4_MULTI_PORT_ID GENMASK(2, 0) +#define BE_CCTL_INFO_W4_BYPASS_PUNC BIT(3) +#define BE_CCTL_INFO_W4_MBSSID GENMASK(7, 4) +#define BE_CCTL_INFO_W4_TID_DISABLE_V1 GENMASK(15, 8) +#define BE_CCTL_INFO_W4_ACT_SUBCH_CBW GENMASK(31, 16) +#define BE_CCTL_INFO_W4_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W5_ADDR_CAM_INDEX_V1 GENMASK(9, 0) +#define BE_CCTL_INFO_W5_SR_MCS_SU GENMASK(14, 10) +#define BE_CCTL_INFO_W5_A_CTRL_BQR_V1 BIT(15) +#define BE_CCTL_INFO_W5_A_CTRL_BSR_V1 BIT(16) +#define BE_CCTL_INFO_W5_A_CTRL_CAS_V1 BIT(17) +#define BE_CCTL_INFO_W5_DATA_ER_V1 BIT(18) +#define BE_CCTL_INFO_W5_DATA_DCM_V1 BIT(19) +#define BE_CCTL_INFO_W5_DATA_LDPC_V1 BIT(20) +#define BE_CCTL_INFO_W5_DATA_STBC_V1 BIT(21) +#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING0_V1 GENMASK(23, 22) +#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING1_V1 GENMASK(25, 24) +#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING2_V1 GENMASK(27, 26) +#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING3_V1 GENMASK(29, 28) +#define BE_CCTL_INFO_W5_NOMINAL_PKT_PADDING4_V1 GENMASK(31, 30) +#define BE_CCTL_INFO_W5_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W6_AID12_PAID GENMASK(11, 0) +#define BE_CCTL_INFO_W6_RESP_REF_RATE GENMASK(23, 12) +#define BE_CCTL_INFO_W6_ULDL BIT(31) +#define BE_CCTL_INFO_W6_ALL (BIT(31) | GENMASK(23, 0)) +#define BE_CCTL_INFO_W7_NC GENMASK(2, 0) +#define BE_CCTL_INFO_W7_NR GENMASK(5, 3) +#define BE_CCTL_INFO_W7_NG GENMASK(7, 6) +#define BE_CCTL_INFO_W7_CB GENMASK(9, 8) +#define BE_CCTL_INFO_W7_CS GENMASK(11, 10) +#define BE_CCTL_INFO_W7_CSI_STBC_EN BIT(13) +#define BE_CCTL_INFO_W7_CSI_LDPC_EN BIT(14) +#define BE_CCTL_INFO_W7_CSI_PARA_EN BIT(15) +#define BE_CCTL_INFO_W7_CSI_FIX_RATE GENMASK(27, 16) +#define BE_CCTL_INFO_W7_CSI_BW GENMASK(31, 29) +#define BE_CCTL_INFO_W7_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W8_ALL_ACK_SUPPORT_V1 BIT(0) +#define BE_CCTL_INFO_W8_BSR_QUEUE_SIZE_FORMAT_V1 BIT(1) +#define BE_CCTL_INFO_W8_BSR_OM_UPD_EN_V1 BIT(2) +#define BE_CCTL_INFO_W8_MACID_FWD_IDC_V1 BIT(3) +#define BE_CCTL_INFO_W8_AZ_SEC_EN BIT(4) +#define BE_CCTL_INFO_W8_BF_SEC_EN BIT(5) +#define BE_CCTL_INFO_W8_FIX_UL_ADDRCAM_IDX_V1 BIT(6) +#define BE_CCTL_INFO_W8_CTRL_CNT_VLD_V1 BIT(7) +#define BE_CCTL_INFO_W8_CTRL_CNT_V1 GENMASK(11, 8) +#define BE_CCTL_INFO_W8_RESP_SEC_TYPE GENMASK(15, 12) +#define BE_CCTL_INFO_W8_ALL GENMASK(15, 0) +#define BE_CCTL_INFO_W9_EMLSR_TRANS_DLY GENMASK(2, 0) +#define BE_CCTL_INFO_W9_ALL GENMASK(2, 0) +#define BE_CCTL_INFO_W10_SW_EHT_NLTF GENMASK(1, 0) +#define BE_CCTL_INFO_W10_TB_MLO_MODE BIT(2) +#define BE_CCTL_INFO_W10_ALL GENMASK(2, 0) +#define BE_CCTL_INFO_W14_VO_CURR_RATE GENMASK(11, 0) +#define BE_CCTL_INFO_W14_VI_CURR_RATE GENMASK(23, 12) +#define BE_CCTL_INFO_W14_BE_CURR_RATE_L GENMASK(31, 24) +#define BE_CCTL_INFO_W14_ALL GENMASK(31, 0) +#define BE_CCTL_INFO_W15_BE_CURR_RATE_H GENMASK(3, 0) +#define BE_CCTL_INFO_W15_BK_CURR_RATE GENMASK(15, 4) +#define BE_CCTL_INFO_W15_MGNT_CURR_RATE GENMASK(27, 16) +#define BE_CCTL_INFO_W15_ALL GENMASK(27, 0) + struct rtw89_h2c_bcn_upd { __le32 w0; __le32 w1; @@ -1598,6 +1762,28 @@ struct rtw89_h2c_bcn_upd_be { #define RTW89_H2C_BCN_UPD_BE_W7_ECSA_OFST GENMASK(30, 16) #define RTW89_H2C_BCN_UPD_BE_W7_PROTECTION_KEY_ID BIT(31) +struct rtw89_h2c_tbtt_tuning { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_H2C_TBTT_TUNING_W0_BAND GENMASK(3, 0) +#define RTW89_H2C_TBTT_TUNING_W0_PORT GENMASK(7, 4) +#define RTW89_H2C_TBTT_TUNING_W1_SHIFT GENMASK(31, 0) + +struct rtw89_h2c_pwr_lvl { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_H2C_PWR_LVL_W0_MACID GENMASK(7, 0) +#define RTW89_H2C_PWR_LVL_W0_BCN_TO_VAL GENMASK(15, 8) +#define RTW89_H2C_PWR_LVL_W0_PS_LVL GENMASK(19, 16) +#define RTW89_H2C_PWR_LVL_W0_TRX_LVL GENMASK(23, 20) +#define RTW89_H2C_PWR_LVL_W0_BCN_TO_LVL GENMASK(27, 24) +#define RTW89_H2C_PWR_LVL_W0_DTIM_TO_VAL GENMASK(31, 28) +#define RTW89_H2C_PWR_LVL_W1_MACID_EXT GENMASK(7, 0) + struct rtw89_h2c_role_maintain { __le32 w0; }; @@ -1831,10 +2017,71 @@ struct rtw89_h2c_lps_ml_cmn_info { u8 dup_bcn_ofst[RTW89_PHY_NUM]; } __packed; -static inline void RTW89_SET_FWCMD_CPU_EXCEPTION_TYPE(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)cmd, val, GENMASK(31, 0)); -} +#define BB_RX_GAIN_TB_RSSI_COMP_NUM 3 +#define BB_RX_GAIN_CCK_RPL_BIAS_COMP_NUM 2 +#define BB_GT2_GS_IDX_NUM 11 +#define BB_GT2_WB_GIDX_ELNA_NUM 16 +#define BB_GT2_G_ELNA_NUM 2 + +enum rtw89_bb_link_rx_gain_table_type { + RTW89_BB_PS_LINK_RX_GAIN_TAB_BCN_PATH_A = 0x00, + RTW89_BB_PS_LINK_RX_GAIN_TAB_BCN_PATH_B = 0x01, + RTW89_BB_PS_LINK_RX_GAIN_TAB_NOR_PATH_A = 0x02, + RTW89_BB_PS_LINK_RX_GAIN_TAB_NOR_PATH_B = 0x03, + RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX, +}; + +enum rtw89_bb_ps_link_buf_id { + RTW89_BB_PS_LINK_BUF_0 = 0x00, + RTW89_BB_PS_LINK_BUF_1 = 0x01, + RTW89_BB_PS_LINK_BUF_2 = 0x02, + RTW89_BB_PS_LINK_BUF_MAX, +}; + +struct rtw89_bb_link_info_rx_gain { + u8 gain_ofst[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX]; + __le16 rpl_bias_comp[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX]; + u8 tb_rssi_m_bias_comp[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX] + [BB_RX_GAIN_TB_RSSI_COMP_NUM]; + u8 cck_gain_ofst[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX]; + u8 cck_rpl_bias_comp[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX] + [BB_RX_GAIN_CCK_RPL_BIAS_COMP_NUM]; + u8 gain_err_lna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][LNA_GAIN_NUM]; + __le16 gain_err_tia[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][TIA_GAIN_NUM]; + u8 op1db_lna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][LNA_GAIN_NUM]; + u8 op1db_tia[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][TIA_LNA_OP1DB_NUM]; + struct { + u8 _20M[RTW89_BW20_SC_20M]; + u8 _40M[RTW89_BW20_SC_40M]; + u8 _80M[RTW89_BW20_SC_80M]; + u8 _160M[RTW89_BW20_SC_160M]; + } rpl_bias_comp_bw[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX]; + u8 wb_gs[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][BB_GT2_GS_IDX_NUM]; + u8 bypass_lna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][LNA_GAIN_NUM]; + u8 wb_lna_tia[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][BB_GT2_WB_GIDX_ELNA_NUM]; + u8 wb_g_elna[RTW89_BB_PS_LINK_RX_GAIN_TAB_MAX][BB_GT2_G_ELNA_NUM]; +} __packed; + +struct rtw89_h2c_lps_ml_cmn_info_v1 { + u8 fmt_id; + u8 rfe_type; + u8 rssi_main; + u8 rsvd0; + __le32 mlo_dbcc_mode; + u8 link_id[RTW89_BB_PS_LINK_BUF_MAX]; + u8 central_ch[RTW89_BB_PS_LINK_BUF_MAX]; + u8 pri_ch[RTW89_BB_PS_LINK_BUF_MAX]; + u8 bw[RTW89_BB_PS_LINK_BUF_MAX]; + u8 band[RTW89_BB_PS_LINK_BUF_MAX]; + u8 dup_bcn_ofst[RTW89_BB_PS_LINK_BUF_MAX]; + struct rtw89_bb_link_info_rx_gain rx_gain[RTW89_BB_PS_LINK_BUF_MAX]; +} __packed; + +struct rtw89_h2c_trig_cpu_except { + __le32 w0; +} __packed; + +#define RTW89_H2C_CPU_EXCEPTION_TYPE GENMASK(31, 0) static inline void RTW89_SET_FWCMD_PKT_DROP_SEL(void *cmd, u32 val) { @@ -2017,70 +2264,55 @@ static inline void RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(void *h2c, u32 val) le32p_replace_bits((__le32 *)h2c, val, GENMASK(31, 24)); } -static inline void RTW89_SET_WOW_CAM_UPD_R_W(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c, val, BIT(0)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_IDX(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c, val, GENMASK(7, 1)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_WKFM1(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 1, val, GENMASK(31, 0)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_WKFM2(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 2, val, GENMASK(31, 0)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_WKFM3(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 3, val, GENMASK(31, 0)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_WKFM4(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 4, val, GENMASK(31, 0)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_CRC(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, GENMASK(15, 0)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, BIT(22)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, BIT(23)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_UC(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, BIT(24)); -} - -static inline void RTW89_SET_WOW_CAM_UPD_MC(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, BIT(25)); -} +struct rtw89_h2c_wow_cam_update { + __le32 w0; + __le32 wkfm0; + __le32 wkfm1; + __le32 wkfm2; + __le32 wkfm3; + __le32 w5; +} __packed; -static inline void RTW89_SET_WOW_CAM_UPD_BC(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, BIT(26)); -} +#define RTW89_H2C_WOW_CAM_UPD_W0_R_W BIT(0) +#define RTW89_H2C_WOW_CAM_UPD_W0_IDX GENMASK(7, 1) +#define RTW89_H2C_WOW_CAM_UPD_WKFM0 GENMASK(31, 0) +#define RTW89_H2C_WOW_CAM_UPD_WKFM1 GENMASK(31, 0) +#define RTW89_H2C_WOW_CAM_UPD_WKFM2 GENMASK(31, 0) +#define RTW89_H2C_WOW_CAM_UPD_WKFM3 GENMASK(31, 0) +#define RTW89_H2C_WOW_CAM_UPD_W5_CRC GENMASK(15, 0) +#define RTW89_H2C_WOW_CAM_UPD_W5_NEGATIVE_PATTERN_MATCH BIT(22) +#define RTW89_H2C_WOW_CAM_UPD_W5_SKIP_MAC_HDR BIT(23) +#define RTW89_H2C_WOW_CAM_UPD_W5_UC BIT(24) +#define RTW89_H2C_WOW_CAM_UPD_W5_MC BIT(25) +#define RTW89_H2C_WOW_CAM_UPD_W5_BC BIT(26) +#define RTW89_H2C_WOW_CAM_UPD_W5_VALID BIT(31) + +struct rtw89_h2c_wow_payload_cam_update { + __le32 w0; + __le32 wkfm0; + __le32 wkfm1; + __le32 wkfm2; + __le32 wkfm3; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; +} __packed; -static inline void RTW89_SET_WOW_CAM_UPD_VALID(void *h2c, u32 val) -{ - le32p_replace_bits((__le32 *)h2c + 5, val, BIT(31)); -} +#define RTW89_H2C_WOW_PLD_CAM_UPD_W0_R_W BIT(0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W0_IDX GENMASK(7, 1) +#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM0 GENMASK(31, 0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM1 GENMASK(31, 0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM2 GENMASK(31, 0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_WKFM3 GENMASK(31, 0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_UC BIT(0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_MC BIT(1) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_BC BIT(2) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W5_SKIP_MAC_HDR BIT(7) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W6_CRC GENMASK(15, 0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W7_NEGATIVE_PATTERN_MATCH BIT(0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W8_VALID BIT(0) +#define RTW89_H2C_WOW_PLD_CAM_UPD_W8_WOW_PTR BIT(1) struct rtw89_h2c_wow_gtk_ofld { __le32 w0; @@ -2791,6 +3023,7 @@ struct rtw89_h2c_scanofld_be_macc_role { __le32 w0; } __packed; +#define RTW89_MAX_OP_NUM_BE 2 #define RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_BAND GENMASK(1, 0) #define RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_PORT GENMASK(4, 2) #define RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_MACID GENMASK(23, 8) @@ -2819,6 +3052,7 @@ struct rtw89_h2c_scanofld_be_opch { #define RTW89_H2C_SCANOFLD_BE_OPCH_W2_PKTS_CTRL GENMASK(7, 0) #define RTW89_H2C_SCANOFLD_BE_OPCH_W2_SW_DEF GENMASK(15, 8) #define RTW89_H2C_SCANOFLD_BE_OPCH_W2_SS GENMASK(18, 16) +#define RTW89_H2C_SCANOFLD_BE_OPCH_W2_TXBCN BIT(19) #define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT0 GENMASK(7, 0) #define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT1 GENMASK(15, 8) #define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT2 GENMASK(23, 16) @@ -3566,6 +3800,8 @@ struct rtw89_fw_c2h_attr { u8 class; u8 func; u16 len; + u8 is_scan_event: 1; + u8 scan_seq: 2; }; static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb) @@ -3617,6 +3853,15 @@ struct rtw89_fw_c2h_log_fmt { #define RTW89_C2H_FW_LOG_SIGNATURE 0xA5A5 #define RTW89_C2H_FW_LOG_STR_BUF_SIZE 512 +struct rtw89_c2h_bcn_upd_done { + struct rtw89_c2h_hdr hdr; + __le32 w2; +} __packed; + +#define RTW89_C2H_BCN_UPD_DONE_W2_PORT GENMASK(2, 0) +#define RTW89_C2H_BCN_UPD_DONE_W2_MBSSID GENMASK(6, 3) +#define RTW89_C2H_BCN_UPD_DONE_W2_BAND_IDX BIT(7) + struct rtw89_c2h_mac_bcnfltr_rpt { __le32 w0; __le32 w1; @@ -3644,6 +3889,26 @@ struct rtw89_c2h_ra_rpt { #define RTW89_C2H_RA_RPT_W3_MD_SEL_B2 BIT(15) #define RTW89_C2H_RA_RPT_W3_BW_B2 BIT(16) +struct rtw89_c2h_lps_rpt { + struct rtw89_c2h_hdr hdr; + u8 type; + u8 cnt_bbcr; + u8 cnt_bbmcucr; + u8 cnt_rfcr; + u8 data[]; + /* + * The layout of data: + * u8 info[][4], size = total_len - size of below fields + * __le16 bbcr_addr[], size = cnt_bbcr + * __le32 bbcr_data[], size = cnt_bbcr + * __le16 bbmcucr_addr[], size = cnt_bbmcucr + * __le32 bbmcucr_data[], size = cnt_bbmcucr + * __le16 rfcr_addr[], size = cnt_rfcr + * __le32 rfcr_data_a[], size = cnt_rfcr + * __le32 rfcr_data_b[], size = cnt_rfcr + */ +} __packed; + struct rtw89_c2h_fw_scan_rpt { struct rtw89_c2h_hdr hdr; u8 phy_idx; @@ -3954,6 +4219,9 @@ enum rtw89_fw_element_id { RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_2GHZ = 24, RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ = 25, RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ = 26, + RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ = 27, + RTW89_FW_ELEMENT_ID_DIAG_MAC = 28, + RTW89_FW_ELEMENT_ID_TX_COMP = 29, RTW89_FW_ELEMENT_ID_NUM, }; @@ -4059,11 +4327,36 @@ struct rtw89_fw_txpwr_track_cfg { BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N) | \ BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P)) +enum rtw89_fw_afe_action { + RTW89_FW_AFE_ACTION_WRITE = 0, + RTW89_FW_AFE_ACTION_DELAY = 1, + RTW89_FW_AFE_ACTION_POLL = 2, +}; + +enum rtw89_fw_afe_cat { + RTW89_FW_AFE_CAT_BB = 0, + RTW89_FW_AFE_CAT_BB1 = 1, + RTW89_FW_AFE_CAT_MAC = 2, + RTW89_FW_AFE_CAT_MAC1 = 3, + RTW89_FW_AFE_CAT_AFEDIG = 4, + RTW89_FW_AFE_CAT_AFEDIG1 = 5, +}; + +enum rtw89_fw_afe_class { + RTW89_FW_AFE_CLASS_P0 = 0, + RTW89_FW_AFE_CLASS_P1 = 1, + RTW89_FW_AFE_CLASS_P2 = 2, + RTW89_FW_AFE_CLASS_P3 = 3, + RTW89_FW_AFE_CLASS_P4 = 4, + RTW89_FW_AFE_CLASS_CMN = 5, +}; + struct rtw89_fw_element_hdr { __le32 id; /* enum rtw89_fw_element_id */ __le32 size; /* exclude header size */ u8 ver[4]; - __le32 rsvd0; + __le16 aid; /* should match rtw89_hal::aid */ + __le16 rsvd0; __le32 rsvd1; __le32 rsvd2; union { @@ -4096,6 +4389,22 @@ struct rtw89_fw_element_hdr { u8 rsvd1[3]; __le16 offset[]; } __packed rfk_log_fmt; + struct { + u8 rsvd[8]; + struct rtw89_phy_afe_info { + __le32 action; /* enum rtw89_fw_afe_action */ + __le32 cat; /* enum rtw89_fw_afe_cat */ + __le32 class; /* enum rtw89_fw_afe_class */ + __le32 addr; + __le32 mask; + __le32 val; + } __packed infos[]; + } __packed afe; + struct { + __le32 rule_size; + u8 rsvd[4]; + u8 rules_and_msgs[]; + } __packed diag_mac; struct __rtw89_fw_txpwr_element txpwr; struct __rtw89_fw_regd_element regd; } __packed u; @@ -4177,6 +4486,7 @@ enum rtw89_wow_h2c_func { H2C_FUNC_WAKEUP_CTRL = 0x8, H2C_FUNC_WOW_CAM_UPD = 0xC, H2C_FUNC_AOAC_REPORT_REQ = 0xD, + H2C_FUNC_WOW_PLD_CAM_UPD = 0x12, NUM_OF_RTW89_WOW_H2C_FUNC, }; @@ -4193,6 +4503,8 @@ enum rtw89_ps_h2c_func { H2C_FUNC_MAC_LPS_PARM = 0x0, H2C_FUNC_P2P_ACT = 0x1, H2C_FUNC_IPS_CFG = 0x3, + H2C_FUNC_PS_POWER_LEVEL = 0x7, + H2C_FUNC_TBTT_TUNING = 0xA, NUM_OF_RTW89_PS_H2C_FUNC, }; @@ -4215,6 +4527,7 @@ enum rtw89_ps_h2c_func { #define H2C_FUNC_MAC_CCTLINFO_UD_V1 0xa #define H2C_FUNC_MAC_DCTLINFO_UD_V2 0xc #define H2C_FUNC_MAC_BCN_UPD_BE 0xd +#define H2C_FUNC_MAC_DCTLINFO_UD_V3 0x10 #define H2C_FUNC_MAC_CCTLINFO_UD_G7 0x11 /* CLASS 6 - Address CAM */ @@ -4343,6 +4656,7 @@ enum rtw89_mrc_h2c_func { #define H2C_FUNC_OUTSRC_RA_MACIDCFG 0x0 #define H2C_CL_OUTSRC_DM 0x2 +#define H2C_FUNC_FW_MCC_DIG 0x6 #define H2C_FUNC_FW_LPS_CH_INFO 0xb #define H2C_FUNC_FW_LPS_ML_CMN_INFO 0xe @@ -4350,6 +4664,7 @@ enum rtw89_mrc_h2c_func { #define H2C_CL_OUTSRC_RF_REG_B 0x9 #define H2C_CL_OUTSRC_RF_FW_NOTIFY 0xa #define H2C_FUNC_OUTSRC_RF_GET_MCCCH 0x2 +#define H2C_FUNC_OUTSRC_RF_MCC_INFO 0xf #define H2C_FUNC_OUTSRC_RF_PS_INFO 0x10 #define H2C_CL_OUTSRC_RF_FW_RFK 0xb @@ -4361,6 +4676,9 @@ enum rtw89_rfk_offload_h2c_func { H2C_FUNC_RFK_DACK_OFFLOAD = 0x5, H2C_FUNC_RFK_RXDCK_OFFLOAD = 0x6, H2C_FUNC_RFK_PRE_NOTIFY = 0x8, + H2C_FUNC_RFK_TAS_OFFLOAD = 0x9, + H2C_FUNC_RFK_TXIQK_OFFOAD = 0xc, + H2C_FUNC_RFK_CIM3K_OFFOAD = 0xe, }; struct rtw89_fw_h2c_rf_get_mccch { @@ -4380,6 +4698,27 @@ struct rtw89_fw_h2c_rf_get_mccch_v0 { __le32 current_band_type; } __packed; +struct rtw89_h2c_mcc_dig { + __le32 w0; + __le32 w1; + __le32 w2; +} __packed; + +#define RTW89_H2C_MCC_DIG_W0_REG_CNT GENMASK(7, 0) +#define RTW89_H2C_MCC_DIG_W0_DM_EN BIT(8) +#define RTW89_H2C_MCC_DIG_W0_IDX GENMASK(10, 9) +#define RTW89_H2C_MCC_DIG_W0_SET BIT(11) +#define RTW89_H2C_MCC_DIG_W0_PHY0_EN BIT(12) +#define RTW89_H2C_MCC_DIG_W0_PHY1_EN BIT(13) +#define RTW89_H2C_MCC_DIG_W0_CENTER_CH GENMASK(23, 16) +#define RTW89_H2C_MCC_DIG_W0_BAND_TYPE GENMASK(31, 24) +#define RTW89_H2C_MCC_DIG_W1_ADDR_LSB GENMASK(7, 0) +#define RTW89_H2C_MCC_DIG_W1_ADDR_MSB GENMASK(15, 8) +#define RTW89_H2C_MCC_DIG_W1_BMASK_LSB GENMASK(23, 16) +#define RTW89_H2C_MCC_DIG_W1_BMASK_MSB GENMASK(31, 24) +#define RTW89_H2C_MCC_DIG_W2_VAL_LSB GENMASK(7, 0) +#define RTW89_H2C_MCC_DIG_W2_VAL_MSB GENMASK(15, 8) + #define NUM_OF_RTW89_FW_RFK_PATH 2 #define NUM_OF_RTW89_FW_RFK_TBL 3 @@ -4431,11 +4770,38 @@ struct rtw89_fw_h2c_rfk_pre_info_v1 { __le32 mlo_1_1; } __packed; -struct rtw89_fw_h2c_rfk_pre_info { +struct rtw89_fw_h2c_rfk_pre_info_v2 { struct rtw89_fw_h2c_rfk_pre_info_v1 base_v1; __le32 cur_bandwidth[NUM_OF_RTW89_FW_RFK_PATH]; } __packed; +struct rtw89_fw_h2c_rfk_pre_info { + __le32 mlo_mode; + __le32 phy_idx; + __le32 mlo_1_1; +} __packed; + +struct rtw89_fw_h2c_rfk_pre_info_mcc_v0 { + __le32 tbl_18[NUM_OF_RTW89_FW_RFK_TBL][NUM_OF_RTW89_FW_RFK_PATH]; + __le32 cur_18[NUM_OF_RTW89_FW_RFK_PATH]; + __le32 mlo_mode; +} __packed; + +struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 { + __le32 tbl_18[NUM_OF_RTW89_FW_RFK_TBL]; + __le32 cur_18[NUM_OF_RTW89_FW_RFK_PATH]; + __le32 mlo_mode; + __le32 mlo_1_1; + u8 phy_idx; + u8 tbl_idx; +} __packed; + +struct rtw89_fw_h2c_rfk_pre_info_mcc { + struct rtw89_fw_h2c_rfk_pre_info_mcc_v1 base; + u8 rsvd[2]; + __le32 aid; +} __packed; + struct rtw89_h2c_rf_tssi { __le16 len; u8 phy; @@ -4505,9 +4871,9 @@ struct rtw89_h2c_rf_txgapk { } __packed; struct rtw89_h2c_rf_dack { - __le32 len; - __le32 phy; - __le32 type; + u8 len; + u8 phy; + u8 type; } __packed; struct rtw89_h2c_rf_rxdck_v0 { @@ -4521,11 +4887,39 @@ struct rtw89_h2c_rf_rxdck_v0 { u8 rxdck_dbg_en; } __packed; +struct rtw89_h2c_rf_tas { + __le32 enable; +} __packed; + struct rtw89_h2c_rf_rxdck { struct rtw89_h2c_rf_rxdck_v0 v0; u8 is_chl_k; } __packed; +struct rtw89_h2c_rf_txiqk { + u8 len; + u8 phy; + u8 txiqk_enable; + u8 is_wb_txiqk; + u8 kpath; + u8 cur_band; + u8 cur_bw; + u8 cur_ch; + u8 txiqk_dbg_en; +} __packed; + +struct rtw89_h2c_rf_cim3k { + u8 len; + u8 phy; + u8 su_cim3k_enable[2]; + u8 ru_cim3k_enable[2]; + u8 kpath; + u8 cur_band; + u8 cur_bw; + u8 cur_ch; + u8 cim3k_dbg_en; +} __packed; + enum rtw89_rf_log_type { RTW89_RF_RUN_LOG = 0, RTW89_RF_RPT_LOG = 1, @@ -4570,12 +4964,16 @@ struct rtw89_c2h_rf_iqk_rpt_log { u8 rsvd; __le32 reload_cnt; __le32 iqk_fail_cnt; + __le32 rf_0x18[2]; __le32 lok_idac[2]; __le32 lok_vbuf[2]; - __le32 rftxgain[2][4]; - __le32 rfrxgain[2][4]; - __le32 tx_xym[2][4]; - __le32 rx_xym[2][4]; + __le32 rftxgain[2][6]; + __le32 rfrxgain[2][6]; + __le32 tx_xym[2][6]; + __le32 rx_xym[2][6]; + __le32 rx_wb_xym[2][32]; + bool is_radar; + u8 rsvd1[3]; } __packed; struct rtw89_c2h_rf_dpk_rpt_log { @@ -4618,6 +5016,7 @@ struct rtw89_c2h_rf_dack_rpt_log { u8 dack_fail; u8 wbdck_d[2]; u8 rck_d; + u8 adgaink_ex_d; } __packed; struct rtw89_c2h_rf_rxdck_rpt_log { @@ -4644,7 +5043,57 @@ struct rtw89_c2h_rf_txgapk_rpt_log { u8 is_txgapk_ok; u8 chk_id; u8 ver; - u8 rsv1; + u8 d_bnd_ok; + __le32 stage[2]; + __le16 failcode[2]; + u8 rsvd[4]; +} __packed; + +struct rtw89_c2h_rf_txiqk_rpt_log { + u8 fw_txiqk_ver; + u8 iqk_band[2]; + u8 iqk_ch[2]; + u8 iqk_bw[2]; + bool tx_iqk_fail[2]; + bool is_iqk_init; + bool txiqk_en; + bool lok_en; + bool lok_fail[2]; + u8 rsvd[2]; + __le32 iqk_times; + bool txiqk_nctldone[2]; + u8 rsvd2[2]; + __le32 txgain[2][6]; + __le32 tx_iqc[2][6]; + __le32 tx_xym[2][6][14]; + __le32 kidx[2]; +} __packed; + +struct rtw89_c2h_rf_cim3k_rpt_log { + u8 cim3k_band[2]; + u8 cim3k_ch[2]; + u8 cim3k_bw[2]; + u8 su_path_ok[2]; + u8 ru_path_ok[2]; + u8 txagc_cim3k[2]; + u8 ther_cim3k[2]; + u8 cim3k_gs[2]; + __le16 cim3k_pwsf[2]; + bool cim3k_nctldone[2]; + u8 rsvd[2]; + __le32 cim3k_rxiqc[2]; + __le32 cim3k_su_coef[2][3]; + __le16 dc_i[2]; + __le16 dc_q[2]; + u8 corr_val[2]; + u8 corr_idx[2]; + u8 rxbb_ov[2]; + u8 cim3k_txiqc[2]; + u8 kidx[2]; + u8 fw_cim3k_ver; + bool su_cim3k_en[2]; + bool ru_cim3k_en[2]; + u8 rsvd1; } __packed; struct rtw89_c2h_rfk_report { @@ -4653,12 +5102,16 @@ struct rtw89_c2h_rfk_report { u8 version; } __packed; -struct rtw89_c2h_rf_tas_info { - struct rtw89_c2h_hdr hdr; +struct rtw89_c2h_rf_tas_rpt_log { __le32 cur_idx; __le16 txpwr_history[20]; } __packed; +struct rtw89_c2h_rf_tas_info { + struct rtw89_c2h_hdr hdr; + struct rtw89_c2h_rf_tas_rpt_log content; +} __packed; + #define RTW89_FW_RSVD_PLE_SIZE 0x800 #define RTW89_FW_BACKTRACE_INFO_SIZE 8 @@ -4669,6 +5122,7 @@ struct rtw89_c2h_rf_tas_info { #define RTW89_FW_BACKTRACE_KEY 0xBACEBACE #define FWDL_WAIT_CNT 400000 +#define FWDL_WAIT_CNT_USB 3200 int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type); int rtw89_fw_recognize(struct rtw89_dev *rtwdev); @@ -4694,38 +5148,67 @@ int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev, int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_default_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_default_dmac_tbl_v3(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_assoc_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_ampdu_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_txtime_cmac_tbl_g7(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_txtime_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_punctured_cmac_tbl_g7(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 punctured); +int rtw89_fw_h2c_punctured_cmac_tbl_be(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 punctured); int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); +int rtw89_fw_h2c_tbtt_tuning(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, u32 offset); +int rtw89_fw_h2c_pwr_lvl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link); int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif_link *vif, - struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr); + struct rtw89_sta_link *rtwsta_link, const u8 *scan_mac_addr, + enum rtw89_upd_mode upd_mode); int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link); +int rtw89_fw_h2c_dctl_sec_cam_v3(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_sta_link *rtwsta_link); void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h); void rtw89_fw_c2h_work(struct wiphy *wiphy, struct wiphy_work *work); +void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev); +void rtw89_fw_c2h_dummy_handler(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len); int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, struct rtw89_sta_link *rtwsta_link, @@ -4776,6 +5259,10 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev); int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +int rtw89_fw_h2c_rf_pre_ntfy_mcc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +int rtw89_fw_h2c_mcc_dig(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_idx chanctx_idx, + u8 mcc_role_idx, u8 pd_val, bool en); int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, enum rtw89_tssi_mode tssi_mode); int rtw89_fw_h2c_rf_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, @@ -4788,6 +5275,11 @@ int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan); int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, bool is_chl_k); +int rtw89_fw_h2c_rf_tas_trigger(struct rtw89_dev *rtwdev, bool enable); +int rtw89_fw_h2c_rf_txiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan); +int rtw89_fw_h2c_rf_cim3k(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan); int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func, u8 *buf, u16 len, bool rack, bool dack); @@ -4818,6 +5310,11 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev, int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif); +void rtw89_bb_lps_cmn_info_rx_gain_fill(struct rtw89_dev *rtwdev, + struct rtw89_bb_link_info_rx_gain *h2c_gain, + const struct rtw89_chan *chan, u8 phy_idx); +int rtw89_fw_h2c_lps_ml_cmn_info_v1(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif); int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len); @@ -4878,8 +5375,10 @@ int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtw bool enable); int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); -int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, - struct rtw89_wow_cam_info *cam_info); +int rtw89_fw_h2c_wow_cam_update(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info); +int rtw89_fw_h2c_wow_cam_update_v1(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info); int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool enable); @@ -5009,6 +5508,19 @@ int rtw89_chip_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev, return chip->ops->h2c_txtime_cmac_tbl(rtwdev, rtwsta_link); } +static inline +int rtw89_chip_h2c_punctured_cmac_tbl(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + u16 punctured) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (!chip->ops->h2c_punctured_cmac_tbl) + return 0; + + return chip->ops->h2c_punctured_cmac_tbl(rtwdev, rtwvif_link, punctured); +} + static inline int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, bool valid, struct ieee80211_ampdu_params *params) @@ -5030,6 +5542,15 @@ int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta, return 0; } +static inline +int rtw89_chip_h2c_wow_cam_update(struct rtw89_dev *rtwdev, + struct rtw89_wow_cam_info *cam_info) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + return chip->ops->h2c_wow_cam_update(rtwdev, cam_info); +} + /* Must consider compatibility; don't insert new in the mid. * Fill each field's default value in rtw89_regd_entcpy(). */ diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index eec4039740e5e..ffd9733f3a74a 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -9,8 +9,10 @@ #include "fw.h" #include "mac.h" #include "pci.h" +#include "phy.h" #include "ps.h" #include "reg.h" +#include "ser.h" #include "util.h" static const u32 rtw89_mac_mem_base_addrs_ax[RTW89_MAC_MEM_NUM] = { @@ -88,7 +90,7 @@ int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val) ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0, 50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3); - if (ret) + if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) rtw89_err(rtwdev, "[ERR]lte not ready(W)\n"); rtw89_write32(rtwdev, R_AX_LTE_WDATA, val); @@ -104,7 +106,7 @@ int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val) ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0, 50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3); - if (ret) + if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) rtw89_err(rtwdev, "[ERR]lte not ready(W)\n"); rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0x800F0000 | offset); @@ -177,7 +179,7 @@ int rtw89_mac_dle_dfi_qempty_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_qempty *qempty) { struct rtw89_mac_dle_dfi_ctrl ctrl; - u32 ret; + int ret; ctrl.type = qempty->dle_type; ctrl.target = DLE_DFI_TYPE_QEMPTY; @@ -846,6 +848,7 @@ EXPORT_SYMBOL(rtw89_mac_get_err_status); int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err) { struct rtw89_ser *ser = &rtwdev->ser; + bool ser_l1_hdl = false; u32 halt; int ret = 0; @@ -854,6 +857,12 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err) return -EINVAL; } + if (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN) + ser_l1_hdl = true; + + if (RTW89_CHK_FW_FEATURE(SER_L1_BY_EVENT, &rtwdev->fw) && ser_l1_hdl) + goto set; + ret = read_poll_timeout(rtw89_read32, halt, (halt == 0x0), 1000, 100000, false, rtwdev, R_AX_HALT_H2C_CTRL); if (ret) { @@ -861,10 +870,10 @@ int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err) return -EFAULT; } +set: rtw89_write32(rtwdev, R_AX_HALT_H2C, err); - if (ser->prehandle_l1 && - (err == MAC_AX_ERR_L1_DISABLE_EN || err == MAC_AX_ERR_L1_RCVY_EN)) + if (ser->prehandle_l1 && ser_l1_hdl) return 0; rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, B_AX_HALT_H2C_TRIGGER); @@ -875,31 +884,30 @@ EXPORT_SYMBOL(rtw89_mac_set_err_status); static int hfc_reset_param(struct rtw89_dev *rtwdev) { + const struct rtw89_hfc_param_ini *param_ini, *param_inis; struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; - struct rtw89_hfc_param_ini param_ini = {NULL}; u8 qta_mode = rtwdev->mac.dle_info.qta_mode; - switch (rtwdev->hci.type) { - case RTW89_HCI_TYPE_PCIE: - param_ini = rtwdev->chip->hfc_param_ini[qta_mode]; - param->en = 0; - break; - default: + param_inis = rtwdev->chip->hfc_param_ini[rtwdev->hci.type]; + if (!param_inis) return -EINVAL; - } - if (param_ini.pub_cfg) - param->pub_cfg = *param_ini.pub_cfg; + param_ini = ¶m_inis[qta_mode]; + + param->en = 0; - if (param_ini.prec_cfg) - param->prec_cfg = *param_ini.prec_cfg; + if (param_ini->pub_cfg) + param->pub_cfg = *param_ini->pub_cfg; - if (param_ini.ch_cfg) - param->ch_cfg = param_ini.ch_cfg; + if (param_ini->prec_cfg) + param->prec_cfg = *param_ini->prec_cfg; + + if (param_ini->ch_cfg) + param->ch_cfg = param_ini->ch_cfg; memset(¶m->ch_info, 0, sizeof(param->ch_info)); memset(¶m->pub_info, 0, sizeof(param->pub_info)); - param->mode = param_ini.mode; + param->mode = param_ini->mode; return 0; } @@ -986,7 +994,7 @@ static int hfc_upd_ch_info(struct rtw89_dev *rtwdev, u8 ch) struct rtw89_hfc_ch_info *info = param->ch_info; const struct rtw89_hfc_ch_cfg *cfg = param->ch_cfg; u32 val; - u32 ret; + int ret; ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL); if (ret) @@ -1177,8 +1185,8 @@ int rtw89_mac_hfc_init(struct rtw89_dev *rtwdev, bool reset, bool en, bool h2c_e const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_chip_info *chip = rtwdev->chip; u32 dma_ch_mask = chip->dma_ch_mask; + int ret = 0; u8 ch; - u32 ret = 0; if (reset) ret = hfc_reset_param(rtwdev); @@ -1194,7 +1202,7 @@ int rtw89_mac_hfc_init(struct rtw89_dev *rtwdev, bool reset, bool en, bool h2c_e if (!en && h2c_en) { mac->hfc_h2c_cfg(rtwdev); mac->hfc_func_en(rtwdev, en, h2c_en); - return ret; + return 0; } for (ch = RTW89_DMA_ACH0; ch < RTW89_DMA_H2C; ch++) { @@ -1423,13 +1431,15 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter) if (!ret) break; - if (i == RPWM_TRY_CNT - 1) + if (i == RPWM_TRY_CNT - 1) { rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n", enter ? "entering" : "leaving"); - else + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + } else { rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "%d time firmware failed to ack for %s ps mode\n", i + 1, enter ? "entering" : "leaving"); + } } } @@ -1458,15 +1468,37 @@ static void rtw89_mac_power_switch_boot_mode(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST); } +static int rtw89_mac_pwr_off_func_for_unplugged(struct rtw89_dev *rtwdev) +{ + /* + * Avoid accessing IO for unplugged power-off to prevent warnings, + * especially XTAL SI. + */ + return 0; +} + +static void rtw89_mac_update_scoreboard(struct rtw89_dev *rtwdev, u8 val) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 reg; + int i; + + for (i = 0; i < ARRAY_SIZE(chip->btc_sb.n); i++) { + reg = chip->btc_sb.n[i].cfg; + if (!reg) + continue; + + rtw89_write8(rtwdev, reg + 3, val); + } +} + static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) { -#define PWR_ACT 1 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_pwr_cfg * const *cfg_seq; int (*cfg_func)(struct rtw89_dev *rtwdev); int ret; - u8 val; rtw89_mac_power_switch_boot_mode(rtwdev); @@ -1474,17 +1506,22 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) cfg_seq = chip->pwr_on_seq; cfg_func = chip->ops->pwr_on_func; } else { - cfg_seq = chip->pwr_off_seq; - cfg_func = chip->ops->pwr_off_func; + if (test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) { + cfg_seq = NULL; + cfg_func = rtw89_mac_pwr_off_func_for_unplugged; + } else { + cfg_seq = chip->pwr_off_seq; + cfg_func = chip->ops->pwr_off_func; + } } if (test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)) __rtw89_leave_ps_mode(rtwdev); - val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK); - if (on && val == PWR_ACT) { - rtw89_err(rtwdev, "MAC has already powered on\n"); - return -EBUSY; + if (on) { + ret = mac->reset_pwr_state(rtwdev); + if (ret) + return ret; } ret = cfg_func ? cfg_func(rtwdev) : rtw89_mac_pwr_seq(rtwdev, cfg_seq); @@ -1492,26 +1529,32 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) return ret; if (on) { - if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags)) + if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags)) { + rtw89_mac_efuse_read_ecv(rtwdev); mac->efuse_read_fw_secure(rtwdev); + } set_bit(RTW89_FLAG_POWERON, rtwdev->flags); set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags); set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags); - rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_TP_MAJOR); + + rtw89_mac_update_scoreboard(rtwdev, MAC_AX_NOTIFY_TP_MAJOR); + rtw89_mac_clr_aon_intr(rtwdev); } else { clear_bit(RTW89_FLAG_POWERON, rtwdev->flags); clear_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags); clear_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags); clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags); + clear_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags); + clear_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags); clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags); - rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR); + + rtw89_mac_update_scoreboard(rtwdev, MAC_AX_NOTIFY_PWR_MAJOR); rtw89_set_entity_state(rtwdev, RTW89_PHY_0, false); rtw89_set_entity_state(rtwdev, RTW89_PHY_1, false); } return 0; -#undef PWR_ACT } int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev) @@ -1646,8 +1689,8 @@ static int sys_init_ax(struct rtw89_dev *rtwdev) const struct rtw89_mac_size_set rtw89_mac_size = { .hfc_preccfg_pcie = {2, 40, 0, 0, 1, 0, 0, 0}, - .hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0}, - .hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0}, + .hfc_prec_cfg_c0 = {2, 32, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0}, + .hfc_prec_cfg_c2 = {0, 256, 0, 0, 0, 0, 0, 0, 0, 256, 0, 0}, /* PCIE 64 */ .wde_size0 = {RTW89_WDE_PG_64, 4095, 1,}, .wde_size0_v1 = {RTW89_WDE_PG_64, 3328, 0, 0,}, @@ -1660,11 +1703,15 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .wde_size7 = {RTW89_WDE_PG_64, 510, 2,}, /* DLFW */ .wde_size9 = {RTW89_WDE_PG_64, 0, 1024,}, + .wde_size16_v1 = {RTW89_WDE_PG_64, 639, 1, 0,}, /* 8852C DLFW */ .wde_size18 = {RTW89_WDE_PG_64, 0, 2048,}, + .wde_size18_v1 = {RTW89_WDE_PG_64, 0, 640, 0,}, /* 8852C PCIE SCC */ .wde_size19 = {RTW89_WDE_PG_64, 3328, 0,}, .wde_size23 = {RTW89_WDE_PG_64, 1022, 2,}, + /* 8852B USB2.0/USB3.0 SCC */ + .wde_size25 = {RTW89_WDE_PG_64, 162, 94,}, /* PCIE */ .ple_size0 = {RTW89_PLE_PG_128, 1520, 16,}, .ple_size0_v1 = {RTW89_PLE_PG_128, 2688, 240, 212992,}, @@ -1680,6 +1727,12 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .ple_size18 = {RTW89_PLE_PG_128, 2544, 16,}, /* 8852C PCIE SCC */ .ple_size19 = {RTW89_PLE_PG_128, 1904, 16,}, + .ple_size20_v1 = {RTW89_PLE_PG_128, 2554, 182, 40960,}, + .ple_size22_v1 = {RTW89_PLE_PG_128, 2736, 0, 40960,}, + /* 8852B USB2.0 SCC */ + .ple_size32 = {RTW89_PLE_PG_128, 620, 20,}, + /* 8852B USB3.0 SCC */ + .ple_size33 = {RTW89_PLE_PG_128, 632, 8,}, /* PCIE 64 */ .wde_qt0 = {3792, 196, 0, 107,}, .wde_qt0_v1 = {3302, 6, 0, 20,}, @@ -1693,13 +1746,17 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .wde_qt17 = {0, 0, 0, 0,}, /* 8852C PCIE SCC */ .wde_qt18 = {3228, 60, 0, 40,}, + .wde_qt19_v1 = {613, 6, 0, 20,}, .wde_qt23 = {958, 48, 0, 16,}, + /* 8852B USB2.0/USB3.0 SCC */ + .wde_qt25 = {152, 2, 0, 8,}, .ple_qt0 = {320, 320, 32, 16, 13, 13, 292, 292, 64, 18, 1, 4, 0,}, .ple_qt1 = {320, 320, 32, 16, 1316, 1316, 1595, 1595, 1367, 1321, 1, 1307, 0,}, /* PCIE SCC */ .ple_qt4 = {264, 0, 16, 20, 26, 13, 356, 0, 32, 40, 8,}, /* PCIE SCC */ .ple_qt5 = {264, 0, 32, 20, 64, 13, 1101, 0, 64, 128, 120,}, + .ple_qt5_v2 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,}, .ple_qt9 = {0, 0, 32, 256, 0, 0, 0, 0, 0, 0, 1, 0, 0,}, /* DLFW */ .ple_qt13 = {0, 0, 16, 48, 0, 0, 0, 0, 0, 0, 0,}, @@ -1717,6 +1774,13 @@ const struct rtw89_mac_size_set rtw89_mac_size = { /* PCIE 64 */ .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,}, .ple_qt59 = {147, 0, 32, 20, 1860, 13, 2025, 0, 1879, 14, 24, 0,}, + /* USB2.0 52B SCC */ + .ple_qt72 = {130, 0, 16, 48, 4, 13, 322, 0, 32, 14, 8, 0, 0,}, + /* USB2.0 52B 92K */ + .ple_qt73 = {130, 0, 32, 48, 37, 13, 355, 0, 65, 14, 24, 0, 0,}, + /* USB3.0 52B 92K */ + .ple_qt74 = {286, 0, 16, 48, 4, 13, 178, 0, 32, 14, 8, 0, 0,}, + .ple_qt75 = {286, 0, 32, 48, 37, 13, 211, 0, 65, 14, 24, 0, 0,}, /* 8852A PCIE WOW */ .ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,}, /* 8852B PCIE WOW */ @@ -1727,8 +1791,13 @@ const struct rtw89_mac_size_set rtw89_mac_size = { .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,}, .ple_rsvd_qt0 = {2, 107, 107, 6, 6, 6, 6, 0, 0, 0,}, .ple_rsvd_qt1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + .ple_rsvd_qt9 = {1, 44, 44, 6, 6, 6, 6, 69, 0, 0,}, .rsvd0_size0 = {212992, 0,}, + .rsvd0_size6 = {40960, 0,}, .rsvd1_size0 = {587776, 2048,}, + .rsvd1_size2 = {391168, 2048,}, + .dle_input3 = {0, 0, 0, 16384, 0, 2048, 0, 0,}, + .dle_input18 = {128, 128, 11454, 2048, 0, 2048, 24, 24,}, }; EXPORT_SYMBOL(rtw89_mac_size); @@ -1736,18 +1805,20 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode) { struct rtw89_mac_info *mac = &rtwdev->mac; - const struct rtw89_dle_mem *cfg; + const struct rtw89_dle_mem *cfg, *cfgs; - cfg = &rtwdev->chip->dle_mem[mode]; - if (!cfg) + cfgs = rtwdev->chip->dle_mem[rtwdev->hci.dle_type]; + if (!cfgs) return NULL; + cfg = &cfgs[mode]; if (cfg->mode != mode) { rtw89_warn(rtwdev, "qta mode unmatch!\n"); return NULL; } mac->dle_info.rsvd_qt = cfg->rsvd_qt; + mac->dle_info.dle_input = cfg->dle_input; mac->dle_info.ple_pg_size = cfg->ple_size->pge_size; mac->dle_info.ple_free_pg = cfg->ple_size->lnk_pge_num; mac->dle_info.qta_mode = mode; @@ -2168,8 +2239,8 @@ int rtw89_mac_dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode, return ret; } -static int preload_init_set(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx, - enum rtw89_qta_mode mode) +static int preload_init_set_ax(struct rtw89_dev *rtwdev, u8 mac_idx, + enum rtw89_qta_mode mode) { u32 reg, max_preld_size, min_rsvd_size; @@ -2197,13 +2268,14 @@ static bool is_qta_poh(struct rtw89_dev *rtwdev) int rtw89_mac_preload_init(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx, enum rtw89_qta_mode mode) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_chip_info *chip = rtwdev->chip; if (chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev) || !is_qta_poh(rtwdev)) return 0; - return preload_init_set(rtwdev, mac_idx, mode); + return mac->preload_init(rtwdev, mac_idx, mode); } static bool dle_is_txq_empty(struct rtw89_dev *rtwdev) @@ -2398,7 +2470,7 @@ static int addr_cam_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx) static int scheduler_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx) { - u32 ret; + int ret; u32 reg; u32 val; @@ -2479,6 +2551,20 @@ static int rtw89_mac_typ_fltr_opt_ax(struct rtw89_dev *rtwdev, return 0; } +void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + u32 reg; + u32 val; + + reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, mac_idx); + + val = rtw89_read32(rtwdev, reg); + /* B_AX_RX_FLTR_CFG_MASK is not a consecutive bit mask */ + val = (val & ~B_AX_RX_FLTR_CFG_MASK) | (rx_fltr & B_AX_RX_FLTR_CFG_MASK); + rtw89_write32(rtwdev, reg, val); +} + static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx) { int ret, i; @@ -2939,7 +3025,7 @@ static int rtw89_mac_read_phycap(struct rtw89_dev *rtwdev, struct rtw89_mac_h2c_info h2c_info = {}; enum rtw89_mac_c2h_type c2h_type; u8 content_len; - u32 ret; + int ret; if (chip->chip_gen == RTW89_CHIP_AX) content_len = 0; @@ -2983,6 +3069,7 @@ static int rtw89_mac_setup_phycap_part0(struct rtw89_dev *rtwdev) struct rtw89_efuse *efuse = &rtwdev->efuse; struct rtw89_mac_c2h_info c2h_info = {}; struct rtw89_hal *hal = &rtwdev->hal; + u8 protocol; u8 tx_nss; u8 rx_nss; u8 tx_ant; @@ -3030,6 +3117,10 @@ static int rtw89_mac_setup_phycap_part0(struct rtw89_dev *rtwdev) rtw89_debug(rtwdev, RTW89_DBG_FW, "TX path diversity=%d\n", hal->tx_path_diversity); rtw89_debug(rtwdev, RTW89_DBG_FW, "Antenna diversity=%d\n", hal->ant_diversity); + protocol = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_PROT); + if (protocol < RTW89_C2HREG_PHYCAP_W1_PROT_11BE) + hal->no_eht = true; + return 0; } @@ -3090,10 +3181,10 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band, u16 tx_en_u16, u16 mask_u16) { - u32 ret; struct rtw89_mac_c2h_info c2h_info = {0}; struct rtw89_mac_h2c_info h2c_info = {0}; struct rtw89_h2creg_sch_tx_en *sch_tx_en = &h2c_info.u.sch_tx_en; + int ret; h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN; h2c_info.content_len = sizeof(*sch_tx_en) - RTW89_H2CREG_HDR_LEN; @@ -3853,6 +3944,29 @@ static int rtw89_mac_feat_init(struct rtw89_dev *rtwdev) return 0; } +static int rtw89_mac_reset_pwr_state_ax(struct rtw89_dev *rtwdev) +{ + u8 val; + + val = rtw89_read32_mask(rtwdev, R_AX_IC_PWR_STATE, B_AX_WLMAC_PWR_STE_MASK); + if (val == MAC_AX_MAC_ON) { + /* + * A USB adapter might play as USB mass storage with driver and + * then switch to WiFi adapter, causing it stays on power-on + * state when doing WiFi USB probe. Return EAGAIN to caller to + * power-off and power-on again to reset the state. + */ + if (rtwdev->hci.type == RTW89_HCI_TYPE_USB && + !test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags)) + return -EAGAIN; + + rtw89_err(rtwdev, "MAC has already powered on\n"); + return -EBUSY; + } + + return 0; +} + static void rtw89_disable_fw_watchdog(struct rtw89_dev *rtwdev) { u32 val32; @@ -4033,9 +4147,12 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb) rtw89_mac_ctrl_hci_dma_trx(rtwdev, true); if (include_bb) { - rtw89_chip_bb_preinit(rtwdev, RTW89_PHY_0); - if (rtwdev->dbcc_en) - rtw89_chip_bb_preinit(rtwdev, RTW89_PHY_1); + /* Only call BB preinit including configuration of BB MCU for + * the chips which need to download BB MCU firmware. Otherwise, + * calling preinit later to prevent touching registers affecting + * download firmware. + */ + rtw89_chip_bb_preinit(rtwdev); } ret = rtw89_mac_dmac_pre_init(rtwdev); @@ -4055,17 +4172,31 @@ int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb) return 0; } -int rtw89_mac_init(struct rtw89_dev *rtwdev) +int rtw89_mac_preinit(struct rtw89_dev *rtwdev) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; - const struct rtw89_chip_info *chip = rtwdev->chip; - bool include_bb = !!chip->bbmcu_nr; int ret; ret = rtw89_mac_pwr_on(rtwdev); if (ret) return ret; + if (mac->mac_func_en) { + ret = mac->mac_func_en(rtwdev); + if (ret) + return ret; + } + + return 0; +} + +int rtw89_mac_init(struct rtw89_dev *rtwdev) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool include_bb = !!chip->bbmcu_nr; + int ret; + ret = rtw89_mac_partial_init(rtwdev, include_bb); if (ret) goto fail; @@ -4182,11 +4313,18 @@ static const struct rtw89_port_reg rtw89_port_base_ax = { .ptcl_dbg = R_AX_PTCL_DBG, .ptcl_dbg_info = R_AX_PTCL_DBG_INFO, .bcn_drop_all = R_AX_BCN_DROP_ALL0, + .bcn_psr_rpt = R_AX_BCN_PSR_RPT_P0, .hiq_win = {R_AX_P0MB_HGQ_WINDOW_CFG_0, R_AX_PORT_HGQ_WINDOW_CFG, R_AX_PORT_HGQ_WINDOW_CFG + 1, R_AX_PORT_HGQ_WINDOW_CFG + 2, R_AX_PORT_HGQ_WINDOW_CFG + 3}, }; +static const struct rtw89_mac_mu_gid_addr rtw89_mac_mu_gid_addr_ax = { + .position_en = {R_AX_GID_POSITION_EN0, R_AX_GID_POSITION_EN1}, + .position = {R_AX_GID_POSITION0, R_AX_GID_POSITION1, + R_AX_GID_POSITION2, R_AX_GID_POSITION3}, +}; + static void rtw89_mac_check_packet_ctrl(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, u8 type) { @@ -4245,6 +4383,7 @@ static void rtw89_mac_bcn_drop(struct rtw89_dev *rtwdev, #define BCN_HOLD_DEF 200 #define BCN_MASK_DEF 0 #define TBTT_ERLY_DEF 5 +#define TBTT_AGG_DEF 1 #define BCN_SET_UNIT 32 #define BCN_ERLY_SET_DLY (10 * 2) @@ -4548,6 +4687,16 @@ static void rtw89_mac_port_cfg_tbtt_early(struct rtw89_dev *rtwdev, B_AX_TBTTERLY_MASK, TBTT_ERLY_DEF); } +static void rtw89_mac_port_cfg_tbtt_agg(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_port_reg *p = mac->port_base; + + rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_agg, + B_AX_TBTT_AGG_NUM_MASK, TBTT_AGG_DEF); +} + static void rtw89_mac_port_cfg_bss_color(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { @@ -4634,25 +4783,28 @@ static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev, BCN_ERLY_DEF); } -static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) +static void rtw89_mac_port_cfg_bcn_psr_rpt(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; const struct rtw89_port_reg *p = mac->port_base; - u16 val; + struct ieee80211_bss_conf *bss_conf; + u8 bssid_index; + u32 reg; - if (rtwdev->chip->chip_id != RTL8852C) - return; + rcu_read_lock(); - if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT && - rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION) - return; + bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); + if (bss_conf->nontransmitted) + bssid_index = bss_conf->bssid_index; + else + bssid_index = 0; - val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) | - B_AX_TBTT_SHIFT_OFST_SIGN; + rcu_read_unlock(); - rtw89_write16_port_mask(rtwdev, rtwvif_link, p->tbtt_shift, - B_AX_TBTT_SHIFT_OFST_MASK, val); + reg = rtw89_mac_reg_by_idx(rtwdev, p->bcn_psr_rpt + rtwvif_link->port * 4, + rtwvif_link->mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_BCAID_P0_MASK, bssid_index); } void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, @@ -4750,7 +4902,7 @@ int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l if (ret) return ret; - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_CREATE); if (ret) return ret; @@ -4775,7 +4927,7 @@ int rtw89_mac_vif_deinit(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif rtw89_cam_deinit(rtwdev, rtwvif_link); - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_REMOVE); if (ret) return ret; @@ -4805,13 +4957,14 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvi rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif_link); rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif_link); rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif_link); - rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_tbtt_agg(rtwdev, rtwvif_link); rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif_link); rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif_link); rtw89_mac_port_cfg_func_en(rtwdev, rtwvif_link, true); rtw89_mac_port_tsf_resync_all(rtwdev); fsleep(BCN_ERLY_SET_DLY); rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif_link); + rtw89_mac_port_cfg_bcn_psr_rpt(rtwdev, rtwvif_link); return 0; } @@ -5026,6 +5179,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (op_chan) { rtw89_mac_enable_aps_bcn_by_chan(rtwdev, op_chan, false); ieee80211_stop_queues(rtwdev->hw); + } else { + rtw89_phy_nhm_get_result(rtwdev, band, chan); } return; case RTW89_SCAN_END_SCAN_NOTIFY: @@ -5034,6 +5189,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, if (rtwvif_link && rtwvif->scan_req && !list_empty(&rtwdev->scan_info.chan_list)) { + rtwdev->scan_info.delay = 0; ret = rtw89_hw_scan_offload(rtwdev, rtwvif_link, true); if (ret) { rtw89_hw_scan_abort(rtwdev, rtwvif_link); @@ -5055,6 +5211,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb, RTW89_CHANNEL_WIDTH_20); rtw89_assign_entity_chan(rtwdev, rtwvif_link->chanctx_idx, &new); + rtw89_phy_nhm_trigger(rtwdev); } break; default: @@ -5072,6 +5229,7 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l const struct rtw89_c2h_mac_bcnfltr_rpt *c2h = (const struct rtw89_c2h_mac_bcnfltr_rpt *)skb->data; u8 type, event, mac_id; + bool start_detect; s8 sig; type = le32_get_bits(c2h->w2, RTW89_C2H_MAC_BCNFLTR_RPT_W2_TYPE); @@ -5089,10 +5247,15 @@ rtw89_mac_bcn_fltr_rpt(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l switch (type) { case RTW89_BCN_FLTR_BEACON_LOSS: if (!rtwdev->scanning && !rtwvif->offchan && - !rtwvif_link->noa_once.in_duration) - ieee80211_connection_loss(vif); - else - rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); + !rtwvif_link->noa_once.in_duration) { + start_detect = rtw89_mcc_detect_go_bcn(rtwdev, rtwvif_link); + if (start_detect) + return; + + ieee80211_beacon_loss(vif); + } + + rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true); return; case RTW89_BCN_FLTR_NOTIFY: nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; @@ -5143,6 +5306,7 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le { /* N.B. This will run in interrupt context. */ struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; struct rtw89_wait_info *ps_wait = &rtwdev->mac.ps_wait; const struct rtw89_c2h_done_ack *c2h = (const struct rtw89_c2h_done_ack *)skb_c2h->data; @@ -5185,9 +5349,11 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN; break; case H2C_FUNC_SCANOFLD: + scan_info->seq++; cond = RTW89_SCANOFLD_WAIT_COND_START; break; case H2C_FUNC_SCANOFLD_BE: + scan_info->seq++; cond = RTW89_SCANOFLD_BE_WAIT_COND_START; h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN; break; @@ -5210,6 +5376,22 @@ rtw89_mac_c2h_bcn_cnt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { } +static void +rtw89_mac_c2h_bcn_upd_done(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len) +{ + const struct rtw89_c2h_bcn_upd_done *c2h = + (const struct rtw89_c2h_bcn_upd_done *)skb_c2h->data; + u8 band, port, mbssid; + + port = le32_get_bits(c2h->w2, RTW89_C2H_BCN_UPD_DONE_W2_PORT); + mbssid = le32_get_bits(c2h->w2, RTW89_C2H_BCN_UPD_DONE_W2_MBSSID); + band = le32_get_bits(c2h->w2, RTW89_C2H_BCN_UPD_DONE_W2_BAND_IDX); + + rtw89_debug(rtwdev, RTW89_DBG_FW, + "BCN update done on port:%d mbssid:%d band:%d\n", + port, mbssid, band); +} + static void rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len) @@ -5232,6 +5414,11 @@ rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, rtw89_complete_cond(wait, cond, &data); } +static void +rtw89_mac_c2h_bcn_resend(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ +} + static void rtw89_mac_c2h_tx_duty_rpt(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 len) { @@ -5621,7 +5808,7 @@ void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev, [RTW89_MAC_C2H_FUNC_EFUSE_DUMP] = NULL, [RTW89_MAC_C2H_FUNC_READ_RSP] = NULL, [RTW89_MAC_C2H_FUNC_PKT_OFLD_RSP] = rtw89_mac_c2h_pkt_ofld_rsp, - [RTW89_MAC_C2H_FUNC_BCN_RESEND] = NULL, + [RTW89_MAC_C2H_FUNC_BCN_RESEND] = rtw89_mac_c2h_bcn_resend, [RTW89_MAC_C2H_FUNC_MACID_PAUSE] = rtw89_mac_c2h_macid_pause, [RTW89_MAC_C2H_FUNC_SCANOFLD_RSP] = rtw89_mac_c2h_scanofld_rsp, [RTW89_MAC_C2H_FUNC_TX_DUTY_RPT] = rtw89_mac_c2h_tx_duty_rpt, @@ -5636,6 +5823,7 @@ void (* const rtw89_mac_c2h_info_handler[])(struct rtw89_dev *rtwdev, [RTW89_MAC_C2H_FUNC_DONE_ACK] = rtw89_mac_c2h_done_ack, [RTW89_MAC_C2H_FUNC_C2H_LOG] = rtw89_mac_c2h_log, [RTW89_MAC_C2H_FUNC_BCN_CNT] = rtw89_mac_c2h_bcn_cnt, + [RTW89_MAC_C2H_FUNC_BCN_UPD_DONE] = rtw89_mac_c2h_bcn_upd_done, }; static @@ -5684,10 +5872,15 @@ static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev, const struct rtw89_c2h_scanofld *c2h = (const struct rtw89_c2h_scanofld *)skb->data; struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait; + struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info; + struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb); struct rtw89_completion_data data = {}; unsigned int cond; u8 status, reason; + attr->is_scan_event = 1; + attr->scan_seq = scan_info->seq; + status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS); reason = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_RSN); data.err = status != RTW89_SCAN_STATUS_SUCCESS; @@ -5783,12 +5976,11 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, case RTW89_MAC_C2H_CLASS_ROLE: return; default: - rtw89_info(rtwdev, "MAC c2h class %d not support\n", class); - return; + break; } if (!handler) { - rtw89_info(rtwdev, "MAC c2h class %d func %d not support\n", class, - func); + rtw89_info_once(rtwdev, "MAC c2h class %d func %d not support\n", + class, func); return; } handler(rtwdev, skb, len); @@ -5843,7 +6035,7 @@ int rtw89_mac_cfg_ppdu_status_ax(struct rtw89_dev *rtwdev, u8 mac_idx, bool enab rtw89_write32(rtwdev, reg, B_AX_PPDU_STAT_RPT_EN | B_AX_APP_MAC_INFO_RPT | - B_AX_APP_RX_CNT_RPT | B_AX_APP_PLCP_HDR_RPT | + B_AX_APP_PLCP_HDR_RPT | B_AX_PPDU_STAT_RPT_CRC32); rtw89_write32_mask(rtwdev, R_AX_HW_RPT_FWD, B_AX_FWD_PPDU_STAT_MASK, RTW89_PRPT_DEST_HOST); @@ -5926,13 +6118,15 @@ int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex ret = rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_2, &val32); if (ret) { - rtw89_err(rtwdev, "Read R_AX_LTE_SW_CFG_2 fail!\n"); + if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) + rtw89_err(rtwdev, "Read R_AX_LTE_SW_CFG_2 fail!\n"); return ret; } val32 = val32 & B_AX_WL_RX_CTRL; ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_2, val32); if (ret) { - rtw89_err(rtwdev, "Write R_AX_LTE_SW_CFG_2 fail!\n"); + if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) + rtw89_err(rtwdev, "Write R_AX_LTE_SW_CFG_2 fail!\n"); return ret; } @@ -6056,7 +6250,8 @@ int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev, ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_1, val); if (ret) { - rtw89_err(rtwdev, "Write LTE fail!\n"); + if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) + rtw89_err(rtwdev, "Write LTE fail!\n"); return ret; } @@ -6139,9 +6334,11 @@ int rtw89_mac_cfg_plt_ax(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt) void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val) { + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 reg = chip->btc_sb.n[0].cfg; u32 fw_sb; - fw_sb = rtw89_read32(rtwdev, R_AX_SCOREBOARD); + fw_sb = rtw89_read32(rtwdev, reg); fw_sb = FIELD_GET(B_MAC_AX_SB_FW_MASK, fw_sb); fw_sb = fw_sb & ~B_MAC_AX_BTGS1_NOTIFY; if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) @@ -6152,13 +6349,16 @@ void rtw89_mac_cfg_sb(struct rtw89_dev *rtwdev, u32 val) val = B_AX_TOGGLE | FIELD_PREP(B_MAC_AX_SB_DRV_MASK, val) | FIELD_PREP(B_MAC_AX_SB_FW_MASK, fw_sb); - rtw89_write32(rtwdev, R_AX_SCOREBOARD, val); + rtw89_write32(rtwdev, reg, val); fsleep(1000); /* avoid BT FW loss information */ } u32 rtw89_mac_get_sb(struct rtw89_dev *rtwdev) { - return rtw89_read32(rtwdev, R_AX_SCOREBOARD); + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 reg = chip->btc_sb.n[0].get; + + return rtw89_read32(rtwdev, reg); } int rtw89_mac_cfg_ctrl_path(struct rtw89_dev *rtwdev, bool wl) @@ -6452,6 +6652,8 @@ void rtw89_mac_bf_disassoc(struct rtw89_dev *rtwdev, void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf) { + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + const struct rtw89_mac_mu_gid_addr *addr = mac->mu_gid; struct rtw89_vif *rtwvif = vif_to_rtwvif(vif); struct rtw89_vif_link *rtwvif_link; u8 mac_idx; @@ -6471,20 +6673,20 @@ void rtw89_mac_bf_set_gid_table(struct rtw89_dev *rtwdev, struct ieee80211_vif * p = (__le32 *)conf->mu_group.membership; rtw89_write32(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN0, mac_idx), + rtw89_mac_reg_by_idx(rtwdev, addr->position_en[0], mac_idx), le32_to_cpu(p[0])); rtw89_write32(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION_EN1, mac_idx), + rtw89_mac_reg_by_idx(rtwdev, addr->position_en[1], mac_idx), le32_to_cpu(p[1])); p = (__le32 *)conf->mu_group.position; - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION0, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[0], mac_idx), le32_to_cpu(p[0])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION1, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[1], mac_idx), le32_to_cpu(p[1])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION2, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[2], mac_idx), le32_to_cpu(p[2])); - rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, R_AX_GID_POSITION3, mac_idx), + rtw89_write32(rtwdev, rtw89_mac_reg_by_idx(rtwdev, addr->position[3], mac_idx), le32_to_cpu(p[3])); } @@ -6696,7 +6898,7 @@ int rtw89_mac_set_hw_muedca_ctrl(struct rtw89_dev *rtwdev, u8 mac_idx = rtwvif_link->mac_idx; u16 set = mac->muedca_ctrl.mask; u32 reg; - u32 ret; + int ret; ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); if (ret) @@ -6732,6 +6934,12 @@ int rtw89_mac_write_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 m return ret; } + if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags) && + (u32_get_bits(val32, B_AX_WL_XTAL_SI_ADDR_MASK) != offset || + u32_get_bits(val32, B_AX_WL_XTAL_SI_DATA_MASK) != val)) + rtw89_warn(rtwdev, "xtal si write: offset=%x val=%x poll=%x\n", + offset, val, val32); + return 0; } @@ -6755,7 +6963,12 @@ int rtw89_mac_read_xtal_si_ax(struct rtw89_dev *rtwdev, u8 offset, u8 *val) return ret; } - *val = rtw89_read8(rtwdev, R_AX_WLAN_XTAL_SI_CTRL + 1); + if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags) && + u32_get_bits(val32, B_AX_WL_XTAL_SI_ADDR_MASK) != offset) + rtw89_warn(rtwdev, "xtal si read: offset=%x poll=%x\n", + offset, val32); + + *val = u32_get_bits(val32, B_AX_WL_XTAL_SI_DATA_MASK); return 0; } @@ -6838,7 +7051,7 @@ int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable) { struct rtw89_mac_h2c_info h2c_info = {}; struct rtw89_mac_c2h_info c2h_info = {}; - u32 ret; + int ret; if (RTW89_CHK_FW_FEATURE(NO_WOW_CPU_IO_RX, &rtwdev->fw)) return 0; @@ -6916,10 +7129,16 @@ int rtw89_fwdl_check_path_ready_ax(struct rtw89_dev *rtwdev, bool h2c_or_fwdl) { u8 check = h2c_or_fwdl ? B_AX_H2C_PATH_RDY : B_AX_FWDL_PATH_RDY; + u32 timeout; u8 val; + if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + timeout = FWDL_WAIT_CNT_USB; + else + timeout = FWDL_WAIT_CNT; + return read_poll_timeout_atomic(rtw89_read8, val, val & check, - 1, FWDL_WAIT_CNT, false, + 1, timeout, false, rtwdev, R_AX_WCPU_FW_CTRL); } @@ -6947,6 +7166,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .port_base = &rtw89_port_base_ax, .agg_len_ht = R_AX_AGG_LEN_HT_0, .ps_status = R_AX_PPWRBIT_SETTING, + .mu_gid = &rtw89_mac_mu_gid_addr_ax, .muedca_ctrl = { .addr = R_AX_MUEDCA_EN, @@ -6968,6 +7188,10 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .check_mac_en = rtw89_mac_check_mac_en_ax, .sys_init = sys_init_ax, .trx_init = trx_init_ax, + .preload_init = preload_init_set_ax, + .clr_aon_intr = NULL, + .err_imr_ctrl = err_imr_ctrl_ax, + .mac_func_en = NULL, .hci_func_en = rtw89_mac_hci_func_en_ax, .dmac_func_pre_en = rtw89_mac_dmac_func_pre_en_ax, .dle_func_en = dle_func_en_ax, @@ -6977,6 +7201,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .typ_fltr_opt = rtw89_mac_typ_fltr_opt_ax, .cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_ax, .cfg_phy_rpt = NULL, + .set_edcca_mode = NULL, .dle_mix_cfg = dle_mix_cfg_ax, .chk_dle_rdy = chk_dle_rdy_ax, @@ -6990,6 +7215,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .set_cpuio = set_cpuio_ax, .dle_quota_change = dle_quota_change_ax, + .reset_pwr_state = rtw89_mac_reset_pwr_state_ax, .disable_cpu = rtw89_mac_disable_cpu_ax, .fwdl_enable_wcpu = rtw89_mac_enable_cpu_ax, .fwdl_get_status = rtw89_fw_get_rdy_ax, @@ -6999,6 +7225,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = { .parse_phycap_map = rtw89_parse_phycap_map_ax, .cnv_efuse_state = rtw89_cnv_efuse_state_ax, .efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax, + .efuse_read_ecv = NULL, .cfg_plt = rtw89_mac_cfg_plt_ax, .get_plt_cnt = rtw89_mac_get_plt_cnt_ax, diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index b7fd4a0fdb84a..0f6e168cfcda2 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -6,6 +6,7 @@ #define __RTW89_MAC_H__ #include "core.h" +#include "fw.h" #include "reg.h" #define MAC_MEM_DUMP_PAGE_SIZE_AX 0x40000 @@ -418,6 +419,7 @@ enum rtw89_mac_c2h_info_func { RTW89_MAC_C2H_FUNC_DONE_ACK, RTW89_MAC_C2H_FUNC_C2H_LOG, RTW89_MAC_C2H_FUNC_BCN_CNT, + RTW89_MAC_C2H_FUNC_BCN_UPD_DONE = 0x06, RTW89_MAC_C2H_FUNC_INFO_MAX, }; @@ -572,8 +574,6 @@ enum rtw89_mac_bf_rrsc_rate { RTW89_MAC_BF_RRSC_MAX = 32 }; -#define RTW89_R32_EA 0xEAEAEAEA -#define RTW89_R32_DEAD 0xDEADBEEF #define MAC_REG_POOL_COUNT 10 #define ACCESS_CMAC(_addr) \ ({typeof(_addr) __addr = (_addr); \ @@ -907,6 +907,9 @@ enum mac_ax_err_info { MAC_AX_ERR_L0_CFG_DIS_NOTIFY = 0x0011, MAC_AX_ERR_L0_CFG_HANDSHAKE = 0x0012, MAC_AX_ERR_L0_RCVY_EN = 0x0013, + MAC_AX_ERR_L0_RESET_FORCE = 0x0020, + MAC_AX_ERR_L0_RESET_FORCE_C1 = 0x0021, + MAC_AX_ERR_L1_RESET_FORCE = 0x0022, MAC_AX_SET_ERR_MAX, }; @@ -921,9 +924,12 @@ struct rtw89_mac_size_set { const struct rtw89_dle_size wde_size6; const struct rtw89_dle_size wde_size7; const struct rtw89_dle_size wde_size9; + const struct rtw89_dle_size wde_size16_v1; const struct rtw89_dle_size wde_size18; + const struct rtw89_dle_size wde_size18_v1; const struct rtw89_dle_size wde_size19; const struct rtw89_dle_size wde_size23; + const struct rtw89_dle_size wde_size25; const struct rtw89_dle_size ple_size0; const struct rtw89_dle_size ple_size0_v1; const struct rtw89_dle_size ple_size3_v1; @@ -933,6 +939,10 @@ struct rtw89_mac_size_set { const struct rtw89_dle_size ple_size9; const struct rtw89_dle_size ple_size18; const struct rtw89_dle_size ple_size19; + const struct rtw89_dle_size ple_size20_v1; + const struct rtw89_dle_size ple_size22_v1; + const struct rtw89_dle_size ple_size32; + const struct rtw89_dle_size ple_size33; const struct rtw89_wde_quota wde_qt0; const struct rtw89_wde_quota wde_qt0_v1; const struct rtw89_wde_quota wde_qt4; @@ -940,11 +950,14 @@ struct rtw89_mac_size_set { const struct rtw89_wde_quota wde_qt7; const struct rtw89_wde_quota wde_qt17; const struct rtw89_wde_quota wde_qt18; + const struct rtw89_wde_quota wde_qt19_v1; const struct rtw89_wde_quota wde_qt23; + const struct rtw89_wde_quota wde_qt25; const struct rtw89_ple_quota ple_qt0; const struct rtw89_ple_quota ple_qt1; const struct rtw89_ple_quota ple_qt4; const struct rtw89_ple_quota ple_qt5; + const struct rtw89_ple_quota ple_qt5_v2; const struct rtw89_ple_quota ple_qt9; const struct rtw89_ple_quota ple_qt13; const struct rtw89_ple_quota ple_qt18; @@ -955,18 +968,33 @@ struct rtw89_mac_size_set { const struct rtw89_ple_quota ple_qt57; const struct rtw89_ple_quota ple_qt58; const struct rtw89_ple_quota ple_qt59; + const struct rtw89_ple_quota ple_qt72; + const struct rtw89_ple_quota ple_qt73; + const struct rtw89_ple_quota ple_qt74; + const struct rtw89_ple_quota ple_qt75; const struct rtw89_ple_quota ple_qt_52a_wow; const struct rtw89_ple_quota ple_qt_52b_wow; const struct rtw89_ple_quota ple_qt_52bt_wow; const struct rtw89_ple_quota ple_qt_51b_wow; const struct rtw89_rsvd_quota ple_rsvd_qt0; const struct rtw89_rsvd_quota ple_rsvd_qt1; + const struct rtw89_rsvd_quota ple_rsvd_qt1_v1; + const struct rtw89_rsvd_quota ple_rsvd_qt9; const struct rtw89_dle_rsvd_size rsvd0_size0; + const struct rtw89_dle_rsvd_size rsvd0_size6; const struct rtw89_dle_rsvd_size rsvd1_size0; + const struct rtw89_dle_rsvd_size rsvd1_size2; + const struct rtw89_dle_input dle_input3; + const struct rtw89_dle_input dle_input18; }; extern const struct rtw89_mac_size_set rtw89_mac_size; +struct rtw89_mac_mu_gid_addr { + u32 position_en[2]; + u32 position[4]; +}; + struct rtw89_mac_gen_def { u32 band1_offset; u32 filter_model_addr; @@ -977,6 +1005,7 @@ struct rtw89_mac_gen_def { const struct rtw89_port_reg *port_base; u32 agg_len_ht; u32 ps_status; + const struct rtw89_mac_mu_gid_addr *mu_gid; struct rtw89_reg_def muedca_ctrl; struct rtw89_reg_def bfee_ctrl; @@ -989,6 +1018,11 @@ struct rtw89_mac_gen_def { enum rtw89_mac_hwmod_sel sel); int (*sys_init)(struct rtw89_dev *rtwdev); int (*trx_init)(struct rtw89_dev *rtwdev); + int (*preload_init)(struct rtw89_dev *rtwdev, u8 mac_idx, + enum rtw89_qta_mode mode); + void (*clr_aon_intr)(struct rtw89_dev *rtwdev); + void (*err_imr_ctrl)(struct rtw89_dev *rtwdev, bool en); + int (*mac_func_en)(struct rtw89_dev *rtwdev); void (*hci_func_en)(struct rtw89_dev *rtwdev); void (*dmac_func_pre_en)(struct rtw89_dev *rtwdev); void (*dle_func_en)(struct rtw89_dev *rtwdev, bool enable); @@ -1003,6 +1037,7 @@ struct rtw89_mac_gen_def { u8 mac_idx); int (*cfg_ppdu_status)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable); void (*cfg_phy_rpt)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable); + void (*set_edcca_mode)(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal); int (*dle_mix_cfg)(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg); int (*chk_dle_rdy)(struct rtw89_dev *rtwdev, bool wde_or_ple); @@ -1022,6 +1057,7 @@ struct rtw89_mac_gen_def { struct rtw89_cpuio_ctrl *ctrl_para, bool wd); int (*dle_quota_change)(struct rtw89_dev *rtwdev, bool band1_en); + int (*reset_pwr_state)(struct rtw89_dev *rtwdev); void (*disable_cpu)(struct rtw89_dev *rtwdev); int (*fwdl_enable_wcpu)(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw, bool include_bb); @@ -1032,6 +1068,7 @@ struct rtw89_mac_gen_def { int (*parse_phycap_map)(struct rtw89_dev *rtwdev); int (*cnv_efuse_state)(struct rtw89_dev *rtwdev, bool idle); int (*efuse_read_fw_secure)(struct rtw89_dev *rtwdev); + int (*efuse_read_ecv)(struct rtw89_dev *rtwdev); int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt); u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band); @@ -1075,6 +1112,22 @@ u32 rtw89_mac_reg_by_idx(struct rtw89_dev *rtwdev, u32 reg_base, u8 band) return band == 0 ? reg_base : (reg_base + mac->band1_offset); } +static inline void +rtw89_write16_idx(struct rtw89_dev *rtwdev, u32 addr, u16 data, u8 band) +{ + addr = rtw89_mac_reg_by_idx(rtwdev, addr, band); + + rtw89_write16(rtwdev, addr, data); +} + +static inline void +rtw89_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data, u8 band) +{ + addr = rtw89_mac_reg_by_idx(rtwdev, addr, band); + + rtw89_write32_mask(rtwdev, addr, mask, data); +} + static inline u32 rtw89_mac_reg_by_port(struct rtw89_dev *rtwdev, u32 base, u8 port, u8 mac_idx) { @@ -1171,6 +1224,7 @@ rtw89_write32_port_set(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_l int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev); void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev); int rtw89_mac_partial_init(struct rtw89_dev *rtwdev, bool include_bb); +int rtw89_mac_preinit(struct rtw89_dev *rtwdev); int rtw89_mac_init(struct rtw89_dev *rtwdev); int rtw89_mac_dle_init(struct rtw89_dev *rtwdev, enum rtw89_qta_mode mode, enum rtw89_qta_mode ext_mode); @@ -1187,6 +1241,14 @@ int rtw89_mac_check_mac_en(struct rtw89_dev *rtwdev, u8 band, return mac->check_mac_en(rtwdev, band, sel); } +static inline void rtw89_mac_clr_aon_intr(struct rtw89_dev *rtwdev) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (mac->clr_aon_intr) + mac->clr_aon_intr(rtwdev); +} + int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val); int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val); int rtw89_mac_dle_dfi_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_dfi_ctrl *ctrl); @@ -1309,6 +1371,25 @@ int rtw89_mac_cfg_ppdu_status_bands(struct rtw89_dev *rtwdev, bool enable) return rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_1, enable); } +static inline +void rtw89_mac_set_edcca_mode(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (!mac->set_edcca_mode) + return; + + mac->set_edcca_mode(rtwdev, mac_idx, normal); +} + +static inline +void rtw89_mac_set_edcca_mode_bands(struct rtw89_dev *rtwdev, bool normal) +{ + rtw89_mac_set_edcca_mode(rtwdev, RTW89_MAC_0, normal); + rtw89_mac_set_edcca_mode(rtwdev, RTW89_MAC_1, normal); +} + +void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr); void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev); void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop); int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex *coex); @@ -1320,6 +1401,8 @@ int rtw89_mac_cfg_gnt_v1(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex_gnt *gnt_cfg); int rtw89_mac_cfg_gnt_v2(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex_gnt *gnt_cfg); +int rtw89_mac_cfg_gnt_v3(struct rtw89_dev *rtwdev, + const struct rtw89_mac_ax_coex_gnt *gnt_cfg); static inline int rtw89_mac_cfg_plt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt) @@ -1535,6 +1618,8 @@ enum rtw89_mac_xtal_si_offset { XTAL_SI_APBT = 0xD1, XTAL_SI_PLL = 0xE0, XTAL_SI_PLL_1 = 0xE1, + XTAL_SI_CHIP_ID_L = 0xFD, + XTAL_SI_CHIP_ID_H = 0xFE, }; static inline @@ -1565,6 +1650,16 @@ int rtw89_mac_get_dle_rsvd_qt_cfg(struct rtw89_dev *rtwdev, struct rtw89_mac_dle_rsvd_qt_cfg *cfg); int rtw89_mac_cpu_io_rx(struct rtw89_dev *rtwdev, bool wow_enable); +static inline int rtw89_mac_efuse_read_ecv(struct rtw89_dev *rtwdev) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + if (!mac->efuse_read_ecv) + return -ENOENT; + + return mac->efuse_read_ecv(rtwdev); +} + static inline void rtw89_fwdl_secure_idmem_share_mode(struct rtw89_dev *rtwdev, u8 mode) { @@ -1573,6 +1668,42 @@ void rtw89_fwdl_secure_idmem_share_mode(struct rtw89_dev *rtwdev, u8 mode) if (!mac->fwdl_secure_idmem_share_mode) return; - return mac->fwdl_secure_idmem_share_mode(rtwdev, mode); + mac->fwdl_secure_idmem_share_mode(rtwdev, mode); +} + +static inline +int rtw89_mac_scan_offload(struct rtw89_dev *rtwdev, + struct rtw89_scan_option *option, + struct rtw89_vif_link *rtwvif_link, + bool wowlan) +{ + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + int ret; + + ret = mac->scan_offload(rtwdev, option, rtwvif_link, wowlan); + + if (option->enable) { + /* + * At this point, new scan request is acknowledged by firmware, + * so scan events of previous scan request become obsoleted. + * Purge the queued scan events to prevent interference to + * current new request. + */ + rtw89_fw_c2h_purge_obsoleted_scan_events(rtwdev); + } + + return ret; } + +static inline bool rtw89_mac_chk_preload_allow(struct rtw89_dev *rtwdev) +{ + if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE) + return false; + + if (rtwdev->chip->chip_id == RTL8922D && rtwdev->hal.cid == RTL8922D_CID7090) + return true; + + return false; +} + #endif diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 526933899f16a..fe9cf52fb0c25 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -113,6 +113,8 @@ static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev, wiphy_work_init(&rtwvif_link->update_beacon_work, rtw89_core_update_beacon_work); wiphy_delayed_work_init(&rtwvif_link->csa_beacon_work, rtw89_core_csa_beacon_work); + wiphy_delayed_work_init(&rtwvif_link->mcc_gc_detect_beacon_work, + rtw89_mcc_gc_detect_beacon_work); INIT_LIST_HEAD(&rtwvif_link->general_pkt_list); @@ -124,6 +126,8 @@ static int __rtw89_ops_add_iface_link(struct rtw89_dev *rtwdev, rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; rtwvif_link->rand_tsf_done = false; + rtwvif_link->detect_bcn_count = 0; + rtwvif_link->last_sync_bcn_tsf = 0; rcu_read_lock(); @@ -147,6 +151,8 @@ static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev, wiphy_work_cancel(rtwdev->hw->wiphy, &rtwvif_link->update_beacon_work); wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwvif_link->csa_beacon_work); + wiphy_delayed_work_cancel(rtwdev->hw->wiphy, + &rtwvif_link->mcc_gc_detect_beacon_work); rtw89_p2p_noa_once_deinit(rtwvif_link); @@ -215,6 +221,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, if (ret) goto unset_link; + rtwdev->pure_monitor_mode_vif = vif->type == NL80211_IFTYPE_MONITOR ? + rtwvif : NULL; rtw89_recalc_lps(rtwdev); return 0; @@ -262,6 +270,8 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, rtw89_core_release_bit_map(rtwdev->hw_port, port); rtw89_release_mac_id(rtwdev, macid); + rtwdev->pure_monitor_mode_vif = NULL; + rtw89_recalc_lps(rtwdev); rtw89_enter_ips_by_hwflags(rtwdev); } @@ -298,7 +308,6 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, u64 multicast) { struct rtw89_dev *rtwdev = hw->priv; - const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; u32 rx_fltr; lockdep_assert_wiphy(hw->wiphy); @@ -360,16 +369,10 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw, rx_fltr &= ~B_AX_A_A1_MATCH; } - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_0), - B_AX_RX_FLTR_CFG_MASK, - rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, RTW89_MAC_0, rx_fltr); if (!rtwdev->dbcc_en) return; - rtw89_write32_mask(rtwdev, - rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, RTW89_MAC_1), - B_AX_RX_FLTR_CFG_MASK, - rx_fltr); + rtw89_mac_set_rx_fltr(rtwdev, RTW89_MAC_1, rx_fltr); } static const u8 ac_to_fw_idx[IEEE80211_NUM_ACS] = { @@ -713,6 +716,18 @@ static void rtw89_ops_vif_cfg_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ARP_FILTER) rtwvif->ip_addr = vif->cfg.arp_addr_list[0]; + + if (changed & BSS_CHANGED_MLD_VALID_LINKS) { + struct rtw89_vif_link *cur = rtw89_get_designated_link(rtwvif); + + if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) + rtw89_chip_rfk_channel(rtwdev, cur); + + if (hweight16(vif->active_links) == 1) + rtwvif->mlo_mode = RTW89_MLO_MODE_MLSR; + else + rtwvif->mlo_mode = RTW89_MLO_MODE_EMLSR; + } } static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, @@ -739,7 +754,7 @@ static void rtw89_ops_link_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) { ether_addr_copy(rtwvif_link->bssid, conf->bssid); rtw89_cam_bssid_changed(rtwdev, rtwvif_link); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_INFO_CHANGE); WRITE_ONCE(rtwvif_link->sync_bcn_tsf, 0); } @@ -790,7 +805,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL); rtw89_fw_h2c_role_maintain(rtwdev, rtwvif_link, NULL, RTW89_ROLE_TYPE_CHANGE); rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true); - rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL); + rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL, RTW89_ROLE_TYPE_CHANGE); /* must do rtw89_reg_6ghz_recalc() before rfk channel */ rtw89_reg_6ghz_recalc(rtwdev, rtwvif_link, true); rtw89_chip_rfk_channel(rtwdev, rtwvif_link); @@ -944,6 +959,7 @@ static int rtw89_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } break; case DISABLE_KEY: + flush_work(&rtwdev->txq_work); rtw89_hci_flush_queues(rtwdev, BIT(rtwdev->hw->queues) - 1, false); rtw89_mac_flush_txq(rtwdev, BIT(rtwdev->hw->queues) - 1, false); @@ -1121,12 +1137,17 @@ int rtw89_ops_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { struct rtw89_dev *rtwdev = hw->priv; struct rtw89_hal *hal = &rtwdev->hal; + const struct rtw89_chip_info *chip; lockdep_assert_wiphy(hw->wiphy); + chip = rtwdev->chip; + if (hal->ant_diversity) { if (tx_ant != rx_ant || hweight32(tx_ant) != 1) return -EINVAL; + } else if (chip->ops->cfg_txrx_path) { + /* With cfg_txrx_path ops, chips can configure rx_ant */ } else if (rx_ant != hw->wiphy->available_antennas_rx && rx_ant != hal->antenna_rx) { return -EINVAL; } @@ -1411,9 +1432,9 @@ static void rtw89_ops_channel_switch_beacon(struct ieee80211_hw *hw, BUILD_BUG_ON(RTW89_MLD_NON_STA_LINK_NUM != 1); - rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); + rtwvif_link = rtw89_get_designated_link(rtwvif); if (unlikely(!rtwvif_link)) { - rtw89_err(rtwdev, "chsw bcn: find no link on HW-0\n"); + rtw89_err(rtwdev, "chsw bcn: find no designated link\n"); return; } @@ -1557,6 +1578,33 @@ static int __rtw89_ops_set_vif_links(struct rtw89_dev *rtwdev, return 0; } +static void rtw89_vif_update_fw_links(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + u16 current_links, bool en) +{ + struct rtw89_vif_ml_trans *trans = &rtwvif->ml_trans; + struct rtw89_vif_link *rtwvif_link; + unsigned int link_id; + unsigned long links; + + /* Do follow-up when all updating links exist. */ + if (current_links != trans->mediate_links) + return; + + if (en) + links = trans->links_to_add; + else + links = trans->links_to_del; + + for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { + rtwvif_link = rtwvif->links[link_id]; + if (unlikely(!rtwvif_link)) + continue; + + rtw89_fw_h2c_mlo_link_cfg(rtwdev, rtwvif_link, en); + } +} + static int rtw89_ops_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1598,6 +1646,8 @@ int rtw89_ops_change_vif_links(struct ieee80211_hw *hw, if (rtwdev->scanning) rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); + rtw89_vif_update_fw_links(rtwdev, rtwvif, old_links, true); + if (!old_links) __rtw89_ops_clr_vif_links(rtwdev, rtwvif, BIT(RTW89_VIF_IDLE_LINK_ID)); @@ -1629,6 +1679,9 @@ int rtw89_ops_change_vif_links(struct ieee80211_hw *hw, BIT(RTW89_VIF_IDLE_LINK_ID)); } + if (!ret) + rtw89_vif_update_fw_links(rtwdev, rtwvif, new_links, false); + rtw89_enter_ips_by_hwflags(rtwdev); return ret; } @@ -1755,6 +1808,7 @@ static int rtw89_ops_suspend(struct ieee80211_hw *hw, set_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags); wiphy_delayed_work_cancel(hw->wiphy, &rtwdev->track_work); + wiphy_delayed_work_cancel(hw->wiphy, &rtwdev->track_ps_work); ret = rtw89_wow_suspend(rtwdev, wowlan); if (ret) { @@ -1780,6 +1834,8 @@ static int rtw89_ops_resume(struct ieee80211_hw *hw) clear_bit(RTW89_FLAG_FORBIDDEN_TRACK_WORK, rtwdev->flags); wiphy_delayed_work_queue(hw->wiphy, &rtwdev->track_work, RTW89_TRACK_WORK_PERIOD); + wiphy_delayed_work_queue(hw->wiphy, &rtwdev->track_ps_work, + RTW89_TRACK_PS_WORK_PERIOD); return ret ? 1 : 0; } @@ -1812,6 +1868,40 @@ static void rtw89_set_rekey_data(struct ieee80211_hw *hw, } #endif +static int rtw89_ops_get_survey(struct ieee80211_hw *hw, int idx, + struct survey_info *survey) +{ + struct ieee80211_conf *conf = &hw->conf; + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_bb_ctx *bb; + + if (idx == 0) { + survey->channel = conf->chandef.chan; + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = RTW89_NOISE_DEFAULT; + + return 0; + } + + rtw89_for_each_active_bb(rtwdev, bb) { + struct rtw89_env_monitor_info *env = &bb->env_monitor; + struct rtw89_nhm_report *rpt; + + rpt = list_first_entry_or_null(&env->nhm_rpt_list, typeof(*rpt), list); + if (!rpt) + continue; + + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = rpt->noise - MAX_RSSI; + survey->channel = rpt->channel; + list_del_init(&rpt->list); + + return 0; + } + + return -EINVAL; +} + void rtw89_ops_rfkill_poll(struct ieee80211_hw *hw) { struct rtw89_dev *rtwdev = hw->priv; @@ -1843,6 +1933,7 @@ const struct ieee80211_ops rtw89_ops = { .sta_state = rtw89_ops_sta_state, .set_key = rtw89_ops_set_key, .ampdu_action = rtw89_ops_ampdu_action, + .get_survey = rtw89_ops_get_survey, .set_rts_threshold = rtw89_ops_set_rts_threshold, .sta_statistics = rtw89_ops_sta_statistics, .flush = rtw89_ops_flush, diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c index 8087606e521ad..4821f9df15771 100644 --- a/drivers/net/wireless/realtek/rtw89/mac_be.c +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c @@ -56,11 +56,18 @@ static const struct rtw89_port_reg rtw89_port_base_be = { .ptcl_dbg = R_BE_PTCL_DBG, .ptcl_dbg_info = R_BE_PTCL_DBG_INFO, .bcn_drop_all = R_BE_BCN_DROP_ALL0, + .bcn_psr_rpt = R_BE_BCN_PSR_RPT_P0, .hiq_win = {R_BE_P0MB_HGQ_WINDOW_CFG_0, R_BE_PORT_HGQ_WINDOW_CFG, R_BE_PORT_HGQ_WINDOW_CFG + 1, R_BE_PORT_HGQ_WINDOW_CFG + 2, R_BE_PORT_HGQ_WINDOW_CFG + 3}, }; +static const struct rtw89_mac_mu_gid_addr rtw89_mac_mu_gid_addr_be = { + .position_en = {R_BE_GID_POSITION_EN0, R_BE_GID_POSITION_EN1}, + .position = {R_BE_GID_POSITION0, R_BE_GID_POSITION1, + R_BE_GID_POSITION2, R_BE_GID_POSITION3}, +}; + static int rtw89_mac_check_mac_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, enum rtw89_mac_hwmod_sel sel) { @@ -88,6 +95,7 @@ static void hfc_get_mix_info_be(struct rtw89_dev *rtwdev) struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg; struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; struct rtw89_hfc_pub_info *info = ¶m->pub_info; + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val; val = rtw89_read32(rtwdev, R_BE_PUB_PAGE_INFO1); @@ -115,14 +123,23 @@ static void hfc_get_mix_info_be(struct rtw89_dev *rtwdev) val = rtw89_read32(rtwdev, R_BE_CH_PAGE_CTRL); prec_cfg->ch011_prec = u32_get_bits(val, B_BE_PREC_PAGE_CH011_V1_MASK); + if (chip->chip_id == RTL8922D) + prec_cfg->ch011_full_page = u32_get_bits(val, B_BE_FULL_WD_PG_MASK); prec_cfg->h2c_prec = u32_get_bits(val, B_BE_PREC_PAGE_CH12_V1_MASK); val = rtw89_read32(rtwdev, R_BE_PUB_PAGE_CTRL2); pub_cfg->pub_max = u32_get_bits(val, B_BE_PUBPG_ALL_MASK); val = rtw89_read32(rtwdev, R_BE_WP_PAGE_CTRL1); - prec_cfg->wp_ch07_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH07_MASK); - prec_cfg->wp_ch811_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH811_MASK); + if (chip->chip_id == RTL8922D) { + prec_cfg->wp_ch07_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH07_V1_MASK); + prec_cfg->wp_ch07_full_page = u32_get_bits(val, B_BE_FULL_PAGE_WP_CH07_MASK); + prec_cfg->wp_ch811_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH811_V1_MASK); + prec_cfg->wp_ch811_full_page = u32_get_bits(val, B_BE_FULL_PAGE_WP_CH811_MASK); + } else { + prec_cfg->wp_ch07_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH07_MASK); + prec_cfg->wp_ch811_prec = u32_get_bits(val, B_BE_PREC_PAGE_WP_CH811_MASK); + } val = rtw89_read32(rtwdev, R_BE_WP_PAGE_CTRL2); pub_cfg->wp_thrd = u32_get_bits(val, B_BE_WP_THRD_MASK); @@ -147,17 +164,26 @@ static void hfc_mix_cfg_be(struct rtw89_dev *rtwdev) struct rtw89_hfc_param *param = &rtwdev->mac.hfc_param; const struct rtw89_hfc_prec_cfg *prec_cfg = ¶m->prec_cfg; const struct rtw89_hfc_pub_cfg *pub_cfg = ¶m->pub_cfg; + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val; val = u32_encode_bits(prec_cfg->ch011_prec, B_BE_PREC_PAGE_CH011_V1_MASK) | u32_encode_bits(prec_cfg->h2c_prec, B_BE_PREC_PAGE_CH12_V1_MASK); + if (chip->chip_id == RTL8922D) + val = u32_replace_bits(val, prec_cfg->ch011_full_page, B_BE_FULL_WD_PG_MASK); rtw89_write32(rtwdev, R_BE_CH_PAGE_CTRL, val); val = u32_encode_bits(pub_cfg->pub_max, B_BE_PUBPG_ALL_MASK); rtw89_write32(rtwdev, R_BE_PUB_PAGE_CTRL2, val); - val = u32_encode_bits(prec_cfg->wp_ch07_prec, B_BE_PREC_PAGE_WP_CH07_MASK) | - u32_encode_bits(prec_cfg->wp_ch811_prec, B_BE_PREC_PAGE_WP_CH811_MASK); + if (chip->chip_id == RTL8922D) + val = u32_encode_bits(prec_cfg->wp_ch07_prec, B_BE_PREC_PAGE_WP_CH07_V1_MASK) | + u32_encode_bits(prec_cfg->wp_ch07_full_page, B_BE_FULL_PAGE_WP_CH07_MASK) | + u32_encode_bits(prec_cfg->wp_ch811_prec, B_BE_PREC_PAGE_WP_CH811_V1_MASK) | + u32_encode_bits(prec_cfg->wp_ch811_full_page, B_BE_FULL_PAGE_WP_CH811_MASK); + else + val = u32_encode_bits(prec_cfg->wp_ch07_prec, B_BE_PREC_PAGE_WP_CH07_MASK) | + u32_encode_bits(prec_cfg->wp_ch811_prec, B_BE_PREC_PAGE_WP_CH811_MASK); rtw89_write32(rtwdev, R_BE_WP_PAGE_CTRL1, val); val = u32_replace_bits(rtw89_read32(rtwdev, R_BE_HCI_FC_CTRL), @@ -199,6 +225,9 @@ static void dle_func_en_be(struct rtw89_dev *rtwdev, bool enable) static void dle_clk_en_be(struct rtw89_dev *rtwdev, bool enable) { + if (rtwdev->chip->chip_id != RTL8922A) + return; + if (enable) rtw89_write32_set(rtwdev, R_BE_DMAC_CLK_EN, B_BE_DLE_WDE_CLK_EN | B_BE_DLE_PLE_CLK_EN); @@ -330,6 +359,11 @@ static void ple_quota_cfg_be(struct rtw89_dev *rtwdev, SET_QUOTA(cpu_io, PLE, 10); SET_QUOTA(tx_rpt, PLE, 11); SET_QUOTA(h2d, PLE, 12); + + if (rtwdev->chip->chip_id == RTL8922A) + return; + + SET_QUOTA(snrpt, PLE, 13); } static void rtw89_mac_hci_func_en_be(struct rtw89_dev *rtwdev) @@ -340,6 +374,8 @@ static void rtw89_mac_hci_func_en_be(struct rtw89_dev *rtwdev) static void rtw89_mac_dmac_func_pre_en_be(struct rtw89_dev *rtwdev) { + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 mask; u32 val; val = rtw89_read32(rtwdev, R_BE_HAXI_INIT_CFG1); @@ -363,12 +399,12 @@ static void rtw89_mac_dmac_func_pre_en_be(struct rtw89_dev *rtwdev) rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val); - rtw89_write32_clr(rtwdev, R_BE_HAXI_DMA_STOP1, - B_BE_STOP_CH0 | B_BE_STOP_CH1 | B_BE_STOP_CH2 | - B_BE_STOP_CH3 | B_BE_STOP_CH4 | B_BE_STOP_CH5 | - B_BE_STOP_CH6 | B_BE_STOP_CH7 | B_BE_STOP_CH8 | - B_BE_STOP_CH9 | B_BE_STOP_CH10 | B_BE_STOP_CH11 | - B_BE_STOP_CH12 | B_BE_STOP_CH13 | B_BE_STOP_CH14); + if (chip->chip_id == RTL8922A) + mask = B_BE_TX_STOP1_MASK; + else + mask = B_BE_TX_STOP1_MASK_V1; + + rtw89_write32_clr(rtwdev, R_BE_HAXI_DMA_STOP1, mask); rtw89_write32_set(rtwdev, R_BE_DMAC_TABLE_CTRL, B_BE_DMAC_ADDR_MODE); } @@ -395,6 +431,11 @@ int rtw89_mac_write_xtal_si_be(struct rtw89_dev *rtwdev, u8 offset, u8 val, u8 m return ret; } + if (u32_get_bits(val32, B_BE_WL_XTAL_SI_ADDR_MASK) != offset || + u32_get_bits(val32, B_BE_WL_XTAL_SI_DATA_MASK) != val) + rtw89_warn(rtwdev, "xtal si write: offset=%x val=%x poll=%x\n", + offset, val, val32); + return 0; } @@ -419,7 +460,140 @@ int rtw89_mac_read_xtal_si_be(struct rtw89_dev *rtwdev, u8 offset, u8 *val) return ret; } - *val = rtw89_read8(rtwdev, R_BE_WLAN_XTAL_SI_CTRL + 1); + if (u32_get_bits(val32, B_BE_WL_XTAL_SI_ADDR_MASK) != offset) + rtw89_warn(rtwdev, "xtal si read: offset=%x poll=%x\n", + offset, val32); + + *val = u32_get_bits(val32, B_BE_WL_XTAL_SI_DATA_MASK); + + return 0; +} + +static int rtw89_mac_reset_pwr_state_be(struct rtw89_dev *rtwdev) +{ + u32 val32; + int ret; + + val32 = rtw89_read32(rtwdev, R_BE_SYSON_FSM_MON); + val32 &= WLAN_FSM_MASK; + val32 |= WLAN_FSM_SET; + rtw89_write32(rtwdev, R_BE_SYSON_FSM_MON, val32); + + ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == WLAN_FSM_IDLE, + 1000, 2000000, false, + rtwdev, R_BE_SYSON_FSM_MON, WLAN_FSM_STATE_MASK); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling WLAN PMC timeout= %X\n", val32); + return ret; + } + + val32 = rtw89_read32_mask(rtwdev, R_BE_IC_PWR_STATE, B_BE_WLMAC_PWR_STE_MASK); + if (val32 == MAC_AX_MAC_OFF) { + rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN); + + ret = read_poll_timeout(rtw89_read32_mask, val32, !val32, + 1000, 2000000, false, + rtwdev, R_BE_HCI_OPT_CTRL, + B_BE_HAXIDMA_IO_ST | B_BE_HAXIDMA_BACKUP_RESTORE_ST); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling HAXI IO timeout= %X\n", val32); + return ret; + } + + rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN); + + ret = read_poll_timeout(rtw89_read32_mask, val32, !val32, + 1000, 2000000, false, + rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_ST); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling WLAN IO timeout= %X\n", val32); + return ret; + } + + rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON); + rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS); + } else if (val32 == MAC_AX_MAC_ON) { + rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN); + + ret = read_poll_timeout(rtw89_read32_mask, val32, !val32, + 1000, 2000000, false, + rtwdev, R_BE_HCI_OPT_CTRL, + B_BE_HAXIDMA_IO_ST | B_BE_HAXIDMA_BACKUP_RESTORE_ST); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling HAXI IO timeout= %X\n", val32); + return ret; + } + + rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN); + + ret = read_poll_timeout(rtw89_read32_mask, val32, !val32, + 1000, 2000000, false, + rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_ST); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling WLAN IO timeout= %X\n", val32); + return ret; + } + + rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON); + rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC); + + ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == MAC_AX_MAC_OFF, + 1000, 2000000, false, + rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling MAC state timeout= %X\n", val32); + return ret; + } + + rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON); + rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS); + } else if (val32 == MAC_AX_MAC_LPS) { + rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN); + + ret = read_poll_timeout(rtw89_read32_mask, val32, !val32, + 1000, 2000000, false, + rtwdev, R_BE_HCI_OPT_CTRL, + B_BE_HAXIDMA_IO_ST | B_BE_HAXIDMA_BACKUP_RESTORE_ST); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling HAXI IO timeout= %X\n", val32); + return ret; + } + + rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN); + + ret = read_poll_timeout(rtw89_read32_mask, val32, !val32, + 1000, 2000000, false, + rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_ST); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling WLAN IO timeout= %X\n", val32); + return ret; + } + + rtw89_write32_set(rtwdev, R_BE_WLLPS_CTRL, B_BE_FORCE_LEAVE_LPS); + + ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == MAC_AX_MAC_ON, + 1000, 2000000, false, + rtwdev, R_BE_IC_PWR_STATE, B_BE_WLMAC_PWR_STE_MASK); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling MAC STS timeout= %X\n", val32); + return ret; + } + + rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON); + rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC); + + ret = read_poll_timeout(rtw89_read32_mask, val32, val32 == MAC_AX_MAC_OFF, + 1000, 2000000, false, + rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC); + if (ret) { + rtw89_err(rtwdev, "[ERR]Polling MAC state timeout= %X\n", val32); + return ret; + } + + rtw89_write32_clr(rtwdev, R_BE_WLLPS_CTRL, B_BE_FORCE_LEAVE_LPS); + rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON); + rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS); + } return 0; } @@ -438,7 +612,8 @@ static void rtw89_mac_disable_cpu_be(struct rtw89_dev *rtwdev) val32 &= B_BE_RUN_ENV_MASK; rtw89_write32(rtwdev, R_BE_WCPU_FW_CTRL, val32); - rtw89_write32_set(rtwdev, R_BE_DCPU_PLATFORM_ENABLE, B_BE_DCPU_PLATFORM_EN); + if (rtwdev->chip->chip_id == RTL8922A) + rtw89_write32_set(rtwdev, R_BE_DCPU_PLATFORM_ENABLE, B_BE_DCPU_PLATFORM_EN); rtw89_write32(rtwdev, R_BE_UDM0, 0); rtw89_write32(rtwdev, R_BE_HALT_C2H, 0); @@ -457,6 +632,7 @@ static void set_cpu_en(struct rtw89_dev *rtwdev, bool include_bb) static int wcpu_on(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val32; int ret; @@ -478,6 +654,7 @@ static int wcpu_on(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) rtw89_write32(rtwdev, R_BE_UDM1, 0); rtw89_write32(rtwdev, R_BE_UDM2, 0); + rtw89_write32(rtwdev, R_BE_BOOT_DBG, 0x0); rtw89_write32(rtwdev, R_BE_HALT_H2C, 0); rtw89_write32(rtwdev, R_BE_HALT_C2H, 0); rtw89_write32(rtwdev, R_BE_HALT_H2C_CTRL, 0); @@ -492,6 +669,11 @@ static int wcpu_on(struct rtw89_dev *rtwdev, u8 boot_reason, bool dlfw) B_BE_WDT_WAKE_PCIE_EN | B_BE_WDT_WAKE_USB_EN); rtw89_write32_clr(rtwdev, R_BE_WCPU_FW_CTRL, B_BE_WDT_PLT_RST_EN | B_BE_WCPU_ROM_CUT_GET); + rtw89_write32(rtwdev, R_BE_SECURE_BOOT_MALLOC_INFO, 0); + rtw89_write32_clr(rtwdev, R_BE_GPIO_MUXCFG, B_BE_BOOT_MODE); + + if (chip->chip_id != RTL8922A) + rtw89_write32_set(rtwdev, R_BE_WCPU_FW_CTRL, B_BE_HOST_EXIST); rtw89_write16_mask(rtwdev, R_BE_BOOT_REASON, B_BE_BOOT_REASON_MASK, boot_reason); rtw89_write32_clr(rtwdev, R_BE_PLATFORM_ENABLE, B_BE_WCPU_EN); @@ -577,31 +759,125 @@ static int rtw89_fwdl_check_path_ready_be(struct rtw89_dev *rtwdev, static int dmac_func_en_be(struct rtw89_dev *rtwdev) { + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->chip_id == RTL8922A) + return 0; + + rtw89_write32_set(rtwdev, R_BE_DMAC_FUNC_EN, + B_BE_MAC_FUNC_EN | B_BE_DMAC_FUNC_EN | + B_BE_MPDU_PROC_EN | B_BE_WD_RLS_EN | + B_BE_DLE_WDE_EN | B_BE_TXPKT_CTRL_EN | + B_BE_STA_SCH_EN | B_BE_DLE_PLE_EN | + B_BE_PKT_BUF_EN | B_BE_DMAC_TBL_EN | + B_BE_PKT_IN_EN | B_BE_DLE_CPUIO_EN | + B_BE_DISPATCHER_EN | B_BE_BBRPT_EN | + B_BE_MAC_SEC_EN | B_BE_H_AXIDMA_EN | + B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN | + B_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN); + + return 0; +} + +static int cmac_share_func_en_be(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->chip_id == RTL8922A) + return 0; + + rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_FUNC_EN, + B_BE_CMAC_SHARE_EN | B_BE_RESPBA_EN | + B_BE_ADDRSRCH_EN | B_BE_BTCOEX_EN); + + return 0; +} + +static int cmac_pwr_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) +{ + if (mac_idx > RTW89_MAC_1) + return -EINVAL; + + if (mac_idx == RTW89_MAC_0) { + if (en == test_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags)) + return 0; + + if (en) { + rtw89_write32_set(rtwdev, R_BE_AFE_CTRL1, + B_BE_R_SYM_WLCMAC0_ALL_EN); + rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_R_SYM_ISO_CMAC02PP); + rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_CMAC0_FEN); + + set_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags); + } else { + rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_CMAC0_FEN); + rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_R_SYM_ISO_CMAC02PP); + rtw89_write32_clr(rtwdev, R_BE_AFE_CTRL1, + B_BE_R_SYM_WLCMAC0_ALL_EN); + + clear_bit(RTW89_FLAG_CMAC0_PWR, rtwdev->flags); + } + } else { + if (en == test_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags)) + return 0; + + if (en) { + rtw89_write32_set(rtwdev, R_BE_AFE_CTRL1, + B_BE_R_SYM_WLCMAC1_ALL_EN); + rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_R_SYM_ISO_CMAC12PP); + rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_CMAC1_FEN); + + set_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags); + } else { + rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_CMAC1_FEN); + rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, + B_BE_R_SYM_ISO_CMAC12PP); + rtw89_write32_clr(rtwdev, R_BE_AFE_CTRL1, + B_BE_R_SYM_WLCMAC1_ALL_EN); + + clear_bit(RTW89_FLAG_CMAC1_PWR, rtwdev->flags); + } + } + return 0; } static int cmac_func_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) { + enum rtw89_flags pwr_flag, func_flag; u32 reg; if (mac_idx > RTW89_MAC_1) return -EINVAL; - if (mac_idx == RTW89_MAC_0) + if (mac_idx == RTW89_MAC_0) { + pwr_flag = RTW89_FLAG_CMAC0_PWR; + func_flag = RTW89_FLAG_CMAC0_FUNC; + } else { + pwr_flag = RTW89_FLAG_CMAC1_PWR; + func_flag = RTW89_FLAG_CMAC1_FUNC; + } + + if (!test_bit(pwr_flag, rtwdev->flags)) { + rtw89_warn(rtwdev, "CMAC %u power cut did not release\n", mac_idx); return 0; + } if (en) { - rtw89_write32_set(rtwdev, R_BE_AFE_CTRL1, B_BE_AFE_CTRL1_SET); - rtw89_write32_clr(rtwdev, R_BE_SYS_ISO_CTRL_EXTEND, B_BE_R_SYM_ISO_CMAC12PP); - rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_CMAC1_FEN); - reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CK_EN, mac_idx); rtw89_write32_set(rtwdev, reg, B_BE_CK_EN_SET); reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CMAC_FUNC_EN, mac_idx); rtw89_write32_set(rtwdev, reg, B_BE_CMAC_FUNC_EN_SET); - set_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags); + set_bit(func_flag, rtwdev->flags); } else { reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CMAC_FUNC_EN, mac_idx); rtw89_write32_clr(rtwdev, reg, B_BE_CMAC_FUNC_EN_SET); @@ -609,11 +885,7 @@ static int cmac_func_en_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool en) reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CK_EN, mac_idx); rtw89_write32_clr(rtwdev, reg, B_BE_CK_EN_SET); - rtw89_write32_clr(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_CMAC1_FEN); - rtw89_write32_set(rtwdev, R_BE_SYS_ISO_CTRL_EXTEND, B_BE_R_SYM_ISO_CMAC12PP); - rtw89_write32_clr(rtwdev, R_BE_AFE_CTRL1, B_BE_AFE_CTRL1_SET); - - clear_bit(RTW89_FLAG_CMAC1_FUNC, rtwdev->flags); + clear_bit(func_flag, rtwdev->flags); } return 0; @@ -632,6 +904,14 @@ static int sys_init_be(struct rtw89_dev *rtwdev) if (ret) return ret; + ret = cmac_share_func_en_be(rtwdev); + if (ret) + return ret; + + ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_0, true); + if (ret) + return ret; + ret = cmac_func_en_be(rtwdev, RTW89_MAC_0, true); if (ret) return ret; @@ -643,11 +923,53 @@ static int sys_init_be(struct rtw89_dev *rtwdev) return ret; } +static int mac_func_en_be(struct rtw89_dev *rtwdev) +{ + u32 val; + int ret; + + ret = dmac_func_en_be(rtwdev); + if (ret) + return ret; + + ret = cmac_share_func_en_be(rtwdev); + if (ret) + return ret; + + val = rtw89_read32(rtwdev, R_BE_FEN_RST_ENABLE); + if (val & B_BE_CMAC0_FEN) { + ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_0, true); + if (ret) + return ret; + + ret = cmac_func_en_be(rtwdev, RTW89_MAC_0, true); + if (ret) + return ret; + } + + if (val & B_BE_CMAC1_FEN) { + ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_1, true); + if (ret) + return ret; + + ret = cmac_func_en_be(rtwdev, RTW89_MAC_1, true); + if (ret) + return ret; + } + + return 0; +} + static int sta_sch_init_be(struct rtw89_dev *rtwdev) { u32 p_val; int ret; + if (rtwdev->chip->chip_id == RTL8922D) { + rtw89_write32_set(rtwdev, R_BE_SS_LITE_TXL_MACID, B_BE_RPT_OTHER_BAND_EN); + return 0; + } + ret = rtw89_mac_check_mac_en(rtwdev, RTW89_MAC_0, RTW89_DMAC_SEL); if (ret) return ret; @@ -677,14 +999,16 @@ static int mpdu_proc_init_be(struct rtw89_dev *rtwdev) return ret; rtw89_write32_set(rtwdev, R_BE_MPDU_PROC, B_BE_APPEND_FCS); - rtw89_write32(rtwdev, R_BE_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL); + rtw89_write32(rtwdev, R_BE_CUT_AMSDU_CTRL, TRXCFG_MPDU_PROC_CUT_CTRL | + B_BE_CA_CHK_ADDRCAM_EN); val32 = rtw89_read32(rtwdev, R_BE_HDR_SHCUT_SETTING); val32 |= (B_BE_TX_HW_SEQ_EN | B_BE_TX_HW_ACK_POLICY_EN | B_BE_TX_MAC_MPDU_PROC_EN); val32 &= ~B_BE_TX_ADDR_MLD_TO_LIK; rtw89_write32_set(rtwdev, R_BE_HDR_SHCUT_SETTING, val32); - rtw89_write32(rtwdev, R_BE_RX_HDRTRNS, TRXCFG_MPDU_PROC_RX_HDR_CONV); + rtw89_write32(rtwdev, R_BE_RX_HDRTRNS, TRXCFG_MPDU_PROC_RX_HDR_CONV | + B_BE_HC_ADDR_HIT_EN); val32 = rtw89_read32(rtwdev, R_BE_DISP_FWD_WLAN_0); val32 = u32_replace_bits(val32, 1, B_BE_FWD_WLAN_CPU_TYPE_0_DATA_MASK); @@ -720,7 +1044,10 @@ static int sec_eng_init_be(struct rtw89_dev *rtwdev) static int txpktctrl_init_be(struct rtw89_dev *rtwdev) { + struct rtw89_mac_info *mac = &rtwdev->mac; struct rtw89_mac_dle_rsvd_qt_cfg qt_cfg; + const struct rtw89_dle_input *dle_input; + u32 mpdu_info_b1_ofst; u32 val32; int ret; @@ -731,9 +1058,16 @@ static int txpktctrl_init_be(struct rtw89_dev *rtwdev) return ret; } + dle_input = mac->dle_info.dle_input; + if (dle_input) + mpdu_info_b1_ofst = DIV_ROUND_UP(dle_input->mpdu_info_tbl_b0, + BIT(MPDU_INFO_TBL_FACTOR)); + else + mpdu_info_b1_ofst = MPDU_INFO_B1_OFST; + val32 = rtw89_read32(rtwdev, R_BE_TXPKTCTL_MPDUINFO_CFG); val32 = u32_replace_bits(val32, qt_cfg.pktid, B_BE_MPDUINFO_PKTID_MASK); - val32 = u32_replace_bits(val32, MPDU_INFO_B1_OFST, B_BE_MPDUINFO_B1_BADDR_MASK); + val32 = u32_replace_bits(val32, mpdu_info_b1_ofst, B_BE_MPDUINFO_B1_BADDR_MASK); val32 |= B_BE_MPDUINFO_FEN; rtw89_write32(rtwdev, R_BE_TXPKTCTL_MPDUINFO_CFG, val32); @@ -742,7 +1076,9 @@ static int txpktctrl_init_be(struct rtw89_dev *rtwdev) static int mlo_init_be(struct rtw89_dev *rtwdev) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val32; + u32 reg; int ret; val32 = rtw89_read32(rtwdev, R_BE_MLO_INIT_CTL); @@ -758,7 +1094,12 @@ static int mlo_init_be(struct rtw89_dev *rtwdev) if (ret) rtw89_err(rtwdev, "[MLO]%s: MLO init polling timeout\n", __func__); - rtw89_write32_set(rtwdev, R_BE_SS_CTRL, B_BE_MLO_HW_CHGLINK_EN); + if (chip->chip_id == RTL8922A) + reg = R_BE_SS_CTRL; + else + reg = R_BE_SS_CTRL_V1; + + rtw89_write32_set(rtwdev, reg, B_BE_MLO_HW_CHGLINK_EN); rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_ACQCHK_CFG_0, B_BE_R_MACID_ACQ_CHK_EN); return ret; @@ -821,6 +1162,7 @@ static int dmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val32; u32 reg; int ret; @@ -829,6 +1171,11 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) if (ret) return ret; + if (chip->chip_id == RTL8922D) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SCH_EXT_CTRL, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_CWCNT_PLUS_MODE); + } + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_HE_CTN_CHK_CCA_NAV, mac_idx); val32 = B_BE_HE_CTN_CHK_CCA_P20 | B_BE_HE_CTN_CHK_EDCCA_P20 | B_BE_HE_CTN_CHK_CCA_BITMAP | B_BE_HE_CTN_CHK_EDCCA_BITMAP | @@ -862,6 +1209,11 @@ static int scheduler_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) rtw89_write32_mask(rtwdev, reg, B_BE_BCNQ_CW_MASK, 0x32); rtw89_write32_mask(rtwdev, reg, B_BE_BCNQ_AIFS_MASK, BCN_IFS_25US); + if (chip->chip_id == RTL8922D) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SCH_EDCA_RST_CFG, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_TX_NAV_RST_EDCA_EN); + } + return 0; } @@ -977,6 +1329,12 @@ static int nav_ctrl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) rtw89_write32(rtwdev, reg, val32); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_SPECIAL_TX_SETTING, mac_idx); + rtw89_write32_clr(rtwdev, reg, B_BE_BMC_NAV_PROTECT); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_WMAC_MBA_DUR_FORCE); + return 0; } @@ -1000,14 +1358,23 @@ static int spatial_reuse_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) static int tmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_hal *hal = &rtwdev->hal; u32 reg; reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TB_PPDU_CTRL, mac_idx); rtw89_write32_clr(rtwdev, reg, B_BE_QOSNULL_UPD_MUEDCA_EN); - reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMTX_TCR_BE_4, mac_idx); - rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_4XLTF_ZLD_USTIMER_MASK, 0x12); - rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_2XLTF_ZLD_USTIMER_MASK, 0xe); + if (chip->chip_id == RTL8922A) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_WMTX_TCR_BE_4, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_4XLTF_ZLD_USTIMER_MASK, 0x12); + rtw89_write32_mask(rtwdev, reg, B_BE_EHT_HE_PPDU_2XLTF_ZLD_USTIMER_MASK, 0xe); + } + + if (chip->chip_id == RTL8922D && hal->cid != RTL8922D_CID7090) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_COMMON_PHYINTF_CTRL_0, mac_idx); + rtw89_write32_clr(rtwdev, reg, CLEAR_DTOP_DIS); + } return 0; } @@ -1032,6 +1399,15 @@ static int trxptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) val32 &= ~B_BE_MACLBK_EN; rtw89_write32(rtwdev, reg, val32); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_CMAC_FUNC_EN, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_PHYINTF_EN); + + if (chip->chip_id == RTL8922D) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_PLCP_EXT_OPTION_2, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_PLCP_PHASE_B_CRC_CHK_EN | + B_BE_PLCP_PHASE_A_CRC_CHK_EN); + } + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_TRXPTCL_RESP_0, mac_idx); val32 = rtw89_read32(rtwdev, reg); val32 = u32_replace_bits(val32, WMAC_SPEC_SIFS_CCK, @@ -1101,6 +1477,7 @@ static int rst_bacam_be(struct rtw89_dev *rtwdev) static int rmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 rx_min_qta, rx_max_len, rx_max_pg; u16 val16; u32 reg; @@ -1144,6 +1521,17 @@ static int rmac_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_PLCP_EXT_OPTION_1, mac_idx); rtw89_write16_set(rtwdev, reg, B_BE_PLCP_SU_PSDU_LEN_SRC); + if (chip->chip_id == RTL8922D) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_BSR_UPD_CTRL, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_QSIZE_RULE); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RXGCK_CTRL, mac_idx); + rtw89_write16_mask(rtwdev, reg, B_BE_RXGCK_GCK_RATE_LIMIT_MASK, RX_GCK_LEGACY); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PLCP_HDR_FLTR, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_DIS_CHK_MIN_LEN); + } + return 0; } @@ -1167,7 +1555,7 @@ static int resp_pktctl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RESP_CSI_RESERVED_PAGE, mac_idx); rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_START_PAGE_MASK, qt_cfg.pktid); - rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_PAGE_NUM_MASK, qt_cfg.pg_num); + rtw89_write32_mask(rtwdev, reg, B_BE_CSI_RESERVED_PAGE_NUM_MASK, qt_cfg.pg_num + 1); return 0; } @@ -1202,6 +1590,7 @@ static int cmac_com_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val32; u8 val8; u32 reg; @@ -1216,8 +1605,9 @@ static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) val32 = rtw89_read32(rtwdev, reg); val32 = u32_replace_bits(val32, S_AX_CTS2S_TH_1K, B_BE_HW_CTS2SELF_PKT_LEN_TH_MASK); - val32 = u32_replace_bits(val32, S_AX_CTS2S_TH_SEC_256B, - B_BE_HW_CTS2SELF_PKT_LEN_TH_TWW_MASK); + if (chip->chip_id == RTL8922A) + val32 = u32_replace_bits(val32, S_AX_CTS2S_TH_SEC_256B, + B_BE_HW_CTS2SELF_PKT_LEN_TH_TWW_MASK); val32 |= B_BE_HW_CTS2SELF_EN; rtw89_write32(rtwdev, reg, val32); @@ -1238,7 +1628,46 @@ static int ptcl_init_be(struct rtw89_dev *rtwdev, u8 mac_idx) rtw89_write8(rtwdev, reg, val8); reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AMPDU_AGG_LIMIT, mac_idx); - rtw89_write32_mask(rtwdev, reg, B_BE_AMPDU_MAX_TIME_MASK, AMPDU_MAX_TIME); + if (chip->chip_id == RTL8922A) + val32 = AMPDU_MAX_TIME; + else + val32 = AMPDU_MAX_TIME_V1; + rtw89_write32_mask(rtwdev, reg, B_BE_AMPDU_MAX_TIME_MASK, val32); + + if (chip->chip_id == RTL8922D) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AGG_BK_0, mac_idx); + rtw89_write32_clr(rtwdev, reg, B_BE_WDBK_CFG | B_BE_EN_RTY_BK | + B_BE_EN_RTY_BK_COD); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AMPDU_AGG_LIMIT, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_BE_MAX_AGG_NUM_MASK, + MAX_TX_AMPDU_NUM_V1 - 1); + } + + if (rtw89_mac_chk_preload_allow(rtwdev)) { + reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_AGG_BK_0, mac_idx); + rtw89_write32_set(rtwdev, reg, B_BE_PRELD_MGQ0_EN | + B_BE_PRELD_HIQ_P4_EN | + B_BE_PRELD_HIQ_P3_EN | + B_BE_PRELD_HIQ_P2_EN | + B_BE_PRELD_HIQ_P1_EN | + B_BE_PRELD_HIQ_P0MB15_EN | + B_BE_PRELD_HIQ_P0MB14_EN | + B_BE_PRELD_HIQ_P0MB13_EN | + B_BE_PRELD_HIQ_P0MB12_EN | + B_BE_PRELD_HIQ_P0MB11_EN | + B_BE_PRELD_HIQ_P0MB10_EN | + B_BE_PRELD_HIQ_P0MB9_EN | + B_BE_PRELD_HIQ_P0MB8_EN | + B_BE_PRELD_HIQ_P0MB7_EN | + B_BE_PRELD_HIQ_P0MB6_EN | + B_BE_PRELD_HIQ_P0MB5_EN | + B_BE_PRELD_HIQ_P0MB4_EN | + B_BE_PRELD_HIQ_P0MB3_EN | + B_BE_PRELD_HIQ_P0MB2_EN | + B_BE_PRELD_HIQ_P0MB1_EN | + B_BE_PRELD_HIQ_P0_EN); + } return 0; } @@ -1525,22 +1954,22 @@ static int dle_quota_change_be(struct rtw89_dev *rtwdev, bool band1_en) static int preload_init_be(struct rtw89_dev *rtwdev, u8 mac_idx, enum rtw89_qta_mode mode) { + const struct rtw89_chip_info *chip = rtwdev->chip; u32 max_preld_size, min_rsvd_size; + u8 preld_acq, preld_miscq; u32 val32; u32 reg; + if (!(chip->chip_id == RTL8922A || rtw89_mac_chk_preload_allow(rtwdev))) + return 0; + max_preld_size = mac_idx == RTW89_MAC_0 ? PRELD_B0_ENT_NUM : PRELD_B1_ENT_NUM; + if (chip->chip_id == RTL8922D) + max_preld_size = PRELD_B01_ENT_NUM_8922D; max_preld_size *= PRELD_AMSDU_SIZE; + min_rsvd_size = PRELD_NEXT_MIN_SIZE; - reg = mac_idx == RTW89_MAC_0 ? R_BE_TXPKTCTL_B0_PRELD_CFG0 : - R_BE_TXPKTCTL_B1_PRELD_CFG0; - val32 = rtw89_read32(rtwdev, reg); - val32 = u32_replace_bits(val32, max_preld_size, B_BE_B0_PRELD_USEMAXSZ_MASK); - val32 |= B_BE_B0_PRELD_FEN; - rtw89_write32(rtwdev, reg, val32); - - min_rsvd_size = PRELD_AMSDU_SIZE; reg = mac_idx == RTW89_MAC_0 ? R_BE_TXPKTCTL_B0_PRELD_CFG1 : R_BE_TXPKTCTL_B1_PRELD_CFG1; val32 = rtw89_read32(rtwdev, reg); @@ -1548,9 +1977,36 @@ static int preload_init_be(struct rtw89_dev *rtwdev, u8 mac_idx, val32 = u32_replace_bits(val32, min_rsvd_size, B_BE_B0_PRELD_NXT_RSVMINSZ_MASK); rtw89_write32(rtwdev, reg, val32); + reg = mac_idx == RTW89_MAC_0 ? R_BE_TXPKTCTL_B0_PRELD_CFG0 : + R_BE_TXPKTCTL_B1_PRELD_CFG0; + if (chip->chip_id == RTL8922D) { + preld_acq = PRELD_ACQ_ENT_NUM_8922D; + preld_miscq = PRELD_MISCQ_ENT_NUM_8922D; + } else { + preld_acq = mac_idx == RTW89_MAC_0 ? PRELD_B0_ACQ_ENT_NUM_8922A : + PRELD_B1_ACQ_ENT_NUM_8922A; + preld_miscq = PRELD_MISCQ_ENT_NUM_8922A; + } + + val32 = rtw89_read32(rtwdev, reg); + val32 = u32_replace_bits(val32, preld_acq, B_BE_B0_PRELD_CAM_G0ENTNUM_MASK); + val32 = u32_replace_bits(val32, preld_miscq, B_BE_B0_PRELD_CAM_G1ENTNUM_MASK); + val32 = u32_replace_bits(val32, max_preld_size, B_BE_B0_PRELD_USEMAXSZ_MASK); + val32 |= B_BE_B0_PRELD_FEN; + rtw89_write32(rtwdev, reg, val32); + return 0; } +static void clr_aon_intr_be(struct rtw89_dev *rtwdev) +{ + if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE) + return; + + rtw89_write32_clr(rtwdev, R_BE_FWS0IMR, B_BE_FS_GPIOA_INT_EN); + rtw89_write32_set(rtwdev, R_BE_FWS0ISR, B_BE_FS_GPIOA_INT); +} + static int dbcc_bb_ctrl_be(struct rtw89_dev *rtwdev, bool bb1_en) { u32 set = B_BE_FEN_BB1PLAT_RSTB | B_BE_FEN_BB1_IP_RSTN; @@ -1580,6 +2036,10 @@ static int enable_imr_be(struct rtw89_dev *rtwdev, u8 mac_idx, else return -EINVAL; + if (chip->chip_id == RTL8922D) + rtw89_write32_mask(rtwdev, R_BE_NO_RX_ERR_CFG, + B_BE_NO_RX_ERR_TO_MASK, 0); + for (i = 0; i < table->n_regs; i++) { reg = &table->regs[i]; addr = rtw89_mac_reg_by_idx(rtwdev, reg->addr, mac_idx); @@ -1630,6 +2090,12 @@ static int band1_enable_be(struct rtw89_dev *rtwdev) return ret; } + ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_1, true); + if (ret) { + rtw89_err(rtwdev, "[ERR]CMAC%d pwr en %d\n", RTW89_MAC_1, ret); + return ret; + } + ret = cmac_func_en_be(rtwdev, RTW89_MAC_1, true); if (ret) { rtw89_err(rtwdev, "[ERR]CMAC%d func en %d\n", RTW89_MAC_1, ret); @@ -1673,6 +2139,12 @@ static int band1_disable_be(struct rtw89_dev *rtwdev) return ret; } + ret = cmac_pwr_en_be(rtwdev, RTW89_MAC_1, false); + if (ret) { + rtw89_err(rtwdev, "[ERR]CMAC%d pwr dis %d\n", RTW89_MAC_1, ret); + return ret; + } + ret = rtw89_mac_dle_quota_change(rtwdev, rtwdev->mac.qta_mode, false); if (ret) { rtw89_err(rtwdev, "[ERR]DLE quota change %d\n", ret); @@ -1723,26 +2195,40 @@ static int dbcc_enable_be(struct rtw89_dev *rtwdev, bool enable) static int set_host_rpr_be(struct rtw89_dev *rtwdev) { + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; u32 val32; u32 mode; u32 fltr; + u32 qid; bool poh; poh = is_qta_poh(rtwdev); if (poh) { mode = RTW89_RPR_MODE_POH; - fltr = S_BE_WDRLS_FLTR_TXOK | S_BE_WDRLS_FLTR_RTYLMT | - S_BE_WDRLS_FLTR_LIFTIM | S_BE_WDRLS_FLTR_MACID; + qid = WDRLS_DEST_QID_POH; } else { mode = RTW89_RPR_MODE_STF; fltr = 0; + qid = WDRLS_DEST_QID_STF; + } + + if (chip_id == RTL8922A) { + fltr = S_BE_WDRLS_FLTR_TXOK | S_BE_WDRLS_FLTR_RTYLMT | + S_BE_WDRLS_FLTR_LIFTIM | S_BE_WDRLS_FLTR_MACID; + } else { + fltr = S_BE_WDRLS_FLTR_TXOK_V1 | S_BE_WDRLS_FLTR_RTYLMT_V1 | + S_BE_WDRLS_FLTR_LIFTIM_V1 | S_BE_WDRLS_FLTR_MACID_V1; } rtw89_write32_mask(rtwdev, R_BE_WDRLS_CFG, B_BE_WDRLS_MODE_MASK, mode); + rtw89_write32_mask(rtwdev, R_BE_RLSRPT0_CFG0, B_BE_RLSRPT0_QID_MASK, qid); val32 = rtw89_read32(rtwdev, R_BE_RLSRPT0_CFG1); - val32 = u32_replace_bits(val32, fltr, B_BE_RLSRPT0_FLTR_MAP_MASK); + if (chip_id == RTL8922A) + val32 = u32_replace_bits(val32, fltr, B_BE_RLSRPT0_FLTR_MAP_MASK); + else + val32 = u32_replace_bits(val32, fltr, B_BE_RLSRPT0_FLTR_MAP_V1_MASK); val32 = u32_replace_bits(val32, 30, B_BE_RLSRPT0_AGGNUM_MASK); val32 = u32_replace_bits(val32, 255, B_BE_RLSRPT0_TO_MASK); rtw89_write32(rtwdev, R_BE_RLSRPT0_CFG1, val32); @@ -1855,12 +2341,65 @@ int rtw89_mac_cfg_gnt_v2(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_mac_cfg_gnt_v2); +int rtw89_mac_cfg_gnt_v3(struct rtw89_dev *rtwdev, + const struct rtw89_mac_ax_coex_gnt *gnt_cfg) +{ + u32 val = 0; + + if (gnt_cfg->band[0].gnt_bt) + val |= B_BE_PTA_GNT_BT0_BB_VAL | B_BE_PTA_GNT_BT0_RX_BB0_VAL | + B_BE_PTA_GNT_BT0_TX_BB0_VAL; + + if (gnt_cfg->band[0].gnt_bt_sw_en) + val |= B_BE_PTA_GNT_BT0_BB_SWCTRL | B_BE_PTA_GNT_BT0_RX_BB0_SWCTRL | + B_BE_PTA_GNT_BT0_TX_BB0_SWCTRL; + + if (gnt_cfg->band[0].gnt_wl) + val |= B_BE_PTA_GNT_WL_BB0_VAL; + + if (gnt_cfg->band[0].gnt_wl_sw_en) + val |= B_BE_PTA_GNT_WL_BB0_SWCTRL; + + if (gnt_cfg->band[1].gnt_bt) + val |= B_BE_PTA_GNT_BT0_BB_VAL | B_BE_PTA_GNT_BT0_RX_BB1_VAL | + B_BE_PTA_GNT_BT0_TX_BB1_VAL; + + if (gnt_cfg->band[1].gnt_bt_sw_en) + val |= B_BE_PTA_GNT_BT0_BB_SWCTRL | B_BE_PTA_GNT_BT0_RX_BB1_SWCTRL | + B_BE_PTA_GNT_BT0_TX_BB1_SWCTRL; + + if (gnt_cfg->band[1].gnt_wl) + val |= B_BE_PTA_GNT_WL_BB1_VAL; + + if (gnt_cfg->band[1].gnt_wl_sw_en) + val |= B_BE_PTA_GNT_WL_BB1_SWCTRL; + + if (gnt_cfg->bt[0].wlan_act_en) + val |= B_BE_PTA_WL_ACT0_SWCTRL | B_BE_PTA_WL_ACT_RX_BT0_SWCTRL | + B_BE_PTA_WL_ACT_TX_BT0_SWCTRL; + if (gnt_cfg->bt[0].wlan_act) + val |= B_BE_PTA_WL_ACT0_VAL | B_BE_PTA_WL_ACT_RX_BT0_VAL | + B_BE_PTA_WL_ACT_TX_BT0_VAL; + if (gnt_cfg->bt[1].wlan_act_en) + val |= B_BE_PTA_WL_ACT1_SWCTRL | B_BE_PTA_WL_ACT_RX_BT1_SWCTRL | + B_BE_PTA_WL_ACT_TX_BT1_SWCTRL; + if (gnt_cfg->bt[1].wlan_act) + val |= B_BE_PTA_WL_ACT1_VAL | B_BE_PTA_WL_ACT_RX_BT1_VAL | + B_BE_PTA_WL_ACT_TX_BT1_VAL; + + rtw89_write32(rtwdev, R_BE_PTA_GNT_SW_CTRL, val); + + return 0; +} +EXPORT_SYMBOL(rtw89_mac_cfg_gnt_v3); + int rtw89_mac_cfg_ctrl_path_v2(struct rtw89_dev *rtwdev, bool wl) { struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_dm *dm = &btc->dm; struct rtw89_mac_ax_gnt *g = dm->gnt.band; struct rtw89_mac_ax_wl_act *gbt = dm->gnt.bt; + const struct rtw89_chip_info *chip = rtwdev->chip; int i; if (wl) @@ -1875,7 +2414,11 @@ int rtw89_mac_cfg_ctrl_path_v2(struct rtw89_dev *rtwdev, bool wl) gbt[i].wlan_act_en = 0; } - return rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt); + if (chip->chip_id == RTL8922A) + return rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt); + else + return rtw89_mac_cfg_gnt_v3(rtwdev, &dm->gnt); + } EXPORT_SYMBOL(rtw89_mac_cfg_ctrl_path_v2); @@ -2003,6 +2546,65 @@ void rtw89_mac_cfg_phy_rpt_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) } EXPORT_SYMBOL(rtw89_mac_cfg_phy_rpt_be); +static +void rtw89_mac_set_edcca_mode_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal) +{ + u16 resp_ack, resp_rts, resp_rts_punc, resp_normal, resp_normal_punc; + + if (rtwdev->chip->chip_id == RTL8922A) + return; + + resp_ack = RESP_ACK_CFG_BE; + resp_rts = RESP_RTS_CFG_BE; + resp_rts_punc = RESP_RTS_PUNC_CFG_BE; + resp_normal = RESP_NORMAL_CFG_BE; + resp_normal_punc = RESP_NORMAL_PUNC_CFG_BE; + + if (normal) { + rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_LEGACY, + resp_ack, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_HE, + resp_ack, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_EHT_LEG_PUNC, + resp_ack, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY, + resp_rts, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC, + resp_rts_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY, + resp_normal, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC, + resp_normal_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_LEGACY, + resp_normal, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_HE, + resp_normal_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC, + resp_normal_punc, mac_idx); + } else { + rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_LEGACY, + resp_normal, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_HE, + resp_normal_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_ACK_BA_RESP_EHT_LEG_PUNC, + resp_normal_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY, + resp_rts, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC, + resp_rts_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY, + resp_normal, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC, + resp_normal_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_LEGACY, + resp_normal, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_HE, + resp_normal_punc, mac_idx); + rtw89_write16_idx(rtwdev, R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC, + resp_normal_punc, mac_idx); + } +} + static int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable) { @@ -2019,7 +2621,7 @@ int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enab } rtw89_write32_mask(rtwdev, R_BE_HW_PPDU_STATUS, B_BE_FWD_PPDU_STAT_MASK, 3); - rtw89_write32(rtwdev, reg, B_BE_PPDU_STAT_RPT_EN | B_BE_PPDU_MAC_INFO | + rtw89_write32(rtwdev, reg, B_BE_PPDU_STAT_RPT_EN | B_BE_APP_RX_CNT_RPT | B_BE_APP_PLCP_HDR_RPT | B_BE_PPDU_STAT_RPT_CRC32 | B_BE_PPDU_STAT_RPT_DMA); @@ -2574,6 +3176,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .port_base = &rtw89_port_base_be, .agg_len_ht = R_BE_AGG_LEN_HT_0, .ps_status = R_BE_WMTX_POWER_BE_BIT_CTL, + .mu_gid = &rtw89_mac_mu_gid_addr_be, .muedca_ctrl = { .addr = R_BE_MUEDCA_EN, @@ -2595,6 +3198,10 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .check_mac_en = rtw89_mac_check_mac_en_be, .sys_init = sys_init_be, .trx_init = trx_init_be, + .preload_init = preload_init_be, + .clr_aon_intr = clr_aon_intr_be, + .err_imr_ctrl = err_imr_ctrl_be, + .mac_func_en = mac_func_en_be, .hci_func_en = rtw89_mac_hci_func_en_be, .dmac_func_pre_en = rtw89_mac_dmac_func_pre_en_be, .dle_func_en = dle_func_en_be, @@ -2604,6 +3211,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .typ_fltr_opt = rtw89_mac_typ_fltr_opt_be, .cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_be, .cfg_phy_rpt = rtw89_mac_cfg_phy_rpt_be, + .set_edcca_mode = rtw89_mac_set_edcca_mode_be, .dle_mix_cfg = dle_mix_cfg_be, .chk_dle_rdy = chk_dle_rdy_be, @@ -2617,6 +3225,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .set_cpuio = set_cpuio_be, .dle_quota_change = dle_quota_change_be, + .reset_pwr_state = rtw89_mac_reset_pwr_state_be, .disable_cpu = rtw89_mac_disable_cpu_be, .fwdl_enable_wcpu = rtw89_mac_fwdl_enable_wcpu_be, .fwdl_get_status = fwdl_get_status_be, @@ -2626,6 +3235,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = { .parse_phycap_map = rtw89_parse_phycap_map_be, .cnv_efuse_state = rtw89_cnv_efuse_state_be, .efuse_read_fw_secure = rtw89_efuse_read_fw_secure_be, + .efuse_read_ecv = rtw89_efuse_read_ecv_be, .cfg_plt = rtw89_mac_cfg_plt_be, .get_plt_cnt = rtw89_mac_get_plt_cnt_be, diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index d73e0a1d1bec4..dd1739a1fa42f 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -137,7 +137,7 @@ static void rtw89_pci_release_fwcmd(struct rtw89_dev *rtwdev, static void rtw89_pci_reclaim_tx_fwcmd(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) { - struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[RTW89_TXCH_CH12]; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx.rings[RTW89_TXCH_CH12]; u32 cnt; cnt = rtw89_pci_txbd_recalc(rtwdev, tx_ring); @@ -443,7 +443,7 @@ static int rtw89_pci_poll_rxq_dma(struct rtw89_dev *rtwdev, int countdown = rtwdev->napi_budget_countdown; u32 cnt; - rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RXQ]; + rx_ring = &rtwpci->rx.rings[RTW89_RXCH_RXQ]; cnt = rtw89_pci_rxbd_recalc(rtwdev, rx_ring); if (!cnt) @@ -467,7 +467,8 @@ static void rtw89_pci_tx_status(struct rtw89_dev *rtwdev, struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); struct ieee80211_tx_info *info; - rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE); + if (rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status)) + return; info = IEEE80211_SKB_CB(skb); ieee80211_tx_info_clear_status(info); @@ -571,31 +572,59 @@ static void rtw89_pci_release_txwd_skb(struct rtw89_dev *rtwdev, rtw89_pci_enqueue_txwd(tx_ring, txwd); } -static void rtw89_pci_release_rpp(struct rtw89_dev *rtwdev, - struct rtw89_pci_rpp_fmt *rpp) +void rtw89_pci_parse_rpp(struct rtw89_dev *rtwdev, void *_rpp, + struct rtw89_pci_rpp_info *rpp_info) +{ + const struct rtw89_pci_rpp_fmt *rpp = _rpp; + + rpp_info->seq = le32_get_bits(rpp->dword, RTW89_PCI_RPP_SEQ); + rpp_info->qsel = le32_get_bits(rpp->dword, RTW89_PCI_RPP_QSEL); + rpp_info->tx_status = le32_get_bits(rpp->dword, RTW89_PCI_RPP_TX_STATUS); + rpp_info->txch = rtw89_chip_get_ch_dma(rtwdev, rpp_info->qsel); +} +EXPORT_SYMBOL(rtw89_pci_parse_rpp); + +void rtw89_pci_parse_rpp_v1(struct rtw89_dev *rtwdev, void *_rpp, + struct rtw89_pci_rpp_info *rpp_info) +{ + const struct rtw89_pci_rpp_fmt_v1 *rpp = _rpp; + + rpp_info->seq = le32_get_bits(rpp->w0, RTW89_PCI_RPP_W0_PCIE_SEQ_V1_MASK); + rpp_info->qsel = le32_get_bits(rpp->w1, RTW89_PCI_RPP_W1_QSEL_V1_MASK); + rpp_info->tx_status = le32_get_bits(rpp->w0, RTW89_PCI_RPP_W0_TX_STATUS_V1_MASK); + rpp_info->txch = le32_get_bits(rpp->w0, RTW89_PCI_RPP_W0_DMA_CH_MASK); +} +EXPORT_SYMBOL(rtw89_pci_parse_rpp_v1); + +static void rtw89_pci_release_rpp(struct rtw89_dev *rtwdev, void *rpp) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - struct rtw89_pci_tx_ring *tx_ring; + const struct rtw89_pci_info *info = rtwdev->pci_info; + struct rtw89_pci_rpp_info rpp_info = {}; struct rtw89_pci_tx_wd_ring *wd_ring; + struct rtw89_pci_tx_ring *tx_ring; struct rtw89_pci_tx_wd *txwd; - u16 seq; - u8 qsel, tx_status, txch; - seq = le32_get_bits(rpp->dword, RTW89_PCI_RPP_SEQ); - qsel = le32_get_bits(rpp->dword, RTW89_PCI_RPP_QSEL); - tx_status = le32_get_bits(rpp->dword, RTW89_PCI_RPP_TX_STATUS); - txch = rtw89_core_get_ch_dma(rtwdev, qsel); + info->parse_rpp(rtwdev, rpp, &rpp_info); - if (txch == RTW89_TXCH_CH12) { - rtw89_warn(rtwdev, "should no fwcmd release report\n"); + if (unlikely(rpp_info.txch >= RTW89_TXCH_NUM || + info->tx_dma_ch_mask & BIT(rpp_info.txch))) { + rtw89_warn(rtwdev, "should no release report on txch %d\n", + rpp_info.txch); return; } - tx_ring = &rtwpci->tx_rings[txch]; + if (unlikely(rpp_info.seq >= RTW89_PCI_TXWD_NUM_MAX)) { + rtw89_warn(rtwdev, "invalid seq %d\n", rpp_info.seq); + return; + } + + tx_ring = &rtwpci->tx.rings[rpp_info.txch]; wd_ring = &tx_ring->wd_ring; - txwd = &wd_ring->pages[seq]; + txwd = &wd_ring->pages[rpp_info.seq]; - rtw89_pci_release_txwd_skb(rtwdev, tx_ring, txwd, seq, tx_status); + rtw89_pci_release_txwd_skb(rtwdev, tx_ring, txwd, rpp_info.seq, + rpp_info.tx_status); } static void rtw89_pci_release_pending_txwd_skb(struct rtw89_dev *rtwdev, @@ -620,13 +649,14 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev, u32 max_cnt) { struct rtw89_pci_dma_ring *bd_ring = &rx_ring->bd_ring; - struct rtw89_pci_rx_info *rx_info; - struct rtw89_pci_rpp_fmt *rpp; + const struct rtw89_pci_info *info = rtwdev->pci_info; struct rtw89_rx_desc_info desc_info = {}; + struct rtw89_pci_rx_info *rx_info; struct sk_buff *skb; - u32 cnt = 0; - u32 rpp_size = sizeof(struct rtw89_pci_rpp_fmt); + void *rpp; u32 rxinfo_size = sizeof(struct rtw89_pci_rxbd_info); + u32 rpp_size = info->rpp_fmt_size; + u32 cnt = 0; u32 skb_idx; u32 offset; int ret; @@ -652,7 +682,7 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev, /* first segment has RX desc */ offset = desc_info.offset + desc_info.rxd_len; for (; offset + rpp_size <= rx_info->len; offset += rpp_size) { - rpp = (struct rtw89_pci_rpp_fmt *)(skb->data + offset); + rpp = skb->data + offset; rtw89_pci_release_rpp(rtwdev, rpp); } @@ -697,7 +727,7 @@ static int rtw89_pci_poll_rpq_dma(struct rtw89_dev *rtwdev, u32 cnt; int work_done; - rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ]; + rx_ring = &rtwpci->rx.rings[RTW89_RXCH_RPQ]; spin_lock_bh(&rtwpci->trx_lock); @@ -727,7 +757,7 @@ static void rtw89_pci_isr_rxd_unavail(struct rtw89_dev *rtwdev, int i; for (i = 0; i < RTW89_RXCH_NUM; i++) { - rx_ring = &rtwpci->rx_rings[i]; + rx_ring = &rtwpci->rx.rings[i]; bd_ring = &rx_ring->bd_ring; reg_idx = rtw89_read32(rtwdev, bd_ring->addr.idx); @@ -800,6 +830,29 @@ void rtw89_pci_recognize_intrs_v2(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_pci_recognize_intrs_v2); +void rtw89_pci_recognize_intrs_v3(struct rtw89_dev *rtwdev, + struct rtw89_pci *rtwpci, + struct rtw89_pci_isrs *isrs) +{ + isrs->ind_isrs = rtw89_read32(rtwdev, R_BE_PCIE_HISR) & rtwpci->ind_intrs; + isrs->halt_c2h_isrs = isrs->ind_isrs & B_BE_HS0ISR_IND_INT ? + rtw89_read32(rtwdev, R_BE_HISR0) & rtwpci->halt_c2h_intrs : 0; + isrs->isrs[1] = rtw89_read32(rtwdev, R_BE_PCIE_DMA_ISR) & rtwpci->intrs[1]; + + /* isrs[0] is not used, so borrow to store RDU status to share common + * flow in rtw89_pci_interrupt_threadfn(). + */ + isrs->isrs[0] = isrs->isrs[1] & (B_BE_PCIE_RDU_CH1_INT | + B_BE_PCIE_RDU_CH0_INT); + + if (isrs->halt_c2h_isrs) + rtw89_write32(rtwdev, R_BE_HISR0, isrs->halt_c2h_isrs); + if (isrs->isrs[1]) + rtw89_write32(rtwdev, R_BE_PCIE_DMA_ISR, isrs->isrs[1]); + rtw89_write32(rtwdev, R_BE_PCIE_HISR, isrs->ind_isrs); +} +EXPORT_SYMBOL(rtw89_pci_recognize_intrs_v3); + void rtw89_pci_enable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) { rtw89_write32(rtwdev, R_AX_HIMR0, rtwpci->halt_c2h_intrs); @@ -847,6 +900,21 @@ void rtw89_pci_disable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpc } EXPORT_SYMBOL(rtw89_pci_disable_intr_v2); +void rtw89_pci_enable_intr_v3(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) +{ + rtw89_write32(rtwdev, R_BE_HIMR0, rtwpci->halt_c2h_intrs); + rtw89_write32(rtwdev, R_BE_PCIE_DMA_IMR_0_V1, rtwpci->intrs[1]); + rtw89_write32(rtwdev, R_BE_PCIE_HIMR0, rtwpci->ind_intrs); +} +EXPORT_SYMBOL(rtw89_pci_enable_intr_v3); + +void rtw89_pci_disable_intr_v3(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci) +{ + rtw89_write32(rtwdev, R_BE_PCIE_HIMR0, 0); + rtw89_write32(rtwdev, R_BE_PCIE_DMA_IMR_0_V1, 0); +} +EXPORT_SYMBOL(rtw89_pci_disable_intr_v3); + static void rtw89_pci_ops_recovery_start(struct rtw89_dev *rtwdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; @@ -905,6 +973,9 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev) if (unlikely(isrs.halt_c2h_isrs & isr_def->isr_wdt_timeout)) rtw89_ser_notify(rtwdev, MAC_AX_ERR_L2_ERR_WDT_TIMEOUT_INT); + if (unlikely(isrs.halt_c2h_isrs & isr_def->isr_sps_ocp)) + rtw89_warn(rtwdev, "SPS OCP alarm 0x%x\n", isrs.halt_c2h_isrs); + if (unlikely(rtwpci->under_recovery)) goto enable_intr; @@ -953,6 +1024,24 @@ static irqreturn_t rtw89_pci_interrupt_handler(int irq, void *dev) return irqret; } +#define DEF_TXCHADDRS_TYPE3(gen, ch_idx, txch, v...) \ + [RTW89_TXCH_##ch_idx] = { \ + .num = R_##gen##_##txch##_TXBD_CFG, \ + .idx = R_##gen##_##txch##_TXBD_IDX ##v, \ + .bdram = 0, \ + .desa_l = 0, \ + .desa_h = 0, \ + } + +#define DEF_TXCHADDRS_TYPE3_GRP_BASE(gen, ch_idx, txch, grp, v...) \ + [RTW89_TXCH_##ch_idx] = { \ + .num = R_##gen##_##txch##_TXBD_CFG, \ + .idx = R_##gen##_##txch##_TXBD_IDX ##v, \ + .bdram = 0, \ + .desa_l = R_##gen##_##grp##_TXBD_DESA_L, \ + .desa_h = R_##gen##_##grp##_TXBD_DESA_H, \ + } + #define DEF_TXCHADDRS_TYPE2(gen, ch_idx, txch, v...) \ [RTW89_TXCH_##ch_idx] = { \ .num = R_##gen##_##txch##_TXBD_NUM ##v, \ @@ -980,6 +1069,22 @@ static irqreturn_t rtw89_pci_interrupt_handler(int irq, void *dev) .desa_h = R_AX_##txch##_TXBD_DESA_H ##v, \ } +#define DEF_RXCHADDRS_TYPE3(gen, ch_idx, rxch, v...) \ + [RTW89_RXCH_##ch_idx] = { \ + .num = R_##gen##_RX_##rxch##_RXBD_CONFIG, \ + .idx = R_##gen##_##ch_idx##0_RXBD_IDX ##v, \ + .desa_l = 0, \ + .desa_h = 0, \ + } + +#define DEF_RXCHADDRS_TYPE3_GRP_BASE(gen, ch_idx, rxch, grp, v...) \ + [RTW89_RXCH_##ch_idx] = { \ + .num = R_##gen##_RX_##rxch##_RXBD_CONFIG, \ + .idx = R_##gen##_##ch_idx##0_RXBD_IDX ##v, \ + .desa_l = R_##gen##_##grp##_RXBD_DESA_L, \ + .desa_h = R_##gen##_##grp##_RXBD_DESA_H, \ + } + #define DEF_RXCHADDRS(gen, ch_idx, rxch, v...) \ [RTW89_RXCH_##ch_idx] = { \ .num = R_##gen##_##rxch##_RXBD_NUM ##v, \ @@ -1057,8 +1162,36 @@ const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be = { }; EXPORT_SYMBOL(rtw89_pci_ch_dma_addr_set_be); +const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be_v1 = { + .tx = { + DEF_TXCHADDRS_TYPE3_GRP_BASE(BE, ACH0, CH0, ACQ, _V1), + /* no CH1 */ + DEF_TXCHADDRS_TYPE3(BE, ACH2, CH2, _V1), + /* no CH3 */ + DEF_TXCHADDRS_TYPE3(BE, ACH4, CH4, _V1), + /* no CH5 */ + DEF_TXCHADDRS_TYPE3(BE, ACH6, CH6, _V1), + /* no CH7 */ + DEF_TXCHADDRS_TYPE3_GRP_BASE(BE, CH8, CH8, NACQ, _V1), + /* no CH9 */ + DEF_TXCHADDRS_TYPE3(BE, CH10, CH10, _V1), + /* no CH11 */ + DEF_TXCHADDRS_TYPE3(BE, CH12, CH12, _V1), + }, + .rx = { + DEF_RXCHADDRS_TYPE3_GRP_BASE(BE, RXQ, CH0, HOST0, _V1), + DEF_RXCHADDRS_TYPE3(BE, RPQ, CH1, _V1), + }, +}; +EXPORT_SYMBOL(rtw89_pci_ch_dma_addr_set_be_v1); + +#undef DEF_TXCHADDRS_TYPE3 +#undef DEF_TXCHADDRS_TYPE3_GRP_BASE +#undef DEF_TXCHADDRS_TYPE2 #undef DEF_TXCHADDRS_TYPE1 #undef DEF_TXCHADDRS +#undef DEF_RXCHADDRS_TYPE3 +#undef DEF_RXCHADDRS_TYPE3_GRP_BASE #undef DEF_RXCHADDRS static int rtw89_pci_get_txch_addrs(struct rtw89_dev *rtwdev, @@ -1104,7 +1237,7 @@ static u32 __rtw89_pci_check_and_reclaim_tx_fwcmd_resource(struct rtw89_dev *rtwdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[RTW89_TXCH_CH12]; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx.rings[RTW89_TXCH_CH12]; u32 cnt; spin_lock_bh(&rtwpci->trx_lock); @@ -1120,7 +1253,7 @@ u32 __rtw89_pci_check_and_reclaim_tx_resource_noio(struct rtw89_dev *rtwdev, u8 txch) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx.rings[txch]; struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; u32 cnt; @@ -1137,7 +1270,7 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, u8 txch) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx.rings[txch]; struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; const struct rtw89_chip_info *chip = rtwdev->chip; u32 bd_cnt, wd_cnt, min_cnt = 0; @@ -1145,7 +1278,7 @@ static u32 __rtw89_pci_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, enum rtw89_debug_mask debug_mask; u32 cnt; - rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ]; + rx_ring = &rtwpci->rx.rings[RTW89_RXCH_RPQ]; spin_lock_bh(&rtwpci->trx_lock); bd_cnt = rtw89_pci_get_avail_txbd_num(tx_ring); @@ -1230,7 +1363,7 @@ static void rtw89_pci_tx_bd_ring_update(struct rtw89_dev *rtwdev, struct rtw89_p static void rtw89_pci_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx.rings[txch]; if (rtwdev->hci.paused) { set_bit(txch, rtwpci->kick_map); @@ -1250,7 +1383,7 @@ static void rtw89_pci_tx_kick_off_pending(struct rtw89_dev *rtwdev) if (!test_and_clear_bit(txch, rtwpci->kick_map)) continue; - tx_ring = &rtwpci->tx_rings[txch]; + tx_ring = &rtwpci->tx.rings[txch]; __rtw89_pci_tx_kick_off(rtwdev, tx_ring); } } @@ -1258,7 +1391,7 @@ static void rtw89_pci_tx_kick_off_pending(struct rtw89_dev *rtwdev) static void __pci_flush_txch(struct rtw89_dev *rtwdev, u8 txch, bool drop) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; - struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx.rings[txch]; struct rtw89_pci_dma_ring *bd_ring = &tx_ring->bd_ring; u32 cur_idx, cur_rp; u8 i; @@ -1374,7 +1507,6 @@ static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev, struct pci_dev *pdev = rtwpci->pdev; struct sk_buff *skb = tx_req->skb; struct rtw89_pci_tx_data *tx_data = RTW89_PCI_TX_SKB_CB(skb); - struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); bool en_wd_info = desc_info->en_wd_info; u32 txwd_len; u32 txwp_len; @@ -1390,7 +1522,6 @@ static int rtw89_pci_txwd_submit(struct rtw89_dev *rtwdev, } tx_data->dma = dma; - rcu_assign_pointer(skb_data->wait, NULL); txwp_len = sizeof(*txwp_info); txwd_len = chip->txwd_body_size; @@ -1524,7 +1655,7 @@ static int rtw89_pci_tx_write(struct rtw89_dev *rtwdev, struct rtw89_core_tx_req return -EINVAL; } - tx_ring = &rtwpci->tx_rings[txch]; + tx_ring = &rtwpci->tx.rings[txch]; spin_lock_bh(&rtwpci->trx_lock); n_avail_txbd = rtw89_pci_get_avail_txbd_num(tx_ring); @@ -1610,6 +1741,41 @@ static void rtw89_pci_init_wp_16sel(struct rtw89_dev *rtwdev) } } +static u16 rtw89_pci_enc_bd_cfg(struct rtw89_dev *rtwdev, u16 bd_num, + u32 dma_offset) +{ + u16 dma_offset_sel; + u16 num_sel; + + /* B_BE_TX_NUM_SEL_MASK, B_BE_RX_NUM_SEL_MASK: + * 0 -> 0 + * 1 -> 64 = 2^6 + * 2 -> 128 = 2^7 + * ... + * 7 -> 4096 = 2^12 + */ + num_sel = ilog2(bd_num) - 5; + + if (hweight16(bd_num) != 1) + rtw89_warn(rtwdev, "bd_num %u is not power of 2\n", bd_num); + + /* B_BE_TX_START_OFFSET_MASK, B_BE_RX_START_OFFSET_MASK: + * 0 -> 0 = 0 * 2^9 + * 1 -> 512 = 1 * 2^9 + * 2 -> 1024 = 2 * 2^9 + * 3 -> 1536 = 3 * 2^9 + * ... + * 255 -> 130560 = 255 * 2^9 + */ + dma_offset_sel = dma_offset >> 9; + + if (dma_offset % 512) + rtw89_warn(rtwdev, "offset %u is not multiple of 512\n", dma_offset); + + return u16_encode_bits(num_sel, B_BE_TX_NUM_SEL_MASK) | + u16_encode_bits(dma_offset_sel, B_BE_TX_START_OFFSET_MASK); +} + static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; @@ -1619,10 +1785,12 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) struct rtw89_pci_rx_ring *rx_ring; struct rtw89_pci_dma_ring *bd_ring; const struct rtw89_pci_bd_ram *bd_ram; + dma_addr_t group_dma_base = 0; + u16 num_or_offset; + u32 addr_desa_l; + u32 addr_bdram; u32 addr_num; u32 addr_idx; - u32 addr_bdram; - u32 addr_desa_l; u32 val32; int i; @@ -1630,7 +1798,7 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) if (info->tx_dma_ch_mask & BIT(i)) continue; - tx_ring = &rtwpci->tx_rings[i]; + tx_ring = &rtwpci->tx.rings[i]; bd_ring = &tx_ring->bd_ring; bd_ram = bd_ram_table ? &bd_ram_table[i] : NULL; addr_num = bd_ring->addr.num; @@ -1639,7 +1807,18 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) bd_ring->wp = 0; bd_ring->rp = 0; - rtw89_write16(rtwdev, addr_num, bd_ring->len); + if (info->group_bd_addr) { + if (addr_desa_l) + group_dma_base = bd_ring->dma; + + num_or_offset = + rtw89_pci_enc_bd_cfg(rtwdev, bd_ring->len, + bd_ring->dma - group_dma_base); + } else { + num_or_offset = bd_ring->len; + } + rtw89_write16(rtwdev, addr_num, num_or_offset); + if (addr_bdram && bd_ram) { val32 = FIELD_PREP(BDRAM_SIDX_MASK, bd_ram->start_idx) | FIELD_PREP(BDRAM_MAX_MASK, bd_ram->max_num) | @@ -1647,12 +1826,14 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) rtw89_write32(rtwdev, addr_bdram, val32); } - rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma); - rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma)); + if (addr_desa_l) { + rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma); + rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma)); + } } for (i = 0; i < RTW89_RXCH_NUM; i++) { - rx_ring = &rtwpci->rx_rings[i]; + rx_ring = &rtwpci->rx.rings[i]; bd_ring = &rx_ring->bd_ring; addr_num = bd_ring->addr.num; addr_idx = bd_ring->addr.idx; @@ -1666,9 +1847,22 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev) rx_ring->diliver_desc.ready = false; rx_ring->target_rx_tag = 0; - rtw89_write16(rtwdev, addr_num, bd_ring->len); - rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma); - rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma)); + if (info->group_bd_addr) { + if (addr_desa_l) + group_dma_base = bd_ring->dma; + + num_or_offset = + rtw89_pci_enc_bd_cfg(rtwdev, bd_ring->len, + bd_ring->dma - group_dma_base); + } else { + num_or_offset = bd_ring->len; + } + rtw89_write16(rtwdev, addr_num, num_or_offset); + + if (addr_desa_l) { + rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma); + rtw89_write32(rtwdev, addr_desa_l + 4, upper_32_bits(bd_ring->dma)); + } if (info->rx_ring_eq_is_full) rtw89_write16(rtwdev, addr_idx, bd_ring->wp); @@ -1701,7 +1895,7 @@ void rtw89_pci_ops_reset(struct rtw89_dev *rtwdev) skb_queue_len(&rtwpci->h2c_queue), true); continue; } - rtw89_pci_release_tx_ring(rtwdev, &rtwpci->tx_rings[txch]); + rtw89_pci_release_tx_ring(rtwdev, &rtwpci->tx.rings[txch]); } spin_unlock_bh(&rtwpci->trx_lock); } @@ -1777,14 +1971,14 @@ void rtw89_pci_switch_bd_idx_addr(struct rtw89_dev *rtwdev, bool low_power) return; for (i = 0; i < RTW89_TXCH_NUM; i++) { - tx_ring = &rtwpci->tx_rings[i]; + tx_ring = &rtwpci->tx.rings[i]; tx_ring->bd_ring.addr.idx = low_power ? bd_idx_addr->tx_bd_addrs[i] : dma_addr_set->tx[i].idx; } for (i = 0; i < RTW89_RXCH_NUM; i++) { - rx_ring = &rtwpci->rx_rings[i]; + rx_ring = &rtwpci->rx.rings[i]; rx_ring->bd_ring.addr.idx = low_power ? bd_idx_addr->rx_bd_addrs[i] : dma_addr_set->rx[i].idx; @@ -1883,6 +2077,20 @@ static void rtw89_pci_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 data) writel(data, rtwpci->mmap + addr); } +static u32 rtw89_pci_ops_read32_pci_cfg(struct rtw89_dev *rtwdev, u32 addr) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct pci_dev *pdev = rtwpci->pdev; + u32 value; + int ret; + + ret = pci_read_config_dword(pdev, addr, &value); + if (ret) + return RTW89_R32_EA; + + return value; +} + static void rtw89_pci_ctrl_dma_trx(struct rtw89_dev *rtwdev, bool enable) { const struct rtw89_pci_info *info = rtwdev->pci_info; @@ -2641,6 +2849,10 @@ static void rtw89_pci_set_dbg(struct rtw89_dev *rtwdev) rtw89_write32_set(rtwdev, R_AX_PCIE_DBG_CTRL, B_AX_ASFF_FULL_NO_STK | B_AX_EN_STUCK_DBG); + rtw89_write32_mask(rtwdev, R_AX_PCIE_EXP_CTRL, + B_AX_EN_STUCK_DBG | B_AX_ASFF_FULL_NO_STK, + B_AX_EN_STUCK_DBG); + if (rtwdev->chip->chip_id == RTL8852A) rtw89_write32_set(rtwdev, R_AX_PCIE_EXP_CTRL, B_AX_EN_CHKDSC_NO_RX_STUCK); @@ -2724,7 +2936,7 @@ static int rtw89_pci_poll_rxdma_ch_idle_ax(struct rtw89_dev *rtwdev) static int rtw89_pci_poll_dma_all_idle(struct rtw89_dev *rtwdev) { - u32 ret; + int ret; ret = rtw89_pci_poll_txdma_ch_idle_ax(rtwdev); if (ret) { @@ -3214,15 +3426,6 @@ static void rtw89_pci_free_tx_ring(struct rtw89_dev *rtwdev, struct pci_dev *pdev, struct rtw89_pci_tx_ring *tx_ring) { - int ring_sz; - u8 *head; - dma_addr_t dma; - - head = tx_ring->bd_ring.head; - dma = tx_ring->bd_ring.dma; - ring_sz = tx_ring->bd_ring.desc_size * tx_ring->bd_ring.len; - dma_free_coherent(&pdev->dev, ring_sz, head, dma); - tx_ring->bd_ring.head = NULL; } @@ -3230,6 +3433,7 @@ static void rtw89_pci_free_tx_rings(struct rtw89_dev *rtwdev, struct pci_dev *pdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct rtw89_pci_dma_pool *bd_pool = &rtwpci->tx.bd_pool; const struct rtw89_pci_info *info = rtwdev->pci_info; struct rtw89_pci_tx_ring *tx_ring; int i; @@ -3237,10 +3441,12 @@ static void rtw89_pci_free_tx_rings(struct rtw89_dev *rtwdev, for (i = 0; i < RTW89_TXCH_NUM; i++) { if (info->tx_dma_ch_mask & BIT(i)) continue; - tx_ring = &rtwpci->tx_rings[i]; + tx_ring = &rtwpci->tx.rings[i]; rtw89_pci_free_tx_wd_ring(rtwdev, pdev, tx_ring); rtw89_pci_free_tx_ring(rtwdev, pdev, tx_ring); } + + dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma); } static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev, @@ -3251,8 +3457,6 @@ static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev, struct sk_buff *skb; dma_addr_t dma; u32 buf_sz; - u8 *head; - int ring_sz = rx_ring->bd_ring.desc_size * rx_ring->bd_ring.len; int i; buf_sz = rx_ring->buf_sz; @@ -3268,10 +3472,6 @@ static void rtw89_pci_free_rx_ring(struct rtw89_dev *rtwdev, rx_ring->buf[i] = NULL; } - head = rx_ring->bd_ring.head; - dma = rx_ring->bd_ring.dma; - dma_free_coherent(&pdev->dev, ring_sz, head, dma); - rx_ring->bd_ring.head = NULL; } @@ -3279,13 +3479,16 @@ static void rtw89_pci_free_rx_rings(struct rtw89_dev *rtwdev, struct pci_dev *pdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct rtw89_pci_dma_pool *bd_pool = &rtwpci->rx.bd_pool; struct rtw89_pci_rx_ring *rx_ring; int i; for (i = 0; i < RTW89_RXCH_NUM; i++) { - rx_ring = &rtwpci->rx_rings[i]; + rx_ring = &rtwpci->rx.rings[i]; rtw89_pci_free_rx_ring(rtwdev, pdev, rx_ring); } + + dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma); } static void rtw89_pci_free_trx_rings(struct rtw89_dev *rtwdev, @@ -3377,12 +3580,10 @@ static int rtw89_pci_alloc_tx_ring(struct rtw89_dev *rtwdev, struct pci_dev *pdev, struct rtw89_pci_tx_ring *tx_ring, u32 desc_size, u32 len, - enum rtw89_tx_channel txch) + enum rtw89_tx_channel txch, + void *head, dma_addr_t dma) { const struct rtw89_pci_ch_dma_addr *txch_addr; - int ring_sz = desc_size * len; - u8 *head; - dma_addr_t dma; int ret; ret = rtw89_pci_alloc_tx_wd_ring(rtwdev, pdev, tx_ring, txch); @@ -3397,12 +3598,6 @@ static int rtw89_pci_alloc_tx_ring(struct rtw89_dev *rtwdev, goto err_free_wd_ring; } - head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); - if (!head) { - ret = -ENOMEM; - goto err_free_wd_ring; - } - INIT_LIST_HEAD(&tx_ring->busy_pages); tx_ring->bd_ring.head = head; tx_ring->bd_ring.dma = dma; @@ -3425,25 +3620,48 @@ static int rtw89_pci_alloc_tx_rings(struct rtw89_dev *rtwdev, struct pci_dev *pdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct rtw89_pci_dma_pool *bd_pool = &rtwpci->tx.bd_pool; const struct rtw89_pci_info *info = rtwdev->pci_info; struct rtw89_pci_tx_ring *tx_ring; + u32 i, tx_allocated; + dma_addr_t dma; u32 desc_size; + u32 ring_sz; + u32 pool_sz; + u32 ch_num; + void *head; u32 len; - u32 i, tx_allocated; int ret; + BUILD_BUG_ON(RTW89_PCI_TXBD_NUM_MAX % 16); + + desc_size = sizeof(struct rtw89_pci_tx_bd_32); + len = RTW89_PCI_TXBD_NUM_MAX; + ch_num = RTW89_TXCH_NUM - hweight32(info->tx_dma_ch_mask); + ring_sz = desc_size * len; + pool_sz = ring_sz * ch_num; + + head = dma_alloc_coherent(&pdev->dev, pool_sz, &dma, GFP_KERNEL); + if (!head) + return -ENOMEM; + + bd_pool->head = head; + bd_pool->dma = dma; + bd_pool->size = pool_sz; + for (i = 0; i < RTW89_TXCH_NUM; i++) { if (info->tx_dma_ch_mask & BIT(i)) continue; - tx_ring = &rtwpci->tx_rings[i]; - desc_size = sizeof(struct rtw89_pci_tx_bd_32); - len = RTW89_PCI_TXBD_NUM_MAX; + tx_ring = &rtwpci->tx.rings[i]; ret = rtw89_pci_alloc_tx_ring(rtwdev, pdev, tx_ring, - desc_size, len, i); + desc_size, len, i, head, dma); if (ret) { rtw89_err(rtwdev, "failed to alloc tx ring %d\n", i); goto err_free; } + + head += ring_sz; + dma += ring_sz; } return 0; @@ -3451,24 +3669,24 @@ static int rtw89_pci_alloc_tx_rings(struct rtw89_dev *rtwdev, err_free: tx_allocated = i; for (i = 0; i < tx_allocated; i++) { - tx_ring = &rtwpci->tx_rings[i]; + tx_ring = &rtwpci->tx.rings[i]; rtw89_pci_free_tx_ring(rtwdev, pdev, tx_ring); } + dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma); + return ret; } static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev, struct pci_dev *pdev, struct rtw89_pci_rx_ring *rx_ring, - u32 desc_size, u32 len, u32 rxch) + u32 desc_size, u32 len, u32 rxch, + void *head, dma_addr_t dma) { const struct rtw89_pci_info *info = rtwdev->pci_info; const struct rtw89_pci_ch_dma_addr *rxch_addr; struct sk_buff *skb; - u8 *head; - dma_addr_t dma; - int ring_sz = desc_size * len; int buf_sz = RTW89_PCI_RX_BUF_SIZE; int i, allocated; int ret; @@ -3479,12 +3697,6 @@ static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev, return ret; } - head = dma_alloc_coherent(&pdev->dev, ring_sz, &dma, GFP_KERNEL); - if (!head) { - ret = -ENOMEM; - goto err; - } - rx_ring->bd_ring.head = head; rx_ring->bd_ring.dma = dma; rx_ring->bd_ring.len = len; @@ -3533,12 +3745,8 @@ static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev, rx_ring->buf[i] = NULL; } - head = rx_ring->bd_ring.head; - dma = rx_ring->bd_ring.dma; - dma_free_coherent(&pdev->dev, ring_sz, head, dma); - rx_ring->bd_ring.head = NULL; -err: + return ret; } @@ -3546,22 +3754,43 @@ static int rtw89_pci_alloc_rx_rings(struct rtw89_dev *rtwdev, struct pci_dev *pdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct rtw89_pci_dma_pool *bd_pool = &rtwpci->rx.bd_pool; struct rtw89_pci_rx_ring *rx_ring; + int i, rx_allocated; + dma_addr_t dma; u32 desc_size; + u32 ring_sz; + u32 pool_sz; + void *head; u32 len; - int i, rx_allocated; int ret; + desc_size = sizeof(struct rtw89_pci_rx_bd_32); + len = RTW89_PCI_RXBD_NUM_MAX; + ring_sz = desc_size * len; + pool_sz = ring_sz * RTW89_RXCH_NUM; + + head = dma_alloc_coherent(&pdev->dev, pool_sz, &dma, GFP_KERNEL); + if (!head) + return -ENOMEM; + + bd_pool->head = head; + bd_pool->dma = dma; + bd_pool->size = pool_sz; + for (i = 0; i < RTW89_RXCH_NUM; i++) { - rx_ring = &rtwpci->rx_rings[i]; - desc_size = sizeof(struct rtw89_pci_rx_bd_32); - len = RTW89_PCI_RXBD_NUM_MAX; + rx_ring = &rtwpci->rx.rings[i]; + ret = rtw89_pci_alloc_rx_ring(rtwdev, pdev, rx_ring, - desc_size, len, i); + desc_size, len, i, + head, dma); if (ret) { rtw89_err(rtwdev, "failed to alloc rx ring %d\n", i); goto err_free; } + + head += ring_sz; + dma += ring_sz; } return 0; @@ -3569,10 +3798,12 @@ static int rtw89_pci_alloc_rx_rings(struct rtw89_dev *rtwdev, err_free: rx_allocated = i; for (i = 0; i < rx_allocated; i++) { - rx_ring = &rtwpci->rx_rings[i]; + rx_ring = &rtwpci->rx.rings[i]; rtw89_pci_free_rx_ring(rtwdev, pdev, rx_ring); } + dma_free_coherent(&pdev->dev, bd_pool->size, bd_pool->head, bd_pool->dma); + return ret; } @@ -3779,6 +4010,42 @@ void rtw89_pci_config_intr_mask_v2(struct rtw89_dev *rtwdev) } EXPORT_SYMBOL(rtw89_pci_config_intr_mask_v2); +static void rtw89_pci_recovery_intr_mask_v3(struct rtw89_dev *rtwdev) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + + rtwpci->ind_intrs = B_BE_HS0_IND_INT_EN0; + rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN | + B_BE_SPSANA_OCP_INT_EN | B_BE_SPS_OCP_INT_EN; + rtwpci->intrs[0] = 0; + rtwpci->intrs[1] = 0; +} + +static void rtw89_pci_default_intr_mask_v3(struct rtw89_dev *rtwdev) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + + rtwpci->ind_intrs = B_BE_HS0_IND_INT_EN0; + rtwpci->halt_c2h_intrs = B_BE_HALT_C2H_INT_EN | B_BE_WDT_TIMEOUT_INT_EN | + B_BE_SPSANA_OCP_INT_EN | B_BE_SPS_OCP_INT_EN; + rtwpci->intrs[0] = 0; + rtwpci->intrs[1] = B_BE_PCIE_RDU_CH1_IMR | + B_BE_PCIE_RDU_CH0_IMR | + B_BE_PCIE_RX_RX0P2_IMR0_V1 | + B_BE_PCIE_RX_RPQ0_IMR0_V1; +} + +void rtw89_pci_config_intr_mask_v3(struct rtw89_dev *rtwdev) +{ + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + + if (rtwpci->under_recovery) + rtw89_pci_recovery_intr_mask_v3(rtwdev); + else + rtw89_pci_default_intr_mask_v3(rtwdev); +} +EXPORT_SYMBOL(rtw89_pci_config_intr_mask_v3); + static int rtw89_pci_request_irq(struct rtw89_dev *rtwdev, struct pci_dev *pdev) { @@ -4161,7 +4428,7 @@ static int rtw89_pci_lv1rst_stop_dma_ax(struct rtw89_dev *rtwdev) static int rtw89_pci_lv1rst_start_dma_ax(struct rtw89_dev *rtwdev) { - u32 ret; + int ret; if (rtwdev->chip->chip_id == RTL8852C) return 0; @@ -4175,7 +4442,7 @@ static int rtw89_pci_lv1rst_start_dma_ax(struct rtw89_dev *rtwdev) return ret; rtw89_pci_ctrl_dma_all(rtwdev, true); - return ret; + return 0; } static int rtw89_pci_ops_mac_lv1_recovery(struct rtw89_dev *rtwdev, @@ -4407,6 +4674,7 @@ const struct rtw89_pci_isr_def rtw89_pci_isr_ax = { .isr_rdu = B_AX_RDU_INT, .isr_halt_c2h = B_AX_HALT_C2H_INT_EN, .isr_wdt_timeout = B_AX_WDT_TIMEOUT_INT_EN, + .isr_sps_ocp = 0, .isr_clear_rpq = {R_AX_PCIE_HISR00, B_AX_RPQDMA_INT | B_AX_RPQBD_FULL_INT}, .isr_clear_rxq = {R_AX_PCIE_HISR00, B_AX_RXP1DMA_INT | B_AX_RXDMA_INT | B_AX_RDU_INT}, @@ -4455,6 +4723,8 @@ static const struct rtw89_hci_ops rtw89_pci_ops = { .write16 = rtw89_pci_ops_write16, .write32 = rtw89_pci_ops_write32, + .read32_pci_cfg = rtw89_pci_ops_read32_pci_cfg, + .mac_pre_init = rtw89_pci_ops_mac_pre_init, .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit, .mac_post_init = rtw89_pci_ops_mac_post_init, @@ -4502,6 +4772,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) rtwdev->pci_info = info->bus.pci; rtwdev->hci.ops = &rtw89_pci_ops; rtwdev->hci.type = RTW89_HCI_TYPE_PCIE; + rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_PCIE; rtwdev->hci.rpwm_addr = pci_info->rpwm_addr; rtwdev->hci.cpwm_addr = pci_info->cpwm_addr; diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h index 08309926fd54a..12043636405a6 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.h +++ b/drivers/net/wireless/realtek/rtw89/pci.h @@ -55,6 +55,8 @@ #define B_AX_CALIB_EN BIT(13) #define B_AX_DIV GENMASK(15, 14) #define RAC_SET_PPR_V1 0x31 +#define RAC_ANA41 0x41 +#define PHY_ERR_FLAG_EN BIT(6) #define R_AX_DBI_FLAG 0x1090 #define B_AX_DBI_RFLAG BIT(17) @@ -145,6 +147,11 @@ #define R_RAC_DIRECT_OFFSET_BE_LANE0_G2 0x3900 #define R_RAC_DIRECT_OFFSET_BE_LANE1_G2 0x3980 +#define RAC_DIRECT_OFFESET_L0_G1 0x3800 +#define RAC_DIRECT_OFFESET_L1_G1 0x3900 +#define RAC_DIRECT_OFFESET_L0_G2 0x3A00 +#define RAC_DIRECT_OFFESET_L1_G2 0x3B00 + #define RTW89_PCI_WR_RETRY_CNT 20 /* Interrupts */ @@ -296,6 +303,10 @@ #define B_BE_PCIE_EN_AUX_CLK BIT(0) #define R_BE_PCIE_PS_CTRL 0x3008 +#define B_BE_ASPM_L11_EN BIT(19) +#define B_BE_ASPM_L12_EN BIT(18) +#define B_BE_PCIPM_L11_EN BIT(17) +#define B_BE_PCIPM_L12_EN BIT(16) #define B_BE_RSM_L0S_EN BIT(8) #define B_BE_CMAC_EXIT_L1_EN BIT(7) #define B_BE_DMAC0_EXIT_L1_EN BIT(6) @@ -372,6 +383,14 @@ #define B_BE_HS0ISR_IND_INT BIT(0) #define R_BE_PCIE_DMA_IMR_0_V1 0x30B8 +#define B_BE_PCIE_RDU_CH7_IMR BIT(31) +#define B_BE_PCIE_RDU_CH6_IMR BIT(30) +#define B_BE_PCIE_RDU_CH5_IMR BIT(29) +#define B_BE_PCIE_RDU_CH4_IMR BIT(28) +#define B_BE_PCIE_RDU_CH3_IMR BIT(27) +#define B_BE_PCIE_RDU_CH2_IMR BIT(26) +#define B_BE_PCIE_RDU_CH1_IMR BIT(25) +#define B_BE_PCIE_RDU_CH0_IMR BIT(24) #define B_BE_PCIE_RX_RX1P1_IMR0_V1 BIT(23) #define B_BE_PCIE_RX_RX0P1_IMR0_V1 BIT(22) #define B_BE_PCIE_RX_ROQ1_IMR0_V1 BIT(21) @@ -397,6 +416,14 @@ #define B_BE_PCIE_TX_CH0_IMR0 BIT(0) #define R_BE_PCIE_DMA_ISR 0x30BC +#define B_BE_PCIE_RDU_CH7_INT BIT(31) +#define B_BE_PCIE_RDU_CH6_INT BIT(30) +#define B_BE_PCIE_RDU_CH5_INT BIT(29) +#define B_BE_PCIE_RDU_CH4_INT BIT(28) +#define B_BE_PCIE_RDU_CH3_INT BIT(27) +#define B_BE_PCIE_RDU_CH2_INT BIT(26) +#define B_BE_PCIE_RDU_CH1_INT BIT(25) +#define B_BE_PCIE_RDU_CH0_INT BIT(24) #define B_BE_PCIE_RX_RX1P1_ISR_V1 BIT(23) #define B_BE_PCIE_RX_RX0P1_ISR_V1 BIT(22) #define B_BE_PCIE_RX_ROQ1_ISR_V1 BIT(21) @@ -426,9 +453,13 @@ #define B_BE_RDU_CH4_INT_IMR_V1 BIT(29) #define B_BE_RDU_CH3_INT_IMR_V1 BIT(28) #define B_BE_RDU_CH2_INT_IMR_V1 BIT(27) +#define B_BE_RDU_CH1_INT_EN_V2 BIT(27) #define B_BE_RDU_CH1_INT_IMR_V1 BIT(26) +#define B_BE_RDU_CH0_INT_EN_V2 BIT(26) #define B_BE_RDU_CH0_INT_IMR_V1 BIT(25) +#define B_BE_RXDMA_STUCK_INT_EN_V2 BIT(25) #define B_BE_RXDMA_STUCK_INT_EN_V1 BIT(24) +#define B_BE_TXDMA_STUCK_INT_EN_V2 BIT(24) #define B_BE_TXDMA_STUCK_INT_EN_V1 BIT(23) #define B_BE_TXDMA_CH14_INT_EN_V1 BIT(22) #define B_BE_TXDMA_CH13_INT_EN_V1 BIT(21) @@ -459,9 +490,13 @@ #define B_BE_RDU_CH4_INT_V1 BIT(29) #define B_BE_RDU_CH3_INT_V1 BIT(28) #define B_BE_RDU_CH2_INT_V1 BIT(27) +#define B_BE_RDU_CH1_INT_V2 BIT(27) #define B_BE_RDU_CH1_INT_V1 BIT(26) +#define B_BE_RDU_CH0_INT_V2 BIT(26) #define B_BE_RDU_CH0_INT_V1 BIT(25) +#define B_BE_RXDMA_STUCK_INT_V2 BIT(25) #define B_BE_RXDMA_STUCK_INT_V1 BIT(24) +#define B_BE_TXDMA_STUCK_INT_V2 BIT(24) #define B_BE_TXDMA_STUCK_INT_V1 BIT(23) #define B_BE_TXDMA_CH14_INT_V1 BIT(22) #define B_BE_TXDMA_CH13_INT_V1 BIT(21) @@ -743,31 +778,6 @@ #define R_AX_WP_ADDR_H_SEL8_11 0x133C #define R_AX_WP_ADDR_H_SEL12_15 0x1340 -#define R_BE_HAXI_DMA_STOP1 0xB010 -#define B_BE_STOP_WPDMA BIT(31) -#define B_BE_STOP_CH14 BIT(14) -#define B_BE_STOP_CH13 BIT(13) -#define B_BE_STOP_CH12 BIT(12) -#define B_BE_STOP_CH11 BIT(11) -#define B_BE_STOP_CH10 BIT(10) -#define B_BE_STOP_CH9 BIT(9) -#define B_BE_STOP_CH8 BIT(8) -#define B_BE_STOP_CH7 BIT(7) -#define B_BE_STOP_CH6 BIT(6) -#define B_BE_STOP_CH5 BIT(5) -#define B_BE_STOP_CH4 BIT(4) -#define B_BE_STOP_CH3 BIT(3) -#define B_BE_STOP_CH2 BIT(2) -#define B_BE_STOP_CH1 BIT(1) -#define B_BE_STOP_CH0 BIT(0) -#define B_BE_TX_STOP1_MASK (B_BE_STOP_CH0 | B_BE_STOP_CH1 | \ - B_BE_STOP_CH2 | B_BE_STOP_CH3 | \ - B_BE_STOP_CH4 | B_BE_STOP_CH5 | \ - B_BE_STOP_CH6 | B_BE_STOP_CH7 | \ - B_BE_STOP_CH8 | B_BE_STOP_CH9 | \ - B_BE_STOP_CH10 | B_BE_STOP_CH11 | \ - B_BE_STOP_CH12) - #define R_BE_CH0_TXBD_NUM_V1 0xB030 #define R_BE_CH1_TXBD_NUM_V1 0xB032 #define R_BE_CH2_TXBD_NUM_V1 0xB034 @@ -784,9 +794,25 @@ #define R_BE_CH13_TXBD_NUM_V1 0xB04C #define R_BE_CH14_TXBD_NUM_V1 0xB04E +#define R_BE_CH0_TXBD_CFG 0xB030 +#define R_BE_CH2_TXBD_CFG 0xB034 +#define R_BE_CH4_TXBD_CFG 0xB038 +#define R_BE_CH6_TXBD_CFG 0xB03C +#define R_BE_CH8_TXBD_CFG 0xB040 +#define R_BE_CH10_TXBD_CFG 0xB044 +#define R_BE_CH12_TXBD_CFG 0xB048 +#define B_BE_TX_FLAG BIT(14) +#define B_BE_TX_START_OFFSET_MASK GENMASK(12, 4) +#define B_BE_TX_NUM_SEL_MASK GENMASK(2, 0) + #define R_BE_RXQ0_RXBD_NUM_V1 0xB050 #define R_BE_RPQ0_RXBD_NUM_V1 0xB052 +#define R_BE_RX_CH0_RXBD_CONFIG 0xB050 +#define R_BE_RX_CH1_RXBD_CONFIG 0xB052 +#define B_BE_RX_START_OFFSET_MASK GENMASK(11, 4) +#define B_BE_RX_NUM_SEL_MASK GENMASK(2, 0) + #define R_BE_CH0_TXBD_IDX_V1 0xB100 #define R_BE_CH1_TXBD_IDX_V1 0xB104 #define R_BE_CH2_TXBD_IDX_V1 0xB108 @@ -837,11 +863,25 @@ #define R_BE_CH14_TXBD_DESA_L_V1 0xB270 #define R_BE_CH14_TXBD_DESA_H_V1 0xB274 +#define R_BE_ACQ_TXBD_DESA_L 0xB200 +#define B_BE_TX_ACQ_DESA_L_MASK GENMASK(31, 3) +#define R_BE_ACQ_TXBD_DESA_H 0xB204 +#define B_BE_TX_ACQ_DESA_H_MASK GENMASK(7, 0) +#define R_BE_NACQ_TXBD_DESA_L 0xB240 +#define B_BE_TX_NACQ_DESA_L_MASK GENMASK(31, 3) +#define R_BE_NACQ_TXBD_DESA_H 0xB244 +#define B_BE_TX_NACQ_DESA_H_MASK GENMASK(7, 0) + #define R_BE_RXQ0_RXBD_DESA_L_V1 0xB300 #define R_BE_RXQ0_RXBD_DESA_H_V1 0xB304 #define R_BE_RPQ0_RXBD_DESA_L_V1 0xB308 #define R_BE_RPQ0_RXBD_DESA_H_V1 0xB30C +#define R_BE_HOST0_RXBD_DESA_L 0xB300 +#define B_BE_RX_HOST0_DESA_L_MASK GENMASK(31, 3) +#define R_BE_HOST0_RXBD_DESA_H 0xB304 +#define B_BE_RX_HOST0_DESA_H_MASK GENMASK(7, 0) + #define R_BE_WP_ADDR_H_SEL0_3_V1 0xB420 #define R_BE_WP_ADDR_H_SEL4_7_V1 0xB424 #define R_BE_WP_ADDR_H_SEL8_11_V1 0xB428 @@ -920,6 +960,12 @@ #define R_BE_PCIE_CRPWM 0x30C4 #define R_BE_L1_2_CTRL_HCILDO 0x3110 +#define B_BE_PM_CLKREQ_EXT_RB BIT(11) +#define B_BE_PCIE_DIS_RTK_PRST_N_L1_2 BIT(10) +#define B_BE_PCIE_PRST_IN_L1_2_RB BIT(9) +#define B_BE_PCIE_PRST_SEL_RB_V1 BIT(8) +#define B_BE_PCIE_DIS_L2_CTRL_APHY_SUSB BIT(7) +#define B_BE_PCIE_DIS_L1_2_CTRL_APHY_SUSB BIT(6) #define B_BE_PCIE_DIS_L1_2_CTRL_HCILDO BIT(0) #define R_BE_PL1_DBG_INFO 0x3120 @@ -969,9 +1015,11 @@ #define B_BE_PL1_SER_PL1_EN BIT(31) #define B_BE_PL1_IGNORE_HOT_RST BIT(30) #define B_BE_PL1_TIMER_UNIT_MASK GENMASK(19, 17) +#define PCIE_SER_TIMER_UNIT 0x2 #define B_BE_PL1_TIMER_CLEAR BIT(0) #define R_BE_REG_PL1_MASK 0x34B0 +#define B_BE_SER_LTSSM_UNSTABLE_MASK BIT(6) #define B_BE_SER_PCLKREQ_ACK_MASK BIT(5) #define B_BE_SER_PM_CLK_MASK BIT(4) #define B_BE_SER_LTSSM_IMR BIT(3) @@ -1001,6 +1049,18 @@ #define B_BE_CLR_CH2_IDX BIT(2) #define B_BE_CLR_CH1_IDX BIT(1) #define B_BE_CLR_CH0_IDX BIT(0) +#define B_BE_CLR_ALL_IDX_MASK (B_BE_CLR_CH0_IDX | B_BE_CLR_CH1_IDX | \ + B_BE_CLR_CH2_IDX | B_BE_CLR_CH3_IDX | \ + B_BE_CLR_CH4_IDX | B_BE_CLR_CH5_IDX | \ + B_BE_CLR_CH6_IDX | B_BE_CLR_CH7_IDX | \ + B_BE_CLR_CH8_IDX | B_BE_CLR_CH9_IDX | \ + B_BE_CLR_CH10_IDX | B_BE_CLR_CH11_IDX | \ + B_BE_CLR_CH12_IDX | B_BE_CLR_CH13_IDX | \ + B_BE_CLR_CH14_IDX) +#define B_BE_CLR_ALL_IDX_MASK_V1 (B_BE_CLR_CH0_IDX | B_BE_CLR_CH2_IDX | \ + B_BE_CLR_CH4_IDX | B_BE_CLR_CH6_IDX | \ + B_BE_CLR_CH8_IDX | B_BE_CLR_CH10_IDX | \ + B_BE_CLR_CH12_IDX) #define R_BE_RXBD_RWPTR_CLR1_V1 0xB018 #define B_BE_CLR_ROQ1_IDX_V1 BIT(5) @@ -1249,7 +1309,7 @@ struct rtw89_pci_bd_idx_addr { }; struct rtw89_pci_ch_dma_addr { - u32 num; + u32 num; /* also `offset` addr for group_bd_addr design */ u32 idx; u32 bdram; u32 desa_l; @@ -1271,6 +1331,7 @@ struct rtw89_pci_isr_def { u32 isr_rdu; u32 isr_halt_c2h; u32 isr_wdt_timeout; + u32 isr_sps_ocp; struct rtw89_reg2_def isr_clear_rpq; struct rtw89_reg2_def isr_clear_rxq; }; @@ -1311,6 +1372,13 @@ struct rtw89_pci_ssid_quirk { unsigned long bitmap; /* bitmap of rtw89_quirks */ }; +struct rtw89_pci_rpp_info { + u16 seq; + u8 qsel; + u8 tx_status; + u8 txch; +}; + struct rtw89_pci_info { const struct rtw89_pci_gen_def *gen_def; const struct rtw89_pci_isr_def *isr_def; @@ -1331,6 +1399,8 @@ struct rtw89_pci_info { bool rx_ring_eq_is_full; bool check_rx_tag; bool no_rxbd_fs; + bool group_bd_addr; + u32 rpp_fmt_size; u32 init_cfg_reg; u32 txhci_en_bit; @@ -1360,6 +1430,8 @@ struct rtw89_pci_info { u32 (*fill_txaddr_info)(struct rtw89_dev *rtwdev, void *txaddr_info_addr, u32 total_len, dma_addr_t dma, u8 *add_info_nr); + void (*parse_rpp)(struct rtw89_dev *rtwdev, void *rpp, + struct rtw89_pci_rpp_info *rpp_info); void (*config_intr_mask)(struct rtw89_dev *rtwdev); void (*enable_intr)(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void (*disable_intr)(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); @@ -1422,10 +1494,6 @@ struct rtw89_pci_tx_addr_info_32_v1 { #define RTW89_PCI_RPP_POLLUTED BIT(31) #define RTW89_PCI_RPP_SEQ GENMASK(30, 16) #define RTW89_PCI_RPP_TX_STATUS GENMASK(15, 13) -#define RTW89_TX_DONE 0x0 -#define RTW89_TX_RETRY_LIMIT 0x1 -#define RTW89_TX_LIFE_TIME 0x2 -#define RTW89_TX_MACID_DROP 0x3 #define RTW89_PCI_RPP_QSEL GENMASK(12, 8) #define RTW89_PCI_RPP_MACID GENMASK(7, 0) @@ -1433,6 +1501,19 @@ struct rtw89_pci_rpp_fmt { __le32 dword; } __packed; +#define RTW89_PCI_RPP_W0_MACID_V1_MASK GENMASK(9, 0) +#define RTW89_PCI_RPP_W0_DMA_CH_MASK GENMASK(13, 10) +#define RTW89_PCI_RPP_W0_TX_STATUS_V1_MASK GENMASK(16, 14) +#define RTW89_PCI_RPP_W0_PCIE_SEQ_V1_MASK GENMASK(31, 17) +#define RTW89_PCI_RPP_W1_QSEL_V1_MASK GENMASK(5, 0) +#define RTW89_PCI_RPP_W1_TID_IND BIT(6) +#define RTW89_PCI_RPP_W1_CHANGE_LINK BIT(7) + +struct rtw89_pci_rpp_fmt_v1 { + __le32 w0; + __le32 w1; +} __packed; + struct rtw89_pci_rx_bd_32 { __le16 buf_size; __le16 opt; @@ -1471,6 +1552,12 @@ struct rtw89_pci_dma_ring { u32 rp; /* hw idx */ }; +struct rtw89_pci_dma_pool { + void *head; + dma_addr_t dma; + u32 size; +}; + struct rtw89_pci_tx_wd_ring { void *head; dma_addr_t dma; @@ -1500,6 +1587,11 @@ struct rtw89_pci_tx_ring { u64 tx_mac_id_drop; }; +struct rtw89_pci_tx_rings { + struct rtw89_pci_tx_ring rings[RTW89_TXCH_NUM]; + struct rtw89_pci_dma_pool bd_pool; +}; + struct rtw89_pci_rx_ring { struct rtw89_pci_dma_ring bd_ring; struct sk_buff *buf[RTW89_PCI_RXBD_NUM_MAX]; @@ -1509,6 +1601,11 @@ struct rtw89_pci_rx_ring { u32 target_rx_tag:13; }; +struct rtw89_pci_rx_rings { + struct rtw89_pci_rx_ring rings[RTW89_RXCH_NUM]; + struct rtw89_pci_dma_pool bd_pool; +}; + struct rtw89_pci_isrs { u32 ind_isrs; u32 halt_c2h_isrs; @@ -1526,8 +1623,8 @@ struct rtw89_pci { bool low_power; bool under_recovery; bool enable_dac; - struct rtw89_pci_tx_ring tx_rings[RTW89_TXCH_NUM]; - struct rtw89_pci_rx_ring rx_rings[RTW89_RXCH_NUM]; + struct rtw89_pci_tx_rings tx; + struct rtw89_pci_rx_rings rx; struct sk_buff_head h2c_queue; struct sk_buff_head h2c_release_queue; DECLARE_BITMAP(kick_map, RTW89_TXCH_NUM); @@ -1540,10 +1637,7 @@ struct rtw89_pci { static inline struct rtw89_pci_rx_info *RTW89_PCI_RX_SKB_CB(struct sk_buff *skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - BUILD_BUG_ON(sizeof(struct rtw89_pci_tx_data) > - sizeof(info->status.status_driver_data)); + BUILD_BUG_ON(sizeof(struct rtw89_pci_rx_info) > sizeof(skb->cb)); return (struct rtw89_pci_rx_info *)skb->cb; } @@ -1574,6 +1668,10 @@ static inline struct rtw89_pci_tx_data *RTW89_PCI_TX_SKB_CB(struct sk_buff *skb) { struct rtw89_tx_skb_data *data = RTW89_TX_SKB_CB(skb); + BUILD_BUG_ON(sizeof(struct rtw89_tx_skb_data) + + sizeof(struct rtw89_pci_tx_data) > + sizeof_field(struct ieee80211_tx_info, driver_data)); + return (struct rtw89_pci_tx_data *)data->hci_priv; } @@ -1629,10 +1727,12 @@ extern const struct pci_error_handlers rtw89_pci_err_handler; extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set; extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_v1; extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be; +extern const struct rtw89_pci_ch_dma_addr_set rtw89_pci_ch_dma_addr_set_be_v1; extern const struct rtw89_pci_bd_ram rtw89_bd_ram_table_dual[RTW89_TXCH_NUM]; extern const struct rtw89_pci_bd_ram rtw89_bd_ram_table_single[RTW89_TXCH_NUM]; extern const struct rtw89_pci_isr_def rtw89_pci_isr_ax; extern const struct rtw89_pci_isr_def rtw89_pci_isr_be; +extern const struct rtw89_pci_isr_def rtw89_pci_isr_be_v1; extern const struct rtw89_pci_gen_def rtw89_pci_gen_ax; extern const struct rtw89_pci_gen_def rtw89_pci_gen_be; @@ -1651,16 +1751,23 @@ 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_parse_rpp(struct rtw89_dev *rtwdev, void *_rpp, + struct rtw89_pci_rpp_info *rpp_info); +void rtw89_pci_parse_rpp_v1(struct rtw89_dev *rtwdev, void *_rpp, + struct rtw89_pci_rpp_info *rpp_info); 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_config_intr_mask_v2(struct rtw89_dev *rtwdev); +void rtw89_pci_config_intr_mask_v3(struct rtw89_dev *rtwdev); void rtw89_pci_enable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void rtw89_pci_disable_intr(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void rtw89_pci_enable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void rtw89_pci_disable_intr_v1(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void rtw89_pci_enable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void rtw89_pci_disable_intr_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); +void rtw89_pci_enable_intr_v3(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); +void rtw89_pci_disable_intr_v3(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci); void rtw89_pci_recognize_intrs(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci, struct rtw89_pci_isrs *isrs); @@ -1670,6 +1777,9 @@ void rtw89_pci_recognize_intrs_v1(struct rtw89_dev *rtwdev, void rtw89_pci_recognize_intrs_v2(struct rtw89_dev *rtwdev, struct rtw89_pci *rtwpci, struct rtw89_pci_isrs *isrs); +void rtw89_pci_recognize_intrs_v3(struct rtw89_dev *rtwdev, + struct rtw89_pci *rtwpci, + struct rtw89_pci_isrs *isrs); static inline u32 rtw89_chip_fill_txaddr_info(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c index 7547031db9afc..12065aba8053e 100644 --- a/drivers/net/wireless/realtek/rtw89/pci_be.c +++ b/drivers/net/wireless/realtek/rtw89/pci_be.c @@ -46,6 +46,14 @@ static void rtw89_pci_aspm_set_be(struct rtw89_dev *rtwdev, bool enable) static void rtw89_pci_l1ss_set_be(struct rtw89_dev *rtwdev, bool enable) { + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + struct rtw89_hal *hal = &rtwdev->hal; + + if (enable && chip_id == RTL8922D && hal->cid == RTL8922D_CID7090) + rtw89_write32_set(rtwdev, R_BE_PCIE_PS_CTRL, + B_BE_ASPM_L11_EN | B_BE_ASPM_L12_EN | + B_BE_PCIPM_L11_EN | B_BE_PCIPM_L12_EN); + if (enable) rtw89_write32_set(rtwdev, R_BE_PCIE_MIX_CFG, B_BE_L1SUB_ENABLE); @@ -154,7 +162,7 @@ static void rtw89_pci_ctrl_trxdma_pcie_be(struct rtw89_dev *rtwdev, rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val); - if (io_en == MAC_AX_PCIE_ENABLE) + if (io_en == MAC_AX_PCIE_ENABLE && rtwdev->chip->chip_id == RTL8922A) rtw89_write32_mask(rtwdev, R_BE_HAXI_MST_WDT_TIMEOUT_SEL_V1, B_BE_HAXI_MST_WDT_TIMEOUT_SEL_MASK, 4); } @@ -162,32 +170,36 @@ static void rtw89_pci_ctrl_trxdma_pcie_be(struct rtw89_dev *rtwdev, static void rtw89_pci_clr_idx_all_be(struct rtw89_dev *rtwdev) { struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_pci_rx_ring *rx_ring; u32 val; - val = B_BE_CLR_CH0_IDX | B_BE_CLR_CH1_IDX | B_BE_CLR_CH2_IDX | - B_BE_CLR_CH3_IDX | B_BE_CLR_CH4_IDX | B_BE_CLR_CH5_IDX | - B_BE_CLR_CH6_IDX | B_BE_CLR_CH7_IDX | B_BE_CLR_CH8_IDX | - B_BE_CLR_CH9_IDX | B_BE_CLR_CH10_IDX | B_BE_CLR_CH11_IDX | - B_BE_CLR_CH12_IDX | B_BE_CLR_CH13_IDX | B_BE_CLR_CH14_IDX; + if (chip->chip_id == RTL8922A) + val = B_BE_CLR_ALL_IDX_MASK; + else + val = B_BE_CLR_ALL_IDX_MASK_V1; + rtw89_write32(rtwdev, R_BE_TXBD_RWPTR_CLR1, val); rtw89_write32(rtwdev, R_BE_RXBD_RWPTR_CLR1_V1, B_BE_CLR_RXQ0_IDX | B_BE_CLR_RPQ0_IDX); - rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RXQ]; + rx_ring = &rtwpci->rx.rings[RTW89_RXCH_RXQ]; rtw89_write16(rtwdev, R_BE_RXQ0_RXBD_IDX_V1, rx_ring->bd_ring.len - 1); - rx_ring = &rtwpci->rx_rings[RTW89_RXCH_RPQ]; + rx_ring = &rtwpci->rx.rings[RTW89_RXCH_RPQ]; rtw89_write16(rtwdev, R_BE_RPQ0_RXBD_IDX_V1, rx_ring->bd_ring.len - 1); } static int rtw89_pci_poll_txdma_ch_idle_be(struct rtw89_dev *rtwdev) { + const struct rtw89_pci_info *info = rtwdev->pci_info; + u32 dma_busy1 = info->dma_busy1.addr; + u32 check = info->dma_busy1.mask; u32 val; - return read_poll_timeout(rtw89_read32, val, (val & DMA_BUSY1_CHECK_BE) == 0, - 10, 1000, false, rtwdev, R_BE_HAXI_DMA_BUSY1); + return read_poll_timeout(rtw89_read32, val, (val & check) == 0, + 10, 1000, false, rtwdev, dma_busy1); } static int rtw89_pci_poll_rxdma_ch_idle_be(struct rtw89_dev *rtwdev) @@ -223,20 +235,24 @@ static int rtw89_pci_poll_dma_all_idle_be(struct rtw89_dev *rtwdev) static void rtw89_pci_mode_op_be(struct rtw89_dev *rtwdev) { const struct rtw89_pci_info *info = rtwdev->pci_info; + const struct rtw89_chip_info *chip = rtwdev->chip; u32 val32_init1, val32_rxapp, val32_exp; val32_init1 = rtw89_read32(rtwdev, R_BE_HAXI_INIT_CFG1); - val32_rxapp = rtw89_read32(rtwdev, R_BE_RX_APPEND_MODE); + if (chip->chip_id == RTL8922A) + val32_rxapp = rtw89_read32(rtwdev, R_BE_RX_APPEND_MODE); val32_exp = rtw89_read32(rtwdev, R_BE_HAXI_EXP_CTRL_V1); - if (info->rxbd_mode == MAC_AX_RXBD_PKT) { - val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_NORM, - B_BE_RXQ_RXBD_MODE_MASK); - } else if (info->rxbd_mode == MAC_AX_RXBD_SEP) { - val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_SEP, - B_BE_RXQ_RXBD_MODE_MASK); - val32_rxapp = u32_replace_bits(val32_rxapp, 0, - B_BE_APPEND_LEN_MASK); + if (chip->chip_id == RTL8922A) { + if (info->rxbd_mode == MAC_AX_RXBD_PKT) { + val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_NORM, + B_BE_RXQ_RXBD_MODE_MASK); + } else if (info->rxbd_mode == MAC_AX_RXBD_SEP) { + val32_init1 = u32_replace_bits(val32_init1, PCIE_RXBD_SEP, + B_BE_RXQ_RXBD_MODE_MASK); + val32_rxapp = u32_replace_bits(val32_rxapp, 0, + B_BE_APPEND_LEN_MASK); + } } val32_init1 = u32_replace_bits(val32_init1, info->tx_burst, @@ -251,7 +267,8 @@ static void rtw89_pci_mode_op_be(struct rtw89_dev *rtwdev) B_BE_CFG_WD_PERIOD_ACTIVE_MASK); rtw89_write32(rtwdev, R_BE_HAXI_INIT_CFG1, val32_init1); - rtw89_write32(rtwdev, R_BE_RX_APPEND_MODE, val32_rxapp); + if (chip->chip_id == RTL8922A) + rtw89_write32(rtwdev, R_BE_RX_APPEND_MODE, val32_rxapp); rtw89_write32(rtwdev, R_BE_HAXI_EXP_CTRL_V1, val32_exp); } @@ -277,6 +294,10 @@ static void rtw89_pci_debounce_be(struct rtw89_dev *rtwdev) static void rtw89_pci_ldo_low_pwr_be(struct rtw89_dev *rtwdev) { + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + struct rtw89_hal *hal = &rtwdev->hal; + u32 clr; + rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_PSUS_OFF_CAPC_EN); rtw89_write32_set(rtwdev, R_BE_SYS_PAGE_CLK_GATED, B_BE_SOP_OFFPOOBS_PC | B_BE_CPHY_AUXCLK_OP | @@ -284,7 +305,16 @@ static void rtw89_pci_ldo_low_pwr_be(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_PCIE_FORCE_IBX_EN | B_BE_PCIE_DIS_L2_RTK_PERST | B_BE_PCIE_DIS_L2__CTRL_LDO_HCI); - rtw89_write32_clr(rtwdev, R_BE_L1_2_CTRL_HCILDO, B_BE_PCIE_DIS_L1_2_CTRL_HCILDO); + + if (chip_id == RTL8922D && hal->cid == RTL8922D_CID7090) + clr = B_BE_PCIE_DIS_L1_2_CTRL_HCILDO | + B_BE_PCIE_DIS_L1_2_CTRL_APHY_SUSB | + B_BE_PCIE_DIS_RTK_PRST_N_L1_2 | + B_BE_PCIE_DIS_L2_CTRL_APHY_SUSB; + else + clr = B_BE_PCIE_DIS_L1_2_CTRL_HCILDO; + + rtw89_write32_clr(rtwdev, R_BE_L1_2_CTRL_HCILDO, clr); } static void rtw89_pci_pcie_setting_be(struct rtw89_dev *rtwdev) @@ -300,11 +330,25 @@ static void rtw89_pci_pcie_setting_be(struct rtw89_dev *rtwdev) rtw89_write32_set(rtwdev, R_BE_EFUSE_CTRL_2_V1, B_BE_R_SYM_AUTOLOAD_WITH_PMC_SEL); rtw89_write32_set(rtwdev, R_BE_PCIE_LAT_CTRL, B_BE_SYM_AUX_CLK_SEL); + + if (chip->chip_id != RTL8922D) + return; + + rtw89_write32_set(rtwdev, R_BE_RSV_CTRL, B_BE_R_SYM_PRST_CPHY_RST); + rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_USUS_OFFCAPC_EN); } static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev) { + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + struct rtw89_hal *hal = &rtwdev->hal; u32 val32; + int ret; + + if (chip_id == RTL8922D) + goto be2_chips; + else if (chip_id != RTL8922A) + return; rtw89_write32(rtwdev, R_BE_PL1_DBG_INFO, 0x0); rtw89_write32_set(rtwdev, R_BE_FWS1IMR, B_BE_PCIE_SER_TIMEOUT_INDIC_EN); @@ -315,10 +359,48 @@ static void rtw89_pci_ser_setting_be(struct rtw89_dev *rtwdev) val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR | B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK; rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32); + + return; + +be2_chips: + rtw89_write32_clr(rtwdev, R_BE_PCIE_SER_DBG, B_BE_PCIE_SER_FLUSH_RSTB); + rtw89_write32_set(rtwdev, R_BE_PCIE_SER_DBG, B_BE_PCIE_SER_FLUSH_RSTB); + + rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G1 + + RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN); + rtw89_write16_clr(rtwdev, RAC_DIRECT_OFFESET_L0_G2 + + RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN); + rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G1 + + RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN); + rtw89_write16_set(rtwdev, RAC_DIRECT_OFFESET_L0_G2 + + RAC_ANA41 * RAC_MULT, PHY_ERR_FLAG_EN); + + val32 = rtw89_read32(rtwdev, R_BE_SER_PL1_CTRL); + val32 &= ~B_BE_PL1_SER_PL1_EN; + rtw89_write32(rtwdev, R_BE_SER_PL1_CTRL, val32); + + ret = read_poll_timeout_atomic(rtw89_read32, val32, !val32, + 1, 1000, false, rtwdev, R_BE_REG_PL1_ISR); + if (ret) + rtw89_warn(rtwdev, "[ERR] PCIE SER clear poll fail\n"); + + val32 = rtw89_read32(rtwdev, R_BE_REG_PL1_MASK); + val32 |= B_BE_SER_PMU_IMR | B_BE_SER_L1SUB_IMR | B_BE_SER_PM_MASTER_IMR | + B_BE_SER_LTSSM_IMR | B_BE_SER_PM_CLK_MASK | B_BE_SER_PCLKREQ_ACK_MASK | + B_BE_SER_LTSSM_UNSTABLE_MASK; + rtw89_write32(rtwdev, R_BE_REG_PL1_MASK, val32); + + rtw89_write32_mask(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_TIMER_UNIT_MASK, + PCIE_SER_TIMER_UNIT); + rtw89_write32_set(rtwdev, R_BE_SER_PL1_CTRL, B_BE_PL1_SER_PL1_EN); + + if (hal->cid == RTL8922D_CID7090) + rtw89_write32_set(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_SER_DETECT_EN); } static void rtw89_pci_ctrl_txdma_ch_be(struct rtw89_dev *rtwdev, bool enable) { + const struct rtw89_pci_info *info = rtwdev->pci_info; u32 mask_all; u32 val; @@ -327,6 +409,9 @@ static void rtw89_pci_ctrl_txdma_ch_be(struct rtw89_dev *rtwdev, bool enable) B_BE_STOP_CH6 | B_BE_STOP_CH7 | B_BE_STOP_CH8 | B_BE_STOP_CH9 | B_BE_STOP_CH10 | B_BE_STOP_CH11; + /* mask out unsupported channels for certains chips */ + mask_all &= info->dma_stop1.mask; + val = rtw89_read32(rtwdev, R_BE_HAXI_DMA_STOP1); val |= B_BE_STOP_CH13 | B_BE_STOP_CH14; @@ -409,6 +494,7 @@ static int rtw89_pci_ops_mac_pre_deinit_be(struct rtw89_dev *rtwdev) int rtw89_pci_ltr_set_v2(struct rtw89_dev *rtwdev, bool en) { u32 ctrl0, cfg0, cfg1, dec_ctrl, idle_ltcy, act_ltcy, dis_ltcy; + u32 ltr_idle_lat_ctrl, ltr_act_lat_ctrl; ctrl0 = rtw89_read32(rtwdev, R_BE_LTR_CTRL_0); if (rtw89_pci_ltr_is_err_reg_val(ctrl0)) @@ -451,8 +537,16 @@ int rtw89_pci_ltr_set_v2(struct rtw89_dev *rtwdev, bool en) cfg0 = u32_replace_bits(cfg0, 3, B_BE_LTR_IDX_IDLE_MASK); dec_ctrl = u32_replace_bits(dec_ctrl, 0, B_BE_LTR_IDX_DISABLE_V1_MASK); - rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX3_V1, 0x90039003); - rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX1_V1, 0x880b880b); + if (rtwdev->chip->chip_id == RTL8922A) { + ltr_idle_lat_ctrl = 0x90039003; + ltr_act_lat_ctrl = 0x880b880b; + } else { + ltr_idle_lat_ctrl = 0x90019001; + ltr_act_lat_ctrl = 0x88018801; + } + + rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX3_V1, ltr_idle_lat_ctrl); + rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX1_V1, ltr_act_lat_ctrl); rtw89_write32(rtwdev, R_BE_LTR_LATENCY_IDX0_V1, 0); rtw89_write32(rtwdev, R_BE_LTR_DECISION_CTRL_V1, dec_ctrl); rtw89_write32(rtwdev, R_BE_LTR_CFG_0, cfg0); @@ -669,11 +763,22 @@ const struct rtw89_pci_isr_def rtw89_pci_isr_be = { .isr_rdu = B_BE_RDU_CH1_INT_V1 | B_BE_RDU_CH0_INT_V1, .isr_halt_c2h = B_BE_HALT_C2H_INT, .isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT, + .isr_sps_ocp = 0, .isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1}, .isr_clear_rxq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RX0P2_ISR_V1}, }; EXPORT_SYMBOL(rtw89_pci_isr_be); +const struct rtw89_pci_isr_def rtw89_pci_isr_be_v1 = { + .isr_rdu = B_BE_PCIE_RDU_CH1_INT | B_BE_PCIE_RDU_CH0_INT, + .isr_halt_c2h = B_BE_HALT_C2H_INT, + .isr_wdt_timeout = B_BE_WDT_TIMEOUT_INT, + .isr_sps_ocp = B_BE_SPS_OCP_INT | B_BE_SPSANA_OCP_INT, + .isr_clear_rpq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RPQ0_ISR_V1}, + .isr_clear_rxq = {R_BE_PCIE_DMA_ISR, B_BE_PCIE_RX_RX0P2_ISR_V1}, +}; +EXPORT_SYMBOL(rtw89_pci_isr_be_v1); + const struct rtw89_pci_gen_def rtw89_pci_gen_be = { .mac_pre_init = rtw89_pci_ops_mac_pre_init_be, .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit_be, diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 00f20aa64e461..fede80515edd6 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -277,8 +277,7 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); - u8 he_ltf = mask->control[nl_band].he_ltf; - u8 he_gi = mask->control[nl_band].he_gi; + u8 ltf, gi; *fix_giltf_en = true; @@ -289,22 +288,28 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev, else *fix_giltf = RTW89_GILTF_2XHE08; - if (!(rtwsta_link->use_cfg_mask && link_sta->he_cap.has_he)) + if (!rtwsta_link->use_cfg_mask) + return; + + if (link_sta->he_cap.has_he) { + ltf = mask->control[nl_band].he_ltf; + gi = mask->control[nl_band].he_gi; + } else { return; + } - if (he_ltf == 2 && he_gi == 2) { + if (ltf == 2 && gi == 2) *fix_giltf = RTW89_GILTF_LGI_4XHE32; - } else if (he_ltf == 2 && he_gi == 0) { + else if (ltf == 2 && gi == 0) *fix_giltf = RTW89_GILTF_SGI_4XHE08; - } else if (he_ltf == 1 && he_gi == 1) { + else if (ltf == 1 && gi == 1) *fix_giltf = RTW89_GILTF_2XHE16; - } else if (he_ltf == 1 && he_gi == 0) { + else if (ltf == 1 && gi == 0) *fix_giltf = RTW89_GILTF_2XHE08; - } else if (he_ltf == 0 && he_gi == 1) { + else if (ltf == 0 && gi == 1) *fix_giltf = RTW89_GILTF_1XHE16; - } else if (he_ltf == 0 && he_gi == 0) { + else if (ltf == 0 && gi == 0) *fix_giltf = RTW89_GILTF_1XHE08; - } } static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, @@ -473,6 +478,10 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->ra_mask = ra_mask; ra->fix_giltf_en = fix_giltf_en; ra->fix_giltf = fix_giltf; + ra->partial_bw_er = link_sta->he_cap.has_he ? + !!(link_sta->he_cap.he_cap_elem.phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE) : 0; + ra->band = chan->band_type; if (!csi) return; @@ -559,6 +568,14 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, return true; } +enum __rtw89_hw_rate_invalid_bases { + /* no EHT rate for ax chip */ + RTW89_HW_RATE_EHT_NSS1_MCS0 = RTW89_HW_RATE_INVAL, + RTW89_HW_RATE_EHT_NSS2_MCS0 = RTW89_HW_RATE_INVAL, + RTW89_HW_RATE_EHT_NSS3_MCS0 = RTW89_HW_RATE_INVAL, + RTW89_HW_RATE_EHT_NSS4_MCS0 = RTW89_HW_RATE_INVAL, +}; + #define RTW89_HW_RATE_BY_CHIP_GEN(rate) \ { \ [RTW89_CHIP_AX] = RTW89_HW_RATE_ ## rate, \ @@ -642,6 +659,13 @@ void __rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, if (!next_pattern.enable) goto out; + if (unlikely(next_pattern.rate >= RTW89_HW_RATE_INVAL)) { + rtw89_debug(rtwdev, RTW89_DBG_RA, + "pattern invalid target: chip_gen %d, mode 0x%x\n", + chip_gen, next_pattern.ra_mode); + goto out; + } + rtwvif_link->rate_pattern = next_pattern; rtw89_debug(rtwdev, RTW89_DBG_RA, "configure pattern: rate 0x%x, mask 0x%llx, mode 0x%x\n", @@ -899,7 +923,8 @@ static u32 rtw89_phy_read_rf_a(struct rtw89_dev *rtwdev, 30, false, rtwdev, R_SWSI_V1, B_SWSI_R_DATA_DONE_V1); if (ret) { - rtw89_err(rtwdev, "read swsi busy\n"); + if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) + rtw89_err(rtwdev, "read swsi busy\n"); return INV_RF_DATA; } @@ -988,6 +1013,68 @@ u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, } EXPORT_SYMBOL(rtw89_phy_read_rf_v2); +static u32 rtw89_phy_read_full_rf_v3_a(struct rtw89_dev *rtwdev, + enum rtw89_rf_path rf_path, u32 addr) +{ + bool done; + u32 busy; + int ret; + u32 val; + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy, + 1, 30, false, + rtwdev, R_SW_SI_DATA_BE4, + B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4); + if (ret) { + rtw89_warn(rtwdev, "poll HWSI is busy\n"); + return INV_RF_DATA; + } + + val = u32_encode_bits(rf_path, GENMASK(10, 8)) | + u32_encode_bits(addr, GENMASK(7, 0)); + + rtw89_phy_write32_mask(rtwdev, R_SW_SI_READ_ADDR_BE4, B_SW_SI_READ_ADDR_BE4, val); + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, done, done, + 1, 30, false, + rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_DONE_BE4); + if (ret) { + rtw89_warn(rtwdev, "read HWSI is busy\n"); + return INV_RF_DATA; + } + + val = rtw89_phy_read32_mask(rtwdev, R_SW_SI_DATA_BE4, B_SW_SI_READ_DATA_BE4); + + return val; +} + +static u32 rtw89_phy_read_rf_v3_a(struct rtw89_dev *rtwdev, + enum rtw89_rf_path rf_path, u32 addr, u32 mask) +{ + u32 val; + + val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr); + + return (val & mask) >> __ffs(mask); +} + +u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, + u32 addr, u32 mask) +{ + bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK); + + if (rf_path >= rtwdev->chip->rf_path_num) { + rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path); + return INV_RF_DATA; + } + + if (ad_sel) + return rtw89_phy_read_rf(rtwdev, rf_path, addr, mask); + else + return rtw89_phy_read_rf_v3_a(rtwdev, rf_path, addr, mask); +} +EXPORT_SYMBOL(rtw89_phy_read_rf_v3); + bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask, u32 data) { @@ -1127,6 +1214,66 @@ bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, } EXPORT_SYMBOL(rtw89_phy_write_rf_v2); +static +bool rtw89_phy_write_full_rf_v3_a(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, + u32 addr, u32 data) +{ + u32 busy; + u32 val; + int ret; + + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, busy, !busy, + 1, 30, false, + rtwdev, R_SW_SI_DATA_BE4, + B_SW_SI_W_BUSY_BE4 | B_SW_SI_R_BUSY_BE4); + if (ret) { + rtw89_warn(rtwdev, "[%s] HWSI is busy\n", __func__); + return false; + } + + val = u32_encode_bits(rf_path, B_SW_SI_DATA_PATH_BE4) | + u32_encode_bits(addr, B_SW_SI_DATA_ADR_BE4) | + u32_encode_bits(data, B_SW_SI_DATA_DAT_BE4); + + rtw89_phy_write32(rtwdev, R_SW_SI_WDATA_BE4, val); + + return true; +} + +static +bool rtw89_phy_write_rf_a_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, + u32 addr, u32 mask, u32 data) +{ + u32 val; + + if (mask == RFREG_MASK) { + val = data; + } else { + val = rtw89_phy_read_full_rf_v3_a(rtwdev, rf_path, addr); + val &= ~mask; + val |= (data << __ffs(mask)) & mask; + } + + return rtw89_phy_write_full_rf_v3_a(rtwdev, rf_path, addr, val); +} + +bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, + u32 addr, u32 mask, u32 data) +{ + bool ad_sel = u32_get_bits(addr, RTW89_RF_ADDR_ADSEL_MASK); + + if (rf_path >= rtwdev->chip->rf_path_num) { + rtw89_err(rtwdev, "unsupported rf path (%d)\n", rf_path); + return INV_RF_DATA; + } + + if (ad_sel) + return rtw89_phy_write_rf(rtwdev, rf_path, addr, mask, data); + else + return rtw89_phy_write_rf_a_v3(rtwdev, rf_path, addr, mask, data); +} +EXPORT_SYMBOL(rtw89_phy_write_rf_v3); + static bool rtw89_chip_rf_v1(struct rtw89_dev *rtwdev) { return rtwdev->chip->ops->write_rf == rtw89_phy_write_rf_v1; @@ -1703,6 +1850,91 @@ void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev) rtw89_phy_bb_reset(rtwdev); } +void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + const struct rtw89_fw_element_hdr *afe_elm = elm_info->afe; + const struct rtw89_phy_afe_info *info; + u32 action, cat, class; + u32 addr, mask, val; + u32 poll, rpt; + u32 n, i; + + if (!afe_elm) + return; + + n = le32_to_cpu(afe_elm->size) / sizeof(*info); + + for (i = 0; i < n; i++) { + info = &afe_elm->u.afe.infos[i]; + + class = le32_to_cpu(info->class); + switch (class) { + case RTW89_FW_AFE_CLASS_P0: + case RTW89_FW_AFE_CLASS_P1: + case RTW89_FW_AFE_CLASS_CMN: + /* Currently support two paths */ + break; + case RTW89_FW_AFE_CLASS_P2: + case RTW89_FW_AFE_CLASS_P3: + case RTW89_FW_AFE_CLASS_P4: + default: + rtw89_warn(rtwdev, "unexpected AFE class %u\n", class); + continue; + } + + addr = le32_to_cpu(info->addr); + mask = le32_to_cpu(info->mask); + val = le32_to_cpu(info->val); + cat = le32_to_cpu(info->cat); + action = le32_to_cpu(info->action); + + switch (action) { + case RTW89_FW_AFE_ACTION_WRITE: + switch (cat) { + case RTW89_FW_AFE_CAT_MAC: + case RTW89_FW_AFE_CAT_MAC1: + rtw89_write32_mask(rtwdev, addr, mask, val); + break; + case RTW89_FW_AFE_CAT_AFEDIG: + case RTW89_FW_AFE_CAT_AFEDIG1: + rtw89_write32_mask(rtwdev, addr, mask, val); + break; + case RTW89_FW_AFE_CAT_BB: + rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_0); + break; + case RTW89_FW_AFE_CAT_BB1: + rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_1); + break; + default: + rtw89_warn(rtwdev, + "unexpected AFE writing action %u\n", action); + break; + } + break; + case RTW89_FW_AFE_ACTION_POLL: + for (poll = 0; poll <= 10; poll++) { + /* + * For CAT_BB, AFE reads register with mcu_offset 0, + * so both CAT_MAC and CAT_BB use the same method. + */ + rpt = rtw89_read32_mask(rtwdev, addr, mask); + if (rpt == val) + goto poll_done; + + fsleep(1); + } + rtw89_warn(rtwdev, "failed to poll AFE cat=%u addr=0x%x mask=0x%x\n", + cat, addr, mask); +poll_done: + break; + case RTW89_FW_AFE_ACTION_DELAY: + fsleep(addr); + break; + } + } +} + static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev) { rtw89_phy_write32(rtwdev, 0x8080, 0x4); @@ -2255,6 +2487,21 @@ static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel) } } +static bool rtw89_phy_validate_txpwr_limit_bw(struct rtw89_dev *rtwdev, + u8 band, u8 bw) +{ + switch (band) { + case RTW89_BAND_2G: + return bw < RTW89_2G_BW_NUM; + case RTW89_BAND_5G: + return bw < RTW89_5G_BW_NUM; + case RTW89_BAND_6G: + return bw < RTW89_6G_BW_NUM; + default: + return false; + } +} + s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch) { @@ -2279,6 +2526,11 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, }; s8 cstr; + if (!rtw89_phy_validate_txpwr_limit_bw(rtwdev, band, bw)) { + rtw89_warn(rtwdev, "invalid band %u bandwidth %u\n", band, bw); + return 0; + } + switch (band) { case RTW89_BAND_2G: if (has_ant_gain) @@ -2944,7 +3196,7 @@ static void __rtw89_phy_c2h_ra_rpt_iter(struct rtw89_sta_link *rtwsta_link, } if (mode == RTW89_RA_RPT_MODE_LEGACY) { - valid = rtw89_ra_report_to_bitrate(rtwdev, rate, &legacy_bitrate); + valid = rtw89_legacy_rate_to_bitrate(rtwdev, rate, &legacy_bitrate); if (!valid) return; } @@ -3057,6 +3309,7 @@ void (* const rtw89_phy_c2h_ra_handler[])(struct rtw89_dev *rtwdev, [RTW89_PHY_C2H_FUNC_STS_RPT] = rtw89_phy_c2h_ra_rpt, [RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT] = NULL, [RTW89_PHY_C2H_FUNC_TXSTS] = NULL, + [RTW89_PHY_C2H_FUNC_ACCELERATE_EN] = rtw89_fw_c2h_dummy_handler, }; static void @@ -3064,6 +3317,64 @@ rtw89_phy_c2h_lowrt_rty(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { } +static void +rtw89_phy_c2h_lps_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ + const struct rtw89_c2h_lps_rpt *c2h_rpt = (const void *)c2h->data; + const __le32 *data_a, *data_b; + u16 len_info, cr_len, idx; + const __le16 *addr; + const u8 *info; + + /* elements size of BBCR/BBMCUCR/RFCR are 6/6/10 bytes respectively */ + cr_len = c2h_rpt->cnt_bbcr * 6 + + c2h_rpt->cnt_bbmcucr * 6 + + c2h_rpt->cnt_rfcr * 10; + len_info = len - (sizeof(*c2h_rpt) + cr_len); + + if (len < sizeof(*c2h_rpt) + cr_len || len_info % 4 != 0) { + rtw89_debug(rtwdev, RTW89_DBG_PS, + "Invalid LPS RPT len(%d) TYPE(%d) CRCNT: BB(%d) MCU(%d) RF(%d)\n", + len, c2h_rpt->type, c2h_rpt->cnt_bbcr, + c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr); + return; + } + + rtw89_debug(rtwdev, RTW89_DBG_PS, + "LPS RPT TYPE(%d), CRCNT: BB(%d) MCU(%d) RF(%d)\n", + c2h_rpt->type, c2h_rpt->cnt_bbcr, + c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr); + + info = &c2h_rpt->data[0]; + for (idx = 0; idx < len_info; idx += 4, info += 4) + rtw89_debug(rtwdev, RTW89_DBG_PS, + "BB LPS INFO (%02d) - 0x%02x,0x%02x,0x%02x,0x%02x\n", + idx, info[3], info[2], info[1], info[0]); + + addr = (const void *)(info); + data_a = (const void *)(addr + c2h_rpt->cnt_bbcr); + for (idx = 0; idx < c2h_rpt->cnt_bbcr; idx++, addr++, data_a++) + rtw89_debug(rtwdev, RTW89_DBG_PS, + "LPS BB CR - 0x%04x=0x%08x\n", + le16_to_cpu(*addr), le32_to_cpu(*data_a)); + + addr = (const void *)data_a; + data_a = (const void *)(addr + c2h_rpt->cnt_bbmcucr); + for (idx = 0; idx < c2h_rpt->cnt_bbmcucr; idx++, addr++, data_a++) + rtw89_debug(rtwdev, RTW89_DBG_PS, + "LPS BBMCU - 0x%04x=0x%08x\n", + le16_to_cpu(*addr), le32_to_cpu(*data_a)); + + addr = (const void *)data_a; + data_a = (const void *)(addr + c2h_rpt->cnt_rfcr); + data_b = (const void *)(data_a + c2h_rpt->cnt_rfcr); + for (idx = 0; idx < c2h_rpt->cnt_rfcr; idx++, addr++, data_a++, data_b++) + rtw89_debug(rtwdev, RTW89_DBG_PS, + "LPS RFCR - 0x%04x=0x%05x,0x%05x\n", + le16_to_cpu(*addr), le32_to_cpu(*data_a), + le32_to_cpu(*data_b)); +} + static void rtw89_phy_c2h_fw_scan_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { @@ -3085,15 +3396,47 @@ void (* const rtw89_phy_c2h_dm_handler[])(struct rtw89_dev *rtwdev, [RTW89_PHY_C2H_DM_FUNC_SIGB] = NULL, [RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY] = rtw89_phy_c2h_lowrt_rty, [RTW89_PHY_C2H_DM_FUNC_MCC_DIG] = NULL, + [RTW89_PHY_C2H_DM_FUNC_LPS] = rtw89_phy_c2h_lps_rpt, + [RTW89_PHY_C2H_DM_FUNC_ENV_MNTR] = rtw89_fw_c2h_dummy_handler, [RTW89_PHY_C2H_DM_FUNC_FW_SCAN] = rtw89_phy_c2h_fw_scan_rpt, }; +static +void rtw89_phy_c2h_rfk_tas_pwr(struct rtw89_dev *rtwdev, + const struct rtw89_c2h_rf_tas_rpt_log *content) +{ + const enum rtw89_sar_sources src = rtwdev->sar.src; + struct rtw89_tas_info *tas = &rtwdev->tas; + u64 linear = 0; + u32 i, cur_idx; + s16 txpwr; + + if (!tas->enable || src == RTW89_SAR_SOURCE_NONE) + return; + + cur_idx = le32_to_cpu(content->cur_idx); + for (i = 0; i < cur_idx; i++) { + txpwr = le16_to_cpu(content->txpwr_history[i]); + linear += rtw89_db_quarter_to_linear(txpwr); + + rtw89_debug(rtwdev, RTW89_DBG_SAR, + "tas: index: %u, txpwr: %d\n", i, txpwr); + } + + if (cur_idx == 0) + tas->instant_txpwr = rtw89_db_to_linear(0); + else + tas->instant_txpwr = DIV_ROUND_DOWN_ULL(linear, cur_idx); +} + static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, enum rtw89_phy_c2h_rfk_log_func func, void *content, u16 len) { struct rtw89_c2h_rf_txgapk_rpt_log *txgapk; struct rtw89_c2h_rf_rxdck_rpt_log *rxdck; + struct rtw89_c2h_rf_txiqk_rpt_log *txiqk; + struct rtw89_c2h_rf_cim3k_rpt_log *cim3k; struct rtw89_c2h_rf_dack_rpt_log *dack; struct rtw89_c2h_rf_tssi_rpt_log *tssi; struct rtw89_c2h_rf_dpk_rpt_log *dpk; @@ -3148,6 +3491,8 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, i, iqk->iqk_ch[i]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_bw[%d] = %x\n", i, iqk->iqk_bw[i]); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->rf_0x18[%d] = %x\n", + i, le32_to_cpu(iqk->rf_0x18[i])); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_idac[%d] = %x\n", i, le32_to_cpu(iqk->lok_idac[i])); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->lok_vbuf[%d] = %x\n", @@ -3156,22 +3501,30 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, i, iqk->iqk_tx_fail[i]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->iqk_rx_fail[%d] = %x\n", i, iqk->iqk_rx_fail[i]); - for (j = 0; j < 4; j++) + for (j = 0; j < 6; j++) rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->rftxgain[%d][%d] = %x\n", i, j, le32_to_cpu(iqk->rftxgain[i][j])); - for (j = 0; j < 4; j++) + for (j = 0; j < 6; j++) rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->tx_xym[%d][%d] = %x\n", i, j, le32_to_cpu(iqk->tx_xym[i][j])); - for (j = 0; j < 4; j++) + for (j = 0; j < 6; j++) rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->rfrxgain[%d][%d] = %x\n", i, j, le32_to_cpu(iqk->rfrxgain[i][j])); - for (j = 0; j < 4; j++) + for (j = 0; j < 6; j++) rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] iqk->rx_xym[%d][%d] = %x\n", i, j, le32_to_cpu(iqk->rx_xym[i][j])); + + if (!iqk->iqk_xym_en) + continue; + + for (j = 0; j < 32; j++) + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[IQK] iqk->rx_wb_xym[%d][%d] = %x\n", + i, j, iqk->rx_wb_xym[i][j]); } return; case RTW89_PHY_C2H_RFK_LOG_FUNC_DPK: @@ -3327,8 +3680,16 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, le32_to_cpu(txgapk->chk_cnt)); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt ver = 0x%x\n", txgapk->ver); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt rsv1 = %d\n", - txgapk->rsv1); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt d_bnd_ok = %d\n", + txgapk->d_bnd_ok); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt stage[0] = 0x%x\n", + le32_to_cpu(txgapk->stage[0])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt stage[1] = 0x%x\n", + le32_to_cpu(txgapk->stage[1])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]failcode[0] = 0x%x\n", + le16_to_cpu(txgapk->failcode[0])); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]failcode[1] = 0x%x\n", + le16_to_cpu(txgapk->failcode[1])); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt track_d[0] = %*ph\n", (int)sizeof(txgapk->track_d[0]), txgapk->track_d[0]); @@ -3339,6 +3700,20 @@ static void rtw89_phy_c2h_rfk_rpt_log(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[TXGAPK]rpt power_d[1] = %*ph\n", (int)sizeof(txgapk->power_d[1]), txgapk->power_d[1]); return; + case RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR: + if (len != sizeof(struct rtw89_c2h_rf_tas_rpt_log)) + goto out; + + rtw89_phy_c2h_rfk_tas_pwr(rtwdev, content); + return; + case RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK: + if (len != sizeof(*txiqk)) + goto out; + return; + case RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K: + if (len != sizeof(*cim3k)) + goto out; + return; default: break; } @@ -3391,9 +3766,6 @@ static void rtw89_phy_c2h_rfk_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u16 chunk_len; bool handled; - if (!rtw89_debug_is_enabled(rtwdev, RTW89_DBG_RFK)) - return; - log_ptr += sizeof(*c2h_hdr); len -= sizeof(*c2h_hdr); @@ -3470,6 +3842,27 @@ rtw89_phy_c2h_rfk_log_txgapk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK, "TXGAPK"); } +static void +rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ + rtw89_phy_c2h_rfk_log(rtwdev, c2h, len, + RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR, "TAS"); +} + +static void +rtw89_phy_c2h_rfk_log_txiqk(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ + rtw89_phy_c2h_rfk_log(rtwdev, c2h, len, + RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK, "TXIQK"); +} + +static void +rtw89_phy_c2h_rfk_log_cim3k(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +{ + rtw89_phy_c2h_rfk_log(rtwdev, c2h, len, + RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K, "CIM3K"); +} + static void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { @@ -3479,6 +3872,9 @@ void (* const rtw89_phy_c2h_rfk_log_handler[])(struct rtw89_dev *rtwdev, [RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK] = rtw89_phy_c2h_rfk_log_rxdck, [RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI] = rtw89_phy_c2h_rfk_log_tssi, [RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK] = rtw89_phy_c2h_rfk_log_txgapk, + [RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR] = rtw89_phy_c2h_rfk_log_tas_pwr, + [RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK] = rtw89_phy_c2h_rfk_log_txiqk, + [RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K] = rtw89_phy_c2h_rfk_log_cim3k, }; static @@ -3541,39 +3937,19 @@ rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u3 } static void -rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) +rtw89_phy_c2h_rfk_report_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { - const struct rtw89_c2h_rf_tas_info *rf_tas = + const struct rtw89_c2h_rf_tas_info *report = (const struct rtw89_c2h_rf_tas_info *)c2h->data; - const enum rtw89_sar_sources src = rtwdev->sar.src; - struct rtw89_tas_info *tas = &rtwdev->tas; - u64 linear = 0; - u32 i, cur_idx; - s16 txpwr; - - if (!tas->enable || src == RTW89_SAR_SOURCE_NONE) - return; - - cur_idx = le32_to_cpu(rf_tas->cur_idx); - for (i = 0; i < cur_idx; i++) { - txpwr = (s16)le16_to_cpu(rf_tas->txpwr_history[i]); - linear += rtw89_db_quarter_to_linear(txpwr); - - rtw89_debug(rtwdev, RTW89_DBG_SAR, - "tas: index: %u, txpwr: %d\n", i, txpwr); - } - if (cur_idx == 0) - tas->instant_txpwr = rtw89_db_to_linear(0); - else - tas->instant_txpwr = DIV_ROUND_DOWN_ULL(linear, cur_idx); + rtw89_phy_c2h_rfk_tas_pwr(rtwdev, &report->content); } static void (* const rtw89_phy_c2h_rfk_report_handler[])(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) = { [RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE] = rtw89_phy_c2h_rfk_report_state, - [RTW89_PHY_C2H_RFK_LOG_TAS_PWR] = rtw89_phy_c2h_rfk_log_tas_pwr, + [RTW89_PHY_C2H_RFK_REPORT_FUNC_TAS_PWR] = rtw89_phy_c2h_rfk_report_tas_pwr, }; bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func) @@ -3587,6 +3963,7 @@ bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func) case RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK: case RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI: case RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK: + case RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK: return true; default: return false; @@ -3611,7 +3988,7 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, switch (class) { case RTW89_PHY_C2H_CLASS_RA: - if (func < RTW89_PHY_C2H_FUNC_RA_MAX) + if (func < ARRAY_SIZE(rtw89_phy_c2h_ra_handler)) handler = rtw89_phy_c2h_ra_handler[func]; break; case RTW89_PHY_C2H_RFK_LOG: @@ -3627,12 +4004,11 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, handler = rtw89_phy_c2h_dm_handler[func]; break; default: - rtw89_info(rtwdev, "PHY c2h class %d not support\n", class); - return; + break; } if (!handler) { - rtw89_info(rtwdev, "PHY c2h class %d func %d not support\n", class, - func); + rtw89_info_once(rtwdev, "PHY c2h class %d func %d not support\n", + class, func); return; } handler(rtwdev, skb, len); @@ -3644,13 +4020,22 @@ int rtw89_phy_rfk_pre_ntfy_and_wait(struct rtw89_dev *rtwdev, { int ret; - rtw89_phy_rfk_report_prep(rtwdev); + if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY, &rtwdev->fw)) { + rtw89_phy_rfk_report_prep(rtwdev); + rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx); + ret = rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms); + if (ret) + return ret; + } - ret = rtw89_fw_h2c_rf_pre_ntfy(rtwdev, phy_idx); - if (ret) - return ret; + if (RTW89_CHK_FW_FEATURE_GROUP(WITH_RFK_PRE_NOTIFY_MCC, &rtwdev->fw)) { + ret = rtw89_fw_h2c_rf_pre_ntfy_mcc(rtwdev, phy_idx); + if (ret) + return ret; + } + + return 0; - return rtw89_phy_rfk_report_wait(rtwdev, "PRE_NTFY", ms); } EXPORT_SYMBOL(rtw89_phy_rfk_pre_ntfy_and_wait); @@ -3757,6 +4142,40 @@ int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_phy_rfk_rxdck_and_wait); +int rtw89_phy_rfk_txiqk_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan, + unsigned int ms) +{ + int ret; + + rtw89_phy_rfk_report_prep(rtwdev); + + ret = rtw89_fw_h2c_rf_txiqk(rtwdev, phy_idx, chan); + if (ret) + return ret; + + return rtw89_phy_rfk_report_wait(rtwdev, "TX_IQK", ms); +} +EXPORT_SYMBOL(rtw89_phy_rfk_txiqk_and_wait); + +int rtw89_phy_rfk_cim3k_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan, + unsigned int ms) +{ + int ret; + + rtw89_phy_rfk_report_prep(rtwdev); + + ret = rtw89_fw_h2c_rf_cim3k(rtwdev, phy_idx, chan); + if (ret) + return ret; + + return rtw89_phy_rfk_report_wait(rtwdev, "CIM3k", ms); +} +EXPORT_SYMBOL(rtw89_phy_rfk_cim3k_and_wait); + static u32 phy_tssi_get_cck_group(u8 ch) { switch (ch) { @@ -4204,6 +4623,7 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, struct rtw89_h2c_rf_tssi *h2c) { + const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; u8 ch = chan->channel; s8 trim_de; @@ -4227,9 +4647,14 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev, cck_de = tssi_info->tssi_cck[i][gidx]; val = u32_get_bits(cck_de + trim_de, 0xff); - h2c->curr_tssi_cck_de[i] = 0x0; - h2c->curr_tssi_cck_de_20m[i] = val; - h2c->curr_tssi_cck_de_40m[i] = val; + if (chip->chip_id == RTL8922A) { + h2c->curr_tssi_cck_de[i] = 0x0; + h2c->curr_tssi_cck_de_20m[i] = val; + h2c->curr_tssi_cck_de_40m[i] = val; + } else { + h2c->curr_tssi_cck_de[i] = val; + } + h2c->curr_tssi_efuse_cck_de[i] = cck_de; rtw89_debug(rtwdev, RTW89_DBG_TSSI, @@ -4238,12 +4663,17 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev, ofdm_de = phy_tssi_get_ofdm_de(rtwdev, phy, chan, i); val = u32_get_bits(ofdm_de + trim_de, 0xff); - h2c->curr_tssi_ofdm_de[i] = 0x0; - h2c->curr_tssi_ofdm_de_20m[i] = val; - h2c->curr_tssi_ofdm_de_40m[i] = val; - h2c->curr_tssi_ofdm_de_80m[i] = val; - h2c->curr_tssi_ofdm_de_160m[i] = val; - h2c->curr_tssi_ofdm_de_320m[i] = val; + if (chip->chip_id == RTL8922A) { + h2c->curr_tssi_ofdm_de[i] = 0x0; + h2c->curr_tssi_ofdm_de_20m[i] = val; + h2c->curr_tssi_ofdm_de_40m[i] = val; + h2c->curr_tssi_ofdm_de_80m[i] = val; + h2c->curr_tssi_ofdm_de_160m[i] = val; + h2c->curr_tssi_ofdm_de_320m[i] = val; + } else { + h2c->curr_tssi_ofdm_de[i] = val; + } + h2c->curr_tssi_efuse_ofdm_de[i] = ofdm_de; rtw89_debug(rtwdev, RTW89_DBG_TSSI, @@ -4258,10 +4688,12 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev, { struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk; struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chip_info *chip = rtwdev->chip; const s8 *thm_up[RF_PATH_B + 1] = {}; const s8 *thm_down[RF_PATH_B + 1] = {}; u8 subband = chan->subband_type; - s8 thm_ofst[128] = {0}; + s8 thm_ofst[128] = {}; + int multiplier; u8 thermal; u8 path; u8 i, j; @@ -4325,6 +4757,11 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI] tmeter tbl on subband: %u\n", subband); + if (chip->chip_id == RTL8922A) + multiplier = 1; + else + multiplier = -1; + for (path = RF_PATH_A; path <= RF_PATH_B; path++) { thermal = tssi_info->thermal[path]; rtw89_debug(rtwdev, RTW89_DBG_TSSI, @@ -4339,16 +4776,20 @@ void rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(struct rtw89_dev *rtwdev, h2c->pg_thermal[path] = thermal; i = 0; - for (j = 0; j < 64; j++) + for (j = 0; j < 64; j++) { thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ? thm_up[path][i++] : thm_up[path][DELTA_SWINGIDX_SIZE - 1]; + thm_ofst[j] *= multiplier; + } i = 1; - for (j = 127; j >= 64; j--) + for (j = 127; j >= 64; j--) { thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ? -thm_down[path][i++] : -thm_down[path][DELTA_SWINGIDX_SIZE - 1]; + thm_ofst[j] *= multiplier; + } for (i = 0; i < 128; i += 4) { h2c->ftable[path][i + 0] = thm_ofst[i + 3]; @@ -4448,7 +4889,7 @@ static void rtw89_dcfo_comp(struct rtw89_dev *rtwdev, s32 curr_cfo) s32 dcfo_comp_val; int sign; - if (rtwdev->chip->chip_id == RTL8922A) + if (!dcfo_comp) return; if (!is_linked) { @@ -5498,6 +5939,34 @@ static void rtw89_phy_ifs_clm_set_th_reg(struct rtw89_dev *rtwdev, i + 1, env->ifs_clm_th_l[i], env->ifs_clm_th_h[i]); } +static void __rtw89_phy_nhm_setting_init(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb) +{ + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + struct rtw89_env_monitor_info *env = &bb->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; + + env->nhm_include_cca = false; + env->nhm_mntr_time = 0; + env->nhm_sum = 0; + + rtw89_phy_write32_idx_set(rtwdev, ccx->nhm_config, ccx->nhm_en_mask, bb->phy_idx); + rtw89_phy_write32_idx_set(rtwdev, ccx->nhm_method, ccx->nhm_pwr_method_msk, + bb->phy_idx); +} + +void rtw89_phy_nhm_setting_init(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_bb_ctx *bb; + + if (!chip->support_noise) + return; + + rtw89_for_each_active_bb(rtwdev, bb) + __rtw89_phy_nhm_setting_init(rtwdev, bb); +} + static void rtw89_phy_ifs_clm_setting_init(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) { @@ -5559,7 +6028,7 @@ static int rtw89_phy_ccx_racing_ctrl(struct rtw89_dev *rtwdev, } static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev, - struct rtw89_bb_ctx *bb) + struct rtw89_bb_ctx *bb, u8 sel) { const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; struct rtw89_env_monitor_info *env = &bb->env_monitor; @@ -5569,10 +6038,17 @@ static void rtw89_phy_ccx_trigger(struct rtw89_dev *rtwdev, bb->phy_idx); rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 0, bb->phy_idx); + if (sel & RTW89_PHY_ENV_MON_NHM) + rtw89_phy_write32_idx_clr(rtwdev, ccx->nhm_config, + ccx->nhm_en_mask, bb->phy_idx); + rtw89_phy_write32_idx(rtwdev, ccx->ifs_cnt_addr, ccx->ifs_clm_cnt_clear_mask, 1, bb->phy_idx); rtw89_phy_write32_idx(rtwdev, ccx->setting_addr, ccx->measurement_trig_mask, 1, bb->phy_idx); + if (sel & RTW89_PHY_ENV_MON_NHM) + rtw89_phy_write32_idx_set(rtwdev, ccx->nhm_config, + ccx->nhm_en_mask, bb->phy_idx); env->ccx_ongoing = true; } @@ -5643,6 +6119,125 @@ static void rtw89_phy_ifs_clm_get_utility(struct rtw89_dev *rtwdev, env->ifs_clm_cca_avg[i]); } +static u8 rtw89_nhm_weighted_avg(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) +{ + struct rtw89_env_monitor_info *env = &bb->env_monitor; + u8 nhm_weight[RTW89_NHM_RPT_NUM]; + u32 nhm_weighted_sum = 0; + u8 weight_zero; + u8 i; + + if (env->nhm_sum == 0) + return 0; + + weight_zero = clamp_t(u16, env->nhm_th[0] - RTW89_NHM_WEIGHT_OFFSET, 0, U8_MAX); + + for (i = 0; i < RTW89_NHM_RPT_NUM; i++) { + if (i == 0) + nhm_weight[i] = weight_zero; + else if (i == (RTW89_NHM_RPT_NUM - 1)) + nhm_weight[i] = env->nhm_th[i - 1] + RTW89_NHM_WEIGHT_OFFSET; + else + nhm_weight[i] = (env->nhm_th[i - 1] + env->nhm_th[i]) / 2; + } + + if (rtwdev->chip->chip_id == RTL8852A || rtwdev->chip->chip_id == RTL8852B || + rtwdev->chip->chip_id == RTL8852C) { + if (env->nhm_th[RTW89_NHM_TH_NUM - 1] == RTW89_NHM_WA_TH) { + nhm_weight[RTW89_NHM_RPT_NUM - 1] = + env->nhm_th[RTW89_NHM_TH_NUM - 2] + + RTW89_NHM_WEIGHT_OFFSET; + nhm_weight[RTW89_NHM_RPT_NUM - 2] = + nhm_weight[RTW89_NHM_RPT_NUM - 1]; + } + + env->nhm_result[0] += env->nhm_result[RTW89_NHM_RPT_NUM - 1]; + env->nhm_result[RTW89_NHM_RPT_NUM - 1] = 0; + } + + for (i = 0; i < RTW89_NHM_RPT_NUM; i++) + nhm_weighted_sum += env->nhm_result[i] * nhm_weight[i]; + + return (nhm_weighted_sum / env->nhm_sum) >> RTW89_NHM_TH_FACTOR; +} + +static void __rtw89_phy_nhm_get_result(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb, enum rtw89_band hw_band, + u16 ch_hw_value) +{ + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + struct rtw89_env_monitor_info *env = &bb->env_monitor; + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_ccx_regs *ccx = phy->ccx; + struct ieee80211_supported_band *sband; + const struct rtw89_reg_def *nhm_rpt; + enum nl80211_band band; + u32 sum = 0; + u8 chan_idx; + u8 nhm_pwr; + u8 i; + + if (!rtw89_phy_read32_idx(rtwdev, ccx->nhm, ccx->nhm_ready, bb->phy_idx)) { + rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "[NHM] Get NHM report Fail\n"); + return; + } + + for (i = 0; i < RTW89_NHM_RPT_NUM; i++) { + nhm_rpt = &(*chip->nhm_report)[i]; + + env->nhm_result[i] = + rtw89_phy_read32_idx(rtwdev, nhm_rpt->addr, + nhm_rpt->mask, bb->phy_idx); + sum += env->nhm_result[i]; + } + env->nhm_sum = sum; + nhm_pwr = rtw89_nhm_weighted_avg(rtwdev, bb); + + if (!ch_hw_value) + return; + + band = rtw89_hw_to_nl80211_band(hw_band); + sband = rtwdev->hw->wiphy->bands[band]; + if (!sband) + return; + + for (chan_idx = 0; chan_idx < sband->n_channels; chan_idx++) { + struct ieee80211_channel *channel; + struct rtw89_nhm_report *rpt; + struct list_head *nhm_list; + + channel = &sband->channels[chan_idx]; + if (channel->hw_value != ch_hw_value) + continue; + + rpt = &env->nhm_his[hw_band][chan_idx]; + nhm_list = &env->nhm_rpt_list; + + rpt->channel = channel; + rpt->noise = nhm_pwr; + + if (list_empty(&rpt->list)) + list_add_tail(&rpt->list, nhm_list); + + return; + } + + rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "[NHM] channel not found\n"); +} + +void rtw89_phy_nhm_get_result(struct rtw89_dev *rtwdev, enum rtw89_band hw_band, + u16 ch_hw_value) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_bb_ctx *bb; + + if (!chip->support_noise) + return; + + rtw89_for_each_active_bb(rtwdev, bb) + __rtw89_phy_nhm_get_result(rtwdev, bb, hw_band, ch_hw_value); +} + static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) { @@ -5683,11 +6278,12 @@ static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev, env->ifs_clm_his[1] = rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr, ccx->ifs_t2_his_mask, bb->phy_idx); + env->ifs_clm_his[2] = - rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr, + rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr2, ccx->ifs_t3_his_mask, bb->phy_idx); env->ifs_clm_his[3] = - rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr, + rtw89_phy_read32_idx(rtwdev, ccx->ifs_his_addr2, ccx->ifs_t4_his_mask, bb->phy_idx); env->ifs_clm_avg[0] = @@ -5743,6 +6339,107 @@ static bool rtw89_phy_ifs_clm_get_result(struct rtw89_dev *rtwdev, return true; } +static void rtw89_phy_nhm_th_update(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb) +{ + struct rtw89_env_monitor_info *env = &bb->env_monitor; + static const u8 nhm_th_11k[RTW89_NHM_RPT_NUM] = { + 18, 21, 24, 27, 30, 35, 40, 45, 50, 55, 60, 0 + }; + const struct rtw89_chip_info *chip = rtwdev->chip; + const struct rtw89_reg_def *nhm_th; + u8 i; + + for (i = 0; i < RTW89_NHM_RPT_NUM; i++) + env->nhm_th[i] = nhm_th_11k[i] << RTW89_NHM_TH_FACTOR; + + if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B || + chip->chip_id == RTL8852C) + env->nhm_th[RTW89_NHM_TH_NUM - 1] = RTW89_NHM_WA_TH; + + for (i = 0; i < RTW89_NHM_TH_NUM; i++) { + nhm_th = &(*chip->nhm_th)[i]; + + rtw89_phy_write32_idx(rtwdev, nhm_th->addr, nhm_th->mask, + env->nhm_th[i], bb->phy_idx); + } +} + +static int rtw89_phy_nhm_set(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb, + struct rtw89_ccx_para_info *para) +{ + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + struct rtw89_env_monitor_info *env = &bb->env_monitor; + const struct rtw89_ccx_regs *ccx = phy->ccx; + u32 unit_idx = 0; + u32 period = 0; + + if (para->mntr_time == 0) { + rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, + "[NHM] MNTR_TIME is 0\n"); + return -EINVAL; + } + + if (rtw89_phy_ccx_racing_ctrl(rtwdev, bb, para->rac_lv)) + return -EINVAL; + + rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, + "[NHM]nhm_incld_cca=%d, mntr_time=%d ms\n", + para->nhm_incld_cca, para->mntr_time); + + if (para->mntr_time != env->nhm_mntr_time) { + rtw89_phy_ccx_ms_to_period_unit(rtwdev, para->mntr_time, + &period, &unit_idx); + rtw89_phy_write32_idx(rtwdev, ccx->nhm_config, + ccx->nhm_period_mask, period, bb->phy_idx); + rtw89_phy_write32_idx(rtwdev, ccx->nhm_config, + ccx->nhm_unit_mask, period, bb->phy_idx); + + env->nhm_mntr_time = para->mntr_time; + env->ccx_period = period; + env->ccx_unit_idx = unit_idx; + } + + if (para->nhm_incld_cca != env->nhm_include_cca) { + rtw89_phy_write32_idx(rtwdev, ccx->nhm_config, + ccx->nhm_include_cca_mask, para->nhm_incld_cca, + bb->phy_idx); + + env->nhm_include_cca = para->nhm_incld_cca; + } + + rtw89_phy_nhm_th_update(rtwdev, bb); + + return 0; +} + +static void __rtw89_phy_nhm_trigger(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) +{ + struct rtw89_ccx_para_info para = { + .mntr_time = RTW89_NHM_MNTR_TIME, + .rac_lv = RTW89_RAC_LV_1, + .nhm_incld_cca = true, + }; + + rtw89_phy_ccx_racing_release(rtwdev, bb); + + rtw89_phy_nhm_set(rtwdev, bb, ¶); + rtw89_phy_ccx_trigger(rtwdev, bb, RTW89_PHY_ENV_MON_NHM); +} + +void rtw89_phy_nhm_trigger(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_bb_ctx *bb; + + if (!chip->support_noise) + return; + + rtw89_for_each_active_bb(rtwdev, bb) + __rtw89_phy_nhm_trigger(rtwdev, bb); +} + static int rtw89_phy_ifs_clm_set(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb, struct rtw89_ccx_para_info *para) @@ -5817,7 +6514,7 @@ static void __rtw89_phy_env_monitor_track(struct rtw89_dev *rtwdev, if (rtw89_phy_ifs_clm_set(rtwdev, bb, ¶) == 0) chk_result |= RTW89_PHY_ENV_MON_IFS_CLM; if (chk_result) - rtw89_phy_ccx_trigger(rtwdev, bb); + rtw89_phy_ccx_trigger(rtwdev, bb, chk_result); rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK, "get_result=0x%x, chk_result:0x%x\n", @@ -5849,14 +6546,16 @@ static bool rtw89_physts_ie_page_valid(struct rtw89_dev *rtwdev, return true; } -static u32 rtw89_phy_get_ie_bitmap_addr(enum rtw89_phy_status_bitmap ie_page) +static u32 rtw89_phy_get_ie_bitmap_addr(struct rtw89_dev *rtwdev, + enum rtw89_phy_status_bitmap ie_page) { + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; static const u8 ie_page_shift = 2; if (ie_page == RTW89_EHT_PKT) - return R_PHY_STS_BITMAP_EHT; + return phy->physt_bmp_eht; - return R_PHY_STS_BITMAP_ADDR_START + (ie_page << ie_page_shift); + return phy->physt_bmp_start + (ie_page << ie_page_shift); } static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, @@ -5868,7 +6567,7 @@ static u32 rtw89_physts_get_ie_bitmap(struct rtw89_dev *rtwdev, if (!rtw89_physts_ie_page_valid(rtwdev, &ie_page)) return 0; - addr = rtw89_phy_get_ie_bitmap_addr(ie_page); + addr = rtw89_phy_get_ie_bitmap_addr(rtwdev, ie_page); return rtw89_phy_read32_idx(rtwdev, addr, MASKDWORD, phy_idx); } @@ -5886,7 +6585,7 @@ static void rtw89_physts_set_ie_bitmap(struct rtw89_dev *rtwdev, if (chip->chip_id == RTL8852A) val &= B_PHY_STS_BITMAP_MSK_52A; - addr = rtw89_phy_get_ie_bitmap_addr(ie_page); + addr = rtw89_phy_get_ie_bitmap_addr(rtwdev, ie_page); rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx); } @@ -5910,6 +6609,17 @@ static void rtw89_physts_enable_fail_report(struct rtw89_dev *rtwdev, } } +static void rtw89_physts_enable_hdr_2(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->chip_gen == RTW89_CHIP_AX || chip->chip_id == RTL8922A) + return; + + rtw89_phy_write32_idx_set(rtwdev, R_STS_HDR2_PARSING_BE4, + B_STS_HDR2_PARSING_BE4, phy_idx); +} + static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { @@ -5919,6 +6629,9 @@ static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev, rtw89_physts_enable_fail_report(rtwdev, false, phy_idx); + /* enable hdr_2 for 8922D (PHYSTS_BE_GEN2 above) */ + rtw89_physts_enable_hdr_2(rtwdev, phy_idx); + for (i = 0; i < RTW89_PHYSTS_BITMAP_NUM; i++) { if (i == RTW89_RSVD_9 || (i == RTW89_EHT_PKT && chip->chip_gen == RTW89_CHIP_AX)) @@ -5931,8 +6644,6 @@ static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev, val |= BIT(RTW89_PHYSTS_IE13_DL_MU_DEF) | BIT(RTW89_PHYSTS_IE01_CMN_OFDM); } else if (i >= RTW89_CCK_PKT) { - val |= BIT(RTW89_PHYSTS_IE09_FTR_0); - val &= ~(GENMASK(RTW89_PHYSTS_IE07_CMN_EXT_PATH_D, RTW89_PHYSTS_IE04_CMN_EXT_PATH_A)); @@ -6286,6 +6997,9 @@ static void rtw89_phy_dig_sdagc_follow_pagc_config(struct rtw89_dev *rtwdev, { const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs; + if (rtwdev->chip->chip_gen != RTW89_CHIP_AX) + return; + rtw89_phy_write32_idx(rtwdev, dig_regs->p0_p20_pagcugc_en.addr, dig_regs->p0_p20_pagcugc_en.mask, enable, bb->phy_idx); rtw89_phy_write32_idx(rtwdev, dig_regs->p0_s20_pagcugc_en.addr, @@ -6317,18 +7031,13 @@ static void rtw89_phy_dig_config_igi(struct rtw89_dev *rtwdev, } } -static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, - struct rtw89_bb_ctx *bb, - u8 rssi, bool enable) +static u8 rtw89_phy_dig_cal_under_region(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb, + const struct rtw89_chan *chan) { - const struct rtw89_chan *chan = rtw89_mgnt_chan_get(rtwdev, bb->phy_idx); - const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs; enum rtw89_bandwidth cbw = chan->band_width; struct rtw89_dig_info *dig = &bb->dig; - u8 final_rssi = 0, under_region = dig->pd_low_th_ofst; - u8 ofdm_cca_th; - s8 cck_cca_th; - u32 pd_val = 0; + u8 under_region = dig->pd_low_th_ofst; if (rtwdev->chip->chip_gen == RTW89_CHIP_AX) under_region += PD_TH_SB_FLTR_CMP_VAL; @@ -6350,6 +7059,20 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, break; } + return under_region; +} + +static u32 __rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb, + u8 rssi, bool enable, + const struct rtw89_chan *chan) +{ + struct rtw89_dig_info *dig = &bb->dig; + u8 ofdm_cca_th, under_region; + u8 final_rssi; + u32 pd_val; + + under_region = rtw89_phy_dig_cal_under_region(rtwdev, bb, chan); dig->dyn_pd_th_max = dig->igi_rssi; final_rssi = min_t(u8, rssi, dig->igi_rssi); @@ -6362,10 +7085,28 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, "igi=%d, ofdm_ccaTH=%d, backoff=%d, PD_low=%d\n", final_rssi, ofdm_cca_th, under_region, pd_val); } else { + pd_val = 0; rtw89_debug(rtwdev, RTW89_DBG_DIG, "Dynamic PD th disabled, Set PD_low_bd=0\n"); } + return pd_val; +} + +static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, + struct rtw89_bb_ctx *bb, + u8 rssi, bool enable) +{ + const struct rtw89_chan *chan = rtw89_mgnt_chan_get(rtwdev, bb->phy_idx); + const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs; + struct rtw89_dig_info *dig = &bb->dig; + u8 final_rssi, under_region = dig->pd_low_th_ofst; + s8 cck_cca_th; + u32 pd_val; + + pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, rssi, enable, chan); + dig->bak_dig = pd_val; + rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg, dig_regs->pd_lower_bound_mask, pd_val, bb->phy_idx); rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg, @@ -6374,6 +7115,8 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, if (!rtwdev->hal.support_cckpd) return; + final_rssi = min_t(u8, rssi, dig->igi_rssi); + under_region = rtw89_phy_dig_cal_under_region(rtwdev, bb, chan); cck_cca_th = max_t(s8, final_rssi - under_region, CCKPD_TH_MIN_RSSI); pd_val = (u32)(cck_cca_th - IGI_RSSI_MAX); @@ -6401,11 +7144,161 @@ void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) #define IGI_RSSI_MIN 10 #define ABS_IGI_MIN 0xc +static +void rtw89_phy_cal_igi_fa_rssi(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) +{ + struct rtw89_dig_info *dig = &bb->dig; + u8 igi_min; + + rtw89_phy_dig_igi_offset_by_env(rtwdev, bb); + + igi_min = max_t(int, dig->igi_rssi - IGI_RSSI_MIN, 0); + dig->dyn_igi_max = min(igi_min + IGI_OFFSET_MAX, igi_max_performance_mode); + dig->dyn_igi_min = max(igi_min, ABS_IGI_MIN); + + if (dig->dyn_igi_max >= dig->dyn_igi_min) { + dig->igi_fa_rssi += dig->fa_rssi_ofst; + dig->igi_fa_rssi = clamp(dig->igi_fa_rssi, dig->dyn_igi_min, + dig->dyn_igi_max); + } else { + dig->igi_fa_rssi = dig->dyn_igi_max; + } +} + +struct rtw89_phy_iter_mcc_dig { + struct rtw89_vif_link *rtwvif_link; + bool has_sta; + u8 rssi_min; +}; + +static void rtw89_phy_set_mcc_dig(struct rtw89_dev *rtwdev, + struct rtw89_vif_link *rtwvif_link, + struct rtw89_bb_ctx *bb, + u8 rssi_min, u8 mcc_role_idx, + bool is_linked) +{ + struct rtw89_dig_info *dig = &bb->dig; + const struct rtw89_chan *chan; + u8 pd_val; + + if (is_linked) { + dig->igi_rssi = rssi_min >> 1; + dig->igi_fa_rssi = dig->igi_rssi; + } else { + rtw89_debug(rtwdev, RTW89_DBG_DIG, "RSSI update : NO Link\n"); + dig->igi_rssi = rssi_nolink; + dig->igi_fa_rssi = dig->igi_rssi; + } + + chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); + rtw89_phy_cal_igi_fa_rssi(rtwdev, bb); + pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, dig->igi_fa_rssi, + is_linked, chan); + rtw89_fw_h2c_mcc_dig(rtwdev, rtwvif_link->chanctx_idx, + mcc_role_idx, pd_val, true); + + rtw89_debug(rtwdev, RTW89_DBG_DIG, + "MCC chanctx_idx %d chan %d rssi %d pd_val %d", + rtwvif_link->chanctx_idx, chan->primary_channel, + dig->igi_rssi, pd_val); +} + +static void rtw89_phy_set_mcc_dig_iter(void *data, struct ieee80211_sta *sta) +{ + struct rtw89_phy_iter_mcc_dig *mcc_dig = (struct rtw89_phy_iter_mcc_dig *)data; + unsigned int link_id = mcc_dig->rtwvif_link->link_id; + struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); + struct rtw89_sta_link *rtwsta_link; + + if (rtwsta->rtwvif != mcc_dig->rtwvif_link->rtwvif) + return; + + rtwsta_link = rtwsta->links[link_id]; + if (!rtwsta_link) + return; + + mcc_dig->has_sta = true; + if (ewma_rssi_read(&rtwsta_link->avg_rssi) < mcc_dig->rssi_min) + mcc_dig->rssi_min = ewma_rssi_read(&rtwsta_link->avg_rssi); +} + +static void rtw89_phy_dig_mcc(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) +{ + struct rtw89_phy_iter_mcc_dig mcc_dig; + struct rtw89_vif_link *rtwvif_link; + struct rtw89_mcc_links_info info; + int i; + + rtw89_mcc_get_links(rtwdev, &info); + for (i = 0; i < ARRAY_SIZE(info.links); i++) { + rtwvif_link = info.links[i]; + if (!rtwvif_link) + continue; + + memset(&mcc_dig, 0, sizeof(mcc_dig)); + mcc_dig.rtwvif_link = rtwvif_link; + mcc_dig.has_sta = false; + mcc_dig.rssi_min = U8_MAX; + ieee80211_iterate_stations_atomic(rtwdev->hw, + rtw89_phy_set_mcc_dig_iter, + &mcc_dig); + + rtw89_phy_set_mcc_dig(rtwdev, rtwvif_link, bb, + mcc_dig.rssi_min, i, mcc_dig.has_sta); + } +} + +static void rtw89_phy_dig_ctrl(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb, + bool pause_dig, bool restore) +{ + const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs; + struct rtw89_dig_info *dig = &bb->dig; + bool en_dig; + u32 pd_val; + + if (dig->pause_dig == pause_dig) + return; + + if (pause_dig) { + en_dig = false; + pd_val = 0; + } else { + en_dig = rtwdev->total_sta_assoc > 0; + pd_val = restore ? dig->bak_dig : 0; + } + + rtw89_debug(rtwdev, RTW89_DBG_DIG, "%s <%s> PD_low=%d", __func__, + pause_dig ? "suspend" : "resume", pd_val); + + rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg, + dig_regs->pd_lower_bound_mask, pd_val, bb->phy_idx); + rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg, + dig_regs->pd_spatial_reuse_en, en_dig, bb->phy_idx); + + dig->pause_dig = pause_dig; +} + +void rtw89_phy_dig_suspend(struct rtw89_dev *rtwdev) +{ + struct rtw89_bb_ctx *bb; + + rtw89_for_each_active_bb(rtwdev, bb) + rtw89_phy_dig_ctrl(rtwdev, bb, true, false); +} + +void rtw89_phy_dig_resume(struct rtw89_dev *rtwdev, bool restore) +{ + struct rtw89_bb_ctx *bb; + + rtw89_for_each_active_bb(rtwdev, bb) + rtw89_phy_dig_ctrl(rtwdev, bb, false, restore); +} + static void __rtw89_phy_dig(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) { struct rtw89_dig_info *dig = &bb->dig; bool is_linked = rtwdev->total_sta_assoc > 0; - u8 igi_min; + enum rtw89_entity_mode mode; if (unlikely(dig->bypass_dig)) { dig->bypass_dig = false; @@ -6416,6 +7309,15 @@ static void __rtw89_phy_dig(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) rtw89_phy_dig_update_rssi_info(rtwdev, bb); + mode = rtw89_get_entity_mode(rtwdev); + if (mode == RTW89_ENTITY_MODE_MCC) { + rtw89_phy_dig_mcc(rtwdev, bb); + return; + } + + if (unlikely(dig->pause_dig)) + return; + if (!dig->is_linked_pre && is_linked) { rtw89_debug(rtwdev, RTW89_DBG_DIG, "First connected\n"); rtw89_phy_dig_update_para(rtwdev, bb); @@ -6427,19 +7329,7 @@ static void __rtw89_phy_dig(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) } dig->is_linked_pre = is_linked; - rtw89_phy_dig_igi_offset_by_env(rtwdev, bb); - - igi_min = max_t(int, dig->igi_rssi - IGI_RSSI_MIN, 0); - dig->dyn_igi_max = min(igi_min + IGI_OFFSET_MAX, igi_max_performance_mode); - dig->dyn_igi_min = max(igi_min, ABS_IGI_MIN); - - if (dig->dyn_igi_max >= dig->dyn_igi_min) { - dig->igi_fa_rssi += dig->fa_rssi_ofst; - dig->igi_fa_rssi = clamp(dig->igi_fa_rssi, dig->dyn_igi_min, - dig->dyn_igi_max); - } else { - dig->igi_fa_rssi = dig->dyn_igi_max; - } + rtw89_phy_cal_igi_fa_rssi(rtwdev, bb); rtw89_debug(rtwdev, RTW89_DBG_DIG, "rssi=%03d, dyn_joint(max,min)=(%d,%d), final_rssi=%d\n", @@ -6735,6 +7625,7 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) rtw89_chip_bb_sethw(rtwdev); rtw89_phy_env_monitor_init(rtwdev); + rtw89_phy_nhm_setting_init(rtwdev); rtw89_physts_parsing_init(rtwdev); rtw89_phy_dig_init(rtwdev); rtw89_phy_cfo_init(rtwdev); @@ -6760,6 +7651,43 @@ void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev) rtw89_physts_parsing_init(rtwdev); } +static void __rtw89_phy_dm_init_data(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb) +{ + struct rtw89_env_monitor_info *env = &bb->env_monitor; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct ieee80211_supported_band *sband; + enum rtw89_band hw_band; + enum nl80211_band band; + u8 idx; + + if (!chip->support_noise) + return; + + for (band = 0; band < NUM_NL80211_BANDS; band++) { + sband = rtwdev->hw->wiphy->bands[band]; + if (!sband) + continue; + + hw_band = rtw89_nl80211_to_hw_band(band); + env->nhm_his[hw_band] = + devm_kcalloc(rtwdev->dev, sband->n_channels, + sizeof(*env->nhm_his[0]), GFP_KERNEL); + + for (idx = 0; idx < sband->n_channels; idx++) + INIT_LIST_HEAD(&env->nhm_his[hw_band][idx].list); + + INIT_LIST_HEAD(&env->nhm_rpt_list); + } +} + +void rtw89_phy_dm_init_data(struct rtw89_dev *rtwdev) +{ + struct rtw89_bb_ctx *bb; + + rtw89_for_each_capab_bb(rtwdev, bb) + __rtw89_phy_dm_init_data(rtwdev, bb); +} + void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { @@ -7131,6 +8059,7 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b bool flag_fb, flag_p20, flag_s20, flag_s40, flag_s80; s8 pwdb_fb, pwdb_p20, pwdb_s20, pwdb_s40, pwdb_s80; u8 path, per20_bitmap = 0; + u8 pwdb_sel = 5; u8 pwdb[8]; u32 tmp; @@ -7142,12 +8071,14 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b else edcca_p_regs = &edcca_regs->p[RTW89_PHY_0]; - if (rtwdev->chip->chip_id == RTL8922A) - rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be, - edcca_regs->rpt_sel_be_mask, 0); - rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel, edcca_p_regs->rpt_sel_mask, 0); + if (rtwdev->chip->chip_id == RTL8922A || rtwdev->chip->chip_id == RTL8922D) { + rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be, + edcca_regs->rpt_sel_be_mask, 0); + per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a, + MASKBYTE0); + } tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b); path = u32_get_bits(tmp, B_EDCCA_RPT_B_PATH_MASK); flag_s80 = u32_get_bits(tmp, B_EDCCA_RPT_B_S80); @@ -7159,13 +8090,16 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b pwdb_p20 = u32_get_bits(tmp, MASKBYTE2); pwdb_fb = u32_get_bits(tmp, MASKBYTE3); + if (rtwdev->chip->chip_id == RTL8922D) + pwdb_sel = 2; + rtw89_phy_write32_mask(rtwdev, edcca_p_regs->rpt_sel, - edcca_p_regs->rpt_sel_mask, 5); + edcca_p_regs->rpt_sel_mask, pwdb_sel); tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b); pwdb_s80 = u32_get_bits(tmp, MASKBYTE1); pwdb_s40 = u32_get_bits(tmp, MASKBYTE2); - if (rtwdev->chip->chip_id == RTL8922A) { + if (rtwdev->chip->chip_id == RTL8922A || rtwdev->chip->chip_id == RTL8922D) { rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be, edcca_regs->rpt_sel_be_mask, 4); tmp = rtw89_phy_read32(rtwdev, edcca_p_regs->rpt_b); @@ -7173,8 +8107,6 @@ static void rtw89_phy_edcca_log(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *b pwdb[1] = u32_get_bits(tmp, MASKBYTE2); pwdb[2] = u32_get_bits(tmp, MASKBYTE1); pwdb[3] = u32_get_bits(tmp, MASKBYTE0); - per20_bitmap = rtw89_phy_read32_mask(rtwdev, edcca_p_regs->rpt_a, - MASKBYTE0); rtw89_phy_write32_mask(rtwdev, edcca_regs->rpt_sel_be, edcca_regs->rpt_sel_be_mask, 5); @@ -7396,6 +8328,7 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_ax = { .ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK, .ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK, .ifs_his_addr = R_IFS_HIS, + .ifs_his_addr2 = R_IFS_HIS, .ifs_t4_his_mask = B_IFS_T4_HIS_MSK, .ifs_t3_his_mask = B_IFS_T3_HIS_MSK, .ifs_t2_his_mask = B_IFS_T2_HIS_MSK, @@ -7415,6 +8348,15 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_ax = { .ifs_total_addr = R_IFSCNT, .ifs_cnt_done_mask = B_IFSCNT_DONE_MSK, .ifs_total_mask = B_IFSCNT_TOTAL_CNT_MSK, + .nhm = R_NHM_AX, + .nhm_ready = B_NHM_READY_MSK, + .nhm_config = R_NHM_CFG, + .nhm_period_mask = B_NHM_PERIOD_MSK, + .nhm_unit_mask = B_NHM_COUNTER_MSK, + .nhm_include_cca_mask = B_NHM_INCLUDE_CCA_MSK, + .nhm_en_mask = B_NHM_EN_MSK, + .nhm_method = R_NHM_TH9, + .nhm_pwr_method_msk = B_NHM_PWDB_METHOD_MSK, }; static const struct rtw89_physts_regs rtw89_physts_regs_ax = { @@ -7432,9 +8374,12 @@ static const struct rtw89_cfo_regs rtw89_cfo_regs_ax = { const struct rtw89_phy_gen_def rtw89_phy_gen_ax = { .cr_base = 0x10000, + .physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START, + .physt_bmp_eht = 0xfc, .ccx = &rtw89_ccx_regs_ax, .physts = &rtw89_physts_regs_ax, .cfo = &rtw89_cfo_regs_ax, + .bb_wrap = NULL, .phy0_phy1_offset = rtw89_phy0_phy1_offset_ax, .config_bb_gain = rtw89_phy_config_bb_gain_ax, .preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_ax, diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 63cc33c16c9a5..ab263738d2120 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -139,7 +139,9 @@ enum rtw89_phy_c2h_ra_func { RTW89_PHY_C2H_FUNC_STS_RPT, RTW89_PHY_C2H_FUNC_MU_GPTBL_RPT, RTW89_PHY_C2H_FUNC_TXSTS, - RTW89_PHY_C2H_FUNC_RA_MAX, + RTW89_PHY_C2H_FUNC_ACCELERATE_EN = 0x7, + + RTW89_PHY_C2H_FUNC_RA_NUM, }; enum rtw89_phy_c2h_rfk_log_func { @@ -149,13 +151,16 @@ enum rtw89_phy_c2h_rfk_log_func { RTW89_PHY_C2H_RFK_LOG_FUNC_RXDCK = 3, RTW89_PHY_C2H_RFK_LOG_FUNC_TSSI = 4, RTW89_PHY_C2H_RFK_LOG_FUNC_TXGAPK = 5, + RTW89_PHY_C2H_RFK_LOG_FUNC_TAS_PWR = 9, + RTW89_PHY_C2H_RFK_LOG_FUNC_TXIQK = 0xc, + RTW89_PHY_C2H_RFK_LOG_FUNC_CIM3K = 0xe, RTW89_PHY_C2H_RFK_LOG_FUNC_NUM, }; enum rtw89_phy_c2h_rfk_report_func { RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE = 0, - RTW89_PHY_C2H_RFK_LOG_TAS_PWR = 6, + RTW89_PHY_C2H_RFK_REPORT_FUNC_TAS_PWR = 6, }; enum rtw89_phy_c2h_dm_func { @@ -164,6 +169,8 @@ enum rtw89_phy_c2h_dm_func { RTW89_PHY_C2H_DM_FUNC_SIGB, RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY, RTW89_PHY_C2H_DM_FUNC_MCC_DIG, + RTW89_PHY_C2H_DM_FUNC_LPS = 0x9, + RTW89_PHY_C2H_DM_FUNC_ENV_MNTR = 0xa, RTW89_PHY_C2H_DM_FUNC_FW_SCAN = 0xc, RTW89_PHY_C2H_DM_FUNC_NUM, }; @@ -188,6 +195,12 @@ enum rtw89_env_monitor_result_level { RTW89_PHY_ENV_MON_EDCCA_CLM = BIT(4), }; +#define RTW89_NHM_WEIGHT_OFFSET 2 +#define RTW89_NHM_WA_TH (109 << 1) +#define RTW89_NOISE_DEFAULT -96 +#define RTW89_NHM_MNTR_TIME 40 +#define RTW89_NHM_TH_FACTOR 1 + #define CCX_US_BASE_RATIO 4 enum rtw89_ccx_unit { RTW89_CCX_4_US = 0, @@ -409,6 +422,7 @@ struct rtw89_ccx_regs { u32 ifs_clm_ofdm_fa_mask; u32 ifs_clm_cck_fa_mask; u32 ifs_his_addr; + u32 ifs_his_addr2; u32 ifs_t4_his_mask; u32 ifs_t3_his_mask; u32 ifs_t2_his_mask; @@ -428,6 +442,15 @@ struct rtw89_ccx_regs { u32 ifs_total_addr; u32 ifs_cnt_done_mask; u32 ifs_total_mask; + u32 nhm; + u32 nhm_ready; + u32 nhm_config; + u32 nhm_period_mask; + u32 nhm_unit_mask; + u32 nhm_include_cca_mask; + u32 nhm_en_mask; + u32 nhm_method; + u32 nhm_pwr_method_msk; }; struct rtw89_physts_regs { @@ -443,6 +466,11 @@ struct rtw89_cfo_regs { u32 valid_0_mask; }; +struct rtw89_bb_wrap_regs { + u32 pwr_macid_lmt; + u32 pwr_macid_path; +}; + enum rtw89_bandwidth_section_num_ax { RTW89_BW20_SEC_NUM_AX = 8, RTW89_BW40_SEC_NUM_AX = 4, @@ -515,9 +543,12 @@ struct rtw89_phy_rfk_log_fmt { struct rtw89_phy_gen_def { u32 cr_base; + u32 physt_bmp_start; + u32 physt_bmp_eht; const struct rtw89_ccx_regs *ccx; const struct rtw89_physts_regs *physts; const struct rtw89_cfo_regs *cfo; + const struct rtw89_bb_wrap_regs *bb_wrap; u32 (*phy0_phy1_offset)(struct rtw89_dev *rtwdev, u32 addr); void (*config_bb_gain)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, @@ -543,6 +574,7 @@ struct rtw89_phy_gen_def { extern const struct rtw89_phy_gen_def rtw89_phy_gen_ax; extern const struct rtw89_phy_gen_def rtw89_phy_gen_be; +extern const struct rtw89_phy_gen_def rtw89_phy_gen_be_v1; static inline void rtw89_phy_write8(struct rtw89_dev *rtwdev, u32 addr, u8 data) @@ -807,13 +839,18 @@ u32 rtw89_phy_read_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask); u32 rtw89_phy_read_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask); +u32 rtw89_phy_read_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, + u32 addr, u32 mask); bool rtw89_phy_write_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask, u32 data); bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask, u32 data); bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, u32 addr, u32 mask, u32 data); +bool rtw89_phy_write_rf_v3(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path, + u32 addr, u32 mask, u32 data); void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev); +void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev); void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio); void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, @@ -821,6 +858,7 @@ void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev, void *extra_data); void rtw89_phy_dm_init(struct rtw89_dev *rtwdev); void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev); +void rtw89_phy_dm_init_data(struct rtw89_dev *rtwdev); void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 data, enum rtw89_phy_idx phy_idx); void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits, @@ -861,6 +899,12 @@ static inline void rtw89_phy_bb_wrap_init(struct rtw89_dev *rtwdev) phy->bb_wrap_init(rtwdev); } +void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx); +void rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx); + static inline void rtw89_phy_ch_info_init(struct rtw89_dev *rtwdev) { const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; @@ -992,6 +1036,14 @@ int rtw89_phy_rfk_rxdck_and_wait(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, const struct rtw89_chan *chan, bool is_chl_k, unsigned int ms); +int rtw89_phy_rfk_txiqk_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan, + unsigned int ms); +int rtw89_phy_rfk_cim3k_and_wait(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, + const struct rtw89_chan *chan, + unsigned int ms); void rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, const struct rtw89_chan *chan, @@ -1010,6 +1062,8 @@ void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask, u32 val); void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb); void rtw89_phy_dig(struct rtw89_dev *rtwdev); +void rtw89_phy_dig_suspend(struct rtw89_dev *rtwdev); +void rtw89_phy_dig_resume(struct rtw89_dev *rtwdev, bool restore); void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev); void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu); @@ -1036,5 +1090,9 @@ enum rtw89_rf_path rtw89_phy_get_syn_sel(struct rtw89_dev *rtwdev, u8 rtw89_rfk_chan_lookup(struct rtw89_dev *rtwdev, const struct rtw89_rfk_chan_desc *desc, u8 desc_nr, const struct rtw89_chan *target_chan); +void rtw89_phy_nhm_setting_init(struct rtw89_dev *rtwdev); +void rtw89_phy_nhm_get_result(struct rtw89_dev *rtwdev, enum rtw89_band hw_band, + u16 ch_hw_value); +void rtw89_phy_nhm_trigger(struct rtw89_dev *rtwdev); #endif diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c index d321cf1fc4850..08fd24a55d852 100644 --- a/drivers/net/wireless/realtek/rtw89/phy_be.c +++ b/drivers/net/wireless/realtek/rtw89/phy_be.c @@ -2,6 +2,7 @@ /* Copyright(c) 2023 Realtek Corporation */ +#include "chan.h" #include "debug.h" #include "mac.h" #include "phy.h" @@ -44,6 +45,7 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_be = { .ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK, .ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK, .ifs_his_addr = R_IFS_HIS_V1, + .ifs_his_addr2 = R_IFS_HIS_V1, .ifs_t4_his_mask = B_IFS_T4_HIS_MSK, .ifs_t3_his_mask = B_IFS_T3_HIS_MSK, .ifs_t2_his_mask = B_IFS_T2_HIS_MSK, @@ -63,6 +65,74 @@ static const struct rtw89_ccx_regs rtw89_ccx_regs_be = { .ifs_total_addr = R_IFSCNT_V1, .ifs_cnt_done_mask = B_IFSCNT_DONE_MSK, .ifs_total_mask = B_IFSCNT_TOTAL_CNT_MSK, + .nhm = R_NHM_BE, + .nhm_ready = B_NHM_READY_BE_MSK, + .nhm_config = R_NHM_CFG, + .nhm_period_mask = B_NHM_PERIOD_MSK, + .nhm_unit_mask = B_NHM_COUNTER_MSK, + .nhm_include_cca_mask = B_NHM_INCLUDE_CCA_MSK, + .nhm_en_mask = B_NHM_EN_MSK, + .nhm_method = R_NHM_TH9, + .nhm_pwr_method_msk = B_NHM_PWDB_METHOD_MSK, +}; + +static const struct rtw89_ccx_regs rtw89_ccx_regs_be_v1 = { + .setting_addr = R_CCX_BE4, + .edcca_opt_mask = B_CCX_EDCCA_OPT_MSK_V1, + .measurement_trig_mask = B_MEASUREMENT_TRIG_MSK, + .trig_opt_mask = B_CCX_TRIG_OPT_MSK, + .en_mask = B_CCX_EN_MSK, + .ifs_cnt_addr = R_IFS_COUNTER_BE4, + .ifs_clm_period_mask = B_IFS_CLM_PERIOD_MSK, + .ifs_clm_cnt_unit_mask = B_IFS_CLM_COUNTER_UNIT_MSK, + .ifs_clm_cnt_clear_mask = B_IFS_COUNTER_CLR_MSK, + .ifs_collect_en_mask = B_IFS_COLLECT_EN, + .ifs_t1_addr = R_IFS_T1_BE4, + .ifs_t1_th_h_mask = B_IFS_T1_TH_HIGH_MSK, + .ifs_t1_en_mask = B_IFS_T1_EN_MSK, + .ifs_t1_th_l_mask = B_IFS_T1_TH_LOW_MSK, + .ifs_t2_addr = R_IFS_T2_BE4, + .ifs_t2_th_h_mask = B_IFS_T2_TH_HIGH_MSK, + .ifs_t2_en_mask = B_IFS_T2_EN_MSK, + .ifs_t2_th_l_mask = B_IFS_T2_TH_LOW_MSK, + .ifs_t3_addr = R_IFS_T3_BE4, + .ifs_t3_th_h_mask = B_IFS_T3_TH_HIGH_MSK, + .ifs_t3_en_mask = B_IFS_T3_EN_MSK, + .ifs_t3_th_l_mask = B_IFS_T3_TH_LOW_MSK, + .ifs_t4_addr = R_IFS_T4_BE4, + .ifs_t4_th_h_mask = B_IFS_T4_TH_HIGH_MSK, + .ifs_t4_en_mask = B_IFS_T4_EN_MSK, + .ifs_t4_th_l_mask = B_IFS_T4_TH_LOW_MSK, + .ifs_clm_tx_cnt_addr = R_IFS_CLM_TX_CNT_BE4, + .ifs_clm_edcca_excl_cca_fa_mask = B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK, + .ifs_clm_tx_cnt_msk = B_IFS_CLM_TX_CNT_MSK, + .ifs_clm_cca_addr = R_IFS_CLM_CCA_BE4, + .ifs_clm_ofdmcca_excl_fa_mask = B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK, + .ifs_clm_cckcca_excl_fa_mask = B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK, + .ifs_clm_fa_addr = R_IFS_CLM_FA_BE4, + .ifs_clm_ofdm_fa_mask = B_IFS_CLM_OFDM_FA_MSK, + .ifs_clm_cck_fa_mask = B_IFS_CLM_CCK_FA_MSK, + .ifs_his_addr = R_IFS_T1_HIS_BE4, + .ifs_his_addr2 = R_IFS_T3_HIS_BE4, /* for 3/4 */ + .ifs_t4_his_mask = B_IFS_T4_HIS_BE4, + .ifs_t3_his_mask = B_IFS_T3_HIS_BE4, + .ifs_t2_his_mask = B_IFS_T2_HIS_BE4, + .ifs_t1_his_mask = B_IFS_T1_HIS_BE4, + .ifs_avg_l_addr = R_IFS_T1_AVG_BE4, + .ifs_t2_avg_mask = B_IFS_T2_AVG_BE4, + .ifs_t1_avg_mask = B_IFS_T1_AVG_BE4, + .ifs_avg_h_addr = R_IFS_T3_AVG_BE4, + .ifs_t4_avg_mask = B_IFS_T4_AVG_BE4, + .ifs_t3_avg_mask = B_IFS_T3_AVG_BE4, + .ifs_cca_l_addr = R_IFS_T1_CLM_BE4, + .ifs_t2_cca_mask = B_IFS_T2_CLM_BE4, + .ifs_t1_cca_mask = B_IFS_T1_CLM_BE4, + .ifs_cca_h_addr = R_IFS_T3_CLM_BE4, + .ifs_t4_cca_mask = B_IFS_T4_CLM_BE4, + .ifs_t3_cca_mask = B_IFS_T3_CLM_BE4, + .ifs_total_addr = R_IFS_TOTAL_BE4, + .ifs_cnt_done_mask = B_IFS_CNT_DONE_BE4, + .ifs_total_mask = B_IFS_TOTAL_BE4, }; static const struct rtw89_physts_regs rtw89_physts_regs_be = { @@ -71,11 +141,34 @@ static const struct rtw89_physts_regs rtw89_physts_regs_be = { .dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK, }; +static const struct rtw89_physts_regs rtw89_physts_regs_be_v1 = { + .setting_addr = R_PLCP_HISTOGRAM_BE_V1, + .dis_trigger_fail_mask = B_STS_DIS_TRIG_BY_FAIL, + .dis_trigger_brk_mask = B_STS_DIS_TRIG_BY_BRK, +}; + static const struct rtw89_cfo_regs rtw89_cfo_regs_be = { - .comp = R_DCFO_WEIGHT_V1, - .weighting_mask = B_DCFO_WEIGHT_MSK_V1, - .comp_seg0 = R_DCFO_OPT_V1, - .valid_0_mask = B_DCFO_OPT_EN_V1, + .comp = R_DCFO_WEIGHT_BE, + .weighting_mask = B_DCFO_WEIGHT_MSK_BE, + .comp_seg0 = R_DCFO_OPT_BE, + .valid_0_mask = B_DCFO_OPT_EN_BE, +}; + +static const struct rtw89_cfo_regs rtw89_cfo_regs_be_v1 = { + .comp = R_DCFO_WEIGHT_BE_V1, + .weighting_mask = B_DCFO_WEIGHT_MSK_BE, + .comp_seg0 = R_DCFO_OPT_BE_V1, + .valid_0_mask = B_DCFO_OPT_EN_BE, +}; + +static const struct rtw89_bb_wrap_regs rtw89_bb_wrap_regs_be = { + .pwr_macid_lmt = R_BE_PWR_MACID_LMT_BASE, + .pwr_macid_path = R_BE_PWR_MACID_PATH_BASE, +}; + +static const struct rtw89_bb_wrap_regs rtw89_bb_wrap_regs_be_v1 = { + .pwr_macid_lmt = R_BE_PWR_MACID_LMT_BASE_V1, + .pwr_macid_path = R_BE_PWR_MACID_PATH_BASE_V1, }; static u32 rtw89_phy0_phy1_offset_be(struct rtw89_dev *rtwdev, u32 addr) @@ -96,6 +189,25 @@ static u32 rtw89_phy0_phy1_offset_be(struct rtw89_dev *rtwdev, u32 addr) return ofst; } +static u32 rtw89_phy0_phy1_offset_be_v1(struct rtw89_dev *rtwdev, u32 addr) +{ + u32 phy_page = addr >> 8; + u32 ofst = 0; + + if ((phy_page >= 0x204 && phy_page <= 0x20F) || + (phy_page >= 0x220 && phy_page <= 0x22F) || + (phy_page >= 0x240 && phy_page <= 0x24f) || + (phy_page >= 0x260 && phy_page <= 0x26f) || + (phy_page >= 0x2C0 && phy_page <= 0x2C9) || + (phy_page >= 0x2E4 && phy_page <= 0x2E8) || + phy_page == 0x2EE) + ofst = 0x1000; + else + ofst = 0x0; + + return ofst; +} + union rtw89_phy_bb_gain_arg_be { u32 addr; struct { @@ -257,6 +369,10 @@ static void rtw89_phy_config_bb_gain_be(struct rtw89_dev *rtwdev, case 3: rtw89_phy_cfg_bb_gain_op1db_be(rtwdev, arg, reg->data); break; + case 15: + rtw89_phy_write32_idx(rtwdev, reg->addr & 0xFFFFF, MASKHWORD, + reg->data, RTW89_PHY_0); + break; case 4: /* This cfg_type is only used by rfe_type >= 50 with eFEM */ if (efuse->rfe_type < 50) @@ -288,40 +404,101 @@ static void rtw89_phy_preinit_rf_nctl_be(struct rtw89_dev *rtwdev) } } +static void rtw89_phy_preinit_rf_nctl_be_v1(struct rtw89_dev *rtwdev) +{ + rtw89_phy_write32_mask(rtwdev, R_GOTX_IQKDPK_C0_BE4, B_GOTX_IQKDPK, 0x3); + rtw89_phy_write32_mask(rtwdev, R_GOTX_IQKDPK_C1_BE4, B_GOTX_IQKDPK, 0x3); + rtw89_phy_write32_mask(rtwdev, R_IOQ_IQK_DPK_BE4, B_IOQ_IQK_DPK_RST, 0x1); + rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_RST_BE4, B_IQK_DPK_RST, 0x1); + rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_PRST_BE4, B_IQK_DPK_PRST, 0x1); + rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_PRST_C1_BE4, B_IQK_DPK_PRST, 0x1); +} + +static u32 rtw89_phy_bb_wrap_flush_addr(struct rtw89_dev *rtwdev, u32 addr) +{ + struct rtw89_hal *hal = &rtwdev->hal; + + if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags)) + return 0; + + if (rtwdev->chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7025) { + if (addr >= R_BE_PWR_MACID_PATH_BASE_V1 && + addr <= R_BE_PWR_MACID_PATH_BASE_V1 + 0xFF) + return addr + 0x800; + + if (addr >= R_BE_PWR_MACID_LMT_BASE_V1 && + addr <= R_BE_PWR_MACID_LMT_BASE_V1 + 0xFF) + return addr - 0x800; + } + + return 0; +} + +static +void rtw89_write_bb_wrap_flush(struct rtw89_dev *rtwdev, u32 addr, u32 data) +{ + /* To write registers of pwr_macid_lmt and pwr_macid_path with flush */ + u32 flush_addr; + u32 val32; + + flush_addr = rtw89_phy_bb_wrap_flush_addr(rtwdev, addr); + if (flush_addr) { + val32 = rtw89_read32(rtwdev, flush_addr); + rtw89_write32(rtwdev, flush_addr, val32); + } + + rtw89_write32(rtwdev, addr, data); +} + static void rtw89_phy_bb_wrap_pwr_by_macid_init(struct rtw89_dev *rtwdev) { - u32 macid_idx, cr, base_macid_lmt, max_macid = 32; + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + const struct rtw89_bb_wrap_regs *bb_wrap = phy->bb_wrap; + u32 max_macid = rtwdev->chip->support_macid_num; + u32 macid_idx, cr, base_macid_lmt; - base_macid_lmt = R_BE_PWR_MACID_LMT_BASE; + base_macid_lmt = bb_wrap->pwr_macid_lmt; for (macid_idx = 0; macid_idx < 4 * max_macid; macid_idx += 4) { cr = base_macid_lmt + macid_idx; - rtw89_write32(rtwdev, cr, 0x03007F7F); + rtw89_write_bb_wrap_flush(rtwdev, cr, 0); } } static void rtw89_phy_bb_wrap_tx_path_by_macid_init(struct rtw89_dev *rtwdev) { - int i, max_macid = 32; - u32 cr = R_BE_PWR_MACID_PATH_BASE; + const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def; + const struct rtw89_bb_wrap_regs *bb_wrap = phy->bb_wrap; + u32 max_macid = rtwdev->chip->support_macid_num; + u32 cr = bb_wrap->pwr_macid_path; + int i; for (i = 0; i < max_macid; i++, cr += 4) - rtw89_write32(rtwdev, cr, 0x03C86000); + rtw89_write_bb_wrap_flush(rtwdev, cr, 0); } static void rtw89_phy_bb_wrap_tpu_set_all(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx) { - u32 addr; + u32 addr, t; - for (addr = R_BE_PWR_BY_RATE; addr <= R_BE_PWR_BY_RATE_END; addr += 4) - rtw89_write32(rtwdev, addr, 0); - for (addr = R_BE_PWR_RULMT_START; addr <= R_BE_PWR_RULMT_END; addr += 4) - rtw89_write32(rtwdev, addr, 0); - for (addr = R_BE_PWR_RATE_OFST_CTRL; addr <= R_BE_PWR_RATE_OFST_END; addr += 4) - rtw89_write32(rtwdev, addr, 0); + addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_FTM_SS, mac_idx); + rtw89_write32_mask(rtwdev, addr, B_BE_PWR_BY_RATE_DBW_ON, 0x3); + + for (addr = R_BE_PWR_BY_RATE; addr <= R_BE_PWR_BY_RATE_END; addr += 4) { + t = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx); + rtw89_write32(rtwdev, t, 0); + } + for (addr = R_BE_PWR_RULMT_START; addr <= R_BE_PWR_RULMT_END; addr += 4) { + t = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx); + rtw89_write32(rtwdev, t, 0); + } + for (addr = R_BE_PWR_RATE_OFST_CTRL; addr <= R_BE_PWR_RATE_OFST_END; addr += 4) { + t = rtw89_mac_reg_by_idx(rtwdev, addr, mac_idx); + rtw89_write32(rtwdev, t, 0); + } addr = rtw89_mac_reg_by_idx(rtwdev, R_BE_PWR_REF_CTRL, mac_idx); rtw89_write32_mask(rtwdev, addr, B_BE_PWR_OFST_LMT_DB, 0); @@ -381,6 +558,332 @@ static void rtw89_phy_bb_wrap_ftm_init(struct rtw89_dev *rtwdev, rtw89_write32_mask(rtwdev, addr, 0x7, 0); } +static u32 rtw89_phy_bb_wrap_be_bandedge_decision(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + u8 pri_ch = chan->primary_channel; + u32 val = 0; + + switch (chan->band_type) { + default: + case RTW89_BAND_2G: + if (pri_ch == 1 || pri_ch == 13) + val = BIT(1) | BIT(0); + else if (pri_ch == 3 || pri_ch == 11) + val = BIT(1); + break; + case RTW89_BAND_5G: + if (pri_ch == 36 || pri_ch == 64 || pri_ch == 100) + val = BIT(3) | BIT(2) | BIT(1) | BIT(0); + else if (pri_ch == 40 || pri_ch == 60 || pri_ch == 104) + val = BIT(3) | BIT(2) | BIT(1); + else if ((pri_ch > 40 && pri_ch < 60) || pri_ch == 108 || pri_ch == 112) + val = BIT(3) | BIT(2); + else if (pri_ch > 112 && pri_ch < 132) + val = BIT(3); + break; + case RTW89_BAND_6G: + if (pri_ch == 233) + val = BIT(0); + break; + } + + return val; +} + +void rtw89_phy_bb_wrap_set_rfsi_ct_opt(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + u32 reg; + + reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_0_BE4, phy_idx); + rtw89_write32(rtwdev, reg, 0x00010001); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_RFSI_CT_OPT_8_BE4, phy_idx); + rtw89_write32(rtwdev, reg, 0x00010001); +} +EXPORT_SYMBOL(rtw89_phy_bb_wrap_set_rfsi_ct_opt); + +void rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u32 reg; + u32 val; + + val = rtw89_phy_bb_wrap_be_bandedge_decision(rtwdev, chan); + + rtw89_phy_write32_idx(rtwdev, R_TX_CFR_MANUAL_EN_BE4, B_TX_CFR_MANUAL_EN_BE4_M, + chan->primary_channel == 13, phy_idx); + + reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWX_BE4, phy_idx); + rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW20_BE4, val & BIT(0)); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWX_BE4, phy_idx); + rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW40_BE4, (val & BIT(1)) >> 1); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWX_BE4, phy_idx); + rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW80_BE4, (val & BIT(2)) >> 2); + reg = rtw89_mac_reg_by_idx(rtwdev, R_BANDEDGE_DBWY_BE4, phy_idx); + rtw89_write32_mask(rtwdev, reg, B_BANDEDGE_DBW160_BE4, (val & BIT(3)) >> 3); +} +EXPORT_SYMBOL(rtw89_phy_bb_wrap_set_rfsi_bandedge_ch); + +static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + /* TH0 */ + rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_0_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_3_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_1_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_4_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_7_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_0_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_3_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_6_BE4, 0x1, mac_idx); + /* TH1 */ + rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_1_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_4_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_2_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_5_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_8_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_1_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_4_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_7_BE4, 0x2, mac_idx); + /* TH2 */ + rtw89_write32_idx(rtwdev, R_QAM_TH0_BE4, B_QAM_TH0_2_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_0_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_3_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_6_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH1_BE4, B_QAM_TH1_9_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_2_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_5_BE4, 0x4, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_TH2_BE4, B_QAM_TH2_8_BE4, 0x4, mac_idx); + /* DPD 160M */ + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_0_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_1_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_2_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_3_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH0_BE4, B_DPD_DBW160_TH0_4_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_5_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_6_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_DBW160_TH1_BE4, B_DPD_DBW160_TH1_7_BE4, 0x1, mac_idx); + /* DPD 20M */ + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_0_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_1_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_2_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_3_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_4_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_5_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH0_BE4, B_DPD_CBW20_TH0_6_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH1_7_BE4, 0x2, mac_idx); + /* DPD 40M */ + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_0_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_1_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_2_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_3_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW40_TH1_4_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH0_3_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH0_4_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW20_TH0_5_BE4, 0x2, mac_idx); + /* DPD 80M */ + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH1_BE4, B_DPD_CBW80_TH1_0_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_1_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_2_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_3_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_4_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_5_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_6_BE4, 0x2, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW_TH2_BE4, B_DPD_CBW80_TH2_7_BE4, 0x2, mac_idx); + /* CIM3K */ + rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH2_BE4, 0x2, mac_idx); +} + +static void rtw89_phy_bb_wrap_tx_rfsi_scenario_def(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_ER_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_SUBF_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_FTM_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_RFSI_CT_DEF_BE4, B_RFSI_CT_SENS_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DEF_BE, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_PB_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DL_WO_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_DL_BF_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_MUMIMO_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_FTM_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_FBTB_CT_DEF_BE4, B_FBTB_CT_SENS_BE4, 0x0, mac_idx); +} + +static void rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKLWORD, 0x4010, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKHWORD, 0x4410, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKLWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKHWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKLWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKHWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKLWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKHWORD, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_L, 0x8, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_M, 0x8, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_H, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_L, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_M, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_H, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_L, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_M, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2L, 0x8, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2M, 0x8, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH4_BE4, B_QAM_COMP_TH4_2H, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2L, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2M, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH5_BE4, B_QAM_COMP_TH5_2H, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2L, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_QAM_COMP_TH6_BE4, B_QAM_COMP_TH6_2M, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKLWORD, 0x4010, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKHWORD, 0x4010, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKLWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKHWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKLWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKHWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKLWORD, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKHWORD, 0x0, mac_idx); +} + +static void rtw89_phy_bb_set_oob_dpd_qam_comp_val(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_CCK7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_CCK7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW20_BE4, B_OOB_CBW20_TH7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_TH7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_TH7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW20_OW7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW40_BE4, B_OOB_CBW40_OW7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_OOB_CBW80_BE4, B_OOB_CBW80_OW7_BE4, 0x0, mac_idx); +} + +static void rtw89_phy_bb_set_mdpd_qam_comp_val(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_TH7_BE4, 0x0, mac_idx); + + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW0_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW1_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW2_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW3_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW4_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW5_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW6_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_DPD_CBW160_BE4, B_DPD_CBW160_OW7_BE4, 0x0, mac_idx); +} + +static void rtw89_phy_bb_set_cim3k_val(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_TH_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_OW_BE4, 0x0, mac_idx); + rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_NONBE_BE4, 0x1, mac_idx); + rtw89_write32_idx(rtwdev, R_COMP_CIM3K_BE4, B_COMP_CIM3K_BANDEDGE_BE4, 0x1, mac_idx); +} + +static void rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(struct rtw89_dev *rtwdev, + enum rtw89_mac_idx mac_idx) +{ + enum rtw89_phy_idx phy_idx = mac_idx != RTW89_MAC_0 ? RTW89_PHY_1 : RTW89_PHY_0; + enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; + const struct rtw89_chan *chan; + + if (chip_id != RTL8922D) + return; + + rtw89_phy_bb_wrap_tx_rfsi_qam_comp_th_init(rtwdev, mac_idx); + rtw89_phy_bb_wrap_tx_rfsi_scenario_def(rtwdev, mac_idx); + rtw89_phy_bb_wrap_tx_rfsi_qam_comp_val(rtwdev, mac_idx); + rtw89_phy_bb_set_oob_dpd_qam_comp_val(rtwdev, mac_idx); + rtw89_phy_bb_set_mdpd_qam_comp_val(rtwdev, mac_idx); + rtw89_phy_bb_set_cim3k_val(rtwdev, mac_idx); + + rtw89_phy_bb_wrap_set_rfsi_ct_opt(rtwdev, phy_idx); + + chan = rtw89_mgnt_chan_get(rtwdev, phy_idx); + if (chan) + rtw89_phy_bb_wrap_set_rfsi_bandedge_ch(rtwdev, chan, phy_idx); +} + static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev) { enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; @@ -401,12 +904,13 @@ static void rtw89_phy_bb_wrap_ul_pwr(struct rtw89_dev *rtwdev) static void __rtw89_phy_bb_wrap_init_be(struct rtw89_dev *rtwdev, enum rtw89_mac_idx mac_idx) { - rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev); rtw89_phy_bb_wrap_tx_path_by_macid_init(rtwdev); - rtw89_phy_bb_wrap_listen_path_en_init(rtwdev); + rtw89_phy_bb_wrap_pwr_by_macid_init(rtwdev); + rtw89_phy_bb_wrap_tpu_set_all(rtwdev, mac_idx); + rtw89_phy_bb_wrap_tx_rfsi_ctrl_init(rtwdev, mac_idx); rtw89_phy_bb_wrap_force_cr_init(rtwdev, mac_idx); rtw89_phy_bb_wrap_ftm_init(rtwdev, mac_idx); - rtw89_phy_bb_wrap_tpu_set_all(rtwdev, mac_idx); + rtw89_phy_bb_wrap_listen_path_en_init(rtwdev); rtw89_phy_bb_wrap_ul_pwr(rtwdev); } @@ -428,6 +932,14 @@ static void rtw89_phy_ch_info_init_be(struct rtw89_dev *rtwdev) rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_TYPE_SCAL, B_CHINFO_SCAL, 0x0); } +static void rtw89_phy_ch_info_init_be_v1(struct rtw89_dev *rtwdev) +{ + rtw89_phy_write32_mask(rtwdev, R_CHINFO_SEG_BE4, B_CHINFO_SEG_LEN_BE4, 0); + rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_OPT_BE4, B_CHINFO_OPT_BE4, 0x3); + rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_NX_BE4, B_CHINFO_NX_BE4, 0x669); + rtw89_phy_set_phy_regs(rtwdev, R_CHINFO_ALG_BE4, B_CHINFO_ALG_BE4, 0); +} + struct rtw89_byr_spec_ent_be { struct rtw89_rate_desc init; u8 num_of_idx; @@ -991,9 +1503,12 @@ static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev, const struct rtw89_phy_gen_def rtw89_phy_gen_be = { .cr_base = 0x20000, + .physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START, + .physt_bmp_eht = R_PHY_STS_BITMAP_EHT, .ccx = &rtw89_ccx_regs_be, .physts = &rtw89_physts_regs_be, .cfo = &rtw89_cfo_regs_be, + .bb_wrap = &rtw89_bb_wrap_regs_be, .phy0_phy1_offset = rtw89_phy0_phy1_offset_be, .config_bb_gain = rtw89_phy_config_bb_gain_be, .preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_be, @@ -1006,3 +1521,24 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_be = { .set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_be, }; EXPORT_SYMBOL(rtw89_phy_gen_be); + +const struct rtw89_phy_gen_def rtw89_phy_gen_be_v1 = { + .cr_base = 0x0, + .physt_bmp_start = R_PHY_STS_BITMAP_ADDR_START_BE4, + .physt_bmp_eht = R_PHY_STS_BITMAP_EHT_BE4, + .ccx = &rtw89_ccx_regs_be_v1, + .physts = &rtw89_physts_regs_be_v1, + .cfo = &rtw89_cfo_regs_be_v1, + .bb_wrap = &rtw89_bb_wrap_regs_be_v1, + .phy0_phy1_offset = rtw89_phy0_phy1_offset_be_v1, + .config_bb_gain = rtw89_phy_config_bb_gain_be, + .preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_be_v1, + .bb_wrap_init = rtw89_phy_bb_wrap_init_be, + .ch_info_init = rtw89_phy_ch_info_init_be_v1, + + .set_txpwr_byrate = rtw89_phy_set_txpwr_byrate_be, + .set_txpwr_offset = rtw89_phy_set_txpwr_offset_be, + .set_txpwr_limit = rtw89_phy_set_txpwr_limit_be, + .set_txpwr_limit_ru = rtw89_phy_set_txpwr_limit_ru_be, +}; +EXPORT_SYMBOL(rtw89_phy_gen_be_v1); diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index 3411d642c84a7..aad2ee7926d67 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -11,8 +11,45 @@ #include "phy.h" #include "ps.h" #include "reg.h" +#include "ser.h" #include "util.h" +static int rtw89_fw_receive_lps_h2c_check(struct rtw89_dev *rtwdev, u8 macid) +{ + struct rtw89_mac_c2h_info c2h_info = {.timeout = 5000}; + u16 c2hreg_macid; + u32 c2hreg_ret; + int ret; + + if (!RTW89_CHK_FW_FEATURE(LPS_DACK_BY_C2H_REG, &rtwdev->fw)) + return 0; + + c2h_info.id = RTW89_FWCMD_C2HREG_FUNC_PS_LEAVE_ACK; + ret = rtw89_fw_msg_reg(rtwdev, NULL, &c2h_info); + if (ret) + goto fw_fail; + + c2hreg_macid = u32_get_bits(c2h_info.u.c2hreg[0], + RTW89_C2HREG_PS_LEAVE_ACK_MACID); + c2hreg_ret = u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_PS_LEAVE_ACK_RET); + + if (macid != c2hreg_macid || c2hreg_ret) { + rtw89_warn(rtwdev, "rtw89: check lps h2c received by firmware fail\n"); + ret = -EINVAL; + goto fw_fail; + } + rtwdev->ps_hang_cnt = 0; + + return 0; + +fw_fail: + rtwdev->ps_hang_cnt++; + if (rtwdev->ps_hang_cnt >= RTW89_PS_HANG_MAX_CNT) + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + + return ret; +} + static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid) { const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; @@ -26,9 +63,16 @@ static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid) mac->ps_status, chk_msk); if (ret) { rtw89_info(rtwdev, "rtw89: failed to leave lps state\n"); + + rtwdev->ps_hang_cnt++; + if (rtwdev->ps_hang_cnt >= RTW89_PS_HANG_MAX_CNT) + rtw89_ser_notify(rtwdev, MAC_AX_ERR_ASSERTION); + return -EBUSY; } + rtwdev->ps_hang_cnt = 0; + return 0; } @@ -94,6 +138,9 @@ static void __rtw89_enter_lps_link(struct rtw89_dev *rtwdev, rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL); rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); + + if (RTW89_CHK_FW_FEATURE(BEACON_TRACKING, &rtwdev->fw)) + rtw89_fw_h2c_pwr_lvl(rtwdev, rtwvif_link); } static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, @@ -106,7 +153,8 @@ static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, }; rtw89_fw_h2c_lps_parm(rtwdev, &lps_param); - rtw89_fw_leave_lps_check(rtwdev, 0); + rtw89_fw_receive_lps_h2c_check(rtwdev, rtwvif_link->mac_id); + rtw89_fw_leave_lps_check(rtwdev, rtwvif_link->mac_id); rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx); } @@ -141,6 +189,8 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw)) rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif); + else if (RTW89_CHK_FW_FEATURE(LPS_ML_INFO_V1, &rtwdev->fw)) + rtw89_fw_h2c_lps_ml_cmn_info_v1(rtwdev, rtwvif); else rtw89_fw_h2c_lps_ml_cmn_info(rtwdev, rtwvif); diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index c0ec7538b832e..b239cf5aed9de 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -21,6 +21,7 @@ #define R_AX_SYS_PW_CTRL 0x0004 #define B_AX_SOP_ASWRM BIT(31) #define B_AX_SOP_PWMM_DSWR BIT(29) +#define B_AX_SOP_EDSWR BIT(28) #define B_AX_XTAL_OFF_A_DIE BIT(22) #define B_AX_DIS_WLBT_PDNSUSEN_SOPC BIT(18) #define B_AX_RDY_SYSPWR BIT(17) @@ -148,6 +149,7 @@ #define R_AX_WLLPS_CTRL 0x0090 #define B_AX_LPSOP_ASWRM BIT(17) #define B_AX_LPSOP_DSWRM BIT(9) +#define B_AX_FORCE_LEAVE_LPS BIT(3) #define B_AX_DIS_WLBT_LPSEN_LOPC BIT(1) #define SW_LPS_OPTION 0x0001A0B2 @@ -279,6 +281,9 @@ #define R_AX_GPIO0_7_FUNC_SEL 0x02D0 +#define R_AX_GPIO8_15_FUNC_SEL 0x02D4 +#define B_AX_PINMUX_GPIO9_FUNC_SEL_MASK GENMASK(7, 4) + #define R_AX_EECS_EESK_FUNC_SEL 0x02D8 #define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4) @@ -309,13 +314,18 @@ #define R_AX_IC_PWR_STATE 0x03F0 #define B_AX_WHOLE_SYS_PWR_STE_MASK GENMASK(25, 16) #define B_AX_WLMAC_PWR_STE_MASK GENMASK(9, 8) +#define MAC_AX_MAC_OFF 0 +#define MAC_AX_MAC_ON 1 +#define MAC_AX_MAC_LPS 2 #define B_AX_UART_HCISYS_PWR_STE_MASK GENMASK(7, 6) #define B_AX_SDIO_HCISYS_PWR_STE_MASK GENMASK(5, 4) #define B_AX_USB_HCISYS_PWR_STE_MASK GENMASK(3, 2) #define B_AX_PCIE_HCISYS_PWR_STE_MASK GENMASK(1, 0) #define R_AX_SPS_DIG_OFF_CTRL0 0x0400 +#define B_AX_R1_L1_MASK GENMASK(7, 6) #define B_AX_C3_L1_MASK GENMASK(5, 4) +#define B_AX_C2_L1_MASK GENMASK(3, 2) #define B_AX_C1_L1_MASK GENMASK(1, 0) #define R_AX_AFE_OFF_CTRL1 0x0444 @@ -378,6 +388,18 @@ #define B_AX_ACH1_BUSY BIT(9) #define B_AX_ACH0_BUSY BIT(8) +#define R_AX_USB_ENDPOINT_0 0x1060 +#define B_AX_EP_IDX GENMASK(3, 0) +#define R_AX_USB_ENDPOINT_2 0x1068 +#define NUMP 0x1 +#define R_AX_USB_HOST_REQUEST_2 0x1078 +#define B_AX_R_USBIO_MODE BIT(4) +#define R_AX_USB3_MAC_NPI_CONFIG_INTF_0 0x1114 +#define B_AX_SSPHY_LFPS_FILTER BIT(31) +#define R_AX_USB_WLAN0_1 0x1174 +#define B_AX_USBRX_RST BIT(9) +#define B_AX_USBTX_RST BIT(8) + #define R_AX_PCIE_DBG_CTRL 0x11C0 #define B_AX_DBG_DUMMY_MASK GENMASK(23, 16) #define B_AX_PCIE_DBG_SEL_MASK GENMASK(15, 13) @@ -457,6 +479,17 @@ #define R_AX_WP_PAGE_CTRL2_V1 0x17A4 #define R_AX_WP_PAGE_INFO1_V1 0x17A8 +#define R_AX_USB_ENDPOINT_0_V1 0x5060 +#define B_AX_EP_IDX_V1 GENMASK(3, 0) +#define R_AX_USB_ENDPOINT_2_V1 0x5068 +#define R_AX_USB_HOST_REQUEST_2_V1 0x5078 +#define B_AX_R_USBIO_MODE_V1 BIT(4) +#define R_AX_USB3_MAC_NPI_CONFIG_INTF_0_V1 0x5114 +#define B_AX_SSPHY_LFPS_FILTER_V1 BIT(31) +#define R_AX_USB_WLAN0_1_V1 0x5174 +#define B_AX_USBRX_RST_V1 BIT(9) +#define B_AX_USBTX_RST_V1 BIT(8) + #define R_AX_H2CREG_DATA0_V1 0x7140 #define R_AX_H2CREG_DATA1_V1 0x7144 #define R_AX_H2CREG_DATA2_V1 0x7148 @@ -576,6 +609,9 @@ #define R_AX_SER_DBG_INFO 0x8424 #define B_AX_L0_TO_L1_EVENT_MASK GENMASK(31, 28) +#define B_AX_SER_L1_COUNTER_MASK GENMASK(27, 24) +#define B_AX_RMAC_PPDU_HANG_CNT_MASK GENMASK(23, 16) +#define B_AX_SER_L0_COUNTER_MASK GENMASK(7, 0) #define R_AX_DLE_EMPTY0 0x8430 #define B_AX_PLE_EMPTY_QTA_DMAC_CPUIO BIT(26) @@ -1023,6 +1059,12 @@ #define B_AX_DISPATCHER_INTN_SEL_MASK GENMASK(7, 4) #define B_AX_DISPATCHER_CH_SEL_MASK GENMASK(3, 0) +#define R_AX_RXDMA_SETTING 0x8908 +#define B_AX_BULK_SIZE GENMASK(1, 0) +#define USB11_BULKSIZE 0x2 +#define USB2_BULKSIZE 0x1 +#define USB3_BULKSIZE 0x0 + #define R_AX_RX_FUNCTION_STOP 0x8920 #define B_AX_HDR_RX_STOP BIT(0) @@ -1925,7 +1967,9 @@ #define B_AX_B0_PRELD_FEN BIT(31) #define B_AX_B0_PRELD_USEMAXSZ_MASK GENMASK(25, 16) #define PRELD_B0_ENT_NUM 10 +#define PRELD_B01_ENT_NUM_8922D 2 #define PRELD_AMSDU_SIZE 52 +#define PRELD_NEXT_MIN_SIZE 255 #define B_AX_B0_PRELD_CAM_G1ENTNUM_MASK GENMASK(12, 8) #define B_AX_B0_PRELD_CAM_G0ENTNUM_MASK GENMASK(4, 0) @@ -2061,6 +2105,7 @@ #define B_AX_B1_ISR_ERR_USRCTL_REINIT BIT(0) #define R_AX_AFE_CTRL1 0x0024 +#define B_AX_CMAC_CLK_SEL BIT(21) #define B_AX_R_SYM_WLCMAC1_P4_PC_EN BIT(4) #define B_AX_R_SYM_WLCMAC1_P3_PC_EN BIT(3) @@ -2074,6 +2119,12 @@ #define B_AX_R_SYM_FEN_WLBBFUN_1 BIT(16) #define B_AX_R_SYM_ISO_CMAC12PP BIT(5) +#define R_AX_SYSON_FSM_MON 0x00A0 +#define B_AX_FSM_MON_SEL_MASK GENMASK(26, 24) +#define B_AX_DOP_ELDO BIT(23) +#define B_AX_FSM_MON_UPD BIT(15) +#define B_AX_FSM_PAR_MASK GENMASK(14, 0) + #define R_AX_CMAC_REG_START 0xC000 #define R_AX_CMAC_FUNC_EN 0xC000 @@ -3338,6 +3389,10 @@ #define B_AX_CSIPRT_VHTSU_AID_EN BIT(24) #define B_AX_CSIRPT_EMPTY_APPZERO BIT(1) +#define R_AX_BCN_PSR_RPT_P0 0xCE84 +#define R_AX_BCN_PSR_RPT_P0_C1 0xEE84 +#define B_AX_BCAID_P0_MASK GENMASK(10, 0) + #define R_AX_RX_STATE_MONITOR 0xCEF0 #define R_AX_RX_STATE_MONITOR_C1 0xEEF0 #define B_AX_RX_STATE_MONITOR_MASK GENMASK(31, 0) @@ -3780,6 +3835,7 @@ #define B_BE_EN_WLON BIT(16) #define B_BE_APDM_HPDN BIT(15) #define B_BE_PSUS_OFF_CAPC_EN BIT(14) +#define B_BE_USUS_OFFCAPC_EN BIT(13) #define B_BE_AFSM_PCIE_SUS_EN BIT(12) #define B_BE_AFSM_WLSUS_EN BIT(11) #define B_BE_APFM_SWLPS BIT(10) @@ -3848,6 +3904,8 @@ #define B_BE_SYM_PADPDN_WL_RFC0_1P3 BIT(5) #define R_BE_RSV_CTRL 0x001C +#define B_BE_R_SYM_PRST_CPHY_RST BIT(25) +#define B_BE_R_SYM_PRST_PDN_EN BIT(24) #define B_BE_HR_BE_DBG GENMASK(23, 12) #define B_BE_R_SYM_DIS_PCIE_FLR BIT(9) #define B_BE_R_EN_HRST_PWRON BIT(8) @@ -3894,6 +3952,11 @@ #define B_BE_R_SYM_WLCMAC0_P2_PC_EN BIT(26) #define B_BE_R_SYM_WLCMAC0_P1_PC_EN BIT(25) #define B_BE_R_SYM_WLCMAC0_PC_EN BIT(24) +#define B_BE_R_SYM_WLCMAC0_ALL_EN (B_BE_R_SYM_WLCMAC0_PC_EN | \ + B_BE_R_SYM_WLCMAC0_P1_PC_EN | \ + B_BE_R_SYM_WLCMAC0_P2_PC_EN | \ + B_BE_R_SYM_WLCMAC0_P3_PC_EN | \ + B_BE_R_SYM_WLCMAC0_P4_PC_EN) #define B_BE_DATAMEM_PC3_EN BIT(23) #define B_BE_DATAMEM_PC2_EN BIT(22) #define B_BE_DATAMEM_PC1_EN BIT(21) @@ -3915,11 +3978,11 @@ #define B_BE_R_SYM_WLCMAC1_P2_PC_EN BIT(2) #define B_BE_R_SYM_WLCMAC1_P1_PC_EN BIT(1) #define B_BE_R_SYM_WLCMAC1_PC_EN BIT(0) -#define B_BE_AFE_CTRL1_SET (B_BE_R_SYM_WLCMAC1_PC_EN | \ - B_BE_R_SYM_WLCMAC1_P1_PC_EN | \ - B_BE_R_SYM_WLCMAC1_P2_PC_EN | \ - B_BE_R_SYM_WLCMAC1_P3_PC_EN | \ - B_BE_R_SYM_WLCMAC1_P4_PC_EN) +#define B_BE_R_SYM_WLCMAC1_ALL_EN (B_BE_R_SYM_WLCMAC1_PC_EN | \ + B_BE_R_SYM_WLCMAC1_P1_PC_EN | \ + B_BE_R_SYM_WLCMAC1_P2_PC_EN | \ + B_BE_R_SYM_WLCMAC1_P3_PC_EN | \ + B_BE_R_SYM_WLCMAC1_P4_PC_EN) #define R_BE_EFUSE_CTRL 0x0030 #define B_BE_EF_MODE_SEL_MASK GENMASK(31, 30) @@ -3930,6 +3993,33 @@ #define R_BE_EFUSE_CTRL_1_V1 0x0034 #define B_BE_EF_DATA_MASK GENMASK(31, 0) +#define R_BE_GPIO_MUXCFG 0x0040 +#define B_BE_WCPU_AUTO_EN BIT(26) +#define B_BE_WCPU_JTAG_EN BIT(24) +#define B_BE_WCPU_DBG_EN BIT(23) +#define B_BE_JTAG_CHAIN_EN BIT(20) +#define B_BE_BOOT_MODE BIT(19) +#define B_BE_WL_EECS_EXT_32K_SEL BIT(18) +#define B_BE_WL_SEC_BONDING_OPT_STS BIT(17) +#define B_BE_SECSIC_SEL BIT(16) +#define B_BE_ENHTP BIT(14) +#define B_BE_ENSIC BIT(12) +#define B_BE_SIC_SWRST BIT(11) +#define B_BE_PINMUX_PTA_EN BIT(10) +#define B_BE_WL_BT_PTA_SEC BIT(9) +#define B_BE_ENUARTTX BIT(8) +#define B_BE_DBG_GNT_BT_S1_POLARITY BIT(4) +#define B_BE_ENUARTRX BIT(2) + +#define R_BE_GPIO_EXT_CTRL 0x0060 +#define B_BE_GPIO_MOD_15_TO_8_MASK GENMASK(31, 24) +#define B_BE_GPIO_MOD_9 BIT(25) +#define B_BE_GPIO_IO_SEL_15_TO_8_MASK GENMASK(23, 16) +#define B_BE_GPIO_IO_SEL_9 BIT(17) +#define B_BE_GPIO_OUT_15_TO_8_MASK GENMASK(15, 8) +#define B_BE_GPIO_IN_15_TO_8_MASK GENMASK(7, 0) +#define B_BE_GPIO_IN_9 BIT(1) + #define R_BE_WL_BT_PWR_CTRL 0x0068 #define B_BE_ISO_BD2PP BIT(31) #define B_BE_LDOV12B_EN BIT(30) @@ -3955,6 +4045,7 @@ #define R_BE_SYS_SDIO_CTRL 0x0070 #define B_BE_MCM_FLASH_EN BIT(28) +#define B_BE_SER_DETECT_EN BIT(26) #define B_BE_PCIE_SEC_LOAD BIT(26) #define B_BE_PCIE_SER_RSTB BIT(25) #define B_BE_PCIE_SEC_LOAD_CLR BIT(24) @@ -4112,6 +4203,22 @@ #define B_BE_LPSROP_LOWPWRPLL BIT(7) #define B_BE_LPSROP_DSWRSD_SEL_MASK GENMASK(5, 4) +#define R_BE_SYSON_FSM_MON 0x00A0 +#define B_BE_FSM_MON_SEL_MASK GENMASK(26, 24) +#define B_BE_DOP_ELDO BIT(23) +#define B_BE_AFE_PLL_BYPASS BIT(22) +#define B_BE_PON_SWR_BYPASS BIT(21) +#define B_BE_PON_ADIE_BYPASS BIT(20) +#define B_BE_AFE_LS_BYPASS BIT(19) +#define B_BE_BTPMC_XTAL_SI_BYPASS BIT(17) +#define B_BE_WLPMC_XTAL_SI_BYPASS BIT(16) +#define B_BE_FSM_MON_UPD BIT(15) +#define B_BE_FSM_PAR_MASK GENMASK(14, 0) +#define WLAN_FSM_MASK 0xFFFFFF +#define WLAN_FSM_SET 0x4000000 +#define WLAN_FSM_STATE_MASK 0x1FF +#define WLAN_FSM_IDLE 0 + #define R_BE_EFUSE_CTRL_2_V1 0x00A4 #define B_BE_EF_ENT BIT(31) #define B_BE_EF_TCOLUMN_EN BIT(29) @@ -4128,6 +4235,10 @@ #define B_BE_EF_DSB_EN BIT(11) #define B_BE_EF_DLY_SEL_MASK GENMASK(3, 0) +#define R_BE_SCOREBOARD 0x00AC +#define B_BE_TOGGLE BIT(31) +#define B_BE_DATA_LINE_MASK GENMASK(30, 0) + #define R_BE_PMC_DBG_CTRL2 0x00CC #define B_BE_EFUSE_BURN_GNT_MASK GENMASK(31, 24) #define B_BE_DIS_IOWRAP_TIMEOUT BIT(16) @@ -4177,6 +4288,13 @@ #define R_BE_PCIE_MIO_INTD 0x00E8 #define B_BE_PCIE_MIO_DATA_MASK GENMASK(31, 0) +#define R_BE_SYS_CHIPINFO 0x00FC +#define B_BE_USB2_SEL BIT(31) +#define B_BE_U3PHY_RST_V1 BIT(30) +#define B_BE_U3_TERM_DETECT BIT(29) +#define B_BE_VERIFY_ENV_MASK GENMASK(9, 8) +#define B_BE_HW_ID_MASK GENMASK(7, 0) + #define R_BE_HALT_H2C_CTRL 0x0160 #define B_BE_HALT_H2C_TRIGGER BIT(0) @@ -4201,6 +4319,72 @@ #define R_BE_SECURE_BOOT_MALLOC_INFO 0x0184 +#define R_BE_FWS0IMR 0x0190 +#define B_BE_FS_HALT_H2C_INT_EN BIT(31) +#define B_BE_FS_FSM_HIOE_TO_EVENT_INT_EN BIT(30) +#define B_BE_FS_HCI_SUS_INT_EN BIT(29) +#define B_BE_FS_HCI_RES_INT_EN BIT(28) +#define B_BE_FS_HCI_RESET_INT_EN BIT(27) +#define B_BE_FS_BT_SB1_INT_EN BIT(26) +#define B_BE_FS_ACT2RECOVERY_INT_EN BIT(25) +#define B_BE_FS_GEN1GEN2_SWITCH_INT_EN BIT(24) +#define B_BE_FS_USB_LPMRSM_INT_EN BIT(22) +#define B_BE_FS_USB_LPMINT_INT_EN BIT(21) +#define B_BE_FS_PWMERR_INT_EN BIT(20) +#define B_BE_FS_PDNINT_EN BIT(19) +#define B_BE_FS_SPSA_OCP_INT_EN BIT(18) +#define B_BE_FS_SPSD_OCP_INT_EN BIT(17) +#define B_BE_FS_BT_SB0_INT_EN BIT(16) +#define B_BE_FS_GPIOF_INT_EN BIT(15) +#define B_BE_FS_GPIOE_INT_EN BIT(14) +#define B_BE_FS_GPIOD_INT_EN BIT(13) +#define B_BE_FS_GPIOC_INT_EN BIT(12) +#define B_BE_FS_GPIOB_INT_EN BIT(11) +#define B_BE_FS_GPIOA_INT_EN BIT(10) +#define B_BE_FS_GPIO9_INT_EN BIT(9) +#define B_BE_FS_GPIO8_INT_EN BIT(8) +#define B_BE_FS_GPIO7_INT_EN BIT(7) +#define B_BE_FS_GPIO6_INT_EN BIT(6) +#define B_BE_FS_GPIO5_INT_EN BIT(5) +#define B_BE_FS_GPIO4_INT_EN BIT(4) +#define B_BE_FS_GPIO3_INT_EN BIT(3) +#define B_BE_FS_GPIO2_INT_EN BIT(2) +#define B_BE_FS_GPIO1_INT_EN BIT(1) +#define B_BE_FS_GPIO0_INT_EN BIT(0) + +#define R_BE_FWS0ISR 0x0194 +#define B_BE_FS_HALT_H2C_INT BIT(31) +#define B_BE_FS_FSM_HIOE_TO_EVENT_INT BIT(30) +#define B_BE_FS_HCI_SUS_INT BIT(29) +#define B_BE_FS_HCI_RES_INT BIT(28) +#define B_BE_FS_HCI_RESET_INT BIT(27) +#define B_BE_FS_BT_SB1_INT BIT(26) +#define B_BE_FS_ACT2RECOVERY_INT BIT(25) +#define B_BE_FS_GEN1GEN2_SWITCH_INT BIT(24) +#define B_BE_FS_USB_LPMRSM_INT BIT(22) +#define B_BE_FS_USB_LPMINT_INT BIT(21) +#define B_BE_FS_PWMERR_INT BIT(20) +#define B_BE_FS_PDNINT BIT(19) +#define B_BE_FS_SPSA_OCP_INT BIT(18) +#define B_BE_FS_SPSD_OCP_INT BIT(17) +#define B_BE_FS_BT_SB0_INT BIT(16) +#define B_BE_FS_GPIOF_INT BIT(15) +#define B_BE_FS_GPIOE_INT BIT(14) +#define B_BE_FS_GPIOD_INT BIT(13) +#define B_BE_FS_GPIOC_INT BIT(12) +#define B_BE_FS_GPIOB_INT BIT(11) +#define B_BE_FS_GPIOA_INT BIT(10) +#define B_BE_FS_GPIO9_INT BIT(9) +#define B_BE_FS_GPIO8_INT BIT(8) +#define B_BE_FS_GPIO7_INT BIT(7) +#define B_BE_FS_GPIO6_INT BIT(6) +#define B_BE_FS_GPIO5_INT BIT(5) +#define B_BE_FS_GPIO4_INT BIT(4) +#define B_BE_FS_GPIO3_INT BIT(3) +#define B_BE_FS_GPIO2_INT BIT(2) +#define B_BE_FS_GPIO1_INT BIT(1) +#define B_BE_FS_GPIO0_INT BIT(0) + #define R_BE_FWS1IMR 0x0198 #define B_BE_FS_RPWM_INT_EN_V1 BIT(24) #define B_BE_PCIE_HOTRST_EN BIT(22) @@ -4281,6 +4465,7 @@ #define B_BE_RUN_ENV_MASK GENMASK(31, 30) #define B_BE_WCPU_FWDL_STATUS_MASK GENMASK(29, 26) #define B_BE_WDT_PLT_RST_EN BIT(17) +#define B_BE_HOST_EXIST BIT(16) #define B_BE_FW_SEC_AUTH_DONE BIT(14) #define B_BE_FW_CPU_UTIL_STS_EN BIT(13) #define B_BE_BBMCU1_FWDL_EN BIT(12) @@ -4375,6 +4560,9 @@ #define B_BE_REG_CK40M_EN BIT(1) #define B_BE_REG_CK640M_EN BIT(0) +#define R_BE_GPIO8_15_FUNC_SEL 0x02D4 +#define B_BE_PINMUX_GPIO9_FUNC_SEL_MASK GENMASK(7, 4) + #define R_BE_WLAN_XTAL_SI_CTRL 0x0270 #define B_BE_WL_XTAL_SI_CMD_POLL BIT(31) #define B_BE_WL_XTAL_SI_CHIPID_MASK GENMASK(30, 28) @@ -4383,6 +4571,16 @@ #define B_BE_WL_XTAL_SI_DATA_MASK GENMASK(15, 8) #define B_BE_WL_XTAL_SI_ADDR_MASK GENMASK(7, 0) +#define R_BE_PCIE_SER_DBG 0x02FC +#define B_BE_PCIE_SER_DBG_MASK GENMASK(31, 10) +#define B_BE_PCIE_SER_PHY_PROTECT BIT(9) +#define B_BE_PCIE_SER_MAC_PROTECT BIT(8) +#define B_BE_PCIE_SER_FLUSH_RSTB BIT(4) +#define B_BE_PCIE_AXI_BRG_FLUSH_EN BIT(3) +#define B_BE_PCIE_SER_AUXCLK_RDY BIT(2) +#define B_BE_PCIE_SER_FRZ_REG_RST BIT(1) +#define B_BE_PCIE_SER_FRZ_CFG_SPC_RST BIT(0) + #define R_BE_IC_PWR_STATE 0x03F0 #define B_BE_WHOLE_SYS_PWR_STE_MASK GENMASK(25, 16) #define MAC_AX_SYS_ACT 0x220 @@ -4535,6 +4733,10 @@ #define R_BE_LTR_LATENCY_IDX2_V1 0x361C #define R_BE_LTR_LATENCY_IDX3_V1 0x3620 +#define R_BE_HCI_BUF_IMR 0x6018 +#define B_BE_HCI_BUF_IMR_CLR 0xC0000303 +#define B_BE_HCI_BUF_IMR_SET 0xC0000301 + #define R_BE_H2CREG_DATA0 0x7140 #define R_BE_H2CREG_DATA1 0x7144 #define R_BE_H2CREG_DATA2 0x7148 @@ -4554,6 +4756,10 @@ #define B_BE_HCI_RXDMA_EN BIT(1) #define B_BE_HCI_TXDMA_EN BIT(0) +#define R_BE_BOOT_DBG 0x78F0 +#define B_BE_BOOT_STATUS_MASK GENMASK(31, 16) +#define B_BE_SECUREBOOT_STATUS_MASK GENMASK(15, 0) + #define R_BE_DBG_WOW_READY 0x815E #define B_BE_DBG_WOW_READY GENMASK(7, 0) @@ -4625,6 +4831,9 @@ #define B_BE_LTR_CMAC1_RX_USE_PG_TH_MASK GENMASK(27, 16) #define B_BE_LTR_CMAC0_RX_USE_PG_TH_MASK GENMASK(11, 0) +#define R_BE_NO_RX_ERR_CFG 0x841C +#define B_BE_NO_RX_ERR_TO_MASK GENMASK(31, 29) + #define R_BE_DMAC_TABLE_CTRL 0x8420 #define B_BE_HWAMSDU_PADDING_MODE BIT(31) #define B_BE_MACID_MPDU_PROCESSOR_OFFSET_MASK GENMASK(26, 16) @@ -4636,7 +4845,7 @@ #define B_BE_SER_L0_PROMOTE_L1_EVENT_MASK GENMASK(31, 28) #define B_BE_SER_L1_COUNTER_MASK GENMASK(27, 24) #define B_BE_RMAC_PPDU_HANG_CNT_MASK GENMASK(23, 16) -#define B_BE_SER_L0_COUNTER_MASK GENMASK(8, 0) +#define B_BE_SER_L0_COUNTER_MASK GENMASK(7, 0) #define R_BE_DMAC_SYS_CR32B 0x842C #define B_BE_DMAC_BB_PHY1_MASK GENMASK(31, 16) @@ -4755,6 +4964,10 @@ #define R_BE_SER_L1_DBG_CNT_7 0x845C #define B_BE_SER_L1_DBG_2_MASK GENMASK(31, 0) +#define R_BE_FW_TRIGGER_IDCT_ISR 0x8508 +#define B_BE_DMAC_FW_ERR_IDCT_IMR BIT(31) +#define B_BE_DMAC_FW_TRIG_IDCT BIT(0) + #define R_BE_DMAC_ERR_IMR 0x8520 #define B_BE_DMAC_NOTX_ERR_INT_EN BIT(21) #define B_BE_DMAC_NORX_ERR_INT_EN BIT(20) @@ -4958,6 +5171,8 @@ B_BE_STF_WRFF_UNDERFLOW_ERR_INT_EN | \ B_BE_STF_OQT_OVERFLOW_ERR_INT_EN | \ B_BE_STF_OQT_UNDERFLOW_ERR_INT_EN) +#define B_BE_DISP_OTHER_IMR_CLR_V1 0xFFFFFFFF +#define B_BE_DISP_OTHER_IMR_SET_V1 0x3F002000 #define R_BE_DISP_HOST_IMR 0x8874 #define B_BE_HR_WRFF_UNDERFLOW_ERR_INT_EN BIT(31) @@ -5035,6 +5250,8 @@ B_BE_HR_DMA_PROCESS_ERR_INT_EN | \ B_BE_HR_WRFF_OVERFLOW_ERR_INT_EN | \ B_BE_HR_WRFF_UNDERFLOW_ERR_INT_EN) +#define B_BE_DISP_HOST_IMR_CLR_V1 0xFBFFFFFF +#define B_BE_DISP_HOST_IMR_SET_V1 0xC8B3E579 #define R_BE_DISP_CPU_IMR 0x8878 #define B_BE_CR_PLD_LEN_ERR_INT_EN BIT(30) @@ -5109,6 +5326,8 @@ B_BE_CR_DMA_PROCESS_ERR_INT_EN | \ B_BE_CR_WRFF_OVERFLOW_ERR_INT_EN | \ B_BE_CR_WRFF_UNDERFLOW_ERR_INT_EN) +#define B_BE_DISP_CPU_IMR_CLR_V1 0x7DFFFFFD +#define B_BE_DISP_CPU_IMR_SET_V1 0x34F938FD #define R_BE_RX_STOP 0x8914 #define B_BE_CPU_RX_STOP BIT(17) @@ -5403,6 +5622,10 @@ #define B_BE_PLE_Q12_MAX_SIZE_MASK GENMASK(27, 16) #define B_BE_PLE_Q12_MIN_SIZE_MASK GENMASK(11, 0) +#define R_BE_PLE_QTA13_CFG 0x9074 +#define B_BE_PLE_Q13_MAX_SIZE_MASK GENMASK(27, 16) +#define B_BE_PLE_Q13_MIN_SIZE_MASK GENMASK(11, 0) + #define R_BE_PLE_ERRFLAG1_IMR 0x90C0 #define B_BE_PLE_SRCHPG_PGOFST_IMR BIT(26) #define B_BE_PLE_SRCHPG_STRPG_IMR BIT(25) @@ -5460,7 +5683,21 @@ B_BE_WDRLS_RPT1_AGGNUM0_ERR_INT_EN | \ B_BE_WDRLS_RPT1_FRZTO_ERR_INT_EN) +#define R_BE_RLSRPT0_CFG0 0x9440 +#define B_BE_RLSRPT0_FWRLS BIT(31) +#define B_BE_RLSRPT0_FWD_TRGT_MASK GENMASK(23, 16) +#define B_BE_RLSRPT0_PID_MASK GENMASK(10, 8) +#define B_BE_RLSRPT0_QID_MASK GENMASK(5, 0) +#define WDRLS_DEST_QID_POH 1 +#define WDRLS_DEST_QID_STF 0 + #define R_BE_RLSRPT0_CFG1 0x9444 +#define B_BE_RLSRPT0_FLTR_MAP_V1_MASK GENMASK(28, 24) +#define S_BE_WDRLS_FLTR_TXOK_V1 BIT(0) +#define S_BE_WDRLS_FLTR_RTYLMT_V1 BIT(1) +#define S_BE_WDRLS_FLTR_LIFTIM_V1 BIT(2) +#define S_BE_WDRLS_FLTR_MACID_V1 BIT(3) +#define S_BE_WDRLS_FLTR_RELINK_V1 BIT(4) #define B_BE_RLSRPT0_FLTR_MAP_MASK GENMASK(27, 24) #define S_BE_WDRLS_FLTR_TXOK 1 #define S_BE_WDRLS_FLTR_RTYLMT 2 @@ -5754,12 +5991,18 @@ #define B_BE_MPDUINFO_PKTID_MASK GENMASK(27, 16) #define B_BE_MPDUINFO_B1_BADDR_MASK GENMASK(5, 0) #define MPDU_INFO_B1_OFST 18 +#define MPDU_INFO_TBL_FACTOR 3 #define R_BE_TXPKTCTL_B0_PRELD_CFG0 0x9F48 #define B_BE_B0_PRELD_FEN BIT(31) #define B_BE_B0_PRELD_USEMAXSZ_MASK GENMASK(25, 16) #define B_BE_B0_PRELD_CAM_G1ENTNUM_MASK GENMASK(12, 8) +#define PRELD_MISCQ_ENT_NUM_8922A 2 +#define PRELD_MISCQ_ENT_NUM_8922D 1 #define B_BE_B0_PRELD_CAM_G0ENTNUM_MASK GENMASK(4, 0) +#define PRELD_B0_ACQ_ENT_NUM_8922A 8 +#define PRELD_B1_ACQ_ENT_NUM_8922A 2 +#define PRELD_ACQ_ENT_NUM_8922D 1 #define R_BE_TXPKTCTL_B0_PRELD_CFG1 0x9F4C #define B_BE_B0_PRELD_NXT_TXENDWIN_MASK GENMASK(11, 8) @@ -5871,6 +6114,7 @@ #define B_BE_PLRLS_CTL_FRZTO_ISR BIT(0) #define R_BE_SS_CTRL 0xA310 +#define R_BE_SS_CTRL_V1 0xA610 #define B_BE_SS_INIT_DONE BIT(31) #define B_BE_WDE_STA_DIS BIT(30) #define B_BE_WARM_INIT BIT(29) @@ -5910,6 +6154,24 @@ #define B_BE_RPT_TIMEOUT_ISR BIT(1) #define B_BE_SEARCH_TIMEOUT_ISR BIT(0) +#define R_BE_PLRLS_ERR_IMR_V1 0xA518 +#define B_BE_PLRLS_DUMMY_ISR6 BIT(7) +#define B_BE_PLRLS_DUMMY_ISR5 BIT(6) +#define B_BE_PLRLS_DUMMY_ISR4 BIT(5) +#define B_BE_PLRLS_DUMMY_ISR3 BIT(4) +#define B_BE_PLRLS_DUMMY_ISR2 BIT(3) +#define B_BE_PLRLS_DUMMY_ISR1 BIT(2) +#define B_BE_PLRLS_DUMMY_ISR0 BIT(1) +#define B_BE_PLRLS_ERR_IMR_V1_CLR 0x1 +#define B_BE_PLRLS_ERR_IMR_V1_SET 0x1 + +#define R_BE_SS_LITE_TXL_MACID 0xA790 +#define B_BE_RPT_OTHER_BAND_EN BIT(31) +#define B_BE_TXL_CMD_EN BIT(30) +#define B_BE_TXL_READ_MACID_MASK GENMASK(29, 20) +#define B_BE_TXL_MACID_1_MASK GENMASK(19, 10) +#define B_BE_TXL_MACID_0_MASK GENMASK(9, 0) + #define R_BE_HAXI_INIT_CFG1 0xB000 #define B_BE_CFG_WD_PERIOD_IDLE_MASK GENMASK(31, 28) #define B_BE_CFG_WD_PERIOD_ACTIVE_MASK GENMASK(27, 24) @@ -5949,6 +6211,18 @@ #define B_BE_STOP_CH2 BIT(2) #define B_BE_STOP_CH1 BIT(1) #define B_BE_STOP_CH0 BIT(0) +#define B_BE_TX_STOP1_MASK (B_BE_STOP_CH0 | B_BE_STOP_CH1 | \ + B_BE_STOP_CH2 | B_BE_STOP_CH3 | \ + B_BE_STOP_CH4 | B_BE_STOP_CH5 | \ + B_BE_STOP_CH6 | B_BE_STOP_CH7 | \ + B_BE_STOP_CH8 | B_BE_STOP_CH9 | \ + B_BE_STOP_CH10 | B_BE_STOP_CH11 | \ + B_BE_STOP_CH12 | B_BE_STOP_CH13 | \ + B_BE_STOP_CH14) +#define B_BE_TX_STOP1_MASK_V1 (B_BE_STOP_CH0 | B_BE_STOP_CH2 | \ + B_BE_STOP_CH4 | B_BE_STOP_CH6 | \ + B_BE_STOP_CH8 | B_BE_STOP_CH10 | \ + B_BE_STOP_CH12) #define R_BE_HAXI_MST_WDT_TIMEOUT_SEL_V1 0xB02C #define B_BE_HAXI_MST_WDT_TIMEOUT_SEL_MASK GENMASK(4, 0) @@ -6001,6 +6275,7 @@ #define R_BE_CH_PAGE_CTRL 0xB704 #define B_BE_PREC_PAGE_CH12_V1_MASK GENMASK(21, 16) +#define B_BE_FULL_WD_PG_MASK GENMASK(15, 8) #define B_BE_PREC_PAGE_CH011_V1_MASK GENMASK(5, 0) #define R_BE_CH0_PAGE_CTRL 0xB718 @@ -6033,6 +6308,10 @@ #define R_BE_WP_PAGE_CTRL1 0xB7A4 #define B_BE_PREC_PAGE_WP_CH811_MASK GENMASK(24, 16) #define B_BE_PREC_PAGE_WP_CH07_MASK GENMASK(8, 0) +#define B_BE_FULL_PAGE_WP_CH811_MASK GENMASK(31, 24) +#define B_BE_PREC_PAGE_WP_CH811_V1_MASK GENMASK(23, 16) +#define B_BE_FULL_PAGE_WP_CH07_MASK GENMASK(15, 8) +#define B_BE_PREC_PAGE_WP_CH07_V1_MASK GENMASK(7, 0) #define R_BE_WP_PAGE_CTRL2 0xB7A8 #define B_BE_WP_THRD_MASK GENMASK(12, 0) @@ -6091,8 +6370,79 @@ #define B_BE_GNT_WL_BB_PWR_VAL BIT(1) #define B_BE_GNT_WL_BB_PWR_SWCTRL BIT(0) +#define R_BE_PTA_GNT_SW_CTRL 0x0E348 +#define B_BE_PTA_WL_ACT0_VAL BIT(19) +#define B_BE_PTA_WL_ACT0_SWCTRL BIT(18) +#define B_BE_PTA_GNT_BT0_RX_BB1_VAL BIT(17) +#define B_BE_PTA_GNT_BT0_RX_BB1_SWCTRL BIT(16) +#define B_BE_PTA_GNT_BT0_TX_BB1_VAL BIT(15) +#define B_BE_PTA_GNT_BT0_TX_BB1_SWCTRL BIT(14) +#define B_BE_PTA_GNT_BT0_RX_BB0_VAL BIT(13) +#define B_BE_PTA_GNT_BT0_RX_BB0_SWCTRL BIT(12) +#define B_BE_PTA_GNT_BT0_TX_BB0_VAL BIT(11) +#define B_BE_PTA_GNT_BT0_TX_BB0_SWCTRL BIT(10) +#define B_BE_PTA_GNT_BT0_BB_VAL BIT(9) +#define B_BE_PTA_GNT_BT0_BB_SWCTRL BIT(8) +#define B_BE_PTA_WL_ACT_RX_BT0_VAL BIT(7) +#define B_BE_PTA_WL_ACT_RX_BT0_SWCTRL BIT(6) +#define B_BE_PTA_WL_ACT_TX_BT0_VAL BIT(5) +#define B_BE_PTA_WL_ACT_TX_BT0_SWCTRL BIT(4) +#define B_BE_PTA_GNT_WL_BB1_VAL BIT(3) +#define B_BE_PTA_GNT_WL_BB1_SWCTRL BIT(2) +#define B_BE_PTA_GNT_WL_BB0_VAL BIT(1) +#define B_BE_PTA_GNT_WL_BB0_SWCTRL BIT(0) + +#define R_BE_PTA_GNT_VAL 0x0E34C +#define B_BE_PTA_WL_ACT2 BIT(20) +#define B_BE_PTA_GNT_ZB_TX_BB1 BIT(19) +#define B_BE_PTA_GNT_ZB_TX_BB0 BIT(18) +#define B_BE_PTA_WL_ACT1 BIT(17) +#define B_BE_PTA_GNT_BT1_RX_BB1 BIT(16) +#define B_BE_PTA_GNT_BT1_RX_BB0 BIT(15) +#define B_BE_PTA_GNT_BT1_TX_BB1 BIT(14) +#define B_BE_PTA_GNT_BT1_TX_BB0 BIT(13) +#define B_BE_PTA_WL_ACT_RX_BT1 BIT(12) +#define B_BE_PTA_WL_ACT_TX_BT1 BIT(11) +#define B_BE_PTA_GNT_BT1_BB BIT(10) +#define B_BE_PTA_WL_ACT0 BIT(9) +#define B_BE_PTA_GNT_BT0_RX_BB1 BIT(8) +#define B_BE_PTA_GNT_BT0_TX_BB1 BIT(7) +#define B_BE_PTA_GNT_BT0_RX_BB0 BIT(6) +#define B_BE_PTA_GNT_BT0_TX_BB0 BIT(5) +#define B_BE_PTA_GNT_BT0_BB BIT(4) +#define B_BE_PTA_WL_ACT_RX_BT0 BIT(3) +#define B_BE_PTA_WL_ACT_TX_BT0 BIT(2) +#define B_BE_PTA_GNT_WL_BB1 BIT(1) +#define B_BE_PTA_GNT_WL_BB0 BIT(0) + +#define R_BE_PTA_GNT_ZL_SW_CTRL 0x0E350 +#define B_BE_PTA_WL_ACT2_VAL BIT(21) +#define B_BE_PTA_WL_ACT2_SWCTRL BIT(20) +#define B_BE_PTA_GNT_ZB_TX_BB1_VAL BIT(19) +#define B_BE_PTA_GNT_ZB_TX_BB1_SWCTRL BIT(18) +#define B_BE_PTA_GNT_ZB_TX_BB0_VAL BIT(17) +#define B_BE_PTA_GNT_ZB_TX_BB0_SWCTRL BIT(16) +#define B_BE_PTA_WL_ACT1_VAL BIT(15) +#define B_BE_PTA_WL_ACT1_SWCTRL BIT(14) +#define B_BE_PTA_GNT_BT1_RX_BB1_VAL BIT(13) +#define B_BE_PTA_GNT_BT1_RX_BB1_SWCTRL BIT(12) +#define B_BE_PTA_GNT_BT1_RX_BB0_VAL BIT(11) +#define B_BE_PTA_GNT_BT1_RX_BB0_SWCTRL BIT(10) +#define B_BE_PTA_GNT_BT1_TX_BB1_VAL BIT(9) +#define B_BE_PTA_GNT_BT1_TX_BB1_SWCTRL BIT(8) +#define B_BE_PTA_GNT_BT1_TX_BB0_VAL BIT(7) +#define B_BE_PTA_GNT_BT1_TX_BB0_SWCTRL BIT(6) +#define B_BE_PTA_WL_ACT_RX_BT1_VAL BIT(5) +#define B_BE_PTA_WL_ACT_RX_BT1_SWCTRL BIT(4) +#define B_BE_PTA_WL_ACT_TX_BT1_VAL BIT(3) +#define B_BE_PTA_WL_ACT_TX_BT1_SWCTRL BIT(2) +#define B_BE_PTA_GNT_BT1_BB_VAL BIT(1) +#define B_BE_PTA_GNT_BT1_BB_SWCTRL BIT(0) + #define R_BE_PWR_MACID_PATH_BASE 0x0E500 +#define R_BE_PWR_MACID_PATH_BASE_V1 0x1C000 #define R_BE_PWR_MACID_LMT_BASE 0x0ED00 +#define R_BE_PWR_MACID_LMT_BASE_V1 0x1C800 #define R_BE_CMAC_FUNC_EN 0x10000 #define R_BE_CMAC_FUNC_EN_C1 0x14000 @@ -6155,6 +6505,19 @@ #define BE_WMAC_RFMOD_160M 3 #define BE_WMAC_RFMOD_320M 4 +#define R_BE_GID_POSITION0 0x10070 +#define R_BE_GID_POSITION0_C1 0x14070 +#define R_BE_GID_POSITION1 0x10074 +#define R_BE_GID_POSITION1_C1 0x14074 +#define R_BE_GID_POSITION2 0x10078 +#define R_BE_GID_POSITION2_C1 0x14078 +#define R_BE_GID_POSITION3 0x1007C +#define R_BE_GID_POSITION3_C1 0x1407C +#define R_BE_GID_POSITION_EN0 0x10080 +#define R_BE_GID_POSITION_EN0_C1 0x14080 +#define R_BE_GID_POSITION_EN1 0x10084 +#define R_BE_GID_POSITION_EN1_C1 0x14084 + #define R_BE_TX_SUB_BAND_VALUE 0x10088 #define R_BE_TX_SUB_BAND_VALUE_C1 0x14088 #define B_BE_PRI20_BITMAP_MASK GENMASK(31, 16) @@ -6189,6 +6552,21 @@ #define B_BE_RSC_MASK GENMASK(7, 6) #define B_BE_RRSR_CCK_MASK GENMASK(3, 0) +#define R_BE_COMMON_PHYINTF_CTRL_0 0x100B8 +#define R_BE_COMMON_PHYINTF_CTRL_0_C1 0x140B8 +#define B_BE_SEQ_EN_GUARD_CYE_MASK GENMASK(23, 20) +#define B_BE_PARA_FIFO_CRC_EN BIT(18) +#define B_BE_SEQ_FIFO_TO_EN BIT(17) +#define B_BE_PARA_FIFO_TO_EN BIT(16) +#define B_BE_SEQ_FIFO_CLR_EN BIT(6) +#define B_BE_PARA_FIFO_CLR_EN_V1 BIT(5) +#define B_BE_CSI_FIFO_CLR_EN_V1 BIT(4) +#define B_BE_FTM_FIFO_CLR_EN_V1 BIT(3) +#define B_BE_RXD_FIFO_CLR_EN_V1 BIT(2) +#define B_BE_TXD_FIFO_CLR_EN_V1 BIT(1) +#define B_BE_TXUID_FIFO_CLR_EN_V1 BIT(0) +#define CLEAR_DTOP_DIS (BIT(1) | BIT(5) | BIT(6)) + #define R_BE_CMAC_ERR_IMR 0x10160 #define R_BE_CMAC_ERR_IMR_C1 0x14160 #define B_BE_CMAC_FW_ERR_IDCT_EN BIT(16) @@ -6217,6 +6595,11 @@ #define B_BE_PTCL_TOP_ERR_IND BIT(1) #define B_BE_SCHEDULE_TOP_ERR_IND BIT(0) +#define R_BE_CMAC_FW_TRIGGER_IDCT_ISR 0x10168 +#define R_BE_CMAC_FW_TRIGGER_IDCT_ISR_C1 0x14168 +#define B_BE_CMAC_FW_ERR_IDCT_IMR BIT(31) +#define B_BE_CMAC_FW_TRIG_IDCT BIT(0) + #define R_BE_SER_L0_DBG_CNT 0x10170 #define R_BE_SER_L0_DBG_CNT_C1 0x14170 #define B_BE_SER_L0_PHYINTF_CNT_MASK GENMASK(31, 24) @@ -6276,6 +6659,25 @@ #define B_BE_P0_SYNC_PORT_SRC_SEL_MASK GENMASK(26, 24) #define B_BE_P0_TSFTR_SYNC_OFFSET_MASK GENMASK(18, 0) +#define R_BE_SCH_EDCA_RST_CFG 0x102E4 +#define R_BE_SCH_EDCA_RST_CFG_C1 0x142E4 +#define B_BE_EDCCA_S160_RST_EDCA_EN BIT(23) +#define B_BE_EDCCA_S80_RST_EDCA_EN BIT(22) +#define B_BE_EDCCA_S40_RST_EDCA_EN BIT(21) +#define B_BE_EDCCA_S20_RST_EDCA_EN BIT(20) +#define B_BE_OFDM_CCA_S160_RST_EDCA_EN BIT(19) +#define B_BE_CCA_PEB_BE_BITMAP_RST_EDCA_EN BIT(18) +#define B_BE_RX_INTRA_NAV_RST_EDCA_EN BIT(15) +#define B_BE_RX_BASIC_NAV_RST_EDCA_EN BIT(14) +#define B_BE_EDCCA_PER20_BITMAP_SIFS_RST_EDCA_EN BIT(10) +#define B_BE_TX_NAV_RST_EDCA_EN BIT(7) +#define B_BE_NO_GNT_WL_RST_EDCA_EN BIT(5) +#define B_BE_EDCCA_P20_RST_EDCA_EN BIT(4) +#define B_BE_OFDM_CCA_S80_RST_EDCA_EN BIT(3) +#define B_BE_OFDM_CCA_S40_RST_EDCA_EN BIT(2) +#define B_BE_OFDM_CCA_S20_RST_EDCA_EN BIT(1) +#define B_BE_CCA_P20_RST_EDCA_EN BIT(0) + #define R_BE_EDCA_BCNQ_PARAM 0x10324 #define R_BE_EDCA_BCNQ_PARAM_C1 0x14324 #define B_BE_BCNQ_CW_MASK GENMASK(31, 24) @@ -6566,6 +6968,34 @@ #define B_BE_CMAC_TX_MODE_1 BIT(1) #define B_BE_CMAC_TX_MODE_0 BIT(0) +#define R_BE_AGG_BK_0 0x10804 +#define R_BE_AGG_BK_0_C1 0x14804 +#define B_BE_DIS_SAMPDU_TXIME_SR_CHECK BIT(24) +#define B_BE_TX_PAIR_MACID_LEN_EN BIT(23) +#define B_BE_DIS_SND_STS_CHECK_SU BIT(22) +#define B_BE_MAX_AGG_NUM_FIX_MODE_EN_V1 BIT(21) +#define B_BE_DIS_SIFS_BK_AGG_AMPDU BIT(20) +#define B_BE_EN_MU2SU_CHK_PROTECT_PPDU BIT(19) +#define B_BE_RPT_TXOP_START_PROTECT BIT(18) +#define B_BE_RANDOM_GEN_CMD_ABORT_EN BIT(17) +#define B_BE_PHYTXON_ENDPS_RESP_CHK BIT(16) +#define B_BE_CTN_CHK_SEQ_REQ_EN BIT(15) +#define B_BE_PTCL_RLS_ALLFAIL_EN BIT(14) +#define B_BE_DIS_MURU_PRI_Q_EMPTY_CHK BIT(13) +#define B_BE_DIS_MURU_SEC_Q_EMPTY_CHK BIT(12) +#define B_BE_EN_SAMPDU_TXIME_TWT_CHECK BIT(11) +#define B_BE_DIS_SAMPDU_TXIME_P2P_CHECK BIT(10) +#define B_BE_DIS_SAMPDU_TXIME_BCN_CHECK BIT(9) +#define B_BE_DIS_UL_SEQ_ABORT_CHECK BIT(8) +#define B_BE_DIS_SND_STS_CHECK BIT(7) +#define B_BE_NAV_PAUS_PHB_EN BIT(6) +#define B_BE_TXOP_SHT_PHB_EN BIT(5) +#define B_BE_AGG_BRK_PHB_EN BIT(4) +#define B_BE_DIS_SSN_CHK BIT(3) +#define B_BE_WDBK_CFG BIT(2) +#define B_BE_EN_RTY_BK BIT(1) +#define B_BE_EN_RTY_BK_COD BIT(0) + #define R_BE_TB_PPDU_CTRL 0x1080C #define R_BE_TB_PPDU_CTRL_C1 0x1480C #define B_BE_TB_PPDU_BK_DIS BIT(15) @@ -6580,9 +7010,11 @@ #define R_BE_AMPDU_AGG_LIMIT_C1 0x14810 #define B_BE_AMPDU_MAX_TIME_MASK GENMASK(31, 24) #define AMPDU_MAX_TIME 0x9E +#define AMPDU_MAX_TIME_V1 0xA4 #define B_BE_RA_TRY_RATE_AGG_LMT_MASK GENMASK(23, 16) #define B_BE_RTS_MAX_AGG_NUM_MASK GENMASK(15, 8) #define B_BE_MAX_AGG_NUM_MASK GENMASK(7, 0) +#define MAX_TX_AMPDU_NUM_V1 128 #define R_BE_AGG_LEN_HT_0 0x10814 #define R_BE_AGG_LEN_HT_0_C1 0x14814 @@ -6590,6 +7022,20 @@ #define B_BE_RTS_TXTIME_TH_MASK GENMASK(15, 8) #define B_BE_RTS_LEN_TH_MASK GENMASK(7, 0) +#define R_BE_SPECIAL_TX_SETTING 0x10820 +#define R_BE_SPECIAL_TX_SETTING_C1 0x14820 +#define B_BE_TRI_PADDING_EXTEND BIT(31) +#define B_BE_TX_SN_BYPASS_EN BIT(30) +#define B_BE_USE_DATA_BW BIT(29) +#define B_BE_BW_SIGTA_MASK GENMASK(28, 27) +#define B_BE_BMC_NAV_PROTECT BIT(26) +#define B_BE_F2P_KEEP_NON_SR_CMD BIT(25) +#define B_BE_F2P_SU_FIXRATE_OVER_WD BIT(24) +#define B_BE_BAR_TXRATE_FOR_NULL_WD_MASK GENMASK(23, 20) +#define B_BE_STBC_CFEND_MASK GENMASK(19, 18) +#define B_BE_STBC_CFEND_RATE_MASK GENMASK(17, 9) +#define B_BE_BASIC_CFEND_RATE_MASK GENMASK(8, 0) + #define R_BE_SIFS_SETTING 0x10824 #define R_BE_SIFS_SETTING_C1 0x14824 #define B_BE_HW_CTS2SELF_PKT_LEN_TH_MASK GENMASK(31, 24) @@ -6623,6 +7069,44 @@ #define B_BE_PORT_DROP_4_0_MASK GENMASK(20, 16) #define B_BE_MBSSID_DROP_15_0_MASK GENMASK(15, 0) +#define R_BE_PTCL_PRELD_CTRL 0x10868 +#define R_BE_PTCL_PRELD_CTRL_C1 0x14868 +#define B_BE_PRELD_MGQ2_EN BIT(22) +#define B_BE_PRELD_MGQ1_EN BIT(21) +#define B_BE_PRELD_MGQ0_EN BIT(20) +#define B_BE_PRELD_HIQ_P4_EN BIT(19) +#define B_BE_PRELD_HIQ_P3_EN BIT(18) +#define B_BE_PRELD_HIQ_P2_EN BIT(17) +#define B_BE_PRELD_HIQ_P1_EN BIT(16) +#define B_BE_PRELD_HIQ_P0MB15_EN BIT(15) +#define B_BE_PRELD_HIQ_P0MB14_EN BIT(14) +#define B_BE_PRELD_HIQ_P0MB13_EN BIT(13) +#define B_BE_PRELD_HIQ_P0MB12_EN BIT(12) +#define B_BE_PRELD_HIQ_P0MB11_EN BIT(11) +#define B_BE_PRELD_HIQ_P0MB10_EN BIT(10) +#define B_BE_PRELD_HIQ_P0MB9_EN BIT(9) +#define B_BE_PRELD_HIQ_P0MB8_EN BIT(8) +#define B_BE_PRELD_HIQ_P0MB7_EN BIT(7) +#define B_BE_PRELD_HIQ_P0MB6_EN BIT(6) +#define B_BE_PRELD_HIQ_P0MB5_EN BIT(5) +#define B_BE_PRELD_HIQ_P0MB4_EN BIT(4) +#define B_BE_PRELD_HIQ_P0MB3_EN BIT(3) +#define B_BE_PRELD_HIQ_P0MB2_EN BIT(2) +#define B_BE_PRELD_HIQ_P0MB1_EN BIT(1) +#define B_BE_PRELD_HIQ_P0_EN BIT(0) +#define B_BE_PRELD_HIQ_ALL_EN (B_BE_PRELD_HIQ_P0_EN | B_BE_PRELD_HIQ_P1_EN | \ + B_BE_PRELD_HIQ_P2_EN | B_BE_PRELD_HIQ_P3_EN | \ + B_BE_PRELD_HIQ_P4_EN) +#define B_BE_PRELD_HIQ_P0MB_ALL_EN \ + (B_BE_PRELD_HIQ_P0_EN | B_BE_PRELD_HIQ_P0MB1_EN | \ + B_BE_PRELD_HIQ_P0MB2_EN | B_BE_PRELD_HIQ_P0MB3_EN | \ + B_BE_PRELD_HIQ_P0MB4_EN | B_BE_PRELD_HIQ_P0MB5_EN | \ + B_BE_PRELD_HIQ_P0MB6_EN | B_BE_PRELD_HIQ_P0MB7_EN | \ + B_BE_PRELD_HIQ_P0MB8_EN | B_BE_PRELD_HIQ_P0MB9_EN | \ + B_BE_PRELD_HIQ_P0MB10_EN | B_BE_PRELD_HIQ_P0MB11_EN | \ + B_BE_PRELD_HIQ_P0MB12_EN | B_BE_PRELD_HIQ_P0MB13_EN | \ + B_BE_PRELD_HIQ_P0MB14_EN | B_BE_PRELD_HIQ_P0MB15_EN) + #define R_BE_BT_PLT 0x1087C #define R_BE_BT_PLT_C1 0x1487C #define B_BE_BT_PLT_PKT_CNT_MASK GENMASK(31, 16) @@ -6863,6 +7347,8 @@ B_BE_RX_RU1_FSM_HANG_ERROR_IMR | \ B_BE_RX_RU0_FSM_HANG_ERROR_IMR | \ B_BE_RX_GET_NULL_PKT_ERROR_IMR) +#define B_BE_RX_ERROR_FLAG_IMR_CLR_V1 0x7FFFFFF8 +#define B_BE_RX_ERROR_FLAG_IMR_SET_V1 0x7FFFFF38 #define R_BE_RX_CTRL_1 0x10C0C #define R_BE_RX_CTRL_1_C1 0x14C0C @@ -7280,6 +7766,8 @@ #define B_BE_ACK_BA_RESP_LEGACY_CHK_SEC_CCA20 BIT(2) #define B_BE_ACK_BA_RESP_LEGACY_CHK_EDCCA BIT(1) #define B_BE_ACK_BA_RESP_LEGACY_CHK_CCA BIT(0) +#define RESP_ACK_CFG_BE (B_BE_ACK_BA_RESP_LEGACY_CHK_BTCCA | \ + B_BE_ACK_BA_RESP_LEGACY_CHK_TX_NAV) #define R_BE_WMAC_ACK_BA_RESP_HE 0x11204 #define R_BE_WMAC_ACK_BA_RESP_HE_C1 0x15204 @@ -7321,6 +7809,188 @@ #define B_BE_ACK_BA_EHT_LEG_PUNC_CHK_EDCCA BIT(1) #define B_BE_ACK_BA_EHT_LEG_PUNC_CHK_CCA BIT(0) +#define R_BE_WMAC_RX_RTS_RESP_LEGACY 0x1120C +#define R_BE_WMAC_RX_RTS_RESP_LEGACY_C1 0x1520C +#define B_BE_RX_RTS_RESP_LEGACY_CHK_NSTR BIT(16) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV BIT(15) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_INTRA_NAV BIT(14) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV BIT(13) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA BIT(12) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA160 BIT(5) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA80 BIT(4) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA40 BIT(3) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA20 BIT(2) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA BIT(1) +#define B_BE_RX_RTS_RESP_LEGACY_CHK_CCA BIT(0) +#define RESP_RTS_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA20 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA40 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA80 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA160 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA20 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA40 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA80 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA160 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_INTRA_NAV | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV) +#define RESP_RTS_PUNC_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_CCA_PER20_BMP | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_INTRA_NAV | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV) +#define RESP_NORMAL_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA20 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA40 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA80 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_CCA160 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA20 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA40 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA80 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_SEC_EDCCA160 | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV) +#define RESP_NORMAL_PUNC_CFG_BE (B_BE_RX_RTS_RESP_LEGACY_CHK_CCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_CCA_PER20_BMP | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BTCCA | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_BASIC_NAV | \ + B_BE_RX_RTS_RESP_LEGACY_CHK_TX_NAV) + +#define R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC 0x11210 +#define R_BE_WMAC_RX_RTS_RESP_LEGACY_PUNC_C1 0x15210 +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_NSTR BIT(16) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_TX_NAV BIT(15) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_INTRA_NAV BIT(14) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_BASIC_NAV BIT(13) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_BTCCA BIT(12) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA160 BIT(5) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA80 BIT(4) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA40 BIT(3) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_SEC_CCA20 BIT(2) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_EDCCA BIT(1) +#define B_BE_RX_RTS_RESP_LEGACY_PUNC_CHK_CCA BIT(0) + +#define R_BE_WMAC_RX_MURTS_RESP_LEGACY 0x11214 +#define R_BE_WMAC_RX_MURTS_RESP_LEGACY_C1 0x15214 +#define B_BE_MURTS_RESP_LEGACY_CHK_NSTR BIT(16) +#define B_BE_MURTS_RESP_LEGACY_CHK_TX_NAV BIT(15) +#define B_BE_MURTS_RESP_LEGACY_CHK_INTRA_NAV BIT(14) +#define B_BE_MURTS_RESP_LEGACY_CHK_BASIC_NAV BIT(13) +#define B_BE_MURTS_RESP_LEGACY_CHK_BTCCA BIT(12) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_MURTS_RESP_LEGACY_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_MURTS_RESP_LEGACY_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA160 BIT(5) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA80 BIT(4) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA40 BIT(3) +#define B_BE_MURTS_RESP_LEGACY_CHK_SEC_CCA20 BIT(2) +#define B_BE_MURTS_RESP_LEGACY_CHK_EDCCA BIT(1) +#define B_BE_MURTS_RESP_LEGACY_CHK_CCA BIT(0) + +#define R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC 0x11218 +#define R_BE_WMAC_RX_MURTS_RESP_LEGACY_PUNC_C1 0x15218 +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_NSTR BIT(16) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_TX_NAV BIT(15) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_INTRA_NAV BIT(14) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_BASIC_NAV BIT(13) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_BTCCA BIT(12) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA160 BIT(5) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA80 BIT(4) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA40 BIT(3) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_SEC_CCA20 BIT(2) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_EDCCA BIT(1) +#define B_BE_MURTS_RESP_LEGACY_PUNC_CHK_CCA BIT(0) + +#define R_BE_WMAC_OTHERS_RESP_LEGACY 0x1121C +#define R_BE_WMAC_OTHERS_RESP_LEGACY_C1 0x1521C +#define B_BE_OTHERS_RESP_LEGACY_CHK_NSTR BIT(16) +#define B_BE_OTHERS_RESP_LEGACY_CHK_TX_NAV BIT(15) +#define B_BE_OTHERS_RESP_LEGACY_CHK_INTRA_NAV BIT(14) +#define B_BE_OTHERS_RESP_LEGACY_CHK_BASIC_NAV BIT(13) +#define B_BE_OTHERS_RESP_LEGACY_CHK_BTCCA BIT(12) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_OTHERS_RESP_LEGACY_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_OTHERS_RESP_LEGACY_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA160 BIT(5) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA80 BIT(4) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA40 BIT(3) +#define B_BE_OTHERS_RESP_LEGACY_CHK_SEC_CCA20 BIT(2) +#define B_BE_OTHERS_RESP_LEGACY_CHK_EDCCA BIT(1) +#define B_BE_OTHERS_RESP_LEGACY_CHK_CCA BIT(0) + +#define R_BE_WMAC_OTHERS_RESP_HE 0x11220 +#define R_BE_WMAC_OTHERS_RESP_HE_C1 0x15220 +#define B_BE_OTHERS_RESP_HE_CHK_NSTR BIT(16) +#define B_BE_OTHERS_RESP_HE_CHK_TX_NAV BIT(15) +#define B_BE_OTHERS_RESP_HE_CHK_INTRA_NAV BIT(14) +#define B_BE_OTHERS_RESP_HE_CHK_BASIC_NAV BIT(13) +#define B_BE_OTHERS_RESP_HE_CHK_BTCCA BIT(12) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_OTHERS_RESP_HE_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_OTHERS_RESP_HE_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA160 BIT(5) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA80 BIT(4) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA40 BIT(3) +#define B_BE_OTHERS_RESP_HE_CHK_SEC_CCA20 BIT(2) +#define B_BE_OTHERS_RESP_HE_CHK_EDCCA BIT(1) +#define B_BE_OTHERS_RESP_HE_CHK_CCA BIT(0) + +#define R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC 0x11224 +#define R_BE_WMAC_OTHERS_RESP_EHT_LEG_PUNC_C1 0x15224 +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_NSTR BIT(16) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_TX_NAV BIT(15) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_INTRA_NAV BIT(14) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_BASIC_NAV BIT(13) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_BTCCA BIT(12) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA160 BIT(11) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA80 BIT(10) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA40 BIT(9) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_EDCCA20 BIT(8) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_EDCCA_PER20_BMP BIT(7) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_CCA_PER20_BMP BIT(6) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA160 BIT(5) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA80 BIT(4) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA40 BIT(3) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_SEC_CCA20 BIT(2) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_EDCCA BIT(1) +#define B_BE_OTHERS_RESP_EHT_LEG_PUNC_CHK_CCA BIT(0) + #define R_BE_RCR 0x11400 #define R_BE_RCR_C1 0x15400 #define B_BE_BUSY_CHKSN BIT(15) @@ -7358,6 +8028,17 @@ #define B_BE_CCK_SIG_CHK BIT(1) #define B_BE_CCK_CRC_CHK BIT(0) +#define R_BE_RXGCK_CTRL 0x11406 +#define R_BE_RXGCK_CTRL_C1 0x15406 +#define B_BE_RXGCK_BCNPRS_DISGCLK BIT(12) +#define B_BE_RXGCK_GCK_RATE_LIMIT_MASK GENMASK(9, 8) +#define RX_GCK_LEGACY 2 +#define B_BE_RXGCK_DISREG_GCLK BIT(7) +#define B_BE_RXGCK_ENTRY_DELAY_MASK GENMASK(6, 4) +#define B_BE_RXGCK_GCK_CYCLE_MASK GENMASK(3, 2) +#define B_BE_RXGCK_CCA_EN BIT(1) +#define B_BE_DISGCLK BIT(0) + #define R_BE_RX_FLTR_OPT 0x11420 #define R_BE_RX_FLTR_OPT_C1 0x15420 #define B_BE_UID_FILTER_MASK GENMASK(31, 24) @@ -7430,7 +8111,6 @@ #define B_BE_PPDU_STAT_RPT_ADDR BIT(4) #define B_BE_APP_PLCP_HDR_RPT BIT(3) #define B_BE_APP_RX_CNT_RPT BIT(2) -#define B_BE_PPDU_MAC_INFO BIT(1) #define B_BE_PPDU_STAT_RPT_EN BIT(0) #define R_BE_RX_SR_CTRL 0x1144A @@ -7453,10 +8133,19 @@ #define B_BE_CSIPRT_HESU_AID_EN BIT(25) #define B_BE_CSIPRT_VHTSU_AID_EN BIT(24) +#define R_BE_BSR_UPD_CTRL 0x11468 +#define R_BE_BSR_UPD_CTRL_C1 0x15468 +#define B_BE_QSIZE_RULE BIT(1) +#define B_BE_QSIZE_UPD BIT(0) + #define R_BE_DRV_INFO_OPTION 0x11470 #define R_BE_DRV_INFO_OPTION_C1 0x15470 #define B_BE_DRV_INFO_PHYRPT_EN BIT(0) +#define R_BE_BCN_PSR_RPT_P0 0x11484 +#define R_BE_BCN_PSR_RPT_P0_C1 0x15484 +#define B_BE_BCAID_P0_MASK GENMASK(10, 0) + #define R_BE_RX_ERR_ISR 0x114F4 #define R_BE_RX_ERR_ISR_C1 0x154F4 #define B_BE_RX_ERR_TRIG_ACT_TO BIT(9) @@ -7514,11 +8203,35 @@ #define B_BE_PLCP_CH20_WIDATA_SRC BIT(1) #define B_BE_PLCP_PPDU_TYPE_SRC BIT(0) +#define R_BE_RX_PLCP_EXT_OPTION_2 0x11518 +#define R_BE_RX_PLCP_EXT_OPTION_2_C1 0x15518 +#define B_BE_PLCP_PHASE_B_CRC_CHK_EN BIT(17) +#define B_BE_PLCP_PHASE_A_CRC_CHK_EN BIT(16) +#define B_BE_EHTTB_EHTSIG_CRC_CHK_EN BIT(3) +#define B_BE_EHTTB_USIG_CRC_CHK_EN BIT(2) +#define B_BE_EHTMU_EHTSIG_CRC_CHK_EN BIT(1) +#define B_BE_EHTMU_USIG_CRC_CHK_EN BIT(0) + #define R_BE_RESP_CSI_RESERVED_PAGE 0x11810 #define R_BE_RESP_CSI_RESERVED_PAGE_C1 0x15810 #define B_BE_CSI_RESERVED_PAGE_NUM_MASK GENMASK(27, 16) #define B_BE_CSI_RESERVED_START_PAGE_MASK GENMASK(11, 0) +#define R_BE_RESP_IMR1 0x11878 +#define R_BE_RESP_IMR1_C1 0x15878 +#define B_BE_RESP_IMR_1_MASK GENMASK(31, 9) +#define B_BE_FSM_TIMEOUT_ERR_IMR BIT(8) +#define B_BE_SEC_DOUBLE_HIT_ERR_IMR BIT(7) +#define B_BE_WRPTR_ERR_IMR BIT(6) +#define B_BE_SMR_TOO_MANY_PLD_ERR_IMR BIT(5) +#define B_BE_LMR_TOO_MANY_PLD_ERR_IMR BIT(4) +#define B_BE_CSI_TOO_MANY_PLD_ERR_IMR BIT(3) +#define B_BE_FTM_LMR_PLDID_READY_ERR_IMR BIT(2) +#define B_BE_SMR_PLDID_READY_ERR_IMR BIT(1) +#define B_BE_CSI_PLDID_READY_ERR_IMR BIT(0) +#define B_BE_RESP_IMR1_CLR 0x1FF +#define B_BE_RESP_IMR1_SET 0xFF + #define R_BE_RESP_IMR 0x11884 #define R_BE_RESP_IMR_C1 0x15884 #define B_BE_RESP_TBL_FLAG_ERR_ISR_EN BIT(17) @@ -7563,6 +8276,8 @@ B_BE_RESP_PLDID_RDY_ERR_ISR_EN | \ B_BE_RESP_WRPTR_CROSS_ERR_ISR_EN | \ B_BE_RESP_SEC_DOUBLE_HIT_ERR_ISR_EN) +#define B_BE_RESP_IMR_CLR_V1 0xFFFFFFFF +#define B_BE_RESP_IMR_SET_V1 0xFFFFFFFF #define R_BE_PWR_MODULE 0x11900 #define R_BE_PWR_MODULE_C1 0x15900 @@ -7621,6 +8336,7 @@ #define R_BE_PWR_FTM 0x11B00 #define R_BE_PWR_FTM_SS 0x11B04 +#define B_BE_PWR_BY_RATE_DBW_ON GENMASK(27, 26) #define R_BE_PWR_BY_RATE 0x11E00 #define R_BE_PWR_BY_RATE_MAX 0x11FA8 @@ -7641,6 +8357,10 @@ #define R_BE_TXPWR_ERR_FLAG_C1 0x158E4 #define R_BE_TXPWR_ERR_IMR_C1 0x158E0 +#define R_BE_SCH_EXT_CTRL 0x103FC +#define R_BE_SCH_EXT_CTRL_C1 0x143FC +#define B_BE_CWCNT_PLUS_MODE BIT(31) + #define CMAC1_START_ADDR_BE 0x14000 #define CMAC1_END_ADDR_BE 0x17FFF @@ -7925,6 +8645,7 @@ #define B_UPD_P0_EN BIT(31) #define R_EMLSR 0x0044 #define B_EMLSR_PARM GENMASK(27, 12) +#define R_CHK_LPS_STAT_BE4 0x3007C #define R_CHK_LPS_STAT 0x0058 #define B_CHK_LPS_STAT BIT(0) #define R_SPOOF_CG 0x00B4 @@ -7998,10 +8719,12 @@ #define R_MAC_PIN_SEL 0x0734 #define B_CH_IDX_SEG0 GENMASK(23, 16) #define R_PLCP_HISTOGRAM 0x0738 +#define R_PLCP_HISTOGRAM_BE_V1 0x20738 #define B_STS_PARSING_TIME GENMASK(19, 16) #define B_STS_DIS_TRIG_BY_FAIL BIT(3) #define B_STS_DIS_TRIG_BY_BRK BIT(2) #define R_PHY_STS_BITMAP_ADDR_START R_PHY_STS_BITMAP_SEARCH_FAIL +#define R_PHY_STS_BITMAP_ADDR_START_BE4 0x2073C #define B_PHY_STS_BITMAP_ADDR_MASK GENMASK(6, 2) #define R_PHY_STS_BITMAP_SEARCH_FAIL 0x073C #define B_PHY_STS_BITMAP_MSK_52A 0x337cff3f @@ -8020,6 +8743,7 @@ #define R_PHY_STS_BITMAP_VHT 0x0770 #define R_PHY_STS_BITMAP_HE 0x0774 #define R_PHY_STS_BITMAP_EHT 0x0788 +#define R_PHY_STS_BITMAP_EHT_BE4 0x20788 #define R_EDCCA_RPTREG_SEL_BE 0x078C #define B_EDCCA_RPTREG_SEL_BE_MSK GENMASK(22, 20) #define R_PMAC_GNT 0x0980 @@ -8050,42 +8774,71 @@ #define R_DBCC_80P80_SEL_EVM_RPT 0x0A10 #define B_DBCC_80P80_SEL_EVM_RPT_EN BIT(0) #define R_CCX 0x0C00 +#define R_CCX_BE4 0x20C00 #define B_CCX_EDCCA_OPT_MSK GENMASK(6, 4) #define B_CCX_EDCCA_OPT_MSK_V1 GENMASK(7, 4) #define B_MEASUREMENT_TRIG_MSK BIT(2) #define B_CCX_TRIG_OPT_MSK BIT(1) #define B_CCX_EN_MSK BIT(0) +#define R_NHM_CFG 0x0C08 +#define B_NHM_PERIOD_MSK GENMASK(15, 0) +#define B_NHM_COUNTER_MSK GENMASK(17, 16) +#define B_NHM_EN_MSK BIT(18) +#define B_NHM_INCLUDE_CCA_MSK BIT(19) +#define B_NHM_TH0_MSK GENMASK(31, 24) +#define R_NHM_TH1 0x0C0C +#define B_NHM_TH1_MSK GENMASK(7, 0) +#define B_NHM_TH2_MSK GENMASK(15, 8) +#define B_NHM_TH3_MSK GENMASK(23, 16) +#define B_NHM_TH4_MSK GENMASK(31, 24) +#define R_NHM_TH5 0x0C10 +#define B_NHM_TH5_MSK GENMASK(7, 0) +#define B_NHM_TH6_MSK GENMASK(15, 8) +#define B_NHM_TH7_MSK GENMASK(23, 16) +#define B_NHM_TH8_MSK GENMASK(31, 24) +#define R_NHM_TH9 0x0C14 +#define B_NHM_TH9_MSK GENMASK(7, 0) +#define B_NHM_TH10_MSK GENMASK(15, 8) +#define B_NHM_PWDB_METHOD_MSK GENMASK(17, 16) #define R_FAHM 0x0C1C #define B_RXTD_CKEN BIT(2) #define R_IFS_COUNTER 0x0C28 +#define R_IFS_COUNTER_BE4 0x20C28 #define B_IFS_CLM_PERIOD_MSK GENMASK(31, 16) #define B_IFS_CLM_COUNTER_UNIT_MSK GENMASK(15, 14) #define B_IFS_COUNTER_CLR_MSK BIT(13) #define B_IFS_COLLECT_EN BIT(12) #define R_IFS_T1 0x0C2C +#define R_IFS_T1_BE4 0x20C2C #define B_IFS_T1_TH_HIGH_MSK GENMASK(31, 16) #define B_IFS_T1_EN_MSK BIT(15) #define B_IFS_T1_TH_LOW_MSK GENMASK(14, 0) #define R_IFS_T2 0x0C30 +#define R_IFS_T2_BE4 0x20C30 #define B_IFS_T2_TH_HIGH_MSK GENMASK(31, 16) #define B_IFS_T2_EN_MSK BIT(15) #define B_IFS_T2_TH_LOW_MSK GENMASK(14, 0) #define R_IFS_T3 0x0C34 +#define R_IFS_T3_BE4 0x20C34 #define B_IFS_T3_TH_HIGH_MSK GENMASK(31, 16) #define B_IFS_T3_EN_MSK BIT(15) #define B_IFS_T3_TH_LOW_MSK GENMASK(14, 0) #define R_IFS_T4 0x0C38 +#define R_IFS_T4_BE4 0x20C38 #define B_IFS_T4_TH_HIGH_MSK GENMASK(31, 16) #define B_IFS_T4_EN_MSK BIT(15) #define B_IFS_T4_TH_LOW_MSK GENMASK(14, 0) #define R_PD_CTRL 0x0C3C #define B_PD_HIT_DIS BIT(9) #define R_IOQ_IQK_DPK 0x0C60 +#define R_IOQ_IQK_DPK_BE4 0x20C60 #define B_IOQ_IQK_DPK_CLKEN GENMASK(1, 0) #define B_IOQ_IQK_DPK_EN BIT(1) +#define B_IOQ_IQK_DPK_RST BIT(0) #define R_GNT_BT_WGT_EN 0x0C6C #define B_GNT_BT_WGT_EN BIT(21) #define R_IQK_DPK_RST 0x0C6C +#define R_IQK_DPK_RST_BE4 0x20C6C #define R_IQK_DPK_RST_C1 0x1C6C #define B_IQK_DPK_RST BIT(0) #define R_TX_COLLISION_T2R_ST 0x0C70 @@ -8124,6 +8877,8 @@ #define R_BRK_ASYNC_RST_EN_1 0x0DC0 #define R_BRK_ASYNC_RST_EN_2 0x0DC4 #define R_BRK_ASYNC_RST_EN_3 0x0DC8 +#define R_NHM_BE 0x0EA4 +#define B_NHM_READY_BE_MSK BIT(16) #define R_CTLTOP 0x1008 #define B_CTLTOP_ON BIT(23) #define B_CTLTOP_VAL GENMASK(15, 12) @@ -8179,16 +8934,39 @@ #define B_SWSI_R_BUSY_V1 BIT(25) #define B_SWSI_R_DATA_DONE_V1 BIT(26) #define R_TX_COUNTER 0x1A40 +#define R_NHM_CNT0 0x1A88 +#define B_NHM_CNT0_MSK GENMASK(15, 0) +#define B_NHM_CNT1_MSK GENMASK(31, 16) +#define R_NHM_CNT2 0x1A8C +#define B_NHM_CNT2_MSK GENMASK(15, 0) +#define B_NHM_CNT3_MSK GENMASK(31, 16) +#define R_NHM_CNT4 0x1A90 +#define B_NHM_CNT4_MSK GENMASK(15, 0) +#define B_NHM_CNT5_MSK GENMASK(31, 16) +#define R_NHM_CNT6 0x1A94 +#define B_NHM_CNT6_MSK GENMASK(15, 0) +#define B_NHM_CNT7_MSK GENMASK(31, 16) +#define R_NHM_CNT8 0x1A98 +#define B_NHM_CNT8_MSK GENMASK(15, 0) +#define B_NHM_CNT9_MSK GENMASK(31, 16) +#define R_NHM_CNT10 0x1A9C +#define B_NHM_CNT10_MSK GENMASK(15, 0) +#define B_NHM_CNT11_MSK GENMASK(31, 16) +#define R_NHM_AX 0x1AA4 +#define B_NHM_READY_MSK BIT(16) #define R_IFS_CLM_TX_CNT 0x1ACC #define R_IFS_CLM_TX_CNT_V1 0x0ECC +#define R_IFS_CLM_TX_CNT_BE4 0x20ECC #define B_IFS_CLM_EDCCA_EXCLUDE_CCA_FA_MSK GENMASK(31, 16) #define B_IFS_CLM_TX_CNT_MSK GENMASK(15, 0) #define R_IFS_CLM_CCA 0x1AD0 #define R_IFS_CLM_CCA_V1 0x0ED0 +#define R_IFS_CLM_CCA_BE4 0x20ED0 #define B_IFS_CLM_OFDMCCA_EXCLUDE_FA_MSK GENMASK(31, 16) #define B_IFS_CLM_CCKCCA_EXCLUDE_FA_MSK GENMASK(15, 0) #define R_IFS_CLM_FA 0x1AD4 #define R_IFS_CLM_FA_V1 0x0ED4 +#define R_IFS_CLM_FA_BE4 0x20ED4 #define B_IFS_CLM_OFDM_FA_MSK GENMASK(31, 16) #define B_IFS_CLM_CCK_FA_MSK GENMASK(15, 0) #define R_IFS_HIS 0x1AD8 @@ -8769,6 +9547,8 @@ #define B_P0_TSSI_RFC GENMASK(28, 27) #define B_P0_TSSI_OFT_EN BIT(28) #define B_P0_TSSI_OFT GENMASK(7, 0) +#define R_P0_TSSI_SLOPE_CAL 0x581c +#define B_P0_TSSI_SLOPE_CAL_EN BIT(20) #define R_P0_TSSI_AVG 0x5820 #define B_P0_TSSI_EN BIT(31) #define B_P0_TSSI_AVG GENMASK(15, 12) @@ -8843,12 +9623,14 @@ #define B_S0_DACKQ7_K GENMASK(15, 8) #define R_S0_DACKQ8 0x5E98 #define B_S0_DACKQ8_K GENMASK(15, 8) -#define R_DCFO_WEIGHT_V1 0x6244 -#define B_DCFO_WEIGHT_MSK_V1 GENMASK(31, 28) +#define R_DCFO_WEIGHT_BE 0x6244 +#define R_DCFO_WEIGHT_BE_V1 0x24808 +#define B_DCFO_WEIGHT_MSK_BE GENMASK(31, 28) #define R_DAC_CLK 0x625C #define B_DAC_CLK GENMASK(31, 30) -#define R_DCFO_OPT_V1 0x6260 -#define B_DCFO_OPT_EN_V1 BIT(17) +#define R_DCFO_OPT_BE 0x6260 +#define R_DCFO_OPT_BE_V1 0x24824 +#define B_DCFO_OPT_EN_BE BIT(17) #define R_TXFCTR 0x627C #define B_TXFCTR_THD GENMASK(19, 10) #define R_TXSCALE 0x6284 @@ -9087,6 +9869,7 @@ #define B_COEF_SEL_MDPD BIT(8) #define B_COEF_SEL_MDPD_V1 GENMASK(9, 8) #define B_COEF_SEL_EN BIT(31) +#define R_CFIR_COEF 0x810c #define R_CFIR_SYS 0x8120 #define R_IQK_RES 0x8124 #define B_IQK_RES_K BIT(28) @@ -9262,6 +10045,7 @@ #define B_WDADC_SEL GENMASK(5, 4) #define R_ADCMOD 0xC0E8 #define B_ADCMOD_LP GENMASK(31, 16) +#define B_ADCMOD_AUTO_RST BIT(6) #define R_DCIM 0xC0EC #define B_DCIM_RC GENMASK(23, 16) #define B_DCIM_FR GENMASK(14, 13) @@ -9356,10 +10140,14 @@ #define R_GAIN_MAP1 0xE54C #define B_GAIN_MAP1_EN BIT(0) #define R_GOTX_IQKDPK_C0 0xE464 +#define R_GOTX_IQKDPK_C0_BE4 0x2E464 #define R_GOTX_IQKDPK_C1 0xE564 +#define R_GOTX_IQKDPK_C1_BE4 0x2E564 #define B_GOTX_IQKDPK GENMASK(28, 27) #define R_IQK_DPK_PRST 0xE4AC +#define R_IQK_DPK_PRST_BE4 0x2E4AC #define R_IQK_DPK_PRST_C1 0xE5AC +#define R_IQK_DPK_PRST_C1_BE4 0x2E5AC #define B_IQK_DPK_PRST BIT(27) #define R_TXPWR_RSTA 0xE60C #define B_TXPWR_RSTA BIT(16) @@ -9386,6 +10174,258 @@ #define R_TSSI_K_P1 0xE7A0 #define B_TSSI_K_OFDM_P1 GENMASK(29, 20) +#define R_COMP_CIM3K_BE4 0x11998 +#define B_COMP_CIM3K_OW_BE4 BIT(1) +#define B_COMP_CIM3K_TH_BE4 BIT(2) +#define B_COMP_CIM3K_TH2_BE4 GENMASK(5, 3) +#define B_COMP_CIM3K_TXPWR_EN_BE4 BIT(6) +#define B_COMP_CIM3K_NONBE_BE4 BIT(7) +#define B_COMP_CIM3K_BANDEDGE_BE4 BIT(8) +#define R_DPD_CBW160_BE4 0x119B4 +#define B_DPD_CBW160_TH0_BE4 BIT(0) +#define B_DPD_CBW160_TH1_BE4 BIT(1) +#define B_DPD_CBW160_TH2_BE4 BIT(2) +#define B_DPD_CBW160_TH3_BE4 BIT(3) +#define B_DPD_CBW160_TH4_BE4 BIT(4) +#define B_DPD_CBW160_TH5_BE4 BIT(5) +#define B_DPD_CBW160_TH6_BE4 BIT(6) +#define B_DPD_CBW160_TH7_BE4 BIT(7) +#define B_DPD_CBW160_OW0_BE4 BIT(8) +#define B_DPD_CBW160_OW1_BE4 BIT(9) +#define B_DPD_CBW160_OW2_BE4 BIT(10) +#define B_DPD_CBW160_OW3_BE4 BIT(11) +#define B_DPD_CBW160_OW4_BE4 BIT(12) +#define B_DPD_CBW160_OW5_BE4 BIT(13) +#define B_DPD_CBW160_OW6_BE4 BIT(14) +#define B_DPD_CBW160_OW7_BE4 BIT(15) +#define R_OOB_CBW20_BE4 0x119B4 +#define B_OOB_CBW20_CCK0_BE4 BIT(16) +#define B_OOB_CBW20_CCK1_BE4 BIT(17) +#define B_OOB_CBW20_CCK2_BE4 BIT(18) +#define B_OOB_CBW20_CCK3_BE4 BIT(19) +#define B_OOB_CBW20_CCK4_BE4 BIT(20) +#define B_OOB_CBW20_CCK5_BE4 BIT(21) +#define B_OOB_CBW20_CCK6_BE4 BIT(22) +#define B_OOB_CBW20_CCK7_BE4 BIT(23) +#define B_OOB_CBW20_TH0_BE4 BIT(24) +#define B_OOB_CBW20_TH1_BE4 BIT(25) +#define B_OOB_CBW20_TH2_BE4 BIT(26) +#define B_OOB_CBW20_TH3_BE4 BIT(27) +#define B_OOB_CBW20_TH4_BE4 BIT(28) +#define B_OOB_CBW20_TH5_BE4 BIT(29) +#define B_OOB_CBW20_TH6_BE4 BIT(30) +#define B_OOB_CBW20_TH7_BE4 BIT(31) +#define R_OOB_CBW40_BE4 0x119B8 +#define B_OOB_CBW20_OW0_BE4 BIT(0) +#define B_OOB_CBW20_OW1_BE4 BIT(1) +#define B_OOB_CBW20_OW2_BE4 BIT(2) +#define B_OOB_CBW20_OW3_BE4 BIT(3) +#define B_OOB_CBW20_OW4_BE4 BIT(4) +#define B_OOB_CBW20_OW5_BE4 BIT(5) +#define B_OOB_CBW20_OW6_BE4 BIT(6) +#define B_OOB_CBW20_OW7_BE4 BIT(7) +#define B_OOB_CBW40_CCK0_BE4 BIT(8) +#define B_OOB_CBW40_CCK1_BE4 BIT(9) +#define B_OOB_CBW40_CCK2_BE4 BIT(10) +#define B_OOB_CBW40_CCK3_BE4 BIT(11) +#define B_OOB_CBW40_CCK4_BE4 BIT(12) +#define B_OOB_CBW40_CCK5_BE4 BIT(13) +#define B_OOB_CBW40_CCK6_BE4 BIT(14) +#define B_OOB_CBW40_CCK7_BE4 BIT(15) +#define B_OOB_CBW40_TH0_BE4 BIT(16) +#define B_OOB_CBW40_TH1_BE4 BIT(17) +#define B_OOB_CBW40_TH2_BE4 BIT(18) +#define B_OOB_CBW40_TH3_BE4 BIT(19) +#define B_OOB_CBW40_TH4_BE4 BIT(20) +#define B_OOB_CBW40_TH5_BE4 BIT(21) +#define B_OOB_CBW40_TH6_BE4 BIT(22) +#define B_OOB_CBW40_TH7_BE4 BIT(23) +#define B_OOB_CBW40_OW0_BE4 BIT(24) +#define B_OOB_CBW40_OW1_BE4 BIT(25) +#define B_OOB_CBW40_OW2_BE4 BIT(26) +#define B_OOB_CBW40_OW3_BE4 BIT(27) +#define B_OOB_CBW40_OW4_BE4 BIT(28) +#define B_OOB_CBW40_OW5_BE4 BIT(29) +#define B_OOB_CBW40_OW6_BE4 BIT(30) +#define B_OOB_CBW40_OW7_BE4 BIT(31) +#define R_OOB_CBW80_BE4 0x119BC +#define B_OOB_CBW80_TH0_BE4 BIT(0) +#define B_OOB_CBW80_TH1_BE4 BIT(1) +#define B_OOB_CBW80_TH2_BE4 BIT(2) +#define B_OOB_CBW80_TH3_BE4 BIT(3) +#define B_OOB_CBW80_TH4_BE4 BIT(4) +#define B_OOB_CBW80_TH5_BE4 BIT(5) +#define B_OOB_CBW80_TH6_BE4 BIT(6) +#define B_OOB_CBW80_TH7_BE4 BIT(7) +#define B_OOB_CBW80_OW0_BE4 BIT(8) +#define B_OOB_CBW80_OW1_BE4 BIT(9) +#define B_OOB_CBW80_OW2_BE4 BIT(10) +#define B_OOB_CBW80_OW3_BE4 BIT(11) +#define B_OOB_CBW80_OW4_BE4 BIT(12) +#define B_OOB_CBW80_OW5_BE4 BIT(13) +#define B_OOB_CBW80_OW6_BE4 BIT(14) +#define B_OOB_CBW80_OW7_BE4 BIT(15) +#define R_DPD_DBW160_TH0_BE4 0x119BC +#define B_DPD_DBW160_TH0_0_BE4 GENMASK(18, 16) +#define B_DPD_DBW160_TH0_1_BE4 GENMASK(21, 19) +#define B_DPD_DBW160_TH0_2_BE4 GENMASK(24, 22) +#define B_DPD_DBW160_TH0_3_BE4 GENMASK(27, 25) +#define B_DPD_DBW160_TH0_4_BE4 GENMASK(30, 28) +#define R_DPD_DBW160_TH1_BE4 0x119C0 +#define B_DPD_DBW160_TH1_5_BE4 GENMASK(2, 0) +#define B_DPD_DBW160_TH1_6_BE4 GENMASK(5, 3) +#define B_DPD_DBW160_TH1_7_BE4 GENMASK(8, 6) +#define R_DPD_CBW_TH0_BE4 0x119C0 +#define B_DPD_CBW20_TH0_0_BE4 GENMASK(11, 9) +#define B_DPD_CBW20_TH0_1_BE4 GENMASK(14, 12) +#define B_DPD_CBW20_TH0_2_BE4 GENMASK(17, 15) +#define B_DPD_CBW20_TH0_3_BE4 GENMASK(20, 18) +#define B_DPD_CBW20_TH0_4_BE4 GENMASK(23, 21) +#define B_DPD_CBW20_TH0_5_BE4 GENMASK(26, 24) +#define B_DPD_CBW20_TH0_6_BE4 GENMASK(29, 27) +#define R_DPD_CBW_TH1_BE4 0x119C4 +#define B_DPD_CBW20_TH1_7_BE4 GENMASK(2, 0) +#define B_DPD_CBW40_TH1_0_BE4 GENMASK(5, 3) +#define B_DPD_CBW40_TH1_1_BE4 GENMASK(8, 6) +#define B_DPD_CBW40_TH1_2_BE4 GENMASK(11, 9) +#define B_DPD_CBW40_TH1_3_BE4 GENMASK(14, 12) +#define B_DPD_CBW40_TH1_4_BE4 GENMASK(17, 15) +#define B_DPD_CBW40_TH1_5_BE4 GENMASK(20, 18) +#define B_DPD_CBW40_TH1_6_BE4 GENMASK(23, 21) +#define B_DPD_CBW40_TH1_7_BE4 GENMASK(26, 24) +#define B_DPD_CBW80_TH1_0_BE4 GENMASK(29, 27) +#define R_DPD_CBW_TH2_BE4 0x119C8 +#define B_DPD_CBW80_TH2_1_BE4 GENMASK(2, 0) +#define B_DPD_CBW80_TH2_2_BE4 GENMASK(5, 3) +#define B_DPD_CBW80_TH2_3_BE4 GENMASK(8, 6) +#define B_DPD_CBW80_TH2_4_BE4 GENMASK(11, 9) +#define B_DPD_CBW80_TH2_5_BE4 GENMASK(14, 12) +#define B_DPD_CBW80_TH2_6_BE4 GENMASK(17, 15) +#define B_DPD_CBW80_TH2_7_BE4 GENMASK(20, 18) +#define R_QAM_TH0_BE4 0x119E4 +#define B_QAM_TH0_0_BE4 GENMASK(18, 16) +#define B_QAM_TH0_1_BE4 GENMASK(21, 19) +#define B_QAM_TH0_2_BE4 GENMASK(24, 22) +#define B_QAM_TH0_3_BE4 GENMASK(27, 25) +#define B_QAM_TH0_4_BE4 GENMASK(30, 28) +#define R_QAM_TH1_BE4 0x119E8 +#define B_QAM_TH1_0_BE4 GENMASK(2, 0) +#define B_QAM_TH1_1_BE4 GENMASK(5, 3) +#define B_QAM_TH1_2_BE4 GENMASK(8, 6) +#define B_QAM_TH1_3_BE4 GENMASK(11, 9) +#define B_QAM_TH1_4_BE4 GENMASK(14, 12) +#define B_QAM_TH1_5_BE4 GENMASK(17, 15) +#define B_QAM_TH1_6_BE4 GENMASK(20, 18) +#define B_QAM_TH1_7_BE4 GENMASK(23, 21) +#define B_QAM_TH1_8_BE4 GENMASK(26, 24) +#define B_QAM_TH1_9_BE4 GENMASK(29, 27) +#define R_QAM_TH2_BE4 0x119EC +#define B_QAM_TH2_0_BE4 GENMASK(2, 0) +#define B_QAM_TH2_1_BE4 GENMASK(5, 3) +#define B_QAM_TH2_2_BE4 GENMASK(8, 6) +#define B_QAM_TH2_3_BE4 GENMASK(11, 9) +#define B_QAM_TH2_4_BE4 GENMASK(14, 12) +#define B_QAM_TH2_5_BE4 GENMASK(17, 15) +#define B_QAM_TH2_6_BE4 GENMASK(20, 18) +#define B_QAM_TH2_7_BE4 GENMASK(23, 21) +#define B_QAM_TH2_8_BE4 GENMASK(26, 24) +#define R_RFSI_CT_DEF_BE4 0x119F0 +#define B_RFSI_CT_ER_BE4 GENMASK(18, 15) +#define B_RFSI_CT_SUBF_BE4 GENMASK(22, 19) +#define B_RFSI_CT_FTM_BE4 GENMASK(26, 23) +#define B_RFSI_CT_SENS_BE4 GENMASK(30, 27) +#define R_FBTB_CT_DEF_BE4 0x119F4 +#define B_FBTB_CT_DEF_BE GENMASK(3, 0) +#define B_FBTB_CT_PB_BE4 GENMASK(7, 4) +#define B_FBTB_CT_DL_WO_BE4 GENMASK(11, 8) +#define B_FBTB_CT_DL_BF_BE4 GENMASK(15, 12) +#define B_FBTB_CT_MUMIMO_BE4 GENMASK(19, 16) +#define B_FBTB_CT_FTM_BE4 GENMASK(23, 20) +#define B_FBTB_CT_SENS_BE4 GENMASK(27, 24) +#define R_RFSI_CT_OPT_0_BE4 0x11A94 +#define R_RFSI_CT_OPT_8_BE4 0x11A98 +#define R_QAM_COMP_TH0_BE4 0x11A9C +#define R_QAM_COMP_TH1_BE4 0x11AA0 +#define R_QAM_COMP_TH2_BE4 0x11AA4 +#define R_QAM_COMP_TH3_BE4 0x11AA8 +#define R_QAM_COMP_TH4_BE4 0x11ABC +#define B_QAM_COMP_TH4_L GENMASK(4, 0) +#define B_QAM_COMP_TH4_M GENMASK(14, 10) +#define B_QAM_COMP_TH4_H GENMASK(24, 20) +#define B_QAM_COMP_TH4_2L GENMASK(9, 5) +#define B_QAM_COMP_TH4_2M GENMASK(19, 15) +#define B_QAM_COMP_TH4_2H GENMASK(29, 25) +#define R_QAM_COMP_TH5_BE4 0x11AC0 +#define B_QAM_COMP_TH5_L GENMASK(4, 0) +#define B_QAM_COMP_TH5_M GENMASK(14, 10) +#define B_QAM_COMP_TH5_H GENMASK(24, 20) +#define B_QAM_COMP_TH5_2L GENMASK(9, 5) +#define B_QAM_COMP_TH5_2M GENMASK(19, 15) +#define B_QAM_COMP_TH5_2H GENMASK(29, 25) +#define R_QAM_COMP_TH6_BE4 0x11AC4 +#define B_QAM_COMP_TH6_L GENMASK(4, 0) +#define B_QAM_COMP_TH6_M GENMASK(14, 10) +#define B_QAM_COMP_TH6_2L GENMASK(9, 5) +#define B_QAM_COMP_TH6_2M GENMASK(19, 15) +#define R_OW_VAL_0_BE4 0x11AAC +#define R_OW_VAL_1_BE4 0x11AB0 +#define R_OW_VAL_2_BE4 0x11AB4 +#define R_OW_VAL_3_BE4 0x11AB8 +#define R_BANDEDGE_DBWX_BE4 0x11ACC +#define B_BANDEDGE_DBW20_BE4 BIT(29) +#define B_BANDEDGE_DBW40_BE4 BIT(30) +#define B_BANDEDGE_DBW80_BE4 BIT(31) +#define R_BANDEDGE_DBWY_BE4 0x11AD0 +#define B_BANDEDGE_DBW160_BE4 BIT(0) + +#define R_CHINFO_SEG_BE4 0x200B4 +#define B_CHINFO_SEG_LEN_BE4 GENMASK(12, 10) +#define R_STS_HDR2_PARSING_BE4 0x2070C +#define B_STS_HDR2_PARSING_BE4 BIT(10) +#define R_SW_SI_WDATA_BE4 0x20370 +#define B_SW_SI_DATA_PATH_BE4 GENMASK(31, 28) +#define B_SW_SI_DATA_ADR_BE4 GENMASK(27, 20) +#define B_SW_SI_DATA_DAT_BE4 GENMASK(19, 0) +#define R_SW_SI_READ_ADDR_BE4 0x20378 +#define B_SW_SI_READ_ADDR_BE4 GENMASK(10, 0) +#define R_IFS_T1_AVG_BE4 0x20EDC +#define B_IFS_T1_AVG_BE4 GENMASK(15, 0) +#define B_IFS_T2_AVG_BE4 GENMASK(31, 16) +#define R_IFS_T3_AVG_BE4 0x20EE0 +#define B_IFS_T3_AVG_BE4 GENMASK(15, 0) +#define B_IFS_T4_AVG_BE4 GENMASK(31, 16) +#define R_IFS_T1_CLM_BE4 0x20EE4 +#define B_IFS_T1_CLM_BE4 GENMASK(15, 0) +#define B_IFS_T2_CLM_BE4 GENMASK(31, 16) +#define R_IFS_T3_CLM_BE4 0x20EE8 +#define B_IFS_T3_CLM_BE4 GENMASK(15, 0) +#define B_IFS_T4_CLM_BE4 GENMASK(31, 16) +#define R_IFS_TOTAL_BE4 0x20EEC +#define B_IFS_TOTAL_BE4 GENMASK(15, 0) +#define B_IFS_CNT_DONE_BE4 BIT(16) +#define R_IFS_T1_HIS_BE4 0x20F50 +#define B_IFS_T1_HIS_BE4 GENMASK(15, 0) +#define B_IFS_T2_HIS_BE4 GENMASK(31, 16) +#define R_IFS_T3_HIS_BE4 0x20F54 +#define B_IFS_T3_HIS_BE4 GENMASK(15, 0) +#define B_IFS_T4_HIS_BE4 GENMASK(31, 16) + +#define R_TX_CFR_MANUAL_EN_BE4 0x2483C +#define B_TX_CFR_MANUAL_EN_BE4_M BIT(30) + +#define R_CHINFO_OPT_BE4 0x267C8 +#define B_CHINFO_OPT_BE4 GENMASK(14, 13) +#define R_CHINFO_NX_BE4 0x267D0 +#define B_CHINFO_NX_BE4 GENMASK(16, 6) +#define R_CHINFO_ALG_BE4 0x267C8 +#define B_CHINFO_ALG_BE4 GENMASK(31, 30) + +#define R_SW_SI_DATA_BE4 0x2CF4C +#define B_SW_SI_READ_DATA_BE4 GENMASK(19, 0) +#define B_SW_SI_W_BUSY_BE4 BIT(24) +#define B_SW_SI_R_BUSY_BE4 BIT(25) +#define B_SW_SI_READ_DATA_DONE_BE4 BIT(26) + /* WiFi CPU local domain */ #define R_AX_WDT_CTRL 0x0040 #define B_AX_WDT_EN BIT(31) diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index b8f822183496a..b915d9074d024 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -38,7 +38,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0), COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0), COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0), - COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0), + COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x1), COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0), @@ -95,7 +95,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), - COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR, 0x0), @@ -111,12 +111,12 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), - COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN, 0x0), COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), - COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC, 0x1), COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), @@ -125,7 +125,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI, 0x0), COUNTRY_REGD("TH", RTW89_THAILAND, RTW89_THAILAND, RTW89_THAILAND, 0x0), - COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0), COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA, 0x0), COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), @@ -134,7 +134,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0), - COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0), @@ -187,9 +187,9 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), - COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), - COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), @@ -214,7 +214,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), - COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0), COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), @@ -260,7 +260,7 @@ static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), - COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), + COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI, 0x0), COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("CU", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA, 0x0), @@ -360,15 +360,13 @@ static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev, struct wiphy *wiphy) { struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; - const struct rtw89_regd_ctrl *regd_ctrl = ®ulatory->ctrl; const struct rtw89_chip_info *chip = rtwdev->chip; struct ieee80211_supported_band *sband; struct rtw89_acpi_dsm_result res = {}; - bool enable_by_fcc; - bool enable_by_ic; + bool enable; + u8 index; int ret; u8 val; - int i; sband = wiphy->bands[NL80211_BAND_5GHZ]; if (!sband) @@ -385,35 +383,25 @@ static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev, if (ret) { rtw89_debug(rtwdev, RTW89_DBG_REGD, "acpi: cannot eval unii 4: %d\n", ret); - enable_by_fcc = true; - enable_by_ic = false; + val = u8_encode_bits(1, RTW89_ACPI_CONF_UNII4_US); goto bottom; } val = res.u.value; - enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC); - enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC); rtw89_debug(rtwdev, RTW89_DBG_REGD, "acpi: eval if allow unii-4: 0x%x\n", val); bottom: - for (i = 0; i < regd_ctrl->nr; i++) { - const struct rtw89_regd *regd = ®d_ctrl->map[i]; - - switch (regd->txpwr_regd[RTW89_BAND_5G]) { - case RTW89_FCC: - if (enable_by_fcc) - clear_bit(i, regulatory->block_unii4); - break; - case RTW89_IC: - if (enable_by_ic) - clear_bit(i, regulatory->block_unii4); - break; - default: - break; - } - } + index = rtw89_regd_get_index_by_name(rtwdev, "US"); + enable = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_US); + if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM) + clear_bit(index, regulatory->block_unii4); + + index = rtw89_regd_get_index_by_name(rtwdev, "CA"); + enable = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_CA); + if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM) + clear_bit(index, regulatory->block_unii4); } static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block, @@ -490,12 +478,11 @@ static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev) static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev) { struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; - const struct rtw89_regd_ctrl *regd_ctrl = ®ulatory->ctrl; const struct rtw89_acpi_policy_6ghz_sp *ptr; struct rtw89_acpi_dsm_result res = {}; - bool enable_by_us; + bool enable; + u8 index; int ret; - int i; ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res); if (ret) { @@ -520,16 +507,66 @@ static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev) bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM); - enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US); + index = rtw89_regd_get_index_by_name(rtwdev, "US"); + enable = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US); + if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM) + clear_bit(index, regulatory->block_6ghz_sp); - for (i = 0; i < regd_ctrl->nr; i++) { - const struct rtw89_regd *tmp = ®d_ctrl->map[i]; + index = rtw89_regd_get_index_by_name(rtwdev, "CA"); + enable = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_CA); + if (enable && index != RTW89_REGD_MAX_COUNTRY_NUM) + clear_bit(index, regulatory->block_6ghz_sp); + +out: + kfree(ptr); +} + +static void rtw89_regd_setup_policy_6ghz_vlp(struct rtw89_dev *rtwdev) +{ + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + const struct rtw89_acpi_policy_6ghz_vlp *ptr = NULL; + struct rtw89_acpi_dsm_result res = {}; + bool enable; + u8 index; + int ret; + u8 val; + + /* By default, allow 6 GHz VLP on all countries except US and CA. */ + val = ~(RTW89_ACPI_CONF_6GHZ_VLP_US | RTW89_ACPI_CONF_6GHZ_VLP_CA); - if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0) - clear_bit(i, regulatory->block_6ghz_sp); + ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP, &res); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: cannot eval policy 6ghz-vlp: %d\n", ret); + goto bottom; } -out: + ptr = res.u.policy_6ghz_vlp; + + switch (ptr->override) { + default: + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "%s: unknown override case: %d\n", __func__, + ptr->override); + fallthrough; + case 0: + break; + case 1: + val = ptr->conf; + break; + } + +bottom: + index = rtw89_regd_get_index_by_name(rtwdev, "US"); + enable = u8_get_bits(val, RTW89_ACPI_CONF_6GHZ_VLP_US); + if (!enable && index != RTW89_REGD_MAX_COUNTRY_NUM) + set_bit(index, regulatory->block_6ghz_vlp); + + index = rtw89_regd_get_index_by_name(rtwdev, "CA"); + enable = u8_get_bits(val, RTW89_ACPI_CONF_6GHZ_VLP_CA); + if (!enable && index != RTW89_REGD_MAX_COUNTRY_NUM) + set_bit(index, regulatory->block_6ghz_vlp); + kfree(ptr); } @@ -576,6 +613,7 @@ static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy) if (regd_allow_6ghz) { rtw89_regd_setup_policy_6ghz(rtwdev); rtw89_regd_setup_policy_6ghz_sp(rtwdev); + rtw89_regd_setup_policy_6ghz_vlp(rtwdev); return; } @@ -620,6 +658,30 @@ const char *rtw89_regd_get_string(enum rtw89_regulation_type regd) return rtw89_regd_string[regd]; } +static void rtw89_regd_setup_reg_rules(struct rtw89_dev *rtwdev) +{ + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + const struct rtw89_acpi_policy_reg_rules *ptr; + struct rtw89_acpi_dsm_result res = {}; + int ret; + + regulatory->txpwr_uk_follow_etsi = true; + + ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_REG_RULES_EN, &res); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: cannot eval policy reg-rules: %d\n", ret); + return; + } + + ptr = res.u.policy_reg_rules; + + regulatory->txpwr_uk_follow_etsi = + !u8_get_bits(ptr->conf, RTW89_ACPI_CONF_REG_RULE_REGD_UK); + + kfree(ptr); +} + int rtw89_regd_setup(struct rtw89_dev *rtwdev) { struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; @@ -636,7 +698,8 @@ int rtw89_regd_setup(struct rtw89_dev *rtwdev) } regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; - regulatory->txpwr_uk_follow_etsi = true; + + rtw89_regd_setup_reg_rules(rtwdev); if (!wiphy) return -EINVAL; @@ -660,6 +723,8 @@ int rtw89_regd_init_hint(struct rtw89_dev *rtwdev) chip_regd = rtw89_regd_find_reg_by_name(rtwdev, rtwdev->efuse.country_code); if (!rtw89_regd_is_ww(chip_regd)) { rtwdev->regulatory.regd = chip_regd; + rtwdev->regulatory.programmed = true; + /* Ignore country ie if there is a country domain programmed in chip */ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; wiphy->regulatory_flags |= REGULATORY_STRICT_REG; @@ -804,11 +869,6 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev, wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; else wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; - - rtw89_regd_apply_policy_unii4(rtwdev, wiphy); - rtw89_regd_apply_policy_6ghz(rtwdev, wiphy); - rtw89_regd_apply_policy_tas(rtwdev); - rtw89_regd_apply_policy_ant_gain(rtwdev); } static @@ -820,19 +880,22 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request wiphy_lock(wiphy); rtw89_leave_ps_mode(rtwdev); - if (wiphy->regd) { - rtw89_debug(rtwdev, RTW89_DBG_REGD, - "There is a country domain programmed in chip, ignore notifications\n"); - goto exit; - } + if (rtwdev->regulatory.programmed) + goto policy; + rtw89_regd_notifier_apply(rtwdev, wiphy, request); rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, "get from initiator %d, alpha2", request->initiator); +policy: + rtw89_regd_apply_policy_unii4(rtwdev, wiphy); + rtw89_regd_apply_policy_6ghz(rtwdev, wiphy); + rtw89_regd_apply_policy_tas(rtwdev); + rtw89_regd_apply_policy_ant_gain(rtwdev); + rtw89_core_set_chip_txpwr(rtwdev); -exit: wiphy_unlock(wiphy); } @@ -901,7 +964,16 @@ static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link, bool active, unsigned int *changed) { + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + const struct rtw89_regd *regd = regulatory->regd; + bool blocked[NUM_OF_RTW89_REG_6GHZ_POWER] = {}; + u8 index = rtw89_regd_get_index(rtwdev, regd); struct ieee80211_bss_conf *bss_conf; + bool dflt = false; + + if (index == RTW89_REGD_MAX_COUNTRY_NUM || + test_bit(index, regulatory->block_6ghz_vlp)) + blocked[RTW89_REG_6GHZ_POWER_VLP] = true; rcu_read_lock(); @@ -920,14 +992,24 @@ static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, break; default: rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + dflt = true; break; } } else { rtwvif_link->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + dflt = true; } rcu_read_unlock(); + if (!dflt && blocked[rtwvif_link->reg_6ghz_power]) { + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "%c%c 6 GHz power type-%u is blocked by policy\n", + regd->alpha2[0], regd->alpha2[1], + rtwvif_link->reg_6ghz_power); + return -EINVAL; + } + *changed += __rtw89_reg_6ghz_power_recalc(rtwdev); return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 23a8d758f5c4b..4c9184ca0a315 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -51,6 +51,48 @@ static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_pcie[] = { [RTW89_QTA_INVALID] = {NULL}, }; +static const struct rtw89_hfc_ch_cfg rtw8851b_hfc_chcfg_usb[] = { + {18, 152, grp_0}, /* ACH 0 */ + {18, 152, grp_0}, /* ACH 1 */ + {18, 152, grp_0}, /* ACH 2 */ + {18, 152, grp_0}, /* ACH 3 */ + {0, 0, grp_0}, /* ACH 4 */ + {0, 0, grp_0}, /* ACH 5 */ + {0, 0, grp_0}, /* ACH 6 */ + {0, 0, grp_0}, /* ACH 7 */ + {18, 152, grp_0}, /* B0MGQ */ + {18, 152, grp_0}, /* B0HIQ */ + {0, 0, grp_0}, /* B1MGQ */ + {0, 0, grp_0}, /* B1HIQ */ + {0, 0, 0} /* FWCMDQ */ +}; + +static const struct rtw89_hfc_pub_cfg rtw8851b_hfc_pubcfg_usb = { + 152, /* Group 0 */ + 0, /* Group 1 */ + 152, /* Public Max */ + 0 /* WP threshold */ +}; + +static const struct rtw89_hfc_prec_cfg rtw8851b_hfc_preccfg_usb = { + 9, /* CH 0-11 pre-cost */ + 32, /* H2C pre-cost */ + 64, /* WP CH 0-7 pre-cost */ + 24, /* WP CH 8-11 pre-cost */ + 1, /* CH 0-11 full condition */ + 1, /* H2C full condition */ + 1, /* WP CH 0-7 full condition */ + 1, /* WP CH 8-11 full condition */ +}; + +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = { + [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb, + &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_DLFW] = {NULL, NULL, + &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_INVALID] = {NULL}, +}; + static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = { [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6, &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6, @@ -68,6 +110,32 @@ static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = { NULL}, }; +static const struct rtw89_dle_mem rtw8851b_dle_mem_usb2[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size25, + &rtw89_mac_size.ple_size32, &rtw89_mac_size.wde_qt25, + &rtw89_mac_size.wde_qt25, &rtw89_mac_size.ple_qt72, + &rtw89_mac_size.ple_qt73}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9, + &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4, + &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, + &rtw89_mac_size.ple_qt13}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + +static const struct rtw89_dle_mem rtw8851b_dle_mem_usb3[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size25, + &rtw89_mac_size.ple_size33, &rtw89_mac_size.wde_qt25, + &rtw89_mac_size.wde_qt25, &rtw89_mac_size.ple_qt74, + &rtw89_mac_size.ple_qt75}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9, + &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4, + &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, + &rtw89_mac_size.ple_qt13}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + static const struct rtw89_reg3_def rtw8851b_btc_preagc_en_defs[] = { {0x46D0, GENMASK(1, 0), 0x3}, {0x4AD4, GENMASK(31, 0), 0xf}, @@ -185,6 +253,15 @@ static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = { .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8851b_rfkill_regs = { + .pinmux = {R_AX_GPIO8_15_FUNC_SEL, + B_AX_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_AX_GPIO_EXT_CTRL + 2, + (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8851b_dig_regs = { .seg0_pd_reg = R_SEG0R_PD_V1, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, @@ -308,7 +385,8 @@ static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); - rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_WEI, XTAL_SI_OFF_WEI); @@ -353,8 +431,9 @@ static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); - rtw89_write32_set(rtwdev, R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN, - B_AX_GPIO10_PULL_LOW_EN | B_AX_GPIO16_PULL_LOW_EN_V1); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_set(rtwdev, R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN, + B_AX_GPIO10_PULL_LOW_EN | B_AX_GPIO16_PULL_LOW_EN_V1); if (rtwdev->hal.cv == CHIP_CAV) { ret = rtw89_read_efuse_ver(rtwdev, &val8); @@ -438,7 +517,10 @@ static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev) if (ret) return ret; - rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_EDSWR); if (rtwdev->hal.cv == CHIP_CAV) { rtw8851b_patch_swr_pfm2pwm(rtwdev); @@ -447,19 +529,18 @@ static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev) rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY); } - rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) { + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + } else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) { + val32 = rtw89_read32(rtwdev, R_AX_SYS_PW_CTRL); + val32 &= ~B_AX_AFSM_PCIE_SUS_EN; + val32 |= B_AX_AFSM_WLSUS_EN; + rtw89_write32(rtwdev, R_AX_SYS_PW_CTRL, val32); + } return 0; } -static void rtw8851b_efuse_parsing(struct rtw89_efuse *efuse, - struct rtw8851b_efuse *map) -{ - ether_addr_copy(efuse->addr, map->e.mac_addr); - efuse->rfe_type = map->rfe_type; - efuse->xtal_cap = map->xtal_k; -} - static void rtw8851b_efuse_parsing_tssi(struct rtw89_dev *rtwdev, struct rtw8851b_efuse *map) { @@ -540,13 +621,17 @@ static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, switch (rtwdev->hci.type) { case RTW89_HCI_TYPE_PCIE: - rtw8851b_efuse_parsing(efuse, map); + ether_addr_copy(efuse->addr, map->e.mac_addr); + break; + case RTW89_HCI_TYPE_USB: + ether_addr_copy(efuse->addr, map->u.mac_addr); break; default: return -EOPNOTSUPP; } - rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; return 0; } @@ -703,12 +788,22 @@ static void rtw8851b_phycap_parsing_gain_comp(struct rtw89_dev *rtwdev, u8 *phyc gain->comp_valid = valid; } +static void rtw8851b_phycap_parsing_adc_td(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + u32 phycap_addr = rtwdev->chip->phycap_addr; + struct rtw89_efuse *efuse = &rtwdev->efuse; + const u32 addr_adc_td = 0x5AF; + + efuse->adc_td = phycap_map[addr_adc_td - phycap_addr] & GENMASK(4, 0); +} + static int rtw8851b_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map) { rtw8851b_phycap_parsing_tssi(rtwdev, phycap_map); rtw8851b_phycap_parsing_thermal_trim(rtwdev, phycap_map); rtw8851b_phycap_parsing_pa_bias_trim(rtwdev, phycap_map); rtw8851b_phycap_parsing_gain_comp(rtwdev, phycap_map); + rtw8851b_phycap_parsing_adc_td(rtwdev, phycap_map); return 0; } @@ -1074,39 +1169,72 @@ static void rtw8851b_ctrl_ch(struct rtw89_dev *rtwdev, static void rtw8851b_bw_setting(struct rtw89_dev *rtwdev, u8 bw) { - rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); - rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); - rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); - rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1, B_P0_CFCH_BW1, 0x4); + struct rtw89_efuse *efuse = &rtwdev->efuse; + u8 adc_bw_sel; + + switch (efuse->adc_td) { + default: + case 0x19: + adc_bw_sel = 0x4; + break; + case 0x11: + adc_bw_sel = 0x5; + break; + case 0x9: + adc_bw_sel = 0x3; + break; + } + + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1, B_P0_CFCH_BW1, adc_bw_sel); rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_MUL, 0xf); rtw89_phy_write32_mask(rtwdev, R_ADCMOD, B_ADCMOD_LP, 0xa); - rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_RC, 0x3); switch (bw) { case RTW89_CHANNEL_WIDTH_5: + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1); rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x0); rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); break; case RTW89_CHANNEL_WIDTH_10: + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1); rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x1); rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); break; case RTW89_CHANNEL_WIDTH_20: + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2); rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); break; case RTW89_CHANNEL_WIDTH_40: + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2); rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); break; case RTW89_CHANNEL_WIDTH_80: + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x0); rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); break; default: rtw89_warn(rtwdev, "Fail to set ADC\n"); @@ -2402,11 +2530,13 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = { .cfg_txrx_path = rtw8851b_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset, .digital_pwr_comp = NULL, + .calc_rx_gain_normal = NULL, .pwr_on_func = rtw8851b_pwr_on_func, .pwr_off_func = rtw8851b_pwr_off_func, .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, + .get_ch_dma = rtw89_core_get_ch_dma, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -2416,9 +2546,11 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = { .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl, .h2c_ampdu_cmac_tbl = NULL, .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl, + .h2c_punctured_cmac_tbl = NULL, .h2c_default_dmac_tbl = NULL, .h2c_update_beacon = rtw89_fw_h2c_update_beacon, .h2c_ba_cam = rtw89_fw_h2c_ba_cam, + .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update, .btc_set_rfe = rtw8851b_btc_set_rfe, .btc_init_cfg = rtw8851b_btc_init_cfg, @@ -2456,10 +2588,19 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .small_fifo_size = true, .dle_scc_rsvd_size = 98304, .max_amsdu_limit = 3500, + .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + .max_eht_mpdu_cap = 0, + .max_tx_agg_num = 128, + .max_rx_agg_num = 64, .dis_2g_40m_ul_ofdma = true, .rsvd_ple_ofst = 0x2f800, - .hfc_param_ini = rtw8851b_hfc_param_ini_pcie, - .dle_mem = rtw8851b_dle_mem_pcie, + .hfc_param_ini = {rtw8851b_hfc_param_ini_pcie, + rtw8851b_hfc_param_ini_usb, + NULL}, + .dle_mem = {rtw8851b_dle_mem_pcie, + rtw8851b_dle_mem_usb2, + rtw8851b_dle_mem_usb3, + NULL}, .wde_qempty_acq_grpnum = 4, .wde_qempty_mgq_grpsel = 4, .rf_base_addr = {0xe000}, @@ -2492,6 +2633,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .support_ant_gain = false, .support_tas = false, .support_sar_by_ant = false, + .support_noise = false, .ul_tb_waveform_ctrl = true, .ul_tb_pwr_diff = false, .rx_freq_frome_ie = true, @@ -2508,6 +2650,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, @@ -2553,14 +2696,17 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .cfo_hw_comp = true, .dcfo_comp = &rtw8851b_dcfo_comp, .dcfo_comp_sft = 12, + .nhm_report = NULL, + .nhm_th = NULL, .imr_info = &rtw8851b_imr_info, .imr_dmac_table = NULL, .imr_cmac_table = NULL, .rrsr_cfgs = &rtw8851b_rrsr_cfgs, .bss_clr_vld = {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0}, .bss_clr_map_reg = R_BSS_CLR_MAP_V1, - .rfkill_init = {}, - .rfkill_get = {}, + .rfkill_init = &rtw8851b_rfkill_regs, + .rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9}, + .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}}, .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) | BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) | BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI), @@ -2569,6 +2715,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .wowlan_stub = &rtw_wowlan_stub_8851b, #endif .xtal_info = &rtw8851b_xtal_info, + .default_quirks = 0, }; EXPORT_SYMBOL(rtw8851b_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c index f72b3ac6f1492..e574a9950a3b5 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c @@ -12,14 +12,15 @@ #include "rtw8851b_rfk_table.h" #include "rtw8851b_table.h" -#define DPK_VER_8851B 0x5 -#define DPK_KIP_REG_NUM_8851B 7 +#define DPK_VER_8851B 0x11 +#define DPK_KIP_REG_NUM_8851B 8 #define DPK_RF_REG_NUM_8851B 4 #define DPK_KSET_NUM 4 #define RTW8851B_RXK_GROUP_NR 4 -#define RTW8851B_RXK_GROUP_IDX_NR 2 -#define RTW8851B_TXK_GROUP_NR 1 -#define RTW8851B_IQK_VER 0x2a +#define RTW8851B_RXK_GROUP_IDX_NR 4 +#define RTW8851B_A_TXK_GROUP_NR 2 +#define RTW8851B_G_TXK_GROUP_NR 1 +#define RTW8851B_IQK_VER 0x14 #define RTW8851B_IQK_SS 1 #define RTW8851B_LOK_GRAM 10 #define RTW8851B_TSSI_PATH_NR 1 @@ -85,6 +86,24 @@ enum rf_mode { RF_RXK2 = 0x7, }; +enum adc_ck { + ADC_NA = 0, + ADC_480M = 1, + ADC_960M = 2, + ADC_1920M = 3, +}; + +enum dac_ck { + DAC_40M = 0, + DAC_80M = 1, + DAC_120M = 2, + DAC_160M = 3, + DAC_240M = 4, + DAC_320M = 5, + DAC_480M = 6, + DAC_960M = 7, +}; + static const u32 _tssi_de_cck_long[RF_PATH_NUM_8851B] = {0x5858}; static const u32 _tssi_de_cck_short[RF_PATH_NUM_8851B] = {0x5860}; static const u32 _tssi_de_mcs_20m[RF_PATH_NUM_8851B] = {0x5838}; @@ -96,19 +115,21 @@ static const u32 _tssi_de_mcs_10m[RF_PATH_NUM_8851B] = {0x5830}; static const u32 g_idxrxgain[RTW8851B_RXK_GROUP_NR] = {0x10e, 0x116, 0x28e, 0x296}; static const u32 g_idxattc2[RTW8851B_RXK_GROUP_NR] = {0x0, 0xf, 0x0, 0xf}; static const u32 g_idxrxagc[RTW8851B_RXK_GROUP_NR] = {0x0, 0x1, 0x2, 0x3}; -static const u32 a_idxrxgain[RTW8851B_RXK_GROUP_IDX_NR] = {0x10C, 0x28c}; -static const u32 a_idxattc2[RTW8851B_RXK_GROUP_IDX_NR] = {0xf, 0xf}; -static const u32 a_idxrxagc[RTW8851B_RXK_GROUP_IDX_NR] = {0x4, 0x6}; -static const u32 a_power_range[RTW8851B_TXK_GROUP_NR] = {0x0}; -static const u32 a_track_range[RTW8851B_TXK_GROUP_NR] = {0x6}; -static const u32 a_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x0a}; -static const u32 a_itqt[RTW8851B_TXK_GROUP_NR] = {0x12}; -static const u32 g_power_range[RTW8851B_TXK_GROUP_NR] = {0x0}; -static const u32 g_track_range[RTW8851B_TXK_GROUP_NR] = {0x6}; -static const u32 g_gain_bb[RTW8851B_TXK_GROUP_NR] = {0x10}; -static const u32 g_itqt[RTW8851B_TXK_GROUP_NR] = {0x12}; - -static const u32 rtw8851b_backup_bb_regs[] = {0xc0d4, 0xc0d8, 0xc0c4, 0xc0ec, 0xc0e8}; +static const u32 a_idxrxgain[RTW8851B_RXK_GROUP_IDX_NR] = {0x10C, 0x112, 0x28c, 0x292}; +static const u32 a_idxattc2[RTW8851B_RXK_GROUP_IDX_NR] = {0xf, 0xf, 0xf, 0xf}; +static const u32 a_idxrxagc[RTW8851B_RXK_GROUP_IDX_NR] = {0x4, 0x5, 0x6, 0x7}; +static const u32 a_power_range[RTW8851B_A_TXK_GROUP_NR] = {0x0, 0x0}; +static const u32 a_track_range[RTW8851B_A_TXK_GROUP_NR] = {0x7, 0x7}; +static const u32 a_gain_bb[RTW8851B_A_TXK_GROUP_NR] = {0x08, 0x0d}; +static const u32 a_itqt[RTW8851B_A_TXK_GROUP_NR] = {0x12, 0x12}; +static const u32 a_att_smxr[RTW8851B_A_TXK_GROUP_NR] = {0x0, 0x2}; +static const u32 g_power_range[RTW8851B_G_TXK_GROUP_NR] = {0x0}; +static const u32 g_track_range[RTW8851B_G_TXK_GROUP_NR] = {0x6}; +static const u32 g_gain_bb[RTW8851B_G_TXK_GROUP_NR] = {0x10}; +static const u32 g_itqt[RTW8851B_G_TXK_GROUP_NR] = {0x12}; + +static const u32 rtw8851b_backup_bb_regs[] = { + 0xc0d4, 0xc0d8, 0xc0c4, 0xc0ec, 0xc0e8, 0x12a0, 0xc0f0}; static const u32 rtw8851b_backup_rf_regs[] = { 0xef, 0xde, 0x0, 0x1e, 0x2, 0x85, 0x90, 0x5}; @@ -116,22 +137,11 @@ static const u32 rtw8851b_backup_rf_regs[] = { #define BACKUP_RF_REGS_NR ARRAY_SIZE(rtw8851b_backup_rf_regs) static const u32 dpk_kip_reg[DPK_KIP_REG_NUM_8851B] = { - 0x813c, 0x8124, 0xc0ec, 0xc0e8, 0xc0c4, 0xc0d4, 0xc0d8}; + 0x813c, 0x8124, 0xc0ec, 0xc0e8, 0xc0c4, 0xc0d4, 0xc0d8, 0x12a0}; static const u32 dpk_rf_reg[DPK_RF_REG_NUM_8851B] = {0xde, 0x8f, 0x5, 0x10005}; static void _set_ch(struct rtw89_dev *rtwdev, u32 val); -static u8 _rxk_5ghz_group_from_idx(u8 idx) -{ - /* There are four RXK groups (RTW8851B_RXK_GROUP_NR), but only group 0 - * and 2 are used in 5 GHz band, so reduce elements to 2. - */ - if (idx < RTW8851B_RXK_GROUP_IDX_NR) - return idx * 2; - - return 0; -} - static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { return RF_A; @@ -163,6 +173,51 @@ static void _rfk_drf_direct_cntrl(struct rtw89_dev *rtwdev, rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x0); } +static void _txck_force(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool force, enum dac_ck ck) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 13), B_P0_TXCK_ON, 0x0); + + if (!force) + return; + + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 13), B_P0_TXCK_VAL, ck); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 13), B_P0_TXCK_ON, 0x1); +} + +static void _rxck_force(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool force, enum adc_ck ck) +{ + static const u32 ck960_8851b[] = {0x8, 0x2, 0x2, 0x4, 0xf, 0xa, 0x92}; + static const u32 ck1920_8851b[] = {0x9, 0x0, 0x0, 0x3, 0xf, 0xa, 0x49}; + const u32 *data; + + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 13), B_P0_RXCK_ON, 0x0); + if (!force) + return; + + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 13), B_P0_RXCK_VAL, ck); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 13), B_P0_RXCK_ON, 0x1); + + switch (ck) { + case ADC_960M: + data = ck960_8851b; + break; + case ADC_1920M: + default: + data = ck1920_8851b; + break; + } + + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0 | (path << 8), B_P0_CFCH_CTL, data[0]); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0 | (path << 8), B_P0_CFCH_EN, data[1]); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0 | (path << 8), B_P0_CFCH_BW0, data[2]); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1 | (path << 8), B_P0_CFCH_BW1, data[3]); + rtw89_phy_write32_mask(rtwdev, R_DRCK | (path << 8), B_DRCK_MUL, data[4]); + rtw89_phy_write32_mask(rtwdev, R_ADCMOD | (path << 8), B_ADCMOD_LP, data[5]); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK | (path << 8), B_P0_RXCK_ADJ, data[6]); +} + static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) { u32 rf_mode; @@ -737,7 +792,7 @@ static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, "[IQK]============ S%d ID_NBTXK ============\n", path); rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, - 0x00b); + 0x11); iqk_cmd = 0x408 | (1 << (4 + path)); break; case ID_NBRXK: @@ -755,7 +810,7 @@ static bool _iqk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, iqk_cmd + 1); notready = _iqk_check_cal(rtwdev, path); if (iqk_info->iqk_sram_en && - (ktype == ID_NBRXK || ktype == ID_RXK)) + (ktype == ID_NBRXK || ktype == ID_RXK || ktype == ID_NBTXK)) _iqk_sram(rtwdev, path); rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_IQK_RFC_ON, 0x0); @@ -842,18 +897,27 @@ static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev, bool kfail = false; bool notready; u32 rf_0; - u8 idx; + u32 val; u8 gp; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); - for (idx = 0; idx < RTW8851B_RXK_GROUP_IDX_NR; idx++) { - gp = _rxk_5ghz_group_from_idx(idx); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x1000); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x4); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x17); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x5); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x27); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x0); + + val = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RXA2, 0x20); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0xc); + for (gp = 0; gp < RTW8851B_RXK_GROUP_IDX_NR; gp++) { rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[gp]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[gp]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, 0x20, 0x1); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0); @@ -863,7 +927,7 @@ static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev, fsleep(100); rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK); rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0); - rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]); + rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[gp]); rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11); notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC); @@ -896,6 +960,7 @@ static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev, _iqk_sram(rtwdev, path); if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_IQK_RES, B_IQK_RES_RXCFIR, 0x0); rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, iqk_info->nb_rxcfir[path] | 0x2); iqk_info->is_wb_txiqk[path] = false; @@ -905,6 +970,14 @@ static bool _rxk_5g_group_sel(struct rtw89_dev *rtwdev, iqk_info->is_wb_txiqk[path] = true; } + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, 0x20, val); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x1000); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x4); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x37); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x5); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x27); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x0); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail, 1 << path, iqk_info->nb_rxcfir[path]); @@ -917,17 +990,26 @@ static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; bool kfail = false; bool notready; - u8 idx = 0x1; + u8 gp = 2; u32 rf_0; - u8 gp; - - gp = _rxk_5ghz_group_from_idx(idx); + u32 val; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, gp = %x\n", path, gp); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[idx]); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[idx]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x1000); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x4); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x17); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x5); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x27); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x0); + + val = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RXA2, 0x20); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0xc); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_RGM, a_idxrxgain[gp]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, RR_RXA2_ATT, a_idxattc2[gp]); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, 0x20, 0x1); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x0); @@ -937,7 +1019,7 @@ static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, fsleep(100); rf_0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK); rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI, rf_0); - rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[idx]); + rtw89_phy_write32_mask(rtwdev, R_IQK_RXA, B_IQK_RXAGC, a_idxrxagc[gp]); rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x11); notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXAGC); @@ -963,6 +1045,7 @@ static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); if (kfail) { + rtw89_phy_write32_mask(rtwdev, R_IQK_RES + (path << 8), 0xf, 0x0); rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, 0x40000002); iqk_info->is_wb_rxiqk[path] = false; @@ -970,6 +1053,14 @@ static bool _iqk_5g_nbrxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, iqk_info->is_wb_rxiqk[path] = false; } + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RXA2, 0x20, val); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x1000); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x4); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x37); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWA, RFREG_MASK, 0x5); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWD0, RFREG_MASK, 0x27); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_LUTWE, RFREG_MASK, 0x0); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, kfail = 0x%x, 0x8%x3c = 0x%x\n", path, kfail, 1 << path, iqk_info->nb_rxcfir[path]); @@ -1044,15 +1135,49 @@ static void _iqk_rxclk_setting(struct rtw89_dev *rtwdev, u8 path) rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_CKT, 0x1); - if (iqk_info->iqk_bw[path] == RTW89_CHANNEL_WIDTH_80) + if (iqk_info->iqk_bw[path] == RTW89_CHANNEL_WIDTH_80) { + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0101); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_DPD_GDIS, 0x1); + + _rxck_force(rtwdev, path, true, ADC_960M); + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_80_defs_tbl); - else + } else { + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0101); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_DPD_GDIS, 0x1); + + _rxck_force(rtwdev, path, true, ADC_960M); + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_rxclk_others_defs_tbl); + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, (2)before RXK IQK\n", path); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[07:10] = 0x%x\n", path, + 0xc0d4, rtw89_phy_read32_mask(rtwdev, 0xc0d4, GENMASK(10, 7))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[11:14] = 0x%x\n", path, + 0xc0d4, rtw89_phy_read32_mask(rtwdev, 0xc0d4, GENMASK(14, 11))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[26:27] = 0x%x\n", path, + 0xc0d4, rtw89_phy_read32_mask(rtwdev, 0xc0d4, GENMASK(27, 26))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[05:08] = 0x%x\n", path, + 0xc0d8, rtw89_phy_read32_mask(rtwdev, 0xc0d8, GENMASK(8, 5))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[17:21] = 0x%x\n", path, + 0xc0c4, rtw89_phy_read32_mask(rtwdev, 0xc0c4, GENMASK(21, 17))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[16:31] = 0x%x\n", path, + 0xc0e8, rtw89_phy_read32_mask(rtwdev, 0xc0e8, GENMASK(31, 16))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[04:05] = 0x%x\n", path, + 0xc0e4, rtw89_phy_read32_mask(rtwdev, 0xc0e4, GENMASK(5, 4))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[23:31] = 0x%x\n", path, + 0x12a0, rtw89_phy_read32_mask(rtwdev, 0x12a0, GENMASK(31, 23))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[13:14] = 0x%x\n", path, + 0xc0ec, rtw89_phy_read32_mask(rtwdev, 0xc0ec, GENMASK(14, 13))); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x%x[16:23] = 0x%x\n", path, + 0xc0ec, rtw89_phy_read32_mask(rtwdev, 0xc0ec, GENMASK(23, 16))); } static bool _txk_5g_group_sel(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u8 path) { + static const u8 a_idx[RTW8851B_A_TXK_GROUP_NR] = {2, 3}; struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; bool kfail = false; bool notready; @@ -1060,16 +1185,20 @@ static bool _txk_5g_group_sel(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); - for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + rtw89_phy_write32_mask(rtwdev, R_CFIR_COEF, MASKDWORD, 0x33332222); + + for (gp = 0x0; gp < RTW8851B_A_TXK_GROUP_NR; gp++) { rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]); rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]); rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]); + rtw89_write_rf(rtwdev, path, RR_BIASA, RR_BIASA_A, a_att_smxr[gp]); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); - rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, a_idx[gp]); rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x11); rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]); notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); @@ -1110,7 +1239,9 @@ static bool _txk_2g_group_sel(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); - for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + rtw89_phy_write32_mask(rtwdev, R_CFIR_COEF, MASKDWORD, 0x0); + + for (gp = 0x0; gp < RTW8851B_G_TXK_GROUP_NR; gp++) { rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]); rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]); rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]); @@ -1153,29 +1284,29 @@ static bool _txk_2g_group_sel(struct rtw89_dev *rtwdev, static bool _iqk_5g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u8 path) { + static const u8 a_idx[RTW8851B_A_TXK_GROUP_NR] = {2, 3}; struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; bool kfail = false; bool notready; - u8 gp; + u8 gp = 0; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); - for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { - rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]); - rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]); - rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, a_power_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, a_track_range[gp]); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, a_gain_bb[gp]); + rtw89_write_rf(rtwdev, path, RR_BIASA, RR_BIASA_A, a_att_smxr[gp]); - rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); - rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); - rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); - rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, gp); - rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); - rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G3, 0x1); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_G2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT, B_CFIR_LUT_GP, a_idx[gp]); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP, 0x00); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP, MASKDWORD, a_itqt[gp]); - notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); - iqk_info->nb_txcfir[path] = - rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2; - } + notready = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK); + iqk_info->nb_txcfir[path] = + rtw89_phy_read32_mask(rtwdev, R_TXIQC, MASKDWORD) | 0x2; if (!notready) kfail = !!rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, B_NCTL_RPT_FLG); @@ -1204,7 +1335,7 @@ static bool _iqk_2g_nbtxk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); - for (gp = 0x0; gp < RTW8851B_TXK_GROUP_NR; gp++) { + for (gp = 0x0; gp < RTW8851B_G_TXK_GROUP_NR; gp++) { rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, g_power_range[gp]); rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, g_track_range[gp]); rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, g_gain_bb[gp]); @@ -1495,7 +1626,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, iqk_info->iqk_table_idx[path] = idx; rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", - path, phy, rtwdev->dbcc_en ? "on" : "off", + path, phy, str_on_off(rtwdev->dbcc_en), iqk_info->iqk_band[path] == 0 ? "2G" : iqk_info->iqk_band[path] == 1 ? "5G" : "6G", iqk_info->iqk_ch[path], @@ -1553,6 +1684,14 @@ static void _iqk_macbb_setting(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__); rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_macbb_defs_tbl); + + _txck_force(rtwdev, path, true, DAC_960M); + + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK, B_DPD_GDIS, 0x1); + + _rxck_force(rtwdev, path, true, ADC_1920M); + + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_macbb_bh_defs_tbl); } static void _iqk_init(struct rtw89_dev *rtwdev) @@ -1560,8 +1699,6 @@ static void _iqk_init(struct rtw89_dev *rtwdev) struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; u8 idx, path; - rtw89_phy_write32_mask(rtwdev, R_IQKINF, MASKDWORD, 0x0); - if (iqk_info->is_iqk_init) return; @@ -1764,8 +1901,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -1794,7 +1931,21 @@ static void _dpk_bb_afe_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path pat rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0); rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0xd801dffd); - rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_bb_afe_defs_tbl); + _txck_force(rtwdev, path, true, DAC_960M); + _rxck_force(rtwdev, path, true, ADC_1920M); + + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADCMOD, B_ADCMOD_AUTO_RST, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG, 0x1); + udelay(1); + rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15, 0x1f); + udelay(10); + rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15, 0x13); + udelay(2); + rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0x0001); + udelay(2); + rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0x0041); + udelay(10); rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x1); rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x1); @@ -1827,6 +1978,17 @@ static void _dpk_tssi_pause(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, is_pause ? "pause" : "resume"); } +static +void _dpk_tssi_slope_k_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool is_on) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_SLOPE_CAL + (path << 13), + B_P0_TSSI_SLOPE_CAL_EN, is_on); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d TSSI slpoe_k %s\n", path, + str_on_off(is_on)); +} + static void _dpk_tpg_sel(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) { struct rtw89_dpk_info *dpk = &rtwdev->dpk; @@ -1854,7 +2016,7 @@ static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev, rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n", - path, force ? "on" : "off"); + path, str_on_off(force)); } static void _dpk_kip_pwr_clk_onoff(struct rtw89_dev *rtwdev, bool turn_on) @@ -1874,9 +2036,6 @@ static void _dpk_kip_control_rfc(struct rtw89_dev *rtwdev, { rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), B_IQK_RFC_ON, ctrl_by_kip); - - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] RFC is controlled by %s\n", - ctrl_by_kip ? "KIP" : "BB"); } static void _dpk_kip_preset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, @@ -2279,7 +2438,7 @@ static void _dpk_set_mdpd_para(struct rtw89_dev *rtwdev, u8 order) case 0: /* (5,3,1) */ rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x0); rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x2); - rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x3); rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1); break; case 1: /* (5,3,0) */ @@ -2315,8 +2474,6 @@ static void _dpk_set_mdpd_para(struct rtw89_dev *rtwdev, u8 order) static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, enum rtw89_rf_path path, u8 kidx) { - rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_MA, 0x1); - if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD500) == 0x1) _dpk_set_mdpd_para(rtwdev, 0x2); else if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD530) == 0x1) @@ -2419,9 +2576,6 @@ static bool _dpk_main(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, u8 init_xdbm = 17; bool is_fail; - if (dpk->bp[path][kidx].band != RTW89_BAND_2G) - init_xdbm = 15; - _dpk_kip_control_rfc(rtwdev, path, false); _rfk_rf_direct_cntrl(rtwdev, path, false); rtw89_write_rf(rtwdev, path, RR_BBDC, RFREG_MASK, 0x03ffd); @@ -2485,6 +2639,7 @@ static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force, "[DPK] ========= S%d[%d] DPK Start =========\n", path, dpk->cur_idx[path]); + _dpk_tssi_slope_k_onoff(rtwdev, path, false); _dpk_rxagc_onoff(rtwdev, path, false); _rfk_drf_direct_cntrl(rtwdev, path, false); _dpk_bb_afe_setting(rtwdev, path); @@ -2502,7 +2657,7 @@ static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force, _dpk_reload_rf(rtwdev, dpk_rf_reg, rf_bkup, path); _dpk_bb_afe_restore(rtwdev, path); _dpk_rxagc_onoff(rtwdev, path, true); - + _dpk_tssi_slope_k_onoff(rtwdev, path, true); if (rtwdev->is_tssi_mode[path]) _dpk_tssi_pause(rtwdev, path, false); } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c index 0abf7978ccab1..c5f70c045692f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.c @@ -63,16 +63,7 @@ static const struct rtw89_reg5_def rtw8851b_dack_manual_off_defs[] = { RTW89_DECLARE_RFK_TBL(rtw8851b_dack_manual_off_defs); static const struct rtw89_reg5_def rtw8851b_iqk_rxclk_80_defs[] = { - RTW89_DECL_RFK_WM(0x20fc, 0xffff0000, 0x0101), - RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x2), RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x1), - RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x8), - RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x2), - RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x2), - RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x5), - RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xf), RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x0), RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1), RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x0f), @@ -85,16 +76,7 @@ static const struct rtw89_reg5_def rtw8851b_iqk_rxclk_80_defs[] = { RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_rxclk_80_defs); static const struct rtw89_reg5_def rtw8851b_iqk_rxclk_others_defs[] = { - RTW89_DECL_RFK_WM(0x20fc, 0xffff0000, 0x0101), - RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x2), RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x0), - RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x8), - RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x2), - RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x2), - RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x5), - RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xf), RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x2), RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1), RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x0f), @@ -157,55 +139,38 @@ static const struct rtw89_reg5_def rtw8851b_iqk_macbb_defs[] = { RTW89_DECL_RFK_WM(0x20fc, 0x10000000, 0x0), RTW89_DECL_RFK_WM(0x5670, MASKDWORD, 0xf801fffd), RTW89_DECL_RFK_WM(0x5670, 0x00004000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00008000, 0x1), RTW89_DECL_RFK_WM(0x5670, 0x80000000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00007000, 0x7), - RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x3), +}; + +RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_macbb_defs); + +static const struct rtw89_reg5_def rtw8851b_iqk_macbb_bh_defs[] = { RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x2), - RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x9), - RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x1), - RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x0), - RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x3), - RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xa), - RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x0), - RTW89_DECL_RFK_WM(0xc0e8, 0x00000040, 0x1), RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1), + RTW89_DECL_RFK_DELAY(2), + RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x1f), + RTW89_DECL_RFK_DELAY(10), + RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x13), + RTW89_DECL_RFK_DELAY(2), + RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0001), + RTW89_DECL_RFK_DELAY(2), + RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0041), + RTW89_DECL_RFK_DELAY(10), + RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1), + RTW89_DECL_RFK_DELAY(2), RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x1f), + RTW89_DECL_RFK_DELAY(10), RTW89_DECL_RFK_WM(0x030c, 0xff000000, 0x13), + RTW89_DECL_RFK_DELAY(2), RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0001), + RTW89_DECL_RFK_DELAY(2), RTW89_DECL_RFK_WM(0x032c, 0xffff0000, 0x0041), + RTW89_DECL_RFK_DELAY(10), RTW89_DECL_RFK_WM(0x20fc, 0x00100000, 0x1), RTW89_DECL_RFK_WM(0x20fc, 0x10000000, 0x1), }; -RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_macbb_defs); - -static const struct rtw89_reg5_def rtw8851b_iqk_bb_afe_defs[] = { - RTW89_DECL_RFK_WM(0x5670, 0x00004000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00008000, 0x1), - RTW89_DECL_RFK_WM(0x5670, 0x80000000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00007000, 0x7), - RTW89_DECL_RFK_WM(0x5670, 0x00002000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00080000, 0x1), - RTW89_DECL_RFK_WM(0x12a0, 0x00070000, 0x3), - RTW89_DECL_RFK_WM(0x5670, 0x60000000, 0x2), - RTW89_DECL_RFK_WM(0xc0d4, 0x00000780, 0x9), - RTW89_DECL_RFK_WM(0xc0d4, 0x00007800, 0x1), - RTW89_DECL_RFK_WM(0xc0d4, 0x0c000000, 0x0), - RTW89_DECL_RFK_WM(0xc0d8, 0x000001e0, 0x3), - RTW89_DECL_RFK_WM(0xc0c4, 0x003e0000, 0xa), - RTW89_DECL_RFK_WM(0xc0ec, 0x00006000, 0x0), - RTW89_DECL_RFK_WM(0xc0e8, 0x00000040, 0x1), - RTW89_DECL_RFK_WM(0x12b8, 0x40000000, 0x1), - RTW89_DECL_RFK_WM(0x030c, MASKBYTE3, 0x1f), - RTW89_DECL_RFK_WM(0x030c, MASKBYTE3, 0x13), - RTW89_DECL_RFK_WM(0x032c, MASKHWORD, 0x0001), - RTW89_DECL_RFK_WM(0x032c, MASKHWORD, 0x0041), -}; - -RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_bb_afe_defs); +RTW89_DECLARE_RFK_TBL(rtw8851b_iqk_macbb_bh_defs); static const struct rtw89_reg5_def rtw8851b_tssi_sys_defs[] = { RTW89_DECL_RFK_WM(0x12bc, 0x000ffff0, 0xb5b5), diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h index febfbecb691c1..3f1547f57505a 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk_table.h @@ -17,8 +17,8 @@ extern const struct rtw89_rfk_tbl rtw8851b_iqk_rxclk_others_defs_tbl; extern const struct rtw89_rfk_tbl rtw8851b_iqk_txk_2ghz_defs_tbl; extern const struct rtw89_rfk_tbl rtw8851b_iqk_txk_5ghz_defs_tbl; extern const struct rtw89_rfk_tbl rtw8851b_iqk_afebb_restore_defs_tbl; -extern const struct rtw89_rfk_tbl rtw8851b_iqk_bb_afe_defs_tbl; extern const struct rtw89_rfk_tbl rtw8851b_iqk_macbb_defs_tbl; +extern const struct rtw89_rfk_tbl rtw8851b_iqk_macbb_bh_defs_tbl; extern const struct rtw89_rfk_tbl rtw8851b_tssi_sys_defs_tbl; extern const struct rtw89_rfk_tbl rtw8851b_tssi_sys_a_defs_2g_tbl; extern const struct rtw89_rfk_tbl rtw8851b_tssi_sys_a_defs_5g_tbl; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c index 522883c8dfb98..a9c309c245c33 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c @@ -2320,9 +2320,9 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x813c, 0x40000000}, {0x8140, 0x00000000}, {0x8144, 0x0b040b03}, - {0x8148, 0x07020b04}, - {0x814c, 0x07020b04}, - {0x8150, 0xa0a00000}, + {0x8148, 0x07020a04}, + {0x814c, 0x07020a04}, + {0x8150, 0xe4e40000}, {0x8158, 0xffffffff}, {0x815c, 0xffffffff}, {0x8160, 0xffffffff}, @@ -2577,14 +2577,14 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8534, 0x400042fe}, {0x8538, 0x50554200}, {0x853c, 0xb4183000}, - {0x8540, 0xe537a50f}, + {0x8540, 0xe535a50f}, {0x8544, 0xf12bf02b}, {0x8548, 0xf32bf22b}, {0x854c, 0xf62bf42b}, {0x8550, 0xf82bf72b}, {0x8554, 0xfa2bf92b}, {0x8558, 0xfd2bfc2b}, - {0x855c, 0xe537fe2b}, + {0x855c, 0xe535fe2b}, {0x8560, 0xf12af02a}, {0x8564, 0xf32af22a}, {0x8568, 0xf52af42a}, @@ -2653,7 +2653,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8664, 0x9700140f}, {0x8668, 0x00017430}, {0x866c, 0xe39ce35e}, - {0x8670, 0xe52a0bbd}, + {0x8670, 0xe5280bbd}, {0x8674, 0xe36a0001}, {0x8678, 0x0001e3c4}, {0x867c, 0x55005b30}, @@ -2664,93 +2664,93 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8690, 0x46100005}, {0x8694, 0x00010004}, {0x8698, 0x30f8e35e}, - {0x869c, 0xe52a0023}, + {0x869c, 0xe5280023}, {0x86a0, 0x54ed0002}, {0x86a4, 0x00230baa}, - {0x86a8, 0x0002e52a}, + {0x86a8, 0x0002e528}, {0x86ac, 0xe356e3e4}, {0x86b0, 0xe35e0001}, {0x86b4, 0x002230f3}, - {0x86b8, 0x0002e52a}, + {0x86b8, 0x0002e528}, {0x86bc, 0x0baa54ec}, - {0x86c0, 0xe52a0022}, + {0x86c0, 0xe5280022}, {0x86c4, 0xe3e40002}, {0x86c8, 0x0001e356}, {0x86cc, 0x0baae35e}, {0x86d0, 0xe3e430ec}, {0x86d4, 0x0001e356}, {0x86d8, 0x6d0f6c67}, - {0x86dc, 0xe52ae39c}, + {0x86dc, 0xe528e39c}, {0x86e0, 0xe39c6c8b}, - {0x86e4, 0x0bace52a}, + {0x86e4, 0x0bace528}, {0x86e8, 0x6d0f6cb3}, - {0x86ec, 0xe52ae39c}, + {0x86ec, 0xe528e39c}, {0x86f0, 0x6cdb0bad}, {0x86f4, 0xe39c6d0f}, - {0x86f8, 0x6cf5e52a}, + {0x86f8, 0x6cf5e528}, {0x86fc, 0xe39c6d0f}, - {0x8700, 0x6c0be52a}, + {0x8700, 0x6c0be528}, {0x8704, 0xe39c6d00}, - {0x8708, 0x6c25e52a}, - {0x870c, 0xe52ae39c}, + {0x8708, 0x6c25e528}, + {0x870c, 0xe528e39c}, {0x8710, 0x6c4df8c6}, - {0x8714, 0xe52ae39c}, + {0x8714, 0xe528e39c}, {0x8718, 0x6c75f9cf}, - {0x871c, 0xe52ae39c}, + {0x871c, 0xe528e39c}, {0x8720, 0xe39c6c99}, - {0x8724, 0xfad6e52a}, + {0x8724, 0xfad6e528}, {0x8728, 0x21e87410}, {0x872c, 0x6e670009}, {0x8730, 0xe3c46f0f}, - {0x8734, 0x7410e52f}, + {0x8734, 0x7410e52d}, {0x8738, 0x000b21e8}, {0x873c, 0xe3c46e8b}, - {0x8740, 0x7410e52f}, + {0x8740, 0x7410e52d}, {0x8744, 0x000d21e8}, {0x8748, 0x6f0f6eb3}, - {0x874c, 0xe52fe3c4}, + {0x874c, 0xe52de3c4}, {0x8750, 0xfe07ff08}, {0x8754, 0x21e87410}, {0x8758, 0x6ec7000e}, - {0x875c, 0xe52fe3c4}, + {0x875c, 0xe52de3c4}, {0x8760, 0x21e87410}, {0x8764, 0x6edb000f}, {0x8768, 0xe3c46f0f}, - {0x876c, 0x7410e52f}, + {0x876c, 0x7410e52d}, {0x8770, 0x001021e8}, {0x8774, 0xe3c46eef}, - {0x8778, 0xff03e52f}, - {0x877c, 0xe52ffe02}, + {0x8778, 0xff03e52d}, + {0x877c, 0xe52dfe02}, {0x8780, 0x21e87410}, {0x8784, 0x6e110013}, {0x8788, 0xe3c46f00}, - {0x878c, 0xff03e52f}, - {0x8790, 0xe52ffe02}, + {0x878c, 0xff03e52d}, + {0x8790, 0xe52dfe02}, {0x8794, 0x21e87410}, {0x8798, 0x6e250014}, - {0x879c, 0xe52fe3c4}, + {0x879c, 0xe52de3c4}, {0x87a0, 0xff08fc24}, {0x87a4, 0x7410fe07}, {0x87a8, 0x001521e8}, {0x87ac, 0xe3c46e39}, - {0x87b0, 0x7410e52f}, + {0x87b0, 0x7410e52d}, {0x87b4, 0x001621e8}, {0x87b8, 0xe3c46e4d}, - {0x87bc, 0xfd27e52f}, + {0x87bc, 0xfd27e52d}, {0x87c0, 0x21e87410}, {0x87c4, 0x6e750018}, - {0x87c8, 0xe52fe3c4}, + {0x87c8, 0xe52de3c4}, {0x87cc, 0x21e87410}, {0x87d0, 0x6e99001a}, - {0x87d4, 0xe52fe3c4}, + {0x87d4, 0xe52de3c4}, {0x87d8, 0xe36afe24}, {0x87dc, 0x63404380}, {0x87e0, 0x43006880}, {0x87e4, 0x31300bac}, - {0x87e8, 0xe52f0022}, + {0x87e8, 0xe52d0022}, {0x87ec, 0x54ec0002}, {0x87f0, 0x00220baa}, - {0x87f4, 0x0002e52f}, + {0x87f4, 0x0002e52d}, {0x87f8, 0xe362e3e4}, {0x87fc, 0xe36a0001}, {0x8800, 0x63404380}, @@ -2770,7 +2770,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8838, 0x55010004}, {0x883c, 0x66055b40}, {0x8840, 0x62000007}, - {0x8844, 0xe40e6300}, + {0x8844, 0xe40c6300}, {0x8848, 0x09000004}, {0x884c, 0x0b400a01}, {0x8850, 0x0e010d00}, @@ -2782,13 +2782,13 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8868, 0x00044d01}, {0x886c, 0x00074300}, {0x8870, 0x05a30562}, - {0x8874, 0xe40e961f}, + {0x8874, 0xe40c961f}, {0x8878, 0xe37e0004}, {0x887c, 0x06a20007}, - {0x8880, 0xe40e07a3}, + {0x8880, 0xe40c07a3}, {0x8884, 0xe37e0004}, - {0x8888, 0x0002e3fe}, - {0x888c, 0x4380e406}, + {0x8888, 0x0002e3fc}, + {0x888c, 0x4380e404}, {0x8890, 0x4d000007}, {0x8894, 0x43000004}, {0x8898, 0x000742fe}, @@ -2815,13 +2815,13 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x88ec, 0x42000004}, {0x88f0, 0x00070001}, {0x88f4, 0x62006220}, - {0x88f8, 0x0001e406}, + {0x88f8, 0x0001e404}, {0x88fc, 0x63000007}, {0x8900, 0x09000004}, {0x8904, 0x0e010a00}, {0x8908, 0x00070032}, - {0x890c, 0xe40e06a2}, - {0x8910, 0x0002e41a}, + {0x890c, 0xe40c06a2}, + {0x8910, 0x0002e418}, {0x8914, 0x000742fe}, {0x8918, 0x00044d00}, {0x891c, 0x00014200}, @@ -2839,50 +2839,50 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x894c, 0x00014300}, {0x8950, 0x6c060005}, {0x8954, 0xe2aae298}, - {0x8958, 0xe42ae285}, - {0x895c, 0xe432e2f3}, + {0x8958, 0xe428e285}, + {0x895c, 0xe430e2f3}, {0x8960, 0x0001e30c}, {0x8964, 0x0005e285}, {0x8968, 0xe2986c06}, - {0x896c, 0xe42ae4a9}, - {0x8970, 0xe432e2f3}, + {0x896c, 0xe428e4a7}, + {0x8970, 0xe430e2f3}, {0x8974, 0x0001e30c}, {0x8978, 0x6c000005}, {0x897c, 0xe2aae298}, - {0x8980, 0xe445e285}, - {0x8984, 0xe44de2f3}, + {0x8980, 0xe443e285}, + {0x8984, 0xe44be2f3}, {0x8988, 0x0001e30c}, {0x898c, 0x0005e285}, {0x8990, 0xe2986c00}, - {0x8994, 0xe445e4a9}, - {0x8998, 0xe44de2f3}, + {0x8994, 0xe443e4a7}, + {0x8998, 0xe44be2f3}, {0x899c, 0x0001e30c}, {0x89a0, 0x6c040005}, {0x89a4, 0xe2aae298}, - {0x89a8, 0xe460e285}, - {0x89ac, 0xe468e2f3}, + {0x89a8, 0xe45ee285}, + {0x89ac, 0xe466e2f3}, {0x89b0, 0x0001e30c}, {0x89b4, 0x0005e285}, {0x89b8, 0xe2986c04}, - {0x89bc, 0xe460e4a9}, - {0x89c0, 0xe468e2f3}, + {0x89bc, 0xe45ee4a7}, + {0x89c0, 0xe466e2f3}, {0x89c4, 0x0001e30c}, {0x89c8, 0x6c020005}, {0x89cc, 0xe2aae298}, - {0x89d0, 0xe47be285}, - {0x89d4, 0xe483e2f3}, + {0x89d0, 0xe479e285}, + {0x89d4, 0xe481e2f3}, {0x89d8, 0x0001e30c}, {0x89dc, 0x0005e285}, {0x89e0, 0xe2986c02}, - {0x89e4, 0xe47be4a9}, - {0x89e8, 0xe483e2f3}, + {0x89e4, 0xe479e4a7}, + {0x89e8, 0xe481e2f3}, {0x89ec, 0x0001e30c}, {0x89f0, 0x43800004}, {0x89f4, 0x610a6008}, {0x89f8, 0x63ce6200}, {0x89fc, 0x60800006}, {0x8a00, 0x00047f00}, - {0x8a04, 0xe4e04300}, + {0x8a04, 0xe4de4300}, {0x8a08, 0x00070001}, {0x8a0c, 0x4d015500}, {0x8a10, 0x74200004}, @@ -2895,22 +2895,22 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8a2c, 0x00014300}, {0x8a30, 0x74200004}, {0x8a34, 0x77000005}, - {0x8a38, 0x73887e07}, + {0x8a38, 0x73887e06}, {0x8a3c, 0x8f007380}, {0x8a40, 0x0004140f}, {0x8a44, 0x00057430}, {0x8a48, 0x00017300}, - {0x8a4c, 0x0005e496}, + {0x8a4c, 0x0005e494}, {0x8a50, 0x00017300}, {0x8a54, 0x43800004}, {0x8a58, 0x0006b103}, {0x8a5c, 0x91037cdb}, {0x8a60, 0x40db0007}, {0x8a64, 0x43000004}, - {0x8a68, 0x0005e496}, + {0x8a68, 0x0005e494}, {0x8a6c, 0x00067380}, {0x8a70, 0x60025d01}, - {0x8a74, 0xe4ba6200}, + {0x8a74, 0xe4b86200}, {0x8a78, 0x73000005}, {0x8a7c, 0x76080007}, {0x8a80, 0x00047578}, @@ -2943,8 +2943,8 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8aec, 0x7cdb0006}, {0x8af0, 0x00079103}, {0x8af4, 0x000440db}, - {0x8af8, 0xe4964300}, - {0x8afc, 0xe4ba7e03}, + {0x8af8, 0xe4944300}, + {0x8afc, 0xe4b87e03}, {0x8b00, 0x43800004}, {0x8b04, 0x0006b103}, {0x8b08, 0x91037c5b}, @@ -2976,14 +2976,14 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8b70, 0x43000004}, {0x8b74, 0x73000005}, {0x8b78, 0x76000007}, - {0x8b7c, 0xe4c30001}, + {0x8b7c, 0xe4c10001}, {0x8b80, 0x00040001}, {0x8b84, 0x60004380}, {0x8b88, 0x62016100}, {0x8b8c, 0x00066310}, {0x8b90, 0x00046000}, {0x8b94, 0x00014300}, - {0x8b98, 0x0001e4e0}, + {0x8b98, 0x0001e4de}, {0x8b9c, 0x4e004f02}, {0x8ba0, 0x52015302}, {0x8ba4, 0x140f0001}, @@ -3030,7 +3030,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8c48, 0xbf1ae3ac}, {0x8c4c, 0xe36e300b}, {0x8c50, 0xe390e377}, - {0x8c54, 0x0001e523}, + {0x8c54, 0x0001e521}, {0x8c58, 0x54c054bf}, {0x8c5c, 0x54c154a3}, {0x8c60, 0x4c1854a4}, @@ -3039,7 +3039,7 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8c6c, 0xbf051402}, {0x8c70, 0x54a354c1}, {0x8c74, 0xbf011402}, - {0x8c78, 0x54dfe534}, + {0x8c78, 0x54dfe532}, {0x8c7c, 0x54bf0001}, {0x8c80, 0x050a54e5}, {0x8c84, 0x000154df}, @@ -3060,186 +3060,185 @@ static const struct rtw89_reg2_def rtw89_8851b_phy_nctl_regs[] = { {0x8cc0, 0x56005610}, {0x8cc4, 0x00018c00}, {0x8cc8, 0x57005704}, - {0x8ccc, 0xa7038e00}, - {0x8cd0, 0x33f0aff7}, - {0x8cd4, 0xaf034019}, - {0x8cd8, 0x33f0402b}, - {0x8cdc, 0x33df402b}, - {0x8ce0, 0x57005708}, - {0x8ce4, 0x57818e00}, - {0x8ce8, 0x8e005780}, - {0x8cec, 0x00074380}, - {0x8cf0, 0x5c005c01}, - {0x8cf4, 0x00041403}, - {0x8cf8, 0x00014300}, - {0x8cfc, 0x0007427f}, - {0x8d00, 0x62006280}, - {0x8d04, 0x00049200}, - {0x8d08, 0x00014200}, - {0x8d0c, 0x0007427f}, - {0x8d10, 0x63146394}, - {0x8d14, 0x00049200}, - {0x8d18, 0x00014200}, - {0x8d1c, 0x42fe0004}, - {0x8d20, 0x4d010007}, - {0x8d24, 0x42000004}, - {0x8d28, 0x140f7420}, - {0x8d2c, 0x57005710}, - {0x8d30, 0x0001141f}, - {0x8d34, 0x42fe0004}, - {0x8d38, 0x4d010007}, - {0x8d3c, 0x42000004}, - {0x8d40, 0x140f7420}, - {0x8d44, 0x000742bf}, - {0x8d48, 0x62006240}, - {0x8d4c, 0x0004141f}, - {0x8d50, 0x00014200}, - {0x8d54, 0x5d060006}, - {0x8d58, 0x61046003}, - {0x8d5c, 0x00056201}, - {0x8d60, 0x00017310}, - {0x8d64, 0x43800004}, - {0x8d68, 0x5e010007}, - {0x8d6c, 0x140a5e00}, - {0x8d70, 0x0006b103}, - {0x8d74, 0x91037f07}, - {0x8d78, 0x43070007}, - {0x8d7c, 0x5c000006}, - {0x8d80, 0x5e035d02}, - {0x8d84, 0x43000004}, - {0x8d88, 0x00060001}, - {0x8d8c, 0x60005d04}, - {0x8d90, 0x62016104}, - {0x8d94, 0x73100005}, - {0x8d98, 0x00040001}, - {0x8d9c, 0x00074380}, - {0x8da0, 0x5e005e01}, - {0x8da4, 0xb103140a}, - {0x8da8, 0x7fc60006}, - {0x8dac, 0x00079103}, - {0x8db0, 0x000643c6}, - {0x8db4, 0x5d025c00}, - {0x8db8, 0x00045e03}, - {0x8dbc, 0x00014300}, - {0x8dc0, 0x5d040006}, - {0x8dc4, 0x61046000}, - {0x8dc8, 0x00056201}, - {0x8dcc, 0x00017310}, - {0x8dd0, 0x43800004}, - {0x8dd4, 0x5e010007}, - {0x8dd8, 0x140a5e00}, - {0x8ddc, 0x0006b103}, - {0x8de0, 0x91037fc6}, - {0x8de4, 0x43c60007}, - {0x8de8, 0x5c000006}, - {0x8dec, 0x5e035d02}, - {0x8df0, 0x43000004}, - {0x8df4, 0x00060001}, - {0x8df8, 0x60025d00}, - {0x8dfc, 0x62016100}, - {0x8e00, 0x73000005}, - {0x8e04, 0x00040001}, - {0x8e08, 0x00074380}, - {0x8e0c, 0x5e005e01}, - {0x8e10, 0xb103140a}, - {0x8e14, 0x7fc00006}, - {0x8e18, 0x00079103}, - {0x8e1c, 0x000643c0}, - {0x8e20, 0x5d025c00}, - {0x8e24, 0x00045e03}, - {0x8e28, 0x00014300}, - {0x8e2c, 0x7e020005}, - {0x8e30, 0x42f70004}, - {0x8e34, 0x6c080005}, - {0x8e38, 0x42700004}, - {0x8e3c, 0x73810005}, - {0x8e40, 0x93007380}, - {0x8e44, 0x42f70004}, - {0x8e48, 0x6c000005}, - {0x8e4c, 0x42000004}, - {0x8e50, 0x00040001}, - {0x8e54, 0x00074380}, - {0x8e58, 0x73007304}, - {0x8e5c, 0x72401405}, - {0x8e60, 0x43000004}, - {0x8e64, 0x74040006}, - {0x8e68, 0x40010007}, - {0x8e6c, 0xab004000}, - {0x8e70, 0x0001140f}, - {0x8e74, 0x140ae517}, - {0x8e78, 0x140ae4c3}, - {0x8e7c, 0x0001e51e}, - {0x8e80, 0xe4c3e517}, - {0x8e84, 0x00040001}, - {0x8e88, 0x00047410}, - {0x8e8c, 0x42f04380}, - {0x8e90, 0x62080007}, - {0x8e94, 0x24206301}, - {0x8e98, 0x14c80000}, - {0x8e9c, 0x00002428}, - {0x8ea0, 0x1a4215f4}, - {0x8ea4, 0x6300000b}, - {0x8ea8, 0x42000004}, - {0x8eac, 0x74304300}, - {0x8eb0, 0x4380140f}, - {0x8eb4, 0x73080007}, - {0x8eb8, 0x00047300}, - {0x8ebc, 0x00014300}, - {0x8ec0, 0x4bf00007}, - {0x8ec4, 0x490b4a8f}, - {0x8ec8, 0x4a8e48f1}, - {0x8ecc, 0x48a5490a}, - {0x8ed0, 0x49094a8d}, - {0x8ed4, 0x4a8c487d}, - {0x8ed8, 0x48754908}, - {0x8edc, 0x49074a8b}, - {0x8ee0, 0x4a8a4889}, - {0x8ee4, 0x48b74906}, - {0x8ee8, 0x49054a89}, - {0x8eec, 0x4a8848fc}, - {0x8ef0, 0x48564905}, - {0x8ef4, 0x49044a87}, - {0x8ef8, 0x4a8648c1}, - {0x8efc, 0x483d4904}, - {0x8f00, 0x49034a85}, - {0x8f04, 0x4a8448c7}, - {0x8f08, 0x485e4903}, - {0x8f0c, 0x49024a83}, - {0x8f10, 0x4a8248ac}, - {0x8f14, 0x48624902}, - {0x8f18, 0x49024a81}, - {0x8f1c, 0x4a804820}, - {0x8f20, 0x48004900}, - {0x8f24, 0x49014a90}, - {0x8f28, 0x4a10481f}, - {0x8f2c, 0x00060001}, - {0x8f30, 0x5f005f80}, - {0x8f34, 0x00059900}, - {0x8f38, 0x00017300}, - {0x8f3c, 0x63800006}, - {0x8f40, 0x98006300}, - {0x8f44, 0x549f0001}, - {0x8f48, 0x5c015400}, - {0x8f4c, 0x540054df}, - {0x8f50, 0x00015c02}, - {0x8f54, 0x07145c01}, - {0x8f58, 0x5c025400}, - {0x8f5c, 0x5c020001}, - {0x8f60, 0x54000714}, - {0x8f64, 0x00015c01}, - {0x8f68, 0x4c184c98}, - {0x8f6c, 0x00080001}, - {0x8f70, 0x5c020004}, - {0x8f74, 0x09017430}, - {0x8f78, 0x0ba60c01}, - {0x8f7c, 0x77800005}, - {0x8f80, 0x52200007}, - {0x8f84, 0x43800004}, - {0x8f88, 0x610a6008}, - {0x8f8c, 0x63c26200}, - {0x8f90, 0x5c000007}, - {0x8f94, 0x43000004}, - {0x8f98, 0x00000001}, + {0x8ccc, 0x33ee8e00}, + {0x8cd0, 0xaf034019}, + {0x8cd4, 0x33ee402b}, + {0x8cd8, 0x33df402b}, + {0x8cdc, 0x57005708}, + {0x8ce0, 0x57818e00}, + {0x8ce4, 0x8e005780}, + {0x8ce8, 0x00074380}, + {0x8cec, 0x5c005c01}, + {0x8cf0, 0x00041403}, + {0x8cf4, 0x00014300}, + {0x8cf8, 0x0007427f}, + {0x8cfc, 0x62006280}, + {0x8d00, 0x00049200}, + {0x8d04, 0x00014200}, + {0x8d08, 0x0007427f}, + {0x8d0c, 0x63146394}, + {0x8d10, 0x00049200}, + {0x8d14, 0x00014200}, + {0x8d18, 0x42fe0004}, + {0x8d1c, 0x4d010007}, + {0x8d20, 0x42000004}, + {0x8d24, 0x140f7420}, + {0x8d28, 0x57005710}, + {0x8d2c, 0x0001141f}, + {0x8d30, 0x42fe0004}, + {0x8d34, 0x4d010007}, + {0x8d38, 0x42000004}, + {0x8d3c, 0x140f7420}, + {0x8d40, 0x000742bf}, + {0x8d44, 0x62006240}, + {0x8d48, 0x0004141f}, + {0x8d4c, 0x00014200}, + {0x8d50, 0x5d060006}, + {0x8d54, 0x61046003}, + {0x8d58, 0x00056200}, + {0x8d5c, 0x00017310}, + {0x8d60, 0x43800004}, + {0x8d64, 0x5e010007}, + {0x8d68, 0x140a5e00}, + {0x8d6c, 0x0006b103}, + {0x8d70, 0x91037f07}, + {0x8d74, 0x43070007}, + {0x8d78, 0x5c000006}, + {0x8d7c, 0x5e035d02}, + {0x8d80, 0x43000004}, + {0x8d84, 0x00060001}, + {0x8d88, 0x60005d04}, + {0x8d8c, 0x62006104}, + {0x8d90, 0x73100005}, + {0x8d94, 0x00040001}, + {0x8d98, 0x00074380}, + {0x8d9c, 0x5e005e01}, + {0x8da0, 0xb103140a}, + {0x8da4, 0x7fc60006}, + {0x8da8, 0x00079103}, + {0x8dac, 0x000643c6}, + {0x8db0, 0x5d025c00}, + {0x8db4, 0x00045e03}, + {0x8db8, 0x00014300}, + {0x8dbc, 0x5d040006}, + {0x8dc0, 0x61046000}, + {0x8dc4, 0x00056200}, + {0x8dc8, 0x00017310}, + {0x8dcc, 0x43800004}, + {0x8dd0, 0x5e010007}, + {0x8dd4, 0x140a5e00}, + {0x8dd8, 0x0006b103}, + {0x8ddc, 0x91037fc6}, + {0x8de0, 0x43c60007}, + {0x8de4, 0x5c000006}, + {0x8de8, 0x5e035d02}, + {0x8dec, 0x43000004}, + {0x8df0, 0x00060001}, + {0x8df4, 0x60025d00}, + {0x8df8, 0x62006100}, + {0x8dfc, 0x73000005}, + {0x8e00, 0x00040001}, + {0x8e04, 0x00074380}, + {0x8e08, 0x5e005e01}, + {0x8e0c, 0xb103140a}, + {0x8e10, 0x7fc00006}, + {0x8e14, 0x00079103}, + {0x8e18, 0x000643c0}, + {0x8e1c, 0x5d025c00}, + {0x8e20, 0x00045e03}, + {0x8e24, 0x00014300}, + {0x8e28, 0x7e020005}, + {0x8e2c, 0x42f70004}, + {0x8e30, 0x6c080005}, + {0x8e34, 0x42700004}, + {0x8e38, 0x73810005}, + {0x8e3c, 0x93007380}, + {0x8e40, 0x42f70004}, + {0x8e44, 0x6c000005}, + {0x8e48, 0x42000004}, + {0x8e4c, 0x00040001}, + {0x8e50, 0x00074380}, + {0x8e54, 0x73007304}, + {0x8e58, 0x72401405}, + {0x8e5c, 0x43000004}, + {0x8e60, 0x74040006}, + {0x8e64, 0x40010007}, + {0x8e68, 0xab004000}, + {0x8e6c, 0x0001140f}, + {0x8e70, 0x140ae515}, + {0x8e74, 0x140ae4c1}, + {0x8e78, 0x0001e51c}, + {0x8e7c, 0xe4c1e515}, + {0x8e80, 0x00040001}, + {0x8e84, 0x00047410}, + {0x8e88, 0x42f04380}, + {0x8e8c, 0x62080007}, + {0x8e90, 0x24206301}, + {0x8e94, 0x14c80000}, + {0x8e98, 0x00002428}, + {0x8e9c, 0x1a4215f4}, + {0x8ea0, 0x6300000b}, + {0x8ea4, 0x42000004}, + {0x8ea8, 0x74304300}, + {0x8eac, 0x4380140f}, + {0x8eb0, 0x73080007}, + {0x8eb4, 0x00047300}, + {0x8eb8, 0x00014300}, + {0x8ebc, 0x4bf00007}, + {0x8ec0, 0x490b4a8f}, + {0x8ec4, 0x4a8e48f1}, + {0x8ec8, 0x48a5490a}, + {0x8ecc, 0x49094a8d}, + {0x8ed0, 0x4a8c487d}, + {0x8ed4, 0x48754908}, + {0x8ed8, 0x49074a8b}, + {0x8edc, 0x4a8a4889}, + {0x8ee0, 0x48b74906}, + {0x8ee4, 0x49054a89}, + {0x8ee8, 0x4a8848fc}, + {0x8eec, 0x48564905}, + {0x8ef0, 0x49044a87}, + {0x8ef4, 0x4a8648c1}, + {0x8ef8, 0x483d4904}, + {0x8efc, 0x49034a85}, + {0x8f00, 0x4a8448c7}, + {0x8f04, 0x485e4903}, + {0x8f08, 0x49024a83}, + {0x8f0c, 0x4a8248ac}, + {0x8f10, 0x48624902}, + {0x8f14, 0x49024a81}, + {0x8f18, 0x4a804820}, + {0x8f1c, 0x48004900}, + {0x8f20, 0x49014a90}, + {0x8f24, 0x4a10481f}, + {0x8f28, 0x00060001}, + {0x8f2c, 0x5f005f80}, + {0x8f30, 0x00059900}, + {0x8f34, 0x00017300}, + {0x8f38, 0x63800006}, + {0x8f3c, 0x98006300}, + {0x8f40, 0x549f0001}, + {0x8f44, 0x5c015400}, + {0x8f48, 0x540054df}, + {0x8f4c, 0x00015c02}, + {0x8f50, 0x07145c01}, + {0x8f54, 0x5c025400}, + {0x8f58, 0x5c020001}, + {0x8f5c, 0x54000714}, + {0x8f60, 0x00015c01}, + {0x8f64, 0x4c184c98}, + {0x8f68, 0x00080001}, + {0x8f6c, 0x5c020004}, + {0x8f70, 0x09017430}, + {0x8f74, 0x0ba60c01}, + {0x8f78, 0x77800005}, + {0x8f7c, 0x52200007}, + {0x8f80, 0x43800004}, + {0x8f84, 0x610a6008}, + {0x8f88, 0x63c26200}, + {0x8f8c, 0x5c000007}, + {0x8f90, 0x43000004}, + {0x8f94, 0x00000001}, {0x8080, 0x00000004}, {0x8080, 0x00000000}, {0x8088, 0x00000000}, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c index c9d60870ed9e0..ce59ac9f56ba8 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c @@ -29,6 +29,8 @@ static const struct rtw89_pci_info rtw8851b_pci_info = { .rx_ring_eq_is_full = false, .check_rx_tag = false, .no_rxbd_fs = false, + .group_bd_addr = false, + .rpp_fmt_size = sizeof(struct rtw89_pci_rpp_fmt), .init_cfg_reg = R_AX_PCIE_INIT_CFG1, .txhci_en_bit = B_AX_TXHCI_EN, @@ -58,6 +60,7 @@ static const struct rtw89_pci_info rtw8851b_pci_info = { .ltr_set = rtw89_pci_ltr_set, .fill_txaddr_info = rtw89_pci_fill_txaddr_info, + .parse_rpp = rtw89_pci_parse_rpp, .config_intr_mask = rtw89_pci_config_intr_mask, .enable_intr = rtw89_pci_enable_intr, .disable_intr = rtw89_pci_disable_intr, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c new file mode 100644 index 0000000000000..04e1ab13b7535 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2025 Realtek Corporation + */ + +#include +#include +#include "rtw8851b.h" +#include "usb.h" + +static const struct rtw89_driver_info rtw89_8851bu_info = { + .chip = &rtw8851b_chip_info, + .variant = NULL, + .quirks = NULL, +}; + +static const struct usb_device_id rtw_8851bu_id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb851, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8851bu_info }, + /* D-Link AX9U rev. A1 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x332a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8851bu_info }, + /* TP-Link Archer TX10UB Nano */ + { USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8851bu_info }, + /* Edimax EW-7611UXB */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xe611, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8851bu_info }, + {}, +}; +MODULE_DEVICE_TABLE(usb, rtw_8851bu_id_table); + +static struct usb_driver rtw_8851bu_driver = { + .name = KBUILD_MODNAME, + .id_table = rtw_8851bu_id_table, + .probe = rtw89_usb_probe, + .disconnect = rtw89_usb_disconnect, +}; +module_usb_driver(rtw_8851bu_driver); + +MODULE_AUTHOR("Bitterblue Smith "); +MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851BU driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 45dd2253553de..bd3443afc5a7b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -426,6 +426,35 @@ static const struct rtw89_reg_def rtw8852a_dcfo_comp = { R_DCFO_COMP_S0, B_DCFO_COMP_S0_MSK }; +static const struct rtw89_reg_def rtw8852a_nhm_th[RTW89_NHM_TH_NUM] = { + {R_NHM_CFG, B_NHM_TH0_MSK}, + {R_NHM_TH1, B_NHM_TH1_MSK}, + {R_NHM_TH1, B_NHM_TH2_MSK}, + {R_NHM_TH1, B_NHM_TH3_MSK}, + {R_NHM_TH1, B_NHM_TH4_MSK}, + {R_NHM_TH5, B_NHM_TH5_MSK}, + {R_NHM_TH5, B_NHM_TH6_MSK}, + {R_NHM_TH5, B_NHM_TH7_MSK}, + {R_NHM_TH5, B_NHM_TH8_MSK}, + {R_NHM_TH9, B_NHM_TH9_MSK}, + {R_NHM_TH9, B_NHM_TH10_MSK}, +}; + +static const struct rtw89_reg_def rtw8852a_nhm_rpt[RTW89_NHM_RPT_NUM] = { + {R_NHM_CNT0, B_NHM_CNT0_MSK}, + {R_NHM_CNT0, B_NHM_CNT1_MSK}, + {R_NHM_CNT2, B_NHM_CNT2_MSK}, + {R_NHM_CNT2, B_NHM_CNT3_MSK}, + {R_NHM_CNT4, B_NHM_CNT4_MSK}, + {R_NHM_CNT4, B_NHM_CNT5_MSK}, + {R_NHM_CNT6, B_NHM_CNT6_MSK}, + {R_NHM_CNT6, B_NHM_CNT7_MSK}, + {R_NHM_CNT8, B_NHM_CNT8_MSK}, + {R_NHM_CNT8, B_NHM_CNT9_MSK}, + {R_NHM_CNT10, B_NHM_CNT10_MSK}, + {R_NHM_CNT10, B_NHM_CNT11_MSK}, +}; + static const struct rtw89_imr_info rtw8852a_imr_info = { .wdrls_imr_set = B_AX_WDRLS_IMR_SET, .wsec_imr_reg = R_AX_SEC_DEBUG, @@ -483,6 +512,15 @@ static const struct rtw89_rrsr_cfgs rtw8852a_rrsr_cfgs = { .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8852a_rfkill_regs = { + .pinmux = {R_AX_GPIO8_15_FUNC_SEL, + B_AX_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_AX_GPIO_EXT_CTRL + 2, + (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8852a_dig_regs = { .seg0_pd_reg = R_SEG0R_PD, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, @@ -587,8 +625,6 @@ static int rtw8852a_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, return -ENOTSUPP; } - rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); - return 0; } @@ -2071,10 +2107,17 @@ static void rtw8852a_query_ppdu(struct rtw89_dev *rtwdev, { u8 path; u8 *rx_power = phy_ppdu->rssi; + u8 raw; + + if (!status->signal) { + if (phy_ppdu->to_self) + raw = ewma_rssi_read(&rtwdev->phystat.bcn_rssi); + else + raw = max(rx_power[RF_PATH_A], rx_power[RF_PATH_B]); + + status->signal = RTW89_RSSI_RAW_TO_DBM(raw); + } - if (!status->signal) - status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], - rx_power[RF_PATH_B])); for (path = 0; path < rtwdev->chip->rf_path_num; path++) { status->chains |= BIT(path); status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); @@ -2128,11 +2171,13 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .cfg_txrx_path = NULL, .set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset, .digital_pwr_comp = NULL, + .calc_rx_gain_normal = NULL, .pwr_on_func = NULL, .pwr_off_func = NULL, .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, + .get_ch_dma = rtw89_core_get_ch_dma, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -2142,9 +2187,11 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl, .h2c_ampdu_cmac_tbl = NULL, .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl, + .h2c_punctured_cmac_tbl = NULL, .h2c_default_dmac_tbl = NULL, .h2c_update_beacon = rtw89_fw_h2c_update_beacon, .h2c_ba_cam = rtw89_fw_h2c_ba_cam, + .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update, .btc_set_rfe = rtw8852a_btc_set_rfe, .btc_init_cfg = rtw8852a_btc_init_cfg, @@ -2173,10 +2220,14 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 3500, + .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + .max_eht_mpdu_cap = 0, + .max_tx_agg_num = 128, + .max_rx_agg_num = 64, .dis_2g_40m_ul_ofdma = true, .rsvd_ple_ofst = 0x6f800, - .hfc_param_ini = rtw8852a_hfc_param_ini_pcie, - .dle_mem = rtw8852a_dle_mem_pcie, + .hfc_param_ini = {rtw8852a_hfc_param_ini_pcie, NULL, NULL}, + .dle_mem = {rtw8852a_dle_mem_pcie, NULL, NULL, NULL}, .wde_qempty_acq_grpnum = 16, .wde_qempty_mgq_grpsel = 16, .rf_base_addr = {0xc000, 0xd000}, @@ -2210,6 +2261,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .support_ant_gain = false, .support_tas = false, .support_sar_by_ant = false, + .support_noise = true, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = false, .rx_freq_frome_ie = true, @@ -2226,6 +2278,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, @@ -2272,20 +2325,24 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .cfo_hw_comp = false, .dcfo_comp = &rtw8852a_dcfo_comp, .dcfo_comp_sft = 10, + .nhm_report = &rtw8852a_nhm_rpt, + .nhm_th = &rtw8852a_nhm_th, .imr_info = &rtw8852a_imr_info, .imr_dmac_table = NULL, .imr_cmac_table = NULL, .rrsr_cfgs = &rtw8852a_rrsr_cfgs, .bss_clr_vld = {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0}, .bss_clr_map_reg = R_BSS_CLR_MAP, - .rfkill_init = {}, - .rfkill_get = {}, + .rfkill_init = &rtw8852a_rfkill_regs, + .rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9}, + .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}}, .dma_ch_mask = 0, .edcca_regs = &rtw8852a_edcca_regs, #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8852a, #endif .xtal_info = &rtw8852a_xtal_info, + .default_quirks = 0, }; EXPORT_SYMBOL(rtw8852a_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c index 9db8713ac99be..4633994133185 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c @@ -756,8 +756,8 @@ static void _iqk_rxk_setting(struct rtw89_dev *rtwdev, u8 path) rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_FLTRST, 0x1); rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15_H2, 0x0); udelay(1); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0303); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0000); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0303); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0000); switch (iqk_info->iqk_band[path]) { case RTW89_BAND_2G: @@ -1239,8 +1239,8 @@ static void _iqk_txk_setting(struct rtw89_dev *rtwdev, u8 path) udelay(1); rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0x0041); udelay(1); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0303); - rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0000); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0303); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x0000); switch (iqk_info->iqk_band[path]) { case RTW89_BAND_2G: rtw89_write_rf(rtwdev, path, RR_XALNA2, RR_XALNA2_SW, 0x00); @@ -1403,7 +1403,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, path, iqk_info->iqk_ch[path]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", path, phy, - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->dbcc_en), iqk_info->iqk_band[path] == 0 ? "2G" : iqk_info->iqk_band[path] == 1 ? "5G" : "6G", iqk_info->iqk_ch[path], @@ -1881,8 +1881,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -2736,7 +2736,7 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, MASKBYTE3, 0x6 | val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, dpk->is_dpk_enable && !off ? "enable" : "disable"); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_track(struct rtw89_dev *rtwdev) diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c index 1bfade7e7e1b7..9e05e831569d2 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c @@ -29,6 +29,8 @@ static const struct rtw89_pci_info rtw8852a_pci_info = { .rx_ring_eq_is_full = false, .check_rx_tag = false, .no_rxbd_fs = false, + .group_bd_addr = false, + .rpp_fmt_size = sizeof(struct rtw89_pci_rpp_fmt), .init_cfg_reg = R_AX_PCIE_INIT_CFG1, .txhci_en_bit = B_AX_TXHCI_EN, @@ -56,6 +58,7 @@ static const struct rtw89_pci_info rtw8852a_pci_info = { .ltr_set = rtw89_pci_ltr_set, .fill_txaddr_info = rtw89_pci_fill_txaddr_info, + .parse_rpp = rtw89_pci_parse_rpp, .config_intr_mask = rtw89_pci_config_intr_mask, .enable_intr = rtw89_pci_enable_intr, .disable_intr = rtw89_pci_disable_intr, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index f3ac547f08e76..811991f3f0601 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -49,6 +49,48 @@ static const struct rtw89_hfc_param_ini rtw8852b_hfc_param_ini_pcie[] = { [RTW89_QTA_INVALID] = {NULL}, }; +static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_usb[] = { + {18, 152, grp_0}, /* ACH 0 */ + {18, 152, grp_0}, /* ACH 1 */ + {18, 152, grp_0}, /* ACH 2 */ + {18, 152, grp_0}, /* ACH 3 */ + {0, 0, grp_0}, /* ACH 4 */ + {0, 0, grp_0}, /* ACH 5 */ + {0, 0, grp_0}, /* ACH 6 */ + {0, 0, grp_0}, /* ACH 7 */ + {18, 152, grp_0}, /* B0MGQ */ + {18, 152, grp_0}, /* B0HIQ */ + {0, 0, grp_0}, /* B1MGQ */ + {0, 0, grp_0}, /* B1HIQ */ + {0, 0, 0} /* FWCMDQ */ +}; + +static const struct rtw89_hfc_pub_cfg rtw8852b_hfc_pubcfg_usb = { + 152, /* Group 0 */ + 0, /* Group 1 */ + 152, /* Public Max */ + 0 /* WP threshold */ +}; + +static const struct rtw89_hfc_prec_cfg rtw8852b_hfc_preccfg_usb = { + 9, /* CH 0-11 pre-cost */ + 32, /* H2C pre-cost */ + 64, /* WP CH 0-7 pre-cost */ + 24, /* WP CH 8-11 pre-cost */ + 1, /* CH 0-11 full condition */ + 1, /* H2C full condition */ + 1, /* WP CH 0-7 full condition */ + 1, /* WP CH 8-11 full condition */ +}; + +static const struct rtw89_hfc_param_ini rtw8852b_hfc_param_ini_usb[] = { + [RTW89_QTA_SCC] = {rtw8852b_hfc_chcfg_usb, &rtw8852b_hfc_pubcfg_usb, + &rtw8852b_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_DLFW] = {NULL, NULL, + &rtw8852b_hfc_preccfg_usb, RTW89_HCIFC_STF}, + [RTW89_QTA_INVALID] = {NULL}, +}; + static const struct rtw89_dle_mem rtw8852b_dle_mem_pcie[] = { [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size7, &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt7, @@ -66,6 +108,19 @@ static const struct rtw89_dle_mem rtw8852b_dle_mem_pcie[] = { NULL}, }; +static const struct rtw89_dle_mem rtw8852b_dle_mem_usb3[] = { + [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size25, + &rtw89_mac_size.ple_size33, &rtw89_mac_size.wde_qt25, + &rtw89_mac_size.wde_qt25, &rtw89_mac_size.ple_qt74, + &rtw89_mac_size.ple_qt75}, + [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9, + &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4, + &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13, + &rtw89_mac_size.ple_qt13}, + [RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL, + NULL}, +}; + static const u32 rtw8852b_h2c_regs[RTW89_H2CREG_MAX] = { R_AX_H2CREG_DATA0, R_AX_H2CREG_DATA1, R_AX_H2CREG_DATA2, R_AX_H2CREG_DATA3 @@ -150,6 +205,15 @@ static const struct rtw89_rrsr_cfgs rtw8852b_rrsr_cfgs = { .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8852b_rfkill_regs = { + .pinmux = {R_AX_GPIO8_15_FUNC_SEL, + B_AX_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_AX_GPIO_EXT_CTRL + 2, + (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8852b_dig_regs = { .seg0_pd_reg = R_SEG0R_PD_V1, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, @@ -249,6 +313,27 @@ static void rtw8852b_pwr_sps_ana(struct rtw89_dev *rtwdev) rtw89_write16(rtwdev, R_AX_SPS_ANA_ON_CTRL2, RTL8852B_RFE_05_SPS_ANA); } +static void rtw8852b_pwr_sps_dig_off(struct rtw89_dev *rtwdev) +{ + struct rtw89_efuse *efuse = &rtwdev->efuse; + + if (efuse->rfe_type == 0x5) { + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, + B_AX_C1_L1_MASK, 0x1); + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, + B_AX_C2_L1_MASK, 0x1); + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, + B_AX_C3_L1_MASK, 0x2); + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, + B_AX_R1_L1_MASK, 0x1); + } else { + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, + B_AX_C1_L1_MASK, 0x1); + rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, + B_AX_C3_L1_MASK, 0x3); + } +} + static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev) { u32 val32; @@ -274,8 +359,7 @@ static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev) if (ret) return ret; - rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, B_AX_C1_L1_MASK, 0x1); - rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_OFF_CTRL0, B_AX_C3_L1_MASK, 0x3); + rtw8852b_pwr_sps_dig_off(rtwdev); rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON); rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC); @@ -290,7 +374,8 @@ static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); - rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); rtw89_write32_set(rtwdev, R_AX_SYS_ADIE_PAD_PWR_CTRL, B_AX_SYM_PADPDN_WL_PTA_1P3); @@ -352,7 +437,7 @@ static int rtw8852b_pwr_on_func(struct rtw89_dev *rtwdev) rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, B_AX_VOL_L1_MASK, 0x9); rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, B_AX_VREFPFM_L_MASK, 0xA); - if (rtwdev->hal.cv == CHIP_CBV) { + if (rtwdev->hal.cv == CHIP_CBV && rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) { rtw89_write32_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); rtw89_write16_mask(rtwdev, R_AX_HCI_LDO_CTRL, B_AX_R_AX_VADJ_MASK, 0xA); rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); @@ -434,10 +519,22 @@ static int rtw8852b_pwr_off_func(struct rtw89_dev *rtwdev) if (ret) return ret; - rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) + rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_EDSWR); + rtw89_write32_set(rtwdev, R_AX_SYS_SWR_CTRL1, B_AX_SYM_CTRL_SPS_PWMFREQ); rtw89_write32_mask(rtwdev, R_AX_SPS_DIG_ON_CTRL0, B_AX_REG_ZCDC_H_MASK, 0x3); - rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + + if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE) { + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + } else if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) { + val32 = rtw89_read32(rtwdev, R_AX_SYS_PW_CTRL); + val32 &= ~B_AX_AFSM_PCIE_SUS_EN; + val32 |= B_AX_AFSM_WLSUS_EN; + rtw89_write32(rtwdev, R_AX_SYS_PW_CTRL, val32); + } return 0; } @@ -551,8 +648,11 @@ static void rtw8852b_set_channel_help(struct rtw89_dev *rtwdev, bool enter, static void rtw8852b_rfk_init(struct rtw89_dev *rtwdev) { + struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; + rtwdev->is_tssi_mode[RF_PATH_A] = false; rtwdev->is_tssi_mode[RF_PATH_B] = false; + memset(rfk_mcc, 0, sizeof(*rfk_mcc)); rtw8852b_dpk_init(rtwdev); rtw8852b_rck(rtwdev); @@ -566,6 +666,7 @@ static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + rtw8852b_mcc_get_ch_info(rtwdev, phy_idx); rtw89_btc_ntfy_conn_rfk(rtwdev, true); rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx); @@ -576,6 +677,7 @@ static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev, rtw8852b_dpk(rtwdev, phy_idx, chanctx_idx); rtw89_btc_ntfy_conn_rfk(rtwdev, false); + rtw89_fw_h2c_rf_ntfy_mcc(rtwdev); } static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev, @@ -755,11 +857,13 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset, .digital_pwr_comp = NULL, + .calc_rx_gain_normal = NULL, .pwr_on_func = rtw8852b_pwr_on_func, .pwr_off_func = rtw8852b_pwr_off_func, .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, + .get_ch_dma = rtw89_core_get_ch_dma, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -769,9 +873,11 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl, .h2c_ampdu_cmac_tbl = NULL, .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl, + .h2c_punctured_cmac_tbl = NULL, .h2c_default_dmac_tbl = NULL, .h2c_update_beacon = rtw89_fw_h2c_update_beacon, .h2c_ba_cam = rtw89_fw_h2c_ba_cam, + .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update, .btc_set_rfe = rtw8852b_btc_set_rfe, .btc_init_cfg = rtw8852bx_btc_init_cfg, @@ -784,6 +890,10 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .btc_set_policy = rtw89_btc_set_policy_v1, }; +static const struct rtw89_chanctx_listener rtw8852b_chanctx_listener = { + .callbacks[RTW89_CHANCTX_CALLBACK_RFK] = rtw8852b_rfk_chanctx_cb, +}; + #ifdef CONFIG_PM static const struct wiphy_wowlan_support rtw_wowlan_stub_8852b = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, @@ -809,10 +919,19 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .small_fifo_size = true, .dle_scc_rsvd_size = 98304, .max_amsdu_limit = 5000, + .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + .max_eht_mpdu_cap = 0, + .max_tx_agg_num = 128, + .max_rx_agg_num = 64, .dis_2g_40m_ul_ofdma = true, .rsvd_ple_ofst = 0x2f800, - .hfc_param_ini = rtw8852b_hfc_param_ini_pcie, - .dle_mem = rtw8852b_dle_mem_pcie, + .hfc_param_ini = {rtw8852b_hfc_param_ini_pcie, + rtw8852b_hfc_param_ini_usb, + NULL}, + .dle_mem = {rtw8852b_dle_mem_pcie, + rtw8852b_dle_mem_usb3, + rtw8852b_dle_mem_usb3, + NULL}, .wde_qempty_acq_grpnum = 4, .wde_qempty_mgq_grpsel = 4, .rf_base_addr = {0xe000, 0xf000}, @@ -827,6 +946,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .nctl_post_table = NULL, .dflt_parms = &rtw89_8852b_dflt_parms, .rfe_parms_conf = NULL, + .chanctx_listener = &rtw8852b_chanctx_listener, .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, @@ -835,7 +955,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .tssi_dbw_table = NULL, .support_macid_num = RTW89_MAX_MAC_ID_NUM, .support_link_num = 0, - .support_chanctx_num = 0, + .support_chanctx_num = 2, .support_rnr = false, .support_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), @@ -846,6 +966,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .support_ant_gain = true, .support_tas = false, .support_sar_by_ant = true, + .support_noise = false, .ul_tb_waveform_ctrl = true, .ul_tb_pwr_diff = false, .rx_freq_frome_ie = true, @@ -862,6 +983,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, @@ -908,15 +1030,17 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .cfo_hw_comp = true, .dcfo_comp = &rtw8852b_dcfo_comp, .dcfo_comp_sft = 10, + .nhm_report = NULL, + .nhm_th = NULL, .imr_info = &rtw8852b_imr_info, .imr_dmac_table = NULL, .imr_cmac_table = NULL, .rrsr_cfgs = &rtw8852b_rrsr_cfgs, .bss_clr_vld = {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0}, .bss_clr_map_reg = R_BSS_CLR_MAP_V1, - .rfkill_init = {R_AX_GPIO_EXT_CTRL + 2, - (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, 0x0}, + .rfkill_init = &rtw8852b_rfkill_regs, .rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9}, + .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}}, .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) | BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) | BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI), @@ -925,6 +1049,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .wowlan_stub = &rtw_wowlan_stub_8852b, #endif .xtal_info = NULL, + .default_quirks = 0, }; EXPORT_SYMBOL(rtw8852b_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c index 0cf03f18cbb1a..65b839323e3e3 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c @@ -172,14 +172,6 @@ static const struct rtw89_reg3_def rtw8852bx_btc_preagc_dis_defs[] = { static DECLARE_PHY_REG3_TBL(rtw8852bx_btc_preagc_dis_defs); -static void rtw8852be_efuse_parsing(struct rtw89_efuse *efuse, - struct rtw8852bx_efuse *map) -{ - ether_addr_copy(efuse->addr, map->e.mac_addr); - efuse->rfe_type = map->rfe_type; - efuse->xtal_cap = map->xtal_k; -} - static void rtw8852bx_efuse_parsing_tssi(struct rtw89_dev *rtwdev, struct rtw8852bx_efuse *map) { @@ -261,13 +253,17 @@ static int __rtw8852bx_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, switch (rtwdev->hci.type) { case RTW89_HCI_TYPE_PCIE: - rtw8852be_efuse_parsing(efuse, map); + ether_addr_copy(efuse->addr, map->e.mac_addr); + break; + case RTW89_HCI_TYPE_USB: + ether_addr_copy(efuse->addr, map->u.mac_addr); break; default: return -EOPNOTSUPP; } - rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; return 0; } @@ -1749,11 +1745,15 @@ static void __rtw8852bx_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) struct rtw89_hal *hal = &rtwdev->hal; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); enum rtw89_rf_path_bit rx_path = hal->antenna_rx ? hal->antenna_rx : RF_AB; + u8 rx_nss = rtwdev->hal.rx_nss; + + if (rx_path != RF_AB) + rx_nss = 1; rtw8852bx_bb_ctrl_rx_path(rtwdev, rx_path, chan); rtw8852bx_bb_ctrl_rf_mode_rx_path(rtwdev, rx_path); - if (rtwdev->hal.rx_nss == 1) { + if (rx_nss == 1) { rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c index fbf82d42687ba..70b1515c00fa5 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2022 Realtek Corporation */ +#include "chan.h" #include "coex.h" #include "debug.h" #include "mac.h" @@ -1145,19 +1146,19 @@ static void _lok_res_table(struct rtw89_dev *rtwdev, u8 path, u8 ibias) static bool _lok_finetune_check(struct rtw89_dev *rtwdev, u8 path) { + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + u8 ch = rfk_mcc->table_idx; bool is_fail1, is_fail2; u32 vbuff_i; u32 vbuff_q; u32 core_i; u32 core_q; u32 tmp; - u8 ch; tmp = rtw89_read_rf(rtwdev, path, RR_TXMO, RFREG_MASK); core_i = FIELD_GET(RR_TXMO_COI, tmp); core_q = FIELD_GET(RR_TXMO_COQ, tmp); - ch = (iqk_info->iqk_times / 2) % RTW89_IQK_CHS_NR; if (core_i < 0x2 || core_i > 0x1d || core_q < 0x2 || core_q > 0x1d) is_fail1 = true; @@ -1386,26 +1387,11 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, u enum rtw89_chanctx_idx chanctx_idx) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx); + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; + u8 idx = rfk_mcc->table_idx; u32 reg_rf18; u32 reg_35c; - u8 idx; - u8 get_empty_table = false; - - for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) { - if (iqk_info->iqk_mcc_ch[idx][path] == 0) { - get_empty_table = true; - break; - } - } - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (1)idx = %x\n", idx); - - if (!get_empty_table) { - idx = iqk_info->iqk_table_idx[path] + 1; - if (idx > 1) - idx = 0; - } - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (2)idx = %x\n", idx); reg_rf18 = rtw89_read_rf(rtwdev, path, RR_CFGCH, RFREG_MASK); reg_35c = rtw89_phy_read32_mask(rtwdev, R_CIRST, B_CIRST_SYN); @@ -1506,11 +1492,10 @@ static void _iqk_afebb_restore(struct rtw89_dev *rtwdev, static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path) { - struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; - u8 idx; + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + u8 idx = rfk_mcc->table_idx; - idx = iqk_info->iqk_table_idx[path]; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (3)idx = %x\n", idx); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] idx = %x\n", idx); rtw89_phy_write32_mask(rtwdev, R_COEF_SEL + (path << 8), B_COEF_SEL_IQC, idx); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_G3, idx); @@ -1711,7 +1696,7 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, bool o MASKBYTE3, _dpk_order_convert(rtwdev) << 1 | val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, dpk->is_dpk_enable && !off ? "enable" : "disable"); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, @@ -1778,8 +1763,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -4179,3 +4164,49 @@ void rtw8852b_set_channel_rf(struct rtw89_dev *rtwdev, rtw8852b_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type, chan->band_width); } + +void rtw8852b_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + const struct rtw89_chan *chan = rtw89_mgnt_chan_get(rtwdev, 0); + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V0] = {}; + u8 idx; + + for (idx = 0; idx < ARRAY_SIZE(desc); idx++) { + struct rtw89_rfk_chan_desc *p = &desc[idx]; + + p->ch = rfk_mcc->ch[idx]; + + p->has_band = true; + p->band = rfk_mcc->band[idx]; + } + + idx = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan); + + rfk_mcc->ch[idx] = chan->channel; + rfk_mcc->band[idx] = chan->band_type; + rfk_mcc->table_idx = idx; +} + +void rtw8852b_rfk_chanctx_cb(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_state state) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 path; + + switch (state) { + case RTW89_CHANCTX_STATE_MCC_START: + dpk->is_dpk_enable = false; + for (path = 0; path < RTW8852B_DPK_RF_PATH; path++) + _dpk_onoff(rtwdev, path, false); + break; + case RTW89_CHANCTX_STATE_MCC_STOP: + dpk->is_dpk_enable = true; + for (path = 0; path < RTW8852B_DPK_RF_PATH; path++) + _dpk_onoff(rtwdev, path, false); + rtw8852b_dpk(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); + break; + default: + break; + } +} diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.h index c31ba446e6e09..5fae980d5e2c2 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.h @@ -27,5 +27,8 @@ void rtw8852b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, void rtw8852b_set_channel_rf(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx); +void rtw8852b_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw8852b_rfk_chanctx_cb(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_state state); #endif diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852be.c b/drivers/net/wireless/realtek/rtw89/rtw8852be.c index 8f7676a0a89e3..12db0d0be5479 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852be.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852be.c @@ -29,6 +29,8 @@ static const struct rtw89_pci_info rtw8852b_pci_info = { .rx_ring_eq_is_full = false, .check_rx_tag = false, .no_rxbd_fs = false, + .group_bd_addr = false, + .rpp_fmt_size = sizeof(struct rtw89_pci_rpp_fmt), .init_cfg_reg = R_AX_PCIE_INIT_CFG1, .txhci_en_bit = B_AX_TXHCI_EN, @@ -58,6 +60,7 @@ static const struct rtw89_pci_info rtw8852b_pci_info = { .ltr_set = rtw89_pci_ltr_set, .fill_txaddr_info = rtw89_pci_fill_txaddr_info, + .parse_rpp = rtw89_pci_parse_rpp, .config_intr_mask = rtw89_pci_config_intr_mask, .enable_intr = rtw89_pci_enable_intr, .disable_intr = rtw89_pci_disable_intr, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index e2172ce8d4f55..294e3a4aec0b6 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -148,6 +148,15 @@ static const struct rtw89_rrsr_cfgs rtw8852bt_rrsr_cfgs = { .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8852bt_rfkill_regs = { + .pinmux = {R_AX_GPIO8_15_FUNC_SEL, + B_AX_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_AX_GPIO_EXT_CTRL + 2, + (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8852bt_dig_regs = { .seg0_pd_reg = R_SEG0R_PD_V1, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, @@ -524,8 +533,11 @@ static void rtw8852bt_set_channel_help(struct rtw89_dev *rtwdev, bool enter, static void rtw8852bt_rfk_init(struct rtw89_dev *rtwdev) { + struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; + rtwdev->is_tssi_mode[RF_PATH_A] = false; rtwdev->is_tssi_mode[RF_PATH_B] = false; + memset(rfk_mcc, 0, sizeof(*rfk_mcc)); rtw8852bt_dpk_init(rtwdev); rtw8852bt_rck(rtwdev); @@ -539,6 +551,7 @@ static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx; enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx; + rtw8852bt_mcc_get_ch_info(rtwdev, phy_idx); rtw89_btc_ntfy_conn_rfk(rtwdev, true); rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx); @@ -549,6 +562,7 @@ static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev, rtw8852bt_dpk(rtwdev, phy_idx, chanctx_idx); rtw89_btc_ntfy_conn_rfk(rtwdev, false); + rtw89_fw_h2c_rf_ntfy_mcc(rtwdev); } static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev, @@ -689,11 +703,13 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset, .digital_pwr_comp = NULL, + .calc_rx_gain_normal = NULL, .pwr_on_func = rtw8852bt_pwr_on_func, .pwr_off_func = rtw8852bt_pwr_off_func, .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, + .get_ch_dma = rtw89_core_get_ch_dma, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, .mac_cfg_gnt = rtw89_mac_cfg_gnt, .stop_sch_tx = rtw89_mac_stop_sch_tx, @@ -703,9 +719,11 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl, .h2c_ampdu_cmac_tbl = NULL, .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl, + .h2c_punctured_cmac_tbl = NULL, .h2c_default_dmac_tbl = NULL, .h2c_update_beacon = rtw89_fw_h2c_update_beacon, .h2c_ba_cam = rtw89_fw_h2c_ba_cam, + .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update, .btc_set_rfe = rtw8852bt_btc_set_rfe, .btc_init_cfg = rtw8852bx_btc_init_cfg, @@ -718,6 +736,10 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = { .btc_set_policy = rtw89_btc_set_policy_v1, }; +static const struct rtw89_chanctx_listener rtw8852bt_chanctx_listener = { + .callbacks[RTW89_CHANCTX_CALLBACK_RFK] = rtw8852bt_rfk_chanctx_cb, +}; + #ifdef CONFIG_PM static const struct wiphy_wowlan_support rtw_wowlan_stub_8852bt = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, @@ -743,10 +765,14 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .small_fifo_size = true, .dle_scc_rsvd_size = 98304, .max_amsdu_limit = 5000, + .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + .max_eht_mpdu_cap = 0, + .max_tx_agg_num = 128, + .max_rx_agg_num = 64, .dis_2g_40m_ul_ofdma = true, .rsvd_ple_ofst = 0x6f800, - .hfc_param_ini = rtw8852bt_hfc_param_ini_pcie, - .dle_mem = rtw8852bt_dle_mem_pcie, + .hfc_param_ini = {rtw8852bt_hfc_param_ini_pcie, NULL, NULL}, + .dle_mem = {rtw8852bt_dle_mem_pcie, NULL, NULL, NULL}, .wde_qempty_acq_grpnum = 4, .wde_qempty_mgq_grpsel = 4, .rf_base_addr = {0xe000, 0xf000}, @@ -760,6 +786,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .nctl_post_table = NULL, .dflt_parms = NULL, .rfe_parms_conf = NULL, + .chanctx_listener = &rtw8852bt_chanctx_listener, .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, @@ -768,7 +795,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .tssi_dbw_table = NULL, .support_macid_num = RTW89_MAX_MAC_ID_NUM, .support_link_num = 0, - .support_chanctx_num = 1, + .support_chanctx_num = 2, .support_rnr = false, .support_bands = BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ), @@ -795,6 +822,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .bacam_num = 2, .bacam_dynamic_num = 4, .bacam_ver = RTW89_BACAM_V0, + .addrcam_ver = 0, .ppdu_max_usr = 4, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, @@ -847,6 +875,9 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .rrsr_cfgs = &rtw8852bt_rrsr_cfgs, .bss_clr_vld = {R_BSS_CLR_MAP_V1, B_BSS_CLR_MAP_VLD0}, .bss_clr_map_reg = R_BSS_CLR_MAP_V1, + .rfkill_init = &rtw8852bt_rfkill_regs, + .rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9}, + .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}}, .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) | BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) | BIT(RTW89_DMA_B1MG) | BIT(RTW89_DMA_B1HI), @@ -855,6 +886,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .wowlan_stub = &rtw_wowlan_stub_8852bt, #endif .xtal_info = NULL, + .default_quirks = 0, }; EXPORT_SYMBOL(rtw8852bt_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c index 6e6889eea9a0d..961b26ba2d3c4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.c @@ -2,6 +2,7 @@ /* Copyright(c) 2024 Realtek Corporation */ +#include "chan.h" #include "coex.h" #include "debug.h" #include "fw.h" @@ -1529,26 +1530,11 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, u enum rtw89_chanctx_idx chanctx_idx) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx); + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; struct rtw89_iqk_info *iqk_info = &rtwdev->iqk; - u8 get_empty_table = false; + u8 idx = rfk_mcc->table_idx; u32 reg_rf18; u32 reg_35c; - u8 idx; - - for (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) { - if (iqk_info->iqk_mcc_ch[idx][path] == 0) { - get_empty_table = true; - break; - } - } - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (1)idx = %x\n", idx); - - if (!get_empty_table) { - idx = iqk_info->iqk_table_idx[path] + 1; - if (idx > 1) - idx = 0; - } - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] (2)idx = %x\n", idx); reg_rf18 = rtw89_read_rf(rtwdev, path, RR_CFGCH, RFREG_MASK); reg_35c = rtw89_phy_read32_mask(rtwdev, R_CIRST, B_CIRST_SYN); @@ -1640,7 +1626,8 @@ static void _iqk_afebb_restore(struct rtw89_dev *rtwdev, static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path) { - u8 idx = 0; + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + u8 idx = rfk_mcc->table_idx; rtw89_phy_write32_mask(rtwdev, R_COEF_SEL + (path << 8), 0x00000001, idx); rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), 0x00000008, idx); @@ -1812,22 +1799,14 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, bool o { struct rtw89_dpk_info *dpk = &rtwdev->dpk; u8 val, kidx = dpk->cur_idx[path]; - bool off_reverse; val = dpk->is_dpk_enable && !off && dpk->bp[path][kidx].path_ok; - if (off) - off_reverse = false; - else - off_reverse = true; - - val = dpk->is_dpk_enable & off_reverse & dpk->bp[path][kidx].path_ok; - rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), BIT(24), val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, str_enable_disable(dpk->is_dpk_enable & off_reverse)); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, @@ -1896,8 +1875,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -4252,3 +4231,49 @@ void rtw8852bt_set_channel_rf(struct rtw89_dev *rtwdev, rtw8852bt_ctrl_bw_ch(rtwdev, phy_idx, chan->channel, chan->band_type, chan->band_width); } + +void rtw8852bt_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + const struct rtw89_chan *chan = rtw89_mgnt_chan_get(rtwdev, 0); + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V0] = {}; + u8 idx; + + for (idx = 0; idx < ARRAY_SIZE(desc); idx++) { + struct rtw89_rfk_chan_desc *p = &desc[idx]; + + p->ch = rfk_mcc->ch[idx]; + + p->has_band = true; + p->band = rfk_mcc->band[idx]; + } + + idx = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan); + + rfk_mcc->ch[idx] = chan->channel; + rfk_mcc->band[idx] = chan->band_type; + rfk_mcc->table_idx = idx; +} + +void rtw8852bt_rfk_chanctx_cb(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_state state) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 path; + + switch (state) { + case RTW89_CHANCTX_STATE_MCC_START: + dpk->is_dpk_enable = false; + for (path = 0; path < RTW8852BT_SS; path++) + _dpk_onoff(rtwdev, path, false); + break; + case RTW89_CHANCTX_STATE_MCC_STOP: + dpk->is_dpk_enable = true; + for (path = 0; path < RTW8852BT_SS; path++) + _dpk_onoff(rtwdev, path, false); + rtw8852bt_dpk(rtwdev, RTW89_PHY_0, RTW89_CHANCTX_0); + break; + default: + break; + } +} diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h index e34560b4905f8..a663bbda40758 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt_rfk.h @@ -27,5 +27,8 @@ void rtw8852bt_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, void rtw8852bt_set_channel_rf(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx); +void rtw8852bt_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw8852bt_rfk_chanctx_cb(struct rtw89_dev *rtwdev, + enum rtw89_chanctx_state state); #endif diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c index 642ab20e9d06b..8c995aa953251 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bte.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bte.c @@ -35,6 +35,8 @@ static const struct rtw89_pci_info rtw8852bt_pci_info = { .rx_ring_eq_is_full = false, .check_rx_tag = false, .no_rxbd_fs = false, + .group_bd_addr = false, + .rpp_fmt_size = sizeof(struct rtw89_pci_rpp_fmt), .init_cfg_reg = R_AX_PCIE_INIT_CFG1, .txhci_en_bit = B_AX_TXHCI_EN, @@ -64,6 +66,7 @@ static const struct rtw89_pci_info rtw8852bt_pci_info = { .ltr_set = rtw89_pci_ltr_set, .fill_txaddr_info = rtw89_pci_fill_txaddr_info, + .parse_rpp = rtw89_pci_parse_rpp, .config_intr_mask = rtw89_pci_config_intr_mask, .enable_intr = rtw89_pci_enable_intr, .disable_intr = rtw89_pci_disable_intr, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c new file mode 100644 index 0000000000000..0694272f7ffae --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2025 Realtek Corporation + */ + +#include +#include +#include "rtw8852b.h" +#include "usb.h" + +static const struct rtw89_driver_info rtw89_8852bu_info = { + .chip = &rtw8852b_chip_info, + .variant = NULL, + .quirks = NULL, +}; + +static const struct usb_device_id rtw_8852bu_id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb832, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb83a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb852, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb85a, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xa85b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x3428, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1a62, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x0db0, 0x6931, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3327, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0100, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0108, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x6822, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&rtw89_8852bu_info }, + {}, +}; +MODULE_DEVICE_TABLE(usb, rtw_8852bu_id_table); + +static struct usb_driver rtw_8852bu_driver = { + .name = KBUILD_MODNAME, + .id_table = rtw_8852bu_id_table, + .probe = rtw89_usb_probe, + .disconnect = rtw89_usb_disconnect, +}; +module_usb_driver(rtw_8852bu_driver); + +MODULE_AUTHOR("Bitterblue Smith "); +MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852BU driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 575ebaf723729..61dbd9cdf5767 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -148,6 +148,15 @@ static const struct rtw89_rrsr_cfgs rtw8852c_rrsr_cfgs = { .rsc = {R_AX_PTCL_RRSR1, B_AX_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8852c_rfkill_regs = { + .pinmux = {R_AX_GPIO8_15_FUNC_SEL, + B_AX_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_AX_GPIO_EXT_CTRL + 2, + (B_AX_GPIO_MOD_9 | B_AX_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8852c_dig_regs = { .seg0_pd_reg = R_SEG0R_PD, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, @@ -508,8 +517,6 @@ static int rtw8852c_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map, return -ENOTSUPP; } - rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); - return 0; } @@ -578,12 +585,16 @@ static void rtw8852c_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev, } } +#define __THM_MASK_SIGN BIT(0) +#define __THM_MASK_3BITS GENMASK(3, 1) +#define __THM_MASK_VAL8 BIT(4) + static void rtw8852c_thermal_trim(struct rtw89_dev *rtwdev) { -#define __thm_setting(raw) \ -({ \ - u8 __v = (raw); \ - ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \ +#define __thm_setting(raw) \ +({ \ + u8 __v = (raw); \ + ((__v & __THM_MASK_SIGN) << 3) | ((__v & __THM_MASK_3BITS) >> 1); \ }) struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; u8 i, val; @@ -2406,10 +2417,20 @@ static void rtw8852c_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en, static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) { struct rtw89_hal *hal = &rtwdev->hal; + u8 nrx_path = RF_PATH_AB; + u8 rx_nss = hal->rx_nss; + + if (hal->antenna_rx == RF_A) + nrx_path = RF_PATH_A; + else if (hal->antenna_rx == RF_B) + nrx_path = RF_PATH_B; + + if (nrx_path != RF_PATH_AB) + rx_nss = 1; - rtw8852c_bb_cfg_rx_path(rtwdev, RF_PATH_AB); + rtw8852c_bb_cfg_rx_path(rtwdev, nrx_path); - if (hal->rx_nss == 1) { + if (rx_nss == 1) { rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); @@ -2424,13 +2445,26 @@ static void rtw8852c_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) static u8 rtw8852c_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) { + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + s8 comp = 0; + u8 val; + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0); rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); fsleep(200); - return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); + val = rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); + + if (info->pg_thermal_trim) { + u8 trim = info->thermal_trim[rf_path]; + + if (trim & __THM_MASK_VAL8) + comp = 8 * (trim & __THM_MASK_SIGN ? -1 : 1); + } + + return val + comp; } static void rtw8852c_btc_set_rfe(struct rtw89_dev *rtwdev) @@ -2948,11 +2982,13 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .cfg_txrx_path = rtw8852c_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, .digital_pwr_comp = NULL, + .calc_rx_gain_normal = NULL, .pwr_on_func = rtw8852c_pwr_on_func, .pwr_off_func = rtw8852c_pwr_off_func, .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc_v1, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1, + .get_ch_dma = rtw89_core_get_ch_dma, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1, .mac_cfg_gnt = rtw89_mac_cfg_gnt_v1, .stop_sch_tx = rtw89_mac_stop_sch_tx_v1, @@ -2962,9 +2998,11 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl, .h2c_ampdu_cmac_tbl = NULL, .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl, + .h2c_punctured_cmac_tbl = NULL, .h2c_default_dmac_tbl = NULL, .h2c_update_beacon = rtw89_fw_h2c_update_beacon, .h2c_ba_cam = rtw89_fw_h2c_ba_cam, + .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update, .btc_set_rfe = rtw8852c_btc_set_rfe, .btc_init_cfg = rtw8852c_btc_init_cfg, @@ -2993,10 +3031,14 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 8000, + .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + .max_eht_mpdu_cap = 0, + .max_tx_agg_num = 128, + .max_rx_agg_num = 64, .dis_2g_40m_ul_ofdma = false, .rsvd_ple_ofst = 0x6f800, - .hfc_param_ini = rtw8852c_hfc_param_ini_pcie, - .dle_mem = rtw8852c_dle_mem_pcie, + .hfc_param_ini = {rtw8852c_hfc_param_ini_pcie, NULL, NULL}, + .dle_mem = {rtw8852c_dle_mem_pcie, NULL, NULL, NULL}, .wde_qempty_acq_grpnum = 16, .wde_qempty_mgq_grpsel = 16, .rf_base_addr = {0xe000, 0xf000}, @@ -3033,6 +3075,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .support_ant_gain = true, .support_tas = true, .support_sar_by_ant = true, + .support_noise = false, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = true, .rx_freq_frome_ie = false, @@ -3049,6 +3092,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .bacam_num = 8, .bacam_dynamic_num = 8, .bacam_ver = RTW89_BACAM_V0_EXT, + .addrcam_ver = 0, .ppdu_max_usr = 8, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 1216, @@ -3096,20 +3140,24 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .cfo_hw_comp = false, .dcfo_comp = &rtw8852c_dcfo_comp, .dcfo_comp_sft = 12, + .nhm_report = NULL, + .nhm_th = NULL, .imr_info = &rtw8852c_imr_info, .imr_dmac_table = NULL, .imr_cmac_table = NULL, .rrsr_cfgs = &rtw8852c_rrsr_cfgs, .bss_clr_vld = {R_BSS_CLR_MAP, B_BSS_CLR_MAP_VLD0}, .bss_clr_map_reg = R_BSS_CLR_MAP, - .rfkill_init = {}, - .rfkill_get = {}, + .rfkill_init = &rtw8852c_rfkill_regs, + .rfkill_get = {R_AX_GPIO_EXT_CTRL, B_AX_GPIO_IN_9}, + .btc_sb = {{{R_AX_SCOREBOARD, R_AX_SCOREBOARD},}}, .dma_ch_mask = 0, .edcca_regs = &rtw8852c_edcca_regs, #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8852c, #endif .xtal_info = NULL, + .default_quirks = 0, }; EXPORT_SYMBOL(rtw8852c_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c index b92e2ce4f4adc..cbee484dee302 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c @@ -1344,7 +1344,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev, path, iqk_info->iqk_ch[path]); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", path, phy, - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->dbcc_en), iqk_info->iqk_band[path] == 0 ? "2G" : iqk_info->iqk_band[path] == 1 ? "5G" : "6G", iqk_info->iqk_ch[path], @@ -1920,8 +1920,8 @@ static void _dpk_information(struct rtw89_dev *rtwdev, rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", path, dpk->cur_idx[path], phy, - rtwdev->is_tssi_mode[path] ? "on" : "off", - rtwdev->dbcc_en ? "on" : "off", + str_on_off(rtwdev->is_tssi_mode[path]), + str_on_off(rtwdev->dbcc_en), dpk->bp[path][kidx].band == 0 ? "2G" : dpk->bp[path][kidx].band == 1 ? "5G" : "6G", dpk->bp[path][kidx].ch, @@ -2000,7 +2000,7 @@ static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev, u8 path, bool force) rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n", - path, force ? "on" : "off"); + path, str_on_off(force)); } static void _dpk_kip_restore(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, @@ -2828,7 +2828,7 @@ static void _dpk_onoff(struct rtw89_dev *rtwdev, B_DPD_MEN, val); rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, - kidx, dpk->is_dpk_enable && !off ? "enable" : "disable"); + kidx, str_enable_disable(dpk->is_dpk_enable && !off)); } static void _dpk_track(struct rtw89_dev *rtwdev) @@ -3987,37 +3987,56 @@ static void _ctrl_ch(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, } } +static void _set_rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + enum rtw89_bandwidth bw) +{ + u32 val; + + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1); + rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0xa); + + switch (bw) { + case RTW89_CHANNEL_WIDTH_20: + val = 0x1b; + break; + case RTW89_CHANNEL_WIDTH_40: + val = 0x13; + break; + case RTW89_CHANNEL_WIDTH_80: + val = 0xb; + break; + case RTW89_CHANNEL_WIDTH_160: + default: + val = 0x3; + break; + } + + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, val); + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0); +} + +static void _set_tia_bw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + enum rtw89_bandwidth bw) +{ + if (bw == RTW89_CHANNEL_WIDTH_160) + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x0); + else + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x2); +} + static void _rxbb_bw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, enum rtw89_bandwidth bw) { u8 kpath; u8 path; - u32 val; kpath = _kpath(rtwdev, phy); for (path = 0; path < 2; path++) { if (!(kpath & BIT(path))) continue; - rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x1); - rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_M2, 0xa); - switch (bw) { - case RTW89_CHANNEL_WIDTH_20: - val = 0x1b; - break; - case RTW89_CHANNEL_WIDTH_40: - val = 0x13; - break; - case RTW89_CHANNEL_WIDTH_80: - val = 0xb; - break; - case RTW89_CHANNEL_WIDTH_160: - default: - val = 0x3; - break; - } - rtw89_write_rf(rtwdev, path, RR_LUTWD0, RR_LUTWD0_LB, val); - rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_RTXBW, 0x0); + _set_rxbb_bw(rtwdev, path, bw); + _set_tia_bw(rtwdev, path, bw); } } diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c index 4c7682f1d00c4..150fed189414d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c @@ -38,6 +38,8 @@ static const struct rtw89_pci_info rtw8852c_pci_info = { .rx_ring_eq_is_full = false, .check_rx_tag = false, .no_rxbd_fs = false, + .group_bd_addr = false, + .rpp_fmt_size = sizeof(struct rtw89_pci_rpp_fmt), .init_cfg_reg = R_AX_HAXI_INIT_CFG1, .txhci_en_bit = B_AX_TXHCI_EN_V1, @@ -65,6 +67,7 @@ static const struct rtw89_pci_info rtw8852c_pci_info = { .ltr_set = rtw89_pci_ltr_set_v1, .fill_txaddr_info = rtw89_pci_fill_txaddr_info_v1, + .parse_rpp = rtw89_pci_parse_rpp, .config_intr_mask = rtw89_pci_config_intr_mask_v1, .enable_intr = rtw89_pci_enable_intr_v1, .disable_intr = rtw89_pci_disable_intr_v1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index 69c8abb16bd8c..657662ed42a35 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -167,6 +167,15 @@ static const struct rtw89_rrsr_cfgs rtw8922a_rrsr_cfgs = { .rsc = {R_BE_PTCL_RRSR1, B_BE_RSC_MASK, 2}, }; +static const struct rtw89_rfkill_regs rtw8922a_rfkill_regs = { + .pinmux = {R_BE_GPIO8_15_FUNC_SEL, + B_BE_PINMUX_GPIO9_FUNC_SEL_MASK, + 0xf}, + .mode = {R_BE_GPIO_EXT_CTRL + 2, + (B_BE_GPIO_MOD_9 | B_BE_GPIO_IO_SEL_9) >> 16, + 0x0}, +}; + static const struct rtw89_dig_regs rtw8922a_dig_regs = { .seg0_pd_reg = R_SEG0R_PD_V2, .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, @@ -619,8 +628,6 @@ static int rtw8922a_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map) rtw8922a_efuse_parsing_tssi(rtwdev, map); rtw8922a_efuse_parsing_gain_offset(rtwdev, map); - rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); - return 0; } @@ -1747,6 +1754,32 @@ static int rtw8922a_ctrl_rx_path_tmac(struct rtw89_dev *rtwdev, } #define DIGITAL_PWR_COMP_REG_NUM 22 +static const u32 rtw8922a_digital_pwr_comp_2g_s0_val[][DIGITAL_PWR_COMP_REG_NUM] = { + {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320, + 0x0D05091D, 0x14D50FA0, 0x00000000, 0x01010000, 0x00000101, + 0x01010101, 0x02020201, 0x02010000, 0x03030202, 0x00000303, + 0x03020101, 0x06060504, 0x01010000, 0x06050403, 0x01000606, + 0x05040202, 0x07070706}, + {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320, + 0x0D05091D, 0x14D50FA0, 0x00000000, 0x01010100, 0x00000101, + 0x01000000, 0x01010101, 0x01010000, 0x02020202, 0x00000404, + 0x03020101, 0x04040303, 0x02010000, 0x03030303, 0x00000505, + 0x03030201, 0x05050303}, +}; + +static const u32 rtw8922a_digital_pwr_comp_2g_s1_val[][DIGITAL_PWR_COMP_REG_NUM] = { + {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320, + 0x0D05091D, 0x14D50FA0, 0x01010000, 0x01010101, 0x00000101, + 0x01010100, 0x01010101, 0x01010000, 0x02020202, 0x01000202, + 0x02020101, 0x03030202, 0x02010000, 0x05040403, 0x01000606, + 0x05040302, 0x07070605}, + {0x012C0064, 0x04B00258, 0x00432710, 0x019000A7, 0x06400320, + 0x0D05091D, 0x14D50FA0, 0x00000000, 0x01010100, 0x00000101, + 0x01010000, 0x02020201, 0x02010100, 0x03030202, 0x01000404, + 0x04030201, 0x05050404, 0x01010100, 0x04030303, 0x01000505, + 0x03030101, 0x05050404}, +}; + static const u32 rtw8922a_digital_pwr_comp_val[][DIGITAL_PWR_COMP_REG_NUM] = { {0x012C0096, 0x044C02BC, 0x00322710, 0x015E0096, 0x03C8028A, 0x0BB80708, 0x17701194, 0x02020100, 0x03030303, 0x01000303, @@ -1761,7 +1794,7 @@ static const u32 rtw8922a_digital_pwr_comp_val[][DIGITAL_PWR_COMP_REG_NUM] = { }; static void rtw8922a_set_digital_pwr_comp(struct rtw89_dev *rtwdev, - bool enable, u8 nss, + u8 band, u8 nss, enum rtw89_rf_path path) { static const u32 ltpc_t0[2] = {R_BE_LTPC_T0_PATH0, R_BE_LTPC_T0_PATH1}; @@ -1769,14 +1802,25 @@ static void rtw8922a_set_digital_pwr_comp(struct rtw89_dev *rtwdev, u32 addr, val; u32 i; - if (nss == 1) - digital_pwr_comp = rtw8922a_digital_pwr_comp_val[0]; - else - digital_pwr_comp = rtw8922a_digital_pwr_comp_val[1]; + if (nss == 1) { + if (band == RTW89_BAND_2G) + digital_pwr_comp = path == RF_PATH_A ? + rtw8922a_digital_pwr_comp_2g_s0_val[0] : + rtw8922a_digital_pwr_comp_2g_s1_val[0]; + else + digital_pwr_comp = rtw8922a_digital_pwr_comp_val[0]; + } else { + if (band == RTW89_BAND_2G) + digital_pwr_comp = path == RF_PATH_A ? + rtw8922a_digital_pwr_comp_2g_s0_val[1] : + rtw8922a_digital_pwr_comp_2g_s1_val[1]; + else + digital_pwr_comp = rtw8922a_digital_pwr_comp_val[1]; + } addr = ltpc_t0[path]; for (i = 0; i < DIGITAL_PWR_COMP_REG_NUM; i++, addr += 4) { - val = enable ? digital_pwr_comp[i] : 0; + val = digital_pwr_comp[i]; rtw89_phy_write32(rtwdev, addr, val); } } @@ -1785,7 +1829,7 @@ static void rtw8922a_digital_pwr_comp(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); - bool enable = chan->band_type != RTW89_BAND_2G; + u8 band = chan->band_type; u8 path; if (rtwdev->mlo_dbcc_mode == MLO_1_PLUS_1_1RF) { @@ -1793,10 +1837,10 @@ static void rtw8922a_digital_pwr_comp(struct rtw89_dev *rtwdev, path = RF_PATH_A; else path = RF_PATH_B; - rtw8922a_set_digital_pwr_comp(rtwdev, enable, 1, path); + rtw8922a_set_digital_pwr_comp(rtwdev, band, 1, path); } else { - rtw8922a_set_digital_pwr_comp(rtwdev, enable, 2, RF_PATH_A); - rtw8922a_set_digital_pwr_comp(rtwdev, enable, 2, RF_PATH_B); + rtw8922a_set_digital_pwr_comp(rtwdev, band, 2, RF_PATH_A); + rtw8922a_set_digital_pwr_comp(rtwdev, band, 2, RF_PATH_B); } } @@ -2338,19 +2382,29 @@ static void rtw8922a_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) enum rtw89_band band = chan->band_type; struct rtw89_hal *hal = &rtwdev->hal; u8 ntx_path = RF_PATH_AB; + u8 nrx_path = RF_PATH_AB; u32 tx_en0, tx_en1; + u8 rx_nss = 2; if (hal->antenna_tx == RF_A) ntx_path = RF_PATH_A; else if (hal->antenna_tx == RF_B) ntx_path = RF_PATH_B; + if (hal->antenna_rx == RF_A) + nrx_path = RF_PATH_A; + else if (hal->antenna_rx == RF_B) + nrx_path = RF_PATH_B; + + if (nrx_path != RF_PATH_AB) + rx_nss = 1; + rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, true); if (rtwdev->dbcc_en) rtw8922a_hal_reset(rtwdev, RTW89_PHY_1, RTW89_MAC_1, band, &tx_en1, true); - rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, RF_PATH_AB, 2); + rtw8922a_ctrl_trx_path(rtwdev, ntx_path, 2, nrx_path, rx_nss); rtw8922a_hal_reset(rtwdev, RTW89_PHY_0, RTW89_MAC_0, band, &tx_en0, false); if (rtwdev->dbcc_en) @@ -2756,6 +2810,10 @@ static int rtw8922a_mac_disable_bb_rf(struct rtw89_dev *rtwdev) return 0; } +static const struct rtw89_chanctx_listener rtw8922a_chanctx_listener = { + .callbacks[RTW89_CHANCTX_CALLBACK_TAS] = rtw89_tas_chanctx_cb, +}; + #ifdef CONFIG_PM static const struct wiphy_wowlan_support rtw_wowlan_stub_8922a = { .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | @@ -2803,11 +2861,13 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .cfg_txrx_path = rtw8922a_bb_cfg_txrx_path, .set_txpwr_ul_tb_offset = NULL, .digital_pwr_comp = rtw8922a_digital_pwr_comp, + .calc_rx_gain_normal = NULL, .pwr_on_func = rtw8922a_pwr_on_func, .pwr_off_func = rtw8922a_pwr_off_func, .query_rxdesc = rtw89_core_query_rxdesc_v2, .fill_txdesc = rtw89_core_fill_txdesc_v2, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v2, + .get_ch_dma = rtw89_core_get_ch_dma, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v2, .mac_cfg_gnt = rtw89_mac_cfg_gnt_v2, .stop_sch_tx = rtw89_mac_stop_sch_tx_v2, @@ -2817,9 +2877,11 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = { .h2c_assoc_cmac_tbl = rtw89_fw_h2c_assoc_cmac_tbl_g7, .h2c_ampdu_cmac_tbl = rtw89_fw_h2c_ampdu_cmac_tbl_g7, .h2c_txtime_cmac_tbl = rtw89_fw_h2c_txtime_cmac_tbl_g7, + .h2c_punctured_cmac_tbl = rtw89_fw_h2c_punctured_cmac_tbl_g7, .h2c_default_dmac_tbl = rtw89_fw_h2c_default_dmac_tbl_v2, .h2c_update_beacon = rtw89_fw_h2c_update_beacon_be, .h2c_ba_cam = rtw89_fw_h2c_ba_cam_v1, + .h2c_wow_cam_update = rtw89_fw_h2c_wow_cam_update, .btc_set_rfe = rtw8922a_btc_set_rfe, .btc_init_cfg = rtw8922a_btc_init_cfg, @@ -2848,10 +2910,14 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .small_fifo_size = false, .dle_scc_rsvd_size = 0, .max_amsdu_limit = 8000, + .max_vht_mpdu_cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454, + .max_eht_mpdu_cap = IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_7991, + .max_tx_agg_num = 128, + .max_rx_agg_num = 64, .dis_2g_40m_ul_ofdma = false, .rsvd_ple_ofst = 0x8f800, - .hfc_param_ini = rtw8922a_hfc_param_ini_pcie, - .dle_mem = rtw8922a_dle_mem_pcie, + .hfc_param_ini = {rtw8922a_hfc_param_ini_pcie, NULL, NULL}, + .dle_mem = {rtw8922a_dle_mem_pcie, NULL, NULL, NULL}, .wde_qempty_acq_grpnum = 4, .wde_qempty_mgq_grpsel = 4, .rf_base_addr = {0xe000, 0xf000}, @@ -2865,6 +2931,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .nctl_post_table = NULL, .dflt_parms = NULL, /* load parm from fw */ .rfe_parms_conf = NULL, /* load parm from fw */ + .chanctx_listener = &rtw8922a_chanctx_listener, .txpwr_factor_bb = 3, .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, @@ -2884,8 +2951,9 @@ const struct rtw89_chip_info rtw8922a_chip_info = { BIT(NL80211_CHAN_WIDTH_160), .support_unii4 = true, .support_ant_gain = true, - .support_tas = false, + .support_tas = true, .support_sar_by_ant = true, + .support_noise = false, .ul_tb_waveform_ctrl = false, .ul_tb_pwr_diff = false, .rx_freq_frome_ie = false, @@ -2902,6 +2970,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .bacam_num = 24, .bacam_dynamic_num = 8, .bacam_ver = RTW89_BACAM_V1, + .addrcam_ver = 0, .ppdu_max_usr = 16, .sec_ctrl_efuse_size = 4, .physical_efuse_size = 0x1300, @@ -2948,20 +3017,24 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .cfo_hw_comp = true, .dcfo_comp = NULL, .dcfo_comp_sft = 0, + .nhm_report = NULL, + .nhm_th = NULL, .imr_info = NULL, .imr_dmac_table = &rtw8922a_imr_dmac_table, .imr_cmac_table = &rtw8922a_imr_cmac_table, .rrsr_cfgs = &rtw8922a_rrsr_cfgs, .bss_clr_vld = {R_BSS_CLR_VLD_V2, B_BSS_CLR_VLD0_V2}, .bss_clr_map_reg = R_BSS_CLR_MAP_V2, - .rfkill_init = {}, - .rfkill_get = {}, + .rfkill_init = &rtw8922a_rfkill_regs, + .rfkill_get = {R_BE_GPIO_EXT_CTRL, B_BE_GPIO_IN_9}, + .btc_sb = {{{R_BE_SCOREBOARD, R_BE_SCOREBOARD},}}, .dma_ch_mask = 0, .edcca_regs = &rtw8922a_edcca_regs, #ifdef CONFIG_PM .wowlan_stub = &rtw_wowlan_stub_8922a, #endif .xtal_info = NULL, + .default_quirks = 0, }; EXPORT_SYMBOL(rtw8922a_chip_info); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c index fce094c7ce939..98f14b31cf527 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a_rfk.c @@ -205,11 +205,11 @@ static void rtw8922a_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx) } } -static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, - const struct rtw89_chan *chan, u8 path) +static u8 rtw8922a_chlk_reload_sel_tbl_v0(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 path) { - struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {}; + struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc; u8 tbl_sel; for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) { @@ -229,11 +229,53 @@ static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, rfk_mcc->data[path].ch[tbl_sel] = chan->channel; rfk_mcc->data[path].band[tbl_sel] = chan->band_type; rfk_mcc->data[path].bw[tbl_sel] = chan->band_width; + rfk_mcc->data[path].rf18[tbl_sel] = rtw89_chip_chan_to_rf18_val(rtwdev, chan); rfk_mcc->data[path].table_idx = tbl_sel; return tbl_sel; } +static u8 rtw8922a_chlk_reload_sel_tbl_v1(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 path) +{ + struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data; + struct rtw89_rfk_chan_desc desc[__RTW89_RFK_CHS_NR_V1] = {}; + u8 tbl_sel; + + for (tbl_sel = 0; tbl_sel < ARRAY_SIZE(desc); tbl_sel++) { + struct rtw89_rfk_chan_desc *p = &desc[tbl_sel]; + + p->ch = rfk_mcc->ch[tbl_sel]; + + p->has_band = true; + p->band = rfk_mcc->band[tbl_sel]; + + p->has_bw = true; + p->bw = rfk_mcc->bw[tbl_sel]; + } + + tbl_sel = rtw89_rfk_chan_lookup(rtwdev, desc, ARRAY_SIZE(desc), chan); + + rfk_mcc->ch[tbl_sel] = chan->channel; + rfk_mcc->band[tbl_sel] = chan->band_type; + rfk_mcc->bw[tbl_sel] = chan->band_width; + rfk_mcc->rf18[tbl_sel] = rtw89_chip_chan_to_rf18_val(rtwdev, chan); + + /* shared table array, but tbl_sel can be independent by path */ + rfk_mcc[path].table_idx = tbl_sel; + + return tbl_sel; +} + +static u8 rtw8922a_chlk_reload_sel_tbl(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, u8 path) +{ + if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_MCC_V1, &rtwdev->fw)) + return rtw8922a_chlk_reload_sel_tbl_v1(rtwdev, chan, path); + else + return rtw8922a_chlk_reload_sel_tbl_v0(rtwdev, chan, path); +} + static void rtw8922a_chlk_reload(struct rtw89_dev *rtwdev) { const struct rtw89_chan *chan0, *chan1; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c index a0fc6b2832e16..90c62b757c57b 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c @@ -35,6 +35,8 @@ static const struct rtw89_pci_info rtw8922a_pci_info = { .rx_ring_eq_is_full = true, .check_rx_tag = true, .no_rxbd_fs = true, + .group_bd_addr = false, + .rpp_fmt_size = sizeof(struct rtw89_pci_rpp_fmt), .init_cfg_reg = R_BE_HAXI_INIT_CFG1, .txhci_en_bit = B_BE_TXDMA_EN, @@ -62,6 +64,7 @@ static const struct rtw89_pci_info rtw8922a_pci_info = { .ltr_set = rtw89_pci_ltr_set_v2, .fill_txaddr_info = rtw89_pci_fill_txaddr_info_v1, + .parse_rpp = rtw89_pci_parse_rpp, .config_intr_mask = rtw89_pci_config_intr_mask_v2, .enable_intr = rtw89_pci_enable_intr_v2, .disable_intr = rtw89_pci_disable_intr_v2, diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c index 7f568ffb3766f..ef7feccccd5e1 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.c +++ b/drivers/net/wireless/realtek/rtw89/sar.c @@ -4,6 +4,7 @@ #include "acpi.h" #include "debug.h" +#include "fw.h" #include "phy.h" #include "reg.h" #include "sar.h" @@ -843,6 +844,20 @@ void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev, } EXPORT_SYMBOL(rtw89_tas_chanctx_cb); +void rtw89_tas_fw_timer_enable(struct rtw89_dev *rtwdev, bool enable) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_tas_info *tas = &rtwdev->tas; + + if (!tas->enable) + return; + + if (chip->chip_gen == RTW89_CHIP_AX) + return; + + rtw89_fw_h2c_rf_tas_trigger(rtwdev, enable); +} + void rtw89_sar_init(struct rtw89_dev *rtwdev) { rtw89_set_sar_from_acpi(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/sar.h b/drivers/net/wireless/realtek/rtw89/sar.h index 4b7f3d44f57bf..60b3aec5b3be1 100644 --- a/drivers/net/wireless/realtek/rtw89/sar.h +++ b/drivers/net/wireless/realtek/rtw89/sar.h @@ -37,6 +37,7 @@ void rtw89_tas_reset(struct rtw89_dev *rtwdev, bool force); void rtw89_tas_scan(struct rtw89_dev *rtwdev, bool start); void rtw89_tas_chanctx_cb(struct rtw89_dev *rtwdev, enum rtw89_chanctx_state state); +void rtw89_tas_fw_timer_enable(struct rtw89_dev *rtwdev, bool enable); void rtw89_sar_init(struct rtw89_dev *rtwdev); void rtw89_sar_track(struct rtw89_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 1eb9cc7749e07..7fdc69578da31 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -431,6 +431,14 @@ static void hal_send_m4_event(struct rtw89_ser *ser) rtw89_mac_set_err_status(rtwdev, MAC_AX_ERR_L1_RCVY_EN); } +static void hal_enable_err_imr(struct rtw89_ser *ser) +{ + struct rtw89_dev *rtwdev = container_of(ser, struct rtw89_dev, ser); + const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def; + + mac->err_imr_ctrl(rtwdev, true); +} + /* state handler */ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) { @@ -491,6 +499,7 @@ static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt) case SER_EV_STATE_IN: wiphy_lock(wiphy); wiphy_delayed_work_cancel(wiphy, &rtwdev->track_work); + wiphy_delayed_work_cancel(wiphy, &rtwdev->track_ps_work); wiphy_unlock(wiphy); drv_stop_tx(ser); @@ -500,7 +509,9 @@ static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt) } drv_stop_rx(ser); + wiphy_lock(wiphy); drv_trx_reset(ser); + wiphy_unlock(wiphy); /* wait m3 */ hal_send_m2_event(ser); @@ -524,6 +535,8 @@ static void ser_reset_trx_st_hdl(struct rtw89_ser *ser, u8 evt) drv_resume_tx(ser); wiphy_delayed_work_queue(wiphy, &rtwdev->track_work, RTW89_TRACK_WORK_PERIOD); + wiphy_delayed_work_queue(wiphy, &rtwdev->track_ps_work, + RTW89_TRACK_PS_WORK_PERIOD); break; default: @@ -547,6 +560,8 @@ static void ser_do_hci_st_hdl(struct rtw89_ser *ser, u8 evt) break; case SER_EV_MAC_RESET_DONE: + hal_enable_err_imr(ser); + ser_state_goto(ser, SER_IDLE_ST); break; diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index 94f27a9ee9f70..4c12d4cb0c220 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -73,6 +73,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define RTW89_TXWD_BODY0_FW_DL BIT(20) #define RTW89_TXWD_BODY0_CHANNEL_DMA GENMASK(19, 16) #define RTW89_TXWD_BODY0_HDR_LLC_LEN GENMASK(15, 11) +#define RTW89_TXWD_BODY0_STF_MODE BIT(10) #define RTW89_TXWD_BODY0_WD_PAGE BIT(7) #define RTW89_TXWD_BODY0_HW_AMSDU BIT(5) #define RTW89_TXWD_BODY0_HW_SSN_SEL GENMASK(3, 2) @@ -183,12 +184,16 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_BODY2_QSEL GENMASK(22, 17) #define BE_TXD_BODY2_TID_IND BIT(23) #define BE_TXD_BODY2_MACID GENMASK(31, 24) +#define BE_TXD_BODY2_QSEL_V1 GENMASK(20, 15) +#define BE_TXD_BODY2_TID_IND_V1 BIT(21) +#define BE_TXD_BODY2_MACID_V1 GENMASK(31, 22) /* TX WD BODY DWORD 3 */ #define BE_TXD_BODY3_WIFI_SEQ GENMASK(11, 0) #define BE_TXD_BODY3_MLO_FLAG BIT(12) #define BE_TXD_BODY3_IS_MLD_SW_EN BIT(13) #define BE_TXD_BODY3_TRY_RATE BIT(14) +#define BE_TXD_BODY3_BK_V1 BIT(14) #define BE_TXD_BODY3_RELINK_FLAG_V1 BIT(15) #define BE_TXD_BODY3_BAND0_SU_TC_V1 GENMASK(21, 16) #define BE_TXD_BODY3_TOTAL_TC GENMASK(27, 22) @@ -196,6 +201,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_BODY3_MU_PRI_RTY BIT(29) #define BE_TXD_BODY3_MU_2ND_RTY BIT(30) #define BE_TXD_BODY3_BAND1_SU_RTY_V1 BIT(31) +#define BE_TXD_BODY3_DRIVER_QUEUE_TIME GENMASK(31, 16) /* TX WD BODY DWORD 4 */ #define BE_TXD_BODY4_TXDESC_CHECKSUM GENMASK(15, 0) @@ -219,6 +225,10 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_BODY6_EOSP_BIT BIT(15) #define BE_TXD_BODY6_S_IDX GENMASK(23, 16) #define BE_TXD_BODY6_RU_POS GENMASK(31, 24) +#define BE_TXD_BODY6_MU_TC_V1 GENMASK(3, 0) +#define BE_TXD_BODY6_RU_TC_V1 GENMASK(8, 5) +#define BE_TXD_BODY6_RELINK_EN BIT(9) +#define BE_TXD_BODY6_RELINK_LAST BIT(10) /* TX WD BODY DWORD 7 */ #define BE_TXD_BODY7_RTS_TC GENMASK(5, 0) @@ -257,6 +267,8 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) /* TX WD INFO DWORD 2 */ #define BE_TXD_INFO2_SEC_CAM_IDX GENMASK(7, 0) #define BE_TXD_INFO2_FORCE_KEY_EN BIT(8) +#define BE_TXD_INFO2_SEC_CAM_IDX_V1 GENMASK(9, 0) +#define BE_TXD_INFO2_FORCE_KEY_EN_V1 BIT(10) #define BE_TXD_INFO2_LIFETIME_SEL GENMASK(15, 13) #define BE_TXD_INFO2_FORCE_TXOP BIT(17) #define BE_TXD_INFO2_AMPDU_DENSITY GENMASK(20, 18) @@ -272,6 +284,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_INFO3_RTT_EN BIT(9) #define BE_TXD_INFO3_HT_DATA_SND_V1 BIT(10) #define BE_TXD_INFO3_BT_NULL BIT(11) +#define BE_TXD_INFO3_DISABLE_TXBF BIT(11) #define BE_TXD_INFO3_TRI_FRAME BIT(12) #define BE_TXD_INFO3_NULL_0 BIT(13) #define BE_TXD_INFO3_NULL_1 BIT(14) @@ -287,6 +300,8 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_INFO4_PUNC_MODE GENMASK(17, 16) #define BE_TXD_INFO4_SW_TX_OK_0 BIT(18) #define BE_TXD_INFO4_SW_TX_OK_1 BIT(19) +#define BE_TXD_INFO4_SW_EHT_NLTF_SWITCH BIT(20) +#define BE_TXD_INFO4_SW_EHT_NLTF GENMASK(22, 21) #define BE_TXD_INFO4_SW_TX_PWR_DBM GENMASK(26, 23) #define BE_TXD_INFO4_RTS_EN BIT(27) #define BE_TXD_INFO4_CTS2SELF BIT(28) @@ -303,6 +318,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_INFO6_UL_GI_LTF GENMASK(14, 12) #define BE_TXD_INFO6_UL_DOPPLER BIT(15) #define BE_TXD_INFO6_UL_STBC BIT(16) +#define BE_TXD_INFO6_UL_MU_MIMO_EN BIT(17) #define BE_TXD_INFO6_UL_LENGTH_REF GENMASK(21, 18) #define BE_TXD_INFO6_UL_RF_GAIN_IDX GENMASK(31, 22) @@ -317,6 +333,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) #define BE_TXD_INFO7_UL_HELTF_SYMBOL_NUM GENMASK(19, 17) #define BE_TXD_INFO7_ULBW GENMASK(21, 20) #define BE_TXD_INFO7_ULBW_EXT GENMASK(23, 22) +#define BE_TXD_INFO7_UL_TRI_PAD_TSF BIT(24) #define BE_TXD_INFO7_USE_WD_UL GENMASK(25, 24) #define BE_TXD_INFO7_EXTEND_MODE_SEL GENMASK(31, 28) @@ -416,6 +433,7 @@ struct rtw89_rxinfo_user { #define RTW89_RXINFO_USER_MGMT BIT(3) #define RTW89_RXINFO_USER_BCN BIT(4) #define RTW89_RXINFO_USER_MACID GENMASK(15, 8) +#define RTW89_RXINFO_USER_MACID_V1 GENMASK(31, 20) struct rtw89_rxinfo { __le32 w0; @@ -482,6 +500,7 @@ struct rtw89_phy_sts_iehdr { /* BE RXD dword2 */ #define BE_RXD_MAC_ID_MASK GENMASK(7, 0) +#define BE_RXD_MAC_ID_V1 GENMASK(9, 0) #define BE_RXD_TYPE_MASK GENMASK(11, 10) #define BE_RXD_LAST_MSDU BIT(12) #define BE_RXD_AMSDU_CUT BIT(13) @@ -513,6 +532,7 @@ struct rtw89_phy_sts_iehdr { #define BE_RXD_QNULL BIT(22) #define BE_RXD_A4_FRAME BIT(23) #define BE_RXD_FRAG_MASK GENMASK(27, 24) +#define BE_RXD_GET_CH_INFO_V2 GENMASK(31, 29) #define BE_RXD_GET_CH_INFO_V1_MASK GENMASK(31, 30) /* BE RXD dword4 */ @@ -528,10 +548,14 @@ struct rtw89_phy_sts_iehdr { /* BE RXD dword6 */ #define BE_RXD_ADDR_CAM_MASK GENMASK(7, 0) +#define BE_RXD_ADDR_CAM_V1 GENMASK(9, 0) +#define BE_RXD_RX_STATISTICS_V1 BIT(11) +#define BE_RXD_SMART_ANT_V1 BIT(12) #define BE_RXD_SR_EN BIT(13) #define BE_RXD_NON_SRG_PPDU BIT(14) #define BE_RXD_INTER_PPDU BIT(15) #define BE_RXD_USER_ID_MASK GENMASK(21, 16) +#define BE_RXD_SEC_CAM_IDX_V1 GENMASK(31, 22) #define BE_RXD_RX_STATISTICS BIT(22) #define BE_RXD_SMART_ANT BIT(23) #define BE_RXD_SEC_CAM_IDX_MASK GENMASK(31, 24) @@ -571,6 +595,7 @@ struct rtw89_phy_sts_ie00 { } __packed; #define RTW89_PHY_STS_IE00_W0_RPL GENMASK(15, 7) +#define RTW89_PHY_STS_IE00_W3_RX_PATH_EN GENMASK(31, 28) struct rtw89_phy_sts_ie00_v2 { __le32 w0; @@ -731,43 +756,6 @@ rtw89_core_get_qsel_mgmt(struct rtw89_dev *rtwdev, struct rtw89_core_tx_request return RTW89_TX_QSEL_B0_MGMT; } -static inline u8 rtw89_core_get_ch_dma(struct rtw89_dev *rtwdev, u8 qsel) -{ - switch (qsel) { - default: - rtw89_warn(rtwdev, "Cannot map qsel to dma: %d\n", qsel); - fallthrough; - case RTW89_TX_QSEL_BE_0: - case RTW89_TX_QSEL_BE_1: - case RTW89_TX_QSEL_BE_2: - case RTW89_TX_QSEL_BE_3: - return RTW89_TXCH_ACH0; - case RTW89_TX_QSEL_BK_0: - case RTW89_TX_QSEL_BK_1: - case RTW89_TX_QSEL_BK_2: - case RTW89_TX_QSEL_BK_3: - return RTW89_TXCH_ACH1; - case RTW89_TX_QSEL_VI_0: - case RTW89_TX_QSEL_VI_1: - case RTW89_TX_QSEL_VI_2: - case RTW89_TX_QSEL_VI_3: - return RTW89_TXCH_ACH2; - case RTW89_TX_QSEL_VO_0: - case RTW89_TX_QSEL_VO_1: - case RTW89_TX_QSEL_VO_2: - case RTW89_TX_QSEL_VO_3: - return RTW89_TXCH_ACH3; - case RTW89_TX_QSEL_B0_MGMT: - return RTW89_TXCH_CH8; - case RTW89_TX_QSEL_B0_HI: - return RTW89_TXCH_CH9; - case RTW89_TX_QSEL_B1_MGMT: - return RTW89_TXCH_CH10; - case RTW89_TX_QSEL_B1_HI: - return RTW89_TXCH_CH11; - } -} - static inline u8 rtw89_core_get_tid_indicate(struct rtw89_dev *rtwdev, u8 tid) { switch (tid) { diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c new file mode 100644 index 0000000000000..afbd1fb79021d --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/usb.c @@ -0,0 +1,1042 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) 2025 Realtek Corporation + */ + +#include +#include "debug.h" +#include "mac.h" +#include "reg.h" +#include "txrx.h" +#include "usb.h" + +static void rtw89_usb_read_port_complete(struct urb *urb); + +static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr, + void *data, u16 len, u8 reqtype) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct usb_device *udev = rtwusb->udev; + unsigned int pipe; + u16 value, index; + int attempt, ret; + + if (test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) + return; + + value = u32_get_bits(addr, GENMASK(15, 0)); + index = u32_get_bits(addr, GENMASK(23, 16)); + + for (attempt = 0; attempt < 10; attempt++) { + *rtwusb->vendor_req_buf = 0; + + if (reqtype == RTW89_USB_VENQT_READ) { + pipe = usb_rcvctrlpipe(udev, 0); + } else { /* RTW89_USB_VENQT_WRITE */ + pipe = usb_sndctrlpipe(udev, 0); + + memcpy(rtwusb->vendor_req_buf, data, len); + } + + ret = usb_control_msg(udev, pipe, RTW89_USB_VENQT, reqtype, + value, index, rtwusb->vendor_req_buf, + len, 500); + + if (ret == len) { /* Success */ + atomic_set(&rtwusb->continual_io_error, 0); + + if (reqtype == RTW89_USB_VENQT_READ) + memcpy(data, rtwusb->vendor_req_buf, len); + + break; + } + + if (ret == -ESHUTDOWN || ret == -ENODEV) + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + else if (ret < 0) + rtw89_warn(rtwdev, + "usb %s%u 0x%x fail ret=%d value=0x%x attempt=%d\n", + str_read_write(reqtype == RTW89_USB_VENQT_READ), + len * 8, addr, ret, + le32_to_cpup(rtwusb->vendor_req_buf), + attempt); + else if (ret > 0 && reqtype == RTW89_USB_VENQT_READ) + memcpy(data, rtwusb->vendor_req_buf, len); + + if (atomic_inc_return(&rtwusb->continual_io_error) > 4) { + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + break; + } + } +} + +static u32 rtw89_usb_read_cmac(struct rtw89_dev *rtwdev, u32 addr) +{ + u32 addr32, val32, shift; + __le32 data = 0; + int count; + + addr32 = addr & ~0x3; + shift = (addr & 0x3) * 8; + + for (count = 0; ; count++) { + rtw89_usb_vendorreq(rtwdev, addr32, &data, 4, + RTW89_USB_VENQT_READ); + + val32 = le32_to_cpu(data); + if (val32 != RTW89_R32_DEAD) + break; + + if (count >= MAC_REG_POOL_COUNT) { + rtw89_warn(rtwdev, "%s: addr %#x = %#x\n", + __func__, addr32, val32); + val32 = RTW89_R32_DEAD; + break; + } + + rtw89_write32(rtwdev, R_AX_CK_EN, B_AX_CMAC_ALLCKEN); + } + + return val32 >> shift; +} + +static u8 rtw89_usb_ops_read8(struct rtw89_dev *rtwdev, u32 addr) +{ + u8 data = 0; + + if (ACCESS_CMAC(addr)) + return rtw89_usb_read_cmac(rtwdev, addr); + + rtw89_usb_vendorreq(rtwdev, addr, &data, 1, RTW89_USB_VENQT_READ); + + return data; +} + +static u16 rtw89_usb_ops_read16(struct rtw89_dev *rtwdev, u32 addr) +{ + __le16 data = 0; + + if (ACCESS_CMAC(addr)) + return rtw89_usb_read_cmac(rtwdev, addr); + + rtw89_usb_vendorreq(rtwdev, addr, &data, 2, RTW89_USB_VENQT_READ); + + return le16_to_cpu(data); +} + +static u32 rtw89_usb_ops_read32(struct rtw89_dev *rtwdev, u32 addr) +{ + __le32 data = 0; + + if (ACCESS_CMAC(addr)) + return rtw89_usb_read_cmac(rtwdev, addr); + + rtw89_usb_vendorreq(rtwdev, addr, &data, 4, + RTW89_USB_VENQT_READ); + + return le32_to_cpu(data); +} + +static void rtw89_usb_ops_write8(struct rtw89_dev *rtwdev, u32 addr, u8 val) +{ + u8 data = val; + + rtw89_usb_vendorreq(rtwdev, addr, &data, 1, RTW89_USB_VENQT_WRITE); +} + +static void rtw89_usb_ops_write16(struct rtw89_dev *rtwdev, u32 addr, u16 val) +{ + __le16 data = cpu_to_le16(val); + + rtw89_usb_vendorreq(rtwdev, addr, &data, 2, RTW89_USB_VENQT_WRITE); +} + +static void rtw89_usb_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 val) +{ + __le32 data = cpu_to_le32(val); + + rtw89_usb_vendorreq(rtwdev, addr, &data, 4, RTW89_USB_VENQT_WRITE); +} + +static u32 +rtw89_usb_ops_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev, + u8 txch) +{ + if (txch == RTW89_TXCH_CH12) + return 1; + + return 42; /* TODO some kind of calculation? */ +} + +static u8 rtw89_usb_get_bulkout_id(u8 ch_dma) +{ + switch (ch_dma) { + case RTW89_DMA_ACH0: + return 3; + case RTW89_DMA_ACH1: + return 4; + case RTW89_DMA_ACH2: + return 5; + case RTW89_DMA_ACH3: + return 6; + default: + case RTW89_DMA_B0MG: + return 0; + case RTW89_DMA_B0HI: + return 1; + case RTW89_DMA_H2C: + return 2; + } +} + +static void rtw89_usb_write_port_complete(struct urb *urb) +{ + struct rtw89_usb_tx_ctrl_block *txcb = urb->context; + struct rtw89_dev *rtwdev = txcb->rtwdev; + struct ieee80211_tx_info *info; + struct rtw89_txwd_body *txdesc; + struct sk_buff *skb; + u32 txdesc_size; + + while (true) { + skb = skb_dequeue(&txcb->tx_ack_queue); + if (!skb) + break; + + if (txcb->txch == RTW89_TXCH_CH12) { + dev_kfree_skb_any(skb); + continue; + } + + txdesc = (struct rtw89_txwd_body *)skb->data; + + txdesc_size = rtwdev->chip->txwd_body_size; + if (le32_get_bits(txdesc->dword0, RTW89_TXWD_BODY0_WD_INFO_EN)) + txdesc_size += rtwdev->chip->txwd_info_size; + + skb_pull(skb, txdesc_size); + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + if (urb->status == 0) { + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; + else + info->flags |= IEEE80211_TX_STAT_ACK; + } + + ieee80211_tx_status_irqsafe(rtwdev->hw, skb); + } + + switch (urb->status) { + case 0: + case -EPIPE: + case -EPROTO: + case -EINPROGRESS: + case -ENOENT: + case -ECONNRESET: + break; + default: + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + break; + } + + kfree(txcb); + usb_free_urb(urb); +} + +static int rtw89_usb_write_port(struct rtw89_dev *rtwdev, u8 ch_dma, + void *data, int len, void *context) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct usb_device *usbd = rtwusb->udev; + struct urb *urb; + u8 bulkout_id = rtw89_usb_get_bulkout_id(ch_dma); + unsigned int pipe; + int ret; + + if (test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags)) + return 0; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + pipe = usb_sndbulkpipe(usbd, rtwusb->out_pipe[bulkout_id]); + + usb_fill_bulk_urb(urb, usbd, pipe, data, len, + rtw89_usb_write_port_complete, context); + urb->transfer_flags |= URB_ZERO_PACKET; + ret = usb_submit_urb(urb, GFP_ATOMIC); + + if (ret) + usb_free_urb(urb); + + if (ret == -ENODEV) + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + + return ret; +} + +static void rtw89_usb_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct rtw89_usb_tx_ctrl_block *txcb; + struct sk_buff *skb; + int ret; + + while (true) { + skb = skb_dequeue(&rtwusb->tx_queue[txch]); + if (!skb) + break; + + txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC); + if (!txcb) { + dev_kfree_skb_any(skb); + continue; + } + + txcb->rtwdev = rtwdev; + txcb->txch = txch; + skb_queue_head_init(&txcb->tx_ack_queue); + + skb_queue_tail(&txcb->tx_ack_queue, skb); + + ret = rtw89_usb_write_port(rtwdev, txch, skb->data, skb->len, + txcb); + if (ret) { + rtw89_err(rtwdev, "write port txch %d failed: %d\n", + txch, ret); + + skb_dequeue(&txcb->tx_ack_queue); + kfree(txcb); + dev_kfree_skb_any(skb); + } + } +} + +static int rtw89_usb_tx_write_fwcmd(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) +{ + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct sk_buff *skb = tx_req->skb; + struct sk_buff *skb512; + u32 txdesc_size = rtwdev->chip->h2c_desc_size; + void *txdesc; + + if (((desc_info->pkt_size + txdesc_size) % 512) == 0) { + rtw89_debug(rtwdev, RTW89_DBG_HCI, "avoiding multiple of 512\n"); + + skb512 = dev_alloc_skb(txdesc_size + desc_info->pkt_size + + RTW89_USB_MOD512_PADDING); + if (!skb512) { + rtw89_err(rtwdev, "%s: failed to allocate skb\n", + __func__); + + return -ENOMEM; + } + + skb_pull(skb512, txdesc_size); + skb_put_data(skb512, skb->data, skb->len); + skb_put_zero(skb512, RTW89_USB_MOD512_PADDING); + + dev_kfree_skb_any(skb); + skb = skb512; + tx_req->skb = skb512; + + desc_info->pkt_size += RTW89_USB_MOD512_PADDING; + } + + txdesc = skb_push(skb, txdesc_size); + memset(txdesc, 0, txdesc_size); + rtw89_chip_fill_txdesc_fwcmd(rtwdev, desc_info, txdesc); + + skb_queue_tail(&rtwusb->tx_queue[desc_info->ch_dma], skb); + + return 0; +} + +static int rtw89_usb_ops_tx_write(struct rtw89_dev *rtwdev, + struct rtw89_core_tx_request *tx_req) +{ + struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info; + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct sk_buff *skb = tx_req->skb; + struct rtw89_txwd_body *txdesc; + u32 txdesc_size; + + if ((desc_info->ch_dma == RTW89_TXCH_CH12 || + tx_req->tx_type == RTW89_CORE_TX_TYPE_FWCMD) && + (desc_info->ch_dma != RTW89_TXCH_CH12 || + tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD)) { + rtw89_err(rtwdev, "dma channel %d/TX type %d mismatch\n", + desc_info->ch_dma, tx_req->tx_type); + return -EINVAL; + } + + if (desc_info->ch_dma == RTW89_TXCH_CH12) + return rtw89_usb_tx_write_fwcmd(rtwdev, tx_req); + + txdesc_size = rtwdev->chip->txwd_body_size; + if (desc_info->en_wd_info) + txdesc_size += rtwdev->chip->txwd_info_size; + + txdesc = skb_push(skb, txdesc_size); + memset(txdesc, 0, txdesc_size); + rtw89_chip_fill_txdesc(rtwdev, desc_info, txdesc); + + le32p_replace_bits(&txdesc->dword0, 1, RTW89_TXWD_BODY0_STF_MODE); + + skb_queue_tail(&rtwusb->tx_queue[desc_info->ch_dma], skb); + + return 0; +} + +static void rtw89_usb_rx_handler(struct work_struct *work) +{ + struct rtw89_usb *rtwusb = container_of(work, struct rtw89_usb, rx_work); + struct rtw89_dev *rtwdev = rtwusb->rtwdev; + struct rtw89_rx_desc_info desc_info; + struct sk_buff *rx_skb; + struct sk_buff *skb; + u32 pkt_offset; + int limit; + + for (limit = 0; limit < 200; limit++) { + rx_skb = skb_dequeue(&rtwusb->rx_queue); + if (!rx_skb) + break; + + if (skb_queue_len(&rtwusb->rx_queue) >= RTW89_USB_MAX_RXQ_LEN) { + rtw89_warn(rtwdev, "rx_queue overflow\n"); + dev_kfree_skb_any(rx_skb); + continue; + } + + memset(&desc_info, 0, sizeof(desc_info)); + rtw89_chip_query_rxdesc(rtwdev, &desc_info, rx_skb->data, 0); + + skb = rtw89_alloc_skb_for_rx(rtwdev, desc_info.pkt_size); + if (!skb) { + rtw89_debug(rtwdev, RTW89_DBG_HCI, + "failed to allocate RX skb of size %u\n", + desc_info.pkt_size); + continue; + } + + pkt_offset = desc_info.offset + desc_info.rxd_len; + + skb_put_data(skb, rx_skb->data + pkt_offset, + desc_info.pkt_size); + + rtw89_core_rx(rtwdev, &desc_info, skb); + + if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW89_USB_RX_SKB_NUM) + dev_kfree_skb_any(rx_skb); + else + skb_queue_tail(&rtwusb->rx_free_queue, rx_skb); + } + + if (limit == 200) { + rtw89_debug(rtwdev, RTW89_DBG_HCI, + "left %d rx skbs in the queue for later\n", + skb_queue_len(&rtwusb->rx_queue)); + queue_work(rtwusb->rxwq, &rtwusb->rx_work); + } +} + +static void rtw89_usb_rx_resubmit(struct rtw89_usb *rtwusb, + struct rtw89_usb_rx_ctrl_block *rxcb, + gfp_t gfp) +{ + struct rtw89_dev *rtwdev = rtwusb->rtwdev; + struct sk_buff *rx_skb; + int ret; + + rx_skb = skb_dequeue(&rtwusb->rx_free_queue); + if (!rx_skb) + rx_skb = alloc_skb(RTW89_USB_RECVBUF_SZ, gfp); + + if (!rx_skb) + goto try_later; + + skb_reset_tail_pointer(rx_skb); + rx_skb->len = 0; + + rxcb->rx_skb = rx_skb; + + usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev, + usb_rcvbulkpipe(rtwusb->udev, rtwusb->in_pipe), + rxcb->rx_skb->data, RTW89_USB_RECVBUF_SZ, + rtw89_usb_read_port_complete, rxcb); + + ret = usb_submit_urb(rxcb->rx_urb, gfp); + if (ret) { + skb_queue_tail(&rtwusb->rx_free_queue, rxcb->rx_skb); + + if (ret == -ENODEV) + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + else + rtw89_err(rtwdev, "Err sending rx data urb %d\n", ret); + + if (ret == -ENOMEM) + goto try_later; + } + + return; + +try_later: + rxcb->rx_skb = NULL; + queue_work(rtwusb->rxwq, &rtwusb->rx_urb_work); +} + +static void rtw89_usb_rx_resubmit_work(struct work_struct *work) +{ + struct rtw89_usb *rtwusb = container_of(work, struct rtw89_usb, rx_urb_work); + struct rtw89_usb_rx_ctrl_block *rxcb; + int i; + + for (i = 0; i < RTW89_USB_RXCB_NUM; i++) { + rxcb = &rtwusb->rx_cb[i]; + + if (!rxcb->rx_skb) + rtw89_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC); + } +} + +static void rtw89_usb_read_port_complete(struct urb *urb) +{ + struct rtw89_usb_rx_ctrl_block *rxcb = urb->context; + struct rtw89_dev *rtwdev = rxcb->rtwdev; + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct sk_buff *skb = rxcb->rx_skb; + + if (urb->status == 0) { + if (urb->actual_length > urb->transfer_buffer_length || + urb->actual_length < sizeof(struct rtw89_rxdesc_short)) { + rtw89_err(rtwdev, "failed to get urb length: %d\n", + urb->actual_length); + skb_queue_tail(&rtwusb->rx_free_queue, skb); + } else { + skb_put(skb, urb->actual_length); + skb_queue_tail(&rtwusb->rx_queue, skb); + queue_work(rtwusb->rxwq, &rtwusb->rx_work); + } + + rtw89_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC); + } else { + skb_queue_tail(&rtwusb->rx_free_queue, skb); + + if (atomic_inc_return(&rtwusb->continual_io_error) > 4) + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + + switch (urb->status) { + case -EINVAL: + case -EPIPE: + case -ENODEV: + case -ESHUTDOWN: + set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags); + break; + case -EPROTO: + case -EILSEQ: + case -ETIME: + case -ECOMM: + case -EOVERFLOW: + case -ENOENT: + break; + case -EINPROGRESS: + rtw89_info(rtwdev, "URB is in progress\n"); + break; + default: + rtw89_err(rtwdev, "%s status %d\n", + __func__, urb->status); + break; + } + } +} + +static void rtw89_usb_cancel_rx_bufs(struct rtw89_usb *rtwusb) +{ + struct rtw89_usb_rx_ctrl_block *rxcb; + int i; + + for (i = 0; i < RTW89_USB_RXCB_NUM; i++) { + rxcb = &rtwusb->rx_cb[i]; + usb_kill_urb(rxcb->rx_urb); + } +} + +static void rtw89_usb_free_rx_bufs(struct rtw89_usb *rtwusb) +{ + struct rtw89_usb_rx_ctrl_block *rxcb; + int i; + + for (i = 0; i < RTW89_USB_RXCB_NUM; i++) { + rxcb = &rtwusb->rx_cb[i]; + usb_free_urb(rxcb->rx_urb); + } +} + +static int rtw89_usb_alloc_rx_bufs(struct rtw89_usb *rtwusb) +{ + struct rtw89_usb_rx_ctrl_block *rxcb; + int i; + + for (i = 0; i < RTW89_USB_RXCB_NUM; i++) { + rxcb = &rtwusb->rx_cb[i]; + + rxcb->rtwdev = rtwusb->rtwdev; + rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rxcb->rx_urb) { + rtw89_usb_free_rx_bufs(rtwusb); + return -ENOMEM; + } + } + + return 0; +} + +static int rtw89_usb_init_rx(struct rtw89_dev *rtwdev) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct sk_buff *rx_skb; + int i; + + rtwusb->rxwq = alloc_workqueue("rtw89_usb: rx wq", WQ_BH, 0); + if (!rtwusb->rxwq) { + rtw89_err(rtwdev, "failed to create RX work queue\n"); + return -ENOMEM; + } + + skb_queue_head_init(&rtwusb->rx_queue); + skb_queue_head_init(&rtwusb->rx_free_queue); + + INIT_WORK(&rtwusb->rx_work, rtw89_usb_rx_handler); + INIT_WORK(&rtwusb->rx_urb_work, rtw89_usb_rx_resubmit_work); + + for (i = 0; i < RTW89_USB_RX_SKB_NUM; i++) { + rx_skb = alloc_skb(RTW89_USB_RECVBUF_SZ, GFP_KERNEL); + if (rx_skb) + skb_queue_tail(&rtwusb->rx_free_queue, rx_skb); + } + + return 0; +} + +static void rtw89_usb_deinit_rx(struct rtw89_dev *rtwdev) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + + skb_queue_purge(&rtwusb->rx_queue); + + destroy_workqueue(rtwusb->rxwq); + + skb_queue_purge(&rtwusb->rx_free_queue); +} + +static void rtw89_usb_start_rx(struct rtw89_dev *rtwdev) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + int i; + + for (i = 0; i < RTW89_USB_RXCB_NUM; i++) + rtw89_usb_rx_resubmit(rtwusb, &rtwusb->rx_cb[i], GFP_KERNEL); +} + +static void rtw89_usb_init_tx(struct rtw89_dev *rtwdev) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + int i; + + for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) + skb_queue_head_init(&rtwusb->tx_queue[i]); +} + +static void rtw89_usb_deinit_tx(struct rtw89_dev *rtwdev) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + int i; + + for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++) { + if (i == RTW89_TXCH_CH12) + skb_queue_purge(&rtwusb->tx_queue[i]); + else + ieee80211_purge_tx_queue(rtwdev->hw, &rtwusb->tx_queue[i]); + } +} + +static void rtw89_usb_ops_reset(struct rtw89_dev *rtwdev) +{ + /* TODO: anything to do here? */ +} + +static int rtw89_usb_ops_start(struct rtw89_dev *rtwdev) +{ + return 0; /* Nothing to do. */ +} + +static void rtw89_usb_ops_stop(struct rtw89_dev *rtwdev) +{ + /* Nothing to do. */ +} + +static void rtw89_usb_ops_pause(struct rtw89_dev *rtwdev, bool pause) +{ + /* Nothing to do? */ +} + +static void rtw89_usb_ops_switch_mode(struct rtw89_dev *rtwdev, bool low_power) +{ + /* Nothing to do. */ +} + +static int rtw89_usb_ops_deinit(struct rtw89_dev *rtwdev) +{ + return 0; /* Nothing to do. */ +} + +static int rtw89_usb_ops_mac_pre_init(struct rtw89_dev *rtwdev) +{ + u32 val32; + + rtw89_write32_set(rtwdev, R_AX_USB_HOST_REQUEST_2, B_AX_R_USBIO_MODE); + + /* fix USB IO hang suggest by chihhanli@realtek.com */ + rtw89_write32_clr(rtwdev, R_AX_USB_WLAN0_1, + B_AX_USBRX_RST | B_AX_USBTX_RST); + + val32 = rtw89_read32(rtwdev, R_AX_HCI_FUNC_EN); + val32 &= ~(B_AX_HCI_RXDMA_EN | B_AX_HCI_TXDMA_EN); + rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val32); + + val32 |= B_AX_HCI_RXDMA_EN | B_AX_HCI_TXDMA_EN; + rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val32); + /* fix USB TRX hang suggest by chihhanli@realtek.com */ + + return 0; +} + +static int rtw89_usb_ops_mac_pre_deinit(struct rtw89_dev *rtwdev) +{ + return 0; /* Nothing to do. */ +} + +static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + enum usb_device_speed speed; + u32 ep; + + rtw89_write32_clr(rtwdev, R_AX_USB3_MAC_NPI_CONFIG_INTF_0, + B_AX_SSPHY_LFPS_FILTER); + + speed = rtwusb->udev->speed; + + if (speed == USB_SPEED_SUPER) + rtw89_write8(rtwdev, R_AX_RXDMA_SETTING, USB3_BULKSIZE); + else if (speed == USB_SPEED_HIGH) + rtw89_write8(rtwdev, R_AX_RXDMA_SETTING, USB2_BULKSIZE); + else + rtw89_write8(rtwdev, R_AX_RXDMA_SETTING, USB11_BULKSIZE); + + for (ep = 5; ep <= 12; ep++) { + if (ep == 8) + continue; + + rtw89_write8_mask(rtwdev, R_AX_USB_ENDPOINT_0, + B_AX_EP_IDX, ep); + rtw89_write8(rtwdev, R_AX_USB_ENDPOINT_2 + 1, NUMP); + } + + return 0; +} + +static void rtw89_usb_ops_recalc_int_mit(struct rtw89_dev *rtwdev) +{ + /* Nothing to do. */ +} + +static int rtw89_usb_ops_mac_lv1_rcvy(struct rtw89_dev *rtwdev, + enum rtw89_lv1_rcvy_step step) +{ + u32 reg, mask; + + switch (rtwdev->chip->chip_id) { + case RTL8851B: + case RTL8852A: + case RTL8852B: + reg = R_AX_USB_WLAN0_1; + mask = B_AX_USBRX_RST | B_AX_USBTX_RST; + break; + case RTL8852C: + reg = R_AX_USB_WLAN0_1_V1; + mask = B_AX_USBRX_RST_V1 | B_AX_USBTX_RST_V1; + break; + default: + rtw89_err(rtwdev, "%s: fix me\n", __func__); + return -EOPNOTSUPP; + } + + switch (step) { + case RTW89_LV1_RCVY_STEP_1: + rtw89_write32_set(rtwdev, reg, mask); + + msleep(30); + break; + case RTW89_LV1_RCVY_STEP_2: + rtw89_write32_clr(rtwdev, reg, mask); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void rtw89_usb_ops_dump_err_status(struct rtw89_dev *rtwdev) +{ + rtw89_warn(rtwdev, "%s TODO\n", __func__); +} + +static const struct rtw89_hci_ops rtw89_usb_ops = { + .tx_write = rtw89_usb_ops_tx_write, + .tx_kick_off = rtw89_usb_ops_tx_kick_off, + .flush_queues = NULL, /* Not needed? */ + .reset = rtw89_usb_ops_reset, + .start = rtw89_usb_ops_start, + .stop = rtw89_usb_ops_stop, + .pause = rtw89_usb_ops_pause, + .switch_mode = rtw89_usb_ops_switch_mode, + .recalc_int_mit = rtw89_usb_ops_recalc_int_mit, + + .read8 = rtw89_usb_ops_read8, + .read16 = rtw89_usb_ops_read16, + .read32 = rtw89_usb_ops_read32, + .write8 = rtw89_usb_ops_write8, + .write16 = rtw89_usb_ops_write16, + .write32 = rtw89_usb_ops_write32, + + .mac_pre_init = rtw89_usb_ops_mac_pre_init, + .mac_pre_deinit = rtw89_usb_ops_mac_pre_deinit, + .mac_post_init = rtw89_usb_ops_mac_post_init, + .deinit = rtw89_usb_ops_deinit, + + .check_and_reclaim_tx_resource = rtw89_usb_ops_check_and_reclaim_tx_resource, + .mac_lv1_rcvy = rtw89_usb_ops_mac_lv1_rcvy, + .dump_err_status = rtw89_usb_ops_dump_err_status, + .napi_poll = NULL, + + .recovery_start = NULL, + .recovery_complete = NULL, + + .ctrl_txdma_ch = NULL, + .ctrl_txdma_fw_ch = NULL, + .ctrl_trxhci = NULL, + .poll_txdma_ch_idle = NULL, + + .clr_idx_all = NULL, + .clear = NULL, + .disable_intr = NULL, + .enable_intr = NULL, + .rst_bdram = NULL, +}; + +static int rtw89_usb_parse(struct rtw89_dev *rtwdev, + struct usb_interface *intf) +{ + struct usb_host_interface *host_interface = &intf->altsetting[0]; + struct usb_interface_descriptor *intf_desc = &host_interface->desc; + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + struct usb_endpoint_descriptor *endpoint; + int num_out_pipes = 0; + u8 num; + int i; + + if (intf_desc->bNumEndpoints > RTW89_MAX_ENDPOINT_NUM) { + rtw89_err(rtwdev, "found %d endpoints, expected %d max\n", + intf_desc->bNumEndpoints, RTW89_MAX_ENDPOINT_NUM); + return -EINVAL; + } + + for (i = 0; i < intf_desc->bNumEndpoints; i++) { + endpoint = &host_interface->endpoint[i].desc; + num = usb_endpoint_num(endpoint); + + if (usb_endpoint_dir_in(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (rtwusb->in_pipe) { + rtw89_err(rtwdev, + "found more than 1 bulk in endpoint\n"); + return -EINVAL; + } + + rtwusb->in_pipe = num; + } + + if (usb_endpoint_dir_out(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (num_out_pipes >= RTW89_MAX_BULKOUT_NUM) { + rtw89_err(rtwdev, + "found more than %d bulk out endpoints\n", + RTW89_MAX_BULKOUT_NUM); + return -EINVAL; + } + + rtwusb->out_pipe[num_out_pipes++] = num; + } + } + + if (num_out_pipes < 1) { + rtw89_err(rtwdev, "no bulk out endpoints found\n"); + return -EINVAL; + } + + return 0; +} + +static int rtw89_usb_intf_init(struct rtw89_dev *rtwdev, + struct usb_interface *intf) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + int ret; + + ret = rtw89_usb_parse(rtwdev, intf); + if (ret) + return ret; + + rtwusb->vendor_req_buf = kmalloc(sizeof(*rtwusb->vendor_req_buf), + GFP_KERNEL); + if (!rtwusb->vendor_req_buf) + return -ENOMEM; + + rtwusb->udev = usb_get_dev(interface_to_usbdev(intf)); + + usb_set_intfdata(intf, rtwdev->hw); + + SET_IEEE80211_DEV(rtwdev->hw, &intf->dev); + + return 0; +} + +static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev, + struct usb_interface *intf) +{ + struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev); + + usb_put_dev(rtwusb->udev); + kfree(rtwusb->vendor_req_buf); + usb_set_intfdata(intf, NULL); +} + +int rtw89_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + const struct rtw89_driver_info *info; + struct rtw89_dev *rtwdev; + struct rtw89_usb *rtwusb; + int ret; + + info = (const struct rtw89_driver_info *)id->driver_info; + + rtwdev = rtw89_alloc_ieee80211_hw(&intf->dev, + sizeof(struct rtw89_usb), + info->chip, info->variant); + if (!rtwdev) { + dev_err(&intf->dev, "failed to allocate hw\n"); + return -ENOMEM; + } + + rtwusb = rtw89_usb_priv(rtwdev); + rtwusb->rtwdev = rtwdev; + + rtwdev->hci.ops = &rtw89_usb_ops; + rtwdev->hci.type = RTW89_HCI_TYPE_USB; + + ret = rtw89_usb_intf_init(rtwdev, intf); + if (ret) { + rtw89_err(rtwdev, "failed to initialise intf: %d\n", ret); + goto err_free_hw; + } + + if (rtwusb->udev->speed == USB_SPEED_SUPER) + rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_USB3; + else + rtwdev->hci.dle_type = RTW89_HCI_DLE_TYPE_USB2; + + rtw89_usb_init_tx(rtwdev); + + ret = rtw89_usb_alloc_rx_bufs(rtwusb); + if (ret) + goto err_intf_deinit; + + ret = rtw89_usb_init_rx(rtwdev); + if (ret) + goto err_free_rx_bufs; + + ret = rtw89_core_init(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to initialise core: %d\n", ret); + goto err_deinit_rx; + } + + ret = rtw89_chip_info_setup(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to setup chip information\n"); + goto err_core_deinit; + } + + ret = rtw89_core_register(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to register core\n"); + goto err_core_deinit; + } + + rtw89_usb_start_rx(rtwdev); + + set_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags); + + return 0; + +err_core_deinit: + rtw89_core_deinit(rtwdev); +err_deinit_rx: + rtw89_usb_deinit_rx(rtwdev); +err_free_rx_bufs: + rtw89_usb_free_rx_bufs(rtwusb); +err_intf_deinit: + rtw89_usb_intf_deinit(rtwdev, intf); +err_free_hw: + rtw89_free_ieee80211_hw(rtwdev); + + return ret; +} +EXPORT_SYMBOL(rtw89_usb_probe); + +void rtw89_usb_disconnect(struct usb_interface *intf) +{ + struct ieee80211_hw *hw = usb_get_intfdata(intf); + struct rtw89_dev *rtwdev; + struct rtw89_usb *rtwusb; + + if (!hw) + return; + + rtwdev = hw->priv; + rtwusb = rtw89_usb_priv(rtwdev); + + rtw89_usb_cancel_rx_bufs(rtwusb); + + rtw89_core_unregister(rtwdev); + rtw89_core_deinit(rtwdev); + rtw89_usb_deinit_rx(rtwdev); + rtw89_usb_free_rx_bufs(rtwusb); + rtw89_usb_deinit_tx(rtwdev); + rtw89_usb_intf_deinit(rtwdev, intf); + rtw89_free_ieee80211_hw(rtwdev); +} +EXPORT_SYMBOL(rtw89_usb_disconnect); + +MODULE_AUTHOR("Bitterblue Smith "); +MODULE_DESCRIPTION("Realtek USB 802.11ax wireless driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h new file mode 100644 index 0000000000000..c1b4bfa209795 --- /dev/null +++ b/drivers/net/wireless/realtek/rtw89/usb.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ +/* Copyright(c) 2025 Realtek Corporation + */ + +#ifndef __RTW89_USB_H__ +#define __RTW89_USB_H__ + +#include "txrx.h" + +#define RTW89_USB_VENQT 0x05 +#define RTW89_USB_VENQT_READ 0xc0 +#define RTW89_USB_VENQT_WRITE 0x40 + +#define RTW89_USB_RECVBUF_SZ 20480 +#define RTW89_USB_RXCB_NUM 8 +#define RTW89_USB_RX_SKB_NUM 16 +#define RTW89_USB_MAX_RXQ_LEN 512 +#define RTW89_USB_MOD512_PADDING 4 + +#define RTW89_MAX_ENDPOINT_NUM 9 +#define RTW89_MAX_BULKOUT_NUM 7 + +struct rtw89_usb_rx_ctrl_block { + struct rtw89_dev *rtwdev; + struct urb *rx_urb; + struct sk_buff *rx_skb; +}; + +struct rtw89_usb_tx_ctrl_block { + struct rtw89_dev *rtwdev; + u8 txch; + struct sk_buff_head tx_ack_queue; +}; + +struct rtw89_usb { + struct rtw89_dev *rtwdev; + struct usb_device *udev; + + __le32 *vendor_req_buf; + + atomic_t continual_io_error; + + u8 in_pipe; + u8 out_pipe[RTW89_MAX_BULKOUT_NUM]; + + struct workqueue_struct *rxwq; + struct rtw89_usb_rx_ctrl_block rx_cb[RTW89_USB_RXCB_NUM]; + struct sk_buff_head rx_queue; + struct sk_buff_head rx_free_queue; + struct work_struct rx_work; + struct work_struct rx_urb_work; + + struct sk_buff_head tx_queue[RTW89_TXCH_NUM]; +}; + +static inline struct rtw89_usb *rtw89_usb_priv(struct rtw89_dev *rtwdev) +{ + return (struct rtw89_usb *)rtwdev->priv; +} + +int rtw89_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id); +void rtw89_usb_disconnect(struct usb_interface *intf); + +#endif diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 1dfce65a6e991..2b7da5ca196bc 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -12,7 +12,7 @@ #include "util.h" #include "wow.h" -void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb) +void __rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb) { struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; struct rtw89_wow_param *rtw_wow = &rtwdev->wow; @@ -99,13 +99,26 @@ static int rtw89_rx_pn_to_iv(struct rtw89_dev *rtwdev, ieee80211_get_key_rx_seq(key, 0, &seq); - /* seq.ccmp.pn[] is BE order array */ - pn = u64_encode_bits(seq.ccmp.pn[0], RTW89_KEY_PN_5) | - u64_encode_bits(seq.ccmp.pn[1], RTW89_KEY_PN_4) | - u64_encode_bits(seq.ccmp.pn[2], RTW89_KEY_PN_3) | - u64_encode_bits(seq.ccmp.pn[3], RTW89_KEY_PN_2) | - u64_encode_bits(seq.ccmp.pn[4], RTW89_KEY_PN_1) | - u64_encode_bits(seq.ccmp.pn[5], RTW89_KEY_PN_0); + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + pn = u64_encode_bits(seq.tkip.iv32, RTW89_KEY_TKIP_PN_IV32) | + u64_encode_bits(seq.tkip.iv16, RTW89_KEY_TKIP_PN_IV16); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP_256: + /* seq.ccmp.pn[] is BE order array */ + pn = u64_encode_bits(seq.ccmp.pn[0], RTW89_KEY_PN_5) | + u64_encode_bits(seq.ccmp.pn[1], RTW89_KEY_PN_4) | + u64_encode_bits(seq.ccmp.pn[2], RTW89_KEY_PN_3) | + u64_encode_bits(seq.ccmp.pn[3], RTW89_KEY_PN_2) | + u64_encode_bits(seq.ccmp.pn[4], RTW89_KEY_PN_1) | + u64_encode_bits(seq.ccmp.pn[5], RTW89_KEY_PN_0); + break; + default: + return -EINVAL; + } err = _pn_to_iv(rtwdev, key, iv, pn, key->keyidx); if (err) @@ -177,13 +190,26 @@ static int rtw89_rx_iv_to_pn(struct rtw89_dev *rtwdev, if (err) return err; - /* seq.ccmp.pn[] is BE order array */ - seq.ccmp.pn[0] = u64_get_bits(pn, RTW89_KEY_PN_5); - seq.ccmp.pn[1] = u64_get_bits(pn, RTW89_KEY_PN_4); - seq.ccmp.pn[2] = u64_get_bits(pn, RTW89_KEY_PN_3); - seq.ccmp.pn[3] = u64_get_bits(pn, RTW89_KEY_PN_2); - seq.ccmp.pn[4] = u64_get_bits(pn, RTW89_KEY_PN_1); - seq.ccmp.pn[5] = u64_get_bits(pn, RTW89_KEY_PN_0); + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + seq.tkip.iv32 = u64_get_bits(pn, RTW89_KEY_TKIP_PN_IV32); + seq.tkip.iv16 = u64_get_bits(pn, RTW89_KEY_TKIP_PN_IV16); + break; + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP_256: + /* seq.ccmp.pn[] is BE order array */ + seq.ccmp.pn[0] = u64_get_bits(pn, RTW89_KEY_PN_5); + seq.ccmp.pn[1] = u64_get_bits(pn, RTW89_KEY_PN_4); + seq.ccmp.pn[2] = u64_get_bits(pn, RTW89_KEY_PN_3); + seq.ccmp.pn[3] = u64_get_bits(pn, RTW89_KEY_PN_2); + seq.ccmp.pn[4] = u64_get_bits(pn, RTW89_KEY_PN_1); + seq.ccmp.pn[5] = u64_get_bits(pn, RTW89_KEY_PN_0); + break; + default: + return -EINVAL; + } ieee80211_set_key_rx_seq(key, 0, &seq); rtw89_debug(rtwdev, RTW89_DBG_WOW, "%s key %d iv-%*ph to pn-%*ph\n", @@ -285,6 +311,11 @@ static void rtw89_wow_get_key_info_iter(struct ieee80211_hw *hw, switch (key->cipher) { case WLAN_CIPHER_SUITE_TKIP: + if (sta) + memcpy(gtk_info->txmickey, + key->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, + sizeof(gtk_info->txmickey)); + fallthrough; case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_CCMP_256: @@ -348,10 +379,27 @@ static void rtw89_wow_set_key_info_iter(struct ieee80211_hw *hw, struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; struct rtw89_set_key_info_iter_data *iter_data = data; bool update_tx_key_info = iter_data->rx_ready; + u8 tmp[RTW89_MIC_KEY_LEN]; int ret; switch (key->cipher) { case WLAN_CIPHER_SUITE_TKIP: + /* + * TX MIC KEY and RX MIC KEY is oppsite in FW, + * need to swap it before sending to mac80211. + */ + if (!sta && update_tx_key_info && aoac_rpt->rekey_ok && + !iter_data->tkip_gtk_swapped) { + memcpy(tmp, &aoac_rpt->gtk[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], + RTW89_MIC_KEY_LEN); + memcpy(&aoac_rpt->gtk[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], + &aoac_rpt->gtk[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], + RTW89_MIC_KEY_LEN); + memcpy(&aoac_rpt->gtk[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], + tmp, RTW89_MIC_KEY_LEN); + iter_data->tkip_gtk_swapped = true; + } + fallthrough; case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_CCMP_256: @@ -639,7 +687,8 @@ static void rtw89_wow_update_key_info(struct rtw89_dev *rtwdev, bool rx_ready) struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_aoac_report *aoac_rpt = &rtw_wow->aoac_rpt; struct rtw89_set_key_info_iter_data data = {.error = false, - .rx_ready = rx_ready}; + .rx_ready = rx_ready, + .tkip_gtk_swapped = false}; struct ieee80211_bss_conf *bss_conf; struct ieee80211_key_conf *key; @@ -1022,7 +1071,7 @@ static void rtw89_wow_pattern_clear_cam(struct rtw89_dev *rtwdev) for (i = 0; i < rtw_wow->pattern_cnt; i++) { rtw_pattern = &rtw_wow->patterns[i]; rtw_pattern->valid = false; - rtw89_fw_wow_cam_update(rtwdev, rtw_pattern); + rtw89_chip_h2c_wow_cam_update(rtwdev, rtw_pattern); } } @@ -1033,7 +1082,7 @@ static void rtw89_wow_pattern_write(struct rtw89_dev *rtwdev) int i; for (i = 0; i < rtw_wow->pattern_cnt; i++) - rtw89_fw_wow_cam_update(rtwdev, rtw_pattern + i); + rtw89_chip_h2c_wow_cam_update(rtwdev, rtw_pattern + i); } static void rtw89_wow_pattern_clear(struct rtw89_dev *rtwdev) @@ -1173,7 +1222,8 @@ static int rtw89_wow_cfg_wake(struct rtw89_dev *rtwdev, bool wow) } } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_INFO_CHANGE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -1200,7 +1250,7 @@ static int rtw89_wow_check_fw_status(struct rtw89_dev *rtwdev, bool wow_enable) mac->wow_ctrl.addr, mac->wow_ctrl.mask); if (ret) rtw89_err(rtwdev, "failed to check wow status %s\n", - wow_enable ? "enabled" : "disabled"); + str_enabled_disabled(wow_enable)); return ret; } @@ -1214,15 +1264,15 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id; const struct rtw89_chip_info *chip = rtwdev->chip; bool include_bb = !!chip->bbmcu_nr; - bool disable_intr_for_dlfw = false; + bool disable_intr_for_dlfw = true; struct ieee80211_sta *wow_sta; struct rtw89_sta_link *rtwsta_link = NULL; struct rtw89_sta *rtwsta; bool is_conn = true; int ret; - if (chip_id == RTL8852C || chip_id == RTL8922A) - disable_intr_for_dlfw = true; + if (chip->chip_gen == RTW89_CHIP_AX && chip_id != RTL8852C) + disable_intr_for_dlfw = false; wow_sta = ieee80211_find_sta(wow_vif, wow_vif->cfg.ap_addr); if (wow_sta) { @@ -1270,7 +1320,8 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow) return ret; } - ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL); + ret = rtw89_fw_h2c_cam(rtwdev, rtwvif_link, rtwsta_link, NULL, + RTW89_ROLE_FW_RESTORE); if (ret) { rtw89_warn(rtwdev, "failed to send h2c cam\n"); return ret; @@ -1416,6 +1467,8 @@ static void rtw89_fw_release_pno_pkt_list(struct rtw89_dev *rtwdev, static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link) { + static const u8 basic_rate_ie[] = {WLAN_EID_SUPP_RATES, 0x08, + 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c}; struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; u8 num = nd_config->n_match_sets, i; @@ -1427,10 +1480,11 @@ static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, nd_config->match_sets[i].ssid.ssid, nd_config->match_sets[i].ssid.ssid_len, - nd_config->ie_len); + nd_config->ie_len + sizeof(basic_rate_ie)); if (!skb) return -ENOMEM; + skb_put_data(skb, basic_rate_ie, sizeof(basic_rate_ie)); skb_put_data(skb, nd_config->ie, nd_config->ie_len); info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -1481,7 +1535,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) opt.enable = enable; opt.repeat = RTW89_SCAN_NORMAL; opt.norm_pd = max(interval, 1) * 10; /* in unit of 100ms */ - opt.delay = max(rtw_wow->nd_config->delay, 1); + opt.delay = max(rtw_wow->nd_config->delay, 1) * 1000; if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) { opt.operation = enable ? RTW89_SCAN_OP_START : RTW89_SCAN_OP_STOP; @@ -1493,7 +1547,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable) opt.opch_end = RTW89_CHAN_INVALID; } - mac->scan_offload(rtwdev, &opt, rtwvif_link, true); + rtw89_mac_scan_offload(rtwdev, &opt, rtwvif_link, true); return 0; } diff --git a/drivers/net/wireless/realtek/rtw89/wow.h b/drivers/net/wireless/realtek/rtw89/wow.h index d4b618fa4e3e5..71e07f482174f 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.h +++ b/drivers/net/wireless/realtek/rtw89/wow.h @@ -5,6 +5,9 @@ #ifndef __RTW89_WOW_H__ #define __RTW89_WOW_H__ +#define RTW89_KEY_TKIP_PN_IV16 GENMASK_ULL(15, 0) +#define RTW89_KEY_TKIP_PN_IV32 GENMASK_ULL(47, 16) + #define RTW89_KEY_PN_0 GENMASK_ULL(7, 0) #define RTW89_KEY_PN_1 GENMASK_ULL(15, 8) #define RTW89_KEY_PN_2 GENMASK_ULL(23, 16) @@ -25,6 +28,8 @@ #define RTW89_WOW_SYMBOL_CHK_PTK BIT(0) #define RTW89_WOW_SYMBOL_CHK_GTK BIT(1) +#define RTW89_MIC_KEY_LEN 8 + enum rtw89_wake_reason { RTW89_WOW_RSN_RX_PTK_REKEY = 0x1, RTW89_WOW_RSN_RX_GTK_REKEY = 0x2, @@ -74,6 +79,7 @@ struct rtw89_set_key_info_iter_data { u32 igtk_cipher; bool rx_ready; bool error; + bool tkip_gtk_swapped; }; static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev) @@ -117,9 +123,21 @@ static inline bool rtw_wow_has_mgd_features(struct rtw89_dev *rtwdev) return !bitmap_empty(rtw_wow->flags, RTW89_WOW_FLAG_NUM); } +void __rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb); + +static inline +void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + if (likely(!ieee80211_is_assoc_req(hdr->frame_control))) + return; + + __rtw89_wow_parse_akm(rtwdev, skb); +} + int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan); int rtw89_wow_resume(struct rtw89_dev *rtwdev); -void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb); #else static inline void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb)