mt_hotplug_strategy_procfs.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  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/proc_fs.h>
  18. #include <linux/seq_file.h>
  19. #include <linux/uaccess.h>
  20. #include "mt_hotplug_strategy_internal.h"
  21. typedef void (*func_void)(void);
  22. static int hps_proc_uint_show(struct seq_file *m, void *v)
  23. {
  24. unsigned int *pv = (unsigned int *)m->private;
  25. seq_printf(m, "%u\n", *pv);
  26. return 0;
  27. }
  28. static ssize_t hps_proc_uint_write(
  29. struct file *file, const char __user *buffer,
  30. size_t count, loff_t *pos,
  31. func_void before_write, func_void after_write)
  32. {
  33. int len = 0;
  34. char desc[32];
  35. unsigned int var;
  36. unsigned int *pv;
  37. pv = (unsigned int *)((struct seq_file *)file->private_data)->private;
  38. len = min(count, sizeof(desc) - 1);
  39. if (copy_from_user(desc, buffer, len))
  40. return 0;
  41. desc[len] = '\0';
  42. if (!kstrtouint(desc, 0, &var)) {
  43. if (before_write)
  44. before_write();
  45. *pv = var;
  46. if (after_write)
  47. after_write();
  48. return count;
  49. }
  50. hps_warn("%s(): bad argument\n", __func__);
  51. return -EINVAL;
  52. }
  53. static void lock_hps_ctxt(void)
  54. {
  55. mutex_lock(&hps_ctxt.lock);
  56. }
  57. static void unlock_hps_ctxt(void)
  58. {
  59. mutex_unlock(&hps_ctxt.lock);
  60. }
  61. static void reset_unlock_hps_ctxt(void)
  62. {
  63. hps_ctxt_reset_stas_nolock();
  64. mutex_unlock(&hps_ctxt.lock);
  65. }
  66. static ssize_t hps_proc_uint_write_with_lock(
  67. struct file *file, const char __user *buffer,
  68. size_t count, loff_t *pos)
  69. {
  70. return hps_proc_uint_write(file, buffer, count, pos,
  71. lock_hps_ctxt, unlock_hps_ctxt);
  72. }
  73. static ssize_t hps_proc_uint_write_with_lock_reset(
  74. struct file *file, const char __user *buffer,
  75. size_t count, loff_t *pos)
  76. {
  77. return hps_proc_uint_write(file, buffer, count, pos,
  78. lock_hps_ctxt, reset_unlock_hps_ctxt);
  79. }
  80. #define RPOC_FOPS_OPEN_WRITE(_name, _open, _write) \
  81. static const struct file_operations _name = { \
  82. .owner = THIS_MODULE, \
  83. .open = _open, \
  84. .read = seq_read, \
  85. .llseek = seq_lseek, \
  86. .release = single_release, \
  87. .write = _write, \
  88. }
  89. #define PROC_FOPS_RW_UINT(name, var, _write) \
  90. static int hps_##name##_proc_open( \
  91. struct inode *inode, struct file *file) \
  92. { \
  93. return single_open(file, hps_proc_uint_show, &(var)); \
  94. } \
  95. RPOC_FOPS_OPEN_WRITE( \
  96. hps_##name##_proc_fops, hps_##name##_proc_open, _write)
  97. #define PROC_FOPS_RO_UINT(name, var) PROC_FOPS_RW_UINT(name, var, NULL)
  98. #define PROC_FOPS_RW(name) \
  99. static int hps_##name##_proc_open( \
  100. struct inode *inode, struct file *file) \
  101. { \
  102. return single_open(file, hps_##name##_proc_show, \
  103. PDE_DATA(inode)); \
  104. } \
  105. RPOC_FOPS_OPEN_WRITE( \
  106. hps_##name##_proc_fops, \
  107. hps_##name##_proc_open, \
  108. hps_##name##_proc_write)
  109. #define PROC_ENTRY(name) {__stringify(name), &hps_##name##_proc_fops}
  110. /***********************************************************
  111. * procfs callback - state series
  112. * - init_state
  113. * - state
  114. ***********************************************************/
  115. PROC_FOPS_RO_UINT(init_state, hps_ctxt.init_state);
  116. PROC_FOPS_RO_UINT(state, hps_ctxt.state);
  117. /***********************************************************
  118. * procfs callback - enabled series
  119. * - enabled
  120. * - suspend_enabled
  121. * - cur_dump_enabled
  122. * - stats_dump_enabled
  123. ***********************************************************/
  124. PROC_FOPS_RW_UINT(
  125. enabled,
  126. hps_ctxt.enabled,
  127. hps_proc_uint_write_with_lock_reset);
  128. PROC_FOPS_RW_UINT(
  129. suspend_enabled,
  130. hps_ctxt.suspend_enabled,
  131. hps_proc_uint_write_with_lock);
  132. PROC_FOPS_RW_UINT(
  133. cur_dump_enabled,
  134. hps_ctxt.cur_dump_enabled,
  135. hps_proc_uint_write_with_lock);
  136. PROC_FOPS_RW_UINT(
  137. stats_dump_enabled,
  138. hps_ctxt.stats_dump_enabled,
  139. hps_proc_uint_write_with_lock);
  140. /***********************************************************
  141. * procfs callback - algo config series
  142. * - up_threshold
  143. * - up_times
  144. * - down_threshold
  145. * - down_times
  146. * - input_boost_enabled
  147. * - input_boost_cpu_num
  148. * - rush_boost_enabled
  149. * - rush_boost_threshold
  150. * - rush_boost_times
  151. * - tlp_times
  152. ***********************************************************/
  153. PROC_FOPS_RW_UINT(
  154. up_threshold,
  155. hps_ctxt.up_threshold,
  156. hps_proc_uint_write_with_lock_reset);
  157. PROC_FOPS_RW_UINT(
  158. up_times,
  159. hps_ctxt.up_times,
  160. hps_proc_uint_write_with_lock_reset);
  161. PROC_FOPS_RW_UINT(
  162. down_threshold,
  163. hps_ctxt.down_threshold,
  164. hps_proc_uint_write_with_lock_reset);
  165. PROC_FOPS_RW_UINT(
  166. down_times,
  167. hps_ctxt.down_times,
  168. hps_proc_uint_write_with_lock_reset);
  169. PROC_FOPS_RW_UINT(
  170. input_boost_enabled,
  171. hps_ctxt.input_boost_enabled,
  172. hps_proc_uint_write_with_lock);
  173. PROC_FOPS_RW_UINT(
  174. input_boost_cpu_num,
  175. hps_ctxt.input_boost_cpu_num,
  176. hps_proc_uint_write_with_lock);
  177. PROC_FOPS_RW_UINT(
  178. rush_boost_enabled,
  179. hps_ctxt.rush_boost_enabled,
  180. hps_proc_uint_write_with_lock);
  181. PROC_FOPS_RW_UINT(
  182. rush_boost_threshold,
  183. hps_ctxt.rush_boost_threshold,
  184. hps_proc_uint_write_with_lock_reset);
  185. PROC_FOPS_RW_UINT(
  186. rush_boost_times,
  187. hps_ctxt.rush_boost_times,
  188. hps_proc_uint_write_with_lock_reset);
  189. PROC_FOPS_RW_UINT(
  190. tlp_times,
  191. hps_ctxt.tlp_times,
  192. hps_proc_uint_write_with_lock_reset);
  193. /***********************************************************
  194. * procfs callback - algo bound series
  195. * - little_num_base_perf_serv
  196. * - big_num_base_perf_serv
  197. ***********************************************************/
  198. static int hps_num_base_perf_serv_proc_show(struct seq_file *m, void *v)
  199. {
  200. if (hps_ctxt.is_hmp)
  201. seq_printf(m, "%u %u\n", hps_ctxt.little_num_base_perf_serv,
  202. hps_ctxt.big_num_base_perf_serv);
  203. else
  204. seq_printf(m, "%u\n", hps_ctxt.little_num_base_perf_serv);
  205. return 0;
  206. }
  207. static ssize_t hps_num_base_perf_serv_proc_write(
  208. struct file *file,
  209. const char __user *buffer,
  210. size_t count,
  211. loff_t *pos)
  212. {
  213. int len = 0, little_num_base_perf_serv = 0, big_num_base_perf_serv = 0;
  214. char desc[32];
  215. unsigned int num_online;
  216. len = min(count, sizeof(desc) - 1);
  217. if (copy_from_user(desc, buffer, len))
  218. return 0;
  219. desc[len] = '\0';
  220. if (hps_ctxt.is_hmp &&
  221. (sscanf(desc, "%u %u",
  222. &little_num_base_perf_serv,
  223. &big_num_base_perf_serv) == 2)) {
  224. if (little_num_base_perf_serv > num_possible_little_cpus()
  225. || little_num_base_perf_serv < 1) {
  226. hps_warn(
  227. "hps_num_base_perf_serv_proc_write, bad argument(%u, %u)\n",
  228. little_num_base_perf_serv,
  229. big_num_base_perf_serv);
  230. return -EINVAL;
  231. }
  232. if (big_num_base_perf_serv > num_possible_big_cpus()) {
  233. hps_warn(
  234. "hps_num_base_perf_serv_proc_write, bad argument(%u, %u)\n",
  235. little_num_base_perf_serv,
  236. big_num_base_perf_serv);
  237. return -EINVAL;
  238. }
  239. mutex_lock(&hps_ctxt.lock);
  240. hps_ctxt.little_num_base_perf_serv = little_num_base_perf_serv;
  241. hps_ctxt.big_num_base_perf_serv = big_num_base_perf_serv;
  242. num_online = num_online_big_cpus();
  243. if ((num_online < big_num_base_perf_serv) &&
  244. (num_online <
  245. min(hps_ctxt.big_num_limit_thermal,
  246. hps_ctxt.big_num_limit_low_battery)) &&
  247. (num_online <
  248. min(hps_ctxt.big_num_limit_ultra_power_saving,
  249. hps_ctxt.big_num_limit_power_serv)))
  250. hps_task_wakeup_nolock();
  251. else {
  252. num_online = num_online_little_cpus();
  253. if ((num_online < little_num_base_perf_serv) &&
  254. (num_online <
  255. min(
  256. hps_ctxt.little_num_limit_thermal,
  257. hps_ctxt.little_num_limit_low_battery)) &&
  258. (num_online <
  259. min(
  260. hps_ctxt.little_num_limit_ultra_power_saving,
  261. hps_ctxt.little_num_limit_power_serv)) &&
  262. (num_online_cpus() <
  263. (little_num_base_perf_serv +
  264. big_num_base_perf_serv)))
  265. hps_task_wakeup_nolock();
  266. }
  267. /* XXX: should we move mutex_unlock(&hps_ctxt.lock) to
  268. earlier stage? no! */
  269. mutex_unlock(&hps_ctxt.lock);
  270. return count;
  271. } else if (!hps_ctxt.is_hmp &&
  272. !kstrtouint(desc, 0, &little_num_base_perf_serv)) {
  273. if (little_num_base_perf_serv > num_possible_little_cpus()
  274. || little_num_base_perf_serv < 1) {
  275. hps_warn(
  276. "hps_num_base_perf_serv_proc_write, bad argument(%u)\n",
  277. little_num_base_perf_serv);
  278. return -EINVAL;
  279. }
  280. mutex_lock(&hps_ctxt.lock);
  281. hps_ctxt.little_num_base_perf_serv = little_num_base_perf_serv;
  282. num_online = num_online_little_cpus();
  283. if ((num_online < little_num_base_perf_serv) &&
  284. (num_online <
  285. min(hps_ctxt.little_num_limit_thermal,
  286. hps_ctxt.little_num_limit_low_battery)) &&
  287. (num_online <
  288. min(hps_ctxt.little_num_limit_ultra_power_saving,
  289. hps_ctxt.little_num_limit_power_serv)))
  290. hps_task_wakeup_nolock();
  291. /* XXX: should we move mutex_unlock(&hps_ctxt.lock)
  292. to earlier stage? no! */
  293. mutex_unlock(&hps_ctxt.lock);
  294. return count;
  295. }
  296. hps_warn("hps_num_base_perf_serv_proc_write, bad argument\n");
  297. return -EINVAL;
  298. }
  299. PROC_FOPS_RW(num_base_perf_serv);
  300. /***********************************************************
  301. * procfs callback - algo bound series
  302. * - little_num_limit_thermal
  303. * - big_num_limit_thermal
  304. ***********************************************************/
  305. static int hps_num_limit_thermal_proc_show(struct seq_file *m, void *v)
  306. {
  307. if (hps_ctxt.is_hmp)
  308. seq_printf(m, "%u %u\n", hps_ctxt.little_num_limit_thermal,
  309. hps_ctxt.big_num_limit_thermal);
  310. else
  311. seq_printf(m, "%u\n", hps_ctxt.little_num_limit_thermal);
  312. return 0;
  313. }
  314. static ssize_t hps_num_limit_thermal_proc_write(
  315. struct file *file,
  316. const char __user *buffer,
  317. size_t count,
  318. loff_t *pos)
  319. {
  320. int len = 0, little_num_limit_thermal = 0, big_num_limit_thermal = 0;
  321. char desc[32];
  322. len = min(count, sizeof(desc) - 1);
  323. if (copy_from_user(desc, buffer, len))
  324. return 0;
  325. desc[len] = '\0';
  326. if (hps_ctxt.is_hmp &&
  327. (sscanf(desc, "%u %u", &little_num_limit_thermal,
  328. &big_num_limit_thermal) == 2)) {
  329. if (little_num_limit_thermal > num_possible_little_cpus()
  330. || little_num_limit_thermal < 1) {
  331. hps_warn(
  332. "hps_num_limit_thermal_proc_write, bad argument(%u, %u)\n",
  333. little_num_limit_thermal,
  334. big_num_limit_thermal);
  335. return -EINVAL;
  336. }
  337. if (big_num_limit_thermal > num_possible_big_cpus()) {
  338. hps_warn(
  339. "hps_num_limit_thermal_proc_write, bad argument(%u, %u)\n",
  340. little_num_limit_thermal,
  341. big_num_limit_thermal);
  342. return -EINVAL;
  343. }
  344. mutex_lock(&hps_ctxt.lock);
  345. hps_ctxt.little_num_limit_thermal = little_num_limit_thermal;
  346. hps_ctxt.big_num_limit_thermal = big_num_limit_thermal;
  347. if (num_online_big_cpus() > big_num_limit_thermal)
  348. hps_task_wakeup_nolock();
  349. else if (num_online_little_cpus() > little_num_limit_thermal)
  350. hps_task_wakeup_nolock();
  351. mutex_unlock(&hps_ctxt.lock);
  352. return count;
  353. } else if (!hps_ctxt.is_hmp &&
  354. !kstrtouint(desc, 0, &little_num_limit_thermal)) {
  355. if (little_num_limit_thermal > num_possible_little_cpus()
  356. || little_num_limit_thermal < 1) {
  357. hps_warn(
  358. "hps_num_limit_thermal_proc_write, bad argument(%u)\n",
  359. little_num_limit_thermal);
  360. return -EINVAL;
  361. }
  362. mutex_lock(&hps_ctxt.lock);
  363. hps_ctxt.little_num_limit_thermal = little_num_limit_thermal;
  364. if (num_online_little_cpus() > little_num_limit_thermal)
  365. hps_task_wakeup_nolock();
  366. mutex_unlock(&hps_ctxt.lock);
  367. return count;
  368. }
  369. hps_warn("hps_num_limit_thermal_proc_write, bad argument\n");
  370. return -EINVAL;
  371. }
  372. PROC_FOPS_RW(num_limit_thermal);
  373. /***********************************************************
  374. * procfs callback - algo bound series
  375. * - little_num_limit_low_battery
  376. * - big_num_limit_low_battery
  377. ***********************************************************/
  378. static int hps_num_limit_low_battery_proc_show(struct seq_file *m, void *v)
  379. {
  380. if (hps_ctxt.is_hmp)
  381. seq_printf(m, "%u %u\n", hps_ctxt.little_num_limit_low_battery,
  382. hps_ctxt.big_num_limit_low_battery);
  383. else
  384. seq_printf(m, "%u\n", hps_ctxt.little_num_limit_low_battery);
  385. return 0;
  386. }
  387. static ssize_t hps_num_limit_low_battery_proc_write(
  388. struct file *file,
  389. const char __user *buffer,
  390. size_t count,
  391. loff_t *pos)
  392. {
  393. int len = 0;
  394. int little_num_limit_low_battery = 0, big_num_limit_low_battery = 0;
  395. char desc[32];
  396. len = min(count, sizeof(desc) - 1);
  397. if (copy_from_user(desc, buffer, len))
  398. return 0;
  399. desc[len] = '\0';
  400. if (hps_ctxt.is_hmp &&
  401. (sscanf(desc, "%u %u", &little_num_limit_low_battery,
  402. &big_num_limit_low_battery) == 2)) {
  403. if (little_num_limit_low_battery > num_possible_little_cpus()
  404. || little_num_limit_low_battery < 1) {
  405. hps_warn(
  406. "hps_num_limit_low_battery_proc_write, bad argument(%u, %u)\n",
  407. little_num_limit_low_battery,
  408. big_num_limit_low_battery);
  409. return -EINVAL;
  410. }
  411. if (big_num_limit_low_battery > num_possible_big_cpus()) {
  412. hps_warn(
  413. "hps_num_limit_low_battery_proc_write, bad argument(%u, %u)\n",
  414. little_num_limit_low_battery,
  415. big_num_limit_low_battery);
  416. return -EINVAL;
  417. }
  418. mutex_lock(&hps_ctxt.lock);
  419. hps_ctxt.little_num_limit_low_battery =
  420. little_num_limit_low_battery;
  421. hps_ctxt.big_num_limit_low_battery = big_num_limit_low_battery;
  422. if (num_online_big_cpus() > big_num_limit_low_battery)
  423. hps_task_wakeup_nolock();
  424. else if (num_online_little_cpus() >
  425. little_num_limit_low_battery)
  426. hps_task_wakeup_nolock();
  427. mutex_unlock(&hps_ctxt.lock);
  428. return count;
  429. } else if (!hps_ctxt.is_hmp &&
  430. !kstrtouint(desc, 0, &little_num_limit_low_battery)) {
  431. if (little_num_limit_low_battery > num_possible_little_cpus()
  432. || little_num_limit_low_battery < 1) {
  433. hps_warn(
  434. "hps_num_limit_low_battery_proc_write, bad argument(%u)\n",
  435. little_num_limit_low_battery);
  436. return -EINVAL;
  437. }
  438. mutex_lock(&hps_ctxt.lock);
  439. hps_ctxt.little_num_limit_low_battery =
  440. little_num_limit_low_battery;
  441. if (num_online_little_cpus() > little_num_limit_low_battery)
  442. hps_task_wakeup_nolock();
  443. mutex_unlock(&hps_ctxt.lock);
  444. return count;
  445. }
  446. hps_warn("hps_num_limit_low_battery_proc_write, bad argument\n");
  447. return -EINVAL;
  448. }
  449. PROC_FOPS_RW(num_limit_low_battery);
  450. /***********************************************************
  451. * procfs callback - algo bound series
  452. * - little_num_limit_ultra_power_saving
  453. * - big_num_limit_ultra_power_saving
  454. ***********************************************************/
  455. static int hps_num_limit_ultra_power_saving_proc_show(
  456. struct seq_file *m, void *v)
  457. {
  458. if (hps_ctxt.is_hmp)
  459. seq_printf(m, "%u %u\n",
  460. hps_ctxt.little_num_limit_ultra_power_saving,
  461. hps_ctxt.big_num_limit_ultra_power_saving);
  462. else
  463. seq_printf(m, "%u\n",
  464. hps_ctxt.little_num_limit_ultra_power_saving);
  465. return 0;
  466. }
  467. static ssize_t hps_num_limit_ultra_power_saving_proc_write(
  468. struct file *file,
  469. const char __user *buffer,
  470. size_t count,
  471. loff_t *pos)
  472. {
  473. int len = 0;
  474. int little_num_limit_ultra_power_saving = 0;
  475. int big_num_limit_ultra_power_saving = 0;
  476. char desc[32];
  477. len = min(count, sizeof(desc) - 1);
  478. if (copy_from_user(desc, buffer, len))
  479. return 0;
  480. desc[len] = '\0';
  481. if (hps_ctxt.is_hmp &&
  482. (sscanf(desc, "%u %u",
  483. &little_num_limit_ultra_power_saving,
  484. &big_num_limit_ultra_power_saving) == 2)) {
  485. if (little_num_limit_ultra_power_saving >
  486. num_possible_little_cpus() ||
  487. little_num_limit_ultra_power_saving < 1) {
  488. hps_warn(
  489. "hps_num_limit_ultra_power_saving_proc_write, bad argument(%u, %u)\n",
  490. little_num_limit_ultra_power_saving,
  491. big_num_limit_ultra_power_saving);
  492. return -EINVAL;
  493. }
  494. if (big_num_limit_ultra_power_saving >
  495. num_possible_big_cpus()) {
  496. hps_warn(
  497. "hps_num_limit_ultra_power_saving_proc_write, bad argument(%u, %u)\n",
  498. little_num_limit_ultra_power_saving,
  499. big_num_limit_ultra_power_saving);
  500. return -EINVAL;
  501. }
  502. mutex_lock(&hps_ctxt.lock);
  503. hps_ctxt.little_num_limit_ultra_power_saving =
  504. little_num_limit_ultra_power_saving;
  505. hps_ctxt.big_num_limit_ultra_power_saving =
  506. big_num_limit_ultra_power_saving;
  507. if (num_online_big_cpus() > big_num_limit_ultra_power_saving)
  508. hps_task_wakeup_nolock();
  509. else if (num_online_little_cpus() >
  510. little_num_limit_ultra_power_saving)
  511. hps_task_wakeup_nolock();
  512. mutex_unlock(&hps_ctxt.lock);
  513. return count;
  514. } else if (!hps_ctxt.is_hmp &&
  515. !kstrtouint(desc, 0,
  516. &little_num_limit_ultra_power_saving)) {
  517. if (little_num_limit_ultra_power_saving >
  518. num_possible_little_cpus()
  519. || little_num_limit_ultra_power_saving < 1) {
  520. hps_warn(
  521. "hps_num_limit_ultra_power_saving_proc_write, bad argument(%u)\n",
  522. little_num_limit_ultra_power_saving);
  523. return -EINVAL;
  524. }
  525. mutex_lock(&hps_ctxt.lock);
  526. hps_ctxt.little_num_limit_ultra_power_saving =
  527. little_num_limit_ultra_power_saving;
  528. if (num_online_little_cpus() >
  529. little_num_limit_ultra_power_saving)
  530. hps_task_wakeup_nolock();
  531. mutex_unlock(&hps_ctxt.lock);
  532. return count;
  533. }
  534. hps_warn("hps_num_limit_ultra_power_saving_proc_write, bad argument\n");
  535. return -EINVAL;
  536. }
  537. PROC_FOPS_RW(num_limit_ultra_power_saving);
  538. /***********************************************************
  539. * procfs callback - algo bound series
  540. * - little_num_limit_power_serv
  541. * - big_num_limit_power_serv
  542. ***********************************************************/
  543. static int hps_num_limit_power_serv_proc_show(struct seq_file *m, void *v)
  544. {
  545. if (hps_ctxt.is_hmp)
  546. seq_printf(m, "%u %u\n", hps_ctxt.little_num_limit_power_serv,
  547. hps_ctxt.big_num_limit_power_serv);
  548. else
  549. seq_printf(m, "%u\n", hps_ctxt.little_num_limit_power_serv);
  550. return 0;
  551. }
  552. static ssize_t hps_num_limit_power_serv_proc_write(
  553. struct file *file,
  554. const char __user *buffer,
  555. size_t count,
  556. loff_t *pos)
  557. {
  558. int len = 0;
  559. int little_num_limit_power_serv = 0, big_num_limit_power_serv = 0;
  560. char desc[32];
  561. len = min(count, sizeof(desc) - 1);
  562. if (copy_from_user(desc, buffer, len))
  563. return 0;
  564. desc[len] = '\0';
  565. if (hps_ctxt.is_hmp &&
  566. (sscanf(desc, "%u %u",
  567. &little_num_limit_power_serv,
  568. &big_num_limit_power_serv) == 2)) {
  569. if (little_num_limit_power_serv > num_possible_little_cpus()
  570. || little_num_limit_power_serv < 1) {
  571. hps_warn(
  572. "hps_num_limit_power_serv_proc_write, bad argument(%u, %u)\n",
  573. little_num_limit_power_serv,
  574. big_num_limit_power_serv);
  575. return -EINVAL;
  576. }
  577. if (big_num_limit_power_serv > num_possible_big_cpus()) {
  578. hps_warn(
  579. "hps_num_limit_power_serv_proc_write, bad argument(%u, %u)\n",
  580. little_num_limit_power_serv,
  581. big_num_limit_power_serv);
  582. return -EINVAL;
  583. }
  584. mutex_lock(&hps_ctxt.lock);
  585. hps_ctxt.little_num_limit_power_serv =
  586. little_num_limit_power_serv;
  587. hps_ctxt.big_num_limit_power_serv = big_num_limit_power_serv;
  588. if (num_online_big_cpus() > big_num_limit_power_serv)
  589. hps_task_wakeup_nolock();
  590. else if (num_online_little_cpus() > little_num_limit_power_serv)
  591. hps_task_wakeup_nolock();
  592. mutex_unlock(&hps_ctxt.lock);
  593. return count;
  594. } else if (!hps_ctxt.is_hmp &&
  595. !kstrtouint(desc, 0, &little_num_limit_power_serv)) {
  596. if (little_num_limit_power_serv > num_possible_little_cpus()
  597. || little_num_limit_power_serv < 1) {
  598. hps_warn(
  599. "hps_num_limit_power_serv_proc_write, bad argument(%u)\n",
  600. little_num_limit_power_serv);
  601. return -EINVAL;
  602. }
  603. mutex_lock(&hps_ctxt.lock);
  604. hps_ctxt.little_num_limit_power_serv =
  605. little_num_limit_power_serv;
  606. if (num_online_little_cpus() > little_num_limit_power_serv)
  607. hps_task_wakeup_nolock();
  608. mutex_unlock(&hps_ctxt.lock);
  609. return count;
  610. }
  611. hps_warn("hps_num_limit_power_serv_proc_write, bad argument\n");
  612. return -EINVAL;
  613. }
  614. PROC_FOPS_RW(num_limit_power_serv);
  615. /*
  616. * init
  617. */
  618. int hps_procfs_init(void)
  619. {
  620. /* struct proc_dir_entry *entry = NULL; */
  621. struct proc_dir_entry *hps_dir = NULL;
  622. int r = 0;
  623. int i;
  624. struct pentry {
  625. const char *name;
  626. const struct file_operations *fops;
  627. };
  628. const struct pentry entries[] = {
  629. PROC_ENTRY(init_state),
  630. PROC_ENTRY(state),
  631. PROC_ENTRY(enabled),
  632. PROC_ENTRY(suspend_enabled),
  633. PROC_ENTRY(cur_dump_enabled),
  634. PROC_ENTRY(stats_dump_enabled),
  635. PROC_ENTRY(up_threshold),
  636. PROC_ENTRY(up_times),
  637. PROC_ENTRY(down_threshold),
  638. PROC_ENTRY(down_times),
  639. PROC_ENTRY(input_boost_enabled),
  640. PROC_ENTRY(input_boost_cpu_num),
  641. PROC_ENTRY(rush_boost_enabled),
  642. PROC_ENTRY(rush_boost_threshold),
  643. PROC_ENTRY(rush_boost_times),
  644. PROC_ENTRY(tlp_times),
  645. PROC_ENTRY(num_base_perf_serv),
  646. PROC_ENTRY(num_limit_thermal),
  647. PROC_ENTRY(num_limit_low_battery),
  648. PROC_ENTRY(num_limit_ultra_power_saving),
  649. PROC_ENTRY(num_limit_power_serv),
  650. };
  651. hps_warn("hps_procfs_init\n");
  652. hps_dir = proc_mkdir("hps", NULL);
  653. if (hps_dir == NULL) {
  654. hps_emerg("mkdir /proc/hps fail\n");
  655. return -1;
  656. }
  657. for (i = 0; i < ARRAY_SIZE(entries); i++) {
  658. if (!proc_create(entries[i].name,
  659. S_IRUGO | S_IWUSR | S_IWGRP,
  660. hps_dir, entries[i].fops))
  661. hps_emerg("create /proc/hps/%s failed\n",
  662. entries[i].name);
  663. }
  664. return r;
  665. }