wifi: rtw88: 8822c: Parse channel from IE to correct invalid hardware reports

For CCK packets we could get incorrect reports from hardware.
And this causes wrong frequencies being reported. Parse the channel
information from IE if provided by AP to fix this.

Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240724050501.7550-1-pkshih@realtek.com
This commit is contained in:
Po-Hao Huang
2024-07-24 13:05:01 +08:00
committed by Ping-Ke Shih
parent 0129e5ff28
commit 53ed4b25a7
7 changed files with 63 additions and 3 deletions
@@ -623,6 +623,7 @@ struct rtw_rx_pkt_stat {
bool crc_err;
bool decrypted;
bool is_c2h;
bool channel_invalid;
s32 signal_power;
u16 pkt_len;
+1
View File
@@ -1088,6 +1088,7 @@ static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
/* remove rx_desc */
skb_pull(new, pkt_offset);
rtw_update_rx_freq_for_invalid(rtwdev, new, &rx_status, &pkt_stat);
rtw_rx_stats(rtwdev, pkt_stat.vif, new);
memcpy(new->cb, &rx_status, sizeof(rx_status));
ieee80211_rx_napi(rtwdev->hw, NULL, new, napi);
@@ -2576,9 +2576,10 @@ static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
rx_power[RF_PATH_B] -= 110;
channel = GET_PHY_STAT_P0_CHANNEL(phy_status);
if (channel == 0)
channel = rtwdev->hal.current_channel;
rtw_set_rx_freq_band(pkt_stat, channel);
if (channel != 0)
rtw_set_rx_freq_band(pkt_stat, channel);
else
pkt_stat->channel_invalid = true;
pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A];
pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B];
+41
View File
@@ -146,6 +146,47 @@ static void rtw_set_rx_freq_by_pktstat(struct rtw_rx_pkt_stat *pkt_stat,
rx_status->band = pkt_stat->band;
}
void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
int channel = rtwdev->hal.current_channel;
size_t hdr_len, ielen;
int channel_number;
u8 *variable;
if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
goto fill_rx_status;
if (ieee80211_is_beacon(mgmt->frame_control)) {
variable = mgmt->u.beacon.variable;
hdr_len = offsetof(struct ieee80211_mgmt,
u.beacon.variable);
} else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
variable = mgmt->u.probe_resp.variable;
hdr_len = offsetof(struct ieee80211_mgmt,
u.probe_resp.variable);
} else {
goto fill_rx_status;
}
if (skb->len > hdr_len)
ielen = skb->len - hdr_len;
else
goto fill_rx_status;
channel_number = cfg80211_get_ies_channel_number(variable, ielen,
NL80211_BAND_2GHZ);
if (channel_number != -1)
channel = channel_number;
fill_rx_status:
rtw_set_rx_freq_band(pkt_stat, channel);
rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
}
EXPORT_SYMBOL(rtw_update_rx_freq_from_ie);
void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
struct rtw_rx_pkt_stat *pkt_stat,
struct ieee80211_hdr *hdr,
+13
View File
@@ -50,5 +50,18 @@ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *rx_status,
u8 *phy_status);
void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status,
struct rtw_rx_pkt_stat *pkt_stat);
static inline
void rtw_update_rx_freq_for_invalid(struct rtw_dev *rtwdev, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status,
struct rtw_rx_pkt_stat *pkt_stat)
{
if (pkt_stat->channel_invalid)
rtw_update_rx_freq_from_ie(rtwdev, skb, rx_status, pkt_stat);
}
#endif
@@ -948,6 +948,7 @@ static void rtw_sdio_rx_skb(struct rtw_dev *rtwdev, struct sk_buff *skb,
skb_put(skb, pkt_stat->pkt_len);
skb_reserve(skb, pkt_offset);
rtw_update_rx_freq_for_invalid(rtwdev, skb, rx_status, pkt_stat);
rtw_rx_stats(rtwdev, pkt_stat->vif, skb);
ieee80211_rx_irqsafe(rtwdev->hw, skb);
+2
View File
@@ -579,6 +579,8 @@ static void rtw_usb_rx_handler(struct work_struct *work)
skb_put(skb, pkt_stat.pkt_len);
skb_reserve(skb, pkt_offset);
rtw_update_rx_freq_for_invalid(rtwdev, skb, &rx_status, &pkt_stat);
memcpy(skb->cb, &rx_status, sizeof(rx_status));
ieee80211_rx_irqsafe(rtwdev->hw, skb);
}