remoteproc_virtio.c (edd1533d3ccd82dd5d600986d27d524e6be4c5fd) | remoteproc_virtio.c (ccf22a48cc8789a35befea783448c259463a5eef) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Remote processor messaging transport (OMAP platform-specific bits) 4 * 5 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Copyright (C) 2011 Google, Inc. 7 * 8 * Ohad Ben-Cohen <ohad@wizery.com> 9 * Brian Swetland <swetland@google.com> 10 */ 11 | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Remote processor messaging transport (OMAP platform-specific bits) 4 * 5 * Copyright (C) 2011 Texas Instruments, Inc. 6 * Copyright (C) 2011 Google, Inc. 7 * 8 * Ohad Ben-Cohen <ohad@wizery.com> 9 * Brian Swetland <swetland@google.com> 10 */ 11 |
12#include <linux/dma-direct.h> |
|
12#include <linux/dma-map-ops.h> | 13#include <linux/dma-map-ops.h> |
14#include <linux/dma-mapping.h> |
|
13#include <linux/export.h> 14#include <linux/of_reserved_mem.h> | 15#include <linux/export.h> 16#include <linux/of_reserved_mem.h> |
17#include <linux/platform_device.h> |
|
15#include <linux/remoteproc.h> 16#include <linux/virtio.h> 17#include <linux/virtio_config.h> 18#include <linux/virtio_ids.h> 19#include <linux/virtio_ring.h> 20#include <linux/err.h> 21#include <linux/kref.h> 22#include <linux/slab.h> 23 24#include "remoteproc_internal.h" 25 | 18#include <linux/remoteproc.h> 19#include <linux/virtio.h> 20#include <linux/virtio_config.h> 21#include <linux/virtio_ids.h> 22#include <linux/virtio_ring.h> 23#include <linux/err.h> 24#include <linux/kref.h> 25#include <linux/slab.h> 26 27#include "remoteproc_internal.h" 28 |
29static int copy_dma_range_map(struct device *to, struct device *from) 30{ 31 const struct bus_dma_region *map = from->dma_range_map, *new_map, *r; 32 int num_ranges = 0; 33 34 if (!map) 35 return 0; 36 37 for (r = map; r->size; r++) 38 num_ranges++; 39 40 new_map = kmemdup(map, array_size(num_ranges + 1, sizeof(*map)), 41 GFP_KERNEL); 42 if (!new_map) 43 return -ENOMEM; 44 to->dma_range_map = new_map; 45 return 0; 46} 47 |
|
26static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) 27{ | 48static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) 49{ |
28 return container_of(vdev->dev.parent, struct rproc_vdev, dev); | 50 struct platform_device *pdev; 51 52 pdev = container_of(vdev->dev.parent, struct platform_device, dev); 53 54 return platform_get_drvdata(pdev); |
29} 30 31static struct rproc *vdev_to_rproc(struct virtio_device *vdev) 32{ 33 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 34 35 return rvdev->rproc; 36} --- 280 unchanged lines hidden (view full) --- 317 * 318 * Never call this function directly; it will be called by the driver 319 * core when needed. 320 */ 321static void rproc_virtio_dev_release(struct device *dev) 322{ 323 struct virtio_device *vdev = dev_to_virtio(dev); 324 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); | 55} 56 57static struct rproc *vdev_to_rproc(struct virtio_device *vdev) 58{ 59 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 60 61 return rvdev->rproc; 62} --- 280 unchanged lines hidden (view full) --- 343 * 344 * Never call this function directly; it will be called by the driver 345 * core when needed. 346 */ 347static void rproc_virtio_dev_release(struct device *dev) 348{ 349 struct virtio_device *vdev = dev_to_virtio(dev); 350 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); |
325 struct rproc *rproc = vdev_to_rproc(vdev); | |
326 327 kfree(vdev); 328 | 351 352 kfree(vdev); 353 |
329 kref_put(&rvdev->refcount, rproc_vdev_release); 330 331 put_device(&rproc->dev); | 354 put_device(&rvdev->pdev->dev); |
332} 333 334/** 335 * rproc_add_virtio_dev() - register an rproc-induced virtio device 336 * @rvdev: the remote vdev 337 * @id: the device type identification (used to match it with a driver). 338 * 339 * This function registers a virtio device. This vdev's partent is 340 * the rproc device. 341 * 342 * Return: 0 on success or an appropriate error value otherwise 343 */ | 355} 356 357/** 358 * rproc_add_virtio_dev() - register an rproc-induced virtio device 359 * @rvdev: the remote vdev 360 * @id: the device type identification (used to match it with a driver). 361 * 362 * This function registers a virtio device. This vdev's partent is 363 * the rproc device. 364 * 365 * Return: 0 on success or an appropriate error value otherwise 366 */ |
344int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) | 367static int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) |
345{ 346 struct rproc *rproc = rvdev->rproc; | 368{ 369 struct rproc *rproc = rvdev->rproc; |
347 struct device *dev = &rvdev->dev; | 370 struct device *dev = &rvdev->pdev->dev; |
348 struct virtio_device *vdev; 349 struct rproc_mem_entry *mem; 350 int ret; 351 352 if (rproc->ops->kick == NULL) { 353 ret = -EINVAL; 354 dev_err(dev, ".kick method not defined for %s\n", rproc->name); 355 goto out; --- 53 unchanged lines hidden (view full) --- 409 ret = -ENOMEM; 410 goto out; 411 } 412 vdev->id.device = id, 413 vdev->config = &rproc_virtio_config_ops, 414 vdev->dev.parent = dev; 415 vdev->dev.release = rproc_virtio_dev_release; 416 | 371 struct virtio_device *vdev; 372 struct rproc_mem_entry *mem; 373 int ret; 374 375 if (rproc->ops->kick == NULL) { 376 ret = -EINVAL; 377 dev_err(dev, ".kick method not defined for %s\n", rproc->name); 378 goto out; --- 53 unchanged lines hidden (view full) --- 432 ret = -ENOMEM; 433 goto out; 434 } 435 vdev->id.device = id, 436 vdev->config = &rproc_virtio_config_ops, 437 vdev->dev.parent = dev; 438 vdev->dev.release = rproc_virtio_dev_release; 439 |
417 /* 418 * We're indirectly making a non-temporary copy of the rproc pointer 419 * here, because drivers probed with this vdev will indirectly 420 * access the wrapping rproc. 421 * 422 * Therefore we must increment the rproc refcount here, and decrement 423 * it _only_ when the vdev is released. 424 */ 425 get_device(&rproc->dev); 426 | |
427 /* Reference the vdev and vring allocations */ | 440 /* Reference the vdev and vring allocations */ |
428 kref_get(&rvdev->refcount); | 441 get_device(dev); |
429 430 ret = register_virtio_device(vdev); 431 if (ret) { 432 put_device(&vdev->dev); 433 dev_err(dev, "failed to register vdev: %d\n", ret); 434 goto out; 435 } 436 --- 7 unchanged lines hidden (view full) --- 444 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device 445 * @dev: the virtio device 446 * @data: must be null 447 * 448 * This function unregisters an existing virtio device. 449 * 450 * Return: 0 451 */ | 442 443 ret = register_virtio_device(vdev); 444 if (ret) { 445 put_device(&vdev->dev); 446 dev_err(dev, "failed to register vdev: %d\n", ret); 447 goto out; 448 } 449 --- 7 unchanged lines hidden (view full) --- 457 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device 458 * @dev: the virtio device 459 * @data: must be null 460 * 461 * This function unregisters an existing virtio device. 462 * 463 * Return: 0 464 */ |
452int rproc_remove_virtio_dev(struct device *dev, void *data) | 465static int rproc_remove_virtio_dev(struct device *dev, void *data) |
453{ 454 struct virtio_device *vdev = dev_to_virtio(dev); 455 456 unregister_virtio_device(vdev); 457 return 0; 458} | 466{ 467 struct virtio_device *vdev = dev_to_virtio(dev); 468 469 unregister_virtio_device(vdev); 470 return 0; 471} |
472 473static int rproc_vdev_do_start(struct rproc_subdev *subdev) 474{ 475 struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 476 477 return rproc_add_virtio_dev(rvdev, rvdev->id); 478} 479 480static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed) 481{ 482 struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 483 struct device *dev = &rvdev->pdev->dev; 484 int ret; 485 486 ret = device_for_each_child(dev, NULL, rproc_remove_virtio_dev); 487 if (ret) 488 dev_warn(dev, "can't remove vdev child device: %d\n", ret); 489} 490 491static int rproc_virtio_probe(struct platform_device *pdev) 492{ 493 struct device *dev = &pdev->dev; 494 struct rproc_vdev_data *rvdev_data = dev->platform_data; 495 struct rproc_vdev *rvdev; 496 struct rproc *rproc = container_of(dev->parent, struct rproc, dev); 497 struct fw_rsc_vdev *rsc; 498 int i, ret; 499 500 if (!rvdev_data) 501 return -EINVAL; 502 503 rvdev = devm_kzalloc(dev, sizeof(*rvdev), GFP_KERNEL); 504 if (!rvdev) 505 return -ENOMEM; 506 507 rvdev->id = rvdev_data->id; 508 rvdev->rproc = rproc; 509 rvdev->index = rvdev_data->index; 510 511 ret = copy_dma_range_map(dev, rproc->dev.parent); 512 if (ret) 513 return ret; 514 515 /* Make device dma capable by inheriting from parent's capabilities */ 516 set_dma_ops(dev, get_dma_ops(rproc->dev.parent)); 517 518 ret = dma_coerce_mask_and_coherent(dev, dma_get_mask(rproc->dev.parent)); 519 if (ret) { 520 dev_warn(dev, "Failed to set DMA mask %llx. Trying to continue... (%pe)\n", 521 dma_get_mask(rproc->dev.parent), ERR_PTR(ret)); 522 } 523 524 platform_set_drvdata(pdev, rvdev); 525 rvdev->pdev = pdev; 526 527 rsc = rvdev_data->rsc; 528 529 /* parse the vrings */ 530 for (i = 0; i < rsc->num_of_vrings; i++) { 531 ret = rproc_parse_vring(rvdev, rsc, i); 532 if (ret) 533 return ret; 534 } 535 536 /* remember the resource offset*/ 537 rvdev->rsc_offset = rvdev_data->rsc_offset; 538 539 /* allocate the vring resources */ 540 for (i = 0; i < rsc->num_of_vrings; i++) { 541 ret = rproc_alloc_vring(rvdev, i); 542 if (ret) 543 goto unwind_vring_allocations; 544 } 545 546 rproc_add_rvdev(rproc, rvdev); 547 548 rvdev->subdev.start = rproc_vdev_do_start; 549 rvdev->subdev.stop = rproc_vdev_do_stop; 550 551 rproc_add_subdev(rproc, &rvdev->subdev); 552 553 /* 554 * We're indirectly making a non-temporary copy of the rproc pointer 555 * here, because the platform device or the vdev device will indirectly 556 * access the wrapping rproc. 557 * 558 * Therefore we must increment the rproc refcount here, and decrement 559 * it _only_ on platform remove. 560 */ 561 get_device(&rproc->dev); 562 563 return 0; 564 565unwind_vring_allocations: 566 for (i--; i >= 0; i--) 567 rproc_free_vring(&rvdev->vring[i]); 568 569 return ret; 570} 571 572static int rproc_virtio_remove(struct platform_device *pdev) 573{ 574 struct rproc_vdev *rvdev = dev_get_drvdata(&pdev->dev); 575 struct rproc *rproc = rvdev->rproc; 576 struct rproc_vring *rvring; 577 int id; 578 579 for (id = 0; id < ARRAY_SIZE(rvdev->vring); id++) { 580 rvring = &rvdev->vring[id]; 581 rproc_free_vring(rvring); 582 } 583 584 rproc_remove_subdev(rproc, &rvdev->subdev); 585 rproc_remove_rvdev(rvdev); 586 587 of_reserved_mem_device_release(&pdev->dev); 588 dma_release_coherent_memory(&pdev->dev); 589 590 put_device(&rproc->dev); 591 592 return 0; 593} 594 595/* Platform driver */ 596static struct platform_driver rproc_virtio_driver = { 597 .probe = rproc_virtio_probe, 598 .remove = rproc_virtio_remove, 599 .driver = { 600 .name = "rproc-virtio", 601 }, 602}; 603builtin_platform_driver(rproc_virtio_driver); |
|