/[soft]/drakx-kbd-mouse-x11/trunk/tools/display_driver_helper
ViewVC logotype

Contents of /drakx-kbd-mouse-x11/trunk/tools/display_driver_helper

Parent Directory Parent Directory | Revision Log Revision Log


Revision 961 - (show annotations) (download)
Wed Apr 20 23:05:34 2011 UTC (10 years, 5 months ago) by anssi
File size: 12791 byte(s)
Try unloading unconfigured drivers in "display_driver_helper --check-loaded".
1 #!/bin/sh
2 #
3 # Display driver helper
4 #
5 # Copyright (c) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
6 #
7 # - Load drivers for specified modaliases, skipping disabled display drivers
8 # that would cause conflicts (KMS vs. vesa, KMS vs. proprietary).
9 # - Get information about enabled driver modules
10 # - Check that the loaded modules are correct
11 #
12 # Licensed under terms of GPLv2 or later.
13 #
14 # When updating, check:
15 # - the variables below
16 # - check_driver function
17 # - check_dkms_status function
18 #
19
20 if [ -n "$DEBUG_DISPLAY_DRIVER_HELPER" ]; then
21 echo "$(date) $*" >> /dev/ddh_debug
22 exec 2>>/dev/ddh_debug
23 set -x
24 fi
25
26 export LC_ALL=C
27
28 KMS_DRIVERS="i915 radeon nouveau"
29 # module names at run-time (hence nvidia instead of nvidia*):
30 KNOWN_MODULES="i915|radeon|nouveau|fglrx|nvidia"
31
32 XORG_i915="intel"
33 CONFLICTS_i915=""
34
35 XORG_nouveau="nouveau"
36 CONFLICTS_nouveau="nv nvidia"
37
38 XORG_radeon="ati radeon"
39 CONFLICTS_radeon="fglrx"
40
41 # Note: no /usr
42 # See end of script for descriptions of global variables.
43 check_driver() {
44 local name="$1"
45 case "$name" in
46 i915)
47 # implicitely loaded by X.org
48 check_xorg $name 0 || return 1
49 IS_KMS=1
50 ;;
51 radeon)
52 # implicitely loaded by X.org
53 check_xorg $name 0 || return 1
54 IS_KMS=1
55 # radeon needs to loaded before X server
56 NEEDS_LOAD_NOW=1
57 ;;
58 nouveau)
59 # these KMS drivers require an explicit directive in xorg.conf
60 check_xorg $name 1 || return 1
61 IS_KMS=1
62 ;;
63 fglrx)
64 check_xorg fglrx 1 || return 1
65 check_dkms fglrx || return 1
66 ;;
67 nvidia)
68 # manually installed driver or a call from check_loaded()
69 UNSURE=1
70 check_xorg nvidia 1 || return 1
71 ;;
72 nvidiafb)
73 # this is only reached if nvidiafb is manually unblacklisted
74 return 2
75 ;;
76 nvidia*)
77 [ "$name" = "nvidia_current" ] && name=nvidia-current
78 # there are multiple co-installable driver versions, so check
79 # the active alternative as well
80 check_gl /etc/$name/ld.so.conf || return 1
81 check_xorg nvidia 1 || return 1
82 check_dkms $name || return 1
83 ;;
84 *)
85 # unknown, will be loaded only if no known drivers were found
86 return 2
87 ;;
88 esac
89 return 0
90 }
91
92 # Return success if there is no new pending DKMS build (needed to disallow
93 # speedboot on very early boot).
94 # Previously failed build or a missing module is counted as no pending build.
95 # Note: no /usr
96 check_dkms_status() {
97 [ -e /etc/alternatives/gl_conf ] || return 0
98 # return fast for non-DKMS
99 check_gl /etc/ld.so.conf.d/GL/standard.conf && return 0
100
101 local active="$(ls -l /etc/alternatives/gl_conf | awk '{ print $NF }')"
102
103 local modname=
104
105 case $active in
106 /etc/nvidia*/ld.so.conf)
107 modname="nvidia${active#*nvidia}"
108 modname="${modname%/*}"
109 ;;
110 /etc/ld.so.conf.d/GL/ati.conf)
111 modname="fglrx"
112 ;;
113 *)
114 # Unknown DKMS-looking driver,
115 # allow speedboot.
116 return 0
117 ;;
118 esac
119 check_dkms "$modname" 1
120 }
121
122 # Check if all loaded kernel modules have correct xorg.conf
123 check_loaded() {
124 for module in $(grep -oE "^($KNOWN_MODULES) " /proc/modules); do
125 # try to unload the driver in case it is not in use before bailing
126 check_driver "$module" || rmmod "$module" &>/dev/null || return 1
127 done
128 return 0
129 }
130
131 # Check that specified DKMS driver is not queued for build for the current
132 # kernel. Used to check if we 1) should disable speedboot for this boot
133 # (--check-dkms-status), and 2) if should should load the currently
134 # existing driver (--load). Doing otherwise might cause us to load a wrong old
135 # version of the driver that had been installed using e.g. binary DKMS
136 # packages.
137 # Note: no /usr
138 check_dkms() {
139 local driver="$1"
140 local force="$2"
141
142 # If called from DKMS itself or we are not in rc.sysinit anymore,
143 # there are no pending builds.
144 if [ -z "$force" ]; then
145 [ "$DKMS_AUTOLOAD_MODULE" = "$driver" ] && return 0
146 [ -z "$STARTUP" ] && [ ! -f "/dev/.in_sysinit" ] && return 0
147 fi
148
149 local found=
150 local uname_r="$(uname -r)"
151
152 for dir in /var/lib/dkms/$driver/*; do
153 [ -e "$dir" ] || return 0 # no module, no build; or no /var
154 [ -L "$dir" ] && continue # not a module version
155 found=1 # module version found
156 [ -e "$dir/$uname_r" ] && return 0
157 [ -e "/var/lib/dkms-binary/$driver/$(basename "$dir")/$uname_r" ] && return 0
158
159 if [ -e "$dir/build/make.log" ]; then
160 # Build has failed for some kernel, check if it is this one.
161 # If so, there is no point in returning 1.
162 grep -q "^DKMS make\.log.* $uname_r " && return 0
163 fi
164 done
165
166 # if module versions were found but none were built for this kernel, return 1
167 [ -n "$found" ] && return 1 || return 0
168 }
169
170 # Note: no /usr
171 check_gl() {
172 local alt_inode="$(stat -L -c%i $1 2>/dev/null)"
173 [ -n "$alt_inode" ] || return 1
174 [ -n "$GL_INODE" ] || GL_INODE="$(stat -L -c%i /etc/alternatives/gl_conf 2>/dev/null)"
175 [ "$alt_inode" = "$GL_INODE" ] || return 1
176 return 0
177 }
178
179 # Note: no /usr
180 get_xorg_drivers() {
181 if [ -z "$XORG_DRIVERS" ]; then
182 XORG_DRIVERS="$(cat /etc/X11/xorg.conf /etc/X11/xorg.conf.d/*.conf 2>/dev/null |
183 awk -F'"' -vORS=' ' -vIGNORECASE=1 '
184 /^[[:space:]]+*section[[:space:]]+"device"/ { device=1 }
185 /endsection/ { device=0 }
186 /^[[:space:]]*driver[[:space:]]*".*"/ { if (device) drivers[$2]=$2 }
187 END { for (driver in drivers) print driver }
188 ')"
189 [ -n "$XORG_DRIVERS" ] || XORG_DRIVERS="-"
190 fi
191 }
192
193 # Note: no /usr
194 # parameter 1: xorg driver
195 # parameter 2: 1 the check if the driver is explicitely enabled
196 # 0 means that check only for conflicts
197 check_xorg() {
198 local driver="$1"
199 local explicit_only="$2"
200
201 eval local xorg_drivers=\"\$XORG_$driver\"
202 [ -n "$xorg_drivers" ] || xorg_drivers="$driver"
203 eval local conflicts=\"\$CONFLICTS_$driver\"
204
205 get_xorg_drivers
206
207 conflict_found=
208 for enabled_driver in $XORG_DRIVERS; do
209 for xorg_driver in $xorg_drivers; do
210 [ "$enabled_driver" = "$xorg_driver" ] && return 0
211 done
212
213 # if the X.org driver can be loaded implicitely, check that
214 # there are no conflicting drivers that override the driver
215 if [ "$explicit_only" = "0" -a -z "$conflict_found" ]; then
216 for conflict in vesa $conflicts; do
217 if [ "$enabled_driver" = "$conflict" ]; then
218 conflict_found=1
219 continue 2
220 # continue loop to check for an explicit load
221 fi
222 done
223 fi
224 done
225
226 # in case of a conflict, do not load the module
227 [ -n "$conflict_found" ] && return 1
228
229 # no driver is selected - don't load if explicit_only is 1
230 [ "$explicit_only" = "1" ] && return 1
231
232 # implicit load allowed; still don't load if no xorg.conf (i.e. live cd)
233 [ -e "/etc/X11/xorg.conf" ]
234 }
235
236 # Load the driver for the specified modalias, if configured.
237 # Note: no /usr
238 load_driver() {
239 local modulename
240 local load_default=1
241
242 # NOTE: UPDATE when module-init-tools is upgraded to get better performance
243 # modprobe has -R option:
244 #for modulename in $(/home/anssi/module-init-tools-3.12/build/modprobe -Rq "$1"); do
245 # modprobe does not have -R option:
246 for mod in $(/sbin/modprobe -biqvn "$1"); do
247 [ "$mod" = "insmod" ] && continue
248 modulename="${mod##*/}"
249 modulename="${modulename%%.*}"
250
251 check_driver "$modulename"
252 case $? in
253 1) # a driver which needs handling by this script matches
254 # the modalias, but was not configured - do not run
255 # the generic modprobe if no other drivers are
256 # configured either
257 load_default=
258 continue
259 ;;
260 2) continue
261 ;;
262 esac
263
264 if [ -n "$IS_KMS" ]; then
265 grep -q "^$modulename " /proc/modules && return 0
266 echo "$modulename" > /dev/.late_kms 2>/dev/null
267 # If NEEDS_LOAD_NOW is not set and plymouth is running,
268 # skip loading the driver to avoid quitting plymouth.
269 # The driver will be loaded later by X server itself.
270 [ -z "$NEEDS_LOAD_NOW" ] && /bin/plymouth --ping 2>/dev/null && return 0
271 /bin/plymouth quit 2>/dev/null
272 fi
273 /sbin/modprobe -b "$modulename" && return 0
274 done
275
276 # no specially handled modules were loaded, so load all modules normally
277 # unless $load_default was set above
278 [ -z "$load_default" ] || /sbin/modprobe -b "$1"
279 }
280
281 is_kms_allowed() {
282 for driver in $KMS_DRIVERS; do
283 # Check all drivers for conflicts only.
284 check_xorg $driver 0 || return 1
285 done
286 return 0
287 }
288
289 get_initrd_kms_drivers() {
290 local initrd="$1"
291
292 local kms_drivers="$(echo "$KMS_DRIVERS" | tr " " "|")"
293 zcat "$initrd" | cpio -t --quiet | sed -nr "s,.*/($kms_drivers)\.ko.*$,\1,p"
294 }
295
296 # Check that the initrd doesn't contain disabled modules
297 check_initrd() {
298 local initrd="$1"
299 local initrd_drivers="$(get_initrd_kms_drivers "$initrd")"
300 for driver in $initrd_drivers; do
301 check_driver "$driver" || return 1
302 done
303 for driver2 in $(get_active_kms_drivers); do
304 for driver in $initrd_drivers; do
305 [ "$driver" = "$driver2" ] && continue 2
306 done
307 # An enabled module for present hardware was not in initrd
308 return 1
309 done
310 return 0
311 }
312
313 get_active_kms_drivers() {
314 local kms_drivers=
315 for device in $(grep -l 0x03 /sys/bus/pci/devices/0000\:0*/class); do
316 [ -e "$device" ] || continue
317 device="$(dirname $device)"
318 [ -f "$device/modalias" ] || continue
319 modalias="$(cat "$device/modalias")"
320 for mod in $(/sbin/modprobe --first-time -biqvn "$modalias" 2>&1); do
321 modulename="${mod##*/}"
322 modulename="${modulename%%.*}"
323 IS_KMS=
324 check_driver "$modulename" || continue
325 [ -n "$IS_KMS" ] && echo $modulename
326 done
327 done
328 }
329
330 usage() {
331 cat <<EOF
332 Usage: $0 action [arguments]
333
334 Known actions:
335
336 --load MODALIAS
337 Load drivers matching MODALIAS, checking that they are enabled and
338 configured.
339
340 --load-dkms-autoload MODNAME MODALIAS
341 Same as --load, but assume MODNAME is built and correct so that
342 checking dkms status is unnecessary.
343
344 --is-disabled MODNAME
345 Checks whether the driver corresponding to MODNAME is disabled (e.g.
346 a conflicting driver is configured, etc.). Unknown MODNAMEs are
347 considered not disabled.
348
349 --is-enabled-kms MODNAME
350 Checks whether the driver corresponding to MODNAME is enabled and
351 MODNAME is a known KMS module. Note that drivers may be enabled even
352 if there is no such hardware. This just checks that there are
353 no conflicting drivers in use etc.
354
355 --is-kms-allowed
356 Checks whether it is ok to load KMS drivers in initrd. This returns
357 a failure when a conflicting driver is set up (vesa or a proprietary
358 one).
359
360 --get-all-kms-drivers
361 Get a list of the known KMS drivers.
362
363 --get-active-kms-drivers
364 Get a list of the known KMS drivers which are enabled and the hardware
365 is present.
366
367 --get-initrd-kms-drivers INITRD
368 Get a list of the known KMS drivers in initrd INITRD.
369
370 --check-dkms-status
371 Checks if there are no pending DKMS builds for the currently enabled
372 drivers.
373
374 --check-loaded
375 Checks that there are no disabled drivers loaded.
376
377 --check-speedboot
378 Does --check-dkms-status and --check-loaded.
379
380 --check-loaded-strict
381 As --check-loaded, and consider ambigious cases (e.g. nvidia where
382 we can't detect if the loaded driver has the correct version) as
383 failure.
384
385 --check-initrd INITRD
386 Check that INITRD doesn't contain disabled KMS drivers.
387 EOF
388 }
389
390 # clear global variables
391
392 # cache for check_gl()
393 GL_INODE=
394
395 # cache for check_xorg()
396 XORG_DRIVERS=
397
398 # The driver is a KMS enabled driver. This will cause the script to quit
399 # plymouth when a driver is loaded by --load and NEEDS_LOAD_NOW below is set.
400 # This is done as plymouth is still attached to the default framebuffer (the
401 # issues caused by not doing this don't seem to be fatal, though, but the
402 # display may be lost completely until plymouth eventually stops).
403 # There is no option in plymouth to "reload" a driver, it expects any KMS
404 # driver to be loaded be before starting it.
405 IS_KMS=
406
407 # This KMS driver needs to be loaded before X server starts, so load it now
408 # even if we have to shut down plymouth (see above).
409 NEEDS_LOAD_NOW=
410
411 # dkms module that was built when calling from DKMS
412 DKMS_AUTOLOAD_MODULE=
413
414 # Set by check_loaded() when it can't be sure that the correct driver is loaded
415 # (e.g. in case of the multiple proprietary nvidia drivers which all identify as
416 # "nvidia" in loaded modules list).
417 UNSURE=
418
419 case "$1" in
420 --load)
421 load_driver "$2"
422 ;;
423 --load-dkms-autoload)
424 DKMS_AUTOLOAD_MODULE="$2"
425 load_driver "$3"
426 ;;
427 --is-disabled)
428 check_driver "$2"
429 [ $? -eq 1 ]
430 # unknown (2) are not considered disabled :)
431 ;;
432 --is-enabled-kms)
433 check_driver "$2" && [ -n "$IS_KMS" ]
434 ;;
435 --is-kms-allowed)
436 is_kms_allowed
437 ;;
438 --check-dkms-status)
439 check_dkms_status
440 ;;
441 --get-all-kms-drivers)
442 echo $KMS_DRIVERS
443 ;;
444 --get-active-kms-drivers)
445 get_active_kms_drivers
446 ;;
447 --get-initrd-kms-drivers)
448 get_initrd_kms_drivers "$2"
449 ;;
450 --check-initrd)
451 check_initrd "$2"
452 ;;
453 --check-loaded)
454 check_loaded
455 ;;
456 --check-loaded-strict)
457 check_loaded && [ -z "$UNSURE" ]
458 ;;
459 --check-speedboot)
460 check_dkms_status && check_loaded
461 ;;
462 *)
463 usage
464 ;;
465 esac

  ViewVC Help
Powered by ViewVC 1.1.28