* [PATCH 1/3] wifi: rtw89: fix proceeding MCC with wrong scanning state after sequence changes
2024-12-31 0:48 [PATCH 0/3] wifi: rtw89: fixes MCC and header conversion issues Ping-Ke Shih
@ 2024-12-31 0:48 ` Ping-Ke Shih
2025-01-12 1:19 ` Ping-Ke Shih
2024-12-31 0:48 ` [PATCH 2/3] wifi: rtw89: chan: fix soft lockup in rtw89_entity_recalc_mgnt_roles() Ping-Ke Shih
2024-12-31 0:48 ` [PATCH 3/3] wifi: rtw89: correct header conversion rule for MLO only Ping-Ke Shih
2 siblings, 1 reply; 5+ messages in thread
From: Ping-Ke Shih @ 2024-12-31 0:48 UTC (permalink / raw)
To: linux-wireless; +Cc: phhuang, kevin_yang
From: Zong-Zhe Yang <kevin_yang@realtek.com>
When starting/proceeding MCC, it will abort an ongoing hw scan process.
In the proceeding cases, it unexpectedly tries to abort a non-exist hw
scan process. Then, a trace shown at the bottom will happen. This problem
is caused by a previous commit which changed some call sequence inside
rtw89_hw_scan_complete() to fix some coex problems. These changes lead
to our scanning flag was not cleared when proceeding MCC. To keep the
fixes on coex, and resolve the problem here, re-consider the related
call sequence.
The known sequence requirements are listed below.
* the old sequence:
A. notify coex
B. clear scanning flag
C. proceed chanctx
C-1. set channel
C-2. proceed MCC
(the problem: A needs to be after C-1)
* the current sequence:
C. proceed chanctx
C-1. set channel
C-2. proceed MCC
A. notify coex
B. clear scanning flag
(the problem: C-2 needs to be after B)
So, now let hw scan caller pass a callback to proceed chanctx if needed.
Then, the new sequence will be like the below.
C-1. set channel
A. notify coex
B. clear scanning flag
C-2. proceed MCC
The following is the kernel log for the problem in current sequence.
rtw89_8852be 0000:04:00.0: rtw89_hw_scan_offload failed ret -110
------------[ cut here ]------------
[...]
CPU: 2 PID: 3991 Comm: kworker/u16:0 Tainted: G OE 6.6.17 #3
Hardware name: LENOVO 2356AD1/2356AD1, BIOS G7ETB3WW (2.73 ) 11/28/2018
Workqueue: events_unbound wiphy_work_cancel [cfg80211]
RIP: 0010:ieee80211_sched_scan_stopped+0xaea/0xd80 [mac80211]
Code: 9c 24 d0 11 00 00 49 39 dd 0f 85 46 ff ff ff 4c 89 e7 e8 09 2d
RSP: 0018:ffffb27783643d48 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: ffff8a2280964bc0 RSI: 0000000000000000 RDI: ffff8a23df580900
RBP: ffffb27783643d88 R08: 0000000000000001 R09: 0000000000000400
R10: 0000000000000000 R11: 0000000000008268 R12: ffff8a23df580900
R13: ffff8a23df581b00 R14: 0000000000000000 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff8a258e680000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f26a0654000 CR3: 000000002ea2e002 CR4: 00000000001706e0
Call Trace:
<TASK>
? show_regs+0x68/0x70
? ieee80211_sched_scan_stopped+0xaea/0xd80 [mac80211]
? __warn+0x8f/0x150
? ieee80211_sched_scan_stopped+0xaea/0xd80 [mac80211]
? report_bug+0x1f5/0x200
? handle_bug+0x46/0x80
? exc_invalid_op+0x19/0x70
? asm_exc_invalid_op+0x1b/0x20
? ieee80211_sched_scan_stopped+0xaea/0xd80 [mac80211]
ieee80211_scan_work+0x14a/0x650 [mac80211]
? __queue_work+0x10f/0x410
wiphy_work_cancel+0x2fb/0x310 [cfg80211]
process_scheduled_works+0x9d/0x390
? __pfx_worker_thread+0x10/0x10
worker_thread+0x15b/0x2d0
? __pfx_worker_thread+0x10/0x10
kthread+0x108/0x140
? __pfx_kthread+0x10/0x10
ret_from_fork+0x3c/0x60
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1b/0x30
</TASK>
---[ end trace 0000000000000000 ]---
Fixes: f16c40acd319 ("wifi: rtw89: Fix TX fail with A2DP after scanning")
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/chan.c | 26 +++++++++++++--
drivers/net/wireless/realtek/rtw89/chan.h | 9 ++++-
drivers/net/wireless/realtek/rtw89/core.c | 2 +-
drivers/net/wireless/realtek/rtw89/fw.c | 40 +++++++++++++++++++----
4 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index fb9449930c40..abc78716596d 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -2530,7 +2530,25 @@ void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
hal->entity_pause = true;
}
-void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
+static void rtw89_chanctx_proceed_cb(struct rtw89_dev *rtwdev,
+ const struct rtw89_chanctx_cb_parm *parm)
+{
+ int ret;
+
+ if (!parm || !parm->cb)
+ return;
+
+ ret = parm->cb(rtwdev, parm->data);
+ if (ret)
+ rtw89_warn(rtwdev, "%s (%s): cb failed: %d\n", __func__,
+ parm->caller ?: "unknown", ret);
+}
+
+/* pass @cb_parm if there is a @cb_parm->cb which needs to invoke right after
+ * call rtw89_set_channel() and right before proceed entity according to mode.
+ */
+void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev,
+ const struct rtw89_chanctx_cb_parm *cb_parm)
{
struct rtw89_hal *hal = &rtwdev->hal;
enum rtw89_entity_mode mode;
@@ -2538,14 +2556,18 @@ void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
lockdep_assert_held(&rtwdev->mutex);
- if (!hal->entity_pause)
+ if (unlikely(!hal->entity_pause)) {
+ rtw89_chanctx_proceed_cb(rtwdev, cb_parm);
return;
+ }
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx proceed\n");
hal->entity_pause = false;
rtw89_set_channel(rtwdev);
+ rtw89_chanctx_proceed_cb(rtwdev, cb_parm);
+
mode = rtw89_get_entity_mode(rtwdev);
switch (mode) {
case RTW89_ENTITY_MODE_MCC:
diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h
index 2eb31dff2083..092a6f676894 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.h
+++ b/drivers/net/wireless/realtek/rtw89/chan.h
@@ -38,6 +38,12 @@ enum rtw89_chanctx_pause_reasons {
RTW89_CHANCTX_PAUSE_REASON_ROC,
};
+struct rtw89_chanctx_cb_parm {
+ int (*cb)(struct rtw89_dev *rtwdev, void *data);
+ void *data;
+ const char *caller;
+};
+
struct rtw89_entity_weight {
unsigned int active_chanctxs;
unsigned int active_roles;
@@ -100,7 +106,8 @@ void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_pause_reasons rsn);
-void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev);
+void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev,
+ const struct rtw89_chanctx_cb_parm *cb_parm);
const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
const char *caller_message,
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index f848185e2ced..bb4621d38658 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -3357,7 +3357,7 @@ void rtw89_roc_end(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
roc->state = RTW89_ROC_IDLE;
rtw89_config_roc_chandef(rtwdev, rtwvif_link->chanctx_idx, NULL);
- rtw89_chanctx_proceed(rtwdev);
+ rtw89_chanctx_proceed(rtwdev, NULL);
ret = rtw89_core_send_nullfunc(rtwdev, rtwvif_link, true, false);
if (ret)
rtw89_debug(rtwdev, RTW89_DBG_TXRX,
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 90db15685728..6c105e4b1cb3 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -6919,22 +6919,25 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
rtw89_chanctx_pause(rtwdev, RTW89_CHANCTX_PAUSE_REASON_HW_SCAN);
}
-void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
- struct rtw89_vif_link *rtwvif_link,
- bool aborted)
+struct rtw89_hw_scan_complete_cb_data {
+ struct rtw89_vif_link *rtwvif_link;
+ bool aborted;
+};
+
+static int rtw89_hw_scan_complete_cb(struct rtw89_dev *rtwdev, void *data)
{
const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
+ struct rtw89_hw_scan_complete_cb_data *cb_data = data;
+ struct rtw89_vif_link *rtwvif_link = cb_data->rtwvif_link;
struct cfg80211_scan_info info = {
- .aborted = aborted,
+ .aborted = cb_data->aborted,
};
struct rtw89_vif *rtwvif;
u32 reg;
if (!rtwvif_link)
- return;
-
- rtw89_chanctx_proceed(rtwdev);
+ return -EINVAL;
rtwvif = rtwvif_link->rtwvif;
@@ -6953,6 +6956,29 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
scan_info->last_chan_idx = 0;
scan_info->scanning_vif = NULL;
scan_info->abort = false;
+
+ return 0;
+}
+
+void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ bool aborted)
+{
+ struct rtw89_hw_scan_complete_cb_data cb_data = {
+ .rtwvif_link = rtwvif_link,
+ .aborted = aborted,
+ };
+ const struct rtw89_chanctx_cb_parm cb_parm = {
+ .cb = rtw89_hw_scan_complete_cb,
+ .data = &cb_data,
+ .caller = __func__,
+ };
+
+ /* The things here needs to be done after setting channel (for coex)
+ * and before proceeding entity mode (for MCC). So, pass a callback
+ * of them for the right sequence rather than doing them directly.
+ */
+ rtw89_chanctx_proceed(rtwdev, &cb_parm);
}
void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev,
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/3] wifi: rtw89: chan: fix soft lockup in rtw89_entity_recalc_mgnt_roles()
2024-12-31 0:48 [PATCH 0/3] wifi: rtw89: fixes MCC and header conversion issues Ping-Ke Shih
2024-12-31 0:48 ` [PATCH 1/3] wifi: rtw89: fix proceeding MCC with wrong scanning state after sequence changes Ping-Ke Shih
@ 2024-12-31 0:48 ` Ping-Ke Shih
2024-12-31 0:48 ` [PATCH 3/3] wifi: rtw89: correct header conversion rule for MLO only Ping-Ke Shih
2 siblings, 0 replies; 5+ messages in thread
From: Ping-Ke Shih @ 2024-12-31 0:48 UTC (permalink / raw)
To: linux-wireless; +Cc: phhuang, kevin_yang
From: Zong-Zhe Yang <kevin_yang@realtek.com>
During rtw89_entity_recalc_mgnt_roles(), there is a normalizing process
which will re-order the list if an entry with target pattern is found.
And once one is found, should have aborted the list_for_each_entry. But,
`break` just aborted the inner for-loop. The outer list_for_each_entry
still continues. Normally, only the first entry will match the target
pattern, and the re-ordering will change nothing, so there won't be
soft lockup. However, in some special cases, soft lockup would happen.
Fix it by `goto fill` to break from the list_for_each_entry.
The following is a sample of kernel log for this problem.
watchdog: BUG: soft lockup - CPU#1 stuck for 26s! [wpa_supplicant:2055]
[...]
RIP: 0010:rtw89_entity_recalc ([...] chan.c:392 chan.c:479) rtw89_core
[...]
Fixes: 68ec751b2881 ("wifi: rtw89: chan: manage active interfaces")
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/chan.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
index abc78716596d..c06d305519df 100644
--- a/drivers/net/wireless/realtek/rtw89/chan.c
+++ b/drivers/net/wireless/realtek/rtw89/chan.c
@@ -391,11 +391,12 @@ static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
list_del(&role->mgnt_entry);
list_add(&role->mgnt_entry, &mgnt->active_list);
- break;
+ goto fill;
}
}
}
+fill:
list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) {
rtw89_warn(rtwdev,
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3] wifi: rtw89: correct header conversion rule for MLO only
2024-12-31 0:48 [PATCH 0/3] wifi: rtw89: fixes MCC and header conversion issues Ping-Ke Shih
2024-12-31 0:48 ` [PATCH 1/3] wifi: rtw89: fix proceeding MCC with wrong scanning state after sequence changes Ping-Ke Shih
2024-12-31 0:48 ` [PATCH 2/3] wifi: rtw89: chan: fix soft lockup in rtw89_entity_recalc_mgnt_roles() Ping-Ke Shih
@ 2024-12-31 0:48 ` Ping-Ke Shih
2 siblings, 0 replies; 5+ messages in thread
From: Ping-Ke Shih @ 2024-12-31 0:48 UTC (permalink / raw)
To: linux-wireless; +Cc: phhuang, kevin_yang
From: Po-Hao Huang <phhuang@realtek.com>
Header conversion should only be used with MLO connections. Otherwise
P2P connection fails due to wrong probe responses sent. Fix it
accordingly.
Fixes: b8499664fca9 ("wifi: rtw89: Add header conversion for MLO connections")
Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.c | 9 ++++++++-
drivers/net/wireless/realtek/rtw89/core.h | 3 +++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index bb4621d38658..74bf590ad88c 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -980,6 +980,11 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
bool is_bmc;
u16 seq;
+ if (tx_req->sta)
+ desc_info->mlo = tx_req->sta->mlo;
+ else if (tx_req->vif)
+ desc_info->mlo = ieee80211_vif_is_mld(tx_req->vif);
+
seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
if (tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD) {
tx_type = rtw89_core_get_tx_type(rtwdev, skb);
@@ -987,7 +992,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link,
tx_req->rtwsta_link);
- if (addr_cam->valid)
+ if (addr_cam->valid && desc_info->mlo)
upd_wlan_hdr = true;
}
is_bmc = (is_broadcast_ether_addr(hdr->addr1) ||
@@ -1127,6 +1132,8 @@ int rtw89_core_tx_write(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
}
tx_req.skb = skb;
+ tx_req.vif = vif;
+ tx_req.sta = sta;
tx_req.rtwvif_link = rtwvif_link;
tx_req.rtwsta_link = rtwsta_link;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 37722a0b6a8b..77af3cf3019a 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -1170,12 +1170,15 @@ struct rtw89_tx_desc_info {
bool stbc;
bool ldpc;
bool upd_wlan_hdr;
+ bool mlo;
};
struct rtw89_core_tx_request {
enum rtw89_core_tx_type tx_type;
struct sk_buff *skb;
+ struct ieee80211_vif *vif;
+ struct ieee80211_sta *sta;
struct rtw89_vif_link *rtwvif_link;
struct rtw89_sta_link *rtwsta_link;
struct rtw89_tx_desc_info desc_info;
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread