resend the three patches per Len's request. No real change except adding
patch description and diffstat.

Fix the cpuidle sysfs issue.
a. make kobject dynamicaly allocated
b. fixed sysfs init issue to avoid suspend/resume issue

Signed-off-by: Shaohua Li <[EMAIL PROTECTED]>
---
 drivers/acpi/processor_idle.c |    2 -
 drivers/cpuidle/cpuidle.c     |   29 ++++++++++++++++-----
 drivers/cpuidle/sysfs.c       |   57 +++++++++++++++++++++++++++++++++---------
 include/linux/cpuidle.h       |   13 +++++----
 4 files changed, 76 insertions(+), 25 deletions(-)

Index: 21-rc6-mm1/drivers/acpi/processor_idle.c
===================================================================
--- 21-rc6-mm1.orig/drivers/acpi/processor_idle.c       2007-04-26 
10:03:49.000000000 +0800
+++ 21-rc6-mm1/drivers/acpi/processor_idle.c    2007-04-26 10:05:55.000000000 
+0800
@@ -624,7 +624,7 @@ int acpi_processor_cst_has_changed(struc
                return -ENODEV;
 
        acpi_processor_get_power_info(pr);
-       return cpuidle_force_redetect(&per_cpu(cpuidle_devices, pr->id));
+       return cpuidle_force_redetect(per_cpu(cpuidle_devices, pr->id));
 }
 
 /* proc interface */
Index: 21-rc6-mm1/drivers/cpuidle/cpuidle.c
===================================================================
--- 21-rc6-mm1.orig/drivers/cpuidle/cpuidle.c   2007-04-26 10:03:49.000000000 
+0800
+++ 21-rc6-mm1/drivers/cpuidle/cpuidle.c        2007-04-26 10:05:55.000000000 
+0800
@@ -18,7 +18,7 @@
 
 #include "cpuidle.h"
 
-DEFINE_PER_CPU(struct cpuidle_device, cpuidle_devices);
+DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
 EXPORT_PER_CPU_SYMBOL_GPL(cpuidle_devices);
 
 DEFINE_MUTEX(cpuidle_lock);
@@ -34,13 +34,13 @@ static void (*pm_idle_old)(void);
  */
 static void cpuidle_idle_call(void)
 {
-       struct cpuidle_device *dev = &__get_cpu_var(cpuidle_devices);
+       struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
 
        struct cpuidle_state *target_state;
        int next_state;
 
        /* check if the device is ready */
-       if (dev->status != CPUIDLE_STATUS_DOIDLE) {
+       if (!dev || dev->status != CPUIDLE_STATUS_DOIDLE) {
                if (pm_idle_old)
                        pm_idle_old();
                return;
@@ -117,19 +117,32 @@ static int cpuidle_add_device(struct sys
        int cpu = sys_dev->id;
        struct cpuidle_device *dev;
 
-       dev = &per_cpu(cpuidle_devices, cpu);
+       dev = per_cpu(cpuidle_devices, cpu);
 
-       dev->cpu = cpu;
        mutex_lock(&cpuidle_lock);
        if (cpu_is_offline(cpu)) {
                mutex_unlock(&cpuidle_lock);
                return 0;
        }
 
+       if (!dev) {
+               dev = kzalloc(sizeof(struct cpuidle_device), GFP_KERNEL);
+               if (!dev) {
+                       mutex_unlock(&cpuidle_lock);
+                       return -ENOMEM;
+               }
+               init_completion(&dev->kobj_unregister);
+               per_cpu(cpuidle_devices, cpu) = dev;
+       }
+       dev->cpu = cpu;
+
        if (dev->status & CPUIDLE_STATUS_DETECTED) {
                mutex_unlock(&cpuidle_lock);
                return 0;
        }
+
+       cpuidle_add_sysfs(sys_dev);
+
        if (cpuidle_curr_driver) {
                if (cpuidle_attach_driver(dev))
                        goto err_ret;
@@ -146,7 +159,6 @@ static int cpuidle_add_device(struct sys
                cpuidle_install_idle_handler();
 
        list_add(&dev->device_list, &cpuidle_detected_devices);
-       cpuidle_add_sysfs(sys_dev);
        dev->status |= CPUIDLE_STATUS_DETECTED;
 
 err_ret:
@@ -165,7 +177,7 @@ static int __cpuidle_remove_device(struc
 {
        struct cpuidle_device *dev;
 
-       dev = &per_cpu(cpuidle_devices, sys_dev->id);
+       dev = per_cpu(cpuidle_devices, sys_dev->id);
 
        if (!(dev->status & CPUIDLE_STATUS_DETECTED)) {
                return 0;
@@ -178,6 +190,9 @@ static int __cpuidle_remove_device(struc
                cpuidle_detach_driver(dev);
        cpuidle_remove_sysfs(sys_dev);
        list_del(&dev->device_list);
+       wait_for_completion(&dev->kobj_unregister);
+       per_cpu(cpuidle_devices, sys_dev->id) = NULL;
+       kfree(dev);
 
        return 0;
 }
Index: 21-rc6-mm1/drivers/cpuidle/sysfs.c
===================================================================
--- 21-rc6-mm1.orig/drivers/cpuidle/sysfs.c     2007-04-26 10:03:49.000000000 
+0800
+++ 21-rc6-mm1/drivers/cpuidle/sysfs.c  2007-04-26 10:05:55.000000000 +0800
@@ -210,8 +210,16 @@ static struct sysfs_ops cpuidle_sysfs_op
        .store = cpuidle_store,
 };
 
+static void cpuidle_sysfs_release(struct kobject *kobj)
+{
+       struct cpuidle_device *dev = kobj_to_cpuidledev(kobj);
+
+       complete(&dev->kobj_unregister);
+}
+
 static struct kobj_type ktype_cpuidle = {
        .sysfs_ops = &cpuidle_sysfs_ops,
+       .release = cpuidle_sysfs_release,
 };
 
 struct cpuidle_state_attr {
@@ -246,7 +254,8 @@ static struct attribute *cpuidle_state_d
        NULL
 };
 
-#define kobj_to_state(k) container_of(k, struct cpuidle_state, kobj)
+#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
+#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
 static ssize_t cpuidle_state_show(struct kobject * kobj,
        struct attribute * attr ,char * buf)
@@ -265,11 +274,27 @@ static struct sysfs_ops cpuidle_state_sy
        .show = cpuidle_state_show,
 };
 
+static void cpuidle_state_sysfs_release(struct kobject *kobj)
+{
+       struct cpuidle_state_kobj *state_obj = kobj_to_state_obj(kobj);
+
+       complete(&state_obj->kobj_unregister);
+}
+
 static struct kobj_type ktype_state_cpuidle = {
        .sysfs_ops = &cpuidle_state_sysfs_ops,
        .default_attrs = cpuidle_state_default_attrs,
+       .release = cpuidle_state_sysfs_release,
 };
 
+static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int 
i)
+{
+       kobject_unregister(&device->kobjs[i]->kobj);
+       wait_for_completion(&device->kobjs[i]->kobj_unregister);
+       kfree(device->kobjs[i]);
+       device->kobjs[i] = NULL;
+}
+
 /**
  * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
  * @device: the target device
@@ -277,24 +302,32 @@ static struct kobj_type ktype_state_cpui
 int cpuidle_add_driver_sysfs(struct cpuidle_device *device)
 {
        int i, ret;
-       struct cpuidle_state *state;
+       struct cpuidle_state_kobj *kobj;
 
        /* state statistics */
        for (i = 0; i < device->state_count; i++) {
-               state = &device->states[i];
-               state->kobj.parent = &device->kobj;
-               state->kobj.ktype = &ktype_state_cpuidle;
-               kobject_set_name(&state->kobj, "state%d", i);
-               ret = kobject_register(&state->kobj);
-               if (ret)
+               kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
+               if (!kobj)
+                       goto error_state;
+               kobj->state = &device->states[i];
+               init_completion(&kobj->kobj_unregister);
+
+               kobj->kobj.parent = &device->kobj;
+               kobj->kobj.ktype = &ktype_state_cpuidle;
+               kobject_set_name(&kobj->kobj, "state%d", i);
+               ret = kobject_register(&kobj->kobj);
+               if (ret) {
+                       kfree(kobj);
                        goto error_state;
+               }
+               device->kobjs[i] = kobj;
        }
 
        return 0;
 
 error_state:
        for (i = i - 1; i >= 0; i--)
-               kobject_unregister(&device->states[i].kobj);
+               cpuidle_free_state_kobj(device, i);
        return ret;
 }
 
@@ -307,7 +340,7 @@ void cpuidle_remove_driver_sysfs(struct 
        int i;
 
        for (i = 0; i < device->state_count; i++)
-               kobject_unregister(&device->states[i].kobj);
+               cpuidle_free_state_kobj(device, i);
 }
 
 /**
@@ -319,7 +352,7 @@ int cpuidle_add_sysfs(struct sys_device 
        int cpu = sysdev->id;
        struct cpuidle_device *dev;
 
-       dev = &per_cpu(cpuidle_devices, cpu);
+       dev = per_cpu(cpuidle_devices, cpu);
        dev->kobj.parent = &sysdev->kobj;
        dev->kobj.ktype = &ktype_cpuidle;
        kobject_set_name(&dev->kobj, "%s", "cpuidle");
@@ -335,6 +368,6 @@ void cpuidle_remove_sysfs(struct sys_dev
        int cpu = sysdev->id;
        struct cpuidle_device *dev;
 
-       dev = &per_cpu(cpuidle_devices, cpu);
+       dev = per_cpu(cpuidle_devices, cpu);
        kobject_unregister(&dev->kobj);
 }
Index: 21-rc6-mm1/include/linux/cpuidle.h
===================================================================
--- 21-rc6-mm1.orig/include/linux/cpuidle.h     2007-04-26 10:03:49.000000000 
+0800
+++ 21-rc6-mm1/include/linux/cpuidle.h  2007-04-26 10:05:55.000000000 +0800
@@ -41,8 +41,6 @@ struct cpuidle_state {
 
        int (*enter)    (struct cpuidle_device *dev,
                         struct cpuidle_state *state);
-
-       struct kobject  kobj;
 };
 
 /* Idle State Flags */
@@ -74,6 +72,12 @@ cpuidle_set_statedata(struct cpuidle_sta
        state->driver_data = data;
 }
 
+struct cpuidle_state_kobj {
+       struct cpuidle_state *state;
+       struct completion kobj_unregister;
+       struct kobject kobj;
+};
+
 struct cpuidle_device {
        unsigned int            status;
        int                     cpu;
@@ -81,6 +85,7 @@ struct cpuidle_device {
        int                     last_residency;
        int                     state_count;
        struct cpuidle_state    states[CPUIDLE_STATE_MAX];
+       struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
        struct cpuidle_state    *last_state;
 
        struct list_head        device_list;
@@ -89,9 +94,7 @@ struct cpuidle_device {
        void                    *governor_data;
 };
 
-#define to_cpuidle_device(n) container_of(n, struct cpuidle_device, kobj);
-
-DECLARE_PER_CPU(struct cpuidle_device, cpuidle_devices);
+DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
 
 /* Device Status Flags */
 #define CPUIDLE_STATUS_DETECTED                 (0x1)
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to