1 /* 2 * sysfs.c - ACPI sysfs interface to userspace. 3 */ 4 5 #include <linux/init.h> 6 #include <linux/kernel.h> 7 #include <linux/moduleparam.h> 8 #include <acpi/acpi_drivers.h> 9 10 #define _COMPONENT ACPI_SYSTEM_COMPONENT 11 ACPI_MODULE_NAME("sysfs"); 12 13 #define PREFIX "ACPI: " 14 15 #ifdef CONFIG_ACPI_DEBUG 16 /* 17 * ACPI debug sysfs I/F, including: 18 * /sys/modules/acpi/parameters/debug_layer 19 * /sys/modules/acpi/parameters/debug_level 20 * /sys/modules/acpi/parameters/trace_method_name 21 * /sys/modules/acpi/parameters/trace_state 22 * /sys/modules/acpi/parameters/trace_debug_layer 23 * /sys/modules/acpi/parameters/trace_debug_level 24 */ 25 26 struct acpi_dlayer { 27 const char *name; 28 unsigned long value; 29 }; 30 struct acpi_dlevel { 31 const char *name; 32 unsigned long value; 33 }; 34 #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } 35 36 static const struct acpi_dlayer acpi_debug_layers[] = { 37 ACPI_DEBUG_INIT(ACPI_UTILITIES), 38 ACPI_DEBUG_INIT(ACPI_HARDWARE), 39 ACPI_DEBUG_INIT(ACPI_EVENTS), 40 ACPI_DEBUG_INIT(ACPI_TABLES), 41 ACPI_DEBUG_INIT(ACPI_NAMESPACE), 42 ACPI_DEBUG_INIT(ACPI_PARSER), 43 ACPI_DEBUG_INIT(ACPI_DISPATCHER), 44 ACPI_DEBUG_INIT(ACPI_EXECUTER), 45 ACPI_DEBUG_INIT(ACPI_RESOURCES), 46 ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER), 47 ACPI_DEBUG_INIT(ACPI_OS_SERVICES), 48 ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), 49 ACPI_DEBUG_INIT(ACPI_COMPILER), 50 ACPI_DEBUG_INIT(ACPI_TOOLS), 51 52 ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), 53 ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), 54 ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), 55 ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), 56 ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), 57 ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), 58 ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), 59 ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), 60 ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), 61 ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), 62 ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), 63 ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), 64 ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), 65 ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), 66 }; 67 68 static const struct acpi_dlevel acpi_debug_levels[] = { 69 ACPI_DEBUG_INIT(ACPI_LV_INIT), 70 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), 71 ACPI_DEBUG_INIT(ACPI_LV_INFO), 72 73 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), 74 ACPI_DEBUG_INIT(ACPI_LV_PARSE), 75 ACPI_DEBUG_INIT(ACPI_LV_LOAD), 76 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), 77 ACPI_DEBUG_INIT(ACPI_LV_EXEC), 78 ACPI_DEBUG_INIT(ACPI_LV_NAMES), 79 ACPI_DEBUG_INIT(ACPI_LV_OPREGION), 80 ACPI_DEBUG_INIT(ACPI_LV_BFIELD), 81 ACPI_DEBUG_INIT(ACPI_LV_TABLES), 82 ACPI_DEBUG_INIT(ACPI_LV_VALUES), 83 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), 84 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), 85 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), 86 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), 87 88 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), 89 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), 90 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), 91 92 ACPI_DEBUG_INIT(ACPI_LV_MUTEX), 93 ACPI_DEBUG_INIT(ACPI_LV_THREADS), 94 ACPI_DEBUG_INIT(ACPI_LV_IO), 95 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), 96 97 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), 98 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), 99 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), 100 ACPI_DEBUG_INIT(ACPI_LV_EVENTS), 101 }; 102 103 static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) 104 { 105 int result = 0; 106 int i; 107 108 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 109 110 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { 111 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", 112 acpi_debug_layers[i].name, 113 acpi_debug_layers[i].value, 114 (acpi_dbg_layer & acpi_debug_layers[i].value) 115 ? '*' : ' '); 116 } 117 result += 118 sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", 119 ACPI_ALL_DRIVERS, 120 (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 121 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) 122 == 0 ? ' ' : '-'); 123 result += 124 sprintf(buffer + result, 125 "--\ndebug_layer = 0x%08X ( * = enabled)\n", 126 acpi_dbg_layer); 127 128 return result; 129 } 130 131 static int param_get_debug_level(char *buffer, const struct kernel_param *kp) 132 { 133 int result = 0; 134 int i; 135 136 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 137 138 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { 139 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", 140 acpi_debug_levels[i].name, 141 acpi_debug_levels[i].value, 142 (acpi_dbg_level & acpi_debug_levels[i].value) 143 ? '*' : ' '); 144 } 145 result += 146 sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n", 147 acpi_dbg_level); 148 149 return result; 150 } 151 152 static const struct kernel_param_ops param_ops_debug_layer = { 153 .set = param_set_uint, 154 .get = param_get_debug_layer, 155 }; 156 157 static const struct kernel_param_ops param_ops_debug_level = { 158 .set = param_set_uint, 159 .get = param_get_debug_level, 160 }; 161 162 module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); 163 module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); 164 165 static char trace_method_name[6]; 166 module_param_string(trace_method_name, trace_method_name, 6, 0644); 167 static unsigned int trace_debug_layer; 168 module_param(trace_debug_layer, uint, 0644); 169 static unsigned int trace_debug_level; 170 module_param(trace_debug_level, uint, 0644); 171 172 static int param_set_trace_state(const char *val, struct kernel_param *kp) 173 { 174 int result = 0; 175 176 if (!strncmp(val, "enable", sizeof("enable") - 1)) { 177 result = acpi_debug_trace(trace_method_name, trace_debug_level, 178 trace_debug_layer, 0); 179 if (result) 180 result = -EBUSY; 181 goto exit; 182 } 183 184 if (!strncmp(val, "disable", sizeof("disable") - 1)) { 185 int name = 0; 186 result = acpi_debug_trace((char *)&name, trace_debug_level, 187 trace_debug_layer, 0); 188 if (result) 189 result = -EBUSY; 190 goto exit; 191 } 192 193 if (!strncmp(val, "1", 1)) { 194 result = acpi_debug_trace(trace_method_name, trace_debug_level, 195 trace_debug_layer, 1); 196 if (result) 197 result = -EBUSY; 198 goto exit; 199 } 200 201 result = -EINVAL; 202 exit: 203 return result; 204 } 205 206 static int param_get_trace_state(char *buffer, struct kernel_param *kp) 207 { 208 if (!acpi_gbl_trace_method_name) 209 return sprintf(buffer, "disable"); 210 else { 211 if (acpi_gbl_trace_flags & 1) 212 return sprintf(buffer, "1"); 213 else 214 return sprintf(buffer, "enable"); 215 } 216 return 0; 217 } 218 219 module_param_call(trace_state, param_set_trace_state, param_get_trace_state, 220 NULL, 0644); 221 #endif /* CONFIG_ACPI_DEBUG */ 222 223 224 /* /sys/modules/acpi/parameters/aml_debug_output */ 225 226 module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, 227 bool, 0644); 228 MODULE_PARM_DESC(aml_debug_output, 229 "To enable/disable the ACPI Debug Object output."); 230 231 /* /sys/module/acpi/parameters/acpica_version */ 232 static int param_get_acpica_version(char *buffer, struct kernel_param *kp) 233 { 234 int result; 235 236 result = sprintf(buffer, "%x", ACPI_CA_VERSION); 237 238 return result; 239 } 240 241 module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); 242 243 /* 244 * ACPI table sysfs I/F: 245 * /sys/firmware/acpi/tables/ 246 * /sys/firmware/acpi/tables/dynamic/ 247 */ 248 249 static LIST_HEAD(acpi_table_attr_list); 250 static struct kobject *tables_kobj; 251 static struct kobject *dynamic_tables_kobj; 252 253 struct acpi_table_attr { 254 struct bin_attribute attr; 255 char name[8]; 256 int instance; 257 struct list_head node; 258 }; 259 260 static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, 261 struct bin_attribute *bin_attr, char *buf, 262 loff_t offset, size_t count) 263 { 264 struct acpi_table_attr *table_attr = 265 container_of(bin_attr, struct acpi_table_attr, attr); 266 struct acpi_table_header *table_header = NULL; 267 acpi_status status; 268 char name[ACPI_NAME_SIZE]; 269 270 if (strncmp(table_attr->name, "NULL", 4)) 271 memcpy(name, table_attr->name, ACPI_NAME_SIZE); 272 else 273 memcpy(name, "\0\0\0\0", 4); 274 275 status = acpi_get_table(name, table_attr->instance, &table_header); 276 if (ACPI_FAILURE(status)) 277 return -ENODEV; 278 279 return memory_read_from_buffer(buf, count, &offset, 280 table_header, table_header->length); 281 } 282 283 static void acpi_table_attr_init(struct acpi_table_attr *table_attr, 284 struct acpi_table_header *table_header) 285 { 286 struct acpi_table_header *header = NULL; 287 struct acpi_table_attr *attr = NULL; 288 289 sysfs_attr_init(&table_attr->attr.attr); 290 if (table_header->signature[0] != '\0') 291 memcpy(table_attr->name, table_header->signature, 292 ACPI_NAME_SIZE); 293 else 294 memcpy(table_attr->name, "NULL", 4); 295 296 list_for_each_entry(attr, &acpi_table_attr_list, node) { 297 if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) 298 if (table_attr->instance < attr->instance) 299 table_attr->instance = attr->instance; 300 } 301 table_attr->instance++; 302 303 if (table_attr->instance > 1 || (table_attr->instance == 1 && 304 !acpi_get_table 305 (table_header->signature, 2, &header))) 306 sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", 307 table_attr->instance); 308 309 table_attr->attr.size = 0; 310 table_attr->attr.read = acpi_table_show; 311 table_attr->attr.attr.name = table_attr->name; 312 table_attr->attr.attr.mode = 0400; 313 314 return; 315 } 316 317 static acpi_status 318 acpi_sysfs_table_handler(u32 event, void *table, void *context) 319 { 320 struct acpi_table_attr *table_attr; 321 322 switch (event) { 323 case ACPI_TABLE_EVENT_LOAD: 324 table_attr = 325 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 326 if (!table_attr) 327 return AE_NO_MEMORY; 328 329 acpi_table_attr_init(table_attr, table); 330 if (sysfs_create_bin_file(dynamic_tables_kobj, 331 &table_attr->attr)) { 332 kfree(table_attr); 333 return AE_ERROR; 334 } else 335 list_add_tail(&table_attr->node, &acpi_table_attr_list); 336 break; 337 case ACPI_TABLE_EVENT_UNLOAD: 338 /* 339 * we do not need to do anything right now 340 * because the table is not deleted from the 341 * global table list when unloading it. 342 */ 343 break; 344 default: 345 return AE_BAD_PARAMETER; 346 } 347 return AE_OK; 348 } 349 350 static int acpi_tables_sysfs_init(void) 351 { 352 struct acpi_table_attr *table_attr; 353 struct acpi_table_header *table_header = NULL; 354 int table_index = 0; 355 int result; 356 357 tables_kobj = kobject_create_and_add("tables", acpi_kobj); 358 if (!tables_kobj) 359 goto err; 360 361 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); 362 if (!dynamic_tables_kobj) 363 goto err_dynamic_tables; 364 365 do { 366 result = acpi_get_table_by_index(table_index, &table_header); 367 if (!result) { 368 table_index++; 369 table_attr = NULL; 370 table_attr = 371 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 372 if (!table_attr) 373 return -ENOMEM; 374 375 acpi_table_attr_init(table_attr, table_header); 376 result = 377 sysfs_create_bin_file(tables_kobj, 378 &table_attr->attr); 379 if (result) { 380 kfree(table_attr); 381 return result; 382 } else 383 list_add_tail(&table_attr->node, 384 &acpi_table_attr_list); 385 } 386 } while (!result); 387 kobject_uevent(tables_kobj, KOBJ_ADD); 388 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); 389 result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); 390 391 return result == AE_OK ? 0 : -EINVAL; 392 err_dynamic_tables: 393 kobject_put(tables_kobj); 394 err: 395 return -ENOMEM; 396 } 397 398 /* 399 * Detailed ACPI IRQ counters: 400 * /sys/firmware/acpi/interrupts/ 401 */ 402 403 u32 acpi_irq_handled; 404 u32 acpi_irq_not_handled; 405 406 #define COUNT_GPE 0 407 #define COUNT_SCI 1 /* acpi_irq_handled */ 408 #define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ 409 #define COUNT_ERROR 3 /* other */ 410 #define NUM_COUNTERS_EXTRA 4 411 412 struct event_counter { 413 u32 count; 414 u32 flags; 415 }; 416 417 static struct event_counter *all_counters; 418 static u32 num_gpes; 419 static u32 num_counters; 420 static struct attribute **all_attrs; 421 static u32 acpi_gpe_count; 422 423 static struct attribute_group interrupt_stats_attr_group = { 424 .name = "interrupts", 425 }; 426 427 static struct kobj_attribute *counter_attrs; 428 429 static void delete_gpe_attr_array(void) 430 { 431 struct event_counter *tmp = all_counters; 432 433 all_counters = NULL; 434 kfree(tmp); 435 436 if (counter_attrs) { 437 int i; 438 439 for (i = 0; i < num_gpes; i++) 440 kfree(counter_attrs[i].attr.name); 441 442 kfree(counter_attrs); 443 } 444 kfree(all_attrs); 445 446 return; 447 } 448 449 static void gpe_count(u32 gpe_number) 450 { 451 acpi_gpe_count++; 452 453 if (!all_counters) 454 return; 455 456 if (gpe_number < num_gpes) 457 all_counters[gpe_number].count++; 458 else 459 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 460 COUNT_ERROR].count++; 461 462 return; 463 } 464 465 static void fixed_event_count(u32 event_number) 466 { 467 if (!all_counters) 468 return; 469 470 if (event_number < ACPI_NUM_FIXED_EVENTS) 471 all_counters[num_gpes + event_number].count++; 472 else 473 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 474 COUNT_ERROR].count++; 475 476 return; 477 } 478 479 static void acpi_global_event_handler(u32 event_type, acpi_handle device, 480 u32 event_number, void *context) 481 { 482 if (event_type == ACPI_EVENT_TYPE_GPE) 483 gpe_count(event_number); 484 485 if (event_type == ACPI_EVENT_TYPE_FIXED) 486 fixed_event_count(event_number); 487 } 488 489 static int get_status(u32 index, acpi_event_status *status, 490 acpi_handle *handle) 491 { 492 int result = 0; 493 494 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 495 goto end; 496 497 if (index < num_gpes) { 498 result = acpi_get_gpe_device(index, handle); 499 if (result) { 500 ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, 501 "Invalid GPE 0x%x\n", index)); 502 goto end; 503 } 504 result = acpi_get_gpe_status(*handle, index, status); 505 } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) 506 result = acpi_get_event_status(index - num_gpes, status); 507 508 end: 509 return result; 510 } 511 512 static ssize_t counter_show(struct kobject *kobj, 513 struct kobj_attribute *attr, char *buf) 514 { 515 int index = attr - counter_attrs; 516 int size; 517 acpi_handle handle; 518 acpi_event_status status; 519 int result = 0; 520 521 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = 522 acpi_irq_handled; 523 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = 524 acpi_irq_not_handled; 525 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = 526 acpi_gpe_count; 527 size = sprintf(buf, "%8d", all_counters[index].count); 528 529 /* "gpe_all" or "sci" */ 530 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 531 goto end; 532 533 result = get_status(index, &status, &handle); 534 if (result) 535 goto end; 536 537 if (!(status & ACPI_EVENT_FLAG_HANDLE)) 538 size += sprintf(buf + size, " invalid"); 539 else if (status & ACPI_EVENT_FLAG_ENABLED) 540 size += sprintf(buf + size, " enabled"); 541 else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) 542 size += sprintf(buf + size, " wake_enabled"); 543 else 544 size += sprintf(buf + size, " disabled"); 545 546 end: 547 size += sprintf(buf + size, "\n"); 548 return result ? result : size; 549 } 550 551 /* 552 * counter_set() sets the specified counter. 553 * setting the total "sci" file to any value clears all counters. 554 * enable/disable/clear a gpe/fixed event in user space. 555 */ 556 static ssize_t counter_set(struct kobject *kobj, 557 struct kobj_attribute *attr, const char *buf, 558 size_t size) 559 { 560 int index = attr - counter_attrs; 561 acpi_event_status status; 562 acpi_handle handle; 563 int result = 0; 564 565 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { 566 int i; 567 for (i = 0; i < num_counters; ++i) 568 all_counters[i].count = 0; 569 acpi_gpe_count = 0; 570 acpi_irq_handled = 0; 571 acpi_irq_not_handled = 0; 572 goto end; 573 } 574 575 /* show the event status for both GPEs and Fixed Events */ 576 result = get_status(index, &status, &handle); 577 if (result) 578 goto end; 579 580 if (!(status & ACPI_EVENT_FLAG_HANDLE)) { 581 printk(KERN_WARNING PREFIX 582 "Can not change Invalid GPE/Fixed Event status\n"); 583 return -EINVAL; 584 } 585 586 if (index < num_gpes) { 587 if (!strcmp(buf, "disable\n") && 588 (status & ACPI_EVENT_FLAG_ENABLED)) 589 result = acpi_disable_gpe(handle, index); 590 else if (!strcmp(buf, "enable\n") && 591 !(status & ACPI_EVENT_FLAG_ENABLED)) 592 result = acpi_enable_gpe(handle, index); 593 else if (!strcmp(buf, "clear\n") && 594 (status & ACPI_EVENT_FLAG_SET)) 595 result = acpi_clear_gpe(handle, index); 596 else 597 all_counters[index].count = strtoul(buf, NULL, 0); 598 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { 599 int event = index - num_gpes; 600 if (!strcmp(buf, "disable\n") && 601 (status & ACPI_EVENT_FLAG_ENABLED)) 602 result = acpi_disable_event(event, ACPI_NOT_ISR); 603 else if (!strcmp(buf, "enable\n") && 604 !(status & ACPI_EVENT_FLAG_ENABLED)) 605 result = acpi_enable_event(event, ACPI_NOT_ISR); 606 else if (!strcmp(buf, "clear\n") && 607 (status & ACPI_EVENT_FLAG_SET)) 608 result = acpi_clear_event(event); 609 else 610 all_counters[index].count = strtoul(buf, NULL, 0); 611 } else 612 all_counters[index].count = strtoul(buf, NULL, 0); 613 614 if (ACPI_FAILURE(result)) 615 result = -EINVAL; 616 end: 617 return result ? result : size; 618 } 619 620 void acpi_irq_stats_init(void) 621 { 622 acpi_status status; 623 int i; 624 625 if (all_counters) 626 return; 627 628 num_gpes = acpi_current_gpe_count; 629 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; 630 631 all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), 632 GFP_KERNEL); 633 if (all_attrs == NULL) 634 return; 635 636 all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), 637 GFP_KERNEL); 638 if (all_counters == NULL) 639 goto fail; 640 641 status = acpi_install_global_event_handler(acpi_global_event_handler, NULL); 642 if (ACPI_FAILURE(status)) 643 goto fail; 644 645 counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), 646 GFP_KERNEL); 647 if (counter_attrs == NULL) 648 goto fail; 649 650 for (i = 0; i < num_counters; ++i) { 651 char buffer[12]; 652 char *name; 653 654 if (i < num_gpes) 655 sprintf(buffer, "gpe%02X", i); 656 else if (i == num_gpes + ACPI_EVENT_PMTIMER) 657 sprintf(buffer, "ff_pmtimer"); 658 else if (i == num_gpes + ACPI_EVENT_GLOBAL) 659 sprintf(buffer, "ff_gbl_lock"); 660 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON) 661 sprintf(buffer, "ff_pwr_btn"); 662 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON) 663 sprintf(buffer, "ff_slp_btn"); 664 else if (i == num_gpes + ACPI_EVENT_RTC) 665 sprintf(buffer, "ff_rt_clk"); 666 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE) 667 sprintf(buffer, "gpe_all"); 668 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) 669 sprintf(buffer, "sci"); 670 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT) 671 sprintf(buffer, "sci_not"); 672 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) 673 sprintf(buffer, "error"); 674 else 675 sprintf(buffer, "bug%02X", i); 676 677 name = kzalloc(strlen(buffer) + 1, GFP_KERNEL); 678 if (name == NULL) 679 goto fail; 680 strncpy(name, buffer, strlen(buffer) + 1); 681 682 sysfs_attr_init(&counter_attrs[i].attr); 683 counter_attrs[i].attr.name = name; 684 counter_attrs[i].attr.mode = 0644; 685 counter_attrs[i].show = counter_show; 686 counter_attrs[i].store = counter_set; 687 688 all_attrs[i] = &counter_attrs[i].attr; 689 } 690 691 interrupt_stats_attr_group.attrs = all_attrs; 692 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group)) 693 return; 694 695 fail: 696 delete_gpe_attr_array(); 697 return; 698 } 699 700 static void __exit interrupt_stats_exit(void) 701 { 702 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group); 703 704 delete_gpe_attr_array(); 705 706 return; 707 } 708 709 static ssize_t 710 acpi_show_profile(struct device *dev, struct device_attribute *attr, 711 char *buf) 712 { 713 return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile); 714 } 715 716 static const struct device_attribute pm_profile_attr = 717 __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL); 718 719 int __init acpi_sysfs_init(void) 720 { 721 int result; 722 723 result = acpi_tables_sysfs_init(); 724 if (result) 725 return result; 726 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr); 727 return result; 728 } 729