hyst_qos.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include <linux/spinlock.h>
  2. #include <linux/syscalls.h>
  3. #include <linux/module.h>
  4. #include <linux/init.h>
  5. #include <linux/kernel.h>
  6. #include "hyst_qos.h"
  7. unsigned int busy_hyst_qos_value;
  8. int initialized;
  9. unsigned int cur_max_val = U32_MAX, cur_min_val;
  10. spinlock_t hyst_qos_lock;
  11. struct mutex qos_lock;
  12. struct list_head hyst_req_list;
  13. void hyst_add_request(struct user_req *req, int res_type, char *name)
  14. {
  15. unsigned long flags;
  16. struct user_req *iter_req;
  17. if (!initialized)
  18. hyst_init();
  19. spin_lock_irqsave(&hyst_qos_lock, flags);
  20. list_for_each_entry_rcu(iter_req, &hyst_req_list, list) {
  21. if (list_empty(&hyst_req_list))
  22. break;
  23. if (!iter_req)
  24. continue;
  25. if (iter_req == req) {
  26. pr_err(HQTAG " Try to add duplicated Req\n");
  27. spin_unlock_irqrestore(&hyst_qos_lock, flags);
  28. return;
  29. }
  30. }
  31. list_add_tail_rcu(&(req->list), &hyst_req_list);
  32. spin_unlock_irqrestore(&hyst_qos_lock, flags);
  33. req->name = name;
  34. req->res_type = res_type;
  35. }
  36. EXPORT_SYMBOL_GPL(hyst_add_request);
  37. void hyst_update_request(struct user_req *req, int type, unsigned int value)
  38. {
  39. unsigned long flags;
  40. unsigned int qos_value = 0, max_of_min_reqval = 0, min_of_max_reqval = U32_MAX;
  41. struct user_req *iter_req;
  42. if (!initialized)
  43. hyst_init();
  44. mutex_lock(&qos_lock);
  45. req->values[type] = value;
  46. /* Update Min Limit */
  47. if (type == PM_QOS_MIN_LIMIT) {
  48. spin_lock_irqsave(&hyst_qos_lock, flags);
  49. list_for_each_entry_rcu(iter_req, &hyst_req_list, list) {
  50. if (list_empty(&hyst_req_list))
  51. break;
  52. if (!iter_req || req->res_type != iter_req->res_type)
  53. continue;
  54. if (iter_req->values[PM_QOS_MIN_LIMIT] > max_of_min_reqval)
  55. max_of_min_reqval = iter_req->values[PM_QOS_MIN_LIMIT];
  56. }
  57. qos_value = (cur_max_val < max_of_min_reqval) ? cur_max_val : max_of_min_reqval;
  58. cur_min_val = max_of_min_reqval;
  59. spin_unlock_irqrestore(&hyst_qos_lock, flags);
  60. pr_info(HQTAG" %s ::: Rqst Val(%u), Type(%d), Qos Value(%u)\n", req->name, value, req->res_type, qos_value);
  61. } else if (type == PM_QOS_MAX_LIMIT) {
  62. /* Update Max Limit */
  63. spin_lock_irqsave(&hyst_qos_lock, flags);
  64. list_for_each_entry_rcu(iter_req, &hyst_req_list, list) {
  65. if (list_empty(&hyst_req_list))
  66. break;
  67. if (!iter_req || req->res_type != iter_req->res_type)
  68. continue;
  69. if (iter_req->values[PM_QOS_MAX_LIMIT] < min_of_max_reqval)
  70. min_of_max_reqval = iter_req->values[PM_QOS_MAX_LIMIT];
  71. }
  72. qos_value = (cur_min_val > min_of_max_reqval) ? min_of_max_reqval : cur_min_val;
  73. cur_max_val = min_of_max_reqval;
  74. spin_unlock_irqrestore(&hyst_qos_lock, flags);
  75. }
  76. mutex_unlock(&qos_lock);
  77. busy_hyst_qos_value = qos_value;
  78. sched_update_hyst_times();
  79. }
  80. EXPORT_SYMBOL_GPL(hyst_update_request);
  81. void hyst_remove_request(struct user_req *req)
  82. {
  83. unsigned long flags;
  84. hyst_update_request(req, PM_QOS_MIN_LIMIT, MIN_DEFAULT_VALUE);
  85. hyst_update_request(req, PM_QOS_MAX_LIMIT, MAX_DEFAULT_VALUE);
  86. spin_lock_irqsave(&hyst_qos_lock, flags);
  87. list_del_rcu(&(req->list));
  88. spin_unlock_irqrestore(&hyst_qos_lock, flags);
  89. }
  90. EXPORT_SYMBOL_GPL(hyst_remove_request);
  91. void hyst_init(void)
  92. {
  93. INIT_LIST_HEAD(&hyst_req_list);
  94. spin_lock_init(&hyst_qos_lock);
  95. mutex_init(&qos_lock);
  96. initialized = true;
  97. }