From: 黄涛 Date: Sat, 30 Jul 2011 14:29:16 +0000 (+0800) Subject: Revert "drivers: apanic: Android kernel panic handler." X-Git-Tag: firefly_0821_release~9965 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=7e72dd7104be44b01f95e866c45b4f63ea96481d;p=firefly-linux-kernel-4.4.55.git Revert "drivers: apanic: Android kernel panic handler." This reverts commit 4360c491027cc03cb055b9d1781e5c41b2f1cdd5. Conflicts: drivers/misc/Kconfig drivers/misc/Makefile --- diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2d5eb0352e8e..af690da5db6c 100755 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -269,20 +269,6 @@ config WL127X_RFKILL Creates an rfkill entry in sysfs for power control of Bluetooth TI wl127x chips. -config APANIC - bool "Android kernel panic diagnostics driver" - default n - ---help--- - Driver which handles kernel panics and attempts to write - critical debugging data to flash. - -config APANIC_PLABEL - string "Android panic dump flash partition label" - default "kpanic" - ---help--- - If your platform uses a different flash partition label for storing - crashdumps, enter it here. - config STE bool "STE modem control driver" default n diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c3dc3cf11ce2..d2e8b6ce3b29 100755 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_C2PORT) += c2port/ obj-y += eeprom/ obj-y += cb710/ obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o -obj-$(CONFIG_APANIC) += apanic.o obj-$(CONFIG_MTK23D) += mtk23d.o obj-$(CONFIG_FM580X) += fm580x.o obj-$(CONFIG_MU509) += mu509.o @@ -36,4 +35,3 @@ obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/ obj-$(CONFIG_GPS_GNS7560) += gps/ obj-y += mpu3050/ obj-$(CONFIG_RK29_NEWTON) += newton.o - diff --git a/drivers/misc/apanic.c b/drivers/misc/apanic.c deleted file mode 100644 index fde087122473..000000000000 --- a/drivers/misc/apanic.c +++ /dev/null @@ -1,541 +0,0 @@ -/* drivers/misc/apanic.c - * - * Copyright (C) 2009 Google, Inc. - * Author: San Mehat - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct panic_header { - u32 magic; -#define PANIC_MAGIC 0xdeadf00d - - u32 version; -#define PHDR_VERSION 0x01 - - u32 console_offset; - u32 console_length; - - u32 threads_offset; - u32 threads_length; -}; - -#define CHECK_BB 0 - -struct apanic_data { - struct mtd_info *mtd; - struct panic_header curr; - void *bounce; - struct proc_dir_entry *apanic_console; - struct proc_dir_entry *apanic_threads; -}; - -static struct apanic_data drv_ctx; -static struct work_struct proc_removal_work; -static DEFINE_MUTEX(drv_mutex); - -static void apanic_erase_callback(struct erase_info *done) -{ - wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv; - wake_up(wait_q); -} - -static int apanic_proc_read(char *buffer, char **start, off_t offset, - int count, int *peof, void *dat) -{ - struct apanic_data *ctx = &drv_ctx; - size_t file_length; - off_t file_offset; - unsigned int page_no; - off_t page_offset; - int rc; - size_t len; - - if (!count) - return 0; - - mutex_lock(&drv_mutex); - - switch ((int) dat) { - case 1: /* apanic_console */ - file_length = ctx->curr.console_length; - file_offset = ctx->curr.console_offset; - break; - case 2: /* apanic_threads */ - file_length = ctx->curr.threads_length; - file_offset = ctx->curr.threads_offset; - break; - default: - pr_err("Bad dat (%d)\n", (int) dat); - mutex_unlock(&drv_mutex); - return -EINVAL; - } - - if ((offset + count) > file_length) { - mutex_unlock(&drv_mutex); - return 0; - } - - /* We only support reading a maximum of a flash page */ - if (count > ctx->mtd->writesize) - count = ctx->mtd->writesize; - - page_no = (file_offset + offset) / ctx->mtd->writesize; - page_offset = (file_offset + offset) % ctx->mtd->writesize; - - rc = ctx->mtd->read(ctx->mtd, - (page_no * ctx->mtd->writesize), - ctx->mtd->writesize, - &len, ctx->bounce); - - if (page_offset) - count -= page_offset; - memcpy(buffer, ctx->bounce + page_offset, count); - - *start = count; - - if ((offset + count) == file_length) - *peof = 1; - - mutex_unlock(&drv_mutex); - return count; -} - -static void mtd_panic_erase(void) -{ - struct apanic_data *ctx = &drv_ctx; - struct erase_info erase; - DECLARE_WAITQUEUE(wait, current); - wait_queue_head_t wait_q; - int rc, i; - - init_waitqueue_head(&wait_q); - erase.mtd = ctx->mtd; - erase.callback = apanic_erase_callback; - erase.len = ctx->mtd->erasesize; - erase.priv = (u_long)&wait_q; - for (i = 0; i < ctx->mtd->size; i += ctx->mtd->erasesize) { - erase.addr = i; - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&wait_q, &wait); - - rc = ctx->mtd->block_isbad(ctx->mtd, erase.addr); - if (rc < 0) { - printk(KERN_ERR - "apanic: Bad block check " - "failed (%d)\n", rc); - goto out; - } - if (rc) { - printk(KERN_WARNING - "apanic: Skipping erase of bad " - "block @%llx\n", erase.addr); - set_current_state(TASK_RUNNING); - remove_wait_queue(&wait_q, &wait); - continue; - } - - rc = ctx->mtd->erase(ctx->mtd, &erase); - if (rc) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&wait_q, &wait); - printk(KERN_ERR - "apanic: Erase of 0x%llx, 0x%llx failed\n", - (unsigned long long) erase.addr, - (unsigned long long) erase.len); - if (rc == -EIO) { - if (ctx->mtd->block_markbad(ctx->mtd, - erase.addr)) { - printk(KERN_ERR - "apanic: Err marking blk bad\n"); - goto out; - } - printk(KERN_INFO - "apanic: Marked a bad block" - " @%llx\n", erase.addr); - continue; - } - goto out; - } - schedule(); - remove_wait_queue(&wait_q, &wait); - } - printk(KERN_DEBUG "apanic: %s partition erased\n", - CONFIG_APANIC_PLABEL); -out: - return; -} - -static void apanic_remove_proc_work(struct work_struct *work) -{ - struct apanic_data *ctx = &drv_ctx; - - mutex_lock(&drv_mutex); - mtd_panic_erase(); - memset(&ctx->curr, 0, sizeof(struct panic_header)); - if (ctx->apanic_console) { - remove_proc_entry("apanic_console", NULL); - ctx->apanic_console = NULL; - } - if (ctx->apanic_threads) { - remove_proc_entry("apanic_threads", NULL); - ctx->apanic_threads = NULL; - } - mutex_unlock(&drv_mutex); -} - -static int apanic_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - schedule_work(&proc_removal_work); - return count; -} - -static void mtd_panic_notify_add(struct mtd_info *mtd) -{ - struct apanic_data *ctx = &drv_ctx; - struct panic_header *hdr = ctx->bounce; - size_t len; - int rc; - - if (strcmp(mtd->name, CONFIG_APANIC_PLABEL)) - return; - - ctx->mtd = mtd; - - if (mtd->block_isbad(mtd, 0)) { - printk(KERN_ERR "apanic: Offset 0 bad block. Boourns!\n"); - goto out_err; - } - - rc = mtd->read(mtd, 0, mtd->writesize, &len, ctx->bounce); - if (rc && rc == -EBADMSG) { - printk(KERN_WARNING - "apanic: Bad ECC on block 0 (ignored)\n"); - } else if (rc && rc != -EUCLEAN) { - printk(KERN_ERR "apanic: Error reading block 0 (%d)\n", rc); - goto out_err; - } - - if (len != mtd->writesize) { - printk(KERN_ERR "apanic: Bad read size (%d)\n", rc); - goto out_err; - } - - printk(KERN_INFO "apanic: Bound to mtd partition '%s'\n", mtd->name); - - if (hdr->magic != PANIC_MAGIC) { - printk(KERN_INFO "apanic: No panic data available\n"); - mtd_panic_erase(); - return; - } - - if (hdr->version != PHDR_VERSION) { - printk(KERN_INFO "apanic: Version mismatch (%d != %d)\n", - hdr->version, PHDR_VERSION); - mtd_panic_erase(); - return; - } - - memcpy(&ctx->curr, hdr, sizeof(struct panic_header)); - - printk(KERN_INFO "apanic: c(%u, %u) t(%u, %u)\n", - hdr->console_offset, hdr->console_length, - hdr->threads_offset, hdr->threads_length); - - if (hdr->console_length) { - ctx->apanic_console = create_proc_entry("apanic_console", - S_IFREG | S_IRUGO, NULL); - if (!ctx->apanic_console) - printk(KERN_ERR "%s: failed creating procfile\n", - __func__); - else { - ctx->apanic_console->read_proc = apanic_proc_read; - ctx->apanic_console->write_proc = apanic_proc_write; - ctx->apanic_console->size = hdr->console_length; - ctx->apanic_console->data = (void *) 1; - } - } - - if (hdr->threads_length) { - ctx->apanic_threads = create_proc_entry("apanic_threads", - S_IFREG | S_IRUGO, NULL); - if (!ctx->apanic_threads) - printk(KERN_ERR "%s: failed creating procfile\n", - __func__); - else { - ctx->apanic_threads->read_proc = apanic_proc_read; - ctx->apanic_threads->write_proc = apanic_proc_write; - ctx->apanic_threads->size = hdr->threads_length; - ctx->apanic_threads->data = (void *) 2; - } - } - - return; -out_err: - ctx->mtd = NULL; -} - -static void mtd_panic_notify_remove(struct mtd_info *mtd) -{ - struct apanic_data *ctx = &drv_ctx; - if (mtd == ctx->mtd) { - ctx->mtd = NULL; - printk(KERN_INFO "apanic: Unbound from %s\n", mtd->name); - } -} - -static struct mtd_notifier mtd_panic_notifier = { - .add = mtd_panic_notify_add, - .remove = mtd_panic_notify_remove, -}; - -static int in_panic = 0; - -static int apanic_writeflashpage(struct mtd_info *mtd, loff_t to, - const u_char *buf) -{ - int rc; - size_t wlen; - int panic = in_interrupt() | in_atomic(); - - if (panic && !mtd->panic_write) { - printk(KERN_EMERG "%s: No panic_write available\n", __func__); - return 0; - } else if (!panic && !mtd->write) { - printk(KERN_EMERG "%s: No write available\n", __func__); - return 0; - } - - if (panic) - rc = mtd->panic_write(mtd, to, mtd->writesize, &wlen, buf); - else - rc = mtd->write(mtd, to, mtd->writesize, &wlen, buf); - - if (rc) { - printk(KERN_EMERG - "%s: Error writing data to flash (%d)\n", - __func__, rc); - return rc; - } - - return wlen; -} - -extern int log_buf_copy(char *dest, int idx, int len); -extern void log_buf_clear(void); - -/* - * Writes the contents of the console to the specified offset in flash. - * Returns number of bytes written - */ -static int apanic_write_console(struct mtd_info *mtd, unsigned int off) -{ - struct apanic_data *ctx = &drv_ctx; - int saved_oip; - int idx = 0; - int rc, rc2; - unsigned int last_chunk = 0; - - while (!last_chunk) { - saved_oip = oops_in_progress; - oops_in_progress = 1; - rc = log_buf_copy(ctx->bounce, idx, mtd->writesize); - if (rc < 0) - break; - - if (rc != mtd->writesize) - last_chunk = rc; - - oops_in_progress = saved_oip; - if (rc <= 0) - break; - if (rc != mtd->writesize) - memset(ctx->bounce + rc, 0, mtd->writesize - rc); -#if CHECK_BB -check_badblock: - rc = mtd->block_isbad(mtd, off); - if (rc < 0) { - printk(KERN_ERR - "apanic: Bad block check " - "failed (%d)\n", rc); - } - if (rc) { - printk(KERN_WARNING - "apanic: Skipping over bad " - "block @%x\n", off); - off += mtd->erasesize; - printk("chk %u %llu\n", off, mtd->size); - if (off >= mtd->size) { - printk(KERN_EMERG - "apanic: Too many bad blocks!\n"); - return -EIO; - } - goto check_badblock; - } -#endif - - rc2 = apanic_writeflashpage(mtd, off, ctx->bounce); - if (rc2 <= 0) { - printk(KERN_EMERG - "apanic: Flash write failed (%d)\n", rc2); - return rc2; - } - if (!last_chunk) - idx += rc2; - else - idx += last_chunk; - off += rc2; - } - return idx; -} - -static int apanic(struct notifier_block *this, unsigned long event, - void *ptr) -{ - struct apanic_data *ctx = &drv_ctx; - struct panic_header *hdr = (struct panic_header *) ctx->bounce; - int console_offset = 0; - int console_len = 0; - int threads_offset = 0; - int threads_len = 0; - int rc; - - if (in_panic) - return NOTIFY_DONE; - in_panic = 1; -#ifdef CONFIG_PREEMPT - /* Ensure that cond_resched() won't try to preempt anybody */ - add_preempt_count(PREEMPT_ACTIVE); -#endif - - if (!ctx->mtd) - goto out; - - if (ctx->curr.magic) { - printk(KERN_EMERG "Crash partition in use!\n"); - goto out; - } - console_offset = ctx->mtd->writesize; - - /* - * Write out the console - */ - console_len = apanic_write_console(ctx->mtd, console_offset); - if (console_len < 0) { - printk(KERN_EMERG "Error writing console to panic log! (%d)\n", - console_len); - console_len = 0; - } - - /* - * Write out all threads - */ - threads_offset = ALIGN(console_offset + console_len, - ctx->mtd->writesize); - if (!threads_offset) - threads_offset = ctx->mtd->writesize; - - log_buf_clear(); - show_state_filter(0); - threads_len = apanic_write_console(ctx->mtd, threads_offset); - if (threads_len < 0) { - printk(KERN_EMERG "Error writing threads to panic log! (%d)\n", - threads_len); - threads_len = 0; - } - - /* - * Finally write the panic header - */ - memset(ctx->bounce, 0, PAGE_SIZE); - hdr->magic = PANIC_MAGIC; - hdr->version = PHDR_VERSION; - - hdr->console_offset = console_offset; - hdr->console_length = console_len; - - hdr->threads_offset = threads_offset; - hdr->threads_length = threads_len; - - rc = apanic_writeflashpage(ctx->mtd, 0, ctx->bounce); - if (rc <= 0) { - printk(KERN_EMERG "apanic: Header write failed (%d)\n", - rc); - goto out; - } - - printk(KERN_EMERG "apanic: Panic dump sucessfully written to flash\n"); - - out: -#ifdef CONFIG_PREEMPT - sub_preempt_count(PREEMPT_ACTIVE); -#endif - in_panic = 0; - return NOTIFY_DONE; -} - -static struct notifier_block panic_blk = { - .notifier_call = apanic, -}; - -static int panic_dbg_get(void *data, u64 *val) -{ - apanic(NULL, 0, NULL); - return 0; -} - -static int panic_dbg_set(void *data, u64 val) -{ - BUG(); - return -1; -} - -DEFINE_SIMPLE_ATTRIBUTE(panic_dbg_fops, panic_dbg_get, panic_dbg_set, "%llu\n"); - -int __init apanic_init(void) -{ - register_mtd_user(&mtd_panic_notifier); - atomic_notifier_chain_register(&panic_notifier_list, &panic_blk); - debugfs_create_file("apanic", 0644, NULL, NULL, &panic_dbg_fops); - memset(&drv_ctx, 0, sizeof(drv_ctx)); - drv_ctx.bounce = (void *) __get_free_page(GFP_KERNEL); - INIT_WORK(&proc_removal_work, apanic_remove_proc_work); - printk(KERN_INFO "Android kernel panic handler initialized (bind=%s)\n", - CONFIG_APANIC_PLABEL); - return 0; -} - -module_init(apanic_init);