* [LTP] [PATCH v2 1/2] tpci: refactor kernel module
2026-08-06 8:10 [LTP] [PATCH v2 0/2] tcpi refactoring Andrea Cervesato
@ 2026-08-06 8:10 ` Andrea Cervesato
2026-08-06 10:40 ` [LTP] " linuxtestproject.agent
2026-08-06 8:10 ` [LTP] [PATCH v2 2/2] tpci: refactor test using new API Andrea Cervesato
1 sibling, 1 reply; 4+ messages in thread
From: Andrea Cervesato @ 2026-08-06 8:10 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
The kernel module lacked proper SPDX licensing, documentation, and
used deprecated permission macros.
Update the code to modern kernel standards by applying SPDX tags,
replacing sscanf with kstrto*, replacing custom print macros with
standard pr_* macros, adding a documentation block, and removing
the stale pci-exp-tests-HOWTO file which references long-removed
paths and macros.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
.../device-drivers/pci/tpci_kernel/ltp_tpci.c | 230 +++++++++++----------
.../pci/tpci_kernel/pci-exp-tests-HOWTO | 58 ------
.../kernel/device-drivers/pci/tpci_kernel/tpci.h | 21 +-
3 files changed, 123 insertions(+), 186 deletions(-)
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c b/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
index 45138d834d099b62f201977b284bc8d12647056c..033ac1f0008e358d1afd0240bf1a9855ec32e1fd 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
+++ b/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
@@ -1,47 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
+ * 5/20/2003 - Sean Ruyle (srruyle@us.ibm.com)
* Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ * 8/20/2004 - Amit Khanna (amit.khanna@intel.com)
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * This PCI and PCI-Express testing kernel module allows test calls to be
+ * driven through various sysfs interactions in a user-space program.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * This pci and pci-express testing kernel module will allow test calls
- * to be driven through various ioctl calls in a
- * user space program that has attained the appropriate
- * file descriptor for this device. For the functions of
- * this module to work correctly there must be a pci / pci-express
- * device somewhere in the system. The tests do not need
- * a specific device, and the first pci device available
- * will be grabbed.
+ * For the functions of this module to work correctly, there must be a
+ * PCI / PCI-Express device somewhere in the system. The tests do not need
+ * a specific device; the first PCI device available will be grabbed.
*
- * author: Sean Ruyle (srruyle@us.ibm.com)
- * date: 5/20/2003
- * PCI-Express test scripts author: Amit Khanna (amit.khanna@intel.com)
- * date: 8/20/2004
+ * The following test cases can be called from user-space:
*
- * file: tpci.c,
- * module: tpci
+ * - PCI_DISABLE
+ * - PCI_ENABLE
+ * - FIND_BUS
+ * - FIND_DEVICE
+ * - FIND_CLASS
+ * - FIND_SUBSYS
+ * - BUS_SCAN
+ * - SLOT_SCAN
+ * - BUS_ADD_DEVICES
+ * - MATCH_DEVICE
+ * - REG_DRIVER
+ * - UNREG_DRIVER
+ * - PCI_RESOURCES
+ * - SAVE_STATE
+ * - RESTORE_STATE
+ * - FIND_CAP
+ * - PCI_EXP_CAP_CONFIG
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
-#include <linux/ioctl.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
-
#include "tpci.h"
MODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
@@ -50,13 +52,6 @@ MODULE_AUTHOR("Copyright (c) 2013 Oracle and/or its affiliates");
MODULE_DESCRIPTION("LTP PCI Test");
MODULE_LICENSE("GPL");
-#define prk_err(fmt, ...) \
- pr_err(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-#define prk_info(fmt, ...) \
- pr_info(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-#define prk_debug(fmt, ...) \
- pr_debug(PCI_DEVICE_NAME ": " fmt "\n", ##__VA_ARGS__)
-
#define TPASS 0
#define TFAIL 1
#define TSKIP 32
@@ -105,15 +100,19 @@ static int probe_pci_dev(unsigned int bus, unsigned int slot)
}
dev = pci_get_domain_bus_and_slot(0, bus, slot);
- if (!dev || !dev->driver)
+ if (!dev)
+ return -ENODEV;
+ if (!dev->driver) {
+ pci_dev_put(dev);
return -ENODEV;
+ }
- prk_info("found pci_dev '%s', bus %u, devfn %u",
+ pr_info("found pci_dev '%s', bus %u, devfn %u\n",
pci_name(dev), bus, slot);
ltp_pci.dev = dev;
ltp_pci.bus = dev->bus;
- prk_info("Bus number: %d", dev->bus->number);
+ pr_info("Bus number: %d\n", dev->bus->number);
return 0;
}
@@ -126,20 +125,20 @@ static int pci_enable(void)
{
struct pci_dev *dev = ltp_pci.dev;
- prk_info("enable pci device");
+ pr_info("enable pci device\n");
/* check if can enable the device pointer */
if (!dev) {
- prk_err("dev is NULL");
+ pr_err("dev is NULL\n");
return TFAIL;
}
if (pci_enable_device(dev)) {
- prk_err("failed to enable pci device");
+ pr_err("failed to enable pci device\n");
return TFAIL;
}
- prk_info("enabled pci device");
+ pr_info("enabled pci device\n");
return TPASS;
}
@@ -147,15 +146,15 @@ static int pci_disable(void)
{
struct pci_dev *dev = ltp_pci.dev;
- prk_info("disable pci device");
+ pr_info("disable pci device\n");
/* check if device pointer exists */
if (!dev) {
- prk_err("dev is NULL");
+ pr_err("dev is NULL\n");
return TFAIL;
}
- prk_info("is pci enabled '%d', is managed '%d'",
+ pr_info("is pci enabled '%d', is managed '%d'\n",
pci_is_enabled(dev), pci_is_managed(dev));
pci_release_regions(dev);
@@ -164,13 +163,13 @@ static int pci_disable(void)
if (dev->current_state == PCI_D3hot ||
dev->current_state == PCI_D3cold) {
- prk_info("disabled pci device, state '%s'",
+ pr_info("disabled pci device, state '%s'\n",
pci_power_name(dev->current_state));
return TPASS;
}
- prk_err("failed to disable pci device, state '%s'",
+ pr_err("failed to disable pci device, state '%s'\n",
pci_power_name(dev->current_state));
return TFAIL;
}
@@ -186,19 +185,19 @@ static int test_find_bus(void)
int num = ltp_pci.bus->number;
struct pci_bus *temp = NULL;
- prk_info("find bus");
+ pr_info("find bus\n");
temp = pci_find_bus(pci_domain_nr(ltp_pci.bus), num);
if (!temp) {
- prk_info("pci_find_bus failed");
+ pr_info("pci_find_bus failed\n");
return TFAIL;
} else if (temp->number != num) {
- prk_err("returned bus pointer w/ wrong bus number");
+ pr_err("returned bus pointer w/ wrong bus number\n");
return TFAIL;
}
- prk_info("success returned bus pointer");
+ pr_info("success returned bus pointer\n");
return TPASS;
}
@@ -212,16 +211,16 @@ static int test_find_class(void)
unsigned int num = ltp_pci.dev->class;
struct pci_dev *temp = NULL;
- prk_info("find pci class");
+ pr_info("find pci class\n");
temp = pci_get_class(num, NULL);
if (!temp) {
- prk_err("failed to find pci device from class number");
+ pr_err("failed to find pci device from class number\n");
return TFAIL;
}
- prk_info("found pci device from class number");
+ pr_info("found pci device from class number\n");
pci_dev_put(temp);
return TPASS;
@@ -238,16 +237,16 @@ static int test_find_device(void)
struct pci_dev *temp = NULL;
unsigned short ven = ltp_pci.dev->vendor, dev = ltp_pci.dev->device;
- prk_info("get pci device");
+ pr_info("get pci device\n");
temp = pci_get_device(ven, dev, NULL);
if (!temp) {
- prk_err("failed to find pci device from device info");
+ pr_err("failed to find pci device from device info\n");
return TFAIL;
}
- prk_info("found pci device from device info");
+ pr_info("found pci device from device info\n");
pci_dev_put(temp);
return TPASS;
@@ -267,15 +266,15 @@ static int test_find_subsys(void)
ss_ven = ltp_pci.dev->subsystem_vendor,
ss_dev = ltp_pci.dev->subsystem_device;
- prk_info("get pci subsys");
+ pr_info("get pci subsys\n");
temp = pci_get_subsys(ven, dev, ss_ven, ss_dev, NULL);
if (!temp) {
- prk_err("failed to find pci device from subsys info");
+ pr_err("failed to find pci device from subsys info\n");
return TFAIL;
}
- prk_info("found pci device from subsys info");
+ pr_info("found pci device from subsys info\n");
pci_dev_put(temp);
return TPASS;
@@ -293,7 +292,7 @@ static int test_scan_bus(void)
int num;
struct pci_bus *bus = ltp_pci.bus;
- prk_info("scan pci bus");
+ pr_info("scan pci bus\n");
num = pci_rescan_bus(bus);
/*
@@ -301,10 +300,10 @@ static int test_scan_bus(void)
* max number of bus or less than 0
*/
if (num > MAX_BUS || num < 0) {
- prk_err("failed scan bus");
+ pr_err("failed scan bus\n");
return TFAIL;
}
- prk_info("success scan bus");
+ pr_info("success scan bus\n");
return TPASS;
}
@@ -319,18 +318,18 @@ static int test_slot_scan(void)
int ret, num = ltp_pci.dev->devfn;
struct pci_bus *bus = ltp_pci.bus;
- prk_info("scan pci slot");
+ pr_info("scan pci slot\n");
if ((num % 8) != 0)
return TPASS;
ret = pci_scan_slot(bus, num);
if (ret >= 0) {
- prk_info("found '%d' devices from scan slot", ret);
+ pr_info("found '%d' devices from scan slot\n", ret);
return TPASS;
}
- prk_err("pci_scan_slot failed");
+ pr_err("pci_scan_slot failed\n");
return TFAIL;
}
@@ -345,16 +344,16 @@ static int test_bus_add_devices(void)
{
struct pci_bus *bus = ltp_pci.bus;
- prk_info("add bus device");
+ pr_info("add bus device\n");
pci_bus_add_devices(bus);
if (bus) {
- prk_info("called bus_add_device");
+ pr_info("called bus_add_device\n");
return TPASS;
}
- prk_err("bus_add_device failed");
+ pr_err("bus_add_device failed\n");
return TFAIL;
}
@@ -369,23 +368,23 @@ static int test_match_device(void)
struct pci_driver *drv;
const struct pci_device_id *id;
- prk_info("test pci_device_id()");
+ pr_info("test pci_device_id()\n");
drv = pci_dev_driver(dev);
if (!drv) {
- prk_err("driver pointer not allocated for pci_dev");
+ pr_err("driver pointer not allocated for pci_dev\n");
return TFAIL;
}
id = pci_match_id(drv->id_table, dev);
if (id) {
- prk_info("match device success");
+ pr_info("match device success\n");
return TPASS;
}
- prk_err("failed return pci_device_id");
+ pr_err("failed return pci_device_id\n");
return TFAIL;
}
@@ -398,13 +397,13 @@ static int test_match_device(void)
*/
static int test_reg_driver(void)
{
- prk_info("test pci_register_driver");
+ pr_info("test pci_register_driver\n");
if (pci_register_driver(<p_pci_driver)) {
- prk_err("unsuccessful registering pci driver");
+ pr_err("unsuccessful registering pci driver\n");
return TFAIL;
}
pci_registered = 1;
- prk_info("success driver register");
+ pr_info("success driver register\n");
return TPASS;
}
@@ -431,12 +430,12 @@ static int test_assign_resources(void)
struct pci_dev *dev = ltp_pci.dev;
struct resource *r;
- prk_info("assign resources");
+ pr_info("assign resources\n");
for (i = 0; i < 7; ++i) {
- prk_info("assign resource #%d", i);
+ pr_info("assign resource #%d\n", i);
r = &dev->resource[i];
- prk_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx",
+ pr_info("name = %s, flags = %lu, start 0x%lx, end 0x%lx\n",
r->name, r->flags,
(unsigned long)r->start, (unsigned long)r->end);
@@ -450,14 +449,14 @@ static int test_assign_resources(void)
pci_release_resource(dev, i);
ret = pci_assign_resource(dev, i);
- prk_info("assign resource to '%d', ret '%d'", i, ret);
+ pr_info("assign resource to '%d', ret '%d'\n", i, ret);
if (ret == 0 && dev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
int attach_ret;
attach_ret = device_attach(&dev->dev);
if (attach_ret < 0)
- prk_info("device_attach failed for endpoint, ret: %d", attach_ret);
+ pr_info("device_attach failed for endpoint, ret: %d\n", attach_ret);
}
rc |= (ret < 0 && ret != -EBUSY) ? TFAIL : TPASS;
@@ -483,14 +482,14 @@ static int test_save_state(void)
{
struct pci_dev *dev = ltp_pci.dev;
- prk_info("save state");
+ pr_info("save state\n");
if (pci_save_state(dev)) {
- prk_err("failed save state");
+ pr_err("failed save state\n");
return TFAIL;
}
- prk_info("saved state of device");
+ pr_info("saved state of device\n");
return TPASS;
}
@@ -503,7 +502,7 @@ static int test_restore_state(void)
{
struct pci_dev *dev = ltp_pci.dev;
- prk_info("restore state");
+ pr_info("restore state\n");
pci_restore_state(dev);
@@ -521,12 +520,12 @@ static int test_find_cap(void)
{
struct pci_dev *dev = ltp_pci.dev;
- prk_info("find device capability");
+ pr_info("find device capability\n");
if (pci_find_capability(dev, PCI_CAP_ID_PM))
- prk_info("does not have tested capability");
+ pr_info("device has PM capability\n");
else
- prk_info("device has PM capability");
+ pr_info("does not have tested capability\n");
return TPASS;
}
@@ -546,24 +545,24 @@ static int test_read_pci_exp_config(void)
/* skip the test if device doesn't have PCIe capability */
pos = pci_pcie_cap(dev);
if (!pos) {
- prk_info("device doesn't have PCI-EXP capability");
+ pr_info("device doesn't have PCI-EXP capability\n");
return TSKIP;
}
- prk_info("read the PCI Express configuration registers at 0x%x", pos);
+ pr_info("read the PCI Express configuration registers at 0x%x\n", pos);
if (pci_read_config_dword(dev, pos, &header)) {
- prk_err("failed to read config dword");
+ pr_err("failed to read config dword\n");
return TFAIL;
}
/* comparing the value read with PCI_CAP_ID_EXP macro */
if ((header & 0x000000ff) == PCI_CAP_ID_EXP) {
- prk_info("correct val read using PCIE driver installed: 0x%x",
+ pr_info("correct val read using PCIE driver installed: 0x%x\n",
header);
return TPASS;
}
- prk_err("incorrect val read. PCIE driver/device not installed: 0x%x",
+ pr_err("incorrect val read. PCIE driver/device not installed: 0x%x\n",
header);
return TFAIL;
}
@@ -573,7 +572,7 @@ static int test_case(unsigned int cmd)
int rc = TSKIP;
if (!ltp_pci.dev || !ltp_pci.bus) {
- prk_err("device or bus not selected for test");
+ pr_err("device or bus not selected for test\n");
return TFAIL;
}
@@ -630,7 +629,7 @@ static int test_case(unsigned int cmd)
rc = test_read_pci_exp_config();
break;
default:
- prk_info("mismatching test-case command %d", cmd);
+ pr_info("mismatching test-case command %d\n", cmd);
break;
}
@@ -645,7 +644,7 @@ static int test_result;
static void device_release(struct device *dev)
{
- prk_info("device released\n");
+ pr_info("device released\n");
}
static struct device tdev = {
@@ -654,34 +653,36 @@ static struct device tdev = {
};
/* print test result to sysfs file */
-static ssize_t sys_result(struct device *dev,
+static ssize_t result_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", test_result);
}
-static DEVICE_ATTR(result, S_IRUSR, sys_result, NULL);
+static DEVICE_ATTR_RO(result);
-static ssize_t sys_tcase(struct device *dev,
+static ssize_t tcase_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int tc = 0;
- sscanf(buf, "%d", &tc);
- prk_info("test-case %d", tc);
+ if (kstrtoint(buf, 10, &tc) < 0)
+ return -EINVAL;
+ pr_info("test-case %d\n", tc);
test_result = test_case(tc);
return count;
}
-static DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase);
+static DEVICE_ATTR_WO(tcase);
-static ssize_t sys_bus_slot(struct device *dev,
+static ssize_t bus_slot_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned int res, bus, slot;
int ret;
- sscanf(buf, "%u", &res);
+ if (kstrtouint(buf, 10, &res) < 0)
+ return -EINVAL;
bus = res >> 8 & 0xFF;
slot = res & 0xFF;
@@ -692,35 +693,36 @@ static ssize_t sys_bus_slot(struct device *dev,
return count;
}
-static DEVICE_ATTR(bus_slot, S_IWUSR, NULL, sys_bus_slot);
+static DEVICE_ATTR_WO(bus_slot);
static int tpci_init_module(void)
{
int err = 0;
- prk_info("Starting module");
+
+ pr_info("Starting module\n");
err = device_register(&tdev);
if (err) {
- prk_err("Unable to register device");
+ pr_err("Unable to register device\n");
goto err0;
}
- prk_info("device registered\n");
+ pr_info("device registered\n");
err = device_create_file(&tdev, &dev_attr_result);
if (err) {
- prk_err("Can't create sysfs file 'result'");
+ pr_err("Can't create sysfs file 'result'\n");
goto err1;
}
err = device_create_file(&tdev, &dev_attr_tcase);
if (err) {
- prk_err(": Can't create sysfs file 'tc'");
+ pr_err("Can't create sysfs file 'tc'\n");
goto err2;
}
err = device_create_file(&tdev, &dev_attr_bus_slot);
if (err) {
- prk_err(": Can't create sysfs file 'bus_slot'");
+ pr_err("Can't create sysfs file 'bus_slot'\n");
goto err3;
}
@@ -739,7 +741,7 @@ module_init(tpci_init_module)
static void tpci_exit_module(void)
{
- prk_debug("Unloading module\n");
+ pr_debug("Unloading module\n");
if (ltp_pci.dev)
pci_dev_put(ltp_pci.dev);
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO b/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO
deleted file mode 100644
index fb84dfc6189f2a56240d717eab87e7ee2df86fc6..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/pci-exp-tests-HOWTO
+++ /dev/null
@@ -1,58 +0,0 @@
-HOWTO --> PCI-Express test scripts for LTP
- Amit Khanna amit.khanna@intel.com
- 08/20/2004
-
-1. About this HOWTO
-
-This document describes the addition of PCI-Express test cases to the existing LTP project.
-These test cases/scripts will enhance the LTP's capability to test PCI-Express devices/drivers.
-
-2. Copyright (c) Intel Corporation, 2004
-
-3. What is this patch doing?
-
-a. A function "test_find_pci_exp_cap" has been added to the tpci.c file of LTP project.
- (\ltp\testcases\kernel\device-drivers\pci\tpci\tpci.c)
- This function makes a call to pci_find_capability, which will determine if a device
- has PCI-Express capability. A PCI Express device function indicates PCI-Express support
- by implementing the PCI-Express capability structure in its capability list.
-
-b. A function "test_read_pci_exp_config" has been added to the tpci.c file of LTP project.
- This function calls "pci_config_read" and determines if the PCI-Express enhanced config
- space of the device can be read successfully or not.
-
- "pci_config_read" function here reads the Advanced Error Reporting CAP-ID register located
- at the PCI-Express enhanced config space address 0x100. The value of this register is a READ-ONLY
- value which is constant on all the PCI-Express devices. If the value read from this register matches with the
- defined macro AER_CAP_ID_VALUE(in tpci.h) that means that PCI-Express driver is accessing
- the enhanced config space SUCCESSFULLY.
-
-c. A user space function 'ki_generic()" is already available in user_tpci.c file of LTP project,
- (\ltp\testcases\kernel\device-drivers\pci\user_tpci\user_tpci.c) which will drive the kernel
- module tpci to test various pci and pci-express functions (defined & prototyped in tpci.c).
-
-
-4. Including PCI-Express support into the kernel
-
-By default, the kernel may not enable PCI-Express feature. A kernel
-configuration option must be selected to enable PCI-Express support.
-
-To include PCI-Express support into the kernel requires users to enable PCI-Access mode with
-"Any" or "MMCFG" in the "General Setup" menu in the kernel configuration menu.
-
-5. FAQ
-
-Q1. Are there any limitations on using this patch?
-
-A1. If the device supports PCI-Express feature and the PCI-Express feature is enabled in the kernel,
-then only a user will be able to access the PCI-Express space.
-Even if the device doesn't support PCI-Express feature, the traditional PCI-space would still be accessible.
-
-Q2. What is this AER_CAP_ID_VALUE macro defined in tpci.h?
-
-A2. AER_CAP_ID_VALUE represents the value of Advanced Error Reporting Capability ID in the PCI Express config space.
-The default value of this is always same for all PCI-Express devices. i.e. 0x14011.
-In the function "test_read_pci_exp_config" in tpci.c file, it is compared with the value retrieved from a PCI-Express
-capable device. If both the values match that means that the PCI-Express driver is accessing the PCI-Express config space
-SUCCESSFULLY.
-***FINISH***
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h b/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
index f7defb29ffc781c6ce7472b9c9545189dc4ca804..7791e3ec78a957e97a8123d7776080a7ee46f9e0 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
+++ b/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
@@ -1,22 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) International Business Machines Corp., 2001
* Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
*/
+#ifndef LTP_TPCI_H
+#define LTP_TPCI_H
+
#define PCI_DEVICE_NAME "ltp_tpci"
#define MAX_DEVFN 256
#define MAX_BUS 256
@@ -41,3 +32,5 @@ enum PCI_TCASES {
PCI_EXP_CAP_CONFIG,
PCI_TCASES_NUM,
};
+
+#endif
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 4+ messages in thread* [LTP] [PATCH v2 2/2] tpci: refactor test using new API
2026-08-06 8:10 [LTP] [PATCH v2 0/2] tcpi refactoring Andrea Cervesato
2026-08-06 8:10 ` [LTP] [PATCH v2 1/2] tpci: refactor kernel module Andrea Cervesato
@ 2026-08-06 8:10 ` Andrea Cervesato
1 sibling, 0 replies; 4+ messages in thread
From: Andrea Cervesato @ 2026-08-06 8:10 UTC (permalink / raw)
To: Linux Test Project
From: Andrea Cervesato <andrea.cervesato@suse.com>
Merge kernel module with the current test inside the same folder and
refactor tpci test using new API.
Now test has a -d option to select device for operating destructive
tests on target.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
.../pci/{tpci_kernel => tpci}/.gitignore | 3 +-
testcases/kernel/device-drivers/pci/tpci/Makefile | 22 +++
.../pci/{tpci_kernel => tpci}/ltp_tpci.c | 4 +-
testcases/kernel/device-drivers/pci/tpci/tpci.c | 166 +++++++++++++++++++++
.../pci/{tpci_kernel => tpci}/tpci.h | 0
.../kernel/device-drivers/pci/tpci_kernel/Makefile | 35 -----
.../kernel/device-drivers/pci/tpci_user/.gitignore | 1 -
.../kernel/device-drivers/pci/tpci_user/Makefile | 20 ---
.../kernel/device-drivers/pci/tpci_user/tpci.c | 115 --------------
9 files changed, 192 insertions(+), 174 deletions(-)
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore b/testcases/kernel/device-drivers/pci/tpci/.gitignore
similarity index 76%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore
rename to testcases/kernel/device-drivers/pci/tpci/.gitignore
index ed4712e3adc194b8921e4daba28f8f5c9a8f94df..ec0d18ab921bf6a33e6495a596c1b19b48bbc66d 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/.gitignore
+++ b/testcases/kernel/device-drivers/pci/tpci/.gitignore
@@ -1,3 +1,4 @@
+/tpci
/ltp_tpci.ko
/*.mod.c
/modules.order
@@ -5,4 +6,4 @@
/.*.ko
/.*.cmd
/Module.symvers
-modules.livepatch
+/modules.livepatch
diff --git a/testcases/kernel/device-drivers/pci/tpci/Makefile b/testcases/kernel/device-drivers/pci/tpci/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ae80dec86e4731df3d0d994c21bf8cf87ceaf767
--- /dev/null
+++ b/testcases/kernel/device-drivers/pci/tpci/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+
+ifneq ($(KERNELRELEASE),)
+
+obj-m := ltp_tpci.o
+
+else
+
+top_srcdir ?= ../../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+REQ_VERSION_MAJOR := 2
+REQ_VERSION_PATCH := 6
+
+MAKE_TARGETS := tpci ltp_tpci.ko
+
+include $(top_srcdir)/include/mk/module.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
+
+endif
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c b/testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
similarity index 99%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
rename to testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
index 033ac1f0008e358d1afd0240bf1a9855ec32e1fd..1a7a09661d2ad42d4bfec8dc53dce5ec34b30ff6 100644
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/ltp_tpci.c
+++ b/testcases/kernel/device-drivers/pci/tpci/ltp_tpci.c
@@ -12,8 +12,8 @@
* driven through various sysfs interactions in a user-space program.
*
* For the functions of this module to work correctly, there must be a
- * PCI / PCI-Express device somewhere in the system. The tests do not need
- * a specific device; the first PCI device available will be grabbed.
+ * PCI / PCI-Express device somewhere in the system. The user-space test
+ * selects each device through the bus_slot sysfs file.
*
* The following test cases can be called from user-space:
*
diff --git a/testcases/kernel/device-drivers/pci/tpci/tpci.c b/testcases/kernel/device-drivers/pci/tpci/tpci.c
new file mode 100644
index 0000000000000000000000000000000000000000..73f83f5cfc94dd30715de514890228c06cdb0b59
--- /dev/null
+++ b/testcases/kernel/device-drivers/pci/tpci/tpci.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
+ * Author: Alexey Kodanev <alexey.kodanev@oracle.com>
+ * Copyright (C) 2026 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
+
+/*\
+ * Test various PCI and PCI-Express APIs using the ltp_tpci.ko kernel module.
+ *
+ * [Algorithm]
+ *
+ * - Loads the ltp_tpci.ko kernel module.
+ * - Iterates over all possible PCI buses (0-255) and slots (0-255).
+ * - Attempts to select each device by writing to the module's bus_slot sysfs file.
+ * - For each existing device, executes the available test cases.
+ * Safe test cases are executed on all devices.
+ * Destructive test cases are only executed on a target device specified via -d.
+ * - Reads the result from the result sysfs file and reports it using tst_res().
+ */
+
+#include "tst_test.h"
+#include "tst_module.h"
+#include "tpci.h"
+
+#define MODULE_NAME PCI_DEVICE_NAME ".ko"
+#define DEV_RESULT "/sys/devices/" PCI_DEVICE_NAME "/result"
+#define DEV_TCASE "/sys/devices/" PCI_DEVICE_NAME "/tcase"
+#define DEV_BUSSLOT "/sys/devices/" PCI_DEVICE_NAME "/bus_slot"
+
+static int module_loaded;
+static int devices_found;
+static char *target_device;
+static unsigned int target_bus;
+static unsigned int target_devfn;
+
+static int is_destructive_test(int tc)
+{
+ switch (tc) {
+ case FIND_BUS:
+ case FIND_CLASS:
+ case FIND_DEVICE:
+ case FIND_SUBSYS:
+ case MATCH_DEVICE:
+ case FIND_CAP:
+ case PCI_EXP_CAP_CONFIG:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+static void run_pci_testcases(const unsigned int bus, const unsigned int slot)
+{
+ int res;
+ int is_target = 0;
+
+ if (target_device && bus == target_bus && slot == target_devfn)
+ is_target = 1;
+
+ for (int i = 0; i < PCI_TCASES_NUM; ++i) {
+ if (i == PCI_DISABLE)
+ continue;
+
+ if (!is_target && is_destructive_test(i))
+ continue;
+
+ SAFE_FILE_PRINTF(DEV_TCASE, "%d", i);
+ SAFE_FILE_SCANF(DEV_RESULT, "%d", &res);
+
+ switch (res) {
+ case 0:
+ tst_res(TPASS, "PCI bus %02x slot %02x : Test-case '%d'",
+ bus, slot, i);
+ break;
+ case 1:
+ tst_res(TFAIL, "PCI bus %02x slot %02x : Test-case '%d'",
+ bus, slot, i);
+ break;
+ case 32:
+ tst_res(TCONF, "PCI bus %02x slot %02x : Test-case '%d'",
+ bus, slot, i);
+ break;
+ default:
+ tst_brk(TBROK, "unexpected result code %d from kernel module",
+ res);
+ }
+ }
+}
+
+static void run(void)
+{
+ char buf[16];
+ int fd, count;
+ int target_found = 0;
+
+ devices_found = 0;
+
+ for (int i = 0; i < MAX_BUS; ++i) {
+ for (int j = 0; j < MAX_DEVFN; ++j) {
+ /* set pci device for the test */
+ fd = SAFE_OPEN(DEV_BUSSLOT, O_WRONLY);
+ count = snprintf(buf, sizeof(buf), "%u", i << 8 | j);
+
+ if (write(fd, buf, count) < 0) {
+ if (errno == ENODEV) {
+ SAFE_CLOSE(fd);
+ continue;
+ }
+ SAFE_CLOSE(fd);
+ tst_brk(TBROK | TERRNO, "write to '%s' failed", DEV_BUSSLOT);
+ }
+ SAFE_CLOSE(fd);
+
+ if (target_device && (unsigned int)i == target_bus && (unsigned int)j == target_devfn)
+ target_found = 1;
+
+ devices_found++;
+ run_pci_testcases(i, j);
+ }
+ }
+
+ if (!devices_found)
+ tst_brk(TCONF, "no PCI device found on the system");
+
+ if (target_device && !target_found)
+ tst_brk(TCONF, "target PCI device %02x:%02x not found", target_bus, target_devfn);
+}
+
+static void cleanup(void)
+{
+ if (module_loaded)
+ tst_module_unload(MODULE_NAME);
+}
+
+static void setup(void)
+{
+ if (target_device) {
+ char tail;
+
+ if (sscanf(target_device, "%x:%x%c", &target_bus, &target_devfn, &tail) != 2 ||
+ target_bus > 0xff || target_devfn > 0xff) {
+ tst_brk(TBROK, "Invalid PCI device '%s', expected bus:devfn",
+ target_device);
+ }
+ }
+
+ tst_requires_module_signature_disabled();
+
+ if (tst_lockdown_enabled() > 0 || tst_secureboot_enabled() > 0)
+ tst_brk(TCONF, "Cannot load unsigned modules in Lockdown/Secure Boot");
+
+ tst_module_load(MODULE_NAME, NULL);
+ module_loaded = 1;
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .needs_root = 1,
+ .options = (struct tst_option[]) {
+ {"d:", &target_device, "Target PCI device for destructive tests (e.g. 00:28)"},
+ {}
+ },
+};
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h b/testcases/kernel/device-drivers/pci/tpci/tpci.h
similarity index 100%
rename from testcases/kernel/device-drivers/pci/tpci_kernel/tpci.h
rename to testcases/kernel/device-drivers/pci/tpci/tpci.h
diff --git a/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile b/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile
deleted file mode 100644
index 6e1284d6cf53f078b610f175f2b2d899e6de8be5..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_kernel/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-ifneq ($(KERNELRELEASE),)
-
-obj-m := ltp_tpci.o
-
-else
-
-top_srcdir ?= ../../../../..
-
-include $(top_srcdir)/include/mk/env_pre.mk
-
-REQ_VERSION_MAJOR := 2
-REQ_VERSION_PATCH := 6
-
-MAKE_TARGETS := ltp_tpci.ko
-
-include $(top_srcdir)/include/mk/module.mk
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
-
-endif
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/.gitignore b/testcases/kernel/device-drivers/pci/tpci_user/.gitignore
deleted file mode 100644
index b1817e5fba323c996651324b0879359fd941a43a..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/tpci
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/Makefile b/testcases/kernel/device-drivers/pci/tpci_user/Makefile
deleted file mode 100644
index 6ba346520e199cfe1673548179684c5c606e6e4b..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-top_srcdir ?= ../../../../..
-
-include $(top_srcdir)/include/mk/testcases.mk
-include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/device-drivers/pci/tpci_user/tpci.c b/testcases/kernel/device-drivers/pci/tpci_user/tpci.c
deleted file mode 100644
index 687d2a62b0bccc2fa84bb401b61f7e467a630a41..0000000000000000000000000000000000000000
--- a/testcases/kernel/device-drivers/pci/tpci_user/tpci.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Alexey Kodanev <alexey.kodanev@oracle.com>
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "test.h"
-#include "tso_safe_macros.h"
-#include "tso_module.h"
-#include "tst_security.h"
-
-#include "../tpci_kernel/tpci.h"
-
-char *TCID = "test_pci";
-int TST_TOTAL = PCI_TCASES_NUM;
-
-static const char module_name[] = PCI_DEVICE_NAME ".ko";
-static const char dev_result[] = "/sys/devices/" PCI_DEVICE_NAME "/result";
-static const char dev_tcase[] = "/sys/devices/" PCI_DEVICE_NAME "/tcase";
-static const char dev_busslot[] = "/sys/devices/" PCI_DEVICE_NAME "/bus_slot";
-static int module_loaded;
-
-static void cleanup(void)
-{
- if (module_loaded)
- tst_module_unload(NULL, module_name);
-}
-
-void setup(void)
-{
- tst_require_root();
- tst_sig(FORK, DEF_HANDLER, cleanup);
- tst_requires_module_signature_disabled();
- if (tst_lockdown_enabled() > 0 || tst_secureboot_enabled() > 0)
- tst_brkm(TCONF, NULL, "Cannot load unsigned modules in Lockdown/Secure Boot");
-}
-
-static void run_pci_testcases(int bus, int slot)
-{
- int i, res;
- for (i = 0; i < TST_TOTAL; ++i) {
- /* skip pci disable test-case, it is manual */
- if (i == PCI_DISABLE)
- continue;
-
- SAFE_FILE_PRINTF(cleanup, dev_tcase, "%d", i);
- SAFE_FILE_SCANF(cleanup, dev_result, "%d", &res);
-
- tst_resm(res, "PCI bus %02x slot %02x : Test-case '%d'",
- bus, slot, i);
- }
-}
-
-static void test_run(void)
-{
- tst_module_load(cleanup, module_name, NULL);
- module_loaded = 1;
-
- char buf[6];
- int i, j, fd, count;
-
- for (i = 0; i < MAX_BUS; ++i) {
- for (j = 0; j < MAX_DEVFN; ++j) {
- /* set pci device for the test */
- fd = SAFE_OPEN(cleanup, dev_busslot, O_WRONLY);
- count = snprintf(buf, 6, "%u", i << 8 | j);
- errno = 0;
- if (write(fd, buf, count) < 0) {
- if (errno == ENODEV) {
- SAFE_CLOSE(cleanup, fd);
- continue;
- }
- tst_brkm(TBROK | TERRNO, cleanup,
- "write to '%s' failed", dev_busslot);
- }
- SAFE_CLOSE(cleanup, fd);
-
- run_pci_testcases(i, j);
-
- }
- }
-}
-
-int main(void)
-{
- setup();
-
- test_run();
-
- cleanup();
-
- tst_exit();
-}
--
2.51.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 4+ messages in thread