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