mt_hotplug_strategy_api.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (c) 2015 MediaTek Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/sched.h>
  18. #include <mt-plat/mt_hotplug_strategy_internal.h>
  19. #include <mt-plat/mt_hotplug_strategy.h>
  20. int hps_set_cpu_num_base(enum hps_base_type_e type, unsigned int little_cpu,
  21. unsigned int big_cpu)
  22. {
  23. unsigned int num_online;
  24. if (hps_ctxt.init_state != INIT_STATE_DONE)
  25. return -1;
  26. if ((type < 0) || (type >= BASE_COUNT))
  27. return -1;
  28. if ((little_cpu > num_possible_little_cpus()) || (little_cpu < 1))
  29. return -1;
  30. if (hps_ctxt.is_hmp && (big_cpu > num_possible_big_cpus()))
  31. return -1;
  32. /* check mutex lock or not? use hps_ctxt.lock! */
  33. mutex_lock(&hps_ctxt.lock);
  34. switch (type) {
  35. case BASE_PERF_SERV:
  36. hps_ctxt.little_num_base_perf_serv = little_cpu;
  37. if (hps_ctxt.is_hmp)
  38. hps_ctxt.big_num_base_perf_serv = big_cpu;
  39. break;
  40. case BASE_WIFI:
  41. hps_ctxt.little_num_base_wifi = little_cpu;
  42. if (hps_ctxt.is_hmp)
  43. hps_ctxt.big_num_base_wifi = big_cpu;
  44. break;
  45. default:
  46. break;
  47. }
  48. if (hps_ctxt.is_hmp) {
  49. num_online = num_online_big_cpus();
  50. if ((num_online < big_cpu) &&
  51. (num_online < min(hps_ctxt.big_num_limit_thermal,
  52. hps_ctxt.big_num_limit_low_battery)) &&
  53. (num_online <
  54. min(hps_ctxt.big_num_limit_ultra_power_saving,
  55. hps_ctxt.big_num_limit_power_serv))) {
  56. hps_task_wakeup_nolock();
  57. } else {
  58. num_online = num_online_little_cpus();
  59. if ((num_online < little_cpu) &&
  60. (num_online <
  61. min(hps_ctxt.little_num_limit_thermal,
  62. hps_ctxt.little_num_limit_low_battery)) &&
  63. (num_online <
  64. min(
  65. hps_ctxt.little_num_limit_ultra_power_saving,
  66. hps_ctxt.little_num_limit_power_serv)) &&
  67. (num_online_cpus() < (little_cpu + big_cpu)))
  68. hps_task_wakeup_nolock();
  69. }
  70. } else {
  71. num_online = num_online_little_cpus();
  72. if ((num_online < little_cpu) &&
  73. (num_online <
  74. min(hps_ctxt.little_num_limit_thermal,
  75. hps_ctxt.little_num_limit_low_battery)) &&
  76. (num_online <
  77. min(hps_ctxt.little_num_limit_ultra_power_saving,
  78. hps_ctxt.little_num_limit_power_serv)))
  79. hps_task_wakeup_nolock();
  80. }
  81. mutex_unlock(&hps_ctxt.lock);
  82. return 0;
  83. }
  84. int hps_get_cpu_num_base(enum hps_base_type_e type,
  85. unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr)
  86. {
  87. if (hps_ctxt.init_state != INIT_STATE_DONE)
  88. return -1;
  89. if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL))
  90. return -1;
  91. if ((type < 0) || (type >= BASE_COUNT))
  92. return -1;
  93. switch (type) {
  94. case BASE_PERF_SERV:
  95. *little_cpu_ptr = hps_ctxt.little_num_base_perf_serv;
  96. *big_cpu_ptr = hps_ctxt.big_num_base_perf_serv;
  97. break;
  98. case BASE_WIFI:
  99. *little_cpu_ptr = hps_ctxt.little_num_base_wifi;
  100. *big_cpu_ptr = hps_ctxt.big_num_base_wifi;
  101. break;
  102. default:
  103. break;
  104. }
  105. return 0;
  106. }
  107. /*
  108. * hps cpu num limit
  109. */
  110. int hps_set_cpu_num_limit(enum hps_limit_type_e type,
  111. unsigned int little_cpu, unsigned int big_cpu)
  112. {
  113. if (hps_ctxt.init_state != INIT_STATE_DONE)
  114. return -1;
  115. if ((type < 0) || (type >= LIMIT_COUNT))
  116. return -1;
  117. if ((little_cpu > num_possible_little_cpus()) || (little_cpu < 1))
  118. return -1;
  119. if (hps_ctxt.is_hmp && (big_cpu > num_possible_big_cpus()))
  120. return -1;
  121. mutex_lock(&hps_ctxt.lock);
  122. switch (type) {
  123. case LIMIT_THERMAL:
  124. hps_ctxt.little_num_limit_thermal = little_cpu;
  125. if (hps_ctxt.is_hmp)
  126. hps_ctxt.big_num_limit_thermal = big_cpu;
  127. break;
  128. case LIMIT_LOW_BATTERY:
  129. hps_ctxt.little_num_limit_low_battery = little_cpu;
  130. if (hps_ctxt.is_hmp)
  131. hps_ctxt.big_num_limit_low_battery = big_cpu;
  132. break;
  133. case LIMIT_ULTRA_POWER_SAVING:
  134. hps_ctxt.little_num_limit_ultra_power_saving = little_cpu;
  135. if (hps_ctxt.is_hmp)
  136. hps_ctxt.big_num_limit_ultra_power_saving = big_cpu;
  137. break;
  138. case LIMIT_POWER_SERV:
  139. hps_ctxt.little_num_limit_power_serv = little_cpu;
  140. if (hps_ctxt.is_hmp)
  141. hps_ctxt.big_num_limit_power_serv = big_cpu;
  142. break;
  143. default:
  144. break;
  145. }
  146. if (hps_ctxt.is_hmp) {
  147. if (num_online_big_cpus() > big_cpu)
  148. hps_task_wakeup_nolock();
  149. else if (num_online_little_cpus() > little_cpu)
  150. hps_task_wakeup_nolock();
  151. } else {
  152. if (num_online_little_cpus() > little_cpu)
  153. hps_task_wakeup_nolock();
  154. }
  155. mutex_unlock(&hps_ctxt.lock);
  156. return 0;
  157. }
  158. int hps_get_cpu_num_limit(enum hps_limit_type_e type,
  159. unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr)
  160. {
  161. if (hps_ctxt.init_state != INIT_STATE_DONE)
  162. return -1;
  163. if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL))
  164. return -1;
  165. if ((type < 0) || (type >= LIMIT_COUNT))
  166. return -1;
  167. switch (type) {
  168. case LIMIT_THERMAL:
  169. *little_cpu_ptr = hps_ctxt.little_num_limit_thermal;
  170. *big_cpu_ptr = hps_ctxt.big_num_limit_thermal;
  171. break;
  172. case LIMIT_LOW_BATTERY:
  173. *little_cpu_ptr = hps_ctxt.little_num_limit_low_battery;
  174. *big_cpu_ptr = hps_ctxt.big_num_limit_low_battery;
  175. break;
  176. case LIMIT_ULTRA_POWER_SAVING:
  177. *little_cpu_ptr = hps_ctxt.little_num_limit_ultra_power_saving;
  178. *big_cpu_ptr = hps_ctxt.big_num_limit_ultra_power_saving;
  179. break;
  180. case LIMIT_POWER_SERV:
  181. *little_cpu_ptr = hps_ctxt.little_num_limit_power_serv;
  182. *big_cpu_ptr = hps_ctxt.big_num_limit_power_serv;
  183. break;
  184. default:
  185. break;
  186. }
  187. return 0;
  188. }
  189. /*
  190. * hps tlp
  191. */
  192. int hps_get_tlp(unsigned int *tlp_ptr)
  193. {
  194. if (hps_ctxt.init_state != INIT_STATE_DONE)
  195. return -1;
  196. if (tlp_ptr == NULL)
  197. return -1;
  198. *tlp_ptr = hps_ctxt.tlp_avg;
  199. return 0;
  200. }
  201. /*
  202. * hps num_possible_cpus
  203. */
  204. int hps_get_num_possible_cpus(
  205. unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr)
  206. {
  207. if (hps_ctxt.init_state != INIT_STATE_DONE)
  208. return -1;
  209. if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL))
  210. return -1;
  211. *little_cpu_ptr = num_possible_little_cpus();
  212. *big_cpu_ptr = num_possible_big_cpus();
  213. return 0;
  214. }
  215. /*
  216. * hps num_online_cpus
  217. */
  218. int hps_get_num_online_cpus(
  219. unsigned int *little_cpu_ptr, unsigned int *big_cpu_ptr)
  220. {
  221. if (hps_ctxt.init_state != INIT_STATE_DONE)
  222. return -1;
  223. if ((little_cpu_ptr == NULL) || (big_cpu_ptr == NULL))
  224. return -1;
  225. *little_cpu_ptr = num_online_little_cpus();
  226. *big_cpu_ptr = num_online_big_cpus();
  227. return 0;
  228. }
  229. /*
  230. * hps cpu num base
  231. */
  232. int hps_get_enabled(unsigned int *enabled_ptr)
  233. {
  234. if (hps_ctxt.init_state != INIT_STATE_DONE)
  235. return -1;
  236. if (enabled_ptr == NULL)
  237. return -1;
  238. *enabled_ptr = hps_ctxt.enabled;
  239. return 0;
  240. }
  241. int hps_set_enabled(unsigned int enabled)
  242. {
  243. if (hps_ctxt.init_state != INIT_STATE_DONE)
  244. return -1;
  245. if (enabled > 1)
  246. return -1;
  247. /* check mutex lock or not? use hps_ctxt.lock! */
  248. mutex_lock(&hps_ctxt.lock);
  249. if (!hps_ctxt.enabled && enabled)
  250. hps_ctxt_reset_stas_nolock();
  251. hps_ctxt.enabled = enabled;
  252. mutex_unlock(&hps_ctxt.lock);
  253. return 0;
  254. }