diff options
-rwxr-xr-x | arch/arm/mach-omap2/board-tuna.c | 3 | ||||
-rwxr-xr-x | arch/arm/mach-omap2/omap4_ion.c | 136 | ||||
-rw-r--r-- | arch/arm/plat-omap/omap_rpmsg.c | 59 | ||||
-rw-r--r-- | drivers/remoteproc/omap_remoteproc.c | 21 | ||||
-rwxr-xr-x | drivers/remoteproc/remoteproc.c | 84 | ||||
-rw-r--r-- | include/linux/omap_ion.h | 6 | ||||
-rw-r--r-- | include/linux/remoteproc.h | 2 | ||||
-rw-r--r-- | include/linux/rpmsg.h | 1 |
8 files changed, 286 insertions, 26 deletions
diff --git a/arch/arm/mach-omap2/board-tuna.c b/arch/arm/mach-omap2/board-tuna.c index 3f0cbac6049..43aaf6f38e7 100755 --- a/arch/arm/mach-omap2/board-tuna.c +++ b/arch/arm/mach-omap2/board-tuna.c @@ -1401,10 +1401,11 @@ static void __init tuna_reserve(void) omap_ram_console_init(OMAP_RAM_CONSOLE_START_DEFAULT, OMAP_RAM_CONSOLE_SIZE_DEFAULT); - +#ifndef CONFIG_CMA /* do the static reservations first */ memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE); memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE); +#endif /* ipu needs to recognize secure input buffer area as well */ omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, diff --git a/arch/arm/mach-omap2/omap4_ion.c b/arch/arm/mach-omap2/omap4_ion.c index e5910204e53..2840c427310 100755 --- a/arch/arm/mach-omap2/omap4_ion.c +++ b/arch/arm/mach-omap2/omap4_ion.c @@ -14,6 +14,9 @@ #include <linux/memblock.h> #include <linux/omap_ion.h> #include <linux/platform_device.h> +#ifdef CONFIG_CMA +#include <linux/dma-contiguous.h> +#endif #include <plat/common.h> #include <mach/omap4_ion.h> @@ -46,6 +49,20 @@ static size_t omap4_ducati_heap_size; static size_t omap4_ion_heap_tiler_mem_size; static size_t omap4_ion_heap_nonsec_tiler_mem_size; +#ifdef CONFIG_CMA +static phys_addr_t omap4_ion_ipu_cma_addr; +static size_t omap4_ion_ipu_cma_pages_count; +static struct page* omap4_ion_ipu_cma_pages; + +/* See RPMSG_IPC_MEM calculation in arch/arm/plat-omap/omap_rpmsg.c */ +#define CMA_RPMSG_ADDR ((phys_addr_t)0xb3a00000) +#define CMA_RPMSG_SIZE ((size_t)0x8c000) + +static phys_addr_t omap4_ion_rpmsg_cma_addr; +static size_t omap4_ion_rpmsg_cma_pages_count; +static struct page* omap4_ion_rpmsg_cma_pages; +#endif + static struct ion_platform_data omap4_ion_data = { .nr = 6, .heaps = { @@ -105,11 +122,16 @@ void __init omap4_register_ion(void) void __init omap_ion_init(void) { - int i; - int ret; + int i, ret = 0; #ifndef CONFIG_ION_OMAP_TILER_DYNAMIC_ALLOC u32 nonsecure = omap4_ion_pdata.nonsecure_tiler2d_size; #endif +#ifdef CONFIG_CMA + size_t ipu_cma_pages_count; + phys_addr_t cma_area_addr; + size_t cma_area_size; + const size_t cma_alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order); +#endif system_512m = (omap_total_ram_size() == SZ_512M); @@ -192,6 +214,37 @@ void __init omap_ion_init(void) omap4_ion_heap_tiler_mem_addr, omap4_ion_heap_nonsec_tiler_mem_addr); +#ifdef CONFIG_CMA + ipu_cma_pages_count = (omap4_ion_heap_secure_input_size + + omap4_ion_heap_secure_output_wfdhdcp_size + + omap4_ducati_heap_size + + omap4_ion_heap_nonsec_tiler_mem_size + + omap4_ion_heap_tiler_mem_size) / PAGE_SIZE; + + cma_area_addr = round_down(omap4_ion_heap_nonsec_tiler_mem_addr, cma_alignment); + cma_area_size = round_up(ipu_cma_pages_count * PAGE_SIZE, cma_alignment); + + pr_info("Reserving CMA IPU + RPMSG region at address = 0x%x with size = 0x%x\n", + cma_area_addr, cma_area_size); + dma_declare_contiguous(&omap4_ion_device.dev, cma_area_size, cma_area_addr, 0); + + /* We need to separate RPMSG memory region from the overall Ducati range + * as it has to remain allocated even when the rest of Ducati is unloaded. + * Therefore, IPU carveout area is split into two pieces - below and above + * RPMSG region. */ + omap4_ion_ipu_cma_addr = CMA_RPMSG_ADDR + CMA_RPMSG_SIZE; + omap4_ion_ipu_cma_pages_count = ipu_cma_pages_count - CMA_RPMSG_SIZE / PAGE_SIZE; + + omap4_ion_rpmsg_cma_addr = CMA_RPMSG_ADDR; + omap4_ion_rpmsg_cma_pages_count = CMA_RPMSG_SIZE / PAGE_SIZE; + + pr_info("CMA RPMSG region: address = 0x%x, size = 0x%lx\n", omap4_ion_rpmsg_cma_addr, omap4_ion_rpmsg_cma_pages_count * PAGE_SIZE); + pr_info("CMA IPU region: address = 0x%x, size = 0x%lx\n", omap4_ion_ipu_cma_addr, omap4_ion_ipu_cma_pages_count * PAGE_SIZE); + + omap4_ion_ipu_cma_pages = NULL; + omap4_ion_rpmsg_cma_pages = NULL; +#endif + for (i = 0; i < omap4_ion_data.nr; i++) { struct ion_platform_heap *h = &omap4_ion_data.heaps[i]; @@ -223,8 +276,10 @@ void __init omap_ion_init(void) for (i = 0; i < omap4_ion_data.nr; i++) if (omap4_ion_data.heaps[i].type == ION_HEAP_TYPE_CARVEOUT || omap4_ion_data.heaps[i].type == OMAP_ION_HEAP_TYPE_TILER) { +#ifndef CONFIG_CMA ret = memblock_remove(omap4_ion_data.heaps[i].base, omap4_ion_data.heaps[i].size); +#endif if (!omap4_ion_data.heaps[i].size) continue; if (omap4_ion_data.heaps[i].id == @@ -300,3 +355,80 @@ size_t omap_ion_heap_nonsec_tiler_mem_size(void) { return omap4_ion_heap_nonsec_tiler_mem_size; } + +#ifdef CONFIG_CMA +bool omap_ion_ipu_allocate_memory(void) +{ + if (omap4_ion_ipu_cma_pages) { + pr_err("%s: CMA IPU pages are already allocated\n", __func__); + return false; + } + + omap4_ion_ipu_cma_pages = dma_alloc_from_contiguous_fixed_addr(&omap4_ion_device.dev, + omap4_ion_ipu_cma_addr, omap4_ion_ipu_cma_pages_count); + + if (!omap4_ion_ipu_cma_pages) { + pr_err("CMA IPU region pages allocation failed\n"); + return false; + } + + return true; +} +EXPORT_SYMBOL(omap_ion_ipu_allocate_memory); + +bool omap_ion_ipu_free_memory(void) +{ + if (!omap4_ion_ipu_cma_pages) { + pr_err("%s: CMA IPU pages are not allocated\n", __func__); + return false; + } + + if (!dma_release_from_contiguous(&omap4_ion_device.dev, omap4_ion_ipu_cma_pages, + omap4_ion_ipu_cma_pages_count)) { + pr_err("CMA IPU region pages release failed\n"); + return false; + } + + omap4_ion_ipu_cma_pages = NULL; + + return true; +} +EXPORT_SYMBOL(omap_ion_ipu_free_memory); + +bool omap_ion_rpmsg_allocate_memory(void) +{ + if (omap4_ion_rpmsg_cma_pages) { + pr_err("CMA RPMSG pages are already allocated\n"); + return false; + } + + omap4_ion_rpmsg_cma_pages = dma_alloc_from_contiguous_fixed_addr(&omap4_ion_device.dev, + omap4_ion_rpmsg_cma_addr, omap4_ion_rpmsg_cma_pages_count); + if (!omap4_ion_rpmsg_cma_pages) { + pr_err("CMA RPMSG region pages allocation failed\n"); + return false; + } + + return true; +} +EXPORT_SYMBOL(omap_ion_rpmsg_allocate_memory); + +bool omap_ion_rpmsg_free_memory(void) +{ + if (!omap4_ion_rpmsg_cma_pages) { + pr_err("CMA RPMSG pages are not allocated\n"); + return false; + } + + if (!dma_release_from_contiguous(&omap4_ion_device.dev, omap4_ion_rpmsg_cma_pages, + omap4_ion_rpmsg_cma_pages_count)) { + pr_err("CMA RPMSG region pages release failed\n"); + return false; + } + + omap4_ion_rpmsg_cma_pages = NULL; + + return true; +} +EXPORT_SYMBOL(omap_ion_rpmsg_free_memory); +#endif diff --git a/arch/arm/plat-omap/omap_rpmsg.c b/arch/arm/plat-omap/omap_rpmsg.c index 8ece47954ff..f4bc0eabe32 100644 --- a/arch/arm/plat-omap/omap_rpmsg.c +++ b/arch/arm/plat-omap/omap_rpmsg.c @@ -33,6 +33,8 @@ #include <linux/memblock.h> #include <linux/remoteproc.h> #include <linux/delay.h> +#include <linux/ion.h> +#include <linux/omap_ion.h> #include <asm/io.h> @@ -53,7 +55,7 @@ struct omap_rpmsg_vproc { struct rproc *rproc; struct notifier_block nb; struct notifier_block rproc_nb; - struct work_struct reset_work; + struct work_struct reset_work, reset_keep_rproc_work; bool slave_reset; struct omap_rpmsg_vproc *slave_next; struct virtqueue *vq[2]; @@ -497,17 +499,19 @@ static void omap_rpmsg_vproc_release(struct device *dev) /* this handler is provided so driver core doesn't yell at us */ } -static void rpmsg_reset_work(struct work_struct *work) +static void rpmsg_unregister_devices(struct omap_rpmsg_vproc *rpdev) { - struct omap_rpmsg_vproc *rpdev = - container_of(work, struct omap_rpmsg_vproc, reset_work); struct omap_rpmsg_vproc *tmp; - int ret; - for (tmp = rpdev; tmp; tmp = tmp->slave_next) { pr_err("reseting virtio device %d\n", tmp->vdev.index); unregister_virtio_device(&tmp->vdev); } +} + +static void rpmsg_register_devices(struct omap_rpmsg_vproc *rpdev) +{ + struct omap_rpmsg_vproc *tmp; + int ret; for (tmp = rpdev; tmp; tmp = tmp->slave_next) { memset(&tmp->vdev.dev, 0, sizeof(struct device)); tmp->vdev.dev.release = omap_rpmsg_vproc_release; @@ -517,6 +521,26 @@ static void rpmsg_reset_work(struct work_struct *work) } } +static void rpmsg_reset_work(struct work_struct *work) +{ + struct omap_rpmsg_vproc *rpdev = + container_of(work, struct omap_rpmsg_vproc, reset_work); + rpmsg_unregister_devices(rpdev); + rpmsg_register_devices(rpdev); +} + +static void rpmsg_reset_keep_rproc_work(struct work_struct *work) +{ + struct omap_rpmsg_vproc *rpdev = + container_of(work, struct omap_rpmsg_vproc, reset_keep_rproc_work); + /* Ensure there's extra reference to rproc so that + * we don't trigger unload of the firmware. */ + rproc_get(rpdev->rproc->name); + rpmsg_unregister_devices(rpdev); + rpmsg_register_devices(rpdev); + rproc_put(rpdev->rproc); +} + static struct virtio_config_ops omap_rpmsg_config_ops = { .get_features = omap_rpmsg_get_features, .finalize_features = omap_rpmsg_finalize_features, @@ -562,6 +586,18 @@ static struct omap_rpmsg_vproc omap_rpmsg_vprocs[] = { }, }; +void rpmsg_reset_all_devices(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(omap_rpmsg_vprocs); i++) { + struct omap_rpmsg_vproc *rpdev = &omap_rpmsg_vprocs[i]; + if (!rpdev->slave_reset) { + flush_work_sync(&rpdev->reset_keep_rproc_work); + schedule_work(&rpdev->reset_keep_rproc_work); + } + } +} + static int __init omap_rpmsg_ini(void) { int i, ret = 0; @@ -570,6 +606,12 @@ static int __init omap_rpmsg_ini(void) phys_addr_t psize = omap_ipu_get_mempool_size( OMAP_RPROC_MEMPOOL_STATIC); +#ifdef CONFIG_CMA + if (!omap_ion_rpmsg_allocate_memory()) { + return -ENOMEM; + } +#endif + for (i = 0; i < ARRAY_SIZE(omap_rpmsg_vprocs); i++) { struct omap_rpmsg_vproc *rpdev = &omap_rpmsg_vprocs[i]; @@ -587,6 +629,7 @@ static int __init omap_rpmsg_ini(void) rpdev->vring[0] = paddr + RPMSG_BUFS_SPACE; rpdev->vring[1] = paddr + RPMSG_BUFS_SPACE + RPMSG_RING_SIZE; INIT_WORK(&rpdev->reset_work, rpmsg_reset_work); + INIT_WORK(&rpdev->reset_keep_rproc_work, rpmsg_reset_keep_rproc_work); paddr += RPMSG_IPC_MEM; psize -= RPMSG_IPC_MEM; @@ -616,6 +659,10 @@ static void __exit omap_rpmsg_fini(void) unregister_virtio_device(&rpdev->vdev); } + +#ifdef CONFIG_CMA + omap_ion_rpmsg_free_memory(); +#endif } module_exit(omap_rpmsg_fini); diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 7c10c79501e..cc62ef61ebc 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -479,6 +479,9 @@ static inline int omap_rproc_start(struct rproc *rproc, u64 bootaddr) } ret = omap_device_enable(pdev); + if (ret) { + dev_err(rproc->dev, "failed to enable device: %d\n", ret); + } out: if (ret) { while (i--) { @@ -507,10 +510,16 @@ static int omap_rproc_iommu_exit(struct rproc *rproc) return 0; } +static inline struct omap_device *_find_by_pdev(struct platform_device *pdev) +{ + return container_of(pdev, struct omap_device, pdev); +} + static inline int omap_rproc_stop(struct rproc *rproc) { struct device *dev = rproc->dev; struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = _find_by_pdev(pdev); struct omap_rproc_pdata *pdata = dev->platform_data; struct omap_rproc_timers_info *timers = pdata->timers; int ret, i; @@ -526,9 +535,15 @@ static inline int omap_rproc_stop(struct rproc *rproc) rproc->secure_reset = false; } - ret = omap_device_idle(pdev); - if (ret) - goto err; + /* We might be called from the suspended state, + * in that case we shouldn't try to call omap_device_idle(). */ + if (od->_state == OMAP_DEVICE_STATE_ENABLED) { + ret = omap_device_idle(pdev); + if (ret) + goto err; + } else { + ret = 0; + } for (i = 0; i < pdata->timers_cnt; i++) { #ifdef CONFIG_REMOTEPROC_WATCHDOG diff --git a/drivers/remoteproc/remoteproc.c b/drivers/remoteproc/remoteproc.c index 65d2c79ce06..939274c434e 100755 --- a/drivers/remoteproc/remoteproc.c +++ b/drivers/remoteproc/remoteproc.c @@ -35,11 +35,14 @@ #include <linux/list.h> #include <linux/debugfs.h> #include <linux/remoteproc.h> +#include <linux/rpmsg.h> #include <linux/pm_runtime.h> #include <linux/uaccess.h> #include <linux/elf.h> #include <linux/elfcore.h> #include <plat/remoteproc.h> +#include <linux/ion.h> +#include <linux/omap_ion.h> /* list of available remote processors on this board */ static LIST_HEAD(rprocs); @@ -1261,7 +1264,7 @@ int rproc_error_notify(struct rproc *rproc) } EXPORT_SYMBOL_GPL(rproc_error_notify); -struct rproc *rproc_get(const char *name) +static struct rproc *_rproc_get(const char *name, bool use_refcounting) { struct rproc *rproc, *ret = NULL; struct device *dev; @@ -1297,7 +1300,13 @@ struct rproc *rproc_get(const char *name) } /* bail if rproc is already powered up */ - if (rproc->count++) { + if (use_refcounting && rproc->count++) { + ret = rproc; + goto unlock_mutex; + } + + if (use_refcounting && rproc->state != RPROC_OFFLINE) { + dev_info(dev, "redundant rproc restart request, ignoring\n"); ret = rproc; goto unlock_mutex; } @@ -1305,6 +1314,13 @@ struct rproc *rproc_get(const char *name) /* rproc_put() calls should wait until async loader completes */ init_completion(&rproc->firmware_loading_complete); +#ifdef CONFIG_CMA + if (!omap_ion_ipu_allocate_memory()) { + ret = NULL; + goto unlock_mutex; + } +#endif + dev_info(dev, "powering up %s\n", name); err = rproc_loader(rproc); @@ -1312,7 +1328,7 @@ struct rproc *rproc_get(const char *name) dev_err(dev, "failed to load rproc %s\n", rproc->name); complete_all(&rproc->firmware_loading_complete); module_put(rproc->owner); - --rproc->count; + rproc->count -= (use_refcounting ? 1 : 0); goto unlock_mutex; } @@ -1323,9 +1339,14 @@ unlock_mutex: mutex_unlock(&rproc->lock); return ret; } + +struct rproc *rproc_get(const char *name) +{ + return _rproc_get(name, true); +} EXPORT_SYMBOL_GPL(rproc_get); -void rproc_put(struct rproc *rproc) +static void _rproc_put(struct rproc *rproc, bool use_refcounting) { struct device *dev = rproc->dev; int ret; @@ -1339,14 +1360,14 @@ void rproc_put(struct rproc *rproc) return; } - if (!rproc->count) { + if (use_refcounting && !rproc->count) { dev_warn(dev, "asymmetric rproc_put\n"); ret = -EINVAL; goto out; } /* if the remote proc is still needed, bail out */ - if (--rproc->count) + if (use_refcounting && --rproc->count) goto out; if (mutex_lock_interruptible(&rproc->tlock)) @@ -1380,13 +1401,15 @@ void rproc_put(struct rproc *rproc) */ if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_LOADING) { #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND - /* - * Call resume, it will cancel any pending autosuspend, - * so that no callback is executed after the device is stopped. - * Device stop function takes care of shutting down the device. - */ - pm_runtime_get_sync(rproc->dev); - pm_runtime_put_noidle(rproc->dev); + if (use_refcounting) { + /* + * Call resume, it will cancel any pending autosuspend, + * so that no callback is executed after the device is stopped. + * Device stop function takes care of shutting down the device. + */ + pm_runtime_get_sync(rproc->dev); + pm_runtime_put_noidle(rproc->dev); + } if (!rproc->secure_reset) pm_runtime_disable(rproc->dev); @@ -1423,11 +1446,19 @@ void rproc_put(struct rproc *rproc) dev_info(dev, "stopped remote processor %s\n", rproc->name); +#ifdef CONFIG_CMA + omap_ion_ipu_free_memory(); +#endif + out: mutex_unlock(&rproc->lock); if (!ret) module_put(rproc->owner); } +void rproc_put(struct rproc *rproc) +{ + return _rproc_put(rproc, true); +} EXPORT_SYMBOL_GPL(rproc_put); static void rproc_error_work(struct work_struct *work) @@ -1450,6 +1481,8 @@ int rproc_event_unregister(struct rproc *rproc, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(rproc_event_unregister); +static int rproc_runtime_resume(struct device *dev); + void rproc_last_busy(struct rproc *rproc) { #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND @@ -1471,6 +1504,11 @@ void rproc_last_busy(struct rproc *rproc) mutex_unlock(&rproc->lock); return; } + if (rproc->state == RPROC_OFFLINE) { + mutex_unlock(&rproc->lock); + rproc_runtime_resume(dev); + return; + } mutex_unlock(&rproc->lock); pm_runtime_get_sync(dev); pm_runtime_mark_last_busy(dev); @@ -1556,6 +1594,12 @@ out: return ret; } +static void rproc_unload_work(struct work_struct *work) +{ + struct rproc *rproc = container_of(work, struct rproc, unload_work); + _rproc_put(rproc, false); +} + static int rproc_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -1564,6 +1608,12 @@ static int rproc_runtime_resume(struct device *dev) dev_dbg(dev, "Enter %s\n", __func__); + if (rproc->state == RPROC_OFFLINE) { + dev_info(dev, "rproc_runtime_resume in RPROC_OFFLINE mode - waking up.\n"); + _rproc_get(rproc->name, false); + rpmsg_reset_all_devices(); + } + if (rproc->ops->resume) ret = rproc->ops->resume(rproc); @@ -1628,6 +1678,11 @@ static int rproc_runtime_suspend(struct device *dev) _event_notify(rproc, RPROC_POS_SUSPEND, NULL); mutex_unlock(&rproc->pm_lock); +#ifdef CONFIG_CMA + /* Unload firmware and free memory */ + schedule_work(&rproc->unload_work); +#endif + return 0; abort: pm_runtime_mark_last_busy(dev); @@ -1721,6 +1776,9 @@ int rproc_register(struct device *dev, const char *name, mutex_init(&rproc->secure_lock); mutex_init(&rproc->tlock); INIT_WORK(&rproc->error_work, rproc_error_work); +#ifdef CONFIG_CMA + INIT_WORK(&rproc->unload_work, rproc_unload_work); +#endif BLOCKING_INIT_NOTIFIER_HEAD(&rproc->nbh); rproc->state = RPROC_OFFLINE; diff --git a/include/linux/omap_ion.h b/include/linux/omap_ion.h index 81c73e2f6c1..2fd3a094cc6 100644 --- a/include/linux/omap_ion.h +++ b/include/linux/omap_ion.h @@ -56,6 +56,12 @@ int omap_ion_share_fd_to_buffers(int fd, struct ion_buffer **buffers, int omap_tiler_vinfo(struct ion_client *client, struct ion_handle *handle, unsigned int *vstride, unsigned int *vsize); +#ifdef CONFIG_CMA +bool omap_ion_ipu_allocate_memory(void); +bool omap_ion_ipu_free_memory(void); +bool omap_ion_rpmsg_allocate_memory(void); +bool omap_ion_rpmsg_free_memory(void); +#endif #endif /* __KERNEL__ */ /* additional heaps used only on omap */ diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index cd0105da6a8..d8ca8262f87 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -270,7 +270,7 @@ struct rproc { int cdump_len0, cdump_len1; struct mutex tlock; struct completion firmware_loading_complete; - struct work_struct error_work; + struct work_struct error_work, unload_work; struct blocking_notifier_head nbh; struct completion error_comp; #ifdef CONFIG_REMOTE_PROC_AUTOSUSPEND diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 1f7ba091c50..4bc3abc85f0 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -146,6 +146,7 @@ void rpmsg_destroy_ept(struct rpmsg_endpoint *); struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *, void (*cb)(struct rpmsg_channel *, void *, int, void *, u32), void *priv, u32 addr); +void rpmsg_reset_all_devices(void); int rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool); |