summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);