Commit 728ce22b696f9f1404a74d7b2279a65933553a1b

Authored by Daniel Lezcano
Committed by Rafael J. Wysocki
1 parent f89ae89e27

cpuidle: Make cpuidle's sysfs directory dynamically allocated

The cpuidle sysfs code is designed to have a single instance of per
CPU cpuidle directory.  It is not possible to remove the sysfs entry
and create it again.  This is not a problem with the current code but
future changes will add CPU hotplug support to enable/disable the
device, so it will need to remove the sysfs entry like other
subsystems do.  That won't be possible without this change, because
the kobj is a static object which can't be reused for
kobj_init_and_add().

Add cpuidle_device_kobj to be allocated dynamically when
adding/removing a sysfs entry which is consistent with the other
cpuidle's sysfs entries.

An added benefit is that the sysfs code is now more self-contained
and the includes needed for sysfs can be moved from cpuidle.h
directly into sysfs.c so as to reduce the total number of headers
dragged along with cpuidle.h.

[rjw: Changelog]
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Showing 2 changed files with 51 additions and 19 deletions Side-by-side Diff

drivers/cpuidle/sysfs.c
... ... @@ -11,8 +11,10 @@
11 11 #include <linux/sysfs.h>
12 12 #include <linux/slab.h>
13 13 #include <linux/cpu.h>
  14 +#include <linux/completion.h>
14 15 #include <linux/capability.h>
15 16 #include <linux/device.h>
  17 +#include <linux/kobject.h>
16 18  
17 19 #include "cpuidle.h"
18 20  
19 21  
20 22  
... ... @@ -167,14 +169,27 @@
167 169 #define define_one_rw(_name, show, store) \
168 170 static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
169 171  
170   -#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
171 172 #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
172 173  
  174 +struct cpuidle_device_kobj {
  175 + struct cpuidle_device *dev;
  176 + struct completion kobj_unregister;
  177 + struct kobject kobj;
  178 +};
  179 +
  180 +static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj)
  181 +{
  182 + struct cpuidle_device_kobj *kdev =
  183 + container_of(kobj, struct cpuidle_device_kobj, kobj);
  184 +
  185 + return kdev->dev;
  186 +}
  187 +
173 188 static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr,
174 189 char *buf)
175 190 {
176 191 int ret = -EIO;
177   - struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
  192 + struct cpuidle_device *dev = to_cpuidle_device(kobj);
178 193 struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
179 194  
180 195 if (cattr->show) {
... ... @@ -189,7 +204,7 @@
189 204 const char *buf, size_t count)
190 205 {
191 206 int ret = -EIO;
192   - struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
  207 + struct cpuidle_device *dev = to_cpuidle_device(kobj);
193 208 struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
194 209  
195 210 if (cattr->store) {
196 211  
... ... @@ -207,9 +222,10 @@
207 222  
208 223 static void cpuidle_sysfs_release(struct kobject *kobj)
209 224 {
210   - struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
  225 + struct cpuidle_device_kobj *kdev =
  226 + container_of(kobj, struct cpuidle_device_kobj, kobj);
211 227  
212   - complete(&dev->kobj_unregister);
  228 + complete(&kdev->kobj_unregister);
213 229 }
214 230  
215 231 static struct kobj_type ktype_cpuidle = {
... ... @@ -377,6 +393,7 @@
377 393 {
378 394 int i, ret = -ENOMEM;
379 395 struct cpuidle_state_kobj *kobj;
  396 + struct cpuidle_device_kobj *kdev = device->kobj_dev;
380 397 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
381 398  
382 399 /* state statistics */
... ... @@ -389,7 +406,7 @@
389 406 init_completion(&kobj->kobj_unregister);
390 407  
391 408 ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
392   - &device->kobj, "state%d", i);
  409 + &kdev->kobj, "state%d", i);
393 410 if (ret) {
394 411 kfree(kobj);
395 412 goto error_state;
... ... @@ -506,6 +523,7 @@
506 523 static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
507 524 {
508 525 struct cpuidle_driver_kobj *kdrv;
  526 + struct cpuidle_device_kobj *kdev = dev->kobj_dev;
509 527 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
510 528 int ret;
511 529  
... ... @@ -517,7 +535,7 @@
517 535 init_completion(&kdrv->kobj_unregister);
518 536  
519 537 ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
520   - &dev->kobj, "driver");
  538 + &kdev->kobj, "driver");
521 539 if (ret) {
522 540 kfree(kdrv);
523 541 return ret;
524 542  
525 543  
... ... @@ -586,16 +604,28 @@
586 604 */
587 605 int cpuidle_add_sysfs(struct cpuidle_device *dev)
588 606 {
  607 + struct cpuidle_device_kobj *kdev;
589 608 struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
590 609 int error;
591 610  
592   - init_completion(&dev->kobj_unregister);
  611 + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
  612 + if (!kdev)
  613 + return -ENOMEM;
  614 + kdev->dev = dev;
  615 + dev->kobj_dev = kdev;
593 616  
594   - error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
595   - "cpuidle");
596   - if (!error)
597   - kobject_uevent(&dev->kobj, KOBJ_ADD);
598   - return error;
  617 + init_completion(&kdev->kobj_unregister);
  618 +
  619 + error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
  620 + "cpuidle");
  621 + if (error) {
  622 + kfree(kdev);
  623 + return error;
  624 + }
  625 +
  626 + kobject_uevent(&kdev->kobj, KOBJ_ADD);
  627 +
  628 + return 0;
599 629 }
600 630  
601 631 /**
... ... @@ -604,7 +634,10 @@
604 634 */
605 635 void cpuidle_remove_sysfs(struct cpuidle_device *dev)
606 636 {
607   - kobject_put(&dev->kobj);
608   - wait_for_completion(&dev->kobj_unregister);
  637 + struct cpuidle_device_kobj *kdev = dev->kobj_dev;
  638 +
  639 + kobject_put(&kdev->kobj);
  640 + wait_for_completion(&kdev->kobj_unregister);
  641 + kfree(kdev);
609 642 }
include/linux/cpuidle.h
... ... @@ -13,8 +13,6 @@
13 13  
14 14 #include <linux/percpu.h>
15 15 #include <linux/list.h>
16   -#include <linux/kobject.h>
17   -#include <linux/completion.h>
18 16 #include <linux/hrtimer.h>
19 17  
20 18 #define CPUIDLE_STATE_MAX 10
... ... @@ -61,6 +59,8 @@
61 59  
62 60 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
63 61  
  62 +struct cpuidle_device_kobj;
  63 +
64 64 struct cpuidle_device {
65 65 unsigned int registered:1;
66 66 unsigned int enabled:1;
67 67  
... ... @@ -71,9 +71,8 @@
71 71 struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
72 72 struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
73 73 struct cpuidle_driver_kobj *kobj_driver;
  74 + struct cpuidle_device_kobj *kobj_dev;
74 75 struct list_head device_list;
75   - struct kobject kobj;
76   - struct completion kobj_unregister;
77 76  
78 77 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
79 78 int safe_state_index;