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).