Commit 838f12c3 authored by Ilpo Järvinen's avatar Ilpo Järvinen Committed by Bjorn Helgaas
Browse files

selftests/pcie_bwctrl: Create selftests

Create selftests for PCIe BW control through the PCIe cooling device sysfs
interface.

First, the BW control selftest finds the PCIe Port to test with. By
default, the PCIe Port with the highest Link Speed is selected but
another PCIe Port can be provided with -d parameter.

The actual test steps the cur_state of the cooling device one-by-one
from max_state to what the cur_state was initially. The speed change
is confirmed by observing the current_link_speed for the corresponding
PCIe Port.

Link: https://lore.kernel.org/r/20241018144755.7875-10-ilpo.jarvinen@linux.intel.com


Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent d278b098
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -17940,6 +17940,7 @@ S: Supported
F:	drivers/pci/pcie/bwctrl.c
F:	drivers/thermal/pcie_cooling.c
F:	include/linux/pci-bwctrl.h
F:	tools/testing/selftests/pcie_bwctrl/
PCIE DRIVER FOR AMAZON ANNAPURNA LABS
M:	Jonathan Chocron <jonnyc@amazon.com>
+1 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ TARGETS += net/packetdrill
TARGETS += net/rds
TARGETS += net/tcp_ao
TARGETS += nsfs
TARGETS += pcie_bwctrl
TARGETS += perf_events
TARGETS += pidfd
TARGETS += pid_namespace
+2 −0
Original line number Diff line number Diff line
TEST_PROGS = set_pcie_cooling_state.sh
include ../lib.mk
+122 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later

SYSFS=
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
retval=0
skipmsg="skip all tests:"

PCIEPORTTYPE="PCIe_Port_Link_Speed"

prerequisite()
{
	local ports

	if [ $UID != 0 ]; then
		echo $skipmsg must be run as root >&2
		exit $ksft_skip
	fi

	SYSFS=`mount -t sysfs | head -1 | awk '{ print $3 }'`

	if [ ! -d "$SYSFS" ]; then
		echo $skipmsg sysfs is not mounted >&2
		exit $ksft_skip
	fi

	if ! ls $SYSFS/class/thermal/cooling_device* > /dev/null 2>&1; then
		echo $skipmsg thermal cooling devices missing >&2
		exit $ksft_skip
	fi

	ports=`grep -e "^$PCIEPORTTYPE" $SYSFS/class/thermal/cooling_device*/type | wc -l`
	if [ $ports -eq 0 ]; then
		echo $skipmsg pcie cooling devices missing >&2
		exit $ksft_skip
	fi
}

testport=
find_pcie_port()
{
	local patt="$1"
	local pcieports
	local max
	local cur
	local delta
	local bestdelta=-1

	pcieports=`grep -l -F -e "$patt" /sys/class/thermal/cooling_device*/type`
	if [ -z "$pcieports" ]; then
		return
	fi
	pcieports=${pcieports//\/type/}
	# Find the port with the highest PCIe Link Speed
	for port in $pcieports; do
		max=`cat $port/max_state`
		cur=`cat $port/cur_state`
		delta=$((max-cur))
		if [ $delta -gt $bestdelta ]; then
			testport="$port"
			bestdelta=$delta
		fi
	done
}

sysfspcidev=
find_sysfs_pci_dev()
{
	local typefile="$1/type"
	local pcidir

	pcidir="$SYSFS/bus/pci/devices/`sed -e "s|^${PCIEPORTTYPE}_||g" $typefile`"

	if [ -r "$pcidir/current_link_speed" ]; then
		sysfspcidev="$pcidir/current_link_speed"
	fi
}

usage()
{
	echo "Usage $0 [ -d dev ]"
	echo -e "\t-d: PCIe port BDF string (e.g., 0000:00:04.0)"
}

pattern="$PCIEPORTTYPE"
parse_arguments()
{
	while getopts d:h opt; do
		case $opt in
			h)
				usage "$0"
				exit 0
				;;
			d)
				pattern="$PCIEPORTTYPE_$OPTARG"
				;;
			*)
				usage "$0"
				exit 0
				;;
		esac
	done
}

parse_arguments "$@"
prerequisite
find_pcie_port "$pattern"
if [ -z "$testport" ]; then
	echo $skipmsg "pcie cooling device not found from sysfs" >&2
	exit $ksft_skip
fi
find_sysfs_pci_dev "$testport"
if [ -z "$sysfspcidev" ]; then
	echo $skipmsg "PCIe port device not found from sysfs" >&2
	exit $ksft_skip
fi

./set_pcie_speed.sh "$testport" "$sysfspcidev"
retval=$?

exit $retval
+67 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later

set -e

TESTNAME=set_pcie_speed

declare -a PCIELINKSPEED=(
	"2.5 GT/s PCIe"
	"5.0 GT/s PCIe"
	"8.0 GT/s PCIe"
	"16.0 GT/s PCIe"
	"32.0 GT/s PCIe"
	"64.0 GT/s PCIe"
)

# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4
retval=0

coolingdev="$1"
statefile="$coolingdev/cur_state"
maxfile="$coolingdev/max_state"
linkspeedfile="$2"

oldstate=`cat $statefile`
maxstate=`cat $maxfile`

set_state()
{
	local state=$1
	local linkspeed
	local expected_linkspeed

	echo $state > $statefile

	sleep 1

	linkspeed="`cat $linkspeedfile`"
	expected_linkspeed=$((maxstate-state))
	expected_str="${PCIELINKSPEED[$expected_linkspeed]}"
	if [ ! "${expected_str}" = "${linkspeed}" ]; then
		echo "$TESTNAME failed: expected: ${expected_str}; got ${linkspeed}"
		retval=1
	fi
}

cleanup_skip ()
{
	set_state $oldstate
	exit $ksft_skip
}

trap cleanup_skip EXIT

echo "$TESTNAME: testing states $maxstate .. $oldstate with $coolingdev"
for i in $(seq $maxstate -1 $oldstate); do
	set_state "$i"
done

trap EXIT
if [ $retval -eq 0 ]; then
	echo "$TESTNAME [PASS]"
else
	echo "$TESTNAME [FAIL]"
fi
exit $retval