at v2.6.28-rc4 330 lines 8.7 kB view raw
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 15ACPI_MODULE_NAME("debug"); 16 17#ifdef MODULE_PARAM_PREFIX 18#undef MODULE_PARAM_PREFIX 19#endif 20#define MODULE_PARAM_PREFIX "acpi." 21 22struct acpi_dlayer { 23 const char *name; 24 unsigned long value; 25}; 26struct acpi_dlevel { 27 const char *name; 28 unsigned long value; 29}; 30#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } 31 32static 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 49static 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 -------------------------------------------------------------------------- */ 87static 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 109static 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 128module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); 129module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); 130 131static char trace_method_name[6]; 132module_param_string(trace_method_name, trace_method_name, 6, 0644); 133static unsigned int trace_debug_layer; 134module_param(trace_debug_layer, uint, 0644); 135static unsigned int trace_debug_level; 136module_param(trace_debug_level, uint, 0644); 137 138static 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; 168exit: 169 return result; 170} 171 172static 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 185module_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 195static int 196acpi_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 257static int 258acpi_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 287static 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 329subsys_initcall(acpi_debug_init); 330#endif