[RFC PATCH v2 1/2] kselftest: Add test to verify probe of devices from discoverable busses

Nícolas F. R. A. Prado <[email protected]>
Newsgroups dev.linux.lists.kernelci,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-pci,org.kernel.vger.linux-usb
Message-ID <[email protected]>
Add a new test to verify that a list of expected devices on a given
platform have been successfully probed by a driver.

Add a new test to verify that all expected devices from discoverable
busses (ie USB, PCI) have been successfully instantiated and probed by a
driver.

The per-platform list of expected devices is selected from the ones
under the boards/ directory based on compatible.

Signed-off-by: Nícolas F. R. A. Prado <[email protected]>

---

(no changes since v1)

 tools/testing/selftests/Makefile              |   1 +
 tools/testing/selftests/devices/.gitignore    |   1 +
 tools/testing/selftests/devices/Makefile      |   8 +
 .../devices/test_discoverable_devices.sh      | 160 ++++++++++++++++++
 4 files changed, 170 insertions(+)
 create mode 100644 tools/testing/selftests/devices/.gitignore
 create mode 100644 tools/testing/selftests/devices/Makefile
 create mode 100755 tools/testing/selftests/devices/test_discoverable_devices.sh

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 3b2061d1c1a5..7f5088006c3c 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -13,6 +13,7 @@ TARGETS += core
 TARGETS += cpufreq
 TARGETS += cpu-hotplug
 TARGETS += damon
+TARGETS += devices
 TARGETS += dmabuf-heaps
 TARGETS += drivers/dma-buf
 TARGETS += drivers/s390x/uvdevice
diff --git a/tools/testing/selftests/devices/.gitignore b/tools/testing/selftests/devices/.gitignore
new file mode 100644
index 000000000000..e3c5c04d1b19
--- /dev/null
+++ b/tools/testing/selftests/devices/.gitignore
@@ -0,0 +1 @@
+ktap_helpers.sh
diff --git a/tools/testing/selftests/devices/Makefile b/tools/testing/selftests/devices/Makefile
new file mode 100644
index 000000000000..ff2fdc8fc5e2
--- /dev/null
+++ b/tools/testing/selftests/devices/Makefile
@@ -0,0 +1,8 @@
+TEST_PROGS := test_discoverable_devices.sh
+TEST_GEN_FILES := ktap_helpers.sh
+TEST_FILES := boards
+
+include ../lib.mk
+
+$(OUTPUT)/ktap_helpers.sh:
+	cp ../dt/ktap_helpers.sh $@
diff --git a/tools/testing/selftests/devices/test_discoverable_devices.sh b/tools/testing/selftests/devices/test_discoverable_devices.sh
new file mode 100755
index 000000000000..82bad5ba7081
--- /dev/null
+++ b/tools/testing/selftests/devices/test_discoverable_devices.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (c) 2023 Collabora Ltd
+#
+# This script tests for presence and driver binding of devices from discoverable
+# busses (ie USB, PCI).
+#
+# The per-platform list of devices to be tested is stored inside the boards/
+# directory and chosen based on compatible. Each line of the file follows the
+# following format:
+#
+#   usb|pci test_name number_of_matches field=value [ field=value ... ]
+#
+# The available match fields vary by bus. The field-value match pairs for a
+# device can be retrieved from the device's modalias attribute in sysfs.
+#
+
+DIR="$(dirname $(readlink -f "$0"))"
+
+source "${DIR}"/ktap_helpers.sh
+
+KSFT_FAIL=1
+KSFT_SKIP=4
+
+retval=0
+
+match()
+{
+	FILE="$1"
+	ID="$2"
+
+	[ ! -f "$FILE" ] && return 1
+	[ "$ID" = "" ] && return 0
+	grep -q "$ID" "$FILE" || return 1
+	return 0
+}
+
+usb()
+{
+	name="$1"
+	count="$2"
+	shift 2
+
+	for arg in $@; do
+		[[ "$arg" =~ ^v= ]] && v="${arg#v=}"
+		[[ "$arg" =~ ^p= ]] && p="${arg#p=}"
+		[[ "$arg" =~ ^d= ]] && d="${arg#d=}"
+		[[ "$arg" =~ ^dc= ]] && dc="${arg#dc=}"
+		[[ "$arg" =~ ^dsc= ]] && dsc="${arg#dsc=}"
+		[[ "$arg" =~ ^dp= ]] && dp="${arg#dp=}"
+		[[ "$arg" =~ ^ic= ]] && ic="${arg#ic=}"
+		[[ "$arg" =~ ^isc= ]] && isc="${arg#isc=}"
+		[[ "$arg" =~ ^ip= ]] && ip="${arg#ip=}"
+		[[ "$arg" =~ ^in= ]] && in="${arg#in=}"
+	done
+
+	cur_count=0
+
+	for dev in $(find /sys/bus/usb/devices -maxdepth 1); do
+		match "$dev"/idVendor "$v" || continue
+		match "$dev"/idProduct "$p" || continue
+		match "$dev"/bcdDevice "$d" || continue
+		match "$dev"/bDeviceClass "$dc" || continue
+		match "$dev"/bDeviceSubClass "$dsc" || continue
+		match "$dev"/bDeviceProtocol "$dp" || continue
+
+		# Matched device. Now search through interfaces
+		for intf in $(find "$dev"/ -maxdepth 1 -type d); do
+			match "$intf"/bInterfaceClass "$ic" || continue
+			match "$intf"/bInterfaceSubClass "$isc" || continue
+			match "$intf"/bInterfaceProtocol "$ip" || continue
+			match "$intf"/bInterfaceNumber "$in" || continue
+
+			# Matched interface. Add to count if it was probed by driver.
+			[ -d "$intf"/driver ] && cur_count=$((cur_count+1))
+		done
+	done
+
+	if [ "$cur_count" -eq "$count" ]; then
+		ktap_test_pass usb."$name"
+	else
+		ktap_test_fail usb."$name"
+		retval="$KSFT_FAIL"
+	fi
+}
+
+pci()
+{
+	name="$1"
+	count="$2"
+	shift 2
+
+	for arg in $@; do
+		[[ "$arg" =~ ^v= ]] && v="${arg#v=}"
+		[[ "$arg" =~ ^d= ]] && d="${arg#d=}"
+		[[ "$arg" =~ ^sv= ]] && sv="${arg#sv=}"
+		[[ "$arg" =~ ^sd= ]] && sd="${arg#sd=}"
+		[[ "$arg" =~ ^bc= ]] && bc="${arg#bc=}"
+		[[ "$arg" =~ ^sc= ]] && sc="${arg#sc=}"
+		[[ "$arg" =~ ^i= ]] && i="${arg#i=}"
+	done
+
+	cur_count=0
+
+	for dev in $(find /sys/bus/pci/devices -maxdepth 1); do
+		match "$dev"/vendor "$v" || continue
+		match "$dev"/device "$d" || continue
+		match "$dev"/subsystem_vendor "$sv" || continue
+		match "$dev"/subsystem_device "$sd" || continue
+
+		[ -z "$bc" ] && bc='..'
+		[ -z "$sc" ] && sc='..'
+		[ -z "$i" ] && i='..'
+		match "$dev/"class "$bc$sc$i" || continue
+
+		# Matched device. Add to count if it was probed by driver.
+		[ -d "$dev"/driver ] && cur_count=$((cur_count+1))
+	done
+
+	if [ "$cur_count" -eq "$count" ]; then
+		ktap_test_pass pci."$name"
+	else
+		ktap_test_fail pci."$name"
+		retval="$KSFT_FAIL"
+	fi
+}
+
+ktap_print_header
+
+plat_compatible=/proc/device-tree/compatible
+
+if [ ! -f "$plat_compatible" ]; then
+	ktap_skip_all "No board compatible available"
+	exit "$KSFT_SKIP"
+fi
+
+compatibles=$(tr '\000' '\n' < "$plat_compatible")
+
+for compatible in $compatibles; do
+	if [ -f boards/"$compatible" ]; then
+		board_file=boards/"$compatible"
+		break
+	fi
+done
+
+if [ -z "$board_file" ]; then
+	ktap_skip_all "No matching board file found"
+	exit "$KSFT_SKIP"
+fi
+
+echo "# Using board file: " "$board_file"
+
+num_tests=$(grep -E "^(usb|pci)" "$board_file" | wc -l)
+ktap_set_plan "$num_tests"
+
+source "$board_file"
+
+ktap_print_totals
+exit "${retval}"
-- 
2.42.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.