- more 2.6.17 port work (still does not build)
[linux-flexiantxendom0-3.2.10.git] / drivers / dump / dump_setup.c
1 /*
2  * Standard kernel function entry points for Linux crash dumps.
3  *
4  * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
5  * Copyright (C) 2004 - 2005 Hewlett-Packard Development Company, L.P.
6  * Copyright (C) 2000 - 2002 TurboLinux, Inc.  All rights reserved.
7  * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
8  * Copyright (C) 2002 Free Software Foundation, Inc. All rights reserved.
9  *
10  * This code is released under version 2 of the GNU GPL.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/dump.h>
15 #include <linux/sysrq.h>
16 #include <linux/reboot.h>
17
18 #include "dump_methods.h"
19
20
21 #define LKCD_VERSION    "7.0.1"
22 #define LKCD_DATE       "2005-06-01"
23 #define DUMP_MAJOR 0    /* dynamic major by default */
24
25 MODULE_AUTHOR("LKCD development team <lkcd-devel@lists.sourceforge.net>");
26 MODULE_DESCRIPTION("Linux Kernel Crash Dump (LKCD) driver");
27 MODULE_LICENSE("GPL");
28 MODULE_VERSION(LKCD_VERSION);
29
30 /*
31  * -----------------------------------------------------------------------
32  *                         V A R I A B L E S
33  * -----------------------------------------------------------------------
34  */
35
36 /* Dump tunables */
37 struct dump_config dump_config = {
38         .level          = 0,
39         .polling        = 1,
40         .reboot         = 1,
41         .comp_flag      = 0,
42         .comp_val       = 0,
43         .dump_device    = NULL,
44         .dump_addr      = 0,
45         .dumper         = NULL
46 };
47
48 /* forward declorations */
49 static int dump_target_init(int);
50 static int dumper_setup(const char *);
51 static int dump_compress_init(int compression_type);
52
53 /* sysfs input protection semaphore */
54 static DECLARE_MUTEX(dump_sysfs_mutex);
55
56 /* degree of system freeze when dumping */
57 enum dump_silence_levels dump_silence_level = DUMP_HARD_SPIN_CPUS;
58
59 /* Other global fields */
60 extern struct __dump_header dump_header;
61 struct dump_dev *dump_dev = NULL;  /* Active dump device */
62 struct dump_dev_driver *dump_dev_driver = NULL;  /* acutall driver device */
63 static int dump_compress = 0;
64 int dump_compress_level = 1;
65
66 static u32 dump_compress_none(const u8 *old, u32 oldsize, u8 *new, u32 newsize,
67                 unsigned long loc);
68 struct __dump_compress dump_none_compression = {
69         .compress_type  = DUMP_COMPRESS_NONE,
70         .compress_func  = dump_compress_none,
71         .compress_name  = "none",
72 };
73
74 /* static variables */
75 static int dump_okay = 0;
76 static spinlock_t dump_lock = SPIN_LOCK_UNLOCKED;
77
78 /* used for dump compressors */
79 static struct list_head dump_compress_list = LIST_HEAD_INIT(
80                 dump_compress_list);
81
82 /* list of registered dump targets */
83 static struct list_head dump_target_list = LIST_HEAD_INIT(dump_target_list);
84
85 /* lkcd info structure -- this is used by lcrash for basic system data */
86         struct __lkcdinfo lkcdinfo = {
87                 .ptrsz          = (sizeof(void *) * 8),
88 #if defined(__LITTLE_ENDIAN)
89                 .byte_order     = __LITTLE_ENDIAN,
90 #else
91                 .byte_order     = __BIG_ENDIAN,
92 #endif
93                 .page_shift     = PAGE_SHIFT,
94                 .page_size      = PAGE_SIZE,
95                 .page_mask      = PAGE_MASK,
96                 .page_offset    = PAGE_OFFSET,
97         };
98
99 struct dump_attribute {
100         struct attribute        attr;
101         ssize_t (*show) (struct dump_dev_driver *ddev, char *buf);
102         ssize_t (*store)(struct dump_dev_driver *ddev, const char *buf,
103                         size_t count);
104 };
105
106 #define DUMPVAR_ATTR(_name, _mode, _show, _store) \
107         struct dump_attribute dump_attr_##_name = { \
108                 .attr = {.name = __stringify(_name), \
109                         .mode = _mode, \
110                         .owner = THIS_MODULE}, \
111                 .show = _show, \
112                 .store = _store, \
113         };
114
115 #define to_dump_attr(_attr) container_of(_attr,struct dump_attribute,attr)
116 #define to_dump_dev_driver(obj) container_of(obj,struct dump_dev_driver,kobj)
117
118 ssize_t dump_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
119 {
120         struct dump_dev_driver *dev = to_dump_dev_driver(kobj);
121         struct dump_attribute *dump_attr = to_dump_attr(attr);
122         ssize_t ret = 0;
123
124         if (!dump_config.dumper)
125                 /* dump device must be configured first */
126                 return -ENODEV;
127
128         down_interruptible(&dump_sysfs_mutex);
129         if (dump_attr->show)
130                 ret = dump_attr->show(dev, buf);
131         up(&dump_sysfs_mutex);
132
133         return ret;
134 }
135
136 ssize_t dump_attr_store(struct kobject *kobj, struct attribute *attr,
137                 const char *buf, size_t count)
138 {
139         struct dump_dev_driver *dev = to_dump_dev_driver(kobj);
140         struct dump_attribute *dump_attr = to_dump_attr(attr);
141         ssize_t ret = 0;
142
143         if (!dump_config.dumper)
144                 /* dump device must be configured first */
145                 return -ENODEV;
146
147         if (dump_attr->store)
148                 ret = dump_attr->store(dev, buf, count);
149         return ret;
150 }
151
152 static struct sysfs_ops dump_attr_ops = {
153         .show = dump_attr_show,
154         .store = dump_attr_store,
155 };
156
157 ssize_t show_version(struct dump_dev_driver *ddev, char *buf)
158 {
159         return sprintf(buf, "%s\n%s\n", LKCD_VERSION, LKCD_DATE);
160 }
161
162 ssize_t show_polling(struct dump_dev_driver *ddev, char *buf)
163 {
164         return sprintf(buf, "%d\n", dump_config.polling);
165 }
166
167 ssize_t store_polling(struct dump_dev_driver *ddev, const char *buf,
168                 size_t count)
169 {
170         ulong tmp;
171
172         if (buf == NULL)
173                 return -EINVAL;
174
175         if ((sscanf(buf, "%lx", &tmp)) != 1)
176                 return -EINVAL;
177
178         if ((tmp < 0) || (tmp > 1))
179                 return -EINVAL;
180
181         dump_config.polling = tmp;
182
183         /* If dump_device has already been initalized and we
184          * want to change the polling status we need to
185          * re-init dumpdev with the new polling value.
186          */
187         if (dump_config.dump_device)
188                 dumper_setup(dump_config.dump_device);
189
190         return count;
191 }
192
193 ssize_t show_dumpdev(struct dump_dev_driver *ddev, char *buf)
194 {
195         return sprintf(buf, "%s\n", dump_config.dump_device);
196 }
197
198 ssize_t store_dumpdev(struct dump_dev_driver *ddev, const char *buf,
199                 size_t count)
200 {
201         int err, type;
202         printk("LKCD: Configuring dump device\n");
203
204         if (buf == NULL)
205                 return -EINVAL;
206
207         if ((strncmp(buf, "eth", 3) == 0) |
208                         (strncmp(buf, "ath", 3) == 0) |
209                         (strncmp(buf, "wlan", 4) == 0)){
210
211                 type = DUMP_TYPE_NETDEV;
212         } else
213                                 type = DUMP_TYPE_BLOCKDEV;
214
215         if (dump_target_init(type) < 0)
216                 return -EINVAL;
217
218         __dump_open();
219
220         err = dumper_setup(buf);
221         if (err)
222                 return -EINVAL;
223
224         /* do we have a compress value that was set
225          * before we had a dump dump_dev that needs
226          * to be initalized?
227          */
228         if (dump_config.comp_flag) {
229                 dump_compress_init((int)dump_config.comp_val);
230                 dump_config.comp_flag = 0;
231         }
232
233         return count;
234 }
235
236 ssize_t show_level(struct dump_dev_driver *ddev, char *buf)
237 {
238         return sprintf(buf, "0x%lx\n", dump_config.level);
239 }
240
241 ssize_t store_level(struct dump_dev_driver *ddev, const char *buf,
242                 size_t count)
243 {
244         ulong tmp;
245
246         if (buf == NULL)
247                 return -EINVAL;
248
249         if ( ( sscanf(buf, "%lx", &tmp)) != 1)
250                 return -EINVAL;
251
252         if (tmp < 0)
253                 return -EINVAL;
254
255         dump_config.level = 0;
256
257         /* FIXME this is terrible and make it impossible for
258          * the user to see what they set. I'm leaving it only for
259          * the first rev and will fix this soon! -- troyh
260          */
261         switch ((int)tmp){
262                 case DUMP_LEVEL_ALL:
263                 case DUMP_LEVEL_ALL_RAM:
264                         dump_config.level |= DUMP_MASK_UNUSED;
265                 case DUMP_LEVEL_USED:
266                         dump_config.level |= DUMP_MASK_USED;
267                 case DUMP_LEVEL_KERN:
268                         dump_config.level |= DUMP_MASK_KERN;
269                 case DUMP_LEVEL_HEADER:
270                         dump_config.level |= DUMP_MASK_HEADER;
271                 case DUMP_LEVEL_NONE:
272                         break;
273                 default:
274                         return (-EINVAL);
275         }
276         printk("LKCD: Dump Level 0x%lx\n", dump_config.level);
277
278         return count;
279 }
280
281
282 ssize_t show_compress(struct dump_dev_driver *ddev, char *buf)
283 {
284
285         if (dump_config.comp_flag)
286                 return sprintf(buf, "%d\n", dump_config.comp_val);
287         else
288                 return sprintf(buf, "%d\n", dump_compress);
289 }
290
291 ssize_t store_compress(struct dump_dev_driver *ddev, const char *buf,
292                 size_t count)
293 {
294         ulong tmp;
295
296         if (buf == NULL)
297                 return -EINVAL;
298
299         if ((sscanf(buf, "%lx", &tmp)) != 1)
300                 return -EINVAL;
301
302         if ((tmp < 0) | (tmp > 2))
303                 return -EINVAL;
304
305         /* dump_config.dump_device must valid first to establish
306          * the compression type. Will take the parameter now and
307          * delay the compress_init until we have a dump_device.
308          */
309         if (dump_config.dump_device == 0){
310                 dump_config.comp_flag = 1;
311                 dump_config.comp_val = tmp;
312         } else {
313                 dump_compress_init((int)tmp);
314         }
315
316         return count;
317 }
318
319 ssize_t show_compress_level(struct dump_dev_driver *ddev, char *buf)
320 {
321         return sprintf(buf, "%d\n", dump_compress_level);
322 }
323
324 ssize_t store_compress_level(struct dump_dev_driver *ddev, const char *buf, size_t count)
325 {
326         int tmp;
327
328         if (buf == NULL)
329                 return -EINVAL;
330
331         if (sscanf(buf, "%d", &tmp) != 1)
332                 return -EINVAL;
333
334         /* Small kludge:  We allow levels 1-9 here because that's what
335          * makes sense for gzip, which is currently the only compression
336          * type to make use of multiple levels.
337          */
338         if (tmp < 1 || tmp > 9)
339                 return -EINVAL;
340
341         dump_compress_level = tmp;
342
343         return count;
344 }
345
346 ssize_t show_reboot(struct dump_dev_driver *ddev, char *buf)
347 {
348         return sprintf(buf, "%d\n", dump_config.reboot);
349 }
350
351 ssize_t store_reboot(struct dump_dev_driver *ddev, const char *buf,
352                 size_t count)
353 {
354         ulong tmp;
355
356         if (buf == NULL)
357                 return -EINVAL;
358
359         if ((sscanf(buf, "%lx", &tmp)) != 1)
360                 return -EINVAL;
361
362         if ((tmp < 0) | (tmp > 1))
363                 return -EINVAL;
364
365         dump_config.reboot = tmp;
366
367         return count;
368 }
369
370
371
372 static DUMPVAR_ATTR(polling, 0664, show_polling, store_polling);
373 static DUMPVAR_ATTR(dumpdev, 0664, show_dumpdev, store_dumpdev);
374 static DUMPVAR_ATTR(level, 0664, show_level, store_level);
375 static DUMPVAR_ATTR(compress, 0664, show_compress, store_compress);
376 static DUMPVAR_ATTR(compress_level, 0664, show_compress_level, store_compress_level);
377 static DUMPVAR_ATTR(reboot, 0664, show_reboot, store_reboot);
378 static DUMPVAR_ATTR(version, 0444, show_version, NULL);
379
380 /* These are default attributes for the dump device
381  * There are none.
382  */
383 static struct attribute *def_attrs[] = {
384         NULL,
385 };
386
387 static struct dump_attribute *dump_attrs[] = {
388         &dump_attr_polling,
389         &dump_attr_dumpdev,
390         &dump_attr_level,
391         &dump_attr_compress,
392         &dump_attr_compress_level,
393         &dump_attr_reboot,
394         &dump_attr_version,
395         NULL,
396 };
397
398 /**
399  *      dump_release - free dump structure
400  *      @kobj:  kobject of dump structure
401  *
402  *      This is called when the refcount of the dump structure
403  *      reaches 0. This should happen right after we unregister,
404  *      but just in case, we use the release callback anyway.
405  */
406
407 static void dump_release(struct kobject *kobj)
408 {
409         struct dump_dev_driver *dev = to_dump_dev_driver(kobj);
410         kfree(dev);
411 }
412
413 static struct kobj_type ktype_dump = {
414         .release        = dump_release,
415         .sysfs_ops      = &dump_attr_ops,
416         .default_attrs  = def_attrs,
417 };
418
419 static decl_subsys(dump, &ktype_dump, NULL);
420
421
422 /*
423  * -----------------------------------------------------------------------
424  *              C O M P R E S S I O N   F U N C T I O N S
425  * -----------------------------------------------------------------------
426  */
427
428 /*
429  * Name: dump_compress_none()
430  * Func: Don't do any compression, period.
431  */
432         static u32
433 dump_compress_none(const u8 *old, u32 oldsize, u8 *new, u32 newsize,
434                 unsigned long loc)
435 {
436         /* just return the old size */
437         return oldsize;
438 }
439
440 /*
441  * Name: dump_execute()
442  * Func: Execute the dumping process.  This makes sure all the appropriate
443  *       fields are updated correctly, and calls dump_execute_memdump(),
444  *       which does the real work.
445  */
446 void dump_execute(const char *panic_str, const struct pt_regs *regs)
447 {
448         int state = -1;
449         unsigned long flags;
450         int loglevel_save = console_loglevel;
451
452         if (console_loglevel < 6) /* KERN_INFO */
453                 console_loglevel = 6;
454
455         /* make sure we can dump */
456         if (!dump_okay) {
457                 pr_info("LKCD: not yet configured, can't take dump now\n");
458                 return;
459         }
460
461         /* Exclude multiple dumps at the same time,
462          * and disable interrupts,  some drivers may re-enable
463          * interrupts in with silence()
464          *
465          * Try and acquire spin lock. If successful, leave preempt
466          * and interrupts disabled.  See spin_lock_irqsave in spinlock.h
467          */
468         local_irq_save(flags);
469         if (!spin_trylock(&dump_lock)) {
470                 local_irq_restore(flags);
471                 pr_info("LKCD: dump already in progress\n");
472                 return;
473         }
474
475         /* What state are interrupts really in? */
476         if (in_interrupt()) {
477                 if(in_irq())
478                         printk("LKCD: Dumping from interrupt handler!\n");
479                 else
480                         printk("LKCD: Dumping from bottom half!\n");
481
482                 /*
483                  * If we are not doing polling I/O then we should attempt
484                  * to clean up the irq state.
485                  *
486                  * If polling I/O falls back to interrupt-driven mode then
487                  * it will need to clean the IRQ state
488                  */
489                 if (!(dump_config.polling))
490                         __dump_clean_irq_state();
491         }
492
493         /* Bring system into the strictest level of quiescing for min drift
494          * dump drivers can soften this as required in dev->ops->silence()
495          */
496         dump_oncpu = smp_processor_id() + 1;
497         dump_silence_level = DUMP_HARD_SPIN_CPUS;
498
499         state = dump_generic_execute(panic_str, regs);
500
501         dump_oncpu = 0;
502         spin_unlock_irqrestore(&dump_lock, flags);
503
504         if (state < 0) {
505                 printk("LKCD: Dump Incomplete or failed!\n");
506         } else {
507                 printk("LKCD: Dump Complete; %d dump pages saved.\n",
508                                 dump_header.dh_num_dump_pages);
509         }
510
511         console_loglevel = loglevel_save;
512
513         if (dump_config.reboot)
514                 emergency_restart();
515
516 }
517
518 /*
519  * Name: dump_register_compression()
520  * Func: Register a dump compression mechanism.
521  */
522 void dump_register_compression(struct __dump_compress *item)
523 {
524         if (item)
525                 list_add(&(item->list), &dump_compress_list);
526 }
527
528 /*
529  * Name: dump_unregister_compression()
530  * Func: Remove a dump compression mechanism, and re-assign the dump
531  *       compression pointer if necessary.
532  */
533 void dump_unregister_compression(int compression_type)
534 {
535         struct list_head *tmp;
536         struct __dump_compress *dc;
537
538         /* let's make sure our list is valid */
539         if (compression_type == DUMP_COMPRESS_NONE)
540                 return;
541         list_for_each(tmp, &dump_compress_list) {
542                 dc = list_entry(tmp, struct __dump_compress, list);
543                 if (dc->compress_type == compression_type) {
544                         /*
545                          * If we're currently configured to dump using
546                          * the compression mechanism we're removing,
547                          * unconfigure ourselves.
548                          */
549                         if (dump_config.dumper &&
550                                         dump_config.dumper->compress == dc) {
551                                 dump_okay = 0;
552                                 dump_unconfigure();
553                                 dump_dev = NULL;
554                                 dump_config.dumper = NULL;
555                         }
556                         list_del(&(dc->list));
557                         break;
558                 }
559         }
560 }
561
562 /*
563  * Name: dump_compress_init()
564  * Func: Initialize (or re-initialize) compression scheme.
565  */
566 static int dump_compress_init(int compression_type)
567 {
568         struct list_head *tmp;
569         struct __dump_compress *dc;
570
571         list_for_each(tmp, &dump_compress_list) {
572                 dc = list_entry(tmp, struct __dump_compress, list);
573                 if (dc->compress_type == compression_type) {
574                         dump_config.dumper->compress = dc;
575                         dump_compress = compression_type;
576                         printk("LKCD: %s compression initalized\n",
577                                         dc->compress_name);
578                         return 0;
579                 }
580         }
581
582         printk("LKCD: compression_type:%d not found\n", compression_type);
583         return -ENODATA;
584 }
585
586 static int dumper_setup(const char *devid)
587 {
588         int ret = 0;
589
590         /* unconfigure old dumper if it exists */
591         dump_okay = 0;
592         if (dump_config.dumper) {
593                 printk("LKCD: Unconfiguring current dumper\n");
594                 dump_unconfigure();
595         }
596         /* set up new dumper */
597         dump_config.dumper = &dumper_singlestage;
598
599         dump_config.dumper->dev = dump_dev;
600
601         if (dump_config.dump_device != devid) {
602                 kfree(dump_config.dump_device);
603                 if (!(dump_config.dump_device = kstrdup(devid, GFP_KERNEL)))
604                         return -ENOMEM;
605         }
606
607         ret = dump_configure(devid);
608         if (!ret) {
609                 dump_okay = 1;
610                 printk("LKCD: %s dumper set up for dev %s\n",
611                                 dump_config.dumper->name,
612                                 dump_config.dump_device);
613         } else {
614                 printk("LKCD: %s dumper set up failed for dev %s\n",
615                                 dump_config.dumper->name,
616                                 dump_config.dump_device);
617                 dump_config.dumper = NULL;
618                 dump_config.dump_device = NULL;
619         }
620         return ret;
621 }
622
623 static int dump_target_init(int type)
624 {
625         struct list_head *tmp;
626         struct dump_dev *dev;
627
628         list_for_each(tmp, &dump_target_list) {
629                 dev = list_entry(tmp, struct dump_dev, list);
630                 if (type == dev->type) {
631                         dump_dev = dev;
632                         return 0;
633                 }
634         }
635
636         return -1;
637 }
638
639
640
641 /*
642  * -----------------------------------------------------------------------
643  *                     I N I T   F U N C T I O N S
644  * -----------------------------------------------------------------------
645  */
646
647 static void dump_populate_dir(struct dump_dev_driver * ddev)
648 {
649         struct dump_attribute *attr;
650         int err = 0, i;
651
652         for (i = 0; (attr = dump_attrs[i]) && !err; i++) {
653                 if (attr->show)
654                         err = sysfs_create_file(&dump_subsys.kset.kobj,
655                                         &attr->attr);
656         }
657 }
658
659 /*
660  * These register and unregister routines are exported for modules
661  * to register their dump drivers (like block, net etc)
662  */
663 int dump_register_device(struct dump_dev *ddev)
664 {
665         struct list_head *tmp;
666         struct dump_dev *dev;
667
668         list_for_each(tmp, &dump_target_list) {
669                 dev = list_entry(tmp, struct dump_dev, list);
670                 if (ddev->type == dev->type) {
671                         printk("LKCD: Target type %d already registered\n",
672                                         dev->type);
673                         return -1; /* return proper error */
674                 }
675         }
676         list_add(&(ddev->list), &dump_target_list);
677
678         return 0;
679 }
680
681 void dump_unregister_device(struct dump_dev *ddev)
682 {
683         list_del(&(ddev->list));
684         if (ddev != dump_dev)
685                 return;
686
687         dump_okay = 0;
688
689         if (dump_config.dumper)
690                 dump_unconfigure();
691
692         dump_okay = 0;
693         dump_dev = NULL;
694         dump_config.dumper = NULL;
695 }
696
697 static int panic_event(struct notifier_block *this, unsigned long event,
698                 void *ptr)
699 {
700         struct pt_regs regs;
701
702         get_current_regs(&regs);
703         dump_execute((const char *)ptr, &regs);
704         return 0;
705 }
706
707 extern struct notifier_block *panic_notifier_list;
708 static int panic_event(struct notifier_block *, unsigned long, void *);
709 static struct notifier_block panic_block = {
710         .notifier_call = panic_event,
711 };
712
713 #ifdef CONFIG_MAGIC_SYSRQ
714 /* Sysrq handler */
715 static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
716                 struct tty_struct *tty) {
717         if (!pt_regs) {
718                 struct pt_regs regs;
719                 get_current_regs(&regs);
720                 dump_execute("sysrq", &regs);
721
722         } else {
723                 dump_execute("sysrq", pt_regs);
724         }
725 }
726
727 static struct sysrq_key_op sysrq_crashdump_op = {
728         .handler        =       sysrq_handle_crashdump,
729         .help_msg       =       "Dump",
730         .action_msg     =       "Starting crash dump",
731 };
732 #endif
733
734 static inline void dump_sysrq_register(void)
735 {
736 #ifdef CONFIG_MAGIC_SYSRQ
737         register_sysrq_key(DUMP_SYSRQ_KEY, &sysrq_crashdump_op);
738 #endif
739 }
740
741 static inline void dump_sysrq_unregister(void)
742 {
743 #ifdef CONFIG_MAGIC_SYSRQ
744         unregister_sysrq_key(DUMP_SYSRQ_KEY, &sysrq_crashdump_op);
745 #endif
746 }
747
748 /*
749  * Name: dump_init()
750  * Func: Initialize the dump process.  This will set up any architecture
751  *       dependent code.
752  */
753 static int __init dump_init(void)
754 {
755         struct sysinfo info;
756         int err;
757
758         err = subsystem_register(&dump_subsys);
759         if (err)
760                 return err;
761
762
763         dump_dev_driver = kmalloc(sizeof(struct dump_dev_driver), GFP_KERNEL);
764         if (!dump_dev_driver) {
765                 subsystem_unregister(&dump_subsys);
766                 return -ENOMEM;
767         }
768
769         memset(dump_dev_driver, 0, sizeof(struct dump_dev_driver));
770
771         kobject_set_name(&dump_dev_driver->kobj, "dump_dev_driver");
772         kobj_set_kset_s(dump_dev_driver, dump_subsys);
773
774         /* initalize but do not register the kobject
775          * that represents the dump device, we only want
776          * if for refcount, the important attributes are
777          * assigned to the dump_subsys kobject anyway.
778          */
779         kobject_init(&dump_dev_driver->kobj);
780
781         dump_populate_dir(dump_dev_driver);
782
783         __dump_init((u64) PAGE_OFFSET);
784
785         /* set the dump_compression_list structure up */
786         dump_register_compression(&dump_none_compression);
787
788         /* grab the total memory size now (not if/when we crash) */
789         si_meminfo(&info);
790
791         /* set the memory size */
792         dump_header.dh_memory_size = (u64) info.totalram;
793
794         dump_sysrq_register();
795
796         notifier_chain_register(&panic_notifier_list, &panic_block);
797         dump_function_ptr = dump_execute;
798
799         pr_info("LKCD: Crash dump driver initialized.\n");
800         return 0;
801 }
802
803 static inline void dump_device_driver_unregister(struct dump_dev_driver *dev)
804 {
805         kobject_unregister(&dev->kobj);
806 }
807
808 static void __exit dump_cleanup(void)
809 {
810         subsystem_unregister(&dump_subsys);
811
812         if (dump_dev_driver) {
813                 dump_device_driver_unregister(dump_dev_driver);
814         }
815
816         dump_okay = 0;
817
818         if (dump_config.dumper)
819                 dump_unconfigure();
820
821         /* arch-specific cleanup routine */
822         __dump_cleanup();
823
824         /* ignore errors while unregistering -- since can't do anything */
825         dump_sysrq_unregister();
826         notifier_chain_unregister(&panic_notifier_list, &panic_block);
827         dump_function_ptr = NULL;
828
829         pr_info("LKCD: Crash dump driver unloaded.\n");
830 }
831
832 EXPORT_SYMBOL_GPL(dump_register_compression);
833 EXPORT_SYMBOL_GPL(dump_unregister_compression);
834 EXPORT_SYMBOL_GPL(dump_register_device);
835 EXPORT_SYMBOL_GPL(dump_unregister_device);
836 EXPORT_SYMBOL_GPL(dump_config);
837 EXPORT_SYMBOL_GPL(dump_compress_level);
838 EXPORT_SYMBOL_GPL(dump_silence_level);
839 EXPORT_SYMBOL_GPL(__dump_irq_enable);
840 EXPORT_SYMBOL_GPL(__dump_irq_restore);
841
842 module_init(dump_init);
843 module_exit(dump_cleanup);