eal: provide functions to access PCI config
Some drivers need ability to access PCI config (for example for power management). This adds an abstraction to do this for both Linux and BSD. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Acked-by: Harish Patil <harish.patil@qlogic.com>
This commit is contained in:
parent
d12b6da14b
commit
632b2d1dee
@ -396,6 +396,89 @@ rte_eal_pci_scan(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read PCI config space. */
|
||||
int rte_eal_pci_read_config(const struct rte_pci_device *dev,
|
||||
void *buf, size_t len, off_t offset)
|
||||
{
|
||||
int fd = -1;
|
||||
struct pci_io pi = {
|
||||
.pi_sel = {
|
||||
.pc_domain = dev->addr.domain,
|
||||
.pc_bus = dev->addr.bus,
|
||||
.pc_dev = dev->addr.devid,
|
||||
.pc_func = dev->addr.function,
|
||||
},
|
||||
.pi_reg = offset,
|
||||
.pi_width = len,
|
||||
};
|
||||
|
||||
if (len == 3 || len > sizeof(pi.pi_data)) {
|
||||
RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
fd = open("/dev/pci", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ioctl(fd, PCIOCREAD, &pi) < 0)
|
||||
goto error;
|
||||
close(fd);
|
||||
|
||||
memcpy(buf, &pi.pi_data, len);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write PCI config space. */
|
||||
int rte_eal_pci_write_config(const struct rte_pci_device *dev,
|
||||
const void *buf, size_t len, off_t offset)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
struct pci_io pi = {
|
||||
.pi_sel = {
|
||||
.pc_domain = dev->addr.domain,
|
||||
.pc_bus = dev->addr.bus,
|
||||
.pc_dev = dev->addr.devid,
|
||||
.pc_func = dev->addr.function,
|
||||
},
|
||||
.pi_reg = offset,
|
||||
.pi_data = *(u_int32_t *)buf,
|
||||
.pi_width = len,
|
||||
};
|
||||
|
||||
if (len == 3 || len > sizeof(pi.pi_data)) {
|
||||
RTE_LOG(ERR, EAL, "%s(): invalid pci read length\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(pi.pi_data, buf, len);
|
||||
|
||||
fd = open("/dev/pci", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ioctl(fd, PCIOCWRITE, &pi) < 0)
|
||||
goto error;
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Init the PCI EAL subsystem */
|
||||
int
|
||||
rte_eal_pci_init(void)
|
||||
|
@ -116,6 +116,8 @@ DPDK_2.1 {
|
||||
global:
|
||||
|
||||
rte_eal_pci_detach;
|
||||
rte_eal_pci_read_config;
|
||||
rte_eal_pci_write_config;
|
||||
rte_memzone_free;
|
||||
|
||||
} DPDK_2.0;
|
||||
|
@ -455,6 +455,38 @@ void rte_eal_pci_register(struct rte_pci_driver *driver);
|
||||
*/
|
||||
void rte_eal_pci_unregister(struct rte_pci_driver *driver);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
int rte_eal_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_eal_pci_write_config(const struct rte_pci_device *device,
|
||||
const void *buf, size_t len, off_t offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -571,6 +571,56 @@ pci_config_space_set(struct rte_pci_device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Read PCI config space. */
|
||||
int rte_eal_pci_read_config(const struct rte_pci_device *device,
|
||||
void *buf, size_t len, off_t offset)
|
||||
{
|
||||
const struct rte_intr_handle *intr_handle = &device->intr_handle;
|
||||
|
||||
switch (intr_handle->type) {
|
||||
case RTE_INTR_HANDLE_UIO:
|
||||
case RTE_INTR_HANDLE_UIO_INTX:
|
||||
return pci_uio_read_config(intr_handle, buf, len, offset);
|
||||
|
||||
#ifdef VFIO_PRESENT
|
||||
case RTE_INTR_HANDLE_VFIO_MSIX:
|
||||
case RTE_INTR_HANDLE_VFIO_MSI:
|
||||
case RTE_INTR_HANDLE_VFIO_LEGACY:
|
||||
return pci_vfio_read_config(intr_handle, buf, len, offset);
|
||||
#endif
|
||||
default:
|
||||
RTE_LOG(ERR, EAL,
|
||||
"Unknown handle type of fd %d\n",
|
||||
intr_handle->fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write PCI config space. */
|
||||
int rte_eal_pci_write_config(const struct rte_pci_device *device,
|
||||
const void *buf, size_t len, off_t offset)
|
||||
{
|
||||
const struct rte_intr_handle *intr_handle = &device->intr_handle;
|
||||
|
||||
switch (intr_handle->type) {
|
||||
case RTE_INTR_HANDLE_UIO:
|
||||
case RTE_INTR_HANDLE_UIO_INTX:
|
||||
return pci_uio_write_config(intr_handle, buf, len, offset);
|
||||
|
||||
#ifdef VFIO_PRESENT
|
||||
case RTE_INTR_HANDLE_VFIO_MSIX:
|
||||
case RTE_INTR_HANDLE_VFIO_MSI:
|
||||
case RTE_INTR_HANDLE_VFIO_LEGACY:
|
||||
return pci_vfio_write_config(intr_handle, buf, len, offset);
|
||||
#endif
|
||||
default:
|
||||
RTE_LOG(ERR, EAL,
|
||||
"Unknown handle type of fd %d\n",
|
||||
intr_handle->fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init the PCI EAL subsystem */
|
||||
int
|
||||
rte_eal_pci_init(void)
|
||||
|
@ -49,6 +49,11 @@ void pci_uio_free_resource(struct rte_pci_device *dev,
|
||||
int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
|
||||
struct mapped_pci_resource *uio_res, int map_idx);
|
||||
|
||||
int pci_uio_read_config(const struct rte_intr_handle *intr_handle,
|
||||
void *buf, size_t len, off_t offs);
|
||||
int pci_uio_write_config(const struct rte_intr_handle *intr_handle,
|
||||
const void *buf, size_t len, off_t offs);
|
||||
|
||||
#ifdef VFIO_PRESENT
|
||||
|
||||
#define VFIO_MAX_GROUPS 64
|
||||
@ -57,6 +62,12 @@ int pci_vfio_enable(void);
|
||||
int pci_vfio_is_enabled(void);
|
||||
int pci_vfio_mp_sync_setup(void);
|
||||
|
||||
/* access config space */
|
||||
int pci_vfio_read_config(const struct rte_intr_handle *intr_handle,
|
||||
void *buf, size_t len, off_t offs);
|
||||
int pci_vfio_write_config(const struct rte_intr_handle *intr_handle,
|
||||
const void *buf, size_t len, off_t offs);
|
||||
|
||||
/* map VFIO resource prototype */
|
||||
int pci_vfio_map_resource(struct rte_pci_device *dev);
|
||||
int pci_vfio_get_group_fd(int iommu_group_fd);
|
||||
|
@ -52,6 +52,20 @@ void *pci_map_addr = NULL;
|
||||
|
||||
#define OFF_MAX ((uint64_t)(off_t)-1)
|
||||
|
||||
int
|
||||
pci_uio_read_config(const struct rte_intr_handle *intr_handle,
|
||||
void *buf, size_t len, off_t offset)
|
||||
{
|
||||
return pread(intr_handle->uio_cfg_fd, buf, len, offset);
|
||||
}
|
||||
|
||||
int
|
||||
pci_uio_write_config(const struct rte_intr_handle *intr_handle,
|
||||
const void *buf, size_t len, off_t offset)
|
||||
{
|
||||
return pwrite(intr_handle->uio_cfg_fd, buf, len, offset);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_uio_set_bus_master(int dev_fd)
|
||||
{
|
||||
|
@ -77,6 +77,22 @@ EAL_REGISTER_TAILQ(rte_vfio_tailq)
|
||||
/* per-process VFIO config */
|
||||
static struct vfio_config vfio_cfg;
|
||||
|
||||
int
|
||||
pci_vfio_read_config(const struct rte_intr_handle *intr_handle,
|
||||
void *buf, size_t len, off_t offs)
|
||||
{
|
||||
return pread64(intr_handle->vfio_dev_fd, buf, len,
|
||||
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);
|
||||
}
|
||||
|
||||
int
|
||||
pci_vfio_write_config(const struct rte_intr_handle *intr_handle,
|
||||
const void *buf, size_t len, off_t offs)
|
||||
{
|
||||
return pwrite64(intr_handle->vfio_dev_fd, buf, len,
|
||||
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);
|
||||
}
|
||||
|
||||
/* get PCI BAR number where MSI-X interrupts are */
|
||||
static int
|
||||
pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset,
|
||||
|
@ -116,6 +116,8 @@ DPDK_2.1 {
|
||||
global:
|
||||
|
||||
rte_eal_pci_detach;
|
||||
rte_eal_pci_read_config;
|
||||
rte_eal_pci_write_config;
|
||||
rte_memzone_free;
|
||||
|
||||
} DPDK_2.0;
|
||||
|
Loading…
Reference in New Issue
Block a user