thermal_sysfs.c 22 KB

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