aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2012-02-13 16:30:39 -0500
committerOhad Ben-Cohen <ohad@wizery.com>2012-03-06 12:14:12 -0500
commit7a186941626d19f668b08108db158379b32e6e02 (patch)
treed478210fa3ae45ef8b3eaf6a6432eadc49cbb55a /drivers/remoteproc
parent41a6ee09ee8dd7ac3a6ac12a24e26279b5d93385 (diff)
remoteproc: remove the single rpmsg vdev limitation
Now that the resource table supports publishing a virtio device in a single resource entry, firmware images can start supporting more than a single vdev. This patch removes the single vdev limitation of the remoteproc framework so multi-vdev firmwares can be leveraged: VDEV resource entries are parsed when the rproc is registered, and as a result their vrings are set up and the virtio devices are registered (and they go away when the rproc goes away). Moreover, we no longer only support VIRTIO_ID_RPMSG vdevs; any virtio device type goes now. As a result, there's no more any rpmsg-specific APIs or code in remoteproc: it all becomes generic virtio handling. Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com> Cc: Brian Swetland <swetland@google.com> Cc: Iliyan Malchev <malchev@google.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Grant Likely <grant.likely@secretlab.ca> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Mark Grosen <mgrosen@ti.com> Cc: John Williams <john.williams@petalogix.com> Cc: Michal Simek <monstr@monstr.eu> Cc: Loic PALLARDY <loic.pallardy@stericsson.com> Cc: Ludovic BARRE <ludovic.barre@stericsson.com> Cc: Omar Ramirez Luna <omar.luna@linaro.org> Cc: Guzman Lugo Fernando <fernando.lugo@ti.com> Cc: Anna Suman <s-anna@ti.com> Cc: Clark Rob <rob@ti.com> Cc: Stephen Boyd <sboyd@codeaurora.org> Cc: Saravana Kannan <skannan@codeaurora.org> Cc: David Brown <davidb@codeaurora.org> Cc: Kieran Bingham <kieranbingham@gmail.com> Cc: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/remoteproc_core.c292
-rw-r--r--drivers/remoteproc/remoteproc_internal.h6
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c140
3 files changed, 218 insertions, 220 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 10348451c6c9..ca02f128b435 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -52,8 +52,8 @@ static void klist_rproc_put(struct klist_node *n);
52 * We need this in order to support name-based lookups (needed by the 52 * We need this in order to support name-based lookups (needed by the
53 * rproc_get_by_name()). 53 * rproc_get_by_name()).
54 * 54 *
55 * That said, we don't use rproc_get_by_name() anymore within the rpmsg 55 * That said, we don't use rproc_get_by_name() at this point.
56 * framework. The use cases that do require its existence should be 56 * The use cases that do require its existence should be
57 * scrutinized, and hopefully migrated to rproc_boot() using device-based 57 * scrutinized, and hopefully migrated to rproc_boot() using device-based
58 * binding. 58 * binding.
59 * 59 *
@@ -279,80 +279,112 @@ rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len)
279 return ret; 279 return ret;
280} 280}
281 281
282/** 282static int
283 * rproc_handle_early_vdev() - early handle a virtio header resource 283__rproc_handle_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
284 * @rproc: the remote processor
285 * @rsc: the resource descriptor
286 * @avail: size of available data (for sanity checking the image)
287 *
288 * The existence of this virtio hdr resource entry means that the firmware
289 * of this @rproc supports this virtio device.
290 *
291 * Currently we support only a single virtio device of type VIRTIO_ID_RPMSG,
292 * but the plan is to remove this limitation and support any number
293 * of virtio devices (and of any type). We'll also add support for dynamically
294 * adding (and removing) virtio devices over the rpmsg bus, but simple
295 * firmwares that doesn't want to get involved with rpmsg will be able
296 * to simply use the resource table for this.
297 *
298 * Returns 0 on success, or an appropriate error code otherwise
299 */
300static int rproc_handle_early_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
301 int avail)
302{ 284{
303 struct rproc_vdev *rvdev; 285 struct rproc *rproc = rvdev->rproc;
286 struct device *dev = rproc->dev;
287 struct fw_rsc_vdev_vring *vring = &rsc->vring[i];
288 dma_addr_t dma;
289 void *va;
290 int ret, size, notifyid;
304 291
305 /* make sure resource isn't truncated */ 292 dev_dbg(dev, "vdev rsc: vring%d: da %x, qsz %d, align %d\n",
306 if (sizeof(*rsc) > avail) { 293 i, vring->da, vring->num, vring->align);
307 dev_err(rproc->dev, "vdev rsc is truncated\n"); 294
295 /* make sure reserved bytes are zeroes */
296 if (vring->reserved) {
297 dev_err(dev, "vring rsc has non zero reserved bytes\n");
308 return -EINVAL; 298 return -EINVAL;
309 } 299 }
310 300
311 /* we only support VIRTIO_ID_RPMSG devices for now */ 301 /* the firmware must provide the expected queue size */
312 if (rsc->id != VIRTIO_ID_RPMSG) { 302 if (!vring->num) {
313 dev_warn(rproc->dev, "unsupported vdev: %d\n", rsc->id); 303 dev_err(dev, "invalid qsz (%d)\n", vring->num);
314 return -EINVAL; 304 return -EINVAL;
315 } 305 }
316 306
317 /* we only support a single vdev per rproc for now */ 307 /* actual size of vring (in bytes) */
318 if (rproc->rvdev) { 308 size = PAGE_ALIGN(vring_size(vring->num, AMP_VRING_ALIGN));
319 dev_warn(rproc->dev, "redundant vdev entry\n"); 309
310 if (!idr_pre_get(&rproc->notifyids, GFP_KERNEL)) {
311 dev_err(dev, "idr_pre_get failed\n");
312 return -ENOMEM;
313 }
314
315 /*
316 * Allocate non-cacheable memory for the vring. In the future
317 * this call will also configure the IOMMU for us
318 */
319 va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL);
320 if (!va) {
321 dev_err(dev, "dma_alloc_coherent failed\n");
320 return -EINVAL; 322 return -EINVAL;
321 } 323 }
322 324
323 rvdev = kzalloc(sizeof(struct rproc_vdev), GFP_KERNEL); 325 /* assign an rproc-wide unique index for this vring */
324 if (!rvdev) 326 /* TODO: assign a notifyid for rvdev updates as well */
325 return -ENOMEM; 327 ret = idr_get_new(&rproc->notifyids, &rvdev->vring[i], &notifyid);
328 if (ret) {
329 dev_err(dev, "idr_get_new failed: %d\n", ret);
330 dma_free_coherent(dev, size, va, dma);
331 return ret;
332 }
326 333
327 /* remember the device features */ 334 /* let the rproc know the da and notifyid of this vring */
328 rvdev->dfeatures = rsc->dfeatures; 335 /* TODO: expose this to remote processor */
336 vring->da = dma;
337 vring->notifyid = notifyid;
329 338
330 rproc->rvdev = rvdev; 339 dev_dbg(dev, "vring%d: va %p dma %x size %x idr %d\n", i, va,
331 rvdev->rproc = rproc; 340 dma, size, notifyid);
341
342 rvdev->vring[i].len = vring->num;
343 rvdev->vring[i].va = va;
344 rvdev->vring[i].dma = dma;
345 rvdev->vring[i].notifyid = notifyid;
346 rvdev->vring[i].rvdev = rvdev;
332 347
333 return 0; 348 return 0;
334} 349}
335 350
351static void __rproc_free_vrings(struct rproc_vdev *rvdev, int i)
352{
353 struct rproc *rproc = rvdev->rproc;
354
355 for (i--; i > 0; i--) {
356 struct rproc_vring *rvring = &rvdev->vring[i];
357 int size = PAGE_ALIGN(vring_size(rvring->len, AMP_VRING_ALIGN));
358
359 dma_free_coherent(rproc->dev, size, rvring->va, rvring->dma);
360 idr_remove(&rproc->notifyids, rvring->notifyid);
361 }
362}
363
336/** 364/**
337 * rproc_handle_vdev() - handle a vdev fw resource 365 * rproc_handle_vdev() - handle a vdev fw resource
338 * @rproc: the remote processor 366 * @rproc: the remote processor
339 * @rsc: the vring resource descriptor 367 * @rsc: the vring resource descriptor
340 * @avail: size of available data (for sanity checking the image) 368 * @avail: size of available data (for sanity checking the image)
341 * 369 *
342 * This resource entry requires allocation of non-cacheable memory 370 * This resource entry requests the host to statically register a virtio
343 * for a virtio vring. Currently we only support two vrings per remote 371 * device (vdev), and setup everything needed to support it. It contains
344 * processor, required for the virtio rpmsg device. 372 * everything needed to make it possible: the virtio device id, virtio
345 * 373 * device features, vrings information, virtio config space, etc...
346 * The 'len' member of @rsc should contain the number of buffers this vring 374 *
347 * support and 'da' should either contain the device address where 375 * Before registering the vdev, the vrings are allocated from non-cacheable
348 * the remote processor is expecting the vring, or indicate that 376 * physically contiguous memory. Currently we only support two vrings per
349 * dynamically allocation of the vring's device address is supported. 377 * remote processor (temporary limitation). We might also want to consider
350 * 378 * doing the vring allocation only later when ->find_vqs() is invoked, and
351 * Note: 'da' is currently not handled. This will be revised when the generic 379 * then release them upon ->del_vqs().
352 * iommu-based DMA API will arrive, or a dynanic & non-iommu use case show 380 *
353 * up. Meanwhile, statically-addressed iommu-based images should use 381 * Note: @da is currently not really handled correctly: we dynamically
354 * RSC_DEVMEM resource entries to map their require 'da' to the physical 382 * allocate it using the DMA API, ignoring requested hard coded addresses,
355 * address of their base CMA region. 383 * and we don't take care of any required IOMMU programming. This is all
384 * going to be taken care of when the generic iommu-based DMA API will be
385 * merged. Meanwhile, statically-addressed iommu-based firmware images should
386 * use RSC_DEVMEM resource entries to map their required @da to the physical
387 * address of their base CMA region (ouch, hacky!).
356 * 388 *
357 * Returns 0 on success, or an appropriate error code otherwise 389 * Returns 0 on success, or an appropriate error code otherwise
358 */ 390 */
@@ -360,8 +392,8 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
360 int avail) 392 int avail)
361{ 393{
362 struct device *dev = rproc->dev; 394 struct device *dev = rproc->dev;
363 struct rproc_vdev *rvdev = rproc->rvdev; 395 struct rproc_vdev *rvdev;
364 int i; 396 int i, ret;
365 397
366 /* make sure resource isn't truncated */ 398 /* make sure resource isn't truncated */
367 if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) 399 if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring)
@@ -379,61 +411,41 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
379 dev_dbg(dev, "vdev rsc: id %d, dfeatures %x, cfg len %d, %d vrings\n", 411 dev_dbg(dev, "vdev rsc: id %d, dfeatures %x, cfg len %d, %d vrings\n",
380 rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings); 412 rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings);
381 413
382 /* no vdev is in place ? */ 414 /* we currently support only two vrings per rvdev */
383 if (!rvdev) { 415 if (rsc->num_of_vrings > ARRAY_SIZE(rvdev->vring)) {
384 dev_err(dev, "vring requested without a virtio dev entry\n");
385 return -EINVAL;
386 }
387
388 /* we currently support two vrings per rproc (for rx and tx) */
389 if (rsc->num_of_vrings != ARRAY_SIZE(rvdev->vring)) {
390 dev_err(dev, "too many vrings: %d\n", rsc->num_of_vrings); 416 dev_err(dev, "too many vrings: %d\n", rsc->num_of_vrings);
391 return -EINVAL; 417 return -EINVAL;
392 } 418 }
393 419
394 /* initialize the vrings */ 420 rvdev = kzalloc(sizeof(struct rproc_vdev), GFP_KERNEL);
395 for (i = 0; i < rsc->num_of_vrings; i++) { 421 if (!rvdev)
396 struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; 422 return -ENOMEM;
397 dma_addr_t dma;
398 int size;
399 void *va;
400
401 /* make sure reserved bytes are zeroes */
402 if (vring->reserved) {
403 dev_err(dev, "vring rsc has non zero reserved bytes\n");
404 return -EINVAL;
405 }
406 423
407 /* the firmware must provide the expected queue size */ 424 rvdev->rproc = rproc;
408 if (!vring->num) {
409 dev_err(dev, "missing expected queue size\n");
410 /* potential cleanups are taken care of later on */
411 return -EINVAL;
412 }
413 425
414 /* actual size of vring (in bytes) */ 426 /* allocate the vrings */
415 size = PAGE_ALIGN(vring_size(vring->num, AMP_VRING_ALIGN)); 427 for (i = 0; i < rsc->num_of_vrings; i++) {
428 ret = __rproc_handle_vring(rvdev, rsc, i);
429 if (ret)
430 goto free_vrings;
431 }
416 432
417 /* 433 /* remember the device features */
418 * Allocate non-cacheable memory for the vring. In the future 434 rvdev->dfeatures = rsc->dfeatures;
419 * this call will also configure the IOMMU for us
420 */
421 va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL);
422 if (!va) {
423 dev_err(dev, "dma_alloc_coherent failed\n");
424 /* potential cleanups are taken care of later on */
425 return -EINVAL;
426 }
427 435
428 dev_dbg(dev, "vring%d: va %p dma %x qsz %d ring size %x\n", i, 436 list_add_tail(&rvdev->node, &rproc->rvdevs);
429 va, dma, vring->num, size);
430 437
431 rvdev->vring[i].len = vring->num; 438 /* it is now safe to add the virtio device */
432 rvdev->vring[i].va = va; 439 ret = rproc_add_virtio_dev(rvdev, rsc->id);
433 rvdev->vring[i].dma = dma; 440 if (ret)
434 } 441 goto free_vrings;
435 442
436 return 0; 443 return 0;
444
445free_vrings:
446 __rproc_free_vrings(rvdev, i);
447 kfree(rvdev);
448 return ret;
437} 449}
438 450
439/** 451/**
@@ -731,7 +743,7 @@ static rproc_handle_resource_t rproc_handle_rsc[] = {
731 [RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout, 743 [RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout,
732 [RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem, 744 [RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem,
733 [RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace, 745 [RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace,
734 [RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev, 746 [RSC_VDEV] = NULL, /* VDEVs were handled upon registrarion */
735}; 747};
736 748
737/* handle firmware resource entries before booting the remote processor */ 749/* handle firmware resource entries before booting the remote processor */
@@ -784,6 +796,7 @@ rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int l
784 int offset = table->offset[i]; 796 int offset = table->offset[i];
785 struct fw_rsc_hdr *hdr = (void *)table + offset; 797 struct fw_rsc_hdr *hdr = (void *)table + offset;
786 int avail = len - offset - sizeof(*hdr); 798 int avail = len - offset - sizeof(*hdr);
799 struct fw_rsc_vdev *vrsc;
787 800
788 /* make sure table isn't truncated */ 801 /* make sure table isn't truncated */
789 if (avail < 0) { 802 if (avail < 0) {
@@ -793,12 +806,14 @@ rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int l
793 806
794 dev_dbg(dev, "%s: rsc type %d\n", __func__, hdr->type); 807 dev_dbg(dev, "%s: rsc type %d\n", __func__, hdr->type);
795 808
796 if (hdr->type == RSC_VDEV) { 809 if (hdr->type != RSC_VDEV)
797 struct fw_rsc_vdev *vrsc = 810 continue;
798 (struct fw_rsc_vdev *)hdr->data; 811
799 ret = rproc_handle_early_vdev(rproc, vrsc, avail); 812 vrsc = (struct fw_rsc_vdev *)hdr->data;
813
814 ret = rproc_handle_vdev(rproc, vrsc, avail);
815 if (ret)
800 break; 816 break;
801 }
802 } 817 }
803 818
804 return ret; 819 return ret;
@@ -889,14 +904,12 @@ static int rproc_handle_resources(struct rproc *rproc, const u8 *elf_data,
889 * @rproc: rproc handle 904 * @rproc: rproc handle
890 * 905 *
891 * This function will free all resources acquired for @rproc, and it 906 * This function will free all resources acquired for @rproc, and it
892 * is called when @rproc shuts down, or just failed booting. 907 * is called whenever @rproc either shuts down or fails to boot.
893 */ 908 */
894static void rproc_resource_cleanup(struct rproc *rproc) 909static void rproc_resource_cleanup(struct rproc *rproc)
895{ 910{
896 struct rproc_mem_entry *entry, *tmp; 911 struct rproc_mem_entry *entry, *tmp;
897 struct device *dev = rproc->dev; 912 struct device *dev = rproc->dev;
898 struct rproc_vdev *rvdev = rproc->rvdev;
899 int i;
900 913
901 /* clean up debugfs trace entries */ 914 /* clean up debugfs trace entries */
902 list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { 915 list_for_each_entry_safe(entry, tmp, &rproc->traces, node) {
@@ -906,23 +919,6 @@ static void rproc_resource_cleanup(struct rproc *rproc)
906 kfree(entry); 919 kfree(entry);
907 } 920 }
908 921
909 /* free the coherent memory allocated for the vrings */
910 for (i = 0; rvdev && i < ARRAY_SIZE(rvdev->vring); i++) {
911 int qsz = rvdev->vring[i].len;
912 void *va = rvdev->vring[i].va;
913 int dma = rvdev->vring[i].dma;
914
915 /* virtqueue size is expressed in number of buffers supported */
916 if (qsz) {
917 /* how many bytes does this vring really occupy ? */
918 int size = PAGE_ALIGN(vring_size(qsz, AMP_VRING_ALIGN));
919
920 dma_free_coherent(rproc->dev, size, va, dma);
921
922 rvdev->vring[i].len = 0;
923 }
924 }
925
926 /* clean up carveout allocations */ 922 /* clean up carveout allocations */
927 list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { 923 list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) {
928 dma_free_coherent(dev, entry->len, entry->va, entry->dma); 924 dma_free_coherent(dev, entry->len, entry->va, entry->dma);
@@ -1100,11 +1096,6 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
1100 goto out; 1096 goto out;
1101 } 1097 }
1102 1098
1103 /* add the virtio device (currently only rpmsg vdevs are supported) */
1104 ret = rproc_add_rpmsg_vdev(rproc);
1105 if (ret)
1106 goto out;
1107
1108out: 1099out:
1109 if (fw) 1100 if (fw)
1110 release_firmware(fw); 1101 release_firmware(fw);
@@ -1266,13 +1257,23 @@ EXPORT_SYMBOL(rproc_shutdown);
1266void rproc_release(struct kref *kref) 1257void rproc_release(struct kref *kref)
1267{ 1258{
1268 struct rproc *rproc = container_of(kref, struct rproc, refcount); 1259 struct rproc *rproc = container_of(kref, struct rproc, refcount);
1260 struct rproc_vdev *rvdev, *rvtmp;
1269 1261
1270 dev_info(rproc->dev, "removing %s\n", rproc->name); 1262 dev_info(rproc->dev, "removing %s\n", rproc->name);
1271 1263
1272 rproc_delete_debug_dir(rproc); 1264 rproc_delete_debug_dir(rproc);
1273 1265
1274 /* at this point no one holds a reference to rproc anymore */ 1266 /* clean up remote vdev entries */
1275 kfree(rproc); 1267 list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node) {
1268 __rproc_free_vrings(rvdev, RVDEV_NUM_VRINGS);
1269 list_del(&rvdev->node);
1270 }
1271
1272 /*
1273 * At this point no one holds a reference to rproc anymore,
1274 * so we can directly unroll rproc_alloc()
1275 */
1276 rproc_free(rproc);
1276} 1277}
1277 1278
1278/* will be called when an rproc is added to the rprocs klist */ 1279/* will be called when an rproc is added to the rprocs klist */
@@ -1316,7 +1317,7 @@ static struct rproc *next_rproc(struct klist_iter *i)
1316 * use rproc_put() to decrement it back once rproc isn't needed anymore. 1317 * use rproc_put() to decrement it back once rproc isn't needed anymore.
1317 * 1318 *
1318 * Note: currently this function (and its counterpart rproc_put()) are not 1319 * Note: currently this function (and its counterpart rproc_put()) are not
1319 * used anymore by the rpmsg subsystem. We need to scrutinize the use cases 1320 * being used. We need to scrutinize the use cases
1320 * that still need them, and see if we can migrate them to use the non 1321 * that still need them, and see if we can migrate them to use the non
1321 * name-based boot/shutdown interface. 1322 * name-based boot/shutdown interface.
1322 */ 1323 */
@@ -1391,11 +1392,8 @@ EXPORT_SYMBOL(rproc_put);
1391 * firmware. 1392 * firmware.
1392 * 1393 *
1393 * If found, those virtio devices will be created and added, so as a result 1394 * If found, those virtio devices will be created and added, so as a result
1394 * of registering this remote processor, additional virtio drivers will be 1395 * of registering this remote processor, additional virtio drivers might be
1395 * probed. 1396 * probed.
1396 *
1397 * Currently, though, we only support a single RPMSG virtio vdev per remote
1398 * processor.
1399 */ 1397 */
1400int rproc_register(struct rproc *rproc) 1398int rproc_register(struct rproc *rproc)
1401{ 1399{
@@ -1418,7 +1416,7 @@ int rproc_register(struct rproc *rproc)
1418 1416
1419 /* 1417 /*
1420 * We must retrieve early virtio configuration info from 1418 * We must retrieve early virtio configuration info from
1421 * the firmware (e.g. whether to register a virtio rpmsg device, 1419 * the firmware (e.g. whether to register a virtio device,
1422 * what virtio features does it support, ...). 1420 * what virtio features does it support, ...).
1423 * 1421 *
1424 * We're initiating an asynchronous firmware loading, so we can 1422 * We're initiating an asynchronous firmware loading, so we can
@@ -1487,9 +1485,12 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
1487 1485
1488 mutex_init(&rproc->lock); 1486 mutex_init(&rproc->lock);
1489 1487
1488 idr_init(&rproc->notifyids);
1489
1490 INIT_LIST_HEAD(&rproc->carveouts); 1490 INIT_LIST_HEAD(&rproc->carveouts);
1491 INIT_LIST_HEAD(&rproc->mappings); 1491 INIT_LIST_HEAD(&rproc->mappings);
1492 INIT_LIST_HEAD(&rproc->traces); 1492 INIT_LIST_HEAD(&rproc->traces);
1493 INIT_LIST_HEAD(&rproc->rvdevs);
1493 1494
1494 rproc->state = RPROC_OFFLINE; 1495 rproc->state = RPROC_OFFLINE;
1495 1496
@@ -1509,6 +1510,9 @@ EXPORT_SYMBOL(rproc_alloc);
1509 */ 1510 */
1510void rproc_free(struct rproc *rproc) 1511void rproc_free(struct rproc *rproc)
1511{ 1512{
1513 idr_remove_all(&rproc->notifyids);
1514 idr_destroy(&rproc->notifyids);
1515
1512 kfree(rproc); 1516 kfree(rproc);
1513} 1517}
1514EXPORT_SYMBOL(rproc_free); 1518EXPORT_SYMBOL(rproc_free);
@@ -1535,18 +1539,22 @@ EXPORT_SYMBOL(rproc_free);
1535 */ 1539 */
1536int rproc_unregister(struct rproc *rproc) 1540int rproc_unregister(struct rproc *rproc)
1537{ 1541{
1542 struct rproc_vdev *rvdev;
1543
1538 if (!rproc) 1544 if (!rproc)
1539 return -EINVAL; 1545 return -EINVAL;
1540 1546
1541 /* if rproc is just being registered, wait */ 1547 /* if rproc is just being registered, wait */
1542 wait_for_completion(&rproc->firmware_loading_complete); 1548 wait_for_completion(&rproc->firmware_loading_complete);
1543 1549
1544 /* was an rpmsg vdev created ? */ 1550 /* clean up remote vdev entries */
1545 if (rproc->rvdev) 1551 list_for_each_entry(rvdev, &rproc->rvdevs, node)
1546 rproc_remove_rpmsg_vdev(rproc); 1552 rproc_remove_virtio_dev(rvdev);
1547 1553
1548 klist_remove(&rproc->node); 1554 /* the rproc is downref'ed as soon as it's removed from the klist */
1555 klist_del(&rproc->node);
1549 1556
1557 /* the rproc will only be released after its refcount drops to zero */
1550 kref_put(&rproc->refcount, rproc_release); 1558 kref_put(&rproc->refcount, rproc_release);
1551 1559
1552 return 0; 1560 return 0;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 8b2fc40e92d0..9f336d6bdef3 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -28,9 +28,9 @@ struct rproc;
28void rproc_release(struct kref *kref); 28void rproc_release(struct kref *kref);
29irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); 29irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
30 30
31/* from remoteproc_rpmsg.c */ 31/* from remoteproc_virtio.c */
32int rproc_add_rpmsg_vdev(struct rproc *); 32int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
33void rproc_remove_rpmsg_vdev(struct rproc *rproc); 33void rproc_remove_virtio_dev(struct rproc_vdev *rvdev);
34 34
35/* from remoteproc_debugfs.c */ 35/* from remoteproc_debugfs.c */
36void rproc_remove_trace_file(struct dentry *tfile); 36void rproc_remove_trace_file(struct dentry *tfile);
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 78d8527a8fec..07004106c954 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -19,7 +19,6 @@
19 19
20#include <linux/export.h> 20#include <linux/export.h>
21#include <linux/remoteproc.h> 21#include <linux/remoteproc.h>
22#include <linux/rpmsg.h>
23#include <linux/virtio.h> 22#include <linux/virtio.h>
24#include <linux/virtio_config.h> 23#include <linux/virtio_config.h>
25#include <linux/virtio_ids.h> 24#include <linux/virtio_ids.h>
@@ -30,45 +29,41 @@
30 29
31#include "remoteproc_internal.h" 30#include "remoteproc_internal.h"
32 31
33/**
34 * struct rproc_virtio_vq_info - virtqueue state
35 * @vq_id: a unique index of this virtqueue (unique for this @rproc)
36 * @rproc: handle to the remote processor
37 *
38 * Such a struct will be maintained for every virtqueue we're
39 * using to communicate with the remote processor
40 */
41struct rproc_virtio_vq_info {
42 __u16 vq_id;
43 struct rproc *rproc;
44};
45
46/* kick the remote processor, and let it know which virtqueue to poke at */ 32/* kick the remote processor, and let it know which virtqueue to poke at */
47static void rproc_virtio_notify(struct virtqueue *vq) 33static void rproc_virtio_notify(struct virtqueue *vq)
48{ 34{
49 struct rproc_virtio_vq_info *rpvq = vq->priv; 35 struct rproc_vring *rvring = vq->priv;
50 struct rproc *rproc = rpvq->rproc; 36 struct rproc *rproc = rvring->rvdev->rproc;
37 int notifyid = rvring->notifyid;
51 38
52 dev_dbg(rproc->dev, "kicking vq id: %d\n", rpvq->vq_id); 39 dev_dbg(rproc->dev, "kicking vq index: %d\n", notifyid);
53 40
54 rproc->ops->kick(rproc, rpvq->vq_id); 41 rproc->ops->kick(rproc, notifyid);
55} 42}
56 43
57/** 44/**
58 * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted 45 * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted
59 * @rproc: handle to the remote processor 46 * @rproc: handle to the remote processor
60 * @vq_id: index of the signalled virtqueue 47 * @notifyid: index of the signalled virtqueue (unique per this @rproc)
61 * 48 *
62 * This function should be called by the platform-specific rproc driver, 49 * This function should be called by the platform-specific rproc driver,
63 * when the remote processor signals that a specific virtqueue has pending 50 * when the remote processor signals that a specific virtqueue has pending
64 * messages available. 51 * messages available.
65 * 52 *
66 * Returns IRQ_NONE if no message was found in the @vq_id virtqueue, 53 * Returns IRQ_NONE if no message was found in the @notifyid virtqueue,
67 * and otherwise returns IRQ_HANDLED. 54 * and otherwise returns IRQ_HANDLED.
68 */ 55 */
69irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id) 56irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
70{ 57{
71 return vring_interrupt(0, rproc->rvdev->vq[vq_id]); 58 struct rproc_vring *rvring;
59
60 dev_dbg(rproc->dev, "vq index %d is interrupted\n", notifyid);
61
62 rvring = idr_find(&rproc->notifyids, notifyid);
63 if (!rvring || !rvring->vq)
64 return IRQ_NONE;
65
66 return vring_interrupt(0, rvring->vq);
72} 67}
73EXPORT_SYMBOL(rproc_vq_interrupt); 68EXPORT_SYMBOL(rproc_vq_interrupt);
74 69
@@ -77,24 +72,28 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
77 void (*callback)(struct virtqueue *vq), 72 void (*callback)(struct virtqueue *vq),
78 const char *name) 73 const char *name)
79{ 74{
75 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
80 struct rproc *rproc = vdev_to_rproc(vdev); 76 struct rproc *rproc = vdev_to_rproc(vdev);
81 struct rproc_vdev *rvdev = rproc->rvdev; 77 struct rproc_vring *rvring;
82 struct rproc_virtio_vq_info *rpvq;
83 struct virtqueue *vq; 78 struct virtqueue *vq;
84 void *addr; 79 void *addr;
85 int ret, len; 80 int len, size;
86 81
87 rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL); 82 /* we're temporarily limited to two virtqueues per rvdev */
88 if (!rpvq) 83 if (id >= ARRAY_SIZE(rvdev->vring))
89 return ERR_PTR(-ENOMEM); 84 return ERR_PTR(-EINVAL);
85
86 rvring = &rvdev->vring[id];
90 87
91 rpvq->rproc = rproc; 88 addr = rvring->va;
92 rpvq->vq_id = id; 89 len = rvring->len;
93 90
94 addr = rvdev->vring[id].va; 91 /* zero vring */
95 len = rvdev->vring[id].len; 92 size = vring_size(len, rvring->align);
93 memset(addr, 0, size);
96 94
97 dev_dbg(rproc->dev, "vring%d: va %p qsz %d\n", id, addr, len); 95 dev_dbg(rproc->dev, "vring%d: va %p qsz %d notifyid %d\n",
96 id, addr, len, rvring->notifyid);
98 97
99 /* 98 /*
100 * Create the new vq, and tell virtio we're not interested in 99 * Create the new vq, and tell virtio we're not interested in
@@ -104,32 +103,28 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
104 rproc_virtio_notify, callback, name); 103 rproc_virtio_notify, callback, name);
105 if (!vq) { 104 if (!vq) {
106 dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); 105 dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name);
107 ret = -ENOMEM; 106 return ERR_PTR(-ENOMEM);
108 goto free_rpvq;
109 } 107 }
110 108
111 rvdev->vq[id] = vq; 109 rvring->vq = vq;
112 vq->priv = rpvq; 110 vq->priv = rvring;
113 111
114 return vq; 112 return vq;
115
116free_rpvq:
117 kfree(rpvq);
118 return ERR_PTR(ret);
119} 113}
120 114
121static void rproc_virtio_del_vqs(struct virtio_device *vdev) 115static void rproc_virtio_del_vqs(struct virtio_device *vdev)
122{ 116{
123 struct virtqueue *vq, *n; 117 struct virtqueue *vq, *n;
124 struct rproc *rproc = vdev_to_rproc(vdev); 118 struct rproc *rproc = vdev_to_rproc(vdev);
119 struct rproc_vring *rvring;
125 120
126 /* power down the remote processor before deleting vqs */ 121 /* power down the remote processor before deleting vqs */
127 rproc_shutdown(rproc); 122 rproc_shutdown(rproc);
128 123
129 list_for_each_entry_safe(vq, n, &vdev->vqs, list) { 124 list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
130 struct rproc_virtio_vq_info *rpvq = vq->priv; 125 rvring = vq->priv;
126 rvring->vq = NULL;
131 vring_del_virtqueue(vq); 127 vring_del_virtqueue(vq);
132 kfree(rpvq);
133 } 128 }
134} 129}
135 130
@@ -141,10 +136,6 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
141 struct rproc *rproc = vdev_to_rproc(vdev); 136 struct rproc *rproc = vdev_to_rproc(vdev);
142 int i, ret; 137 int i, ret;
143 138
144 /* we maintain two virtqueues per remote processor (for RX and TX) */
145 if (nvqs != 2)
146 return -EINVAL;
147
148 for (i = 0; i < nvqs; ++i) { 139 for (i = 0; i < nvqs; ++i) {
149 vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); 140 vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
150 if (IS_ERR(vqs[i])) { 141 if (IS_ERR(vqs[i])) {
@@ -170,7 +161,7 @@ error:
170/* 161/*
171 * We don't support yet real virtio status semantics. 162 * We don't support yet real virtio status semantics.
172 * 163 *
173 * The plan is to provide this via the VIRTIO HDR resource entry 164 * The plan is to provide this via the VDEV resource entry
174 * which is part of the firmware: this way the remote processor 165 * which is part of the firmware: this way the remote processor
175 * will be able to access the status values as set by us. 166 * will be able to access the status values as set by us.
176 */ 167 */
@@ -181,7 +172,7 @@ static u8 rproc_virtio_get_status(struct virtio_device *vdev)
181 172
182static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status) 173static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status)
183{ 174{
184 dev_dbg(&vdev->dev, "new status: %d\n", status); 175 dev_dbg(&vdev->dev, "status: %d\n", status);
185} 176}
186 177
187static void rproc_virtio_reset(struct virtio_device *vdev) 178static void rproc_virtio_reset(struct virtio_device *vdev)
@@ -192,15 +183,14 @@ static void rproc_virtio_reset(struct virtio_device *vdev)
192/* provide the vdev features as retrieved from the firmware */ 183/* provide the vdev features as retrieved from the firmware */
193static u32 rproc_virtio_get_features(struct virtio_device *vdev) 184static u32 rproc_virtio_get_features(struct virtio_device *vdev)
194{ 185{
195 struct rproc *rproc = vdev_to_rproc(vdev); 186 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
196 187
197 /* we only support a single vdev device for now */ 188 return rvdev->dfeatures;
198 return rproc->rvdev->dfeatures;
199} 189}
200 190
201static void rproc_virtio_finalize_features(struct virtio_device *vdev) 191static void rproc_virtio_finalize_features(struct virtio_device *vdev)
202{ 192{
203 struct rproc *rproc = vdev_to_rproc(vdev); 193 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
204 194
205 /* Give virtio_ring a chance to accept features */ 195 /* Give virtio_ring a chance to accept features */
206 vring_transport_features(vdev); 196 vring_transport_features(vdev);
@@ -214,7 +204,7 @@ static void rproc_virtio_finalize_features(struct virtio_device *vdev)
214 * fixed as part of a small resource table overhaul and then an 204 * fixed as part of a small resource table overhaul and then an
215 * extension of the virtio resource entries. 205 * extension of the virtio resource entries.
216 */ 206 */
217 rproc->rvdev->gfeatures = vdev->features[0]; 207 rvdev->gfeatures = vdev->features[0];
218} 208}
219 209
220static struct virtio_config_ops rproc_virtio_config_ops = { 210static struct virtio_config_ops rproc_virtio_config_ops = {
@@ -244,26 +234,25 @@ static void rproc_vdev_release(struct device *dev)
244} 234}
245 235
246/** 236/**
247 * rproc_add_rpmsg_vdev() - create an rpmsg virtio device 237 * rproc_add_virtio_dev() - register an rproc-induced virtio device
248 * @rproc: the rproc handle 238 * @rvdev: the remote vdev
249 * 239 *
250 * This function is called if virtio rpmsg support was found in the 240 * This function registers a virtio device. This vdev's partent is
251 * firmware of the remote processor. 241 * the rproc device.
252 * 242 *
253 * Today we only support creating a single rpmsg vdev (virtio device), 243 * Returns 0 on success or an appropriate error value otherwise.
254 * but the plan is to remove this limitation. At that point this interface
255 * will be revised/extended.
256 */ 244 */
257int rproc_add_rpmsg_vdev(struct rproc *rproc) 245int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
258{ 246{
247 struct rproc *rproc = rvdev->rproc;
259 struct device *dev = rproc->dev; 248 struct device *dev = rproc->dev;
260 struct rproc_vdev *rvdev = rproc->rvdev; 249 struct virtio_device *vdev = &rvdev->vdev;
261 int ret; 250 int ret;
262 251
263 rvdev->vdev.id.device = VIRTIO_ID_RPMSG, 252 vdev->id.device = id,
264 rvdev->vdev.config = &rproc_virtio_config_ops, 253 vdev->config = &rproc_virtio_config_ops,
265 rvdev->vdev.dev.parent = dev; 254 vdev->dev.parent = dev;
266 rvdev->vdev.dev.release = rproc_vdev_release; 255 vdev->dev.release = rproc_vdev_release;
267 256
268 /* 257 /*
269 * We're indirectly making a non-temporary copy of the rproc pointer 258 * We're indirectly making a non-temporary copy of the rproc pointer
@@ -275,25 +264,26 @@ int rproc_add_rpmsg_vdev(struct rproc *rproc)
275 */ 264 */
276 kref_get(&rproc->refcount); 265 kref_get(&rproc->refcount);
277 266
278 ret = register_virtio_device(&rvdev->vdev); 267 ret = register_virtio_device(vdev);
279 if (ret) { 268 if (ret) {
280 kref_put(&rproc->refcount, rproc_release); 269 kref_put(&rproc->refcount, rproc_release);
281 dev_err(dev, "failed to register vdev: %d\n", ret); 270 dev_err(dev, "failed to register vdev: %d\n", ret);
271 goto out;
282 } 272 }
283 273
274 dev_info(dev, "registered %s (type %d)\n", dev_name(&vdev->dev), id);
275
276out:
284 return ret; 277 return ret;
285} 278}
286 279
287/** 280/**
288 * rproc_remove_rpmsg_vdev() - remove an rpmsg vdev device 281 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device
289 * @rproc: the rproc handle 282 * @rvdev: the remote vdev
290 * 283 *
291 * This function is called whenever @rproc is removed _iff_ an rpmsg 284 * This function unregisters an existing virtio device.
292 * vdev was created beforehand.
293 */ 285 */
294void rproc_remove_rpmsg_vdev(struct rproc *rproc) 286void rproc_remove_virtio_dev(struct rproc_vdev *rvdev)
295{ 287{
296 struct rproc_vdev *rvdev = rproc->rvdev;
297
298 unregister_virtio_device(&rvdev->vdev); 288 unregister_virtio_device(&rvdev->vdev);
299} 289}