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
|
|
|
|
|
|
|
#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"
|
|
|
|
|
2014-02-28 17:25:44 +00:00
|
|
|
struct pci_driver_list pci_driver_list;
|
|
|
|
struct pci_device_list 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
|
|
|
/*
|
|
|
|
* If vendor/device ID match, call the devinit() function of the
|
|
|
|
* 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,
|
|
|
|
dev->numa_node);
|
|
|
|
|
|
|
|
/* no initialization when blacklisted, return without error */
|
|
|
|
if (dev->devargs != NULL &&
|
|
|
|
dev->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,
|
|
|
|
dev->id.device_id, dr->name);
|
|
|
|
|
2015-07-08 10:34:53 +00:00
|
|
|
if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
|
|
|
|
/* map resources for devices that use igb_uio */
|
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;
|
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reference driver structure */
|
|
|
|
dev->driver = dr;
|
|
|
|
|
|
|
|
/* call the driver devinit() function */
|
|
|
|
return dr->devinit(dr, dev);
|
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If vendor/device ID match, call the devuninit() function of the
|
|
|
|
* 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,
|
|
|
|
loc->function, dev->numa_node);
|
|
|
|
|
|
|
|
RTE_LOG(DEBUG, EAL, " remove driver: %x:%x %s\n", dev->id.vendor_id,
|
|
|
|
dev->id.device_id, dr->name);
|
|
|
|
|
|
|
|
if (dr->devuninit && (dr->devuninit(dev) < 0))
|
|
|
|
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
|
|
|
/*
|
|
|
|
* If vendor/device ID match, call the devinit() 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
|
|
|
|
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
|
|
|
/*
|
|
|
|
* If vendor/device ID match, call the devuninit() function of all
|
|
|
|
* 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;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dev, &pci_device_list, next) {
|
|
|
|
if (rte_eal_compare_pci_addr(&dev->addr, addr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ret = pci_probe_all_drivers(dev);
|
|
|
|
if (ret < 0)
|
|
|
|
goto err_return;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
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);
|
|
|
|
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
|
|
|
/*
|
|
|
|
* Scan the content of the PCI bus, and call the devinit() function for
|
|
|
|
* 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;
|
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) {
|
2014-03-01 12:14:54 +00:00
|
|
|
|
|
|
|
/* set devargs in PCI structure */
|
|
|
|
devargs = pci_devargs_lookup(dev);
|
|
|
|
if (devargs != NULL)
|
|
|
|
dev->devargs = devargs;
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
if (ret < 0)
|
2014-03-01 12:14:34 +00:00
|
|
|
rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
|
|
|
|
" cannot be used\n", dev->addr.domain, dev->addr.bus,
|
|
|
|
dev->addr.devid, dev->addr.function);
|
|
|
|
}
|
2013-09-18 10:00:00 +00:00
|
|
|
|
2012-09-04 12:54:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
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)
|
|
|
|
{
|
2014-02-28 17:25:44 +00:00
|
|
|
TAILQ_REMOVE(&pci_driver_list, driver, next);
|
2013-06-03 00:00:00 +00:00
|
|
|
}
|