All of lore.kernel.org
 help / color / mirror / Atom feed
From: Long Li <longli@microsoft.com>
To: Srikanth Kaka <srikanth.k@oneconvergence.com>,
	Stephen Hemminger <sthemmin@microsoft.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>,
	Vag Singh <vag.singh@oneconvergence.com>,
	Anand Thulasiram <avelu@juniper.net>
Subject: Re: [dpdk-dev] [PATCH 01/11] bus/vmbus: stub for FreeBSD support
Date: Sat, 6 Nov 2021 20:44:35 +0000	[thread overview]
Message-ID: <BY5PR21MB150635EBDC4A738410F06534CE8F9@BY5PR21MB1506.namprd21.prod.outlook.com> (raw)
In-Reply-To: <20210927134231.11177-2-srikanth.k@oneconvergence.com>

> From: Srikanth Kaka <srikanth.k@oneconvergence.com>
> Sent: Monday, September 27, 2021 6:42 AM
> To: Stephen Hemminger <sthemmin@microsoft.com>; Long Li
> <longli@microsoft.com>
> Cc: dev@dpdk.org; Vag Singh <vag.singh@oneconvergence.com>; Anand
> Thulasiram <avelu@juniper.net>; Srikanth Kaka
> <srikanth.k@oneconvergence.com>
> Subject: [PATCH 01/11] bus/vmbus: stub for FreeBSD support
> 
> [You don't often get email from srikanth.k@oneconvergence.com. Learn why
> this is important at http://aka.ms/LearnAboutSenderIdentification.]
> 
> These files are a copy of their Linux equivalents.
> They will be ported to FreeBSD.
> 
> Signed-off-by: Srikanth Kaka <srikanth.k@oneconvergence.com>
> Signed-off-by: Vag Singh <vag.singh@oneconvergence.com>
> Signed-off-by: Anand Thulasiram <avelu@juniper.net>

Reviewed-by: Long Li <longli@microsoft.com>
> ---
>  drivers/bus/vmbus/freebsd/vmbus_bus.c | 376 +++++++++++++++++++++
> drivers/bus/vmbus/freebsd/vmbus_uio.c | 453 ++++++++++++++++++++++++++
>  2 files changed, 829 insertions(+)
>  create mode 100644 drivers/bus/vmbus/freebsd/vmbus_bus.c
>  create mode 100644 drivers/bus/vmbus/freebsd/vmbus_uio.c
> 
> diff --git a/drivers/bus/vmbus/freebsd/vmbus_bus.c
> b/drivers/bus/vmbus/freebsd/vmbus_bus.c
> new file mode 100644
> index 0000000000..3c924eee14
> --- /dev/null
> +++ b/drivers/bus/vmbus/freebsd/vmbus_bus.c
> @@ -0,0 +1,376 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2018, Microsoft Corporation.
> + * All Rights Reserved.
> + */
> +
> +#include <string.h>
> +#include <unistd.h>
> +#include <dirent.h>
> +#include <fcntl.h>
> +#include <sys/mman.h>
> +#include <sys/stat.h>
> +
> +#include <rte_eal.h>
> +#include <rte_uuid.h>
> +#include <rte_tailq.h>
> +#include <rte_log.h>
> +#include <rte_devargs.h>
> +#include <rte_memory.h>
> +#include <rte_malloc.h>
> +#include <rte_bus_vmbus.h>
> +
> +#include "eal_filesystem.h"
> +#include "private.h"
> +
> +/** Pathname of VMBUS devices directory. */ #define SYSFS_VMBUS_DEVICES
> +"/sys/bus/vmbus/devices"
> +
> +/*
> + * GUID associated with network devices
> + * {f8615163-df3e-46c5-913f-f2d2f965ed0e}
> + */
> +static const rte_uuid_t vmbus_nic_uuid = {
> +       0xf8, 0x61, 0x51, 0x63,
> +       0xdf, 0x3e,
> +       0x46, 0xc5,
> +       0x91, 0x3f,
> +       0xf2, 0xd2, 0xf9, 0x65, 0xed, 0xe };
> +
> +extern struct rte_vmbus_bus rte_vmbus_bus;
> +
> +/* Read sysfs file to get UUID */
> +static int
> +parse_sysfs_uuid(const char *filename, rte_uuid_t uu) {
> +       char buf[BUFSIZ];
> +       char *cp, *in = buf;
> +       FILE *f;
> +
> +       f = fopen(filename, "r");
> +       if (f == NULL) {
> +               VMBUS_LOG(ERR, "cannot open sysfs value %s: %s",
> +                         filename, strerror(errno));
> +               return -1;
> +       }
> +
> +       if (fgets(buf, sizeof(buf), f) == NULL) {
> +               VMBUS_LOG(ERR, "cannot read sysfs value %s",
> +                               filename);
> +               fclose(f);
> +               return -1;
> +       }
> +       fclose(f);
> +
> +       cp = strchr(buf, '\n');
> +       if (cp)
> +               *cp = '\0';
> +
> +       /* strip { } notation */
> +       if (buf[0] == '{') {
> +               in = buf + 1;
> +               cp = strchr(in, '}');
> +               if (cp)
> +                       *cp = '\0';
> +       }
> +
> +       if (rte_uuid_parse(in, uu) < 0) {
> +               VMBUS_LOG(ERR, "%s %s not a valid UUID",
> +                       filename, buf);
> +               return -1;
> +       }
> +
> +       return 0;
> +}
> +
> +static int
> +get_sysfs_string(const char *filename, char *buf, size_t buflen) {
> +       char *cp;
> +       FILE *f;
> +
> +       f = fopen(filename, "r");
> +       if (f == NULL) {
> +               VMBUS_LOG(ERR, "cannot open sysfs value %s:%s",
> +                         filename, strerror(errno));
> +               return -1;
> +       }
> +
> +       if (fgets(buf, buflen, f) == NULL) {
> +               VMBUS_LOG(ERR, "cannot read sysfs value %s",
> +                               filename);
> +               fclose(f);
> +               return -1;
> +       }
> +       fclose(f);
> +
> +       /* remove trailing newline */
> +       cp = memchr(buf, '\n', buflen);
> +       if (cp)
> +               *cp = '\0';
> +
> +       return 0;
> +}
> +
> +static int
> +vmbus_get_uio_dev(const struct rte_vmbus_device *dev,
> +                 char *dstbuf, size_t buflen) {
> +       char dirname[PATH_MAX];
> +       unsigned int uio_num;
> +       struct dirent *e;
> +       DIR *dir;
> +
> +       /* Assume recent kernel where uio is in uio/uioX */
> +       snprintf(dirname, sizeof(dirname),
> +                SYSFS_VMBUS_DEVICES "/%s/uio", dev->device.name);
> +
> +       dir = opendir(dirname);
> +       if (dir == NULL)
> +               return -1; /* Not a UIO device */
> +
> +       /* take the first file starting with "uio" */
> +       while ((e = readdir(dir)) != NULL) {
> +               const int prefix_len = 3;
> +               char *endptr;
> +
> +               if (strncmp(e->d_name, "uio", prefix_len) != 0)
> +                       continue;
> +
> +               /* try uio%d */
> +               errno = 0;
> +               uio_num = strtoull(e->d_name + prefix_len, &endptr, 10);
> +               if (errno == 0 && endptr != (e->d_name + prefix_len)) {
> +                       snprintf(dstbuf, buflen, "%s/uio%u", dirname, uio_num);
> +                       break;
> +               }
> +       }
> +       closedir(dir);
> +
> +       if (e == NULL)
> +               return -1;
> +
> +       return uio_num;
> +}
> +
> +/* Check map names with kernel names */ static const char
> +*map_names[VMBUS_MAX_RESOURCE] = {
> +       [HV_TXRX_RING_MAP] = "txrx_rings",
> +       [HV_INT_PAGE_MAP]  = "int_page",
> +       [HV_MON_PAGE_MAP]  = "monitor_page",
> +       [HV_RECV_BUF_MAP]  = "recv:",
> +       [HV_SEND_BUF_MAP]  = "send:",
> +};
> +
> +
> +/* map the resources of a vmbus device in virtual memory */ int
> +rte_vmbus_map_device(struct rte_vmbus_device *dev) {
> +       char uioname[PATH_MAX], filename[PATH_MAX];
> +       char dirname[PATH_MAX], mapname[64];
> +       int i;
> +
> +       dev->uio_num = vmbus_get_uio_dev(dev, uioname, sizeof(uioname));
> +       if (dev->uio_num < 0) {
> +               VMBUS_LOG(DEBUG, "Not managed by UIO driver, skipped");
> +               return 1;
> +       }
> +
> +       /* Extract resource value */
> +       for (i = 0; i < VMBUS_MAX_RESOURCE; i++) {
> +               struct rte_mem_resource *res = &dev->resource[i];
> +               unsigned long len, gpad = 0;
> +               char *cp;
> +
> +               snprintf(dirname, sizeof(dirname),
> +                        "%s/maps/map%d", uioname, i);
> +
> +               snprintf(filename, sizeof(filename),
> +                        "%s/name", dirname);
> +
> +               if (get_sysfs_string(filename, mapname, sizeof(mapname)) < 0) {
> +                       VMBUS_LOG(ERR, "could not read %s", filename);
> +                       return -1;
> +               }
> +
> +               if (strncmp(map_names[i], mapname, strlen(map_names[i])) != 0) {
> +                       VMBUS_LOG(ERR,
> +                               "unexpected resource %s (expected %s)",
> +                               mapname, map_names[i]);
> +                       return -1;
> +               }
> +
> +               snprintf(filename, sizeof(filename),
> +                        "%s/size", dirname);
> +               if (eal_parse_sysfs_value(filename, &len) < 0) {
> +                       VMBUS_LOG(ERR,
> +                               "could not read %s", filename);
> +                       return -1;
> +               }
> +               res->len = len;
> +
> +               /* both send and receive buffers have gpad in name */
> +               cp = memchr(mapname, ':', sizeof(mapname));
> +               if (cp)
> +                       gpad = strtoul(cp+1, NULL, 0);
> +
> +               /* put the GPAD value in physical address */
> +               res->phys_addr = gpad;
> +       }
> +
> +       return vmbus_uio_map_resource(dev); }
> +
> +void
> +rte_vmbus_unmap_device(struct rte_vmbus_device *dev) {
> +       vmbus_uio_unmap_resource(dev);
> +}
> +
> +/* Scan one vmbus sysfs entry, and fill the devices list from it. */
> +static int vmbus_scan_one(const char *name) {
> +       struct rte_vmbus_device *dev, *dev2;
> +       char filename[PATH_MAX];
> +       char dirname[PATH_MAX];
> +       unsigned long tmp;
> +
> +       dev = calloc(1, sizeof(*dev));
> +       if (dev == NULL)
> +               return -1;
> +
> +       dev->device.bus = &rte_vmbus_bus.bus;
> +       dev->device.name = strdup(name);
> +       if (!dev->device.name)
> +               goto error;
> +
> +       /* sysfs base directory
> +        *   /sys/bus/vmbus/devices/7a08391f-f5a0-4ac0-9802-d13fd964f8df
> +        * or on older kernel
> +        *   /sys/bus/vmbus/devices/vmbus_1
> +        */
> +       snprintf(dirname, sizeof(dirname), "%s/%s",
> +                SYSFS_VMBUS_DEVICES, name);
> +
> +       /* get device class  */
> +       snprintf(filename, sizeof(filename), "%s/class_id", dirname);
> +       if (parse_sysfs_uuid(filename, dev->class_id) < 0)
> +               goto error;
> +
> +       /* skip non-network devices */
> +       if (rte_uuid_compare(dev->class_id, vmbus_nic_uuid) != 0) {
> +               free(dev);
> +               return 0;
> +       }
> +
> +       /* get device id */
> +       snprintf(filename, sizeof(filename), "%s/device_id", dirname);
> +       if (parse_sysfs_uuid(filename, dev->device_id) < 0)
> +               goto error;
> +
> +       /* get relid */
> +       snprintf(filename, sizeof(filename), "%s/id", dirname);
> +       if (eal_parse_sysfs_value(filename, &tmp) < 0)
> +               goto error;
> +       dev->relid = tmp;
> +
> +       /* get monitor id */
> +       snprintf(filename, sizeof(filename), "%s/monitor_id", dirname);
> +       if (eal_parse_sysfs_value(filename, &tmp) < 0)
> +               goto error;
> +       dev->monitor_id = tmp;
> +
> +       /* get numa node (if present) */
> +       snprintf(filename, sizeof(filename), "%s/numa_node",
> +                dirname);
> +
> +       if (access(filename, R_OK) == 0) {
> +               if (eal_parse_sysfs_value(filename, &tmp) < 0)
> +                       goto error;
> +               dev->device.numa_node = tmp;
> +       } else {
> +               /* if no NUMA support, set default to 0 */
> +               dev->device.numa_node = SOCKET_ID_ANY;
> +       }
> +
> +       dev->device.devargs = vmbus_devargs_lookup(dev);
> +
> +       /* device is valid, add in list (sorted) */
> +       VMBUS_LOG(DEBUG, "Adding vmbus device %s", name);
> +
> +       TAILQ_FOREACH(dev2, &rte_vmbus_bus.device_list, next) {
> +               int ret;
> +
> +               ret = rte_uuid_compare(dev->device_id, dev2->device_id);
> +               if (ret > 0)
> +                       continue;
> +
> +               if (ret < 0) {
> +                       vmbus_insert_device(dev2, dev);
> +               } else { /* already registered */
> +                       VMBUS_LOG(NOTICE,
> +                               "%s already registered", name);
> +                       free(dev);
> +               }
> +               return 0;
> +       }
> +
> +       vmbus_add_device(dev);
> +       return 0;
> +error:
> +       VMBUS_LOG(DEBUG, "failed");
> +
> +       free(dev);
> +       return -1;
> +}
> +
> +/*
> + * Scan the content of the vmbus, and the devices in the devices list
> +*/ int
> +rte_vmbus_scan(void)
> +{
> +       struct dirent *e;
> +       DIR *dir;
> +
> +       dir = opendir(SYSFS_VMBUS_DEVICES);
> +       if (dir == NULL) {
> +               if (errno == ENOENT)
> +                       return 0;
> +
> +               VMBUS_LOG(ERR, "opendir %s failed: %s",
> +                         SYSFS_VMBUS_DEVICES, strerror(errno));
> +               return -1;
> +       }
> +
> +       while ((e = readdir(dir)) != NULL) {
> +               if (e->d_name[0] == '.')
> +                       continue;
> +
> +               if (vmbus_scan_one(e->d_name) < 0)
> +                       goto error;
> +       }
> +       closedir(dir);
> +       return 0;
> +
> +error:
> +       closedir(dir);
> +       return -1;
> +}
> +
> +void rte_vmbus_irq_mask(struct rte_vmbus_device *device) {
> +       vmbus_uio_irq_control(device, 1); }
> +
> +void rte_vmbus_irq_unmask(struct rte_vmbus_device *device) {
> +       vmbus_uio_irq_control(device, 0); }
> +
> +int rte_vmbus_irq_read(struct rte_vmbus_device *device) {
> +       return vmbus_uio_irq_read(device); }
> diff --git a/drivers/bus/vmbus/freebsd/vmbus_uio.c
> b/drivers/bus/vmbus/freebsd/vmbus_uio.c
> new file mode 100644
> index 0000000000..b52ca5bf1d
> --- /dev/null
> +++ b/drivers/bus/vmbus/freebsd/vmbus_uio.c
> @@ -0,0 +1,453 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2018, Microsoft Corporation.
> + * All Rights Reserved.
> + */
> +
> +#include <string.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <dirent.h>
> +#include <inttypes.h>
> +#include <sys/stat.h>
> +#include <sys/mman.h>
> +
> +#include <rte_log.h>
> +#include <rte_bus.h>
> +#include <rte_memory.h>
> +#include <rte_common.h>
> +#include <rte_malloc.h>
> +#include <rte_bus_vmbus.h>
> +#include <rte_string_fns.h>
> +
> +#include "private.h"
> +
> +/** Pathname of VMBUS devices directory. */ #define SYSFS_VMBUS_DEVICES
> +"/sys/bus/vmbus/devices"
> +
> +static void *vmbus_map_addr;
> +
> +/* Control interrupts */
> +void vmbus_uio_irq_control(struct rte_vmbus_device *dev, int32_t onoff)
> +{
> +       if (write(dev->intr_handle.fd, &onoff, sizeof(onoff)) < 0) {
> +               VMBUS_LOG(ERR, "cannot write to %d:%s",
> +                       dev->intr_handle.fd, strerror(errno));
> +       }
> +}
> +
> +int vmbus_uio_irq_read(struct rte_vmbus_device *dev) {
> +       int32_t count;
> +       int cc;
> +
> +       cc = read(dev->intr_handle.fd, &count, sizeof(count));
> +       if (cc < (int)sizeof(count)) {
> +               if (cc < 0) {
> +                       VMBUS_LOG(ERR, "IRQ read failed %s",
> +                                 strerror(errno));
> +                       return -errno;
> +               }
> +               VMBUS_LOG(ERR, "can't read IRQ count");
> +               return -EINVAL;
> +       }
> +
> +       return count;
> +}
> +
> +void
> +vmbus_uio_free_resource(struct rte_vmbus_device *dev,
> +               struct mapped_vmbus_resource *uio_res) {
> +       rte_free(uio_res);
> +
> +       if (dev->intr_handle.uio_cfg_fd >= 0) {
> +               close(dev->intr_handle.uio_cfg_fd);
> +               dev->intr_handle.uio_cfg_fd = -1;
> +       }
> +
> +       if (dev->intr_handle.fd >= 0) {
> +               close(dev->intr_handle.fd);
> +               dev->intr_handle.fd = -1;
> +               dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
> +       }
> +}
> +
> +int
> +vmbus_uio_alloc_resource(struct rte_vmbus_device *dev,
> +                        struct mapped_vmbus_resource **uio_res) {
> +       char devname[PATH_MAX]; /* contains the /dev/uioX */
> +
> +       /* save fd if in primary process */
> +       snprintf(devname, sizeof(devname), "/dev/uio%u", dev->uio_num);
> +       dev->intr_handle.fd = open(devname, O_RDWR);
> +       if (dev->intr_handle.fd < 0) {
> +               VMBUS_LOG(ERR, "Cannot open %s: %s",
> +                       devname, strerror(errno));
> +               goto error;
> +       }
> +       dev->intr_handle.type = RTE_INTR_HANDLE_UIO_INTX;
> +
> +       /* allocate the mapping details for secondary processes*/
> +       *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0);
> +       if (*uio_res == NULL) {
> +               VMBUS_LOG(ERR, "cannot store uio mmap details");
> +               goto error;
> +       }
> +
> +       strlcpy((*uio_res)->path, devname, PATH_MAX);
> +       rte_uuid_copy((*uio_res)->id, dev->device_id);
> +
> +       return 0;
> +
> +error:
> +       vmbus_uio_free_resource(dev, *uio_res);
> +       return -1;
> +}
> +
> +static int
> +find_max_end_va(const struct rte_memseg_list *msl, void *arg) {
> +       size_t sz = msl->memseg_arr.len * msl->page_sz;
> +       void *end_va = RTE_PTR_ADD(msl->base_va, sz);
> +       void **max_va = arg;
> +
> +       if (*max_va < end_va)
> +               *max_va = end_va;
> +       return 0;
> +}
> +
> +/*
> + * TODO: this should be part of memseg api.
> + *       code is duplicated from PCI.
> + */
> +static void *
> +vmbus_find_max_end_va(void)
> +{
> +       void *va = NULL;
> +
> +       rte_memseg_list_walk(find_max_end_va, &va);
> +       return va;
> +}
> +
> +int
> +vmbus_uio_map_resource_by_index(struct rte_vmbus_device *dev, int idx,
> +                               struct mapped_vmbus_resource *uio_res,
> +                               int flags) {
> +       size_t size = dev->resource[idx].len;
> +       struct vmbus_map *maps = uio_res->maps;
> +       void *mapaddr;
> +       off_t offset;
> +       int fd;
> +
> +       /* devname for mmap  */
> +       fd = open(uio_res->path, O_RDWR);
> +       if (fd < 0) {
> +               VMBUS_LOG(ERR, "Cannot open %s: %s",
> +                         uio_res->path, strerror(errno));
> +               return -1;
> +       }
> +
> +       /* try mapping somewhere close to the end of hugepages */
> +       if (vmbus_map_addr == NULL)
> +               vmbus_map_addr = vmbus_find_max_end_va();
> +
> +       /* offset is special in uio it indicates which resource */
> +       offset = idx * rte_mem_page_size();
> +
> +       mapaddr = vmbus_map_resource(vmbus_map_addr, fd, offset, size, flags);
> +       close(fd);
> +
> +       if (mapaddr == MAP_FAILED)
> +               return -1;
> +
> +       dev->resource[idx].addr = mapaddr;
> +       vmbus_map_addr = RTE_PTR_ADD(mapaddr, size);
> +
> +       /* Record result of successful mapping for use by secondary */
> +       maps[idx].addr = mapaddr;
> +       maps[idx].size = size;
> +
> +       return 0;
> +}
> +
> +static int vmbus_uio_map_primary(struct vmbus_channel *chan,
> +                                void **ring_buf, uint32_t *ring_size) {
> +       struct mapped_vmbus_resource *uio_res;
> +
> +       uio_res = vmbus_uio_find_resource(chan->device);
> +       if (!uio_res) {
> +               VMBUS_LOG(ERR, "can not find resources!");
> +               return -ENOMEM;
> +       }
> +
> +       if (uio_res->nb_maps < VMBUS_MAX_RESOURCE) {
> +               VMBUS_LOG(ERR, "VMBUS: only %u resources found!",
> +                         uio_res->nb_maps);
> +               return -EINVAL;
> +       }
> +
> +       *ring_size = uio_res->maps[HV_TXRX_RING_MAP].size / 2;
> +       *ring_buf  = uio_res->maps[HV_TXRX_RING_MAP].addr;
> +       return 0;
> +}
> +
> +static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev,
> +                                const struct vmbus_channel *chan,
> +                                void **ring_buf, uint32_t *ring_size) {
> +       char ring_path[PATH_MAX];
> +       size_t file_size;
> +       struct stat sb;
> +       void *mapaddr;
> +       int fd;
> +
> +       snprintf(ring_path, sizeof(ring_path),
> +                "%s/%s/channels/%u/ring",
> +                SYSFS_VMBUS_DEVICES, dev->device.name,
> +                chan->relid);
> +
> +       fd = open(ring_path, O_RDWR);
> +       if (fd < 0) {
> +               VMBUS_LOG(ERR, "Cannot open %s: %s",
> +                         ring_path, strerror(errno));
> +               return -errno;
> +       }
> +
> +       if (fstat(fd, &sb) < 0) {
> +               VMBUS_LOG(ERR, "Cannot state %s: %s",
> +                         ring_path, strerror(errno));
> +               close(fd);
> +               return -errno;
> +       }
> +       file_size = sb.st_size;
> +
> +       if (file_size == 0 || (file_size & (rte_mem_page_size() - 1))) {
> +               VMBUS_LOG(ERR, "incorrect size %s: %zu",
> +                         ring_path, file_size);
> +
> +               close(fd);
> +               return -EINVAL;
> +       }
> +
> +       mapaddr = vmbus_map_resource(vmbus_map_addr, fd,
> +                                    0, file_size, 0);
> +       close(fd);
> +
> +       if (mapaddr == MAP_FAILED)
> +               return -EIO;
> +
> +       *ring_size = file_size / 2;
> +       *ring_buf = mapaddr;
> +
> +       vmbus_map_addr = RTE_PTR_ADD(mapaddr, file_size);
> +       return 0;
> +}
> +
> +int
> +vmbus_uio_map_secondary_subchan(const struct rte_vmbus_device *dev,
> +                               const struct vmbus_channel *chan) {
> +       const struct vmbus_br *br = &chan->txbr;
> +       char ring_path[PATH_MAX];
> +       void *mapaddr, *ring_buf;
> +       uint32_t ring_size;
> +       int fd;
> +
> +       snprintf(ring_path, sizeof(ring_path),
> +                "%s/%s/channels/%u/ring",
> +                SYSFS_VMBUS_DEVICES, dev->device.name,
> +                chan->relid);
> +
> +       ring_buf = br->vbr;
> +       ring_size = br->dsize + sizeof(struct vmbus_bufring);
> +       VMBUS_LOG(INFO, "secondary ring_buf %p size %u",
> +                 ring_buf, ring_size);
> +
> +       fd = open(ring_path, O_RDWR);
> +       if (fd < 0) {
> +               VMBUS_LOG(ERR, "Cannot open %s: %s",
> +                         ring_path, strerror(errno));
> +               return -errno;
> +       }
> +
> +       mapaddr = vmbus_map_resource(ring_buf, fd, 0, 2 * ring_size, 0);
> +       close(fd);
> +
> +       if (mapaddr == ring_buf)
> +               return 0;
> +
> +       if (mapaddr == MAP_FAILED)
> +               VMBUS_LOG(ERR,
> +                         "mmap subchan %u in secondary failed", chan->relid);
> +       else {
> +               VMBUS_LOG(ERR,
> +                         "mmap subchan %u in secondary address mismatch",
> +                         chan->relid);
> +               vmbus_unmap_resource(mapaddr, 2 * ring_size);
> +       }
> +       return -1;
> +}
> +
> +int vmbus_uio_map_rings(struct vmbus_channel *chan) {
> +       const struct rte_vmbus_device *dev = chan->device;
> +       uint32_t ring_size;
> +       void *ring_buf;
> +       int ret;
> +
> +       /* Primary channel */
> +       if (chan->subchannel_id == 0)
> +               ret = vmbus_uio_map_primary(chan, &ring_buf, &ring_size);
> +       else
> +               ret = vmbus_uio_map_subchan(dev, chan, &ring_buf,
> + &ring_size);
> +
> +       if (ret)
> +               return ret;
> +
> +       vmbus_br_setup(&chan->txbr, ring_buf, ring_size);
> +       vmbus_br_setup(&chan->rxbr, (char *)ring_buf + ring_size, ring_size);
> +       return 0;
> +}
> +
> +static int vmbus_uio_sysfs_read(const char *dir, const char *name,
> +                               unsigned long *val, unsigned long
> +max_range) {
> +       char path[PATH_MAX];
> +       FILE *f;
> +       int ret;
> +
> +       snprintf(path, sizeof(path), "%s/%s", dir, name);
> +       f = fopen(path, "r");
> +       if (!f) {
> +               VMBUS_LOG(ERR, "can't open %s:%s",
> +                         path, strerror(errno));
> +               return -errno;
> +       }
> +
> +       if (fscanf(f, "%lu", val) != 1)
> +               ret = -EIO;
> +       else if (*val > max_range)
> +               ret = -ERANGE;
> +       else
> +               ret = 0;
> +       fclose(f);
> +
> +       return ret;
> +}
> +
> +static bool vmbus_uio_ring_present(const struct rte_vmbus_device *dev,
> +                                  uint32_t relid) {
> +       char ring_path[PATH_MAX];
> +
> +       /* Check if kernel has subchannel sysfs files */
> +       snprintf(ring_path, sizeof(ring_path),
> +                "%s/%s/channels/%u/ring",
> +                SYSFS_VMBUS_DEVICES, dev->device.name, relid);
> +
> +       return access(ring_path, R_OK|W_OK) == 0; }
> +
> +bool vmbus_uio_subchannels_supported(const struct rte_vmbus_device *dev,
> +                                    const struct vmbus_channel *chan) {
> +       return vmbus_uio_ring_present(dev, chan->relid); }
> +
> +static bool vmbus_isnew_subchannel(struct vmbus_channel *primary,
> +                                  unsigned long id) {
> +       const struct vmbus_channel *c;
> +
> +       STAILQ_FOREACH(c, &primary->subchannel_list, next) {
> +               if (c->relid == id)
> +                       return false;
> +       }
> +       return true;
> +}
> +
> +int vmbus_uio_get_subchan(struct vmbus_channel *primary,
> +                         struct vmbus_channel **subchan) {
> +       const struct rte_vmbus_device *dev = primary->device;
> +       char chan_path[PATH_MAX], subchan_path[PATH_MAX];
> +       struct dirent *ent;
> +       DIR *chan_dir;
> +       int err;
> +
> +       snprintf(chan_path, sizeof(chan_path),
> +                "%s/%s/channels",
> +                SYSFS_VMBUS_DEVICES, dev->device.name);
> +
> +       chan_dir = opendir(chan_path);
> +       if (!chan_dir) {
> +               VMBUS_LOG(ERR, "cannot open %s: %s",
> +                         chan_path, strerror(errno));
> +               return -errno;
> +       }
> +
> +       while ((ent = readdir(chan_dir))) {
> +               unsigned long relid, subid, monid;
> +               char *endp;
> +
> +               if (ent->d_name[0] == '.')
> +                       continue;
> +
> +               errno = 0;
> +               relid = strtoul(ent->d_name, &endp, 0);
> +               if (*endp || errno != 0 || relid > UINT16_MAX) {
> +                       VMBUS_LOG(NOTICE, "not a valid channel relid: %s",
> +                                 ent->d_name);
> +                       continue;
> +               }
> +
> +               if (!vmbus_isnew_subchannel(primary, relid)) {
> +                       VMBUS_LOG(DEBUG, "skip already found channel: %lu",
> +                                 relid);
> +                       continue;
> +               }
> +
> +               if (!vmbus_uio_ring_present(dev, relid)) {
> +                       VMBUS_LOG(DEBUG, "ring mmap not found (yet) for: %lu",
> +                                 relid);
> +                       continue;
> +               }
> +
> +               snprintf(subchan_path, sizeof(subchan_path), "%s/%lu",
> +                        chan_path, relid);
> +               err = vmbus_uio_sysfs_read(subchan_path, "subchannel_id",
> +                                          &subid, UINT16_MAX);
> +               if (err) {
> +                       VMBUS_LOG(NOTICE, "no subchannel_id in %s:%s",
> +                                 subchan_path, strerror(-err));
> +                       goto fail;
> +               }
> +
> +               if (subid == 0)
> +                       continue;       /* skip primary channel */
> +
> +               err = vmbus_uio_sysfs_read(subchan_path, "monitor_id",
> +                                          &monid, UINT8_MAX);
> +               if (err) {
> +                       VMBUS_LOG(NOTICE, "no monitor_id in %s:%s",
> +                                 subchan_path, strerror(-err));
> +                       goto fail;
> +               }
> +
> +               err = vmbus_chan_create(dev, relid, subid, monid, subchan);
> +               if (err) {
> +                       VMBUS_LOG(ERR, "subchannel setup failed");
> +                       goto fail;
> +               }
> +               break;
> +       }
> +       closedir(chan_dir);
> +
> +       return (ent == NULL) ? -ENOENT : 0;
> +fail:
> +       closedir(chan_dir);
> +       return err;
> +}
> --
> 2.30.2


  reply	other threads:[~2021-11-06 20:44 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-27 13:42 [dpdk-dev] [PATCH 00/11] add FreeBSD support to VMBUS & NetVSC PMDs Srikanth Kaka
2021-09-27 13:42 ` [dpdk-dev] [PATCH 01/11] bus/vmbus: stub for FreeBSD support Srikanth Kaka
2021-11-06 20:44   ` Long Li [this message]
2021-09-27 13:42 ` [dpdk-dev] [PATCH 02/11] bus/vmbus: scan and get the network device Srikanth Kaka
2021-10-08 11:39   ` [dpdk-dev] [PATCH v2 " Srikanth Kaka
2021-09-27 13:42 ` [dpdk-dev] [PATCH 03/11] bus/vmbus: handle mapping of device resources Srikanth Kaka
2021-09-27 13:42 ` [dpdk-dev] [PATCH 04/11] bus/vmbus: get device resource values using sysctl Srikanth Kaka
2021-09-27 13:42 ` [dpdk-dev] [PATCH 05/11] bus/vmbus: open subchannels Srikanth Kaka
2021-09-30 23:17   ` Long Li
2021-10-08 11:41   ` [dpdk-dev] [PATCH v2 " Srikanth Kaka
2021-11-06 20:49     ` Long Li
2022-02-08 16:35       ` Thomas Monjalon
2021-09-27 13:42 ` [dpdk-dev] [PATCH 06/11] net/netvsc: request HV_UIO to open sub-channels Srikanth Kaka
2021-09-30 23:19   ` Long Li
2021-10-01  5:31     ` Srikanth K
2021-09-27 13:42 ` [dpdk-dev] [PATCH 07/11] bus/vmbus: map the subchannel resources Srikanth Kaka
2021-09-27 13:42 ` [dpdk-dev] [PATCH 08/11] net/netvsc: moving event monitoring support Srikanth Kaka
2021-11-06 20:51   ` Long Li
2021-09-27 13:42 ` [dpdk-dev] [PATCH 09/11] net/netvsc: moving hotplug retry to OS dir Srikanth Kaka
2021-11-06 20:54   ` Long Li
2021-09-27 13:42 ` [dpdk-dev] [PATCH 10/11] bus/vmbus: add meson support for FreeBSD OS Srikanth Kaka
2021-11-06 20:54   ` Long Li
2021-09-27 13:42 ` [dpdk-dev] [PATCH 11/11] net/netvsc: add meson support for FreeBSD Srikanth Kaka
2021-10-08 11:42   ` [dpdk-dev] [PATCH v2 " Srikanth Kaka
2021-11-06 20:50     ` Long Li
2021-09-30 23:25 ` [dpdk-dev] [PATCH 00/11] add FreeBSD support to VMBUS & NetVSC PMDs Long Li
2022-02-17 16:05 ` [PATCH v3 00/15] " Srikanth Kaka
2022-02-17 16:05   ` [PATCH v3 01/15] bus/vmbus: scan and get the network device Srikanth Kaka
2022-02-17 16:29     ` Stephen Hemminger
2022-02-17 16:06   ` [PATCH v3 02/15] bus/vmbus: handle mapping of device resources Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 03/15] bus/vmbus: get device resource values using sysctl Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 04/15] bus/vmbus: add resource by index Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 05/15] net/netvsc: make event monitor OS dependent Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 06/15] bus/vmbus: add ring mapping APIs Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 07/15] bus/vmbus: add stub for subchannel support API Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 08/15] bus/vmbus: open subchannels Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 09/15] net/netvsc: make IOCTL call to " Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 10/15] bus/vmbus: get subchannel info Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 11/15] net/netvsc: moving hotplug retry to OS dir Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 12/15] bus/vmbus: add meson support for FreeBSD Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 13/15] net/netvsc: " Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 14/15] bus/vmbus: add APIs to mask/unmask IRQs Srikanth Kaka
2022-02-17 16:06   ` [PATCH v3 15/15] bus/vmbus: update MAINTAINERS and docs Srikanth Kaka
2022-04-18  4:29     ` [PATCH v4 00/14] add FreeBSD support to VMBUS & NetVSC PMDs Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 01/14] bus/vmbus: move independent code from Linux Srikanth Kaka
2022-04-19 14:49         ` Stephen Hemminger
2022-04-19 14:52           ` Srikanth K
2022-04-18  4:29       ` [PATCH v4 02/14] bus/vmbus: move independent bus functions Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 03/14] bus/vmbus: move OS independent UIO functions Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 04/14] bus/vmbus: scan and get the network device on FreeBSD Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 05/14] bus/vmbus: handle mapping of device resources Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 06/14] bus/vmbus: get device resource values using sysctl Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 07/14] net/netvsc: make event monitor OS dependent Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 08/14] bus/vmbus: add sub-channel mapping support Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 09/14] bus/vmbus: open subchannels Srikanth Kaka
2022-04-19 15:00         ` Stephen Hemminger
2022-04-18  4:29       ` [PATCH v4 10/14] net/netvsc: make IOCTL call to " Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 11/14] bus/vmbus: get subchannel info Srikanth Kaka
2022-04-19 14:51         ` Stephen Hemminger
2022-04-18  4:29       ` [PATCH v4 12/14] net/netvsc: moving hotplug retry to OS dir Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 13/14] bus/vmbus: add meson support for FreeBSD Srikanth Kaka
2022-04-18  4:29       ` [PATCH v4 14/14] bus/vmbus: update MAINTAINERS and docs Srikanth Kaka
2022-04-23  4:28       ` [PATCH v5 00/14] add FreeBSD support to VMBUS & NetVSC PMDs Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 01/14] bus/vmbus: move independent code from Linux Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 02/14] bus/vmbus: move independent bus functions Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 03/14] bus/vmbus: move OS independent UIO functions Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 04/14] bus/vmbus: scan and get the network device on FreeBSD Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 05/14] bus/vmbus: handle mapping of device resources Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 06/14] bus/vmbus: get device resource values using sysctl Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 07/14] net/netvsc: make event monitor OS dependent Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 08/14] bus/vmbus: add sub-channel mapping support Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 09/14] bus/vmbus: open subchannels Srikanth Kaka
2023-08-10 15:41           ` Stephen Hemminger
2022-04-23  4:28         ` [PATCH v5 10/14] net/netvsc: make IOCTL call to " Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 11/14] bus/vmbus: get subchannel info Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 12/14] net/netvsc: moving hotplug retry to OS dir Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 13/14] bus/vmbus: add meson support for FreeBSD Srikanth Kaka
2022-04-23  4:28         ` [PATCH v5 14/14] bus/vmbus: update MAINTAINERS and docs Srikanth Kaka
2023-08-10 15:44           ` Stephen Hemminger
2022-05-18  8:18         ` [PATCH v5 00/14] add FreeBSD support to VMBUS & NetVSC PMDs Thomas Monjalon
2022-10-06 14:58           ` Thomas Monjalon
2023-07-04  0:07             ` Stephen Hemminger
2022-04-14  8:54   ` [PATCH v3 00/15] " Thomas Monjalon
2022-04-14  9:01     ` Srikanth K

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BY5PR21MB150635EBDC4A738410F06534CE8F9@BY5PR21MB1506.namprd21.prod.outlook.com \
    --to=longli@microsoft.com \
    --cc=avelu@juniper.net \
    --cc=dev@dpdk.org \
    --cc=srikanth.k@oneconvergence.com \
    --cc=sthemmin@microsoft.com \
    --cc=vag.singh@oneconvergence.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.