aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpuidle/driver.c29
-rw-r--r--include/linux/cpuidle.h6
2 files changed, 33 insertions, 2 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 40cd3f3024df..58bf3b1ac9c4 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -16,6 +16,7 @@
16 16
17static struct cpuidle_driver *cpuidle_curr_driver; 17static struct cpuidle_driver *cpuidle_curr_driver;
18DEFINE_SPINLOCK(cpuidle_driver_lock); 18DEFINE_SPINLOCK(cpuidle_driver_lock);
19int cpuidle_driver_refcount;
19 20
20static void __cpuidle_register_driver(struct cpuidle_driver *drv) 21static void __cpuidle_register_driver(struct cpuidle_driver *drv)
21{ 22{
@@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
89 } 90 }
90 91
91 spin_lock(&cpuidle_driver_lock); 92 spin_lock(&cpuidle_driver_lock);
92 cpuidle_curr_driver = NULL; 93
94 if (!WARN_ON(cpuidle_driver_refcount > 0))
95 cpuidle_curr_driver = NULL;
96
93 spin_unlock(&cpuidle_driver_lock); 97 spin_unlock(&cpuidle_driver_lock);
94} 98}
95 99
96EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); 100EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
101
102struct cpuidle_driver *cpuidle_driver_ref(void)
103{
104 struct cpuidle_driver *drv;
105
106 spin_lock(&cpuidle_driver_lock);
107
108 drv = cpuidle_curr_driver;
109 cpuidle_driver_refcount++;
110
111 spin_unlock(&cpuidle_driver_lock);
112 return drv;
113}
114
115void cpuidle_driver_unref(void)
116{
117 spin_lock(&cpuidle_driver_lock);
118
119 if (!WARN_ON(cpuidle_driver_refcount <= 0))
120 cpuidle_driver_refcount--;
121
122 spin_unlock(&cpuidle_driver_lock);
123}
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 8570012a535a..27cfced7b57b 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -136,7 +136,9 @@ struct cpuidle_driver {
136extern void disable_cpuidle(void); 136extern void disable_cpuidle(void);
137extern int cpuidle_idle_call(void); 137extern int cpuidle_idle_call(void);
138extern int cpuidle_register_driver(struct cpuidle_driver *drv); 138extern int cpuidle_register_driver(struct cpuidle_driver *drv);
139struct cpuidle_driver *cpuidle_get_driver(void); 139extern struct cpuidle_driver *cpuidle_get_driver(void);
140extern struct cpuidle_driver *cpuidle_driver_ref(void);
141extern void cpuidle_driver_unref(void);
140extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); 142extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
141extern int cpuidle_register_device(struct cpuidle_device *dev); 143extern int cpuidle_register_device(struct cpuidle_device *dev);
142extern void cpuidle_unregister_device(struct cpuidle_device *dev); 144extern void cpuidle_unregister_device(struct cpuidle_device *dev);
@@ -157,6 +159,8 @@ static inline int cpuidle_idle_call(void) { return -ENODEV; }
157static inline int cpuidle_register_driver(struct cpuidle_driver *drv) 159static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
158{return -ENODEV; } 160{return -ENODEV; }
159static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } 161static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
162static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; }
163static inline void cpuidle_driver_unref(void) {}
160static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } 164static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
161static inline int cpuidle_register_device(struct cpuidle_device *dev) 165static inline int cpuidle_register_device(struct cpuidle_device *dev)
162{return -ENODEV; } 166{return -ENODEV; }