2012-09-04 12:54:00 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2014-02-10 11:46:50 +00:00
|
|
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
2012-09-04 12:54:00 +00:00
|
|
|
* All rights reserved.
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2013-09-18 10:00:00 +00:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
2012-09-04 12:54:00 +00:00
|
|
|
* are met:
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2013-09-18 10:00:00 +00:00
|
|
|
* * Redistributions of source code must retain the above copyright
|
2012-09-04 12:54:00 +00:00
|
|
|
* notice, this list of conditions and the following disclaimer.
|
2013-09-18 10:00:00 +00:00
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
2012-09-04 12:54:00 +00:00
|
|
|
* distribution.
|
2013-09-18 10:00:00 +00:00
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
2012-09-04 12:54:00 +00:00
|
|
|
* from this software without specific prior written permission.
|
2014-06-03 23:42:50 +00:00
|
|
|
*
|
2013-09-18 10:00:00 +00:00
|
|
|
* 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
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
2012-09-04 12:54:00 +00:00
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2012-12-19 16:55:37 +00:00
|
|
|
/* BSD LICENSE
|
|
|
|
*
|
2014-03-01 12:14:54 +00:00
|
|
|
* Copyright 2013-2014 6WIND S.A.
|
2012-12-19 16:55:37 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of 6WIND S.A. 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
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-03-01 12:14:34 +00:00
|
|
|
#include <string.h>
|
2012-09-04 12:54:00 +00:00
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdint.h>
|
2012-12-19 23:00:00 +00:00
|
|
|
#include <stdlib.h>
|
2012-09-04 12:54:00 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/queue.h>
|
2015-07-08 10:34:50 +00:00
|
|
|
#include <sys/mman.h>
|
2012-09-04 12:54:00 +00:00
|
|
|
|
eal: do not panic on PCI failures
Some devices may be inaccessible for a variety of reasons, or the
PCI-bus may be unavailable causing the whole thing to fail. Still,
better to continue attempts at probes.
Since PCI isn't neccessarily required, it may be possible to simply log
the error and continue on letting the user check the logs and restart
the application when things have failed.
This will usually be an issue because of permissions. However, it could
also be caused by OOM. In either case, errno will contain the
underlying cause.
For linux, it is safe to re-init the system here, so allow the
application to take corrective action and reinit.
For BSD, this is not the case, for other reasons, including hugepage
allocation has already happened, and needs to be properly uninitialized.
Signed-off-by: Aaron Conole <aconole@redhat.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
2017-03-22 20:19:37 +00:00
|
|
|
#include <rte_errno.h>
|
2012-09-04 12:54:00 +00:00
|
|
|
#include <rte_interrupts.h>
|
2012-12-19 23:00:00 +00:00
|
|
|
#include <rte_log.h>
|
2012-09-04 12:54:00 +00:00
|
|
|
#include <rte_pci.h>
|
|
|
|
#include <rte_per_lcore.h>
|
|
|
|
#include <rte_memory.h>
|
|
|
|
#include <rte_memzone.h>
|
|
|
|
#include <rte_eal.h>
|
2013-09-18 10:00:00 +00:00
|
|
|
#include <rte_string_fns.h>
|
|
|
|
#include <rte_common.h>
|
2014-03-01 12:14:34 +00:00
|
|
|
#include <rte_devargs.h>
|
2012-09-04 12:54:00 +00:00
|
|
|
|
|
|
|
#include "eal_private.h"
|
|
|
|
|
2016-09-20 12:41:14 +00:00
|
|
|
struct pci_driver_list pci_driver_list =
|
|
|
|
TAILQ_HEAD_INITIALIZER(pci_driver_list);
|
|
|
|
struct pci_device_list pci_device_list =
|
|
|
|
TAILQ_HEAD_INITIALIZER(pci_device_list);
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2016-06-13 15:07:44 +00:00
|
|
|
#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
|
|
|
|
|
|
|
|
const char *pci_get_sysfs_path(void)
|
|
|
|
{
|
|
|
|
const char *path = NULL;
|
|
|
|
|
|
|
|
path = getenv("SYSFS_PCI_DEVICES");
|
|
|
|
if (path == NULL)
|
|
|
|
return SYSFS_PCI_DEVICES;
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2014-03-01 12:14:54 +00:00
|
|
|
static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)
|
2012-09-04 12:54:00 +00:00
|
|
|
{
|
2014-03-01 12:14:34 +00:00
|
|
|
struct rte_devargs *devargs;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(devargs, &devargs_list, next) {
|
2014-03-01 12:14:54 +00:00
|
|
|
if (devargs->type != RTE_DEVTYPE_BLACKLISTED_PCI &&
|
|
|
|
devargs->type != RTE_DEVTYPE_WHITELISTED_PCI)
|
2014-03-01 12:14:34 +00:00
|
|
|
continue;
|
2015-02-25 19:32:19 +00:00
|
|
|
if (!rte_eal_compare_pci_addr(&dev->addr, &devargs->pci.addr))
|
2014-03-01 12:14:54 +00:00
|
|
|
return devargs;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
2014-03-01 12:14:54 +00:00
|
|
|
return NULL;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
2015-07-08 10:34:50 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* unmap a particular resource */
|
|
|
|
void
|
|
|
|
pci_unmap_resource(void *requested_addr, size_t size)
|
|
|
|
{
|
|
|
|
if (requested_addr == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Unmap the PCI memory resource of device */
|
|
|
|
if (munmap(requested_addr, size)) {
|
|
|
|
RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n",
|
|
|
|
__func__, requested_addr, (unsigned long)size,
|
|
|
|
strerror(errno));
|
|
|
|
} else
|
|
|
|
RTE_LOG(DEBUG, EAL, " PCI memory unmapped at %p\n",
|
|
|
|
requested_addr);
|
|
|
|
}
|
|
|
|
|
2015-07-08 10:34:53 +00:00
|
|
|
/*
|
2016-09-20 12:41:15 +00:00
|
|
|
* If vendor/device ID match, call the probe() function of the
|
2015-07-08 10:34:53 +00:00
|
|
|
* driver.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
const 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;
|
2016-05-24 12:50:36 +00:00
|
|
|
if (id_table->class_id != dev->id.class_id &&
|
|
|
|
id_table->class_id != RTE_CLASS_ANY_ID)
|
|
|
|
continue;
|
2015-07-08 10:34:53 +00:00
|
|
|
|
|
|
|
struct rte_pci_addr *loc = &dev->addr;
|
|
|
|
|
2016-04-22 13:03:02 +00:00
|
|
|
RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
|
2015-07-08 10:34:53 +00:00
|
|
|
loc->domain, loc->bus, loc->devid, loc->function,
|
2016-09-20 12:41:36 +00:00
|
|
|
dev->device.numa_node);
|
2015-07-08 10:34:53 +00:00
|
|
|
|
|
|
|
/* no initialization when blacklisted, return without error */
|
2016-09-20 12:41:36 +00:00
|
|
|
if (dev->device.devargs != NULL &&
|
|
|
|
dev->device.devargs->type ==
|
|
|
|
RTE_DEVTYPE_BLACKLISTED_PCI) {
|
2016-05-31 02:40:12 +00:00
|
|
|
RTE_LOG(INFO, EAL, " Device is blacklisted, not initializing\n");
|
2015-07-08 10:34:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-04-22 13:03:02 +00:00
|
|
|
RTE_LOG(INFO, EAL, " probe driver: %x:%x %s\n", dev->id.vendor_id,
|
2016-09-20 12:41:33 +00:00
|
|
|
dev->id.device_id, dr->driver.name);
|
2016-04-22 13:03:02 +00:00
|
|
|
|
2015-07-08 10:34:53 +00:00
|
|
|
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
|
2017-03-29 09:54:50 +00:00
|
|
|
/* map resources for devices that use igb_uio or VFIO */
|
2016-02-02 13:48:18 +00:00
|
|
|
ret = rte_eal_pci_map_device(dev);
|
2015-07-08 10:34:53 +00:00
|
|
|
if (ret != 0)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reference driver structure */
|
|
|
|
dev->driver = dr;
|
|
|
|
|
2016-09-20 12:41:15 +00:00
|
|
|
/* call the driver probe() function */
|
2016-11-07 09:03:29 +00:00
|
|
|
ret = dr->probe(dr, dev);
|
2017-01-11 17:10:10 +00:00
|
|
|
if (ret) {
|
2016-11-07 09:03:29 +00:00
|
|
|
dev->driver = NULL;
|
2017-01-11 17:10:10 +00:00
|
|
|
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
|
|
|
|
rte_eal_pci_unmap_device(dev);
|
|
|
|
}
|
2016-11-07 09:03:29 +00:00
|
|
|
|
|
|
|
return ret;
|
2015-07-08 10:34:53 +00:00
|
|
|
}
|
2016-03-08 15:33:38 +00:00
|
|
|
/* return positive value if driver doesn't support this device */
|
2015-07-08 10:34:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2016-09-20 12:41:15 +00:00
|
|
|
* If vendor/device ID match, call the remove() function of the
|
2015-07-08 10:34:53 +00:00
|
|
|
* driver.
|
|
|
|
*/
|
|
|
|
static int
|
2015-07-18 18:35:57 +00:00
|
|
|
rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
|
2015-07-08 10:34:53 +00:00
|
|
|
struct rte_pci_device *dev)
|
|
|
|
{
|
|
|
|
const struct rte_pci_id *id_table;
|
|
|
|
|
|
|
|
if ((dr == NULL) || (dev == NULL))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
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,
|
2016-09-20 12:41:36 +00:00
|
|
|
loc->function, dev->device.numa_node);
|
2015-07-08 10:34:53 +00:00
|
|
|
|
|
|
|
RTE_LOG(DEBUG, EAL, " remove driver: %x:%x %s\n", dev->id.vendor_id,
|
2016-09-20 12:41:33 +00:00
|
|
|
dev->id.device_id, dr->driver.name);
|
2015-07-08 10:34:53 +00:00
|
|
|
|
2016-09-20 12:41:15 +00:00
|
|
|
if (dr->remove && (dr->remove(dev) < 0))
|
2015-07-08 10:34:53 +00:00
|
|
|
return -1; /* negative value is an error */
|
|
|
|
|
|
|
|
/* clear driver structure */
|
|
|
|
dev->driver = NULL;
|
|
|
|
|
|
|
|
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
|
|
|
|
/* unmap resources for devices that use igb_uio */
|
2016-02-02 13:48:18 +00:00
|
|
|
rte_eal_pci_unmap_device(dev);
|
2015-07-08 10:34:53 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:33:38 +00:00
|
|
|
/* return positive value if driver doesn't support this device */
|
2015-07-08 10:34:53 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/*
|
2016-09-20 12:41:15 +00:00
|
|
|
* If vendor/device ID match, call the probe() function of all
|
2014-06-13 14:52:38 +00:00
|
|
|
* registered driver for the given device. Return -1 if initialization
|
|
|
|
* failed, return 1 if no driver is found for this device.
|
2012-09-04 12:54:00 +00:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
pci_probe_all_drivers(struct rte_pci_device *dev)
|
|
|
|
{
|
|
|
|
struct rte_pci_driver *dr = NULL;
|
2015-02-25 19:32:23 +00:00
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (dev == NULL)
|
|
|
|
return -1;
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2016-10-25 21:50:40 +00:00
|
|
|
/* Check if a driver is already loaded */
|
|
|
|
if (dev->driver != NULL)
|
|
|
|
return 0;
|
|
|
|
|
2014-02-28 17:25:44 +00:00
|
|
|
TAILQ_FOREACH(dr, &pci_driver_list, next) {
|
2013-07-22 22:00:00 +00:00
|
|
|
rc = rte_eal_pci_probe_one_driver(dr, dev);
|
|
|
|
if (rc < 0)
|
|
|
|
/* negative value is an error */
|
2014-06-13 14:52:38 +00:00
|
|
|
return -1;
|
2013-07-22 22:00:00 +00:00
|
|
|
if (rc > 0)
|
2016-03-08 15:33:38 +00:00
|
|
|
/* positive value means driver doesn't support it */
|
2012-12-19 16:55:37 +00:00
|
|
|
continue;
|
|
|
|
return 0;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
2014-06-13 14:52:38 +00:00
|
|
|
return 1;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
2015-02-25 19:32:23 +00:00
|
|
|
/*
|
2016-09-20 12:41:15 +00:00
|
|
|
* If vendor/device ID match, call the remove() function of all
|
2015-02-25 19:32:23 +00:00
|
|
|
* registered driver for the given device. Return -1 if initialization
|
|
|
|
* failed, return 1 if no driver is found for this device.
|
|
|
|
*/
|
|
|
|
static int
|
2015-07-18 18:35:57 +00:00
|
|
|
pci_detach_all_drivers(struct rte_pci_device *dev)
|
2015-02-25 19:32:23 +00:00
|
|
|
{
|
|
|
|
struct rte_pci_driver *dr = NULL;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (dev == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dr, &pci_driver_list, next) {
|
2015-07-18 18:35:57 +00:00
|
|
|
rc = rte_eal_pci_detach_dev(dr, dev);
|
2015-02-25 19:32:23 +00:00
|
|
|
if (rc < 0)
|
|
|
|
/* negative value is an error */
|
|
|
|
return -1;
|
|
|
|
if (rc > 0)
|
2016-03-08 15:33:38 +00:00
|
|
|
/* positive value means driver doesn't support it */
|
2015-02-25 19:32:23 +00:00
|
|
|
continue;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the pci device specified by pci address, then invoke probe function of
|
|
|
|
* the driver of the devive.
|
|
|
|
*/
|
|
|
|
int
|
2015-04-16 23:23:40 +00:00
|
|
|
rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
|
2015-02-25 19:32:23 +00:00
|
|
|
{
|
|
|
|
struct rte_pci_device *dev = NULL;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (addr == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2016-09-20 12:41:23 +00:00
|
|
|
/* update current pci device in global list, kernel bindings might have
|
|
|
|
* changed since last time we looked at it.
|
|
|
|
*/
|
|
|
|
if (pci_update_device(addr) < 0)
|
|
|
|
goto err_return;
|
|
|
|
|
2015-02-25 19:32:23 +00:00
|
|
|
TAILQ_FOREACH(dev, &pci_device_list, next) {
|
|
|
|
if (rte_eal_compare_pci_addr(&dev->addr, addr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ret = pci_probe_all_drivers(dev);
|
2016-08-04 11:50:06 +00:00
|
|
|
if (ret)
|
2015-02-25 19:32:23 +00:00
|
|
|
goto err_return;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
err_return:
|
2016-09-20 12:41:23 +00:00
|
|
|
RTE_LOG(WARNING, EAL,
|
|
|
|
"Requested device " PCI_PRI_FMT " cannot be used\n",
|
|
|
|
addr->domain, addr->bus, addr->devid, addr->function);
|
2015-02-25 19:32:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-07-18 18:35:57 +00:00
|
|
|
* Detach device specified by its pci address.
|
2015-02-25 19:32:23 +00:00
|
|
|
*/
|
|
|
|
int
|
2015-07-18 18:35:57 +00:00
|
|
|
rte_eal_pci_detach(const struct rte_pci_addr *addr)
|
2015-02-25 19:32:23 +00:00
|
|
|
{
|
|
|
|
struct rte_pci_device *dev = NULL;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (addr == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dev, &pci_device_list, next) {
|
|
|
|
if (rte_eal_compare_pci_addr(&dev->addr, addr))
|
|
|
|
continue;
|
|
|
|
|
2015-07-18 18:35:57 +00:00
|
|
|
ret = pci_detach_all_drivers(dev);
|
2015-02-25 19:32:23 +00:00
|
|
|
if (ret < 0)
|
|
|
|
goto err_return;
|
|
|
|
|
|
|
|
TAILQ_REMOVE(&pci_device_list, dev, next);
|
2016-09-29 01:41:10 +00:00
|
|
|
free(dev);
|
2015-02-25 19:32:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
err_return:
|
|
|
|
RTE_LOG(WARNING, EAL, "Requested device " PCI_PRI_FMT
|
|
|
|
" cannot be used\n", dev->addr.domain, dev->addr.bus,
|
|
|
|
dev->addr.devid, dev->addr.function);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
/*
|
2016-09-20 12:41:15 +00:00
|
|
|
* Scan the content of the PCI bus, and call the probe() function for
|
2012-09-04 12:54:00 +00:00
|
|
|
* all registered drivers that have a matching entry in its id_table
|
|
|
|
* for discovered devices.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
rte_eal_pci_probe(void)
|
|
|
|
{
|
|
|
|
struct rte_pci_device *dev = NULL;
|
eal: do not panic on PCI failures
Some devices may be inaccessible for a variety of reasons, or the
PCI-bus may be unavailable causing the whole thing to fail. Still,
better to continue attempts at probes.
Since PCI isn't neccessarily required, it may be possible to simply log
the error and continue on letting the user check the logs and restart
the application when things have failed.
This will usually be an issue because of permissions. However, it could
also be caused by OOM. In either case, errno will contain the
underlying cause.
For linux, it is safe to re-init the system here, so allow the
application to take corrective action and reinit.
For BSD, this is not the case, for other reasons, including hugepage
allocation has already happened, and needs to be properly uninitialized.
Signed-off-by: Aaron Conole <aconole@redhat.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
2017-03-22 20:19:37 +00:00
|
|
|
size_t probed = 0, failed = 0;
|
2014-03-01 12:14:54 +00:00
|
|
|
struct rte_devargs *devargs;
|
2014-03-01 12:14:34 +00:00
|
|
|
int probe_all = 0;
|
2014-06-13 14:52:38 +00:00
|
|
|
int ret = 0;
|
2012-09-04 12:54:00 +00:00
|
|
|
|
2014-03-01 12:14:34 +00:00
|
|
|
if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
|
|
|
|
probe_all = 1;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dev, &pci_device_list, next) {
|
eal: do not panic on PCI failures
Some devices may be inaccessible for a variety of reasons, or the
PCI-bus may be unavailable causing the whole thing to fail. Still,
better to continue attempts at probes.
Since PCI isn't neccessarily required, it may be possible to simply log
the error and continue on letting the user check the logs and restart
the application when things have failed.
This will usually be an issue because of permissions. However, it could
also be caused by OOM. In either case, errno will contain the
underlying cause.
For linux, it is safe to re-init the system here, so allow the
application to take corrective action and reinit.
For BSD, this is not the case, for other reasons, including hugepage
allocation has already happened, and needs to be properly uninitialized.
Signed-off-by: Aaron Conole <aconole@redhat.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
2017-03-22 20:19:37 +00:00
|
|
|
probed++;
|
2014-03-01 12:14:54 +00:00
|
|
|
|
|
|
|
/* set devargs in PCI structure */
|
|
|
|
devargs = pci_devargs_lookup(dev);
|
|
|
|
if (devargs != NULL)
|
2016-09-20 12:41:36 +00:00
|
|
|
dev->device.devargs = devargs;
|
2014-03-01 12:14:54 +00:00
|
|
|
|
|
|
|
/* probe all or only whitelisted devices */
|
2014-03-01 12:14:34 +00:00
|
|
|
if (probe_all)
|
2014-06-13 14:52:38 +00:00
|
|
|
ret = pci_probe_all_drivers(dev);
|
2014-03-01 12:14:54 +00:00
|
|
|
else if (devargs != NULL &&
|
2014-06-13 14:52:38 +00:00
|
|
|
devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
|
|
|
|
ret = pci_probe_all_drivers(dev);
|
eal: do not panic on PCI failures
Some devices may be inaccessible for a variety of reasons, or the
PCI-bus may be unavailable causing the whole thing to fail. Still,
better to continue attempts at probes.
Since PCI isn't neccessarily required, it may be possible to simply log
the error and continue on letting the user check the logs and restart
the application when things have failed.
This will usually be an issue because of permissions. However, it could
also be caused by OOM. In either case, errno will contain the
underlying cause.
For linux, it is safe to re-init the system here, so allow the
application to take corrective action and reinit.
For BSD, this is not the case, for other reasons, including hugepage
allocation has already happened, and needs to be properly uninitialized.
Signed-off-by: Aaron Conole <aconole@redhat.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
2017-03-22 20:19:37 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
|
2014-03-01 12:14:34 +00:00
|
|
|
" cannot be used\n", dev->addr.domain, dev->addr.bus,
|
|
|
|
dev->addr.devid, dev->addr.function);
|
eal: do not panic on PCI failures
Some devices may be inaccessible for a variety of reasons, or the
PCI-bus may be unavailable causing the whole thing to fail. Still,
better to continue attempts at probes.
Since PCI isn't neccessarily required, it may be possible to simply log
the error and continue on letting the user check the logs and restart
the application when things have failed.
This will usually be an issue because of permissions. However, it could
also be caused by OOM. In either case, errno will contain the
underlying cause.
For linux, it is safe to re-init the system here, so allow the
application to take corrective action and reinit.
For BSD, this is not the case, for other reasons, including hugepage
allocation has already happened, and needs to be properly uninitialized.
Signed-off-by: Aaron Conole <aconole@redhat.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
2017-03-22 20:19:37 +00:00
|
|
|
rte_errno = errno;
|
|
|
|
failed++;
|
|
|
|
}
|
2014-03-01 12:14:34 +00:00
|
|
|
}
|
2013-09-18 10:00:00 +00:00
|
|
|
|
eal: do not panic on PCI failures
Some devices may be inaccessible for a variety of reasons, or the
PCI-bus may be unavailable causing the whole thing to fail. Still,
better to continue attempts at probes.
Since PCI isn't neccessarily required, it may be possible to simply log
the error and continue on letting the user check the logs and restart
the application when things have failed.
This will usually be an issue because of permissions. However, it could
also be caused by OOM. In either case, errno will contain the
underlying cause.
For linux, it is safe to re-init the system here, so allow the
application to take corrective action and reinit.
For BSD, this is not the case, for other reasons, including hugepage
allocation has already happened, and needs to be properly uninitialized.
Signed-off-by: Aaron Conole <aconole@redhat.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
2017-03-22 20:19:37 +00:00
|
|
|
return (probed && probed == failed) ? -1 : 0;
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* dump one device */
|
|
|
|
static int
|
2014-05-02 23:42:56 +00:00
|
|
|
pci_dump_one_device(FILE *f, struct rte_pci_device *dev)
|
2012-09-04 12:54:00 +00:00
|
|
|
{
|
2013-05-30 17:12:39 +00:00
|
|
|
int i;
|
|
|
|
|
2014-05-02 23:42:56 +00:00
|
|
|
fprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,
|
2012-09-04 12:54:00 +00:00
|
|
|
dev->addr.devid, dev->addr.function);
|
2014-05-02 23:42:56 +00:00
|
|
|
fprintf(f, " - vendor:%x device:%x\n", dev->id.vendor_id,
|
2012-09-04 12:54:00 +00:00
|
|
|
dev->id.device_id);
|
2013-05-30 17:12:39 +00:00
|
|
|
|
|
|
|
for (i = 0; i != sizeof(dev->mem_resource) /
|
|
|
|
sizeof(dev->mem_resource[0]); i++) {
|
2014-05-02 23:42:56 +00:00
|
|
|
fprintf(f, " %16.16"PRIx64" %16.16"PRIx64"\n",
|
2014-06-03 23:42:50 +00:00
|
|
|
dev->mem_resource[i].phys_addr,
|
2013-05-30 17:12:39 +00:00
|
|
|
dev->mem_resource[i].len);
|
|
|
|
}
|
2012-09-04 12:54:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dump devices on the bus */
|
|
|
|
void
|
2014-05-02 23:42:56 +00:00
|
|
|
rte_eal_pci_dump(FILE *f)
|
2012-09-04 12:54:00 +00:00
|
|
|
{
|
|
|
|
struct rte_pci_device *dev = NULL;
|
|
|
|
|
2014-02-28 17:25:44 +00:00
|
|
|
TAILQ_FOREACH(dev, &pci_device_list, next) {
|
2014-05-02 23:42:56 +00:00
|
|
|
pci_dump_one_device(f, dev);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* register a driver */
|
|
|
|
void
|
|
|
|
rte_eal_pci_register(struct rte_pci_driver *driver)
|
|
|
|
{
|
2014-02-28 17:25:44 +00:00
|
|
|
TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
|
2016-09-20 12:41:34 +00:00
|
|
|
rte_eal_driver_register(&driver->driver);
|
2012-09-04 12:54:00 +00:00
|
|
|
}
|
|
|
|
|
2013-06-03 00:00:00 +00:00
|
|
|
/* unregister a driver */
|
|
|
|
void
|
|
|
|
rte_eal_pci_unregister(struct rte_pci_driver *driver)
|
|
|
|
{
|
2016-09-20 12:41:34 +00:00
|
|
|
rte_eal_driver_unregister(&driver->driver);
|
2014-02-28 17:25:44 +00:00
|
|
|
TAILQ_REMOVE(&pci_driver_list, driver, next);
|
2013-06-03 00:00:00 +00:00
|
|
|
}
|