1 From 53ed4b25a79aeec5991c2dc579e635b136ef7676 Mon Sep 17 00:00:00 2001
2 From: Po-Hao Huang <phhuang@realtek.com>
3 Date: Wed, 24 Jul 2024 13:05:01 +0800
4 Subject: [PATCH] wifi: rtw88: 8822c: Parse channel from IE to correct invalid
7 For CCK packets we could get incorrect reports from hardware.
8 And this causes wrong frequencies being reported. Parse the channel
9 information from IE if provided by AP to fix this.
11 Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
12 Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
13 Link: https://patch.msgid.link/20240724050501.7550-1-pkshih@realtek.com
15 drivers/net/wireless/realtek/rtw88/main.h | 1 +
16 drivers/net/wireless/realtek/rtw88/pci.c | 1 +
17 drivers/net/wireless/realtek/rtw88/rtw8822c.c | 7 ++--
18 drivers/net/wireless/realtek/rtw88/rx.c | 41 +++++++++++++++++++
19 drivers/net/wireless/realtek/rtw88/rx.h | 13 ++++++
20 drivers/net/wireless/realtek/rtw88/sdio.c | 1 +
21 drivers/net/wireless/realtek/rtw88/usb.c | 2 +
22 7 files changed, 63 insertions(+), 3 deletions(-)
24 --- a/drivers/net/wireless/realtek/rtw88/main.h
25 +++ b/drivers/net/wireless/realtek/rtw88/main.h
26 @@ -623,6 +623,7 @@ struct rtw_rx_pkt_stat {
30 + bool channel_invalid;
34 --- a/drivers/net/wireless/realtek/rtw88/pci.c
35 +++ b/drivers/net/wireless/realtek/rtw88/pci.c
36 @@ -1088,6 +1088,7 @@ static u32 rtw_pci_rx_napi(struct rtw_de
38 skb_pull(new, pkt_offset);
40 + rtw_update_rx_freq_for_invalid(rtwdev, new, &rx_status, &pkt_stat);
41 rtw_rx_stats(rtwdev, pkt_stat.vif, new);
42 memcpy(new->cb, &rx_status, sizeof(rx_status));
43 ieee80211_rx_napi(rtwdev->hw, NULL, new, napi);
44 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
45 +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
46 @@ -2576,9 +2576,10 @@ static void query_phy_status_page0(struc
47 rx_power[RF_PATH_B] -= 110;
49 channel = GET_PHY_STAT_P0_CHANNEL(phy_status);
51 - channel = rtwdev->hal.current_channel;
52 - rtw_set_rx_freq_band(pkt_stat, channel);
54 + rtw_set_rx_freq_band(pkt_stat, channel);
56 + pkt_stat->channel_invalid = true;
58 pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A];
59 pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B];
60 --- a/drivers/net/wireless/realtek/rtw88/rx.c
61 +++ b/drivers/net/wireless/realtek/rtw88/rx.c
62 @@ -146,6 +146,47 @@ static void rtw_set_rx_freq_by_pktstat(s
63 rx_status->band = pkt_stat->band;
66 +void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
67 + struct ieee80211_rx_status *rx_status,
68 + struct rtw_rx_pkt_stat *pkt_stat)
70 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
71 + int channel = rtwdev->hal.current_channel;
72 + size_t hdr_len, ielen;
76 + if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
77 + goto fill_rx_status;
79 + if (ieee80211_is_beacon(mgmt->frame_control)) {
80 + variable = mgmt->u.beacon.variable;
81 + hdr_len = offsetof(struct ieee80211_mgmt,
83 + } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
84 + variable = mgmt->u.probe_resp.variable;
85 + hdr_len = offsetof(struct ieee80211_mgmt,
86 + u.probe_resp.variable);
88 + goto fill_rx_status;
91 + if (skb->len > hdr_len)
92 + ielen = skb->len - hdr_len;
94 + goto fill_rx_status;
96 + channel_number = cfg80211_get_ies_channel_number(variable, ielen,
98 + if (channel_number != -1)
99 + channel = channel_number;
102 + rtw_set_rx_freq_band(pkt_stat, channel);
103 + rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
105 +EXPORT_SYMBOL(rtw_update_rx_freq_from_ie);
107 void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
108 struct rtw_rx_pkt_stat *pkt_stat,
109 struct ieee80211_hdr *hdr,
110 --- a/drivers/net/wireless/realtek/rtw88/rx.h
111 +++ b/drivers/net/wireless/realtek/rtw88/rx.h
112 @@ -50,5 +50,18 @@ void rtw_rx_fill_rx_status(struct rtw_de
113 struct ieee80211_hdr *hdr,
114 struct ieee80211_rx_status *rx_status,
116 +void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
117 + struct ieee80211_rx_status *rx_status,
118 + struct rtw_rx_pkt_stat *pkt_stat);
121 +void rtw_update_rx_freq_for_invalid(struct rtw_dev *rtwdev, struct sk_buff *skb,
122 + struct ieee80211_rx_status *rx_status,
123 + struct rtw_rx_pkt_stat *pkt_stat)
125 + if (pkt_stat->channel_invalid)
126 + rtw_update_rx_freq_from_ie(rtwdev, skb, rx_status, pkt_stat);
131 --- a/drivers/net/wireless/realtek/rtw88/sdio.c
132 +++ b/drivers/net/wireless/realtek/rtw88/sdio.c
133 @@ -948,6 +948,7 @@ static void rtw_sdio_rx_skb(struct rtw_d
134 skb_put(skb, pkt_stat->pkt_len);
135 skb_reserve(skb, pkt_offset);
137 + rtw_update_rx_freq_for_invalid(rtwdev, skb, rx_status, pkt_stat);
138 rtw_rx_stats(rtwdev, pkt_stat->vif, skb);
140 ieee80211_rx_irqsafe(rtwdev->hw, skb);
141 --- a/drivers/net/wireless/realtek/rtw88/usb.c
142 +++ b/drivers/net/wireless/realtek/rtw88/usb.c
143 @@ -579,6 +579,8 @@ static void rtw_usb_rx_handler(struct wo
145 skb_put(skb, pkt_stat.pkt_len);
146 skb_reserve(skb, pkt_offset);
148 + rtw_update_rx_freq_for_invalid(rtwdev, skb, &rx_status, &pkt_stat);
149 memcpy(skb->cb, &rx_status, sizeof(rx_status));
150 ieee80211_rx_irqsafe(rtwdev->hw, skb);