diff --git a/drivers/staging/blackbox/blackbox_common.c b/drivers/staging/blackbox/blackbox_common.c index 5e4d16ce1cb2290cfad7d4df36ff0f713fd52ed8..407f57fd09cfb598d34fc1f1b5f56eec8c4505c5 100644 --- a/drivers/staging/blackbox/blackbox_common.c +++ b/drivers/staging/blackbox/blackbox_common.c @@ -74,9 +74,11 @@ int full_write_file(const char *pfile_path, char *buf, old_fs = get_fs(); set_fs(KERNEL_DS); #endif - +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) + ret = __kernel_write(filp, (const void *)buf, buf_size, &pos); +#else ret = vfs_write(filp, buf, buf_size, &pos); - +#endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 197) set_fs(old_fs); #endif diff --git a/drivers/staging/blackbox/blackbox_storage.c b/drivers/staging/blackbox/blackbox_storage.c index 635e3aa036aba14ae09ff4c4625a20a737c2bc0e..8a5a28cc1af00ae7a3fdbe7675b5c6c6b447daad 100644 --- a/drivers/staging/blackbox/blackbox_storage.c +++ b/drivers/staging/blackbox/blackbox_storage.c @@ -11,6 +11,7 @@ #include #include #include +#include char *storage_material = #ifdef CONFIG_DEF_BLACKBOX_STORAGE @@ -20,8 +21,13 @@ char *storage_material = #endif const struct reboot_crashlog_storage *storage_lastword __ro_after_init; +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) +bool g_blackbox_flag = false; +EXPORT_SYMBOL(g_blackbox_flag); +#endif + #if IS_ENABLED(CONFIG_DEF_BLACKBOX_STORAGE_BY_MEMORY) -static DEFINE_SEMAPHORE(kmsg_sem); +static DEFINE_SEMAPHORE(kmsg_sem, 1); static char *lastlog; unsigned int lastlog_len; static int get_log_by_memory(void *in, unsigned int inlen) @@ -45,7 +51,7 @@ static void do_kmsg_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) { struct fault_log_info *pinfo; - + struct kmsg_dump_iter iter; if (unlikely(!lastlog)) return; @@ -54,6 +60,7 @@ static void do_kmsg_dump(struct kmsg_dumper *dumper, bbox_print_err("down_trylock failed!\n"); return; } + kmsg_dump_rewind(&iter); pinfo = (struct fault_log_info *)lastlog; (void)kmsg_dump_get_buffer(dumper, true, lastlog + sizeof(*pinfo), lastlog_len - sizeof(*pinfo), (size_t *)&pinfo->len); @@ -121,7 +128,9 @@ static int get_log_by_pstore(void *in, unsigned int inlen) char pstore_file[PATH_MAX_LEN]; struct file *filp = NULL; char *pathname = NULL; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 192) mm_segment_t old_fs; +#endif void *pbuf = NULL; loff_t pos = 0; static int retry; @@ -142,12 +151,17 @@ static int get_log_by_pstore(void *in, unsigned int inlen) PTR_ERR(filp)); return -EBADF; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) + printk("bbox %s %d, read %s is succ\n", __func__, __LINE__, getfullpath(filp) ? getfullpath(filp) : ""); + g_blackbox_flag = true; +#else memset(in, 0, inlen); pbuf = in; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 192) old_fs = get_fs(); set_fs(KERNEL_DS); - +#endif ret = vfs_read(filp, pbuf, inlen, &pos); if (ret < 0) { pathname = getfullpath(filp); @@ -156,7 +170,10 @@ static int get_log_by_pstore(void *in, unsigned int inlen) goto __error; } +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 192) set_fs(old_fs); +#endif +#endif /*KERNEL_VERSION(5, 10, 197)*/ file_close(filp); file_delete(filp); return 0; @@ -164,7 +181,9 @@ static int get_log_by_pstore(void *in, unsigned int inlen) return -EBADF; __error: +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 192) set_fs(old_fs); +#endif file_close(filp); return -EIO; } diff --git a/drivers/staging/hievent/hievent_driver.c b/drivers/staging/hievent/hievent_driver.c index 36fa7eb06b090d2d8e29e90f9bcfb1e4f9687e55..b4933a9cf41a662cba285a090ab60adee32c0791 100644 --- a/drivers/staging/hievent/hievent_driver.c +++ b/drivers/staging/hievent/hievent_driver.c @@ -23,6 +23,7 @@ #include #include #include +#include static struct class *hievent_class; static dev_t hievent_devno; @@ -252,6 +253,9 @@ int hievent_write_internal(const char *buffer, size_t buf_len) return retval; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) +EXPORT_SYMBOL(hievent_write_internal); +#endif static unsigned int hievent_poll(struct file *filep, poll_table *wait) { diff --git a/drivers/staging/hisysevent/hiview_hisysevent.c b/drivers/staging/hisysevent/hiview_hisysevent.c index 8503dd7ae644b1b50b5f85fcaba1faf4a8784123..82ba8247d2e1d13e841f1c1944fcfc31618ff5ff 100644 --- a/drivers/staging/hisysevent/hiview_hisysevent.c +++ b/drivers/staging/hisysevent/hiview_hisysevent.c @@ -21,6 +21,10 @@ #include #include +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) +int hievent_write_internal(const char *buffer, size_t buf_len); +#endif + #include "hisysevent_builder.h" #include "hisysevent_raw_data.h" @@ -94,6 +98,9 @@ int hisysevent_write(struct hiview_hisysevent *event) { struct hisysevent_raw_data *raw_data; int ret; +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) + int retval; +#endif struct file *filp; unsigned long vcount; struct iovec vec[3]; @@ -130,12 +137,19 @@ int hisysevent_write(struct hiview_hisysevent *event) goto event_wrote_err; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 197) + retval = hievent_write_internal(raw_data->data, raw_data->len + 1); + if (retval < 0) { + retval = -EIO; + goto event_wrote_err; + } +#else filp = filp_open(HISYSEVENT_WRITER_DEV, O_WRONLY, 0); if (!filp || IS_ERR(filp)) { ret = PTR_ERR(filp); pr_err("failed to access '%s', res=%d", HISYSEVENT_WRITER_DEV, ret); - goto event_wrote_err; + goto filp_err; } vcount = 0; @@ -156,9 +170,9 @@ int hisysevent_write(struct hiview_hisysevent *event) if (ret < 0) pr_err("failed to write hisysevent, ret=%d", ret); - +filp_err: filp_close(filp, NULL); - +#endif /*KERNEL_VERSION*/ event_wrote_err: raw_data_destroy(raw_data); return ret; diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 3acc38600cd1a2d026dfe82132696ad3d1f650dc..70dd4971da2c74f08c0ca64c363dc10eead52359 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -13,6 +13,16 @@ config PSTORE If you don't have a platform persistent store driver, say N. +config PSTORE_DEFLATE_COMPRESS + tristate "DEFLATE (ZLIB) compression" + default y + depends on PSTORE + select CRYPTO_DEFLATE + help + This option enables DEFLATE (also known as ZLIB) compression + algorithm support. + + config PSTORE_DEFAULT_KMSG_BYTES int "Default kernel log storage space" if EXPERT depends on PSTORE @@ -34,6 +44,26 @@ config PSTORE_COMPRESS blown crypto API. This reduces the risk of secondary oopses or other problems while pstore is recording panic metadata. +choice + prompt "Default pstore compression algorithm" + depends on PSTORE_COMPRESS + help + This option chooses the default active compression algorithm. + This change be changed at boot with "pstore.compress=..." on + the kernel command line. + + Currently, pstore has support for 6 compression algorithms: + deflate, lzo, lz4, lz4hc, 842 and zstd. + + The default compression algorithm is deflate. + config PSTORE_DEFLATE_COMPRESS_DEFAULT + bool "deflate" if PSTORE_DEFLATE_COMPRESS +endchoice +config PSTORE_COMPRESS_DEFAULT + string + depends on PSTORE_COMPRESS + default "deflate" if PSTORE_DEFLATE_COMPRESS_DEFAULT + config PSTORE_CONSOLE bool "Log kernel console messages" depends on PSTORE @@ -65,6 +95,18 @@ config PSTORE_FTRACE If unsure, say N. +config PSTORE_BLACKBOX + bool "Store customised fault log" + depends on PSTORE + depends on BLACKBOX + help + Enable storing the customised fault log for BlackBox. + + With the option enabled, pstore will store the customised kernel + fault log for BlackBox when oops or panic happened. + + If unsure, say N. + config PSTORE_RAM tristate "Log panic/oops to a RAM buffer" depends on PSTORE @@ -189,3 +231,24 @@ config PSTORE_BLK_FTRACE_SIZE NOTE that, both Kconfig and module parameters can configure pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLK_BLACKBOX_SIZE + int "Size in Kbytes of fault log for BlackBox to store" + depends on PSTORE_BLK + depends on PSTORE_BLACKBOX + default 64 + help + This just sets size of fault log (blackbox_size) for pstore/blk. + The size is in KB and must be a multiple of 4. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLACKBOX_STACK_SIZE + int "Default stack size for BlackBox" if EXPERT + depends on PSTORE + depends on PSTORE_BLACKBOX + default 1024 + help + Defines default size of pstore stack size for blackbox. + Can be enlarged if needed. not recommended to shrink it. diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index 801d6c0b170c3aaee647ad9fd1f536ae03de331a..824ef8e84dabd3220f2e94ff5630b50a37a1e065 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -49,4 +49,7 @@ extern void pstore_record_init(struct pstore_record *record, int __init pstore_init_fs(void); void __exit pstore_exit_fs(void); +#ifdef CONFIG_PSTORE_BLACKBOX +extern bool pstore_ready; /* flag which pstore_blk is ready */ +#endif #endif diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 03425928d2fb3cbba146fc775280427e5bf2abec..da24d3754eb64f647cf3cd3a9a8c43ca7c602c2a 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -17,6 +17,10 @@ #include #include #include +#ifdef CONFIG_PSTORE_BLACKBOX +#include +#include +#endif #include #include #include @@ -51,6 +55,7 @@ static const char * const pstore_type_names[] = { "powerpc-common", "pmsg", "powerpc-opal", + "blackbox", }; static int pstore_new_entry; @@ -270,6 +275,111 @@ void pstore_record_init(struct pstore_record *record, record->time = ns_to_timespec64(ktime_get_real_fast_ns()); } +/* + * Store the customised fault log + */ +#ifdef CONFIG_PSTORE_BLACKBOX +#define PSTORE_FLAG "PSTORE" +#define CALLSTACK_MAX_ENTRIES 20 +static void dump_stacktrace(char *pbuf, size_t buf_size, bool is_panic) +{ + int i; + size_t stack_len = 0; + size_t com_len = 0; + unsigned long entries[CALLSTACK_MAX_ENTRIES]; + unsigned int nr_entries; + char tmp_buf[ERROR_DESC_MAX_LEN]; + bool find_panic = false; + + if (unlikely(!pbuf || !buf_size)) + return; + memset(pbuf, 0, buf_size); + memset(tmp_buf, 0, sizeof(tmp_buf)); + nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 0); + com_len = scnprintf(pbuf, buf_size, "Comm:%s,CPU:%d,Stack:", + current->comm, raw_smp_processor_id()); + for (i = 0; i < nr_entries; i++) { + if (stack_len >= sizeof(tmp_buf)) { + tmp_buf[sizeof(tmp_buf) - 1] = '\0'; + break; + } + stack_len += scnprintf(tmp_buf + stack_len, sizeof(tmp_buf) - stack_len, + "%pS-", (void *)entries[i]); + if (!find_panic && is_panic) { + if (strncmp(tmp_buf, "panic", strlen("panic")) == 0) + find_panic = true; + else + (void)memset(tmp_buf, 0, sizeof(tmp_buf)); + } + } + if (com_len >= buf_size) + return; + stack_len = min(buf_size - com_len, strlen(tmp_buf)); + memcpy(pbuf + com_len, tmp_buf, stack_len); + *(pbuf + buf_size - 1) = '\0'; +} + +void pstore_blackbox_dump(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) +{ + struct fault_log_info *pfault_log_info; + struct pstore_record record; + struct kmsg_dump_iter iter; + size_t dst_size; + const char *why; + char *dst; + unsigned long flags = 0; + int ret; + +#if defined(CONFIG_PSTORE_BLK) || defined(CONFIG_PSTORE_RAM) + if (!pstore_ready) + return; +#endif + kmsg_dump_rewind(&iter); + why = kmsg_dump_reason_str(reason); + + if (pstore_cannot_block_path(reason)) { + if (!spin_trylock_irqsave(&psinfo->buf_lock, flags)) { + pr_err("dump skipped in %s path because of concurrent dump\n", + in_nmi() ? "NMI" : why); + return; + } + } else { + spin_lock_irqsave(&psinfo->buf_lock, flags); + } + + pfault_log_info = (struct fault_log_info *)psinfo->buf; + + memset(pfault_log_info, 0, sizeof(*pfault_log_info)); + + pstore_record_init(&record, psinfo); + + record.type = PSTORE_TYPE_BLACKBOX; + record.reason = reason; + + memcpy(pfault_log_info->flag, LOG_FLAG, strlen(LOG_FLAG)); + strncpy(pfault_log_info->info.event, why, + min(strlen(why), sizeof(pfault_log_info->info.event) - 1)); + strncpy(pfault_log_info->info.module, PSTORE_FLAG, + min(strlen(PSTORE_FLAG), sizeof(pfault_log_info->info.module) - 1)); + get_timestamp(pfault_log_info->info.error_time, TIMESTAMP_MAX_LEN); + dump_stacktrace(pfault_log_info->info.error_desc, sizeof(pfault_log_info->info.error_desc), false); + + record.buf = psinfo->buf; + + dst = psinfo->buf; + dst_size = psinfo->bufsize; + + dst_size -= sizeof(struct fault_log_info); + (void)kmsg_dump_get_buffer(&iter, true, dst + sizeof(struct fault_log_info), dst_size, + &(pfault_log_info->len)); + + record.size = sizeof(struct fault_log_info) + pfault_log_info->len; + ret = psinfo->write(&record); + spin_unlock_irqrestore(&psinfo->buf_lock, flags); +} +EXPORT_SYMBOL_GPL(pstore_blackbox_dump); +#endif + /* * callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the * end of the buffer. diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 88b34fdbf7592fd5e7a469cf9d84229b48557b1b..70a1ae218beeb4740ef557eb5787374328ee7510 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -45,6 +45,14 @@ static ulong ramoops_pmsg_size = MIN_MEM_SIZE; module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400); MODULE_PARM_DESC(pmsg_size, "size of user space message log"); +static ulong ramoops_blackbox_size = MIN_MEM_SIZE; +module_param_named(blackbox_size, ramoops_blackbox_size, ulong, 0400); +MODULE_PARM_DESC(blackbox_size, "size of blackbox log"); +#if IS_ENABLED(CONFIG_PSTORE_BLACKBOX) +bool pstore_ready; +#endif + + static unsigned long long mem_address; module_param_hw(mem_address, ullong, other, 0400); MODULE_PARM_DESC(mem_address, @@ -82,6 +90,7 @@ struct ramoops_context { struct persistent_ram_zone *cprz; /* Console zone */ struct persistent_ram_zone **fprzs; /* Ftrace zones */ struct persistent_ram_zone *mprz; /* PMSG zone */ + struct persistent_ram_zone *bprz; /* BLACKBOX zone */ phys_addr_t phys_addr; unsigned long size; unsigned int memtype; @@ -89,6 +98,7 @@ struct ramoops_context { size_t console_size; size_t ftrace_size; size_t pmsg_size; + size_t blackbox_size; u32 flags; struct persistent_ram_ecc_info ecc_info; unsigned int max_dump_cnt; @@ -99,6 +109,7 @@ struct ramoops_context { unsigned int max_ftrace_cnt; unsigned int ftrace_read_cnt; unsigned int pmsg_read_cnt; + unsigned int blackbox_read_cnt; struct pstore_info pstore; }; @@ -112,6 +123,7 @@ static int ramoops_pstore_open(struct pstore_info *psi) cxt->console_read_cnt = 0; cxt->ftrace_read_cnt = 0; cxt->pmsg_read_cnt = 0; + cxt->blackbox_read_cnt = 0; return 0; } @@ -215,6 +227,9 @@ static ssize_t ramoops_pstore_read(struct pstore_record *record) if (!prz_ok(prz) && !cxt->pmsg_read_cnt++) prz = ramoops_get_next_prz(&cxt->mprz, 0 /* single */, record); + if (!prz_ok(prz) && !cxt->blackbox_read_cnt++) + prz = ramoops_get_next_prz(&cxt->bprz, 0 /* single */, record); + /* ftrace is last since it may want to dynamically allocate memory. */ if (!prz_ok(prz)) { if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU) && @@ -336,6 +351,11 @@ static int notrace ramoops_pstore_write(struct pstore_record *record) } else if (record->type == PSTORE_TYPE_PMSG) { pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__); return -EINVAL; + } else if (record->type == PSTORE_TYPE_BLACKBOX) { + if (!cxt->bprz) + return -ENOMEM; + persistent_ram_write(cxt->bprz, record->buf, record->size); + return 0; } if (record->type != PSTORE_TYPE_DMESG) @@ -427,6 +447,9 @@ static int ramoops_pstore_erase(struct pstore_record *record) case PSTORE_TYPE_PMSG: prz = cxt->mprz; break; + case PSTORE_TYPE_BLACKBOX: + prz = cxt->bprz; + break; default: return -EINVAL; } @@ -687,6 +710,7 @@ static int ramoops_parse_dt(struct platform_device *pdev, parse_u32("console-size", pdata->console_size, 0); parse_u32("ftrace-size", pdata->ftrace_size, 0); parse_u32("pmsg-size", pdata->pmsg_size, 0); + parse_u32("blackbox-size", pdata->blackbox_size, 0); parse_u32("ecc-size", pdata->ecc_info.ecc_size, 0); parse_u32("flags", pdata->flags, 0); parse_u32("max-reason", pdata->max_reason, pdata->max_reason); @@ -707,9 +731,11 @@ static int ramoops_parse_dt(struct platform_device *pdev, parent_node = of_get_parent(of_node); if (!of_node_name_eq(parent_node, "reserved-memory") && !pdata->console_size && !pdata->ftrace_size && - !pdata->pmsg_size && !pdata->ecc_info.ecc_size) { + !pdata->pmsg_size && !pdata->ecc_info.ecc_size && + !pdata->blackbox_size) { pdata->console_size = pdata->record_size; pdata->pmsg_size = pdata->record_size; + pdata->blackbox_size = pdata->record_size; } of_node_put(parent_node); @@ -752,7 +778,7 @@ static int ramoops_probe(struct platform_device *pdev) } if (!pdata->mem_size || (!pdata->record_size && !pdata->console_size && - !pdata->ftrace_size && !pdata->pmsg_size)) { + !pdata->ftrace_size && !pdata->pmsg_size && !pdata->blackbox_size)) { pr_err("The memory size and the record/console size must be " "non-zero\n"); err = -EINVAL; @@ -767,6 +793,8 @@ static int ramoops_probe(struct platform_device *pdev) pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size)) pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size); + if (pdata->blackbox_size && !is_power_of_2(pdata->blackbox_size)) + pdata->blackbox_size = rounddown_pow_of_two(pdata->blackbox_size); cxt->size = pdata->mem_size; cxt->phys_addr = pdata->mem_address; @@ -775,13 +803,22 @@ static int ramoops_probe(struct platform_device *pdev) cxt->console_size = pdata->console_size; cxt->ftrace_size = pdata->ftrace_size; cxt->pmsg_size = pdata->pmsg_size; + cxt->blackbox_size = pdata->blackbox_size; cxt->flags = pdata->flags; cxt->ecc_info = pdata->ecc_info; paddr = cxt->phys_addr; dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size - - cxt->pmsg_size; + - cxt->pmsg_size - cxt->blackbox_size; + err = ramoops_init_prz("blackbox", dev, cxt, &cxt->bprz, &paddr, + cxt->blackbox_size, 0); + if (err) + goto fail_init; +#if IS_ENABLED(CONFIG_PSTORE_BLACKBOX) + else + pstore_ready = true; +#endif err = ramoops_init_przs("dmesg", dev, cxt, &cxt->dprzs, &paddr, dump_mem_sz, cxt->record_size, &cxt->max_dump_cnt, 0, 0); @@ -827,6 +864,8 @@ static int ramoops_probe(struct platform_device *pdev) cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; if (cxt->pmsg_size) cxt->pstore.flags |= PSTORE_FLAGS_PMSG; + if (cxt->blackbox_size) + cxt->pstore.flags |= PSTORE_FLAGS_BLACKBOX; /* * Since bufsize is only used for dmesg crash dumps, it @@ -860,6 +899,7 @@ static int ramoops_probe(struct platform_device *pdev) ramoops_console_size = pdata->console_size; ramoops_pmsg_size = pdata->pmsg_size; ramoops_ftrace_size = pdata->ftrace_size; + ramoops_blackbox_size = pdata->blackbox_size; pr_info("using 0x%lx@0x%llx, ecc: %d\n", cxt->size, (unsigned long long)cxt->phys_addr, @@ -931,6 +971,7 @@ static void __init ramoops_register_dummy(void) pdata.console_size = ramoops_console_size; pdata.ftrace_size = ramoops_ftrace_size; pdata.pmsg_size = ramoops_pmsg_size; + pdata.blackbox_size = ramoops_blackbox_size; /* If "max_reason" is set, its value has priority over "dump_oops". */ if (ramoops_max_reason >= 0) pdata.max_reason = ramoops_max_reason; diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 638507a3c8ff194e22a27955ca40dab238328f2f..df2c4ee0573ad643d1bce9d0f90806d9a57e1b8f 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -39,6 +39,8 @@ enum pstore_type_id { PSTORE_TYPE_PMSG = 7, PSTORE_TYPE_PPC_OPAL = 8, + PSTORE_TYPE_BLACKBOX = 9, + /* End of the list */ PSTORE_TYPE_MAX }; @@ -206,6 +208,7 @@ struct pstore_info { #define PSTORE_FLAGS_CONSOLE BIT(1) #define PSTORE_FLAGS_FTRACE BIT(2) #define PSTORE_FLAGS_PMSG BIT(3) +#define PSTORE_FLAGS_BLACKBOX BIT(4) extern int pstore_register(struct pstore_info *); extern void pstore_unregister(struct pstore_info *); @@ -286,4 +289,9 @@ pstore_ftrace_write_timestamp(struct pstore_ftrace_record *rec, u64 val) } #endif +#ifdef CONFIG_PSTORE_BLACKBOX +extern void pstore_blackbox_dump(struct kmsg_dumper *dumper, + enum kmsg_dump_reason reason); +#endif + #endif /*_LINUX_PSTORE_H*/ diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index 9d65ff94e216f000b2bb6f4580f946c16b3797ec..95981aa833181e7d54ce1983d94248029b6f659f 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -34,6 +34,7 @@ struct ramoops_platform_data { unsigned long console_size; unsigned long ftrace_size; unsigned long pmsg_size; + unsigned long blackbox_size; int max_reason; u32 flags; struct persistent_ram_ecc_info ecc_info;