diff --git a/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/Ethernet_Inventory_Validation.yaml b/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/Ethernet_Inventory_Validation.yaml index 317181059..94a8844ac 100644 --- a/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/Ethernet_Inventory_Validation.yaml +++ b/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/Ethernet_Inventory_Validation.yaml @@ -1,7 +1,7 @@ metadata: name: ethernet-inventory-validation format: "Lava-Test Test Definition 1.0" - description: "Inventory physical Ethernet interfaces, MAC drivers, PHY identity, device-tree identity, queue topology, and platform bindings without changing network configuration." + description: "Inventory Ethernet interfaces, drivers, PHY and queue topology, including runtime-gated QPS615 readiness, without changing network configuration." os: - linux scope: diff --git a/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/README.md b/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/README.md index 7b628d0fc..a7d1d7226 100644 --- a/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/README.md +++ b/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/README.md @@ -21,6 +21,38 @@ For each interface, the testcase reports and validates: The testcase does not bring interfaces up, run DHCP, change link settings, or transmit traffic. +When the runtime PCI topology contains a QPS615 switch (`1179:0623`), the +testcase also correlates downstream TC956x driver functions with exported +Ethernet interfaces and verifies that `TC956X_Firmware_PCIeBridge.bin` remains +available from a standard firmware root. Images without QPS615 retain the +generic Ethernet inventory behavior. + +For each expected Toshiba `1179:0220` Ethernet function, the live log and TSV +include its PCI modalias, bound driver, exported netdevs, and availability of +the running-kernel `tc956x_pcie_eth` module. They also report whether that +module registered its `tc956x_pci-eth` PCI driver and expose the current +`tc956x_eth_ports_bdf` value, PCI driver-autoprobe state, per-function driver +override, runtime power state, and runtime OF node as diagnostic evidence. The +driver's all-zero BDF array selects its built-in defaults and is not itself a +failure. An enumerated Ethernet function that remains unbound is a real +Ethernet failure only when its runtime OF node declares a platform Ethernet +port through the current `phy-reset-gpios` property or the legacy +`qcom,phy-rst-gpio` property. Bare embedded PCI functions can be enumerated for +IOMMU/topology description even when no MAC/PHY port is provisioned, and are +reported as SKIP. The PCIe suite continues to evaluate switch topology and +firmware independently. + +This classification follows the Qualcomm Linux PCIe and Ethernet guides: the +QPS615 MAC driver and kernel configuration are enabled by default, and the +supported Ethernet interfaces are expected to activate during startup once the +QPS615 driver is loaded and the PCIe link is established. Link carrier and the +optional AQR PHY are not required by this inventory-only testcase. + +References: + +- [Qualcomm Linux PCIe guide](https://docs.qualcomm.com/doc/80-70023-8/topic/pcie.html#pcie-software-support-feature-for-qps615) +- [Qualcomm Linux Ethernet bring-up guide](https://docs.qualcomm.com/bundle/publicresource/80-70023-26/topics/bring_up-ethernet.md) + ## Prerequisites and infrastructure - No cable, peer, DHCP service, or Internet connection is required. @@ -52,9 +84,21 @@ Example: ## Result -```text -Ethernet_Inventory_Validation.res -Ethernet_Inventory_Validation.results.tsv +Check the final result and per-check summary: + +```sh +cat Ethernet_Inventory_Validation.res +cat Ethernet_Inventory_Validation.results.tsv ``` The testcase passes when at least one physical Ethernet interface is enumerated with a bound driver and valid RX/TX queue entries. Optional OF and PHY properties are reported as SKIP when the corresponding bus or driver does not expose them. + +On QPS615 systems, inspect the correlated PCIe, driver, and netdev evidence: + +```sh +cat qps615_runtime/qps615_switches.log +cat qps615_runtime/qps615_runtime.tsv +``` + +The QPS615 files are empty or contain no switch records when the capability is +not present. That does not change the generic Ethernet result path. diff --git a/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/run.sh b/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/run.sh index 9467d0551..49743c404 100755 --- a/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/run.sh +++ b/Runner/suites/Connectivity/Ethernet/Ethernet_Inventory_Validation/run.sh @@ -109,6 +109,7 @@ if ! CHECK_DEPS_NO_EXIT=1 check_dependencies \ grep \ cat \ find \ + head \ readlink \ uname; then @@ -123,6 +124,58 @@ fi log_info "Platform Details: machine='${PLATFORM_MACHINE:-unknown}' target='${PLATFORM_TARGET:-unknown}' kernel='$(uname -r 2>/dev/null || echo unknown)' arch='$(uname -m 2>/dev/null || echo unknown)'" +QPS615_RESULT_DIR="./qps615_runtime" +ethv_qps615_collect_runtime "$QPS615_RESULT_DIR" +qps615_status=$? + +case "$qps615_status" in + 0|1) + if [ -n "$QPS615_TOPOLOGY_FAILURE_REASON" ]; then + ethv_record_result \ + "$RESULT_TABLE" \ + "QPS615 PCIe topology and firmware" \ + "FAIL" \ + "$QPS615_TOPOLOGY_FAILURE_REASON" + else + ethv_record_result \ + "$RESULT_TABLE" \ + "QPS615 PCIe topology and firmware" \ + "PASS" \ + "bridge_functions=$QPS615_SWITCH_COUNT downstream=$QPS615_DOWNSTREAM_COUNT firmware=$QPS615_FIRMWARE_PATH" + fi + + if [ -n "$QPS615_ETHERNET_FAILURE_REASON" ]; then + ethv_record_result \ + "$RESULT_TABLE" \ + "QPS615 Ethernet endpoint readiness" \ + "FAIL" \ + "$QPS615_ETHERNET_FAILURE_REASON" + elif [ -n "$QPS615_ETHERNET_SKIP_REASON" ]; then + ethv_record_result \ + "$RESULT_TABLE" \ + "QPS615 Ethernet endpoint readiness" \ + "SKIP" \ + "$QPS615_ETHERNET_SKIP_REASON" + else + ethv_record_result \ + "$RESULT_TABLE" \ + "QPS615 Ethernet endpoint readiness" \ + "PASS" \ + "devices=$QPS615_ETHERNET_DEVICE_COUNT declared_ports=$QPS615_ETHERNET_DECLARED_COUNT bound_declared_ports=$QPS615_DECLARED_DRIVER_DEVICE_COUNT declared_port_netdevs=$QPS615_DECLARED_NETDEV_COUNT module_state=$QPS615_MODULE_STATE pci_driver_state=$QPS615_PCI_DRIVER_STATE module_path=${QPS615_MODULE_PATH:-built-in-or-unexposed}" + fi + ;; + 2) + log_info "QPS615 PCIe switch is not present, preserving generic Ethernet inventory validation" + ;; + *) + ethv_record_result \ + "$RESULT_TABLE" \ + "QPS615 runtime collection" \ + "FAIL" \ + "runtime topology collection could not complete" + ;; +esac + if [ -n "$ETH_INTERFACE" ]; then ETH_IFACES="$ETH_INTERFACE" else @@ -130,19 +183,34 @@ else fi if [ -z "$ETH_IFACES" ]; then - ethv_record_result \ - "$RESULT_TABLE" \ - "Physical Ethernet inventory" \ - "SKIP" \ - "no physical Ethernet interfaces are currently enumerated" - - ethv_print_summary "$RESULT_TABLE" "Ethernet Inventory Summary" - echo "$TESTNAME SKIP" >"$RES_FILE" - exit 0 + case "$qps615_status" in + 0) + if [ -n "$QPS615_ETHERNET_SKIP_REASON" ]; then + ethv_record_result \ + "$RESULT_TABLE" \ + "Physical Ethernet inventory" \ + "SKIP" \ + "no runtime-provisioned Ethernet interface is present" + else + ethv_record_result \ + "$RESULT_TABLE" \ + "Physical Ethernet inventory" \ + "FAIL" \ + "QPS615 reported $QPS615_NETDEV_COUNT netdev(s), but physical Ethernet discovery returned none" + fi + ;; + 2) + ethv_record_result \ + "$RESULT_TABLE" \ + "Physical Ethernet inventory" \ + "SKIP" \ + "no physical Ethernet interfaces are currently enumerated" + ;; + esac +else + log_info "Detected physical Ethernet interfaces: $(printf '%s' "$ETH_IFACES" | tr '\n' ' ')" fi -log_info "Detected physical Ethernet interfaces: $(printf '%s' "$ETH_IFACES" | tr '\n' ' ')" - for iface in $ETH_IFACES; do driver="$(ethv_get_driver "$iface")" module="$(ethv_get_driver_module "$iface")" @@ -242,7 +310,7 @@ log_info "---- Ethernet-related kernel messages ----" if command -v get_kernel_log >/dev/null 2>&1; then get_kernel_log 2>/dev/null \ | grep -iE \ - 'ethqos|stmmac|dwmac|gmac|emac|phylink|mdio|sgmii|hsgmii|2500base|rgmii|qca808|marvell|aquantia|aqr|dp83867|ptp' \ + 'ethqos|stmmac|dwmac|gmac|emac|tc956|qps615|phylink|mdio|sgmii|hsgmii|2500base|rgmii|qca808|marvell|aquantia|aqr|dp83867|ptp' \ | tail -n 200 \ | while IFS= read -r line; do [ -n "$line" ] && log_info "[eth-kernel] $line" diff --git a/Runner/suites/Kernel/Baseport/PCIe/PCIe.yaml b/Runner/suites/Kernel/Baseport/PCIe/PCIe.yaml index e9ec86741..80e54073b 100644 --- a/Runner/suites/Kernel/Baseport/PCIe/PCIe.yaml +++ b/Runner/suites/Kernel/Baseport/PCIe/PCIe.yaml @@ -1,16 +1,18 @@ metadata: name: pcio format: "Lava-Test Test Definition 1.0" - description: "Test basic PCIe features" + description: "Test basic PCIe features and capability-gated QPS615 topology and firmware readiness, with downstream Ethernet diagnostics" os: - linux scope: - functional +params: + PCIE_DMESG_STRICT: "0" + run: steps: - REPO_PATH=$PWD - cd Runner/suites/Kernel/Baseport/PCIe - ./run.sh || true - $REPO_PATH/Runner/utils/send-to-lava.sh PCIe.res || true - diff --git a/Runner/suites/Kernel/Baseport/PCIe/README.md b/Runner/suites/Kernel/Baseport/PCIe/README.md index 437316d91..aec80452a 100644 --- a/Runner/suites/Kernel/Baseport/PCIe/README.md +++ b/Runner/suites/Kernel/Baseport/PCIe/README.md @@ -1,47 +1,99 @@ # PCIe Validation Test -© Qualcomm Technologies, Inc. and/or its subsidiaries. -SPDX-License-Identifier: BSD-3-Clause## Overview +Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +SPDX-License-Identifier: BSD-3-Clause + +## Overview + This test case validates the PCIe interface on the target device by checking for the presence of key PCIe attributes using the `lspci -vvv` command. It ensures that the PCIe subsystem is correctly enumerated and functional + ### The test checks for: + - Presence of **Device Tree Node** - Availability of **PCIe Capabilities** - Binding of a **Kernel Driver** +- Per-device negotiated and maximum link speed and width +- MSI/MSI-X runtime IRQ exposure +- Runtime power state +- PCIe controller, link-training, and uncorrected AER kernel errors + +Unused PCIe bridge ports may legitimately report zero negotiated width. They +are identified as inactive bridge ports, while a zero-width non-bridge +endpoint remains a failure. These checks help confirm that the PCIe root port is properly initialized and ready for use + +When an enumerated Toshiba `1179:0623` switch identifies QPS615 hardware, the +suite also validates the discovered downstream PCIe topology, TC956x Ethernet +function enumeration, and the image-provided +`TC956X_Firmware_PCIeBridge.bin`. Driver and netdev readiness are logged for +diagnosis but are owned by `Ethernet_Inventory_Validation`, so an Ethernet +driver packaging or binding failure does not incorrectly fail the generic PCIe +contract. Systems without QPS615 continue through the existing generic checks. + +The split follows the documented startup sequence. The QPS615 switch power, +I2C initialization, firmware, PCIe link, and bridge enumeration establish the +PCIe capability. The downstream `1179:0220` functions, `tc956x_pci-eth` driver +binding, and exported netdevs establish Ethernet readiness. This keeps a +downstream MAC/PHY problem visible without misclassifying it as a failed PCIe +switch topology. + +References: + +- [Qualcomm Linux PCIe guide](https://docs.qualcomm.com/doc/80-70023-8/topic/pcie.html#pcie-software-support-feature-for-qps615) +- [Qualcomm Linux Ethernet bring-up guide](https://docs.qualcomm.com/bundle/publicresource/80-70023-26/topics/bring_up-ethernet.md) + ## Usage -### Instructions: -1. **Copy the test suite to the target device** using `scp` or any preferred method. -2. **Navigate to the test directory** on the target device. -3. **Run the test script** using the test runner or directly. ---- -### Quick Example -```bash -git clone -cd -scp -r common Runner user@target_device_ip: -ssh user@target_device_ip -cd /Runner && ./run-test.sh PCIe + +Run the suite directly on the target: + +```sh +cd Runner/suites/Kernel/Baseport/PCIe +./run.sh +``` + +It can also be launched through the repository runner: + +```sh +cd Runner +./run-test.sh PCIe ``` ---- -### Prerequisites + +## Prerequisites + 1. `lspci` must be available on the target device 2. PCIe interface must be exposed and initialized 3. Root access may be required depending on system configuration ---- + ## Result Format -Test result will be saved in `PCIe.res` as: -## Output -A .res file is generated in the same directory: -`PCIe PASS` OR `PCIe FAIL` -## Sample Log + +Check the final result: + +```sh +cat PCIe.res +``` + +The file contains `PCIe PASS`, `PCIe FAIL`, or `PCIe SKIP`. + +On QPS615 systems, inspect the retained topology evidence: + +```sh +cat qps615_runtime/qps615_switches.log +cat qps615_runtime/qps615_runtime.tsv +find /lib/firmware /usr/lib/firmware \ + -name 'TC956X_Firmware_PCIeBridge.bin*' -print 2>/dev/null +``` + +Generic PCIe runtime and kernel-health evidence is retained in: + +```sh +cat pcie_runtime/pcie_runtime.tsv +cat pcie_runtime/dmesg_errors.log +``` + +Kernel-log findings are advisory by default because the boot log can contain +history from unused ports or previously detached endpoints. To make matching +PCIe controller, link, or uncorrected AER errors fail the suite: + +```sh +PCIE_DMESG_STRICT=1 ./run.sh ``` -[INFO] 1980-01-06 00:43:54 - ----------------------------------------------------------------------------------------- -[INFO] 1980-01-06 00:43:54 - -------------------Starting PCIe Testcase---------------------------- -[INFO] 1980-01-06 00:43:54 - === Test Initialization === -[INFO] 1980-01-06 00:43:54 - Checking if required tools are available -[INFO] 1980-01-06 00:43:54 - Running PCIe -[INFO] 1980-01-06 00:43:54 - DT node is present -[INFO] 1980-01-06 00:43:54 - Yes, 'Capabilities:' is found -[INFO] 1980-01-06 00:43:54 - Driver is loaded -[PASS] 1980-01-06 00:43:54 - PCIe : Test Passed -``` \ No newline at end of file diff --git a/Runner/suites/Kernel/Baseport/PCIe/run.sh b/Runner/suites/Kernel/Baseport/PCIe/run.sh index fb2a75e97..23dbf6c82 100755 --- a/Runner/suites/Kernel/Baseport/PCIe/run.sh +++ b/Runner/suites/Kernel/Baseport/PCIe/run.sh @@ -1,11 +1,15 @@ #!/bin/sh - # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. # SPDX-License-Identifier: BSD-3-Clause -# Robustly find and source init_env -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# ---------- Repo env + helpers ---------- +SCRIPT_DIR="$( + cd "$(dirname "$0")" || exit 1 + pwd +)" INIT_ENV="" SEARCH="$SCRIPT_DIR" + while [ "$SEARCH" != "/" ]; do if [ -f "$SEARCH/init_env" ]; then INIT_ENV="$SEARCH/init_env" @@ -19,58 +23,178 @@ if [ -z "$INIT_ENV" ]; then exit 1 fi -# Only source if not already loaded (idempotent) -if [ -z "$__INIT_ENV_LOADED" ]; then +# Only source once (idempotent) +# NOTE: We intentionally **do not export** any new vars. They stay local to this shell. +if [ -z "${__INIT_ENV_LOADED:-}" ]; then # shellcheck disable=SC1090 . "$INIT_ENV" + __INIT_ENV_LOADED=1 fi -# Always source functestlib.sh, using $TOOLS exported by init_env -# shellcheck disable=SC1090,SC1091 + +# shellcheck disable=SC1090 +. "$INIT_ENV" +# shellcheck disable=SC1091 . "$TOOLS/functestlib.sh" +# shellcheck disable=SC1091 +. "$TOOLS/lib_ethernet.sh" TESTNAME="PCIe" -test_path=$(find_test_case_by_name "$TESTNAME") -cd "$test_path" || exit 1 -res_file="./$TESTNAME.res" +RES_FILE="$SCRIPT_DIR/$TESTNAME.res" +QPS615_RESULT_DIR="$SCRIPT_DIR/qps615_runtime" +PCIE_RESULT_DIR="$SCRIPT_DIR/pcie_runtime" +PCIE_DMESG_STRICT="${PCIE_DMESG_STRICT:-0}" + +test_result_init "$TESTNAME" "$RES_FILE" || exit 1 -log_info "-----------------------------------------------------------------------------------------" -log_info "-------------------Starting $TESTNAME Testcase----------------------------" -log_info "=== Test Initialization ===" -log_info "Checking if required tools are available" +log_info "--------------------------------------------------------------------------" +log_info "Starting $TESTNAME Testcase" -check_dependencies "lspci" -log_info "Running PCIe " -lspci_output=$(lspci -vvv) +case "$PCIE_DMESG_STRICT" in + 0|1) + ;; + *) + log_warn "Invalid PCIE_DMESG_STRICT='$PCIE_DMESG_STRICT', using 0" + PCIE_DMESG_STRICT=0 + ;; +esac -missing="" +log_info "Configuration: PCIE_DMESG_STRICT=$PCIE_DMESG_STRICT" -if echo "$lspci_output" | grep -q "Device tree node:"; then - log_info "DT node is present" +if ! CHECK_DEPS_RECOVER=0 CHECK_DEPS_NO_EXIT=1 check_dependencies \ + awk \ + basename \ + cat \ + find \ + grep \ + head \ + lspci \ + mkdir \ + readlink \ + rm \ + tr \ + uname; then + test_result_finish "SKIP" "$TESTNAME SKIP: required base utilities are unavailable" +fi + +if ! lspci_output="$(lspci -vvv 2>&1)"; then + test_result_finish "FAIL" "$TESTNAME FAIL: lspci inventory command failed" +fi + +pcie_dt_association=0 +for pcie_of_node in /sys/bus/pci/devices/*/of_node; do + [ -e "$pcie_of_node" ] || continue + pcie_dt_association=1 + break +done + +if printf '%s\n' "$lspci_output" | grep -q "Device tree node:" || + [ "$pcie_dt_association" -eq 1 ]; then + test_result_record "PASS" "PCIe inventory exposes device-tree node information" else - log_warn "DT node is not present" - missing=1 + test_result_record "SKIP" "PCIe device-tree association is not exposed by pciutils or sysfs" fi -if echo "$lspci_output" | grep -q "Capabilities:"; then - log_info "Yes, 'Capabilities:' is found" +if printf '%s\n' "$lspci_output" | grep -q "Capabilities:"; then + test_result_record "PASS" "PCIe capabilities are exposed" else - log_warn "No, 'Capabilities:' is missing" - missing=1 + test_result_record "FAIL" "PCIe capabilities are not exposed" fi -if echo "$lspci_output" | grep -q "Kernel driver in use:"; then - log_info "Driver is loaded" +if printf '%s\n' "$lspci_output" | grep -q "Kernel driver in use:"; then + test_result_record "PASS" "At least one PCIe device has a bound kernel driver" else - log_warn "Driver is not loaded" - missing=1 + test_result_record "FAIL" "No bound PCIe kernel driver was reported" fi -if [ -z "$missing" ]; then - log_pass "$TESTNAME : Test Passed" - echo "$TESTNAME PASS" > "$res_file" - exit 0 +pcie_collect_runtime_health "$PCIE_RESULT_DIR" +pcie_runtime_status=$? + +case "$pcie_runtime_status" in + 0) + test_result_record \ + "PASS" \ + "PCIe runtime inventory is readable: devices=$PCIE_RUNTIME_DEVICE_COUNT link_records=$PCIE_RUNTIME_LINK_COUNT power_records=$PCIE_RUNTIME_POWER_COUNT" + if [ "$PCIE_RUNTIME_INACTIVE_PORT_COUNT" -gt 0 ]; then + test_result_record \ + "SKIP" \ + "$PCIE_RUNTIME_INACTIVE_PORT_COUNT unused PCIe bridge port(s) currently have no negotiated downstream link" + fi + if [ "$PCIE_RUNTIME_MSI_DEVICE_COUNT" -gt 0 ]; then + test_result_record \ + "PASS" \ + "PCIe MSI/MSI-X runtime evidence is present for $PCIE_RUNTIME_MSI_DEVICE_COUNT device(s)" + else + test_result_record "SKIP" "No PCIe MSI/MSI-X IRQ directories are exposed" + fi + ;; + 1) + test_result_record \ + "FAIL" \ + "PCIe runtime health validation failed: ${PCIE_RUNTIME_FAILURE_REASON:-malformed sysfs evidence}" + ;; + 2) + test_result_record "FAIL" "lspci reports PCI devices but PCI sysfs inventory is empty" + ;; + *) + test_result_record "FAIL" "PCIe runtime health inventory could not complete" + ;; +esac + +ethv_qps615_collect_runtime "$QPS615_RESULT_DIR" +qps615_status=$? + +case "$qps615_status" in + 0|1) + if [ -n "$QPS615_TOPOLOGY_FAILURE_REASON" ]; then + test_result_record \ + "FAIL" \ + "QPS615 PCIe topology or firmware validation failed: $QPS615_TOPOLOGY_FAILURE_REASON" + else + test_result_record \ + "PASS" \ + "QPS615 PCIe topology and firmware are healthy: bridge_functions=$QPS615_SWITCH_COUNT downstream=$QPS615_DOWNSTREAM_COUNT ethernet_devices=$QPS615_ETHERNET_DEVICE_COUNT firmware=$QPS615_FIRMWARE_PATH" + fi + + if [ -n "$QPS615_ETHERNET_FAILURE_REASON" ]; then + test_result_record \ + "SKIP" \ + "QPS615 Ethernet readiness is reported by Ethernet_Inventory_Validation: $QPS615_ETHERNET_FAILURE_REASON" + elif [ -n "$QPS615_ETHERNET_SKIP_REASON" ]; then + test_result_record \ + "SKIP" \ + "QPS615 Ethernet is not runtime-provisioned: $QPS615_ETHERNET_SKIP_REASON" + else + log_info "QPS615 Ethernet evidence: devices=$QPS615_ETHERNET_DEVICE_COUNT declared_ports=$QPS615_ETHERNET_DECLARED_COUNT bound_declared_ports=$QPS615_DECLARED_DRIVER_DEVICE_COUNT declared_port_netdevs=$QPS615_DECLARED_NETDEV_COUNT module_state=$QPS615_MODULE_STATE module_path=${QPS615_MODULE_PATH:-built-in-or-unexposed}" + fi + ;; + 2) + log_info "QPS615 PCIe switch is not present, preserving generic PCIe validation" + ;; + 3) + test_result_record \ + "FAIL" \ + "QPS615 topology validation could not complete because its arguments or runtime paths were invalid" + ;; + *) + test_result_record "FAIL" "QPS615 topology validation could not complete" + ;; +esac + +log_info "PCIe kernel-health validation: capturing link-training, controller, and AER errors" +scan_dmesg_errors \ + "$PCIE_RESULT_DIR" \ + 'pcieport.*|qcom-pcie.*|pci.*' \ + 'AER: Corrected|corrected error|deferred probe|EPROBE_DEFER|using dummy regulator|supply [^ ]+ not found' +pcie_dmesg_status=$? + +if [ ! -s "$PCIE_RESULT_DIR/dmesg_snapshot.log" ]; then + test_result_record "SKIP" "Kernel log access is unavailable for PCIe health validation" +elif [ "$pcie_dmesg_status" -eq 0 ] && [ "$PCIE_DMESG_STRICT" -eq 1 ]; then + test_result_record "FAIL" "PCIe link, controller, or uncorrected AER errors were found in $PCIE_RESULT_DIR/dmesg_errors.log" +elif [ "$pcie_dmesg_status" -eq 0 ]; then + test_result_record "SKIP" "PCIe kernel errors were retained as advisory evidence, set PCIE_DMESG_STRICT=1 to gate them" else - log_fail "$TESTNAME : Test Failed" - echo "$TESTNAME FAIL" > "$res_file" - exit 1 + test_result_record "PASS" "No non-benign PCIe controller or AER errors were found in the captured kernel log" fi + +test_result_finish diff --git a/Runner/utils/lib_ethernet.sh b/Runner/utils/lib_ethernet.sh index 7d16f8512..b46c5f35f 100755 --- a/Runner/utils/lib_ethernet.sh +++ b/Runner/utils/lib_ethernet.sh @@ -258,6 +258,329 @@ ethv_get_physical_interfaces() { done } +# ethv_qps615_collect_runtime [pci-devices-root] +# Collect and validate the runtime QPS615/TC956x PCIe Ethernet topology. +# QPS615 applicability comes from the enumerated Toshiba 1179:0623 switch, +# not from an installed package or module alone. Exported QPS615_* values +# summarize the result for PCIe and Ethernet suite orchestration. +# return: 0 when applicable and healthy, 1 when declared hardware is broken, +# 2 when QPS615 is not present, and 3 for invalid arguments. +ethv_qps615_collect_runtime() { + ethv_qcr_result_dir="${1:-}" + ethv_qcr_pci_root="${2:-/sys/bus/pci/devices}" + ethv_qcr_inventory="$ethv_qcr_result_dir/qps615_runtime.tsv" + ethv_qcr_switches="$ethv_qcr_result_dir/qps615_switches.log" + + [ -n "$ethv_qcr_result_dir" ] || return 3 + mkdir -p "$ethv_qcr_result_dir" || return 1 + : >"$ethv_qcr_inventory" || return 1 + : >"$ethv_qcr_switches" || return 1 + + QPS615_SWITCH_COUNT=0 + QPS615_DOWNSTREAM_COUNT=0 + QPS615_ETHERNET_DEVICE_COUNT=0 + QPS615_ETHERNET_DECLARED_COUNT=0 + QPS615_DRIVER_DEVICE_COUNT=0 + QPS615_DECLARED_DRIVER_DEVICE_COUNT=0 + QPS615_UNBOUND_ETHERNET_COUNT=0 + QPS615_NETDEV_COUNT=0 + QPS615_DECLARED_NETDEV_COUNT=0 + QPS615_ETHERNET_OF_NODE_COUNT=0 + QPS615_ETHERNET_OVERRIDE_COUNT=0 + QPS615_FIRMWARE_PATH="" + QPS615_MODULE_PATH="" + QPS615_MODULE_STATE="absent" + QPS615_MODULE_PORT_BDFS="" + QPS615_MODULE_PORT_CONFIG="unavailable" + QPS615_PCI_DRIVER_PATH="" + QPS615_PCI_DRIVER_STATE="absent" + QPS615_PCI_AUTOPROBE="unknown" + QPS615_TOPOLOGY_FAILURE_REASON="" + QPS615_ETHERNET_FAILURE_REASON="" + QPS615_ETHERNET_SKIP_REASON="" + QPS615_FAILURE_REASON="" + + log_info "QPS615 validation: scanning PCI devices under $ethv_qcr_pci_root for switch 1179:0623" + + if [ ! -d "$ethv_qcr_pci_root" ]; then + log_info "QPS615 validation is not applicable because the PCI sysfs inventory is not exposed" + export QPS615_SWITCH_COUNT QPS615_DOWNSTREAM_COUNT QPS615_ETHERNET_DEVICE_COUNT + export QPS615_ETHERNET_DECLARED_COUNT QPS615_DRIVER_DEVICE_COUNT + export QPS615_DECLARED_DRIVER_DEVICE_COUNT QPS615_UNBOUND_ETHERNET_COUNT QPS615_NETDEV_COUNT + export QPS615_DECLARED_NETDEV_COUNT + export QPS615_ETHERNET_OF_NODE_COUNT QPS615_ETHERNET_OVERRIDE_COUNT + export QPS615_FIRMWARE_PATH QPS615_MODULE_PATH QPS615_MODULE_STATE + export QPS615_MODULE_PORT_BDFS QPS615_MODULE_PORT_CONFIG + export QPS615_PCI_DRIVER_PATH QPS615_PCI_DRIVER_STATE + export QPS615_PCI_AUTOPROBE + export QPS615_TOPOLOGY_FAILURE_REASON QPS615_ETHERNET_FAILURE_REASON + export QPS615_ETHERNET_SKIP_REASON QPS615_FAILURE_REASON + return 2 + fi + + for ethv_qcr_device in "$ethv_qcr_pci_root"/*; do + [ -d "$ethv_qcr_device" ] || continue + ethv_qcr_vendor="$(ethv_read_first_line "$ethv_qcr_device/vendor" 2>/dev/null || true)" + ethv_qcr_id="$(ethv_read_first_line "$ethv_qcr_device/device" 2>/dev/null || true)" + + if [ "$ethv_qcr_vendor" = "0x1179" ] && \ + [ "$ethv_qcr_id" = "0x0623" ]; then + ethv_qcr_resolved="$(readlink -f "$ethv_qcr_device" 2>/dev/null || true)" + QPS615_SWITCH_COUNT=$((QPS615_SWITCH_COUNT + 1)) + if [ -n "$ethv_qcr_resolved" ]; then + printf '%s\n' "$ethv_qcr_resolved" >>"$ethv_qcr_switches" + fi + printf 'switch\t%s\t%s\t%s\t%s\n' \ + "${ethv_qcr_device##*/}" \ + "$ethv_qcr_vendor" \ + "$ethv_qcr_id" \ + "${ethv_qcr_resolved:-unresolved}" >>"$ethv_qcr_inventory" + log_info "[QPS615] switch=${ethv_qcr_device##*/} vendor=$ethv_qcr_vendor device=$ethv_qcr_id path=${ethv_qcr_resolved:-unresolved}" + fi + done + + if [ "$QPS615_SWITCH_COUNT" -eq 0 ]; then + log_info "QPS615 validation is not applicable because switch 1179:0623 was not enumerated" + export QPS615_SWITCH_COUNT QPS615_DOWNSTREAM_COUNT QPS615_ETHERNET_DEVICE_COUNT + export QPS615_ETHERNET_DECLARED_COUNT QPS615_DRIVER_DEVICE_COUNT + export QPS615_DECLARED_DRIVER_DEVICE_COUNT QPS615_UNBOUND_ETHERNET_COUNT QPS615_NETDEV_COUNT + export QPS615_DECLARED_NETDEV_COUNT + export QPS615_ETHERNET_OF_NODE_COUNT QPS615_ETHERNET_OVERRIDE_COUNT + export QPS615_FIRMWARE_PATH QPS615_MODULE_PATH QPS615_MODULE_STATE + export QPS615_MODULE_PORT_BDFS QPS615_MODULE_PORT_CONFIG + export QPS615_PCI_DRIVER_PATH QPS615_PCI_DRIVER_STATE + export QPS615_PCI_AUTOPROBE + export QPS615_TOPOLOGY_FAILURE_REASON QPS615_ETHERNET_FAILURE_REASON + export QPS615_ETHERNET_SKIP_REASON QPS615_FAILURE_REASON + return 2 + fi + + for ethv_qcr_device in "$ethv_qcr_pci_root"/*; do + [ -d "$ethv_qcr_device" ] || continue + ethv_qcr_resolved="$(readlink -f "$ethv_qcr_device" 2>/dev/null || true)" + ethv_qcr_is_downstream=0 + + while IFS= read -r ethv_qcr_switch_path; do + [ -n "$ethv_qcr_switch_path" ] || continue + case "$ethv_qcr_resolved" in + "$ethv_qcr_switch_path"/*) + ethv_qcr_is_downstream=1 + break + ;; + esac + done <"$ethv_qcr_switches" + + [ "$ethv_qcr_is_downstream" -eq 1 ] || continue + QPS615_DOWNSTREAM_COUNT=$((QPS615_DOWNSTREAM_COUNT + 1)) + + ethv_qcr_driver="" + if [ -L "$ethv_qcr_device/driver" ]; then + ethv_qcr_driver="$(basename "$(readlink -f "$ethv_qcr_device/driver" 2>/dev/null)" 2>/dev/null || true)" + fi + ethv_qcr_vendor="$(ethv_read_first_line "$ethv_qcr_device/vendor" 2>/dev/null || true)" + ethv_qcr_id="$(ethv_read_first_line "$ethv_qcr_device/device" 2>/dev/null || true)" + printf 'downstream\t%s\t%s\t%s\t%s\t%s\n' \ + "${ethv_qcr_device##*/}" \ + "${ethv_qcr_vendor:-unknown}" \ + "${ethv_qcr_id:-unknown}" \ + "${ethv_qcr_driver:-unbound}" \ + "${ethv_qcr_resolved:-unknown}" >>"$ethv_qcr_inventory" + log_info "[QPS615] downstream=${ethv_qcr_device##*/} vendor=${ethv_qcr_vendor:-unknown} device=${ethv_qcr_id:-unknown} driver=${ethv_qcr_driver:-unbound}" + + if [ "$ethv_qcr_vendor" = "0x1179" ] && \ + [ "$ethv_qcr_id" = "0x0220" ]; then + QPS615_ETHERNET_DEVICE_COUNT=$((QPS615_ETHERNET_DEVICE_COUNT + 1)) + ethv_qcr_modalias="$(ethv_read_first_line "$ethv_qcr_device/modalias" 2>/dev/null || true)" + ethv_qcr_driver_override="$(ethv_read_first_line "$ethv_qcr_device/driver_override" 2>/dev/null || true)" + ethv_qcr_of_node="$(readlink -f "$ethv_qcr_device/of_node" 2>/dev/null || true)" + ethv_qcr_runtime_status="$(ethv_read_first_line "$ethv_qcr_device/power/runtime_status" 2>/dev/null || true)" + ethv_qcr_port_declaration="absent" + case "$ethv_qcr_driver_override" in + ''|'(null)') + ethv_qcr_driver_override="none" + ;; + *) + QPS615_ETHERNET_OVERRIDE_COUNT=$((QPS615_ETHERNET_OVERRIDE_COUNT + 1)) + ;; + esac + if [ -n "$ethv_qcr_of_node" ]; then + QPS615_ETHERNET_OF_NODE_COUNT=$((QPS615_ETHERNET_OF_NODE_COUNT + 1)) + if [ -e "$ethv_qcr_of_node/phy-reset-gpios" ] || \ + [ -e "$ethv_qcr_of_node/qcom,phy-rst-gpio" ]; then + ethv_qcr_port_declaration="declared" + QPS615_ETHERNET_DECLARED_COUNT=$((QPS615_ETHERNET_DECLARED_COUNT + 1)) + fi + fi + printf 'ethernet-function\t%s\tdriver=%s\tmodalias=%s\tdriver_override=%s\tof_node=%s\tport_configuration=%s\truntime_status=%s\n' \ + "${ethv_qcr_device##*/}" \ + "${ethv_qcr_driver:-unbound}" \ + "${ethv_qcr_modalias:-unavailable}" \ + "$ethv_qcr_driver_override" \ + "${ethv_qcr_of_node:-unavailable}" \ + "$ethv_qcr_port_declaration" \ + "${ethv_qcr_runtime_status:-unknown}" >>"$ethv_qcr_inventory" + log_info "[QPS615-ETH] function=${ethv_qcr_device##*/} driver=${ethv_qcr_driver:-unbound} port_configuration=$ethv_qcr_port_declaration driver_override=$ethv_qcr_driver_override of_node=${ethv_qcr_of_node:-unavailable} runtime_status=${ethv_qcr_runtime_status:-unknown} modalias=${ethv_qcr_modalias:-unavailable}" + + case "$ethv_qcr_driver" in + tc956x*) + QPS615_DRIVER_DEVICE_COUNT=$((QPS615_DRIVER_DEVICE_COUNT + 1)) + if [ "$ethv_qcr_port_declaration" = "declared" ]; then + QPS615_DECLARED_DRIVER_DEVICE_COUNT=$((QPS615_DECLARED_DRIVER_DEVICE_COUNT + 1)) + fi + for ethv_qcr_netdev in "$ethv_qcr_device"/net/*; do + [ -d "$ethv_qcr_netdev" ] || continue + QPS615_NETDEV_COUNT=$((QPS615_NETDEV_COUNT + 1)) + if [ "$ethv_qcr_port_declaration" = "declared" ]; then + QPS615_DECLARED_NETDEV_COUNT=$((QPS615_DECLARED_NETDEV_COUNT + 1)) + fi + printf 'netdev\t%s\t%s\n' \ + "${ethv_qcr_device##*/}" \ + "${ethv_qcr_netdev##*/}" >>"$ethv_qcr_inventory" + log_info "[QPS615] ethernet_function=${ethv_qcr_device##*/} netdev=${ethv_qcr_netdev##*/}" + done + ;; + "") + QPS615_UNBOUND_ETHERNET_COUNT=$((QPS615_UNBOUND_ETHERNET_COUNT + 1)) + ;; + *) + QPS615_UNBOUND_ETHERNET_COUNT=$((QPS615_UNBOUND_ETHERNET_COUNT + 1)) + log_warn "[QPS615-ETH] function=${ethv_qcr_device##*/} is bound to unexpected driver=$ethv_qcr_driver" + ;; + esac + fi + done + + QPS615_FIRMWARE_PATH="$(find_image_firmware TC956X_Firmware_PCIeBridge.bin 2>/dev/null || true)" + if [ -n "$QPS615_FIRMWARE_PATH" ]; then + log_info "[QPS615] firmware=$QPS615_FIRMWARE_PATH" + else + log_warn "[QPS615] firmware TC956X_Firmware_PCIeBridge.bin was not found" + fi + + ethv_qcr_module_candidate="$(find_kernel_module tc956x_pcie_eth 2>/dev/null | awk '/^\// { print; exit }' || true)" + ethv_qcr_running_kernel="$(uname -r 2>/dev/null || true)" + case "$ethv_qcr_module_candidate" in + "/lib/modules/$ethv_qcr_running_kernel/"*) + QPS615_MODULE_PATH="$ethv_qcr_module_candidate" + QPS615_MODULE_STATE="available" + ;; + "") + ;; + *) + log_warn "[QPS615-ETH] tc956x_pcie_eth exists only outside the running-kernel module tree: $ethv_qcr_module_candidate" + ;; + esac + + if [ -d /sys/module/tc956x_pcie_eth ]; then + QPS615_MODULE_STATE="loaded-or-built-in" + fi + + if [ -r /sys/module/tc956x_pcie_eth/parameters/tc956x_eth_ports_bdf ]; then + QPS615_MODULE_PORT_BDFS="$( + ethv_read_first_line \ + /sys/module/tc956x_pcie_eth/parameters/tc956x_eth_ports_bdf \ + 2>/dev/null || true + )" + ethv_qcr_nonzero_bdfs="$( + printf '%s' "$QPS615_MODULE_PORT_BDFS" | + tr -d '0,[:space:]' + )" + if [ -n "$QPS615_MODULE_PORT_BDFS" ] && \ + [ -z "$ethv_qcr_nonzero_bdfs" ]; then + QPS615_MODULE_PORT_CONFIG="driver-defaults" + elif [ -n "$QPS615_MODULE_PORT_BDFS" ]; then + QPS615_MODULE_PORT_CONFIG="configured" + fi + printf 'module-configuration\ttc956x_eth_ports_bdf=%s\tstate=%s\n' \ + "${QPS615_MODULE_PORT_BDFS:-unreadable}" \ + "$QPS615_MODULE_PORT_CONFIG" >>"$ethv_qcr_inventory" + log_info "[QPS615-ETH] module_parameter=tc956x_eth_ports_bdf value=${QPS615_MODULE_PORT_BDFS:-unreadable} state=$QPS615_MODULE_PORT_CONFIG" + fi + + if [ -d /sys/bus/pci/drivers/tc956x_pci-eth ]; then + QPS615_PCI_DRIVER_PATH="/sys/bus/pci/drivers/tc956x_pci-eth" + QPS615_PCI_DRIVER_STATE="registered" + log_info "[QPS615-ETH] pci_driver=tc956x_pci-eth state=registered path=$QPS615_PCI_DRIVER_PATH" + elif [ "$QPS615_MODULE_STATE" = "loaded-or-built-in" ]; then + log_warn "[QPS615-ETH] module is loaded but PCI driver tc956x_pci-eth is not registered" + fi + printf 'pci-driver\tname=tc956x_pci-eth\tstate=%s\tpath=%s\n' \ + "$QPS615_PCI_DRIVER_STATE" \ + "${QPS615_PCI_DRIVER_PATH:-unavailable}" >>"$ethv_qcr_inventory" + + QPS615_PCI_AUTOPROBE="$( + ethv_read_first_line /sys/bus/pci/drivers_autoprobe 2>/dev/null || true + )" + [ -n "$QPS615_PCI_AUTOPROBE" ] || QPS615_PCI_AUTOPROBE="unknown" + printf 'pci-autoprobe\tstate=%s\n' \ + "$QPS615_PCI_AUTOPROBE" >>"$ethv_qcr_inventory" + log_info "[QPS615-ETH] pci_drivers_autoprobe=$QPS615_PCI_AUTOPROBE" + + if [ -n "$QPS615_MODULE_PATH" ]; then + log_info "[QPS615-ETH] module=tc956x_pcie_eth state=$QPS615_MODULE_STATE path=$QPS615_MODULE_PATH" + elif [ "$QPS615_MODULE_STATE" = "loaded-or-built-in" ]; then + log_info "[QPS615-ETH] module=tc956x_pcie_eth state=$QPS615_MODULE_STATE path=built-in-or-unexposed" + else + log_warn "[QPS615-ETH] module=tc956x_pcie_eth was not found for the running kernel" + fi + + log_info "[QPS615] summary bridge_functions=$QPS615_SWITCH_COUNT downstream=$QPS615_DOWNSTREAM_COUNT ethernet_devices=$QPS615_ETHERNET_DEVICE_COUNT declared_ethernet_ports=$QPS615_ETHERNET_DECLARED_COUNT bound_ethernet_devices=$QPS615_DRIVER_DEVICE_COUNT bound_declared_ports=$QPS615_DECLARED_DRIVER_DEVICE_COUNT unbound_ethernet_devices=$QPS615_UNBOUND_ETHERNET_COUNT of_nodes=$QPS615_ETHERNET_OF_NODE_COUNT driver_overrides=$QPS615_ETHERNET_OVERRIDE_COUNT netdevs=$QPS615_NETDEV_COUNT declared_port_netdevs=$QPS615_DECLARED_NETDEV_COUNT artifact=$ethv_qcr_inventory" + + if [ "$QPS615_DOWNSTREAM_COUNT" -eq 0 ]; then + QPS615_TOPOLOGY_FAILURE_REASON="QPS615 bridge is enumerated but exposes no downstream PCIe functions" + elif [ -z "$QPS615_FIRMWARE_PATH" ]; then + QPS615_TOPOLOGY_FAILURE_REASON="required TC956X_Firmware_PCIeBridge.bin is not readable in a standard firmware root" + fi + + if [ "$QPS615_ETHERNET_DEVICE_COUNT" -eq 0 ]; then + QPS615_ETHERNET_SKIP_REASON="QPS615 is enumerated but exposes no Toshiba 1179:0220 Ethernet functions" + elif [ "$QPS615_ETHERNET_DECLARED_COUNT" -eq 0 ] && \ + [ "$QPS615_DRIVER_DEVICE_COUNT" -eq 0 ]; then + QPS615_ETHERNET_SKIP_REASON="$QPS615_ETHERNET_DEVICE_COUNT embedded Ethernet function(s) are enumerated, but no runtime DT port configuration declares them for Ethernet use" + elif [ "$QPS615_DECLARED_DRIVER_DEVICE_COUNT" -lt "$QPS615_ETHERNET_DECLARED_COUNT" ]; then + if [ "$QPS615_PCI_AUTOPROBE" = "0" ]; then + QPS615_ETHERNET_FAILURE_REASON="$QPS615_ETHERNET_DECLARED_COUNT declared QPS615 Ethernet port(s) are not ready because PCI driver autoprobe is disabled" + elif [ "$QPS615_ETHERNET_OVERRIDE_COUNT" -gt 0 ]; then + QPS615_ETHERNET_FAILURE_REASON="$QPS615_ETHERNET_DECLARED_COUNT declared QPS615 Ethernet port(s) are not ready and $QPS615_ETHERNET_OVERRIDE_COUNT function(s) have a driver override" + elif [ "$QPS615_MODULE_STATE" = "loaded-or-built-in" ]; then + if [ "$QPS615_PCI_DRIVER_STATE" != "registered" ]; then + QPS615_ETHERNET_FAILURE_REASON="$QPS615_ETHERNET_DECLARED_COUNT declared QPS615 Ethernet port(s) are not bound, tc956x_pcie_eth is loaded but PCI driver tc956x_pci-eth is not registered" + else + QPS615_ETHERNET_FAILURE_REASON="$QPS615_ETHERNET_DECLARED_COUNT declared QPS615 Ethernet port(s) did not bind after automatic matching, PCI driver tc956x_pci-eth is registered and endpoint probe did not complete" + fi + elif [ -n "$QPS615_MODULE_PATH" ]; then + QPS615_ETHERNET_FAILURE_REASON="$QPS615_ETHERNET_DECLARED_COUNT declared QPS615 Ethernet port(s) are not bound although module $QPS615_MODULE_PATH is available" + else + QPS615_ETHERNET_FAILURE_REASON="$QPS615_ETHERNET_DECLARED_COUNT declared QPS615 Ethernet port(s) are not bound and tc956x_pcie_eth is not available for the running kernel" + fi + elif [ "$QPS615_DECLARED_NETDEV_COUNT" -lt "$QPS615_DECLARED_DRIVER_DEVICE_COUNT" ]; then + QPS615_ETHERNET_FAILURE_REASON="$QPS615_DECLARED_DRIVER_DEVICE_COUNT declared TC956x Ethernet port(s) are bound but only $QPS615_DECLARED_NETDEV_COUNT netdev(s) are exposed" + elif [ "$QPS615_ETHERNET_DECLARED_COUNT" -eq 0 ] && \ + [ "$QPS615_NETDEV_COUNT" -lt "$QPS615_DRIVER_DEVICE_COUNT" ]; then + QPS615_ETHERNET_FAILURE_REASON="$QPS615_DRIVER_DEVICE_COUNT TC956x Ethernet function(s) are bound without an explicit runtime DT port declaration, but only $QPS615_NETDEV_COUNT netdev(s) are exposed" + fi + + if [ -n "$QPS615_TOPOLOGY_FAILURE_REASON" ]; then + QPS615_FAILURE_REASON="$QPS615_TOPOLOGY_FAILURE_REASON" + else + QPS615_FAILURE_REASON="$QPS615_ETHERNET_FAILURE_REASON" + fi + + export QPS615_SWITCH_COUNT QPS615_DOWNSTREAM_COUNT QPS615_ETHERNET_DEVICE_COUNT + export QPS615_ETHERNET_DECLARED_COUNT QPS615_DRIVER_DEVICE_COUNT + export QPS615_DECLARED_DRIVER_DEVICE_COUNT QPS615_UNBOUND_ETHERNET_COUNT QPS615_NETDEV_COUNT + export QPS615_DECLARED_NETDEV_COUNT + export QPS615_ETHERNET_OF_NODE_COUNT QPS615_ETHERNET_OVERRIDE_COUNT + export QPS615_FIRMWARE_PATH QPS615_MODULE_PATH QPS615_MODULE_STATE + export QPS615_MODULE_PORT_BDFS QPS615_MODULE_PORT_CONFIG + export QPS615_PCI_DRIVER_PATH QPS615_PCI_DRIVER_STATE + export QPS615_PCI_AUTOPROBE + export QPS615_TOPOLOGY_FAILURE_REASON QPS615_ETHERNET_FAILURE_REASON + export QPS615_ETHERNET_SKIP_REASON QPS615_FAILURE_REASON + + [ -z "$QPS615_FAILURE_REASON" ] +} + # ethv_get_driver # Query the bound network driver through ethtool or the sysfs driver link. # stdout: driver name, or an empty line when unavailable.