cpufreq_governor_attr_set.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Abstract code for CPUFreq governor tunable sysfs attributes.
  3. *
  4. * Copyright (C) 2016, Intel Corporation
  5. * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include "cpufreq_governor.h"
  12. static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj)
  13. {
  14. return container_of(kobj, struct gov_attr_set, kobj);
  15. }
  16. static inline struct governor_attr *to_gov_attr(struct attribute *attr)
  17. {
  18. return container_of(attr, struct governor_attr, attr);
  19. }
  20. static ssize_t governor_show(struct kobject *kobj, struct attribute *attr,
  21. char *buf)
  22. {
  23. struct governor_attr *gattr = to_gov_attr(attr);
  24. return gattr->show(to_gov_attr_set(kobj), buf);
  25. }
  26. static ssize_t governor_store(struct kobject *kobj, struct attribute *attr,
  27. const char *buf, size_t count)
  28. {
  29. struct gov_attr_set *attr_set = to_gov_attr_set(kobj);
  30. struct governor_attr *gattr = to_gov_attr(attr);
  31. int ret;
  32. mutex_lock(&attr_set->update_lock);
  33. ret = attr_set->usage_count ? gattr->store(attr_set, buf, count) : -EBUSY;
  34. mutex_unlock(&attr_set->update_lock);
  35. return ret;
  36. }
  37. const struct sysfs_ops governor_sysfs_ops = {
  38. .show = governor_show,
  39. .store = governor_store,
  40. };
  41. EXPORT_SYMBOL_GPL(governor_sysfs_ops);
  42. void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node)
  43. {
  44. INIT_LIST_HEAD(&attr_set->policy_list);
  45. mutex_init(&attr_set->update_lock);
  46. attr_set->usage_count = 1;
  47. list_add(list_node, &attr_set->policy_list);
  48. }
  49. EXPORT_SYMBOL_GPL(gov_attr_set_init);
  50. void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node)
  51. {
  52. mutex_lock(&attr_set->update_lock);
  53. attr_set->usage_count++;
  54. list_add(list_node, &attr_set->policy_list);
  55. mutex_unlock(&attr_set->update_lock);
  56. }
  57. EXPORT_SYMBOL_GPL(gov_attr_set_get);
  58. unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node)
  59. {
  60. unsigned int count;
  61. mutex_lock(&attr_set->update_lock);
  62. list_del(list_node);
  63. count = --attr_set->usage_count;
  64. mutex_unlock(&attr_set->update_lock);
  65. if (count)
  66. return count;
  67. kobject_put(&attr_set->kobj);
  68. mutex_destroy(&attr_set->update_lock);
  69. return 0;
  70. }
  71. EXPORT_SYMBOL_GPL(gov_attr_set_put);