Skip to content

SM8550: fix slow WiFi reconnect, ath12k never sends its scan priority - #3189

Open
xiaodoudou wants to merge 1 commit into
ROCKNIX:nextfrom
xiaodoudou:sm8550-ath12k-11d-per-interface
Open

SM8550: fix slow WiFi reconnect, ath12k never sends its scan priority#3189
xiaodoudou wants to merge 1 commit into
ROCKNIX:nextfrom
xiaodoudou:sm8550-ath12k-11d-per-interface

Conversation

@xiaodoudou

@xiaodoudou xiaodoudou commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Summary

WiFi reconnects slowly and erratically after the radio is taken down and brought back up on the Odin 2, which is what the suspend hooks do around every sleep cycle. On a stock image, five off/on cycles reconnect in 4.4 to 8 seconds, degrading as cycles accumulate, with bursts of firmware scan refusals along the way.

The cause is a one-line regression in ath12k. The driver computes a priority for every hardware scan and then never sends it: ath12k_wmi_send_scan_start_cmd() fills arg->scan_priority (LOW as the baseline, MEDIUM when its own 11d regulatory scan is about to run, precisely so host scans do not get starved by it) but cmd->scan_priority is never assigned, so every hardware scan reaches the firmware as priority 0, WMI_SCAN_PRIORITY_VERY_LOW. ath11k computes the same value and does send it; the copy was lost in the ath12k rework. The firmware schedules all scans through one queue and runs the 11d scan at MEDIUM, so after every bring-up the first hardware scan starts the 11d scan and every further scan submitted while it is pending is refused:

scan event start failed type 64 reason 4 freq 0 ... state starting (1)
received scan start failure event

Reason 4 is WMI_SCAN_REASON_INTERNAL_FAILURE. The driver reports each refused scan to iwd as an aborted scan, iwd abandons its quick reconnect plan and falls back to full sweeps with growing backoff, and that is the whole slowdown.

The fix sends the priority the driver already computes:

	cmd->scan_priority = cpu_to_le32(arg->scan_priority);

Testing

AYN Odin 2 (SM8550, WCN7850 hw2.0), linux 7.1.2, shipped c5 firmware, everything from a fresh boot, timing from radio unblock to carrier plus an IPv4 address.

Ten rfkill off/on cycles through the real resume path (wifictl disable, then wifi-resume):

before (5 cycles) after (10 cycles)
reconnected 5/5 10/10
cycle times 4459, 4442, 5929, 5856, 7962 ms 1030, 1024, 1025, 10414*, 1041, 1027, 1024, 1021, 1026, 1032 ms
scan refusals 9, growing per cycle 0 over the whole boot

Nine of ten cycles land within 20 ms of each other. The starred outlier shows zero refusals and matches a NetworkManager-level stall that exists on stock as well (where it produces the 8 s cycles and occasional 40 s timeouts); the driver side stayed clean through it.

On top of the rfkill cycles, real suspend/resume endurance: deep suspend entered via systemctl suspend with an RTC wake, about 25 seconds asleep per cycle, WiFi remeasured after every wake. 36 consecutive cycles before the run was ended manually, every one a verified real suspend (suspend_stats incremented), every reconnect between 2.0 and 3.2 seconds, zero scan refusals across the entire run. The same pattern on the unfixed driver produces refusal bursts from the second or third cycle and degrades from there.

Additional context

How this was found. The earlier version of this PR moved the 11d arming from the per-scan vdev to the interface, based on the observation that ath12k churns an 11d scan start/stop around every hardware scan. The churn is real, but an A/B on the real resume path measured identical refusal counts with and without that patch, which meant the refusals had another cause. Debug traces then showed refused scans staying refused when resent as-is (same vdev or a recycled one, up to 660 ms later) while any different scan submitted moments later sailed through; that ruled out timing and vdev state and left the request itself, and the missing priority assignment accounts for everything, including why a wedged 11d scan used to block every scan for minutes.

This likely fixes the Pocket S Mini workaround target too. #3177 carries 0507-wifi-ath12k-skip-11d-scan-on-ayaneo-pocket-s-mini.patch for the same symptom on the same chip (scans permanently refused after 11d starts and stops, until power cycle). That is the priority starvation in its hardest form. With this fix, host scans coexist with the 11d scan instead of losing to it, so the per-device 11d amputation (and the regulatory blind spot it brings) should no longer be needed; worth a retest on that hardware.

Upstream. This is a mechanical divergence from ath11k and worth sending to linux-wireless. The ath12k 11d-offload commit message documents the MEDIUM/LOW queue model this restores. A related patch in review upstream ("wifi: ath12k: restore country code during resume") fixes country loss across a full firmware reload; complementary, no overlap.


AI Usage

Did you use AI tools to help write this code? YES

@xiaodoudou

Copy link
Copy Markdown
Contributor Author

My automated test and real test give me not the same result, I'm putting in draft for now. I will investigate this more.

@xiaodoudou
xiaodoudou marked this pull request as draft August 15, 2026 03:48
@mydanyi

mydanyi commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

这个问题在我的设备上有复现。我在提交的#3177 添加 AYANEO Pocket S Mini 支持- # 3177 有提到,修复针对 ath12k 的 11d 扫描竞争;上游资料也说明 11d 扫描可能取消普通硬件扫描。芯片最终识别出的监管域已经是 CN,但系统启动时全局监管域仍是 00,于是 ath12k 会先启动一次固件 11d 国家扫描;上游驱动明确说明 11d 扫描会抢占普通扫描。这个固件组合很可能在停止 11d 后没有正确释放扫描引擎。好像是这个全局监管冲突导致我们连接C N的Wi Fi的时候呢,通道被它占用了,失败一定次数以后,它就会停止 5G 的扫描,导致只能扫描到 2.4G,所以就只能连接到 2.4G 了。我在我的设备上能复现并且也修复了这个问题。

@xiaodoudou

Copy link
Copy Markdown
Contributor Author

这个问题在我的设备上有复现。我在提交的#3177 添加 AYANEO Pocket S Mini 支持- # 3177 有提到,修复针对 ath12k 的 11d 扫描竞争;上游资料也说明 11d 扫描可能取消普通硬件扫描。芯片最终识别出的监管域已经是 CN,但系统启动时全局监管域仍是 00,于是 ath12k 会先启动一次固件 11d 国家扫描;上游驱动明确说明 11d 扫描会抢占普通扫描。这个固件组合很可能在停止 11d 后没有正确释放扫描引擎。好像是这个全局监管冲突导致我们连接C N的Wi Fi的时候呢,通道被它占用了,失败一定次数以后,它就会停止 5G 的扫描,导致只能扫描到 2.4G,所以就只能连接到 2.4G 了。我在我的设备上能复现并且也修复了这个问题。

Translation for anyone following the issue:

"I've reproduced this issue on my device. As I mentioned in my submitted PR #3177 (Add AYANEO Pocket S Mini support), which fixes the 11d scan race condition for ath12k, upstream documentation also indicates that 11d scans can cancel standard hardware scans. While the regulatory domain ultimately identified by the chip is CN, the global regulatory domain during system boot remains 00. Consequently, ath12k first initiates a firmware 11d country scan; the upstream driver explicitly notes that the 11d scan will preempt standard scans. It is highly likely that this firmware combination fails to correctly release the scan engine after stopping the 11d scan. It seems this global regulatory conflict causes the channel to be occupied when we attempt to connect to a CN Wi-Fi network. After failing a certain number of times, it stops the 5G scan, resulting in only 2.4G being scannable, which is why it only connects to 2.4G. I was able to reproduce and fix this issue on my own device."

ath12k computes a priority for every hardware scan, LOW as the
baseline and MEDIUM while its 11d regulatory scan is about to run, so
host scans are not starved by the 11d service the firmware runs at
MEDIUM priority in its single scan queue. The value never leaves the
driver: cmd->scan_priority is never assigned, so every hardware scan
reaches the firmware as priority 0, VERY_LOW. ath11k sends the same
computation with the command; the copy was lost in the ath12k rework.

On the WCN7850 every radio bring-up therefore opens with a refusal
storm. The first hardware scan arms and starts the 11d scan, and every
scan submitted while that MEDIUM scan is pending fails with
WMI_SCAN_REASON_INTERNAL_FAILURE. iwd sees aborted scans, abandons its
quick reconnect plan and falls back to full sweeps with growing
backoff. Reconnecting after the suspend hooks toggle rfkill takes 4.4
to 8 seconds and degrades as refusals accumulate.

With the priority on the wire, ten fresh-boot rfkill cycles on an AYN
Odin 2 reconnect 10/10 with zero scan refusals, nine of them between
1021 and 1041 ms, reconnecting from the first quick scan every time.

This replaces the earlier attempt that moved the 11d arming to the
interface: an A/B on the real resume path measured identical refusal
counts with and without it, which is what pointed away from the 11d
churn and at the scan request itself.
@xiaodoudou
xiaodoudou force-pushed the sm8550-ath12k-11d-per-interface branch from 6b870a0 to 8638e1d Compare August 15, 2026 21:22
@xiaodoudou

Copy link
Copy Markdown
Contributor Author

Rework: this PR now carries a different, one-line fix. The 11d patch that used to be here is gone.

What happened: when I retested the 11d patch on the real resume path (what the sleep hooks actually run, not my earlier synthetic harness), it made no measurable difference. Same number of firmware scan refusals with it as without it. The diagnosis in the old body was describing something real, but it was not what refused the scans.

Debug traces found the actual cause. A refused scan stays refused if you resend it unchanged, even on a freshly recreated vdev, yet a different scan submitted right after goes through fine. That pointed at the scan request itself, and the request has a bug: ath12k computes a priority for every hardware scan but never sends it. The assignment is simply missing, so every scan reaches the firmware as priority 0, the lowest there is. The firmware runs its 11d country scan at MEDIUM priority in the same queue, so after every radio bring-up, everything iwd submits while 11d is pending gets refused. Each refusal makes iwd fall back to slow full scans with backoff, and that is the whole slowdown. ath11k computes the same priority and does send it; the copy was lost somewhere in the ath12k rework.

The fix is restoring that one line:

cmd->scan_priority = cpu_to_le32(arg->scan_priority);

Results on the Odin 2, fresh boot each time, real resume path:

before after
rfkill off/on cycles 5/5, but 4.4 to 8 s and getting worse each cycle 10/10, nine cycles at about 1.03 s
scan refusals 9 in five cycles 0
real suspend/resume with RTC wake not run 36/36, reconnect in 2 to 3.2 s, 0 refusals

The PR body has been rewritten to match the new patch.

One more thing, for #3177: the Pocket S Mini patch that disables 11d entirely (0507) works around this same bug in its hardest form, a stuck 11d scan starving priority-0 scans until the device is power cycled. With the priority actually sent, that per-device workaround should no longer be needed. Worth a retest on that hardware.

@xiaodoudou xiaodoudou changed the title SM8550: stop ath12k restarting the 11d scan on every hardware scan SM8550: fix slow WiFi reconnect, ath12k never sends its scan priority Aug 15, 2026
@xiaodoudou
xiaodoudou marked this pull request as ready for review August 15, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants