From eee3f8c0132d4b53b45876d957c55c92b2d14219 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Mon, 2 Jul 2018 21:40:59 +0900 Subject: [PATCH] chub: add itmon notifier Change-Id: I3712e75bc92057d41f18b313b6ea60e5a8c910c9 Signed-off-by: Boojin Kim --- drivers/staging/nanohub/chub.c | 191 ++++++++++++++++++----------- drivers/staging/nanohub/chub.h | 18 ++- drivers/staging/nanohub/chub_dbg.c | 109 +++++++++++----- drivers/staging/nanohub/chub_dbg.h | 5 +- drivers/staging/nanohub/chub_ipc.c | 15 ++- drivers/staging/nanohub/chub_ipc.h | 1 - drivers/staging/nanohub/chub_log.c | 19 +++ drivers/staging/nanohub/comms.c | 17 ++- 8 files changed, 251 insertions(+), 124 deletions(-) diff --git a/drivers/staging/nanohub/chub.c b/drivers/staging/nanohub/chub.c index 58965bfc463d..6bb91d53b125 100644 --- a/drivers/staging/nanohub/chub.c +++ b/drivers/staging/nanohub/chub.c @@ -29,6 +29,9 @@ #include #include #include +#ifdef CONFIG_EXYNOS_ITMON +#include +#endif #ifdef CONFIG_CHRE_SENSORHUB_HAL #include "main.h" @@ -239,6 +242,23 @@ static inline void read_put_unlocked(struct contexthub_ipc_info *ipc) atomic_dec(&ipc->read_lock.cnt); } +static void enable_debug_workqueue(struct contexthub_ipc_info *ipc, enum chub_err_type err) +{ + ipc->err_cnt[err]++; + ipc->active_err |= (1 << err); + + dev_info(ipc->dev, "%s: err:%d(cnt:%d), active:0x%x\n", + __func__, err, ipc->err_cnt[err], ipc->active_err); + + if (err == CHUB_ERR_ITMON) { + chub_dbg_dump_gpr(ipc); + chub_dbg_dump_ram(ipc, err); + chub_dbg_print_hw(ipc); + } else { + schedule_work(&ipc->debug_work); + } +} + int contexthub_ipc_read(struct contexthub_ipc_info *ipc, uint8_t *rx, int max_length, int timeout) { @@ -311,11 +331,7 @@ search_channel: #endif fail_get_channel: - ipc->err_cnt[CHUB_ERR_READ_FAIL]++; - dev_err(ipc->dev, - "%s: fails to get data errcnt:%d\n", - __func__, ipc->err_cnt[CHUB_ERR_READ_FAIL]); - schedule_work(&ipc->debug_work); + enable_debug_workqueue(ipc, CHUB_ERR_READ_FAIL); return -EINVAL; } @@ -327,10 +343,9 @@ int contexthub_ipc_write(struct contexthub_ipc_info *ipc, ret = ipc_write_data(IPC_DATA_A2C, tx, (u16)length); if (ret) { - ipc->err_cnt[CHUB_ERR_WRITE_FAIL]++; pr_err("%s: fails to write data: ret:%d, len:%d errcnt:%d\n", __func__, ret, length, ipc->err_cnt[CHUB_ERR_WRITE_FAIL]); - schedule_work(&ipc->debug_work); + enable_debug_workqueue(ipc, CHUB_ERR_WRITE_FAIL); length = 0; } return length; @@ -648,8 +663,7 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc, if (atomic_read(&ipc->chub_status) == CHUB_ST_RUN || atomic_read(&ipc->chub_status) == CHUB_ST_NO_RESPONSE) { atomic_set(&ipc->chub_status, CHUB_ST_NO_RESPONSE); - ipc->err_cnt[CHUB_ERR_CHUB_NO_RESPONSE]++; - schedule_work(&ipc->debug_work); + enable_debug_workqueue(ipc, CHUB_ERR_CHUB_NO_RESPONSE); } ret = -EINVAL; } @@ -673,7 +687,6 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc, ipc_write_debug_event(AP, (u32)event); ipc_add_evt(IPC_EVT_A2C, IRQ_EVT_A2C_DEBUG); } - return ret; } @@ -725,18 +738,15 @@ int contexthub_reset(struct contexthub_ipc_info *ipc) int ret; dev_info(ipc->dev, "%s\n", __func__); -#if 0 - spin_lock(&ipc->reset_lock); - if (atomic_read(&ipc->chub_status) == CHUB_ST_RUN) { - spin_unlock(&ipc->reset_lock); - pr_err("%s: chub already reset. run: %d\n", - __func__, atomic_read(&ipc->chub_status)); - return 0; + if (atomic_read(&ipc->in_reset)) { + dev_info(ipc->dev, "%s is in-progress\n", __func__); + return -EINVAL; } -#endif + + atomic_inc(&ipc->in_reset); ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_SHUTDOWN); if (ret) { - pr_err("%s: shutdonw fails, ret:%d\n", __func__, ret); + dev_err(ipc->dev, "%s: shutdonw fails, ret:%d\n", __func__, ret); return ret; } if (ipc->block_reset) { @@ -744,20 +754,22 @@ int contexthub_reset(struct contexthub_ipc_info *ipc) if (!ret) { ret = contexthub_download_image(ipc, 0); if (ret) { - pr_err("%s: download os fails\n", __func__); + dev_err(ipc->dev, "%s: download os fails\n", __func__); return ret; } } else { - pr_err("%s: download bl fails\n", __func__); + dev_err(ipc->dev, "%s: download bl fails\n", __func__); return ret; } } ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_RESET); if (ret) - pr_err("%s: reset fails, ret:%d\n", __func__, ret); -#if 0 - spin_unlock(&ipc->reset_lock); -#endif + dev_err(ipc->dev, "%s: reset fails, ret:%d\n", __func__, ret); + else + dev_info(ipc->dev, "%s: chub reseted! (cnt:%d)\n", + __func__, atomic_read(&ipc->in_reset)); + + atomic_dec(&ipc->in_reset); return ret; } @@ -846,16 +858,15 @@ static void handle_debug_work_func(struct work_struct *work) { struct contexthub_ipc_info *ipc = container_of(work, struct contexthub_ipc_info, debug_work); - enum ipc_debug_event event = ipc_read_debug_event(AP); - enum CHUB_ERR_TYPE fw_err = 0; + enum ipc_debug_event event = 0; + enum chub_err_type err = 0; bool need_reset = 0; bool alive = contexthub_lowlevel_alive(ipc); - int err = 0; int ret; int i; - dev_info(ipc->dev, "%s: fw_err:%d, alive:%d\n", - __func__, event, alive); + dev_info(ipc->dev, "%s: active_err:0x%x, alive:%d\n", + __func__, ipc->active_err, alive); if (!alive || ipc->err_cnt[CHUB_ERR_NANOHUB_WDT]) { need_reset = 1; @@ -863,48 +874,53 @@ static void handle_debug_work_func(struct work_struct *work) goto do_reset; } - for (i = 0; i < CHUB_ERR_MAX; i++) { - if (ipc->err_cnt[i]) - dev_info(ipc->dev, "%s: err%d-%d\n", - __func__, i, ipc->err_cnt[i]); - /* if error is bigger than MAX_ERR_CNT, should be reset */ - if (ipc->err_cnt[i] > MAX_ERR_CNT) { + /* print error status */ + for (i = 0; i < CHUB_ERR_CHUB_MAX; i++) { + if (ipc->active_err & (1 << i)) { + dev_info(ipc->dev, "%s: err%d-%d, active_err:0x%x\n", + __func__, i, ipc->err_cnt[i], ipc->active_err); + ipc->active_err &= ~(1 << i); err = i; - need_reset = 1; } } - - if (need_reset) - goto do_reset; - - /* chub fw error */ - switch (event) { - case IPC_DEBUG_CHUB_FULL_LOG: - dev_warn(ipc->dev, - "Contexthub notified that logbuf is full\n"); - break; - case IPC_DEBUG_CHUB_PRINT_LOG: - break; - case IPC_DEBUG_CHUB_FAULT: - dev_warn(ipc->dev, "Contexthub notified fault\n"); - err = CHUB_ERR_NANOHUB_FAULT; - break; - case IPC_DEBUG_CHUB_ASSERT: - dev_warn(ipc->dev, "Contexthub notified assert\n"); - err = CHUB_ERR_NANOHUB_ASSERT; - break; - case IPC_DEBUG_CHUB_ERROR: - dev_warn(ipc->dev, "Contexthub notified error\n"); - err = CHUB_ERR_NANOHUB_ERROR; - break; - default: - break; + /* print comms error status */ + for (i = CHUB_ERR_MAX + 1; i < CHUB_ERR_COMMS_MAX; i++) { + if (ipc->err_cnt[i]) + dev_info(ipc->dev, "%s: comms: err%d-%d\n", + __func__, i, ipc->err_cnt[i]); } - if (event) /* clear dbg event */ + /* check chub fw error */ + event = ipc_read_debug_event(AP); + if (event) { + switch (event) { + case IPC_DEBUG_CHUB_FULL_LOG: + dev_warn(ipc->dev, + "Contexthub notified that logbuf is full\n"); + break; + case IPC_DEBUG_CHUB_PRINT_LOG: + break; + case IPC_DEBUG_CHUB_FAULT: + dev_warn(ipc->dev, "Contexthub notified fault\n"); + err = CHUB_ERR_NANOHUB_FAULT; + break; + case IPC_DEBUG_CHUB_ASSERT: + dev_warn(ipc->dev, "Contexthub notified assert\n"); + err = CHUB_ERR_NANOHUB_ASSERT; + break; + case IPC_DEBUG_CHUB_ERROR: + dev_warn(ipc->dev, "Contexthub notified error\n"); + err = CHUB_ERR_NANOHUB_ERROR; + break; + default: + break; + } + + /* clear dbg event */ ipc_write_debug_event(AP, 0); - if (err) - ipc->err_cnt[fw_err]++; + if (err) + ipc->err_cnt[err]++; + } do_reset: dev_info(ipc->dev, "%s: error:%d, alive:%d\n", @@ -913,6 +929,7 @@ do_reset: /* dump hw & sram into file */ chub_dbg_dump_hw(ipc, err); if (need_reset) { +#ifdef CHUB_RESET_ENABLE ret = contexthub_reset(ipc); if (ret) dev_warn(ipc->dev, "%s: fails to reset %d.\n", @@ -925,6 +942,7 @@ do_reset: if (ipc->irq_wdt) enable_irq(ipc->irq_wdt); } +#endif } else { /* dump log into file: DO NOT logbuf dueto sram corruption */ log_dump_all(err); @@ -937,7 +955,7 @@ static void handle_irq(struct contexthub_ipc_info *ipc, enum irq_evt_chub evt) switch (evt) { case IRQ_EVT_C2A_DEBUG: - schedule_work(&ipc->debug_work); + enable_debug_workqueue(ipc, CHUB_ERR_NANOHUB); break; case IRQ_EVT_C2A_INT: if (atomic_read(&ipc->irq1_apInt) == C2A_OFF) { @@ -995,7 +1013,7 @@ static irqreturn_t contexthub_irq_handler(int irq, void *data) int start_index = ipc_hw_read_int_start_index(AP); unsigned int status = ipc_hw_read_int_status_reg(AP); struct ipc_evt_buf *cur_evt; - enum CHUB_ERR_TYPE err = 0; + enum chub_err_type err = 0; enum irq_chub evt = 0; int irq_num = IRQ_EVT_CHUB_ALIVE + start_index; @@ -1038,20 +1056,19 @@ static irqreturn_t contexthub_irq_handler(int irq, void *data) ipc_hw_read_int_gen_reg(AP)); ipc->err_cnt[err]++; ipc_hw_clear_all_int_pend_reg(AP); - schedule_work(&ipc->debug_work); + enable_debug_workqueue(ipc, err); } return IRQ_HANDLED; } -#ifdef WDT_ENABLE +#ifdef CHUB_RESET_ENABLE static irqreturn_t contexthub_irq_wdt_handler(int irq, void *data) { struct contexthub_ipc_info *ipc = data; dev_info(ipc->dev, "%s calledn", __func__); - ipc->err_cnt[CHUB_ERR_NANOHUB_WDT]++; disable_irq_nosync(ipc->irq_wdt); - schedule_work(&ipc->debug_work); + enable_debug_workqueue(ipc, CHUB_ERR_NANOHUB_WDT); return IRQ_HANDLED; } @@ -1175,7 +1192,7 @@ static __init int contexthub_ipc_hw_init(struct platform_device *pdev, return ret; } -#ifdef WDT_ENABLE +#ifdef CHUB_RESET_ENABLE /* get wdt interrupt optionally */ chub->irq_wdt = irq_of_parse_and_map(node, 1); if (chub->irq_wdt > 0) { @@ -1328,6 +1345,27 @@ static struct device_attribute attributes[] = { __ATTR(reset, 0220, NULL, chub_reset), }; +#ifdef CONFIG_EXYNOS_ITMON +static int chub_itmon_notifier(struct notifier_block *nb, + unsigned long action, void *nb_data) +{ + struct contexthub_ipc_info *data = container_of(nb, struct contexthub_ipc_info, itmon_nb); + struct itmon_notifier *itmon_data = nb_data; + + if (itmon_data && itmon_data->master && + ((!strncmp("CM4_SHUB_CD", itmon_data->master, sizeof("CM4_SHUB_CD") - 1)) || + (!strncmp("CM4_SHUB_P", itmon_data->master, sizeof("CM4_SHUB_P") - 1)) || + (!strncmp("PDMA_SHUB", itmon_data->master, sizeof("PDMA_SHUB") - 1)))) { + dev_info(data->dev, "%s: chub(%s) itmon detected: action:%d!!\n", + __func__, itmon_data->master, action); + enable_debug_workqueue(data, CHUB_ERR_ITMON); + return NOTIFY_OK; + } + + return NOTIFY_DONE; +} +#endif + static int contexthub_ipc_probe(struct platform_device *pdev) { struct contexthub_ipc_info *chub; @@ -1374,7 +1412,9 @@ static int contexthub_ipc_probe(struct platform_device *pdev) #endif atomic_set(&chub->chub_status, CHUB_ST_NO_POWER); + atomic_set(&chub->in_reset, 0); chub->powermode = 0; /* updated by fw bl */ + chub->active_err = 0; chub->dev = &pdev->dev; platform_set_drvdata(pdev, chub); contexthub_config_init(chub); @@ -1386,13 +1426,16 @@ static int contexthub_ipc_probe(struct platform_device *pdev) attributes[i].attr.name); } - spin_lock_init(&chub->reset_lock); init_waitqueue_head(&chub->read_lock.event); init_waitqueue_head(&chub->chub_alive_lock.event); INIT_WORK(&chub->debug_work, handle_debug_work_func); #ifdef CONFIG_CONTEXTHUB_DEBUG INIT_WORK(&chub->utc_work, handle_utc_work_func); #endif +#ifdef CONFIG_EXYNOS_ITMON + chub->itmon_nb.notifier_call = chub_itmon_notifier; + itmon_notifier_chain_register(&chub->itmon_nb); +#endif dev_info(chub->dev, "%s with %s FW and %lu clk is done\n", __func__, chub->os_name, chub->clkrate); diff --git a/drivers/staging/nanohub/chub.h b/drivers/staging/nanohub/chub.h index aa080694b23d..4494a729b1d2 100644 --- a/drivers/staging/nanohub/chub.h +++ b/drivers/staging/nanohub/chub.h @@ -110,21 +110,25 @@ struct chub_alive { wait_queue_head_t event; }; -enum CHUB_ERR_TYPE { +enum chub_err_type { CHUB_ERR_NONE, CHUB_ERR_EVTQ_EMTPY, /* ap error */ CHUB_ERR_READ_FAIL, CHUB_ERR_WRITE_FAIL, CHUB_ERR_EVTQ_NO_HW_TRIGGER, CHUB_ERR_CHUB_NO_RESPONSE, - CHUB_ERR_COMMS_NACK, - CHUB_ERR_COMMS_BUSY, - CHUB_ERR_COMMS_UNKNOWN, - CHUB_ERR_COMMS, + CHUB_ERR_ITMON, + CHUB_ERR_NANOHUB, + CHUB_ERR_CHUB_MAX, CHUB_ERR_NANOHUB_FAULT, /* chub error */ CHUB_ERR_NANOHUB_ASSERT, CHUB_ERR_NANOHUB_ERROR, CHUB_ERR_NANOHUB_WDT, + CHUB_ERR_COMMS_NACK, + CHUB_ERR_COMMS_BUSY, + CHUB_ERR_COMMS_UNKNOWN, + CHUB_ERR_COMMS, + CHUB_ERR_COMMS_MAX, CHUB_ERR_MAX, }; @@ -161,17 +165,19 @@ struct contexthub_ipc_info { struct LOG_BUFFER *dd_log_buffer; unsigned long clkrate; atomic_t chub_status; + atomic_t in_reset; atomic_t irq1_apInt; atomic_t wakeup_chub; - spinlock_t reset_lock; int irq_mailbox; int irq_wdt; int err_cnt[CHUB_ERR_MAX]; + u32 active_err; int utc_run; int powermode; int block_reset; bool os_load; char os_name[MAX_FILE_LEN]; + struct notifier_block itmon_nb; #ifdef CONFIG_CONTEXTHUB_DEBUG struct work_struct utc_work; #endif diff --git a/drivers/staging/nanohub/chub_dbg.c b/drivers/staging/nanohub/chub_dbg.c index 84daddebb1b9..faf9ea2d8160 100644 --- a/drivers/staging/nanohub/chub_dbg.c +++ b/drivers/staging/nanohub/chub_dbg.c @@ -47,19 +47,39 @@ struct dbg_dump { static struct dbg_dump *p_dbg_dump; static struct reserved_mem *chub_rmem; -void chub_dbg_dump_gpr(struct contexthub_ipc_info *ipc) +void chub_dbg_print_hw(struct contexthub_ipc_info *ipc) { - int ret = contexthub_request(ipc); + if (p_dbg_dump) { + int i; + struct dbg_dump *p_dump = p_dbg_dump; - if (ret) { - pr_err("%s: fails to contexthub_request\n", __func__); - return; + dev_info(ipc->dev, "%s: err:%d, time:%lld\n", + __func__, p_dump->reason, p_dump->time); + + for (i = 0; i <= GPR_PC_INDEX; i++) + pr_info("gpr: R%d: 0x%x\n", i, p_dump->gpr[i]); + + print_hex_dump(KERN_CONT, "dram:", + DUMP_PREFIX_OFFSET, 16, 1, p_dbg_dump, sizeof(struct dbg_dump), false); +#if 0 + print_hex_dump(KERN_CONT, "sram:", + DUMP_PREFIX_OFFSET, 16, 1, &p_dbg_dump->sram[p_dbg_dump->sram_start], + ipc_get_chub_mem_size(), false); +#endif } +} +void chub_dbg_dump_gpr(struct contexthub_ipc_info *ipc) +{ if (p_dbg_dump) { int i; struct dbg_dump *p_dump = p_dbg_dump; + if (contexthub_request(ipc)) { + pr_err("%s: fails to contexthub_request\n", __func__); + return; + } + IPC_HW_WRITE_DUMPGPR_CTRL(ipc->chub_dumpgrp, 0x1); /* dump GPR */ for (i = 0; i <= GPR_PC_INDEX - 1; i++) @@ -68,9 +88,9 @@ void chub_dbg_dump_gpr(struct contexthub_ipc_info *ipc) i * 4); p_dump->gpr[GPR_PC_INDEX] = readl(ipc->chub_dumpgrp + REG_CHUB_DUMPGPR_PCR); - } - contexthub_release(ipc); + contexthub_release(ipc); + } } static u32 get_dbg_dump_size(void) @@ -110,41 +130,57 @@ out: } #endif -void chub_dbg_dump_hw(struct contexthub_ipc_info *ipc, int reason) +/* dump hw into dram (chub reserved mem) */ +void chub_dbg_dump_ram(struct contexthub_ipc_info *ipc, enum chub_err_type reason) { - int ret = contexthub_request(ipc); - - if (ret) { - pr_err("%s: fails to contexthub_request\n", __func__); - return; - } - if (p_dbg_dump) { + if (contexthub_request(ipc)) { + pr_err("%s: fails to contexthub_request\n", __func__); + return; + } + p_dbg_dump->time = sched_clock(); p_dbg_dump->reason = reason; - /* dump GPR */ - chub_dbg_dump_gpr(ipc); /* dump SRAM to reserved DRAM */ memcpy_fromio(&p_dbg_dump->sram[p_dbg_dump->sram_start], ipc_get_base(IPC_REG_DUMP), ipc_get_chub_mem_size()); + contexthub_release(ipc); + } +} + +void chub_dbg_dump_hw(struct contexthub_ipc_info *ipc, enum chub_err_type reason) +{ + dev_info(ipc->dev, "%s: reason:%d\n", __func__, reason); + chub_dbg_dump_gpr(ipc); + chub_dbg_dump_ram(ipc, reason); + + if (p_dbg_dump) { #ifdef CONFIG_CONTEXTHUB_DEBUG + if (contexthub_request(ipc)) { + pr_err("%s: fails to contexthub_request\n", __func__); + return; + } + /* write file */ - dev_dbg(ipc->dev, + dev_info(ipc->dev, "%s: write file: sram:%p, dram:%p(off:%d), size:%d\n", __func__, ipc_get_base(IPC_REG_DUMP), &p_dbg_dump->sram[p_dbg_dump->sram_start], p_dbg_dump->sram_start, ipc_get_chub_mem_size()); + chub_dbg_write_file(ipc->dev, "dram", p_dbg_dump, sizeof(struct dbg_dump)); + chub_dbg_write_file(ipc->dev, "sram", &p_dbg_dump->sram[p_dbg_dump->sram_start], ipc_get_chub_mem_size()); + + contexthub_release(ipc); #endif } - contexthub_release(ipc); } void chub_dbg_check_and_download_image(struct contexthub_ipc_info *ipc) @@ -277,10 +313,25 @@ char chub_utc_name[][SIZE_UTC_NAME] = { [IPC_DEBUG_UTC_CHECK_CPU_UTIL] = "utilization", [IPC_DEBUG_UTC_HEAP_DEBUG] = "heap", [IPC_DEBUG_UTC_HANG] = "hang", - [IPC_DEBUG_NANOHUB_CHUB_ALIVE] = "alive", }; -static ssize_t chub_utc_show(struct device *kobj, + +static ssize_t chub_alive_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int index = 0; + struct contexthub_ipc_info *ipc = dev_get_drvdata(dev); + int ret = contexthub_ipc_write_event(ipc, MAILBOX_EVT_CHUB_ALIVE); + + if (!ret) + index += sprintf(buf, "chub alive\n"); + else + index += sprintf(buf, "chub isn't alive\n"); + + return index; +} + +static ssize_t chub_utc_show(struct device *dev, struct device_attribute *attr, char *buf) { int i; @@ -305,19 +356,12 @@ static ssize_t chub_utc_store(struct device *dev, err = kstrtol(&buf[0], 10, &event); if (!err) { - if (event == IPC_DEBUG_NANOHUB_CHUB_ALIVE) - event = MAILBOX_EVT_CHUB_ALIVE; - - if (event != MAILBOX_EVT_CHUB_ALIVE) { - err = contexthub_request(ipc); - if (err) - pr_err("%s: fails to request contexthub. ret:%d\n", __func__, err); - } + err = contexthub_request(ipc); + if (err) + pr_err("%s: fails to request contexthub. ret:%d\n", __func__, err); contexthub_ipc_write_event(ipc, event); - if (event != MAILBOX_EVT_CHUB_ALIVE) - contexthub_release(ipc); - + contexthub_release(ipc); return count; } else { return 0; @@ -476,6 +520,7 @@ static struct device_attribute attributes[] = { __ATTR(dump_hw, 0220, NULL, chub_set_dump_hw_store), __ATTR(utc, 0664, chub_utc_show, chub_utc_store), __ATTR(ipc_test, 0220, NULL, chub_ipc_store), + __ATTR(alive, 0440, chub_alive_show, NULL), __ATTR(wakeup, 0220, NULL, chub_wakeup_store), }; diff --git a/drivers/staging/nanohub/chub_dbg.h b/drivers/staging/nanohub/chub_dbg.h index ad2061e39221..7d1038ee2d2b 100644 --- a/drivers/staging/nanohub/chub_dbg.h +++ b/drivers/staging/nanohub/chub_dbg.h @@ -23,7 +23,10 @@ enum dbg_dump_area { int chub_dbg_init(struct device *dev); void *chub_dbg_get_memory(enum dbg_dump_area area); -void chub_dbg_dump_hw(struct contexthub_ipc_info *ipc, int reason); +void chub_dbg_dump_hw(struct contexthub_ipc_info *ipc, enum chub_err_type reason); +void chub_dbg_dump_ram(struct contexthub_ipc_info *ipc, enum chub_err_type reason); +void chub_dbg_dump_gpr(struct contexthub_ipc_info *ipc); +void chub_dbg_print_hw(struct contexthub_ipc_info *ipc); void chub_dbg_dump_status(struct contexthub_ipc_info *ipc); void chub_dbg_check_and_download_image(struct contexthub_ipc_info *ipc); #endif /* __CHUB_DEBUG_H */ diff --git a/drivers/staging/nanohub/chub_ipc.c b/drivers/staging/nanohub/chub_ipc.c index 23c5d81fd18f..ae2202641183 100644 --- a/drivers/staging/nanohub/chub_ipc.c +++ b/drivers/staging/nanohub/chub_ipc.c @@ -300,7 +300,8 @@ static inline int ipc_io_data(enum ipc_data_list dir, u8 *buf, u16 length) else if (eq < dq) useful = dq - eq; else if (ipc_data->full) { - CSP_PRINTF_ERROR("%s is full\n", __func__); + CSP_PRINTF_ERROR("%s is full(eq:%d, dq:%d, f:%d, e:%d)\n", + __func__, ipc_data->eq, ipc_data->dq, ipc_data->full, ipc_data->empty); return -1; } else { useful = IPC_DATA_SIZE; @@ -313,8 +314,8 @@ static inline int ipc_io_data(enum ipc_data_list dir, u8 *buf, u16 length) /* check length */ if (length + sizeof(u16) > useful) { CSP_PRINTF_ERROR - ("%s: no buffer. len:%d, remain:%d, eq:%d, dq:%d\n", - __func__, length, useful, eq, dq); + ("%s: no buffer. len:%d, remain:%d eq:%d, dq:%d (eq:%d, dq:%d, f:%d, e:%d)\n", + __func__, length, useful, eq, dq, ipc_data->eq, ipc_data->dq, ipc_data->full, ipc_data->empty); return -1; } @@ -366,7 +367,8 @@ static inline int ipc_io_data(enum ipc_data_list dir, u8 *buf, u16 length) else if (eq < dq) useful = (IPC_DATA_SIZE - dq) + eq; else if (ipc_data->empty) { - CSP_PRINTF_ERROR("%s is empty\n", __func__); + CSP_PRINTF_ERROR("%s is empty (eq:%d, dq:%d, f:%d, e:%d)\n", + __func__, ipc_data->eq, ipc_data->dq, ipc_data->full, ipc_data->empty); return 0; } else { useful = IPC_DATA_SIZE; @@ -395,8 +397,9 @@ static inline int ipc_io_data(enum ipc_data_list dir, u8 *buf, u16 length) #endif if (useful < sizeof(u16) + size_to_read) { - CSP_PRINTF_ERROR("%s: no enought read size: useful:%d, read_to_size:%d,%d\n", - __func__, useful, size_to_read, sizeof(u16)); + CSP_PRINTF_ERROR("%s: no enough read size: useful:%d, read_to_size:%d,%d (eq:%d, dq:%d, f:%d, e:%d)\n", + __func__, useful, size_to_read, sizeof(u16), + ipc_data->eq, ipc_data->dq, ipc_data->full, ipc_data->empty); return 0; } diff --git a/drivers/staging/nanohub/chub_ipc.h b/drivers/staging/nanohub/chub_ipc.h index 26730030e476..74cf4d6caaac 100644 --- a/drivers/staging/nanohub/chub_ipc.h +++ b/drivers/staging/nanohub/chub_ipc.h @@ -186,7 +186,6 @@ enum ipc_debug_event { IPC_DEBUG_UTC_IPC_TEST_START, IPC_DEBUG_UTC_IPC_TEST_END, IPC_DEBUG_UTC_MAX, - IPC_DEBUG_NANOHUB_CHUB_ALIVE = IPC_DEBUG_UTC_MAX, IPC_DEBUG_NANOHUB_MAX, IPC_DEBUG_DUMP_STATUS, IPC_DEBUG_FLUSH_LOG, diff --git a/drivers/staging/nanohub/chub_log.c b/drivers/staging/nanohub/chub_log.c index 5144fb382de7..6ffbba7d8952 100644 --- a/drivers/staging/nanohub/chub_log.c +++ b/drivers/staging/nanohub/chub_log.c @@ -92,6 +92,16 @@ void log_flush(struct log_buffer_info *info) struct log_kernel_buffer *kernel_buffer = &info->kernel_buffer; unsigned int index_writer = buffer->index_writer; + /* check logbuf index dueto sram corruption */ + if ((buffer->index_reader >= ipc_get_offset(IPC_REG_LOG)) + || (buffer->index_writer >= ipc_get_offset(IPC_REG_LOG))) { + dev_err(info->dev, "%s(%d): offset is corrupted. index_writer=%u, index_reader=%u, size=%u-%u\n", + __func__, info->id, buffer->index_writer, buffer->index_reader, buffer->size, + ipc_get_offset(IPC_REG_LOG)); + + return; + } + if (buffer->index_reader == index_writer) return; @@ -335,6 +345,15 @@ static void log_dump(struct log_buffer_info *info, int err) struct LOG_BUFFER *buffer = info->log_buffer; u32 wrap_index = buffer->index_writer; + /* check logbuf index dueto sram corruption */ + if ((buffer->index_reader >= ipc_get_offset(IPC_REG_LOG)) + || (buffer->index_writer >= ipc_get_offset(IPC_REG_LOG))) { + dev_err(info->dev, "%s(%d): offset is corrupted. index_writer=%u, index_reader=%u, size=%u-%u\n", + __func__, info->id, buffer->index_writer, buffer->index_reader, buffer->size, + ipc_get_offset(IPC_REG_LOG)); + return; + } + snprintf(save_file_name, sizeof(save_file_name), "/data/nano-%02d-%02d-%06u.log", info->id, err, (u32)(sched_clock() / NSEC_PER_SEC)); diff --git a/drivers/staging/nanohub/comms.c b/drivers/staging/nanohub/comms.c index 59be58fc073d..3d6eff1c0203 100644 --- a/drivers/staging/nanohub/comms.c +++ b/drivers/staging/nanohub/comms.c @@ -345,8 +345,6 @@ static int get_reply(struct nanohub_data *data, struct nanohub_packet *response, ret = ERROR_NACK; else if (response->reason == CMD_COMMS_BUSY) ret = ERROR_BUSY; - else - pr_warn("nanohub: invalid reason %d\n", __func__, response->reason); } if (response->seq != seq) @@ -367,8 +365,6 @@ static int get_reply(struct nanohub_data *data, struct nanohub_packet *response, b[i + 24]); } ret = ERROR_NACK; - pr_warn("nanohub: invalid seq %d\n", __func__, - response->reason); } return ret; @@ -379,6 +375,12 @@ static int nanohub_comms_tx_rx(struct nanohub_data *data, uint32_t seq, uint8_t *rx, size_t rx_len) { int ret; + struct contexthub_ipc_info *ipc = data->pdata->mailbox_client; + + if (atomic_read(&ipc->in_reset)) { + dev_err(ipc->dev, "%s: chub reset in-progress\n", __func__); + return ERROR_BUSY; + } ret = data->comms.write(data, (uint8_t *)&pad->packet, packet_size, data->comms.timeout_write); @@ -419,6 +421,13 @@ int nanohub_comms_rx_retrans_boottime(struct nanohub_data *data, uint32_t cmd, uint32_t seq; struct timespec ts; s64 boottime; + struct contexthub_ipc_info *ipc = data->pdata->mailbox_client; + + if (atomic_read(&ipc->in_reset)) { + packet_free(pad); + dev_err(ipc->dev, "%s: chub reset in-progress\n", __func__); + return ERROR_BUSY; + } if (pad == NULL) return ERROR_NACK; -- 2.20.1