2c162f9b41722 (Thomas Gleixner 2019-06-03 07:45:02 +0200 1) // SPDX-License-Identifier: GPL-2.0-only
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 2) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 3) * Windfarm PowerMac thermal control. Core
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 4) *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 5) * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 6) * <benh@kernel.crashing.org>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 7) *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 8) * This core code tracks the list of sensors & controls, register
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 9) * clients, and holds the kernel thread used for control.
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 10) *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 11) * TODO:
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 12) *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 13) * Add some information about sensor/control type and data format to
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 14) * sensors/controls, and have the sysfs attribute stuff be moved
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 15) * generically here instead of hard coded in the platform specific
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 16) * driver as it us currently
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 17) *
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 18) * This however requires solving some annoying lifetime issues with
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 19) * sysfs which doesn't seem to have lifetime rules for struct attribute,
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 20) * I may have to create full features kobjects for every sensor/control
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 21) * instead which is a bit of an overkill imho
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 22) */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 23)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 24) #include <linux/types.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 25) #include <linux/errno.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 26) #include <linux/kernel.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 27) #include <linux/slab.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 28) #include <linux/init.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 29) #include <linux/spinlock.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 30) #include <linux/kthread.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 31) #include <linux/jiffies.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 32) #include <linux/reboot.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 33) #include <linux/device.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 34) #include <linux/platform_device.h>
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 35) #include <linux/mutex.h>
7dfb71030f763 (Nigel Cunningham 2006-12-06 20:34:23 -0800 36) #include <linux/freezer.h>
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 37)
b55fafc5a800f (Benjamin Herrenschmidt 2006-03-03 17:03:21 +1100 38) #include <asm/prom.h>
b55fafc5a800f (Benjamin Herrenschmidt 2006-03-03 17:03:21 +1100 39)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 40) #include "windfarm.h"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 41)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 42) #define VERSION "0.2"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 43)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 44) #undef DEBUG
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 45)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 46) #ifdef DEBUG
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 47) #define DBG(args...) printk(args)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 48) #else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 49) #define DBG(args...) do { } while(0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 50) #endif
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 51)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 52) static LIST_HEAD(wf_controls);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 53) static LIST_HEAD(wf_sensors);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 54) static DEFINE_MUTEX(wf_lock);
e041c683412d5 (Alan Stern 2006-03-27 01:16:30 -0800 55) static BLOCKING_NOTIFIER_HEAD(wf_client_list);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 56) static int wf_client_count;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 57) static unsigned int wf_overtemp;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 58) static unsigned int wf_overtemp_counter;
4204ecd598cb0 (Yu Kuai 2021-04-07 20:57:38 +0800 59) static struct task_struct *wf_thread;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 60)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 61) static struct platform_device wf_platform_device = {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 62) .name = "windfarm",
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 63) };
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 64)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 65) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 66) * Utilities & tick thread
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 67) */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 68)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 69) static inline void wf_notify(int event, void *param)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 70) {
e041c683412d5 (Alan Stern 2006-03-27 01:16:30 -0800 71) blocking_notifier_call_chain(&wf_client_list, event, param);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 72) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 73)
ca94bbab1a033 (Paul Bolle 2015-07-31 14:12:20 +0200 74) static int wf_critical_overtemp(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 75) {
377e7a27c049d (Greg Kroah-Hartman 2016-12-11 18:00:43 +0100 76) static char const critical_overtemp_path[] = "/sbin/critical_overtemp";
377e7a27c049d (Greg Kroah-Hartman 2016-12-11 18:00:43 +0100 77) char *argv[] = { (char *)critical_overtemp_path, NULL };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 78) static char *envp[] = { "HOME=/",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 79) "TERM=linux",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 80) "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 81) NULL };
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 82)
86313c488a684 (Jeremy Fitzhardinge 2007-07-17 18:37:03 -0700 83) return call_usermodehelper(critical_overtemp_path,
86313c488a684 (Jeremy Fitzhardinge 2007-07-17 18:37:03 -0700 84) argv, envp, UMH_WAIT_EXEC);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 85) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 86)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 87) static int wf_thread_func(void *data)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 88) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 89) unsigned long next, delay;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 90)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 91) next = jiffies;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 92)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 93) DBG("wf: thread started\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 94)
831441862956f (Rafael J. Wysocki 2007-07-17 04:03:35 -0700 95) set_freezable();
67b60518b0ff5 (Johannes Berg 2007-11-07 21:18:02 +1100 96) while (!kthread_should_stop()) {
67b60518b0ff5 (Johannes Berg 2007-11-07 21:18:02 +1100 97) try_to_freeze();
67b60518b0ff5 (Johannes Berg 2007-11-07 21:18:02 +1100 98)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 99) if (time_after_eq(jiffies, next)) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 100) wf_notify(WF_EVENT_TICK, NULL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 101) if (wf_overtemp) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 102) wf_overtemp_counter++;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 103) /* 10 seconds overtemp, notify userland */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 104) if (wf_overtemp_counter > 10)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 105) wf_critical_overtemp();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 106) /* 30 seconds, shutdown */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 107) if (wf_overtemp_counter > 30) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 108) printk(KERN_ERR "windfarm: Overtemp "
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 109) "for more than 30"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 110) " seconds, shutting down\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 111) machine_power_off();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 112) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 113) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 114) next += HZ;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 115) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 116)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 117) delay = next - jiffies;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 118) if (delay <= HZ)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 119) schedule_timeout_interruptible(delay);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 120) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 121)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 122) DBG("wf: thread stopped\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 123)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 124) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 125) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 126)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 127) static void wf_start_thread(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 128) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 129) wf_thread = kthread_run(wf_thread_func, NULL, "kwindfarm");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 130) if (IS_ERR(wf_thread)) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 131) printk(KERN_ERR "windfarm: failed to create thread,err %ld\n",
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 132) PTR_ERR(wf_thread));
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 133) wf_thread = NULL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 134) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 135) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 136)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 137)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 138) static void wf_stop_thread(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 139) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 140) if (wf_thread)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 141) kthread_stop(wf_thread);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 142) wf_thread = NULL;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 143) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 144)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 145) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 146) * Controls
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 147) */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 148)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 149) static void wf_control_release(struct kref *kref)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 150) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 151) struct wf_control *ct = container_of(kref, struct wf_control, ref);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 152)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 153) DBG("wf: Deleting control %s\n", ct->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 154)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 155) if (ct->ops && ct->ops->release)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 156) ct->ops->release(ct);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 157) else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 158) kfree(ct);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 159) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 160)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 161) static ssize_t wf_show_control(struct device *dev,
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 162) struct device_attribute *attr, char *buf)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 163) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 164) struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 165) const char *typestr;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 166) s32 val = 0;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 167) int err;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 168)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 169) err = ctrl->ops->get_value(ctrl, &val);
6cd3209967469 (Benjamin Herrenschmidt 2012-04-29 15:42:27 +0000 170) if (err < 0) {
6cd3209967469 (Benjamin Herrenschmidt 2012-04-29 15:42:27 +0000 171) if (err == -EFAULT)
6cd3209967469 (Benjamin Herrenschmidt 2012-04-29 15:42:27 +0000 172) return sprintf(buf, "<HW FAULT>\n");
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 173) return err;
6cd3209967469 (Benjamin Herrenschmidt 2012-04-29 15:42:27 +0000 174) }
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 175) switch(ctrl->type) {
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 176) case WF_CONTROL_RPM_FAN:
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 177) typestr = " RPM";
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 178) break;
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 179) case WF_CONTROL_PWM_FAN:
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 180) typestr = " %";
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 181) break;
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 182) default:
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 183) typestr = "";
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 184) }
ea5c64b06743b (Benjamin Herrenschmidt 2012-04-18 22:16:50 +0000 185) return sprintf(buf, "%d%s\n", val, typestr);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 186) }
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 187)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 188) /* This is really only for debugging... */
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 189) static ssize_t wf_store_control(struct device *dev,
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 190) struct device_attribute *attr,
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 191) const char *buf, size_t count)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 192) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 193) struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 194) int val;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 195) int err;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 196) char *endp;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 197)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 198) val = simple_strtoul(buf, &endp, 0);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 199) while (endp < buf + count && (*endp == ' ' || *endp == '\n'))
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 200) ++endp;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 201) if (endp - buf < count)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 202) return -EINVAL;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 203) err = ctrl->ops->set_value(ctrl, val);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 204) if (err < 0)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 205) return err;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 206) return count;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 207) }
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 208)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 209) int wf_register_control(struct wf_control *new_ct)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 210) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 211) struct wf_control *ct;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 212)
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 213) mutex_lock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 214) list_for_each_entry(ct, &wf_controls, link) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 215) if (!strcmp(ct->name, new_ct->name)) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 216) printk(KERN_WARNING "windfarm: trying to register"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 217) " duplicate control %s\n", ct->name);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 218) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 219) return -EEXIST;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 220) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 221) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 222) kref_init(&new_ct->ref);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 223) list_add(&new_ct->link, &wf_controls);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 224)
12765517d9dbb (Wolfram Sang 2010-04-06 14:34:52 -0700 225) sysfs_attr_init(&new_ct->attr.attr);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 226) new_ct->attr.attr.name = new_ct->name;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 227) new_ct->attr.attr.mode = 0644;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 228) new_ct->attr.show = wf_show_control;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 229) new_ct->attr.store = wf_store_control;
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 230) if (device_create_file(&wf_platform_device.dev, &new_ct->attr))
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 231) printk(KERN_WARNING "windfarm: device_create_file failed"
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 232) " for %s\n", new_ct->name);
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 233) /* the subsystem still does useful work without the file */
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 234)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 235) DBG("wf: Registered control %s\n", new_ct->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 236)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 237) wf_notify(WF_EVENT_NEW_CONTROL, new_ct);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 238) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 239)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 240) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 241) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 242) EXPORT_SYMBOL_GPL(wf_register_control);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 243)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 244) void wf_unregister_control(struct wf_control *ct)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 245) {
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 246) mutex_lock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 247) list_del(&ct->link);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 248) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 249)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 250) DBG("wf: Unregistered control %s\n", ct->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 251)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 252) kref_put(&ct->ref, wf_control_release);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 253) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 254) EXPORT_SYMBOL_GPL(wf_unregister_control);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 255)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 256) int wf_get_control(struct wf_control *ct)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 257) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 258) if (!try_module_get(ct->ops->owner))
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 259) return -ENODEV;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 260) kref_get(&ct->ref);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 261) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 262) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 263) EXPORT_SYMBOL_GPL(wf_get_control);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 264)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 265) void wf_put_control(struct wf_control *ct)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 266) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 267) struct module *mod = ct->ops->owner;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 268) kref_put(&ct->ref, wf_control_release);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 269) module_put(mod);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 270) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 271) EXPORT_SYMBOL_GPL(wf_put_control);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 272)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 273)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 274) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 275) * Sensors
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 276) */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 277)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 278)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 279) static void wf_sensor_release(struct kref *kref)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 280) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 281) struct wf_sensor *sr = container_of(kref, struct wf_sensor, ref);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 282)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 283) DBG("wf: Deleting sensor %s\n", sr->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 284)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 285) if (sr->ops && sr->ops->release)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 286) sr->ops->release(sr);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 287) else
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 288) kfree(sr);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 289) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 290)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 291) static ssize_t wf_show_sensor(struct device *dev,
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 292) struct device_attribute *attr, char *buf)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 293) {
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 294) struct wf_sensor *sens = container_of(attr, struct wf_sensor, attr);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 295) s32 val = 0;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 296) int err;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 297)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 298) err = sens->ops->get_value(sens, &val);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 299) if (err < 0)
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 300) return err;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 301) return sprintf(buf, "%d.%03d\n", FIX32TOPRINT(val));
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 302) }
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 303)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 304) int wf_register_sensor(struct wf_sensor *new_sr)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 305) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 306) struct wf_sensor *sr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 307)
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 308) mutex_lock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 309) list_for_each_entry(sr, &wf_sensors, link) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 310) if (!strcmp(sr->name, new_sr->name)) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 311) printk(KERN_WARNING "windfarm: trying to register"
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 312) " duplicate sensor %s\n", sr->name);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 313) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 314) return -EEXIST;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 315) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 316) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 317) kref_init(&new_sr->ref);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 318) list_add(&new_sr->link, &wf_sensors);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 319)
b35c74dab64f4 (Johannes Berg 2010-02-20 16:43:02 +0100 320) sysfs_attr_init(&new_sr->attr.attr);
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 321) new_sr->attr.attr.name = new_sr->name;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 322) new_sr->attr.attr.mode = 0444;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 323) new_sr->attr.show = wf_show_sensor;
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 324) new_sr->attr.store = NULL;
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 325) if (device_create_file(&wf_platform_device.dev, &new_sr->attr))
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 326) printk(KERN_WARNING "windfarm: device_create_file failed"
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 327) " for %s\n", new_sr->name);
ccd308f09a663 (Stephen Rothwell 2007-05-17 11:22:15 +1000 328) /* the subsystem still does useful work without the file */
ac171c46667c1 (Benjamin Herrenschmidt 2006-02-08 16:42:51 +1100 329)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 330) DBG("wf: Registered sensor %s\n", new_sr->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 331)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 332) wf_notify(WF_EVENT_NEW_SENSOR, new_sr);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 333) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 334)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 335) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 336) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 337) EXPORT_SYMBOL_GPL(wf_register_sensor);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 338)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 339) void wf_unregister_sensor(struct wf_sensor *sr)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 340) {
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 341) mutex_lock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 342) list_del(&sr->link);
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 343) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 344)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 345) DBG("wf: Unregistered sensor %s\n", sr->name);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 346)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 347) wf_put_sensor(sr);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 348) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 349) EXPORT_SYMBOL_GPL(wf_unregister_sensor);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 350)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 351) int wf_get_sensor(struct wf_sensor *sr)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 352) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 353) if (!try_module_get(sr->ops->owner))
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 354) return -ENODEV;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 355) kref_get(&sr->ref);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 356) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 357) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 358) EXPORT_SYMBOL_GPL(wf_get_sensor);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 359)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 360) void wf_put_sensor(struct wf_sensor *sr)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 361) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 362) struct module *mod = sr->ops->owner;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 363) kref_put(&sr->ref, wf_sensor_release);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 364) module_put(mod);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 365) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 366) EXPORT_SYMBOL_GPL(wf_put_sensor);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 367)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 368)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 369) /*
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 370) * Client & notification
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 371) */
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 372)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 373) int wf_register_client(struct notifier_block *nb)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 374) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 375) int rc;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 376) struct wf_control *ct;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 377) struct wf_sensor *sr;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 378)
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 379) mutex_lock(&wf_lock);
e041c683412d5 (Alan Stern 2006-03-27 01:16:30 -0800 380) rc = blocking_notifier_chain_register(&wf_client_list, nb);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 381) if (rc != 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 382) goto bail;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 383) wf_client_count++;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 384) list_for_each_entry(ct, &wf_controls, link)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 385) wf_notify(WF_EVENT_NEW_CONTROL, ct);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 386) list_for_each_entry(sr, &wf_sensors, link)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 387) wf_notify(WF_EVENT_NEW_SENSOR, sr);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 388) if (wf_client_count == 1)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 389) wf_start_thread();
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 390) bail:
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 391) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 392) return rc;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 393) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 394) EXPORT_SYMBOL_GPL(wf_register_client);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 395)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 396) int wf_unregister_client(struct notifier_block *nb)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 397) {
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 398) mutex_lock(&wf_lock);
e041c683412d5 (Alan Stern 2006-03-27 01:16:30 -0800 399) blocking_notifier_chain_unregister(&wf_client_list, nb);
fe2b592173ff0 (Paul Bolle 2015-07-31 14:08:58 +0200 400) wf_client_count--;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 401) if (wf_client_count == 0)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 402) wf_stop_thread();
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 403) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 404)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 405) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 406) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 407) EXPORT_SYMBOL_GPL(wf_unregister_client);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 408)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 409) void wf_set_overtemp(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 410) {
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 411) mutex_lock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 412) wf_overtemp++;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 413) if (wf_overtemp == 1) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 414) printk(KERN_WARNING "windfarm: Overtemp condition detected !\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 415) wf_overtemp_counter = 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 416) wf_notify(WF_EVENT_OVERTEMP, NULL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 417) }
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 418) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 419) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 420) EXPORT_SYMBOL_GPL(wf_set_overtemp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 421)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 422) void wf_clear_overtemp(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 423) {
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 424) mutex_lock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 425) WARN_ON(wf_overtemp == 0);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 426) if (wf_overtemp == 0) {
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 427) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 428) return;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 429) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 430) wf_overtemp--;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 431) if (wf_overtemp == 0) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 432) printk(KERN_WARNING "windfarm: Overtemp condition cleared !\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 433) wf_notify(WF_EVENT_NORMALTEMP, NULL);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 434) }
837e9594fc3cb (Ingo Molnar 2006-01-14 16:18:45 +0100 435) mutex_unlock(&wf_lock);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 436) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 437) EXPORT_SYMBOL_GPL(wf_clear_overtemp);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 438)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 439) static int __init windfarm_core_init(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 440) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 441) DBG("wf: core loaded\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 442)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 443) platform_device_register(&wf_platform_device);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 444) return 0;
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 445) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 446)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 447) static void __exit windfarm_core_exit(void)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 448) {
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 449) BUG_ON(wf_client_count != 0);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 450)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 451) DBG("wf: core unloaded\n");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 452)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 453) platform_device_unregister(&wf_platform_device);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 454) }
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 455)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 456)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 457) module_init(windfarm_core_init);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 458) module_exit(windfarm_core_exit);
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 459)
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 460) MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 461) MODULE_DESCRIPTION("Core component of PowerMac thermal control");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 462) MODULE_LICENSE("GPL");
75722d3992f57 (Benjamin Herrenschmidt 2005-11-07 16:08:17 +1100 463)