Skip to content

Commit

Permalink
ACPI / platform / LPSS: Enable async suspend/resume of LPSS devices
Browse files Browse the repository at this point in the history
To seed up suspend and resume of devices included into Intel SoCs
handled by the ACPI LPSS driver during system suspend, make
acpi_lpss_create_device() call device_enable_async_suspend() for
every device created by it.

This requires acpi_create_platform_device() to be modified to return
a pointer to struct platform_device instead of an int.  As a result,
acpi_create_platform_device() cannot be pointed to by the .attach
pointer in platform_handler directly any more, so a simple wrapper
around it is necessary for this purpose.  That, in turn, allows the
second unused argument of acpi_create_platform_device() to be
dropped, which is an improvement.

Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Rafael J. Wysocki committed May 25, 2014
1 parent a3cffce commit 8ce62f8
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 19 deletions.
17 changes: 11 additions & 6 deletions drivers/acpi/acpi_lpss.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,14 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
struct lpss_private_data *pdata;
struct resource_list_entry *rentry;
struct list_head resource_list;
struct platform_device *pdev;
int ret;

dev_desc = (struct lpss_device_desc *)id->driver_data;
if (!dev_desc)
return acpi_create_platform_device(adev, id);

if (!dev_desc) {
pdev = acpi_create_platform_device(adev);
return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1;
}
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
Expand Down Expand Up @@ -322,10 +324,13 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
dev_desc->setup(pdata);

adev->driver_data = pdata;
ret = acpi_create_platform_device(adev, id);
if (ret > 0)
return ret;
pdev = acpi_create_platform_device(adev);
if (!IS_ERR_OR_NULL(pdev)) {
device_enable_async_suspend(&pdev->dev);
return 1;
}

ret = PTR_ERR(pdev);
adev->driver_data = NULL;

err_out:
Expand Down
25 changes: 14 additions & 11 deletions drivers/acpi/acpi_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,14 @@ static const struct acpi_device_id acpi_platform_device_ids[] = {
/**
* acpi_create_platform_device - Create platform device for ACPI device node
* @adev: ACPI device node to create a platform device for.
* @id: ACPI device ID used to match @adev.
*
* Check if the given @adev can be represented as a platform device and, if
* that's the case, create and register a platform device, populate its common
* resources and returns a pointer to it. Otherwise, return %NULL.
*
* Name of the platform device will be the same as @adev's.
*/
int acpi_create_platform_device(struct acpi_device *adev,
const struct acpi_device_id *id)
struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
{
struct platform_device *pdev = NULL;
struct acpi_device *acpi_parent;
Expand All @@ -68,19 +66,19 @@ int acpi_create_platform_device(struct acpi_device *adev,

/* If the ACPI node already has a physical device attached, skip it. */
if (adev->physical_node_count)
return 0;
return NULL;

INIT_LIST_HEAD(&resource_list);
count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (count < 0) {
return 0;
return NULL;
} else if (count > 0) {
resources = kmalloc(count * sizeof(struct resource),
GFP_KERNEL);
if (!resources) {
dev_err(&adev->dev, "No memory for resources\n");
acpi_dev_free_resource_list(&resource_list);
return -ENOMEM;
return ERR_PTR(-ENOMEM);
}
count = 0;
list_for_each_entry(rentry, &resource_list, node)
Expand Down Expand Up @@ -117,22 +115,27 @@ int acpi_create_platform_device(struct acpi_device *adev,
pdevinfo.num_res = count;
pdevinfo.acpi_node.companion = adev;
pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) {
if (IS_ERR(pdev))
dev_err(&adev->dev, "platform device creation failed: %ld\n",
PTR_ERR(pdev));
pdev = NULL;
} else {
else
dev_dbg(&adev->dev, "created platform device %s\n",
dev_name(&pdev->dev));
}

kfree(resources);
return pdev;
}

static int acpi_platform_attach(struct acpi_device *adev,
const struct acpi_device_id *id)
{
acpi_create_platform_device(adev);
return 1;
}

static struct acpi_scan_handler platform_handler = {
.ids = acpi_platform_device_ids,
.attach = acpi_create_platform_device,
.attach = acpi_platform_attach,
};

void __init acpi_platform_init(void)
Expand Down
3 changes: 1 addition & 2 deletions drivers/acpi/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,7 @@ static inline void suspend_nvs_restore(void) {}
-------------------------------------------------------------------------- */
struct platform_device;

int acpi_create_platform_device(struct acpi_device *adev,
const struct acpi_device_id *id);
struct platform_device *acpi_create_platform_device(struct acpi_device *adev);

/*--------------------------------------------------------------------------
Video
Expand Down

0 comments on commit 8ce62f8

Please sign in to comment.