2015-09-21 08:52:41 -07:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
|
|
|
*
|
2016-01-26 10:47:22 -07:00
|
|
|
* Copyright (c) Intel Corporation.
|
2015-09-21 08:52:41 -07:00
|
|
|
* 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
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * 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
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2016-12-05 10:20:20 -07:00
|
|
|
#include "env_internal.h"
|
2015-09-25 09:13:02 -07:00
|
|
|
|
2016-08-10 10:41:12 -07:00
|
|
|
#include "spdk/env.h"
|
2015-09-21 08:52:41 -07:00
|
|
|
|
|
|
|
#define SYSFS_PCI_DRIVERS "/sys/bus/pci/drivers"
|
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
#define PCI_CFG_SIZE 256
|
|
|
|
#define PCI_EXT_CAP_ID_SN 0x03
|
|
|
|
|
2018-11-18 02:48:56 +01:00
|
|
|
static pthread_mutex_t g_pci_mutex = PTHREAD_MUTEX_INITIALIZER;
|
2018-11-18 02:15:19 +01:00
|
|
|
static TAILQ_HEAD(, spdk_pci_device) g_pci_devices = TAILQ_HEAD_INITIALIZER(g_pci_devices);
|
2018-11-18 02:48:56 +01:00
|
|
|
|
2016-12-05 10:20:20 -07:00
|
|
|
int
|
2016-08-08 15:57:49 -07:00
|
|
|
spdk_pci_device_init(struct rte_pci_driver *driver,
|
2018-11-18 02:15:19 +01:00
|
|
|
struct rte_pci_device *_dev)
|
2016-02-03 14:36:26 -07:00
|
|
|
{
|
2016-08-08 15:57:49 -07:00
|
|
|
struct spdk_pci_enum_ctx *ctx = (struct spdk_pci_enum_ctx *)driver;
|
2018-11-18 02:15:19 +01:00
|
|
|
struct spdk_pci_device *dev;
|
2017-12-06 22:52:56 +01:00
|
|
|
int rc;
|
2016-02-03 14:36:26 -07:00
|
|
|
|
2016-11-15 08:37:12 +08:00
|
|
|
if (!ctx->cb_fn) {
|
2018-11-18 01:05:41 +01:00
|
|
|
#if RTE_VERSION < RTE_VERSION_NUM(17, 02, 0, 1)
|
2018-11-18 02:15:19 +01:00
|
|
|
rte_eal_pci_unmap_device(_dev);
|
2016-11-15 08:37:12 +08:00
|
|
|
#endif
|
|
|
|
/* Return a positive value to indicate that this device does not belong to this driver, but
|
|
|
|
* this isn't an error. */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-11-18 02:15:19 +01:00
|
|
|
dev = calloc(1, sizeof(*dev));
|
|
|
|
if (dev == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev->dev_handle = _dev;
|
|
|
|
|
|
|
|
rc = ctx->cb_fn(ctx->cb_arg, dev);
|
2017-12-06 22:52:56 +01:00
|
|
|
if (rc != 0) {
|
2018-11-18 02:15:19 +01:00
|
|
|
free(dev);
|
2017-12-06 22:52:56 +01:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2018-11-20 20:57:38 +01:00
|
|
|
dev->attached = true;
|
2018-11-18 02:15:19 +01:00
|
|
|
TAILQ_INSERT_TAIL(&g_pci_devices, dev, tailq);
|
|
|
|
spdk_vtophys_pci_device_added(dev->dev_handle);
|
2017-12-06 22:52:56 +01:00
|
|
|
return 0;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
2016-12-05 10:20:20 -07:00
|
|
|
int
|
2018-11-18 02:15:19 +01:00
|
|
|
spdk_pci_device_fini(struct rte_pci_device *_dev)
|
2016-02-03 14:36:26 -07:00
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
struct spdk_pci_device *dev;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(dev, &g_pci_devices, tailq) {
|
|
|
|
if (dev->dev_handle == _dev) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-20 20:57:38 +01:00
|
|
|
if (dev == NULL || dev->attached) {
|
|
|
|
/* The device might be still referenced somewhere in SPDK. */
|
2018-11-18 02:15:19 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
spdk_vtophys_pci_device_removed(dev->dev_handle);
|
|
|
|
TAILQ_REMOVE(&g_pci_devices, dev, tailq);
|
|
|
|
free(dev);
|
2016-08-08 15:57:49 -07:00
|
|
|
return 0;
|
2018-11-18 02:15:19 +01:00
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
2016-11-15 09:53:14 +08:00
|
|
|
void
|
2018-11-18 02:15:19 +01:00
|
|
|
spdk_pci_device_detach(struct spdk_pci_device *dev)
|
2016-11-15 09:53:14 +08:00
|
|
|
{
|
2018-11-20 20:40:07 +01:00
|
|
|
struct rte_pci_device *device = dev->dev_handle;
|
|
|
|
|
2018-11-20 20:57:38 +01:00
|
|
|
assert(dev->attached);
|
|
|
|
dev->attached = false;
|
2018-10-24 12:14:48 +02:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0)
|
|
|
|
rte_eal_hotplug_remove("pci", device->device.name);
|
|
|
|
#elif RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 3)
|
2018-11-20 20:40:07 +01:00
|
|
|
rte_eal_dev_detach(&device->device);
|
2017-11-15 23:09:35 +01:00
|
|
|
#elif RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
|
|
|
rte_pci_detach(&device->addr);
|
2017-05-12 10:54:40 +08:00
|
|
|
#else
|
2018-11-18 01:05:41 +01:00
|
|
|
rte_eal_device_remove(&device->device);
|
2017-11-15 23:09:35 +01:00
|
|
|
rte_eal_pci_detach(&device->addr);
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2016-11-15 09:53:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2016-12-05 10:20:20 -07:00
|
|
|
spdk_pci_device_attach(struct spdk_pci_enum_ctx *ctx,
|
2016-11-15 09:53:14 +08:00
|
|
|
spdk_pci_enum_cb enum_cb,
|
|
|
|
void *enum_ctx, struct spdk_pci_addr *pci_address)
|
|
|
|
{
|
2018-11-20 21:49:39 +01:00
|
|
|
int rc;
|
2017-11-15 23:09:35 +01:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 3)
|
2018-11-20 21:49:39 +01:00
|
|
|
char bdf[32];
|
2017-11-15 23:09:35 +01:00
|
|
|
|
|
|
|
spdk_pci_addr_fmt(bdf, sizeof(bdf), pci_address);
|
|
|
|
#else
|
2018-11-20 21:49:39 +01:00
|
|
|
struct rte_pci_addr addr;
|
2016-11-15 09:53:14 +08:00
|
|
|
|
|
|
|
addr.domain = pci_address->domain;
|
|
|
|
addr.bus = pci_address->bus;
|
|
|
|
addr.devid = pci_address->dev;
|
|
|
|
addr.function = pci_address->func;
|
2017-11-15 23:09:35 +01:00
|
|
|
#endif
|
2016-11-15 09:53:14 +08:00
|
|
|
|
2018-11-18 02:48:56 +01:00
|
|
|
pthread_mutex_lock(&g_pci_mutex);
|
2016-11-15 09:53:14 +08:00
|
|
|
|
2017-03-06 11:09:41 -07:00
|
|
|
if (!ctx->is_registered) {
|
|
|
|
ctx->is_registered = true;
|
2017-05-12 10:54:40 +08:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
|
|
|
rte_pci_register(&ctx->driver);
|
|
|
|
#else
|
2017-03-06 11:09:41 -07:00
|
|
|
rte_eal_pci_register(&ctx->driver);
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2017-03-06 11:09:41 -07:00
|
|
|
}
|
|
|
|
|
2016-11-15 09:53:14 +08:00
|
|
|
ctx->cb_fn = enum_cb;
|
|
|
|
ctx->cb_arg = enum_ctx;
|
|
|
|
|
2018-10-24 12:14:48 +02:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0)
|
2018-11-20 21:49:39 +01:00
|
|
|
rc = rte_eal_hotplug_add("pci", bdf, "");
|
2018-10-24 12:14:48 +02:00
|
|
|
#elif RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 3)
|
2018-11-20 21:49:39 +01:00
|
|
|
rc = rte_eal_dev_attach(bdf, "");
|
2017-11-15 23:09:35 +01:00
|
|
|
#elif RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
2018-11-20 21:49:39 +01:00
|
|
|
rc = rte_pci_probe_one(&addr);
|
2017-05-12 10:54:40 +08:00
|
|
|
#else
|
2018-11-20 21:49:39 +01:00
|
|
|
rc = rte_eal_pci_probe_one(&addr);
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2016-11-15 09:53:14 +08:00
|
|
|
|
|
|
|
ctx->cb_arg = NULL;
|
|
|
|
ctx->cb_fn = NULL;
|
2018-11-18 02:48:56 +01:00
|
|
|
pthread_mutex_unlock(&g_pci_mutex);
|
2016-11-15 09:53:14 +08:00
|
|
|
|
2018-11-20 21:49:39 +01:00
|
|
|
return rc == 0 ? 0 : -1;
|
2016-11-15 09:53:14 +08:00
|
|
|
}
|
|
|
|
|
2016-11-15 08:37:12 +08:00
|
|
|
/* Note: You can call spdk_pci_enumerate from more than one thread
|
|
|
|
* simultaneously safely, but you cannot call spdk_pci_enumerate
|
|
|
|
* and rte_eal_pci_probe simultaneously.
|
2017-04-25 10:35:22 -07:00
|
|
|
*/
|
2016-02-16 10:11:25 +08:00
|
|
|
int
|
2016-12-05 10:20:20 -07:00
|
|
|
spdk_pci_enumerate(struct spdk_pci_enum_ctx *ctx,
|
2016-08-08 15:57:49 -07:00
|
|
|
spdk_pci_enum_cb enum_cb,
|
|
|
|
void *enum_ctx)
|
2016-02-16 10:11:25 +08:00
|
|
|
{
|
2018-11-18 02:48:56 +01:00
|
|
|
pthread_mutex_lock(&g_pci_mutex);
|
2016-11-15 08:37:12 +08:00
|
|
|
|
2017-03-06 11:09:41 -07:00
|
|
|
if (!ctx->is_registered) {
|
|
|
|
ctx->is_registered = true;
|
2017-05-12 10:54:40 +08:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
|
|
|
rte_pci_register(&ctx->driver);
|
|
|
|
#else
|
2017-03-06 11:09:41 -07:00
|
|
|
rte_eal_pci_register(&ctx->driver);
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2017-03-06 11:09:41 -07:00
|
|
|
}
|
|
|
|
|
2016-11-15 08:37:12 +08:00
|
|
|
ctx->cb_fn = enum_cb;
|
|
|
|
ctx->cb_arg = enum_ctx;
|
2016-10-12 16:26:05 -07:00
|
|
|
|
2017-11-15 23:09:35 +01:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 3)
|
|
|
|
if (rte_bus_probe() != 0) {
|
|
|
|
#elif RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
2017-05-12 10:54:40 +08:00
|
|
|
if (rte_pci_probe() != 0) {
|
|
|
|
#else
|
2016-11-15 08:37:12 +08:00
|
|
|
if (rte_eal_pci_probe() != 0) {
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2016-11-15 08:37:12 +08:00
|
|
|
ctx->cb_arg = NULL;
|
|
|
|
ctx->cb_fn = NULL;
|
2018-11-18 02:48:56 +01:00
|
|
|
pthread_mutex_unlock(&g_pci_mutex);
|
2016-11-15 08:37:12 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->cb_arg = NULL;
|
|
|
|
ctx->cb_fn = NULL;
|
2018-11-18 02:48:56 +01:00
|
|
|
pthread_mutex_unlock(&g_pci_mutex);
|
2016-11-15 08:37:12 +08:00
|
|
|
|
|
|
|
return 0;
|
2016-02-16 10:11:25 +08:00
|
|
|
}
|
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
int
|
2016-08-08 15:57:49 -07:00
|
|
|
spdk_pci_device_map_bar(struct spdk_pci_device *device, uint32_t bar,
|
|
|
|
void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
|
2016-02-03 14:36:26 -07:00
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
struct rte_pci_device *dev = device->dev_handle;
|
2016-02-03 14:36:26 -07:00
|
|
|
|
2016-08-08 15:57:49 -07:00
|
|
|
*mapped_addr = dev->mem_resource[bar].addr;
|
|
|
|
*phys_addr = (uint64_t)dev->mem_resource[bar].phys_addr;
|
|
|
|
*size = (uint64_t)dev->mem_resource[bar].len;
|
|
|
|
|
|
|
|
return 0;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2016-08-08 15:57:49 -07:00
|
|
|
spdk_pci_device_unmap_bar(struct spdk_pci_device *device, uint32_t bar, void *addr)
|
2016-02-03 14:36:26 -07:00
|
|
|
{
|
2016-08-08 15:57:49 -07:00
|
|
|
return 0;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
2017-06-21 15:05:47 -07:00
|
|
|
uint32_t
|
2016-02-03 14:36:26 -07:00
|
|
|
spdk_pci_device_get_domain(struct spdk_pci_device *dev)
|
2016-02-03 15:00:39 -07:00
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->addr.domain;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
2016-02-03 15:00:39 -07:00
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
uint8_t
|
|
|
|
spdk_pci_device_get_bus(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->addr.bus;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
2016-02-03 15:00:39 -07:00
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
uint8_t
|
|
|
|
spdk_pci_device_get_dev(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->addr.devid;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
2016-02-03 15:00:39 -07:00
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
uint8_t
|
|
|
|
spdk_pci_device_get_func(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->addr.function;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t
|
|
|
|
spdk_pci_device_get_vendor_id(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->id.vendor_id;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t
|
|
|
|
spdk_pci_device_get_device_id(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->id.device_id;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t
|
|
|
|
spdk_pci_device_get_subvendor_id(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->id.subsystem_vendor_id;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t
|
|
|
|
spdk_pci_device_get_subdevice_id(struct spdk_pci_device *dev)
|
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->id.subsystem_device_id;
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
2016-10-28 11:11:45 -07:00
|
|
|
struct spdk_pci_id
|
|
|
|
spdk_pci_device_get_id(struct spdk_pci_device *pci_dev)
|
|
|
|
{
|
|
|
|
struct spdk_pci_id pci_id;
|
|
|
|
|
|
|
|
pci_id.vendor_id = spdk_pci_device_get_vendor_id(pci_dev);
|
|
|
|
pci_id.device_id = spdk_pci_device_get_device_id(pci_dev);
|
|
|
|
pci_id.subvendor_id = spdk_pci_device_get_subvendor_id(pci_dev);
|
|
|
|
pci_id.subdevice_id = spdk_pci_device_get_subdevice_id(pci_dev);
|
|
|
|
|
|
|
|
return pci_id;
|
|
|
|
}
|
|
|
|
|
2017-01-30 17:39:23 -07:00
|
|
|
int
|
2018-11-18 02:15:19 +01:00
|
|
|
spdk_pci_device_get_socket_id(struct spdk_pci_device *dev)
|
2017-01-30 17:39:23 -07:00
|
|
|
{
|
2018-11-18 02:15:19 +01:00
|
|
|
return dev->dev_handle->device.numa_node;
|
2017-01-30 17:39:23 -07:00
|
|
|
}
|
|
|
|
|
2016-02-16 10:11:25 +08:00
|
|
|
int
|
2017-09-21 18:59:10 +02:00
|
|
|
spdk_pci_device_cfg_read(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
|
2016-02-16 10:11:25 +08:00
|
|
|
{
|
2017-09-21 18:59:10 +02:00
|
|
|
int rc;
|
|
|
|
|
2017-05-12 10:54:40 +08:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
2018-11-18 02:15:19 +01:00
|
|
|
rc = rte_pci_read_config(dev->dev_handle, value, len, offset);
|
2017-05-12 10:54:40 +08:00
|
|
|
#else
|
2018-11-18 02:15:19 +01:00
|
|
|
rc = rte_eal_pci_read_config(dev->dev_handle, value, len, offset);
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2018-11-08 11:56:55 +01:00
|
|
|
|
|
|
|
#if defined(__FreeBSD__) && RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
|
|
|
|
/* Older DPDKs return 0 on success and -1 on failure */
|
|
|
|
return rc;
|
|
|
|
#endif
|
2017-09-21 18:59:10 +02:00
|
|
|
return (rc > 0 && (uint32_t) rc == len) ? 0 : -1;
|
2016-02-16 10:11:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-09-21 18:59:10 +02:00
|
|
|
spdk_pci_device_cfg_write(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
|
2016-02-16 10:11:25 +08:00
|
|
|
{
|
2017-09-21 18:59:10 +02:00
|
|
|
int rc;
|
|
|
|
|
2017-05-12 10:54:40 +08:00
|
|
|
#if RTE_VERSION >= RTE_VERSION_NUM(17, 05, 0, 4)
|
2018-11-18 02:15:19 +01:00
|
|
|
rc = rte_pci_write_config(dev->dev_handle, value, len, offset);
|
2017-05-12 10:54:40 +08:00
|
|
|
#else
|
2018-11-18 02:15:19 +01:00
|
|
|
rc = rte_eal_pci_write_config(dev->dev_handle, value, len, offset);
|
2017-05-12 10:54:40 +08:00
|
|
|
#endif
|
2018-11-08 11:56:55 +01:00
|
|
|
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
/* DPDK returns 0 on success and -1 on failure */
|
|
|
|
return rc;
|
|
|
|
#endif
|
2017-09-21 18:59:10 +02:00
|
|
|
return (rc > 0 && (uint32_t) rc == len) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_device_cfg_read8(struct spdk_pci_device *dev, uint8_t *value, uint32_t offset)
|
|
|
|
{
|
|
|
|
return spdk_pci_device_cfg_read(dev, value, 1, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_device_cfg_write8(struct spdk_pci_device *dev, uint8_t value, uint32_t offset)
|
|
|
|
{
|
|
|
|
return spdk_pci_device_cfg_write(dev, &value, 1, offset);
|
2016-02-16 10:11:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_device_cfg_read16(struct spdk_pci_device *dev, uint16_t *value, uint32_t offset)
|
|
|
|
{
|
2017-09-21 18:59:10 +02:00
|
|
|
return spdk_pci_device_cfg_read(dev, value, 2, offset);
|
2016-02-16 10:11:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_device_cfg_write16(struct spdk_pci_device *dev, uint16_t value, uint32_t offset)
|
|
|
|
{
|
2017-09-21 18:59:10 +02:00
|
|
|
return spdk_pci_device_cfg_write(dev, &value, 2, offset);
|
2016-02-16 10:11:25 +08:00
|
|
|
}
|
|
|
|
|
2015-09-21 08:52:41 -07:00
|
|
|
int
|
2016-02-03 14:36:26 -07:00
|
|
|
spdk_pci_device_cfg_read32(struct spdk_pci_device *dev, uint32_t *value, uint32_t offset)
|
|
|
|
{
|
2017-09-21 18:59:10 +02:00
|
|
|
return spdk_pci_device_cfg_read(dev, value, 4, offset);
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_device_cfg_write32(struct spdk_pci_device *dev, uint32_t value, uint32_t offset)
|
|
|
|
{
|
2017-09-21 18:59:10 +02:00
|
|
|
return spdk_pci_device_cfg_write(dev, &value, 4, offset);
|
2016-02-03 14:36:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_device_get_serial_number(struct spdk_pci_device *dev, char *sn, size_t len)
|
2015-09-21 08:52:41 -07:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
uint32_t pos, header = 0;
|
|
|
|
uint32_t i, buf[2];
|
|
|
|
|
2017-12-07 16:23:48 -07:00
|
|
|
if (len < 17) {
|
2015-09-21 08:52:41 -07:00
|
|
|
return -1;
|
2017-12-07 16:23:48 -07:00
|
|
|
}
|
2015-09-21 08:52:41 -07:00
|
|
|
|
2016-02-03 14:36:26 -07:00
|
|
|
err = spdk_pci_device_cfg_read32(dev, &header, PCI_CFG_SIZE);
|
2017-12-07 16:23:48 -07:00
|
|
|
if (err || !header) {
|
2015-09-21 08:52:41 -07:00
|
|
|
return -1;
|
2017-12-07 16:23:48 -07:00
|
|
|
}
|
2015-09-21 08:52:41 -07:00
|
|
|
|
|
|
|
pos = PCI_CFG_SIZE;
|
|
|
|
while (1) {
|
|
|
|
if ((header & 0x0000ffff) == PCI_EXT_CAP_ID_SN) {
|
|
|
|
if (pos) {
|
2017-04-24 11:14:41 -07:00
|
|
|
/* skip the header */
|
2015-09-21 08:52:41 -07:00
|
|
|
pos += 4;
|
|
|
|
for (i = 0; i < 2; i++) {
|
2016-02-03 14:36:26 -07:00
|
|
|
err = spdk_pci_device_cfg_read32(dev, &buf[i], pos + 4 * i);
|
2017-12-07 16:23:48 -07:00
|
|
|
if (err) {
|
2015-09-21 08:52:41 -07:00
|
|
|
return -1;
|
2017-12-07 16:23:48 -07:00
|
|
|
}
|
2015-09-21 08:52:41 -07:00
|
|
|
}
|
2017-03-23 15:44:36 +08:00
|
|
|
snprintf(sn, len, "%08x%08x", buf[1], buf[0]);
|
2015-09-21 08:52:41 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = (header >> 20) & 0xffc;
|
2017-04-24 11:14:41 -07:00
|
|
|
/* 0 if no other items exist */
|
2017-12-07 16:23:48 -07:00
|
|
|
if (pos < PCI_CFG_SIZE) {
|
2015-09-21 08:52:41 -07:00
|
|
|
return -1;
|
2017-12-07 16:23:48 -07:00
|
|
|
}
|
2016-02-03 14:36:26 -07:00
|
|
|
err = spdk_pci_device_cfg_read32(dev, &header, pos);
|
2017-12-07 16:23:48 -07:00
|
|
|
if (err) {
|
2015-09-21 08:52:41 -07:00
|
|
|
return -1;
|
2017-12-07 16:23:48 -07:00
|
|
|
}
|
2015-09-21 08:52:41 -07:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-10-28 11:00:18 -07:00
|
|
|
struct spdk_pci_addr
|
|
|
|
spdk_pci_device_get_addr(struct spdk_pci_device *pci_dev)
|
2016-10-07 20:01:54 -04:00
|
|
|
{
|
2016-10-28 11:00:18 -07:00
|
|
|
struct spdk_pci_addr pci_addr;
|
|
|
|
|
|
|
|
pci_addr.domain = spdk_pci_device_get_domain(pci_dev);
|
|
|
|
pci_addr.bus = spdk_pci_device_get_bus(pci_dev);
|
|
|
|
pci_addr.dev = spdk_pci_device_get_dev(pci_dev);
|
|
|
|
pci_addr.func = spdk_pci_device_get_func(pci_dev);
|
|
|
|
|
|
|
|
return pci_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
|
|
|
|
{
|
|
|
|
if (a1->domain > a2->domain) {
|
|
|
|
return 1;
|
|
|
|
} else if (a1->domain < a2->domain) {
|
|
|
|
return -1;
|
|
|
|
} else if (a1->bus > a2->bus) {
|
|
|
|
return 1;
|
|
|
|
} else if (a1->bus < a2->bus) {
|
|
|
|
return -1;
|
|
|
|
} else if (a1->dev > a2->dev) {
|
|
|
|
return 1;
|
|
|
|
} else if (a1->dev < a2->dev) {
|
|
|
|
return -1;
|
|
|
|
} else if (a1->func > a2->func) {
|
|
|
|
return 1;
|
|
|
|
} else if (a1->func < a2->func) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2016-10-07 20:01:54 -04:00
|
|
|
}
|
|
|
|
|
2016-01-11 15:48:00 -07:00
|
|
|
#ifdef __linux__
|
2015-09-21 08:52:41 -07:00
|
|
|
int
|
2016-10-31 16:01:52 -07:00
|
|
|
spdk_pci_device_claim(const struct spdk_pci_addr *pci_addr)
|
2015-09-21 08:52:41 -07:00
|
|
|
{
|
|
|
|
int dev_fd;
|
2017-12-05 13:44:19 -07:00
|
|
|
char dev_name[64];
|
2015-09-21 08:52:41 -07:00
|
|
|
int pid;
|
|
|
|
void *dev_map;
|
|
|
|
struct flock pcidev_lock = {
|
|
|
|
.l_type = F_WRLCK,
|
|
|
|
.l_whence = SEEK_SET,
|
|
|
|
.l_start = 0,
|
|
|
|
.l_len = 0,
|
|
|
|
};
|
|
|
|
|
2017-12-05 13:44:19 -07:00
|
|
|
snprintf(dev_name, sizeof(dev_name), "/tmp/spdk_pci_lock_%04x:%02x:%02x.%x", pci_addr->domain,
|
|
|
|
pci_addr->bus,
|
2017-06-21 15:05:47 -07:00
|
|
|
pci_addr->dev, pci_addr->func);
|
2015-09-21 08:52:41 -07:00
|
|
|
|
2017-12-05 13:44:19 -07:00
|
|
|
dev_fd = open(dev_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
2015-09-21 08:52:41 -07:00
|
|
|
if (dev_fd == -1) {
|
2017-12-05 13:44:19 -07:00
|
|
|
fprintf(stderr, "could not open %s\n", dev_name);
|
2015-09-21 08:52:41 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ftruncate(dev_fd, sizeof(int)) != 0) {
|
2017-12-05 13:44:19 -07:00
|
|
|
fprintf(stderr, "could not truncate %s\n", dev_name);
|
2015-09-21 08:52:41 -07:00
|
|
|
close(dev_fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dev_map = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
|
|
|
|
MAP_SHARED, dev_fd, 0);
|
2018-03-28 20:07:54 +02:00
|
|
|
if (dev_map == MAP_FAILED) {
|
|
|
|
fprintf(stderr, "could not mmap dev %s (%d)\n", dev_name, errno);
|
2015-09-21 08:52:41 -07:00
|
|
|
close(dev_fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fcntl(dev_fd, F_SETLK, &pcidev_lock) != 0) {
|
|
|
|
pid = *(int *)dev_map;
|
|
|
|
fprintf(stderr, "Cannot create lock on device %s, probably"
|
2017-12-05 13:44:19 -07:00
|
|
|
" process %d has claimed it\n", dev_name, pid);
|
2015-09-21 08:52:41 -07:00
|
|
|
munmap(dev_map, sizeof(int));
|
|
|
|
close(dev_fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(int *)dev_map = (int)getpid();
|
|
|
|
munmap(dev_map, sizeof(int));
|
|
|
|
/* Keep dev_fd open to maintain the lock. */
|
2017-11-02 16:54:51 -07:00
|
|
|
return dev_fd;
|
2015-09-21 08:52:41 -07:00
|
|
|
}
|
2016-07-21 09:00:10 -07:00
|
|
|
#endif /* __linux__ */
|
|
|
|
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
int
|
2016-10-31 16:01:52 -07:00
|
|
|
spdk_pci_device_claim(const struct spdk_pci_addr *pci_addr)
|
2016-07-21 09:00:10 -07:00
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* __FreeBSD__ */
|
2016-10-31 16:29:52 -07:00
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
|
|
|
|
{
|
|
|
|
unsigned domain, bus, dev, func;
|
|
|
|
|
|
|
|
if (addr == NULL || bdf == NULL) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2017-04-17 10:01:55 +08:00
|
|
|
if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
|
|
|
|
(sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
|
2016-10-31 16:29:52 -07:00
|
|
|
/* Matched a full address - all variables are initialized */
|
|
|
|
} else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
|
|
|
|
func = 0;
|
2017-04-17 10:01:55 +08:00
|
|
|
} else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
|
|
|
|
(sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
|
2016-10-31 16:29:52 -07:00
|
|
|
domain = 0;
|
2017-04-17 10:01:55 +08:00
|
|
|
} else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
|
|
|
|
(sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
|
2016-10-31 16:29:52 -07:00
|
|
|
domain = 0;
|
|
|
|
func = 0;
|
|
|
|
} else {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2017-06-21 15:05:47 -07:00
|
|
|
if (bus > 0xFF || dev > 0x1F || func > 7) {
|
2016-10-31 16:29:52 -07:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr->domain = domain;
|
|
|
|
addr->bus = bus;
|
|
|
|
addr->dev = dev;
|
|
|
|
addr->func = func;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-12-02 11:00:55 -07:00
|
|
|
|
|
|
|
int
|
|
|
|
spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2017-06-21 15:05:47 -07:00
|
|
|
rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
|
2016-12-02 11:00:55 -07:00
|
|
|
addr->domain, addr->bus,
|
|
|
|
addr->dev, addr->func);
|
|
|
|
|
|
|
|
if (rc > 0 && (size_t)rc < sz) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|