Commit c6aed238 authored by Loic Pallardy's avatar Loic Pallardy Committed by Bjorn Andersson

remoteproc: modify vring allocation to rely on centralized carveout allocator

Current version of rproc_alloc_vring function supports only dynamic vring
allocation.

This patch allows to allocate vrings based on memory region declatation.
Vrings are now manage like memory carveouts, to communize memory management
code in rproc_alloc_registered_carveouts().

Allocated buffer is retrieved in rp_find_vq() thanks to
rproc_find_carveout_by_name() functions for.

This patch sets vrings names to vdev"x"vring"y" with x vdev index in
resource table and y vring index in vdev. This will be updated when
name will be associated to vdev in firmware resource table.
Signed-off-by: default avatarLoic Pallardy <loic.pallardy@st.com>
Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent 1e2517d1
...@@ -53,6 +53,11 @@ typedef int (*rproc_handle_resources_t)(struct rproc *rproc, ...@@ -53,6 +53,11 @@ typedef int (*rproc_handle_resources_t)(struct rproc *rproc,
typedef int (*rproc_handle_resource_t)(struct rproc *rproc, typedef int (*rproc_handle_resource_t)(struct rproc *rproc,
void *, int offset, int avail); void *, int offset, int avail);
static int rproc_alloc_carveout(struct rproc *rproc,
struct rproc_mem_entry *mem);
static int rproc_release_carveout(struct rproc *rproc,
struct rproc_mem_entry *mem);
/* Unique indices for remoteproc devices */ /* Unique indices for remoteproc devices */
static DEFINE_IDA(rproc_dev_index); static DEFINE_IDA(rproc_dev_index);
...@@ -312,21 +317,33 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) ...@@ -312,21 +317,33 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
struct device *dev = &rproc->dev; struct device *dev = &rproc->dev;
struct rproc_vring *rvring = &rvdev->vring[i]; struct rproc_vring *rvring = &rvdev->vring[i];
struct fw_rsc_vdev *rsc; struct fw_rsc_vdev *rsc;
dma_addr_t dma;
void *va;
int ret, size, notifyid; int ret, size, notifyid;
struct rproc_mem_entry *mem;
/* actual size of vring (in bytes) */ /* actual size of vring (in bytes) */
size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
/* rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
* Allocate non-cacheable memory for the vring. In the future
* this call will also configure the IOMMU for us /* Search for pre-registered carveout */
*/ mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); i);
if (!va) { if (mem) {
dev_err(dev->parent, "dma_alloc_coherent failed\n"); if (rproc_check_carveout_da(rproc, mem, rsc->vring[i].da, size))
return -EINVAL; return -ENOMEM;
} else {
/* Register carveout in in list */
mem = rproc_mem_entry_init(dev, 0, 0, size, rsc->vring[i].da,
rproc_alloc_carveout,
rproc_release_carveout,
"vdev%dvring%d",
rvdev->index, i);
if (!mem) {
dev_err(dev, "Can't allocate memory entry structure\n");
return -ENOMEM;
}
rproc_add_carveout(rproc, mem);
} }
/* /*
...@@ -337,7 +354,6 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) ...@@ -337,7 +354,6 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL); ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "idr_alloc failed: %d\n", ret); dev_err(dev, "idr_alloc failed: %d\n", ret);
dma_free_coherent(dev->parent, size, va, dma);
return ret; return ret;
} }
notifyid = ret; notifyid = ret;
...@@ -346,21 +362,9 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i) ...@@ -346,21 +362,9 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
if (notifyid > rproc->max_notifyid) if (notifyid > rproc->max_notifyid)
rproc->max_notifyid = notifyid; rproc->max_notifyid = notifyid;
dev_dbg(dev, "vring%d: va %pK dma %pad size 0x%x idr %d\n",
i, va, &dma, size, notifyid);
rvring->va = va;
rvring->dma = dma;
rvring->notifyid = notifyid; rvring->notifyid = notifyid;
/* /* Let the rproc know the notifyid of this vring.*/
* Let the rproc know the notifyid and da of this vring.
* Not all platforms use dma_alloc_coherent to automatically
* set up the iommu. In this case the device address (da) will
* hold the physical address and not the device address.
*/
rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
rsc->vring[i].da = dma;
rsc->vring[i].notifyid = notifyid; rsc->vring[i].notifyid = notifyid;
return 0; return 0;
} }
...@@ -392,12 +396,10 @@ rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i) ...@@ -392,12 +396,10 @@ rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
void rproc_free_vring(struct rproc_vring *rvring) void rproc_free_vring(struct rproc_vring *rvring)
{ {
int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
struct rproc *rproc = rvring->rvdev->rproc; struct rproc *rproc = rvring->rvdev->rproc;
int idx = rvring->rvdev->vring - rvring; int idx = rvring->rvdev->vring - rvring;
struct fw_rsc_vdev *rsc; struct fw_rsc_vdev *rsc;
dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma);
idr_remove(&rproc->notifyids, rvring->notifyid); idr_remove(&rproc->notifyids, rvring->notifyid);
/* reset resource entry info */ /* reset resource entry info */
...@@ -484,6 +486,7 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, ...@@ -484,6 +486,7 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
rvdev->id = rsc->id; rvdev->id = rsc->id;
rvdev->rproc = rproc; rvdev->rproc = rproc;
rvdev->index = rproc->nb_vdev++;
/* parse the vrings */ /* parse the vrings */
for (i = 0; i < rsc->num_of_vrings; i++) { for (i = 0; i < rsc->num_of_vrings; i++) {
...@@ -528,9 +531,6 @@ void rproc_vdev_release(struct kref *ref) ...@@ -528,9 +531,6 @@ void rproc_vdev_release(struct kref *ref)
for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
rvring = &rvdev->vring[id]; rvring = &rvdev->vring[id];
if (!rvring->va)
continue;
rproc_free_vring(rvring); rproc_free_vring(rvring);
} }
...@@ -1323,6 +1323,9 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) ...@@ -1323,6 +1323,9 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
/* reset max_notifyid */ /* reset max_notifyid */
rproc->max_notifyid = -1; rproc->max_notifyid = -1;
/* reset handled vdev */
rproc->nb_vdev = 0;
/* handle fw resources which are required to boot rproc */ /* handle fw resources which are required to boot rproc */
ret = rproc_handle_resources(rproc, rproc_loading_handlers); ret = rproc_handle_resources(rproc, rproc_loading_handlers);
if (ret) { if (ret) {
......
...@@ -60,6 +60,8 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw); ...@@ -60,6 +60,8 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw); int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
const struct firmware *fw); const struct firmware *fw);
struct rproc_mem_entry *
rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...);
static inline static inline
int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
......
...@@ -76,7 +76,9 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, ...@@ -76,7 +76,9 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
struct rproc *rproc = vdev_to_rproc(vdev); struct rproc *rproc = vdev_to_rproc(vdev);
struct device *dev = &rproc->dev; struct device *dev = &rproc->dev;
struct rproc_mem_entry *mem;
struct rproc_vring *rvring; struct rproc_vring *rvring;
struct fw_rsc_vdev *rsc;
struct virtqueue *vq; struct virtqueue *vq;
void *addr; void *addr;
int len, size; int len, size;
...@@ -88,8 +90,14 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, ...@@ -88,8 +90,14 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
if (!name) if (!name)
return NULL; return NULL;
/* Search allocated memory region by name */
mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
id);
if (!mem || !mem->va)
return ERR_PTR(-ENOMEM);
rvring = &rvdev->vring[id]; rvring = &rvdev->vring[id];
addr = rvring->va; addr = mem->va;
len = rvring->len; len = rvring->len;
/* zero vring */ /* zero vring */
...@@ -114,6 +122,10 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, ...@@ -114,6 +122,10 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
rvring->vq = vq; rvring->vq = vq;
vq->priv = rvring; vq->priv = rvring;
/* Update vring in resource table */
rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
rsc->vring[id].da = mem->da;
return vq; return vq;
} }
......
...@@ -454,6 +454,7 @@ struct rproc_dump_segment { ...@@ -454,6 +454,7 @@ struct rproc_dump_segment {
* @has_iommu: flag to indicate if remote processor is behind an MMU * @has_iommu: flag to indicate if remote processor is behind an MMU
* @auto_boot: flag to indicate if remote processor should be auto-started * @auto_boot: flag to indicate if remote processor should be auto-started
* @dump_segments: list of segments in the firmware * @dump_segments: list of segments in the firmware
* @nb_vdev: number of vdev currently handled by rproc
*/ */
struct rproc { struct rproc {
struct list_head node; struct list_head node;
...@@ -486,6 +487,7 @@ struct rproc { ...@@ -486,6 +487,7 @@ struct rproc {
bool has_iommu; bool has_iommu;
bool auto_boot; bool auto_boot;
struct list_head dump_segments; struct list_head dump_segments;
int nb_vdev;
}; };
/** /**
...@@ -513,7 +515,6 @@ struct rproc_subdev { ...@@ -513,7 +515,6 @@ struct rproc_subdev {
/** /**
* struct rproc_vring - remoteproc vring state * struct rproc_vring - remoteproc vring state
* @va: virtual address * @va: virtual address
* @dma: dma address
* @len: length, in bytes * @len: length, in bytes
* @da: device address * @da: device address
* @align: vring alignment * @align: vring alignment
...@@ -523,7 +524,6 @@ struct rproc_subdev { ...@@ -523,7 +524,6 @@ struct rproc_subdev {
*/ */
struct rproc_vring { struct rproc_vring {
void *va; void *va;
dma_addr_t dma;
int len; int len;
u32 da; u32 da;
u32 align; u32 align;
...@@ -542,6 +542,7 @@ struct rproc_vring { ...@@ -542,6 +542,7 @@ struct rproc_vring {
* @vdev: the virio device * @vdev: the virio device
* @vring: the vrings for this vdev * @vring: the vrings for this vdev
* @rsc_offset: offset of the vdev's resource entry * @rsc_offset: offset of the vdev's resource entry
* @index: vdev position versus other vdev declared in resource table
*/ */
struct rproc_vdev { struct rproc_vdev {
struct kref refcount; struct kref refcount;
...@@ -554,6 +555,7 @@ struct rproc_vdev { ...@@ -554,6 +555,7 @@ struct rproc_vdev {
struct virtio_device vdev; struct virtio_device vdev;
struct rproc_vring vring[RVDEV_NUM_VRINGS]; struct rproc_vring vring[RVDEV_NUM_VRINGS];
u32 rsc_offset; u32 rsc_offset;
u32 index;
}; };
struct rproc *rproc_get_by_phandle(phandle phandle); struct rproc *rproc_get_by_phandle(phandle phandle);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment