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