Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions cachyos-drm-awaiter/.SRCINFO
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pkgbase = cachyos-drm-awaiter
pkgdesc = Configuration for proper systemd chain-loading of DRM modules
pkgver = 1
pkgrel = 1
url = https://github.com/CachyOS/CachyOS-PKGBUILDS/tree/master/cachyos-drm-awaiter
arch = any
license = GPL-3.0-or-later
makedepends = coreutils
depends = systemd
source = drm-module-awaiter-generator
source = 30-drm-awaiter.rules
sha256sums = a2f6e87c96113fb995cd51f70c0042e55bae790a4ee3aa8be870c00b3208907d
sha256sums = 4457ec33251aa019a83a4637e24851aef6fbb4828c74126fad74b7203b1c3f13

pkgname = cachyos-drm-awaiter
6 changes: 6 additions & 0 deletions cachyos-drm-awaiter/30-drm-awaiter.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Remove SimpleDRM device when some real DRM driver loads.
ACTION=="add", SUBSYSTEM=="module", KERNEL=="amdgpu|radeon|nvidia_drm|i915|xe|nouveau", \
TEST=="/sys/devices/platform/simple-framebuffer.0/drm/card0", RUN+="/bin/rm /dev/dri/card0"
Comment on lines +2 to +3

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this extremely unlikely, besides the same rule is used in Ubuntu and I haven't seen any bugs related with it.


# Creates device units for most DRM modules
ACTION=="add", SUBSYSTEM=="module", KERNEL=="amdgpu|radeon|nvidia_drm|i915|xe|nouveau", TAG+="systemd"
23 changes: 23 additions & 0 deletions cachyos-drm-awaiter/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Maintainer: Vasiliy Stelmachenok <ventureo@cachyos.org>
pkgname=cachyos-drm-awaiter
pkgver=1
pkgrel=1
pkgdesc="Configuration for proper systemd chain-loading of DRM modules"
arch=('any')
license=('GPL-3.0-or-later')
url="https://github.com/CachyOS/CachyOS-PKGBUILDS/tree/master/$pkgname"
depends=('systemd')
makedepends=('coreutils')
source=(
drm-module-awaiter-generator
30-drm-awaiter.rules
)
sha256sums=(
'a2f6e87c96113fb995cd51f70c0042e55bae790a4ee3aa8be870c00b3208907d'
'4457ec33251aa019a83a4637e24851aef6fbb4828c74126fad74b7203b1c3f13'
)

package() {
install -Dm755 drm-module-awaiter-generator "${pkgdir}/usr/lib/systemd/system-generators/drm-module-awaiter-generator"
install -Dm644 30-drm-awaiter.rules "${pkgdir}/usr/lib/udev/rules.d/30-drm-awaiter.rules"
}
140 changes: 140 additions & 0 deletions cachyos-drm-awaiter/drm-module-awaiter-generator
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env bash
# Copyright (C) 2026 Vasiliy Stelmachenok for CachyOS
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# Get generator normal directory
generator_dir="$1"

# NVIDIA driver can be in a race state with additional driver like amdgpu,
# especially on laptops. This configuration forces NVIDIA driver to load later
# than the iGPU one, which eliminates this issue.
function postpone_nvidia_module() {
local module="$1"

mkdir -p /run/modprobe.d
if [[ "$nvidia_module" == "nvidia_drm" ]]; then
cat <<EOF >"/run/modprobe.d/30-$module-load-reorder.conf"
softdep $module post: nvidia nvidia_drm nvidia_modeset nvidia_uvm
softdep nvidia pre: $module post:
softdep nvidia_drm pre: $module post:
softdep nvidia_modeset pre: $module post:
softdep nvidia_uvm pre: $module post:
EOF
elif [[ "$nvidia_module" == "nouveau" ]]; then
cat <<EOF >"/run/modprobe.d/30-$module-load-reorder.conf"
softdep $module post: nouveau
softdep nouveau pre: $module post:
EOF
fi
}

function is_module_forced() {
local module="$1"

while IFS= read -r value; do
[[ "${value,,}" == "!${device}" ]] && return 1
[[ "${value,,}" == "${device}" ]] && return 0
done < <(modprobe --showconfig \
| grep -Po "^options ${module} force_probe=\K(.*)$" \
| tr ',' '\n')

return 1
}

function is_module_blacklisted() {
local module="$1"
modprobe --showconfig | grep -q "^blacklist $1\$" && return 0
return 1
}

function is_module_loadable() {
local module="$1"
is_module_blacklisted "$module" && return 1
modinfo "$module" 2>/dev/null | grep -q "$modalias" || return 1
return 0
}

function generate_load_target() {
local device class vendor sysfs modalias nvidia_module
local -a modules=()

while read -r class; do
sysfs="${class%%/class}"
device="$(cat "${sysfs}/device" | sed 's/0x//')"
vendor="$(cat "${sysfs}/vendor")"
modalias="$(cat "${sysfs}/modalias" | head -c24)"

case "$vendor" in
0x10de)
if modinfo "nvidia" &>/dev/null && ! is_module_blacklisted "nvidia"; then
nvidia_module="nvidia_drm"
elif is_module_loadable "nouveau"; then
nvidia_module="nouveau"
fi
;;
0x1002)
if is_module_loadable "amdgpu"; then
modules+=(amdgpu)
elif is_module_loadable "radeon"; then
modules+=(radeon)
fi
;;
0x8086)
if is_module_loadable "i915" && ! is_module_forced "xe" "$device"; then
modules+=(i915)
elif is_module_loadable "xe" && ! is_module_forced "i915" "$device"; then
modules+=(xe)
fi
;;
esac
done < <(grep -l "0x030[0-9]00" /sys/bus/pci/devices/*/class)

if [ -z "${modules[0]}" ]; then
return 0
fi

if [ -n "$nvidia_module" ]; then
modules+=("$nvidia_module")
for module in "${modules[@]}"; do
if [[ "$module" != "$nvidia_module" ]]; then
postpone_nvidia_module "$module" "$nvidia_module"
fi
done
fi

local -a devices=()
for module in "${modules[@]}"; do
devices+=("sys-module-${module}.device")
done

cat <<EOF >"$generator_dir"/drm-module-load.target
[Unit]
Description=DRM module load target
Documentation=man:systemd.special(7)
JobTimeoutSec=10s

Before=getty@tty1.service display-manager.service
After=${devices[@]} plymouth-quit.service
Wants=${devices[@]}
EOF

mkdir -p "$generator_dir"/getty@tty1.service.wants "$generator_dir"/display-manager.service.wants
ln -s ../drm-module-load.target "$generator_dir"/getty@tty1.service.wants/drm-module-load.target
ln -s ../drm-module-load.target "$generator_dir"/display-manager.service.wants/drm-module-load.target
}

generate_load_target
exit 0