From fd28f879e6274d477378362d848b42747ecb27eb Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Wed, 21 Sep 2022 15:50:41 +0200 Subject: [PATCH] remoteproc: core: Introduce rproc_rvdev_add_device function In preparation of the migration of the management of rvdev in remoteproc_virtio.c, this patch spins off a new function to manage the remoteproc virtio device creation. The rproc_rvdev_add_device will be moved to remoteproc_virtio.c. The rproc_vdev_data structure is introduced to provide information for the rvdev creation. This structure allows to manage the rvdev and vrings allocation in the rproc_rvdev_add_device function. Signed-off-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20220921135044.917140-2-arnaud.pouliquen@foss.st.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_core.c | 191 +++++++++++++---------- drivers/remoteproc/remoteproc_internal.h | 15 ++ 2 files changed, 120 insertions(+), 86 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index f5ba3b305aaf..f8dd8c526299 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -486,6 +486,103 @@ static int copy_dma_range_map(struct device *to, struct device *from) return 0; } +static struct rproc_vdev * +rproc_rvdev_add_device(struct rproc *rproc, struct rproc_vdev_data *rvdev_data) +{ + struct rproc_vdev *rvdev; + struct fw_rsc_vdev *rsc = rvdev_data->rsc; + char name[16]; + int i, ret; + + rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL); + if (!rvdev) + return ERR_PTR(-ENOMEM); + + kref_init(&rvdev->refcount); + + rvdev->id = rvdev_data->id; + rvdev->rproc = rproc; + rvdev->index = rvdev_data->index; + + /* Initialise vdev subdevice */ + snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index); + rvdev->dev.parent = &rproc->dev; + rvdev->dev.release = rproc_rvdev_release; + dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name); + dev_set_drvdata(&rvdev->dev, rvdev); + + ret = device_register(&rvdev->dev); + if (ret) { + put_device(&rvdev->dev); + return ERR_PTR(ret); + } + + ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); + if (ret) + goto free_rvdev; + + /* Make device dma capable by inheriting from parent's capabilities */ + set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent)); + + ret = dma_coerce_mask_and_coherent(&rvdev->dev, + dma_get_mask(rproc->dev.parent)); + if (ret) { + dev_warn(&rvdev->dev, + "Failed to set DMA mask %llx. Trying to continue... (%pe)\n", + dma_get_mask(rproc->dev.parent), ERR_PTR(ret)); + } + + /* parse the vrings */ + for (i = 0; i < rsc->num_of_vrings; i++) { + ret = rproc_parse_vring(rvdev, rsc, i); + if (ret) + goto free_rvdev; + } + + /* remember the resource offset*/ + rvdev->rsc_offset = rvdev_data->rsc_offset; + + /* allocate the vring resources */ + for (i = 0; i < rsc->num_of_vrings; i++) { + ret = rproc_alloc_vring(rvdev, i); + if (ret) + goto unwind_vring_allocations; + } + + list_add_tail(&rvdev->node, &rproc->rvdevs); + + rvdev->subdev.start = rproc_vdev_do_start; + rvdev->subdev.stop = rproc_vdev_do_stop; + + rproc_add_subdev(rproc, &rvdev->subdev); + + return rvdev; + +unwind_vring_allocations: + for (i--; i >= 0; i--) + rproc_free_vring(&rvdev->vring[i]); +free_rvdev: + device_unregister(&rvdev->dev); + return ERR_PTR(ret); +} + +void rproc_vdev_release(struct kref *ref) +{ + struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount); + struct rproc_vring *rvring; + struct rproc *rproc = rvdev->rproc; + int id; + + for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { + rvring = &rvdev->vring[id]; + rproc_free_vring(rvring); + } + + rproc_remove_subdev(rproc, &rvdev->subdev); + list_del(&rvdev->node); + device_unregister(&rvdev->dev); +} + /** * rproc_handle_vdev() - handle a vdev fw resource * @rproc: the remote processor @@ -521,8 +618,7 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, struct device *dev = &rproc->dev; struct rproc_vdev *rvdev; size_t rsc_size; - int i, ret; - char name[16]; + struct rproc_vdev_data rvdev_data; /* make sure resource isn't truncated */ rsc_size = struct_size(rsc, vring, rsc->num_of_vrings); @@ -546,93 +642,16 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, return -EINVAL; } - rvdev = kzalloc(sizeof(*rvdev), GFP_KERNEL); - if (!rvdev) - return -ENOMEM; + rvdev_data.id = rsc->id; + rvdev_data.index = rproc->nb_vdev++; + rvdev_data.rsc_offset = offset; + rvdev_data.rsc = rsc; - kref_init(&rvdev->refcount); - - rvdev->id = rsc->id; - rvdev->rproc = rproc; - rvdev->index = rproc->nb_vdev++; - - /* Initialise vdev subdevice */ - snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index); - rvdev->dev.parent = &rproc->dev; - rvdev->dev.release = rproc_rvdev_release; - dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name); - dev_set_drvdata(&rvdev->dev, rvdev); - - ret = device_register(&rvdev->dev); - if (ret) { - put_device(&rvdev->dev); - return ret; - } - - ret = copy_dma_range_map(&rvdev->dev, rproc->dev.parent); - if (ret) - goto free_rvdev; - - /* Make device dma capable by inheriting from parent's capabilities */ - set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent)); - - ret = dma_coerce_mask_and_coherent(&rvdev->dev, - dma_get_mask(rproc->dev.parent)); - if (ret) { - dev_warn(dev, - "Failed to set DMA mask %llx. Trying to continue... (%pe)\n", - dma_get_mask(rproc->dev.parent), ERR_PTR(ret)); - } - - /* parse the vrings */ - for (i = 0; i < rsc->num_of_vrings; i++) { - ret = rproc_parse_vring(rvdev, rsc, i); - if (ret) - goto free_rvdev; - } - - /* remember the resource offset*/ - rvdev->rsc_offset = offset; - - /* allocate the vring resources */ - for (i = 0; i < rsc->num_of_vrings; i++) { - ret = rproc_alloc_vring(rvdev, i); - if (ret) - goto unwind_vring_allocations; - } - - list_add_tail(&rvdev->node, &rproc->rvdevs); - - rvdev->subdev.start = rproc_vdev_do_start; - rvdev->subdev.stop = rproc_vdev_do_stop; - - rproc_add_subdev(rproc, &rvdev->subdev); + rvdev = rproc_rvdev_add_device(rproc, &rvdev_data); + if (IS_ERR(rvdev)) + return PTR_ERR(rvdev); return 0; - -unwind_vring_allocations: - for (i--; i >= 0; i--) - rproc_free_vring(&rvdev->vring[i]); -free_rvdev: - device_unregister(&rvdev->dev); - return ret; -} - -void rproc_vdev_release(struct kref *ref) -{ - struct rproc_vdev *rvdev = container_of(ref, struct rproc_vdev, refcount); - struct rproc_vring *rvring; - struct rproc *rproc = rvdev->rproc; - int id; - - for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { - rvring = &rvdev->vring[id]; - rproc_free_vring(rvring); - } - - rproc_remove_subdev(rproc, &rvdev->subdev); - list_del(&rvdev->node); - device_unregister(&rvdev->dev); } /** diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 72d4d3d7d94d..07c503de0f95 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -24,6 +24,21 @@ struct rproc_debug_trace { struct rproc_mem_entry trace_mem; }; +/** + * struct rproc_vdev_data - remoteproc virtio device data + * @rsc_offset: offset of the vdev's resource entry + * @id: virtio device id (as in virtio_ids.h) + * @index: vdev position versus other vdev declared in resource table + * @rsc: pointer to the vdev resource entry. Valid only during vdev init as + * the resource can be cached by rproc. + */ +struct rproc_vdev_data { + u32 rsc_offset; + unsigned int id; + u32 index; + struct fw_rsc_vdev *rsc; +}; + /* from remoteproc_core.c */ void rproc_release(struct kref *kref); irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);