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 12 #include "cpufreq_governor.h" 13 14 static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj) 15 { 16 return container_of(kobj, struct gov_attr_set, kobj); 17 } 18 19 static inline struct governor_attr *to_gov_attr(struct attribute *attr) 20 { 21 return container_of(attr, struct governor_attr, attr); 22 } 23 24 static ssize_t governor_show(struct kobject *kobj, struct attribute *attr, 25 char *buf) 26 { 27 struct governor_attr *gattr = to_gov_attr(attr); 28 29 return gattr->show(to_gov_attr_set(kobj), buf); 30 } 31 32 static ssize_t governor_store(struct kobject *kobj, struct attribute *attr, 33 const char *buf, size_t count) 34 { 35 struct gov_attr_set *attr_set = to_gov_attr_set(kobj); 36 struct governor_attr *gattr = to_gov_attr(attr); 37 int ret; 38 39 mutex_lock(&attr_set->update_lock); 40 ret = attr_set->usage_count ? gattr->store(attr_set, buf, count) : -EBUSY; 41 mutex_unlock(&attr_set->update_lock); 42 return ret; 43 } 44 45 const struct sysfs_ops governor_sysfs_ops = { 46 .show = governor_show, 47 .store = governor_store, 48 }; 49 EXPORT_SYMBOL_GPL(governor_sysfs_ops); 50 51 void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node) 52 { 53 INIT_LIST_HEAD(&attr_set->policy_list); 54 mutex_init(&attr_set->update_lock); 55 attr_set->usage_count = 1; 56 list_add(list_node, &attr_set->policy_list); 57 } 58 EXPORT_SYMBOL_GPL(gov_attr_set_init); 59 60 void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node) 61 { 62 mutex_lock(&attr_set->update_lock); 63 attr_set->usage_count++; 64 list_add(list_node, &attr_set->policy_list); 65 mutex_unlock(&attr_set->update_lock); 66 } 67 EXPORT_SYMBOL_GPL(gov_attr_set_get); 68 69 unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node) 70 { 71 unsigned int count; 72 73 mutex_lock(&attr_set->update_lock); 74 list_del(list_node); 75 count = --attr_set->usage_count; 76 mutex_unlock(&attr_set->update_lock); 77 if (count) 78 return count; 79 80 kobject_put(&attr_set->kobj); 81 mutex_destroy(&attr_set->update_lock); 82 return 0; 83 } 84 EXPORT_SYMBOL_GPL(gov_attr_set_put); 85