From fcf1fb679f0bca3b7a3e8bd1d7f0688c9ce5d3f5 Mon Sep 17 00:00:00 2001 From: Hanumant Singh Date: Mon, 10 Aug 2015 21:23:16 -0700 Subject: esoc: mdm-dbg: Add a debug request engine for external mdm Add a stub request engine for debugging external modem. Change-Id: I6360831f21f83fcd25df72492b1d57b30a7d2197 Signed-off-by: Hanumant Singh Signed-off-by: Bruce Levy [satyap@codeaurora.org: fix checkpatch issue] Signed-off-by: Satya Durga Srinivasu Prabhala --- drivers/esoc/Kconfig | 8 ++ drivers/esoc/esoc-mdm-dbg-eng.c | 169 +++++++++++++++++++++++++++++++++++++++- drivers/esoc/esoc-mdm-drv.c | 2 +- drivers/esoc/mdm-dbg.h | 6 +- 4 files changed, 180 insertions(+), 5 deletions(-) diff --git a/drivers/esoc/Kconfig b/drivers/esoc/Kconfig index 91e5c0b8b57b..ce6efd8e529c 100644 --- a/drivers/esoc/Kconfig +++ b/drivers/esoc/Kconfig @@ -58,4 +58,12 @@ config ESOC_MDM_DBG_ENG by command engine to the external modem. Also allows masking of certain notifications being sent to the external modem. +config MDM_DBG_REQ_ENG + tristate "manual request engine for 4x series external modems" + depends on ESOC_MDM_DBG_ENG + help + Provides a user interface to handle incoming requests from + the external modem. Allows for debugging of IPC mechanism + between the external modem and the primary soc. + endif diff --git a/drivers/esoc/esoc-mdm-dbg-eng.c b/drivers/esoc/esoc-mdm-dbg-eng.c index 4d465c18a646..d4ad25123565 100644 --- a/drivers/esoc/esoc-mdm-dbg-eng.c +++ b/drivers/esoc/esoc-mdm-dbg-eng.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -179,7 +179,165 @@ static ssize_t notifier_mask_store(struct device_driver *drv, const char *buf, } static DRIVER_ATTR(notifier_mask, S_IWUSR, NULL, notifier_mask_store); -int mdm_dbg_eng_init(struct esoc_drv *esoc_drv) +#ifdef CONFIG_MDM_DBG_REQ_ENG +static struct esoc_clink *dbg_clink; +/* Last recorded request from esoc */ +static enum esoc_req last_req; +static DEFINE_SPINLOCK(req_lock); +/* + * esoc_to_user: Conversion of esoc ids to user visible strings + * id: esoc request, command, notifier, event id + * str: string equivalent of the above + */ +struct esoc_to_user { + unsigned int id; + char str[20]; +}; + +static struct esoc_to_user in_to_resp[] = { + { + .id = ESOC_IMG_XFER_DONE, + .str = "XFER_DONE", + }, + { + .id = ESOC_BOOT_DONE, + .str = "BOOT_DONE", + }, + { + .id = ESOC_BOOT_FAIL, + .str = "BOOT_FAIL", + }, + { + .id = ESOC_IMG_XFER_RETRY, + .str = "XFER_RETRY", + }, + { .id = ESOC_IMG_XFER_FAIL, + .str = "XFER_FAIL", + }, + { + .id = ESOC_UPGRADE_AVAILABLE, + .str = "UPGRADE", + }, + { .id = ESOC_DEBUG_DONE, + .str = "DEBUG_DONE", + }, + { + .id = ESOC_DEBUG_FAIL, + .str = "DEBUG_FAIL", + }, +}; + +static struct esoc_to_user req_to_str[] = { + { + .id = ESOC_REQ_IMG, + .str = "REQ_IMG", + }, + { + .id = ESOC_REQ_DEBUG, + .str = "REQ_DEBUG", + }, + { + .id = ESOC_REQ_SHUTDOWN, + .str = "REQ_SHUTDOWN", + }, +}; + +static ssize_t req_eng_resp_store(struct device_driver *drv, const char *buf, + size_t count) +{ + unsigned int i; + const struct esoc_clink_ops *const clink_ops = dbg_clink->clink_ops; + + dev_dbg(&dbg_clink->dev, "user input req eng response %s\n", buf); + for (i = 0; i < ARRAY_SIZE(in_to_resp); i++) { + size_t len1 = strlen(buf); + size_t len2 = strlen(in_to_resp[i].str); + + if (len1 == len2 && !strcmp(buf, in_to_resp[i].str)) { + clink_ops->notify(in_to_resp[i].id, dbg_clink); + break; + } + } + if (i > ARRAY_SIZE(in_to_resp)) + dev_err(&dbg_clink->dev, "Invalid resp %s, specified\n", buf); + return count; +} + +static DRIVER_ATTR(req_eng_resp, S_IWUSR, NULL, req_eng_resp_store); + +static ssize_t last_esoc_req_show(struct device_driver *drv, char *buf) +{ + unsigned int i; + unsigned long flags; + size_t count; + + spin_lock_irqsave(&req_lock, flags); + for (i = 0; i < ARRAY_SIZE(req_to_str); i++) { + if (last_req == req_to_str[i].id) { + count = snprintf(buf, PAGE_SIZE, "%s\n", + req_to_str[i].str); + break; + } + } + spin_unlock_irqrestore(&req_lock, flags); + return count; +} +static DRIVER_ATTR(last_esoc_req, S_IRUSR, last_esoc_req_show, NULL); + +static void esoc_handle_req(enum esoc_req req, struct esoc_eng *eng) +{ + unsigned long flags; + + spin_lock_irqsave(&req_lock, flags); + last_req = req; + spin_unlock_irqrestore(&req_lock, flags); +} + +static void esoc_handle_evt(enum esoc_evt evt, struct esoc_eng *eng) +{ +} + +static struct esoc_eng dbg_req_eng = { + .handle_clink_req = esoc_handle_req, + .handle_clink_evt = esoc_handle_evt, +}; + +int register_dbg_req_eng(struct esoc_clink *clink, + struct device_driver *drv) +{ + int ret; + + dbg_clink = clink; + ret = driver_create_file(drv, &driver_attr_req_eng_resp); + if (ret) + return ret; + ret = driver_create_file(drv, &driver_attr_last_esoc_req); + if (ret) { + dev_err(&clink->dev, "Unable to create last esoc req\n"); + goto last_req_err; + } + ret = esoc_clink_register_req_eng(clink, &dbg_req_eng); + if (ret) { + pr_err("Unable to register req eng\n"); + goto req_eng_fail; + } + spin_lock_init(&req_lock); + return 0; +last_req_err: + driver_remove_file(drv, &driver_attr_last_esoc_req); +req_eng_fail: + driver_remove_file(drv, &driver_attr_req_eng_resp); + return ret; +} +#else +int register_dbg_req_eng(struct esoc_clink *clink, struct device_driver *d) +{ + return 0; +} +#endif + +int mdm_dbg_eng_init(struct esoc_drv *esoc_drv, + struct esoc_clink *clink) { int ret; struct device_driver *drv = &esoc_drv->driver; @@ -194,7 +352,14 @@ int mdm_dbg_eng_init(struct esoc_drv *esoc_drv) pr_err("Unable to create notify mask file\n"); goto notify_mask_err; } + ret = register_dbg_req_eng(clink, drv); + if (ret) { + pr_err("Failed to register esoc dbg req eng\n"); + goto dbg_req_fail; + } return 0; +dbg_req_fail: + driver_remove_file(drv, &driver_attr_notifier_mask); notify_mask_err: driver_remove_file(drv, &driver_attr_command_mask); cmd_mask_err: diff --git a/drivers/esoc/esoc-mdm-drv.c b/drivers/esoc/esoc-mdm-drv.c index 0c14929a0339..9abe125f28b5 100644 --- a/drivers/esoc/esoc-mdm-drv.c +++ b/drivers/esoc/esoc-mdm-drv.c @@ -258,7 +258,7 @@ int esoc_ssr_probe(struct esoc_clink *esoc_clink, struct esoc_drv *drv) ret = register_reboot_notifier(&mdm_drv->esoc_restart); if (ret) dev_err(&esoc_clink->dev, "register for reboot failed\n"); - ret = mdm_dbg_eng_init(drv); + ret = mdm_dbg_eng_init(drv, esoc_clink); if (ret) { debug_init_done = false; dev_err(&esoc_clink->dev, "dbg engine failure\n"); diff --git a/drivers/esoc/mdm-dbg.h b/drivers/esoc/mdm-dbg.h index ae31339ab152..ffba87c6f7bb 100644 --- a/drivers/esoc/mdm-dbg.h +++ b/drivers/esoc/mdm-dbg.h @@ -24,7 +24,8 @@ static inline bool dbg_check_notify_mask(unsigned int notify) return false; } -static inline int mdm_dbg_eng_init(struct esoc_drv *drv) +static inline int mdm_dbg_eng_init(struct esoc_drv *drv, + struct esoc_clink *clink) { return 0; } @@ -32,7 +33,8 @@ static inline int mdm_dbg_eng_init(struct esoc_drv *drv) #else extern bool dbg_check_cmd_mask(unsigned int cmd); extern bool dbg_check_notify_mask(unsigned int notify); -extern int mdm_dbg_eng_init(struct esoc_drv *drv); +extern int mdm_dbg_eng_init(struct esoc_drv *drv, + struct esoc_clink *clink); #endif static inline bool mdm_dbg_stall_cmd(unsigned int cmd) -- cgit v1.2.3 From f4523813054ac27f05eeaf0ecb090eee4b557bae Mon Sep 17 00:00:00 2001 From: Hanumant Singh Date: Wed, 11 May 2016 14:59:37 -0700 Subject: esoc: Add check for possible null pointer returns The call to kasprintf() can fail, with a failure to allocate memory. Handle the condition appropriately. CRs-Fixed: 1014400 Change-Id: I83d3a6c8bdfd7a104b88a3bedd50f49faeecd97a Signed-off-by: Hanumant Singh --- drivers/esoc/esoc_client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/esoc/esoc_client.c b/drivers/esoc/esoc_client.c index 6dee2f37b46d..e9932ea3e964 100644 --- a/drivers/esoc/esoc_client.c +++ b/drivers/esoc/esoc_client.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -47,6 +47,8 @@ struct esoc_desc *devm_register_esoc_client(struct device *dev, for (index = 0;; index++) { esoc_prop = kasprintf(GFP_KERNEL, "esoc-%d", index); + if (IS_ERR_OR_NULL(esoc_prop)) + return ERR_PTR(-ENOMEM); parp = of_get_property(np, esoc_prop, NULL); if (parp == NULL) { dev_err(dev, "esoc device not present\n"); -- cgit v1.2.3