From ced9995b9048445813a0a2f699043c5a30edbcd8 Mon Sep 17 00:00:00 2001 From: Arian Date: Thu, 22 Dec 2022 00:18:49 +0100 Subject: [PATCH] Import xiaomi mtd changes from mayfly-s-oss --- drivers/input/misc/pm8941-pwrkey.c | 94 ++++++++ drivers/mtd/devices/block2mtd.c | 37 +++- drivers/mtd/mtdoops.c | 340 +++++++++++++++++++++++++++-- 3 files changed, 450 insertions(+), 21 deletions(-) diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index f8b41c26002f..1f1a59e4fb60 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #define PON_REV2 0x01 @@ -51,6 +53,11 @@ #define PON_DBC_CTL 0x71 #define PON_DBC_DELAY_MASK 0x7 +#if IS_ENABLED(CONFIG_MTD_OOPS) +extern int g_long_press_reason; +extern void mtdoops_do_dump_if(int reason); +#endif + struct pm8941_data { unsigned int pull_up_bit; unsigned int status_bit; @@ -141,6 +148,35 @@ static int pm8941_reboot_notify(struct notifier_block *nb, return NOTIFY_DONE; } + +void show_state_filter_single(unsigned long state_filter) +{ + struct task_struct *g, *p; + +#if BITS_PER_LONG == 32 + printk(KERN_INFO + " task PC stack pid father\n"); +#else + printk(KERN_INFO + " task PC stack pid father\n"); +#endif + rcu_read_lock(); + for_each_process_thread(g, p) { + /* + * reset the NMI-timeout, listing all files on a slow + * console might take a lot of time: + * Also, reset softlockup watchdogs on all CPUs, because + * another CPU might be blocked waiting for us to process + * an IPI. + */ + touch_nmi_watchdog(); + //touch_all_softlockup_watchdogs(); + if (p->state == state_filter) + sched_show_task(p); + } + rcu_read_unlock(); +} + static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) { struct pm8941_pwrkey *pwrkey = _data; @@ -148,6 +184,42 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) int error; u64 elapsed_us; + if (!strcmp(pwrkey->data->name,"pmic_pwrkey_bark")){ + +#if IS_ENABLED(CONFIG_MTD_OOPS) + error = regmap_read(pwrkey->regmap, + pwrkey->baseaddr + PON_RT_STS, &sts); + if (error) + return IRQ_HANDLED; + sts &= pwrkey->data->status_bit; + if(sts){ + dev_err(pwrkey->dev, "pwrkey_bark_irq trigger, start dump mtdoops"); + mtdoops_do_dump_if(g_long_press_reason); + } +#endif + return IRQ_HANDLED; + } + else if (!strcmp(pwrkey->data->name,"pmic_pwrkey_resin_bark")){ + + error = regmap_read(pwrkey->regmap, + pwrkey->baseaddr + PON_RT_STS, &sts); + if (error) + return IRQ_HANDLED; + sts &= pwrkey->data->status_bit; + if(sts){ + int tmp_console = console_loglevel; + dev_err(pwrkey->dev, "pwrkey_resin_bark_irq trigger, start D&R task info"); + console_verbose(); + pr_info("------ collect D&R-state processes info before long comb key ------\n"); + show_state_filter_single(TASK_UNINTERRUPTIBLE); + show_state_filter_single(TASK_RUNNING); + pr_info("------ end collecting D&R-state processes info ------\n"); + console_loglevel = tmp_console; + } + else{ + } + } + if (pwrkey->sw_debounce_time_us) { elapsed_us = ktime_us_delta(ktime_get(), pwrkey->last_release_time); @@ -471,11 +543,33 @@ static const struct pm8941_data pon_gen3_resin_data = { .has_pon_pbs = true, }; +static const struct pm8941_data pon_gen3_pwrkey_bark_data = { + .status_bit = PON_GEN3_KPDPWR_N_SET, + .name = "pmic_pwrkey_bark", + .phys = "pmic_pwrkey_bark/input0", + .supports_ps_hold_poff_config = false, + .supports_debounce_config = false, + .needs_sw_debounce = true, + .has_pon_pbs = true, +}; + +static const struct pm8941_data pon_gen3_pwrkey_resin_bark_data = { + .status_bit = PON_GEN3_KPDPWR_N_SET, + .name = "pmic_pwrkey_resin_bark", + .phys = "pmic_pwrkey_resin_bark/input0", + .supports_ps_hold_poff_config = false, + .supports_debounce_config = false, + .needs_sw_debounce = true, + .has_pon_pbs = true, +}; + static const struct of_device_id pm8941_pwr_key_id_table[] = { { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data }, { .compatible = "qcom,pm8941-resin", .data = &resin_data }, { .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data }, { .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data }, + { .compatible = "qcom,pmk8350-pwrkey-bark", .data = &pon_gen3_pwrkey_bark_data }, + { .compatible = "qcom,pmk8350-pwrkey-resin-bark", .data = &pon_gen3_pwrkey_resin_bark_data }, { } }; MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table); diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index c08721b11642..3bde066d6bf1 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -141,6 +141,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, int offset = to & ~PAGE_MASK; // page offset int cpylen; + printk(KERN_ERR "_block2mtd_write: start len = %d, mapping_index= %d \n",len,index); while (len) { if ((offset+len) > PAGE_SIZE) cpylen = PAGE_SIZE - offset; // multiple pages @@ -168,6 +169,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, offset = 0; index++; } + + printk(KERN_ERR "_block2mtd_write: finish all \n"); return 0; } @@ -183,6 +186,7 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, mutex_unlock(&dev->write_mutex); if (err > 0) err = 0; + dev->mtd._sync(mtd); return err; } @@ -213,16 +217,34 @@ static void block2mtd_free_device(struct block2mtd_dev *dev) } +int delSubStr(char * src, char * sub,char * result) +{ + int i,find = 0; + int len_src = strlen(src); + int len_sub = strlen(sub); + for( i = 0 ; i <= len_src - len_sub; i++){ + if(strncmp(src+i, sub, len_sub)==0){ + strncpy(result,src,i); + strncpy(result+i,src+i+len_sub,len_src-i-len_sub); + find =1; + break; + } + } + return find; +} + + static struct block2mtd_dev *add_device(char *devname, int erase_size, int timeout) { -#ifndef MODULE +//#ifndef MODULE int i; -#endif +//#endif const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; struct block_device *bdev; struct block2mtd_dev *dev; char *name; + char name_for_find_devt[80]={0}; if (!devname) return NULL; @@ -234,11 +256,14 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size, /* Get a handle on the device */ bdev = blkdev_get_by_path(devname, mode, dev); -#ifndef MODULE +//#ifndef MODULE /* * We might not have the root device mounted at this point. * Try to resolve the device name by other means. */ + if(!delSubStr(devname, "block/",name_for_find_devt)) + return NULL; + for (i = 0; IS_ERR(bdev) && i <= timeout; i++) { dev_t devt; @@ -251,12 +276,12 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size, msleep(1000); wait_for_device_probe(); - devt = name_to_dev_t(devname); + devt = name_to_dev_t(name_for_find_devt); if (!devt) continue; bdev = blkdev_get_by_dev(devt, mode, dev); } -#endif +//#endif if (IS_ERR(bdev)) { pr_err("error: cannot open device %s\n", devname); @@ -307,6 +332,8 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size, dev->mtd.index, dev->mtd.name + strlen("block2mtd: "), dev->mtd.erasesize >> 10, dev->mtd.erasesize); + + pr_err("block2mtd: add device sucess \n"); return dev; err_destroy_mutex: diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 774970bfcf85..ebe9129d06b4 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -18,14 +19,77 @@ #include #include #include +#include +#include +#include +#include + + +struct pmsg_buffer_hdr { + uint32_t sig; + atomic_t start; + atomic_t size; + uint8_t data[0]; +}; /* Maximum MTD partition size */ -#define MTDOOPS_MAX_MTD_SIZE (8 * 1024 * 1024) +#define MTDOOPS_MAX_MTD_SIZE (16 * 1024 * 1024) #define MTDOOPS_KERNMSG_MAGIC 0x5d005d00 #define MTDOOPS_HEADER_SIZE 8 +/* Expand kmsg_dump_reason +enum kmsg_dump_reason { + KMSG_DUMP_UNDEF, + KMSG_DUMP_PANIC, + KMSG_DUMP_OOPS, + KMSG_DUMP_EMERG, + KMSG_DUMP_SHUTDOWN, + KMSG_DUMP_MAX +}; +*/ + +enum mtd_dump_reason { + MTD_DUMP_UNDEF, + MTD_DUMP_PANIC, + MTD_DUMP_OOPS, + MTD_DUMP_EMERG, + MTD_DUMP_SHUTDOWN, + MTD_DUMP_RESTART, + MTD_DUMP_POWEROFF, + MTD_DUMP_LONG_PRESS, + MTD_DUMP_MAX +}; + + +static char *kdump_reason[8] = { + "Unknown", + "Kernel Panic", + "Oops!", + "Emerg", + "Shut Down", + "Restart", + "PowerOff", + "Long Press" +}; + + +enum mtdoops_log_type { + MTDOOPS_TYPE_UNDEF, + MTDOOPS_TYPE_DMESG, + MTDOOPS_TYPE_PMSG, +}; +static char *log_type[4] = { + "Unknown", + "LAST KMSG", + "LAST LOGCAT" +}; + +int g_long_press_reason = MTD_DUMP_LONG_PRESS; +EXPORT_SYMBOL_GPL(g_long_press_reason); + static unsigned long record_size = 4096; +static unsigned long lkmsg_record_size = 512 * 1024; module_param(record_size, ulong, 0400); MODULE_PARM_DESC(record_size, "record size for MTD OOPS pages in bytes (default 4096)"); @@ -35,13 +99,27 @@ module_param_string(mtddev, mtddev, 80, 0400); MODULE_PARM_DESC(mtddev, "name or index number of the MTD device to use"); -static int dump_oops = 1; +static int dump_oops = 0; module_param(dump_oops, int, 0600); MODULE_PARM_DESC(dump_oops, "set to 1 to dump oopses, 0 to only dump panics (default 1)"); +#define MAX_CMDLINE_PARAM_LEN 64 +static char build_fingerprint[MAX_CMDLINE_PARAM_LEN] = {0}; +module_param_string(fingerprint, build_fingerprint, MAX_CMDLINE_PARAM_LEN,0644); + + +struct pmsg_platform_data { + unsigned long mem_size; + phys_addr_t mem_address; + unsigned long console_size; + unsigned long pmsg_size; +}; + static struct mtdoops_context { struct kmsg_dumper dump; + struct notifier_block reboot_nb; + struct pmsg_platform_data pmsg_data; int mtd_index; struct work_struct work_erase; @@ -107,13 +185,14 @@ static void mtdoops_inc_counter(struct mtdoops_context *cxt) if (cxt->nextcount == 0xffffffff) cxt->nextcount = 0; + printk(KERN_ERR "mtdoops: ready nextpage= %d, nextcount= %d (no erase), oops_page_used_flag = %lx", + cxt->nextpage, cxt->nextcount, *cxt->oops_page_used ); + if (page_is_used(cxt, cxt->nextpage)) { schedule_work(&cxt->work_erase); return; } - printk(KERN_DEBUG "mtdoops: ready %d, %d (no erase)\n", - cxt->nextpage, cxt->nextcount); } /* Scheduled work - when we can't proceed without erasing a block */ @@ -200,9 +279,10 @@ static void mtdoops_write(struct mtdoops_context *cxt, int panic) printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n", cxt->nextpage * record_size, retlen, record_size, ret); mark_page_used(cxt, cxt->nextpage); - memset(cxt->oops_buf, 0xff, record_size); - mtdoops_inc_counter(cxt); +// device will reboot ,so do not need find next and erase +// if (!panic) +// mtdoops_inc_counter(cxt); } static void mtdoops_workfunc_write(struct work_struct *work) @@ -266,28 +346,160 @@ static void find_next_position(struct mtdoops_context *cxt) mtdoops_inc_counter(cxt); } -static void mtdoops_do_dump(struct kmsg_dumper *dumper, - enum kmsg_dump_reason reason) +static void mtdoops_add_reason(char *oops_buf, enum mtd_dump_reason reason, enum mtdoops_log_type type, int index, int nextpage) { + char str_buf[200] = {0}; + int ret_len = 0; + struct timespec64 now; + struct tm ts; + + ktime_get_coarse_real_ts64(&now); + time64_to_tm(now.tv_sec, 0, &ts); + + if (nextpage > 1) + ret_len = snprintf(str_buf, 200, + "\n```\n## Index: %d\t\n### Build: %s\t\n## REASON: %s\n#### LOG TYPE:%s\n#####%04ld-%02d-%02d %02d:%02d:%02d\t\n```c\t\n", + index, build_fingerprint, kdump_reason[reason], log_type[type], ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec); + else + ret_len = snprintf(str_buf, 200, + "\n\n## Index: %d\t\n### Build: %s\t\n## REASON: %s\n#### LOG TYPE: %s\n#####%04ld-%02d-%02d %02d:%02d:%02d\t\n```c\t\n", + index, build_fingerprint, kdump_reason[reason], log_type[type], ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec); + + memcpy(oops_buf, str_buf, ret_len); +} + + +static void mtdoops_add_pmsg_head(char *oops_buf, enum mtdoops_log_type type) +{ + char str_buf[80] = {0}; + int ret_len = 0; + struct timespec64 now; + struct tm ts; + + ktime_get_coarse_real_ts64(&now); + time64_to_tm(now.tv_sec, 0, &ts); + + ret_len = snprintf(str_buf, 80, + "\n```\n#### LOG TYPE:%s\n#####%04ld-%02d-%02d %02d:%02d:%02d\t\n```c\t\n", + log_type[type], ts.tm_year+1900, ts.tm_mon, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec); + + memcpy(oops_buf, str_buf, ret_len); +} + +static void mtdoops_do_dump(struct kmsg_dumper *dumper, + enum mtd_dump_reason reason) +{ + static int do_dump_count = 0; struct mtdoops_context *cxt = container_of(dumper, struct mtdoops_context, dump); + size_t ret_len = 0; + char *pmsg_buffer_start = NULL; + struct pmsg_buffer_hdr *p_hdr = NULL; + int j, ret; + + if(cxt->mtd == NULL) { + printk(KERN_ERR "mtdoops: init is not finish. Cannot write mtd logs \n"); + return; + } + + do_dump_count++; + printk(KERN_ERR "mtdoops: %s start , count = %d , page = %d, reason = %d, dump_count = %d\n",__func__,cxt->nextcount, cxt->nextpage,reason,do_dump_count); + + if(do_dump_count>1) + { + for (j = 0, ret = -1; (j < 3) && (ret < 0); j++) + ret = mtdoops_erase_block(cxt, cxt->nextpage * record_size); + } /* Only dump oopses if dump_oops is set */ if (reason == KMSG_DUMP_OOPS && !dump_oops) return; kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE, - record_size - MTDOOPS_HEADER_SIZE, NULL); + lkmsg_record_size - MTDOOPS_HEADER_SIZE, &ret_len); - if (reason != KMSG_DUMP_OOPS) { - /* Panics must be written immediately */ + mtdoops_add_reason(cxt->oops_buf + MTDOOPS_HEADER_SIZE, reason, MTDOOPS_TYPE_DMESG, cxt->nextcount, cxt->nextpage); + + pmsg_buffer_start = phys_to_virt((cxt->pmsg_data.mem_address + cxt->pmsg_data.mem_size) - cxt->pmsg_data.pmsg_size); + p_hdr = (struct pmsg_buffer_hdr *)pmsg_buffer_start; + + pr_err("mtdoops: mtdoops_do_dump pmsg paddr = 0x%lx \n",pmsg_buffer_start); + + if(p_hdr->sig == 0x43474244) + { + void *oopsbuf = cxt->oops_buf + (MTDOOPS_HEADER_SIZE + ret_len); + uint8_t *p_buff_end = p_hdr->data + p_hdr->size.counter; + int pmsg_cp_size = 0; + int pstart = p_hdr->start.counter; + int psize = p_hdr->size.counter; + + pmsg_cp_size = (record_size - (ret_len + MTDOOPS_HEADER_SIZE)); + if (psize <= pmsg_cp_size) + pmsg_cp_size = psize; + + if (pstart >= pmsg_cp_size) + memcpy(oopsbuf, p_hdr->data, pmsg_cp_size); + else{ + memcpy(oopsbuf, p_buff_end - (pmsg_cp_size - pstart), pmsg_cp_size - pstart); + memcpy(oopsbuf + (pmsg_cp_size - pstart), p_hdr->data, pstart); + } + mtdoops_add_pmsg_head(cxt->oops_buf + (MTDOOPS_HEADER_SIZE + ret_len), MTDOOPS_TYPE_PMSG); + } + else + printk(KERN_ERR "mtdoops: read pmsg failed sig = 0x%x \n", p_hdr->sig); + + /* Panics must be written immediately */ + if (reason == KMSG_DUMP_OOPS || reason == KMSG_DUMP_PANIC) { mtdoops_write(cxt, 1); } else { /* For other cases, schedule work to write it "nicely" */ - schedule_work(&cxt->work_write); + //schedule_work(&cxt->work_write); + // we should write log immediately , if use work to write, ufs will shutdown before write log finish + mtdoops_write(cxt, 0); } + + printk(KERN_ERR "mtdoops: mtdoops_do_dump() finish \n"); } + +static void mtdoops_do_dump_kmsgdump(struct kmsg_dumper *dumper, + enum kmsg_dump_reason reason) +{ + //mtdoops_do_dump(dumper, (enum mtd_dump_reason)reason); +} + + +void mtdoops_do_dump_if(int reason) +{ + struct mtdoops_context *cxt = &oops_cxt; + + cxt->dump.active = true; + kmsg_dump_rewind(&cxt->dump); + mtdoops_do_dump(&cxt->dump,(enum mtd_dump_reason)reason); + cxt->dump.active = false; +} +EXPORT_SYMBOL_GPL(mtdoops_do_dump_if); + + +static int mtdoops_reboot_nb_handle(struct notifier_block *this, unsigned long event, + void *ptr) +{ + //char *cmd = ptr; + enum mtd_dump_reason reason; + + if (event == SYS_RESTART) + reason = MTD_DUMP_RESTART; + else if(event == SYS_POWER_OFF) + reason = MTD_DUMP_POWEROFF; + else + return NOTIFY_OK; + + mtdoops_do_dump_if(reason); + + return NOTIFY_OK; +} + + static void mtdoops_notify_add(struct mtd_info *mtd) { struct mtdoops_context *cxt = &oops_cxt; @@ -326,8 +538,9 @@ static void mtdoops_notify_add(struct mtd_info *mtd) return; } - cxt->dump.max_reason = KMSG_DUMP_OOPS; - cxt->dump.dump = mtdoops_do_dump; + // for panic + cxt->dump.max_reason = KMSG_DUMP_MAX; + cxt->dump.dump = mtdoops_do_dump_kmsgdump; err = kmsg_dump_register(&cxt->dump); if (err) { printk(KERN_ERR "mtdoops: registering kmsg dumper failed, error %d\n", err); @@ -336,6 +549,12 @@ static void mtdoops_notify_add(struct mtd_info *mtd) return; } + + // for restart and power off + cxt->reboot_nb.notifier_call = mtdoops_reboot_nb_handle; + cxt->reboot_nb.priority = 255; + register_reboot_notifier(&cxt->reboot_nb); + cxt->mtd = mtd; cxt->oops_pages = (int)mtd->size / record_size; find_next_position(cxt); @@ -352,6 +571,8 @@ static void mtdoops_notify_remove(struct mtd_info *mtd) if (kmsg_dump_unregister(&cxt->dump) < 0) printk(KERN_WARNING "mtdoops: could not unregister kmsg_dumper\n"); + unregister_reboot_notifier(&cxt->reboot_nb); + cxt->mtd = NULL; flush_work(&cxt->work_erase); flush_work(&cxt->work_write); @@ -363,12 +584,94 @@ static struct mtd_notifier mtdoops_notifier = { .remove = mtdoops_notify_remove, }; +static int mtdoops_parse_dt_u32(struct platform_device *pdev, + const char *propname, + u32 default_value, u32 *value) +{ + u32 val32 = 0; + int ret; + + ret = of_property_read_u32(pdev->dev.of_node, propname, &val32); + if (ret == -EINVAL) { + /* field is missing, use default value. */ + val32 = default_value; + } else if (ret < 0) { + dev_err(&pdev->dev, "failed to parse property %s: %d\n", + propname, ret); + return ret; + } + + /* Sanity check our results. */ + if (val32 > INT_MAX) { + dev_err(&pdev->dev, "%s %u > INT_MAX\n", propname, val32); + return -EOVERFLOW; + } + + *value = val32; + return 0; +} + + +static int mtdoops_pmsg_probe(struct platform_device *pdev) +{ + struct mtdoops_context *cxt = &oops_cxt; + struct resource *res; + u32 value; + int ret; + + dev_dbg(&pdev->dev, "using Device Tree\n"); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, + "failed to locate DT /reserved-memory resource\n"); + return -EINVAL; + } + + cxt->pmsg_data.mem_size = resource_size(res); + cxt->pmsg_data.mem_address = res->start; + + +#define parse_u32(name, field, default_value) { \ + ret = mtdoops_parse_dt_u32(pdev, name, default_value, \ + &value); \ + if (ret < 0) \ + return ret; \ + field = value; \ + } + parse_u32("console-size", cxt->pmsg_data.console_size, 0); + parse_u32("pmsg-size", cxt->pmsg_data.pmsg_size, 0); +#undef parse_u32 + + printk(KERN_ERR "mtdoops: pares mtd_dt, mem_address =0x%x, mem_size =0x%x \n", cxt->pmsg_data.mem_address, cxt->pmsg_data.mem_size); + printk(KERN_ERR "mtdoops: pares mtd_dt, pmsg_size =0x%x \n", cxt->pmsg_data.pmsg_size); + + return 0; +} + + +static const struct of_device_id dt_match[] = { + { .compatible = "mtdoops_pmsg" }, + {} +}; + + +static struct platform_driver mtdoops_pmsg_driver = { + .probe = mtdoops_pmsg_probe, + .driver = { + .name = "mtdoops_pmsg", + .of_match_table = dt_match, + }, +}; + static int __init mtdoops_init(void) { struct mtdoops_context *cxt = &oops_cxt; int mtd_index; char *endp; + printk(KERN_ERR "mtdoops: %s \n",__func__); + if (strlen(mtddev) == 0) { printk(KERN_ERR "mtdoops: mtd device (mtddev=name/number) must be supplied\n"); return -EINVAL; @@ -388,7 +691,8 @@ static int __init mtdoops_init(void) if (*endp == '\0') cxt->mtd_index = mtd_index; - cxt->oops_buf = vmalloc(record_size); + //cxt->oops_buf = vmalloc(record_size); + cxt->oops_buf = kmalloc(record_size, GFP_KERNEL); if (!cxt->oops_buf) { printk(KERN_ERR "mtdoops: failed to allocate buffer workspace\n"); return -ENOMEM; @@ -396,8 +700,12 @@ static int __init mtdoops_init(void) memset(cxt->oops_buf, 0xff, record_size); INIT_WORK(&cxt->work_erase, mtdoops_workfunc_erase); + + // we should write log immediately , if use work to write, ufs will shutdown before write log finish INIT_WORK(&cxt->work_write, mtdoops_workfunc_write); + platform_driver_register(&mtdoops_pmsg_driver); + register_mtd_user(&mtdoops_notifier); return 0; } @@ -407,7 +715,7 @@ static void __exit mtdoops_exit(void) struct mtdoops_context *cxt = &oops_cxt; unregister_mtd_user(&mtdoops_notifier); - vfree(cxt->oops_buf); + kfree(cxt->oops_buf); vfree(cxt->oops_page_used); }