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, 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, 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 module_param_call(debug_layer, param_set_uint, param_get_debug_layer, 153 &acpi_dbg_layer, 0644); 154 module_param_call(debug_level, param_set_uint, param_get_debug_level, 155 &acpi_dbg_level, 0644); 156 157 static char trace_method_name[6]; 158 module_param_string(trace_method_name, trace_method_name, 6, 0644); 159 static unsigned int trace_debug_layer; 160 module_param(trace_debug_layer, uint, 0644); 161 static unsigned int trace_debug_level; 162 module_param(trace_debug_level, uint, 0644); 163 164 static int param_set_trace_state(const char *val, struct kernel_param *kp) 165 { 166 int result = 0; 167 168 if (!strncmp(val, "enable", strlen("enable") - 1)) { 169 result = acpi_debug_trace(trace_method_name, trace_debug_level, 170 trace_debug_layer, 0); 171 if (result) 172 result = -EBUSY; 173 goto exit; 174 } 175 176 if (!strncmp(val, "disable", strlen("disable") - 1)) { 177 int name = 0; 178 result = acpi_debug_trace((char *)&name, trace_debug_level, 179 trace_debug_layer, 0); 180 if (result) 181 result = -EBUSY; 182 goto exit; 183 } 184 185 if (!strncmp(val, "1", 1)) { 186 result = acpi_debug_trace(trace_method_name, trace_debug_level, 187 trace_debug_layer, 1); 188 if (result) 189 result = -EBUSY; 190 goto exit; 191 } 192 193 result = -EINVAL; 194 exit: 195 return result; 196 } 197 198 static int param_get_trace_state(char *buffer, struct kernel_param *kp) 199 { 200 if (!acpi_gbl_trace_method_name) 201 return sprintf(buffer, "disable"); 202 else { 203 if (acpi_gbl_trace_flags & 1) 204 return sprintf(buffer, "1"); 205 else 206 return sprintf(buffer, "enable"); 207 } 208 return 0; 209 } 210 211 module_param_call(trace_state, param_set_trace_state, param_get_trace_state, 212 NULL, 0644); 213 #endif /* CONFIG_ACPI_DEBUG */ 214 215 /* /sys/module/acpi/parameters/acpica_version */ 216 static int param_get_acpica_version(char *buffer, struct kernel_param *kp) 217 { 218 int result; 219 220 result = sprintf(buffer, "%x", ACPI_CA_VERSION); 221 222 return result; 223 } 224 225 module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); 226 227 /* 228 * ACPI table sysfs I/F: 229 * /sys/firmware/acpi/tables/ 230 * /sys/firmware/acpi/tables/dynamic/ 231 */ 232 233 static LIST_HEAD(acpi_table_attr_list); 234 static struct kobject *tables_kobj; 235 static struct kobject *dynamic_tables_kobj; 236 237 struct acpi_table_attr { 238 struct bin_attribute attr; 239 char name[8]; 240 int instance; 241 struct list_head node; 242 }; 243 244 static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, 245 struct bin_attribute *bin_attr, char *buf, 246 loff_t offset, size_t count) 247 { 248 struct acpi_table_attr *table_attr = 249 container_of(bin_attr, struct acpi_table_attr, attr); 250 struct acpi_table_header *table_header = NULL; 251 acpi_status status; 252 char name[ACPI_NAME_SIZE]; 253 254 if (strncmp(table_attr->name, "NULL", 4)) 255 memcpy(name, table_attr->name, ACPI_NAME_SIZE); 256 else 257 memcpy(name, "\0\0\0\0", 4); 258 259 status = acpi_get_table(name, table_attr->instance, &table_header); 260 if (ACPI_FAILURE(status)) 261 return -ENODEV; 262 263 return memory_read_from_buffer(buf, count, &offset, 264 table_header, table_header->length); 265 } 266 267 static void acpi_table_attr_init(struct acpi_table_attr *table_attr, 268 struct acpi_table_header *table_header) 269 { 270 struct acpi_table_header *header = NULL; 271 struct acpi_table_attr *attr = NULL; 272 273 sysfs_attr_init(&table_attr->attr.attr); 274 if (table_header->signature[0] != '\0') 275 memcpy(table_attr->name, table_header->signature, 276 ACPI_NAME_SIZE); 277 else 278 memcpy(table_attr->name, "NULL", 4); 279 280 list_for_each_entry(attr, &acpi_table_attr_list, node) { 281 if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) 282 if (table_attr->instance < attr->instance) 283 table_attr->instance = attr->instance; 284 } 285 table_attr->instance++; 286 287 if (table_attr->instance > 1 || (table_attr->instance == 1 && 288 !acpi_get_table 289 (table_header->signature, 2, &header))) 290 sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", 291 table_attr->instance); 292 293 table_attr->attr.size = 0; 294 table_attr->attr.read = acpi_table_show; 295 table_attr->attr.attr.name = table_attr->name; 296 table_attr->attr.attr.mode = 0400; 297 298 return; 299 } 300 301 static acpi_status 302 acpi_sysfs_table_handler(u32 event, void *table, void *context) 303 { 304 struct acpi_table_attr *table_attr; 305 306 switch (event) { 307 case ACPI_TABLE_EVENT_LOAD: 308 table_attr = 309 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 310 if (!table_attr) 311 return AE_NO_MEMORY; 312 313 acpi_table_attr_init(table_attr, table); 314 if (sysfs_create_bin_file(dynamic_tables_kobj, 315 &table_attr->attr)) { 316 kfree(table_attr); 317 return AE_ERROR; 318 } else 319 list_add_tail(&table_attr->node, &acpi_table_attr_list); 320 break; 321 case ACPI_TABLE_EVENT_UNLOAD: 322 /* 323 * we do not need to do anything right now 324 * because the table is not deleted from the 325 * global table list when unloading it. 326 */ 327 break; 328 default: 329 return AE_BAD_PARAMETER; 330 } 331 return AE_OK; 332 } 333 334 static int acpi_tables_sysfs_init(void) 335 { 336 struct acpi_table_attr *table_attr; 337 struct acpi_table_header *table_header = NULL; 338 int table_index = 0; 339 int result; 340 341 tables_kobj = kobject_create_and_add("tables", acpi_kobj); 342 if (!tables_kobj) 343 goto err; 344 345 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); 346 if (!dynamic_tables_kobj) 347 goto err_dynamic_tables; 348 349 do { 350 result = acpi_get_table_by_index(table_index, &table_header); 351 if (!result) { 352 table_index++; 353 table_attr = NULL; 354 table_attr = 355 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 356 if (!table_attr) 357 return -ENOMEM; 358 359 acpi_table_attr_init(table_attr, table_header); 360 result = 361 sysfs_create_bin_file(tables_kobj, 362 &table_attr->attr); 363 if (result) { 364 kfree(table_attr); 365 return result; 366 } else 367 list_add_tail(&table_attr->node, 368 &acpi_table_attr_list); 369 } 370 } while (!result); 371 kobject_uevent(tables_kobj, KOBJ_ADD); 372 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); 373 result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); 374 375 return result == AE_OK ? 0 : -EINVAL; 376 err_dynamic_tables: 377 kobject_put(tables_kobj); 378 err: 379 return -ENOMEM; 380 } 381 382 /* 383 * Detailed ACPI IRQ counters: 384 * /sys/firmware/acpi/interrupts/ 385 */ 386 387 u32 acpi_irq_handled; 388 u32 acpi_irq_not_handled; 389 390 #define COUNT_GPE 0 391 #define COUNT_SCI 1 /* acpi_irq_handled */ 392 #define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ 393 #define COUNT_ERROR 3 /* other */ 394 #define NUM_COUNTERS_EXTRA 4 395 396 struct event_counter { 397 u32 count; 398 u32 flags; 399 }; 400 401 static struct event_counter *all_counters; 402 static u32 num_gpes; 403 static u32 num_counters; 404 static struct attribute **all_attrs; 405 static u32 acpi_gpe_count; 406 407 static struct attribute_group interrupt_stats_attr_group = { 408 .name = "interrupts", 409 }; 410 411 static struct kobj_attribute *counter_attrs; 412 413 static void delete_gpe_attr_array(void) 414 { 415 struct event_counter *tmp = all_counters; 416 417 all_counters = NULL; 418 kfree(tmp); 419 420 if (counter_attrs) { 421 int i; 422 423 for (i = 0; i < num_gpes; i++) 424 kfree(counter_attrs[i].attr.name); 425 426 kfree(counter_attrs); 427 } 428 kfree(all_attrs); 429 430 return; 431 } 432 433 void acpi_os_gpe_count(u32 gpe_number) 434 { 435 acpi_gpe_count++; 436 437 if (!all_counters) 438 return; 439 440 if (gpe_number < num_gpes) 441 all_counters[gpe_number].count++; 442 else 443 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 444 COUNT_ERROR].count++; 445 446 return; 447 } 448 449 void acpi_os_fixed_event_count(u32 event_number) 450 { 451 if (!all_counters) 452 return; 453 454 if (event_number < ACPI_NUM_FIXED_EVENTS) 455 all_counters[num_gpes + event_number].count++; 456 else 457 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 458 COUNT_ERROR].count++; 459 460 return; 461 } 462 463 static int get_status(u32 index, acpi_event_status *status, 464 acpi_handle *handle) 465 { 466 int result = 0; 467 468 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 469 goto end; 470 471 if (index < num_gpes) { 472 result = acpi_get_gpe_device(index, handle); 473 if (result) { 474 ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, 475 "Invalid GPE 0x%x\n", index)); 476 goto end; 477 } 478 result = acpi_get_gpe_status(*handle, index, status); 479 } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) 480 result = acpi_get_event_status(index - num_gpes, status); 481 482 end: 483 return result; 484 } 485 486 static ssize_t counter_show(struct kobject *kobj, 487 struct kobj_attribute *attr, char *buf) 488 { 489 int index = attr - counter_attrs; 490 int size; 491 acpi_handle handle; 492 acpi_event_status status; 493 int result = 0; 494 495 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = 496 acpi_irq_handled; 497 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = 498 acpi_irq_not_handled; 499 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = 500 acpi_gpe_count; 501 size = sprintf(buf, "%8d", all_counters[index].count); 502 503 /* "gpe_all" or "sci" */ 504 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 505 goto end; 506 507 result = get_status(index, &status, &handle); 508 if (result) 509 goto end; 510 511 if (!(status & ACPI_EVENT_FLAG_HANDLE)) 512 size += sprintf(buf + size, " invalid"); 513 else if (status & ACPI_EVENT_FLAG_ENABLED) 514 size += sprintf(buf + size, " enabled"); 515 else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) 516 size += sprintf(buf + size, " wake_enabled"); 517 else 518 size += sprintf(buf + size, " disabled"); 519 520 end: 521 size += sprintf(buf + size, "\n"); 522 return result ? result : size; 523 } 524 525 /* 526 * counter_set() sets the specified counter. 527 * setting the total "sci" file to any value clears all counters. 528 * enable/disable/clear a gpe/fixed event in user space. 529 */ 530 static ssize_t counter_set(struct kobject *kobj, 531 struct kobj_attribute *attr, const char *buf, 532 size_t size) 533 { 534 int index = attr - counter_attrs; 535 acpi_event_status status; 536 acpi_handle handle; 537 int result = 0; 538 539 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { 540 int i; 541 for (i = 0; i < num_counters; ++i) 542 all_counters[i].count = 0; 543 acpi_gpe_count = 0; 544 acpi_irq_handled = 0; 545 acpi_irq_not_handled = 0; 546 goto end; 547 } 548 549 /* show the event status for both GPEs and Fixed Events */ 550 result = get_status(index, &status, &handle); 551 if (result) 552 goto end; 553 554 if (!(status & ACPI_EVENT_FLAG_HANDLE)) { 555 printk(KERN_WARNING PREFIX 556 "Can not change Invalid GPE/Fixed Event status\n"); 557 return -EINVAL; 558 } 559 560 if (index < num_gpes) { 561 if (!strcmp(buf, "disable\n") && 562 (status & ACPI_EVENT_FLAG_ENABLED)) 563 result = acpi_disable_gpe(handle, index); 564 else if (!strcmp(buf, "enable\n") && 565 !(status & ACPI_EVENT_FLAG_ENABLED)) 566 result = acpi_enable_gpe(handle, index); 567 else if (!strcmp(buf, "clear\n") && 568 (status & ACPI_EVENT_FLAG_SET)) 569 result = acpi_clear_gpe(handle, index); 570 else 571 all_counters[index].count = strtoul(buf, NULL, 0); 572 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { 573 int event = index - num_gpes; 574 if (!strcmp(buf, "disable\n") && 575 (status & ACPI_EVENT_FLAG_ENABLED)) 576 result = acpi_disable_event(event, ACPI_NOT_ISR); 577 else if (!strcmp(buf, "enable\n") && 578 !(status & ACPI_EVENT_FLAG_ENABLED)) 579 result = acpi_enable_event(event, ACPI_NOT_ISR); 580 else if (!strcmp(buf, "clear\n") && 581 (status & ACPI_EVENT_FLAG_SET)) 582 result = acpi_clear_event(event); 583 else 584 all_counters[index].count = strtoul(buf, NULL, 0); 585 } else 586 all_counters[index].count = strtoul(buf, NULL, 0); 587 588 if (ACPI_FAILURE(result)) 589 result = -EINVAL; 590 end: 591 return result ? result : size; 592 } 593 594 void acpi_irq_stats_init(void) 595 { 596 int i; 597 598 if (all_counters) 599 return; 600 601 num_gpes = acpi_current_gpe_count; 602 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; 603 604 all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), 605 GFP_KERNEL); 606 if (all_attrs == NULL) 607 return; 608 609 all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), 610 GFP_KERNEL); 611 if (all_counters == NULL) 612 goto fail; 613 614 counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), 615 GFP_KERNEL); 616 if (counter_attrs == NULL) 617 goto fail; 618 619 for (i = 0; i < num_counters; ++i) { 620 char buffer[12]; 621 char *name; 622 623 if (i < num_gpes) 624 sprintf(buffer, "gpe%02X", i); 625 else if (i == num_gpes + ACPI_EVENT_PMTIMER) 626 sprintf(buffer, "ff_pmtimer"); 627 else if (i == num_gpes + ACPI_EVENT_GLOBAL) 628 sprintf(buffer, "ff_gbl_lock"); 629 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON) 630 sprintf(buffer, "ff_pwr_btn"); 631 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON) 632 sprintf(buffer, "ff_slp_btn"); 633 else if (i == num_gpes + ACPI_EVENT_RTC) 634 sprintf(buffer, "ff_rt_clk"); 635 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE) 636 sprintf(buffer, "gpe_all"); 637 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) 638 sprintf(buffer, "sci"); 639 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT) 640 sprintf(buffer, "sci_not"); 641 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) 642 sprintf(buffer, "error"); 643 else 644 sprintf(buffer, "bug%02X", i); 645 646 name = kzalloc(strlen(buffer) + 1, GFP_KERNEL); 647 if (name == NULL) 648 goto fail; 649 strncpy(name, buffer, strlen(buffer) + 1); 650 651 sysfs_attr_init(&counter_attrs[i].attr); 652 counter_attrs[i].attr.name = name; 653 counter_attrs[i].attr.mode = 0644; 654 counter_attrs[i].show = counter_show; 655 counter_attrs[i].store = counter_set; 656 657 all_attrs[i] = &counter_attrs[i].attr; 658 } 659 660 interrupt_stats_attr_group.attrs = all_attrs; 661 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group)) 662 return; 663 664 fail: 665 delete_gpe_attr_array(); 666 return; 667 } 668 669 static void __exit interrupt_stats_exit(void) 670 { 671 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group); 672 673 delete_gpe_attr_array(); 674 675 return; 676 } 677 678 int __init acpi_sysfs_init(void) 679 { 680 int result; 681 682 result = acpi_tables_sysfs_init(); 683 684 return result; 685 } 686