ACPI: factor out device type and status checking
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>
This commit is contained in:
@@ -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,
|
static int acpi_add_single_object(struct acpi_device **child,
|
||||||
acpi_handle handle, int type,
|
acpi_handle handle, int type,
|
||||||
|
unsigned long long sta,
|
||||||
struct acpi_bus_ops *ops)
|
struct acpi_bus_ops *ops)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@@ -1268,60 +1269,20 @@ static int acpi_add_single_object(struct acpi_device **child,
|
|||||||
device->handle = handle;
|
device->handle = handle;
|
||||||
device->parent = acpi_bus_get_parent(handle);
|
device->parent = acpi_bus_get_parent(handle);
|
||||||
device->bus_ops = *ops; /* workround for not call .start */
|
device->bus_ops = *ops; /* workround for not call .start */
|
||||||
|
STRUCT_TO_INT(device->status) = sta;
|
||||||
|
|
||||||
acpi_device_get_busid(device);
|
acpi_device_get_busid(device);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags
|
* Flags
|
||||||
* -----
|
* -----
|
||||||
* Get prior to calling acpi_bus_get_status() so we know whether
|
* Note that we only look for object handles -- cannot evaluate objects
|
||||||
* or not _STA is present. Note that we only look for object
|
* until we know the device is present and properly initialized.
|
||||||
* handles -- cannot evaluate objects until we know the device is
|
|
||||||
* present and properly initialized.
|
|
||||||
*/
|
*/
|
||||||
result = acpi_bus_get_flags(device);
|
result = acpi_bus_get_flags(device);
|
||||||
if (result)
|
if (result)
|
||||||
goto end;
|
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
|
* Initialize Device
|
||||||
* -----------------
|
* -----------------
|
||||||
@@ -1393,41 +1354,69 @@ end:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
acpi_object_type acpi_type;
|
||||||
|
|
||||||
|
status = acpi_get_type(handle, &acpi_type);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
switch (acpi_type) {
|
||||||
|
case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
|
||||||
|
case ACPI_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;
|
||||||
|
status = acpi_bus_get_status_handle(handle, sta);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return -ENODEV;
|
||||||
|
break;
|
||||||
|
case ACPI_TYPE_THERMAL:
|
||||||
|
*type = ACPI_BUS_TYPE_THERMAL;
|
||||||
|
*sta = ACPI_STA_DEFAULT;
|
||||||
|
break;
|
||||||
|
case ACPI_TYPE_POWER:
|
||||||
|
*type = ACPI_BUS_TYPE_POWER;
|
||||||
|
*sta = ACPI_STA_DEFAULT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
|
static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
|
||||||
void *context, void **return_value)
|
void *context, void **return_value)
|
||||||
{
|
{
|
||||||
acpi_status status = AE_OK;
|
|
||||||
struct acpi_device *device = NULL;
|
|
||||||
acpi_object_type type = 0;
|
|
||||||
struct acpi_bus_ops *ops = context;
|
struct acpi_bus_ops *ops = context;
|
||||||
|
struct acpi_device *device = NULL;
|
||||||
|
acpi_status status;
|
||||||
|
int type;
|
||||||
|
unsigned long long sta;
|
||||||
|
int result;
|
||||||
|
|
||||||
status = acpi_get_type(handle, &type);
|
result = acpi_bus_type_and_status(handle, &type, &sta);
|
||||||
if (ACPI_FAILURE(status))
|
if (result)
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
|
|
||||||
/*
|
if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
|
||||||
* We're only interested in objects that we consider 'devices'.
|
!(sta & ACPI_STA_DEVICE_FUNCTIONING))
|
||||||
*/
|
return AE_CTRL_DEPTH;
|
||||||
switch (type) {
|
|
||||||
case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
|
|
||||||
case ACPI_TYPE_DEVICE:
|
|
||||||
type = ACPI_BUS_TYPE_DEVICE;
|
|
||||||
break;
|
|
||||||
case ACPI_TYPE_PROCESSOR:
|
|
||||||
type = ACPI_BUS_TYPE_PROCESSOR;
|
|
||||||
break;
|
|
||||||
case ACPI_TYPE_THERMAL:
|
|
||||||
type = ACPI_BUS_TYPE_THERMAL;
|
|
||||||
break;
|
|
||||||
case ACPI_TYPE_POWER:
|
|
||||||
type = ACPI_BUS_TYPE_POWER;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return AE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ops->acpi_op_add)
|
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
|
else
|
||||||
status = acpi_bus_get_device(handle, &device);
|
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;
|
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)
|
if (!*return_value)
|
||||||
*return_value = device;
|
*return_value = device;
|
||||||
return AE_OK;
|
return AE_OK;
|
||||||
@@ -1579,12 +1552,14 @@ static int acpi_bus_scan_fixed(void)
|
|||||||
if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
|
if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
|
||||||
result = acpi_add_single_object(&device, NULL,
|
result = acpi_add_single_object(&device, NULL,
|
||||||
ACPI_BUS_TYPE_POWER_BUTTON,
|
ACPI_BUS_TYPE_POWER_BUTTON,
|
||||||
|
ACPI_STA_DEFAULT,
|
||||||
&ops);
|
&ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
|
if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
|
||||||
result = acpi_add_single_object(&device, NULL,
|
result = acpi_add_single_object(&device, NULL,
|
||||||
ACPI_BUS_TYPE_SLEEP_BUTTON,
|
ACPI_BUS_TYPE_SLEEP_BUTTON,
|
||||||
|
ACPI_STA_DEFAULT,
|
||||||
&ops);
|
&ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user