thermal_sysfs.c 24 KB

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