recover-output-after-resume.sh existed to work around the old ThinkPad's /etc/modprobe.d/i915.conf, which forced PSR2 and the deepest display C-states; the flip pending across suspend never completed, so every later commit returned EBUSY and only a full modeset cleared it. That file is gone and this laptop's iGPU is driven by `xe` (Panther Lake has no i915 support at all), so the original cause cannot recur. The modeset is now conditional on the user journal actually reporting "Atomic commit failed"/"Page-flip failed" within the last 3 minutes. Unconditional disable/enable + `shikanectl reload` on every resume was itself a hazard: it is the exact sequence that re-triggers the shikane VariantInProgress deadlock the watchdog exists to recover from. hypridle.conf's comment no longer references the deleted i915.conf.
61 lines
2.7 KiB
Bash
Executable File
61 lines
2.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# recover-output-after-resume -- clear a post-resume eDP page-flip stall.
|
|
#
|
|
# Symptom (see journalctl --user --since -5m | grep 'Atomic commit failed'):
|
|
# [wlr] backend/drm/atomic.c:82 connector eDP-1: Atomic commit failed:
|
|
# Device or resource busy
|
|
# [sway] desktop/output.c:307 Page-flip failed on output eDP-1
|
|
# ...repeatedly for tens of minutes after a resume.
|
|
#
|
|
# HISTORY: this was originally a workaround for the old ThinkPad's
|
|
# /etc/modprobe.d/i915.conf, which forced PSR2 and the deepest display C-states
|
|
# (options i915 enable_guc=3 enable_psr=2 enable_dc=4 enable_rc6=1 -- both of
|
|
# which taint the kernel). With PSR2 forced on, the flip pending across suspend
|
|
# never completed, so every later commit returned EBUSY, and DPMS "power on"
|
|
# alone did not clear it -- only a full modeset did.
|
|
#
|
|
# STATUS: that file is gone. This machine is a Framework Laptop 13 Pro whose
|
|
# iGPU is driven by `xe` (Panther Lake has no i915 support at all), so the
|
|
# original cause cannot recur. The modeset below is therefore CONDITIONAL and
|
|
# only fires when the stall is actually present in the journal.
|
|
#
|
|
# Why conditional: an unconditional disable/enable plus `shikanectl reload`
|
|
# after every resume is exactly the sequence that re-triggers the shikane
|
|
# 1.1.1 VariantInProgress deadlock (see shikane-watchdog.sh). No point paying
|
|
# that risk on resumes that are already healthy.
|
|
#
|
|
# Lid-aware on purpose: a blind `output eDP-1 enable` raced shikane's
|
|
# "External Display" profile (which keeps eDP-1 off) and caused
|
|
# "Atomic commit failed: Device or resource busy" churn in clamshell mode.
|
|
# See the note in clamshell-mode.sh.
|
|
|
|
set -u
|
|
|
|
LID_STATE="${LID_STATE:-/proc/acpi/button/lid/LID/state}"
|
|
OUTPUT="${OUTPUT:-eDP-1}"
|
|
|
|
# Always undo the idle DPMS-off first (this is what after_sleep_cmd used to do).
|
|
swaymsg "output * power on" 2>/dev/null
|
|
|
|
# Only escalate to a modeset if the page-flip stall is actually being reported.
|
|
# sway runs inside the user session, so its stderr is in the user journal.
|
|
if command -v journalctl >/dev/null 2>&1; then
|
|
if ! journalctl --user --since '-3 min' --no-pager 2>/dev/null \
|
|
| grep -qE 'Atomic commit failed|Page-flip failed on output'; then
|
|
exit 0 # healthy resume -> do not disturb shikane
|
|
fi
|
|
fi
|
|
|
|
# The modeset below is lid-gated only.
|
|
[ -r "$LID_STATE" ] || exit 0
|
|
grep -q 'open' "$LID_STATE" || exit 0 # lid closed -> leave layout to shikane
|
|
|
|
# Give the driver a moment to finish re-training the link before we modeset.
|
|
sleep 1
|
|
swaymsg "output $OUTPUT disable" 2>/dev/null
|
|
sleep 1
|
|
swaymsg "output $OUTPUT enable" 2>/dev/null
|
|
# Re-assert the shikane profile (mode/scale/position) on top of the modeset.
|
|
command -v shikanectl >/dev/null 2>&1 && shikanectl reload 2>/dev/null
|
|
exit 0
|