aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/fan.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index a6e149d692cb..f6e8165c32e8 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -30,7 +30,7 @@
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33 33#include <linux/thermal.h>
34#include <acpi/acpi_bus.h> 34#include <acpi/acpi_bus.h>
35#include <acpi/acpi_drivers.h> 35#include <acpi/acpi_drivers.h>
36 36
@@ -68,9 +68,55 @@ static struct acpi_driver acpi_fan_driver = {
68 }, 68 },
69}; 69};
70 70
71/* thermal cooling device callbacks */
72static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf)
73{
74 /* ACPI fan device only support two states: ON/OFF */
75 return sprintf(buf, "1\n");
76}
77
78static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
79{
80 struct acpi_device *device = cdev->devdata;
81 int state;
82 int result;
83
84 if (!device)
85 return -EINVAL;
86
87 result = acpi_bus_get_power(device->handle, &state);
88 if (result)
89 return result;
90
91 return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" :
92 (state == ACPI_STATE_D0 ? "1" : "unknown"));
93}
94
95static int
96fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
97{
98 struct acpi_device *device = cdev->devdata;
99 int result;
100
101 if (!device || (state != 0 && state != 1))
102 return -EINVAL;
103
104 result = acpi_bus_set_power(device->handle,
105 state ? ACPI_STATE_D0 : ACPI_STATE_D3);
106
107 return result;
108}
109
110static struct thermal_cooling_device_ops fan_cooling_ops = {
111 .get_max_state = fan_get_max_state,
112 .get_cur_state = fan_get_cur_state,
113 .set_cur_state = fan_set_cur_state,
114};
115
71/* -------------------------------------------------------------------------- 116/* --------------------------------------------------------------------------
72 FS Interface (/proc) 117 FS Interface (/proc)
73 -------------------------------------------------------------------------- */ 118 -------------------------------------------------------------------------- */
119#ifdef CONFIG_ACPI_PROCFS
74 120
75static struct proc_dir_entry *acpi_fan_dir; 121static struct proc_dir_entry *acpi_fan_dir;
76 122
@@ -171,7 +217,17 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
171 217
172 return 0; 218 return 0;
173} 219}
220#else
221static int acpi_fan_add_fs(struct acpi_device *device)
222{
223 return 0;
224}
174 225
226static int acpi_fan_remove_fs(struct acpi_device *device)
227{
228 return 0;
229}
230#endif
175/* -------------------------------------------------------------------------- 231/* --------------------------------------------------------------------------
176 Driver Interface 232 Driver Interface
177 -------------------------------------------------------------------------- */ 233 -------------------------------------------------------------------------- */
@@ -179,9 +235,8 @@ static int acpi_fan_remove_fs(struct acpi_device *device)
179static int acpi_fan_add(struct acpi_device *device) 235static int acpi_fan_add(struct acpi_device *device)
180{ 236{
181 int result = 0; 237 int result = 0;
182 struct acpi_fan *fan = NULL;
183 int state = 0; 238 int state = 0;
184 239 struct thermal_cooling_device *cdev;
185 240
186 if (!device) 241 if (!device)
187 return -EINVAL; 242 return -EINVAL;
@@ -199,6 +254,25 @@ static int acpi_fan_add(struct acpi_device *device)
199 acpi_bus_set_power(device->handle, state); 254 acpi_bus_set_power(device->handle, state);
200 device->flags.force_power_state = 0; 255 device->flags.force_power_state = 0;
201 256
257 cdev = thermal_cooling_device_register("Fan", device,
258 &fan_cooling_ops);
259 if (cdev)
260 printk(KERN_INFO PREFIX
261 "%s is registered as cooling_device%d\n",
262 device->dev.bus_id, cdev->id);
263 else
264 goto end;
265 acpi_driver_data(device) = cdev;
266 result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj,
267 "thermal_cooling");
268 if (result)
269 return result;
270
271 result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj,
272 "device");
273 if (result)
274 return result;
275
202 result = acpi_fan_add_fs(device); 276 result = acpi_fan_add_fs(device);
203 if (result) 277 if (result)
204 goto end; 278 goto end;
@@ -208,18 +282,20 @@ static int acpi_fan_add(struct acpi_device *device)
208 !device->power.state ? "on" : "off"); 282 !device->power.state ? "on" : "off");
209 283
210 end: 284 end:
211 if (result)
212 kfree(fan);
213
214 return result; 285 return result;
215} 286}
216 287
217static int acpi_fan_remove(struct acpi_device *device, int type) 288static int acpi_fan_remove(struct acpi_device *device, int type)
218{ 289{
219 if (!device || !acpi_driver_data(device)) 290 struct thermal_cooling_device *cdev = acpi_driver_data(device);
291
292 if (!device || !cdev)
220 return -EINVAL; 293 return -EINVAL;
221 294
222 acpi_fan_remove_fs(device); 295 acpi_fan_remove_fs(device);
296 sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
297 sysfs_remove_link(&cdev->device.kobj, "device");
298 thermal_cooling_device_unregister(cdev);
223 299
224 return 0; 300 return 0;
225} 301}