summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/sysfs.c')
-rw-r--r--drivers/acpi/sysfs.c91
1 files changed, 88 insertions, 3 deletions
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index e414fabf7315..78a5a23010ab 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -2,6 +2,8 @@
2 * sysfs.c - ACPI sysfs interface to userspace. 2 * sysfs.c - ACPI sysfs interface to userspace.
3 */ 3 */
4 4
5#define pr_fmt(fmt) "ACPI: " fmt
6
5#include <linux/init.h> 7#include <linux/init.h>
6#include <linux/kernel.h> 8#include <linux/kernel.h>
7#include <linux/moduleparam.h> 9#include <linux/moduleparam.h>
@@ -306,11 +308,13 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
306/* 308/*
307 * ACPI table sysfs I/F: 309 * ACPI table sysfs I/F:
308 * /sys/firmware/acpi/tables/ 310 * /sys/firmware/acpi/tables/
311 * /sys/firmware/acpi/tables/data/
309 * /sys/firmware/acpi/tables/dynamic/ 312 * /sys/firmware/acpi/tables/dynamic/
310 */ 313 */
311 314
312static LIST_HEAD(acpi_table_attr_list); 315static LIST_HEAD(acpi_table_attr_list);
313static struct kobject *tables_kobj; 316static struct kobject *tables_kobj;
317static struct kobject *tables_data_kobj;
314static struct kobject *dynamic_tables_kobj; 318static struct kobject *dynamic_tables_kobj;
315static struct kobject *hotplug_kobj; 319static struct kobject *hotplug_kobj;
316 320
@@ -325,6 +329,11 @@ struct acpi_table_attr {
325 struct list_head node; 329 struct list_head node;
326}; 330};
327 331
332struct acpi_data_attr {
333 struct bin_attribute attr;
334 u64 addr;
335};
336
328static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, 337static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
329 struct bin_attribute *bin_attr, char *buf, 338 struct bin_attribute *bin_attr, char *buf,
330 loff_t offset, size_t count) 339 loff_t offset, size_t count)
@@ -420,6 +429,70 @@ acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
420 return AE_OK; 429 return AE_OK;
421} 430}
422 431
432static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
433 struct bin_attribute *bin_attr, char *buf,
434 loff_t offset, size_t count)
435{
436 struct acpi_data_attr *data_attr;
437 void __iomem *base;
438 ssize_t rc;
439
440 data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
441
442 base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
443 if (!base)
444 return -ENOMEM;
445 rc = memory_read_from_buffer(buf, count, &offset, base,
446 data_attr->attr.size);
447 acpi_os_unmap_memory(base, data_attr->attr.size);
448
449 return rc;
450}
451
452static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)
453{
454 struct acpi_table_bert *bert = th;
455
456 if (bert->header.length < sizeof(struct acpi_table_bert) ||
457 bert->region_length < sizeof(struct acpi_hest_generic_status)) {
458 kfree(data_attr);
459 return -EINVAL;
460 }
461 data_attr->addr = bert->address;
462 data_attr->attr.size = bert->region_length;
463 data_attr->attr.attr.name = "BERT";
464
465 return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr);
466}
467
468static struct acpi_data_obj {
469 char *name;
470 int (*fn)(void *, struct acpi_data_attr *);
471} acpi_data_objs[] = {
472 { ACPI_SIG_BERT, acpi_bert_data_init },
473};
474
475#define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs)
476
477static int acpi_table_data_init(struct acpi_table_header *th)
478{
479 struct acpi_data_attr *data_attr;
480 int i;
481
482 for (i = 0; i < NUM_ACPI_DATA_OBJS; i++) {
483 if (ACPI_COMPARE_NAME(th->signature, acpi_data_objs[i].name)) {
484 data_attr = kzalloc(sizeof(*data_attr), GFP_KERNEL);
485 if (!data_attr)
486 return -ENOMEM;
487 sysfs_attr_init(&data_attr->attr.attr);
488 data_attr->attr.read = acpi_data_show;
489 data_attr->attr.attr.mode = 0400;
490 return acpi_data_objs[i].fn(th, data_attr);
491 }
492 }
493 return 0;
494}
495
423static int acpi_tables_sysfs_init(void) 496static int acpi_tables_sysfs_init(void)
424{ 497{
425 struct acpi_table_attr *table_attr; 498 struct acpi_table_attr *table_attr;
@@ -432,6 +505,10 @@ static int acpi_tables_sysfs_init(void)
432 if (!tables_kobj) 505 if (!tables_kobj)
433 goto err; 506 goto err;
434 507
508 tables_data_kobj = kobject_create_and_add("data", tables_kobj);
509 if (!tables_data_kobj)
510 goto err_tables_data;
511
435 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); 512 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj);
436 if (!dynamic_tables_kobj) 513 if (!dynamic_tables_kobj)
437 goto err_dynamic_tables; 514 goto err_dynamic_tables;
@@ -456,13 +533,17 @@ static int acpi_tables_sysfs_init(void)
456 return ret; 533 return ret;
457 } 534 }
458 list_add_tail(&table_attr->node, &acpi_table_attr_list); 535 list_add_tail(&table_attr->node, &acpi_table_attr_list);
536 acpi_table_data_init(table_header);
459 } 537 }
460 538
461 kobject_uevent(tables_kobj, KOBJ_ADD); 539 kobject_uevent(tables_kobj, KOBJ_ADD);
540 kobject_uevent(tables_data_kobj, KOBJ_ADD);
462 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); 541 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD);
463 542
464 return 0; 543 return 0;
465err_dynamic_tables: 544err_dynamic_tables:
545 kobject_put(tables_data_kobj);
546err_tables_data:
466 kobject_put(tables_kobj); 547 kobject_put(tables_kobj);
467err: 548err:
468 return -ENOMEM; 549 return -ENOMEM;
@@ -552,11 +633,15 @@ static void fixed_event_count(u32 event_number)
552static void acpi_global_event_handler(u32 event_type, acpi_handle device, 633static void acpi_global_event_handler(u32 event_type, acpi_handle device,
553 u32 event_number, void *context) 634 u32 event_number, void *context)
554{ 635{
555 if (event_type == ACPI_EVENT_TYPE_GPE) 636 if (event_type == ACPI_EVENT_TYPE_GPE) {
556 gpe_count(event_number); 637 gpe_count(event_number);
557 638 pr_debug("GPE event 0x%02x\n", event_number);
558 if (event_type == ACPI_EVENT_TYPE_FIXED) 639 } else if (event_type == ACPI_EVENT_TYPE_FIXED) {
559 fixed_event_count(event_number); 640 fixed_event_count(event_number);
641 pr_debug("Fixed event 0x%02x\n", event_number);
642 } else {
643 pr_debug("Other event 0x%02x\n", event_number);
644 }
560} 645}
561 646
562static int get_status(u32 index, acpi_event_status *status, 647static int get_status(u32 index, acpi_event_status *status,