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 <hanumant@codeaurora.org>
Signed-off-by: Bruce Levy <blevy@codeaurora.org>
[satyap@codeaurora.org: fix checkpatch issue]
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
This commit is contained in:
Hanumant Singh 2015-08-10 21:23:16 -07:00 committed by Satya Durga Srinivasu Prabhala
parent 25becb4433
commit fcf1fb679f
4 changed files with 180 additions and 5 deletions

View file

@ -58,4 +58,12 @@ config ESOC_MDM_DBG_ENG
by command engine to the external modem. Also allows masking by command engine to the external modem. Also allows masking
of certain notifications being sent to the external modem. 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 endif

View file

@ -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 * 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 * 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); 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; int ret;
struct device_driver *drv = &esoc_drv->driver; 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"); pr_err("Unable to create notify mask file\n");
goto notify_mask_err; 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; return 0;
dbg_req_fail:
driver_remove_file(drv, &driver_attr_notifier_mask);
notify_mask_err: notify_mask_err:
driver_remove_file(drv, &driver_attr_command_mask); driver_remove_file(drv, &driver_attr_command_mask);
cmd_mask_err: cmd_mask_err:

View file

@ -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); ret = register_reboot_notifier(&mdm_drv->esoc_restart);
if (ret) if (ret)
dev_err(&esoc_clink->dev, "register for reboot failed\n"); 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) { if (ret) {
debug_init_done = false; debug_init_done = false;
dev_err(&esoc_clink->dev, "dbg engine failure\n"); dev_err(&esoc_clink->dev, "dbg engine failure\n");

View file

@ -24,7 +24,8 @@ static inline bool dbg_check_notify_mask(unsigned int notify)
return false; 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; return 0;
} }
@ -32,7 +33,8 @@ static inline int mdm_dbg_eng_init(struct esoc_drv *drv)
#else #else
extern bool dbg_check_cmd_mask(unsigned int cmd); extern bool dbg_check_cmd_mask(unsigned int cmd);
extern bool dbg_check_notify_mask(unsigned int notify); 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 #endif
static inline bool mdm_dbg_stall_cmd(unsigned int cmd) static inline bool mdm_dbg_stall_cmd(unsigned int cmd)