diff options
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/main.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/pci.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rtw8822c.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rx.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/rx.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/sdio.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/usb.c | 2 |
7 files changed, 63 insertions, 3 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index b60a0f840e13..12b564ad3a58 100644 --- 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; diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index a5b9d6c7be37..5d0580da13fb 100644 --- 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_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); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index e265a35184ab..1dbe1cdbc3fd 100644 --- 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(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]; diff --git a/drivers/net/wireless/realtek/rtw88/rx.c b/drivers/net/wireless/realtek/rtw88/rx.c index 84aedabdf285..66f9419588cf 100644 --- 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(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, diff --git a/drivers/net/wireless/realtek/rtw88/rx.h b/drivers/net/wireless/realtek/rtw88/rx.h index 8a072dd3d73c..9f0019112987 100644 --- 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_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 diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 0cae5746f540..763aa8212a4b 100644 --- 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_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); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 251a5726f3ee..9145c11a063e 100644 --- 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 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); } |