cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sysfs.c (19491B)


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