From 4ba47234f394b41a374b666ea891885b3f4bcdff Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Fri, 25 Sep 2015 09:13:02 -0700 Subject: [PATCH] Add pci_device_has_non_null_driver(). This helps enable FreeBSD, where pciaccess pci_device_has_kernel_driver() is not functional. The function will return 0 if there is no driver attached, or the Linux uio or FreeBSD nic_uio driver is attached. It will return 1 otherwise. Signed-off-by: Jim Harris Change-Id: I0921e61c9040b1e0411b5dc40b36fc7f2721c8c5 --- examples/nvme/identify/identify.c | 5 +-- examples/nvme/perf/perf.c | 5 +-- include/spdk/pci.h | 1 + lib/util/pci.c | 63 +++++++++++++++++++++++++++++++ test/lib/nvme/aer/aer.c | 5 +-- 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/examples/nvme/identify/identify.c b/examples/nvme/identify/identify.c index d09536d460..04d9620c8d 100644 --- a/examples/nvme/identify/identify.c +++ b/examples/nvme/identify/identify.c @@ -467,9 +467,8 @@ int main(int argc, char **argv) while ((pci_dev = pci_device_next(pci_dev_iter))) { struct nvme_controller *ctrlr; - if (pci_device_has_kernel_driver(pci_dev) && - !pci_device_has_uio_driver(pci_dev)) { - fprintf(stderr, "non-uio kernel driver attached to nvme\n"); + if (pci_device_has_non_null_driver(pci_dev)) { + fprintf(stderr, "non-null kernel driver attached to nvme\n"); fprintf(stderr, " controller at pci bdf %d:%d:%d\n", pci_dev->bus, pci_dev->dev, pci_dev->func); fprintf(stderr, " skipping...\n"); diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index 4b09249557..41269724d9 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -432,9 +432,8 @@ register_controllers(void) while ((pci_dev = pci_device_next(pci_dev_iter))) { struct nvme_controller *ctrlr; - if (pci_device_has_kernel_driver(pci_dev) && - !pci_device_has_uio_driver(pci_dev)) { - fprintf(stderr, "non-uio kernel driver attached to nvme\n"); + if (pci_device_has_non_null_driver(pci_dev)) { + fprintf(stderr, "non-null kernel driver attached to nvme\n"); fprintf(stderr, " controller at pci bdf %d:%d:%d\n", pci_dev->bus, pci_dev->dev, pci_dev->func); fprintf(stderr, " skipping...\n"); diff --git a/include/spdk/pci.h b/include/spdk/pci.h index c3af859c5f..1f086bfb26 100644 --- a/include/spdk/pci.h +++ b/include/spdk/pci.h @@ -40,6 +40,7 @@ int pci_device_get_serial_number(struct pci_device *dev, char *sn, int len); int pci_device_has_uio_driver(struct pci_device *dev); +int pci_device_has_non_null_driver(struct pci_device *dev); int pci_device_unbind_kernel_driver(struct pci_device *dev); int pci_device_bind_uio_driver(struct pci_device *dev, char *driver_name); int pci_device_switch_to_uio_driver(struct pci_device *pci_dev); diff --git a/lib/util/pci.c b/lib/util/pci.c index 73970fee9b..8423e3cdf2 100644 --- a/lib/util/pci.c +++ b/lib/util/pci.c @@ -43,6 +43,10 @@ #include +#ifdef __FreeBSD__ +#include +#endif + #include "spdk/pci.h" #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" @@ -126,6 +130,65 @@ pci_device_has_uio_driver(struct pci_device *dev) return 1; } +#ifdef __FreeBSD__ +int +pci_device_has_non_null_driver(struct pci_device *dev) +{ + struct pci_conf_io configsel; + struct pci_match_conf pattern; + struct pci_conf conf; + int fd; + + memset(&pattern, 0, sizeof(pattern)); + pattern.pc_sel.pc_domain = dev->domain; + pattern.pc_sel.pc_bus = dev->bus; + pattern.pc_sel.pc_dev = dev->dev; + pattern.pc_sel.pc_func = dev->func; + pattern.flags = PCI_GETCONF_MATCH_DOMAIN | + PCI_GETCONF_MATCH_BUS | + PCI_GETCONF_MATCH_DEV | + PCI_GETCONF_MATCH_FUNC; + + memset(&configsel, 0, sizeof(configsel)); + configsel.match_buf_len = sizeof(conf); + configsel.matches = &conf; + configsel.num_patterns = 1; + configsel.pat_buf_len = sizeof(pattern); + configsel.patterns = &pattern; + + fd = open("/dev/pci", O_RDONLY, 0); + if (fd < 0) { + fprintf(stderr, "could not open /dev/pci\n"); + return -1; + } + + if (ioctl(fd, PCIOCGETCONF, &configsel) == -1) { + fprintf(stderr, "ioctl(PCIOCGETCONF) failed\n"); + close(fd); + return -1; + } + + close(fd); + + if (configsel.num_matches != 1) { + fprintf(stderr, "could not find specified device\n"); + return -1; + } + + if (conf.pd_name[0] == '\0' || !strcmp(conf.pd_name, "nic_uio")) { + return 0; + } else { + return 1; + } +} +#else +int +pci_device_has_non_null_driver(struct pci_device *dev) +{ + return pci_device_has_kernel_driver(dev) && !pci_device_has_uio_driver(dev); +} +#endif + int pci_device_unbind_kernel_driver(struct pci_device *dev) { diff --git a/test/lib/nvme/aer/aer.c b/test/lib/nvme/aer/aer.c index 5d08948b78..180f3b7a6c 100644 --- a/test/lib/nvme/aer/aer.c +++ b/test/lib/nvme/aer/aer.c @@ -225,9 +225,8 @@ int main(int argc, char **argv) while ((pci_dev = pci_device_next(pci_dev_iter))) { struct dev *dev; - if (pci_device_has_kernel_driver(pci_dev) && - !pci_device_has_uio_driver(pci_dev)) { - fprintf(stderr, "non-uio kernel driver attached to nvme\n"); + if (pci_device_has_non_null_driver(pci_dev)) { + fprintf(stderr, "non-null kernel driver attached to nvme\n"); fprintf(stderr, " controller at pci bdf %d:%d:%d\n", pci_dev->bus, pci_dev->dev, pci_dev->func); fprintf(stderr, " skipping...\n");