Backport support for RTL8812AU/RTL8821AU USB adapters Manually backported patch: 045-v6.13-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver Patches from 046 to 051 are pending. Signed-off-by: Marty Jones <mj8263788@gmail.com> Link: https://github.com/openwrt/openwrt/pull/17079 [Move BPAUTO_WANT_DEV_COREDUMP to original patch] Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> (cherry picked from commit 36f6d6ddcd67e7e32e2281baf5814ece81fad402)
152 lines
5.2 KiB
Diff
152 lines
5.2 KiB
Diff
From 53ed4b25a79aeec5991c2dc579e635b136ef7676 Mon Sep 17 00:00:00 2001
|
|
From: Po-Hao Huang <phhuang@realtek.com>
|
|
Date: Wed, 24 Jul 2024 13:05:01 +0800
|
|
Subject: [PATCH] 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
|
|
---
|
|
drivers/net/wireless/realtek/rtw88/main.h | 1 +
|
|
drivers/net/wireless/realtek/rtw88/pci.c | 1 +
|
|
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 7 ++--
|
|
drivers/net/wireless/realtek/rtw88/rx.c | 41 +++++++++++++++++++
|
|
drivers/net/wireless/realtek/rtw88/rx.h | 13 ++++++
|
|
drivers/net/wireless/realtek/rtw88/sdio.c | 1 +
|
|
drivers/net/wireless/realtek/rtw88/usb.c | 2 +
|
|
7 files changed, 63 insertions(+), 3 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/realtek/rtw88/main.h
|
|
+++ b/drivers/net/wireless/realtek/rtw88/main.h
|
|
@@ -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;
|
|
--- a/drivers/net/wireless/realtek/rtw88/pci.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
|
|
@@ -1088,6 +1088,7 @@ static u32 rtw_pci_rx_napi(struct rtw_de
|
|
/* 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);
|
|
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
@@ -2576,9 +2576,10 @@ static void query_phy_status_page0(struc
|
|
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];
|
|
--- a/drivers/net/wireless/realtek/rtw88/rx.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/rx.c
|
|
@@ -146,6 +146,47 @@ static void rtw_set_rx_freq_by_pktstat(s
|
|
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,
|
|
--- a/drivers/net/wireless/realtek/rtw88/rx.h
|
|
+++ b/drivers/net/wireless/realtek/rtw88/rx.h
|
|
@@ -50,5 +50,18 @@ void rtw_rx_fill_rx_status(struct rtw_de
|
|
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
|
|
--- a/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/sdio.c
|
|
@@ -948,6 +948,7 @@ static void rtw_sdio_rx_skb(struct rtw_d
|
|
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);
|
|
--- a/drivers/net/wireless/realtek/rtw88/usb.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
@@ -579,6 +579,8 @@ static void rtw_usb_rx_handler(struct wo
|
|
|
|
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);
|
|
}
|