a304cd7d0504c226ae35f80fcfcf28ecea3f3421
[openwrt/openwrt.git] /
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
5 hardware reports
6
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.
10
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
14 ---
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(-)
23
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 {
27 bool crc_err;
28 bool decrypted;
29 bool is_c2h;
30 + bool channel_invalid;
31
32 s32 signal_power;
33 u16 pkt_len;
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
37 /* remove rx_desc */
38 skb_pull(new, pkt_offset);
39
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;
48
49 channel = GET_PHY_STAT_P0_CHANNEL(phy_status);
50 - if (channel == 0)
51 - channel = rtwdev->hal.current_channel;
52 - rtw_set_rx_freq_band(pkt_stat, channel);
53 + if (channel != 0)
54 + rtw_set_rx_freq_band(pkt_stat, channel);
55 + else
56 + pkt_stat->channel_invalid = true;
57
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;
64 }
65
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)
69 +{
70 + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
71 + int channel = rtwdev->hal.current_channel;
72 + size_t hdr_len, ielen;
73 + int channel_number;
74 + u8 *variable;
75 +
76 + if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
77 + goto fill_rx_status;
78 +
79 + if (ieee80211_is_beacon(mgmt->frame_control)) {
80 + variable = mgmt->u.beacon.variable;
81 + hdr_len = offsetof(struct ieee80211_mgmt,
82 + u.beacon.variable);
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);
87 + } else {
88 + goto fill_rx_status;
89 + }
90 +
91 + if (skb->len > hdr_len)
92 + ielen = skb->len - hdr_len;
93 + else
94 + goto fill_rx_status;
95 +
96 + channel_number = cfg80211_get_ies_channel_number(variable, ielen,
97 + NL80211_BAND_2GHZ);
98 + if (channel_number != -1)
99 + channel = channel_number;
100 +
101 +fill_rx_status:
102 + rtw_set_rx_freq_band(pkt_stat, channel);
103 + rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
104 +}
105 +EXPORT_SYMBOL(rtw_update_rx_freq_from_ie);
106 +
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,
115 u8 *phy_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);
119 +
120 +static inline
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)
124 +{
125 + if (pkt_stat->channel_invalid)
126 + rtw_update_rx_freq_from_ie(rtwdev, skb, rx_status, pkt_stat);
127 +}
128 +
129
130 #endif
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);
136
137 + rtw_update_rx_freq_for_invalid(rtwdev, skb, rx_status, pkt_stat);
138 rtw_rx_stats(rtwdev, pkt_stat->vif, skb);
139
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
144
145 skb_put(skb, pkt_stat.pkt_len);
146 skb_reserve(skb, pkt_offset);
147 +
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);
151 }