Merge remote-tracking branch 'origin/develop-3.0' into develop-3.0-jb
[firefly-linux-kernel-4.4.55.git] / drivers / misc / apanic.c
1 /* drivers/misc/apanic.c
2  *
3  * Copyright (C) 2009 Google, Inc.
4  * Author: San Mehat <san@android.com>
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <linux/errno.h>
21 #include <linux/init.h>
22 #include <linux/interrupt.h>
23 #include <linux/device.h>
24 #include <linux/types.h>
25 #include <linux/delay.h>
26 #include <linux/sched.h>
27 #include <linux/wait.h>
28 #include <linux/wakelock.h>
29 #include <linux/platform_device.h>
30 #include <linux/uaccess.h>
31 #include <linux/mtd/mtd.h>
32 #include <linux/notifier.h>
33 #include <linux/mtd/mtd.h>
34 #include <linux/debugfs.h>
35 #include <linux/fs.h>
36 #include <linux/proc_fs.h>
37 #include <linux/mutex.h>
38 #include <linux/workqueue.h>
39 #include <linux/preempt.h>
40
41 extern void ram_console_enable_console(int);
42
43 struct panic_header {
44         u32 magic;
45 #define PANIC_MAGIC 0xdeadf00d
46
47         u32 version;
48 #define PHDR_VERSION   0x01
49
50         u32 console_offset;
51         u32 console_length;
52
53         u32 threads_offset;
54         u32 threads_length;
55 };
56
57 struct apanic_data {
58         struct mtd_info         *mtd;
59         struct panic_header     curr;
60         void                    *bounce;
61         struct proc_dir_entry   *apanic_console;
62         struct proc_dir_entry   *apanic_threads;
63 };
64
65 static struct apanic_data drv_ctx;
66 static struct work_struct proc_removal_work;
67 static DEFINE_MUTEX(drv_mutex);
68
69 static unsigned int *apanic_bbt;
70 static unsigned int apanic_erase_blocks;
71 static unsigned int apanic_good_blocks;
72
73 static void set_bb(unsigned int block, unsigned int *bbt)
74 {
75         unsigned int flag = 1;
76
77         BUG_ON(block >= apanic_erase_blocks);
78
79         flag = flag << (block%32);
80         apanic_bbt[block/32] |= flag;
81         apanic_good_blocks--;
82 }
83
84 static unsigned int get_bb(unsigned int block, unsigned int *bbt)
85 {
86         unsigned int flag;
87
88         BUG_ON(block >= apanic_erase_blocks);
89
90         flag = 1 << (block%32);
91         return apanic_bbt[block/32] & flag;
92 }
93
94 static void alloc_bbt(struct mtd_info *mtd, unsigned int *bbt)
95 {
96         int bbt_size;
97         apanic_erase_blocks = (mtd->size)>>(mtd->erasesize_shift);
98         bbt_size = (apanic_erase_blocks+32)/32;
99
100         apanic_bbt = kmalloc(bbt_size*4, GFP_KERNEL);
101         memset(apanic_bbt, 0, bbt_size*4);
102         apanic_good_blocks = apanic_erase_blocks;
103 }
104 static void scan_bbt(struct mtd_info *mtd, unsigned int *bbt)
105 {
106         int i;
107
108         for (i = 0; i < apanic_erase_blocks; i++) {
109                 if (mtd->block_isbad(mtd, i*mtd->erasesize))
110                         set_bb(i, apanic_bbt);
111         }
112 }
113
114 #define APANIC_INVALID_OFFSET 0xFFFFFFFF
115
116 static unsigned int phy_offset(struct mtd_info *mtd, unsigned int offset)
117 {
118         unsigned int logic_block = offset>>(mtd->erasesize_shift);
119         unsigned int phy_block;
120         unsigned good_block = 0;
121
122         for (phy_block = 0; phy_block < apanic_erase_blocks; phy_block++) {
123                 if (!get_bb(phy_block, apanic_bbt))
124                         good_block++;
125                 if (good_block == (logic_block + 1))
126                         break;
127         }
128
129         if (good_block != (logic_block + 1))
130                 return APANIC_INVALID_OFFSET;
131
132         return offset + ((phy_block-logic_block)<<mtd->erasesize_shift);
133 }
134
135 static void apanic_erase_callback(struct erase_info *done)
136 {
137         wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv;
138         wake_up(wait_q);
139 }
140
141 static int apanic_proc_read(char *buffer, char **start, off_t offset,
142                                int count, int *peof, void *dat)
143 {
144         struct apanic_data *ctx = &drv_ctx;
145         size_t file_length;
146         off_t file_offset;
147         unsigned int page_no;
148         off_t page_offset;
149         int rc;
150         size_t len;
151
152         if (!count)
153                 return 0;
154
155         mutex_lock(&drv_mutex);
156
157         switch ((int) dat) {
158         case 1: /* apanic_console */
159                 file_length = ctx->curr.console_length;
160                 file_offset = ctx->curr.console_offset;
161                 break;
162         case 2: /* apanic_threads */
163                 file_length = ctx->curr.threads_length;
164                 file_offset = ctx->curr.threads_offset;
165                 break;
166         default:
167                 pr_err("Bad dat (%d)\n", (int) dat);
168                 mutex_unlock(&drv_mutex);
169                 return -EINVAL;
170         }
171
172         if ((offset + count) > file_length) {
173                 mutex_unlock(&drv_mutex);
174                 return 0;
175         }
176
177         /* We only support reading a maximum of a flash page */
178         if (count > ctx->mtd->writesize)
179                 count = ctx->mtd->writesize;
180
181         page_no = (file_offset + offset) / ctx->mtd->writesize;
182         page_offset = (file_offset + offset) % ctx->mtd->writesize;
183
184
185         if (phy_offset(ctx->mtd, (page_no * ctx->mtd->writesize))
186                 == APANIC_INVALID_OFFSET) {
187                 pr_err("apanic: reading an invalid address\n");
188                 mutex_unlock(&drv_mutex);
189                 return -EINVAL;
190         }
191         rc = ctx->mtd->read(ctx->mtd,
192                 phy_offset(ctx->mtd, (page_no * ctx->mtd->writesize)),
193                 ctx->mtd->writesize,
194                 &len, ctx->bounce);
195
196 #ifdef CONFIG_MTD_RKNAND
197         if (count > (ctx->mtd->writesize - page_offset))
198                 count = ctx->mtd->writesize - page_offset;
199 #else
200         if (page_offset)
201                 count -= page_offset;
202 #endif
203         memcpy(buffer, ctx->bounce + page_offset, count);
204
205         *start = count;
206
207         if ((offset + count) == file_length)
208                 *peof = 1;
209
210         mutex_unlock(&drv_mutex);
211         return count;
212 }
213
214 static void mtd_panic_erase(void)
215 {
216         struct apanic_data *ctx = &drv_ctx;
217 #ifdef CONFIG_MTD_RKNAND
218         size_t wlen;
219         memset(ctx->bounce, 0, ctx->mtd->writesize);
220         ctx->mtd->write(ctx->mtd, 0, ctx->mtd->writesize, &wlen, ctx->bounce);
221 #else
222         struct erase_info erase;
223         DECLARE_WAITQUEUE(wait, current);
224         wait_queue_head_t wait_q;
225         int rc, i;
226
227         init_waitqueue_head(&wait_q);
228         erase.mtd = ctx->mtd;
229         erase.callback = apanic_erase_callback;
230         erase.len = ctx->mtd->erasesize;
231         erase.priv = (u_long)&wait_q;
232         for (i = 0; i < ctx->mtd->size; i += ctx->mtd->erasesize) {
233                 erase.addr = i;
234                 set_current_state(TASK_INTERRUPTIBLE);
235                 add_wait_queue(&wait_q, &wait);
236
237                 if (get_bb(erase.addr>>ctx->mtd->erasesize_shift, apanic_bbt)) {
238                         printk(KERN_WARNING
239                                "apanic: Skipping erase of bad "
240                                "block @%llx\n", erase.addr);
241                         set_current_state(TASK_RUNNING);
242                         remove_wait_queue(&wait_q, &wait);
243                         continue;
244                 }
245
246                 rc = ctx->mtd->erase(ctx->mtd, &erase);
247                 if (rc) {
248                         set_current_state(TASK_RUNNING);
249                         remove_wait_queue(&wait_q, &wait);
250                         printk(KERN_ERR
251                                "apanic: Erase of 0x%llx, 0x%llx failed\n",
252                                (unsigned long long) erase.addr,
253                                (unsigned long long) erase.len);
254                         if (rc == -EIO) {
255                                 if (ctx->mtd->block_markbad(ctx->mtd,
256                                                             erase.addr)) {
257                                         printk(KERN_ERR
258                                                "apanic: Err marking blk bad\n");
259                                         goto out;
260                                 }
261                                 printk(KERN_INFO
262                                        "apanic: Marked a bad block"
263                                        " @%llx\n", erase.addr);
264                                 set_bb(erase.addr>>ctx->mtd->erasesize_shift,
265                                         apanic_bbt);
266                                 continue;
267                         }
268                         goto out;
269                 }
270                 schedule();
271                 remove_wait_queue(&wait_q, &wait);
272         }
273 #endif
274         printk(KERN_DEBUG "apanic: %s partition erased\n",
275                CONFIG_APANIC_PLABEL);
276 out:
277         return;
278 }
279
280 static void apanic_remove_proc_work(struct work_struct *work)
281 {
282         struct apanic_data *ctx = &drv_ctx;
283
284         mutex_lock(&drv_mutex);
285         mtd_panic_erase();
286         memset(&ctx->curr, 0, sizeof(struct panic_header));
287         if (ctx->apanic_console) {
288                 remove_proc_entry("apanic_console", NULL);
289                 ctx->apanic_console = NULL;
290         }
291         if (ctx->apanic_threads) {
292                 remove_proc_entry("apanic_threads", NULL);
293                 ctx->apanic_threads = NULL;
294         }
295         mutex_unlock(&drv_mutex);
296 }
297
298 static int apanic_proc_write(struct file *file, const char __user *buffer,
299                                 unsigned long count, void *data)
300 {
301         schedule_work(&proc_removal_work);
302         return count;
303 }
304
305 static void mtd_panic_notify_add(struct mtd_info *mtd)
306 {
307         struct apanic_data *ctx = &drv_ctx;
308         struct panic_header *hdr = ctx->bounce;
309         size_t len;
310         int rc;
311         int    proc_entry_created = 0;
312
313         if (strcmp(mtd->name, CONFIG_APANIC_PLABEL))
314                 return;
315
316         ctx->mtd = mtd;
317
318         alloc_bbt(mtd, apanic_bbt);
319         scan_bbt(mtd, apanic_bbt);
320
321         if (apanic_good_blocks == 0) {
322                 printk(KERN_ERR "apanic: no any good blocks?!\n");
323                 goto out_err;
324         }
325
326         rc = mtd->read(mtd, phy_offset(mtd, 0), mtd->writesize,
327                         &len, ctx->bounce);
328         if (rc && rc == -EBADMSG) {
329                 printk(KERN_WARNING
330                        "apanic: Bad ECC on block 0 (ignored)\n");
331         } else if (rc && rc != -EUCLEAN) {
332                 printk(KERN_ERR "apanic: Error reading block 0 (%d)\n", rc);
333                 goto out_err;
334         }
335
336         if (len != mtd->writesize) {
337                 printk(KERN_ERR "apanic: Bad read size (%d)\n", rc);
338                 goto out_err;
339         }
340
341         printk(KERN_INFO "apanic: Bound to mtd partition '%s'\n", mtd->name);
342
343         if (hdr->magic != PANIC_MAGIC) {
344                 printk(KERN_INFO "apanic: No panic data available\n");
345 #ifndef CONFIG_MTD_RKNAND
346                 mtd_panic_erase();
347 #endif
348                 return;
349         }
350
351         if (hdr->version != PHDR_VERSION) {
352                 printk(KERN_INFO "apanic: Version mismatch (%d != %d)\n",
353                        hdr->version, PHDR_VERSION);
354 #ifndef CONFIG_MTD_RKNAND
355                 mtd_panic_erase();
356 #endif
357                 return;
358         }
359
360         memcpy(&ctx->curr, hdr, sizeof(struct panic_header));
361
362         printk(KERN_INFO "apanic: c(%u, %u) t(%u, %u)\n",
363                hdr->console_offset, hdr->console_length,
364                hdr->threads_offset, hdr->threads_length);
365
366         if (hdr->console_length) {
367                 ctx->apanic_console = create_proc_entry("apanic_console",
368                                                       S_IFREG | S_IRUGO, NULL);
369                 if (!ctx->apanic_console)
370                         printk(KERN_ERR "%s: failed creating procfile\n",
371                                __func__);
372                 else {
373                         ctx->apanic_console->read_proc = apanic_proc_read;
374                         ctx->apanic_console->write_proc = apanic_proc_write;
375                         ctx->apanic_console->size = hdr->console_length;
376                         ctx->apanic_console->data = (void *) 1;
377                         proc_entry_created = 1;
378                 }
379         }
380
381         if (hdr->threads_length) {
382                 ctx->apanic_threads = create_proc_entry("apanic_threads",
383                                                        S_IFREG | S_IRUGO, NULL);
384                 if (!ctx->apanic_threads)
385                         printk(KERN_ERR "%s: failed creating procfile\n",
386                                __func__);
387                 else {
388                         ctx->apanic_threads->read_proc = apanic_proc_read;
389                         ctx->apanic_threads->write_proc = apanic_proc_write;
390                         ctx->apanic_threads->size = hdr->threads_length;
391                         ctx->apanic_threads->data = (void *) 2;
392                         proc_entry_created = 1;
393                 }
394         }
395
396 #ifndef CONFIG_MTD_RKNAND
397         if (!proc_entry_created)
398                 mtd_panic_erase();
399 #endif
400
401         return;
402 out_err:
403         ctx->mtd = NULL;
404 }
405
406 static void mtd_panic_notify_remove(struct mtd_info *mtd)
407 {
408         struct apanic_data *ctx = &drv_ctx;
409         if (mtd == ctx->mtd) {
410                 ctx->mtd = NULL;
411                 printk(KERN_INFO "apanic: Unbound from %s\n", mtd->name);
412         }
413 }
414
415 static struct mtd_notifier mtd_panic_notifier = {
416         .add    = mtd_panic_notify_add,
417         .remove = mtd_panic_notify_remove,
418 };
419
420 static int in_panic = 0;
421
422 static int apanic_writeflashpage(struct mtd_info *mtd, loff_t to,
423                                  const u_char *buf)
424 {
425         int rc;
426         size_t wlen;
427         int panic = in_interrupt() | in_atomic();
428
429         if (panic && !mtd->panic_write) {
430                 printk(KERN_EMERG "%s: No panic_write available\n", __func__);
431                 return 0;
432         } else if (!panic && !mtd->write) {
433                 printk(KERN_EMERG "%s: No write available\n", __func__);
434                 return 0;
435         }
436
437         to = phy_offset(mtd, to);
438         if (to == APANIC_INVALID_OFFSET) {
439                 printk(KERN_EMERG "apanic: write to invalid address\n");
440                 return 0;
441         }
442
443         if (panic)
444                 rc = mtd->panic_write(mtd, to, mtd->writesize, &wlen, buf);
445         else
446                 rc = mtd->write(mtd, to, mtd->writesize, &wlen, buf);
447
448         if (rc) {
449                 printk(KERN_EMERG
450                        "%s: Error writing data to flash (%d)\n",
451                        __func__, rc);
452                 return rc;
453         }
454
455         return wlen;
456 }
457
458 extern int log_buf_copy(char *dest, int idx, int len);
459 extern void log_buf_clear(void);
460
461 /*
462  * Writes the contents of the console to the specified offset in flash.
463  * Returns number of bytes written
464  */
465 static int apanic_write_console(struct mtd_info *mtd, unsigned int off)
466 {
467         struct apanic_data *ctx = &drv_ctx;
468         int saved_oip;
469         int idx = 0;
470         int rc, rc2;
471         unsigned int last_chunk = 0;
472
473         while (!last_chunk) {
474                 saved_oip = oops_in_progress;
475                 oops_in_progress = 1;
476                 rc = log_buf_copy(ctx->bounce, idx, mtd->writesize);
477                 if (rc < 0)
478                         break;
479
480                 if (rc != mtd->writesize)
481                         last_chunk = rc;
482
483                 oops_in_progress = saved_oip;
484                 if (rc <= 0)
485                         break;
486                 if (rc != mtd->writesize)
487                         memset(ctx->bounce + rc, 0, mtd->writesize - rc);
488
489                 rc2 = apanic_writeflashpage(mtd, off, ctx->bounce);
490                 if (rc2 <= 0) {
491                         printk(KERN_EMERG
492                                "apanic: Flash write failed (%d)\n", rc2);
493                         return idx;
494                 }
495                 if (!last_chunk)
496                         idx += rc2;
497                 else
498                         idx += last_chunk;
499                 off += rc2;
500         }
501         return idx;
502 }
503
504 static int apanic(struct notifier_block *this, unsigned long event,
505                         void *ptr)
506 {
507         struct apanic_data *ctx = &drv_ctx;
508         struct panic_header *hdr = (struct panic_header *) ctx->bounce;
509         int console_offset = 0;
510         int console_len = 0;
511         int threads_offset = 0;
512         int threads_len = 0;
513         int rc;
514
515         if (in_panic)
516                 return NOTIFY_DONE;
517         in_panic = 1;
518 #ifdef CONFIG_PREEMPT
519         /* Ensure that cond_resched() won't try to preempt anybody */
520         add_preempt_count(PREEMPT_ACTIVE);
521 #endif
522         touch_softlockup_watchdog();
523
524         if (!ctx->mtd)
525                 goto out;
526
527         if (ctx->curr.magic) {
528                 printk(KERN_EMERG "Crash partition in use!\n");
529                 goto out;
530         }
531         console_offset = ctx->mtd->erasesize;
532
533         /*
534          * Write out the console
535          */
536         console_len = apanic_write_console(ctx->mtd, console_offset);
537         if (console_len < 0) {
538                 printk(KERN_EMERG "Error writing console to panic log! (%d)\n",
539                        console_len);
540                 console_len = 0;
541         }
542
543         /*
544          * Write out all threads
545          */
546         threads_offset = ALIGN(console_offset + console_len,
547                                ctx->mtd->writesize);
548         if (!threads_offset)
549                 threads_offset = ctx->mtd->writesize;
550
551 #ifdef CONFIG_ANDROID_RAM_CONSOLE
552         ram_console_enable_console(0);
553 #endif
554
555         log_buf_clear();
556         show_state_filter(0);
557         threads_len = apanic_write_console(ctx->mtd, threads_offset);
558         if (threads_len < 0) {
559                 printk(KERN_EMERG "Error writing threads to panic log! (%d)\n",
560                        threads_len);
561                 threads_len = 0;
562         }
563
564         /*
565          * Finally write the panic header
566          */
567         memset(ctx->bounce, 0, PAGE_SIZE);
568         hdr->magic = PANIC_MAGIC;
569         hdr->version = PHDR_VERSION;
570
571         hdr->console_offset = console_offset;
572         hdr->console_length = console_len;
573
574         hdr->threads_offset = threads_offset;
575         hdr->threads_length = threads_len;
576
577         rc = apanic_writeflashpage(ctx->mtd, 0, ctx->bounce);
578         if (rc <= 0) {
579                 printk(KERN_EMERG "apanic: Header write failed (%d)\n",
580                        rc);
581                 goto out;
582         }
583
584         printk(KERN_EMERG "apanic: Panic dump sucessfully written to flash\n");
585
586  out:
587 #ifdef CONFIG_PREEMPT
588         sub_preempt_count(PREEMPT_ACTIVE);
589 #endif
590         in_panic = 0;
591         return NOTIFY_DONE;
592 }
593
594 static struct notifier_block panic_blk = {
595         .notifier_call  = apanic,
596 };
597
598 static int panic_dbg_get(void *data, u64 *val)
599 {
600         apanic(NULL, 0, NULL);
601         return 0;
602 }
603
604 static int panic_dbg_set(void *data, u64 val)
605 {
606         BUG();
607         return -1;
608 }
609
610 DEFINE_SIMPLE_ATTRIBUTE(panic_dbg_fops, panic_dbg_get, panic_dbg_set, "%llu\n");
611
612 int __init apanic_init(void)
613 {
614         register_mtd_user(&mtd_panic_notifier);
615         atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
616         debugfs_create_file("apanic", 0644, NULL, NULL, &panic_dbg_fops);
617         memset(&drv_ctx, 0, sizeof(drv_ctx));
618         drv_ctx.bounce = (void *) __get_free_page(GFP_KERNEL);
619         INIT_WORK(&proc_removal_work, apanic_remove_proc_work);
620         printk(KERN_INFO "Android kernel panic handler initialized (bind=%s)\n",
621                CONFIG_APANIC_PLABEL);
622         return 0;
623 }
624
625 module_init(apanic_init);