Re: [PATCH] ACPI / Thermal: make acpi_thermal_check asynchronous on resume

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tuesday, March 04, 2014 02:24:46 PM Aaron Lu wrote:
> On resume we do not need to wait for acpi_thermal_check to finish.
> Instead, we can run it asynchronously and not block the whole system
> resume. Also, we make sure when we are suspending again, previously
> queued work for acpi_thermal_check is done.
> 
> Signed-off-by: Aaron Lu <aaron.lu@xxxxxxxxx>

Queued up for 3.15, thanks!

> ---
>  drivers/acpi/thermal.c | 37 +++++++++++++++++++++++++++++++++----
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
> index 08626c851be7..964068553334 100644
> --- a/drivers/acpi/thermal.c
> +++ b/drivers/acpi/thermal.c
> @@ -43,6 +43,7 @@
>  #include <linux/device.h>
>  #include <linux/thermal.h>
>  #include <linux/acpi.h>
> +#include <linux/workqueue.h>
>  #include <asm/uaccess.h>
>  
>  #define PREFIX "ACPI: "
> @@ -90,6 +91,8 @@ static int psv;
>  module_param(psv, int, 0644);
>  MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
>  
> +static struct workqueue_struct *acpi_thermal_pm_queue;
> +
>  static int acpi_thermal_add(struct acpi_device *device);
>  static int acpi_thermal_remove(struct acpi_device *device);
>  static void acpi_thermal_notify(struct acpi_device *device, u32 event);
> @@ -101,11 +104,13 @@ static const struct acpi_device_id  thermal_device_ids[] = {
>  MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
>  
>  #ifdef CONFIG_PM_SLEEP
> +static int acpi_thermal_suspend(struct device *dev);
>  static int acpi_thermal_resume(struct device *dev);
>  #else
> +#define acpi_thermal_suspend NULL
>  #define acpi_thermal_resume NULL
>  #endif
> -static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
> +static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume);
>  
>  static struct acpi_driver acpi_thermal_driver = {
>  	.name = "thermal",
> @@ -186,6 +191,7 @@ struct acpi_thermal {
>  	struct thermal_zone_device *thermal_zone;
>  	int tz_enabled;
>  	int kelvin_offset;
> +	struct work_struct thermal_check_work;
>  };
>  
>  /* --------------------------------------------------------------------------
> @@ -1064,6 +1070,13 @@ static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
>  		tz->kelvin_offset = 2732;
>  }
>  
> +static void acpi_thermal_check_fn(struct work_struct *work)
> +{
> +	struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
> +					       thermal_check_work);
> +	acpi_thermal_check(tz);
> +}
> +
>  static int acpi_thermal_add(struct acpi_device *device)
>  {
>  	int result = 0;
> @@ -1093,6 +1106,8 @@ static int acpi_thermal_add(struct acpi_device *device)
>  	if (result)
>  		goto free_memory;
>  
> +	INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
> +
>  	pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
>  		acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
>  	goto end;
> @@ -1110,6 +1125,7 @@ static int acpi_thermal_remove(struct acpi_device *device)
>  	if (!device || !acpi_driver_data(device))
>  		return -EINVAL;
>  
> +	flush_workqueue(acpi_thermal_pm_queue);
>  	tz = acpi_driver_data(device);
>  
>  	acpi_thermal_unregister_thermal_zone(tz);
> @@ -1118,6 +1134,13 @@ static int acpi_thermal_remove(struct acpi_device *device)
>  }
>  
>  #ifdef CONFIG_PM_SLEEP
> +static int acpi_thermal_suspend(struct device *dev)
> +{
> +	/* Make sure the previously queued thermal check work has been done */
> +	flush_workqueue(acpi_thermal_pm_queue);
> +	return 0;
> +}
> +
>  static int acpi_thermal_resume(struct device *dev)
>  {
>  	struct acpi_thermal *tz;
> @@ -1148,7 +1171,7 @@ static int acpi_thermal_resume(struct device *dev)
>  		tz->state.active |= tz->trips.active[i].flags.enabled;
>  	}
>  
> -	acpi_thermal_check(tz);
> +	queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
>  
>  	return AE_OK;
>  }
> @@ -1240,16 +1263,22 @@ static int __init acpi_thermal_init(void)
>  		return -ENODEV;
>  	}
>  
> +	acpi_thermal_pm_queue = create_workqueue("acpi_thermal_pm");
> +	if (!acpi_thermal_pm_queue)
> +		return -ENODEV;
> +
>  	result = acpi_bus_register_driver(&acpi_thermal_driver);
> -	if (result < 0)
> +	if (result < 0) {
> +		destroy_workqueue(acpi_thermal_pm_queue);
>  		return -ENODEV;
> +	}
>  
>  	return 0;
>  }
>  
>  static void __exit acpi_thermal_exit(void)
>  {
> -
> +	destroy_workqueue(acpi_thermal_pm_queue);
>  	acpi_bus_unregister_driver(&acpi_thermal_driver);
>  
>  	return;
> 

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux