.. | .. |
---|
38 | 38 | #include <linux/types.h> |
---|
39 | 39 | #include <linux/mutex.h> |
---|
40 | 40 | #include <linux/virtio.h> |
---|
| 41 | +#include <linux/cdev.h> |
---|
41 | 42 | #include <linux/completion.h> |
---|
42 | 43 | #include <linux/idr.h> |
---|
43 | 44 | #include <linux/of.h> |
---|
.. | .. |
---|
73 | 74 | u32 ver; |
---|
74 | 75 | u32 num; |
---|
75 | 76 | u32 reserved[2]; |
---|
76 | | - u32 offset[0]; |
---|
| 77 | + u32 offset[]; |
---|
77 | 78 | } __packed; |
---|
78 | 79 | |
---|
79 | 80 | /** |
---|
.. | .. |
---|
87 | 88 | */ |
---|
88 | 89 | struct fw_rsc_hdr { |
---|
89 | 90 | u32 type; |
---|
90 | | - u8 data[0]; |
---|
| 91 | + u8 data[]; |
---|
91 | 92 | } __packed; |
---|
92 | 93 | |
---|
93 | 94 | /** |
---|
.. | .. |
---|
100 | 101 | * the remote processor will be writing logs. |
---|
101 | 102 | * @RSC_VDEV: declare support for a virtio device, and serve as its |
---|
102 | 103 | * virtio header. |
---|
103 | | - * @RSC_LAST: just keep this one at the end |
---|
| 104 | + * @RSC_LAST: just keep this one at the end of standard resources |
---|
| 105 | + * @RSC_VENDOR_START: start of the vendor specific resource types range |
---|
| 106 | + * @RSC_VENDOR_END: end of the vendor specific resource types range |
---|
104 | 107 | * |
---|
105 | 108 | * For more details regarding a specific resource type, please see its |
---|
106 | 109 | * dedicated structure below. |
---|
.. | .. |
---|
111 | 114 | * please update it as needed. |
---|
112 | 115 | */ |
---|
113 | 116 | enum fw_resource_type { |
---|
114 | | - RSC_CARVEOUT = 0, |
---|
115 | | - RSC_DEVMEM = 1, |
---|
116 | | - RSC_TRACE = 2, |
---|
117 | | - RSC_VDEV = 3, |
---|
118 | | - RSC_LAST = 4, |
---|
| 117 | + RSC_CARVEOUT = 0, |
---|
| 118 | + RSC_DEVMEM = 1, |
---|
| 119 | + RSC_TRACE = 2, |
---|
| 120 | + RSC_VDEV = 3, |
---|
| 121 | + RSC_LAST = 4, |
---|
| 122 | + RSC_VENDOR_START = 128, |
---|
| 123 | + RSC_VENDOR_END = 512, |
---|
119 | 124 | }; |
---|
120 | 125 | |
---|
121 | 126 | #define FW_RSC_ADDR_ANY (-1) |
---|
.. | .. |
---|
302 | 307 | u8 status; |
---|
303 | 308 | u8 num_of_vrings; |
---|
304 | 309 | u8 reserved[2]; |
---|
305 | | - struct fw_rsc_vdev_vring vring[0]; |
---|
| 310 | + struct fw_rsc_vdev_vring vring[]; |
---|
306 | 311 | } __packed; |
---|
| 312 | + |
---|
| 313 | +struct rproc; |
---|
307 | 314 | |
---|
308 | 315 | /** |
---|
309 | 316 | * struct rproc_mem_entry - memory entry descriptor |
---|
310 | 317 | * @va: virtual address |
---|
| 318 | + * @is_iomem: io memory |
---|
311 | 319 | * @dma: dma address |
---|
312 | 320 | * @len: length, in bytes |
---|
313 | 321 | * @da: device address |
---|
| 322 | + * @release: release associated memory |
---|
314 | 323 | * @priv: associated data |
---|
| 324 | + * @name: associated memory region name (optional) |
---|
315 | 325 | * @node: list node |
---|
| 326 | + * @rsc_offset: offset in resource table |
---|
| 327 | + * @flags: iommu protection flags |
---|
| 328 | + * @of_resm_idx: reserved memory phandle index |
---|
| 329 | + * @alloc: specific memory allocator function |
---|
316 | 330 | */ |
---|
317 | 331 | struct rproc_mem_entry { |
---|
318 | 332 | void *va; |
---|
| 333 | + bool is_iomem; |
---|
319 | 334 | dma_addr_t dma; |
---|
320 | | - int len; |
---|
| 335 | + size_t len; |
---|
321 | 336 | u32 da; |
---|
322 | 337 | void *priv; |
---|
| 338 | + char name[32]; |
---|
323 | 339 | struct list_head node; |
---|
| 340 | + u32 rsc_offset; |
---|
| 341 | + u32 flags; |
---|
| 342 | + u32 of_resm_idx; |
---|
| 343 | + int (*alloc)(struct rproc *rproc, struct rproc_mem_entry *mem); |
---|
| 344 | + int (*release)(struct rproc *rproc, struct rproc_mem_entry *mem); |
---|
324 | 345 | }; |
---|
325 | 346 | |
---|
326 | | -struct rproc; |
---|
327 | 347 | struct firmware; |
---|
328 | 348 | |
---|
329 | 349 | /** |
---|
| 350 | + * enum rsc_handling_status - return status of rproc_ops handle_rsc hook |
---|
| 351 | + * @RSC_HANDLED: resource was handled |
---|
| 352 | + * @RSC_IGNORED: resource was ignored |
---|
| 353 | + */ |
---|
| 354 | +enum rsc_handling_status { |
---|
| 355 | + RSC_HANDLED = 0, |
---|
| 356 | + RSC_IGNORED = 1, |
---|
| 357 | +}; |
---|
| 358 | + |
---|
| 359 | +/** |
---|
330 | 360 | * struct rproc_ops - platform-specific device handlers |
---|
| 361 | + * @prepare: prepare device for code loading |
---|
| 362 | + * @unprepare: unprepare device after stop |
---|
331 | 363 | * @start: power on the device and boot it |
---|
332 | 364 | * @stop: power off the device |
---|
| 365 | + * @attach: attach to a device that his already powered up |
---|
333 | 366 | * @kick: kick a virtqueue (virtqueue id given as a parameter) |
---|
334 | 367 | * @da_to_va: optional platform hook to perform address translations |
---|
| 368 | + * @parse_fw: parse firmware to extract information (e.g. resource table) |
---|
| 369 | + * @handle_rsc: optional platform hook to handle vendor resources. Should return |
---|
| 370 | + * RSC_HANDLED if resource was handled, RSC_IGNORED if not handled and a |
---|
| 371 | + * negative value on error |
---|
335 | 372 | * @load_rsc_table: load resource table from firmware image |
---|
336 | 373 | * @find_loaded_rsc_table: find the loaded resouce table |
---|
337 | | - * @load: load firmeware to memory, where the remote processor |
---|
| 374 | + * @load: load firmware to memory, where the remote processor |
---|
338 | 375 | * expects to find it |
---|
339 | 376 | * @sanity_check: sanity check the fw image |
---|
340 | 377 | * @get_boot_addr: get boot address to entry point specified in firmware |
---|
| 378 | + * @panic: optional callback to react to system panic, core will delay |
---|
| 379 | + * panic at least the returned number of milliseconds |
---|
| 380 | + * @coredump: collect firmware dump after the subsystem is shutdown |
---|
341 | 381 | */ |
---|
342 | 382 | struct rproc_ops { |
---|
| 383 | + int (*prepare)(struct rproc *rproc); |
---|
| 384 | + int (*unprepare)(struct rproc *rproc); |
---|
343 | 385 | int (*start)(struct rproc *rproc); |
---|
344 | 386 | int (*stop)(struct rproc *rproc); |
---|
| 387 | + int (*attach)(struct rproc *rproc); |
---|
345 | 388 | void (*kick)(struct rproc *rproc, int vqid); |
---|
346 | | - void * (*da_to_va)(struct rproc *rproc, u64 da, int len); |
---|
| 389 | + void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len, bool *is_iomem); |
---|
347 | 390 | int (*parse_fw)(struct rproc *rproc, const struct firmware *fw); |
---|
| 391 | + int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc, |
---|
| 392 | + int offset, int avail); |
---|
348 | 393 | struct resource_table *(*find_loaded_rsc_table)( |
---|
349 | 394 | struct rproc *rproc, const struct firmware *fw); |
---|
350 | 395 | int (*load)(struct rproc *rproc, const struct firmware *fw); |
---|
351 | 396 | int (*sanity_check)(struct rproc *rproc, const struct firmware *fw); |
---|
352 | | - u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw); |
---|
| 397 | + u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw); |
---|
| 398 | + unsigned long (*panic)(struct rproc *rproc); |
---|
| 399 | + void (*coredump)(struct rproc *rproc); |
---|
353 | 400 | }; |
---|
354 | 401 | |
---|
355 | 402 | /** |
---|
.. | .. |
---|
360 | 407 | * @RPROC_RUNNING: device is up and running |
---|
361 | 408 | * @RPROC_CRASHED: device has crashed; need to start recovery |
---|
362 | 409 | * @RPROC_DELETED: device is deleted |
---|
| 410 | + * @RPROC_DETACHED: device has been booted by another entity and waiting |
---|
| 411 | + * for the core to attach to it |
---|
363 | 412 | * @RPROC_LAST: just keep this one at the end |
---|
364 | 413 | * |
---|
365 | 414 | * Please note that the values of these states are used as indices |
---|
.. | .. |
---|
374 | 423 | RPROC_RUNNING = 2, |
---|
375 | 424 | RPROC_CRASHED = 3, |
---|
376 | 425 | RPROC_DELETED = 4, |
---|
377 | | - RPROC_LAST = 5, |
---|
| 426 | + RPROC_DETACHED = 5, |
---|
| 427 | + RPROC_LAST = 6, |
---|
378 | 428 | }; |
---|
379 | 429 | |
---|
380 | 430 | /** |
---|
.. | .. |
---|
395 | 445 | }; |
---|
396 | 446 | |
---|
397 | 447 | /** |
---|
| 448 | + * enum rproc_dump_mechanism - Coredump options for core |
---|
| 449 | + * @RPROC_COREDUMP_DISABLED: Don't perform any dump |
---|
| 450 | + * @RPROC_COREDUMP_ENABLED: Copy dump to separate buffer and carry on with |
---|
| 451 | + recovery |
---|
| 452 | + * @RPROC_COREDUMP_INLINE: Read segments directly from device memory. Stall |
---|
| 453 | + recovery until all segments are read |
---|
| 454 | + */ |
---|
| 455 | +enum rproc_dump_mechanism { |
---|
| 456 | + RPROC_COREDUMP_DISABLED, |
---|
| 457 | + RPROC_COREDUMP_ENABLED, |
---|
| 458 | + RPROC_COREDUMP_INLINE, |
---|
| 459 | +}; |
---|
| 460 | + |
---|
| 461 | +/** |
---|
398 | 462 | * struct rproc_dump_segment - segment info from ELF header |
---|
399 | 463 | * @node: list node related to the rproc segment list |
---|
400 | 464 | * @da: device address of the segment |
---|
401 | 465 | * @size: size of the segment |
---|
| 466 | + * @priv: private data associated with the dump_segment |
---|
| 467 | + * @dump: custom dump function to fill device memory segment associated |
---|
| 468 | + * with coredump |
---|
402 | 469 | */ |
---|
403 | 470 | struct rproc_dump_segment { |
---|
404 | 471 | struct list_head node; |
---|
.. | .. |
---|
406 | 473 | dma_addr_t da; |
---|
407 | 474 | size_t size; |
---|
408 | 475 | |
---|
| 476 | + void *priv; |
---|
| 477 | + void (*dump)(struct rproc *rproc, struct rproc_dump_segment *segment, |
---|
| 478 | + void *dest, size_t offset, size_t size); |
---|
409 | 479 | loff_t offset; |
---|
410 | 480 | }; |
---|
411 | 481 | |
---|
.. | .. |
---|
420 | 490 | * @dev: virtual device for refcounting and common remoteproc behavior |
---|
421 | 491 | * @power: refcount of users who need this rproc powered up |
---|
422 | 492 | * @state: state of the device |
---|
| 493 | + * @dump_conf: Currently selected coredump configuration |
---|
423 | 494 | * @lock: lock which protects concurrent manipulations of the rproc |
---|
424 | 495 | * @dbg_dir: debugfs directory of this rproc device |
---|
425 | 496 | * @traces: list of trace buffers |
---|
.. | .. |
---|
439 | 510 | * @cached_table: copy of the resource table |
---|
440 | 511 | * @table_sz: size of @cached_table |
---|
441 | 512 | * @has_iommu: flag to indicate if remote processor is behind an MMU |
---|
| 513 | + * @auto_boot: flag to indicate if remote processor should be auto-started |
---|
| 514 | + * @autonomous: true if an external entity has booted the remote processor |
---|
442 | 515 | * @dump_segments: list of segments in the firmware |
---|
| 516 | + * @nb_vdev: number of vdev currently handled by rproc |
---|
| 517 | + * @char_dev: character device of the rproc |
---|
| 518 | + * @cdev_put_on_release: flag to indicate if remoteproc should be shutdown on @char_dev release |
---|
443 | 519 | */ |
---|
444 | 520 | struct rproc { |
---|
445 | 521 | struct list_head node; |
---|
446 | 522 | struct iommu_domain *domain; |
---|
447 | 523 | const char *name; |
---|
448 | | - char *firmware; |
---|
| 524 | + const char *firmware; |
---|
449 | 525 | void *priv; |
---|
450 | 526 | struct rproc_ops *ops; |
---|
451 | 527 | struct device dev; |
---|
452 | 528 | atomic_t power; |
---|
453 | 529 | unsigned int state; |
---|
| 530 | + enum rproc_dump_mechanism dump_conf; |
---|
454 | 531 | struct mutex lock; |
---|
455 | 532 | struct dentry *dbg_dir; |
---|
456 | 533 | struct list_head traces; |
---|
457 | 534 | int num_traces; |
---|
458 | 535 | struct list_head carveouts; |
---|
459 | 536 | struct list_head mappings; |
---|
460 | | - u32 bootaddr; |
---|
| 537 | + u64 bootaddr; |
---|
461 | 538 | struct list_head rvdevs; |
---|
462 | 539 | struct list_head subdevs; |
---|
463 | 540 | struct idr notifyids; |
---|
.. | .. |
---|
471 | 548 | size_t table_sz; |
---|
472 | 549 | bool has_iommu; |
---|
473 | 550 | bool auto_boot; |
---|
| 551 | + bool autonomous; |
---|
474 | 552 | struct list_head dump_segments; |
---|
| 553 | + int nb_vdev; |
---|
| 554 | + u8 elf_class; |
---|
| 555 | + u16 elf_machine; |
---|
| 556 | + struct cdev cdev; |
---|
| 557 | + bool cdev_put_on_release; |
---|
475 | 558 | }; |
---|
476 | 559 | |
---|
477 | 560 | /** |
---|
.. | .. |
---|
499 | 582 | /** |
---|
500 | 583 | * struct rproc_vring - remoteproc vring state |
---|
501 | 584 | * @va: virtual address |
---|
502 | | - * @dma: dma address |
---|
503 | 585 | * @len: length, in bytes |
---|
504 | 586 | * @da: device address |
---|
505 | 587 | * @align: vring alignment |
---|
.. | .. |
---|
509 | 591 | */ |
---|
510 | 592 | struct rproc_vring { |
---|
511 | 593 | void *va; |
---|
512 | | - dma_addr_t dma; |
---|
513 | 594 | int len; |
---|
514 | 595 | u32 da; |
---|
515 | 596 | u32 align; |
---|
.. | .. |
---|
528 | 609 | * @vdev: the virio device |
---|
529 | 610 | * @vring: the vrings for this vdev |
---|
530 | 611 | * @rsc_offset: offset of the vdev's resource entry |
---|
| 612 | + * @index: vdev position versus other vdev declared in resource table |
---|
531 | 613 | */ |
---|
532 | 614 | struct rproc_vdev { |
---|
533 | 615 | struct kref refcount; |
---|
534 | 616 | |
---|
535 | 617 | struct rproc_subdev subdev; |
---|
| 618 | + struct device dev; |
---|
536 | 619 | |
---|
537 | 620 | unsigned int id; |
---|
538 | 621 | struct list_head node; |
---|
539 | 622 | struct rproc *rproc; |
---|
540 | | - struct virtio_device vdev; |
---|
541 | 623 | struct rproc_vring vring[RVDEV_NUM_VRINGS]; |
---|
542 | 624 | u32 rsc_offset; |
---|
| 625 | + u32 index; |
---|
543 | 626 | }; |
---|
544 | 627 | |
---|
545 | 628 | struct rproc *rproc_get_by_phandle(phandle phandle); |
---|
.. | .. |
---|
552 | 635 | int rproc_add(struct rproc *rproc); |
---|
553 | 636 | int rproc_del(struct rproc *rproc); |
---|
554 | 637 | void rproc_free(struct rproc *rproc); |
---|
| 638 | +void rproc_resource_cleanup(struct rproc *rproc); |
---|
| 639 | + |
---|
| 640 | +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, |
---|
| 641 | + const struct rproc_ops *ops, |
---|
| 642 | + const char *firmware, int len); |
---|
| 643 | +int devm_rproc_add(struct device *dev, struct rproc *rproc); |
---|
| 644 | + |
---|
| 645 | +void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem); |
---|
| 646 | + |
---|
| 647 | +struct rproc_mem_entry * |
---|
| 648 | +rproc_mem_entry_init(struct device *dev, |
---|
| 649 | + void *va, dma_addr_t dma, size_t len, u32 da, |
---|
| 650 | + int (*alloc)(struct rproc *, struct rproc_mem_entry *), |
---|
| 651 | + int (*release)(struct rproc *, struct rproc_mem_entry *), |
---|
| 652 | + const char *name, ...); |
---|
| 653 | + |
---|
| 654 | +struct rproc_mem_entry * |
---|
| 655 | +rproc_of_resm_mem_entry_init(struct device *dev, u32 of_resm_idx, size_t len, |
---|
| 656 | + u32 da, const char *name, ...); |
---|
555 | 657 | |
---|
556 | 658 | int rproc_boot(struct rproc *rproc); |
---|
557 | 659 | void rproc_shutdown(struct rproc *rproc); |
---|
| 660 | +int rproc_set_firmware(struct rproc *rproc, const char *fw_name); |
---|
558 | 661 | void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type); |
---|
| 662 | + |
---|
| 663 | +/* from remoteproc_coredump.c */ |
---|
| 664 | +void rproc_coredump_cleanup(struct rproc *rproc); |
---|
| 665 | +void rproc_coredump(struct rproc *rproc); |
---|
| 666 | +void rproc_coredump_using_sections(struct rproc *rproc); |
---|
559 | 667 | int rproc_coredump_add_segment(struct rproc *rproc, dma_addr_t da, size_t size); |
---|
| 668 | +int rproc_coredump_add_custom_segment(struct rproc *rproc, |
---|
| 669 | + dma_addr_t da, size_t size, |
---|
| 670 | + void (*dumpfn)(struct rproc *rproc, |
---|
| 671 | + struct rproc_dump_segment *segment, |
---|
| 672 | + void *dest, size_t offset, |
---|
| 673 | + size_t size), |
---|
| 674 | + void *priv); |
---|
| 675 | +int rproc_coredump_set_elf_info(struct rproc *rproc, u8 class, u16 machine); |
---|
560 | 676 | |
---|
561 | 677 | static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) |
---|
562 | 678 | { |
---|
563 | | - return container_of(vdev, struct rproc_vdev, vdev); |
---|
| 679 | + return container_of(vdev->dev.parent, struct rproc_vdev, dev); |
---|
564 | 680 | } |
---|
565 | 681 | |
---|
566 | 682 | static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev) |
---|