aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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