^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * sysfs.c - sysfs support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (C) 2006-2007 Shaohua Li <shaohua.li@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This code is licenced under the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/cpuidle.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "cpuidle.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static ssize_t show_available_governors(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) ssize_t i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct cpuidle_governor *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) mutex_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) list_for_each_entry(tmp, &cpuidle_governors, governor_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (i >= (ssize_t) (PAGE_SIZE - (CPUIDLE_NAME_LEN + 2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) i += scnprintf(&buf[i], CPUIDLE_NAME_LEN + 1, "%s ", tmp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) i+= sprintf(&buf[i], "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) mutex_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static ssize_t show_current_driver(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct cpuidle_driver *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) spin_lock(&cpuidle_driver_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) drv = cpuidle_get_driver();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ret = sprintf(buf, "%s\n", drv->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ret = sprintf(buf, "none\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) spin_unlock(&cpuidle_driver_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static ssize_t show_current_governor(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mutex_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (cpuidle_curr_governor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ret = sprintf(buf, "%s\n", cpuidle_curr_governor->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = sprintf(buf, "none\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mutex_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static ssize_t store_current_governor(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) char gov_name[CPUIDLE_NAME_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct cpuidle_governor *gov;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ret = sscanf(buf, "%" __stringify(CPUIDLE_NAME_LEN) "s", gov_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (ret != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) mutex_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) list_for_each_entry(gov, &cpuidle_governors, governor_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!strncmp(gov->name, gov_name, CPUIDLE_NAME_LEN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ret = cpuidle_switch_governor(gov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mutex_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static DEVICE_ATTR(available_governors, 0444, show_available_governors, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static DEVICE_ATTR(current_driver, 0444, show_current_driver, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static DEVICE_ATTR(current_governor, 0644, show_current_governor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) store_current_governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static DEVICE_ATTR(current_governor_ro, 0444, show_current_governor, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static struct attribute *cpuidle_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) &dev_attr_available_governors.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) &dev_attr_current_driver.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) &dev_attr_current_governor.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) &dev_attr_current_governor_ro.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static struct attribute_group cpuidle_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .attrs = cpuidle_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .name = "cpuidle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * cpuidle_add_interface - add CPU global sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @dev: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int cpuidle_add_interface(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return sysfs_create_group(&dev->kobj, &cpuidle_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * cpuidle_remove_interface - remove CPU global sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @dev: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) void cpuidle_remove_interface(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) sysfs_remove_group(&dev->kobj, &cpuidle_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct cpuidle_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ssize_t (*show)(struct cpuidle_device *, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ssize_t (*store)(struct cpuidle_device *, const char *, size_t count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct cpuidle_device_kobj {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct cpuidle_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct completion kobj_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct kobject kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct cpuidle_device_kobj *kdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) container_of(kobj, struct cpuidle_device_kobj, kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return kdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct cpuidle_device *dev = to_cpuidle_device(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (cattr->show) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mutex_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ret = cattr->show(dev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mutex_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct cpuidle_device *dev = to_cpuidle_device(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (cattr->store) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) mutex_lock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ret = cattr->store(dev, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) mutex_unlock(&cpuidle_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static const struct sysfs_ops cpuidle_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .show = cpuidle_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .store = cpuidle_store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void cpuidle_sysfs_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct cpuidle_device_kobj *kdev =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) container_of(kobj, struct cpuidle_device_kobj, kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) complete(&kdev->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static struct kobj_type ktype_cpuidle = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .sysfs_ops = &cpuidle_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .release = cpuidle_sysfs_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct cpuidle_state_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ssize_t (*show)(struct cpuidle_state *, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct cpuidle_state_usage *, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ssize_t (*store)(struct cpuidle_state *, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct cpuidle_state_usage *, const char *, size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #define define_one_state_ro(_name, show) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #define define_one_state_rw(_name, show, store) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0644, show, store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define define_show_state_function(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static ssize_t show_state_##_name(struct cpuidle_state *state, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct cpuidle_state_usage *state_usage, char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return sprintf(buf, "%u\n", state->_name);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define define_show_state_ull_function(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static ssize_t show_state_##_name(struct cpuidle_state *state, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct cpuidle_state_usage *state_usage, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return sprintf(buf, "%llu\n", state_usage->_name);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #define define_show_state_str_function(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static ssize_t show_state_##_name(struct cpuidle_state *state, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct cpuidle_state_usage *state_usage, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (state->_name[0] == '\0')\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return sprintf(buf, "<null>\n");\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return sprintf(buf, "%s\n", state->_name);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define define_show_state_time_function(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static ssize_t show_state_##_name(struct cpuidle_state *state, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct cpuidle_state_usage *state_usage, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return sprintf(buf, "%llu\n", ktime_to_us(state->_name##_ns)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) define_show_state_time_function(exit_latency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) define_show_state_time_function(target_residency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) define_show_state_function(power_usage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) define_show_state_ull_function(usage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) define_show_state_ull_function(rejected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) define_show_state_str_function(name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) define_show_state_str_function(desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) define_show_state_ull_function(above)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) define_show_state_ull_function(below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static ssize_t show_state_time(struct cpuidle_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct cpuidle_state_usage *state_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return sprintf(buf, "%llu\n", ktime_to_us(state_usage->time_ns));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static ssize_t show_state_disable(struct cpuidle_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct cpuidle_state_usage *state_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return sprintf(buf, "%llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) state_usage->disable & CPUIDLE_STATE_DISABLED_BY_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static ssize_t store_state_disable(struct cpuidle_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct cpuidle_state_usage *state_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) err = kstrtouint(buf, 0, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) state_usage->disable |= CPUIDLE_STATE_DISABLED_BY_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) state_usage->disable &= ~CPUIDLE_STATE_DISABLED_BY_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static ssize_t show_state_default_status(struct cpuidle_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct cpuidle_state_usage *state_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return sprintf(buf, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) state->flags & CPUIDLE_FLAG_OFF ? "disabled" : "enabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) define_one_state_ro(name, show_state_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) define_one_state_ro(desc, show_state_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) define_one_state_ro(latency, show_state_exit_latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) define_one_state_ro(residency, show_state_target_residency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) define_one_state_ro(power, show_state_power_usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) define_one_state_ro(usage, show_state_usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) define_one_state_ro(rejected, show_state_rejected);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) define_one_state_ro(time, show_state_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) define_one_state_rw(disable, show_state_disable, store_state_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) define_one_state_ro(above, show_state_above);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) define_one_state_ro(below, show_state_below);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) define_one_state_ro(default_status, show_state_default_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static struct attribute *cpuidle_state_default_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) &attr_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) &attr_desc.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) &attr_latency.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) &attr_residency.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) &attr_power.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) &attr_usage.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) &attr_rejected.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) &attr_time.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) &attr_disable.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) &attr_above.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) &attr_below.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) &attr_default_status.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct cpuidle_state_kobj {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct cpuidle_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct cpuidle_state_usage *state_usage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct completion kobj_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct kobject kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct cpuidle_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) #ifdef CONFIG_SUSPEND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #define define_show_state_s2idle_ull_function(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static ssize_t show_state_s2idle_##_name(struct cpuidle_state *state, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct cpuidle_state_usage *state_usage, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return sprintf(buf, "%llu\n", state_usage->s2idle_##_name);\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) define_show_state_s2idle_ull_function(usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) define_show_state_s2idle_ull_function(time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #define define_one_state_s2idle_ro(_name, show) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static struct cpuidle_state_attr attr_s2idle_##_name = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) __ATTR(_name, 0444, show, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) define_one_state_s2idle_ro(usage, show_state_s2idle_usage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) define_one_state_s2idle_ro(time, show_state_s2idle_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static struct attribute *cpuidle_state_s2idle_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) &attr_s2idle_usage.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) &attr_s2idle_time.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static const struct attribute_group cpuidle_state_s2idle_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .name = "s2idle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .attrs = cpuidle_state_s2idle_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!kobj->state->enter_s2idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = sysfs_create_group(&kobj->kobj, &cpuidle_state_s2idle_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) pr_debug("%s: sysfs attribute group not created\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (kobj->state->enter_s2idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) sysfs_remove_group(&kobj->kobj, &cpuidle_state_s2idle_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static inline void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) #endif /* CONFIG_SUSPEND */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) #define kobj_to_device(k) (kobj_to_state_obj(k)->device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct cpuidle_state *state = kobj_to_state(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (cattr->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ret = cattr->show(state, state_usage, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) int ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct cpuidle_state *state = kobj_to_state(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct cpuidle_device *dev = kobj_to_device(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (cattr->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ret = cattr->store(state, state_usage, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* reset poll time cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dev->poll_limit_ns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static const struct sysfs_ops cpuidle_state_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .show = cpuidle_state_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .store = cpuidle_state_store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void cpuidle_state_sysfs_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct cpuidle_state_kobj *state_obj = kobj_to_state_obj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) complete(&state_obj->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static struct kobj_type ktype_state_cpuidle = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) .sysfs_ops = &cpuidle_state_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) .default_attrs = cpuidle_state_default_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .release = cpuidle_state_sysfs_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) cpuidle_remove_s2idle_attr_group(device->kobjs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) kobject_put(&device->kobjs[i]->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) wait_for_completion(&device->kobjs[i]->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) kfree(device->kobjs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) device->kobjs[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * cpuidle_add_state_sysfs - adds cpuidle states sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * @device: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int i, ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct cpuidle_state_kobj *kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct cpuidle_device_kobj *kdev = device->kobj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* state statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) for (i = 0; i < drv->state_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!kobj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) goto error_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) kobj->state = &drv->states[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) kobj->state_usage = &device->states_usage[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) kobj->device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) init_completion(&kobj->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) &kdev->kobj, "state%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) kobject_put(&kobj->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) kfree(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto error_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) cpuidle_add_s2idle_attr_group(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) kobject_uevent(&kobj->kobj, KOBJ_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) device->kobjs[i] = kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) error_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) for (i = i - 1; i >= 0; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) cpuidle_free_state_kobj(device, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * cpuidle_remove_driver_sysfs - removes the cpuidle states sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * @device: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) for (i = 0; i < drv->state_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) cpuidle_free_state_kobj(device, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #define kobj_to_driver_kobj(k) container_of(k, struct cpuidle_driver_kobj, kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) #define attr_to_driver_attr(a) container_of(a, struct cpuidle_driver_attr, attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) #define define_one_driver_ro(_name, show) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static struct cpuidle_driver_attr attr_driver_##_name = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) __ATTR(_name, 0444, show, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct cpuidle_driver_kobj {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) struct cpuidle_driver *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct completion kobj_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) struct kobject kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct cpuidle_driver_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ssize_t (*show)(struct cpuidle_driver *, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ssize_t (*store)(struct cpuidle_driver *, const char *, size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static ssize_t show_driver_name(struct cpuidle_driver *drv, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) spin_lock(&cpuidle_driver_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ret = sprintf(buf, "%s\n", drv ? drv->name : "none");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) spin_unlock(&cpuidle_driver_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static void cpuidle_driver_sysfs_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) complete(&driver_kobj->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) int ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (dattr->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = dattr->show(driver_kobj->drv, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static ssize_t cpuidle_driver_store(struct kobject *kobj, struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (dattr->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ret = dattr->store(driver_kobj->drv, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) define_one_driver_ro(name, show_driver_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static const struct sysfs_ops cpuidle_driver_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .show = cpuidle_driver_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .store = cpuidle_driver_store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) static struct attribute *cpuidle_driver_default_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) &attr_driver_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static struct kobj_type ktype_driver_cpuidle = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .sysfs_ops = &cpuidle_driver_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) .default_attrs = cpuidle_driver_default_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) .release = cpuidle_driver_sysfs_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * cpuidle_add_driver_sysfs - adds the driver name sysfs attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * @dev: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct cpuidle_driver_kobj *kdrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct cpuidle_device_kobj *kdev = dev->kobj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) kdrv = kzalloc(sizeof(*kdrv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (!kdrv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) kdrv->drv = drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) init_completion(&kdrv->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) &kdev->kobj, "driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) kobject_put(&kdrv->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) kfree(kdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) kobject_uevent(&kdrv->kobj, KOBJ_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) dev->kobj_driver = kdrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * cpuidle_remove_driver_sysfs - removes the driver name sysfs attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * @dev: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct cpuidle_driver_kobj *kdrv = dev->kobj_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) kobject_put(&kdrv->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) wait_for_completion(&kdrv->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) kfree(kdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static inline int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static inline void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * cpuidle_add_device_sysfs - adds device specific sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * @device: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) int cpuidle_add_device_sysfs(struct cpuidle_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ret = cpuidle_add_state_sysfs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ret = cpuidle_add_driver_sysfs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) cpuidle_remove_state_sysfs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * cpuidle_remove_device_sysfs : removes device specific sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * @device : the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) cpuidle_remove_driver_sysfs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cpuidle_remove_state_sysfs(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * cpuidle_add_sysfs - creates a sysfs instance for the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @dev: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) int cpuidle_add_sysfs(struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) struct cpuidle_device_kobj *kdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * Return if cpu_device is not setup for this CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * This could happen if the arch did not set up cpu_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * since this CPU is not in cpu_present mask and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * driver did not send a correct CPU mask during registration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * Without this check we would end up passing bogus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * value for &cpu_dev->kobj in kobject_init_and_add()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!cpu_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (!kdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) kdev->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) init_completion(&kdev->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) "cpuidle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) kobject_put(&kdev->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) kfree(kdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) dev->kobj_dev = kdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) kobject_uevent(&kdev->kobj, KOBJ_ADD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * cpuidle_remove_sysfs - deletes a sysfs instance on the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * @dev: the target device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) void cpuidle_remove_sysfs(struct cpuidle_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct cpuidle_device_kobj *kdev = dev->kobj_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) kobject_put(&kdev->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) wait_for_completion(&kdev->kobj_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) kfree(kdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }