Repository navigation
T8140 sleep: fixes from review - #1313
Closed
DjDeveloperr wants to merge 16 commits into
Closed
DjDeveloperr wants to merge 16 commits into
DjDeveloperr wants to merge 16 commits into
Conversation
A firmware-driven suspend stops cout, cin and the speaker tap, and only their DAI prepare starts them again. The dmaengine refine still adds SNDRV_PCM_INFO_PAUSE and _RESUME, so after a wake user space resumes these PCMs instead of preparing them: headphone playback, the headset microphone and Speaker Sense run silent until reopened. Mask both flags after the refine, as aop_spkr.rs does. Without RESUME user space prepares again. PAUSE goes too: with it the suspend only pauses the ADMAC transfer, and the paused one blocks the next start. Signed-off-by: Diljit Singh <hey@djdev.me>
On T8140, DPMS off stops the internal DCP's firmware with presentation paused until DPMS on restarts it. A suspend that isn't firmware-driven (s2idle, also the default without the loader's PCIe tunables) still runs dcp_hold_for_sleep(), and dcp_release_after_sleep() then unpauses presentation on the stopped firmware. A present queued after the wake is never answered, the IOMFB timeout marks the DCP crashed, and the next DPMS on fails: the panel stays dark until reboot. Skip the hold while the firmware is stopped: it sends nothing, and its presentation stays paused for DPMS on. Signed-off-by: Diljit Singh <hey@djdev.me>
A DCP that crashed, or gave no reply to A500, is stopped cold at the next sleep and started again after it, but the AP side of its transport is left as it was: the unanswered call keeps its channel depth, the transaction in flight stays iomfb.active, and while crashed is still set the new firmware's IOMFB messages and calls are dropped. The queue never runs again: DCPEXT's display stays dead, every later sleep is refused as "display updates still pending", and the internal DCP's set_power_state after the restart fails with -EIO. Before either start function brings up a firmware that stopped while crashed, release the active and pending transactions, zero the channel depths and the present state, and clear crashed. This covers the restart after a sleep, DPMS on, DCPEXT's power cycle and the end of a dark wake. A failed start marks it crashed again, as before. Signed-off-by: Diljit Singh <hey@djdev.me>
…nation Once a platform registers spin-table power ops, spin_table_cpus_stuck() returns false and kexec goes ahead. But machine_shutdown() only parks the secondaries: each waits in smp_rvbar_spin_table_cpu_die(), in this kernel's text and on its idle stack, and the power ops run only at a suspend's commit. The new image overwrites that memory under the parked CPUs, and the new kernel can't start them. Before the parking ops such a kexec failed cleanly with -EBUSY. Hibernation has the same problem: cpus_are_stuck_in_kernel() is false because the ops have a cpu_die. Take parking CPUs as stuck whether or not power ops are registered, and check that before hibernating too. Hotplug and suspend-to-RAM don't look at it, and a crash kexec still goes ahead. Signed-off-by: Diljit Singh <hey@djdev.me>
apple_rtkit_sleep_stop() promises that on an error the firmware still runs. But when the AP and IOP idles are both acknowledged and only the 5 ms status poll misses, it returns -ETIMEDOUT with the firmware idled, and an idled firmware doesn't come back without a real sleep. SIO's suspend_late then refuses the sleep with nothing to restart the firmware: every SIO transfer fails, and every later sleep is refused until reboot. PMP and DCPEXT use the same call. Once both idles took, warn and finish the stop, so the caller's resume path brings the firmware back. The other half: when only the AP idle took, apple_rtkit_sleep_return() reports the firmware as running after a refused sleep, but its AP state is still idle and every endpoint send fails. Send AP on there. Signed-off-by: Diljit Singh <hey@djdev.me>
After a real sleep, sio_resume_early() clears sio->asleep before it tries the warm restart. If that fails, SIO's firmware is down but marked awake, so the next sio_suspend_late() sends an idle notice to nothing, times out and refuses the sleep, and so does every later one until reboot. Clear asleep only once the firmware is back. A failed restart then leaves SIO as the sleep left it: the next real sleep restarts it, and a refused one takes the existing engine-reset path. Signed-off-by: Diljit Singh <hey@djdev.me>
When the MTP doesn't answer the AP idle notice in time, .prepare refuses the sleep and leaves idle_unanswered for .complete, which sends AP on if the answer came late. But the PM core calls no .complete for a device whose .prepare failed. A late answer then leaves the MTP, which carries the internal keyboard and trackpad, told the AP is idle while the system runs, until a later sleep gets through. Do the same end-of-sleep step from a PM_POST_SUSPEND notifier when idle_unanswered is still set. That runs after the failed suspend has unwound, so a late answer has had time to arrive, and is a no-op after any sleep whose .complete ran. Signed-off-by: Diljit Singh <hey@djdev.me>
The USB host's PHY lowers ATC0_USB and ATC0_COMMON itself at noirq, and the resync after a wake leaves them to it. genpd's own noirq power-off doesn't know: it keeps ATC0_USB only while a device in it is on the wakeup path and the domain has GENPD_FLAG_ACTIVE_WAKEUP, which it gets only when it was on at probe. Otherwise genpd powers ATC0_USB "off" and walks up, and ATC0_USB_AON, the always-on side the in-place sleep keeps, really goes off. At the wake, or after a refused sleep, genpd then raises USB_AON, COMMON and USB before the PHY opens the fabric bridge, the order the resync avoids. The host restarts and its devices enumerate again. During system sleep, refuse genpd's power-off of a domain its driver took down, as for a sleep-retained one. genpd then leaves it and its parents alone, and has nothing to raise. Signed-off-by: Diljit Singh <hey@djdev.me>
admac_resume_early() marks a held channel's registers lost only when the sleep reached the hardware. The ADMACs' power domains are plain leaves, though, so genpd powers them off at noirq in every system sleep, and a firmware-driven sleep refused after that (a wakeup event, or a refusal in the platform's .enter) brings them back reset. The open stream then runs with no SRAM carveout and the default channel setup until it is reopened. Mark them lost after any firmware-driven sleep. The restore waits for the next transfer start and only writes the saved values back, so it costs nothing when the registers survived. SoCs whose suspend isn't firmware-driven are unchanged. Signed-off-by: Diljit Singh <hey@djdev.me>
After a wake, the glue's sleep_finish work runs apple_atcphy_sleep_finish(), which may update the SuperSpeed mux, and atcphy_usb3_pm_get() takes the dwc3-apple device lock for that. An unbind of dwc3-apple holds that lock across remove() and devres, where devm_work_autocancel() waits for the same work: the unbind hangs, and the next dpm_prepare() blocks on the device lock too. Queue the finish on a work the PHY owns, with a flush for the next sleep's PM_SUSPEND_PREPARE. The PHY's unbind cancels it. An unbind of the controller no longer waits for it: the work takes the lock once the unbind is done, finds no driver bound, and gets -EAGAIN. Signed-off-by: Diljit Singh <hey@djdev.me>
After a T8140 sleep, apple_nvme_resume() only queues the reset work, which waits for ANS and sets the controller up again. A dark wake goes straight back to sleep, so the next apple_nvme_suspend() can arrive while the controller is still RESETTING or CONNECTING: sleep_wanted is false and the change to RESETTING fails with -EBUSY, which turns the dark wake into a full wake behind the closed lid. That .suspend also clears sleep_failed and sleep_restarted while the reset work reads them. Flush the reset work before deciding. It is idle in every other case, and its wait for ANS is bounded. Signed-off-by: Diljit Singh <hey@djdev.me>
…laimed Resuming a paused cyclic transfer whose rings a sleep took restarts it with admac_start_current_tx(), but keeps submitted_pos and nperiods_outstanding from before the sleep. The descriptors the reset dropped never report, so the position stays up to the ring depth behind the DMA for the rest of the stream: playback underruns go unnoticed and capture can overwrite unread periods. Rewind the transfer to the last period reclaimed before restarting it. Signed-off-by: Diljit Singh <hey@djdev.me>
This was referenced Nov 9, 2026
Lines the stack up: the review fixes now sit on the debug port's page select resend, and on integration/aurora 15f88e1. No conflicts. Signed-off-by: Diljit Singh <hey@djdev.me>
DjDeveloperr
changed the base branch from
fix/t8140-debug-link-rearm
to
fix/t8140-debug-port-select
November 9, 2026 18:17
Brings in #1208's aop-bootargs host test fix. No conflicts. Signed-off-by: Diljit Singh <hey@djdev.me>
Signed-off-by: Diljit Singh <hey@djdev.me>
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes from the offline review of the T8140 deep-sleep series (#1208 through #1285), one commit per finding, on top of #1285 at 7072491. All 12 medium-or-higher findings were still real on that head. Ten patches went in as the review wrote them, with comments shortened. Two were rewritten: #3 resets the transport from both firmware-start functions, so the dark-wake finish is covered too, and #7 runs from PM_POST_SUSPEND, so a late answer gets the whole unwind to arrive.
kexec -e; now refused with -EBUSY as before the seriesapple_rtkit_sleep_stop()fails after both idles were acked, andsleep_return()calls a half-idled firmware runningasleepbefore a restart that fails.completeafter a failed.prepare, so a late idle answer is never followed by AP onTested offline only:
sound/soc/apple(aop_audio.o, which includesaop_t8140.rs). Exit 0, with no new warnings: the 11-Wthread-safety-analysiswarnings innvme/host/apple.creset_work are identical on 7072491.hibernate.c. 527/528 passed; the 1 skip is an unrelated G17 test that needsUCLAMP_TASK.-Wno-unused-but-set-globalfor host clang 23), atc-usb3 with mutations 2/2, rtkit-oslog 6/6, t6030-clock 1/1, neo-stability 10/10.checkpatchis clean on all 12.Needs an on-device check on the Neo:
aplayshould print "Restarting stream" at the wake, and the audio should continue.mem_sleep= s2idle), wake, DPMS on. The panel should light, with no "IOMFB transaction timed out" or "display power-on failed".kexec -lshould be refused with "Can't kexec: CPUs are stuck in the kernel" (EBUSY).🤖 Generated with Claude Code