diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 983a533e4c81..680f6f2dc8b9 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -264,6 +264,9 @@ enum fastrpc_msg_type { #define IS_ASYNC_FASTRPC_AVAILABLE (1) +/* User PD Dump Name Max length */ +#define RAMDUMP_NAME_MAX_LENGTH 20 + static int fastrpc_pdr_notifier_cb(struct notifier_block *nb, unsigned long code, void *data); @@ -332,6 +335,7 @@ struct fastrpc_file; struct fastrpc_buf { struct hlist_node hn; struct hlist_node hn_rem; + struct hlist_node hn_init; struct fastrpc_file *fl; void *virt; uint64_t phys; @@ -511,6 +515,7 @@ struct fastrpc_channel_ctx { struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX]; spinlock_t ctxlock; struct fastrpc_rpmsg_log gmsg_log; + struct hlist_head initmems; }; struct fastrpc_apps { @@ -888,6 +893,23 @@ static inline void reset_unique_index(int index) mutex_unlock(&gfa.mut_uid); } +/** + * fastrpc_elf_ramdump - Dump given ram dump entry + * @rh_dump_dev : Device handle for given channel + * @ramdump_entry : Dump region entry + * + * Returns int + */ +static int fastrpc_elf_ramdump(void *rh_dump_dev, struct ramdump_segment *ramdump_seg) +{ + int err = 0; + + err = do_elf_ramdump( + rh_dump_dev, + ramdump_seg, 1); + + return err; +} /** * fastrpc_minidump_add_region - Add mini dump region @@ -2219,6 +2241,42 @@ static void fastrpc_notify_users_staticpd_pdr(struct fastrpc_file *me) spin_unlock(&me->hlock); } +static void fastrpc_ramdump_collection(int cid) +{ + struct fastrpc_file *fl = NULL; + struct hlist_node *n = NULL; + struct fastrpc_apps *me = &gfa; + struct fastrpc_channel_ctx *chan = &me->channel[cid]; + struct ramdump_segment ramdump_entry; + struct fastrpc_buf *buf = NULL; + int ret; + char ramdump_name[RAMDUMP_NAME_MAX_LENGTH]; + + spin_lock(&me->hlock); + hlist_for_each_entry_safe(fl, n, &me->drivers, hn) { + if (fl->cid == cid && fl->init_mem) + hlist_add_head(&fl->init_mem->hn_init, &chan->initmems); + } + spin_unlock(&me->hlock); + + if (chan->rh_dump_dev) { + hlist_for_each_entry_safe(buf, n, &chan->initmems, hn_init) { + ramdump_entry.address = buf->phys; + ramdump_entry.v_address = (void __iomem *)buf->virt; + ramdump_entry.size = buf->size; + if (buf->fl) { + scnprintf(ramdump_name, ARRAY_SIZE(ramdump_name), + "%s_%x_", gcinfo[cid].subsys, buf->fl->tgid); + ramdump_entry.name = ramdump_name; + } + ret = fastrpc_elf_ramdump(chan->rh_dump_dev, &ramdump_entry); + if (ret < 0) + pr_err("adsprpc: %s: unable to dump PD memory (err %d)\n", + __func__, ret); + hlist_del_init(&buf->hn_init); + } + } +} static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) { @@ -2891,6 +2949,7 @@ static void fastrpc_init(struct fastrpc_apps *me) mutex_init(&me->channel[i].rpmsg_mutex); spin_lock_init(&me->channel[i].ctxlock); spin_lock_init(&me->channel[i].gmsg_log.lock); + INIT_HLIST_HEAD(&me->channel[i].initmems); } /* Set CDSP channel to non secure */ me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL; @@ -4436,7 +4495,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) struct hlist_node *n = NULL; int err = 0, ret = 0; struct fastrpc_apps *me = &gfa; - struct ramdump_segment *ramdump_segments_rh = NULL; + struct ramdump_segment ramdump_segments_rh; VERIFY(err, fl->cid == RH_CID); if (err) { @@ -4459,22 +4518,15 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) if (err) goto bail; if (me->ramdump_handle && me->enable_ramdump) { - ramdump_segments_rh = kcalloc(1, - sizeof(struct ramdump_segment), GFP_KERNEL); - if (ramdump_segments_rh) { - ramdump_segments_rh->address = - match->phys; - ramdump_segments_rh->v_address = - (void __iomem *)match->va; - ramdump_segments_rh->size = match->size; - ret = do_elf_ramdump( - me->ramdump_handle, - ramdump_segments_rh, 1); - if (ret < 0) - pr_err("adsprpc: %s: unable to dump heap (err %d)\n", - __func__, ret); - kfree(ramdump_segments_rh); - } + ramdump_segments_rh.address = + match->phys; + ramdump_segments_rh.v_address = + (void __iomem *)match->va; + ramdump_segments_rh.size = match->size; + ret = fastrpc_elf_ramdump(me->ramdump_handle, &ramdump_segments_rh); + if (ret < 0) + pr_err("adsprpc: %s: unable to dump heap (err %d)\n", + __func__, ret); } fastrpc_mmap_free(match, 0); } @@ -4925,7 +4977,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) { int err = 0; int cid = -1; - struct fastrpc_apps *me = &gfa; VERIFY(err, !IS_ERR_OR_NULL(rpdev)); if (err) { @@ -4942,7 +4993,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) mutex_lock(&gcinfo[cid].rpmsg_mutex); gcinfo[cid].rpdev = NULL; mutex_unlock(&gcinfo[cid].rpmsg_mutex); - fastrpc_notify_drivers(me, cid); ADSPRPC_INFO("closed rpmsg channel of %s\n", gcinfo[cid].subsys); bail: @@ -6112,6 +6162,8 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb, if (me->ramdump_handle) me->channel[RH_CID].ramdumpenabled = 1; } + if (cid == CDSP_DOMAIN_ID) + fastrpc_ramdump_collection(cid); pr_info("adsprpc: %s: received RAMDUMP notification for %s\n", __func__, gcinfo[cid].subsys); } else if (code == SUBSYS_BEFORE_POWERUP) { @@ -6122,6 +6174,7 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb, me->channel[RH_CID].ramdumpenabled = 0; } } + fastrpc_notify_drivers(me, cid); } else if (code == SUBSYS_AFTER_POWERUP) { pr_info("adsprpc: %s: %s subsystem is up\n", __func__, gcinfo[cid].subsys); @@ -6719,7 +6772,7 @@ static int __init fastrpc_device_init(void) pr_info("adsprpc: %s: SSR notifier registered for %s\n", __func__, gcinfo[i].subsys); } - + me->channel[CDSP_DOMAIN_ID].rh_dump_dev = create_ramdump_device("cdsp_minidump", NULL); err = register_rpmsg_driver(&fastrpc_rpmsg_client); if (err) { pr_err("Error: adsprpc: %s: register_rpmsg_driver failed with err %d\n",