From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: rjw@sisk.pl
Cc: linux-pm@vger.kernel.org, linaro-kernel@lists.linaro.org,
patches@linaro.org
Subject: [PATCH 4/8] cpuidle: Make cpuidle's sysfs directory dynamically allocated
Date: Wed, 12 Jun 2013 15:08:51 +0200 [thread overview]
Message-ID: <1371042535-22630-4-git-send-email-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <1371042535-22630-1-git-send-email-daniel.lezcano@linaro.org>
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 recreate it. This
is not a problem with the current code but the next patches will add the cpu
hotplug handling to enable/disable the device, thus removing the sysfs entry
like does any other subsystems. Without this patch it is not possible because
the kobj is a static object which can't be reused for kobj_init_and_add.
Create a cpuidle_device_kobj to be allocated dynamically when adding/removing
a sysfs entry. This approach is consistent with the other cpuidle's sysfs
entries.
Another benefit is the sysfs code is more encapsulated and the headers needed
for sysfs are moved from cpuidle.h into the sysfs.c file, preventing useless
header inclusions from cpuidle.h.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/cpuidle/sysfs.c | 63 ++++++++++++++++++++++++++++++++++++-----------
include/linux/cpuidle.h | 7 +++---
2 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 7d4448a..8739cc0 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -11,8 +11,10 @@
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/cpu.h>
+#include <linux/completion.h>
#include <linux/capability.h>
#include <linux/device.h>
+#include <linux/kobject.h>
#include "cpuidle.h"
@@ -167,14 +169,27 @@ struct cpuidle_attr {
#define define_one_rw(_name, show, store) \
static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store)
-#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj)
#define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr)
+struct cpuidle_device_kobj {
+ struct cpuidle_device *dev;
+ struct completion kobj_unregister;
+ struct kobject kobj;
+};
+
+static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj)
+{
+ struct cpuidle_device_kobj *kdev =
+ container_of(kobj, struct cpuidle_device_kobj, kobj);
+
+ return kdev->dev;
+}
+
static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
int ret = -EIO;
- struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+ struct cpuidle_device *dev = to_cpuidle_device(kobj);
struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
if (cattr->show) {
@@ -189,7 +204,7 @@ static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
int ret = -EIO;
- struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+ struct cpuidle_device *dev = to_cpuidle_device(kobj);
struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr);
if (cattr->store) {
@@ -207,9 +222,10 @@ static const struct sysfs_ops cpuidle_sysfs_ops = {
static void cpuidle_sysfs_release(struct kobject *kobj)
{
- struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+ struct cpuidle_device_kobj *kdev =
+ container_of(kobj, struct cpuidle_device_kobj, kobj);
- complete(&dev->kobj_unregister);
+ complete(&kdev->kobj_unregister);
}
static struct kobj_type ktype_cpuidle = {
@@ -377,6 +393,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
{
int i, ret = -ENOMEM;
struct cpuidle_state_kobj *kobj;
+ struct cpuidle_device_kobj *kdev = device->kobj_dev;
struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
/* state statistics */
@@ -389,7 +406,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
init_completion(&kobj->kobj_unregister);
ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
- &device->kobj, "state%d", i);
+ &kdev->kobj, "state%d", i);
if (ret) {
kfree(kobj);
goto error_state;
@@ -506,6 +523,7 @@ static struct kobj_type ktype_driver_cpuidle = {
static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
{
struct cpuidle_driver_kobj *kdrv;
+ struct cpuidle_device_kobj *kdev = dev->kobj_dev;
struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
int ret;
@@ -517,7 +535,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
init_completion(&kdrv->kobj_unregister);
ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
- &dev->kobj, "driver");
+ &kdev->kobj, "driver");
if (ret) {
kfree(kdrv);
return ret;
@@ -586,16 +604,28 @@ void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
*/
int cpuidle_add_sysfs(struct cpuidle_device *dev)
{
+ struct cpuidle_device_kobj *kdev;
struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
int error;
- init_completion(&dev->kobj_unregister);
+ kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+ if (!kdev)
+ return -ENOMEM;
+ kdev->dev = dev;
+ dev->kobj_dev = kdev;
+
+ init_completion(&kdev->kobj_unregister);
+
+ error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
+ "cpuidle");
+ if (error) {
+ kfree(kdev);
+ return error;
+ }
- error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
- "cpuidle");
- if (!error)
- kobject_uevent(&dev->kobj, KOBJ_ADD);
- return error;
+ kobject_uevent(&kdev->kobj, KOBJ_ADD);
+
+ return 0;
}
/**
@@ -604,6 +634,9 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
*/
void cpuidle_remove_sysfs(struct cpuidle_device *dev)
{
- kobject_put(&dev->kobj);
- wait_for_completion(&dev->kobj_unregister);
+ struct cpuidle_device_kobj *kdev = dev->kobj_dev;
+
+ kobject_put(&kdev->kobj);
+ wait_for_completion(&kdev->kobj_unregister);
+ kfree(kdev);
}
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 0bc4b74..b922db5 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -13,8 +13,6 @@
#include <linux/percpu.h>
#include <linux/list.h>
-#include <linux/kobject.h>
-#include <linux/completion.h>
#include <linux/hrtimer.h>
#define CPUIDLE_STATE_MAX 10
@@ -61,6 +59,8 @@ struct cpuidle_state {
#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
+struct cpuidle_device_kobj;
+
struct cpuidle_device {
unsigned int registered:1;
unsigned int enabled:1;
@@ -71,9 +71,8 @@ struct cpuidle_device {
struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
struct cpuidle_driver_kobj *kobj_driver;
+ struct cpuidle_device_kobj *kobj_dev;
struct list_head device_list;
- struct kobject kobj;
- struct completion kobj_unregister;
#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
int safe_state_index;
--
1.7.9.5
next prev parent reply other threads:[~2013-06-12 13:09 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-12 13:08 [PATCH 1/8] cpuidle: Remove governor module format Daniel Lezcano
2013-06-12 13:08 ` [PATCH 2/8] cpuidle: Check cpuidle_enable_device succeed Daniel Lezcano
2013-06-12 13:08 ` [PATCH 3/8] cpuidle: Fix indentation and conform to Coding Style Daniel Lezcano
2013-06-12 13:08 ` Daniel Lezcano [this message]
2013-06-12 13:08 ` [PATCH 5/8] cpuidle: Add missing forward declaration Daniel Lezcano
2013-06-12 13:08 ` [PATCH 6/8] cpuidle: Encapsulate code in __cpuidle_unregister_device Daniel Lezcano
2013-06-12 13:08 ` [PATCH 7/8] cpuidle: Add a cpuidle_device init function Daniel Lezcano
2013-06-12 13:08 ` [PATCH 8/8] cpuidle: Check the device is not already registered Daniel Lezcano
2013-06-12 22:53 ` [PATCH 1/8] cpuidle: Remove governor module format Rafael J. Wysocki
2013-06-13 11:57 ` Daniel Lezcano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1371042535-22630-4-git-send-email-daniel.lezcano@linaro.org \
--to=daniel.lezcano@linaro.org \
--cc=linaro-kernel@lists.linaro.org \
--cc=linux-pm@vger.kernel.org \
--cc=patches@linaro.org \
--cc=rjw@sisk.pl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).