bus/vmbus: map ring in secondary process
authorStephen Hemminger <sthemmin@microsoft.com>
Fri, 8 Feb 2019 03:44:05 +0000 (19:44 -0800)
committerThomas Monjalon <thomas@monjalon.net>
Fri, 29 Mar 2019 12:44:19 +0000 (13:44 +0100)
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 <sthemmin@microsoft.com>
drivers/bus/vmbus/linux/vmbus_uio.c
drivers/bus/vmbus/private.h
drivers/bus/vmbus/vmbus_channel.c
drivers/bus/vmbus/vmbus_common_uio.c

index 8c6bc52..fb60ee1 100644 (file)
@@ -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;
index 211127d..f19b14e 100644 (file)
@@ -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);
 
index bd14c06..46b3ba3 100644 (file)
@@ -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)
index a6545b7..9947f82 100644 (file)
@@ -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;
        }