From 95276ca5ca0a97ea7e0b5828f434743b6a745274 Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Fri, 28 Sep 2018 11:45:01 +0200 Subject: [PATCH] vlib: Add support for pci io read/write Change-Id: I9d96e7782a12c2e19eacbb75edb1fb450cf33bed Signed-off-by: Mohsin Kazmi --- src/vlib/linux/pci.c | 98 ++++++++++++++++++++++++++++++++++++++++++---------- src/vlib/pci/pci.h | 41 +++++++++++++++------- 2 files changed, 108 insertions(+), 31 deletions(-) diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c index 0e2241b0e58..724bb9d3a4a 100644 --- a/src/vlib/linux/pci.c +++ b/src/vlib/linux/pci.c @@ -108,6 +108,10 @@ typedef struct /* Device File descriptor */ int fd; + /* read/write file descriptor for io bar */ + int io_fd; + u64 io_offset; + /* Minor device for uio device. */ u32 uio_minor; @@ -1005,21 +1009,18 @@ vlib_pci_read_write_config (vlib_main_t * vm, vlib_pci_dev_handle_t h, } static clib_error_t * -vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h, - u32 bar, u8 * addr, void **result) +vlib_pci_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 bar, int *fd, + u64 * size, u64 * offset) { linux_pci_device_t *p = linux_pci_get_device (h); - int fd = -1; - clib_error_t *error; - int flags = MAP_SHARED; - u64 size = 0, offset = 0; + clib_error_t *error = 0; + int _fd = -1; + u64 _size = 0, _offset = 0; ASSERT (bar <= 5); error = 0; - pci_log_debug (vm, p, "map region %u to va %p", bar, addr); - if (p->type == LINUX_PCI_DEVICE_TYPE_UIO) { u8 *file_name; @@ -1027,27 +1028,25 @@ vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h, file_name = format (0, "%s/%U/resource%d%c", sysfs_pci_dev_path, format_vlib_pci_addr, &p->addr, bar, 0); - fd = open ((char *) file_name, O_RDWR); - if (fd < 0) + _fd = open ((char *) file_name, O_RDWR); + if (_fd < 0) { error = clib_error_return_unix (0, "open `%s'", file_name); vec_free (file_name); return error; } - if (fstat (fd, &stat_buf) < 0) + if (fstat (_fd, &stat_buf) < 0) { error = clib_error_return_unix (0, "fstat `%s'", file_name); vec_free (file_name); - close (fd); + close (_fd); return error; } vec_free (file_name); - if (addr != 0) - flags |= MAP_FIXED; - size = stat_buf.st_size; - offset = 0; + _size = stat_buf.st_size; + _offset = 0; } else if (p->type == LINUX_PCI_DEVICE_TYPE_VFIO) { @@ -1058,9 +1057,9 @@ vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h, return clib_error_return_unix (0, "ioctl(VFIO_DEVICE_GET_INFO) " "'%U'", format_vlib_pci_addr, &p->addr); - fd = p->fd; - size = reg.size; - offset = reg.offset; + _fd = p->fd; + _size = reg.size; + _offset = reg.offset; pci_log_debug (vm, p, "%s region_info index:%u size:0x%lx offset:0x%lx " "flags: %s%s%s(0x%x)", __func__, reg.index, reg.size, reg.offset, @@ -1072,6 +1071,31 @@ vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h, else ASSERT (0); + *fd = _fd; + *size = _size; + *offset = _offset; + + return error; +} + +static clib_error_t * +vlib_pci_map_region_int (vlib_main_t * vm, vlib_pci_dev_handle_t h, + u32 bar, u8 * addr, void **result) +{ + linux_pci_device_t *p = linux_pci_get_device (h); + int fd = -1; + clib_error_t *error; + int flags = MAP_SHARED; + u64 size = 0, offset = 0; + + pci_log_debug (vm, p, "map region %u to va %p", bar, addr); + + if ((error = vlib_pci_region (vm, h, bar, &fd, &size, &offset))) + return error; + + if (p->type == LINUX_PCI_DEVICE_TYPE_UIO && addr != 0) + flags |= MAP_FIXED; + *result = mmap (addr, size, PROT_READ | PROT_WRITE, flags, fd, offset); if (*result == (void *) -1) { @@ -1106,6 +1130,42 @@ vlib_pci_map_region_fixed (vlib_main_t * vm, vlib_pci_dev_handle_t h, return (vlib_pci_map_region_int (vm, h, resource, addr, result)); } +clib_error_t * +vlib_pci_io_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 resource) +{ + linux_pci_device_t *p = linux_pci_get_device (h); + clib_error_t *error = 0; + int fd = -1; + u64 size = 0, offset = 0; + + if ((error = vlib_pci_region (vm, h, resource, &fd, &size, &offset))) + return error; + + p->io_fd = fd; + p->io_offset = offset; + return error; +} + +clib_error_t * +vlib_pci_read_write_io (vlib_main_t * vm, vlib_pci_dev_handle_t h, + vlib_read_or_write_t read_or_write, + uword offset, void *data, u32 length) +{ + linux_pci_device_t *p = linux_pci_get_device (h); + int n = 0; + + if (read_or_write == VLIB_READ) + n = pread (p->io_fd, data, length, p->io_offset + offset); + else + n = pwrite (p->io_fd, data, length, p->io_offset + offset); + + if (n != length) + return clib_error_return_unix (0, "%s", + read_or_write == VLIB_READ + ? "read" : "write"); + return 0; +} + clib_error_t * vlib_pci_map_dma (vlib_main_t * vm, vlib_pci_dev_handle_t h, void *ptr) { diff --git a/src/vlib/pci/pci.h b/src/vlib/pci/pci.h index e0eacf42948..1c70cc7bb80 100644 --- a/src/vlib/pci/pci.h +++ b/src/vlib/pci/pci.h @@ -186,33 +186,48 @@ clib_error_t *vlib_pci_read_write_config (vlib_main_t * vm, uword address, void *data, u32 n_bytes); -#define _(t) \ +/* io space read/write. */ +clib_error_t *vlib_pci_read_write_io (vlib_main_t * vm, + vlib_pci_dev_handle_t handle, + vlib_read_or_write_t read_or_write, + uword address, void *data, u32 n_bytes); + + +#define _(t, x) \ static inline clib_error_t * \ -vlib_pci_read_config_##t (vlib_main_t *vm, vlib_pci_dev_handle_t h, \ +vlib_pci_read_##x##_##t (vlib_main_t *vm, vlib_pci_dev_handle_t h, \ uword address, t * data) \ { \ - return vlib_pci_read_write_config (vm, h, VLIB_READ,address, data, \ + return vlib_pci_read_write_##x (vm, h, VLIB_READ,address, data, \ sizeof (data[0])); \ } -_(u32); -_(u16); -_(u8); +_(u32, config); +_(u16, config); +_(u8, config); + +_(u32, io); +_(u16, io); +_(u8, io); #undef _ -#define _(t) \ +#define _(t, x) \ static inline clib_error_t * \ -vlib_pci_write_config_##t (vlib_main_t *vm, vlib_pci_dev_handle_t h, \ +vlib_pci_write_##x##_##t (vlib_main_t *vm, vlib_pci_dev_handle_t h, \ uword address, t * data) \ { \ - return vlib_pci_read_write_config (vm, h, VLIB_WRITE, \ + return vlib_pci_read_write_##x (vm, h, VLIB_WRITE, \ address, data, sizeof (data[0])); \ } -_(u32); -_(u16); -_(u8); +_(u32, config); +_(u16, config); +_(u8, config); + +_(u32, io); +_(u16, io); +_(u8, io); #undef _ @@ -278,6 +293,8 @@ clib_error_t *vlib_pci_map_region_fixed (vlib_main_t * vm, vlib_pci_dev_handle_t h, u32 resource, u8 * addr, void **result); +clib_error_t *vlib_pci_io_region (vlib_main_t * vm, vlib_pci_dev_handle_t h, + u32 resource); clib_error_t *vlib_pci_register_intx_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, pci_intx_handler_function_t * -- 2.16.6