Merge branches 'sh/serial-rework' and 'sh/oprofile'
[pandora-kernel.git] / drivers / acpi / debug.c
1 /*
2  * debug.c - ACPI debug interface to userspace.
3  */
4
5 #include <linux/proc_fs.h>
6 #include <linux/init.h>
7 #include <linux/module.h>
8 #include <linux/kernel.h>
9 #include <linux/moduleparam.h>
10 #include <asm/uaccess.h>
11 #include <acpi/acpi_drivers.h>
12 #include <acpi/acglobal.h>
13
14 #define _COMPONENT              ACPI_SYSTEM_COMPONENT
15 ACPI_MODULE_NAME("debug");
16
17 #ifdef MODULE_PARAM_PREFIX
18 #undef MODULE_PARAM_PREFIX
19 #endif
20 #define MODULE_PARAM_PREFIX "acpi."
21
22 struct acpi_dlayer {
23         const char *name;
24         unsigned long value;
25 };
26 struct acpi_dlevel {
27         const char *name;
28         unsigned long value;
29 };
30 #define ACPI_DEBUG_INIT(v)      { .name = #v, .value = v }
31
32 static const struct acpi_dlayer acpi_debug_layers[] = {
33         ACPI_DEBUG_INIT(ACPI_UTILITIES),
34         ACPI_DEBUG_INIT(ACPI_HARDWARE),
35         ACPI_DEBUG_INIT(ACPI_EVENTS),
36         ACPI_DEBUG_INIT(ACPI_TABLES),
37         ACPI_DEBUG_INIT(ACPI_NAMESPACE),
38         ACPI_DEBUG_INIT(ACPI_PARSER),
39         ACPI_DEBUG_INIT(ACPI_DISPATCHER),
40         ACPI_DEBUG_INIT(ACPI_EXECUTER),
41         ACPI_DEBUG_INIT(ACPI_RESOURCES),
42         ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
43         ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
44         ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
45         ACPI_DEBUG_INIT(ACPI_COMPILER),
46         ACPI_DEBUG_INIT(ACPI_TOOLS),
47 };
48
49 static const struct acpi_dlevel acpi_debug_levels[] = {
50         ACPI_DEBUG_INIT(ACPI_LV_INIT),
51         ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
52         ACPI_DEBUG_INIT(ACPI_LV_INFO),
53
54         ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
55         ACPI_DEBUG_INIT(ACPI_LV_PARSE),
56         ACPI_DEBUG_INIT(ACPI_LV_LOAD),
57         ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
58         ACPI_DEBUG_INIT(ACPI_LV_EXEC),
59         ACPI_DEBUG_INIT(ACPI_LV_NAMES),
60         ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
61         ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
62         ACPI_DEBUG_INIT(ACPI_LV_TABLES),
63         ACPI_DEBUG_INIT(ACPI_LV_VALUES),
64         ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
65         ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
66         ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
67         ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
68
69         ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
70         ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
71         ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
72
73         ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
74         ACPI_DEBUG_INIT(ACPI_LV_THREADS),
75         ACPI_DEBUG_INIT(ACPI_LV_IO),
76         ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
77
78         ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
79         ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
80         ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
81         ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
82 };
83
84 /* --------------------------------------------------------------------------
85                               FS Interface (/sys)
86    -------------------------------------------------------------------------- */
87 static int param_get_debug_layer(char *buffer, struct kernel_param *kp) {
88         int result = 0;
89         int i;
90
91         result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
92
93         for(i = 0; i <ARRAY_SIZE(acpi_debug_layers); i++) {
94                 result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
95                                         acpi_debug_layers[i].name,
96                                         acpi_debug_layers[i].value,
97                                         (acpi_dbg_layer & acpi_debug_layers[i].value) ? '*' : ' ');
98         }
99         result += sprintf(buffer+result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
100                                         ACPI_ALL_DRIVERS,
101                                         (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
102                                         ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
103                                         ACPI_ALL_DRIVERS) == 0 ? ' ' : '-');
104         result += sprintf(buffer+result, "--\ndebug_layer = 0x%08X ( * = enabled)\n", acpi_dbg_layer);
105
106         return result;
107 }
108
109 static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
110         int result = 0;
111         int i;
112
113         result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
114
115         for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
116                 result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
117                                      acpi_debug_levels[i].name,
118                                      acpi_debug_levels[i].value,
119                                      (acpi_dbg_level & acpi_debug_levels[i].
120                                       value) ? '*' : ' ');
121         }
122         result += sprintf(buffer+result, "--\ndebug_level = 0x%08X (* = enabled)\n",
123                              acpi_dbg_level);
124
125         return result;
126 }
127
128 module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
129 module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
130
131 static char trace_method_name[6];
132 module_param_string(trace_method_name, trace_method_name, 6, 0644);
133 static unsigned int trace_debug_layer;
134 module_param(trace_debug_layer, uint, 0644);
135 static unsigned int trace_debug_level;
136 module_param(trace_debug_level, uint, 0644);
137
138 static int param_set_trace_state(const char *val, struct kernel_param *kp)
139 {
140         int result = 0;
141
142         if (!strncmp(val, "enable", strlen("enable") - 1)) {
143                 result = acpi_debug_trace(trace_method_name, trace_debug_level,
144                                           trace_debug_layer, 0);
145                 if (result)
146                         result = -EBUSY;
147                 goto exit;
148         }
149
150         if (!strncmp(val, "disable", strlen("disable") - 1)) {
151                 int name = 0;
152                 result = acpi_debug_trace((char *)&name, trace_debug_level,
153                                           trace_debug_layer, 0);
154                 if (result)
155                         result = -EBUSY;
156                 goto exit;
157         }
158
159         if (!strncmp(val, "1", 1)) {
160                 result = acpi_debug_trace(trace_method_name, trace_debug_level,
161                                           trace_debug_layer, 1);
162                 if (result)
163                         result = -EBUSY;
164                 goto exit;
165         }
166
167         result = -EINVAL;
168 exit:
169         return result;
170 }
171
172 static int param_get_trace_state(char *buffer, struct kernel_param *kp)
173 {
174         if (!acpi_gbl_trace_method_name)
175                 return sprintf(buffer, "disable");
176         else {
177                 if (acpi_gbl_trace_flags & 1)
178                         return sprintf(buffer, "1");
179                 else
180                         return sprintf(buffer, "enable");
181         }
182         return 0;
183 }
184
185 module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
186                   NULL, 0644);
187
188 /* --------------------------------------------------------------------------
189                               FS Interface (/proc)
190    -------------------------------------------------------------------------- */
191 #ifdef CONFIG_ACPI_PROCFS
192 #define ACPI_SYSTEM_FILE_DEBUG_LAYER    "debug_layer"
193 #define ACPI_SYSTEM_FILE_DEBUG_LEVEL            "debug_level"
194
195 static int
196 acpi_system_read_debug(char *page,
197                        char **start, off_t off, int count, int *eof, void *data)
198 {
199         char *p = page;
200         int size = 0;
201         unsigned int i;
202
203         if (off != 0)
204                 goto end;
205
206         p += sprintf(p, "%-25s\tHex        SET\n", "Description");
207
208         switch ((unsigned long)data) {
209         case 0:
210                 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
211                         p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
212                                      acpi_debug_layers[i].name,
213                                      acpi_debug_layers[i].value,
214                                      (acpi_dbg_layer & acpi_debug_layers[i].
215                                       value) ? '*' : ' ');
216                 }
217                 p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
218                              ACPI_ALL_DRIVERS,
219                              (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
220                              ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
221                                                        ACPI_ALL_DRIVERS) ==
222                              0 ? ' ' : '-');
223                 p += sprintf(p,
224                              "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
225                              acpi_dbg_layer);
226                 break;
227         case 1:
228                 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
229                         p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
230                                      acpi_debug_levels[i].name,
231                                      acpi_debug_levels[i].value,
232                                      (acpi_dbg_level & acpi_debug_levels[i].
233                                       value) ? '*' : ' ');
234                 }
235                 p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
236                              acpi_dbg_level);
237                 break;
238         default:
239                 p += sprintf(p, "Invalid debug option\n");
240                 break;
241         }
242
243       end:
244         size = (p - page);
245         if (size <= off + count)
246                 *eof = 1;
247         *start = page + off;
248         size -= off;
249         if (size > count)
250                 size = count;
251         if (size < 0)
252                 size = 0;
253
254         return size;
255 }
256
257 static int
258 acpi_system_write_debug(struct file *file,
259                         const char __user * buffer,
260                         unsigned long count, void *data)
261 {
262         char debug_string[12] = { '\0' };
263
264
265         if (count > sizeof(debug_string) - 1)
266                 return -EINVAL;
267
268         if (copy_from_user(debug_string, buffer, count))
269                 return -EFAULT;
270
271         debug_string[count] = '\0';
272
273         switch ((unsigned long)data) {
274         case 0:
275                 acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
276                 break;
277         case 1:
278                 acpi_dbg_level = simple_strtoul(debug_string, NULL, 0);
279                 break;
280         default:
281                 return -EINVAL;
282         }
283
284         return count;
285 }
286
287 static int __init acpi_debug_init(void)
288 {
289         struct proc_dir_entry *entry;
290         int error = 0;
291         char *name;
292
293
294         if (acpi_disabled)
295                 return 0;
296
297         /* 'debug_layer' [R/W] */
298         name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
299         entry =
300             create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
301                                    acpi_root_dir, acpi_system_read_debug,
302                                    (void *)0);
303         if (entry)
304                 entry->write_proc = acpi_system_write_debug;
305         else
306                 goto Error;
307
308         /* 'debug_level' [R/W] */
309         name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
310         entry =
311             create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
312                                    acpi_root_dir, acpi_system_read_debug,
313                                    (void *)1);
314         if (entry)
315                 entry->write_proc = acpi_system_write_debug;
316         else
317                 goto Error;
318
319       Done:
320         return error;
321
322       Error:
323         remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
324         remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
325         error = -ENODEV;
326         goto Done;
327 }
328
329 subsys_initcall(acpi_debug_init);
330 #endif