vlib: Add support for pci io read/write 79/15479/2
authorMohsin Kazmi <sykazmi@cisco.com>
Fri, 28 Sep 2018 09:45:01 +0000 (11:45 +0200)
committerDamjan Marion <dmarion@me.com>
Tue, 23 Oct 2018 18:51:43 +0000 (18:51 +0000)
Change-Id: I9d96e7782a12c2e19eacbb75edb1fb450cf33bed
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
src/vlib/linux/pci.c
src/vlib/pci/pci.h

index 0e2241b..724bb9d 100644 (file)
@@ -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)
 {
index e0eacf4..1c70cc7 100644 (file)
@@ -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 *