cpufreq_userspace.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * linux/drivers/cpufreq/cpufreq_userspace.c
  3. *
  4. * Copyright (C) 2001 Russell King
  5. * (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/smp.h>
  15. #include <linux/init.h>
  16. #include <linux/spinlock.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/cpufreq.h>
  19. #include <linux/cpu.h>
  20. #include <linux/types.h>
  21. #include <linux/fs.h>
  22. #include <linux/sysfs.h>
  23. #include <linux/mutex.h>
  24. #include <asm/uaccess.h>
  25. /**
  26. * A few values needed by the userspace governor
  27. */
  28. static DEFINE_PER_CPU(unsigned int, cpu_max_freq);
  29. static DEFINE_PER_CPU(unsigned int, cpu_min_freq);
  30. static DEFINE_PER_CPU(unsigned int, cpu_cur_freq); /* current CPU freq */
  31. static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by
  32. userspace */
  33. static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
  34. static DEFINE_MUTEX (userspace_mutex);
  35. static int cpus_using_userspace_governor;
  36. #define dprintk(msg...) \
  37. cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
  38. /* keep track of frequency transitions */
  39. static int
  40. userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
  41. void *data)
  42. {
  43. struct cpufreq_freqs *freq = data;
  44. if (!per_cpu(cpu_is_managed, freq->cpu))
  45. return 0;
  46. dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
  47. freq->cpu, freq->new);
  48. per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
  49. return 0;
  50. }
  51. static struct notifier_block userspace_cpufreq_notifier_block = {
  52. .notifier_call = userspace_cpufreq_notifier
  53. };
  54. /**
  55. * cpufreq_set - set the CPU frequency
  56. * @policy: pointer to policy struct where freq is being set
  57. * @freq: target frequency in kHz
  58. *
  59. * Sets the CPU frequency to freq.
  60. */
  61. static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
  62. {
  63. int ret = -EINVAL;
  64. dprintk("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
  65. mutex_lock(&userspace_mutex);
  66. if (!per_cpu(cpu_is_managed, policy->cpu))
  67. goto err;
  68. per_cpu(cpu_set_freq, policy->cpu) = freq;
  69. if (freq < per_cpu(cpu_min_freq, policy->cpu))
  70. freq = per_cpu(cpu_min_freq, policy->cpu);
  71. if (freq > per_cpu(cpu_max_freq, policy->cpu))
  72. freq = per_cpu(cpu_max_freq, policy->cpu);
  73. /*
  74. * We're safe from concurrent calls to ->target() here
  75. * as we hold the userspace_mutex lock. If we were calling
  76. * cpufreq_driver_target, a deadlock situation might occur:
  77. * A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock)
  78. * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex)
  79. */
  80. ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
  81. err:
  82. mutex_unlock(&userspace_mutex);
  83. return ret;
  84. }
  85. static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
  86. {
  87. return sprintf(buf, "%u\n", per_cpu(cpu_cur_freq, policy->cpu));
  88. }
  89. static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
  90. unsigned int event)
  91. {
  92. unsigned int cpu = policy->cpu;
  93. int rc = 0;
  94. switch (event) {
  95. case CPUFREQ_GOV_START:
  96. if (!cpu_online(cpu))
  97. return -EINVAL;
  98. BUG_ON(!policy->cur);
  99. mutex_lock(&userspace_mutex);
  100. if (cpus_using_userspace_governor == 0) {
  101. cpufreq_register_notifier(
  102. &userspace_cpufreq_notifier_block,
  103. CPUFREQ_TRANSITION_NOTIFIER);
  104. }
  105. cpus_using_userspace_governor++;
  106. per_cpu(cpu_is_managed, cpu) = 1;
  107. per_cpu(cpu_min_freq, cpu) = policy->min;
  108. per_cpu(cpu_max_freq, cpu) = policy->max;
  109. per_cpu(cpu_cur_freq, cpu) = policy->cur;
  110. per_cpu(cpu_set_freq, cpu) = policy->cur;
  111. dprintk("managing cpu %u started "
  112. "(%u - %u kHz, currently %u kHz)\n",
  113. cpu,
  114. per_cpu(cpu_min_freq, cpu),
  115. per_cpu(cpu_max_freq, cpu),
  116. per_cpu(cpu_cur_freq, cpu));
  117. mutex_unlock(&userspace_mutex);
  118. break;
  119. case CPUFREQ_GOV_STOP:
  120. mutex_lock(&userspace_mutex);
  121. cpus_using_userspace_governor--;
  122. if (cpus_using_userspace_governor == 0) {
  123. cpufreq_unregister_notifier(
  124. &userspace_cpufreq_notifier_block,
  125. CPUFREQ_TRANSITION_NOTIFIER);
  126. }
  127. per_cpu(cpu_is_managed, cpu) = 0;
  128. per_cpu(cpu_min_freq, cpu) = 0;
  129. per_cpu(cpu_max_freq, cpu) = 0;
  130. per_cpu(cpu_set_freq, cpu) = 0;
  131. dprintk("managing cpu %u stopped\n", cpu);
  132. mutex_unlock(&userspace_mutex);
  133. break;
  134. case CPUFREQ_GOV_LIMITS:
  135. mutex_lock(&userspace_mutex);
  136. dprintk("limit event for cpu %u: %u - %u kHz, "
  137. "currently %u kHz, last set to %u kHz\n",
  138. cpu, policy->min, policy->max,
  139. per_cpu(cpu_cur_freq, cpu),
  140. per_cpu(cpu_set_freq, cpu));
  141. if (policy->max < per_cpu(cpu_set_freq, cpu)) {
  142. __cpufreq_driver_target(policy, policy->max,
  143. CPUFREQ_RELATION_H);
  144. } else if (policy->min > per_cpu(cpu_set_freq, cpu)) {
  145. __cpufreq_driver_target(policy, policy->min,
  146. CPUFREQ_RELATION_L);
  147. } else {
  148. __cpufreq_driver_target(policy,
  149. per_cpu(cpu_set_freq, cpu),
  150. CPUFREQ_RELATION_L);
  151. }
  152. per_cpu(cpu_min_freq, cpu) = policy->min;
  153. per_cpu(cpu_max_freq, cpu) = policy->max;
  154. per_cpu(cpu_cur_freq, cpu) = policy->cur;
  155. mutex_unlock(&userspace_mutex);
  156. break;
  157. }
  158. return rc;
  159. }
  160. #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
  161. static
  162. #endif
  163. struct cpufreq_governor cpufreq_gov_userspace = {
  164. .name = "userspace",
  165. .governor = cpufreq_governor_userspace,
  166. .store_setspeed = cpufreq_set,
  167. .show_setspeed = show_speed,
  168. .owner = THIS_MODULE,
  169. };
  170. static int __init cpufreq_gov_userspace_init(void)
  171. {
  172. return cpufreq_register_governor(&cpufreq_gov_userspace);
  173. }
  174. static void __exit cpufreq_gov_userspace_exit(void)
  175. {
  176. cpufreq_unregister_governor(&cpufreq_gov_userspace);
  177. }
  178. MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux.org.uk>");
  179. MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'");
  180. MODULE_LICENSE ("GPL");
  181. #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
  182. fs_initcall(cpufreq_gov_userspace_init);
  183. #else
  184. module_init(cpufreq_gov_userspace_init);
  185. #endif
  186. module_exit(cpufreq_gov_userspace_exit);