Hello Stephen, - It looks a bit odd to me, we end up with something asymetric between uio / vfio wrt pci config space. Can we an api consistent between the two ? Does this mean that your pmd cannot work / has not been used with vfio ?
- Anyway, I suppose we could reuse this api to remove the RTE_PCI_CONFIG #ifdef / hardcoded stuff from linux eal / igb_uio. Opinion ? -- David Marchand On Fri, Feb 6, 2015 at 7:36 PM, Stephen Hemminger < stephen at networkplumber.org> wrote: > From: Stephen Hemminger <shemming at brocade.com> > > Some drivers need ability to access PCI config (for example for power > management). This adds an abstraction to do this; only implemented > on Linux, but should be possible on BSD. > > Signed-off-by: Stephen Hemminger <stephen at networkplumber.org> > --- > lib/librte_eal/common/include/rte_pci.h | 29 > +++++++++++++++++++++++++ > lib/librte_eal/linuxapp/eal/eal_pci.c | 15 +++++++++++++ > lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 10 +++++++++ > lib/librte_eal/linuxapp/eal/rte_eal_version.map | 2 ++ > 4 files changed, 56 insertions(+) > > diff --git a/lib/librte_eal/common/include/rte_pci.h > b/lib/librte_eal/common/include/rte_pci.h > index 66ed793..a78081f 100644 > --- a/lib/librte_eal/common/include/rte_pci.h > +++ b/lib/librte_eal/common/include/rte_pci.h > @@ -152,6 +152,7 @@ struct rte_pci_device { > uint16_t max_vfs; /**< sriov enable if not > zero */ > int numa_node; /**< NUMA node connection > */ > struct rte_devargs *devargs; /**< Device user arguments > */ > + int config_fd; /**< PCI config access */ > }; > > /** Any PCI device identifier (vendor, device, ...) */ > @@ -298,6 +299,34 @@ 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 size > + * The length of the data buffer. > + */ > +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 size > + * The length of the data buffer. > + */ > +int rte_eal_pci_write_config(const struct rte_pci_device *device, > + const void *buf, size_t len, off_t offset); > + > #ifdef __cplusplus > } > #endif > diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c > b/lib/librte_eal/linuxapp/eal/eal_pci.c > index b5f5410..5bcfffa 100644 > --- a/lib/librte_eal/linuxapp/eal/eal_pci.c > +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c > @@ -233,6 +233,7 @@ pci_scan_one(const char *dirname, uint16_t domain, > uint8_t bus, > dev->addr.bus = bus; > dev->addr.devid = devid; > dev->addr.function = function; > + dev->config_fd = -1; > > /* get vendor id */ > snprintf(filename, sizeof(filename), "%s/vendor", dirname); > @@ -592,6 +593,20 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver > *dr, struct rte_pci_device *d > return 1; > } > > +/* Read PCI config space. */ > +int rte_eal_pci_read_config(const struct rte_pci_device *device, > + void *buf, size_t len, off_t offset) > +{ > + return pread(device->config_fd, buf, len, offset); > +} > + > +/* 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) > +{ > + return pwrite(device->config_fd, buf, len, offset); > +} > + > /* Init the PCI EAL subsystem */ > int > rte_eal_pci_init(void) > diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > index e53f06b..0396eaa 100644 > --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c > @@ -213,6 +213,7 @@ pci_get_uio_dev(struct rte_pci_device *dev, char > *dstbuf, > struct dirent *e; > DIR *dir; > char dirname[PATH_MAX]; > + char filename[PATH_MAX]; > > /* depending on kernel version, uio can be located in uio/uioX > * or uio:uioX */ > @@ -268,6 +269,15 @@ pci_get_uio_dev(struct rte_pci_device *dev, char > *dstbuf, > if (e == NULL) > return -1; > > + /* Open fd for access to PCI config */ > + snprintf(filename, sizeof(filename), "%s/device/config", dirname); > + dev->config_fd = open(filename, O_RDWR); > + if (dev->config_fd < 0) { > + RTE_LOG(ERR, EAL, "%s(): cannot open %s: %s\n", > + __func__, filename, strerror(errno)); > + return -1; > + } > + > /* create uio device if we've been asked to */ > if (internal_config.create_uio_dev && > pci_mknod_uio_dev(dstbuf, uio_num) < 0) > diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map > b/lib/librte_eal/linuxapp/eal/rte_eal_version.map > index d36286e..626689c 100644 > --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map > +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map > @@ -40,6 +40,8 @@ DPDK_2.0 { > rte_eal_pci_probe; > rte_eal_pci_register; > rte_eal_pci_unregister; > + rte_eal_pci_read_config; > + rte_eal_pci_write_config; > rte_eal_process_type; > rte_eal_remote_launch; > rte_eal_tailq_lookup; > -- > 2.1.4 > >