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 set_power_states(struct cpuidle_driver *drv)
  22{
  23        int i;
  24
  25        /*
  26         * cpuidle driver should set the drv->power_specified bit
  27         * before registering if the driver provides
  28         * power_usage numbers.
  29         *
  30         * If power_specified is not set,
  31         * we fill in power_usage with decreasing values as the
  32         * cpuidle code has an implicit assumption that state Cn
  33         * uses less power than C(n-1).
  34         *
  35         * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
  36         * an power value of -1.  So we use -2, -3, etc, for other
  37         * c-states.
  38         */
  39        for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
  40                drv->states[i].power_usage = -1 - i;
  41}
  42
  43/**
  44 * cpuidle_register_driver - registers a driver
  45 * @drv: the driver
  46 */
  47int cpuidle_register_driver(struct cpuidle_driver *drv)
  48{
  49        if (!drv || !drv->state_count)
  50                return -EINVAL;
  51
  52        if (cpuidle_disabled())
  53                return -ENODEV;
  54
  55        spin_lock(&cpuidle_driver_lock);
  56        if (cpuidle_curr_driver) {
  57                spin_unlock(&cpuidle_driver_lock);
  58                return -EBUSY;
  59        }
  60
  61        if (!drv->power_specified)
  62                set_power_states(drv);
  63
  64        cpuidle_curr_driver = drv;
  65
  66        spin_unlock(&cpuidle_driver_lock);
  67
  68        return 0;
  69}
  70EXPORT_SYMBOL_GPL(cpuidle_register_driver);
  71
  72/**
  73 * cpuidle_get_driver - return the current driver
  74 */
  75struct cpuidle_driver *cpuidle_get_driver(void)
  76{
  77        return cpuidle_curr_driver;
  78}
  79EXPORT_SYMBOL_GPL(cpuidle_get_driver);
  80
  81/**
  82 * cpuidle_unregister_driver - unregisters a driver
  83 * @drv: the driver
  84 */
  85void cpuidle_unregister_driver(struct cpuidle_driver *drv)
  86{
  87        if (drv != cpuidle_curr_driver) {
  88                WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
  89                        drv->name);
  90                return;
  91        }
  92
  93        spin_lock(&cpuidle_driver_lock);
  94
  95        if (!WARN_ON(cpuidle_driver_refcount > 0))
  96                cpuidle_curr_driver = NULL;
  97
  98        spin_unlock(&cpuidle_driver_lock);
  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.