Port ROCKNIX deep-sleep and charger-wake kernel fixes - #1
Conversation
7341399 to
1fc6c5d
Compare
|
Cross-repository firmware-path dependency Upstream commit 63010cc in the rebased kernel branch changes the RP6 DTB firmware path from qcom/sm8550/ayn/odin2 to qcom/sm8550/retroidpocket/rp6. The current Armada image did not yet provide that directory, which prevented ADSP startup and caused both null audio and unavailable battery readings in the first full snapshot. The companion Armada PR now fixes the image side in commit 8936883 by providing a validated compatibility alias to the already-tested Odin 2 blobs. The kernel change remains device-specific and unchanged; native RP6 firmware can replace the alias later. See gh123man/armada#1. |
1fc6c5d to
95e7854
Compare
qcom_spmi_haptics_global_playback() is reached from the rsinput force-feedback callback, which runs below input_event() with the input device event lock held and interrupts disabled. It calls haptics_erase() directly, which takes a mutex and synchronously cancels delayed work, so it can sleep: "BUG: scheduling while atomic" during game rumble. Record the latest request atomically and apply it from a workqueue, serialise upload, playback and gain with a mutex in process context, and drain both the playback work and the delayed stop work before the haptics device suspends. Ported from gh123man/armada-packages#1, where it was found, root-caused and validated on hardware while testing the SM8550 deep-suspend series. Not a suspend fix in itself: the crash is reachable on any device carrying 1003-rsinput-add-ff.patch whenever a game rumbles, no suspend involved.
|
Seems like folks are discovering this branch. however it's worth noting that while CPU sleep works, there is still somewhat significant battery draw due to CX/AOSS/DDR remaining on. Not sure if there are reference patches to fix this. Additionally - this series of patches wakes the device when the USB charger is plugged in. However this implementation also causes the device to randomly wake when other operations happen. This requires a userspace wake management routine in this PR: gh123man/armada#1 which is not totally stable yet. Cherrypick at your own risk 😄 |
qcom_spmi_haptics_global_playback() is reached from the rsinput force-feedback callback, which runs below input_event() with the input device event lock held and interrupts disabled. It calls haptics_erase() directly, which takes a mutex and synchronously cancels delayed work, so it can sleep: "BUG: scheduling while atomic" during game rumble. Record the latest request atomically and apply it from a workqueue, serialise upload, playback and gain with a mutex in process context, and drain both the playback work and the delayed stop work before the haptics device suspends. Ported from gh123man/armada-packages#1, where it was found, root-caused and validated on hardware while testing the SM8550 deep-suspend series. Not a suspend fix in itself: the crash is reachable on any device carrying 1003-rsinput-add-ff.patch whenever a game rumbles, no suspend involved.
|
there's more patches from the original developer of the patch here: https://github.com/thorch-os/thorch/pulls?q=is%3Apr+is%3Aclosed+sleep including 10x lower power consumption |
82991f3 to
4a28583
Compare
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
qcom_glink_smem_register() requests every transport interrupt with IRQF_NO_SUSPEND, so GLINK client callbacks can run against already- suspended devices, and IPCC children advertise IRQCHIP_SKIP_SET_WAKE, so no client can arm the GIC summary interrupt as a wake source. Drop IRQF_NO_SUSPEND, let an IPCC child propagate its wake configuration to the shared parent, and register the existing transport interrupt as the device wake IRQ when the edge is described as "wakeup-source". Ported from gh123man/armada-packages#1, renumbered from 0506/0507 because those numbers are taken here. No node is marked wakeup-source in this branch, so nothing gains a wake source: arming the ADSP edge would undo 0502 unless userspace can separate a real charger transition from background BATTMGR chatter, which is what Armada's companion policy does and ROCKNIX has no equivalent of yet.
qcom_spmi_haptics_global_playback() is reached from the rsinput force-feedback callback, which runs below input_event() with the input device event lock held and interrupts disabled. It calls haptics_erase() directly, which takes a mutex and synchronously cancels delayed work, so it can sleep: "BUG: scheduling while atomic" during game rumble. Record the latest request atomically and apply it from a workqueue, serialise upload, playback and gain with a mutex in process context, and drain both the playback work and the delayed stop work before the haptics device suspends. Ported from gh123man/armada-packages#1, where it was found, root-caused and validated on hardware while testing the SM8550 deep-suspend series. Not a suspend fix in itself: the crash is reachable on any device carrying 1003-rsinput-add-ff.patch whenever a game rumbles, no suspend involved.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
qcom_glink_smem_register() requests every transport interrupt with IRQF_NO_SUSPEND, so GLINK client callbacks can run against already- suspended devices, and IPCC children advertise IRQCHIP_SKIP_SET_WAKE, so no client can arm the GIC summary interrupt as a wake source. Drop IRQF_NO_SUSPEND, let an IPCC child propagate its wake configuration to the shared parent, and register the existing transport interrupt as the device wake IRQ when the edge is described as "wakeup-source". Ported from gh123man/armada-packages#1, renumbered from 0506/0507 because those numbers are taken here. No node is marked wakeup-source in this branch, so nothing gains a wake source: arming the ADSP edge would undo 0502 unless userspace can separate a real charger transition from background BATTMGR chatter, which is what Armada's companion policy does and ROCKNIX has no equivalent of yet.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
ufshcd_gate_work() only restores the software gating state when DME_HIBER_ENTER times out; it does not repair the link. During system PM pm_op_in_progress suppresses the generic fatal error handler, so the controller is left operational in software but unable to complete device commands, and a following suspend can block in the filesystem sync after userspace has already blanked the display. That is the shape of the 54s "Filesystems sync" tiopex reported on the Thor. Recover the failed enter inline, using the out-of-band relink completion poller added by 0201, then pin runtime clock gating off for the rest of the boot so the same idle Hibern8 is not retried. System PM keeps working and can still transition the link for suspend. Ported from gh123man/armada-packages#1, written against this same series.
The failure-only diagnostics in the patch above captured the ordering behind that timeout: the gate worker had been admitted and had entered DME_HIBER_ENTER before system PM took its hold, so ufshcd_hold() changed the gating state under a running UIC command and the PM path then waited on that worker. Take a clock-gating hold in ufshcd_suspend_prepare() and release it from ufshcd_resume_complete(). That drains a pending gate worker while normal completion handling is still available, and stops a new idle Hibern8 starting inside the device suspend and resume callbacks. This is the root fix; the inline recovery stays as the storage-safety fallback. Ported from gh123man/armada-packages#1.
Summary
aa7d8320421bd44ec5b46b2d852b544fec237c54IRQF_NO_SUSPENDhandling with opt-in device-tree wake IRQs/sys/power/pm_wakeup_irqinterface used by Armada's userspace wake classifierWhy
Armada already has a real-suspend path, but its Linux 7.0.11 patch series lacked the UFS, TSENS, GENI UART, controller lifecycle, haptics, and charger-wake fixes needed for reliable SM8550 deep sleep. The UFS interrupt hunk is rebased onto Armada's 7.0.11 base; imported changes preserve their ROCKNIX provenance, while Armada-authored patches are attributed to
gh123man <gh123man@users.noreply.github.com>.Hardware testing exposed three additional gaps:
input_event()with the input event spinlock held and interrupts disabled. Calling the QCOM haptics erase/playback callbacks directly from there can sleep and produced atomic-context failures. Playback is now recorded atomically and applied by a workqueue.ufshcd_gate_work()only restored its software state whenDME_HIBER_ENTERtimed out. During system PM,pm_op_in_progresssuppresses generic fatal error handling, so the UFS link remained unusable and a later suspend could hang in filesystem sync after the screen had blanked. The failure is now recovered inline using the existing PM relink completion poller. After successful recovery, runtime UFS clock gating is pinned off for the rest of that boot as a circuit breaker; system deep sleep remains enabled.DME_HIBER_ENTERbefore system PM took its hold. The root fix retains a clock-gating hold across the existing system-PM prepare/complete window, draining any pending gate worker while normal completion handling is available and preventing a new idle Hibern8 command during device suspend/resume callbacks.The inline recovery and per-boot clock-gating circuit breaker remain as a storage-safety fallback; disabling clock gating is no longer the primary fix.
Charger wake architecture
On SM8550, charger and Type-C events are decoded by ADSP firmware and delivered through PMIC GLINK. The sleeping AP can only arm the broad IPCC/GLINK transport wake; it cannot select charger packets by opcode before resume.
ROCKNIX PR #2954 identifies the RP6's unsolicited
BATTMGR_NOTIFICATIONtraffic and supplies the critical IPCCIRQF_NO_SUSPENDfix. This PR additionally makes the selected GLINK child an orderly wake source. The companion Armada userspace policy distinguishes a real offline-to-online charger transition from unrelated GLINK traffic before the graphical session is thawed.CONFIG_PM_DEBUG=yderivesCONFIG_PM_SLEEP_DEBUG=yand exposes the standard/sys/power/pm_wakeup_irqABI used for that classification. It does not create a debug kernel or force verbose PM output;pm_debug_messagesandpm_print_timesremain off. No custom wake-reason ABI is added.Captured UFS race
That failure recovered successfully:
Validation
checkpatch.pl --no-tree --strictfor the UFS root-fix patch with zero errors, warnings, or checksqcom_battmgris present and early remoteproc/GPU firmware plus rsinput/haptics modules are absent from the initramfsbootc container lintcheckskernel-glink-policy-33fd641b3c8eon a Retroid Pocket 6DME_HIBER_ENTERtimeout; inline link recovery completed and diagnostics captured the race/sys/power/pm_wakeup_irqreports the standard IPCC wake source required by the userspace classifier