1 #include <linux/config.h> 2 #include <linux/types.h> 3 #include <linux/errno.h> 4 #include <linux/kernel.h> 5 #include <linux/delay.h> 6 #include <linux/slab.h> 7 #include <linux/init.h> 8 #include <linux/wait.h> 9 #include <linux/cpufreq.h> 10 11 #include "windfarm.h" 12 13 #define VERSION "0.3" 14 15 static int clamped; 16 static struct wf_control *clamp_control; 17 18 static int clamp_notifier_call(struct notifier_block *self, 19 unsigned long event, void *data) 20 { 21 struct cpufreq_policy *p = data; 22 unsigned long max_freq; 23 24 if (event != CPUFREQ_ADJUST) 25 return 0; 26 27 max_freq = clamped ? (p->cpuinfo.min_freq) : (p->cpuinfo.max_freq); 28 cpufreq_verify_within_limits(p, 0, max_freq); 29 30 return 0; 31 } 32 33 static struct notifier_block clamp_notifier = { 34 .notifier_call = clamp_notifier_call, 35 }; 36 37 static int clamp_set(struct wf_control *ct, s32 value) 38 { 39 if (value) 40 printk(KERN_INFO "windfarm: Clamping CPU frequency to " 41 "minimum !\n"); 42 else 43 printk(KERN_INFO "windfarm: CPU frequency unclamped !\n"); 44 clamped = value; 45 cpufreq_update_policy(0); 46 return 0; 47 } 48 49 static int clamp_get(struct wf_control *ct, s32 *value) 50 { 51 *value = clamped; 52 return 0; 53 } 54 55 static s32 clamp_min(struct wf_control *ct) 56 { 57 return 0; 58 } 59 60 static s32 clamp_max(struct wf_control *ct) 61 { 62 return 1; 63 } 64 65 static struct wf_control_ops clamp_ops = { 66 .set_value = clamp_set, 67 .get_value = clamp_get, 68 .get_min = clamp_min, 69 .get_max = clamp_max, 70 .owner = THIS_MODULE, 71 }; 72 73 static int __init wf_cpufreq_clamp_init(void) 74 { 75 struct wf_control *clamp; 76 77 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); 78 if (clamp == NULL) 79 return -ENOMEM; 80 cpufreq_register_notifier(&clamp_notifier, CPUFREQ_POLICY_NOTIFIER); 81 clamp->ops = &clamp_ops; 82 clamp->name = "cpufreq-clamp"; 83 if (wf_register_control(clamp)) 84 goto fail; 85 clamp_control = clamp; 86 return 0; 87 fail: 88 kfree(clamp); 89 return -ENODEV; 90 } 91 92 static void __exit wf_cpufreq_clamp_exit(void) 93 { 94 if (clamp_control) 95 wf_unregister_control(clamp_control); 96 } 97 98 99 module_init(wf_cpufreq_clamp_init); 100 module_exit(wf_cpufreq_clamp_exit); 101 102 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); 103 MODULE_DESCRIPTION("CPU frequency clamp for PowerMacs thermal control"); 104 MODULE_LICENSE("GPL"); 105 106