ACPI / scan: More straightforward preparation of ACPI device objects
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 17 Jan 2013 13:11:05 +0000 (14:11 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 17 Jan 2013 13:11:05 +0000 (14:11 +0100)
Simplify the code preparing struct acpi_device objects for
registration by removing useless code, moving different pieces of
code into the functions they belong to and making a couple of int
functions always returning 0 void.

This also fixes a possible memory leak in ACPI device registration
error code path by making acpi_device_register() detach data from
device->handle if device_register() fails and prepares the scanning
code for special-casing ACPI power resources (next patch).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/scan.c

index c6d6091..02629a8 100644 (file)
@@ -472,6 +472,7 @@ static void acpi_free_ids(struct acpi_device *device)
                kfree(id->id);
                kfree(id);
        }
+       kfree(device->pnp.unique_id);
 }
 
 static void acpi_device_release(struct device *dev)
@@ -479,7 +480,6 @@ static void acpi_device_release(struct device *dev)
        struct acpi_device *acpi_dev = to_acpi_device(dev);
 
        acpi_free_ids(acpi_dev);
-       kfree(acpi_dev->pnp.unique_id);
        kfree(acpi_dev);
 }
 
@@ -623,6 +623,18 @@ static int acpi_device_register(struct acpi_device *device)
        struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
        int found = 0;
 
+       if (device->handle) {
+               acpi_status status;
+
+               status = acpi_attach_data(device->handle, acpi_bus_data_handler,
+                                         device);
+               if (ACPI_FAILURE(status)) {
+                       acpi_handle_err(device->handle,
+                                       "Unable to attach device data\n");
+                       return -ENODEV;
+               }
+       }
+
        /*
         * Linkage
         * -------
@@ -637,8 +649,9 @@ static int acpi_device_register(struct acpi_device *device)
 
        new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
        if (!new_bus_id) {
-               printk(KERN_ERR PREFIX "Memory allocation error\n");
-               return -ENOMEM;
+               pr_err(PREFIX "Memory allocation error\n");
+               result = -ENOMEM;
+               goto err_detach;
        }
 
        mutex_lock(&acpi_device_lock);
@@ -677,7 +690,7 @@ static int acpi_device_register(struct acpi_device *device)
        result = device_register(&device->dev);
        if (result) {
                dev_err(&device->dev, "Error registering device\n");
-               goto end;
+               goto err;
        }
 
        result = acpi_device_setup_files(device);
@@ -687,12 +700,16 @@ static int acpi_device_register(struct acpi_device *device)
 
        device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
        return 0;
-end:
+
+ err:
        mutex_lock(&acpi_device_lock);
        if (device->parent)
                list_del(&device->node);
        list_del(&device->wakeup_list);
        mutex_unlock(&acpi_device_lock);
+
+ err_detach:
+       acpi_detach_data(device->handle, acpi_bus_data_handler);
        return result;
 }
 
@@ -857,12 +874,6 @@ void acpi_bus_data_handler(acpi_handle handle, void *context)
        return;
 }
 
-static int acpi_bus_get_perf_flags(struct acpi_device *device)
-{
-       device->performance.state = ACPI_STATE_UNKNOWN;
-       return 0;
-}
-
 static acpi_status
 acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
                                             struct acpi_device_wakeup *wakeup)
@@ -1013,12 +1024,25 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 
 static void acpi_bus_add_power_resource(acpi_handle handle);
 
-static int acpi_bus_get_power_flags(struct acpi_device *device)
+static void acpi_bus_get_power_flags(struct acpi_device *device)
 {
        acpi_status status = 0;
        acpi_handle handle = NULL;
        u32 i = 0;
 
+       /* Power resources cannot be power manageable. */
+       if (device->device_type == ACPI_BUS_TYPE_POWER)
+               return;
+
+       /* 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;
+       }
+
+       device->flags.power_manageable = 1;
 
        /*
         * Power Management Flags
@@ -1084,16 +1108,13 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
                device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1;
 
        acpi_bus_init_power(device);
-
-       return 0;
 }
 
-static int acpi_bus_get_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))
@@ -1113,21 +1134,6 @@ static int acpi_bus_get_flags(struct acpi_device *device)
                if (ACPI_SUCCESS(status))
                        device->flags.ejectable = 1;
        }
-
-       /* Power resources cannot be power manageable. */
-       if (device->device_type == ACPI_BUS_TYPE_POWER)
-               return 0;
-
-       /* Presence of _PS0|_PR0 indicates 'power manageable' */
-       status = acpi_get_handle(device->handle, "_PS0", &temp);
-       if (ACPI_FAILURE(status))
-               status = acpi_get_handle(device->handle, "_PR0", &temp);
-       if (ACPI_SUCCESS(status))
-               device->flags.power_manageable = 1;
-
-       /* TBD: Performance management */
-
-       return 0;
 }
 
 static void acpi_device_get_busid(struct acpi_device *device)
@@ -1352,27 +1358,18 @@ static void acpi_device_set_id(struct acpi_device *device)
        }
 }
 
-static int acpi_device_set_context(struct acpi_device *device)
+static void acpi_init_device_object(struct acpi_device *device,
+                                    acpi_handle handle,
+                                    int type, unsigned long long sta)
 {
-       acpi_status status;
-
-       /*
-        * Context
-        * -------
-        * Attach this 'struct acpi_device' to the ACPI object.  This makes
-        * resolutions from handle->device very efficient.  Fixed hardware
-        * devices have no handles, so we skip them.
-        */
-       if (!device->handle)
-               return 0;
-
-       status = acpi_attach_data(device->handle,
-                                 acpi_bus_data_handler, device);
-       if (ACPI_SUCCESS(status))
-               return 0;
-
-       printk(KERN_ERR PREFIX "Error attaching device data\n");
-       return -ENODEV;
+       INIT_LIST_HEAD(&device->pnp.ids);
+       device->device_type = type;
+       device->handle = handle;
+       device->parent = acpi_bus_get_parent(handle);
+       STRUCT_TO_INT(device->status) = sta;
+       acpi_device_get_busid(device);
+       acpi_device_set_id(device);
+       acpi_bus_get_flags(device);
 }
 
 static int acpi_add_single_object(struct acpi_device **child,
@@ -1389,78 +1386,25 @@ static int acpi_add_single_object(struct acpi_device **child,
                return -ENOMEM;
        }
 
-       INIT_LIST_HEAD(&device->pnp.ids);
-       device->device_type = type;
-       device->handle = handle;
-       device->parent = acpi_bus_get_parent(handle);
-       STRUCT_TO_INT(device->status) = sta;
-
-       acpi_device_get_busid(device);
-
-       /*
-        * Flags
-        * -----
-        * 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;
-
-       /*
-        * Initialize Device
-        * -----------------
-        * TBD: Synch with Core's enumeration/initialization process.
-        */
-       acpi_device_set_id(device);
-
-       /*
-        * Power Management
-        * ----------------
-        */
-       if (device->flags.power_manageable) {
-               result = acpi_bus_get_power_flags(device);
-               if (result)
-                       goto end;
-       }
-
-       /*
-        * Wakeup device management
-        *-----------------------
-        */
+       acpi_init_device_object(device, handle, type, sta);
+       acpi_bus_get_power_flags(device);
        acpi_bus_get_wakeup_device_flags(device);
 
-       /*
-        * Performance Management
-        * ----------------------
-        */
-       if (device->flags.performance_manageable) {
-               result = acpi_bus_get_perf_flags(device);
-               if (result)
-                       goto end;
-       }
-
-       if ((result = acpi_device_set_context(device)))
-               goto end;
-
        device->flags.match_driver = match_driver;
        result = acpi_device_register(device);
-
-end:
-       if (!result) {
-               acpi_power_add_remove_device(device, true);
-               acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                       "Adding %s [%s] parent %s\n", dev_name(&device->dev),
-                        (char *) buffer.pointer,
-                        device->parent ? dev_name(&device->parent->dev) :
-                                         "(null)"));
-               kfree(buffer.pointer);
-               *child = device;
-       } else
+       if (result) {
                acpi_device_release(&device->dev);
+               return result;
+       }
 
-       return result;
+       acpi_power_add_remove_device(device, true);
+       acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n",
+               dev_name(&device->dev), (char *) buffer.pointer,
+               device->parent ? dev_name(&device->parent->dev) : "(null)"));
+       kfree(buffer.pointer);
+       *child = device;
+       return 0;
 }
 
 #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \