]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/acpi/scan.c
Merge branch 'acpi-hotplug'
[karo-tx-linux.git] / drivers / acpi / scan.c
index 8a46c924effd4e5bef09cb645429170e70ed380a..fbdb82e70d10623c0bbf94aa73723a40fd32e77d 100644 (file)
@@ -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;
@@ -207,8 +204,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
                return -EINVAL;
        }
 
-       lock_device_hotplug();
-
        /*
         * Carry out two passes here and ignore errors in the first pass,
         * because if the devices in question are memory blocks and
@@ -239,9 +234,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
                                            ACPI_UINT32_MAX,
                                            acpi_bus_online_companions, NULL,
                                            NULL, NULL);
-
-                       unlock_device_hotplug();
-
                        put_device(&device->dev);
                        return -EBUSY;
                }
@@ -252,38 +244,19 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
 
        acpi_bus_trim(device);
 
-       unlock_device_hotplug();
-
        /* Device node has been unregistered. */
        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,7 +280,9 @@ 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;
 
+       lock_device_hotplug();
        mutex_lock(&acpi_scan_lock);
 
        acpi_bus_get_device(handle, &device);
@@ -321,20 +296,17 @@ 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);
+       unlock_device_hotplug();
        return;
 
  err_out:
@@ -349,8 +321,8 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
        int error;
 
-       mutex_lock(&acpi_scan_lock);
        lock_device_hotplug();
+       mutex_lock(&acpi_scan_lock);
 
        if (ost_source != ACPI_NOTIFY_BUS_CHECK) {
                acpi_bus_get_device(handle, &device);
@@ -376,9 +348,9 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
                kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
 
  out:
-       unlock_device_hotplug();
        acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
        mutex_unlock(&acpi_scan_lock);
+       unlock_device_hotplug();
 }
 
 static void acpi_scan_bus_check(void *context)
@@ -469,6 +441,7 @@ void acpi_bus_hot_remove_device(void *context)
        acpi_handle handle = device->handle;
        int error;
 
+       lock_device_hotplug();
        mutex_lock(&acpi_scan_lock);
 
        error = acpi_scan_hot_remove(device);
@@ -478,6 +451,7 @@ void acpi_bus_hot_remove_device(void *context)
                                          NULL);
 
        mutex_unlock(&acpi_scan_lock);
+       unlock_device_hotplug();
        kfree(context);
 }
 EXPORT_SYMBOL(acpi_bus_hot_remove_device);
@@ -516,7 +490,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')
@@ -530,43 +503,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);
@@ -654,7 +612,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;
 
@@ -680,8 +637,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))
@@ -711,8 +667,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;
@@ -734,9 +689,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)
@@ -747,20 +699,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)
@@ -999,6 +948,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 *))
 {
@@ -1210,14 +1181,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)
 {
@@ -1336,13 +1299,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,
@@ -1372,7 +1332,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);
@@ -1395,8 +1354,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;
 
        /*
@@ -1415,28 +1373,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;
 
        /*
@@ -1450,8 +1401,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)
@@ -1470,28 +1421,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)
@@ -1532,47 +1473,46 @@ 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_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_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_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)
@@ -1610,34 +1550,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,
@@ -1685,11 +1617,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 */
@@ -1900,7 +1832,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);
@@ -1921,10 +1852,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);