On Tue, 2021-07-06 at 08:56 +0800, Doug Brewer wrote: > On Mon, Jul 5, 2021 at 9:42 AM Pkshih <pkshih@xxxxxxxxxxx> wrote: > > > -----Original Message----- > > > From: Doug Brewer [mailto:brewerdoug@xxxxxxxxx] > > > Sent: Sunday, July 04, 2021 10:35 PM > > > To: linux-wireless@xxxxxxxxxxxxxxx > > > Subject: rtw89: product id 0xa85a support on Linux? > > > > > > Hello, > > > > > > The HP Laptop 15s-eq2028ur have a Realtek 802.11ax device. lspci > > -n shows > > > > > > 01:00.0 Network controller [0280]: Realtek Semiconductor Co., > > Ltd. Device [10ec: > > > a85a] > > > > > > I tried pkshih's rtw89 patchsets [1] and added PID to > > rtw89_pci_id_table. > > > Scanning works but cannot connect to access points. > > > dmesg shows like (hiding MAC address): > > > > > > rtw89_pci 0000:01:00.0: Firmware version 0.13.8.0, cmd version 0, > > type 1 > > > rtw89_pci 0000:01:00.0: Firmware version 0.13.8.0, cmd version 0, > > type 3 > > > rtw89_pci 0000:01:00.0: chip rfe_type is 1 > > > wlan0: authenticate with xx:xx:xx:xx:xx:xx > > > wlan0: send auth to xx:xx:xx:xx:xx:xx (try 1/3) > > > wlan0: authenticated > > > wlan0: associate with xx:xx:xx:xx:xx:xx (try 1/3) > > > wlan0: RX AssocResp from xx:xx:xx:xx:xx:xx (capab=0x411 status=0 > > aid=1) > > > wlan0: associated > > > rtw89_pci 0000:01:00.0: c2h reg timeout > > > rtw89_pci 0000:01:00.0: FW does not process h2c registers > > > rtw89_pci 0000:01:00.0: timed out to flush queues > > > > > > rtw89 will be the driver to support this wifi model? Thanks. > > > > > > > The ID 0xa85a is a variant of 8852AE, and rtw89 will support it > > later. > > I'll provide you a patch when I have a draft implementation. > > Thanks! I'm happy to test your patch. > Before trying new patch, please upgrade your firmware to v0.13.24.0 that you can download it via my github: https://github.com/pkshih/linux-firmware/blob/a5b79c4790da3eb3690e23554225ef8db464f2c6/rtw89/rtw8852a_fw.bin Then, check kernel log to confirm the version like dmesg you mentioned. The path of the attachment patch isn't full path, so please apply it with specified path drivers/net/wireless/realtek/rtw89/ -- Ping-Ke
diff --git a/coex.c b/coex.c index 868aa9d..c224712 100644 --- a/coex.c +++ b/coex.c @@ -4449,6 +4449,7 @@ void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m) { const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_hal *hal = &rtwdev->hal; struct rtw89_btc *btc = &rtwdev->btc; struct rtw89_btc_dm *dm = &btc->dm; struct rtw89_btc_bt_info *bt = &btc->cx.bt; @@ -4515,8 +4516,8 @@ static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m) "1Ant_Pos:S1, " : "1Ant_Pos:S0, "))); seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n", - btc->cx.other.type, rtwdev->dbcc_en, chip->tx_nss, - chip->rx_nss); + btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss, + hal->rx_nss); } static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m) diff --git a/core.c b/core.c index 3bd31e6..f5c1bf7 100644 --- a/core.c +++ b/core.c @@ -1829,33 +1829,49 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, static void rtw89_init_ht_cap(struct rtw89_dev *rtwdev, struct ieee80211_sta_ht_cap *ht_cap) { + static const __le16 highest[] = {cpu_to_le16(150), cpu_to_le16(300)}; + struct rtw89_hal *hal = &rtwdev->hal; + u8 nss = hal->rx_nss; + int i; + ht_cap->ht_supported = true; ht_cap->cap = 0; ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_TX_STBC | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); - ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING; - ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_SGI_40; ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0xFF; + for (i = 0; i < 4; i++) + ht_cap->mcs.rx_mask[i] = i < nss ? 0xFF : 0; ht_cap->mcs.rx_mask[4] = 0x01; - ht_cap->mcs.rx_highest = cpu_to_le16(300); + ht_cap->mcs.rx_highest = nss <= ARRAY_SIZE(highest) ? highest[nss - 1] : 0; } static void rtw89_init_vht_cap(struct rtw89_dev *rtwdev, struct ieee80211_sta_vht_cap *vht_cap) { - u16 mcs_map; - __le16 highest; + static const __le16 highest[] = {cpu_to_le16(433), cpu_to_le16(867)}; + struct rtw89_hal *hal = &rtwdev->hal; + u16 tx_mcs_map = 0, rx_mcs_map = 0; u8 sts_cap = 3; + int i; + + for (i = 0; i < 8; i++) { + if (i < hal->tx_nss) + tx_mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); + else + tx_mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); + if (i < hal->rx_nss) + rx_mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); + else + rx_mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); + } vht_cap->vht_supported = true; vht_cap->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | @@ -1869,20 +1885,12 @@ static void rtw89_init_vht_cap(struct rtw89_dev *rtwdev, vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; vht_cap->cap |= sts_cap << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; - - mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; - highest = cpu_to_le16(867); - mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; - vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); - vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); - vht_cap->vht_mcs.rx_highest = highest; - vht_cap->vht_mcs.tx_highest = highest; + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rx_mcs_map); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(tx_mcs_map); + vht_cap->vht_mcs.rx_highest = hal->rx_nss <= ARRAY_SIZE(highest) ? + highest[hal->rx_nss - 1] : 0; + vht_cap->vht_mcs.tx_highest = hal->tx_nss <= ARRAY_SIZE(highest) ? + highest[hal->tx_nss - 1] : 0; } #define RTW89_SBAND_IFTYPES_NR 2 @@ -1898,7 +1906,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev, (chip->chip_id == RTL8852B && hal->cv == CHIP_CAV); u16 mcs_map = 0; int i; - int nss = chip->rx_nss; + int nss = hal->rx_nss; int idx = 0; iftype_data = kcalloc(RTW89_SBAND_IFTYPES_NR, sizeof(*iftype_data), GFP_KERNEL); @@ -2217,6 +2225,10 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev) if (ret) return ret; + ret = rtw89_mac_setup_phycap(rtwdev); + if (ret) + return ret; + rtw89_mac_pwr_off(rtwdev); return 0; diff --git a/core.h b/core.h index d535b92..42ebd58 100644 --- a/core.h +++ b/core.h @@ -2338,6 +2338,8 @@ struct rtw89_hal { u32 sw_amsdu_max_size; u32 antenna_tx; u32 antenna_rx; + u8 tx_nss; + u8 rx_nss; }; #define RTW89_MAX_MAC_ID_NUM 128 diff --git a/fw.c b/fw.c index 7be5ce2..d0480f1 100644 --- a/fw.c +++ b/fw.c @@ -753,7 +753,7 @@ static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev, { bool ppe_th; u8 ppe16, ppe8; - u8 nss = min(sta->rx_nss, rtwdev->chip->tx_nss) - 1; + u8 nss = min(sta->rx_nss, rtwdev->hal.tx_nss) - 1; u8 ppe_thres_hdr = sta->he_cap.ppe_thres[0]; u8 ru_bitmap; u8 n, idx, sh; diff --git a/fw.h b/fw.h index 9f7c452..e00bb5e 100644 --- a/fw.h +++ b/fw.h @@ -63,6 +63,22 @@ enum rtw89_mac_c2h_type { RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF }; +struct rtw89_c2h_phy_cap { + u32 func:7; + u32 ack:1; + u32 len:4; + u32 seq:4; + u32 rx_nss:8; + u32 bw:8; + + u32 tx_nss:8; + u32 prot:8; + u32 nic:8; + u32 wl_func:8; + + u32 hw_type:8; +} __packed; + enum rtw89_fw_c2h_category { RTW89_C2H_CAT_TEST, RTW89_C2H_CAT_MAC, diff --git a/mac.c b/mac.c index e00652e..46afbb0 100644 --- a/mac.c +++ b/mac.c @@ -2208,6 +2208,51 @@ static int cmac_init(struct rtw89_dev *rtwdev, u8 mac_idx) return ret; } +static int rtw89_mac_read_phycap(struct rtw89_dev *rtwdev, + struct rtw89_mac_c2h_info *c2h_info) +{ + struct rtw89_mac_h2c_info h2c_info = {0}; + u32 ret; + + h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_GET_FEATURE; + h2c_info.content_len = 0; + + ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, c2h_info); + if (ret) + return ret; + + if (c2h_info->id != RTW89_FWCMD_C2HREG_FUNC_PHY_CAP) + return -EINVAL; + + return 0; +} + +int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) +{ + struct rtw89_hal *hal = &rtwdev->hal; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_mac_c2h_info c2h_info = {0}; + struct rtw89_c2h_phy_cap *cap = + (struct rtw89_c2h_phy_cap *)&c2h_info.c2hreg[0]; + u32 ret; + + ret = rtw89_mac_read_phycap(rtwdev, &c2h_info); + if (ret) + return ret; + + hal->tx_nss = cap->tx_nss ? + min_t(u8, cap->tx_nss, chip->tx_nss) : chip->tx_nss; + hal->rx_nss = cap->rx_nss ? + min_t(u8, cap->rx_nss, chip->rx_nss) : chip->rx_nss; + + rtw89_debug(rtwdev, RTW89_DBG_FW, + "phycap hal/phy/chip: tx_nss=0x%x/0x%x/0x%x rx_nss=0x%x/0x%x/0x%x\n", + hal->tx_nss, cap->tx_nss, chip->tx_nss, + hal->rx_nss, cap->rx_nss, chip->rx_nss); + + return 0; +} + static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band, u16 tx_en_u16, u16 mask_u16) { diff --git a/mac.h b/mac.h index efff7cb..b052878 100644 --- a/mac.h +++ b/mac.h @@ -812,6 +812,7 @@ u32 rtw89_mac_get_err_status(struct rtw89_dev *rtwdev); int rtw89_mac_set_err_status(struct rtw89_dev *rtwdev, u32 err); void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len, u8 class, u8 func); +int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev); int rtw89_mac_stop_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u16 *tx_en, enum rtw89_sch_tx_sel sel); int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u16 tx_en); diff --git a/pci.c b/pci.c index 155f463..b5aaf0f 100644 --- a/pci.c +++ b/pci.c @@ -3012,6 +3012,7 @@ static void rtw89_pci_remove(struct pci_dev *pdev) static const struct pci_device_id rtw89_pci_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8852), .driver_data = RTL8852A }, + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xa85a), .driver_data = RTL8852A }, {}, }; MODULE_DEVICE_TABLE(pci, rtw89_pci_id_table); diff --git a/phy.c b/phy.c index de2b000..ac75193 100644 --- a/phy.c +++ b/phy.c @@ -245,7 +245,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, } if (mode >= RTW89_RA_MODE_HT) { - for (i = 0; i < rtwdev->chip->tx_nss; i++) + for (i = 0; i < rtwdev->hal.tx_nss; i++) high_rate_mask |= high_rate_masks[i]; ra_mask &= high_rate_mask; if (mode & RTW89_RA_MODE_OFDM) @@ -292,7 +292,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, ra->macid = rtwsta->mac_id; ra->stbc_cap = stbc_en; ra->ldpc_cap = ldpc_en; - ra->ss_num = min(sta->rx_nss, rtwdev->chip->tx_nss) - 1; + ra->ss_num = min(sta->rx_nss, rtwdev->hal.tx_nss) - 1; ra->en_sgi = sgi; ra->ra_mask = ra_mask;