rtw88: 8723d: Add query_rx_desc

This ops is used to parse RX descriptor to know the length of received
packet and containing PHY status. If PHY status is existing, the order is
RX descriptor, PHY status and then packet.

There are two types of PHY status, named CCK and OFDM. Their size are the
same, but formats are different.

struct ieee80211_rx_status is also filled depends on above information.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200504105010.10780-3-yhchuang@realtek.com
This commit is contained in:
Ping-Ke Shih 2020-05-04 18:50:04 +08:00 committed by Kalle Valo
parent db39a9ddac
commit 158441a2be
2 changed files with 138 additions and 0 deletions

View File

@ -172,6 +172,121 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
return 0;
}
static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
s8 min_rx_power = -120;
u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status);
pkt_stat->rx_power[RF_PATH_A] = pwdb - 97;
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
min_rx_power);
dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
}
static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
u8 rxsc, bw;
s8 min_rx_power = -120;
s8 rx_evm;
if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
else
rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status);
if (GET_PHY_STAT_P1_RF_MODE(phy_status) == 0)
bw = RTW_CHANNEL_WIDTH_20;
else if ((rxsc == 1) || (rxsc == 2))
bw = RTW_CHANNEL_WIDTH_20;
else
bw = RTW_CHANNEL_WIDTH_40;
pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110;
pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
pkt_stat->bw = bw;
pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
min_rx_power);
pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
dm_info->curr_rx_rate = pkt_stat->rate;
dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
dm_info->rx_snr[RF_PATH_A] = pkt_stat->rx_snr[RF_PATH_A] >> 1;
dm_info->cfo_tail[RF_PATH_A] = (pkt_stat->cfo_tail[RF_PATH_A] * 5) >> 1;
rx_evm = clamp_t(s8, -pkt_stat->rx_evm[RF_PATH_A] >> 1, 0, 64);
rx_evm &= 0x3F; /* 64->0: second path of 1SS rate is 64 */
dm_info->rx_evm_dbm[RF_PATH_A] = rx_evm;
}
static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
u8 page;
page = *phy_status & 0xf;
switch (page) {
case 0:
query_phy_status_page0(rtwdev, phy_status, pkt_stat);
break;
case 1:
query_phy_status_page1(rtwdev, phy_status, pkt_stat);
break;
default:
rtw_warn(rtwdev, "unused phy status page (%d)\n", page);
return;
}
}
static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_rx_status *rx_status)
{
struct ieee80211_hdr *hdr;
u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
u8 *phy_status = NULL;
memset(pkt_stat, 0, sizeof(*pkt_stat));
pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
pkt_stat->ppdu_cnt = 0;
pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
/* drv_info_sz is in unit of 8-bytes */
pkt_stat->drv_info_sz *= 8;
/* c2h cmd pkt's rx/phy status is not interested */
if (pkt_stat->is_c2h)
return;
hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
pkt_stat->drv_info_sz);
if (pkt_stat->phy_status) {
phy_status = rx_desc + desc_sz + pkt_stat->shift;
query_phy_status(rtwdev, phy_status, pkt_stat);
}
rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
}
#define BIT_CFENDFORM BIT(9)
#define BIT_WMAC_TCR_ERR0 BIT(12)
#define BIT_WMAC_TCR_ERR1 BIT(13)
@ -267,6 +382,7 @@ static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
.query_rx_desc = rtw8723d_query_rx_desc,
.mac_init = rtw8723d_mac_init,
.read_rf = rtw_phy_read_rf_sipi,
.write_rf = rtw_phy_write_rf_reg_sipi,

View File

@ -44,6 +44,28 @@ struct rtw8723d_efuse {
struct rtw8723de_efuse e;
};
/* phy status page0 */
#define GET_PHY_STAT_P0_PWDB(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
/* phy status page1 */
#define GET_PHY_STAT_P1_PWDB_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
#define GET_PHY_STAT_P1_PWDB_B(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
#define GET_PHY_STAT_P1_RF_MODE(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28))
#define GET_PHY_STAT_P1_L_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
#define GET_PHY_STAT_P1_HT_RXSC(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
#define GET_PHY_STAT_P1_RXEVM_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
#define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \
le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
#define REG_OFDM0_XAAGC1 0x0c50
#define REG_OFDM0_XBAGC1 0x0c58