This commit was manufactured by cvs2svn to create tag 'before-xenU'.
[linux-2.6.git] / drivers / dump / dump_execute.c
1 /*
2  * The file has the common/generic dump execution code 
3  *
4  * Started: Oct 2002 -  Suparna Bhattacharya <suparna@in.ibm.com>
5  *      Split and rewrote high level dump execute code to make use 
6  *      of dump method interfaces.
7  *
8  * Derived from original code in dump_base.c created by 
9  *      Matt Robinson <yakker@sourceforge.net>)
10  *      
11  * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
12  * Copyright (C) 2001 - 2002 Matt D. Robinson.  All rights reserved.
13  * Copyright (C) 2002 International Business Machines Corp. 
14  *
15  * Assumes dumper and dump config settings are in place
16  * (invokes corresponding dumper specific routines as applicable)
17  *
18  * This code is released under version 2 of the GNU GPL.
19  */
20 #include <linux/kernel.h>
21 #include <linux/notifier.h>
22 #include <linux/dump.h>
23 #include <linux/delay.h>
24 #include <linux/reboot.h>
25 #include "dump_methods.h"
26
27 struct notifier_block *dump_notifier_list; /* dump started/ended callback */
28
29 extern int panic_timeout;
30
31 /* Dump progress indicator */
32 void 
33 dump_speedo(int i)
34 {
35         static const char twiddle[4] =  { '|', '\\', '-', '/' };
36         printk("%c\b", twiddle[i&3]);
37 }
38
39 /* Make the device ready and write out the header */
40 int dump_begin(void)
41 {
42         int err = 0;
43
44         /* dump_dev = dump_config.dumper->dev; */
45         dumper_reset();
46         if ((err = dump_dev_silence())) {
47                 /* quiesce failed, can't risk continuing */
48                 /* Todo/Future: switch to alternate dump scheme if possible */
49                 printk("dump silence dev failed ! error %d\n", err);
50                 return err;
51         }
52
53         pr_debug("Writing dump header\n");
54         if ((err = dump_update_header())) {
55                 printk("dump update header failed ! error %d\n", err);
56                 dump_dev_resume();
57                 return err;
58         }
59
60         dump_config.dumper->curr_offset = DUMP_BUFFER_SIZE;
61
62         return 0;
63 }
64
65 /* 
66  * Write the dump terminator, a final header update and let go of 
67  * exclusive use of the device for dump.
68  */
69 int dump_complete(void)
70 {
71         int ret = 0;
72
73         if (dump_config.level != DUMP_LEVEL_HEADER) {
74                 if ((ret = dump_update_end_marker())) {
75                         printk("dump update end marker error %d\n", ret);
76                 }
77                 if ((ret = dump_update_header())) {
78                         printk("dump update header error %d\n", ret);
79                 }
80         }
81         ret = dump_dev_resume();
82
83         if ((panic_timeout > 0) && (!(dump_config.flags & (DUMP_FLAGS_SOFTBOOT | DUMP_FLAGS_NONDISRUPT)))) {
84                 printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
85 #ifdef CONFIG_SMP
86                 smp_send_stop();
87 #endif
88                 mdelay(panic_timeout * 1000);
89                 machine_restart(NULL);
90         }
91
92         return ret;
93 }
94
95 /* Saves all dump data */
96 int dump_execute_savedump(void)
97 {
98         int ret = 0, err = 0;
99
100         if ((ret = dump_begin()))  {
101                 return ret;
102         }
103
104         if (dump_config.level != DUMP_LEVEL_HEADER) { 
105                 ret = dump_sequencer();
106         }
107         if ((err = dump_complete())) {
108                 printk("Dump complete failed. Error %d\n", err);
109         }
110
111         return ret;
112 }
113
114 extern void dump_calc_bootmap_pages(void);
115
116 /* Does all the real work:  Capture and save state */
117 int dump_generic_execute(const char *panic_str, const struct pt_regs *regs)
118 {
119         int ret = 0;
120
121         if ((ret = dump_configure_header(panic_str, regs))) {
122                 printk("dump config header failed ! error %d\n", ret);
123                 return ret;     
124         }
125
126         dump_calc_bootmap_pages();
127         /* tell interested parties that a dump is about to start */
128         notifier_call_chain(&dump_notifier_list, DUMP_BEGIN, 
129                 &dump_config.dump_device);
130
131         if (dump_config.level != DUMP_LEVEL_NONE)
132                 ret = dump_execute_savedump();
133
134         pr_debug("dumped %ld blocks of %d bytes each\n", 
135                 dump_config.dumper->count, DUMP_BUFFER_SIZE);
136         
137         /* tell interested parties that a dump has completed */
138         notifier_call_chain(&dump_notifier_list, DUMP_END, 
139                 &dump_config.dump_device);
140
141         return ret;
142 }