File amdgpu-power.sh of Package amd-dgpu-pwr
#!/bin/bash
# 61‑amdgpu‑power – early‑boot helper for discrete AMD GPUs
# shellcheck shell=sh
. /lib/dracut-lib.sh # getarg(), warn(), etc.
set -ux
# set -e
# ───────────── 0 – fast‑bail conditions ────────────────
[ -n "${resume-}" ] && exit 0 # resume (from hibernate), do nothing
case "$(cat /proc/cmdline)" in
*modprobe.blacklist=amdgpu*|*modprobe.blacklist=*amdgpu*) exit 0 ;;
esac
# ───────────── 1 – defaults + cmdline overrides ────────
PCI_BASE="0000:03:00" #Base dGPU device
PCI_SLOT="0" # For hot reset using /sys/bus/pci/slots/X
POWER1CAP="50000000" # µW
TIMEOUT=20 # seconds total before we give up
arg=$(getarg rd.amdgpu_pci=) && PCI_BASE="${arg#*=}"
arg=$(getarg rd.amdgpu_pci_slot=) && PCI_SLOT="${arg#*=}"
arg=$(getarg rd.amdgpu_cap=) && POWER1CAP="${arg#*=}"
arg=$(getarg rd.amdgpu_wait=) && TIMEOUT="${arg#*=}"
GPUPATH="/sys/bus/pci/devices/${PCI_BASE}.0"
SLOTPATH="/sys/bus/pci/slots/${PCI_SLOT}"
# ───────────── 2 – ensure device & driver exist ────────
echo 0 > "$SLOTPATH/power"
sleep "2s"
echo 1 > "$SLOTPATH/power"
sleep "2s"
(
# echo 1 > /sys/bus/pci/rescan
modprobe -v -a snd_hda_intel amdgpu || {
warn "amdgpu-power: modules not loadable (code $?), giving up"
exit -1; # does not work due to subshell
}
# wait
) 1>&2
# helper: wait until a file/dir appears or TIMEOUT expires
wait_path() {
local path=$1 i=0
while [ $i -lt "$TIMEOUT" ] && [ ! -e "$path" ]; do
i=$((i+1))
sleep 1
done
[ -e "$path" ]
}
# ───────────── 3 – main work ────────────
(
# wait for GPU directory
if ! wait_path "$GPUPATH"; then
warn "amdgpu‑power: GPU path $GPUPATH not found"
exit 0
fi
cd "$GPUPATH" || exit 1
# wait for PM knobs
for knob in power/control d3cold_allowed; do
if ! wait_path "$knob"; then
warn "amdgpu‑power: $knob missing, giving up"
exit 0
fi
done
# wait for pp_features
if ! wait_path "pp_features"; then
warn "amdgpu‑power: pp_features missing, giving up"
exit 0
fi
# snapshot current PM state
POWER_CTRL=$(cat power/control 2>/dev/null || echo auto)
D3COLD=$(cat d3cold_allowed 2>/dev/null || echo 1)
# wait for hwmon/power1_cap and write the cap
i=0
PWRCAP_RET="-1"
while true; do
[[ "$i" -ge "$TIMEOUT" ]] && {
[[ "$PWRCAP_RET" != "0" ]] && warn "amdgpu-power: retries exceeded"
break
}
i=$((i+1))
sleep "1.1s"
cd "$GPUPATH" || exit 1
# ls -l
# ls -l hwmon || :
# ls -l hwmon/* || :
echo on > power/control
echo 0 > d3cold_allowed
{
grep -E 'PPT.*enabled' pp_features || {
warn "amdgpu-power: PPT disabled or not present!"
continue ;
}
CAP_PATH="$(echo -n hwmon/*/power1_cap)"
[[ "$CAP_PATH" == 'hwmon/*/power1_cap' ]] && {
warn "amdgpu-power: hwmon power1_cap not available yet"
continue;
}
#"$(readlink -f hwmon/*/power1_cap)"
# echo "$CAP_PATH"
# ls -l "$CAP_PATH"
echo "$POWER1CAP" > "$CAP_PATH" ;
PWRCAP_RET=$?
} #&& break
[[ "$PWRCAP_RET" == "0" ]] && {
# break
TIMEOUT='3'
}
done
[[ "$PWRCAP_RET" != "0" ]] && {
warn "amdgpu‑power: power1_cap not writable (code $PWRCAP_RET)"
}
sleep 1
# restore previous PM policy
echo "$POWER_CTRL" > power/control
echo "$D3COLD" > d3cold_allowed
) 1>&2
# (
# modprobe -v snd_hda_intel || {
# warn "snd_hda_intel: not loadable (code $?), giving up"
# exit -1; # does not work due to subshell
# }
# )
wait || warn "Got modprobe status $?"
# Reload audio devices, seems like this doesn't work until graphics come up?
AUD_DRV_PATH="/sys/module/snd_hda_intel/drivers/pci:snd_hda_intel/"
#
# for dev in "$AUD_DRV_PATH"/????:??:??.? ; do
# echo 1 > "$dev/remove"
# done
# wait
# sleep "2s"
# echo 1 > /sys/bus/pci/rescan &
exit 0