Add support for passing multiple device BDFs to a test via the command line. This is a prerequisite for multi-device tests. Single-device tests can continue using vfio_selftests_get_bdf(), which will continue to return argv[argc - 1] (if it is a BDF string), or the environment variable $VFIO_SELFTESTS_BDF otherwise. For multi-device tests, a new helper called vfio_selftests_get_bdfs() is introduced which will return an array of all BDFs found at the end of argv[], as well as the number of BDFs found (passed back to the caller via argument). The array of BDFs returned does not need to be freed by the caller. The environment variable VFIO_SELFTESTS_BDF continues to support only a single BDF for the time being. Signed-off-by: David Matlack --- .../selftests/vfio/lib/include/vfio_util.h | 2 + .../selftests/vfio/lib/vfio_pci_device.c | 58 +++++++++++++++---- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/vfio/lib/include/vfio_util.h b/tools/testing/selftests/vfio/lib/include/vfio_util.h index ed31606e01b7..2acf119cbedb 100644 --- a/tools/testing/selftests/vfio/lib/include/vfio_util.h +++ b/tools/testing/selftests/vfio/lib/include/vfio_util.h @@ -198,6 +198,8 @@ struct vfio_pci_device { * If BDF cannot be determined then the test will exit with KSFT_SKIP. */ const char *vfio_selftests_get_bdf(int *argc, char *argv[]); +char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs); + const char *vfio_pci_get_cdev_path(const char *bdf); extern const char *default_iommu_mode; diff --git a/tools/testing/selftests/vfio/lib/vfio_pci_device.c b/tools/testing/selftests/vfio/lib/vfio_pci_device.c index 0921b2451ba5..f2fc5a52902b 100644 --- a/tools/testing/selftests/vfio/lib/vfio_pci_device.c +++ b/tools/testing/selftests/vfio/lib/vfio_pci_device.c @@ -566,29 +566,63 @@ static bool is_bdf(const char *str) return count == 4 && length == strlen(str); } -const char *vfio_selftests_get_bdf(int *argc, char *argv[]) +static char **vfio_selftests_get_bdfs_cmdline(int *argc, char *argv[], int *nr_bdfs) { - char *bdf; + int i; + + for (i = *argc - 1; i > 0 && is_bdf(argv[i]); i--) + continue; + + i++; + *nr_bdfs = *argc - i; + *argc -= *nr_bdfs; + + return *nr_bdfs ? &argv[i] : NULL; +} - if (*argc > 1 && is_bdf(argv[*argc - 1])) - return argv[--(*argc)]; +static char **vfio_selftests_get_bdfs_env(int *argc, char *argv[], int *nr_bdfs) +{ + static char *bdf; bdf = getenv("VFIO_SELFTESTS_BDF"); - if (bdf) { - VFIO_ASSERT_TRUE(is_bdf(bdf), "Invalid BDF: %s\n", bdf); - return bdf; - } + if (!bdf) + return NULL; + + *nr_bdfs = 1; + VFIO_ASSERT_TRUE(is_bdf(bdf), "Invalid BDF: %s\n", bdf); + + return &bdf; +} + +char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs) +{ + char **bdfs; + + bdfs = vfio_selftests_get_bdfs_cmdline(argc, argv, nr_bdfs); + if (bdfs) + return bdfs; + + bdfs = vfio_selftests_get_bdfs_env(argc, argv, nr_bdfs); + if (bdfs) + return bdfs; - fprintf(stderr, "Unable to determine which device to use, skipping test.\n"); + fprintf(stderr, "Unable to determine which device(s) to use, skipping test.\n"); fprintf(stderr, "\n"); fprintf(stderr, "To pass the device address via environment variable:\n"); fprintf(stderr, "\n"); - fprintf(stderr, " export VFIO_SELFTESTS_BDF=segment:bus:device.function\n"); + fprintf(stderr, " export VFIO_SELFTESTS_BDF=\"segment:bus:device.function\"\n"); fprintf(stderr, " %s [options]\n", argv[0]); fprintf(stderr, "\n"); - fprintf(stderr, "To pass the device address via argv:\n"); + fprintf(stderr, "To pass the device address(es) via argv:\n"); fprintf(stderr, "\n"); - fprintf(stderr, " %s [options] segment:bus:device.function\n", argv[0]); + fprintf(stderr, " %s [options] segment:bus:device.function ...\n", argv[0]); fprintf(stderr, "\n"); exit(KSFT_SKIP); } + +const char *vfio_selftests_get_bdf(int *argc, char *argv[]) +{ + int nr_bdfs; + + return vfio_selftests_get_bdfs(argc, argv, &nr_bdfs)[0]; +} -- 2.51.0.710.ga91ca5db03-goog