Especially for devices that are not bound to any driver. Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- tests/virpcimock.c | 3 + tests/virpcitest.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 1 deletion(-) diff --git a/tests/virpcimock.c b/tests/virpcimock.c index bf56143..f8ea9c7 100644 --- a/tests/virpcimock.c +++ b/tests/virpcimock.c @@ -809,6 +809,9 @@ init_env(void) MAKE_PCI_DEVICE("0005:90:01.0", 0x1033, 0x0035); MAKE_PCI_DEVICE("0005:90:01.1", 0x1033, 0x0035); MAKE_PCI_DEVICE("0005:90:01.2", 0x1033, 0x00e0); + MAKE_PCI_DEVICE("0000:0a:01.0", 0x8086, 0x0047); + MAKE_PCI_DEVICE("0000:0a:02.0", 0x8286, 0x0048); + MAKE_PCI_DEVICE("0000:0a:03.0", 0x8386, 0x0048); } diff --git a/tests/virpcitest.c b/tests/virpcitest.c index e96d7c0..848014d 100644 --- a/tests/virpcitest.c +++ b/tests/virpcitest.c @@ -34,6 +34,30 @@ # define VIR_FROM_THIS VIR_FROM_NONE static int +testVirPCIDeviceCheckDriver(virPCIDevicePtr dev, const char *expected) +{ + char *path = NULL; + char *driver = NULL; + int ret = -1; + + if (virPCIDeviceGetDriverPathAndName(dev, &path, &driver) < 0) + goto cleanup; + + if (STRNEQ_NULLABLE(driver, expected)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "PCI device %s driver mismatch: %s, expecting %s", + virPCIDeviceGetName(dev), driver, expected); + goto cleanup; + } + + ret = 0; +cleanup: + VIR_FREE(path); + VIR_FREE(driver); + return ret; +} + +static int testVirPCIDeviceNew(const void *opaque ATTRIBUTE_UNUSED) { int ret = -1; @@ -89,6 +113,9 @@ testVirPCIDeviceDetach(const void *oaque ATTRIBUTE_UNUSED) if (virPCIDeviceDetach(dev[i], activeDevs, inactiveDevs) < 0) goto cleanup; + if (testVirPCIDeviceCheckDriver(dev[i], "pci-stub") < 0) + goto cleanup; + CHECK_LIST_COUNT(activeDevs, 0); CHECK_LIST_COUNT(inactiveDevs, i + 1); } @@ -188,6 +215,7 @@ struct testPCIDevData { unsigned int bus; unsigned int slot; unsigned int function; + const char *driver; }; static int @@ -208,6 +236,88 @@ cleanup: return ret; } +static int +testVirPCIDeviceDetachSingle(const void *opaque) +{ + const struct testPCIDevData *data = opaque; + int ret = -1; + virPCIDevicePtr dev; + + dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function); + if (!dev) + goto cleanup; + + if (virPCIDeviceSetStubDriver(dev, "pci-stub") < 0 || + virPCIDeviceDetach(dev, NULL, NULL) < 0) + goto cleanup; + + ret = 0; +cleanup: + virPCIDeviceFree(dev); + return ret; +} + +static int +testVirPCIDeviceReattachSingle(const void *opaque) +{ + const struct testPCIDevData *data = opaque; + int ret = -1; + virPCIDevicePtr dev; + + dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function); + if (!dev) + goto cleanup; + + virPCIDeviceReattachInit(dev); + if (virPCIDeviceReattach(dev, NULL, NULL) < 0) + goto cleanup; + + ret = 0; +cleanup: + virPCIDeviceFree(dev); + return ret; +} + +static int +testVirPCIDeviceCheckDriverTest(const void *opaque) +{ + const struct testPCIDevData *data = opaque; + int ret = -1; + virPCIDevicePtr dev; + + dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function); + if (!dev) + goto cleanup; + + if (testVirPCIDeviceCheckDriver(dev, data->driver) < 0) + goto cleanup; + + ret = 0; +cleanup: + virPCIDeviceFree(dev); + return ret; +} + +static int +testVirPCIDeviceUnbind(const void *opaque) +{ + const struct testPCIDevData *data = opaque; + int ret = -1; + virPCIDevicePtr dev; + + dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function); + if (!dev) + goto cleanup; + + if (virPCIDeviceUnbind(dev, false) < 0) + goto cleanup; + + ret = 0; +cleanup: + virPCIDeviceFree(dev); + return ret; +} + # define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX" static int @@ -236,7 +346,9 @@ mymain(void) # define DO_TEST_PCI(fnc, domain, bus, slot, function) \ do { \ - struct testPCIDevData data = { domain, bus, slot, function }; \ + struct testPCIDevData data = { \ + domain, bus, slot, function, NULL \ + }; \ char *label = NULL; \ if (virAsprintf(&label, "%s(%04x:%02x:%02x.%x)", \ #fnc, domain, bus, slot, function) < 0) { \ @@ -248,6 +360,28 @@ mymain(void) VIR_FREE(label); \ } while (0) +# define DO_TEST_PCI_DRIVER(domain, bus, slot, function, driver) \ + do { \ + struct testPCIDevData data = { \ + domain, bus, slot, function, driver \ + }; \ + char *label = NULL; \ + if (virAsprintf(&label, "PCI driver %04x:%02x:%02x.%x is %s", \ + domain, bus, slot, function, \ + NULLSTR(driver)) < 0) { \ + ret = -1; \ + break; \ + } \ + if (virtTestRun(label, testVirPCIDeviceCheckDriverTest, \ + &data) < 0) \ + ret = -1; \ + VIR_FREE(label); \ + } while (0) + + /* Changes made to individual devices are persistent and the + * tests often rely on the state set by previous tests. + */ + DO_TEST(testVirPCIDeviceNew); DO_TEST(testVirPCIDeviceDetach); DO_TEST(testVirPCIDeviceReset); @@ -255,6 +389,27 @@ mymain(void) DO_TEST_PCI(testVirPCIDeviceIsAssignable, 5, 0x90, 1, 0); DO_TEST_PCI(testVirPCIDeviceIsAssignable, 1, 1, 0, 0); + /* Reattach a device already bound to non-stub a driver */ + DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915"); + DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 1, 0); + DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915"); + + /* Reattach an unbound device */ + DO_TEST_PCI(testVirPCIDeviceUnbind, 0, 0x0a, 1, 0); + DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, NULL); + DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 1, 0); + DO_TEST_PCI_DRIVER(0, 0x0a, 1, 0, "i915"); + + /* Detach an unbound device */ + DO_TEST_PCI_DRIVER(0, 0x0a, 2, 0, NULL); + DO_TEST_PCI(testVirPCIDeviceDetachSingle, 0, 0x0a, 2, 0); + DO_TEST_PCI_DRIVER(0, 0x0a, 2, 0, "pci-stub"); + + /* Reattach an unknown unbound device */ + DO_TEST_PCI_DRIVER(0, 0x0a, 3, 0, NULL); + DO_TEST_PCI(testVirPCIDeviceReattachSingle, 0, 0x0a, 3, 0); + DO_TEST_PCI_DRIVER(0, 0x0a, 3, 0, NULL); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakesysfsdir); -- 1.8.5.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list