X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Flinux%2Fpci.c;h=b99f54f2a62b7bf5a5ceb0638f0926cd9fef0411;hb=d2bfb78f4f8fbfae204424467a4106530b89e608;hp=69fca9e6098396198f2cf175a9e31478ea5c4333;hpb=2322798bea16ff4092e2361423af6fd451fd1669;p=vpp.git diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c index 69fca9e6098..b99f54f2a62 100644 --- a/src/vlib/linux/pci.c +++ b/src/vlib/linux/pci.c @@ -97,6 +97,7 @@ typedef struct linux_pci_device_type_t type; vlib_pci_dev_handle_t handle; vlib_pci_addr_t addr; + u32 numa_node; /* Resource file descriptors. */ linux_pci_region_t *regions; @@ -108,6 +109,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; @@ -161,6 +166,13 @@ vlib_pci_get_addr (vlib_main_t * vm, vlib_pci_dev_handle_t h) return &d->addr; } +u32 +vlib_pci_get_numa_node (vlib_main_t * vm, vlib_pci_dev_handle_t h) +{ + linux_pci_device_t *d = linux_pci_get_device (h); + return d->numa_node; +} + /* Call to allocate/initialize the pci subsystem. This is not an init function so that users can explicitly enable pci only when it's needed. */ @@ -180,7 +192,7 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr, int fd; di = clib_mem_alloc (sizeof (vlib_pci_device_info_t)); - memset (di, 0, sizeof (vlib_pci_device_info_t)); + clib_memset (di, 0, sizeof (vlib_pci_device_info_t)); di->addr.as_u32 = addr->as_u32; u8 *dev_dir_name = format (0, "%s/%U", sysfs_pci_dev_path, @@ -212,7 +224,7 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr, { static pci_config_header_t all_ones; if (all_ones.vendor_id == 0) - memset (&all_ones, ~0, sizeof (all_ones)); + clib_memset (&all_ones, ~0, sizeof (all_ones)); if (!memcmp (&di->config0.header, &all_ones, sizeof (all_ones))) { @@ -451,8 +463,8 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr, if (e->d_name[0] == '.') /* skip . and .. */ continue; - memset (&ifr, 0, sizeof ifr); - memset (&drvinfo, 0, sizeof drvinfo); + clib_memset (&ifr, 0, sizeof ifr); + clib_memset (&drvinfo, 0, sizeof drvinfo); ifr.ifr_data = (char *) &drvinfo; strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name)); ifr.ifr_name[ARRAY_LEN (ifr.ifr_name) - 1] = '\0'; @@ -469,7 +481,7 @@ vlib_pci_bind_to_uio (vlib_main_t * vm, vlib_pci_addr_t * addr, if (strcmp ((char *) s, drvinfo.bus_info)) continue; - memset (&ifr, 0, sizeof (ifr)); + clib_memset (&ifr, 0, sizeof (ifr)); strncpy (ifr.ifr_name, e->d_name, sizeof (ifr.ifr_name)); ifr.ifr_name[ARRAY_LEN (ifr.ifr_name) - 1] = '\0'; if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0) @@ -580,7 +592,7 @@ vfio_set_irqs (vlib_main_t * vm, linux_pci_device_t * p, u32 index, u32 start, if (efds) { flags |= VFIO_IRQ_SET_DATA_EVENTFD; - clib_memcpy (&irq_set->data, efds, data_len); + clib_memcpy_fast (&irq_set->data, efds, data_len); } else flags |= VFIO_IRQ_SET_DATA_NONE; @@ -951,6 +963,21 @@ add_device_vfio (vlib_main_t * vm, linux_pci_device_t * p, linux_pci_vfio_unmask_intx (vm, p); } + if (p->supports_va_dma) + { + vlib_buffer_pool_t *bp; + /* *INDENT-OFF* */ + vec_foreach (bp, buffer_main.buffer_pools) + { + u32 i; + vlib_physmem_map_t *pm; + pm = vlib_physmem_get_map (vm, bp->physmem_map_index); + for (i = 0; i < pm->n_pages; i++) + vfio_map_physmem_page (vm, pm->base + (i << pm->log2_page_size)); + } + /* *INDENT-ON* */ + } + if (r && r->init_function) err = r->init_function (lpm->vlib_main, p->handle); @@ -990,21 +1017,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; @@ -1012,27 +1036,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) { @@ -1043,9 +1065,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, @@ -1057,6 +1079,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) { @@ -1091,6 +1138,61 @@ 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) +{ + linux_pci_device_t *p = linux_pci_get_device (h); + + if (!p->supports_va_dma) + return 0; + + return vfio_map_physmem_page (vm, ptr); +} + +int +vlib_pci_supports_virtual_addr_dma (vlib_main_t * vm, vlib_pci_dev_handle_t h) +{ + linux_pci_device_t *p = linux_pci_get_device (h); + + return p->supports_va_dma != 0; +} + clib_error_t * vlib_pci_device_open (vlib_main_t * vm, vlib_pci_addr_t * addr, pci_device_id_t ids[], vlib_pci_dev_handle_t * handle) @@ -1116,6 +1218,11 @@ vlib_pci_device_open (vlib_main_t * vm, vlib_pci_addr_t * addr, p->handle = p - lpm->linux_pci_devices; p->addr.as_u32 = di->addr.as_u32; p->intx_irq.fd = -1; + p->numa_node = di->numa_node; + /* + * pci io bar read/write fd + */ + p->io_fd = -1; pci_log_debug (vm, p, "open vid:0x%04x did:0x%04x driver:%s iommu_group:%d", di->vendor_id, di->device_id, di->driver_name, @@ -1138,7 +1245,7 @@ error: if (err) { pci_log_err (vm, p, "%U", format_clib_error, err); - memset (p, 0, sizeof (linux_pci_device_t)); + clib_memset (p, 0, sizeof (linux_pci_device_t)); pool_put (lpm->linux_pci_devices, p); } @@ -1159,6 +1266,8 @@ vlib_pci_device_close (vlib_main_t * vm, vlib_pci_dev_handle_t h) irq = &p->intx_irq; clib_file_del_by_index (&file_main, irq->clib_file_index); close (p->config_fd); + if (p->io_fd != -1) + close (p->io_fd); } else if (p->type == LINUX_PCI_DEVICE_TYPE_VFIO) { @@ -1205,7 +1314,7 @@ vlib_pci_device_close (vlib_main_t * vm, vlib_pci_dev_handle_t h) vec_free (p->regions); close (p->fd); - memset (p, 0, sizeof (linux_pci_device_t)); + clib_memset (p, 0, sizeof (linux_pci_device_t)); pool_put (lpm->linux_pci_devices, p); } @@ -1244,7 +1353,7 @@ init_device_from_registered (vlib_main_t * vm, vlib_pci_device_info_t * di) } /* No driver, close the PCI config-space FD */ - memset (p, 0, sizeof (linux_pci_device_t)); + clib_memset (p, 0, sizeof (linux_pci_device_t)); pool_put (lpm->linux_pci_devices, p); }