My Laptop Froze on the Second Suspend — I Had to Hold the Power Button
Saturday morning I closed my laptop lid. The first suspend worked perfectly — it slept for nine hours and woke up fine. An hour later I triggered sleep again, and the machine never came back. Black screen, no backlight, no Caps Lock blink, no SSH. I held the power button for ten seconds and hoped nothing was corrupt.
The Logs Told the Story
The killer line appeared on every boot and every suspend transition:
amdgpu 0000:03:00.0: [drm] *ERROR* dc_dmub_srv_log_diagnostic_data:
DMCUB error - collecting diagnostic data
But here’s the critical detail: on the first
suspend/resume cycle, the DMCUB error appeared during wake-up and the
system recovered. On the second cycle, the error
appeared during suspend entry — and the journal stopped dead
right after PM: suspend entry (s2idle). The display
microcontroller’s state was corrupted from the first cycle.
Why the First Suspend Worked but the Second Didn’t
The DMCUB (Display Micro-Controller Unit) is a tiny
co-processor inside the AMD Barcelo APU that manages the display
pipeline — panel power states, refresh timing, and the transition
between active and idle modes. It runs a closed-source firmware
blob loaded by the Platform Security Processor at boot. The
amdgpu driver talks to it, but the firmware itself is a
black box from AMD.
What happened: the first suspend/resume cycle left the DMCUB firmware in a partially corrupt state. The second suspend pushed it over the edge, and the display engine hung during the power-down sequence. Since the GPU couldn’t drive the panel and the kernel was mid-suspend, there was no way to recover — not even a TTY switch.
I Already Had a Fix — It Wasn’t Strong Enough
I’d previously added amdgpu.dcdebugmask=0x10 to my
kernel command line via a Limine drop-in at
/etc/limine-entry-tool.d/amdgpu-psr.conf. That masks the
PSR (Panel Self Refresh) path in the Display Core —
enough to prevent mid-session black screens, but not enough to
survive a second suspend.
| Mask | What it disables | Effective against |
|---|---|---|
dcdebugmask=0x10 |
PSR (Panel Self Refresh) | Mid-session black screens, single suspend |
dcdebugmask=0x600 |
PSR + Panel Replay | Multiple suspend/resume cycles |
amdgpu.dc=0 |
Entire Display Core | Everything — but loses modern features |
The upgrade from 0x10 to 0x600 disables
Panel Replay as well — another power-saving feature
that lets the panel replay a cached frame without the GPU resending it.
On this Barcelo APU with this specific panel (16” 1920×1080 in an Acer
Aspire AL15-42P), the Panel Replay transition during the second
suspend cycle triggers the DMCUB hang.
The Fix
# 1. Update the drop-in (replace 0x10 with 0x600)
sudo sed -i 's/dcdebugmask=0x10/dcdebugmask=0x600/' \
/etc/limine-entry-tool.d/amdgpu-psr.conf
# 2. Verify
cat /etc/limine-entry-tool.d/amdgpu-psr.conf
# Should show: KERNEL_CMDLINE[default]+=amdgpu.dcdebugmask=0x600
# 3. Regenerate boot entries
sudo limine-update
# 4. Reboot
sudo reboot
After reboot, confirm it took effect:
cat /proc/cmdline | grep dcdebugmask
# Should show: amdgpu.dcdebugmask=0x600
Then test suspend twice in a row to verify. Both cycles should complete without a freeze.
Why the Limine Drop-in Matters
CachyOS uses Limine, not GRUB. Editing
/boot/limine.conf directly will be silently
overwritten the next time a kernel package triggers
limine-mkinitcpio-hook. The drop-in at
/etc/limine-entry-tool.d/ is the only way to make kernel
parameters survive updates.
The Side Quest: A Misconfigured Service
While digging through the logs, I noticed another problem — a
systemd user service called
career-ops-web.service was failing every 5 seconds because
its ExecStart pointed to a script that didn’t exist:
career-ops-web.service: Failed at step EXEC spawning
~/workspace/web-scripts/start-dev.sh:
No such file or directory
The restart counter was at 3,117 during the previous
boot. Every 5 seconds, a new process spawned and died. This wasn’t
causing the suspend freeze, but it was wasting CPU and flooding the
journal. A quick
systemctl --user disable --now career-ops-web.service put
an end to it.
Lesson: when you’re debugging a system-level problem, always scan the journal for other anomalies. Spammy services add noise that can obscure the real issue.
How to Audit Your Own Suspends
Three commands tell you everything:
# What errors did the previous boot see?
journalctl -b -1 -p err --no-pager -n 50
# Any DMCUB errors in the kernel log?
journalctl -b -1 -k | grep -i dmcub
# Trace every suspend/resume transition
journalctl -b -1 | grep -iE 'suspend|resume|sleep|PM:'
If you see dc_dmub_srv_log_diagnostic_data: DMCUB error
paired with PM: suspend entry (s2idle) and no corresponding
resume, you’ve got the same bug.
Bottom Line
The AMD DMCUB firmware on Barcelo APUs has a state-corruption bug
across multiple suspend/resume cycles.
amdgpu.dcdebugmask=0x10 (PSR off) isn’t sufficient — you
need 0x600 (PSR + Panel Replay off) if your machine freezes
on the second suspend. The Limine drop-in at
/etc/limine-entry-tool.d/ keeps the fix alive across kernel
updates. And while you’re in the logs, clean up any services that are
restarting every 5 seconds — they won’t fix your suspend, but they’ll
make the next debugging session easier.
Hardware: Acer Aspire AL15-42P, AMD Ryzen 7 7730U (Barcelo, 1002:15e7), 16” 1920×1080 panel, 16GB DDR5. CachyOS, linux-cachyos 7.1.6-1 / linux-cachyos-lts 6.18.42-1, linux-firmware 20260622-1, Limine 12.5.2, KDE Plasma 6.7.4 (Wayland).