env_dpdk: add support for DPDK 22.11

DPDK has merged changes which hide remove some DPDK
object such as rte_device and rte_driver from the
public API.

So we add copies of the necessary header files into
our tree, along with a 22.11-specific pci_dpdk
implementation.

These files are copied over exactly, except for one
#include which needs to change from <> to "" so that
it picks up the header in our tree instead of looking
for it in system headers.

Longer-term we may want to look at ways to automated
checking and updating of these header files.  DPDK 22.11
isn't officially released yet, so the header files could
change, but we want to get this in now since without
it SPDK cannot build against DPDK tip at all.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I89ffd0abab52c404cfff911c1c9b0cd9e889241d
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14570
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
This commit is contained in:
Jim Harris 2022-09-15 22:16:20 +00:00 committed by Tomasz Zawadzki
parent 57b0fcc4ce
commit 5497616e8f
9 changed files with 1682 additions and 8 deletions

View File

@ -0,0 +1,309 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2022 Red Hat, Inc.
*/
#ifndef BUS_DRIVER_H
#define BUS_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rte_bus.h"
#include <rte_compat.h>
#include "rte_dev.h"
#include <rte_eal.h>
#include <rte_tailq.h>
struct rte_devargs;
struct rte_device;
/** Double linked list of buses */
RTE_TAILQ_HEAD(rte_bus_list, rte_bus);
/**
* Bus specific scan for devices attached on the bus.
* For each bus object, the scan would be responsible for finding devices and
* adding them to its private device list.
*
* A bus should mandatorily implement this method.
*
* @return
* 0 for successful scan
* <0 for unsuccessful scan with error value
*/
typedef int (*rte_bus_scan_t)(void);
/**
* Implementation specific probe function which is responsible for linking
* devices on that bus with applicable drivers.
*
* This is called while iterating over each registered bus.
*
* @return
* 0 for successful probe
* !0 for any error while probing
*/
typedef int (*rte_bus_probe_t)(void);
/**
* Device iterator to find a device on a bus.
*
* This function returns an rte_device if one of those held by the bus
* matches the data passed as parameter.
*
* If the comparison function returns zero this function should stop iterating
* over any more devices. To continue a search the device of a previous search
* can be passed via the start parameter.
*
* @param cmp
* Comparison function.
*
* @param data
* Data to compare each device against.
*
* @param start
* starting point for the iteration
*
* @return
* The first device matching the data, NULL if none exists.
*/
typedef struct rte_device *
(*rte_bus_find_device_t)(const struct rte_device *start, rte_dev_cmp_t cmp,
const void *data);
/**
* Implementation specific probe function which is responsible for linking
* devices on that bus with applicable drivers.
*
* @param dev
* Device pointer that was returned by a previous call to find_device.
*
* @return
* 0 on success.
* !0 on error.
*/
typedef int (*rte_bus_plug_t)(struct rte_device *dev);
/**
* Implementation specific remove function which is responsible for unlinking
* devices on that bus from assigned driver.
*
* @param dev
* Device pointer that was returned by a previous call to find_device.
*
* @return
* 0 on success.
* !0 on error.
*/
typedef int (*rte_bus_unplug_t)(struct rte_device *dev);
/**
* Bus specific parsing function.
* Validates the syntax used in the textual representation of a device,
* If the syntax is valid and ``addr`` is not NULL, writes the bus-specific
* device representation to ``addr``.
*
* @param[in] name
* device textual description
*
* @param[out] addr
* device information location address, into which parsed info
* should be written. If NULL, nothing should be written, which
* is not an error.
*
* @return
* 0 if parsing was successful.
* !0 for any error.
*/
typedef int (*rte_bus_parse_t)(const char *name, void *addr);
/**
* Parse bus part of the device arguments.
*
* The field name of the struct rte_devargs will be set.
*
* @param da
* Pointer to the devargs to parse.
*
* @return
* 0 on successful parsing, otherwise rte_errno is set.
* -EINVAL: on parsing error.
* -ENODEV: if no key matching a device argument is specified.
* -E2BIG: device name is too long.
*/
typedef int (*rte_bus_devargs_parse_t)(struct rte_devargs *da);
/**
* Device level DMA map function.
* After a successful call, the memory segment will be mapped to the
* given device.
*
* @param dev
* Device pointer.
* @param addr
* Virtual address to map.
* @param iova
* IOVA address to map.
* @param len
* Length of the memory segment being mapped.
*
* @return
* 0 if mapping was successful.
* Negative value and rte_errno is set otherwise.
*/
typedef int (*rte_dev_dma_map_t)(struct rte_device *dev, void *addr,
uint64_t iova, size_t len);
/**
* Device level DMA unmap function.
* After a successful call, the memory segment will no longer be
* accessible by the given device.
*
* @param dev
* Device pointer.
* @param addr
* Virtual address to unmap.
* @param iova
* IOVA address to unmap.
* @param len
* Length of the memory segment being mapped.
*
* @return
* 0 if un-mapping was successful.
* Negative value and rte_errno is set otherwise.
*/
typedef int (*rte_dev_dma_unmap_t)(struct rte_device *dev, void *addr,
uint64_t iova, size_t len);
/**
* Implement a specific hot-unplug handler, which is responsible for
* handle the failure when device be hot-unplugged. When the event of
* hot-unplug be detected, it could call this function to handle
* the hot-unplug failure and avoid app crash.
* @param dev
* Pointer of the device structure.
*
* @return
* 0 on success.
* !0 on error.
*/
typedef int (*rte_bus_hot_unplug_handler_t)(struct rte_device *dev);
/**
* Implement a specific sigbus handler, which is responsible for handling
* the sigbus error which is either original memory error, or specific memory
* error that caused of device be hot-unplugged. When sigbus error be captured,
* it could call this function to handle sigbus error.
* @param failure_addr
* Pointer of the fault address of the sigbus error.
*
* @return
* 0 for success handle the sigbus for hot-unplug.
* 1 for not process it, because it is a generic sigbus error.
* -1 for failed to handle the sigbus for hot-unplug.
*/
typedef int (*rte_bus_sigbus_handler_t)(const void *failure_addr);
/**
* Implementation specific cleanup function which is responsible for cleaning up
* devices on that bus with applicable drivers.
*
* This is called while iterating over each registered bus.
*
* @return
* 0 for successful cleanup
* !0 for any error during cleanup
*/
typedef int (*rte_bus_cleanup_t)(void);
/**
* Bus scan policies
*/
enum rte_bus_scan_mode {
RTE_BUS_SCAN_UNDEFINED,
RTE_BUS_SCAN_ALLOWLIST,
RTE_BUS_SCAN_BLOCKLIST,
};
/**
* A structure used to configure bus operations.
*/
struct rte_bus_conf {
enum rte_bus_scan_mode scan_mode; /**< Scan policy. */
};
/**
* Get common iommu class of the all the devices on the bus. The bus may
* check that those devices are attached to iommu driver.
* If no devices are attached to the bus. The bus may return with don't care
* (_DC) value.
* Otherwise, The bus will return appropriate _pa or _va iova mode.
*
* @return
* enum rte_iova_mode value.
*/
typedef enum rte_iova_mode (*rte_bus_get_iommu_class_t)(void);
/**
* A structure describing a generic bus.
*/
struct rte_bus {
RTE_TAILQ_ENTRY(rte_bus) next; /**< Next bus object in linked list */
const char *name; /**< Name of the bus */
rte_bus_scan_t scan; /**< Scan for devices attached to bus */
rte_bus_probe_t probe; /**< Probe devices on bus */
rte_bus_find_device_t find_device; /**< Find a device on the bus */
rte_bus_plug_t plug; /**< Probe single device for drivers */
rte_bus_unplug_t unplug; /**< Remove single device from driver */
rte_bus_parse_t parse; /**< Parse a device name */
rte_bus_devargs_parse_t devargs_parse; /**< Parse bus devargs */
rte_dev_dma_map_t dma_map; /**< DMA map for device in the bus */
rte_dev_dma_unmap_t dma_unmap; /**< DMA unmap for device in the bus */
struct rte_bus_conf conf; /**< Bus configuration */
rte_bus_get_iommu_class_t get_iommu_class; /**< Get iommu class */
rte_dev_iterate_t dev_iterate; /**< Device iterator. */
rte_bus_hot_unplug_handler_t hot_unplug_handler;
/**< handle hot-unplug failure on the bus */
rte_bus_sigbus_handler_t sigbus_handler;
/**< handle sigbus error on the bus */
rte_bus_cleanup_t cleanup; /**< Cleanup devices on bus */
};
/**
* Register a Bus handler.
*
* @param bus
* A pointer to a rte_bus structure describing the bus
* to be registered.
*/
__rte_internal
void rte_bus_register(struct rte_bus *bus);
/**
* Helper for Bus registration.
* The constructor has higher priority than PMD constructors.
*/
#define RTE_REGISTER_BUS(nm, bus) \
RTE_INIT_PRIO(businitfn_ ##nm, BUS) \
{\
(bus).name = RTE_STR(nm);\
rte_bus_register(&bus); \
}
/**
* Unregister a Bus handler.
*
* @param bus
* A pointer to a rte_bus structure describing the bus
* to be unregistered.
*/
__rte_internal
void rte_bus_unregister(struct rte_bus *bus);
#ifdef __cplusplus
}
#endif
#endif /* BUS_DRIVER_H */

View File

@ -0,0 +1,201 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2015 Intel Corporation.
* Copyright 2013-2014 6WIND S.A.
*/
#ifndef BUS_PCI_DRIVER_H
#define BUS_PCI_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "rte_bus_pci.h"
#include "dev_driver.h"
#include <rte_compat.h>
/** Pathname of PCI devices directory. */
__rte_internal
const char *rte_pci_get_sysfs_path(void);
enum rte_pci_kernel_driver {
RTE_PCI_KDRV_UNKNOWN = 0, /* may be misc UIO or bifurcated driver */
RTE_PCI_KDRV_IGB_UIO, /* igb_uio for Linux */
RTE_PCI_KDRV_VFIO, /* VFIO for Linux */
RTE_PCI_KDRV_UIO_GENERIC, /* uio_pci_generic for Linux */
RTE_PCI_KDRV_NIC_UIO, /* nic_uio for FreeBSD */
RTE_PCI_KDRV_NONE, /* no attached driver */
RTE_PCI_KDRV_NET_UIO, /* NetUIO for Windows */
};
/**
* A structure describing a PCI device.
*/
struct rte_pci_device {
RTE_TAILQ_ENTRY(rte_pci_device) next; /**< Next probed PCI device. */
struct rte_device device; /**< Inherit core device */
struct rte_pci_addr addr; /**< PCI location. */
struct rte_pci_id id; /**< PCI ID. */
struct rte_mem_resource mem_resource[PCI_MAX_RESOURCE];
/**< PCI Memory Resource */
struct rte_intr_handle *intr_handle; /**< Interrupt handle */
struct rte_pci_driver *driver; /**< PCI driver used in probing */
uint16_t max_vfs; /**< sriov enable if not zero */
enum rte_pci_kernel_driver kdrv; /**< Kernel driver passthrough */
char name[PCI_PRI_STR_SIZE+1]; /**< PCI location (ASCII) */
char *bus_info; /**< PCI bus specific info */
struct rte_intr_handle *vfio_req_intr_handle;
/**< Handler of VFIO request interrupt */
};
/**
* @internal
* Helper macro for drivers that need to convert to struct rte_pci_device.
*/
#define RTE_DEV_TO_PCI(ptr) container_of(ptr, struct rte_pci_device, device)
#define RTE_DEV_TO_PCI_CONST(ptr) \
container_of(ptr, const struct rte_pci_device, device)
#define RTE_ETH_DEV_TO_PCI(eth_dev) RTE_DEV_TO_PCI((eth_dev)->device)
#ifdef __cplusplus
/** C++ macro used to help building up tables of device IDs */
#define RTE_PCI_DEVICE(vend, dev) \
RTE_CLASS_ANY_ID, \
(vend), \
(dev), \
RTE_PCI_ANY_ID, \
RTE_PCI_ANY_ID
#else
/** Macro used to help building up tables of device IDs */
#define RTE_PCI_DEVICE(vend, dev) \
.class_id = RTE_CLASS_ANY_ID, \
.vendor_id = (vend), \
.device_id = (dev), \
.subsystem_vendor_id = RTE_PCI_ANY_ID, \
.subsystem_device_id = RTE_PCI_ANY_ID
#endif
/**
* Initialisation function for the driver called during PCI probing.
*/
typedef int (rte_pci_probe_t)(struct rte_pci_driver *, struct rte_pci_device *);
/**
* Uninitialisation function for the driver called during hotplugging.
*/
typedef int (rte_pci_remove_t)(struct rte_pci_device *);
/**
* Driver-specific DMA mapping. After a successful call the device
* will be able to read/write from/to this segment.
*
* @param dev
* Pointer to the PCI device.
* @param addr
* Starting virtual address of memory to be mapped.
* @param iova
* Starting IOVA address of memory to be mapped.
* @param len
* Length of memory segment being mapped.
* @return
* - 0 On success.
* - Negative value and rte_errno is set otherwise.
*/
typedef int (pci_dma_map_t)(struct rte_pci_device *dev, void *addr,
uint64_t iova, size_t len);
/**
* Driver-specific DMA un-mapping. After a successful call the device
* will not be able to read/write from/to this segment.
*
* @param dev
* Pointer to the PCI device.
* @param addr
* Starting virtual address of memory to be unmapped.
* @param iova
* Starting IOVA address of memory to be unmapped.
* @param len
* Length of memory segment being unmapped.
* @return
* - 0 On success.
* - Negative value and rte_errno is set otherwise.
*/
typedef int (pci_dma_unmap_t)(struct rte_pci_device *dev, void *addr,
uint64_t iova, size_t len);
/**
* A structure describing a PCI driver.
*/
struct rte_pci_driver {
RTE_TAILQ_ENTRY(rte_pci_driver) next; /**< Next in list. */
struct rte_driver driver; /**< Inherit core driver. */
rte_pci_probe_t *probe; /**< Device probe function. */
rte_pci_remove_t *remove; /**< Device remove function. */
pci_dma_map_t *dma_map; /**< device dma map function. */
pci_dma_unmap_t *dma_unmap; /**< device dma unmap function. */
const struct rte_pci_id *id_table; /**< ID table, NULL terminated. */
uint32_t drv_flags; /**< Flags RTE_PCI_DRV_*. */
};
/** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */
#define RTE_PCI_DRV_NEED_MAPPING 0x0001
/** Device needs PCI BAR mapping with enabled write combining (wc) */
#define RTE_PCI_DRV_WC_ACTIVATE 0x0002
/** Device already probed can be probed again to check for new ports. */
#define RTE_PCI_DRV_PROBE_AGAIN 0x0004
/** Device driver supports link state interrupt */
#define RTE_PCI_DRV_INTR_LSC 0x0008
/** Device driver supports device removal interrupt */
#define RTE_PCI_DRV_INTR_RMV 0x0010
/** Device driver needs to keep mapped resources if unsupported dev detected */
#define RTE_PCI_DRV_KEEP_MAPPED_RES 0x0020
/** Device driver needs IOVA as VA and cannot work with IOVA as PA */
#define RTE_PCI_DRV_NEED_IOVA_AS_VA 0x0040
/**
* Register a PCI driver.
*
* @param driver
* A pointer to a rte_pci_driver structure describing the driver
* to be registered.
*/
__rte_internal
void rte_pci_register(struct rte_pci_driver *driver);
/** Helper for PCI device registration from driver (eth, crypto) instance */
#define RTE_PMD_REGISTER_PCI(nm, pci_drv) \
RTE_INIT(pciinitfn_ ##nm) \
{\
(pci_drv).driver.name = RTE_STR(nm);\
rte_pci_register(&pci_drv); \
} \
RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
/**
* Unregister a PCI driver.
*
* @param driver
* A pointer to a rte_pci_driver structure describing the driver
* to be unregistered.
*/
__rte_internal
void rte_pci_unregister(struct rte_pci_driver *driver);
/*
* A structure used to access io resources for a pci device.
* rte_pci_ioport is arch, os, driver specific, and should not be used outside
* of pci ioport api.
*/
struct rte_pci_ioport {
struct rte_pci_device *dev;
uint64_t base;
uint64_t len; /* only filled for memory mapped ports */
};
#ifdef __cplusplus
}
#endif
#endif /* BUS_PCI_DRIVER_H */

View File

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2022 Red Hat, Inc.
*/
#ifndef DEV_DRIVER_H
#define DEV_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <rte_common.h>
#include "rte_dev.h"
/**
* A structure describing a device driver.
*/
struct rte_driver {
RTE_TAILQ_ENTRY(rte_driver) next; /**< Next in list. */
const char *name; /**< Driver name. */
const char *alias; /**< Driver alias. */
};
/**
* A structure describing a generic device.
*/
struct rte_device {
RTE_TAILQ_ENTRY(rte_device) next; /**< Next device */
const char *name; /**< Device name */
const char *bus_info; /**< Device bus specific information */
const struct rte_driver *driver; /**< Driver assigned after probing */
const struct rte_bus *bus; /**< Bus handle assigned on scan */
int numa_node; /**< NUMA node connection */
struct rte_devargs *devargs; /**< Arguments for latest probing */
};
#ifdef __cplusplus
}
#endif
#endif /* DEV_DRIVER_H */

View File

@ -0,0 +1,131 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright 2016 NXP
*/
#ifndef _RTE_BUS_H_
#define _RTE_BUS_H_
/**
* @file
*
* DPDK device bus interface
*
* This file exposes API and interfaces for bus abstraction
* over the devices and drivers in EAL.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <rte_eal.h>
struct rte_bus;
struct rte_device;
/**
* Retrieve a bus name.
*
* @param bus
* A pointer to a rte_bus structure.
* @return
* A pointer to the bus name string.
*/
const char *rte_bus_name(const struct rte_bus *bus);
/**
* Scan all the buses.
*
* @return
* 0 in case of success in scanning all buses
* !0 in case of failure to scan
*/
int rte_bus_scan(void);
/**
* For each device on the buses, perform a driver 'match' and call the
* driver-specific probe for device initialization.
*
* @return
* 0 for successful match/probe
* !0 otherwise
*/
int rte_bus_probe(void);
/**
* Dump information of all the buses registered with EAL.
*
* @param f
* A valid and open output stream handle
*/
void rte_bus_dump(FILE *f);
/**
* Bus comparison function.
*
* @param bus
* Bus under test.
*
* @param data
* Data to compare against.
*
* @return
* 0 if the bus matches the data.
* !0 if the bus does not match.
* <0 if ordering is possible and the bus is lower than the data.
* >0 if ordering is possible and the bus is greater than the data.
*/
typedef int (*rte_bus_cmp_t)(const struct rte_bus *bus, const void *data);
/**
* Bus iterator to find a particular bus.
*
* This function compares each registered bus to find one that matches
* the data passed as parameter.
*
* If the comparison function returns zero this function will stop iterating
* over any more buses. To continue a search the bus of a previous search can
* be passed via the start parameter.
*
* @param start
* Starting point for the iteration.
*
* @param cmp
* Comparison function.
*
* @param data
* Data to pass to comparison function.
*
* @return
* A pointer to a rte_bus structure or NULL in case no bus matches
*/
struct rte_bus *rte_bus_find(const struct rte_bus *start, rte_bus_cmp_t cmp,
const void *data);
/**
* Find the registered bus for a particular device.
*/
struct rte_bus *rte_bus_find_by_device(const struct rte_device *dev);
/**
* Find the registered bus for a given name.
*/
struct rte_bus *rte_bus_find_by_name(const char *busname);
/**
* Get the common iommu class of devices bound on to buses available in the
* system. RTE_IOVA_DC means that no preference has been expressed.
*
* @return
* enum rte_iova_mode value.
*/
enum rte_iova_mode rte_bus_get_iommu_class(void);
#ifdef __cplusplus
}
#endif
#endif /* _RTE_BUS_H */

View File

@ -0,0 +1,199 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2015 Intel Corporation.
* Copyright 2013-2014 6WIND S.A.
*/
#ifndef _RTE_BUS_PCI_H_
#define _RTE_BUS_PCI_H_
/**
* @file
* PCI device & driver interface
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>
#include <rte_debug.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
/* Forward declarations */
struct rte_pci_device;
struct rte_pci_driver;
struct rte_pci_ioport;
struct rte_devargs;
/**
* Map the PCI device resources in user space virtual memory address
*
* Note that driver should not call this function when flag
* RTE_PCI_DRV_NEED_MAPPING is set, as EAL will do that for
* you when it's on.
*
* @param dev
* A pointer to a rte_pci_device structure describing the device
* to use
*
* @return
* 0 on success, negative on error and positive if no driver
* is found for the device.
*/
int rte_pci_map_device(struct rte_pci_device *dev);
/**
* Unmap this device
*
* @param dev
* A pointer to a rte_pci_device structure describing the device
* to use
*/
void rte_pci_unmap_device(struct rte_pci_device *dev);
/**
* Dump the content of the PCI bus.
*
* @param f
* A pointer to a file for output
*/
void rte_pci_dump(FILE *f);
/**
* Find device's extended PCI capability.
*
* @param dev
* A pointer to rte_pci_device structure.
*
* @param cap
* Extended capability to be found, which can be any from
* RTE_PCI_EXT_CAP_ID_*, defined in librte_pci.
*
* @return
* > 0: The offset of the next matching extended capability structure
* within the device's PCI configuration space.
* < 0: An error in PCI config space read.
* = 0: Device does not support it.
*/
__rte_experimental
off_t rte_pci_find_ext_capability(struct rte_pci_device *dev, uint32_t cap);
/**
* Enables/Disables Bus Master for device's PCI command register.
*
* @param dev
* A pointer to rte_pci_device structure.
* @param enable
* Enable or disable Bus Master.
*
* @return
* 0 on success, -1 on error in PCI config space read/write.
*/
__rte_experimental
int rte_pci_set_bus_master(struct rte_pci_device *dev, bool enable);
/**
* Read PCI config space.
*
* @param device
* A pointer to a rte_pci_device structure describing the device
* to use
* @param buf
* A data buffer where the bytes should be read into
* @param len
* The length of the data buffer.
* @param offset
* The offset into PCI config space
* @return
* Number of bytes read on success, negative on error.
*/
int rte_pci_read_config(const struct rte_pci_device *device,
void *buf, size_t len, off_t offset);
/**
* Write PCI config space.
*
* @param device
* A pointer to a rte_pci_device structure describing the device
* to use
* @param buf
* A data buffer containing the bytes should be written
* @param len
* The length of the data buffer.
* @param offset
* The offset into PCI config space
*/
int rte_pci_write_config(const struct rte_pci_device *device,
const void *buf, size_t len, off_t offset);
/**
* Initialize a rte_pci_ioport object for a pci device io resource.
*
* This object is then used to gain access to those io resources (see below).
*
* @param dev
* A pointer to a rte_pci_device structure describing the device
* to use.
* @param bar
* Index of the io pci resource we want to access.
* @param p
* The rte_pci_ioport object to be initialized.
* @return
* 0 on success, negative on error.
*/
int rte_pci_ioport_map(struct rte_pci_device *dev, int bar,
struct rte_pci_ioport *p);
/**
* Release any resources used in a rte_pci_ioport object.
*
* @param p
* The rte_pci_ioport object to be uninitialized.
* @return
* 0 on success, negative on error.
*/
int rte_pci_ioport_unmap(struct rte_pci_ioport *p);
/**
* Read from a io pci resource.
*
* @param p
* The rte_pci_ioport object from which we want to read.
* @param data
* A data buffer where the bytes should be read into
* @param len
* The length of the data buffer.
* @param offset
* The offset into the pci io resource.
*/
void rte_pci_ioport_read(struct rte_pci_ioport *p,
void *data, size_t len, off_t offset);
/**
* Write to a io pci resource.
*
* @param p
* The rte_pci_ioport object to which we want to write.
* @param data
* A data buffer where the bytes should be read into
* @param len
* The length of the data buffer.
* @param offset
* The offset into the pci io resource.
*/
void rte_pci_ioport_write(struct rte_pci_ioport *p,
const void *data, size_t len, off_t offset);
#ifdef __cplusplus
}
#endif
#endif /* _RTE_BUS_PCI_H_ */

View File

@ -0,0 +1,563 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2014 6WIND S.A.
*/
#ifndef _RTE_DEV_H_
#define _RTE_DEV_H_
/**
* @file
*
* RTE PMD Registration Interface
*
* This file manages the list of device drivers.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <rte_config.h>
#include <rte_common.h>
#include <rte_compat.h>
#include <rte_log.h>
struct rte_bus;
struct rte_devargs;
struct rte_device;
struct rte_driver;
/**
* The device event type.
*/
enum rte_dev_event_type {
RTE_DEV_EVENT_ADD, /**< device being added */
RTE_DEV_EVENT_REMOVE, /**< device being removed */
RTE_DEV_EVENT_MAX /**< max value of this enum */
};
typedef void (*rte_dev_event_cb_fn)(const char *device_name,
enum rte_dev_event_type event,
void *cb_arg);
/* Macros to check for invalid function pointers */
#define RTE_FUNC_PTR_OR_ERR_RET(func, retval) RTE_DEPRECATED(RTE_FUNC_PTR_OR_ERR_RET) \
do { \
if ((func) == NULL) \
return retval; \
} while (0)
#define RTE_FUNC_PTR_OR_RET(func) RTE_DEPRECATED(RTE_FUNC_PTR_OR_RET) \
do { \
if ((func) == NULL) \
return; \
} while (0)
/**
* Device policies.
*/
enum rte_dev_policy {
RTE_DEV_ALLOWED,
RTE_DEV_BLOCKED,
};
/**
* A generic memory resource representation.
*/
struct rte_mem_resource {
uint64_t phys_addr; /**< Physical address, 0 if not resource. */
uint64_t len; /**< Length of the resource. */
void *addr; /**< Virtual address, NULL when not mapped. */
};
/**
* Retrieve a driver name.
*
* @param driver
* A pointer to a driver structure.
* @return
* A pointer to the driver name string.
*/
const char *
rte_driver_name(const struct rte_driver *driver);
/**
* Retrieve a device bus.
*
* @param dev
* A pointer to a device structure.
* @return
* A pointer to this device bus.
*/
const struct rte_bus *
rte_dev_bus(const struct rte_device *dev);
/**
* Retrieve bus specific information for a device.
*
* @param dev
* A pointer to a device structure.
* @return
* A string describing this device or NULL if none is available.
*/
const char *
rte_dev_bus_info(const struct rte_device *dev);
/**
* Retrieve a device arguments.
*
* @param dev
* A pointer to a device structure.
* @return
* A pointer to this device devargs.
*/
const struct rte_devargs *
rte_dev_devargs(const struct rte_device *dev);
/**
* Retrieve a device driver.
*
* @param dev
* A pointer to a device structure.
* @return
* A pointer to this device driver.
*/
const struct rte_driver *
rte_dev_driver(const struct rte_device *dev);
/**
* Retrieve a device name.
*
* @param dev
* A pointer to a device structure.
* @return
* A pointer to this device name.
*/
const char *
rte_dev_name(const struct rte_device *dev);
/**
* Retrieve a device numa node.
*
* @param dev
* A pointer to a device structure.
* @return
* A pointer to this device numa node.
*/
int
rte_dev_numa_node(const struct rte_device *dev);
/*
* Internal identifier length
* Sufficiently large to allow for UUID or PCI address
*/
#define RTE_DEV_NAME_MAX_LEN 64
/**
* Query status of a device.
*
* @param dev
* Generic device pointer.
* @return
* (int)true if already probed successfully, 0 otherwise.
*/
int rte_dev_is_probed(const struct rte_device *dev);
/**
* Hotplug add a given device to a specific bus.
*
* In multi-process, it will request other processes to add the same device.
* A failure, in any process, will rollback the action
*
* @param busname
* The bus name the device is added to.
* @param devname
* The device name. Based on this device name, eal will identify a driver
* capable of handling it and pass it to the driver probing function.
* @param drvargs
* Device arguments to be passed to the driver.
* @return
* 0 on success, negative on error.
*/
int rte_eal_hotplug_add(const char *busname, const char *devname,
const char *drvargs);
/**
* Add matching devices.
*
* In multi-process, it will request other processes to add the same device.
* A failure, in any process, will rollback the action
*
* @param devargs
* Device arguments including bus, class and driver properties.
* @return
* 0 on success, negative on error.
*/
int rte_dev_probe(const char *devargs);
/**
* Hotplug remove a given device from a specific bus.
*
* In multi-process, it will request other processes to remove the same device.
* A failure, in any process, will rollback the action
*
* @param busname
* The bus name the device is removed from.
* @param devname
* The device name being removed.
* @return
* 0 on success, negative on error.
*/
int rte_eal_hotplug_remove(const char *busname, const char *devname);
/**
* Remove one device.
*
* In multi-process, it will request other processes to remove the same device.
* A failure, in any process, will rollback the action
*
* @param dev
* Data structure of the device to remove.
* @return
* 0 on success, negative on error.
*/
int rte_dev_remove(struct rte_device *dev);
/**
* Device comparison function.
*
* This type of function is used to compare an rte_device with arbitrary
* data.
*
* @param dev
* Device handle.
*
* @param data
* Data to compare against. The type of this parameter is determined by
* the kind of comparison performed by the function.
*
* @return
* 0 if the device matches the data.
* !0 if the device does not match.
* <0 if ordering is possible and the device is lower than the data.
* >0 if ordering is possible and the device is greater than the data.
*/
typedef int (*rte_dev_cmp_t)(const struct rte_device *dev, const void *data);
#define RTE_PMD_EXPORT_NAME_ARRAY(n, idx) n##idx[]
#define RTE_PMD_EXPORT_NAME(name, idx) \
static const char RTE_PMD_EXPORT_NAME_ARRAY(this_pmd_name, idx) \
__rte_used = RTE_STR(name)
#define DRV_EXP_TAG(name, tag) __##name##_##tag
#define RTE_PMD_REGISTER_PCI_TABLE(name, table) \
static const char DRV_EXP_TAG(name, pci_tbl_export)[] __rte_used = \
RTE_STR(table)
#define RTE_PMD_REGISTER_PARAM_STRING(name, str) \
static const char DRV_EXP_TAG(name, param_string_export)[] \
__rte_used = str
/**
* Advertise the list of kernel modules required to run this driver
*
* This string lists the kernel modules required for the devices
* associated to a PMD. The format of each line of the string is:
* "<device-pattern> <kmod-expression>".
*
* The possible formats for the device pattern are:
* "*" all devices supported by this driver
* "pci:*" all PCI devices supported by this driver
* "pci:v8086:d*:sv*:sd*" all PCI devices supported by this driver
* whose vendor id is 0x8086.
*
* The format of the kernel modules list is a parenthesized expression
* containing logical-and (&) and logical-or (|).
*
* The device pattern and the kmod expression are separated by a space.
*
* Example:
* - "* igb_uio | uio_pci_generic | vfio"
*/
#define RTE_PMD_REGISTER_KMOD_DEP(name, str) \
static const char DRV_EXP_TAG(name, kmod_dep_export)[] \
__rte_used = str
/**
* Iteration context.
*
* This context carries over the current iteration state.
*/
struct rte_dev_iterator {
const char *dev_str; /**< device string. */
const char *bus_str; /**< bus-related part of device string. */
const char *cls_str; /**< class-related part of device string. */
struct rte_bus *bus; /**< bus handle. */
struct rte_class *cls; /**< class handle. */
struct rte_device *device; /**< current position. */
void *class_device; /**< additional specialized context. */
};
/**
* Device iteration function.
*
* Find the next device matching properties passed in parameters.
* The function takes an additional ``start`` parameter, that is
* used as starting context when relevant.
*
* The function returns the current element in the iteration.
* This return value will potentially be used as a start parameter
* in subsequent calls to the function.
*
* The additional iterator parameter is only there if a specific
* implementation needs additional context. It must not be modified by
* the iteration function itself.
*
* @param start
* Starting iteration context.
*
* @param devstr
* Device description string.
*
* @param it
* Device iterator.
*
* @return
* The address of the current element matching the device description
* string.
*/
typedef void *(*rte_dev_iterate_t)(const void *start,
const char *devstr,
const struct rte_dev_iterator *it);
/**
* Initializes a device iterator.
*
* This iterator allows accessing a list of devices matching a criteria.
* The device matching is made among all buses and classes currently registered,
* filtered by the device description given as parameter.
*
* This function will not allocate any memory. It is safe to stop the
* iteration at any moment and let the iterator go out of context.
*
* @param it
* Device iterator handle.
*
* @param str
* Device description string.
*
* @return
* 0 on successful initialization.
* <0 on error.
*/
__rte_experimental
int
rte_dev_iterator_init(struct rte_dev_iterator *it, const char *str);
/**
* Iterates on a device iterator.
*
* Generates a new rte_device handle corresponding to the next element
* in the list described in comprehension by the iterator.
*
* The next object is returned, and the iterator is updated.
*
* @param it
* Device iterator handle.
*
* @return
* An rte_device handle if found.
* NULL if an error occurred (rte_errno is set).
* NULL if no device could be found (rte_errno is not set).
*/
__rte_experimental
struct rte_device *
rte_dev_iterator_next(struct rte_dev_iterator *it);
#define RTE_DEV_FOREACH(dev, devstr, it) \
for (rte_dev_iterator_init(it, devstr), \
dev = rte_dev_iterator_next(it); \
dev != NULL; \
dev = rte_dev_iterator_next(it))
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* It registers the callback for the specific device.
* Multiple callbacks can be registered at the same time.
*
* @param device_name
* The device name, that is the param name of the struct rte_device,
* null value means for all devices.
* @param cb_fn
* callback address.
* @param cb_arg
* address of parameter for callback.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
__rte_experimental
int
rte_dev_event_callback_register(const char *device_name,
rte_dev_event_cb_fn cb_fn,
void *cb_arg);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* It unregisters the callback according to the specified device.
*
* @param device_name
* The device name, that is the param name of the struct rte_device,
* null value means for all devices and their callbacks.
* @param cb_fn
* callback address.
* @param cb_arg
* address of parameter for callback, (void *)-1 means to remove all
* registered which has the same callback address.
*
* @return
* - On success, return the number of callback entities removed.
* - On failure, a negative value.
*/
__rte_experimental
int
rte_dev_event_callback_unregister(const char *device_name,
rte_dev_event_cb_fn cb_fn,
void *cb_arg);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Executes all the user application registered callbacks for
* the specific device.
*
* @param device_name
* The device name.
* @param event
* the device event type.
*/
__rte_experimental
void
rte_dev_event_callback_process(const char *device_name,
enum rte_dev_event_type event);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Start the device event monitoring.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
__rte_experimental
int
rte_dev_event_monitor_start(void);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Stop the device event monitoring.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
__rte_experimental
int
rte_dev_event_monitor_stop(void);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Enable hotplug handling for devices.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
__rte_experimental
int
rte_dev_hotplug_handle_enable(void);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Disable hotplug handling for devices.
*
* @return
* - On success, zero.
* - On failure, a negative value.
*/
__rte_experimental
int
rte_dev_hotplug_handle_disable(void);
/**
* Device level DMA map function.
* After a successful call, the memory segment will be mapped to the
* given device.
*
* @note: Memory must be registered in advance using rte_extmem_* APIs.
*
* @param dev
* Device pointer.
* @param addr
* Virtual address to map.
* @param iova
* IOVA address to map.
* @param len
* Length of the memory segment being mapped.
*
* @return
* 0 if mapping was successful.
* Negative value and rte_errno is set otherwise.
*/
__rte_experimental
int
rte_dev_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len);
/**
* Device level DMA unmap function.
* After a successful call, the memory segment will no longer be
* accessible by the given device.
*
* @note: Memory must be registered in advance using rte_extmem_* APIs.
*
* @param dev
* Device pointer.
* @param addr
* Virtual address to unmap.
* @param iova
* IOVA address to unmap.
* @param len
* Length of the memory segment being mapped.
*
* @return
* 0 if un-mapping was successful.
* Negative value and rte_errno is set otherwise.
*/
__rte_experimental
int
rte_dev_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova,
size_t len);
#ifdef __cplusplus
}
#endif
#endif /* _RTE_DEV_H_ */

View File

@ -13,7 +13,7 @@ CFLAGS += $(ENV_CFLAGS)
C_SRCS = env.c memory.c pci.c init.c threads.c
C_SRCS += pci_ioat.c pci_virtio.c pci_vmd.c pci_idxd.c
C_SRCS += pci_event.c sigbus_handler.c pci_dpdk.c
C_SRCS += pci_dpdk_2207.c
C_SRCS += pci_dpdk_2207.c pci_dpdk_2211.c
LIBNAME = env_dpdk
SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_env_dpdk.map)

View File

@ -9,6 +9,7 @@
#include "spdk/log.h"
extern struct dpdk_fn_table fn_table_2207;
extern struct dpdk_fn_table fn_table_2211;
static struct dpdk_fn_table *g_dpdk_fn_table;
@ -32,14 +33,22 @@ dpdk_pci_init(void)
return -EINVAL;
}
/* Anything greater than 22.07 is not supported. */
if (year == 22 && month > 7) {
SPDK_ERRLOG("DPDK version %d.%02d.%d not supported.\n", year, month, minor);
return -EINVAL;
if (year == 22 && month == 11) {
if (minor != 0) {
/* It is possible that LTS minor release changed private ABI, so we
* cannot assume fn_table_2211 works for minor releases. As 22.11
* minor releases occur, this will need to be updated to either affirm
* no ABI changes for the minor release, or add new header files and
* pci_dpdk_xxx.c implementation for the new minor release.
*/
SPDK_ERRLOG("DPDK LTS version 22.11.%d not supported.\n", minor);
return -EINVAL;
}
g_dpdk_fn_table = &fn_table_2211;
} else {
/* Everything else we use the 22.07 implementation. */
g_dpdk_fn_table = &fn_table_2207;
}
/* Everything else we use the 22.07 implementation. */
g_dpdk_fn_table = &fn_table_2207;
return 0;
}

View File

@ -0,0 +1,221 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#define ALLOW_INTERNAL_API
#include <rte_config.h>
#include <rte_version.h>
#include "pci_dpdk.h"
#include "22.11/bus_pci_driver.h"
#include "22.11/bus_driver.h"
#include "22.11/rte_bus_pci.h"
#include "spdk/assert.h"
SPDK_STATIC_ASSERT(offsetof(struct spdk_pci_driver, driver_buf) == 0, "driver_buf must be first");
SPDK_STATIC_ASSERT(offsetof(struct spdk_pci_driver, driver) >= sizeof(struct rte_pci_driver),
"driver_buf not big enough");
static struct rte_mem_resource *
pci_device_get_mem_resource_2211(struct rte_pci_device *dev, uint32_t bar)
{
if (bar >= PCI_MAX_RESOURCE) {
assert(false);
return NULL;
}
return &dev->mem_resource[bar];
}
static const char *
pci_device_get_name_2211(struct rte_pci_device *rte_dev)
{
return rte_dev->name;
}
static struct rte_devargs *
pci_device_get_devargs_2211(struct rte_pci_device *rte_dev)
{
return rte_dev->device.devargs;
}
static struct rte_pci_addr *
pci_device_get_addr_2211(struct rte_pci_device *_dev)
{
return &_dev->addr;
}
static struct rte_pci_id *
pci_device_get_id_2211(struct rte_pci_device *_dev)
{
return &_dev->id;
}
static int
pci_device_get_numa_node_2211(struct rte_pci_device *_dev)
{
return _dev->device.numa_node;
}
static int
pci_device_read_config_2211(struct rte_pci_device *dev, void *value, uint32_t len, uint32_t offset)
{
int rc;
rc = rte_pci_read_config(dev, value, len, offset);
return (rc > 0 && (uint32_t) rc == len) ? 0 : -1;
}
static int
pci_device_write_config_2211(struct rte_pci_device *dev, void *value, uint32_t len, uint32_t offset)
{
int rc;
rc = rte_pci_write_config(dev, value, len, offset);
#ifdef __FreeBSD__
/* DPDK returns 0 on success and -1 on failure */
return rc;
#endif
return (rc > 0 && (uint32_t) rc == len) ? 0 : -1;
}
/* translate spdk_pci_driver to an rte_pci_driver and register it to dpdk */
static int
pci_driver_register_2211(struct spdk_pci_driver *driver,
int (*probe_fn)(struct rte_pci_driver *driver, struct rte_pci_device *device),
int (*remove_fn)(struct rte_pci_device *device))
{
unsigned pci_id_count = 0;
struct rte_pci_id *rte_id_table;
char *rte_name;
size_t rte_name_len;
uint32_t rte_flags;
assert(driver->id_table);
while (driver->id_table[pci_id_count].vendor_id) {
pci_id_count++;
}
assert(pci_id_count > 0);
rte_id_table = calloc(pci_id_count + 1, sizeof(*rte_id_table));
if (!rte_id_table) {
return -ENOMEM;
}
while (pci_id_count > 0) {
struct rte_pci_id *rte_id = &rte_id_table[pci_id_count - 1];
const struct spdk_pci_id *spdk_id = &driver->id_table[pci_id_count - 1];
rte_id->class_id = spdk_id->class_id;
rte_id->vendor_id = spdk_id->vendor_id;
rte_id->device_id = spdk_id->device_id;
rte_id->subsystem_vendor_id = spdk_id->subvendor_id;
rte_id->subsystem_device_id = spdk_id->subdevice_id;
pci_id_count--;
}
assert(driver->name);
rte_name_len = strlen(driver->name) + strlen("spdk_") + 1;
rte_name = calloc(rte_name_len, 1);
if (!rte_name) {
free(rte_id_table);
return -ENOMEM;
}
snprintf(rte_name, rte_name_len, "spdk_%s", driver->name);
driver->driver->driver.name = rte_name;
driver->driver->id_table = rte_id_table;
rte_flags = 0;
if (driver->drv_flags & SPDK_PCI_DRIVER_NEED_MAPPING) {
rte_flags |= RTE_PCI_DRV_NEED_MAPPING;
}
if (driver->drv_flags & SPDK_PCI_DRIVER_WC_ACTIVATE) {
rte_flags |= RTE_PCI_DRV_WC_ACTIVATE;
}
driver->driver->drv_flags = rte_flags;
driver->driver->probe = probe_fn;
driver->driver->remove = remove_fn;
rte_pci_register(driver->driver);
return 0;
}
static int
pci_device_enable_interrupt_2211(struct rte_pci_device *rte_dev)
{
return rte_intr_enable(rte_dev->intr_handle);
}
static int
pci_device_disable_interrupt_2211(struct rte_pci_device *rte_dev)
{
return rte_intr_disable(rte_dev->intr_handle);
}
static int
pci_device_get_interrupt_efd_2211(struct rte_pci_device *rte_dev)
{
return rte_intr_fd_get(rte_dev->intr_handle);
}
static int
bus_probe_2211(void)
{
return rte_bus_probe();
}
static void
bus_scan_2211(void)
{
rte_bus_scan();
}
static struct rte_devargs *
device_get_devargs_2211(struct rte_device *dev)
{
return dev->devargs;
}
static void
device_set_devargs_2211(struct rte_device *dev, struct rte_devargs *devargs)
{
dev->devargs = devargs;
}
static const char *
device_get_name_2211(struct rte_device *dev)
{
return dev->name;
}
static bool
device_scan_allowed_2211(struct rte_device *dev)
{
return dev->bus->conf.scan_mode == RTE_BUS_SCAN_ALLOWLIST;
}
struct dpdk_fn_table fn_table_2211 = {
.pci_device_get_mem_resource = pci_device_get_mem_resource_2211,
.pci_device_get_name = pci_device_get_name_2211,
.pci_device_get_devargs = pci_device_get_devargs_2211,
.pci_device_get_addr = pci_device_get_addr_2211,
.pci_device_get_id = pci_device_get_id_2211,
.pci_device_get_numa_node = pci_device_get_numa_node_2211,
.pci_device_read_config = pci_device_read_config_2211,
.pci_device_write_config = pci_device_write_config_2211,
.pci_driver_register = pci_driver_register_2211,
.pci_device_enable_interrupt = pci_device_enable_interrupt_2211,
.pci_device_disable_interrupt = pci_device_disable_interrupt_2211,
.pci_device_get_interrupt_efd = pci_device_get_interrupt_efd_2211,
.bus_scan = bus_scan_2211,
.bus_probe = bus_probe_2211,
.device_get_devargs = device_get_devargs_2211,
.device_set_devargs = device_set_devargs_2211,
.device_get_name = device_get_name_2211,
.device_scan_allowed = device_scan_allowed_2211,
};