aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bus/vmbus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bus/vmbus')
-rw-r--r--drivers/bus/vmbus/linux/vmbus_uio.c56
-rw-r--r--drivers/bus/vmbus/private.h3
-rw-r--r--drivers/bus/vmbus/vmbus_channel.c20
-rw-r--r--drivers/bus/vmbus/vmbus_common_uio.c22
4 files changed, 91 insertions, 10 deletions
diff --git a/drivers/bus/vmbus/linux/vmbus_uio.c b/drivers/bus/vmbus/linux/vmbus_uio.c
index 38df4d72..7cab5c19 100644
--- a/drivers/bus/vmbus/linux/vmbus_uio.c
+++ b/drivers/bus/vmbus/linux/vmbus_uio.c
@@ -202,6 +202,7 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev,
char ring_path[PATH_MAX];
size_t file_size;
struct stat sb;
+ void *mapaddr;
int fd;
snprintf(ring_path, sizeof(ring_path),
@@ -232,18 +233,65 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev,
return -EINVAL;
}
- *ring_size = file_size / 2;
- *ring_buf = vmbus_map_resource(vmbus_map_addr, fd,
- 0, sb.st_size, 0);
+ mapaddr = vmbus_map_resource(vmbus_map_addr, fd,
+ 0, file_size, 0);
close(fd);
- if (ring_buf == MAP_FAILED)
+ if (mapaddr == MAP_FAILED)
return -EIO;
+ *ring_size = file_size / 2;
+ *ring_buf = mapaddr;
+
vmbus_map_addr = RTE_PTR_ADD(ring_buf, 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;
diff --git a/drivers/bus/vmbus/private.h b/drivers/bus/vmbus/private.h
index 211127dd..f19b14e4 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 bd14c066..46b3ba3f 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 5ddd36ab..9947f82a 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);
@@ -47,9 +48,10 @@ vmbus_uio_map_secondary(struct rte_vmbus_device *dev)
for (i = 0; i != uio_res->nb_maps; i++) {
void *mapaddr;
+ off_t offset = i * PAGE_SIZE;
mapaddr = vmbus_map_resource(uio_res->maps[i].addr,
- fd, 0,
+ fd, offset,
uio_res->maps[i].size, 0);
if (mapaddr == uio_res->maps[i].addr)
@@ -75,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;
}
@@ -97,9 +113,9 @@ vmbus_uio_map_primary(struct rte_vmbus_device *dev)
/* Map the resources */
for (i = 0; i < VMBUS_MAX_RESOURCE; i++) {
- /* skip empty BAR */
+ /* stop at empty BAR */
if (dev->resource[i].len == 0)
- continue;
+ break;
ret = vmbus_uio_map_resource_by_index(dev, i, uio_res, 0);
if (ret)