/*-
* BSD LICENSE
- *
+ *
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
static struct uio_res_list *uio_res_list = NULL;
static int pci_parse_sysfs_value(const char *filename, uint64_t *val);
-/* forward prototype of function called in pci_switch_module below */
-static int pci_uio_map_resource(struct rte_pci_device *dev);
-
-#ifdef RTE_EAL_UNBIND_PORTS
-#define PROC_MODULES "/proc/modules"
-
-#define IGB_UIO_NAME "igb_uio"
-
-#define UIO_DRV_PATH "/sys/bus/pci/drivers/%s"
-
-/* maximum time to wait that /dev/uioX appears */
-#define UIO_DEV_WAIT_TIMEOUT 3 /* seconds */
-
-/*
- * Check that a kernel module is loaded. Returns 0 on success, or if the
- * parameter is NULL, or -1 if the module is not loaded.
- */
-static int
-pci_uio_check_module(const char *module_name)
-{
- FILE *f;
- unsigned i;
- char buf[BUFSIZ];
-
- if (module_name == NULL)
- return 0;
-
- f = fopen(PROC_MODULES, "r");
- if (f == NULL) {
- RTE_LOG(ERR, EAL, "Cannot open "PROC_MODULES": %s\n",
- strerror(errno));
- return -1;
- }
-
- while(fgets(buf, sizeof(buf), f) != NULL) {
-
- for (i = 0; i < sizeof(buf) && buf[i] != '\0'; i++) {
- if (isspace(buf[i]))
- buf[i] = '\0';
- }
-
- if (strncmp(buf, module_name, sizeof(buf)) == 0) {
- fclose(f);
- return 0;
- }
- }
- fclose(f);
- return -1;
-}
-
-/* bind a PCI to the kernel module driver */
-static int
-pci_bind_device(struct rte_pci_device *dev, char dr_path[])
-{
- FILE *f;
- int n;
- char buf[BUFSIZ];
- char dev_bind[PATH_MAX];
- struct rte_pci_addr *loc = &dev->addr;
-
- n = rte_snprintf(dev_bind, sizeof(dev_bind), "%s/bind", dr_path);
- if ((n < 0) || (n >= (int)sizeof(buf))) {
- RTE_LOG(ERR, EAL, "Cannot rte_snprintf device bind path\n");
- return -1;
- }
-
- f = fopen(dev_bind, "w");
- if (f == NULL) {
- RTE_LOG(ERR, EAL, "Cannot open %s\n", dev_bind);
- return -1;
- }
- n = rte_snprintf(buf, sizeof(buf), PCI_PRI_FMT "\n",
- loc->domain, loc->bus, loc->devid, loc->function);
- if ((n < 0) || (n >= (int)sizeof(buf))) {
- RTE_LOG(ERR, EAL, "Cannot rte_snprintf PCI infos\n");
- fclose(f);
- return -1;
- }
- if (fwrite(buf, n, 1, f) == 0) {
- fclose(f);
- return -1;
- }
-
- fclose(f);
- return 0;
-}
-
-static int
-pci_uio_bind_device(struct rte_pci_device *dev, const char *module_name)
-{
- FILE *f;
- int n;
- char buf[BUFSIZ];
- char uio_newid[PATH_MAX];
- char uio_bind[PATH_MAX];
-
- n = rte_snprintf(uio_newid, sizeof(uio_newid), UIO_DRV_PATH "/new_id", module_name);
- if ((n < 0) || (n >= (int)sizeof(uio_newid))) {
- RTE_LOG(ERR, EAL, "Cannot rte_snprintf uio_newid name\n");
- return -1;
- }
-
- n = rte_snprintf(uio_bind, sizeof(uio_bind), UIO_DRV_PATH, module_name);
- if ((n < 0) || (n >= (int)sizeof(uio_bind))) {
- RTE_LOG(ERR, EAL, "Cannot rte_snprintf uio_bind name\n");
- return -1;
- }
-
- n = rte_snprintf(buf, sizeof(buf), "%x %x\n",
- dev->id.vendor_id, dev->id.device_id);
- if ((n < 0) || (n >= (int)sizeof(buf))) {
- RTE_LOG(ERR, EAL, "Cannot rte_snprintf vendor_id/device_id\n");
- return -1;
- }
-
- f = fopen(uio_newid, "w");
- if (f == NULL) {
- RTE_LOG(ERR, EAL, "Cannot open %s\n", uio_newid);
- return -1;
- }
- if (fwrite(buf, n, 1, f) == 0) {
- fclose(f);
- return -1;
- }
- fclose(f);
-
- pci_bind_device(dev, uio_bind);
- return 0;
-}
-
/* unbind kernel driver for this device */
static int
pci_unbind_kernel_driver(struct rte_pci_device *dev)
return -1;
}
-
-static int
-pci_switch_module(struct rte_pci_driver *dr, struct rte_pci_device *dev,
- int uio_status, const char *module_name)
-{
- if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
- /* check that our driver is loaded */
- if (uio_status != 0 &&
- (uio_status = pci_uio_check_module(module_name)) != 0)
- rte_exit(EXIT_FAILURE, "The %s module is required by the "
- "%s driver\n", module_name, dr->name);
-
- /* unbind current driver, bind ours */
- if (pci_unbind_kernel_driver(dev) < 0)
- return -1;
- if (pci_uio_bind_device(dev, module_name) < 0)
- return -1;
- }
- /* map the NIC resources */
- if (pci_uio_map_resource(dev) < 0)
- return -1;
-
- return 0;
-}
-
-#endif /* ifdef EAL_UNBIND_PORTS */
-
/* map a particular resource from a file */
static void *
-pci_map_resource(struct rte_pci_device *dev, void *requested_addr,
- const char *devname, off_t offset, size_t size)
+pci_map_resource(void *requested_addr, const char *devname, off_t offset,
+ size_t size)
{
int fd;
void *mapaddr;
-#ifdef RTE_EAL_UNBIND_PORTS
- /*
- * open devname, and mmap it: it can take some time to
- * appear, so we wait some time before returning an error
- */
- unsigned n;
- fd = dev->intr_handle.fd;
- for (n = 0; n < UIO_DEV_WAIT_TIMEOUT*10 && fd < 0; n++) {
- errno = 0;
- if ((fd = open(devname, O_RDWR)) < 0 && errno != ENOENT)
- break;
- usleep(100000);
- }
-#else
/*
* open devname, to mmap it
*/
fd = open(devname, O_RDWR);
-#endif
if (fd < 0) {
- RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
+ RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
devname, strerror(errno));
goto fail;
}
/* Map the PCI memory resource of device */
mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, offset);
+ close(fd);
if (mapaddr == MAP_FAILED ||
(requested_addr != NULL && mapaddr != requested_addr)) {
RTE_LOG(ERR, EAL, "%s(): cannot mmap(%s(%d), %p, 0x%lx, 0x%lx):"
- " %s (%p)\n", __func__, devname, fd, requested_addr,
+ " %s (%p)\n", __func__, devname, fd, requested_addr,
(unsigned long)size, (unsigned long)offset,
strerror(errno), mapaddr);
- close(fd);
goto fail;
}
- if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
- /* save fd if in primary process */
- dev->intr_handle.fd = fd;
- dev->intr_handle.type = RTE_INTR_HANDLE_UIO;
- } else {
- /* fd is not needed in slave process, close it */
- dev->intr_handle.fd = -1;
- dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
- close(fd);
- }
RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", mapaddr);
return mapaddr;
fail:
- dev->intr_handle.fd = -1;
- dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
-
return NULL;
}
uint64_t offset, size;
for (i = 0; i != nb_maps; i++) {
-
+
/* check if map directory exists */
- rte_snprintf(dirname, sizeof(dirname),
+ rte_snprintf(dirname, sizeof(dirname),
"%s/maps/map%u", devname, i);
-
+
if (access(dirname, F_OK) != 0)
break;
-
+
/* get mapping offset */
rte_snprintf(filename, sizeof(filename),
"%s/offset", dirname);
__func__, dirname);
return (-1);
}
-
+
/* get mapping size */
rte_snprintf(filename, sizeof(filename),
"%s/size", dirname);
__func__, dirname);
return (-1);
}
-
+
/* get mapping physical address */
rte_snprintf(filename, sizeof(filename),
"%s/addr", dirname);
if ((offset > OFF_MAX) || (size > SIZE_MAX)) {
RTE_LOG(ERR, EAL,
"%s(): offset/size exceed system max value\n",
- __func__);
+ __func__);
return (-1);
}
{
size_t i;
struct uio_resource *uio_res;
-
+
TAILQ_FOREACH(uio_res, uio_res_list, next) {
-
+
/* skip this element if it doesn't match our PCI address */
if (memcmp(&uio_res->pci_addr, &dev->addr, sizeof(dev->addr)))
continue;
-
+
for (i = 0; i != uio_res->nb_maps; i++) {
- if (pci_map_resource(dev, uio_res->maps[i].addr,
- uio_res->path,
- (off_t)uio_res->maps[i].offset,
- (size_t)uio_res->maps[i].size) !=
- uio_res->maps[i].addr) {
+ if (pci_map_resource(uio_res->maps[i].addr,
+ uio_res->path,
+ (off_t)uio_res->maps[i].offset,
+ (size_t)uio_res->maps[i].size)
+ != uio_res->maps[i].addr) {
RTE_LOG(ERR, EAL,
"Cannot mmap device resource\n");
return (-1);
/* format could be uio%d ...*/
int shortprefix_len = sizeof("uio") - 1;
/* ... or uio:uio%d */
- int longprefix_len = sizeof("uio:uio") - 1;
+ int longprefix_len = sizeof("uio:uio") - 1;
char *endptr;
if (strncmp(e->d_name, "uio", 3) != 0)
{
int i, j;
char dirname[PATH_MAX];
- char filename[PATH_MAX];
char devname[PATH_MAX]; /* contains the /dev/uioX */
void *mapaddr;
int uio_num;
- unsigned long start,size;
uint64_t phaddr;
uint64_t offset;
uint64_t pagesz;
struct uio_map *maps;
dev->intr_handle.fd = -1;
+ dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
/* secondary processes - use already recorded details */
- if ((rte_eal_process_type() != RTE_PROC_PRIMARY) &&
- (dev->id.vendor_id != PCI_VENDOR_ID_QUMRANET))
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return (pci_uio_map_secondary(dev));
/* find uio resource */
"skipping\n", loc->domain, loc->bus, loc->devid, loc->function);
return -1;
}
+ rte_snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
- if(dev->id.vendor_id == PCI_VENDOR_ID_QUMRANET) {
- /* get portio size */
- rte_snprintf(filename, sizeof(filename),
- "%s/portio/port0/size", dirname);
- if (eal_parse_sysfs_value(filename, &size) < 0) {
- RTE_LOG(ERR, EAL, "%s(): cannot parse size\n",
- __func__);
- return -1;
- }
-
- /* get portio start */
- rte_snprintf(filename, sizeof(filename),
- "%s/portio/port0/start", dirname);
- if (eal_parse_sysfs_value(filename, &start) < 0) {
- RTE_LOG(ERR, EAL, "%s(): cannot parse portio start\n",
- __func__);
- return -1;
- }
- dev->mem_resource[0].addr = (void *)(uintptr_t)start;
- dev->mem_resource[0].len = (uint64_t)size;
- RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%lx with size=0x%lx\n", start, size);
- /* rte_virtio_pmd does not need any other bar even if available */
- return (0);
+ /* save fd if in primary process */
+ dev->intr_handle.fd = open(devname, O_RDWR);
+ if (dev->intr_handle.fd < 0) {
+ RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
+ devname, strerror(errno));
+ return -1;
}
-
+ dev->intr_handle.type = RTE_INTR_HANDLE_UIO;
+
/* allocate the mapping details for secondary processes*/
if ((uio_res = rte_zmalloc("UIO_RES", sizeof (*uio_res), 0)) == NULL) {
RTE_LOG(ERR, EAL,
return (-1);
}
- rte_snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
rte_snprintf(uio_res->path, sizeof(uio_res->path), "%s", devname);
memcpy(&uio_res->pci_addr, &dev->addr, sizeof(uio_res->pci_addr));
/* Map all BARs */
pagesz = sysconf(_SC_PAGESIZE);
-
+
maps = uio_res->maps;
for (i = 0; i != PCI_MAX_RESOURCE; i++) {
-
+
/* skip empty BAR */
if ((phaddr = dev->mem_resource[i].phys_addr) == 0)
continue;
-
+
for (j = 0; j != nb_maps && (phaddr != maps[j].phaddr ||
dev->mem_resource[i].len != maps[j].size);
j++)
;
-
+
/* if matching map is found, then use it */
if (j != nb_maps) {
offset = j * pagesz;
if (maps[j].addr != NULL ||
- (mapaddr = pci_map_resource(dev,
- NULL, devname, (off_t)offset,
- (size_t)maps[j].size)) == NULL) {
+ (mapaddr = pci_map_resource(NULL, devname,
+ (off_t)offset,
+ (size_t)maps[j].size)
+ ) == NULL) {
rte_free(uio_res);
return (-1);
}
-
+
maps[j].addr = mapaddr;
maps[j].offset = offset;
dev->mem_resource[i].addr = mapaddr;
for (i = 0; i<PCI_MAX_RESOURCE; i++) {
if (fgets(buf, sizeof(buf), f) == NULL) {
- RTE_LOG(ERR, EAL,
+ RTE_LOG(ERR, EAL,
"%s(): cannot read resource\n", __func__);
goto error;
}
if (rte_strsplit(buf, sizeof(buf), res_info.ptrs, 3, ' ') != 3) {
- RTE_LOG(ERR, EAL,
+ RTE_LOG(ERR, EAL,
"%s(): bad resource format\n", __func__);
goto error;
}
end_addr = strtoull(res_info.end_addr, NULL, 16);
flags = strtoull(res_info.flags, NULL, 16);
if (errno != 0) {
- RTE_LOG(ERR, EAL,
+ RTE_LOG(ERR, EAL,
"%s(): bad resource format\n", __func__);
goto error;
}
dev->mem_resource[i].phys_addr = phys_addr;
dev->mem_resource[i].len = end_addr - phys_addr + 1;
/* not mapped for now */
- dev->mem_resource[i].addr = NULL;
+ dev->mem_resource[i].addr = NULL;
}
}
fclose(f);
return -1;
}
-/*
- * parse a sysfs file containing one integer value
+/*
+ * parse a sysfs file containing one integer value
* different to the eal version, as it needs to work with 64-bit values
- */
-static int
-pci_parse_sysfs_value(const char *filename, uint64_t *val)
+ */
+static int
+pci_parse_sysfs_value(const char *filename, uint64_t *val)
{
FILE *f;
char buf[BUFSIZ];
char *end = NULL;
-
+
f = fopen(filename, "r");
if (f == NULL) {
RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
__func__, filename);
return -1;
}
-
+
if (fgets(buf, sizeof(buf), f) == NULL) {
RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
__func__, filename);
/* get max_vfs */
dev->max_vfs = 0;
rte_snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);
- if (!access(filename, F_OK) &&
+ if (!access(filename, F_OK) &&
eal_parse_sysfs_value(filename, &tmp) == 0) {
dev->max_vfs = (uint16_t)tmp;
}
/* 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;
}
TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
}
-
+
return 0;
}
return 0;
}
-#ifdef RTE_EAL_UNBIND_PORTS
if (dr->drv_flags & RTE_PCI_DRV_NEED_IGB_UIO) {
- /* unbind driver and load uio resources for Intel NICs */
- if (pci_switch_module(dr, dev, 1, IGB_UIO_NAME) < 0)
+ /* map resources for devices that use igb_uio */
+ if (pci_uio_map_resource(dev) < 0)
return -1;
} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
rte_eal_process_type() == RTE_PROC_PRIMARY) {
if (pci_unbind_kernel_driver(dev) < 0)
return -1;
}
-#else
- if (dr->drv_flags & RTE_PCI_DRV_NEED_IGB_UIO)
- /* just map resources for Intel NICs */
- if (pci_uio_map_resource(dev) < 0)
- return -1;
-#endif
/* reference driver structure */
dev->driver = dr;