cpufreq_userspace.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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. /**
  25. * A few values needed by the userspace governor
  26. */
  27. static DEFINE_PER_CPU(unsigned int, cpu_max_freq);
  28. static DEFINE_PER_CPU(unsigned int, cpu_min_freq);
  29. static DEFINE_PER_CPU(unsigned int, cpu_cur_freq); /* current CPU freq */
  30. static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by
  31. userspace */
  32. static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
  33. static DEFINE_MUTEX(userspace_mutex);
  34. static int cpus_using_userspace_governor;
  35. /* keep track of frequency transitions */
  36. static int
  37. userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
  38. void *data)
  39. {
  40. struct cpufreq_freqs *freq = data;
  41. if (!per_cpu(cpu_is_managed, freq->cpu))
  42. return 0;
  43. pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
  44. freq->cpu, freq->new);
  45. per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
  46. return 0;
  47. }
  48. static struct notifier_block userspace_cpufreq_notifier_block = {
  49. .notifier_call = userspace_cpufreq_notifier
  50. };
  51. /**
  52. * cpufreq_set - set the CPU frequency
  53. * @policy: pointer to policy struct where freq is being set
  54. * @freq: target frequency in kHz
  55. *
  56. * Sets the CPU frequency to freq.
  57. */
  58. static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
  59. {
  60. int ret = -EINVAL;
  61. pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
  62. mutex_lock(&userspace_mutex);
  63. if (!per_cpu(cpu_is_managed, policy->cpu))
  64. goto err;
  65. per_cpu(cpu_set_freq, policy->cpu) = freq;
  66. if (freq < per_cpu(cpu_min_freq, policy->cpu))
  67. freq = per_cpu(cpu_min_freq, policy->cpu);
  68. if (freq > per_cpu(cpu_max_freq, policy->cpu))
  69. freq = per_cpu(cpu_max_freq, policy->cpu);
  70. /*
  71. * We're safe from concurrent calls to ->target() here
  72. * as we hold the userspace_mutex lock. If we were calling
  73. * cpufreq_driver_target, a deadlock situation might occur:
  74. * A: cpufreq_set (lock userspace_mutex) ->
  75. * cpufreq_driver_target(lock policy->lock)
  76. * B: cpufreq_set_policy(lock policy->lock) ->
  77. * __cpufreq_governor ->
  78. * 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. pr_debug("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. pr_debug("managing cpu %u stopped\n", cpu);
  132. mutex_unlock(&userspace_mutex);
  133. break;
  134. case CPUFREQ_GOV_LIMITS:
  135. mutex_lock(&userspace_mutex);
  136. pr_debug("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>, "
  179. "Russell King <rmk@arm.linux.org.uk>");
  180. MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
  181. MODULE_LICENSE("GPL");
  182. #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
  183. fs_initcall(cpufreq_gov_userspace_init);
  184. #else
  185. module_init(cpufreq_gov_userspace_init);
  186. #endif
  187. module_exit(cpufreq_gov_userspace_exit);