events.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // SPDX-License-Identifier: LGPL-2.1+
  2. // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
  3. #include <linux/netlink.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <thermal.h>
  8. #include "thermal_nl.h"
  9. /*
  10. * Optimization: fill this array to tell which event we do want to pay
  11. * attention to. That happens at init time with the ops
  12. * structure. Each ops will enable the event and the general handler
  13. * will be able to discard the event if there is not ops associated
  14. * with it.
  15. */
  16. static int enabled_ops[__THERMAL_GENL_EVENT_MAX];
  17. static int handle_thermal_event(struct nl_msg *n, void *arg)
  18. {
  19. struct nlmsghdr *nlh = nlmsg_hdr(n);
  20. struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
  21. struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
  22. struct thermal_handler_param *thp = arg;
  23. struct thermal_events_ops *ops = &thp->th->ops->events;
  24. genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
  25. arg = thp->arg;
  26. /*
  27. * This is an event we don't care of, bail out.
  28. */
  29. if (!enabled_ops[genlhdr->cmd])
  30. return THERMAL_SUCCESS;
  31. switch (genlhdr->cmd) {
  32. case THERMAL_GENL_EVENT_TZ_CREATE:
  33. return ops->tz_create(nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]),
  34. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
  35. case THERMAL_GENL_EVENT_TZ_DELETE:
  36. return ops->tz_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
  37. case THERMAL_GENL_EVENT_TZ_ENABLE:
  38. return ops->tz_enable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
  39. case THERMAL_GENL_EVENT_TZ_DISABLE:
  40. return ops->tz_disable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
  41. case THERMAL_GENL_EVENT_TZ_TRIP_CHANGE:
  42. return ops->trip_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  43. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
  44. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
  45. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
  46. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
  47. case THERMAL_GENL_EVENT_TZ_TRIP_ADD:
  48. return ops->trip_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  49. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
  50. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
  51. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
  52. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
  53. case THERMAL_GENL_EVENT_TZ_TRIP_DELETE:
  54. return ops->trip_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  55. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), arg);
  56. case THERMAL_GENL_EVENT_TZ_TRIP_UP:
  57. return ops->trip_high(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  58. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
  59. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
  60. case THERMAL_GENL_EVENT_TZ_TRIP_DOWN:
  61. return ops->trip_low(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  62. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
  63. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
  64. case THERMAL_GENL_EVENT_CDEV_ADD:
  65. return ops->cdev_add(nla_get_string(attrs[THERMAL_GENL_ATTR_CDEV_NAME]),
  66. nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
  67. nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]), arg);
  68. case THERMAL_GENL_EVENT_CDEV_DELETE:
  69. return ops->cdev_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]), arg);
  70. case THERMAL_GENL_EVENT_CDEV_STATE_UPDATE:
  71. return ops->cdev_update(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
  72. nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]), arg);
  73. case THERMAL_GENL_EVENT_TZ_GOV_CHANGE:
  74. return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  75. nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]), arg);
  76. case THERMAL_GENL_EVENT_THRESHOLD_ADD:
  77. return ops->threshold_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  78. nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]),
  79. nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION]), arg);
  80. case THERMAL_GENL_EVENT_THRESHOLD_DELETE:
  81. return ops->threshold_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  82. nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]),
  83. nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION]), arg);
  84. case THERMAL_GENL_EVENT_THRESHOLD_FLUSH:
  85. return ops->threshold_flush(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
  86. case THERMAL_GENL_EVENT_THRESHOLD_UP:
  87. return ops->threshold_up(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  88. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]),
  89. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_PREV_TEMP]), arg);
  90. case THERMAL_GENL_EVENT_THRESHOLD_DOWN:
  91. return ops->threshold_down(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
  92. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]),
  93. nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_PREV_TEMP]), arg);
  94. default:
  95. return -1;
  96. }
  97. }
  98. static void thermal_events_ops_init(struct thermal_events_ops *ops)
  99. {
  100. enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create;
  101. enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete;
  102. enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable;
  103. enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable;
  104. enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high;
  105. enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low;
  106. enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change;
  107. enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add;
  108. enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete;
  109. enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add;
  110. enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete;
  111. enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update;
  112. enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change;
  113. enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_ADD] = !!ops->threshold_add;
  114. enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_DELETE] = !!ops->threshold_delete;
  115. enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_FLUSH] = !!ops->threshold_flush;
  116. enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_UP] = !!ops->threshold_up;
  117. enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_DOWN] = !!ops->threshold_down;
  118. }
  119. thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg)
  120. {
  121. struct thermal_handler_param thp = { .th = th, .arg = arg };
  122. if (!th)
  123. return THERMAL_ERROR;
  124. if (nl_cb_set(th->cb_event, NL_CB_VALID, NL_CB_CUSTOM,
  125. handle_thermal_event, &thp))
  126. return THERMAL_ERROR;
  127. return nl_recvmsgs(th->sk_event, th->cb_event);
  128. }
  129. int thermal_events_fd(struct thermal_handler *th)
  130. {
  131. if (!th)
  132. return -1;
  133. return nl_socket_get_fd(th->sk_event);
  134. }
  135. thermal_error_t thermal_events_exit(struct thermal_handler *th)
  136. {
  137. if (nl_unsubscribe_thermal(th->sk_event, th->cb_event,
  138. THERMAL_GENL_EVENT_GROUP_NAME))
  139. return THERMAL_ERROR;
  140. nl_thermal_disconnect(th->sk_event, th->cb_event);
  141. return THERMAL_SUCCESS;
  142. }
  143. thermal_error_t thermal_events_init(struct thermal_handler *th)
  144. {
  145. thermal_events_ops_init(&th->ops->events);
  146. if (nl_thermal_connect(&th->sk_event, &th->cb_event))
  147. return THERMAL_ERROR;
  148. if (nl_subscribe_thermal(th->sk_event, th->cb_event,
  149. THERMAL_GENL_EVENT_GROUP_NAME))
  150. return THERMAL_ERROR;
  151. return THERMAL_SUCCESS;
  152. }