]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: rtw88: 8822c: Parse channel from IE to correct invalid hardware reports
authorPo-Hao Huang <phhuang@realtek.com>
Wed, 24 Jul 2024 05:05:01 +0000 (13:05 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Fri, 2 Aug 2024 01:08:10 +0000 (09:08 +0800)
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
drivers/net/wireless/realtek/rtw88/pci.c
drivers/net/wireless/realtek/rtw88/rtw8822c.c
drivers/net/wireless/realtek/rtw88/rx.c
drivers/net/wireless/realtek/rtw88/rx.h
drivers/net/wireless/realtek/rtw88/sdio.c
drivers/net/wireless/realtek/rtw88/usb.c

index b60a0f840e13f21f1b5cfdce960db7afc26bffb5..12b564ad3a58c7af180317c518f68562c4443e44 100644 (file)
@@ -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;
index a5b9d6c7be37e619de11e5f8d274cb278aaa3b79..5d0580da13fb90127673b200bf432b1124ec2fb2 100644 (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);
index e265a35184abeefb10676592c3495828f99ecfe5..1dbe1cdbc3fd4510f990e78681622b85594a8cdc 100644 (file)
@@ -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];
index 84aedabdf28530d2592f34482682d0db146ae1ea..66f9419588cf3a8f182f3cae33b29cbd1f366dda 100644 (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,
index 8a072dd3d73ce41e8b712bc68ceb211f762ca0fb..9f001911298777cc9307e701ba46cc2d7048df53 100644 (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
index 0cae5746f540fa8a4ff68e2e125c3c46d391daf5..763aa8212a4b78a590f906b655f66a21d05c1c61 100644 (file)
@@ -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);
index 251a5726f3ee6ef484f01464a82527e300fe0b12..9145c11a063ea72fe00472f71662ff0440f149eb 100644 (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);
        }