summaryrefslogtreecommitdiff
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c285
1 files changed, 111 insertions, 174 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 10985573aaa7..61d090b6ce25 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -193,9 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl,
static int acpi_scan_hot_remove(struct acpi_device *device)
{
acpi_handle handle = device->handle;
- acpi_handle not_used;
- struct acpi_object_list arg_list;
- union acpi_object arg;
struct device *errdev;
acpi_status status;
unsigned long long sta;
@@ -258,32 +255,15 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
put_device(&device->dev);
device = NULL;
- if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &not_used))) {
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 0;
- acpi_evaluate_object(handle, "_LCK", &arg_list, NULL);
- }
-
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
-
+ acpi_evaluate_lck(handle, 0);
/*
* TBD: _EJD support.
*/
- status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
- if (ACPI_FAILURE(status)) {
- if (status == AE_NOT_FOUND) {
- return -ENODEV;
- } else {
- acpi_handle_warn(handle, "Eject failed (0x%x)\n",
- status);
- return -EIO;
- }
- }
+ status = acpi_evaluate_ej0(handle);
+ if (status == AE_NOT_FOUND)
+ return -ENODEV;
+ else if (ACPI_FAILURE(status))
+ return -EIO;
/*
* Verify if eject was indeed successful. If not, log an error
@@ -307,6 +287,7 @@ static void acpi_bus_device_eject(void *context)
struct acpi_device *device = NULL;
struct acpi_scan_handler *handler;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+ int error;
mutex_lock(&acpi_scan_lock);
@@ -321,17 +302,13 @@ static void acpi_bus_device_eject(void *context)
}
acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
- if (handler->hotplug.mode == AHM_CONTAINER) {
- device->flags.eject_pending = true;
+ if (handler->hotplug.mode == AHM_CONTAINER)
kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
- } else {
- int error;
- get_device(&device->dev);
- error = acpi_scan_hot_remove(device);
- if (error)
- goto err_out;
- }
+ get_device(&device->dev);
+ error = acpi_scan_hot_remove(device);
+ if (error)
+ goto err_out;
out:
mutex_unlock(&acpi_scan_lock);
@@ -352,10 +329,12 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
mutex_lock(&acpi_scan_lock);
lock_device_hotplug();
- acpi_bus_get_device(handle, &device);
- if (device) {
- dev_warn(&device->dev, "Attempt to re-insert\n");
- goto out;
+ if (ost_source != ACPI_NOTIFY_BUS_CHECK) {
+ acpi_bus_get_device(handle, &device);
+ if (device) {
+ dev_warn(&device->dev, "Attempt to re-insert\n");
+ goto out;
+ }
}
acpi_evaluate_hotplug_ost(handle, ost_source,
ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
@@ -514,7 +493,6 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
struct acpi_eject_event *ej_event;
acpi_object_type not_used;
acpi_status status;
- u32 ost_source;
int ret;
if (!count || buf[0] != '1')
@@ -528,43 +506,28 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
return -ENODEV;
- mutex_lock(&acpi_scan_lock);
-
- if (acpi_device->flags.eject_pending) {
- /* ACPI eject notification event. */
- ost_source = ACPI_NOTIFY_EJECT_REQUEST;
- acpi_device->flags.eject_pending = 0;
- } else {
- /* Eject initiated by user space. */
- ost_source = ACPI_OST_EC_OSPM_EJECT;
- }
ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
if (!ej_event) {
ret = -ENOMEM;
goto err_out;
}
- acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
+ acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
ej_event->device = acpi_device;
- ej_event->event = ost_source;
+ ej_event->event = ACPI_OST_EC_OSPM_EJECT;
get_device(&acpi_device->dev);
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
- if (ACPI_FAILURE(status)) {
- put_device(&acpi_device->dev);
- kfree(ej_event);
- ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
- goto err_out;
- }
- ret = count;
+ if (ACPI_SUCCESS(status))
+ return count;
- out:
- mutex_unlock(&acpi_scan_lock);
- return ret;
+ put_device(&acpi_device->dev);
+ kfree(ej_event);
+ ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
err_out:
- acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
+ acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
- goto out;
+ return ret;
}
static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
@@ -652,7 +615,6 @@ static int acpi_device_setup_files(struct acpi_device *dev)
{
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
- acpi_handle temp;
unsigned long long sun;
int result = 0;
@@ -678,8 +640,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
/*
* If device has _STR, 'description' file is created
*/
- status = acpi_get_handle(dev->handle, "_STR", &temp);
- if (ACPI_SUCCESS(status)) {
+ if (acpi_has_method(dev->handle, "_STR")) {
status = acpi_evaluate_object(dev->handle, "_STR",
NULL, &buffer);
if (ACPI_FAILURE(status))
@@ -709,8 +670,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
* If device has _EJ0, 'eject' file is created that is used to trigger
* hot-removal function from userland.
*/
- status = acpi_get_handle(dev->handle, "_EJ0", &temp);
- if (ACPI_SUCCESS(status)) {
+ if (acpi_has_method(dev->handle, "_EJ0")) {
result = device_create_file(&dev->dev, &dev_attr_eject);
if (result)
return result;
@@ -732,9 +692,6 @@ end:
static void acpi_device_remove_files(struct acpi_device *dev)
{
- acpi_status status;
- acpi_handle temp;
-
if (dev->flags.power_manageable) {
device_remove_file(&dev->dev, &dev_attr_power_state);
if (dev->power.flags.power_resources)
@@ -745,20 +702,17 @@ static void acpi_device_remove_files(struct acpi_device *dev)
/*
* If device has _STR, remove 'description' file
*/
- status = acpi_get_handle(dev->handle, "_STR", &temp);
- if (ACPI_SUCCESS(status)) {
+ if (acpi_has_method(dev->handle, "_STR")) {
kfree(dev->pnp.str_obj);
device_remove_file(&dev->dev, &dev_attr_description);
}
/*
* If device has _EJ0, remove 'eject' file.
*/
- status = acpi_get_handle(dev->handle, "_EJ0", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(dev->handle, "_EJ0"))
device_remove_file(&dev->dev, &dev_attr_eject);
- status = acpi_get_handle(dev->handle, "_SUN", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(dev->handle, "_SUN"))
device_remove_file(&dev->dev, &dev_attr_sun);
if (dev->pnp.unique_id)
@@ -997,6 +951,28 @@ struct bus_type acpi_bus_type = {
.uevent = acpi_device_uevent,
};
+static void acpi_bus_data_handler(acpi_handle handle, void *context)
+{
+ /* Intentionally empty. */
+}
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+ acpi_status status;
+
+ if (!device)
+ return -EINVAL;
+
+ status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
+ if (ACPI_FAILURE(status) || !*device) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+ handle));
+ return -ENODEV;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_get_device);
+
int acpi_device_add(struct acpi_device *device,
void (*release)(struct device *))
{
@@ -1208,14 +1184,6 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
}
EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);
-void acpi_bus_data_handler(acpi_handle handle, void *context)
-{
-
- /* TBD */
-
- return;
-}
-
static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
struct acpi_device_wakeup *wakeup)
{
@@ -1334,13 +1302,10 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
{
- acpi_handle temp;
- acpi_status status = 0;
int err;
/* Presence of _PRW indicates wake capable */
- status = acpi_get_handle(device->handle, "_PRW", &temp);
- if (ACPI_FAILURE(status))
+ if (!acpi_has_method(device->handle, "_PRW"))
return;
err = acpi_bus_extract_wakeup_device_power_package(device->handle,
@@ -1370,7 +1335,6 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
struct acpi_device_power_state *ps = &device->power.states[state];
char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' };
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- acpi_handle handle;
acpi_status status;
INIT_LIST_HEAD(&ps->resources);
@@ -1393,8 +1357,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
/* Evaluate "_PSx" to see if we can do explicit sets */
pathname[2] = 'S';
- status = acpi_get_handle(device->handle, pathname, &handle);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, pathname))
ps->flags.explicit_set = 1;
/*
@@ -1413,28 +1376,21 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
static void acpi_bus_get_power_flags(struct acpi_device *device)
{
- acpi_status status;
- acpi_handle handle;
u32 i;
/* Presence of _PS0|_PR0 indicates 'power manageable' */
- status = acpi_get_handle(device->handle, "_PS0", &handle);
- if (ACPI_FAILURE(status)) {
- status = acpi_get_handle(device->handle, "_PR0", &handle);
- if (ACPI_FAILURE(status))
- return;
- }
+ if (!acpi_has_method(device->handle, "_PS0") &&
+ !acpi_has_method(device->handle, "_PR0"))
+ return;
device->flags.power_manageable = 1;
/*
* Power Management Flags
*/
- status = acpi_get_handle(device->handle, "_PSC", &handle);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_PSC"))
device->power.flags.explicit_get = 1;
- status = acpi_get_handle(device->handle, "_IRC", &handle);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_IRC"))
device->power.flags.inrush_current = 1;
/*
@@ -1448,8 +1404,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
/* Set defaults for D0 and D3 states (always valid) */
device->power.states[ACPI_STATE_D0].flags.valid = 1;
device->power.states[ACPI_STATE_D0].power = 100;
- device->power.states[ACPI_STATE_D3].flags.valid = 1;
- device->power.states[ACPI_STATE_D3].power = 0;
+ device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
+ device->power.states[ACPI_STATE_D3_COLD].power = 0;
/* Set D3cold's explicit_set flag if _PS3 exists. */
if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
@@ -1468,28 +1424,18 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
static void acpi_bus_get_flags(struct acpi_device *device)
{
- acpi_status status = AE_OK;
- acpi_handle temp = NULL;
-
/* Presence of _STA indicates 'dynamic_status' */
- status = acpi_get_handle(device->handle, "_STA", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_STA"))
device->flags.dynamic_status = 1;
/* Presence of _RMV indicates 'removable' */
- status = acpi_get_handle(device->handle, "_RMV", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_RMV"))
device->flags.removable = 1;
/* Presence of _EJD|_EJ0 indicates 'ejectable' */
- status = acpi_get_handle(device->handle, "_EJD", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_EJD") ||
+ acpi_has_method(device->handle, "_EJ0"))
device->flags.ejectable = 1;
- else {
- status = acpi_get_handle(device->handle, "_EJ0", &temp);
- if (ACPI_SUCCESS(status))
- device->flags.ejectable = 1;
- }
}
static void acpi_device_get_busid(struct acpi_device *device)
@@ -1531,46 +1477,45 @@ static void acpi_device_get_busid(struct acpi_device *device)
}
/*
+ * acpi_ata_match - see if an acpi object is an ATA device
+ *
+ * If an acpi object has one of the ACPI ATA methods defined,
+ * then we can safely call it an ATA device.
+ */
+bool acpi_ata_match(acpi_handle handle)
+{
+ return acpi_has_method(handle, "_GTF") ||
+ acpi_has_method(handle, "_GTM") ||
+ acpi_has_method(handle, "_STM") ||
+ acpi_has_method(handle, "_SDD");
+}
+
+/*
* acpi_bay_match - see if an acpi object is an ejectable driver bay
*
* If an acpi object is ejectable and has one of the ACPI ATA methods defined,
* then we can safely call it an ejectable drive bay
*/
-static int acpi_bay_match(acpi_handle handle)
+bool acpi_bay_match(acpi_handle handle)
{
- acpi_status status;
- acpi_handle tmp;
acpi_handle phandle;
- status = acpi_get_handle(handle, "_EJ0", &tmp);
- if (ACPI_FAILURE(status))
- return -ENODEV;
+ if (!acpi_has_method(handle, "_EJ0"))
+ return false;
+ if (acpi_ata_match(handle))
+ return true;
+ if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
+ return false;
- if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
- return 0;
-
- if (acpi_get_parent(handle, &phandle))
- return -ENODEV;
-
- if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) ||
- (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp))))
- return 0;
-
- return -ENODEV;
+ return acpi_ata_match(phandle);
}
/*
* acpi_dock_match - see if an acpi object has a _DCK method
*/
-static int acpi_dock_match(acpi_handle handle)
+bool acpi_dock_match(acpi_handle handle)
{
- acpi_handle tmp;
- return acpi_get_handle(handle, "_DCK", &tmp);
+ return acpi_has_method(handle, "_DCK");
}
const char *acpi_device_hid(struct acpi_device *device)
@@ -1608,34 +1553,26 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
* lacks the SMBUS01 HID and the methods do not have the necessary "_"
* prefix. Work around this.
*/
-static int acpi_ibm_smbus_match(acpi_handle handle)
+static bool acpi_ibm_smbus_match(acpi_handle handle)
{
- acpi_handle h_dummy;
- struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
- int result;
+ char node_name[ACPI_PATH_SEGMENT_LENGTH];
+ struct acpi_buffer path = { sizeof(node_name), node_name };
if (!dmi_name_in_vendors("IBM"))
- return -ENODEV;
+ return false;
/* Look for SMBS object */
- result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path);
- if (result)
- return result;
-
- if (strcmp("SMBS", path.pointer)) {
- result = -ENODEV;
- goto out;
- }
+ if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &path)) ||
+ strcmp("SMBS", path.pointer))
+ return false;
/* Does it have the necessary (but misnamed) methods? */
- result = -ENODEV;
- if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) &&
- ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) &&
- ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy)))
- result = 0;
-out:
- kfree(path.pointer);
- return result;
+ if (acpi_has_method(handle, "SBI") &&
+ acpi_has_method(handle, "SBR") &&
+ acpi_has_method(handle, "SBW"))
+ return true;
+
+ return false;
}
static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
@@ -1683,11 +1620,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
*/
if (acpi_is_video_device(handle))
acpi_add_id(pnp, ACPI_VIDEO_HID);
- else if (ACPI_SUCCESS(acpi_bay_match(handle)))
+ else if (acpi_bay_match(handle))
acpi_add_id(pnp, ACPI_BAY_HID);
- else if (ACPI_SUCCESS(acpi_dock_match(handle)))
+ else if (acpi_dock_match(handle))
acpi_add_id(pnp, ACPI_DOCK_HID);
- else if (!acpi_ibm_smbus_match(handle))
+ else if (acpi_ibm_smbus_match(handle))
acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
@@ -1898,7 +1835,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
struct acpi_device *device = NULL;
int type;
unsigned long long sta;
- acpi_status status;
int result;
acpi_bus_get_device(handle, &device);
@@ -1919,10 +1855,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
!(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
struct acpi_device_wakeup wakeup;
- acpi_handle temp;
- status = acpi_get_handle(handle, "_PRW", &temp);
- if (ACPI_SUCCESS(status)) {
+ if (acpi_has_method(handle, "_PRW")) {
acpi_bus_extract_wakeup_device_power_package(handle,
&wakeup);
acpi_power_resources_list_free(&wakeup.resources);
@@ -1981,6 +1915,9 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
if (acpi_bus_get_device(handle, &device))
return AE_CTRL_DEPTH;
+ if (device->handler)
+ return AE_OK;
+
ret = acpi_scan_attach_handler(device);
if (ret)
return ret > 0 ? AE_OK : AE_CTRL_DEPTH;