ACPI: factor out device type and status checking
authorBjorn Helgaas <bjorn.helgaas@hp.com>
Mon, 21 Sep 2009 19:30:06 +0000 (19:30 +0000)
committerLen Brown <len.brown@intel.com>
Fri, 25 Sep 2009 18:24:31 +0000 (14:24 -0400)
This patch adds acpi_bus_type_and_status(), which determines the type
of the object and whether we want to build an acpi_device for it.  If
it is acpi_device-worthy, it returns the type and the device's current
status.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/scan.c

index ed2b5f9..954bd01 100644 (file)
@@ -1252,6 +1252,7 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
 
 static int acpi_add_single_object(struct acpi_device **child,
                                  acpi_handle handle, int type,
+                                 unsigned long long sta,
                                  struct acpi_bus_ops *ops)
 {
        int result;
@@ -1268,61 +1269,21 @@ static int acpi_add_single_object(struct acpi_device **child,
        device->handle = handle;
        device->parent = acpi_bus_get_parent(handle);
        device->bus_ops = *ops; /* workround for not call .start */
+       STRUCT_TO_INT(device->status) = sta;
 
        acpi_device_get_busid(device);
 
        /*
         * Flags
         * -----
-        * Get prior to calling acpi_bus_get_status() so we know whether
-        * or not _STA is present.  Note that we only look for object
-        * handles -- cannot evaluate objects until we know the device is
-        * present and properly initialized.
+        * Note that we only look for object handles -- cannot evaluate objects
+        * until we know the device is present and properly initialized.
         */
        result = acpi_bus_get_flags(device);
        if (result)
                goto end;
 
        /*
-        * Status
-        * ------
-        * See if the device is present.  We always assume that non-Device
-        * and non-Processor objects (e.g. thermal zones, power resources,
-        * etc.) are present, functioning, etc. (at least when parent object
-        * is present).  Note that _STA has a different meaning for some
-        * objects (e.g. power resources) so we need to be careful how we use
-        * it.
-        */
-       switch (type) {
-       case ACPI_BUS_TYPE_PROCESSOR:
-       case ACPI_BUS_TYPE_DEVICE:
-               result = acpi_bus_get_status(device);
-               if (ACPI_FAILURE(result)) {
-                       result = -ENODEV;
-                       goto end;
-               }
-               /*
-                * When the device is neither present nor functional, the
-                * device should not be added to Linux ACPI device tree.
-                * When the status of the device is not present but functinal,
-                * it should be added to Linux ACPI tree. For example : bay
-                * device , dock device.
-                * In such conditions it is unncessary to check whether it is
-                * bay device or dock device.
-                */
-               if (!device->status.present && !device->status.functional) {
-                       result = -ENODEV;
-                       goto end;
-               }
-               break;
-       default:
-               STRUCT_TO_INT(device->status) =
-                   ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
-                   ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING;
-               break;
-       }
-
-       /*
         * Initialize Device
         * -----------------
         * TBD: Synch with Core's enumeration/initialization process.
@@ -1393,41 +1354,69 @@ end:
        return result;
 }
 
-static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
-                                     void *context, void **return_value)
+#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
+                         ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING)
+
+static int acpi_bus_type_and_status(acpi_handle handle, int *type,
+                                   unsigned long long *sta)
 {
-       acpi_status status = AE_OK;
-       struct acpi_device *device = NULL;
-       acpi_object_type type = 0;
-       struct acpi_bus_ops *ops = context;
+       acpi_status status;
+       acpi_object_type acpi_type;
 
-       status = acpi_get_type(handle, &type);
+       status = acpi_get_type(handle, &acpi_type);
        if (ACPI_FAILURE(status))
-               return AE_OK;
+               return -ENODEV;
 
-       /*
-        * We're only interested in objects that we consider 'devices'.
-        */
-       switch (type) {
+       switch (acpi_type) {
        case ACPI_TYPE_ANY:             /* for ACPI_ROOT_OBJECT */
        case ACPI_TYPE_DEVICE:
-               type = ACPI_BUS_TYPE_DEVICE;
+               *type = ACPI_BUS_TYPE_DEVICE;
+               status = acpi_bus_get_status_handle(handle, sta);
+               if (ACPI_FAILURE(status))
+                       return -ENODEV;
                break;
        case ACPI_TYPE_PROCESSOR:
-               type = ACPI_BUS_TYPE_PROCESSOR;
+               *type = ACPI_BUS_TYPE_PROCESSOR;
+               status = acpi_bus_get_status_handle(handle, sta);
+               if (ACPI_FAILURE(status))
+                       return -ENODEV;
                break;
        case ACPI_TYPE_THERMAL:
-               type = ACPI_BUS_TYPE_THERMAL;
+               *type = ACPI_BUS_TYPE_THERMAL;
+               *sta = ACPI_STA_DEFAULT;
                break;
        case ACPI_TYPE_POWER:
-               type = ACPI_BUS_TYPE_POWER;
+               *type = ACPI_BUS_TYPE_POWER;
+               *sta = ACPI_STA_DEFAULT;
                break;
        default:
-               return AE_OK;
+               return -ENODEV;
        }
 
+       return 0;
+}
+
+static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
+                                     void *context, void **return_value)
+{
+       struct acpi_bus_ops *ops = context;
+       struct acpi_device *device = NULL;
+       acpi_status status;
+       int type;
+       unsigned long long sta;
+       int result;
+
+       result = acpi_bus_type_and_status(handle, &type, &sta);
+       if (result)
+               return AE_OK;
+
+       if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
+           !(sta & ACPI_STA_DEVICE_FUNCTIONING))
+               return AE_CTRL_DEPTH;
+
        if (ops->acpi_op_add)
-               status = acpi_add_single_object(&device, handle, type, ops);
+               status = acpi_add_single_object(&device, handle, type, sta,
+                                               ops);
        else
                status = acpi_bus_get_device(handle, &device);
 
@@ -1440,22 +1429,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
                        return AE_CTRL_DEPTH;
        }
 
-       /*
-        * If the device is present, enabled, and functioning then
-        * parse its scope (depth-first).  Note that we need to
-        * represent absent devices to facilitate PnP notifications
-        * -- but only the subtree head (not all of its children,
-        * which will be enumerated when the parent is inserted).
-        *
-        * TBD: Need notifications and other detection mechanisms
-        *      in place before we can fully implement this.
-        *
-        * When the device is not present but functional, it is also
-        * necessary to scan the children of this device.
-        */
-       if (!device->status.present && !device->status.functional)
-               return AE_CTRL_DEPTH;
-
        if (!*return_value)
                *return_value = device;
        return AE_OK;
@@ -1579,12 +1552,14 @@ static int acpi_bus_scan_fixed(void)
        if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
                result = acpi_add_single_object(&device, NULL,
                                                ACPI_BUS_TYPE_POWER_BUTTON,
+                                               ACPI_STA_DEFAULT,
                                                &ops);
        }
 
        if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
                result = acpi_add_single_object(&device, NULL,
                                                ACPI_BUS_TYPE_SLEEP_BUTTON,
+                                               ACPI_STA_DEFAULT,
                                                &ops);
        }