From 2a28a502c6078ceb3e5b296b5f9cbb7e27ceedbd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 7 Feb 2019 19:44:05 -0800 Subject: [PATCH] bus/vmbus: map ring in secondary process Need to remember primary channel in secondary process. Then use it to iterate over subchannels in secondary process mapping setup. Fixes: 831dba47bd36 ("bus/vmbus: add Hyper-V virtual bus support") Cc: stable@dpdk.org Signed-off-by: Stephen Hemminger --- drivers/bus/vmbus/linux/vmbus_uio.c | 43 ++++++++++++++++++++++++++++ drivers/bus/vmbus/private.h | 3 ++ drivers/bus/vmbus/vmbus_channel.c | 20 +++++++++++-- drivers/bus/vmbus/vmbus_common_uio.c | 15 ++++++++++ 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/drivers/bus/vmbus/linux/vmbus_uio.c b/drivers/bus/vmbus/linux/vmbus_uio.c index 8c6bc52fd4..fb60ee126d 100644 --- a/drivers/bus/vmbus/linux/vmbus_uio.c +++ b/drivers/bus/vmbus/linux/vmbus_uio.c @@ -247,6 +247,49 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev, 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); + return -1; +} + int vmbus_uio_map_rings(struct vmbus_channel *chan) { const struct rte_vmbus_device *dev = chan->device; diff --git a/drivers/bus/vmbus/private.h b/drivers/bus/vmbus/private.h index 211127dd8d..f19b14e4a6 100644 --- a/drivers/bus/vmbus/private.h +++ b/drivers/bus/vmbus/private.h @@ -45,6 +45,7 @@ struct mapped_vmbus_resource { rte_uuid_t id; int nb_maps; + struct vmbus_channel *primary; struct vmbus_map maps[VMBUS_MAX_RESOURCE]; char path[PATH_MAX]; }; @@ -107,6 +108,8 @@ bool vmbus_uio_subchannels_supported(const struct rte_vmbus_device *dev, int vmbus_uio_get_subchan(struct vmbus_channel *primary, struct vmbus_channel **subchan); int vmbus_uio_map_rings(struct vmbus_channel *chan); +int vmbus_uio_map_secondary_subchan(const struct rte_vmbus_device *dev, + const struct vmbus_channel *chan); void vmbus_br_setup(struct vmbus_br *br, void *buf, unsigned int blen); diff --git a/drivers/bus/vmbus/vmbus_channel.c b/drivers/bus/vmbus/vmbus_channel.c index bd14c0662b..46b3ba3f9f 100644 --- a/drivers/bus/vmbus/vmbus_channel.c +++ b/drivers/bus/vmbus/vmbus_channel.c @@ -352,12 +352,21 @@ int vmbus_chan_create(const struct rte_vmbus_device *device, int rte_vmbus_chan_open(struct rte_vmbus_device *device, struct vmbus_channel **new_chan) { + struct mapped_vmbus_resource *uio_res; int err; + uio_res = vmbus_uio_find_resource(device); + if (!uio_res) { + VMBUS_LOG(ERR, "can't find uio resource"); + return -EINVAL; + } + err = vmbus_chan_create(device, device->relid, 0, device->monitor_id, new_chan); - if (!err) + if (!err) { device->primary = *new_chan; + uio_res->primary = *new_chan; + } return err; } @@ -396,11 +405,16 @@ void rte_vmbus_chan_close(struct vmbus_channel *chan) const struct rte_vmbus_device *device = chan->device; struct vmbus_channel *primary = device->primary; - if (chan != primary) + /* + * intentionally leak primary channel because + * secondary may still reference it + */ + if (chan != primary) { STAILQ_REMOVE(&primary->subchannel_list, chan, vmbus_channel, next); + rte_free(chan); + } - rte_free(chan); } static void vmbus_dump_ring(FILE *f, const char *id, const struct vmbus_br *br) diff --git a/drivers/bus/vmbus/vmbus_common_uio.c b/drivers/bus/vmbus/vmbus_common_uio.c index a6545b758e..9947f82ab1 100644 --- a/drivers/bus/vmbus/vmbus_common_uio.c +++ b/drivers/bus/vmbus/vmbus_common_uio.c @@ -27,6 +27,7 @@ static int vmbus_uio_map_secondary(struct rte_vmbus_device *dev) { int fd, i; + struct vmbus_channel *chan; struct mapped_vmbus_resource *uio_res; struct mapped_vmbus_res_list *uio_res_list = RTE_TAILQ_CAST(vmbus_tailq.head, mapped_vmbus_res_list); @@ -76,6 +77,20 @@ vmbus_uio_map_secondary(struct rte_vmbus_device *dev) /* fd is not needed in slave process, close it */ close(fd); + + dev->primary = uio_res->primary; + if (!dev->primary) { + VMBUS_LOG(ERR, "missing primary channel"); + return -1; + } + + STAILQ_FOREACH(chan, &dev->primary->subchannel_list, next) { + if (vmbus_uio_map_secondary_subchan(dev, chan) != 0) { + VMBUS_LOG(ERR, "cannot map secondary subchan"); + return -1; + } + } + return 0; } -- 2.20.1