Phase 3: SCMI binds, the CPUs get cpufreq (2026-11-03)
Attempt 2026-11-03-8. Image ca51a59382dff6c8, kernel #7 (2026-11-03 4:07 PM ET), commit ca81e32. Sources: the
netlog dumps/firstboot/2026-11-03-netlog.txt and the AP console log dumps/firstboot/2026-11-03-ap.log (both
gitignored).
Why
Every boot up to attempt -7 ended with one deferred device: firmware:scmi … supplier 17430000.mailbox not ready,
then arm-scmi: failed to setup channels and failed to setup channel for protocol:0x10. The CPUs stayed at whatever
clocks the firmware left them on.
mailbox@17430000isqcom,x1e80100-cpucp-mbox. Its driver isQCOM_CPUCP_MBOX(drivers/mailbox/Kconfig:343,qcom-cpucp-mbox.c:205),=min defconfig (arch/arm64/configs/defconfig:1614), and the initramfs loads no modules.- The stock tree drives the same block:
cpucp: qcom,cpucp@18830000(qcom,cpucp-v2) with the same two register ranges (0x17430000,0x18830000), anarm,scminode withmboxes = <cpucp 0 cpucp 2>and shmem inmmio-sram@18b4e000(entry00-base.dts:384-402,:908-926,:10534-10540).hamoa.dtsidescribes the same, and each CPU takes itsperfdomain fromscmi_dvfs(hamoa.dtsi:78-79). So no DTS change. The stock tree also lists a vendorprotocol@80thathamoa.dtsidoes not have.
Changes (commit ca81e32)
kernel/mica-scmi.config:QCOM_CPUCP_MBOX=y. It also checks that the mailbox, SCMI core, SCMI mailbox transport, SCMI perf domain and SCMI cpufreq options are=yafter the merge (they were already)./init: onecpufreqline per policy (CPUs, driver, governor, current, min and max kHz) and anscmi-dmesgcapture.
Result: pass
-
SCMI binds over the mailbox:
arm-scmi arm-scmi.0.auto: Using scmi_mailbox_transportat 0.358 s,SCMI Protocol v2.0 'Qualcomm:' Firmware version 0x20000,scmi-perf-domain scmi_dev.4: Initialized 3 performance domainsat 0.376 s. -
cpufreq on all three clusters (
schedutilgovernor):Policy CPUs Driver Current at ~110 s Range policy00-3 scmi806.4 MHz 710.4 MHz to 3417.6 MHz policy44-7 scmi2188.8 MHz 710.4 MHz to 3417.6 MHz policy88-11 scmi2188.8 MHz 710.4 MHz to 3417.6 MHz -
Nothing deferred:
deferredthroughdeferred5are all empty, for the first time on mica. -
Everything else unchanged: both DSPs
runningat the end, Type-C, PCIe, Wi-Fi (6 GHz, DHCP), eDP 2560x1600, GPU firmware and GMU loaded, netlog sent (1379 lines).reboot: Restarting systemat 174.8 s (about 4:11 PM ET). -
Earlier milestones than attempt -7: CDSP up at 0.79 s (was 1.99 s), ADSP at 6.13 s (was 7.41 s, still after the known 5 s SSCTL wait, cdsp-2026-11-03.md), PCIe Gen4 link at 1.11 s (was 2.28 s). Inference: the CPUs now run faster than the firmware’s default clocks. Not measured directly.
Log lines checked
[Firmware Bug]: Failed to add opps_by_lvl at 3417600 for NCC1 - ret:-16(twice each for NCC1 and NCC2). This is adev_infofromdrivers/firmware/arm_scmi/perf.c:381-383(and:403-405):xa_insert()returned-EBUSY, so the firmware lists the 3.4176 GHz level more than once for those domains. The level still registers asmax=3417600. Inference: harmless.region@80a00000 … overlaps with cpucp-log@80e00000at 0.000 s is not new: it is in every boot’s log on 2026-11-03 (7 of 7) and in2026-11-02-2.region@80a00000is not in the mica DTB. Inference: the boot firmware adds it. Not traced further.
Update: attempt -9 (2026-11-03, 4:20 PM ET): SCMI timed out, no cpufreq
Same SCMI config as attempt -8 (the only kernel change was kernel/patches/0001, panel-edp). Sources as above.
arm-scmibound overscmi_mailbox_transportat 0.367 s as before. From 0.437 s on, 10timed out in resp(caller: do_xfer+0xdc/0x180), each about 36 ms after the previous one (the 30 msmax-rx-timeout).- Late answers arrive for older requests:
scmi_protocol scmi_dev.1: Message for 7 type 0 is not expected!, then for 9 and for 32. Inference: the CPUCP firmware answered, but after the kernel had given up on each request. - Results:
SCMI Protocol v2.0 'Qualcomm:' Firmware version 0x0(was0x20000, so the version query failed and thequirk_perf_level_get_fc_forcequirk was not applied),Failed to query supported version for protocol 0x13,scmi-cpufreq scmi_dev.3: probe with driver scmi-cpufreq failed with error -110, and/initsawcpufreq=none.scmi-perf-domainstill initialized 3 performance domains at 0.806 s. - Nothing else failed:
deferredstayed empty, both DSPs ran, display, GPU and Wi-Fi as in -8. - Upstream has seen the same timeout on x1e80100. Review of the series that enabled X1E cpufreq reports
arm-scmi firmware:scmi: timed out in respon the CRD (PATCH V7 0/2 “qcom: x1e80100: Enable CPUFreq”, 2024-11). The mailbox driver ata804c57already clears each channel’s interrupt under the channel lock (drivers/mailbox/qcom-cpucp-mbox.c,qcom_cpucp_mbox_irq_fn).
Open: with one good boot (-8) and one bad (-9), the cause is not known. Next step: more boots of the same image to get a failure rate, then compare the first SCMI exchange’s timing across good and bad boots.
Update: cold boot vs warm reset (2026-11-03, 5:25 PM ET)
Attempts -10, -11 and -12, plus the EC console log dumps/firstboot/2026-11-03-ec.log (gitignored).
| Attempt | Kernel | Start (EC console) | SCMI firmware version | cpufreq |
|---|---|---|---|---|
| -8 | #7, no patches | cold: power button pressed, G3->S5 at EC 10691 s; its reboot 184 s later | 'Qualcomm:' 0x20000 | 3 policies |
| -9 | #9, patch 0001 | warm: AP reset in S0 at EC 11401 s, no G3; reboot 198 s later | 'Qualcomm:' 0x0 | none (-110) |
| -10 | #9, patch 0001 | not logged (the consoles were started mid-boot) | '' 0x0, 13 timeouts | none (-110) |
| -11 | #10, no patches | warm: AP reset in S0 at EC 14388 s; reboot 138 s later | none: the first message timed out, arm-scmi probe -110 | none |
| -12 | #10, no patches (the -11 image) | cold: stock powered off (power state 0 = G3 at EC 14712 s), then power button | 'Qualcomm:' 0x20000, both quirks on, no timeouts | 3 policies |
Matching the EC times to boots: each mainline boot’s reboot comes its uptime plus ~9 s of firmware later (-8: 174.8 s uptime, 184 s; -9: 189.5 s, 198 s; -11: 129.5 s, 138 s).
- Result: SCMI worked in both cold boots and failed in every warm reset from running stock Android, with and
without the panel patch (-11 used the plain pin,
GBOOK_SKIP_PATCHES=1). The same image failed warm (-11) and worked cold (-12). - Inference: stock Android’s kernel leaves the CPUCP in a state that survives a warm reset (the stock tree drives it
as
qcom,cpucp-v2with a vendorprotocol@80), and in that state it answers mainline’s SCMI late or not at all. How the stock kernel uses it is not traced. With two cold and two logged warm boots, this is a strong pattern, not proof. - The failures grew worse from -9 to -11. Inference: each failed boot may leave the firmware in a worse state for the next warm reset (the research note’s quirk hazard, scmi-cpucp-timeouts.md).
Procedure from now on: power stock off fully before each attempt. attempt.sh verify prints that step,
attempt.sh watch shows the EC’s G3->S5 line for a cold start, and /init reports the firmware version as the
scmi-fw key so compare flags a warm-reset boot. arm,max-rx-timeout-ms is not needed for cold boots; it stays
an option if a warm boot must work (for example after a crash reboot).
Update: cold starts fail too (2026-11-03, 5:59 PM ET)
Three later boots each followed an EC G3->S5 (a cold start; EC uptime 15984, 17025 and 17236 s in
dumps/firstboot/2026-11-03-ec.log), with the EC work’s images (ec-2026-11-03.md):
| Boot | SCMI | Firmware version | cpufreq |
|---|---|---|---|
2026-11-03-13 | probe with driver arm-scmi failed with error -110 | none | none |
| repeat of -13 | timed out in resp, many times from 0.43 s | 0x0 | none |
2026-11-03-14 | one timed out in resp at 0.418 s, then bound | 0x20000 | all three policies |
So a cold start does not always bring SCMI up: the “cold boot only” rule above holds for the warm side (no warm
reset has worked) but not as a guarantee on the cold side. Open lead 2 in the handoff (SCMI after a warm reset) widens
to SCMI in general; docs/research/scmi-cpucp-timeouts.md ranks arm,max-rx-timeout-ms first.
Update: the 250 ms window and the trace (2026-11-03, about 8 PM ET)
arm,max-rx-timeout-ms = <250> (commit d555a07, unverified diagnostic) took effect on both boots
(SCMI max-rx-timeout: 250ms).
2026-11-03-20(cold; the EC itself reset at power-on):xfers_response_timeout=7ofsent_ok=78(response_ok=74,err_protocol=1), firmware0x0, noquirk_perf_level_get_fc_force(the hazard path, scmi-cpucp-timeouts.md section 4), cpufreq on 2 of 3 clusters.2026-11-03-21(cold, tracing on): firmware0x20000, the FC quirk, 3 of 3 clusters, 0 timeouts; the trace’sscmi_xfer_begintoscmi_rx_donelatency over 78 replies peaked at 4.0 ms.- So when CPUCP answers, it answers within milliseconds; on a bad boot some messages get no reply even in 250 ms.
A longer window does not help (inference from 2 boots); the next lever is why CPUCP stops answering
(research options 3-4: the guard,
arm,no-completion-irq,cpuidle.off=1).
Update: reply latency per message, attempt -22 (2026-11-03, 8:14 PM ET)
Cold start, 250 ms window, tracing on: firmware 0x20000, the FC quirk, 3 of 3 clusters, and 4 timeouts. The trace
(scmi_xfer_begin to scmi_rx_done, netlog “trace at probe”):
- 67 of 75 replies in under 1 ms.
- The base protocol’s discovery messages (
pt=10,msg_id01 to 06) took 23 to 36 ms each, one after another.msg_id05 (implementation version, the “Firmware version” line) took 36.0 ms. With the driver’s default 30 ms window that reply is missed, the version stays0x0and the FC quirk does not match (inference: it fits every bad boot’stimed out in resplines about 36 ms apart andFirmware version 0x0). - Slower still: base
msg_id07 at 222.4 ms, perf (pt=13)msg_id02 at 155.2 ms and0Bat 67.9 ms. - Timed out at 250 ms: base
msg_id06, perfmsg_id04 and 02 (twice). - So the window matters: 250 ms turned this boot good where 30 ms would have failed it. -20 still failed at 250 ms, so some replies take longer or never come. Two good boots (-21, -22) also both had tracing on; that it shifts the timing is unproven (inference).
Update: 1000 ms window, attempts -23 to -25 (2026-11-03, 8:31 PM ET)
arm,max-rx-timeout-ms = <1000> (commit after 927480c), tracing on, three cold starts of one image:
| Attempt | Result | Timeouts | Slow replies (trace) |
|---|---|---|---|
-23 | pass: 0x20000, FC quirk, 3 of 3 | 1 | base 03 628 ms, perf 09 872 ms, perf 04 1014 ms (the timeout) |
-24 | pass | 1 | base 04 884 ms, perf 02 940 ms, 0B 950 ms, 04 830/950 ms; perf 09 timed out |
-25 | pass | 0 | none: 78 replies, all within 3.6 ms |
- Since the window went to 250 ms and tracing on: 5 good cold starts in a row (-21 to -25), against 2 of 7 before with the default 30 ms (-20 at 250 ms failed).
- Reply time varies by boot: some boots answer everything within milliseconds (-21, -25), others have a tail of single messages at 0.6 to 1 s. Why CPUCP stalls is still open; the window only absorbs it.
- Not a fix: the property is local and unverified (no stock counterpart), and a boot can still lose a message past
1 s (-23’s perf
04at 1014 ms). It costs nothing on a fast boot.
Update: cluster_cl5 A/B, attempt -27 (2026-11-03, 9:50 PM ET)
Attempt 2026-11-03-27: kernel #17 (as -26), 1000 ms window, tracing on, plus the diagnostic fragment
dts/diag/hamoa-no-cluster-cl5.dtsi (commit 5aa73de): domain-idle-states = <&cluster_cl4> on cluster_pd0-2,
so the three CPU clusters never enter cluster_cl5. Source: Jens Glathe’s “arm64: dts: qcom: hamoa: Drop cluster_cl5
idle state from CPU clusters” (https://lore.kernel.org/all/20260604-dc_zva_mitigation-v1-1-d1148c1c0259@oldschoolsolutions.biz/),
carried by Omarchy as linux-omarchy-aarch64 patch 2151. Image a563a107aeedf282, DTB 4fa8ee79b09d1ea9; three cold
starts of one image (stock powered off, EC G3 before each):
| Boot | Result | Timeouts | Max reply | Slow replies (trace, >= 100 ms) |
|---|---|---|---|---|
| 1 | pass: 0x20000, FC quirk, 3 of 3 | 0 | 943.7 ms | base DISCOVER_SUB_VENDOR 111.8 ms, DISCOVER_LIST_PROTOCOLS 496.0 ms, perf DESCRIBE_LEVELS 943.7 ms |
| 2 | pass | 0 | 3.9 ms | none (the AP console’s scmi-latency= line; this boot’s netlog did not arrive) |
| 3 | pass | 0 | 812.0 ms | base DISCOVER_VENDOR 812.0 ms; perf DESCRIBE_LEVELS 507.2/433.7/222.4 ms, PROTOCOL_MESSAGE_ATTRIBUTES 442.0/362.0 ms, NOTIFY_LIMITS 795.2 ms (SCMI probe 0.37 s to 4.11 s) |
- Against the same 1000 ms window with
cluster_cl5(-23 to -26): 2 of 4 boots stalled (-23, -24), 2 answered within 4 ms (-25, -26). Withoutcluster_cl5: 2 of 3 stalled. No improvement: the A/B failed. The stalls do not come from thecluster_cl5idle state (3 boots; a small sample, but the worst probe of the day, boot 3, ran without it). - All three boots came up fully, so the 1000 ms window keeps absorbing the stalls; 0 timeouts here.
- The stalls fall between 0.37 s and 4.1 s of kernel time, during the SCMI probe and before
/initruns, so they do not depend on anything done at the keyboard. - The fragment is deleted (its text is in commit
5aa73de), perdts/diag/README.md. Open: the other idle-state lever in scmi-cpucp-timeouts.md (cpuidle.off=1, which also covers the CPU idle states the fragment left alone).
Update: cpuidle.off=1 A/B, attempt -28 (2026-11-03, 10:02 PM ET)
Attempt 2026-11-03-28: kernel #17, the board DTB as -26 (f30182513670c4e3, no dts/diag), 1000 ms window, tracing
on, plus GBOOK_CMDLINE_EXTRA=cpuidle.off=1 (cpuidle_register_driver() returns -ENODEV while off is set, drivers/cpuidle/driver.c:225 at
a804c57, so the idle loop falls back to plain WFI and no PSCI idle state is requested: not the CPU ret state, the
cluster states or domain_ss3 on system_pd; the last part is inference from the PSCI cpuidle driver being the only
requester). Image
21db583f38e653a3; three cold starts of one image (stock powered off, EC G3 before each):
| Boot | Result | Timeouts | Max reply | Replies under 1 ms |
|---|---|---|---|---|
| 1 | pass: 0x20000, FC quirk, 3 of 3 | 0 | 0.1 ms | 78 of 78 |
| 2 | pass | 0 | 0.1 ms | 78 of 78 |
| 3 | pass | 0 | 0.1 ms | 78 of 78 |
The trace’s only flagged rows are base DISCOVER_SUB_VENDOR and DISCOVER_AGENT with s=-13 (not supported, 0.0 ms),
as on every boot; the SCMI probe ends by 0.38 s.
- With idle states on (1000 ms window, -23 to -27): 4 of 7 cold boots stalled (-23, -24, -27 boots 1 and 3; replies of
0.5 to 1 s), and even the clean ones peaked at 3.6 to 4.0 ms (-21, -25, -26, -27 boot 2). With
cpuidle.off=1: 0 of 3 stalled and every reply within 0.1 ms, a floor 40 times lower. - So the CPUCP’s slow replies follow the AP’s idle states. That matches Sibi Sankar’s statement that the CPUCP firmware bug “happens when idle states are enabled” (scmi-cpucp-timeouts.md section 4). Three boots is a small sample: with 4 of 7 stalling, three clean boots in a row by chance is about 8 % (inference).
cluster_cl5alone is ruled out (-27). Left are the CPUretstate (cluster_c4),cluster_cl4anddomain_ss3; the stock tree has the same four states and topology (entry00-base.dts:cluster_pd0-2with cl4 and cl5,system_pdwithsystem_ss3), so stock Android boots with them (inference: they are not wrong for this board).- Not a config to keep:
cpuidle.off=1costs idle power. It is a diagnostic; the 1000 ms window stays.
Update: what the trace cannot tell (2026-11-03, 10:20 PM ET)
The latency in the tables above runs from scmi_xfer_begin to scmi_rx_done, and rx_done is traced in the mailbox
interrupt’s handler (driver.c:1164 at a804c57), so it cannot separate a late CPUCP reply from an on-time reply whose
interrupt woke an idle AP CPU late. “The slow replies follow the AP’s idle states” (-28) holds either way; which side is
slow is open. Sibi Sankar’s “idle states” statement is about PERF_LEVEL_GET hard resets, not reply latency, so it does
not decide this (inference). The discriminator is arm,no-completion-irq with idle states on
(dts/diag/scmi-no-completion-irq.dtsi): polling skips the interrupt; trace_report.py times a polled reply from begin
to end. Stock wires the mailbox the same way (qcom,cpucp-v2 at 0x17430000/0x18830000, GIC SPI 28 level-high, no
PDC; SCMI channels 0 and 2, no arm,max-rx-timeout-ms), with a downstream mailbox driver.
Update: arm,no-completion-irq A/B, attempt -29 (2026-11-03, 10:24 PM ET)
Attempt 2026-11-03-29: kernel #17, 1000 ms window, tracing on, idle states on, plus
dts/diag/scmi-no-completion-irq.dtsi (polling for every SCMI reply; dmesg: Enabled polling mode TX channel). Image
aa0661198276109c; three cold starts of one image (EC G3 before each):
| Boot | Result | Timeouts | Polled replies | Max reply | apss_cpucp_mbox IRQs |
|---|---|---|---|---|---|
| 1 | pass: 0x20000, FC quirk, 3 of 3 | 0 | 78 of 78 | 0.1 ms | 0 |
| 2 | pass | 0 | 78 of 78 | 0.1 ms | 0 |
| 3 | pass | 0 | 78 of 78 | 0.1 ms | 0 |
(trace_report.py times a polled reply from scmi_xfer_begin to scmi_xfer_end; the two s=-13 replies count as
replies after a fix the same night, so /init’s on-device line on this image still says 76.)
- The CPUCP is not slow. With idle states on, it frees the shared-memory channel within 0.1 ms of every request on all three boots, where 4 of 7 interrupt-mode boots stalled for 0.5 to 1 s. The slow part is the completion interrupt.
- The IRQ count is 0 because a polled message asks for no interrupt (
shmem.c:123: the channel’s flagSCMI_SHMEM_FLAG_INTR_ENABLEDis written as 0 whenpoll_completionis set). In interrupt mode every boot of the day counted oneapss_cpucp_mboxIRQ per reply (75 to 78), all on CPU 0 (GBOOK: irq-counts=, netlog), stalled boots included: the interrupts arrive, late. - Which half is late, the CPUCP raising it or CPU 0 waking for it, is still open. A lead (inference): the stall ceiling
tracks the rx window (timeouts about 36 ms apart at 30 ms, a 222 ms reply at 250 ms, 940 to 1014 ms at 1000 ms), which
fits a CPU 0 that sleeps through the interrupt until its own timeout timer wakes it, then takes the pending interrupt
just before or just after the timeout. GIC SPI 28 has no PDC pin (
qcom,pdc-rangesinhamoa.dtsi:6028maps SPIs 251-255, 480-573, 609-640, 717-728, 816-834), so it cannot wake the SoC from a state that needs the PDC; whetherdomain_ss3onsystem_pdis such a state is unverified. - The fragment stays (status: proven as a diagnostic) until the owner decides between polling, the window, or a narrower idle-state change.
Update: what -29 shows and does not (2026-11-03, 10:28 PM ET)
Polling keeps one AP core spinning through the whole SCMI probe, and cpuidle.off=1 (-28) keeps every core out of the
PSCI states, so both fast cases share one property: the SoC never reaches its deepest state during the probe. -29 shows
that the CPUCP answers within 0.1 ms while one AP core is awake; whether it also does when all cores sleep is untested.
Two readings fit: CPU 0 sleeps through an on-time IRQ (SPI 28 has no PDC pin) until a timer wakes it, or the CPUCP
defers its reply while the AP is in a deep state. The window-tracking lead favours the first (inference). Next A/B:
domain_ss3 dropped from system_pd alone (dts/diag/hamoa-no-system-ss3.dtsi).
Update: domain_ss3 A/B, attempt -30 (2026-11-03, 10:34 PM ET)
Attempt 2026-11-03-30: kernel #17, 1000 ms window, interrupt mode, CPU and cluster idle states as stock, plus
dts/diag/hamoa-no-system-ss3.dtsi (system_pd without domain-idle-states; the built DTB’s
/psci/power-domain-system has none). Image 8296ea098da5e5b3. One cold start (EC G3 before it):
- Pass (
0x20000, FC quirk, cpufreq 3 of 3), but the worst SCMI boot of the day: 1 timeout (perfDESCRIBE_LEVELS, 1012.1 ms,s=-110), baseDISCOVER_AGENT587.0 ms; 76 replies, 76apss_cpucp_mboxIRQs, all on CPU 0. - Failed: dropping the system-level state does not stop the stalls. One stalled boot settles it, so boots 2 and 3
were skipped. With -27, the cluster
cl5state and the systemss3state are each ruled out alone; left are the CPUretstate andcluster_cl4, or a combination. - Also on this boot, unexplained: the touchscreen probe failed with
-110at 12.8 s (usually-22), with GENI I2C errors ona80000.i2c: 4 transaction timeouts, plus NACK, arbitration-lost and bus-protocol errors (attempt.sh trace i2c touchscreen). The NACK and arbitration errors point at the bus or the device, not at interrupt delivery (inference); see touch-tpm-2026-11-03.md. - The fragment is deleted (its text is in commit
9fa5a2d), perdts/diag/README.md.
Update: the wake trace, attempts -31 and -32 (2026-11-03, 11:00 PM ET)
Board DTB, interrupt mode, idle states on, plus trace_event=irq:irq_handler_entry,power:cpu_idle,timer:hrtimer_expire_entry
(debug-tools.md, “the wake trace”). /init keeps these events for CPU 0 only.
-31(image053a4bced558aa41): the default 1.4 MB per-CPU ring wrapped before the probe snapshot and lost the SCMI probe (replies=0). The boot itself stalled (SCMI 1.26 s to 2.30 s), 0 timeouts.-32(image5e565f64ce0e9d30,trace_buf_size=8M): the ring still wrapped (2061301 of 2260937 events kept) but kept all 78 SCMI replies. One slow reply: perfPROTOCOL_MESSAGE_ATTRIBUTES, 534.3 ms (request at 0.434542 s, reply interrupt at 0.968882 s); 0 timeouts. Cold start after an EC reset (Reset cause: sysjump hard efs).
What CPU 0 did during those 534 ms (attempt.sh trace wake, and the raw netlog lines):
- It entered idle
state=1(cpuidle index 1, the PSCIretstatecluster_c4) and left it 26694 times, once every ~20 µs, and took only 3 interrupts: 2 IPIs and 1arch_timer. Per 100 ms bin: about 4960-5000 idle exits and 0-6 interrupts during the stall; in normal periods (0.0-0.4 s, 2.4-4.0 s) the exits roughly match the interrupts. - The stall ended with the
arch_timerinterrupt at 0.968876 s; it expired fourpm_suspend_timer_fnhrtimers, and 6 µs later theapss_cpucp_mboxinterrupt ran and the reply was read. - The same 20 µs loop with no interrupts covers 1.2 to 2.0 s, when no SCMI message was pending: the loop is not caused by the SCMI request (inference from one boot).
Reading (inference, not proven): CPU 0’s ret entries return early every 20 µs without the kernel taking any
interrupt, so something wakes the core that the GIC does not deliver as an interrupt, or delivers only after another
interrupt is acknowledged. With cpuidle.off=1 (-28, plain WFI) the replies take 0.1 ms. The other CPUs were not
traced (the capture keeps CPU 0 only), so whether they were idle is unknown. Neither tree marks an idle state
local-timer-stop, and both have the memory-mapped timer (arm,armv7-timer-mem), so a missing tick broadcast is
not the explanation.
Update: precision on the -32 loop (2026-11-03, 11:08 PM ET)
state=1is not only theretstate: its enter callback ispsci_enter_domain_idle_state(cpuidle-psci.c:271ata804c57), which can escalate to a cluster or system domain state when CPU 0 is the last CPU of its domain. Thecpu_idleevent cannot tell which was requested;power:psci_domain_idle_enter/_exit(power.h:89,:96) can.- Each cycle spends ~20 µs inside the state and ~0 µs outside: a PSCI call that returns without holding the state. Two readings fit: the firmware refuses (or immediately ends) the state while an SCMI command is in flight, or something wakes the core that the kernel does not see as an interrupt. Not decided.
- Two IPIs ran on CPU 0 mid-stall (0.502444 s, 0.538444 s) and the mailbox interrupt still did not follow them: SGIs reached CPU 0 while the SCMI reply’s SPI did not (or was not yet raised).
- No I2C or GENI events fall in 0.43-2.1 s on -32, so this boot cannot say whether other SPIs stall the same way.
- Next capture (one boot, no fragment):
cpuidle/state*/{usage,rejected,time}per CPU (rejectedexists,drivers/cpuidle/sysfs.c:266),pm_genpd_summary(CONFIG_DEBUG_FS=y,CONFIG_PM_GENERIC_DOMAINS=yin the build), the PSCI domain tracepoints, and per-CPU idle-exit counts over the SCMI window.
Update: idle counters, attempt -33 (2026-11-03, 11:21 PM ET)
Attempt 2026-11-03-33 (image fb75f74a4a79d29e, commit 68667c5): as -32 plus power:psci_domain_idle_enter/exit
and the /init idle counters, read at the probe snapshot (cumulative since boot, about 95 s in by the genpd times).
Cold start after an EC reset. SCMI stalled: firmware version at 1.03 s, a timeout at 4.11 s, perf domains at 4.11 s.
The trace ring wrapped (2185344 of 3404814 events kept) and lost the SCMI lines, so the per-window counts are missing
(idle-window=no SCMI window); the cumulative counters are complete.
cpuidle/state1 (cpu-sleep-0, the deepest cpuidle state, whose enter can request a domain state):
| CPUs | usage | rejected |
|---|---|---|
| cpu0 | 218498 | 37 |
| cpu1, cpu2, cpu3 | 3022, 2178, 1730 | 45, 28, 27 |
| cpu4-cpu7 (cluster 1) | 983, 1465, 2215, 1360 | 22563, 44568, 89639, 94845 |
| cpu8-cpu11 (cluster 2) | 1636, 1075, 1273, 1291 | 266040, 20354, 23072, 37093 |
genpd idle_states (debugfs; Usage, Rejected, Above):
power-domain-systemS0 (domain_ss3): usage 2402, rejected 598159, above 599516.power-domain-cpu-cluster1S1 (cl5): usage 252401, rejected 7, above 251683;cluster2S1: 347327, 4, 346622.power-domain-cpu-cluster0S0/S1: usage 1593/3565, rejected 74/18.
What the counters mean at a804c57: cpuidle’s rejected counts an enter that returned an error, and a PSCI domain
state’s genpd rejected counts a CPU_SUSPEND for that composite state that returned an error
(pm_genpd_inc_rejected(), cpuidle-psci.c:102; core.c:816). genpd’s above counts a stay shorter than the
state’s latency plus residency (genpd_reflect_residency(), core.c:331).
- The firmware refused the system state about 598000 times. The refusals sit on the last CPU of clusters 1 and 2
(cpu4-11’s cpuidle rejections add up to 598174, matching
system_pd’s 598159): each time one of them is the last CPU awake, it asks forss3, PSCI returns an error at once, and it tries again. - CPU 0 is not refused (37): it enters
state1and is woken, 218498 times, the 20 µs loop of -32. - Clusters 1 and 2 entered
cl5about 250000 and 350000 times, almost all shorter than its residency. - Reading (inference): a storm of refused system-state requests and early wakes runs while the SoC should be idle. A
busy CPU (polling, -29) or no PSCI idle (-28) never gets all CPUs idle, so no storm, and the replies take 0.1 ms. That
the storm delays the CPUCP’s completion interrupt is not shown. The counters are cumulative to about 95 s, so they
do not prove the storm runs during the SCMI stall; -30 (no
ss3) still stalled, with no counters to show what ran.
Update: precision on -33 (2026-11-03, 11:30 PM ET)
- The refused CPUs are not the stalled one. The mailbox interrupt lands on CPU 0, and CPU 0 is entered-and-woken
(
state1usage 218498, rejected 37); the refusals are on clusters 1 and 2 asking forss3. Two coupled loops, causality unknown either way: CPU 0 bouncing could be why the firmware refusesss3(cluster 0 is not down), or the refusals could be what wakes CPU 0. - The counters are cumulative over about 95 s; -32 showed CPU 0’s loop at about 50000 exits/s during stalls against 1000-6000/s otherwise, so the cumulative numbers understate the rate inside a stall.
- Mode:
psci: OSI mode supportedandCPUidle PSCI: Initialized CPU PM domain topology using OSI mode(-33 dmesg). - Ruled out as a link: the stock tree’s four
qcom,cpucp-enabledflags sit inqcom,memlatmonitors (the memory latency governor), not in an idle-state node. The stockpscinode matches mainline’s (arm,psci-1.0,smc). - Not yet tested: no composite requests at all (
domain-idle-statesremoved fromcluster_pd0-2andsystem_pd, CPUretkept). -27 removed onlycl5, -30 onlyss3.
Decisions (2026-11-03, 11:27 PM ET, owner, grilling round)
- One more boot before choosing the fix: every PSCI domain idle state removed (
dts/diag/hamoa-no-domain-idle.dtsi), CPUretkept, interrupt mode, idle counters read early and at the snapshot. - The board DTS keeps
arm,max-rx-timeout-ms = <1000>until the cause is known; polling stays adts/diagfragment (it would hide the stall from every later trace). - Nothing goes to a mailing list until the cause is known and a fix is tested on mica; then one report to
linux-arm-msm(SCMI and PSCI maintainers on Cc) with the numbers, the cause and a patch, after the owner reviews it. - Time box: this boot plus at most one follow-up, then the next handoff item (the never-bound devices, then the touchscreen).
Update: no PSCI domain idle states, attempt -34 (2026-11-03, 11:41 PM ET)
Attempt 2026-11-03-34 (image 30354ef5b4fcf76c, commit d458b08): kernel #17, interrupt mode, 1000 ms window,
dts/diag/hamoa-no-domain-idle.dtsi (no domain-idle-states on cluster_pd0-2 or system_pd; the 12 per-CPU
domains keep cluster_c4, the CPU ret state). Three cold starts of one image (EC G3 before each):
| Boot | Result | Timeouts | Max reply | cpuidle rejected (all CPUs) | CPU 0 state1 usage, early / snapshot |
|---|---|---|---|---|---|
| 1 | pass: 0x20000, FC quirk, 3 of 3 | 0 | 4.0 ms | 0 | 19190 at 7.04 s / 72367 at 78.71 s |
| 2 | pass | 0 | 1.4 ms | 0 | 14284 at 6.96 s / 97553 at 92.82 s |
| 3 | pass | 0 | 3.6 ms | 0 | 4725 at 6.84 s / 53456 at 78.63 s |
- No stall on any boot, and no PSCI refusal anywhere. With domain idle states present, 8 of 11 interrupt-mode cold
boots stalled (-23, -24, -27 boots 1 and 3, -30, -31, -32, -33); three clean boots in a row by chance at that rate
is about 6 % (inference). Removing
cl5alone (-27) orss3alone (-30) was not enough; removing every composite state is. - CPU 0 entered
state1about 700 to 2700 times a second up to the early read, against about 50000 a second inside -32’s stall: no loop. power-domain-system’s default state still countsrejected(23796, 38188, 40386 at the snapshot). These are vetoes from the RPMh controller’s genpd notifier, which refusesGENPD_NOTIFY_PRE_OFFwhile it is busy or cannot flush (rpmh_rsc_pd_callback(),rpmh-rsc.c:949-951; counted atcore.c:1014): kernel-side, no PSCI call.- Reading (inference): the stall needs the composite cluster or system states that PSCI refuses in OSI mode (-33); why the firmware refuses them, and how that delays the CPUCP’s interrupt to CPU 0, is still open. What the change costs: the clusters and the SoC never power down when idle (more idle power; suspend is untested either way).
Update: ADR 0008 is not enough, attempts 2026-11-04-1 and -2 (2026-11-04, 12:26 AM ET)
Two more cold boots on the ADR 0008 board DTS (no PSCI domain idle states), kernel #18 then #19 (the second
adds only kernel/patches/0008, a GENI I2C timing test for the touchscreen): both stalled.
| Boot (all without domain idle states) | Max reply | Timeouts | CPU 0 state1 usage at the early read | cpuidle rejected |
|---|---|---|---|---|
| -34 boot 1 | 4.0 ms | 0 | 19190 at 7.04 s | 0 |
| -34 boot 2 | 1.4 ms | 0 | 14284 at 6.96 s | 0 |
| -34 boot 3 | 3.6 ms | 0 | 4725 at 6.84 s | 0 |
| -35 | 3.9 ms | 0 | 7775 at 6.92 s | 0 |
| 2026-11-04-1 | 1019.2 ms | 2 | 155711 at 9.94 s | 0 |
| 2026-11-04-2 | 652.0 ms (base DISCOVER_IMPLEMENT_VERSION) | 0 | 132524 at 9.52 s | 0 |
- 2 of 6 stalled, so removing the domain idle states lowers the rate (8 of 11 before) but does not stop it. -34’s 3 of 3 was the lucky case. The 2026-11-04-1 stall was missed live: the touch monitor was not watching SCMI.
- The stall goes with CPU 0’s
state1loop, not with PSCI refusals. Stalled boots reach 130000-156000 CPU 0state1entries by the early read, against 4700-19000 on clean ones (the early read also comes later, because the stall delays the boot). Every CPU’srejectedis 0, and no composite state exists. -33’s refusal storm ran alongside the stall, not as its cause (inference). - What is left fits all the data (inference): CPU 0 enters the PSCI
retstate (cluster_c4,0x4), wakes within ~20 µs again and again, and the SCMI completion interrupt is not taken until another interrupt runs (-32). Plain WFI (cpuidle.off=1, -28) and a busy CPU (polling, -29) never stalled (0 of 3 each). - ADR 0008 gets a dated update; the board DTS change stays until the owner decides.
Update: precision and two dead ends for the next test (2026-11-04, 12:31 AM ET)
- The rate claim was too strong. 2 of 6 stalled boots without domain idle states, against 8 of 11 with them, is not a significant difference at these sample sizes (one-sided p about 0.14, inference). Read it as “may reduce the rate; the sample cannot tell”, not as “cut it to 2 of 6”.
- The window held on the 2-timeout boot. 2026-11-04-1 (2 timeouts, max 1019.2 ms) still came up fully: firmware
0x20000,quirk_perf_level_get_fc_force, cpufreq on all three clusters (netlog, boot 2 of 3 in2026-11-04-netlog.txt). - When the loop starts (-32): the request left at 0.434542 s and CPU 0’s first loop exit came at 0.434606 s,
64 µs later, about when the reply’s interrupt would be asserted (polling replies take ~0.1 ms, -29). Mid-loop
CPU 0 took two SGIs (IPIs) but not the SPI, and a PPI (
arch_timer) released it. Reading (inference): a pending SPI for CPU 0 wakes the core fromretbut is not delivered to its CPU interface; the core re-enters, is woken again every ~20 µs, until a PPI runs. It also fits the 1.2-2.0 s loop with no SCMI pending (another SPI) and -30’s GENI I2C-110timeouts (that controller’s interrupt is an SPI on CPU 0 too). irqaffinity=cannot move SPI 28 off CPU 0:irq_affinity_setup()always adds the boot CPU to the mask (kernel/irq/irqdesc.c:36ata804c57).- CPU 0 alone cannot lose
retby DT: with no state for one CPU,psci_idle_init_cpu()returns-ENODEV(cpuidle-psci.c:399-401) andpsci_cpuidle_probe()fails the whole driver (:437-447), which iscpuidle.off=1for every CPU. Isolating CPU 0 or the interrupt needs a kernel patch.
Update: the stall follows the interrupt’s CPU, attempt 2026-11-04-3 (2026-11-04, 12:44 AM ET)
Attempt 2026-11-04-3: kernel #20 (kernel/patches/0009, commit cee735d), the ADR 0008 board DTS, interrupt
mode, 1000 ms window. The patch calls irq_set_affinity(irq, cpumask_of(1)) in the CPUCP mailbox probe; dmesg shows
qcom_cpucp_mbox 17430000.mailbox: gbook: irq 15 affinity to CPU 1: 0 at 0.226519 s. One cold start (EC G3 first).
- All 78 mailbox interrupts ran on CPU 1:
irq-counts= 15: 0 78 0 0 0 0 0 0 0 0 0 0 GICv3 60 Level apss_cpucp_mbox. - SCMI stalled: max reply 872.0 ms, 0 timeouts, cpufreq on all three clusters.
- The loop moved with it. At the early read (9.63 s), CPU 1’s
state1count was 134862. CPU 0 had 6131 and every other CPU had 79 to 471. - So CPU 0 is not special. The core that takes the reply’s SPI loops in and out of PSCI
retwithout taking it, wherever the SPI is routed (one stalled boot; it moved exactly as the reading predicted). With -28 (plain WFI, 0 of 3 stalled) and -29 (polling, 0 of 3), the mechanism reads (inference): on mica, a core in the PSCIretstate (cluster_c4,arm,psci-suspend-param0x4) is woken by a pending SPI but does not take it until a PPI runs. That fits the other SPIs seen stalling too (-30’s GENI I2C timeouts, -32’s 1.2-2.0 s loop with no SCMI pending). kernel/patches/0009stays until the owner decides the fix, then goes (a diagnostic, ADR 0007).
Update: ADR 0009 confirmed, attempt 2026-11-04-4 (2026-11-04, 12:57 AM ET)
Attempt 2026-11-04-4: kernel #21 (patches 0001-0007, no diagnostics), the board DTS with
ADR 0009 (cluster_c4 deleted from cpu_pd0-11; cluster and system states as
stock), interrupt mode, 1000 ms window. Image 161b32cde0296c3c, commit 1f67420. One cold start.
- No cpuidle driver: every CPU’s
cpuidle-early=andcpuidle=line is empty (/sys/devices/system/cpu/cpuN/ cpuidle/has no states), so cores idle in WFI. The PSCI domain driver still reportsCPUidle PSCI: Initialized CPU PM domain topology using OSI mode. That iscpuidle-psci-domain, not the cpuidle driver. - SCMI clean: 78 replies, max 0.1 ms, 0 timeouts; the SCMI probe ran 0.376-0.391 s. Firmware
0x20000, FC quirk, cpufreq on all three clusters. All 78 mailbox interrupts were on CPU 0. - With -28 (
cpuidle.off=1, 0 of 3), plain WFI is now 4 of 4 cold boots without a stall, every reply within 0.1 ms.
Update: the counts from attempt.sh tally (2026-11-04, 2:31 AM ET)
dumps/firstboot/attempts.tsv now carries machine-read boot health (retro 6), backfilled for -20 to 2026-11-04-4.
The counts above were hand-made; the tally reads:
- Domain idle states present, interrupt mode (-23 to -27, -30 to -33): 7 stalled of 10 known boots, plus -31 unknown (its trace ring lost the SCMI lines; its stall is from dmesg timing only). Against no PSCI cpuidle (-28, 2026-11-04-4): 0 of 4, one-sided Fisher p = 0.035. “8 of 11” above counted -31 as a stall.
- ADR 0008’s DT (-34, -35, 2026-11-04-1 to -3): 3 of 7. Against no PSCI cpuidle: 0 of 4, p = 0.21, not significant on its own. ADR 0009 rests on the mechanism (the stall followed the SPI to CPU 1, 2026-11-04-3) together with the first comparison, not on the boot count against ADR 0008.
- Polling (-29): 0 of 3. Commands:
scripts/attempt.sh tally '^2026-11-03-(2[3-7]|3[0-3])$' '^2026-11-03-28$|^2026-11-04-4$'andscripts/attempt.sh tally '^2026-11-03-3[45]$|^2026-11-04-[123]$' '^2026-11-03-28$|^2026-11-04-4$'.
Update: the tally at ten boots without PSCI cpuidle (2026-11-04, 4:40 AM ET)
The suspend-test boots (2026-11-04-5 to -10, suspend-2026-11-04.md) all ran the
no-PSCI-cpuidle board DT and probed SCMI before suspending. Every one was clean at 0.1 ms. With
'^2026-11-03-28$|^2026-11-04-([4-9]|10)$' as group 2 in the two commands above, no PSCI cpuidle is 0 of 10 known
boots. Against domain states present (7 of 10), the one-sided Fisher p = 0.0015. Against ADR 0008’s DT (3 of 7),
p = 0.051, just above 0.05.