input-boost.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2013-2015,2017,2019-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "input-boost: " fmt
  6. #include <linux/kernel.h>
  7. #include <linux/init.h>
  8. #include <linux/cpufreq.h>
  9. #include <linux/cpu.h>
  10. #include <linux/sched.h>
  11. #include <linux/slab.h>
  12. #include <linux/input.h>
  13. #include <linux/time.h>
  14. #include <linux/sysfs.h>
  15. #include <linux/pm_qos.h>
  16. #include "walt.h"
  17. #define input_boost_attr_rw(_name) \
  18. static struct kobj_attribute _name##_attr = \
  19. __ATTR(_name, 0644, show_##_name, store_##_name)
  20. #define show_one(file_name) \
  21. static ssize_t show_##file_name \
  22. (struct kobject *kobj, struct kobj_attribute *attr, char *buf) \
  23. { \
  24. return scnprintf(buf, PAGE_SIZE, "%u\n", file_name); \
  25. }
  26. #define store_one(file_name) \
  27. static ssize_t store_##file_name \
  28. (struct kobject *kobj, struct kobj_attribute *attr, \
  29. const char *buf, size_t count) \
  30. { \
  31. \
  32. sscanf(buf, "%u", &file_name); \
  33. return count; \
  34. }
  35. struct cpu_sync {
  36. int cpu;
  37. unsigned int input_boost_min;
  38. unsigned int input_boost_freq;
  39. };
  40. static DEFINE_PER_CPU(struct cpu_sync, sync_info);
  41. static struct workqueue_struct *input_boost_wq;
  42. static struct work_struct input_boost_work;
  43. static bool sched_boost_active;
  44. static struct delayed_work input_boost_rem;
  45. static u64 last_input_time;
  46. #define MIN_INPUT_INTERVAL (150 * USEC_PER_MSEC)
  47. static DEFINE_PER_CPU(struct freq_qos_request, qos_req);
  48. static void boost_adjust_notify(struct cpufreq_policy *policy)
  49. {
  50. unsigned int cpu = policy->cpu;
  51. struct cpu_sync *s = &per_cpu(sync_info, cpu);
  52. unsigned int ib_min = s->input_boost_min;
  53. struct freq_qos_request *req = &per_cpu(qos_req, cpu);
  54. int ret;
  55. pr_debug("CPU%u policy min before boost: %u kHz\n",
  56. cpu, policy->min);
  57. pr_debug("CPU%u boost min: %u kHz\n", cpu, ib_min);
  58. ret = freq_qos_update_request(req, ib_min);
  59. if (ret < 0)
  60. pr_err("Failed to update freq constraint in boost_adjust: %d\n",
  61. ib_min);
  62. pr_debug("CPU%u policy min after boost: %u kHz\n", cpu, policy->min);
  63. }
  64. static void update_policy_online(void)
  65. {
  66. unsigned int i;
  67. struct cpufreq_policy *policy;
  68. struct cpumask online_cpus;
  69. /* Re-evaluate policy to trigger adjust notifier for online CPUs */
  70. cpus_read_lock();
  71. online_cpus = *cpu_online_mask;
  72. for_each_cpu(i, &online_cpus) {
  73. policy = cpufreq_cpu_get(i);
  74. if (!policy) {
  75. pr_err("%s: cpufreq policy not found for cpu%d\n",
  76. __func__, i);
  77. return;
  78. }
  79. cpumask_andnot(&online_cpus, &online_cpus,
  80. policy->related_cpus);
  81. boost_adjust_notify(policy);
  82. }
  83. cpus_read_unlock();
  84. }
  85. static void do_input_boost_rem(struct work_struct *work)
  86. {
  87. unsigned int i, ret;
  88. struct cpu_sync *i_sync_info;
  89. /* Reset the input_boost_min for all CPUs in the system */
  90. pr_debug("Resetting input boost min for all CPUs\n");
  91. for_each_possible_cpu(i) {
  92. i_sync_info = &per_cpu(sync_info, i);
  93. i_sync_info->input_boost_min = 0;
  94. }
  95. /* Update policies for all online CPUs */
  96. update_policy_online();
  97. if (sched_boost_active) {
  98. ret = sched_set_boost(0);
  99. if (!ret)
  100. pr_err("input-boost: sched boost disable failed\n");
  101. sched_boost_active = false;
  102. }
  103. }
  104. static void do_input_boost(struct work_struct *work)
  105. {
  106. unsigned int cpu, ret;
  107. struct cpu_sync *i_sync_info;
  108. cancel_delayed_work_sync(&input_boost_rem);
  109. if (sched_boost_active) {
  110. sched_set_boost(0);
  111. sched_boost_active = false;
  112. }
  113. /* Set the input_boost_min for all CPUs in the system */
  114. pr_debug("Setting input boost min for all CPUs\n");
  115. for_each_possible_cpu(cpu) {
  116. i_sync_info = &per_cpu(sync_info, cpu);
  117. i_sync_info->input_boost_min = sysctl_input_boost_freq[cpu];
  118. }
  119. /* Update policies for all online CPUs */
  120. update_policy_online();
  121. /* Enable scheduler boost to migrate tasks to big cluster */
  122. if (sysctl_sched_boost_on_input > 0) {
  123. ret = sched_set_boost(sysctl_sched_boost_on_input);
  124. if (ret)
  125. pr_err("input-boost: sched boost enable failed\n");
  126. else
  127. sched_boost_active = true;
  128. }
  129. queue_delayed_work(input_boost_wq, &input_boost_rem,
  130. msecs_to_jiffies(sysctl_input_boost_ms));
  131. }
  132. static void inputboost_input_event(struct input_handle *handle,
  133. unsigned int type, unsigned int code, int value)
  134. {
  135. u64 now;
  136. int cpu;
  137. int enabled = 0;
  138. for_each_possible_cpu(cpu) {
  139. if (sysctl_input_boost_freq[cpu] > 0) {
  140. enabled = 1;
  141. break;
  142. }
  143. }
  144. if (!enabled)
  145. return;
  146. now = ktime_to_us(ktime_get());
  147. if (now - last_input_time < MIN_INPUT_INTERVAL)
  148. return;
  149. if (work_pending(&input_boost_work))
  150. return;
  151. queue_work(input_boost_wq, &input_boost_work);
  152. last_input_time = ktime_to_us(ktime_get());
  153. }
  154. static int inputboost_input_connect(struct input_handler *handler,
  155. struct input_dev *dev, const struct input_device_id *id)
  156. {
  157. struct input_handle *handle;
  158. int error;
  159. handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
  160. if (!handle)
  161. return -ENOMEM;
  162. handle->dev = dev;
  163. handle->handler = handler;
  164. handle->name = "cpufreq";
  165. error = input_register_handle(handle);
  166. if (error)
  167. goto err2;
  168. error = input_open_device(handle);
  169. if (error)
  170. goto err1;
  171. return 0;
  172. err1:
  173. input_unregister_handle(handle);
  174. err2:
  175. kfree(handle);
  176. return error;
  177. }
  178. static void inputboost_input_disconnect(struct input_handle *handle)
  179. {
  180. input_close_device(handle);
  181. input_unregister_handle(handle);
  182. kfree(handle);
  183. }
  184. static const struct input_device_id inputboost_ids[] = {
  185. /* multi-touch touchscreen */
  186. {
  187. .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
  188. INPUT_DEVICE_ID_MATCH_ABSBIT,
  189. .evbit = { BIT_MASK(EV_ABS) },
  190. .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
  191. BIT_MASK(ABS_MT_POSITION_X) |
  192. BIT_MASK(ABS_MT_POSITION_Y)
  193. },
  194. },
  195. /* touchpad */
  196. {
  197. .flags = INPUT_DEVICE_ID_MATCH_KEYBIT |
  198. INPUT_DEVICE_ID_MATCH_ABSBIT,
  199. .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
  200. .absbit = { [BIT_WORD(ABS_X)] =
  201. BIT_MASK(ABS_X) | BIT_MASK(ABS_Y)
  202. },
  203. },
  204. /* Keypad */
  205. {
  206. .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
  207. .evbit = { BIT_MASK(EV_KEY) },
  208. },
  209. { },
  210. };
  211. static struct input_handler inputboost_input_handler = {
  212. .event = inputboost_input_event,
  213. .connect = inputboost_input_connect,
  214. .disconnect = inputboost_input_disconnect,
  215. .name = "input-boost",
  216. .id_table = inputboost_ids,
  217. };
  218. struct kobject *input_boost_kobj;
  219. int input_boost_init(void)
  220. {
  221. int cpu, ret;
  222. struct cpu_sync *s;
  223. struct cpufreq_policy *policy;
  224. struct freq_qos_request *req;
  225. input_boost_wq = alloc_workqueue("inputboost_wq", WQ_HIGHPRI, 0);
  226. if (!input_boost_wq)
  227. return -EFAULT;
  228. INIT_WORK(&input_boost_work, do_input_boost);
  229. INIT_DELAYED_WORK(&input_boost_rem, do_input_boost_rem);
  230. for_each_possible_cpu(cpu) {
  231. s = &per_cpu(sync_info, cpu);
  232. s->cpu = cpu;
  233. req = &per_cpu(qos_req, cpu);
  234. policy = cpufreq_cpu_get(cpu);
  235. if (!policy) {
  236. pr_err("%s: cpufreq policy not found for cpu%d\n",
  237. __func__, cpu);
  238. return -ESRCH;
  239. }
  240. ret = freq_qos_add_request(&policy->constraints, req,
  241. FREQ_QOS_MIN, policy->min);
  242. if (ret < 0) {
  243. pr_err("%s: Failed to add freq constraint (%d)\n",
  244. __func__, ret);
  245. return ret;
  246. }
  247. }
  248. ret = input_register_handler(&inputboost_input_handler);
  249. return 0;
  250. }