Skip to content

Commit f100038

Browse files
author
Ping-Ke Shih
committed
wifi: rtw89: purge obsoleted scan events with software sequence number
The queued and obsoleted scan events can be wrongly treated as events of new scan request, causing unexpected scan result. Attach a software sequence number to scan request and its corresponding events. When a new scan request is acknowledged by firmware, purge the scan events if its sequence number is not belong to current request. Normal case: mac80211 event work event BH ------------- ---------- -------- scan req kernel-patches#1 ---->o | <----o <...........................o o | <--------------------------+ ieee80211_scan_completed() Abnormal case (late event work): mac80211 event work event BH ------------- ---------- -------- scan req kernel-patches#1 ---->o | <----o <...........................o o kernel-patches#1 scan cancel kernel-patches#2 ->o | <----o <...........................o o kernel-patches#2 | (patch to avoid this) scan req kernel-patches#3 ---->o | | | <----o <..........|................o | o kernel-patches#3 <--------------------------+ ieee80211_scan_completed() Signed-off-by: Ping-Ke Shih <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent b552a3e commit f100038

File tree

6 files changed

+68
-2
lines changed

6 files changed

+68
-2
lines changed

drivers/net/wireless/realtek/rtw89/core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5574,6 +5574,7 @@ struct rtw89_hw_scan_info {
55745574
bool connected;
55755575
bool abort;
55765576
u16 delay; /* in unit of ms */
5577+
u8 seq: 2;
55775578
};
55785579

55795580
enum rtw89_phy_bb_gain_band {

drivers/net/wireless/realtek/rtw89/fw.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6759,6 +6759,34 @@ void rtw89_fw_c2h_work(struct wiphy *wiphy, struct wiphy_work *work)
67596759
}
67606760
}
67616761

6762+
void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev)
6763+
{
6764+
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
6765+
struct sk_buff *skb, *tmp;
6766+
int limit;
6767+
6768+
lockdep_assert_wiphy(rtwdev->hw->wiphy);
6769+
6770+
limit = skb_queue_len(&rtwdev->c2h_queue);
6771+
6772+
skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) {
6773+
struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb);
6774+
6775+
if (--limit < 0)
6776+
return;
6777+
6778+
if (!attr->is_scan_event || attr->scan_seq == scan_info->seq)
6779+
continue;
6780+
6781+
rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
6782+
"purge obsoleted scan event with seq=%d (cur=%d)\n",
6783+
attr->scan_seq, scan_info->seq);
6784+
6785+
skb_unlink(skb, &rtwdev->c2h_queue);
6786+
dev_kfree_skb_any(skb);
6787+
}
6788+
}
6789+
67626790
static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev,
67636791
struct rtw89_mac_h2c_info *info)
67646792
{
@@ -8052,7 +8080,8 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev,
80528080
opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID;
80538081
}
80548082

8055-
ret = mac->scan_offload(rtwdev, &opt, rtwvif_link, false);
8083+
ret = rtw89_mac_scan_offload(rtwdev, &opt, rtwvif_link, false);
8084+
80568085
out:
80578086
return ret;
80588087
}

drivers/net/wireless/realtek/rtw89/fw.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3570,6 +3570,8 @@ struct rtw89_fw_c2h_attr {
35703570
u8 class;
35713571
u8 func;
35723572
u16 len;
3573+
u8 is_scan_event: 1;
3574+
u8 scan_seq: 2;
35733575
};
35743576

35753577
static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb)
@@ -4755,6 +4757,7 @@ int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev,
47554757
struct rtw89_sta_link *rtwsta_link);
47564758
void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h);
47574759
void rtw89_fw_c2h_work(struct wiphy *wiphy, struct wiphy_work *work);
4760+
void rtw89_fw_c2h_purge_obsoleted_scan_events(struct rtw89_dev *rtwdev);
47584761
int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
47594762
struct rtw89_vif_link *rtwvif_link,
47604763
struct rtw89_sta_link *rtwsta_link,

drivers/net/wireless/realtek/rtw89/mac.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5165,6 +5165,7 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
51655165
{
51665166
/* N.B. This will run in interrupt context. */
51675167
struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
5168+
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
51685169
struct rtw89_wait_info *ps_wait = &rtwdev->mac.ps_wait;
51695170
const struct rtw89_c2h_done_ack *c2h =
51705171
(const struct rtw89_c2h_done_ack *)skb_c2h->data;
@@ -5207,9 +5208,11 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
52075208
h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN;
52085209
break;
52095210
case H2C_FUNC_SCANOFLD:
5211+
scan_info->seq++;
52105212
cond = RTW89_SCANOFLD_WAIT_COND_START;
52115213
break;
52125214
case H2C_FUNC_SCANOFLD_BE:
5215+
scan_info->seq++;
52135216
cond = RTW89_SCANOFLD_BE_WAIT_COND_START;
52145217
h2c_return &= RTW89_C2H_SCAN_DONE_ACK_RETURN;
52155218
break;
@@ -5706,10 +5709,15 @@ static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev,
57065709
const struct rtw89_c2h_scanofld *c2h =
57075710
(const struct rtw89_c2h_scanofld *)skb->data;
57085711
struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
5712+
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
5713+
struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb);
57095714
struct rtw89_completion_data data = {};
57105715
unsigned int cond;
57115716
u8 status, reason;
57125717

5718+
attr->is_scan_event = 1;
5719+
attr->scan_seq = scan_info->seq;
5720+
57135721
status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
57145722
reason = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_RSN);
57155723
data.err = status != RTW89_SCAN_STATUS_SUCCESS;

drivers/net/wireless/realtek/rtw89/mac.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define __RTW89_MAC_H__
77

88
#include "core.h"
9+
#include "fw.h"
910
#include "reg.h"
1011

1112
#define MAC_MEM_DUMP_PAGE_SIZE_AX 0x40000
@@ -1583,4 +1584,28 @@ void rtw89_fwdl_secure_idmem_share_mode(struct rtw89_dev *rtwdev, u8 mode)
15831584

15841585
return mac->fwdl_secure_idmem_share_mode(rtwdev, mode);
15851586
}
1587+
1588+
static inline
1589+
int rtw89_mac_scan_offload(struct rtw89_dev *rtwdev,
1590+
struct rtw89_scan_option *option,
1591+
struct rtw89_vif_link *rtwvif_link,
1592+
bool wowlan)
1593+
{
1594+
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1595+
int ret;
1596+
1597+
ret = mac->scan_offload(rtwdev, option, rtwvif_link, wowlan);
1598+
1599+
if (option->enable) {
1600+
/*
1601+
* At this point, new scan request is acknowledged by firmware,
1602+
* so scan events of previous scan request become obsoleted.
1603+
* Purge the queued scan events to prevent interference to
1604+
* current new request.
1605+
*/
1606+
rtw89_fw_c2h_purge_obsoleted_scan_events(rtwdev);
1607+
}
1608+
1609+
return ret;
1610+
}
15861611
#endif

drivers/net/wireless/realtek/rtw89/wow.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,7 @@ static int rtw89_pno_scan_offload(struct rtw89_dev *rtwdev, bool enable)
14891489
opt.opch_end = RTW89_CHAN_INVALID;
14901490
}
14911491

1492-
mac->scan_offload(rtwdev, &opt, rtwvif_link, true);
1492+
rtw89_mac_scan_offload(rtwdev, &opt, rtwvif_link, true);
14931493

14941494
return 0;
14951495
}

0 commit comments

Comments
 (0)