vlib: Add support for pci io read/write

Change-Id: I9d96e7782a12c2e19eacbb75edb1fb450cf33bed
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
This commit is contained in:
Mohsin Kazmi
2018-09-28 11:45:01 +02:00
committed by Damjan Marion
parent 901d16cced
commit 95276ca5ca
2 changed files with 108 additions and 31 deletions

View 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)
{

View 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 *