in remoteproc_virtio.c [342:439]
int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
{
struct rproc *rproc = rvdev->rproc;
struct device *dev = &rvdev->dev;
struct virtio_device *vdev;
struct rproc_mem_entry *mem;
int ret;
if (rproc->ops->kick == NULL) {
ret = -EINVAL;
dev_err(dev, ".kick method not defined for %s\n", rproc->name);
goto out;
}
/* Try to find dedicated vdev buffer carveout */
mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index);
if (mem) {
phys_addr_t pa;
if (mem->of_resm_idx != -1) {
struct device_node *np = rproc->dev.parent->of_node;
/* Associate reserved memory to vdev device */
ret = of_reserved_mem_device_init_by_idx(dev, np,
mem->of_resm_idx);
if (ret) {
dev_err(dev, "Can't associate reserved memory\n");
goto out;
}
} else {
if (mem->va) {
dev_warn(dev, "vdev %d buffer already mapped\n",
rvdev->index);
pa = rproc_va_to_pa(mem->va);
} else {
/* Use dma address as carveout no memmapped yet */
pa = (phys_addr_t)mem->dma;
}
/* Associate vdev buffer memory pool to vdev subdev */
ret = dma_declare_coherent_memory(dev, pa,
mem->da,
mem->len);
if (ret < 0) {
dev_err(dev, "Failed to associate buffer\n");
goto out;
}
}
} else {
struct device_node *np = rproc->dev.parent->of_node;
/*
* If we don't have dedicated buffer, just attempt to re-assign
* the reserved memory from our parent. A default memory-region
* at index 0 from the parent's memory-regions is assigned for
* the rvdev dev to allocate from. Failure is non-critical and
* the allocations will fall back to global pools, so don't
* check return value either.
*/
of_reserved_mem_device_init_by_idx(dev, np, 0);
}
/* Allocate virtio device */
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
if (!vdev) {
ret = -ENOMEM;
goto out;
}
vdev->id.device = id,
vdev->config = &rproc_virtio_config_ops,
vdev->dev.parent = dev;
vdev->dev.release = rproc_virtio_dev_release;
/*
* We're indirectly making a non-temporary copy of the rproc pointer
* here, because drivers probed with this vdev will indirectly
* access the wrapping rproc.
*
* Therefore we must increment the rproc refcount here, and decrement
* it _only_ when the vdev is released.
*/
get_device(&rproc->dev);
/* Reference the vdev and vring allocations */
kref_get(&rvdev->refcount);
ret = register_virtio_device(vdev);
if (ret) {
put_device(&vdev->dev);
dev_err(dev, "failed to register vdev: %d\n", ret);
goto out;
}
dev_info(dev, "registered %s (type %d)\n", dev_name(&vdev->dev), id);
out:
return ret;
}