ACPI: introduce sysfs I/F for dynamic tables
authorZhang Rui <rui.zhang@intel.com>
Thu, 26 Feb 2009 03:27:23 +0000 (11:27 +0800)
committerLen Brown <len.brown@intel.com>
Thu, 26 Feb 2009 06:03:15 +0000 (01:03 -0500)
SSDT tables may be loaded at runtime.
create sysfs I/F for these dynamic tables in
/sys/firmware/acpi/tables/dynamic/.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/system.c

index 391d035..c885904 100644 (file)
@@ -62,6 +62,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
    -------------------------------------------------------------------------- */
 static LIST_HEAD(acpi_table_attr_list);
 static struct kobject *tables_kobj;
+static struct kobject *dynamic_tables_kobj;
 
 struct acpi_table_attr {
        struct bin_attribute attr;
@@ -128,6 +129,40 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
        return;
 }
 
+static acpi_status
+acpi_sysfs_table_handler(u32 event, void *table, void *context)
+{
+       struct acpi_table_attr *table_attr;
+
+       switch (event) {
+       case ACPI_TABLE_EVENT_LOAD:
+               table_attr =
+                       kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
+               if (!table_attr)
+                       return AE_NO_MEMORY;
+
+               acpi_table_attr_init(table_attr, table);
+               if (sysfs_create_bin_file(dynamic_tables_kobj,
+                                       &table_attr->attr)) {
+                       kfree(table_attr);
+                       return AE_ERROR;
+               } else
+                       list_add_tail(&table_attr->node,
+                                       &acpi_table_attr_list);
+               break;
+       case ACPI_TABLE_EVENT_UNLOAD:
+               /*
+                * we do not need to do anything right now
+                * because the table is not deleted from the
+                * global table list when unloading it.
+                */
+               break;
+       default:
+               return AE_BAD_PARAMETER;
+       }
+       return AE_OK;
+}
+
 static int acpi_system_sysfs_init(void)
 {
        struct acpi_table_attr *table_attr;
@@ -137,7 +172,11 @@ static int acpi_system_sysfs_init(void)
 
        tables_kobj = kobject_create_and_add("tables", acpi_kobj);
        if (!tables_kobj)
-               return -ENOMEM;
+               goto err;
+
+       dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj);
+       if (!dynamic_tables_kobj)
+               goto err_dynamic_tables;
 
        do {
                result = acpi_get_table_by_index(table_index, &table_header);
@@ -162,8 +201,14 @@ static int acpi_system_sysfs_init(void)
                }
        } while (!result);
        kobject_uevent(tables_kobj, KOBJ_ADD);
-
-       return 0;
+       kobject_uevent(dynamic_tables_kobj, KOBJ_ADD);
+       result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL);
+
+       return result == AE_OK ? 0 : -EINVAL;
+err_dynamic_tables:
+       kobject_put(tables_kobj);
+err:
+       return -ENOMEM;
 }
 
 /*