|
@@ -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,60 +1269,20 @@ 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
|
|
|
* -----------------
|
|
@@ -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);
|
|
|
}
|
|
|
|