Bug#1033679: hw-detect/check-missing-firmware: add fallback module lookup by modalias and firmware
Package: src:hw-detect
Version: 1.155
Tags: patch
Dear maintainer,
Please find attached 3 patches adding fallback module detection when
dmesg does not provide the actual module name and device driver symlink
is missing. I tried to keep them as clear, short and little invasive as
possible in order to ease review and avoid regressions.
Tested with p54usb (follow-up to bug #1032377). Tested for non
regression with b43.
===============
* 0001 check-missing-firmware: add function get_module_by_bus_address
Call this function for bus types other than usb and mhi. It looks up:
- module name
- driver name
- sysfs modalias
- udevadm modalias
in order and returns whichever exists or matches first.
===============
* 0002 check-missing-firmware: call get_module_by_bus_address for usb
devices too
So modalias lookup can be used with usb devices when no driver is found
(e.g. p54usb).
===============
* 0003 check-missing-firmware: add module lookup by firmware file
Scan all loaded modules for the requested firmware file as fallback if
the detected module is a bus name or is not a loaded driver or module name.From dba86861a56abfbca0f6c760262326ce2c511707 Mon Sep 17 00:00:00 2001
From: Pascal Hambourg <pascal@plouf.fr.eu.org>
Date: Thu, 30 Mar 2023 00:19:42 +0200
Subject: [PATCH 1/3] check-missing-firmware: add function
get_module_by_bus_address
Call this function for bus types other than usb and mhi. It looks up:
- <device>/driver/module
- <device>/driver
- <device>/modalias
- udevadm <device> modalias
in order, and returns whichever exists or matches first.
---
check-missing-firmware.sh | 45 +++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/check-missing-firmware.sh b/check-missing-firmware.sh
index 5db0e180..c5356f27 100755
--- a/check-missing-firmware.sh
+++ b/check-missing-firmware.sh
@@ -21,6 +21,44 @@ log_output() {
log-output -t check-missing-firmware "$@"
}
+get_module_by_bus_address () {
+ local bus=$1
+ local address=$2
+ local device="/sys/bus/$bus/devices/$address"
+ local modalias=
+
+ # return associated module name if it exists
+ if [ -e "$device"/driver/module ]; then
+ basename $(readlink "$device"/driver/module)
+ return
+ fi
+ # else return associated driver name if it exists
+ log "no module found for $bus $address, looking up driver"
+ if [ -e "$device"/driver ]; then
+ basename $(readlink "$device"/driver)
+ return
+ fi
+ log "no driver found for $bus $address, looking up modalias"
+ # else lookup module by modalias if it exists
+ # warning: requires kmod, busybox modprobe does not support --resolve-alias
+ if [ -e "$device"/modalias ]; then
+ modalias="$(cat "$device"/modalias)"
+ else
+ # modalias may not exist in sysfs but only in udev, so also query udevadm
+ log "no modalias found for $bus $address in sysfs, looking up udevadm"
+ modalias="$(udevadm info --query=property $device | grep "^MODALIAS=" | sed 's/^MODALIAS=//')"
+ fi
+ if [ -n "$modalias" ]; then
+ modprobe --resolve-alias "$modalias" 2>/dev/null && return
+ log "no module matching modalias found for $bus $address"
+ else
+ log "no modalias found for $bus $address"
+ fi
+ log "failed to perform $bus $address lookup"
+ log "=> sticking with the $bus module"
+ echo "$bus"
+}
+
# USB is special, and we don't want to take it all done:
get_usb_module() {
address="$1"
@@ -166,6 +204,13 @@ check_missing () {
module=$(get_mhi_holders)
log "using $module instead of mhi"
;;
+ *)
+ # other bus types
+ if [ -e /sys/bus/"$module" ]; then
+ bus="$module"
+ module=$(get_module_by_bus_address "$bus" "$address")
+ fi
+ ;;
esac
# ignore specific files:
--
2.30.2
From b2b56617e9008a74c97d0576bb75a6e5857c800c Mon Sep 17 00:00:00 2001
From: Pascal Hambourg <pascal@plouf.fr.eu.org>
Date: Thu, 30 Mar 2023 00:36:01 +0200
Subject: [PATCH 2/3] check-missing-firmware: call get_module_by_bus_address
for usb devices too
So modalias lookup can be tried with usb devices when no driver is found
(e.g. p54usb).
---
check-missing-firmware.sh | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/check-missing-firmware.sh b/check-missing-firmware.sh
index c5356f27..2d2414d8 100755
--- a/check-missing-firmware.sh
+++ b/check-missing-firmware.sh
@@ -77,9 +77,7 @@ get_usb_module() {
# Make sure driver resolution returns something:
driver=$(basename $(readlink "$subdirs/driver") 2>/dev/null)
if [ "$driver" = "" ]; then
- log "failed to perform usb $address lookup (no driver found)"
- log "=> sticking with the usb module"
- echo 'usb'
+ get_module_by_bus_address "usb" "$(basename $subdirs)"
return
fi
echo $driver
--
2.30.2
From e4b6a9061061c638d6169562dece6f151901353c Mon Sep 17 00:00:00 2001
From: Pascal Hambourg <pascal@plouf.fr.eu.org>
Date: Thu, 30 Mar 2023 00:51:37 +0200
Subject: [PATCH 3/3] check-missing-firmware: add module lookup by firmware
file
Scan all loaded modules for the requested firmware file as fallback if the detected
module is a bus name or is not a loaded driver nor module name.
---
check-missing-firmware.sh | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/check-missing-firmware.sh b/check-missing-firmware.sh
index 2d2414d8..0c71c243 100755
--- a/check-missing-firmware.sh
+++ b/check-missing-firmware.sh
@@ -59,6 +59,25 @@ get_module_by_bus_address () {
echo "$bus"
}
+get_module_by_firmware () {
+ local firmware=$1
+ local module module_path holder
+
+ for module_path in /sys/module/* ; do
+ module="$(basename "$module_path")"
+ if /sbin/modinfo -F firmware "$module" 2>/dev/null | grep -q "^$firmware$" ; then
+ # if a module advertising firmware is used by another module, the latter must be reloaded too
+ # e.g. rtw88_*, atmel*, orinoco*, snd_vx*
+ for holder in $(find -L "$module_path"/holders/ -mindepth 1 -maxdepth 1 -exec basename {} ';') ; do
+ module="$module $holder"
+ done
+ echo "$module"
+ return
+ fi
+ done
+ log "no module matching firmware $firmware found"
+}
+
# USB is special, and we don't want to take it all done:
get_usb_module() {
address="$1"
@@ -211,6 +230,15 @@ check_missing () {
;;
esac
+ if [ -e /sys/bus/"$module" -o \
+ \( ! -e /sys/module/"$module" -a -z "$(find /sys/bus/*/drivers -maxdepth 1 -name "$module")" \) ]; then
+ # $module is a bus name or not a module name nor a driver name, so look up by firmware
+ module_by_fw="$(get_module_by_firmware "$fwfile")"
+ if [ -n "$module_by_fw" ]; then
+ module="$module_by_fw"
+ fi
+ fi
+
# ignore specific files:
# - iwlwifi, debug-only (#969264, #966218)
if [ "$fwfile" = "iwl-debug-yoyo.bin" ]; then
--
2.30.2
Reply to: