aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/thermal.c
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2014-03-04 01:24:46 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-04 19:43:44 -0500
commita59ffb2062df3a5c346dbed931fa1e587fd0f0f3 (patch)
treefe3f973f9a0f85fcdd5e7ce723bd895495453132 /drivers/acpi/thermal.c
parent0414855fdc4a40da05221fc6062cccbc0c30f169 (diff)
ACPI / thermal: make acpi_thermal_check asynchronous on resume
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@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/thermal.c')
-rw-r--r--drivers/acpi/thermal.c37
1 files 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 @@
43#include <linux/device.h> 43#include <linux/device.h>
44#include <linux/thermal.h> 44#include <linux/thermal.h>
45#include <linux/acpi.h> 45#include <linux/acpi.h>
46#include <linux/workqueue.h>
46#include <asm/uaccess.h> 47#include <asm/uaccess.h>
47 48
48#define PREFIX "ACPI: " 49#define PREFIX "ACPI: "
@@ -90,6 +91,8 @@ static int psv;
90module_param(psv, int, 0644); 91module_param(psv, int, 0644);
91MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); 92MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
92 93
94static struct workqueue_struct *acpi_thermal_pm_queue;
95
93static int acpi_thermal_add(struct acpi_device *device); 96static int acpi_thermal_add(struct acpi_device *device);
94static int acpi_thermal_remove(struct acpi_device *device); 97static int acpi_thermal_remove(struct acpi_device *device);
95static void acpi_thermal_notify(struct acpi_device *device, u32 event); 98static void acpi_thermal_notify(struct acpi_device *device, u32 event);
@@ -101,11 +104,13 @@ static const struct acpi_device_id thermal_device_ids[] = {
101MODULE_DEVICE_TABLE(acpi, thermal_device_ids); 104MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
102 105
103#ifdef CONFIG_PM_SLEEP 106#ifdef CONFIG_PM_SLEEP
107static int acpi_thermal_suspend(struct device *dev);
104static int acpi_thermal_resume(struct device *dev); 108static int acpi_thermal_resume(struct device *dev);
105#else 109#else
110#define acpi_thermal_suspend NULL
106#define acpi_thermal_resume NULL 111#define acpi_thermal_resume NULL
107#endif 112#endif
108static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume); 113static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, acpi_thermal_suspend, acpi_thermal_resume);
109 114
110static struct acpi_driver acpi_thermal_driver = { 115static struct acpi_driver acpi_thermal_driver = {
111 .name = "thermal", 116 .name = "thermal",
@@ -186,6 +191,7 @@ struct acpi_thermal {
186 struct thermal_zone_device *thermal_zone; 191 struct thermal_zone_device *thermal_zone;
187 int tz_enabled; 192 int tz_enabled;
188 int kelvin_offset; 193 int kelvin_offset;
194 struct work_struct thermal_check_work;
189}; 195};
190 196
191/* -------------------------------------------------------------------------- 197/* --------------------------------------------------------------------------
@@ -1064,6 +1070,13 @@ static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
1064 tz->kelvin_offset = 2732; 1070 tz->kelvin_offset = 2732;
1065} 1071}
1066 1072
1073static void acpi_thermal_check_fn(struct work_struct *work)
1074{
1075 struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
1076 thermal_check_work);
1077 acpi_thermal_check(tz);
1078}
1079
1067static int acpi_thermal_add(struct acpi_device *device) 1080static int acpi_thermal_add(struct acpi_device *device)
1068{ 1081{
1069 int result = 0; 1082 int result = 0;
@@ -1093,6 +1106,8 @@ static int acpi_thermal_add(struct acpi_device *device)
1093 if (result) 1106 if (result)
1094 goto free_memory; 1107 goto free_memory;
1095 1108
1109 INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
1110
1096 pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), 1111 pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
1097 acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); 1112 acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
1098 goto end; 1113 goto end;
@@ -1110,6 +1125,7 @@ static int acpi_thermal_remove(struct acpi_device *device)
1110 if (!device || !acpi_driver_data(device)) 1125 if (!device || !acpi_driver_data(device))
1111 return -EINVAL; 1126 return -EINVAL;
1112 1127
1128 flush_workqueue(acpi_thermal_pm_queue);
1113 tz = acpi_driver_data(device); 1129 tz = acpi_driver_data(device);
1114 1130
1115 acpi_thermal_unregister_thermal_zone(tz); 1131 acpi_thermal_unregister_thermal_zone(tz);
@@ -1118,6 +1134,13 @@ static int acpi_thermal_remove(struct acpi_device *device)
1118} 1134}
1119 1135
1120#ifdef CONFIG_PM_SLEEP 1136#ifdef CONFIG_PM_SLEEP
1137static int acpi_thermal_suspend(struct device *dev)
1138{
1139 /* Make sure the previously queued thermal check work has been done */
1140 flush_workqueue(acpi_thermal_pm_queue);
1141 return 0;
1142}
1143
1121static int acpi_thermal_resume(struct device *dev) 1144static int acpi_thermal_resume(struct device *dev)
1122{ 1145{
1123 struct acpi_thermal *tz; 1146 struct acpi_thermal *tz;
@@ -1148,7 +1171,7 @@ static int acpi_thermal_resume(struct device *dev)
1148 tz->state.active |= tz->trips.active[i].flags.enabled; 1171 tz->state.active |= tz->trips.active[i].flags.enabled;
1149 } 1172 }
1150 1173
1151 acpi_thermal_check(tz); 1174 queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
1152 1175
1153 return AE_OK; 1176 return AE_OK;
1154} 1177}
@@ -1240,16 +1263,22 @@ static int __init acpi_thermal_init(void)
1240 return -ENODEV; 1263 return -ENODEV;
1241 } 1264 }
1242 1265
1266 acpi_thermal_pm_queue = create_workqueue("acpi_thermal_pm");
1267 if (!acpi_thermal_pm_queue)
1268 return -ENODEV;
1269
1243 result = acpi_bus_register_driver(&acpi_thermal_driver); 1270 result = acpi_bus_register_driver(&acpi_thermal_driver);
1244 if (result < 0) 1271 if (result < 0) {
1272 destroy_workqueue(acpi_thermal_pm_queue);
1245 return -ENODEV; 1273 return -ENODEV;
1274 }
1246 1275
1247 return 0; 1276 return 0;
1248} 1277}
1249 1278
1250static void __exit acpi_thermal_exit(void) 1279static void __exit acpi_thermal_exit(void)
1251{ 1280{
1252 1281 destroy_workqueue(acpi_thermal_pm_queue);
1253 acpi_bus_unregister_driver(&acpi_thermal_driver); 1282 acpi_bus_unregister_driver(&acpi_thermal_driver);
1254 1283
1255 return; 1284 return;