linux/drivers/cpuidle/driver.c
<<
>>
Prefs
   1/*
   2 * driver.c - driver support
   3 *
   4 * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
   5 *               Shaohua Li <shaohua.li@intel.com>
   6 *               Adam Belay <abelay@novell.com>
   7 *
   8 * This code is licenced under the GPL.
   9 */
  10
  11#include <linux/mutex.h>
  12#include <linux/module.h>
  13#include <linux/cpuidle.h>
  14
  15#include "cpuidle.h"
  16
  17static struct cpuidle_driver *cpuidle_curr_driver;
  18DEFINE_SPINLOCK(cpuidle_driver_lock);
  19int cpuidle_driver_refcount;
  20
  21static void __cpuidle_register_driver(struct cpuidle_driver *drv)
  22{
  23        int i;
  24        /*
  25         * cpuidle driver should set the drv->power_specified bit
  26         * before registering if the driver provides
  27         * power_usage numbers.
  28         *
  29         * If power_specified is not set,
  30         * we fill in power_usage with decreasing values as the
  31         * cpuidle code has an implicit assumption that state Cn
  32         * uses less power than C(n-1).
  33         *
  34         * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
  35         * an power value of -1.  So we use -2, -3, etc, for other
  36         * c-states.
  37         */
  38        if (!drv->power_specified) {
  39                for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
  40                        drv->states[i].power_usage = -1 - i;
  41        }
  42}
  43
  44
  45/**
  46 * cpuidle_register_driver - registers a driver
  47 * @drv: the driver
  48 */
  49int cpuidle_register_driver(struct cpuidle_driver *drv)
  50{
  51        if (!drv || !drv->state_count)
  52                return -EINVAL;
  53
  54        if (cpuidle_disabled())
  55                return -ENODEV;
  56
  57        spin_lock(&cpuidle_driver_lock);
  58        if (cpuidle_curr_driver) {
  59                spin_unlock(&cpuidle_driver_lock);
  60                return -EBUSY;
  61        }
  62        __cpuidle_register_driver(drv);
  63        cpuidle_curr_driver = drv;
  64        spin_unlock(&cpuidle_driver_lock);
  65
  66        return 0;
  67}
  68
  69EXPORT_SYMBOL_GPL(cpuidle_register_driver);
  70
  71/**
  72 * cpuidle_get_driver - return the current driver
  73 */
  74struct cpuidle_driver *cpuidle_get_driver(void)
  75{
  76        return cpuidle_curr_driver;
  77}
  78EXPORT_SYMBOL_GPL(cpuidle_get_driver);
  79
  80/**
  81 * cpuidle_unregister_driver - unregisters a driver
  82 * @drv: the driver
  83 */
  84void cpuidle_unregister_driver(struct cpuidle_driver *drv)
  85{
  86        if (drv != cpuidle_curr_driver) {
  87                WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
  88                        drv->name);
  89                return;
  90        }
  91
  92        spin_lock(&cpuidle_driver_lock);
  93
  94        if (!WARN_ON(cpuidle_driver_refcount > 0))
  95                cpuidle_curr_driver = NULL;
  96
  97        spin_unlock(&cpuidle_driver_lock);
  98}
  99
 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}
 124
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.