thermal_sysfs.c 25 KB

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