summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoic Pallardy <loic.pallardy@st.com>2018-07-27 09:14:47 -0400
committerBjorn Andersson <bjorn.andersson@linaro.org>2018-10-15 02:37:40 -0400
commitc6aed238b7a9b15a5c90a0c31f1d36577b5d2cbe (patch)
tree3cd3bbf5c01854a6777c7b47fedafed245d12e64
parent1e2517d126171a41f801738ffd19687836cd178a (diff)
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: Loic Pallardy <loic.pallardy@st.com> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r--drivers/remoteproc/remoteproc_core.c61
-rw-r--r--drivers/remoteproc/remoteproc_internal.h2
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c14
-rw-r--r--include/linux/remoteproc.h6
4 files changed, 51 insertions, 32 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 5abcd27a29f3..f77a42f6a8aa 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -53,6 +53,11 @@ typedef int (*rproc_handle_resources_t)(struct rproc *rproc,
53typedef int (*rproc_handle_resource_t)(struct rproc *rproc, 53typedef int (*rproc_handle_resource_t)(struct rproc *rproc,
54 void *, int offset, int avail); 54 void *, int offset, int avail);
55 55
56static int rproc_alloc_carveout(struct rproc *rproc,
57 struct rproc_mem_entry *mem);
58static int rproc_release_carveout(struct rproc *rproc,
59 struct rproc_mem_entry *mem);
60
56/* Unique indices for remoteproc devices */ 61/* Unique indices for remoteproc devices */
57static DEFINE_IDA(rproc_dev_index); 62static DEFINE_IDA(rproc_dev_index);
58 63
@@ -312,21 +317,33 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
312 struct device *dev = &rproc->dev; 317 struct device *dev = &rproc->dev;
313 struct rproc_vring *rvring = &rvdev->vring[i]; 318 struct rproc_vring *rvring = &rvdev->vring[i];
314 struct fw_rsc_vdev *rsc; 319 struct fw_rsc_vdev *rsc;
315 dma_addr_t dma;
316 void *va;
317 int ret, size, notifyid; 320 int ret, size, notifyid;
321 struct rproc_mem_entry *mem;
318 322
319 /* actual size of vring (in bytes) */ 323 /* actual size of vring (in bytes) */
320 size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); 324 size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
321 325
322 /* 326 rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
323 * Allocate non-cacheable memory for the vring. In the future 327
324 * this call will also configure the IOMMU for us 328 /* Search for pre-registered carveout */
325 */ 329 mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
326 va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL); 330 i);
327 if (!va) { 331 if (mem) {
328 dev_err(dev->parent, "dma_alloc_coherent failed\n"); 332 if (rproc_check_carveout_da(rproc, mem, rsc->vring[i].da, size))
329 return -EINVAL; 333 return -ENOMEM;
334 } else {
335 /* Register carveout in in list */
336 mem = rproc_mem_entry_init(dev, 0, 0, size, rsc->vring[i].da,
337 rproc_alloc_carveout,
338 rproc_release_carveout,
339 "vdev%dvring%d",
340 rvdev->index, i);
341 if (!mem) {
342 dev_err(dev, "Can't allocate memory entry structure\n");
343 return -ENOMEM;
344 }
345
346 rproc_add_carveout(rproc, mem);
330 } 347 }
331 348
332 /* 349 /*
@@ -337,7 +354,6 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
337 ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL); 354 ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
338 if (ret < 0) { 355 if (ret < 0) {
339 dev_err(dev, "idr_alloc failed: %d\n", ret); 356 dev_err(dev, "idr_alloc failed: %d\n", ret);
340 dma_free_coherent(dev->parent, size, va, dma);
341 return ret; 357 return ret;
342 } 358 }
343 notifyid = ret; 359 notifyid = ret;
@@ -346,21 +362,9 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
346 if (notifyid > rproc->max_notifyid) 362 if (notifyid > rproc->max_notifyid)
347 rproc->max_notifyid = notifyid; 363 rproc->max_notifyid = notifyid;
348 364
349 dev_dbg(dev, "vring%d: va %pK dma %pad size 0x%x idr %d\n",
350 i, va, &dma, size, notifyid);
351
352 rvring->va = va;
353 rvring->dma = dma;
354 rvring->notifyid = notifyid; 365 rvring->notifyid = notifyid;
355 366
356 /* 367 /* Let the rproc know the notifyid of this vring.*/
357 * Let the rproc know the notifyid and da of this vring.
358 * Not all platforms use dma_alloc_coherent to automatically
359 * set up the iommu. In this case the device address (da) will
360 * hold the physical address and not the device address.
361 */
362 rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
363 rsc->vring[i].da = dma;
364 rsc->vring[i].notifyid = notifyid; 368 rsc->vring[i].notifyid = notifyid;
365 return 0; 369 return 0;
366} 370}
@@ -392,12 +396,10 @@ rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
392 396
393void rproc_free_vring(struct rproc_vring *rvring) 397void rproc_free_vring(struct rproc_vring *rvring)
394{ 398{
395 int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
396 struct rproc *rproc = rvring->rvdev->rproc; 399 struct rproc *rproc = rvring->rvdev->rproc;
397 int idx = rvring->rvdev->vring - rvring; 400 int idx = rvring->rvdev->vring - rvring;
398 struct fw_rsc_vdev *rsc; 401 struct fw_rsc_vdev *rsc;
399 402
400 dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma);
401 idr_remove(&rproc->notifyids, rvring->notifyid); 403 idr_remove(&rproc->notifyids, rvring->notifyid);
402 404
403 /* reset resource entry info */ 405 /* reset resource entry info */
@@ -484,6 +486,7 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
484 486
485 rvdev->id = rsc->id; 487 rvdev->id = rsc->id;
486 rvdev->rproc = rproc; 488 rvdev->rproc = rproc;
489 rvdev->index = rproc->nb_vdev++;
487 490
488 /* parse the vrings */ 491 /* parse the vrings */
489 for (i = 0; i < rsc->num_of_vrings; i++) { 492 for (i = 0; i < rsc->num_of_vrings; i++) {
@@ -528,9 +531,6 @@ void rproc_vdev_release(struct kref *ref)
528 531
529 for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { 532 for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) {
530 rvring = &rvdev->vring[id]; 533 rvring = &rvdev->vring[id];
531 if (!rvring->va)
532 continue;
533
534 rproc_free_vring(rvring); 534 rproc_free_vring(rvring);
535 } 535 }
536 536
@@ -1323,6 +1323,9 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
1323 /* reset max_notifyid */ 1323 /* reset max_notifyid */
1324 rproc->max_notifyid = -1; 1324 rproc->max_notifyid = -1;
1325 1325
1326 /* reset handled vdev */
1327 rproc->nb_vdev = 0;
1328
1326 /* handle fw resources which are required to boot rproc */ 1329 /* handle fw resources which are required to boot rproc */
1327 ret = rproc_handle_resources(rproc, rproc_loading_handlers); 1330 ret = rproc_handle_resources(rproc, rproc_loading_handlers);
1328 if (ret) { 1331 if (ret) {
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 7570beb035b5..f6cad243d7ca 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -60,6 +60,8 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw);
60int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw); 60int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw);
61struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, 61struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
62 const struct firmware *fw); 62 const struct firmware *fw);
63struct rproc_mem_entry *
64rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...);
63 65
64static inline 66static inline
65int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) 67int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index bbecd44df7e8..de21f620b882 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -76,7 +76,9 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
76 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 76 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
77 struct rproc *rproc = vdev_to_rproc(vdev); 77 struct rproc *rproc = vdev_to_rproc(vdev);
78 struct device *dev = &rproc->dev; 78 struct device *dev = &rproc->dev;
79 struct rproc_mem_entry *mem;
79 struct rproc_vring *rvring; 80 struct rproc_vring *rvring;
81 struct fw_rsc_vdev *rsc;
80 struct virtqueue *vq; 82 struct virtqueue *vq;
81 void *addr; 83 void *addr;
82 int len, size; 84 int len, size;
@@ -88,8 +90,14 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
88 if (!name) 90 if (!name)
89 return NULL; 91 return NULL;
90 92
93 /* Search allocated memory region by name */
94 mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
95 id);
96 if (!mem || !mem->va)
97 return ERR_PTR(-ENOMEM);
98
91 rvring = &rvdev->vring[id]; 99 rvring = &rvdev->vring[id];
92 addr = rvring->va; 100 addr = mem->va;
93 len = rvring->len; 101 len = rvring->len;
94 102
95 /* zero vring */ 103 /* zero vring */
@@ -114,6 +122,10 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
114 rvring->vq = vq; 122 rvring->vq = vq;
115 vq->priv = rvring; 123 vq->priv = rvring;
116 124
125 /* Update vring in resource table */
126 rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
127 rsc->vring[id].da = mem->da;
128
117 return vq; 129 return vq;
118} 130}
119 131
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index d4cabe8da507..8bb0cf0416f1 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -454,6 +454,7 @@ struct rproc_dump_segment {
454 * @has_iommu: flag to indicate if remote processor is behind an MMU 454 * @has_iommu: flag to indicate if remote processor is behind an MMU
455 * @auto_boot: flag to indicate if remote processor should be auto-started 455 * @auto_boot: flag to indicate if remote processor should be auto-started
456 * @dump_segments: list of segments in the firmware 456 * @dump_segments: list of segments in the firmware
457 * @nb_vdev: number of vdev currently handled by rproc
457 */ 458 */
458struct rproc { 459struct rproc {
459 struct list_head node; 460 struct list_head node;
@@ -486,6 +487,7 @@ struct rproc {
486 bool has_iommu; 487 bool has_iommu;
487 bool auto_boot; 488 bool auto_boot;
488 struct list_head dump_segments; 489 struct list_head dump_segments;
490 int nb_vdev;
489}; 491};
490 492
491/** 493/**
@@ -513,7 +515,6 @@ struct rproc_subdev {
513/** 515/**
514 * struct rproc_vring - remoteproc vring state 516 * struct rproc_vring - remoteproc vring state
515 * @va: virtual address 517 * @va: virtual address
516 * @dma: dma address
517 * @len: length, in bytes 518 * @len: length, in bytes
518 * @da: device address 519 * @da: device address
519 * @align: vring alignment 520 * @align: vring alignment
@@ -523,7 +524,6 @@ struct rproc_subdev {
523 */ 524 */
524struct rproc_vring { 525struct rproc_vring {
525 void *va; 526 void *va;
526 dma_addr_t dma;
527 int len; 527 int len;
528 u32 da; 528 u32 da;
529 u32 align; 529 u32 align;
@@ -542,6 +542,7 @@ struct rproc_vring {
542 * @vdev: the virio device 542 * @vdev: the virio device
543 * @vring: the vrings for this vdev 543 * @vring: the vrings for this vdev
544 * @rsc_offset: offset of the vdev's resource entry 544 * @rsc_offset: offset of the vdev's resource entry
545 * @index: vdev position versus other vdev declared in resource table
545 */ 546 */
546struct rproc_vdev { 547struct rproc_vdev {
547 struct kref refcount; 548 struct kref refcount;
@@ -554,6 +555,7 @@ struct rproc_vdev {
554 struct virtio_device vdev; 555 struct virtio_device vdev;
555 struct rproc_vring vring[RVDEV_NUM_VRINGS]; 556 struct rproc_vring vring[RVDEV_NUM_VRINGS];
556 u32 rsc_offset; 557 u32 rsc_offset;
558 u32 index;
557}; 559};
558 560
559struct rproc *rproc_get_by_phandle(phandle phandle); 561struct rproc *rproc_get_by_phandle(phandle phandle);