From patchwork Mon Apr 18 04:29:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srikanth Kaka X-Patchwork-Id: 109873 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 47817A00BE; Tue, 19 Apr 2022 11:34:05 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 328CC427F9; Tue, 19 Apr 2022 11:33:42 +0200 (CEST) Received: from mail-pj1-f68.google.com (mail-pj1-f68.google.com [209.85.216.68]) by mails.dpdk.org (Postfix) with ESMTP id 2752B40141 for ; Mon, 18 Apr 2022 06:29:40 +0200 (CEST) Received: by mail-pj1-f68.google.com with SMTP id h15-20020a17090a054f00b001cb7cd2b11dso13031482pjf.5 for ; Sun, 17 Apr 2022 21:29:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oneconvergence.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8+RWzaA3MUIkhoYz6xAcNAUxsbBzPp7jA3/JMxvjClk=; b=Pw7/e8ffMB4oRkrQ3dflK6ics39hoRwBSpgT02b2wMOhntpoU9maSTvldocI5j6W8K LnMrTwy99DBKfIXYhzxuO3NRlLwnXtP7OFI7AWUpRjF2dMC51sZiD8OdUNox9tD+uaox EWAEqU9/PUTlTK63+1HYMGF2iOoYYWGDYgxXo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8+RWzaA3MUIkhoYz6xAcNAUxsbBzPp7jA3/JMxvjClk=; b=SorM1wDkjGuVHxeEcRs8mH+ArEWO3ICWtcW3+Choe9ei+t12rQZrBI4uS76Xx50NH4 l8mdoJ+e3GUYNCwQ04KDk5sh8y7qs1Fvfqfd01u1YnlNQ5MHHCHJA6peLplDpo/IV/RJ R3NotHC4OPkSxk5jqjGvGoBj47BAefB0ubxOf9gREEpvfkRnULfNpKcQTjKi2xi97+dO h27Ckw/eino4EmxXYu53zm5acJIxTV6kXBmqd+SIkDnDmE2LDxithzZ+DQRI1mub1Npr MDeHyyJ8EP2clAUweWjlaEVL2IrvwaqdS4U8gmxGfDy6fJt1YjxeSy95vvwLkzDTYniI Q+dA== X-Gm-Message-State: AOAM53321UYJkajCZCs9fWBnFavgw/QhnF8qTdeybbw7gy1Hwn6v5n3p x7Esrb2OO8somXm5hhH6E8aMkA== X-Google-Smtp-Source: ABdhPJxiPkhkl1KDWTNJNUMgdwACMmAOuyRKMgqWhKBCypxBmHoAdETckGWLknmtEs6tGurPZU5awQ== X-Received: by 2002:a17:902:b941:b0:14d:af72:3f23 with SMTP id h1-20020a170902b94100b0014daf723f23mr9495513pls.6.1650256179324; Sun, 17 Apr 2022 21:29:39 -0700 (PDT) Received: from srikanth-ThinkPad-T450.. ([49.37.158.191]) by smtp.gmail.com with ESMTPSA id e14-20020aa78c4e000000b00506475da4cesm10377577pfd.49.2022.04.17.21.29.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 17 Apr 2022 21:29:38 -0700 (PDT) From: Srikanth Kaka To: Stephen Hemminger , Long Li Cc: dev@dpdk.org, Vag Singh , Anand Thulasiram , Srikanth Kaka Subject: [PATCH v4 03/14] bus/vmbus: move OS independent UIO functions Date: Mon, 18 Apr 2022 09:59:04 +0530 Message-Id: <20220418042915.5765-4-srikanth.k@oneconvergence.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220418042915.5765-1-srikanth.k@oneconvergence.com> References: <20220217160613.70161-16-srikanth.k@oneconvergence.com> <20220418042915.5765-1-srikanth.k@oneconvergence.com> MIME-Version: 1.0 X-Mailman-Approved-At: Tue, 19 Apr 2022 11:33:36 +0200 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Moved all Linux independent UIO functions to OSI dir. Split the vmbus_uio_map_subchan() by keeping OS dependent code in vmbus_uio_map_subchan_os() function Signed-off-by: Srikanth Kaka Signed-off-by: Vag Singh Signed-off-by: Anand Thulasiram --- drivers/bus/vmbus/linux/vmbus_uio.c | 292 +----------------------- drivers/bus/vmbus/meson.build | 3 +- drivers/bus/vmbus/osi/vmbus_osi.h | 12 + drivers/bus/vmbus/osi/vmbus_osi_uio.c | 306 ++++++++++++++++++++++++++ 4 files changed, 330 insertions(+), 283 deletions(-) create mode 100644 drivers/bus/vmbus/osi/vmbus_osi_uio.c diff --git a/drivers/bus/vmbus/linux/vmbus_uio.c b/drivers/bus/vmbus/linux/vmbus_uio.c index 5db70f8e0d..ea6df21409 100644 --- a/drivers/bus/vmbus/linux/vmbus_uio.c +++ b/drivers/bus/vmbus/linux/vmbus_uio.c @@ -21,233 +21,18 @@ #include #include "private.h" +#include "vmbus_osi.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 ((rte_intr_fd_get(dev->intr_handle) < 0) || - write(rte_intr_fd_get(dev->intr_handle), &onoff, - sizeof(onoff)) < 0) { - VMBUS_LOG(ERR, "cannot write to %d:%s", - rte_intr_fd_get(dev->intr_handle), - strerror(errno)); - } -} - -int vmbus_uio_irq_read(struct rte_vmbus_device *dev) -{ - int32_t count; - int cc; - - if (rte_intr_fd_get(dev->intr_handle) < 0) - return -1; - - cc = read(rte_intr_fd_get(dev->intr_handle), &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 (rte_intr_dev_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_dev_fd_get(dev->intr_handle)); - rte_intr_dev_fd_set(dev->intr_handle, -1); - } - - if (rte_intr_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_fd_get(dev->intr_handle)); - rte_intr_fd_set(dev->intr_handle, -1); - rte_intr_type_set(dev->intr_handle, 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 */ - int fd; - - /* save fd if in primary process */ - snprintf(devname, sizeof(devname), "/dev/uio%u", dev->uio_num); - fd = open(devname, O_RDWR); - if (fd < 0) { - VMBUS_LOG(ERR, "Cannot open %s: %s", - devname, strerror(errno)); - goto error; - } - - if (rte_intr_fd_set(dev->intr_handle, fd)) - goto error; - - if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO_INTX)) - goto error; - - /* 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) +int vmbus_uio_map_subchan_os(const struct rte_vmbus_device *dev, + const struct vmbus_channel *chan, + void **mapaddr, size_t *file_size) { char ring_path[PATH_MAX]; - size_t file_size; struct stat sb; - void *mapaddr; int fd; - struct mapped_vmbus_resource *uio_res; - int channel_idx; - - uio_res = vmbus_uio_find_resource(dev); - if (!uio_res) { - VMBUS_LOG(ERR, "can not find resources for mapping subchan"); - return -ENOMEM; - } - - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - if (uio_res->nb_subchannels >= UIO_MAX_SUBCHANNEL) { - VMBUS_LOG(ERR, - "exceeding max subchannels UIO_MAX_SUBCHANNEL(%d)", - UIO_MAX_SUBCHANNEL); - VMBUS_LOG(ERR, "Change UIO_MAX_SUBCHANNEL and recompile"); - return -ENOMEM; - } - } else { - for (channel_idx = 0; channel_idx < uio_res->nb_subchannels; - channel_idx++) - if (uio_res->subchannel_maps[channel_idx].relid == - chan->relid) - break; - if (channel_idx == uio_res->nb_subchannels) { - VMBUS_LOG(ERR, - "couldn't find sub channel %d from shared mapping in primary", - chan->relid); - return -ENOMEM; - } - vmbus_map_addr = uio_res->subchannel_maps[channel_idx].addr; - } snprintf(ring_path, sizeof(ring_path), "%s/%s/channels/%u/ring", @@ -267,68 +52,23 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev, close(fd); return -errno; } - file_size = sb.st_size; + *file_size = sb.st_size; - if (file_size == 0 || (file_size & (rte_mem_page_size() - 1))) { + if (*file_size == 0 || (*file_size & (rte_mem_page_size() - 1))) { VMBUS_LOG(ERR, "incorrect size %s: %zu", - ring_path, file_size); + ring_path, *file_size); close(fd); return -EINVAL; } - mapaddr = vmbus_map_resource(vmbus_map_addr, fd, - 0, file_size, 0); + *mapaddr = vmbus_map_resource(vmbus_map_addr, fd, + 0, *file_size, 0); close(fd); - if (mapaddr == MAP_FAILED) + if (*mapaddr == MAP_FAILED) return -EIO; - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - - /* Add this mapping to uio_res for use by secondary */ - uio_res->subchannel_maps[uio_res->nb_subchannels].relid = - chan->relid; - uio_res->subchannel_maps[uio_res->nb_subchannels].addr = - mapaddr; - uio_res->subchannel_maps[uio_res->nb_subchannels].size = - file_size; - uio_res->nb_subchannels++; - - vmbus_map_addr = RTE_PTR_ADD(mapaddr, file_size); - } else { - if (mapaddr != vmbus_map_addr) { - VMBUS_LOG(ERR, "failed to map channel %d to addr %p", - chan->relid, mapaddr); - vmbus_unmap_resource(mapaddr, file_size); - return -EIO; - } - } - - *ring_size = file_size / 2; - *ring_buf = mapaddr; - - return 0; -} - -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; } @@ -377,18 +117,6 @@ bool vmbus_uio_subchannels_supported(const struct rte_vmbus_device *dev, 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) { diff --git a/drivers/bus/vmbus/meson.build b/drivers/bus/vmbus/meson.build index cbcba44e16..fe9c72bce1 100644 --- a/drivers/bus/vmbus/meson.build +++ b/drivers/bus/vmbus/meson.build @@ -18,7 +18,8 @@ sources = files( includes += include_directories('osi') sources += files( - 'osi/vmbus_osi_bus.c' + 'osi/vmbus_osi_bus.c', + 'osi/vmbus_osi_uio.c' ) if is_linux diff --git a/drivers/bus/vmbus/osi/vmbus_osi.h b/drivers/bus/vmbus/osi/vmbus_osi.h index 2db9399181..579c4bb99c 100644 --- a/drivers/bus/vmbus/osi/vmbus_osi.h +++ b/drivers/bus/vmbus/osi/vmbus_osi.h @@ -6,6 +6,18 @@ #ifndef _VMBUS_BUS_OSI_H_ #define _VMBUS_BUS_OSI_H_ +#include + +#include "private.h" + extern const rte_uuid_t vmbus_nic_uuid; +extern void *vmbus_map_addr; + +int vmbus_uio_map_subchan_os(const struct rte_vmbus_device *dev, + const struct vmbus_channel *chan, + void **mapaddr, size_t *file_size); + +bool vmbus_isnew_subchannel(struct vmbus_channel *primary, + unsigned long id); #endif /* _VMBUS_BUS_OSI_H_ */ diff --git a/drivers/bus/vmbus/osi/vmbus_osi_uio.c b/drivers/bus/vmbus/osi/vmbus_osi_uio.c new file mode 100644 index 0000000000..35106e247e --- /dev/null +++ b/drivers/bus/vmbus/osi/vmbus_osi_uio.c @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2018, Microsoft Corporation. + * All Rights Reserved. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private.h" +#include "vmbus_osi.h" + +void *vmbus_map_addr; + +/* Control interrupts */ +void vmbus_uio_irq_control(struct rte_vmbus_device *dev, int32_t onoff) +{ + if ((rte_intr_fd_get(dev->intr_handle) < 0) || + write(rte_intr_fd_get(dev->intr_handle), &onoff, + sizeof(onoff)) < 0) { + VMBUS_LOG(ERR, "cannot write to %d:%s", + rte_intr_fd_get(dev->intr_handle), + strerror(errno)); + } +} + +int vmbus_uio_irq_read(struct rte_vmbus_device *dev) +{ + int32_t count; + int cc; + + if (rte_intr_fd_get(dev->intr_handle) < 0) + return -1; + + cc = read(rte_intr_fd_get(dev->intr_handle), &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 (rte_intr_dev_fd_get(dev->intr_handle) >= 0) { + close(rte_intr_dev_fd_get(dev->intr_handle)); + rte_intr_dev_fd_set(dev->intr_handle, -1); + } + + if (rte_intr_fd_get(dev->intr_handle) >= 0) { + close(rte_intr_fd_get(dev->intr_handle)); + rte_intr_fd_set(dev->intr_handle, -1); + rte_intr_type_set(dev->intr_handle, 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 */ + int fd; + + /* save fd if in primary process */ + snprintf(devname, sizeof(devname), "/dev/uio%u", dev->uio_num); + fd = open(devname, O_RDWR); + if (fd < 0) { + VMBUS_LOG(ERR, "Cannot open %s: %s", + devname, strerror(errno)); + goto error; + } + + if (rte_intr_fd_set(dev->intr_handle, fd)) + goto error; + + if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO_INTX)) + goto error; + + /* 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) +{ + size_t file_size = 0; + void *mapaddr = NULL; + struct mapped_vmbus_resource *uio_res; + int channel_idx; + int ret; + + uio_res = vmbus_uio_find_resource(dev); + if (!uio_res) { + VMBUS_LOG(ERR, "can not find resources for mapping subchan"); + return -ENOMEM; + } + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + if (uio_res->nb_subchannels >= UIO_MAX_SUBCHANNEL) { + VMBUS_LOG(ERR, + "exceeding max subchannels UIO_MAX_SUBCHANNEL(%d)", + UIO_MAX_SUBCHANNEL); + VMBUS_LOG(ERR, "Change UIO_MAX_SUBCHANNEL and recompile"); + return -ENOMEM; + } + } else { + for (channel_idx = 0; channel_idx < uio_res->nb_subchannels; + channel_idx++) + if (uio_res->subchannel_maps[channel_idx].relid == + chan->relid) + break; + if (channel_idx == uio_res->nb_subchannels) { + VMBUS_LOG(ERR, + "couldn't find sub channel %d from shared mapping in primary", + chan->relid); + return -ENOMEM; + } + vmbus_map_addr = uio_res->subchannel_maps[channel_idx].addr; + } + + ret = vmbus_uio_map_subchan_os(dev, chan, &mapaddr, &file_size); + if (ret) + return ret; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + + /* Add this mapping to uio_res for use by secondary */ + uio_res->subchannel_maps[uio_res->nb_subchannels].relid = + chan->relid; + uio_res->subchannel_maps[uio_res->nb_subchannels].addr = + mapaddr; + uio_res->subchannel_maps[uio_res->nb_subchannels].size = + file_size; + uio_res->nb_subchannels++; + + vmbus_map_addr = RTE_PTR_ADD(mapaddr, file_size); + } else { + if (mapaddr != vmbus_map_addr) { + VMBUS_LOG(ERR, "failed to map channel %d to addr %p", + chan->relid, mapaddr); + vmbus_unmap_resource(mapaddr, file_size); + return -EIO; + } + } + + *ring_size = file_size / 2; + *ring_buf = mapaddr; + + return 0; +} + +int vmbus_uio_map_rings(struct vmbus_channel *chan) +{ + const struct rte_vmbus_device *dev = chan->device; + uint32_t ring_size = 0; + void *ring_buf = NULL; + 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; +} + +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; +}