cpufreq_userspace.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/smp.h>
  16. #include <linux/init.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/cpufreq.h>
  20. #include <linux/cpu.h>
  21. #include <linux/types.h>
  22. #include <linux/fs.h>
  23. #include <linux/sysfs.h>
  24. #include <linux/mutex.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. /* keep track of frequency transitions */
  37. static int
  38. userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
  39. void *data)
  40. {
  41. struct cpufreq_freqs *freq = data;
  42. if (!per_cpu(cpu_is_managed, freq->cpu))
  43. return 0;
  44. if (val == CPUFREQ_POSTCHANGE) {
  45. pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
  46. freq->cpu, freq->new);
  47. per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
  48. }
  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. pr_debug("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) ->
  78. * cpufreq_driver_target(lock policy->lock)
  79. * B: cpufreq_set_policy(lock policy->lock) ->
  80. * __cpufreq_governor ->
  81. * cpufreq_governor_userspace (lock userspace_mutex)
  82. */
  83. ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
  84. err:
  85. mutex_unlock(&userspace_mutex);
  86. return ret;
  87. }
  88. static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
  89. {
  90. return sprintf(buf, "%u\n", per_cpu(cpu_cur_freq, policy->cpu));
  91. }
  92. static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
  93. unsigned int event)
  94. {
  95. unsigned int cpu = policy->cpu;
  96. int rc = 0;
  97. switch (event) {
  98. case CPUFREQ_GOV_START:
  99. if (!cpu_online(cpu))
  100. return -EINVAL;
  101. BUG_ON(!policy->cur);
  102. mutex_lock(&userspace_mutex);
  103. if (cpus_using_userspace_governor == 0) {
  104. cpufreq_register_notifier(
  105. &userspace_cpufreq_notifier_block,
  106. CPUFREQ_TRANSITION_NOTIFIER);
  107. }
  108. cpus_using_userspace_governor++;
  109. per_cpu(cpu_is_managed, cpu) = 1;
  110. per_cpu(cpu_min_freq, cpu) = policy->min;
  111. per_cpu(cpu_max_freq, cpu) = policy->max;
  112. per_cpu(cpu_cur_freq, cpu) = policy->cur;
  113. per_cpu(cpu_set_freq, cpu) = policy->cur;
  114. pr_debug("managing cpu %u started "
  115. "(%u - %u kHz, currently %u kHz)\n",
  116. cpu,
  117. per_cpu(cpu_min_freq, cpu),
  118. per_cpu(cpu_max_freq, cpu),
  119. per_cpu(cpu_cur_freq, cpu));
  120. mutex_unlock(&userspace_mutex);
  121. break;
  122. case CPUFREQ_GOV_STOP:
  123. mutex_lock(&userspace_mutex);
  124. cpus_using_userspace_governor--;
  125. if (cpus_using_userspace_governor == 0) {
  126. cpufreq_unregister_notifier(
  127. &userspace_cpufreq_notifier_block,
  128. CPUFREQ_TRANSITION_NOTIFIER);
  129. }
  130. per_cpu(cpu_is_managed, cpu) = 0;
  131. per_cpu(cpu_min_freq, cpu) = 0;
  132. per_cpu(cpu_max_freq, cpu) = 0;
  133. per_cpu(cpu_set_freq, cpu) = 0;
  134. pr_debug("managing cpu %u stopped\n", cpu);
  135. mutex_unlock(&userspace_mutex);
  136. break;
  137. case CPUFREQ_GOV_LIMITS:
  138. mutex_lock(&userspace_mutex);
  139. pr_debug("limit event for cpu %u: %u - %u kHz, "
  140. "currently %u kHz, last set to %u kHz\n",
  141. cpu, policy->min, policy->max,
  142. per_cpu(cpu_cur_freq, cpu),
  143. per_cpu(cpu_set_freq, cpu));
  144. if (policy->max < per_cpu(cpu_set_freq, cpu)) {
  145. __cpufreq_driver_target(policy, policy->max,
  146. CPUFREQ_RELATION_H);
  147. } else if (policy->min > per_cpu(cpu_set_freq, cpu)) {
  148. __cpufreq_driver_target(policy, policy->min,
  149. CPUFREQ_RELATION_L);
  150. } else {
  151. __cpufreq_driver_target(policy,
  152. per_cpu(cpu_set_freq, cpu),
  153. CPUFREQ_RELATION_L);
  154. }
  155. per_cpu(cpu_min_freq, cpu) = policy->min;
  156. per_cpu(cpu_max_freq, cpu) = policy->max;
  157. per_cpu(cpu_cur_freq, cpu) = policy->cur;
  158. mutex_unlock(&userspace_mutex);
  159. break;
  160. }
  161. return rc;
  162. }
  163. #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
  164. static
  165. #endif
  166. struct cpufreq_governor cpufreq_gov_userspace = {
  167. .name = "userspace",
  168. .governor = cpufreq_governor_userspace,
  169. .store_setspeed = cpufreq_set,
  170. .show_setspeed = show_speed,
  171. .owner = THIS_MODULE,
  172. };
  173. static int __init cpufreq_gov_userspace_init(void)
  174. {
  175. return cpufreq_register_governor(&cpufreq_gov_userspace);
  176. }
  177. static void __exit cpufreq_gov_userspace_exit(void)
  178. {
  179. cpufreq_unregister_governor(&cpufreq_gov_userspace);
  180. }
  181. MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "
  182. "Russell King <rmk@arm.linux.org.uk>");
  183. MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
  184. MODULE_LICENSE("GPL");
  185. #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
  186. fs_initcall(cpufreq_gov_userspace_init);
  187. #else
  188. module_init(cpufreq_gov_userspace_init);
  189. #endif
  190. module_exit(cpufreq_gov_userspace_exit);