#include <sys/stat.h>
#include <sys/mman.h>
+#include <rte_eal.h>
#include <rte_log.h>
#include <rte_bus.h>
#include <rte_memory.h>
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",
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;
- 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;
uint64_t size; /* length */
};
+#define UIO_MAX_SUBCHANNEL 128
+struct subchannel_map {
+ uint16_t relid;
+ void *addr;
+ uint64_t size;
+};
+
/*
* For multi-process we need to reproduce all vmbus mappings in secondary
* processes, so save them in a tailq.
TAILQ_ENTRY(mapped_vmbus_resource) next;
rte_uuid_t id;
+
int nb_maps;
- struct vmbus_channel *primary;
struct vmbus_map maps[VMBUS_MAX_RESOURCE];
+
char path[PATH_MAX];
+
+ int nb_subchannels;
+ struct subchannel_map subchannel_maps[UIO_MAX_SUBCHANNEL];
};
TAILQ_HEAD(mapped_vmbus_res_list, mapped_vmbus_resource);
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);
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;
}
fd, offset,
uio_res->maps[i].size, 0);
- if (mapaddr == uio_res->maps[i].addr)
+ if (mapaddr == uio_res->maps[i].addr) {
+ dev->resource[i].addr = mapaddr;
continue; /* successful map */
+ }
if (mapaddr == MAP_FAILED)
VMBUS_LOG(ERR,
/* fd is not needed in secondary process, close it */
close(fd);
- dev->primary = uio_res->primary;
- if (!dev->primary) {
- VMBUS_LOG(ERR, "missing primary channel");
- return -1;
+ /* Create and map primary channel */
+ if (vmbus_chan_create(dev, dev->relid, 0,
+ dev->monitor_id, &dev->primary)) {
+ VMBUS_LOG(ERR, "cannot create primary channel");
+ goto failed_primary;
}
- 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;
+ /* Create and map sub channels */
+ for (i = 0; i < uio_res->nb_subchannels; i++) {
+ if (rte_vmbus_subchan_open(dev->primary, &chan)) {
+ VMBUS_LOG(ERR,
+ "failed to create subchannel at index %d", i);
+ goto failed_secondary;
}
}
+
return 0;
+
+failed_secondary:
+ while (!STAILQ_EMPTY(&dev->primary->subchannel_list)) {
+ chan = STAILQ_FIRST(&dev->primary->subchannel_list);
+ vmbus_unmap_resource(chan->txbr.vbr, chan->txbr.dsize * 2);
+ rte_vmbus_chan_close(chan);
+ }
+ rte_vmbus_chan_close(dev->primary);
+
+failed_primary:
+ for (i = 0; i != uio_res->nb_maps; i++) {
+ vmbus_unmap_resource(
+ uio_res->maps[i].addr, uio_res->maps[i].size);
+ }
+
+ return -1;
}
static int
if (uio_res == NULL)
return;
+ for (i = 0; i < uio_res->nb_subchannels; i++) {
+ vmbus_unmap_resource(uio_res->subchannel_maps[i].addr,
+ uio_res->subchannel_maps[i].size);
+ }
+
for (i = 0; i != uio_res->nb_maps; i++) {
vmbus_unmap_resource(uio_res->maps[i].addr,
(size_t)uio_res->maps[i].size);
return;
/* secondary processes - just free maps */
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
- return vmbus_uio_unmap(uio_res);
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ vmbus_uio_unmap(uio_res);
+ rte_free(dev->primary);
+ return;
+ }
TAILQ_REMOVE(uio_res_list, uio_res, next);