diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2012-12-07 17:13:36 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2012-12-07 17:13:36 -0500 |
| commit | bf58cdffac931ff387c657395742a737837b93ca (patch) | |
| tree | 8e5a16a2ece40502f700212220c23c866470d2ff /drivers/devfreq | |
| parent | 6b728f1a906976ec658827adc9c2d27608aa8517 (diff) | |
| parent | 6dcdd8e3cadd8dfcfe63d231631d70e2670970f9 (diff) | |
Merge branch 'pm-devfreq'
* pm-devfreq: (23 commits)
PM / devfreq: remove compiler error with module governors (2)
PM / devfreq: Fix return value in devfreq_remove_governor()
PM / devfreq: Fix incorrect argument in error message
PM / devfreq: missing rcu_read_lock() added for find_device_opp()
PM / devfreq: remove compiler error when a governor is module
PM / devfreq: exynos4_bus.c: Fixed an alignment of the func call args.
PM / devfreq: Add sysfs node to expose available governors
PM / devfreq: allow sysfs governor node to switch governor
PM / devfreq: governors: add GPL module license and allow module build
PM / devfreq: map devfreq drivers to governor using name
PM / devfreq: register governors with devfreq framework
PM / devfreq: provide hooks for governors to be registered
PM / devfreq: export update_devfreq
PM / devfreq: Add sysfs node for representing frequency transition information.
PM / devfreq: Add sysfs node to expose available frequencies
PM / devfreq: documentation cleanups for devfreq header
PM / devfreq: Use devm_* functions in exynos4_bus.c
PM / devfreq: make devfreq_class static
PM / devfreq: fix sscanf handling for writable sysfs entries
PM / devfreq: kernel-doc typo corrections
...
Diffstat (limited to 'drivers/devfreq')
| -rw-r--r-- | drivers/devfreq/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq.c | 917 | ||||
| -rw-r--r-- | drivers/devfreq/exynos4_bus.c | 45 | ||||
| -rw-r--r-- | drivers/devfreq/governor.h | 17 | ||||
| -rw-r--r-- | drivers/devfreq/governor_performance.c | 38 | ||||
| -rw-r--r-- | drivers/devfreq/governor_powersave.c | 38 | ||||
| -rw-r--r-- | drivers/devfreq/governor_simpleondemand.c | 55 | ||||
| -rw-r--r-- | drivers/devfreq/governor_userspace.c | 45 |
8 files changed, 835 insertions, 328 deletions
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index f6b0a6e2ea50..0f079be13305 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig | |||
| @@ -30,7 +30,7 @@ if PM_DEVFREQ | |||
| 30 | comment "DEVFREQ Governors" | 30 | comment "DEVFREQ Governors" |
| 31 | 31 | ||
| 32 | config DEVFREQ_GOV_SIMPLE_ONDEMAND | 32 | config DEVFREQ_GOV_SIMPLE_ONDEMAND |
| 33 | bool "Simple Ondemand" | 33 | tristate "Simple Ondemand" |
| 34 | help | 34 | help |
| 35 | Chooses frequency based on the recent load on the device. Works | 35 | Chooses frequency based on the recent load on the device. Works |
| 36 | similar as ONDEMAND governor of CPUFREQ does. A device with | 36 | similar as ONDEMAND governor of CPUFREQ does. A device with |
| @@ -39,7 +39,7 @@ config DEVFREQ_GOV_SIMPLE_ONDEMAND | |||
| 39 | values to the governor with data field at devfreq_add_device(). | 39 | values to the governor with data field at devfreq_add_device(). |
| 40 | 40 | ||
| 41 | config DEVFREQ_GOV_PERFORMANCE | 41 | config DEVFREQ_GOV_PERFORMANCE |
| 42 | bool "Performance" | 42 | tristate "Performance" |
| 43 | help | 43 | help |
| 44 | Sets the frequency at the maximum available frequency. | 44 | Sets the frequency at the maximum available frequency. |
| 45 | This governor always returns UINT_MAX as frequency so that | 45 | This governor always returns UINT_MAX as frequency so that |
| @@ -47,7 +47,7 @@ config DEVFREQ_GOV_PERFORMANCE | |||
| 47 | at any time. | 47 | at any time. |
| 48 | 48 | ||
| 49 | config DEVFREQ_GOV_POWERSAVE | 49 | config DEVFREQ_GOV_POWERSAVE |
| 50 | bool "Powersave" | 50 | tristate "Powersave" |
| 51 | help | 51 | help |
| 52 | Sets the frequency at the minimum available frequency. | 52 | Sets the frequency at the minimum available frequency. |
| 53 | This governor always returns 0 as frequency so that | 53 | This governor always returns 0 as frequency so that |
| @@ -55,7 +55,7 @@ config DEVFREQ_GOV_POWERSAVE | |||
| 55 | at any time. | 55 | at any time. |
| 56 | 56 | ||
| 57 | config DEVFREQ_GOV_USERSPACE | 57 | config DEVFREQ_GOV_USERSPACE |
| 58 | bool "Userspace" | 58 | tristate "Userspace" |
| 59 | help | 59 | help |
| 60 | Sets the frequency at the user specified one. | 60 | Sets the frequency at the user specified one. |
| 61 | This governor returns the user configured frequency if there | 61 | This governor returns the user configured frequency if there |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 4fa1a22c55ea..53766f39aadd 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
| @@ -27,21 +27,17 @@ | |||
| 27 | #include <linux/hrtimer.h> | 27 | #include <linux/hrtimer.h> |
| 28 | #include "governor.h" | 28 | #include "governor.h" |
| 29 | 29 | ||
| 30 | struct class *devfreq_class; | 30 | static struct class *devfreq_class; |
| 31 | 31 | ||
| 32 | /* | 32 | /* |
| 33 | * devfreq_work periodically monitors every registered device. | 33 | * devfreq core provides delayed work based load monitoring helper |
| 34 | * The minimum polling interval is one jiffy. The polling interval is | 34 | * functions. Governors can use these or can implement their own |
| 35 | * determined by the minimum polling period among all polling devfreq | 35 | * monitoring mechanism. |
| 36 | * devices. The resolution of polling interval is one jiffy. | ||
| 37 | */ | 36 | */ |
| 38 | static bool polling; | ||
| 39 | static struct workqueue_struct *devfreq_wq; | 37 | static struct workqueue_struct *devfreq_wq; |
| 40 | static struct delayed_work devfreq_work; | ||
| 41 | |||
| 42 | /* wait removing if this is to be removed */ | ||
| 43 | static struct devfreq *wait_remove_device; | ||
| 44 | 38 | ||
| 39 | /* The list of all device-devfreq governors */ | ||
| 40 | static LIST_HEAD(devfreq_governor_list); | ||
| 45 | /* The list of all device-devfreq */ | 41 | /* The list of all device-devfreq */ |
| 46 | static LIST_HEAD(devfreq_list); | 42 | static LIST_HEAD(devfreq_list); |
| 47 | static DEFINE_MUTEX(devfreq_list_lock); | 43 | static DEFINE_MUTEX(devfreq_list_lock); |
| @@ -73,6 +69,79 @@ static struct devfreq *find_device_devfreq(struct device *dev) | |||
| 73 | } | 69 | } |
| 74 | 70 | ||
| 75 | /** | 71 | /** |
| 72 | * devfreq_get_freq_level() - Lookup freq_table for the frequency | ||
| 73 | * @devfreq: the devfreq instance | ||
| 74 | * @freq: the target frequency | ||
| 75 | */ | ||
| 76 | static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) | ||
| 77 | { | ||
| 78 | int lev; | ||
| 79 | |||
| 80 | for (lev = 0; lev < devfreq->profile->max_state; lev++) | ||
| 81 | if (freq == devfreq->profile->freq_table[lev]) | ||
| 82 | return lev; | ||
| 83 | |||
| 84 | return -EINVAL; | ||
| 85 | } | ||
| 86 | |||
| 87 | /** | ||
| 88 | * devfreq_update_status() - Update statistics of devfreq behavior | ||
| 89 | * @devfreq: the devfreq instance | ||
| 90 | * @freq: the update target frequency | ||
| 91 | */ | ||
| 92 | static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) | ||
| 93 | { | ||
| 94 | int lev, prev_lev; | ||
| 95 | unsigned long cur_time; | ||
| 96 | |||
| 97 | lev = devfreq_get_freq_level(devfreq, freq); | ||
| 98 | if (lev < 0) | ||
| 99 | return lev; | ||
| 100 | |||
| 101 | cur_time = jiffies; | ||
| 102 | devfreq->time_in_state[lev] += | ||
| 103 | cur_time - devfreq->last_stat_updated; | ||
| 104 | if (freq != devfreq->previous_freq) { | ||
| 105 | prev_lev = devfreq_get_freq_level(devfreq, | ||
| 106 | devfreq->previous_freq); | ||
| 107 | devfreq->trans_table[(prev_lev * | ||
| 108 | devfreq->profile->max_state) + lev]++; | ||
| 109 | devfreq->total_trans++; | ||
| 110 | } | ||
| 111 | devfreq->last_stat_updated = cur_time; | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * find_devfreq_governor() - find devfreq governor from name | ||
| 118 | * @name: name of the governor | ||
| 119 | * | ||
| 120 | * Search the list of devfreq governors and return the matched | ||
| 121 | * governor's pointer. devfreq_list_lock should be held by the caller. | ||
| 122 | */ | ||
| 123 | static struct devfreq_governor *find_devfreq_governor(const char *name) | ||
| 124 | { | ||
| 125 | struct devfreq_governor *tmp_governor; | ||
| 126 | |||
| 127 | if (unlikely(IS_ERR_OR_NULL(name))) { | ||
| 128 | pr_err("DEVFREQ: %s: Invalid parameters\n", __func__); | ||
| 129 | return ERR_PTR(-EINVAL); | ||
| 130 | } | ||
| 131 | WARN(!mutex_is_locked(&devfreq_list_lock), | ||
| 132 | "devfreq_list_lock must be locked."); | ||
| 133 | |||
| 134 | list_for_each_entry(tmp_governor, &devfreq_governor_list, node) { | ||
| 135 | if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN)) | ||
| 136 | return tmp_governor; | ||
| 137 | } | ||
| 138 | |||
| 139 | return ERR_PTR(-ENODEV); | ||
| 140 | } | ||
| 141 | |||
| 142 | /* Load monitoring helper functions for governors use */ | ||
| 143 | |||
| 144 | /** | ||
| 76 | * update_devfreq() - Reevaluate the device and configure frequency. | 145 | * update_devfreq() - Reevaluate the device and configure frequency. |
| 77 | * @devfreq: the devfreq instance. | 146 | * @devfreq: the devfreq instance. |
| 78 | * | 147 | * |
| @@ -90,6 +159,9 @@ int update_devfreq(struct devfreq *devfreq) | |||
| 90 | return -EINVAL; | 159 | return -EINVAL; |
| 91 | } | 160 | } |
| 92 | 161 | ||
| 162 | if (!devfreq->governor) | ||
| 163 | return -EINVAL; | ||
| 164 | |||
| 93 | /* Reevaluate the proper frequency */ | 165 | /* Reevaluate the proper frequency */ |
| 94 | err = devfreq->governor->get_target_freq(devfreq, &freq); | 166 | err = devfreq->governor->get_target_freq(devfreq, &freq); |
| 95 | if (err) | 167 | if (err) |
| @@ -116,16 +188,173 @@ int update_devfreq(struct devfreq *devfreq) | |||
| 116 | if (err) | 188 | if (err) |
| 117 | return err; | 189 | return err; |
| 118 | 190 | ||
