pci: allow to override sysfs path

The SYSFS_PCI_DEVICES is a constant that makes the PCI testing
difficult as it points to an absolute path. We remove using this
constant and introducing a function pci_get_sysfs_path that gives
the same value. However, the user can pass a SYSFS_PCI_DEVICES env
variable to override the path. It is now possible to create a fake
sysfs hierarchy for testing.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
This commit is contained in:
Jan Viktorin 2016-06-13 17:07:44 +02:00 committed by Thomas Monjalon
parent ceabf73721
commit 53c3c30c11
29 changed files with 160 additions and 15 deletions

View File

@ -92,6 +92,7 @@ F: app/test/test_interrupts.c
F: app/test/test_logs.c
F: app/test/test_memcpy*
F: app/test/test_pci.c
F: app/test/test_pci_sysfs/
F: app/test/test_per_lcore.c
F: app/test/test_prefetch.c
F: app/test/test_rwlock.c

View File

@ -73,6 +73,7 @@ SRCS-y += test_resource.c
$(eval $(call linked_resource,test_resource_c,resource.c))
$(eval $(call linked_tar_resource,test_resource_tar,test_resource.c))
SRCS-y += test_pci.c
$(eval $(call linked_tar_resource,test_pci_sysfs,test_pci_sysfs))
SRCS-y += test_prefetch.c
SRCS-y += test_byteorder.c
SRCS-y += test_per_lcore.c

View File

@ -43,6 +43,7 @@
#include <rte_devargs.h>
#include "test.h"
#include "resource.h"
/* Generic maximum number of drivers to have room to allocate all drivers */
#define NUM_MAX_DRIVERS 256
@ -144,37 +145,90 @@ static void free_devargs_list(void)
}
}
/* backup real drivers (not used for testing) */
/* backup real devices & drivers (not used for testing) */
struct pci_driver_list real_pci_driver_list =
TAILQ_HEAD_INITIALIZER(real_pci_driver_list);
struct pci_device_list real_pci_device_list =
TAILQ_HEAD_INITIALIZER(real_pci_device_list);
REGISTER_LINKED_RESOURCE(test_pci_sysfs);
static int
test_pci_setup(void)
{
struct rte_pci_device *dev;
struct rte_pci_driver *dr;
const struct resource *r;
int ret;
/* Unregister original driver list */
r = resource_find("test_pci_sysfs");
TEST_ASSERT_NOT_NULL(r, "missing resource test_pci_sysfs");
ret = resource_untar(r);
TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
ret = setenv("SYSFS_PCI_DEVICES", "test_pci_sysfs/bus/pci/devices", 1);
TEST_ASSERT_SUCCESS(ret, "failed to setenv");
/* Unregister original devices & drivers lists */
while (!TAILQ_EMPTY(&pci_driver_list)) {
dr = TAILQ_FIRST(&pci_driver_list);
rte_eal_pci_unregister(dr);
TAILQ_INSERT_TAIL(&real_pci_driver_list, dr, next);
}
while (!TAILQ_EMPTY(&pci_device_list)) {
dev = TAILQ_FIRST(&pci_device_list);
TAILQ_REMOVE(&pci_device_list, dev, next);
TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
}
ret = rte_eal_pci_scan();
TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
rte_eal_pci_dump(stdout);
return 0;
}
static int
test_pci_cleanup(void)
{
struct rte_pci_device *dev;
struct rte_pci_driver *dr;
const struct resource *r;
int ret;
/* Restore original driver list */
unsetenv("SYSFS_PCI_DEVICES");
r = resource_find("test_pci_sysfs");
TEST_ASSERT_NOT_NULL(r, "missing resource test_pci_sysfs");
ret = resource_rm_by_tar(r);
TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
/*
* FIXME: there is no API in DPDK to free a rte_pci_device so we
* cannot free the devices in the right way. Let's assume that we
* don't care for tests.
*/
while (!TAILQ_EMPTY(&pci_device_list)) {
dev = TAILQ_FIRST(&pci_device_list);
TAILQ_REMOVE(&pci_device_list, dev, next);
}
/* Restore original devices & drivers lists */
while (!TAILQ_EMPTY(&real_pci_driver_list)) {
dr = TAILQ_FIRST(&real_pci_driver_list);
TAILQ_REMOVE(&real_pci_driver_list, dr, next);
rte_eal_pci_register(dr);
}
while (!TAILQ_EMPTY(&real_pci_device_list)) {
dev = TAILQ_FIRST(&real_pci_device_list);
TAILQ_REMOVE(&real_pci_device_list, dev, next);
TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
}
return 0;
}
@ -224,9 +278,37 @@ test_pci_blacklist(void)
return 0;
}
static int test_pci_sysfs(void)
{
const char *orig;
const char *newpath;
int ret;
orig = pci_get_sysfs_path();
ret = setenv("SYSFS_PCI_DEVICES", "My Documents", 1);
TEST_ASSERT_SUCCESS(ret, "Failed setenv to My Documents");
newpath = pci_get_sysfs_path();
TEST_ASSERT(!strcmp(newpath, "My Documents"),
"pci_get_sysfs_path() should return 'My Documents' "
"but gives %s", newpath);
ret = setenv("SYSFS_PCI_DEVICES", orig, 1);
TEST_ASSERT_SUCCESS(ret, "Failed setenv back to '%s'", orig);
newpath = pci_get_sysfs_path();
TEST_ASSERT(!strcmp(orig, newpath),
"pci_get_sysfs_path returned unexpected path: "
"%s (expected: %s)", newpath, orig);
return 0;
}
int
test_pci(void)
{
if (test_pci_sysfs())
return -1;
if (test_pci_setup())
return -1;

View File

@ -0,0 +1 @@
0x020000

View File

@ -0,0 +1 @@
0x10fb

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
pci:v00008086d000010FBsv00008086sd00000003bc02sc00i00

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
-1

View File

@ -0,0 +1,13 @@
0x00000000d0080000 0x00000000d00fffff 0x000000000014220c
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x000000000000e020 0x000000000000e03f 0x0000000000040101
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000d0104000 0x00000000d0107fff 0x000000000014220c
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000ab000000 0x00000000ab0fffff 0x0000000000140204
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000ab100000 0x00000000ab1fffff 0x0000000000140204
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000

View File

@ -0,0 +1 @@
0x0003

View File

@ -0,0 +1 @@
0x8086

View File

@ -0,0 +1,6 @@
DRIVER=ixgbe
PCI_CLASS=20000
PCI_ID=8086:10FB
PCI_SUBSYS_ID=8086:0003
PCI_SLOT_NAME=0000:01:00.0
MODALIAS=pci:v00008086d000010FBsv00008086sd00000003bc02sc00i00

View File

@ -0,0 +1 @@
0x8086

View File

@ -1481,7 +1481,7 @@ rte_szedata2_eth_dev_init(struct rte_eth_dev *dev)
return -EINVAL;
}
snprintf(rsc_filename, PATH_MAX,
SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/resource%u",
"%s/" PCI_PRI_FMT "/resource%u", pci_get_sysfs_path(),
pci_addr->domain, pci_addr->bus,
pci_addr->devid, pci_addr->function, PCI_RESOURCE_NUMBER);
fd = open(rsc_filename, O_RDWR);

View File

@ -179,7 +179,7 @@ legacy_virtio_has_msix(const struct rte_pci_addr *loc)
char dirname[PATH_MAX];
snprintf(dirname, sizeof(dirname),
SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/msi_irqs",
"%s/" PCI_PRI_FMT "/msi_irqs", pci_get_sysfs_path(),
loc->domain, loc->bus, loc->devid, loc->function);
d = opendir(dirname);

View File

@ -151,3 +151,10 @@ DPDK_16.04 {
rte_eal_primary_proc_alive;
} DPDK_2.2;
DPDK_16.07 {
global:
pci_get_sysfs_path;
} DPDK_16.04;

View File

@ -85,6 +85,19 @@
struct pci_driver_list pci_driver_list;
struct pci_device_list pci_device_list;
#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
const char *pci_get_sysfs_path(void)
{
const char *path = NULL;
path = getenv("SYSFS_PCI_DEVICES");
if (path == NULL)
return SYSFS_PCI_DEVICES;
return path;
}
static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)
{
struct rte_devargs *devargs;

View File

@ -91,7 +91,7 @@ extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers.
extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
/** Pathname of PCI devices directory. */
#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
const char *pci_get_sysfs_path(void);
/** Formatting string for PCI device identifier: Ex: 0000:00:01.0 */
#define PCI_PRI_FMT "%.4" PRIx16 ":%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8

View File

@ -66,8 +66,8 @@ pci_unbind_kernel_driver(struct rte_pci_device *dev)
/* open /sys/bus/pci/devices/AAAA:BB:CC.D/driver */
snprintf(filename, sizeof(filename),
SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/driver/unbind",
loc->domain, loc->bus, loc->devid, loc->function);
"%s/" PCI_PRI_FMT "/driver/unbind", pci_get_sysfs_path(),
loc->domain, loc->bus, loc->devid, loc->function);
f = fopen(filename, "w");
if (f == NULL) /* device was not bound */
@ -453,7 +453,7 @@ rte_eal_pci_scan(void)
uint16_t domain;
uint8_t bus, devid, function;
dir = opendir(SYSFS_PCI_DEVICES);
dir = opendir(pci_get_sysfs_path());
if (dir == NULL) {
RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
__func__, strerror(errno));
@ -468,8 +468,8 @@ rte_eal_pci_scan(void)
&bus, &devid, &function) != 0)
continue;
snprintf(dirname, sizeof(dirname), "%s/%s", SYSFS_PCI_DEVICES,
e->d_name);
snprintf(dirname, sizeof(dirname), "%s/%s",
pci_get_sysfs_path(), e->d_name);
if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
goto error;
}

View File

@ -161,14 +161,14 @@ pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,
* or uio:uioX */
snprintf(dirname, sizeof(dirname),
SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio",
"%s/" PCI_PRI_FMT "/uio", pci_get_sysfs_path(),
loc->domain, loc->bus, loc->devid, loc->function);
dir = opendir(dirname);
if (dir == NULL) {
/* retry with the parent directory */
snprintf(dirname, sizeof(dirname),
SYSFS_PCI_DEVICES "/" PCI_PRI_FMT,
"%s/" PCI_PRI_FMT, pci_get_sysfs_path(),
loc->domain, loc->bus, loc->devid, loc->function);
dir = opendir(dirname);
@ -319,7 +319,8 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
/* update devname for mmap */
snprintf(devname, sizeof(devname),
SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/resource%d",
"%s/" PCI_PRI_FMT "/resource%d",
pci_get_sysfs_path(),
loc->domain, loc->bus, loc->devid,
loc->function, res_idx);

View File

@ -602,7 +602,7 @@ pci_vfio_get_group_no(const char *pci_addr, int *iommu_group_no)
/* try to find out IOMMU group for this device */
snprintf(linkname, sizeof(linkname),
SYSFS_PCI_DEVICES "/%s/iommu_group", pci_addr);
"%s/%s/iommu_group", pci_get_sysfs_path(), pci_addr);
ret = readlink(linkname, filename, sizeof(filename));

View File

@ -154,3 +154,10 @@ DPDK_16.04 {
rte_eal_primary_proc_alive;
} DPDK_2.2;
DPDK_16.07 {
global:
pci_get_sysfs_path;
} DPDK_16.04;