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