116 lines
3.3 KiB
Bash
Executable File
116 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Reset Intel SOF audio PCI driver (sof-audio-pci-intel-cnl) for 0000:00:1f.3
|
|
# Goal: recover from SOF/HDA DMA channel exhaustion ("hda-dmac: ... no free channel")
|
|
# that manifests as HDMI hw_params failures / ipc tx error -5 in kernel logs.
|
|
#
|
|
# IMPORTANT:
|
|
# - This script is intended to be run as root (sudo).
|
|
# - For unattended automation from tools without a TTY, add a single sudoers NOPASSWD entry, e.g.:
|
|
# jack ALL=(root) NOPASSWD: /home/jack/文档/chromebox_10th_audio_driver/scripts/reset-sof-hdmi-pci.sh
|
|
#
|
|
# Usage:
|
|
# sudo bash scripts/reset-sof-hdmi-pci.sh
|
|
# sudo bash scripts/reset-sof-hdmi-pci.sh --verify-pcm2
|
|
#
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DOCTOR="${REPO_ROOT}/scripts/kaisa-audio-doctor.sh"
|
|
|
|
DEV_PCI="${DEV_PCI:-0000:00:1f.3}"
|
|
DRIVER_NAME="${DRIVER_NAME:-sof-audio-pci-intel-cnl}"
|
|
DRIVER_SYSFS="/sys/bus/pci/drivers/${DRIVER_NAME}"
|
|
|
|
DESKTOP_USER="${DESKTOP_USER:-jack}"
|
|
|
|
VERIFY_PCM2=0
|
|
if [[ "${1:-}" == "--verify-pcm2" ]]; then
|
|
VERIFY_PCM2=1
|
|
fi
|
|
|
|
log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*"; }
|
|
|
|
require_root() {
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
echo "ERROR: run as root: sudo bash $0" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
mount_debugfs_if_needed() {
|
|
if mountpoint -q /sys/kernel/debug; then
|
|
log "debugfs already mounted"
|
|
return 0
|
|
fi
|
|
log "mounting debugfs on /sys/kernel/debug"
|
|
mount -t debugfs none /sys/kernel/debug
|
|
}
|
|
|
|
stop_user_audio() {
|
|
log "stopping user audio services for ${DESKTOP_USER}"
|
|
# Use sudo -u to target the desktop user's systemd --user session.
|
|
# This requires root privileges (this script runs as root).
|
|
sudo -u "${DESKTOP_USER}" XDG_RUNTIME_DIR="/run/user/$(id -u "${DESKTOP_USER}")" \
|
|
systemctl --user stop wireplumber pipewire-pulse pipewire || true
|
|
sleep 1
|
|
}
|
|
|
|
start_user_audio() {
|
|
log "starting user audio services for ${DESKTOP_USER}"
|
|
sudo -u "${DESKTOP_USER}" XDG_RUNTIME_DIR="/run/user/$(id -u "${DESKTOP_USER}")" \
|
|
systemctl --user start pipewire pipewire-pulse wireplumber || true
|
|
sleep 2
|
|
}
|
|
|
|
pci_reset() {
|
|
if [[ ! -d "${DRIVER_SYSFS}" ]]; then
|
|
echo "ERROR: driver sysfs dir missing: ${DRIVER_SYSFS}" >&2
|
|
ls -la /sys/bus/pci/drivers | grep -i sof || true
|
|
exit 1
|
|
fi
|
|
|
|
log "unbinding ${DEV_PCI} from ${DRIVER_NAME}"
|
|
echo "${DEV_PCI}" >"${DRIVER_SYSFS}/unbind"
|
|
sleep 1
|
|
|
|
log "binding ${DEV_PCI} to ${DRIVER_NAME}"
|
|
echo "${DEV_PCI}" >"${DRIVER_SYSFS}/bind"
|
|
sleep 2
|
|
}
|
|
|
|
tail_kernel_hints() {
|
|
log "kernel hints (last ~120 matching lines)"
|
|
journalctl -k -b --no-pager 2>/dev/null | \
|
|
grep -nE 'sof-audio-pci-intel-cnl|Firmware file:|Topology file:|Firmware info: version|ipc tx error|sof_ipc3_pcm_hw_params|hda-dmac|dma_channel_get|ASoC error|HDMI[0-9]|pcm[0-9]+' | \
|
|
tail -n 120 || true
|
|
}
|
|
|
|
maybe_verify() {
|
|
if [[ "${VERIFY_PCM2}" -ne 1 ]]; then
|
|
return 0
|
|
fi
|
|
if [[ ! -x "${DOCTOR}" ]]; then
|
|
echo "WARN: doctor script missing: ${DOCTOR}" >&2
|
|
return 0
|
|
fi
|
|
log "running doctor verify (pcm2) as ${DESKTOP_USER}"
|
|
sudo -u "${DESKTOP_USER}" XDG_RUNTIME_DIR="/run/user/$(id -u "${DESKTOP_USER}")" \
|
|
bash -lc "cd '${REPO_ROOT}' && ./scripts/kaisa-audio-doctor.sh --verify --only-pcm 2" || true
|
|
}
|
|
|
|
main() {
|
|
require_root
|
|
mount_debugfs_if_needed
|
|
|
|
stop_user_audio
|
|
pci_reset
|
|
start_user_audio
|
|
|
|
tail_kernel_hints
|
|
maybe_verify
|
|
|
|
log "done"
|
|
}
|
|
|
|
main "$@"
|