chub: add itmon notifier
authorBoojin Kim <boojin.kim@samsung.com>
Mon, 2 Jul 2018 12:40:59 +0000 (21:40 +0900)
committerSangwook Ju <sw.ju@samsung.com>
Tue, 3 Jul 2018 12:36:50 +0000 (21:36 +0900)
Change-Id: I3712e75bc92057d41f18b313b6ea60e5a8c910c9
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
drivers/staging/nanohub/chub.c
drivers/staging/nanohub/chub.h
drivers/staging/nanohub/chub_dbg.c
drivers/staging/nanohub/chub_dbg.h
drivers/staging/nanohub/chub_ipc.c
drivers/staging/nanohub/chub_ipc.h
drivers/staging/nanohub/chub_log.c
drivers/staging/nanohub/comms.c

index 58965bfc463da922d3132329047e4fc8395c7031..6bb91d53b125fd95066909b7d0304c97f5642e99 100644 (file)
@@ -29,6 +29,9 @@
 #include <linux/rtc.h>
 #include <linux/clk.h>
 #include <linux/timekeeping.h>
+#ifdef CONFIG_EXYNOS_ITMON
+#include <soc/samsung/exynos-itmon.h>
+#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);
index aa080694b23d43dc0376e016c62829c9294d0f07..4494a729b1d258c46923287471000b79cfc7405b 100644 (file)
@@ -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
index 84daddebb1b9f9ccc12a40cdcd30372f7cfbc0ec..faf9ea2d8160aeca590324797231fed5ae6c841a 100644 (file)
@@ -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),
 };
 
index ad2061e3922153975124cdd3d2592eb57d9d982a..7d1038ee2d2b55ab71d91e7927eebbf40bf534c4 100644 (file)
@@ -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 */
index 23c5d81fd18fc3eb357c59016f5aabfee9617185..ae220264118321f597e5425b2c7217da77fe4605 100644 (file)
@@ -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;
                }
 
index 26730030e4760ff0516fc2f45dda65fc28c56817..74cf4d6caaacb5a0928c975eb7456e7a7c66d50e 100644 (file)
@@ -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,
index 5144fb382de7372912e36dd4a76ad8e638f3c866..6ffbba7d8952bf6303e252deff60a864633d6d3c 100644 (file)
@@ -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));
index 59be58fc073dbda99ac29276020ef2adc8ca50d6..3d6eff1c020342ce1709cd49a8f02b7784cd0478 100644 (file)
@@ -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;