diff options
Diffstat (limited to 'drivers/macintosh/windfarm_core.c')
-rw-r--r-- | drivers/macintosh/windfarm_core.c | 122 |
1 files changed, 92 insertions, 30 deletions
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 6c2a471ea6c0..bb8d5efe19bf 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/reboot.h> | 33 | #include <linux/reboot.h> |
34 | #include <linux/device.h> | 34 | #include <linux/device.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include <linux/mutex.h> | ||
36 | 37 | ||
37 | #include "windfarm.h" | 38 | #include "windfarm.h" |
38 | 39 | ||
@@ -48,13 +49,17 @@ | |||
48 | 49 | ||
49 | static LIST_HEAD(wf_controls); | 50 | static LIST_HEAD(wf_controls); |
50 | static LIST_HEAD(wf_sensors); | 51 | static LIST_HEAD(wf_sensors); |
51 | static DECLARE_MUTEX(wf_lock); | 52 | static DEFINE_MUTEX(wf_lock); |
52 | static struct notifier_block *wf_client_list; | 53 | static struct notifier_block *wf_client_list; |
53 | static int wf_client_count; | 54 | static int wf_client_count; |
54 | static unsigned int wf_overtemp; | 55 | static unsigned int wf_overtemp; |
55 | static unsigned int wf_overtemp_counter; | 56 | static unsigned int wf_overtemp_counter; |
56 | struct task_struct *wf_thread; | 57 | struct task_struct *wf_thread; |
57 | 58 | ||
59 | static struct platform_device wf_platform_device = { | ||
60 | .name = "windfarm", | ||
61 | }; | ||
62 | |||
58 | /* | 63 | /* |
59 | * Utilities & tick thread | 64 | * Utilities & tick thread |
60 | */ | 65 | */ |
@@ -156,26 +161,67 @@ static void wf_control_release(struct kref *kref) | |||
156 | kfree(ct); | 161 | kfree(ct); |
157 | } | 162 | } |
158 | 163 | ||
164 | static ssize_t wf_show_control(struct device *dev, | ||
165 | struct device_attribute *attr, char *buf) | ||
166 | { | ||
167 | struct wf_control *ctrl = container_of(attr, struct wf_control, attr); | ||
168 | s32 val = 0; | ||
169 | int err; | ||
170 | |||
171 | err = ctrl->ops->get_value(ctrl, &val); | ||
172 | if (err < 0) | ||
173 | return err; | ||
174 | return sprintf(buf, "%d\n", val); | ||
175 | } | ||
176 | |||
177 | /* This is really only for debugging... */ | ||
178 | static ssize_t wf_store_control(struct device *dev, | ||
179 | struct device_attribute *attr, | ||
180 | const char *buf, size_t count) | ||
181 | { | ||
182 | struct wf_control *ctrl = container_of(attr, struct wf_control, attr); | ||
183 | int val; | ||
184 | int err; | ||
185 | char *endp; | ||
186 | |||
187 | val = simple_strtoul(buf, &endp, 0); | ||
188 | while (endp < buf + count && (*endp == ' ' || *endp == '\n')) | ||
189 | ++endp; | ||
190 | if (endp - buf < count) | ||
191 | return -EINVAL; | ||
192 | err = ctrl->ops->set_value(ctrl, val); | ||
193 | if (err < 0) | ||
194 | return err; | ||
195 | return count; | ||
196 | } | ||
197 | |||
159 | int wf_register_control(struct wf_control *new_ct) | 198 | int wf_register_control(struct wf_control *new_ct) |
160 | { | 199 | { |
161 | struct wf_control *ct; | 200 | struct wf_control *ct; |
162 | 201 | ||
163 | down(&wf_lock); | 202 | mutex_lock(&wf_lock); |
164 | list_for_each_entry(ct, &wf_controls, link) { | 203 | list_for_each_entry(ct, &wf_controls, link) { |
165 | if (!strcmp(ct->name, new_ct->name)) { | 204 | if (!strcmp(ct->name, new_ct->name)) { |
166 | printk(KERN_WARNING "windfarm: trying to register" | 205 | printk(KERN_WARNING "windfarm: trying to register" |
167 | " duplicate control %s\n", ct->name); | 206 | " duplicate control %s\n", ct->name); |
168 | up(&wf_lock); | 207 | mutex_unlock(&wf_lock); |
169 | return -EEXIST; | 208 | return -EEXIST; |
170 | } | 209 | } |
171 | } | 210 | } |
172 | kref_init(&new_ct->ref); | 211 | kref_init(&new_ct->ref); |
173 | list_add(&new_ct->link, &wf_controls); | 212 | list_add(&new_ct->link, &wf_controls); |
174 | 213 | ||
214 | new_ct->attr.attr.name = new_ct->name; | ||
215 | new_ct->attr.attr.owner = THIS_MODULE; | ||
216 | new_ct->attr.attr.mode = 0644; | ||
217 | new_ct->attr.show = wf_show_control; | ||
218 | new_ct->attr.store = wf_store_control; | ||
219 | device_create_file(&wf_platform_device.dev, &new_ct->attr); | ||
220 | |||
175 | DBG("wf: Registered control %s\n", new_ct->name); | 221 | DBG("wf: Registered control %s\n", new_ct->name); |
176 | 222 | ||
177 | wf_notify(WF_EVENT_NEW_CONTROL, new_ct); | 223 | wf_notify(WF_EVENT_NEW_CONTROL, new_ct); |
178 | up(&wf_lock); | 224 | mutex_unlock(&wf_lock); |
179 | 225 | ||
180 | return 0; | 226 | return 0; |
181 | } | 227 | } |
@@ -183,9 +229,9 @@ EXPORT_SYMBOL_GPL(wf_register_control); | |||
183 | 229 | ||
184 | void wf_unregister_control(struct wf_control *ct) | 230 | void wf_unregister_control(struct wf_control *ct) |
185 | { | 231 | { |
186 | down(&wf_lock); | 232 | mutex_lock(&wf_lock); |
187 | list_del(&ct->link); | 233 | list_del(&ct->link); |
188 | up(&wf_lock); | 234 | mutex_unlock(&wf_lock); |
189 | 235 | ||
190 | DBG("wf: Unregistered control %s\n", ct->name); | 236 | DBG("wf: Unregistered control %s\n", ct->name); |
191 | 237 | ||
@@ -197,16 +243,16 @@ struct wf_control * wf_find_control(const char *name) | |||
197 | { | 243 | { |
198 | struct wf_control *ct; | 244 | struct wf_control *ct; |
199 | 245 | ||
200 | down(&wf_lock); | 246 | mutex_lock(&wf_lock); |
201 | list_for_each_entry(ct, &wf_controls, link) { | 247 | list_for_each_entry(ct, &wf_controls, link) { |
202 | if (!strcmp(ct->name, name)) { | 248 | if (!strcmp(ct->name, name)) { |
203 | if (wf_get_control(ct)) | 249 | if (wf_get_control(ct)) |
204 | ct = NULL; | 250 | ct = NULL; |
205 | up(&wf_lock); | 251 | mutex_unlock(&wf_lock); |
206 | return ct; | 252 | return ct; |
207 | } | 253 | } |
208 | } | 254 | } |
209 | up(&wf_lock); | 255 | mutex_unlock(&wf_lock); |
210 | return NULL; | 256 | return NULL; |
211 | } | 257 | } |
212 | EXPORT_SYMBOL_GPL(wf_find_control); | 258 | EXPORT_SYMBOL_GPL(wf_find_control); |
@@ -246,26 +292,46 @@ static void wf_sensor_release(struct kref *kref) | |||
246 | kfree(sr); | 292 | kfree(sr); |
247 | } | 293 | } |
248 | 294 | ||
295 | static ssize_t wf_show_sensor(struct device *dev, | ||
296 | struct device_attribute *attr, char *buf) | ||
297 | { | ||
298 | struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr); | ||
299 | s32 val = 0; | ||
300 | int err; | ||
301 | |||
302 | err = sens->ops->get_value(sens, &val); | ||
303 | if (err < 0) | ||
304 | return err; | ||
305 | return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val)); | ||
306 | } | ||
307 | |||
249 | int wf_register_sensor(struct wf_sensor *new_sr) | 308 | int wf_register_sensor(struct wf_sensor *new_sr) |
250 | { | 309 | { |
251 | struct wf_sensor *sr; | 310 | struct wf_sensor *sr; |
252 | 311 | ||
253 | down(&wf_lock); | 312 | mutex_lock(&wf_lock); |
254 | list_for_each_entry(sr, &wf_sensors, link) { | 313 | list_for_each_entry(sr, &wf_sensors, link) { |
255 | if (!strcmp(sr->name, new_sr->name)) { | 314 | if (!strcmp(sr->name, new_sr->name)) { |
256 | printk(KERN_WARNING "windfarm: trying to register" | 315 | printk(KERN_WARNING "windfarm: trying to register" |
257 | " duplicate sensor %s\n", sr->name); | 316 | " duplicate sensor %s\n", sr->name); |
258 | up(&wf_lock); | 317 | mutex_unlock(&wf_lock); |
259 | return -EEXIST; | 318 | return -EEXIST; |
260 | } | 319 | } |
261 | } | 320 | } |
262 | kref_init(&new_sr->ref); | 321 | kref_init(&new_sr->ref); |
263 | list_add(&new_sr->link, &wf_sensors); | 322 | list_add(&new_sr->link, &wf_sensors); |
264 | 323 | ||
324 | new_sr->attr.attr.name = new_sr->name; | ||
325 | new_sr->attr.attr.owner = THIS_MODULE; | ||
326 | new_sr->attr.attr.mode = 0444; | ||
327 | new_sr->attr.show = wf_show_sensor; | ||
328 | new_sr->attr.store = NULL; | ||
329 | device_create_file(&wf_platform_device.dev, &new_sr->attr); | ||
330 | |||
265 | DBG("wf: Registered sensor %s\n", new_sr->name); | 331 | DBG("wf: Registered sensor %s\n", new_sr->name); |
266 | 332 | ||
267 | wf_notify(WF_EVENT_NEW_SENSOR, new_sr); | 333 | wf_notify(WF_EVENT_NEW_SENSOR, new_sr); |
268 | up(&wf_lock); | 334 | mutex_unlock(&wf_lock); |
269 | 335 | ||
270 | return 0; | 336 | return 0; |
271 | } | 337 | } |
@@ -273,9 +339,9 @@ EXPORT_SYMBOL_GPL(wf_register_sensor); | |||
273 | 339 | ||
274 | void wf_unregister_sensor(struct wf_sensor *sr) | 340 | void wf_unregister_sensor(struct wf_sensor *sr) |
275 | { | 341 | { |
276 | down(&wf_lock); | 342 | mutex_lock(&wf_lock); |
277 | list_del(&sr->link); | 343 | list_del(&sr->link); |
278 | up(&wf_lock); | 344 | mutex_unlock(&wf_lock); |
279 | 345 | ||
280 | DBG("wf: Unregistered sensor %s\n", sr->name); | 346 | DBG("wf: Unregistered sensor %s\n", sr->name); |
281 | 347 | ||
@@ -287,16 +353,16 @@ struct wf_sensor * wf_find_sensor(const char *name) | |||
287 | { | 353 | { |
288 | struct wf_sensor *sr; | 354 | struct wf_sensor *sr; |
289 | 355 | ||
290 | down(&wf_lock); | 356 | mutex_lock(&wf_lock); |
291 | list_for_each_entry(sr, &wf_sensors, link) { | 357 | list_for_each_entry(sr, &wf_sensors, link) { |
292 | if (!strcmp(sr->name, name)) { | 358 | if (!strcmp(sr->name, name)) { |
293 | if (wf_get_sensor(sr)) | 359 | if (wf_get_sensor(sr)) |
294 | sr = NULL; | 360 | sr = NULL; |
295 | up(&wf_lock); | 361 | mutex_unlock(&wf_lock); |
296 | return sr; | 362 | return sr; |
297 | } | 363 | } |
298 | } | 364 | } |
299 | up(&wf_lock); | 365 | mutex_unlock(&wf_lock); |
300 | return NULL; | 366 | return NULL; |
301 | } | 367 | } |
302 | EXPORT_SYMBOL_GPL(wf_find_sensor); | 368 | EXPORT_SYMBOL_GPL(wf_find_sensor); |
@@ -329,7 +395,7 @@ int wf_register_client(struct notifier_block *nb) | |||
329 | struct wf_control *ct; | 395 | struct wf_control *ct; |
330 | struct wf_sensor *sr; | 396 | struct wf_sensor *sr; |
331 | 397 | ||
332 | down(&wf_lock); | 398 | mutex_lock(&wf_lock); |
333 | rc = notifier_chain_register(&wf_client_list, nb); | 399 | rc = notifier_chain_register(&wf_client_list, nb); |
334 | if (rc != 0) | 400 | if (rc != 0) |
335 | goto bail; | 401 | goto bail; |
@@ -341,19 +407,19 @@ int wf_register_client(struct notifier_block *nb) | |||
341 | if (wf_client_count == 1) | 407 | if (wf_client_count == 1) |
342 | wf_start_thread(); | 408 | wf_start_thread(); |
343 | bail: | 409 | bail: |
344 | up(&wf_lock); | 410 | mutex_unlock(&wf_lock); |
345 | return rc; | 411 | return rc; |
346 | } | 412 | } |
347 | EXPORT_SYMBOL_GPL(wf_register_client); | 413 | EXPORT_SYMBOL_GPL(wf_register_client); |
348 | 414 | ||
349 | int wf_unregister_client(struct notifier_block *nb) | 415 | int wf_unregister_client(struct notifier_block *nb) |
350 | { | 416 | { |
351 | down(&wf_lock); | 417 | mutex_lock(&wf_lock); |
352 | notifier_chain_unregister(&wf_client_list, nb); | 418 | notifier_chain_unregister(&wf_client_list, nb); |
353 | wf_client_count++; | 419 | wf_client_count++; |
354 | if (wf_client_count == 0) | 420 | if (wf_client_count == 0) |
355 | wf_stop_thread(); | 421 | wf_stop_thread(); |
356 | up(&wf_lock); | 422 | mutex_unlock(&wf_lock); |
357 | 423 | ||
358 | return 0; | 424 | return 0; |
359 | } | 425 | } |
@@ -361,23 +427,23 @@ EXPORT_SYMBOL_GPL(wf_unregister_client); | |||
361 | 427 | ||
362 | void wf_set_overtemp(void) | 428 | void wf_set_overtemp(void) |
363 | { | 429 | { |
364 | down(&wf_lock); | 430 | mutex_lock(&wf_lock); |
365 | wf_overtemp++; | 431 | wf_overtemp++; |
366 | if (wf_overtemp == 1) { | 432 | if (wf_overtemp == 1) { |
367 | printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); | 433 | printk(KERN_WARNING "windfarm: Overtemp condition detected !\n"); |
368 | wf_overtemp_counter = 0; | 434 | wf_overtemp_counter = 0; |
369 | wf_notify(WF_EVENT_OVERTEMP, NULL); | 435 | wf_notify(WF_EVENT_OVERTEMP, NULL); |
370 | } | 436 | } |
371 | up(&wf_lock); | 437 | mutex_unlock(&wf_lock); |
372 | } | 438 | } |
373 | EXPORT_SYMBOL_GPL(wf_set_overtemp); | 439 | EXPORT_SYMBOL_GPL(wf_set_overtemp); |
374 | 440 | ||
375 | void wf_clear_overtemp(void) | 441 | void wf_clear_overtemp(void) |
376 | { | 442 | { |
377 | down(&wf_lock); | 443 | mutex_lock(&wf_lock); |
378 | WARN_ON(wf_overtemp == 0); | 444 | WARN_ON(wf_overtemp == 0); |
379 | if (wf_overtemp == 0) { | 445 | if (wf_overtemp == 0) { |
380 | up(&wf_lock); | 446 | mutex_unlock(&wf_lock); |
381 | return; | 447 | return; |
382 | } | 448 | } |
383 | wf_overtemp--; | 449 | wf_overtemp--; |
@@ -385,7 +451,7 @@ void wf_clear_overtemp(void) | |||
385 | printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); | 451 | printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n"); |
386 | wf_notify(WF_EVENT_NORMALTEMP, NULL); | 452 | wf_notify(WF_EVENT_NORMALTEMP, NULL); |
387 | } | 453 | } |
388 | up(&wf_lock); | 454 | mutex_unlock(&wf_lock); |
389 | } | 455 | } |
390 | EXPORT_SYMBOL_GPL(wf_clear_overtemp); | 456 | EXPORT_SYMBOL_GPL(wf_clear_overtemp); |
391 | 457 | ||
@@ -395,10 +461,6 @@ int wf_is_overtemp(void) | |||
395 | } | 461 | } |
396 | EXPORT_SYMBOL_GPL(wf_is_overtemp); | 462 | EXPORT_SYMBOL_GPL(wf_is_overtemp); |
397 | 463 | ||
398 | static struct platform_device wf_platform_device = { | ||
399 | .name = "windfarm", | ||
400 | }; | ||
401 | |||
402 | static int __init windfarm_core_init(void) | 464 | static int __init windfarm_core_init(void) |
403 | { | 465 | { |
404 | DBG("wf: core loaded\n"); | 466 | DBG("wf: core loaded\n"); |