cpuidle: prepare the cpuidle core to handle multiple drivers
[firefly-linux-kernel-4.4.55.git] / drivers / cpuidle / driver.c
index 3e5907569233c4792219166a646dfda00769f5cc..8246662f594ab9cdc1382180604e956830c4018b 100644 (file)
@@ -39,11 +39,20 @@ static void set_power_states(struct cpuidle_driver *drv)
                drv->states[i].power_usage = -1 - i;
 }
 
-/**
- * cpuidle_register_driver - registers a driver
- * @drv: the driver
- */
-int cpuidle_register_driver(struct cpuidle_driver *drv)
+static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+{
+       drv->refcnt = 0;
+
+       if (!drv->power_specified)
+               set_power_states(drv);
+}
+
+static void cpuidle_set_driver(struct cpuidle_driver *drv)
+{
+       cpuidle_curr_driver = drv;
+}
+
+static int __cpuidle_register_driver(struct cpuidle_driver *drv)
 {
        if (!drv || !drv->state_count)
                return -EINVAL;
@@ -51,22 +60,38 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
        if (cpuidle_disabled())
                return -ENODEV;
 
-       spin_lock(&cpuidle_driver_lock);
-       if (cpuidle_curr_driver) {
-               spin_unlock(&cpuidle_driver_lock);
+       if (cpuidle_get_driver())
                return -EBUSY;
-       }
 
-       if (!drv->power_specified)
-               set_power_states(drv);
+       __cpuidle_driver_init(drv);
 
-       drv->refcnt = 0;
+       cpuidle_set_driver(drv);
 
-       cpuidle_curr_driver = drv;
+       return 0;
+}
+
+static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
+{
+       if (drv != cpuidle_get_driver())
+               return;
+
+       if (!WARN_ON(drv->refcnt > 0))
+               cpuidle_set_driver(NULL);
+}
 
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+       int ret;
+
+       spin_lock(&cpuidle_driver_lock);
+       ret = __cpuidle_register_driver(drv);
        spin_unlock(&cpuidle_driver_lock);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
@@ -86,8 +111,7 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
 {
        spin_lock(&cpuidle_driver_lock);
-       if (drv == cpuidle_curr_driver && !WARN_ON(drv->refcnt > 0))
-               cpuidle_curr_driver = NULL;
+       __cpuidle_unregister_driver(drv);
        spin_unlock(&cpuidle_driver_lock);
 }
 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
@@ -98,7 +122,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
 
        spin_lock(&cpuidle_driver_lock);
 
-       drv = cpuidle_curr_driver;
+       drv = cpuidle_get_driver();
        drv->refcnt++;
 
        spin_unlock(&cpuidle_driver_lock);
@@ -107,7 +131,7 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
 
 void cpuidle_driver_unref(void)
 {
-       struct cpuidle_driver *drv = cpuidle_curr_driver;
+       struct cpuidle_driver *drv = cpuidle_get_driver();
 
        spin_lock(&cpuidle_driver_lock);