This implementation just acts as a simple wrapper around pci-vfio. This could grow if other pci access (such as user-io) get involved.
Signed-off-by: Christophe Milard <christophe.mil...@linaro.org> --- platform/linux-generic/Makefile.am | 1 + platform/linux-generic/odp_pci.c | 190 +++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 platform/linux-generic/odp_pci.c diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 6a08811..999c932 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -139,6 +139,7 @@ __LIB__libodp_la_SOURCES = \ odp_packet.c \ odp_packet_flags.c \ odp_packet_io.c \ + odp_pci.c \ odp_pci_vfio.c \ pktio/io_ops.c \ pktio/pktio_common.c \ diff --git a/platform/linux-generic/odp_pci.c b/platform/linux-generic/odp_pci.c new file mode 100644 index 0000000..7cce69f --- /dev/null +++ b/platform/linux-generic/odp_pci.c @@ -0,0 +1,190 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdio.h> +#include <linux/limits.h> +#include <stdlib.h> +#include <odp/dma.h> +#include <odp/pci.h> +#include <odp_debug_internal.h> +#include <odp_pci_internal.h> +#include <odp_pci_vfio_internal.h> + +#define SYSFS_PCI_DEVICES "/sys/bus/pci/devices" + +/* operations on PCI devices: */ + +uint16_t odp_pci_get_vendor(odp_pci_dev_t dev_hdl) +{ + return ((pci_dev_t *)dev_hdl)->pci_id.vendor_id; +} + +uint16_t odp_pci_get_device(odp_pci_dev_t dev_hdl) +{ + return ((pci_dev_t *)dev_hdl)->pci_id.device_id; +} + +uint16_t odp_pci_get_subsystem_vendor(odp_pci_dev_t dev_hdl) +{ + return ((pci_dev_t *)dev_hdl)->pci_id.subsystem_vendor_id; +} + +uint16_t odp_pci_get_subsystem_device(odp_pci_dev_t dev_hdl) +{ + return ((pci_dev_t *)dev_hdl)->pci_id.subsystem_device_id; +} + +void *odp_pci_get_resource_addr(odp_pci_dev_t dev_hdl, int bar) +{ + return ((pci_dev_t *)dev_hdl)->bar_maps[bar].addr; +} + +char *odp_pci_get_addr_str(odp_pci_dev_t dev_hdl) +{ + return ((pci_dev_t *)dev_hdl)->pci_address; +} + +/* + * parse a sysfs (or other) file containing one integer value + */ +static int parse_sysfs_value(const char *filename, unsigned long *val) +{ + FILE *f; + char buf[BUFSIZ]; + char *end = NULL; + + f = fopen(filename, "r"); + if (!f) { + ODP_ERR("%s(): cannot open sysfs value %s\n", + __func__, filename); + return -1; + } + + if (fgets(buf, sizeof(buf), f) == NULL) { + ODP_ERR("%s(): cannot read sysfs value %s\n", + __func__, filename); + fclose(f); + return -1; + } + *val = strtoul(buf, &end, 0); + if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { + ODP_ERR("%s(): cannot parse sysfs value %s\n", + __func__, filename); + fclose(f); + return -1; + } + fclose(f); + return 0; +} + +odp_pci_dev_t _odp_pci_init(const char *pci_addr) +{ + char filename[PATH_MAX]; + unsigned long tmp; + pci_dev_t *dev; + + dev = malloc(sizeof(pci_dev_t)); + if (!dev) + return NULL; + + /* currentely only vfio is supported */ + if (_odp_pci_vfio_init(pci_addr, dev) < 0) + goto pci_init_err; + + /* get vendor id */ + snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/%s/vendor", + pci_addr); + if (parse_sysfs_value(filename, &tmp) < 0) + goto pci_init_err; + + dev->pci_id.vendor_id = (uint16_t)tmp; + + /* get device id */ + snprintf(filename, sizeof(filename), SYSFS_PCI_DEVICES "/%s/device", + pci_addr); + if (parse_sysfs_value(filename, &tmp) < 0) + goto pci_init_err; + + dev->pci_id.device_id = (uint16_t)tmp; + + /* get subsystem_vendor id */ + snprintf(filename, sizeof(filename), + SYSFS_PCI_DEVICES "/%s/subsystem_vendor", + pci_addr); + if (parse_sysfs_value(filename, &tmp) < 0) + goto pci_init_err; + + dev->pci_id.subsystem_vendor_id = (uint16_t)tmp; + + /* get subsystem_device id */ + snprintf(filename, sizeof(filename), + SYSFS_PCI_DEVICES "/%s/subsystem_device", + pci_addr); + if (parse_sysfs_value(filename, &tmp) < 0) + goto pci_init_err; + + dev->pci_id.subsystem_device_id = (uint16_t)tmp; + + return (odp_pci_dev_t)dev; + +pci_init_err: + free(dev); + return NULL; +} + +void _odp_pci_release(odp_pci_dev_t pci_dev) +{ + /* currentely only vfio is supported */ + _odp_pci_vfio_release((pci_dev_t *)pci_dev); + free(pci_dev); +} + +int odp_pci_map_dma_region(odp_pci_dev_t dev_hdl, + odp_dma_map_t region) +{ + pci_dev_t *dev = (pci_dev_t *)dev_hdl; + dma_map_t *map_s = dma_map_handle_to_map(region); + + /* map fragments one by one */ + /* currentely only vfio is supported */ + do { + if (_odp_pci_vfio_map_dma_region_f(dev, map_s)) { + /* remove partially mapped region: */ + odp_pci_unmap_dma_region(dev_hdl, region); + return -1; + } + map_s = map_s->next; + } while (map_s); + + return 0; +} + +int odp_pci_unmap_dma_region(odp_pci_dev_t dev_hdl, + odp_dma_map_t region) +{ + pci_dev_t *dev = (pci_dev_t *)dev_hdl; + dma_map_t *map_s = dma_map_handle_to_map(region); + + /* unmap fragments one by one */ + /* currentely only vfio is supported */ + do { + _odp_pci_vfio_unmap_dma_region_f(dev, map_s); + map_s = map_s->next; + } while (map_s); + + return 0; +} + +int odp_pci_read_config(odp_pci_dev_t dev, void *buf, size_t len, int offs) +{ + return _odp_pci_vfio_read_config((pci_dev_t *)dev, buf, len, offs); +} + +int odp_pci_write_config(odp_pci_dev_t dev, const void *buf, + size_t len, int offs) +{ + return _odp_pci_vfio_write_config((pci_dev_t *)dev, buf, len, offs); +} -- 2.1.4 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp