at v2.6.28 9.3 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 ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), 49 ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), 50 ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), 51 ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), 52 ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), 53 ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), 54 ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), 55 ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), 56 ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), 57 ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), 58 ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), 59 ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), 60 ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), 61 ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), 62}; 63 64static const struct acpi_dlevel acpi_debug_levels[] = { 65 ACPI_DEBUG_INIT(ACPI_LV_INIT), 66 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), 67 ACPI_DEBUG_INIT(ACPI_LV_INFO), 68 69 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), 70 ACPI_DEBUG_INIT(ACPI_LV_PARSE), 71 ACPI_DEBUG_INIT(ACPI_LV_LOAD), 72 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), 73 ACPI_DEBUG_INIT(ACPI_LV_EXEC), 74 ACPI_DEBUG_INIT(ACPI_LV_NAMES), 75 ACPI_DEBUG_INIT(ACPI_LV_OPREGION), 76 ACPI_DEBUG_INIT(ACPI_LV_BFIELD), 77 ACPI_DEBUG_INIT(ACPI_LV_TABLES), 78 ACPI_DEBUG_INIT(ACPI_LV_VALUES), 79 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), 80 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), 81 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), 82 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), 83 84 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), 85 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), 86 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), 87 88 ACPI_DEBUG_INIT(ACPI_LV_MUTEX), 89 ACPI_DEBUG_INIT(ACPI_LV_THREADS), 90 ACPI_DEBUG_INIT(ACPI_LV_IO), 91 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), 92 93 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), 94 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), 95 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), 96 ACPI_DEBUG_INIT(ACPI_LV_EVENTS), 97}; 98 99/* -------------------------------------------------------------------------- 100 FS Interface (/sys) 101 -------------------------------------------------------------------------- */ 102static int param_get_debug_layer(char *buffer, struct kernel_param *kp) { 103 int result = 0; 104 int i; 105 106 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 107 108 for(i = 0; i <ARRAY_SIZE(acpi_debug_layers); i++) { 109 result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n", 110 acpi_debug_layers[i].name, 111 acpi_debug_layers[i].value, 112 (acpi_dbg_layer & acpi_debug_layers[i].value) ? '*' : ' '); 113 } 114 result += sprintf(buffer+result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", 115 ACPI_ALL_DRIVERS, 116 (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 117 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & 118 ACPI_ALL_DRIVERS) == 0 ? ' ' : '-'); 119 result += sprintf(buffer+result, "--\ndebug_layer = 0x%08X ( * = enabled)\n", acpi_dbg_layer); 120 121 return result; 122} 123 124static int param_get_debug_level(char *buffer, struct kernel_param *kp) { 125 int result = 0; 126 int i; 127 128 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 129 130 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { 131 result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n", 132 acpi_debug_levels[i].name, 133 acpi_debug_levels[i].value, 134 (acpi_dbg_level & acpi_debug_levels[i]. 135 value) ? '*' : ' '); 136 } 137 result += sprintf(buffer+result, "--\ndebug_level = 0x%08X (* = enabled)\n", 138 acpi_dbg_level); 139 140 return result; 141} 142 143module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); 144module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); 145 146static char trace_method_name[6]; 147module_param_string(trace_method_name, trace_method_name, 6, 0644); 148static unsigned int trace_debug_layer; 149module_param(trace_debug_layer, uint, 0644); 150static unsigned int trace_debug_level; 151module_param(trace_debug_level, uint, 0644); 152 153static int param_set_trace_state(const char *val, struct kernel_param *kp) 154{ 155 int result = 0; 156 157 if (!strncmp(val, "enable", strlen("enable") - 1)) { 158 result = acpi_debug_trace(trace_method_name, trace_debug_level, 159 trace_debug_layer, 0); 160 if (result) 161 result = -EBUSY; 162 goto exit; 163 } 164 165 if (!strncmp(val, "disable", strlen("disable") - 1)) { 166 int name = 0; 167 result = acpi_debug_trace((char *)&name, trace_debug_level, 168 trace_debug_layer, 0); 169 if (result) 170 result = -EBUSY; 171 goto exit; 172 } 173 174 if (!strncmp(val, "1", 1)) { 175 result = acpi_debug_trace(trace_method_name, trace_debug_level, 176 trace_debug_layer, 1); 177 if (result) 178 result = -EBUSY; 179 goto exit; 180 } 181 182 result = -EINVAL; 183exit: 184 return result; 185} 186 187static int param_get_trace_state(char *buffer, struct kernel_param *kp) 188{ 189 if (!acpi_gbl_trace_method_name) 190 return sprintf(buffer, "disable"); 191 else { 192 if (acpi_gbl_trace_flags & 1) 193 return sprintf(buffer, "1"); 194 else 195 return sprintf(buffer, "enable"); 196 } 197 return 0; 198} 199 200module_param_call(trace_state, param_set_trace_state, param_get_trace_state, 201 NULL, 0644); 202 203/* -------------------------------------------------------------------------- 204 FS Interface (/proc) 205 -------------------------------------------------------------------------- */ 206#ifdef CONFIG_ACPI_PROCFS 207#define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" 208#define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" 209 210static int 211acpi_system_read_debug(char *page, 212 char **start, off_t off, int count, int *eof, void *data) 213{ 214 char *p = page; 215 int size = 0; 216 unsigned int i; 217 218 if (off != 0) 219 goto end; 220 221 p += sprintf(p, "%-25s\tHex SET\n", "Description"); 222 223 switch ((unsigned long)data) { 224 case 0: 225 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { 226 p += sprintf(p, "%-25s\t0x%08lX [%c]\n", 227 acpi_debug_layers[i].name, 228 acpi_debug_layers[i].value, 229 (acpi_dbg_layer & acpi_debug_layers[i]. 230 value) ? '*' : ' '); 231 } 232 p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", 233 ACPI_ALL_DRIVERS, 234 (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 235 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & 236 ACPI_ALL_DRIVERS) == 237 0 ? ' ' : '-'); 238 p += sprintf(p, 239 "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n", 240 acpi_dbg_layer); 241 break; 242 case 1: 243 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { 244 p += sprintf(p, "%-25s\t0x%08lX [%c]\n", 245 acpi_debug_levels[i].name, 246 acpi_debug_levels[i].value, 247 (acpi_dbg_level & acpi_debug_levels[i]. 248 value) ? '*' : ' '); 249 } 250 p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n", 251 acpi_dbg_level); 252 break; 253 default: 254 p += sprintf(p, "Invalid debug option\n"); 255 break; 256 } 257 258 end: 259 size = (p - page); 260 if (size <= off + count) 261 *eof = 1; 262 *start = page + off; 263 size -= off; 264 if (size > count) 265 size = count; 266 if (size < 0) 267 size = 0; 268 269 return size; 270} 271 272static int 273acpi_system_write_debug(struct file *file, 274 const char __user * buffer, 275 unsigned long count, void *data) 276{ 277 char debug_string[12] = { '\0' }; 278 279 280 if (count > sizeof(debug_string) - 1) 281 return -EINVAL; 282 283 if (copy_from_user(debug_string, buffer, count)) 284 return -EFAULT; 285 286 debug_string[count] = '\0'; 287 288 switch ((unsigned long)data) { 289 case 0: 290 acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); 291 break; 292 case 1: 293 acpi_dbg_level = simple_strtoul(debug_string, NULL, 0); 294 break; 295 default: 296 return -EINVAL; 297 } 298 299 return count; 300} 301 302static int __init acpi_debug_init(void) 303{ 304 struct proc_dir_entry *entry; 305 int error = 0; 306 char *name; 307 308 309 if (acpi_disabled) 310 return 0; 311 312 /* 'debug_layer' [R/W] */ 313 name = ACPI_SYSTEM_FILE_DEBUG_LAYER; 314 entry = 315 create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, 316 acpi_root_dir, acpi_system_read_debug, 317 (void *)0); 318 if (entry) 319 entry->write_proc = acpi_system_write_debug; 320 else 321 goto Error; 322 323 /* 'debug_level' [R/W] */ 324 name = ACPI_SYSTEM_FILE_DEBUG_LEVEL; 325 entry = 326 create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, 327 acpi_root_dir, acpi_system_read_debug, 328 (void *)1); 329 if (entry) 330 entry->write_proc = acpi_system_write_debug; 331 else 332 goto Error; 333 334 Done: 335 return error; 336 337 Error: 338 remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir); 339 remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir); 340 error = -ENODEV; 341 goto Done; 342} 343 344subsys_initcall(acpi_debug_init); 345#endif