summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/scan.c129
1 files changed, 52 insertions, 77 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index ed2b5f9a9815..954bd01f295a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -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);
}