2 * LCD Oops/Panic logger
4 * Copyright (C) 2010 Samsung Electronics.
5 * Inki Dae <inki.dae@samsung.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/kmsg_dump.h>
26 #include <linux/time.h>
28 #include <linux/ioport.h>
29 #include <linux/delay.h>
30 #include <linux/platform_device.h>
34 #define LCDOOPS_HEADER_SIZE (5 + sizeof(struct timeval))
36 #define RECORD_SIZE 4096
38 static int dump_oops = 1;
39 module_param(dump_oops, int, 0600);
40 MODULE_PARM_DESC(dump_oops,
41 "set to 1 to dump oopses, 0 to only dump panics (default 1)");
43 static struct lcdoops_context {
44 struct kmsg_dumper dump;
49 static void lcdoops_do_dump(struct kmsg_dumper *dumper,
50 enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
51 const char *s2, unsigned long l2)
53 struct lcdoops_context *cxt = container_of(dumper,
54 struct lcdoops_context, dump);
55 unsigned long s1_start, s2_start;
56 unsigned long l1_cpy, l2_cpy;
58 /* Only dump oopses if dump_oops is set */
59 if (reason == KMSG_DUMP_OOPS && !dump_oops)
62 l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - LCDOOPS_HEADER_SIZE));
63 l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - LCDOOPS_HEADER_SIZE) - l2_cpy);
65 s2_start = l2 - l2_cpy;
66 s1_start = l1 - l1_cpy;
68 memcpy(buf, s1 + s1_start, l1_cpy);
69 memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
74 static int __init lcdoops_probe(struct platform_device *pdev)
76 struct lcdoops_context *cxt = &oops_cxt;
79 cxt->dump.dump = lcdoops_do_dump;
80 err = kmsg_dump_register(&cxt->dump);
82 printk(KERN_ERR "lcdoops: registering kmsg dumper failed");
92 static int __exit lcdoops_remove(struct platform_device *pdev)
94 struct lcdoops_context *cxt = &oops_cxt;
96 if (kmsg_dump_unregister(&cxt->dump) < 0)
97 printk(KERN_WARNING "lcdoops: could not unregister kmsg_dumper");
102 static struct platform_driver lcdoops_driver = {
103 .remove = __exit_p(lcdoops_remove),
106 .owner = THIS_MODULE,
110 static int __init lcdoops_init(void)
112 return platform_driver_probe(&lcdoops_driver, lcdoops_probe);
115 static void __exit lcdoops_exit(void)
117 platform_driver_unregister(&lcdoops_driver);
120 module_init(lcdoops_init);
121 module_exit(lcdoops_exit);
123 MODULE_LICENSE("GPL");
124 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
125 MODULE_DESCRIPTION("LCD Oops/Panic logger/driver");