[ERD][APR-103] [COMMON]chub: support runtimelog
authorBoojin Kim <boojin.kim@samsung.com>
Thu, 20 Dec 2018 04:14:38 +0000 (13:14 +0900)
committerhskang <hs1218.kang@samsung.com>
Sun, 21 Apr 2019 09:09:32 +0000 (18:09 +0900)
Change-Id: I4f67cdc83e86f9994e233dceb517ae00161343f0
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
drivers/staging/nanohub/Kconfig
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/chub_log.h
drivers/staging/nanohub/main.c

index d7cc1155f5f262046ed771f1798d4af099c5af88..2934dccae81db32592436402e062ecc7086a07fb 100644 (file)
@@ -53,4 +53,10 @@ config CONTEXTHUB_DEBUG
        help
          Eanble nanohub device debug message
 
+config CONTEXTHUB_DEBUG_MODE
+       bool "Contexthub reset brings kernel panic"
+       default N
+       help
+         Eanble kernel panic with contexthub FW error
+
 endif # NANOHUB
index e58c8679fe5b26215a9c1c13bfb902535fc87421..4364779ba75fe80ea7af32f028a25915a5819885 100644 (file)
@@ -203,10 +203,10 @@ static int contexthub_ipc_drv_init(struct contexthub_ipc_info *chub)
 
        /* init debug-log */
        /* HACK for clang */
-       chub->ipc_map->logbuf.eq = 0;
-       chub->ipc_map->logbuf.dq = 0;
+       chub->ipc_map->logbuf.logbuf.eq = 0;
+       chub->ipc_map->logbuf.logbuf.dq = 0;
        chub->fw_log = log_register_buffer(chub_dev, 0,
-                                          (void *)&chub->ipc_map->logbuf,
+                                          (void *)&chub->ipc_map->logbuf.logbuf,
                                           "fw", 1);
        if (!chub->fw_log)
                return -EINVAL;
@@ -231,7 +231,7 @@ static int contexthub_ipc_drv_init(struct contexthub_ipc_info *chub)
        chub->dd_log =
            log_register_buffer(chub_dev, 1, chub->dd_log_buffer, "dd", 0);
 #endif
-       ret = chub_dbg_init(chub);
+       ret = chub_dbg_init(chub, chub->chub_rt_log.buffer, chub->chub_rt_log.buffer_size);
        if (ret)
                dev_err(chub_dev, "%s: fails. ret:%d\n", __func__, ret);
 
@@ -405,7 +405,6 @@ static void contexthub_select_os(struct contexthub_ipc_info *ipc)
        dev_info(ipc->dev, "%s selected os_name = %s\n", __func__, ipc->os_name);
 
        log_flush_all();
-
        contexthub_download_image(ipc, IPC_REG_OS);
        ipc_hw_write_shared_reg(AP, ipc->os_load, SR_BOOT_MODE);
        ipc_write_val(AP, 99);
@@ -445,12 +444,31 @@ static void handle_debug_work_func(struct work_struct *work)
        for (i = 0; i < CHUB_ERR_MAX; i++) {
                if (ipc->cur_err & (1 << i)) {
                        dev_info(ipc->dev, "%s: loop: err:%d, cur_err:0x%x\n", __func__, i, ipc->cur_err);
-                       handle_debug_work(ipc, i);
                        ipc->cur_err &= ~(1 << i);
+                       handle_debug_work(ipc, i);
                }
        }
 }
 
+static void print_rtlog(struct contexthub_ipc_info *ipc)
+{
+       if (contexthub_get_token(ipc)) {
+               pr_info("%s: fails to get token\n", __func__);
+               atomic_set(&ipc->log_work_active, 0);
+               return;
+       }
+       ipc_logbuf_outprint(&ipc->chub_rt_log);
+       contexthub_put_token(ipc);
+}
+
+static void handle_log_work_func(struct work_struct *work)
+{
+       struct contexthub_ipc_info *ipc =
+           container_of(work, struct contexthub_ipc_info, debug_work);
+
+       print_rtlog(ipc);
+}
+
 static inline void clear_err_cnt(struct contexthub_ipc_info *ipc, enum chub_err_type err)
 {
        if (ipc->err_cnt[err])
@@ -568,6 +586,7 @@ static int contexthub_hw_reset(struct contexthub_ipc_info *ipc,
        atomic_set(&ipc->wakeup_chub, CHUB_OFF);
        atomic_set(&ipc->irq1_apInt, C2A_OFF);
        atomic_set(&ipc->read_lock.cnt, 0x0);
+       atomic_set(&ipc->log_work_active, 0);
 
        /* chub err init */
        for (i = 0; i < CHUB_ERR_MAX; i++) {
@@ -754,7 +773,7 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
        case MAILBOX_EVT_POWER_ON:
                ret = contexthub_hw_reset(ipc, event);
                if (!ret)
-                       log_schedule_flush_all();
+                       log_flush_all();
                break;
        case MAILBOX_EVT_RESET:
                if (atomic_read(&ipc->chub_status) == CHUB_ST_SHUTDOWN) {
@@ -822,8 +841,14 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
                        dev_err(ipc->dev,
                                "%s : chub isn't alive, should be reset. status:%d\n",
                                __func__, atomic_read(&ipc->chub_status));
-                       atomic_set(&ipc->chub_status, CHUB_ST_NO_RESPONSE);
-                       contexthub_handle_debug(ipc, CHUB_ERR_CHUB_NO_RESPONSE, 0);
+                       if (atomic_read(&ipc->chub_status) == CHUB_ST_POWER_ON) {
+                               atomic_set(&ipc->chub_status, CHUB_ST_NO_RESPONSE);
+                               /* hack don't make panic with chub poweron */
+                               contexthub_reset(ipc, 1, CHUB_ERR_NONE);
+                       } else {
+                               atomic_set(&ipc->chub_status, CHUB_ST_NO_RESPONSE);
+                               contexthub_handle_debug(ipc, CHUB_ERR_CHUB_NO_RESPONSE, 0);
+                       }
                        ret = -EINVAL;
                }
                break;
@@ -855,6 +880,9 @@ int contexthub_ipc_write_event(struct contexthub_ipc_info *ipc,
 
                /* handle ipc */
                switch (event) {
+               case MAILBOX_EVT_RT_LOGLEVEL:
+                       ipc_logbuf_loglevel(ipc->chub_rt_log.loglevel, 1);
+                       break;
                case MAILBOX_EVT_ERASE_SHARED:
                        memset(ipc_get_base(IPC_REG_SHARED), 0, ipc_get_offset(IPC_REG_SHARED));
                        break;
@@ -945,6 +973,10 @@ int contexthub_poweron(struct contexthub_ipc_info *ipc)
                                                                 msecs_to_jiffies(WAIT_TIMEOUT_MS));
                                dev_info(dev, "%s: multi-os poweron %s, ret:%d\n", __func__,
                                        atomic_read(&ipc->chub_status) == CHUB_ST_RUN ? "success" : "fails",  ret);
+#ifdef CONFIG_CONTEXTHUB_DEBUG_MODE
+                               ipc->chub_rt_log.loglevel = 1;
+#endif
+                               contexthub_ipc_write_event(ipc, MAILBOX_EVT_RT_LOGLEVEL);
                        }
                }
        } else {
@@ -991,14 +1023,14 @@ out:
        return ret;
 }
 
-int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump)
+int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, enum chub_err_type err)
 {
        int ret;
        int trycnt = 0;
 
-       dev_info(ipc->dev, "%s: force:%d, status:%d, in-reset:%d, dump:%d, user:%d\n",
+       dev_info(ipc->dev, "%s: force:%d, status:%d, in-reset:%d, err:%d, user:%d\n",
                __func__, force_load, atomic_read(&ipc->chub_status),
-               atomic_read(&ipc->in_reset), dump, atomic_read(&ipc->in_use_ipc));
+               atomic_read(&ipc->in_reset), err, atomic_read(&ipc->in_use_ipc));
        mutex_lock(&reset_mutex);
        if (!force_load && (atomic_read(&ipc->chub_status) == CHUB_ST_RUN)) {
                mutex_unlock(&reset_mutex);
@@ -1020,10 +1052,12 @@ int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump)
                        __func__, atomic_read(&ipc->in_use_ipc));
        } while (atomic_read(&ipc->in_use_ipc));
 
-       if (dump) {
-               ipc->err_cnt[CHUB_ERR_NONE] = dump;
-               chub_dbg_dump_hw(ipc, ipc->cur_err);
-       }
+       chub_dbg_dump_hw(ipc, err);
+
+#ifdef CONFIG_CONTEXTHUB_DEBUG_MODE
+       if (err)
+               panic("%s: %d, %d\n", __func__, err, ipc->cur_err);
+#endif
 
        dev_info(ipc->dev, "%s: start reset status:%d\n", __func__, atomic_read(&ipc->chub_status));
        if (!ipc->block_reset) {
@@ -1118,6 +1152,9 @@ static void handle_irq(struct contexthub_ipc_info *ipc, enum irq_evt_chub evt)
        case IRQ_EVT_C2A_INTCLR:
                atomic_set(&ipc->irq1_apInt, C2A_OFF);
                break;
+       case IRQ_EVT_C2A_LOG:
+               print_rtlog(ipc);
+               return;
        default:
                if (evt < IRQ_EVT_CH_MAX) {
                        int lock;
@@ -1135,6 +1172,8 @@ static void handle_irq(struct contexthub_ipc_info *ipc, enum irq_evt_chub evt)
                }
                break;
        };
+       if (ipc->chub_rt_log.loglevel)
+               print_rtlog(ipc);
 }
 
 static irqreturn_t contexthub_irq_handler(int irq, void *data)
@@ -1481,7 +1520,7 @@ static ssize_t chub_reset(struct device *dev,
                                const char *buf, size_t count)
 {
        struct contexthub_ipc_info *ipc = dev_get_drvdata(dev);
-       int ret = contexthub_reset(ipc, 1, 1);
+       int ret = contexthub_reset(ipc, 1, CHUB_ERR_NONE);
 
        return ret < 0 ? ret : count;
 }
@@ -1556,6 +1595,7 @@ static int contexthub_ipc_probe(struct platform_device *pdev)
        chub->data->irq1 = IRQ_EVT_A2C_WAKEUP;
        chub->data->irq2 = 0;
 #endif
+       chub->chub_rt_log.loglevel = 0;
        atomic_set(&chub->in_use_ipc, 0);
        atomic_set(&chub->chub_status, CHUB_ST_NO_POWER);
        atomic_set(&chub->in_reset, 0);
@@ -1577,11 +1617,21 @@ static int contexthub_ipc_probe(struct platform_device *pdev)
        init_waitqueue_head(&chub->read_lock.event);
        init_waitqueue_head(&chub->chub_alive_lock.event);
        INIT_WORK(&chub->debug_work, handle_debug_work_func);
+       INIT_WORK(&chub->log_work, handle_log_work_func);
 #ifdef CONFIG_EXYNOS_ITMON
        chub->itmon_nb.notifier_call = chub_itmon_notifier;
        itmon_notifier_chain_register(&chub->itmon_nb);
 #endif
 
+       /* init fw runtime log */
+       chub->chub_rt_log.buffer = vzalloc(SZ_512K);
+       if (!chub->chub_rt_log.buffer) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       chub->chub_rt_log.buffer_size = SZ_512K;
+       chub->chub_rt_log.write_index = 0;
+
        dev_info(chub->dev, "%s with %s FW and %lu clk is done\n",
                                        __func__, chub->os_name, chub->clkrate);
        return 0;
index b5d5ac2868486f0498b2f5a01999f4556547ae46..b6aab7a13dd57255d1efc127a00ccd58f4a0d5bb 100644 (file)
@@ -87,6 +87,7 @@ enum mailbox_event {
        MAILBOX_EVT_CHUB_ALIVE,
        MAILBOX_EVT_SHUTDOWN,
        MAILBOX_EVT_RESET,
+       MAILBOX_EVT_RT_LOGLEVEL,
        MAILBOX_EVT_MAX,
 };
 
@@ -159,6 +160,7 @@ struct contexthub_ipc_info {
        struct nanohub_platform_data *pdata;
        wait_queue_head_t wakeup_wait;
        struct work_struct debug_work;
+       struct work_struct log_work;
        struct read_wait read_lock;
 #ifdef USE_IPC_BUF
        u8 rxbuf[PACKET_SIZE_MAX];
@@ -177,7 +179,9 @@ struct contexthub_ipc_info {
        struct log_buffer_info *fw_log;
        struct log_buffer_info *dd_log;
        struct LOG_BUFFER *dd_log_buffer;
+       struct runtimelog_buf chub_rt_log;
        unsigned long clkrate;
+       atomic_t log_work_active;
        atomic_t chub_status;
        atomic_t in_reset;
        atomic_t irq1_apInt;
@@ -299,7 +303,7 @@ int contexthub_ipc_write(struct contexthub_ipc_info *ipc,
                                uint8_t *tx, int length, int timeout);
 int contexthub_poweron(struct contexthub_ipc_info *data);
 int contexthub_download_image(struct contexthub_ipc_info *data, enum ipc_region reg);
-int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, int dump_id);
+int contexthub_reset(struct contexthub_ipc_info *ipc, bool force_load, enum chub_err_type err);
 int contexthub_wakeup(struct contexthub_ipc_info *data, int evt);
 int contexthub_request(struct contexthub_ipc_info *ipc);
 void contexthub_release(struct contexthub_ipc_info *ipc);
index 566563a79d870aa15e8f5b4b88e1b118693b10d8..0c9e57ea76eb39a903980f681504030fbb8abade 100644 (file)
@@ -62,6 +62,9 @@ static void chub_dbg_dump_gpr(struct contexthub_ipc_info *ipc)
                                  i * 4);
                p_dump->gpr[GPR_PC_INDEX] =
                    readl(ipc->chub_dumpgpr + REG_CHUB_DUMPGPR_PCR);
+
+               for (i = 0; i <= GPR_PC_INDEX; i++)
+                       dev_info(ipc->dev, "%s: %d: 0x%x\n", __func__, i, p_dump->gpr[i]);
        }
 }
 
@@ -148,6 +151,7 @@ static void chub_dbg_dump_status(struct contexthub_ipc_info *ipc)
 #ifdef USE_FW_DUMP
        contexthub_ipc_write_event(ipc, MAILBOX_EVT_DUMP_STATUS);
 #endif
+       ipc_dump();
        log_flush(ipc->fw_log);
 }
 
@@ -232,9 +236,6 @@ static ssize_t chub_bin_sram_read(struct file *file, struct kobject *kobj,
                                  struct bin_attribute *battr, char *buf,
                                  loff_t off, size_t size)
 {
-       struct device *dev = kobj_to_dev(kobj);
-
-       dev_info(dev, "%s(%p: %lld, %zu)\n", __func__, battr->private, off, size);
        memcpy_fromio(buf, battr->private + off, size);
        return size;
 }
@@ -258,14 +259,24 @@ static ssize_t chub_bin_dumped_sram_read(struct file *file, struct kobject *kobj
        return size;
 }
 
+static ssize_t chub_bin_logbuf_dram_read(struct file *file, struct kobject *kobj,
+                                 struct bin_attribute *battr, char *buf,
+                                 loff_t off, size_t size)
+{
+       memcpy(buf, battr->private + off, size);
+       return size;
+}
+
 static BIN_ATTR_RO(chub_bin_sram, 0);
 static BIN_ATTR_RO(chub_bin_dram, 0);
 static BIN_ATTR_RO(chub_bin_dumped_sram, 0);
+static BIN_ATTR_RO(chub_bin_logbuf_dram, 0);
 
 static struct bin_attribute *chub_bin_attrs[] = {
        &bin_attr_chub_bin_sram,
        &bin_attr_chub_bin_dram,
        &bin_attr_chub_bin_dumped_sram,
+       &bin_attr_chub_bin_logbuf_dram,
 };
 
 #define SIZE_UTC_NAME (16)
@@ -469,6 +480,40 @@ static ssize_t chub_wakeup_store(struct device *dev,
        return ret ? ret : count;
 }
 
+static ssize_t chub_loglevel_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct contexthub_ipc_info *ipc = dev_get_drvdata(dev);
+       enum ipc_fw_loglevel loglevel = ipc->chub_rt_log.loglevel;
+       int index = 0;
+
+       dev_info(dev, "%s: %d\n", __func__, loglevel);
+       index += sprintf(buf, "%d:%s, %d:%s, %d:%s\n", CHUB_RT_LOG_OFF, "off", CHUB_RT_LOG_DUMP, "dump-only", CHUB_RT_LOG_DUMP_PRT, "dump-prt");
+       index += sprintf(buf + index, "cur-loglevel: %d: %s\n", loglevel, !loglevel ? "off" : ((loglevel == CHUB_RT_LOG_DUMP) ? "dump-only" : "dump-prt"));
+
+       return index;
+}
+
+static ssize_t chub_loglevel_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct contexthub_ipc_info *ipc = dev_get_drvdata(dev);
+       long event;
+       int ret;
+
+       ret = kstrtol(&buf[0], 10, &event);
+       if (ret)
+               return ret;
+
+       ipc->chub_rt_log.loglevel = (enum ipc_fw_loglevel)event;
+       dev_info(dev, "%s: %d->%d\n", __func__, event, ipc->chub_rt_log.loglevel);
+       contexthub_ipc_write_event(ipc, MAILBOX_EVT_RT_LOGLEVEL);
+
+       return ret ? ret : count;
+}
+
+
 static struct device_attribute attributes[] = {
        __ATTR(get_gpr, 0440, chub_get_gpr_show, NULL),
        __ATTR(dump_status, 0220, NULL, chub_get_dump_status_store),
@@ -477,6 +522,7 @@ static struct device_attribute attributes[] = {
        __ATTR(ipc_test, 0220, NULL, chub_ipc_store),
        __ATTR(alive, 0440, chub_alive_show, NULL),
        __ATTR(wakeup, 0220, NULL, chub_wakeup_store),
+       __ATTR(loglevel, 0664, chub_loglevel_show, chub_loglevel_store),
 };
 
 void *chub_dbg_get_memory(enum dbg_dump_area area)
@@ -501,7 +547,7 @@ void *chub_dbg_get_memory(enum dbg_dump_area area)
        return addr;
 }
 
-int chub_dbg_init(struct contexthub_ipc_info *chub)
+int chub_dbg_init(struct contexthub_ipc_info *chub, void *kernel_logbuf, int kernel_logbuf_size)
 {
        int i, ret = 0;
        enum dbg_dump_area area;
@@ -529,6 +575,9 @@ int chub_dbg_init(struct contexthub_ipc_info *chub)
        bin_attr_chub_bin_sram.size = ipc_get_chub_mem_size();
        bin_attr_chub_bin_sram.private = ipc_get_base(IPC_REG_DUMP);
 
+       bin_attr_chub_bin_logbuf_dram.size = kernel_logbuf_size;
+       bin_attr_chub_bin_logbuf_dram.private = kernel_logbuf;
+
        if (chub_rmem->size < get_dbg_dump_size())
                dev_err(dev,
                        "rmem size (%u) should be bigger than dump size(%u)\n",
index 27273a5aa9a573e5e8b04312d3c3020d97d26214..12976e7bf17f7ecd46d2e2c5e31c2e71083ad377 100644 (file)
@@ -21,7 +21,7 @@ enum dbg_dump_area {
        DBG_AREA_MAX
 };
 
-int chub_dbg_init(struct contexthub_ipc_info *chub);
+int chub_dbg_init(struct contexthub_ipc_info *chub, void *logbuf, int logbuf_size);
 void *chub_dbg_get_memory(enum dbg_dump_area area);
 void chub_dbg_dump_hw(struct contexthub_ipc_info *ipc, enum chub_err_type reason);
 void chub_dbg_print_hw(struct contexthub_ipc_info *ipc);
index 4be436a39014dda7af4bb0cbc210ada99086a83d..d640c3b3f3863a1d708c8368b77b9e393a62ba0e 100644 (file)
@@ -246,9 +246,15 @@ void *ipc_get_chub_map(void)
        ipc_addr[IPC_REG_RAM].offset = map->ram_end - map->ram_start;
        ipc_addr[IPC_REG_DUMP].offset = map->dump_end - map->dump_start;
 
+       if (ipc_get_offset(IPC_REG_IPC) < sizeof(struct ipc_map_area)) {
+               CSP_PRINTF_INFO
+                       ("%s: fails. ipc size (0x%x) should be increase to 0x%x\n",
+                       __func__, ipc_get_offset(IPC_REG_IPC), sizeof(struct ipc_map_area));
+               return 0;
+       }
+
        ipc_map = ipc_addr[IPC_REG_IPC].base;
-       ipc_map->logbuf.size =
-           ipc_addr[IPC_REG_IPC].offset - sizeof(struct ipc_map_area) - CHUB_PERSISTBUF_SIZE;
+       ipc_map->logbuf.size = LOGBUF_TOTAL_SIZE;
        strcpy(&ipc_map->magic[0], CHUB_IPC_MAGIC);
 
        ipc_addr[IPC_REG_IPC_EVT_A2C].base = &ipc_map->evt[IPC_EVT_A2C].data;
@@ -266,17 +272,14 @@ void *ipc_get_chub_map(void)
        ipc_addr[IPC_REG_IPC_C2A].offset = sizeof(struct ipc_buf);
        ipc_addr[IPC_REG_IPC_A2C].offset = sizeof(struct ipc_buf);
 
-       ipc_addr[IPC_REG_LOG].base = &ipc_map->logbuf.buf;
-       ipc_addr[IPC_REG_LOG].offset = ipc_map->logbuf.size;
-       ipc_addr[IPC_REG_PERSISTBUF].base = ipc_addr[IPC_REG_LOG].base + ipc_addr[IPC_REG_LOG].offset;
+       /* for rawlevel log */
+       ipc_map->logbuf.size = LOGBUF_TOTAL_SIZE;
+       ipc_map->logbuf.logbuf.size = ipc_addr[IPC_REG_IPC].offset - sizeof(struct ipc_map_area);
+       /* for runtime log */
+       ipc_addr[IPC_REG_LOG].base = &ipc_map->logbuf.log;
+       ipc_addr[IPC_REG_LOG].offset = ipc_map->logbuf.size + ipc_map->logbuf.logbuf.size;
+       ipc_addr[IPC_REG_PERSISTBUF].base = &ipc_map->persist;
        ipc_addr[IPC_REG_PERSISTBUF].offset = CHUB_PERSISTBUF_SIZE;
-
-       if (((u32)ipc_addr[IPC_REG_PERSISTBUF].base + ipc_addr[IPC_REG_PERSISTBUF].offset) >
-                       ((u32)ipc_addr[IPC_REG_IPC].base + ipc_addr[IPC_REG_IPC].offset))
-               CSP_PRINTF_INFO("%s: %s: wrong persistbuf addr:%p, %d, ipc_end:0x%x\n",
-                       NAME_PREFIX, __func__,
-                       ipc_addr[IPC_REG_PERSISTBUF].base, ipc_addr[IPC_REG_PERSISTBUF].offset, map->ipc_end);
-
        ipc_addr[IPC_REG_IPC_SENSORINFO].base = &ipc_map->sensormap;
        ipc_addr[IPC_REG_IPC_SENSORINFO].offset = sizeof(u8) * SENSOR_TYPE_MAX;
 #ifdef SEOS
@@ -284,6 +287,15 @@ void *ipc_get_chub_map(void)
                CSP_PRINTF_INFO("%s: ipc set sensormap and maic: :%p\n", __func__, &ipc_map->sensormap);
                memset(&ipc_map->sensormap, 0, sizeof(struct sensor_map));
                strcpy(&ipc_map->sensormap.magic[0], SENSORMAP_MAGIC);
+               /* clear logbuf with 1st booting */
+               ipc_map->logbuf.eq = 0;
+               ipc_map->logbuf.dq = 0;
+               ipc_map->logbuf.full = 0;
+               ipc_map->logbuf.dbg_full_cnt = 0;
+               ipc_map->logbuf.loglevel = 0;
+               ipc_map->logbuf.logbuf.eq = 0;
+               ipc_map->logbuf.logbuf.dq = 0;
+               ipc_map->logbuf.logbuf.full = 0;
        }
 #endif
 
@@ -298,15 +310,16 @@ void *ipc_get_chub_map(void)
             ipc_addr[IPC_REG_DUMP].base, ipc_addr[IPC_REG_DUMP].offset);
 
        CSP_PRINTF_INFO
-               ("%s: ipc_map information\n ipc(%p %d)\n data_c2a(%p %d)\n data_a2c(%p %d)\n evt_c2a(%p %d)\n evt_a2c(%p %d)\n sensormap(%p %d) \n log(%p %d)\n persistbuf(%p %d)\n",
-               NAME_PREFIX, ipc_get_base(IPC_REG_IPC), ipc_get_offset(IPC_REG_IPC),
+               ("%s: ipc_map information (0x%x/0x%x)\n ipc(%p %d)\n data_c2a(%p %d)\n data_a2c(%p %d)\n evt_c2a(%p %d)\n evt_a2c(%p %d)\n sensormap(%p %d) \n persistbuf(%p %d)\n log(ch:%p %d / raw:%p %d)\n ",
+               NAME_PREFIX, sizeof(struct ipc_map_area), ipc_get_offset(IPC_REG_IPC),
+               ipc_get_base(IPC_REG_IPC), ipc_get_offset(IPC_REG_IPC),
                ipc_get_base(IPC_REG_IPC_C2A), ipc_get_offset(IPC_REG_IPC_C2A),
                ipc_get_base(IPC_REG_IPC_A2C), ipc_get_offset(IPC_REG_IPC_A2C),
                ipc_get_base(IPC_REG_IPC_EVT_C2A), ipc_get_offset(IPC_REG_IPC_EVT_C2A),
                ipc_get_base(IPC_REG_IPC_EVT_A2C), ipc_get_offset(IPC_REG_IPC_EVT_A2C),
                ipc_get_base(IPC_REG_IPC_SENSORINFO), ipc_get_offset(IPC_REG_IPC_SENSORINFO),
-               ipc_get_base(IPC_REG_LOG), ipc_get_offset(IPC_REG_LOG),
-               ipc_get_base(IPC_REG_PERSISTBUF), ipc_get_offset(IPC_REG_PERSISTBUF));
+               ipc_get_base(IPC_REG_PERSISTBUF), ipc_get_offset(IPC_REG_PERSISTBUF),
+               ipc_get_base(IPC_REG_LOG), ipc_map->logbuf.size, ipc_map->logbuf.logbuf.buf, ipc_map->logbuf.logbuf.size);
 
 #ifndef USE_IPC_BUF
        CSP_PRINTF_INFO
@@ -651,8 +664,11 @@ static void ipc_print_logbuf(void)
 {
        struct ipc_logbuf *logbuf = &ipc_map->logbuf;
 
-       CSP_PRINTF_INFO("%s: token:%d, eq:%d, dq:%d, size:%d, full:%d\n",
-               NAME_PREFIX, logbuf->token, logbuf->eq, logbuf->dq, logbuf->size, logbuf->full);
+       CSP_PRINTF_INFO("%s: channel: eq:%d, dq:%d, size:%d, full:%d, dbg_full_cnt:%d, err:%d, fw:%lld, ap:%lld\n",
+               NAME_PREFIX, logbuf->eq, logbuf->dq, logbuf->size, logbuf->full, logbuf->dbg_full_cnt,
+               logbuf->errcnt, logbuf->fw_num, logbuf->ap_num);
+       CSP_PRINTF_INFO("%s: raw: eq:%d, dq:%d, size:%d, full:%d\n",
+               NAME_PREFIX, logbuf->logbuf.eq, logbuf->logbuf.dq, logbuf->logbuf.size, logbuf->logbuf.full);
 }
 
 int ipc_check_reset_valid()
@@ -703,7 +719,6 @@ void ipc_init(void)
        }
 
        ipc_hw_clear_all_int_pend_reg(AP);
-
        for (j = 0; j < IPC_EVT_MAX; j++) {
                ipc_map->evt[j].ctrl.dq = 0;
                ipc_map->evt[j].ctrl.eq = 0;
@@ -716,6 +731,10 @@ void ipc_init(void)
                        ipc_map->evt[j].data[i].irq = IRQ_EVT_INVAL;
                }
        }
+       ipc_map->logbuf.dbg_full_cnt = 0;
+       ipc_map->logbuf.errcnt= 0;
+       ipc_map->logbuf.fw_num = 0;
+       ipc_map->logbuf.ap_num = 0;
 }
 
 /* evt functions */
@@ -754,6 +773,70 @@ struct ipc_evt_buf *ipc_get_evt(enum ipc_evt_list evtq)
 #define EVT_WAIT_TIME (5)
 #define MAX_TRY_CNT (5)
 
+/* ipc_add_evt without lock and print */
+int ipc_add_evt_in_critical(enum ipc_evt_list evtq, enum irq_evt_chub evt)
+{
+       struct ipc_evt *ipc_evt = &ipc_map->evt[evtq];
+       enum ipc_owner owner = (evtq < IPC_EVT_AP_MAX) ? AP : IPC_OWN_MAX;
+       struct ipc_evt_buf *cur_evt = NULL;
+       int trycnt = 0;
+       u32 pending;
+
+       if (!ipc_evt || (owner != AP)) {
+               return -1;
+       }
+
+retry:
+       if (!__raw_readl(&ipc_evt->ctrl.full)) {
+               cur_evt = &ipc_evt->data[ipc_evt->ctrl.eq];
+               if (!cur_evt) {
+                       return -1;
+               }
+
+               /* wait pending clear on irq pend */
+               pending = ipc_hw_read_gen_int_status_reg(AP, ipc_evt->ctrl.irq);
+               if (pending) {
+            /* don't sleep on ap */
+                       do {
+                               busywait(EVT_WAIT_TIME);
+                       } while (ipc_hw_read_gen_int_status_reg(AP, ipc_evt->ctrl.irq) && (trycnt++ < MAX_TRY_CNT));
+
+                       if (ipc_hw_read_gen_int_status_reg(AP, ipc_evt->ctrl.irq)) {
+                               return -1;
+                       }
+               }
+               cur_evt->evt = evt;
+               cur_evt->status = IPC_EVT_EQ;
+               cur_evt->irq = ipc_evt->ctrl.irq;
+               ipc_evt->ctrl.eq = EVT_Q_INT(ipc_evt->ctrl.eq + 1);
+               ipc_evt->ctrl.irq = IRQ_EVT_IDX_INT(ipc_evt->ctrl.irq + 1);
+               if (ipc_evt->ctrl.eq == __raw_readl(&ipc_evt->ctrl.dq))
+                       __raw_writel(1, &ipc_evt->ctrl.full);
+       } else {
+               do {
+                       busywait(EVT_WAIT_TIME);
+               } while (ipc_evt->ctrl.full && (trycnt++ < MAX_TRY_CNT));
+
+               if (!__raw_readl(&ipc_evt->ctrl.full)) {
+                       goto retry;
+               } else {
+                       ipc_dump();
+                       return -1;
+               }
+       }
+
+       if (owner != IPC_OWN_MAX) {
+#if defined(AP_IPC)
+               ipc_write_val(AP, sched_clock());
+#endif
+               if (cur_evt)
+                       ipc_hw_gen_interrupt(owner, cur_evt->irq);
+               else
+                       return -1;
+       }
+       return 0;
+}
+
 int ipc_add_evt(enum ipc_evt_list evtq, enum irq_evt_chub evt)
 {
        struct ipc_evt *ipc_evt = &ipc_map->evt[evtq];
@@ -812,7 +895,7 @@ retry:
 
                if (!__raw_readl(&ipc_evt->ctrl.full)) {
                        CSP_PRINTF_INFO("%s: %s: evt %d during %d ms is full\n",
-                                       NAME_PREFIX, __func__, evt, EVT_WAIT_TIME * trycnt);
+                               NAME_PREFIX, __func__, evt, EVT_WAIT_TIME * trycnt);
                        goto retry;
                } else {
                        CSP_PRINTF_ERROR("%s: %s: fail to add evt by full\n", NAME_PREFIX, __func__);
@@ -872,39 +955,151 @@ void ipc_dump(void)
        ipc_print_logbuf();
 }
 
-u32 ipc_logbuf_get_token(void)
+#ifdef CHUB_IPC
+void ipc_logbuf_put_with_char(char ch)
 {
-       __raw_writel(ipc_map->logbuf.token + 1, &ipc_map->logbuf.token);
+       if (ipc_map) {
+               struct logbuf_raw *logbuf = &ipc_map->logbuf.logbuf;
+
+               if (logbuf->size) {
+                       char *buf = (char *)&logbuf->buf[0];
 
-       return __raw_readl(&ipc_map->logbuf.token);
+                       *(buf + logbuf->eq) = ch;
+                       logbuf->eq = (logbuf->eq + 1) % logbuf->size;
+#ifdef IPC_DEBUG
+                       if (logbuf->eq == logbuf->dq) {
+                               ipc_write_debug_event(AP, IPC_DEBUG_CHUB_FULL_LOG);
+                               ipc_add_evt(IPC_EVT_C2A, IRQ_EVT_CHUB_TO_AP_DEBUG);
+                       }
+#endif
+               }
+       }
 }
 
-void ipc_logbuf_put_with_char(char ch)
+void *ipc_logbuf_inbase(bool force)
 {
-       char *logbuf;
-       int eqNext;
-
        if (ipc_map) {
-               eqNext = ipc_map->logbuf.eq + 1;
+               struct ipc_logbuf *logbuf = &ipc_map->logbuf;
 
-#ifdef IPC_DEBUG
-               if (eqNext == ipc_map->logbuf.dq) {
-                       ipc_write_debug_event(AP, IPC_DEBUG_CHUB_FULL_LOG);
-                       ipc_add_evt(IPC_EVT_C2A, IRQ_EVT_CHUB_TO_AP_DEBUG);
+               if (force || logbuf->loglevel) {
+                       struct logbuf_content *log;
+                       int index;
+
+                       DISABLE_IRQ();
+                       if (logbuf->full) /* logbuf is full overwirte */
+                               logbuf->dbg_full_cnt++;
+
+                       index = logbuf->eq;
+                       logbuf->eq = (logbuf->eq + 1) % LOGBUF_NUM;
+                       if (logbuf->eq == logbuf->dq)
+                               logbuf->full = 1;
+                       ENABLE_IRQ();
+
+                       log = &logbuf->log[index];
+                       memset(log, 0, sizeof(struct logbuf_content));
+                       return log;
                }
+       }
+       return NULL;
+}
+
+void ipc_logbuf_req_flush(struct logbuf_content *log, bool force)
+{
+       if (log) {
+               struct ipc_logbuf *logbuf = &ipc_map->logbuf;
+
+               /* debug check overwrite */
+               log->size = logbuf->fw_num++;
+               if (ipc_map) {
+                       u32 eq = logbuf->eq;
+                       u32 dq = logbuf->dq;
+                       u32 logcnt = (eq >= dq) ? (eq - dq) : (eq + (logbuf->size - dq));
+
+                       if (((ipc_get_ap_wake() == AP_WAKE) && (logcnt > LOGBUF_FLUSH_THRESHOLD)) || force) {
+                               DISABLE_IRQ();
+                               if (!logbuf->flush_req) {
+                                       logbuf->flush_req = 1;
+                                       ipc_add_evt_in_critical(IPC_EVT_C2A, IRQ_EVT_C2A_LOG);
+                               }
+                               ENABLE_IRQ();
+                       }
+               }
+       }
+}
+#else
+#define ipc_logbuf_put_with_char(a) ((void)0)
+#define ipc_logbuf_inbase(a) ((void)0)
+#define ipc_logbuf_req_flush(a, c) ((void)0)
 #endif
-               ipc_map->logbuf.token++;
-               logbuf = ipc_map->logbuf.buf;
 
-               *(logbuf + ipc_map->logbuf.eq) = ch;
+#ifdef AP_IPC
+void ipc_logbuf_outprint(struct runtimelog_buf *rt_buf)
+{
+       if (ipc_map) {
+               struct logbuf_content *log;
+               struct ipc_logbuf *logbuf = &ipc_map->logbuf;
+               int eq;
+               int retrycnt = 0;
 
-               if (eqNext == ipc_map->logbuf.size)
-                       ipc_map->logbuf.eq = 0;
-               else
-                       ipc_map->logbuf.eq = eqNext;
+retry:
+               eq = logbuf->eq;
+               if (logbuf->full) {
+                       logbuf->full = 0;
+                       logbuf->dq =  logbuf->eq;
+               }
+
+               while (eq != logbuf->dq) {
+                       log = &logbuf->log[logbuf->dq];
+
+                       /* debug check overwrite */
+                       if (logbuf->ap_num != log->size) {
+                               logbuf->ap_num = log->size;
+                               logbuf->errcnt++;
+                       }
+                       logbuf->ap_num++;
+
+                       if (logbuf->loglevel == CHUB_RT_LOG_DUMP_PRT)
+                               CSP_PRINTF_INFO("%s: %s", NAME_PREFIX, (char *)log);
+
+                       if (rt_buf) {
+                               int len = strlen((char *)log);
+
+                               if (rt_buf->write_index + len > rt_buf->buffer_size)
+                                       rt_buf->write_index = 0;
+                               memcpy(rt_buf->buffer + rt_buf->write_index, (char *)log, len);
+                               rt_buf->write_index += len;
+                       }
+                       logbuf->dq = (logbuf->dq + 1) % LOGBUF_NUM;
+               }
+
+               if ((eq != logbuf->eq) && !retrycnt) {
+                       CSP_PRINTF_INFO("%s: retry: flush:%d, cnt:%d, eq:%d->%d, dq:%d\n",
+                               NAME_PREFIX, logbuf->flush_req, logbuf->dbg_full_cnt, eq, logbuf->eq, logbuf->dq);
+                       goto retry;
+               }
+
+               if (logbuf->flush_req)
+                       logbuf->flush_req = 0;
        }
 }
 
+enum ipc_fw_loglevel ipc_logbuf_loglevel(enum ipc_fw_loglevel loglevel, int set)
+{
+       if (ipc_map) {
+               struct ipc_logbuf *logbuf = &ipc_map->logbuf;
+
+               if (set)
+                       logbuf->loglevel = (u8)loglevel;
+               return (enum ipc_fw_loglevel)logbuf->loglevel;
+       }
+
+       return 0;
+}
+#else
+#define ipc_logbuf_outprint(a) ((void)0)
+#define ipc_logbuf_loglevel(a, b) ((void)0)
+#endif
+
 void ipc_set_owner(enum ipc_owner owner, void *base, enum ipc_direction dir)
 {
        ipc_own[owner].base = base;
index b19c3a8a6b3275e6a197b3612cb52b26add0b2a8..f88689340c7d999fa0940969468d15809e29280d 100644 (file)
@@ -18,7 +18,7 @@
 #define AP_IPC
 #endif
 
-#define IPC_VERSION (181024)
+#define IPC_VERSION (181213)
 
 #if defined(CHUB_IPC)
 #if defined(SEOS)
@@ -117,7 +117,6 @@ struct chub_bootargs {
  */
 #define IPC_BUF_NUM (IRQ_EVT_CH_MAX)
 #define IPC_EVT_NUM (30)
-#define IPC_LOGBUF_NUM (256)
 
 enum sr_num {
        SR_0 = 0,
@@ -160,6 +159,7 @@ enum irq_evt_chub {
        IRQ_EVT_C2A_ASSERT,
        IRQ_EVT_C2A_INT,
        IRQ_EVT_C2A_INTCLR,
+       IRQ_EVT_C2A_LOG,
        IRQ_EVT_CHUB_EVT_MAX = 15,
        IRQ_EVT_CHUB_ALIVE = IRQ_EVT_CHUB_EVT_MAX,
        IRQ_EVT_CHUB_MAX = 16,  /* max irq number on mailbox */
@@ -319,13 +319,53 @@ struct ipc_log_content {
        u8 buffer[sizeof(u64) + HOSTINTF_SENSOR_DATA_MAX - sizeof(u32)];
 };
 
+#define LOGBUF_TOTAL_SIZE (LOGBUF_SIZE * LOGBUF_NUM)
+#define LOGBUF_SIZE (64)
+#define LOGBUF_NUM (80)
+#define LOGBUF_DATA_SIZE (LOGBUF_SIZE - sizeof(u64))
+#define LOGBUF_FLUSH_THRESHOLD (LOGBUF_NUM / 4)
+
+struct logbuf_content{
+       char buf[LOGBUF_DATA_SIZE];
+       u64 size;
+};
+
+struct logbuf_raw {
+       u32 eq; /* write owner chub (index_writer) */
+       u32 dq; /* read onwer ap (index_reader) */
+       u32 size;
+       u32 full;
+       char buf[0];
+};
+
+enum ipc_fw_loglevel {
+       CHUB_RT_LOG_OFF,
+       CHUB_RT_LOG_DUMP,
+       CHUB_RT_LOG_DUMP_PRT,
+};
+
+struct runtimelog_buf {
+       char *buffer;
+       unsigned int buffer_size;
+       unsigned int write_index;
+       enum ipc_fw_loglevel loglevel;
+};
+
 struct ipc_logbuf {
+       struct logbuf_content log[LOGBUF_NUM];
        u32 eq; /* write owner chub (index_writer) */
        u32 dq; /* read onwer ap (index_reader) */
        u32 size;
-       u32 token;
-       u32 full;
-       char buf[0];
+       u8 dbg_full_cnt;
+       u8 full;
+       u8 flush_req;
+       u8 loglevel;
+       /* for debug */
+       int errcnt;
+       u64 fw_num;
+       u64 ap_num;
+       /* rawlevel logout */
+       struct logbuf_raw logbuf;
 };
 
 #ifndef IPC_DATA_SIZE
@@ -428,6 +468,7 @@ struct ipc_map_area {
        struct ipc_evt evt[IPC_EVT_MAX];
        struct ipc_debug dbg;
        struct sensor_map sensormap;
+       char persist[CHUB_PERSISTBUF_SIZE];
        struct ipc_logbuf logbuf;
 };
 
@@ -500,11 +541,14 @@ int ipc_check_reset_valid(void);
 void ipc_init(void);
 int ipc_hw_read_int_start_index(enum ipc_owner owner);
 /* logbuf functions */
-void *ipc_get_logbuf(void);
-unsigned int ipc_logbuf_get_token(void);
+enum ipc_fw_loglevel ipc_logbuf_loglevel(enum ipc_fw_loglevel loglevel, int set);
+void *ipc_logbuf_inbase(bool force);
+void ipc_logbuf_outprint(struct runtimelog_buf *rt_buf);
+void ipc_logbuf_req_flush(struct logbuf_content *log, bool force);
 /* evt functions */
 struct ipc_evt_buf *ipc_get_evt(enum ipc_evt_list evt);
 int ipc_add_evt(enum ipc_evt_list evt, enum irq_evt_chub irq);
+int ipc_add_evt_in_critical(enum ipc_evt_list evtq, enum irq_evt_chub evt);
 void ipc_print_evt(enum ipc_evt_list evt);
 /* mailbox hw access */
 void ipc_set_owner(enum ipc_owner owner, void *base, enum ipc_direction dir);
@@ -520,7 +564,6 @@ void ipc_hw_set_mcuctrl(enum ipc_owner owner, unsigned int val);
 void ipc_hw_mask_irq(enum ipc_owner owner, int irq);
 void ipc_hw_unmask_irq(enum ipc_owner owner, int irq);
 void ipc_logbuf_put_with_char(char ch);
-int ipc_logbuf_need_flush(void);
 void ipc_write_debug_event(enum ipc_owner owner, enum ipc_debug_event action);
 u32 ipc_read_debug_event(enum ipc_owner owner);
 void ipc_write_debug_val(enum ipc_data_list dir, u32 val);
index 8acc05bc6a2c1bb081c5d1dba0e84be33710dd83..35c507462459abc0f4127e0a689013418d189e2f 100644 (file)
@@ -23,7 +23,7 @@
 #include "chub_ipc.h"
 
 #ifdef CONFIG_CONTEXTHUB_DEBUG
-#define SIZE_OF_BUFFER (SZ_512K + SZ_128K)
+#define SIZE_OF_BUFFER (SZ_128K + SZ_128K)
 #else
 #define SIZE_OF_BUFFER (SZ_128K)
 #endif
@@ -114,11 +114,10 @@ void log_flush(struct log_buffer_info *info)
        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));
+       if ((buffer->index_reader >= buffer->size)
+               || (buffer->index_writer >= buffer->size)) {
+               dev_err(info->dev, "%s(%d): offset is corrupted. index_writer=%u, index_reader=%u, size=%u\n",
+                       __func__, info->id, buffer->index_writer, buffer->index_reader, buffer->size);
 
                return;
        }
@@ -369,11 +368,10 @@ static void log_dump(struct log_buffer_info *info, int err)
        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));
+       if ((buffer->index_reader >= buffer->size)
+               || (buffer->index_writer >= buffer->size)) {
+               dev_err(info->dev, "%s(%d): offset is corrupted. index_writer=%u, index_reader=%u, size=%u\n",
+                       __func__, info->id, buffer->index_writer, buffer->index_reader, buffer->size);
                return;
        }
 
@@ -458,22 +456,19 @@ static ssize_t chub_log_flush_save(struct device *dev,
 
        err = kstrtol(&buf[0], 10, &event);
        if (!err) {
-               if (!auto_log_flush_ms) {
-                       if (!err) {
-                               log_flush_all();
-                       } else {
-                               pr_err("%s: fails to flush log\n", __func__);
-                       }
+               if (!event) {
+                       log_flush_all();
+               } else {
+                       /* update log_flush time */
+                       auto_log_flush_ms = event;
+                       pr_err("%s: set flush ms:%d\n", __func__, auto_log_flush_ms);
+                       schedule_delayed_work(&log_flush_all_work, msecs_to_jiffies(auto_log_flush_ms));
                }
-               /* update log_flush time */
-               auto_log_flush_ms = event * 1000;
-
                return count;
        } else {
+               pr_err("%s: fails event:%d, err:%d\n", __func__, event, err);
                return 0;
        }
-
-       return count;
 }
 
 static ssize_t chub_dump_log_save(struct device *dev,
@@ -508,6 +503,7 @@ struct log_buffer_info *log_register_buffer(struct device *dev, int id,
        info->id = id;
        info->file_created = false;
        info->kernel_buffer.buffer = vzalloc(SIZE_OF_BUFFER);
+       info->kernel_buffer.buffer_size = SIZE_OF_BUFFER;
        info->kernel_buffer.index = 0;
        info->kernel_buffer.index_reader = 0;
        info->kernel_buffer.index_writer = 0;
index 32e6f206db06d9b854bc0012bee400f6c1087a10..d8d4ac85eb5b0821189d20277e00fc00b72843d6 100644 (file)
 #define __CHUB_LOG_H_
 
 #include <linux/device.h>
+#include "chub_ipc.h"
 
 struct log_kernel_buffer {
        char *buffer;
+       unsigned int buffer_size;
        unsigned int index;
        bool wrap;
        volatile bool updated;
@@ -42,7 +44,6 @@ struct LOG_BUFFER {
        volatile u32 index_writer;
        volatile u32 index_reader;
        volatile u32 size;
-       volatile u32 token;
        volatile u32 full;
        char buffer[0];
 };
index d350cad7b2b2ef6ab9b1fb0bf573404fa5176100..36867bfc726c78b0b292a44fc271f63f23bf8064 100644 (file)
@@ -885,7 +885,7 @@ static ssize_t nanohub_download_bl(struct device *dev,
 
        return ret < 0 ? ret : count;
 #elif defined(CONFIG_NANOHUB_MAILBOX)
-       ret = contexthub_reset(data->pdata->mailbox_client, 1, 0);
+       ret = contexthub_reset(data->pdata->mailbox_client, 1, CHUB_ERR_NONE);
 
        return ret < 0 ? ret : count;
 #endif