#include <string.h>
#include <dirent.h>
-#include <sys/mman.h>
#include <rte_log.h>
#include <rte_pci.h>
-#include <rte_tailq.h>
#include <rte_eal_memconfig.h>
#include <rte_malloc.h>
#include <rte_devargs.h>
+#include <rte_memcpy.h>
-#include "rte_pci_dev_ids.h"
#include "eal_filesystem.h"
#include "eal_private.h"
#include "eal_pci_init.h"
* IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).
*/
-struct mapped_pci_res_list *pci_res_list = NULL;
-
/* unbind kernel driver for this device */
-static int
+int
pci_unbind_kernel_driver(struct rte_pci_device *dev)
{
int n;
return -1;
}
+/* Map pci device */
+int
+rte_eal_pci_map_device(struct rte_pci_device *dev)
+{
+ int ret = -1;
+
+ /* try mapping the NIC resources using VFIO if it exists */
+ switch (dev->kdrv) {
+ case RTE_KDRV_VFIO:
+#ifdef VFIO_PRESENT
+ if (pci_vfio_is_enabled())
+ ret = pci_vfio_map_resource(dev);
+#endif
+ break;
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ /* map resources for devices that use uio */
+ ret = pci_uio_map_resource(dev);
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+/* Unmap pci device */
+void
+rte_eal_pci_unmap_device(struct rte_pci_device *dev)
+{
+ /* try unmapping the NIC resources using VFIO if it exists */
+ switch (dev->kdrv) {
+ case RTE_KDRV_VFIO:
+ RTE_LOG(ERR, EAL, "Hotplug doesn't support vfio yet\n");
+ break;
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ /* unmap resources for devices that use uio */
+ pci_uio_unmap_resource(dev);
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ break;
+ }
+}
+
void *
pci_find_max_end_va(void)
{
return RTE_PTR_ADD(last->addr, last->len);
}
-
-/* map a particular resource from a file */
-void *
-pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size,
- int additional_flags)
-{
- void *mapaddr;
-
- /* Map the PCI memory resource of device */
- mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,
- MAP_SHARED | additional_flags, fd, offset);
- if (mapaddr == MAP_FAILED) {
- RTE_LOG(ERR, EAL, "%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\n",
- __func__, fd, requested_addr,
- (unsigned long)size, (unsigned long)offset,
- strerror(errno), mapaddr);
- } else {
- RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", mapaddr);
- }
-
- return mapaddr;
-}
-
/* parse the "resource" sysfs file */
static int
pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
return -1;
}
-/* Compare two PCI device addresses. */
-static int
-pci_addr_comparison(struct rte_pci_addr *addr, struct rte_pci_addr *addr2)
-{
- uint64_t dev_addr = (addr->domain << 24) + (addr->bus << 16) + (addr->devid << 8) + addr->function;
- uint64_t dev_addr2 = (addr2->domain << 24) + (addr2->bus << 16) + (addr2->devid << 8) + addr2->function;
-
- if (dev_addr > dev_addr2)
- return 1;
- else
- return 0;
-}
-
-
/* Scan one pci sysfs entry, and fill the devices list from it. */
static int
pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
snprintf(filename, sizeof(filename), "%s/numa_node",
dirname);
if (access(filename, R_OK) != 0) {
- /* if no NUMA support just set node to -1 */
- dev->numa_node = -1;
+ /* if no NUMA support, set default to 0 */
+ dev->numa_node = 0;
} else {
if (eal_parse_sysfs_value(filename, &tmp) < 0) {
free(dev);
/* parse driver */
snprintf(filename, sizeof(filename), "%s/driver", dirname);
ret = pci_get_kernel_driver_by_path(filename, driver);
+ if (ret < 0) {
+ RTE_LOG(ERR, EAL, "Fail to get kernel driver\n");
+ free(dev);
+ return -1;
+ }
+
if (!ret) {
if (!strcmp(driver, "vfio-pci"))
- dev->pt_driver = RTE_PT_VFIO;
+ dev->kdrv = RTE_KDRV_VFIO;
else if (!strcmp(driver, "igb_uio"))
- dev->pt_driver = RTE_PT_IGB_UIO;
+ dev->kdrv = RTE_KDRV_IGB_UIO;
else if (!strcmp(driver, "uio_pci_generic"))
- dev->pt_driver = RTE_PT_UIO_GENERIC;
+ dev->kdrv = RTE_KDRV_UIO_GENERIC;
else
- dev->pt_driver = RTE_PT_UNKNOWN;
- } else if (ret < 0) {
- RTE_LOG(ERR, EAL, "Fail to get kernel driver\n");
- free(dev);
- return -1;
+ dev->kdrv = RTE_KDRV_UNKNOWN;
} else
- dev->pt_driver = RTE_PT_UNKNOWN;
+ dev->kdrv = RTE_KDRV_NONE;
/* device is valid, add in list (sorted) */
if (TAILQ_EMPTY(&pci_device_list)) {
TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
- }
- else {
- struct rte_pci_device *dev2 = NULL;
+ } else {
+ struct rte_pci_device *dev2;
+ int ret;
TAILQ_FOREACH(dev2, &pci_device_list, next) {
- if (pci_addr_comparison(&dev->addr, &dev2->addr))
+ ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
+ if (ret > 0)
continue;
- else {
+
+ if (ret < 0) {
TAILQ_INSERT_BEFORE(dev2, dev, next);
- return 0;
+ } else { /* already registered */
+ dev2->kdrv = dev->kdrv;
+ dev2->max_vfs = dev->max_vfs;
+ memmove(dev2->mem_resource, dev->mem_resource,
+ sizeof(dev->mem_resource));
+ free(dev);
}
+ return 0;
}
TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
}
* Scan the content of the PCI bus, and the devices in the devices
* list
*/
-static int
-pci_scan(void)
+int
+rte_eal_pci_scan(void)
{
struct dirent *e;
DIR *dir;
}
#ifdef RTE_PCI_CONFIG
-static int
-pci_config_extended_tag(struct rte_pci_device *dev)
+/*
+ * It is deprecated, all its configurations have been moved into
+ * each PMD respectively.
+ */
+void
+pci_config_space_set(__rte_unused struct rte_pci_device *dev)
{
- struct rte_pci_addr *loc = &dev->addr;
- char filename[PATH_MAX];
- char buf[BUFSIZ];
- FILE *f;
+ RTE_LOG(DEBUG, EAL, "Nothing here, as it is deprecated\n");
+}
+#endif
- /* not configured, let it as is */
- if (strncmp(RTE_PCI_EXTENDED_TAG, "on", 2) != 0 &&
- strncmp(RTE_PCI_EXTENDED_TAG, "off", 3) != 0)
- return 0;
+/* Read PCI config space. */
+int rte_eal_pci_read_config(const struct rte_pci_device *device,
+ void *buf, size_t len, off_t offset)
+{
+ const struct rte_intr_handle *intr_handle = &device->intr_handle;
- snprintf(filename, sizeof(filename),
- SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/" "extended_tag",
- loc->domain, loc->bus, loc->devid, loc->function);
- f = fopen(filename, "rw+");
- if (!f)
- return -1;
+ switch (intr_handle->type) {
+ case RTE_INTR_HANDLE_UIO:
+ case RTE_INTR_HANDLE_UIO_INTX:
+ return pci_uio_read_config(intr_handle, buf, len, offset);
- fgets(buf, sizeof(buf), f);
- if (strncmp(RTE_PCI_EXTENDED_TAG, "on", 2) == 0) {
- /* enable Extended Tag*/
- if (strncmp(buf, "on", 2) != 0) {
- fseek(f, 0, SEEK_SET);
- fputs("on", f);
- }
- } else {
- /* disable Extended Tag */
- if (strncmp(buf, "off", 3) != 0) {
- fseek(f, 0, SEEK_SET);
- fputs("off", f);
- }
+#ifdef VFIO_PRESENT
+ case RTE_INTR_HANDLE_VFIO_MSIX:
+ case RTE_INTR_HANDLE_VFIO_MSI:
+ case RTE_INTR_HANDLE_VFIO_LEGACY:
+ return pci_vfio_read_config(intr_handle, buf, len, offset);
+#endif
+ default:
+ RTE_LOG(ERR, EAL,
+ "Unknown handle type of fd %d\n",
+ intr_handle->fd);
+ return -1;
}
- fclose(f);
+}
- return 0;
+/* Write PCI config space. */
+int rte_eal_pci_write_config(const struct rte_pci_device *device,
+ const void *buf, size_t len, off_t offset)
+{
+ const struct rte_intr_handle *intr_handle = &device->intr_handle;
+
+ switch (intr_handle->type) {
+ case RTE_INTR_HANDLE_UIO:
+ case RTE_INTR_HANDLE_UIO_INTX:
+ return pci_uio_write_config(intr_handle, buf, len, offset);
+
+#ifdef VFIO_PRESENT
+ case RTE_INTR_HANDLE_VFIO_MSIX:
+ case RTE_INTR_HANDLE_VFIO_MSI:
+ case RTE_INTR_HANDLE_VFIO_LEGACY:
+ return pci_vfio_write_config(intr_handle, buf, len, offset);
+#endif
+ default:
+ RTE_LOG(ERR, EAL,
+ "Unknown handle type of fd %d\n",
+ intr_handle->fd);
+ return -1;
+ }
}
+#if defined(RTE_ARCH_X86)
static int
-pci_config_max_read_request_size(struct rte_pci_device *dev)
+pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused,
+ struct rte_pci_ioport *p)
{
- struct rte_pci_addr *loc = &dev->addr;
- char filename[PATH_MAX];
- char buf[BUFSIZ], param[BUFSIZ];
- FILE *f;
- /* size can be 128, 256, 512, 1024, 2048, 4096 */
- uint32_t max_size = RTE_PCI_MAX_READ_REQUEST_SIZE;
+ uint16_t start, end;
+ FILE *fp;
+ char *line = NULL;
+ char pci_id[16];
+ int found = 0;
+ size_t linesz;
+
+ snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT,
+ dev->addr.domain, dev->addr.bus,
+ dev->addr.devid, dev->addr.function);
+
+ fp = fopen("/proc/ioports", "r");
+ if (fp == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): can't open ioports\n", __func__);
+ return -1;
+ }
- /* not configured, let it as is */
- if (!max_size)
- return 0;
+ while (getdelim(&line, &linesz, '\n', fp) > 0) {
+ char *ptr = line;
+ char *left;
+ int n;
- snprintf(filename, sizeof(filename),
- SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/" "max_read_request_size",
- loc->domain, loc->bus, loc->devid, loc->function);
- f = fopen(filename, "rw+");
- if (!f)
- return -1;
+ n = strcspn(ptr, ":");
+ ptr[n] = 0;
+ left = &ptr[n + 1];
- fgets(buf, sizeof(buf), f);
- snprintf(param, sizeof(param), "%d", max_size);
+ while (*left && isspace(*left))
+ left++;
- /* check if the size to be set is the same as current */
- if (strcmp(buf, param) == 0) {
- fclose(f);
- return 0;
+ if (!strncmp(left, pci_id, strlen(pci_id))) {
+ found = 1;
+
+ while (*ptr && isspace(*ptr))
+ ptr++;
+
+ sscanf(ptr, "%04hx-%04hx", &start, &end);
+
+ break;
+ }
}
- fseek(f, 0, SEEK_SET);
- fputs(param, f);
- fclose(f);
- return 0;
-}
+ free(line);
+ fclose(fp);
-static void
-pci_config_space_set(struct rte_pci_device *dev)
-{
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
- return;
+ if (!found)
+ return -1;
- /* configure extended tag */
- pci_config_extended_tag(dev);
+ dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
+ p->base = start;
+ RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%x\n", start);
- /* configure max read request size */
- pci_config_max_read_request_size(dev);
+ return 0;
}
#endif
-static int
-pci_map_device(struct rte_pci_device *dev)
+int
+rte_eal_pci_ioport_map(struct rte_pci_device *dev, int bar,
+ struct rte_pci_ioport *p)
{
int ret = -1;
- /* try mapping the NIC resources using VFIO if it exists */
- switch (dev->pt_driver) {
- case RTE_PT_VFIO:
+ switch (dev->kdrv) {
#ifdef VFIO_PRESENT
+ case RTE_KDRV_VFIO:
if (pci_vfio_is_enabled())
- ret = pci_vfio_map_resource(dev);
-#endif
+ ret = pci_vfio_ioport_map(dev, bar, p);
break;
- case RTE_PT_IGB_UIO:
- case RTE_PT_UIO_GENERIC:
- /* map resources for devices that use uio */
- ret = pci_uio_map_resource(dev);
+#endif
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ ret = pci_uio_ioport_map(dev, bar, p);
break;
default:
- RTE_LOG(DEBUG, EAL, " Not managed by known pt driver,"
- " skipped\n");
- ret = 1;
+#if defined(RTE_ARCH_X86)
+ ret = pci_ioport_map(dev, bar, p);
+#endif
break;
}
+ if (!ret)
+ p->dev = dev;
+
return ret;
}
-/*
- * If vendor/device ID match, call the devinit() function of the
- * driver.
- */
-int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+void
+rte_eal_pci_ioport_read(struct rte_pci_ioport *p,
+ void *data, size_t len, off_t offset)
{
- int ret;
- struct rte_pci_id *id_table;
-
- for (id_table = dr->id_table ; id_table->vendor_id != 0; id_table++) {
-
- /* check if device's identifiers match the driver's ones */
- if (id_table->vendor_id != dev->id.vendor_id &&
- id_table->vendor_id != PCI_ANY_ID)
- continue;
- if (id_table->device_id != dev->id.device_id &&
- id_table->device_id != PCI_ANY_ID)
- continue;
- if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
- id_table->subsystem_vendor_id != PCI_ANY_ID)
- continue;
- if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
- id_table->subsystem_device_id != PCI_ANY_ID)
- continue;
-
- struct rte_pci_addr *loc = &dev->addr;
-
- RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
- loc->domain, loc->bus, loc->devid, loc->function,
- dev->numa_node);
-
- RTE_LOG(DEBUG, EAL, " probe driver: %x:%x %s\n", dev->id.vendor_id,
- dev->id.device_id, dr->name);
-
- /* no initialization when blacklisted, return without error */
- if (dev->devargs != NULL &&
- dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
- RTE_LOG(DEBUG, EAL, " Device is blacklisted, not initializing\n");
- return 1;
- }
+ switch (p->dev->kdrv) {
+#ifdef VFIO_PRESENT
+ case RTE_KDRV_VFIO:
+ pci_vfio_ioport_read(p, data, len, offset);
+ break;
+#endif
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ pci_uio_ioport_read(p, data, len, offset);
+ break;
+ default:
+#if defined(RTE_ARCH_X86)
+ /* special case for x86 ... */
+ pci_uio_ioport_read(p, data, len, offset);
+#endif
+ break;
+ }
+}
- if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-#ifdef RTE_PCI_CONFIG
- /*
- * Set PCIe config space for high performance.
- * Return value can be ignored.
- */
- pci_config_space_set(dev);
+void
+rte_eal_pci_ioport_write(struct rte_pci_ioport *p,
+ const void *data, size_t len, off_t offset)
+{
+ switch (p->dev->kdrv) {
+#ifdef VFIO_PRESENT
+ case RTE_KDRV_VFIO:
+ pci_vfio_ioport_write(p, data, len, offset);
+ break;
#endif
- /* map resources for devices that use igb_uio */
- ret = pci_map_device(dev);
- if (ret != 0)
- return ret;
- } else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
- rte_eal_process_type() == RTE_PROC_PRIMARY) {
- /* unbind current driver */
- if (pci_unbind_kernel_driver(dev) < 0)
- return -1;
- }
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ pci_uio_ioport_write(p, data, len, offset);
+ break;
+ default:
+#if defined(RTE_ARCH_X86)
+ /* special case for x86 ... */
+ pci_uio_ioport_write(p, data, len, offset);
+#endif
+ break;
+ }
+}
- /* reference driver structure */
- dev->driver = dr;
+int
+rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
+{
+ int ret;
- /* call the driver devinit() function */
- return dr->devinit(dr, dev);
+ switch (p->dev->kdrv) {
+#ifdef VFIO_PRESENT
+ case RTE_KDRV_VFIO:
+ ret = -1;
+ if (pci_vfio_is_enabled())
+ ret = pci_vfio_ioport_unmap(p);
+ break;
+#endif
+ case RTE_KDRV_IGB_UIO:
+ case RTE_KDRV_UIO_GENERIC:
+ ret = pci_uio_ioport_unmap(p);
+ break;
+ default:
+#if defined(RTE_ARCH_X86)
+ /* special case for x86 ... nothing to do */
+ ret = 0;
+#else
+ ret = -1;
+#endif
+ break;
}
- /* return positive value if driver is not found */
- return 1;
+
+ return ret;
}
/* Init the PCI EAL subsystem */
{
TAILQ_INIT(&pci_driver_list);
TAILQ_INIT(&pci_device_list);
- pci_res_list = RTE_TAILQ_RESERVE_BY_IDX(RTE_TAILQ_PCI,
- mapped_pci_res_list);
/* for debug purposes, PCI can be disabled */
if (internal_config.no_pci)
return 0;
- if (pci_scan() < 0) {
+ if (rte_eal_pci_scan() < 0) {
RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
return -1;
}