lspci reads PCI config space, and the kernel resumes a runtime-suspended device to serve that read. On a hybrid laptop the discrete GPU idles in D3cold, so the first lspci of a Hyprland config load spends over a second waking it — longer than the 1.5s budget Hyprland gives the whole load. The reload then fails at whichever line runs next, which is why the error pointed at default/hypr/apps/1password.lua rather than at nvidia.lua. Read the vendor, class, and device IDs from sysfs instead. Those are served from cached fields and never touch config space, so nothing wakes up. Classify by device ID while we're here: Turing is both the first generation with GSP firmware and the first at 0x1e00 or above, and Maxwell opens at 0x1340, one ID past the last Kepler part. Bounding the older detector at both ends keeps pre-Maxwell cards off the 580xx driver that cannot drive them, and picks up the Maxwell and Pascal parts the lspci name regex used to miss. omarchy-hw-nvidia was also checked in without its executable bit, which it needs now that nvidia.lua runs it. Fixes #6660 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
100 lines
3.2 KiB
Bash
Executable File
100 lines
3.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
|
|
|
tmp_dir=$(mktemp -d)
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
|
|
# Each argument is a PCI device as "vendor:device:class", in sysfs's own format.
|
|
write_pci_devices() {
|
|
rm -rf "$tmp_dir/devices"
|
|
mkdir -p "$tmp_dir/devices"
|
|
|
|
local index=0
|
|
local spec
|
|
for spec in "$@"; do
|
|
local slot
|
|
slot=$(printf '0000:%02x:00.0' "$index")
|
|
mkdir -p "$tmp_dir/devices/$slot"
|
|
printf '%s\n' "${spec%%:*}" >"$tmp_dir/devices/$slot/vendor"
|
|
printf '%s\n' "$(cut -d: -f2 <<<"$spec")" >"$tmp_dir/devices/$slot/device"
|
|
printf '%s\n' "${spec##*:}" >"$tmp_dir/devices/$slot/class"
|
|
index=$((index + 1))
|
|
done
|
|
}
|
|
|
|
hw_nvidia() {
|
|
OMARCHY_PCI_DEVICES_PATH="$tmp_dir/devices" "$ROOT/bin/omarchy-hw-$1"
|
|
}
|
|
|
|
assert_detects() {
|
|
local description="$1" nvidia="$2" gsp="$3" without_gsp="$4"
|
|
|
|
local command
|
|
for command in nvidia gsp without-gsp; do
|
|
local expected
|
|
case $command in
|
|
nvidia) expected=$nvidia ;;
|
|
gsp) expected=$gsp ;;
|
|
without-gsp) expected=$without_gsp ;;
|
|
esac
|
|
|
|
local detector=nvidia
|
|
[[ $command == "nvidia" ]] || detector="nvidia-$command"
|
|
|
|
local actual=no
|
|
hw_nvidia "$detector" && actual=yes
|
|
|
|
[[ $actual == "$expected" ]] ||
|
|
fail "$description" "omarchy-hw-$detector: expected $expected, got $actual"
|
|
done
|
|
|
|
pass "$description"
|
|
}
|
|
|
|
# AMD Cezanne integrated graphics.
|
|
write_pci_devices 0x1002:0x15e7:0x030000
|
|
assert_detects "a machine without an NVIDIA GPU detects nothing" no no no
|
|
|
|
# NVIDIA GA106M [RTX 3060 Mobile] alongside AMD Cezanne, the pair from issue #6660.
|
|
write_pci_devices 0x1002:0x15e7:0x030000 0x10de:0x2560:0x030200
|
|
assert_detects "a hybrid Ampere laptop detects a GSP GPU" yes yes no
|
|
|
|
# NVIDIA TU117M [GTX 1650 Mobile], the first generation with GSP firmware.
|
|
write_pci_devices 0x10de:0x1f91:0x030000
|
|
assert_detects "Turing is the oldest generation with GSP firmware" yes yes no
|
|
|
|
# NVIDIA GV100 [TITAN V], the newest generation without GSP firmware.
|
|
write_pci_devices 0x10de:0x1d81:0x030000
|
|
assert_detects "Volta is the newest generation without GSP firmware" yes no yes
|
|
|
|
# NVIDIA GP104 [GTX 1080].
|
|
write_pci_devices 0x10de:0x1b80:0x030000
|
|
assert_detects "Pascal detects a GPU without GSP firmware" yes no yes
|
|
|
|
# NVIDIA GM108M [GeForce 830M], the oldest part the 580xx driver supports.
|
|
write_pci_devices 0x10de:0x1340:0x030000
|
|
assert_detects "Maxwell detects a GPU without GSP firmware" yes no yes
|
|
|
|
# NVIDIA GK110 [GTX 780]. Kepler predates GSP but also predates 580xx, so
|
|
# claiming it here would install a driver that cannot drive it.
|
|
write_pci_devices 0x10de:0x1004:0x030000
|
|
assert_detects "Kepler is too old for either driver" yes no no
|
|
|
|
# NVIDIA GF100 [GTX 470], older still.
|
|
write_pci_devices 0x10de:0x06cd:0x030000
|
|
assert_detects "Fermi is too old for either driver" yes no no
|
|
|
|
# NVIDIA GB203 [RTX 5080], newer than every other device ID here.
|
|
write_pci_devices 0x10de:0x2c02:0x030000
|
|
assert_detects "Blackwell detects a GSP GPU" yes yes no
|
|
|
|
# The GA106 audio function carries the NVIDIA vendor ID but is not a GPU.
|
|
write_pci_devices 0x10de:0x228e:0x040300
|
|
assert_detects "a non-display NVIDIA function is not a GPU" no no no
|
|
|
|
write_pci_devices
|
|
assert_detects "a machine with no PCI devices detects nothing" no no no
|