Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d43e167d authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

ACPI / scan: More straightforward preparation of ACPI device objects



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: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent bc9b6407
Loading
Loading
Loading
Loading
+61 −117
Original line number Diff line number Diff line
@@ -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);
	if (result) {
		acpi_device_release(&device->dev);
		return result;
	}

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)"));
	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;
	} else
		acpi_device_release(&device->dev);

	return result;
	return 0;
}

#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \