VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
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)