From: Jiang Liu <[email protected]>

This patch implements a default mechanism to detect and manage ACPI system
device hotplug slots based on standard ACPI interfaces.
1) Detech hotplug slot by checking existence of _EJ0 and _STA methods.
2) Power off a slot by excuting _EJ0 method.

It's the default hotplug slot enumerating mechanism, platform specifc drivers
may provide advanced implementation to override the default implementation.

Signed-off-by: Jiang Liu <[email protected]>
Signed-off-by: Gaohuai Han <[email protected]>
Signed-off-by: Jiang Liu <[email protected]>
---
 drivers/acpi/Kconfig                 |   10 +++
 drivers/acpi/hotplug/Makefile        |    1 +
 drivers/acpi/hotplug/slot_enum.c     |    3 +
 drivers/acpi/hotplug/slot_enum_ej0.c |  113 ++++++++++++++++++++++++++++++++++
 4 files changed, 127 insertions(+)
 create mode 100644 drivers/acpi/hotplug/slot_enum_ej0.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 711e18e..c9f7918 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -344,6 +344,16 @@ config ACPI_HOTPLUG_ENUM
          To compile this driver as a module, choose M here:
          the module will be called acpihp_enum.
 
+config ACPI_HOTPLUG_ENUM_EJ0
+       bool "Detecting ACPI Hotplug Slot by Checking _EJ0 Method"
+       depends on ACPI_HOTPLUG_ENUM
+       default y
+       help
+         Enable detecting ACPI hotplug slots by checking ACPI _EJ0 method
+         under ACPI device objects.
+
+         It's the default method to detect ACPI hotplug slots.
+
 config ACPI_CONTAINER
        tristate "Container and Module Devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
diff --git a/drivers/acpi/hotplug/Makefile b/drivers/acpi/hotplug/Makefile
index 41c0da9..23dfa93 100644
--- a/drivers/acpi/hotplug/Makefile
+++ b/drivers/acpi/hotplug/Makefile
@@ -7,3 +7,4 @@ acpihp-y                                        = core.o
 
 obj-$(CONFIG_ACPI_HOTPLUG_ENUM)                        += acpihp_enum.o
 acpihp_enum-y                                  = slot_enum.o
+acpihp_enum-y                                  += slot_enum_ej0.o
diff --git a/drivers/acpi/hotplug/slot_enum.c b/drivers/acpi/hotplug/slot_enum.c
index 80396a3..a251ecf 100644
--- a/drivers/acpi/hotplug/slot_enum.c
+++ b/drivers/acpi/hotplug/slot_enum.c
@@ -40,11 +40,14 @@ struct acpihp_slot_id {
 
 static struct acpihp_slot_ops *slot_ops_curr;
 
+extern struct acpihp_slot_ops acpihp_enum_ej0;
+
 /*
  * Array of platform specific enumeration methods.
  * Entries in the array should be sorted by descending priority order.
  */
 static struct acpihp_slot_ops *slot_ops_array[] = {
+       &acpihp_enum_ej0,
        NULL
 };
 
diff --git a/drivers/acpi/hotplug/slot_enum_ej0.c 
b/drivers/acpi/hotplug/slot_enum_ej0.c
new file mode 100644
index 0000000..2788860
--- /dev/null
+++ b/drivers/acpi/hotplug/slot_enum_ej0.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2011 Huawei Tech. Co., Ltd.
+ * Copyright (C) 2011 Gaohuai Han <[email protected]>
+ * Copyright (C) 2011 Jiang Liu <[email protected]>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/acpi.h>
+#include <acpi/acpi.h>
+#include <acpi/acpi_hotplug.h>
+
+static acpi_status acpihp_enum_ej0_init(void)
+{
+       return AE_OK;
+}
+
+static void acpihp_enum_ej0_fini(void)
+{
+}
+
+static acpi_status acpihp_enum_ej0_check(acpi_handle handle)
+{
+       acpi_handle tmp;
+
+       /* Assume a device object with _EJ0 and _STA has a hotplug slot. */
+       if (ACPI_FAILURE(acpi_get_handle(handle, "_EJ0", &tmp)))
+               return AE_ERROR;
+       if (ACPI_FAILURE(acpi_get_handle(handle, METHOD_NAME__STA, &tmp)))
+               return AE_ERROR;
+
+       return AE_OK;
+}
+
+static acpi_status
+acpihp_enum_ej0_get_capabilities(acpi_handle handle, u32 *capability)
+{
+       /*
+        * Assume device objects with _EJ0 are capable of:
+        * ONLINE, OFFLINE, POWEROFF, HOTPLUG
+        */
+       *capability = ACPIHP_SLOT_CAP_ONLINE | ACPIHP_SLOT_CAP_OFFLINE |
+                     ACPIHP_SLOT_CAP_POWEROFF | ACPIHP_SLOT_CAP_HOTPLUG;
+
+       return AE_OK;
+}
+
+static acpi_status acpihp_enum_ej0_poweron(acpi_handle handle)
+{
+       return AE_SUPPORT;
+}
+
+static acpi_status acpihp_enum_ej0_poweroff(acpi_handle handle)
+{
+       acpi_status status;
+       unsigned long long sta;
+       union acpi_object arg;
+       struct acpi_object_list arg_list;
+
+       if (!handle)
+               return AE_BAD_PARAMETER;
+
+       arg_list.count = 1;
+       arg_list.pointer = &arg;
+       arg.type = ACPI_TYPE_INTEGER;
+       arg.integer.value = 1;
+       status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
+       if (ACPI_FAILURE(status)) {
+               ACPIHP_WARN("fails to power off object %p.\n", handle);
+               return status;
+       }
+
+       status = acpi_evaluate_integer(handle, METHOD_NAME__STA, NULL, &sta);
+       if (ACPI_FAILURE(status)) {
+               ACPIHP_WARN("fails to evaluate _STA method of object %p\n",
+                           handle);
+               return status;
+       }
+
+       if (sta & (ACPI_STA_DEVICE_FUNCTIONING | ACPI_STA_DEVICE_ENABLED)) {
+               ACPIHP_WARN("object %p is still active after executing _EJ0.\n",
+                           handle);
+               return AE_ERROR;
+       }
+
+       return AE_OK;
+}
+
+struct acpihp_slot_ops acpihp_enum_ej0 = {
+       .init = acpihp_enum_ej0_init,
+       .fini = acpihp_enum_ej0_fini,
+       .check = acpihp_enum_ej0_check,
+       .get_capabilities = acpihp_enum_ej0_get_capabilities,
+       .poweron = acpihp_enum_ej0_poweron,
+       .poweroff = acpihp_enum_ej0_poweroff,
+       .owner = THIS_MODULE,
+       .desc = "ACPI _EJ0 Based Hotplug Slot Enumerator"
+};
-- 
1.7.9.5


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to