diff options
-rw-r--r-- | drivers/cpuidle/driver.c | 60 |
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 | /** | 42 | static 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 | |
46 | int cpuidle_register_driver(struct cpuidle_driver *drv) | 46 | if (!drv->power_specified) |
47 | set_power_states(drv); | ||
48 | } | ||
49 | |||
50 | static void cpuidle_set_driver(struct cpuidle_driver *drv) | ||
51 | { | ||
52 | cpuidle_curr_driver = drv; | ||
53 | } | ||
54 | |||
55 | static 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 | |||
73 | static 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 | */ | ||
86 | int 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 | } |
71 | EXPORT_SYMBOL_GPL(cpuidle_register_driver); | 96 | EXPORT_SYMBOL_GPL(cpuidle_register_driver); |
72 | 97 | ||
@@ -86,8 +111,7 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver); | |||
86 | void cpuidle_unregister_driver(struct cpuidle_driver *drv) | 111 | void 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 | } |
93 | EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); | 117 | EXPORT_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 | ||
108 | void cpuidle_driver_unref(void) | 132 | void 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 | ||