thermal_sysfs.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * thermal.c - sysfs interface of thermal devices
  4. *
  5. * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com>
  6. *
  7. * Highly based on original thermal_core.c
  8. * Copyright (C) 2008 Intel Corp
  9. * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
  10. * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
  11. */
  12. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13. #include <linux/container_of.h>
  14. #include <linux/sysfs.h>
  15. #include <linux/device.h>
  16. #include <linux/err.h>
  17. #include <linux/slab.h>
  18. #include <linux/string.h>
  19. #include <linux/jiffies.h>
  20. #include "thermal_core.h"
  21. /* sys I/F for thermal zone */
  22. static ssize_t
  23. type_show(struct device *dev, struct device_attribute *attr, char *buf)
  24. {
  25. struct thermal_zone_device *tz = to_thermal_zone(dev);
  26. return sysfs_emit(buf, "%s\n", tz->type);
  27. }
  28. static ssize_t
  29. temp_show(struct device *dev, struct device_attribute *attr, char *buf)
  30. {
  31. struct thermal_zone_device *tz = to_thermal_zone(dev);
  32. int temperature, ret;
  33. ret = thermal_zone_get_temp(tz, &temperature);
  34. if (!ret)
  35. return sysfs_emit(buf, "%d\n", temperature);
  36. if (ret == -EAGAIN)
  37. return -ENODATA;
  38. return ret;
  39. }
  40. static ssize_t
  41. mode_show(struct device *dev, struct device_attribute *attr, char *buf)
  42. {
  43. struct thermal_zone_device *tz = to_thermal_zone(dev);
  44. guard(thermal_zone)(tz);
  45. if (tz->mode == THERMAL_DEVICE_ENABLED)
  46. return sysfs_emit(buf, "enabled\n");
  47. return sysfs_emit(buf, "disabled\n");
  48. }
  49. static ssize_t
  50. mode_store(struct device *dev, struct device_attribute *attr,
  51. const char *buf, size_t count)
  52. {
  53. struct thermal_zone_device *tz = to_thermal_zone(dev);
  54. int result;
  55. if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
  56. result = thermal_zone_device_enable(tz);
  57. else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
  58. result = thermal_zone_device_disable(tz);
  59. else
  60. result = -EINVAL;
  61. if (result)
  62. return result;
  63. return count;
  64. }
  65. #define thermal_trip_of_attr(_ptr_, _attr_) \
  66. ({ \
  67. struct thermal_trip_desc *td; \
  68. \
  69. td = container_of(_ptr_, struct thermal_trip_desc, \
  70. trip_attrs._attr_.attr); \
  71. &td->trip; \
  72. })
  73. static ssize_t
  74. trip_point_type_show(struct device *dev, struct device_attribute *attr,
  75. char *buf)
  76. {
  77. struct thermal_trip *trip = thermal_trip_of_attr(attr, type);
  78. return sysfs_emit(buf, "%s\n", thermal_trip_type_name(trip->type));
  79. }
  80. static ssize_t
  81. trip_point_temp_store(struct device *dev, struct device_attribute *attr,
  82. const char *buf, size_t count)
  83. {
  84. struct thermal_trip *trip = thermal_trip_of_attr(attr, temp);
  85. struct thermal_zone_device *tz = to_thermal_zone(dev);
  86. int temp;
  87. if (kstrtoint(buf, 10, &temp))
  88. return -EINVAL;
  89. guard(thermal_zone)(tz);
  90. if (temp == trip->temperature)
  91. return count;
  92. /* Arrange the condition to avoid integer overflows. */
  93. if (temp != THERMAL_TEMP_INVALID &&
  94. temp <= trip->hysteresis + THERMAL_TEMP_INVALID)
  95. return -EINVAL;
  96. if (tz->ops.set_trip_temp) {
  97. int ret;
  98. ret = tz->ops.set_trip_temp(tz, trip, temp);
  99. if (ret)
  100. return ret;
  101. }
  102. thermal_zone_set_trip_temp(tz, trip, temp);
  103. __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
  104. return count;
  105. }
  106. static ssize_t
  107. trip_point_temp_show(struct device *dev, struct device_attribute *attr,
  108. char *buf)
  109. {
  110. struct thermal_trip *trip = thermal_trip_of_attr(attr, temp);
  111. return sysfs_emit(buf, "%d\n", READ_ONCE(trip->temperature));
  112. }
  113. static ssize_t
  114. trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
  115. const char *buf, size_t count)
  116. {
  117. struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst);
  118. struct thermal_zone_device *tz = to_thermal_zone(dev);
  119. int hyst;
  120. if (kstrtoint(buf, 10, &hyst) || hyst < 0)
  121. return -EINVAL;
  122. guard(thermal_zone)(tz);
  123. if (hyst == trip->hysteresis)
  124. return count;
  125. /*
  126. * Allow the hysteresis to be updated when the temperature is invalid
  127. * to allow user space to avoid having to adjust hysteresis after a
  128. * valid temperature has been set, but in that case just change the
  129. * value and do nothing else.
  130. */
  131. if (trip->temperature == THERMAL_TEMP_INVALID) {
  132. WRITE_ONCE(trip->hysteresis, hyst);
  133. return count;
  134. }
  135. if (trip->temperature - hyst <= THERMAL_TEMP_INVALID)
  136. return -EINVAL;
  137. thermal_zone_set_trip_hyst(tz, trip, hyst);
  138. __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
  139. return count;
  140. }
  141. static ssize_t
  142. trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
  143. char *buf)
  144. {
  145. struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst);
  146. return sysfs_emit(buf, "%d\n", READ_ONCE(trip->hysteresis));
  147. }
  148. static ssize_t
  149. policy_store(struct device *dev, struct device_attribute *attr,
  150. const char *buf, size_t count)
  151. {
  152. struct thermal_zone_device *tz = to_thermal_zone(dev);
  153. char name[THERMAL_NAME_LENGTH];
  154. int ret;
  155. strscpy(name, buf);
  156. ret = thermal_zone_device_set_policy(tz, name);
  157. if (!ret)
  158. ret = count;
  159. return ret;
  160. }
  161. static ssize_t
  162. policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
  163. {
  164. struct thermal_zone_device *tz = to_thermal_zone(dev);
  165. return sysfs_emit(buf, "%s\n", tz->governor->name);
  166. }
  167. static ssize_t
  168. available_policies_show(struct device *dev, struct device_attribute *devattr,
  169. char *buf)
  170. {
  171. return thermal_build_list_of_policies(buf);
  172. }
  173. #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
  174. static ssize_t
  175. emul_temp_store(struct device *dev, struct device_attribute *attr,
  176. const char *buf, size_t count)
  177. {
  178. struct thermal_zone_device *tz = to_thermal_zone(dev);
  179. int temperature;
  180. if (kstrtoint(buf, 10, &temperature))
  181. return -EINVAL;
  182. guard(thermal_zone)(tz);
  183. if (tz->ops.set_emul_temp) {
  184. int ret;
  185. ret = tz->ops.set_emul_temp(tz, temperature);
  186. if (ret)
  187. return ret;
  188. } else {
  189. tz->emul_temperature = temperature;
  190. }
  191. __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
  192. return count;
  193. }
  194. static DEVICE_ATTR_WO(emul_temp);
  195. #endif
  196. static ssize_t
  197. sustainable_power_show(struct device *dev, struct device_attribute *devattr,
  198. char *buf)
  199. {
  200. struct thermal_zone_device *tz = to_thermal_zone(dev);
  201. if (tz->tzp)
  202. return sysfs_emit(buf, "%u\n", tz->tzp->sustainable_power);
  203. else
  204. return -EIO;
  205. }
  206. static ssize_t
  207. sustainable_power_store(struct device *dev, struct device_attribute *devattr,
  208. const char *buf, size_t count)
  209. {
  210. struct thermal_zone_device *tz = to_thermal_zone(dev);
  211. u32 sustainable_power;
  212. if (!tz->tzp)
  213. return -EIO;
  214. if (kstrtou32(buf, 10, &sustainable_power))
  215. return -EINVAL;
  216. tz->tzp->sustainable_power = sustainable_power;
  217. return count;
  218. }
  219. #define create_s32_tzp_attr(name) \
  220. static ssize_t \
  221. name##_show(struct device *dev, struct device_attribute *devattr, \
  222. char *buf) \
  223. { \
  224. struct thermal_zone_device *tz = to_thermal_zone(dev); \
  225. \
  226. if (tz->tzp) \
  227. return sysfs_emit(buf, "%d\n", tz->tzp->name); \
  228. else \
  229. return -EIO; \
  230. } \
  231. \
  232. static ssize_t \
  233. name##_store(struct device *dev, struct device_attribute *devattr, \
  234. const char *buf, size_t count) \
  235. { \
  236. struct thermal_zone_device *tz = to_thermal_zone(dev); \
  237. s32 value; \
  238. \
  239. if (!tz->tzp) \
  240. return -EIO; \
  241. \
  242. if (kstrtos32(buf, 10, &value)) \
  243. return -EINVAL; \
  244. \
  245. tz->tzp->name = value; \
  246. \
  247. return count; \
  248. } \
  249. static DEVICE_ATTR_RW(name)
  250. create_s32_tzp_attr(k_po);
  251. create_s32_tzp_attr(k_pu);
  252. create_s32_tzp_attr(k_i);
  253. create_s32_tzp_attr(k_d);
  254. create_s32_tzp_attr(integral_cutoff);
  255. create_s32_tzp_attr(slope);
  256. create_s32_tzp_attr(offset);
  257. #undef create_s32_tzp_attr
  258. /*
  259. * These are thermal zone device attributes that will always be present.
  260. * All the attributes created for tzp (create_s32_tzp_attr) also are always
  261. * present on the sysfs interface.
  262. */
  263. static DEVICE_ATTR_RO(type);
  264. static DEVICE_ATTR_RO(temp);
  265. static DEVICE_ATTR_RW(policy);
  266. static DEVICE_ATTR_RO(available_policies);
  267. static DEVICE_ATTR_RW(sustainable_power);
  268. /* These thermal zone device attributes are created based on conditions */
  269. static DEVICE_ATTR_RW(mode);
  270. /* These attributes are unconditionally added to a thermal zone */
  271. static struct attribute *thermal_zone_dev_attrs[] = {
  272. &dev_attr_type.attr,
  273. &dev_attr_temp.attr,
  274. #if (IS_ENABLED(CONFIG_THERMAL_EMULATION))
  275. &dev_attr_emul_temp.attr,
  276. #endif
  277. &dev_attr_policy.attr,
  278. &dev_attr_available_policies.attr,
  279. &dev_attr_sustainable_power.attr,
  280. &dev_attr_k_po.attr,
  281. &dev_attr_k_pu.attr,
  282. &dev_attr_k_i.attr,
  283. &dev_attr_k_d.attr,
  284. &dev_attr_integral_cutoff.attr,
  285. &dev_attr_slope.attr,
  286. &dev_attr_offset.attr,
  287. NULL,
  288. };
  289. static const struct attribute_group thermal_zone_attribute_group = {
  290. .attrs = thermal_zone_dev_attrs,
  291. };
  292. static struct attribute *thermal_zone_mode_attrs[] = {
  293. &dev_attr_mode.attr,
  294. NULL,
  295. };
  296. static const struct attribute_group thermal_zone_mode_attribute_group = {
  297. .attrs = thermal_zone_mode_attrs,
  298. };
  299. static const struct attribute_group *thermal_zone_attribute_groups[] = {
  300. &thermal_zone_attribute_group,
  301. &thermal_zone_mode_attribute_group,
  302. /* This is not NULL terminated as we create the group dynamically */
  303. };
  304. /**
  305. * create_trip_attrs() - create attributes for trip points
  306. * @tz: the thermal zone device
  307. *
  308. * helper function to instantiate sysfs entries for every trip
  309. * point and its properties of a struct thermal_zone_device.
  310. *
  311. * Return: 0 on success, the proper error value otherwise.
  312. */
  313. static int create_trip_attrs(struct thermal_zone_device *tz)
  314. {
  315. struct thermal_trip_desc *td;
  316. struct attribute **attrs;
  317. int i;
  318. attrs = kzalloc_objs(*attrs, tz->num_trips * 3 + 1);
  319. if (!attrs)
  320. return -ENOMEM;
  321. i = 0;
  322. for_each_trip_desc(tz, td) {
  323. struct thermal_trip_attrs *trip_attrs = &td->trip_attrs;
  324. /* create trip type attribute */
  325. snprintf(trip_attrs->type.name, THERMAL_NAME_LENGTH,
  326. "trip_point_%d_type", i);
  327. sysfs_attr_init(&trip_attrs->type.attr.attr);
  328. trip_attrs->type.attr.attr.name = trip_attrs->type.name;
  329. trip_attrs->type.attr.attr.mode = S_IRUGO;
  330. trip_attrs->type.attr.show = trip_point_type_show;
  331. attrs[i] = &trip_attrs->type.attr.attr;
  332. /* create trip temp attribute */
  333. snprintf(trip_attrs->temp.name, THERMAL_NAME_LENGTH,
  334. "trip_point_%d_temp", i);
  335. sysfs_attr_init(&trip_attrs->temp.attr.attr);
  336. trip_attrs->temp.attr.attr.name = trip_attrs->temp.name;
  337. trip_attrs->temp.attr.attr.mode = S_IRUGO;
  338. trip_attrs->temp.attr.show = trip_point_temp_show;
  339. if (td->trip.flags & THERMAL_TRIP_FLAG_RW_TEMP) {
  340. trip_attrs->temp.attr.attr.mode |= S_IWUSR;
  341. trip_attrs->temp.attr.store = trip_point_temp_store;
  342. }
  343. attrs[i + tz->num_trips] = &trip_attrs->temp.attr.attr;
  344. snprintf(trip_attrs->hyst.name, THERMAL_NAME_LENGTH,
  345. "trip_point_%d_hyst", i);
  346. sysfs_attr_init(&trip_attrs->hyst.attr.attr);
  347. trip_attrs->hyst.attr.attr.name = trip_attrs->hyst.name;
  348. trip_attrs->hyst.attr.attr.mode = S_IRUGO;
  349. trip_attrs->hyst.attr.show = trip_point_hyst_show;
  350. if (td->trip.flags & THERMAL_TRIP_FLAG_RW_HYST) {
  351. trip_attrs->hyst.attr.attr.mode |= S_IWUSR;
  352. trip_attrs->hyst.attr.store = trip_point_hyst_store;
  353. }
  354. attrs[i + 2 * tz->num_trips] = &trip_attrs->hyst.attr.attr;
  355. i++;
  356. }
  357. attrs[tz->num_trips * 3] = NULL;
  358. tz->trips_attribute_group.attrs = attrs;
  359. return 0;
  360. }
  361. /**
  362. * destroy_trip_attrs() - destroy attributes for trip points
  363. * @tz: the thermal zone device
  364. *
  365. * helper function to free resources allocated by create_trip_attrs()
  366. */
  367. static void destroy_trip_attrs(struct thermal_zone_device *tz)
  368. {
  369. if (tz)
  370. kfree(tz->trips_attribute_group.attrs);
  371. }
  372. int thermal_zone_create_device_groups(struct thermal_zone_device *tz)
  373. {
  374. const struct attribute_group **groups;
  375. int i, size, result;
  376. /* we need one extra for trips and the NULL to terminate the array */
  377. size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2;
  378. /* This also takes care of API requirement to be NULL terminated */
  379. groups = kzalloc_objs(*groups, size);
  380. if (!groups)
  381. return -ENOMEM;
  382. for (i = 0; i < size - 2; i++)
  383. groups[i] = thermal_zone_attribute_groups[i];
  384. if (tz->num_trips) {
  385. result = create_trip_attrs(tz);
  386. if (result) {
  387. kfree(groups);
  388. return result;
  389. }
  390. groups[size - 2] = &tz->trips_attribute_group;
  391. }
  392. tz->device.groups = groups;
  393. return 0;
  394. }
  395. void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
  396. {
  397. if (!tz)
  398. return;
  399. if (tz->num_trips)
  400. destroy_trip_attrs(tz);
  401. kfree(tz->device.groups);
  402. }
  403. /* sys I/F for cooling device */
  404. static ssize_t
  405. cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf)
  406. {
  407. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  408. return sysfs_emit(buf, "%s\n", cdev->type);
  409. }
  410. static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
  411. char *buf)
  412. {
  413. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  414. return sysfs_emit(buf, "%ld\n", cdev->max_state);
  415. }
  416. static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
  417. char *buf)
  418. {
  419. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  420. unsigned long state;
  421. int ret;
  422. ret = cdev->ops->get_cur_state(cdev, &state);
  423. if (ret)
  424. return ret;
  425. return sysfs_emit(buf, "%ld\n", state);
  426. }
  427. static ssize_t
  428. cur_state_store(struct device *dev, struct device_attribute *attr,
  429. const char *buf, size_t count)
  430. {
  431. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  432. unsigned long state;
  433. int result;
  434. if (sscanf(buf, "%ld\n", &state) != 1)
  435. return -EINVAL;
  436. if ((long)state < 0)
  437. return -EINVAL;
  438. /* Requested state should be less than max_state + 1 */
  439. if (state > cdev->max_state)
  440. return -EINVAL;
  441. guard(cooling_dev)(cdev);
  442. result = cdev->ops->set_cur_state(cdev, state);
  443. if (result)
  444. return result;
  445. thermal_cooling_device_stats_update(cdev, state);
  446. return count;
  447. }
  448. static struct device_attribute
  449. dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL);
  450. static DEVICE_ATTR_RO(max_state);
  451. static DEVICE_ATTR_RW(cur_state);
  452. static struct attribute *cooling_device_attrs[] = {
  453. &dev_attr_cdev_type.attr,
  454. &dev_attr_max_state.attr,
  455. &dev_attr_cur_state.attr,
  456. NULL,
  457. };
  458. static const struct attribute_group cooling_device_attr_group = {
  459. .attrs = cooling_device_attrs,
  460. };
  461. static const struct attribute_group *cooling_device_attr_groups[] = {
  462. &cooling_device_attr_group,
  463. NULL, /* Space allocated for cooling_device_stats_attr_group */
  464. NULL,
  465. };
  466. #ifdef CONFIG_THERMAL_STATISTICS
  467. struct cooling_dev_stats {
  468. spinlock_t lock;
  469. unsigned int total_trans;
  470. unsigned long state;
  471. ktime_t last_time;
  472. ktime_t *time_in_state;
  473. unsigned int *trans_table;
  474. };
  475. static void update_time_in_state(struct cooling_dev_stats *stats)
  476. {
  477. ktime_t now = ktime_get(), delta;
  478. delta = ktime_sub(now, stats->last_time);
  479. stats->time_in_state[stats->state] =
  480. ktime_add(stats->time_in_state[stats->state], delta);
  481. stats->last_time = now;
  482. }
  483. void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
  484. unsigned long new_state)
  485. {
  486. struct cooling_dev_stats *stats = cdev->stats;
  487. lockdep_assert_held(&cdev->lock);
  488. if (!stats)
  489. return;
  490. spin_lock(&stats->lock);
  491. if (stats->state == new_state)
  492. goto unlock;
  493. update_time_in_state(stats);
  494. stats->trans_table[stats->state * (cdev->max_state + 1) + new_state]++;
  495. stats->state = new_state;
  496. stats->total_trans++;
  497. unlock:
  498. spin_unlock(&stats->lock);
  499. }
  500. static ssize_t total_trans_show(struct device *dev,
  501. struct device_attribute *attr, char *buf)
  502. {
  503. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  504. struct cooling_dev_stats *stats;
  505. int ret;
  506. guard(cooling_dev)(cdev);
  507. stats = cdev->stats;
  508. if (!stats)
  509. return 0;
  510. spin_lock(&stats->lock);
  511. ret = sysfs_emit(buf, "%u\n", stats->total_trans);
  512. spin_unlock(&stats->lock);
  513. return ret;
  514. }
  515. static ssize_t
  516. time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
  517. char *buf)
  518. {
  519. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  520. struct cooling_dev_stats *stats;
  521. ssize_t len = 0;
  522. int i;
  523. guard(cooling_dev)(cdev);
  524. stats = cdev->stats;
  525. if (!stats)
  526. return 0;
  527. spin_lock(&stats->lock);
  528. update_time_in_state(stats);
  529. for (i = 0; i <= cdev->max_state; i++) {
  530. len += sysfs_emit_at(buf, len, "state%u\t%llu\n", i,
  531. ktime_to_ms(stats->time_in_state[i]));
  532. }
  533. spin_unlock(&stats->lock);
  534. return len;
  535. }
  536. static ssize_t
  537. reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
  538. size_t count)
  539. {
  540. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  541. struct cooling_dev_stats *stats;
  542. int i, states;
  543. guard(cooling_dev)(cdev);
  544. stats = cdev->stats;
  545. if (!stats)
  546. return count;
  547. states = cdev->max_state + 1;
  548. spin_lock(&stats->lock);
  549. stats->total_trans = 0;
  550. stats->last_time = ktime_get();
  551. memset(stats->trans_table, 0,
  552. states * states * sizeof(*stats->trans_table));
  553. for (i = 0; i < states; i++)
  554. stats->time_in_state[i] = ktime_set(0, 0);
  555. spin_unlock(&stats->lock);
  556. return count;
  557. }
  558. static ssize_t trans_table_show(struct device *dev,
  559. struct device_attribute *attr, char *buf)
  560. {
  561. struct thermal_cooling_device *cdev = to_cooling_device(dev);
  562. struct cooling_dev_stats *stats;
  563. ssize_t len = 0;
  564. int i, j;
  565. guard(cooling_dev)(cdev);
  566. stats = cdev->stats;
  567. if (!stats)
  568. return -ENODATA;
  569. len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
  570. len += snprintf(buf + len, PAGE_SIZE - len, " : ");
  571. for (i = 0; i <= cdev->max_state; i++) {
  572. if (len >= PAGE_SIZE)
  573. break;
  574. len += snprintf(buf + len, PAGE_SIZE - len, "state%2u ", i);
  575. }
  576. if (len >= PAGE_SIZE)
  577. return PAGE_SIZE;
  578. len += snprintf(buf + len, PAGE_SIZE - len, "\n");
  579. for (i = 0; i <= cdev->max_state; i++) {
  580. if (len >= PAGE_SIZE)
  581. break;
  582. len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i);
  583. for (j = 0; j <= cdev->max_state; j++) {
  584. if (len >= PAGE_SIZE)
  585. break;
  586. len += snprintf(buf + len, PAGE_SIZE - len, "%8u ",
  587. stats->trans_table[i * (cdev->max_state + 1) + j]);
  588. }
  589. if (len >= PAGE_SIZE)
  590. break;
  591. len += snprintf(buf + len, PAGE_SIZE - len, "\n");
  592. }
  593. if (len >= PAGE_SIZE) {
  594. pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
  595. len = -EFBIG;
  596. }
  597. return len;
  598. }
  599. static DEVICE_ATTR_RO(total_trans);
  600. static DEVICE_ATTR_RO(time_in_state_ms);
  601. static DEVICE_ATTR_WO(reset);
  602. static DEVICE_ATTR_RO(trans_table);
  603. static struct attribute *cooling_device_stats_attrs[] = {
  604. &dev_attr_total_trans.attr,
  605. &dev_attr_time_in_state_ms.attr,
  606. &dev_attr_reset.attr,
  607. &dev_attr_trans_table.attr,
  608. NULL
  609. };
  610. static const struct attribute_group cooling_device_stats_attr_group = {
  611. .attrs = cooling_device_stats_attrs,
  612. .name = "stats"
  613. };
  614. static void cooling_device_stats_setup(struct thermal_cooling_device *cdev)
  615. {
  616. const struct attribute_group *stats_attr_group = NULL;
  617. struct cooling_dev_stats *stats;
  618. /* Total number of states is highest state + 1 */
  619. unsigned long states = cdev->max_state + 1;
  620. int var;
  621. var = sizeof(*stats);
  622. var += sizeof(*stats->time_in_state) * states;
  623. var += sizeof(*stats->trans_table) * states * states;
  624. stats = kzalloc(var, GFP_KERNEL);
  625. if (!stats)
  626. goto out;
  627. stats->time_in_state = (ktime_t *)(stats + 1);
  628. stats->trans_table = (unsigned int *)(stats->time_in_state + states);
  629. cdev->stats = stats;
  630. stats->last_time = ktime_get();
  631. spin_lock_init(&stats->lock);
  632. stats_attr_group = &cooling_device_stats_attr_group;
  633. out:
  634. /* Fill the empty slot left in cooling_device_attr_groups */
  635. var = ARRAY_SIZE(cooling_device_attr_groups) - 2;
  636. cooling_device_attr_groups[var] = stats_attr_group;
  637. }
  638. static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev)
  639. {
  640. kfree(cdev->stats);
  641. cdev->stats = NULL;
  642. }
  643. #else
  644. static inline void
  645. cooling_device_stats_setup(struct thermal_cooling_device *cdev) {}
  646. static inline void
  647. cooling_device_stats_destroy(struct thermal_cooling_device *cdev) {}
  648. #endif /* CONFIG_THERMAL_STATISTICS */
  649. void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev)
  650. {
  651. cooling_device_stats_setup(cdev);
  652. cdev->device.groups = cooling_device_attr_groups;
  653. }
  654. void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
  655. {
  656. cooling_device_stats_destroy(cdev);
  657. }
  658. void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev)
  659. {
  660. lockdep_assert_held(&cdev->lock);
  661. cooling_device_stats_destroy(cdev);
  662. cooling_device_stats_setup(cdev);
  663. }
  664. /* these helper will be used only at the time of bindig */
  665. ssize_t
  666. trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
  667. {
  668. struct thermal_zone_device *tz = to_thermal_zone(dev);
  669. struct thermal_instance *instance;
  670. instance = container_of(attr, struct thermal_instance, attr);
  671. return sysfs_emit(buf, "%d\n", thermal_zone_trip_id(tz, instance->trip));
  672. }
  673. ssize_t
  674. weight_show(struct device *dev, struct device_attribute *attr, char *buf)
  675. {
  676. struct thermal_instance *instance;
  677. instance = container_of(attr, struct thermal_instance, weight_attr);
  678. return sysfs_emit(buf, "%d\n", instance->weight);
  679. }
  680. ssize_t weight_store(struct device *dev, struct device_attribute *attr,
  681. const char *buf, size_t count)
  682. {
  683. struct thermal_zone_device *tz = to_thermal_zone(dev);
  684. struct thermal_instance *instance;
  685. int ret, weight;
  686. ret = kstrtoint(buf, 0, &weight);
  687. if (ret)
  688. return ret;
  689. instance = container_of(attr, struct thermal_instance, weight_attr);
  690. /* Don't race with governors using the 'weight' value */
  691. guard(thermal_zone)(tz);
  692. instance->weight = weight;
  693. thermal_governor_update_tz(tz, THERMAL_INSTANCE_WEIGHT_CHANGED);
  694. return count;
  695. }