aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/driver.c
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2012-10-31 12:44:47 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-14 18:34:22 -0500
commit13dd52f11a04e616900f565d6a1e5138e58d579f (patch)
treee7ce9521c4dbd93d0be9c7acaa1ceb7b7269e1db /drivers/cpuidle/driver.c
parent41682032715c2c969357c81391a442a24dd1c2c2 (diff)
cpuidle: prepare the cpuidle core to handle multiple drivers
This patch is a preparation for the multiple cpuidle drivers support. As the next patch will introduce the multiple drivers with the Kconfig option and we want to keep the code clean and understandable, this patch defines a set of functions for encapsulating some common parts and splits what should be done under a lock from the rest. [rjw: Modified the subject and changelog slightly.] Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpuidle/driver.c')
-rw-r--r--drivers/cpuidle/driver.c60
1 files changed, 42 insertions, 18 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 3e5907569233..8246662f594a 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -39,11 +39,20 @@ static void set_power_states(struct cpuidle_driver *drv)
39 drv->states[i].power_usage = -1 - i; 39 drv->states[i].power_usage = -1 - i;
40} 40}
41 41
42/** 42static void __cpuidle_driver_init(struct cpuidle_driver *drv)
43 * cpuidle_register_driver - registers a driver 43{
44 * @drv: the driver 44 drv->refcnt = 0;
45 */ 45
46int cpuidle_register_driver(struct cpuidle_driver *drv) 46 if (!drv->power_specified)
47 set_power_states(drv);
48}
49
50static void cpuidle_set_driver(struct cpuidle_driver *drv)
51{
52 cpuidle_curr_driver = drv;
53}
54
55static int __cpuidle_register_driver(struct cpuidle_driver *drv)
47{ 56{
48 if (!drv || !drv->state_count) 57 if (!drv || !drv->state_count)
49 return -EINVAL; 58 return -EINVAL;
@@ -51,22 +60,38 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
51 if (cpuidle_disabled()) 60 if (cpuidle_disabled())
52 return -ENODEV; 61 return -ENODEV;
53 62
54 spin_lock(&cpuidle_driver_lock); 63 if (cpuidle_get_driver())
55 if (cpuidle_curr_driver) {
56 spin_unlock(&cpuidle_driver_lock);
57 return -EBUSY; 64 return -EBUSY;
58 }
59 65
60 if (!drv->power_specified) 66 __cpuidle_driver_init(drv);
61 set_power_states(drv);
62 67
63 drv->refcnt = 0; 68 cpuidle_set_driver(drv);
64 69
65 cpuidle_curr_driver = drv; 70 return 0;
71}
72
73static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
74{
75 if (drv != cpuidle_get_driver())
76 return;
77
78 if (!WARN_ON(drv->refcnt > 0))
79 cpuidle_set_driver(NULL);
80}
66 81
82/**
83 * cpuidle_register_driver - registers a driver
84 * @drv: the driver
85 */
86int cpuidle_register_driver(struct cpuidle_driver *drv)
87{
88 int ret;
89
90 spin_lock(&cpuidle_driver_lock);
91 ret = __cpuidle_register_driver(drv);
67 spin_unlock(&cpuidle_driver_lock); 92 spin_unlock(&cpuidle_driver_lock);
68 93
69 return 0; 94 return ret;
70} 95}
71EXPORT_SYMBOL_GPL(cpuidle_register_driver); 96EXPORT_SYMBOL_GPL(cpuidle_register_driver);
72 97
@@ -86,8 +111,7 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
86void cpuidle_unregister_driver(struct cpuidle_driver *drv) 111void cpuidle_unregister_driver(struct cpuidle_driver *drv)
87{ 112{
88 spin_lock(&cpuidle_driver_lock); 113 spin_lock(&cpuidle_driver_lock);
89 if (drv == cpuidle_curr_driver && !WARN_ON(drv->refcnt > 0)) 114 __cpuidle_unregister_driver(drv);
90 cpuidle_curr_driver = NULL;
91 spin_unlock(&cpuidle_driver_lock); 115 spin_unlock(&cpuidle_driver_lock);
92} 116}
93EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); 117EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
@@ -98,7 +122,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
98 122
99 spin_lock(&cpuidle_driver_lock); 123 spin_lock(&cpuidle_driver_lock);
100 124
101 drv = cpuidle_curr_driver; 125 drv = cpuidle_get_driver();
102 drv->refcnt++; 126 drv->refcnt++;
103 127
104 spin_unlock(&cpuidle_driver_lock); 128 spin_unlock(&cpuidle_driver_lock);
@@ -107,7 +131,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
107 131
108void cpuidle_driver_unref(void) 132void cpuidle_driver_unref(void)
109{ 133{
110 struct cpuidle_driver *drv = cpuidle_curr_driver; 134 struct cpuidle_driver *drv = cpuidle_get_driver();
111 135
112 spin_lock(&cpuidle_driver_lock); 136 spin_lock(&cpuidle_driver_lock);
113 137