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