Пример #1
0
/* unmap the PCI resource of a PCI device in virtual memory */
void pci_uio_unmap_resource(struct odp_pci_device *dev)
{
	struct mapped_pci_resource *uio_res;
	struct mapped_pci_res_list *uio_res_list = ODP_TAILQ_CAST(odp_uio_tailq.head, mapped_pci_res_list);

	if (!dev)
		return;

	/* find an entry for the device */
	uio_res = pci_uio_find_resource(dev);
	if (!uio_res)
		return;

	/* secondary processes - just free maps */
	if (odp_process_type() != ODP_PROC_PRIMARY)
		return pci_uio_unmap(uio_res);

	TAILQ_REMOVE(uio_res_list, uio_res, next);

	/* unmap all resources */
	pci_uio_unmap(uio_res);

	/* free uio resource */
	free(uio_res);

	/* close fd if in primary process */
	close(dev->intr_handle.fd);

	dev->intr_handle.fd = -1;
	dev->intr_handle.type = ODP_INTR_HANDLE_UNKNOWN;
}
Пример #2
0
/* create the ring */
struct odp_ring *odp_ring_create(const char *name, unsigned count,
				 int socket_id, unsigned flags)
{
	char mz_name[ODP_MEMZONE_NAMESIZE];
	struct odp_ring *r;
	struct odp_tailq_entry *te;
	const struct odp_mm_district *mz;
	ssize_t ring_size;
	int mz_flags = 0;
	struct odp_ring_list *ring_list = NULL;

	ring_list = ODP_TAILQ_CAST(odp_ring_tailq.head, odp_ring_list);

	ring_size = odp_ring_get_memsize(count);
	if (ring_size < 0) {
		odp_err = ring_size;
		return NULL;
	}

	te = malloc(sizeof(*te));
	if (te == NULL) {
		ODP_PRINT("Cannot reserve memory for tailq\n");
		odp_err = ENOMEM;
		return NULL;
	}

	snprintf(mz_name, sizeof(mz_name), "%s%s", ODP_RING_MZ_PREFIX, name);

	odp_rwlock_write_lock(ODP_TAILQ_RWLOCK);

	/* reserve a memory zone for this ring. If we can't get odp_config or
	 * we are secondary process, the mm_district_reserve function will set
	 * odp_err for us appropriately-hence no check in this this function */
	mz = odp_mm_district_reserve(mz_name, mz_name, ring_size,
				     socket_id, mz_flags);
	if (mz != NULL) {
		r = mz->addr;

		/* no need to check return value here, we already checked the
		 * arguments above */

		odp_ring_init(r, name, count, flags);

		te->data = (void *)r;

		TAILQ_INSERT_TAIL(ring_list, te, next);
	} else {
		r = NULL;
		ODP_PRINT("Cannot reserve memory\n");
		free(te);
	}

	odp_rwlock_write_unlock(ODP_TAILQ_RWLOCK);

	return r;
}
Пример #3
0
/* dump the status of all rings on the console */
void odp_ring_list_dump(FILE *f)
{
	const struct odp_tailq_entry *te;
	struct odp_ring_list *ring_list;

	ring_list = ODP_TAILQ_CAST(odp_ring_tailq.head, odp_ring_list);

	odp_rwlock_read_lock(ODP_TAILQ_RWLOCK);

	TAILQ_FOREACH(te, ring_list, next)
	{
		odp_ring_dump(f, (struct odp_ring *)te->data);
	}
Пример #4
0
static int pci_uio_map_secondary(struct odp_pci_device *dev)
{
	int fd, i;
	struct mapped_pci_resource *uio_res;
	struct mapped_pci_res_list *uio_res_list = ODP_TAILQ_CAST(odp_uio_tailq.head, mapped_pci_res_list);

	TAILQ_FOREACH(uio_res, uio_res_list, next)
	{
		/* skip this element if it doesn't match our PCI address */
		if (odp_compare_pci_addr(&uio_res->pci_addr, &dev->addr))
			continue;

		for (i = 0; i != uio_res->nb_maps; i++) {
			/*
			 * open devname, to mmap it
			 */
			fd = open(uio_res->maps[i].path, O_RDWR);
			if (fd < 0) {
				PRINT("Cannot open %s: %s\n",
				      uio_res->maps[i].path, strerror(errno));
				return -1;
			}

			void *mapaddr = pci_map_resource(uio_res->maps[i].addr,
							 fd, (off_t)uio_res->maps[i].offset,
							 (size_t)uio_res->maps[i].size, 0);

			if (mapaddr != uio_res->maps[i].addr) {
				if (mapaddr == MAP_FAILED)
					PRINT("Cannot mmap device resource file %s: %s\n",
					      uio_res->maps[i].path,
					      strerror(errno));
				else
					PRINT("Cannot mmap device resource file %s to address: %p\n",
					      uio_res->maps[i].path,
					      uio_res->maps[i].addr);

				close(fd);
				return -1;
			}

			/* fd is not needed in slave process, close it */
			close(fd);
		}

		return 0;
	}

	PRINT("Cannot find resource for device\n");
	return 1;
}
Пример #5
0
static struct mapped_pci_resource *pci_uio_find_resource(struct odp_pci_device *dev)
{
	struct mapped_pci_resource *uio_res;
	struct mapped_pci_res_list *uio_res_list = ODP_TAILQ_CAST(odp_uio_tailq.head, mapped_pci_res_list);

	if (!dev)
		return NULL;

	TAILQ_FOREACH(uio_res, uio_res_list, next)
	{
		/* skip this element if it doesn't match our PCI address */
		if (!odp_compare_pci_addr(&uio_res->pci_addr, &dev->addr))
			return uio_res;
	}
	return NULL;
}
Пример #6
0
/* map the PCI resource of a PCI device in virtual memory */
int pci_uio_map_resource(struct odp_pci_device *dev)
{
	int i, map_idx;
	char dirname[ODP_PATH_MAX];
	char cfgname[ODP_PATH_MAX];
	char devname[ODP_PATH_MAX]; /* contains the /dev/uioX */
	void *mapaddr;
	int  uio_num;
	uint64_t phaddr;
	struct odp_pci_addr *loc = &dev->addr;
	struct mapped_pci_resource *uio_res;
	struct mapped_pci_res_list *uio_res_list = ODP_TAILQ_CAST(odp_uio_tailq.head, mapped_pci_res_list);
	struct pci_map *maps;

	dev->intr_handle.fd = -1;
	dev->intr_handle.uio_cfg_fd = -1;
	dev->intr_handle.type = ODP_INTR_HANDLE_UNKNOWN;

	/* secondary processes - use already recorded details */
	if (odp_process_type() != ODP_PROC_PRIMARY)
		return pci_uio_map_secondary(dev);

	/* find uio resource */
	uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname));
	if (uio_num < 0) {
		PRINT("  " PCI_PRI_FMT " not managed by UIO driver, skipping\n",
		      loc->domain, loc->bus, loc->devid, loc->function);
		return 1;
	}

	snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);

	/* save fd if in primary process */
	dev->intr_handle.fd = open(devname, O_RDWR);
	if (dev->intr_handle.fd < 0) {
		PRINT("Cannot open %s: %s\n",
		      devname, strerror(errno));
		return -1;
	}

	dev->intr_handle.type = ODP_INTR_HANDLE_UIO;

	snprintf(cfgname, sizeof(cfgname),
		 "/sys/class/uio/uio%u/device/config", uio_num);
	dev->intr_handle.uio_cfg_fd = open(cfgname, O_RDWR);
	if (dev->intr_handle.uio_cfg_fd < 0) {
		PRINT("Cannot open %s: %s\n",
		      cfgname, strerror(errno));
		return -1;
	}

	/* set bus master that is not done by uio_pci_generic */
	if (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) {
		PRINT("Cannot set up bus mastering!\n");
		return -1;
	}

	/* allocate the mapping details for secondary processes*/
	uio_res = malloc(sizeof(*uio_res));
	if (!uio_res) {
		PRINT("%s(): cannot store uio mmap details\n", __func__);
		return -1;
	}

	snprintf(uio_res->path, sizeof(uio_res->path), "%s", devname);
	memcpy(&uio_res->pci_addr, &dev->addr, sizeof(uio_res->pci_addr));

	/* Map all BARs */
	maps = uio_res->maps;
	for (i = 0, map_idx = 0; i != PCI_MAX_RESOURCE; i++) {
		int fd;
		int fail = 0;

		/* skip empty BAR */
		phaddr = dev->mem_resource[i].phys_addr;
		if (phaddr == 0)
			continue;

		/* update devname for mmap  */
		snprintf(devname, sizeof(devname),
			 SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/resource%d",
			 loc->domain, loc->bus, loc->devid, loc->function,
			 i);

		/*
		 * open resource file, to mmap it
		 */
		fd = open(devname, O_RDWR);
		if (fd < 0) {
			PRINT("Cannot open %s: %s\n", devname, strerror(errno));
			return -1;
		}

		/* try mapping somewhere close to the end of hugepages */
		if (!pci_map_addr)
			pci_map_addr = pci_find_max_end_va();

		mapaddr = pci_map_resource(pci_map_addr, fd, 0,
					   (size_t)dev->mem_resource[i].len, 0);
		if (mapaddr == MAP_FAILED)
			fail = 1;

		pci_map_addr = ODP_PTR_ADD(mapaddr,
					    (size_t)dev->mem_resource[i].len);

		maps[map_idx].path = malloc(strlen(devname) + 1);
		if (!maps[map_idx].path)
			fail = 1;

		if (fail) {
			free(uio_res);
			close(fd);
			return -1;
		}

		close(fd);

		maps[map_idx].phaddr = dev->mem_resource[i].phys_addr;
		maps[map_idx].size = dev->mem_resource[i].len;
		maps[map_idx].addr = mapaddr;
		maps[map_idx].offset = 0;
		strcpy(maps[map_idx].path, devname);
		map_idx++;
		dev->mem_resource[i].addr = mapaddr;
	}

	uio_res->nb_maps = map_idx;

	TAILQ_INSERT_TAIL(uio_res_list, uio_res, next);

	return 0;
}