Blame view
kernel/power/qos.c
13.2 KB
d82b35186 pm qos infrastruc... |
1 2 3 4 |
/* * This module exposes the interface to kernel space for specifying * QoS dependencies. It provides infrastructure for registration of: * |
ed77134bf PM QOS update |
5 |
* Dependents on a QoS value : register requests |
d82b35186 pm qos infrastruc... |
6 7 8 9 10 11 12 13 14 15 16 |
* Watchers of QoS value : get notified when target QoS value changes * * This QoS design is best effort based. Dependents register their QoS needs. * Watchers register to keep track of the current QoS needs of the system. * * There are 3 basic classes of QoS parameter: latency, timeout, throughput * each have defined units: * latency: usec * timeout: usec <-- currently not used. * throughput: kbs (kilo byte / sec) * |
ed77134bf PM QOS update |
17 |
* There are lists of pm_qos_objects each one wrapping requests, notifiers |
d82b35186 pm qos infrastruc... |
18 |
* |
ed77134bf PM QOS update |
19 |
* User mode requests on a QOS parameter register themselves to the |
d82b35186 pm qos infrastruc... |
20 21 22 |
* subsystem by opening the device node /dev/... and writing there request to * the node. As long as the process holds a file handle open to the node the * client continues to be accounted for. Upon file release the usermode |
ed77134bf PM QOS update |
23 24 |
* request is removed and a new qos target is computed. This way when the * request that the application has is cleaned up when closes the file |
d82b35186 pm qos infrastruc... |
25 26 |
* pointer or exits the pm_qos_object will get an opportunity to clean up. * |
bf1db69fb pm_qos: spelling ... |
27 |
* Mark Gross <mgross@linux.intel.com> |
d82b35186 pm qos infrastruc... |
28 |
*/ |
ed77134bf PM QOS update |
29 |
/*#define DEBUG*/ |
e8db0be12 PM QoS: Move and ... |
30 |
#include <linux/pm_qos.h> |
d82b35186 pm qos infrastruc... |
31 32 33 34 35 36 37 38 39 40 |
#include <linux/sched.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/time.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/miscdevice.h> #include <linux/string.h> #include <linux/platform_device.h> #include <linux/init.h> |
0775a60ac PM: Fix PM QOS's ... |
41 |
#include <linux/kernel.h> |
d82b35186 pm qos infrastruc... |
42 43 |
#include <linux/uaccess.h> |
6e5fdeedc kernel: Fix files... |
44 |
#include <linux/export.h> |
d82b35186 pm qos infrastruc... |
45 46 |
/* |
cc7499861 PM QoS: Minor cle... |
47 |
* locking rule: all changes to constraints or notifiers lists |
d82b35186 pm qos infrastruc... |
48 49 50 |
* or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock * held, taken with _irqsave. One lock to rule them all */ |
d82b35186 pm qos infrastruc... |
51 |
struct pm_qos_object { |
4e1779baa PM QoS: Reorganiz... |
52 |
struct pm_qos_constraints *constraints; |
d82b35186 pm qos infrastruc... |
53 54 |
struct miscdevice pm_qos_power_miscdev; char *name; |
d82b35186 pm qos infrastruc... |
55 |
}; |
5f279845f pm_qos: Reimpleme... |
56 |
static DEFINE_SPINLOCK(pm_qos_lock); |
d82b35186 pm qos infrastruc... |
57 |
static struct pm_qos_object null_pm_qos; |
4e1779baa PM QoS: Reorganiz... |
58 |
|
d82b35186 pm qos infrastruc... |
59 |
static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier); |
4e1779baa PM QoS: Reorganiz... |
60 61 |
static struct pm_qos_constraints cpu_dma_constraints = { .list = PLIST_HEAD_INIT(cpu_dma_constraints.list), |
333c5ae99 idle governor: Av... |
62 63 |
.target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE, .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE, |
5f279845f pm_qos: Reimpleme... |
64 |
.type = PM_QOS_MIN, |
4e1779baa PM QoS: Reorganiz... |
65 66 67 68 |
.notifiers = &cpu_dma_lat_notifier, }; static struct pm_qos_object cpu_dma_pm_qos = { .constraints = &cpu_dma_constraints, |
a6f05b97d PM / QoS: Set cpu... |
69 |
.name = "cpu_dma_latency", |
d82b35186 pm qos infrastruc... |
70 71 72 |
}; static BLOCKING_NOTIFIER_HEAD(network_lat_notifier); |
4e1779baa PM QoS: Reorganiz... |
73 74 |
static struct pm_qos_constraints network_lat_constraints = { .list = PLIST_HEAD_INIT(network_lat_constraints.list), |
333c5ae99 idle governor: Av... |
75 76 |
.target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, |
4e1779baa PM QoS: Reorganiz... |
77 78 79 80 81 82 |
.type = PM_QOS_MIN, .notifiers = &network_lat_notifier, }; static struct pm_qos_object network_lat_pm_qos = { .constraints = &network_lat_constraints, .name = "network_latency", |
d82b35186 pm qos infrastruc... |
83 84 85 86 |
}; static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier); |
4e1779baa PM QoS: Reorganiz... |
87 88 |
static struct pm_qos_constraints network_tput_constraints = { .list = PLIST_HEAD_INIT(network_tput_constraints.list), |
333c5ae99 idle governor: Av... |
89 90 |
.target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, |
5f279845f pm_qos: Reimpleme... |
91 |
.type = PM_QOS_MAX, |
4e1779baa PM QoS: Reorganiz... |
92 93 94 95 96 |
.notifiers = &network_throughput_notifier, }; static struct pm_qos_object network_throughput_pm_qos = { .constraints = &network_tput_constraints, .name = "network_throughput", |
d82b35186 pm qos infrastruc... |
97 98 99 100 101 102 103 104 105 |
}; static struct pm_qos_object *pm_qos_array[] = { &null_pm_qos, &cpu_dma_pm_qos, &network_lat_pm_qos, &network_throughput_pm_qos }; |
d82b35186 pm qos infrastruc... |
106 107 |
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos); |
f9b9e806a PM QoS: Make pm_q... |
108 109 |
static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos); |
d82b35186 pm qos infrastruc... |
110 111 112 113 114 |
static int pm_qos_power_open(struct inode *inode, struct file *filp); static int pm_qos_power_release(struct inode *inode, struct file *filp); static const struct file_operations pm_qos_power_fops = { .write = pm_qos_power_write, |
f9b9e806a PM QoS: Make pm_q... |
115 |
.read = pm_qos_power_read, |
d82b35186 pm qos infrastruc... |
116 117 |
.open = pm_qos_power_open, .release = pm_qos_power_release, |
6038f373a llseek: automatic... |
118 |
.llseek = noop_llseek, |
d82b35186 pm qos infrastruc... |
119 |
}; |
5f279845f pm_qos: Reimpleme... |
120 |
/* unlocked internal variant */ |
abe98ec2d PM QoS: Generaliz... |
121 |
static inline int pm_qos_get_value(struct pm_qos_constraints *c) |
d82b35186 pm qos infrastruc... |
122 |
{ |
abe98ec2d PM QoS: Generaliz... |
123 124 |
if (plist_head_empty(&c->list)) return c->default_value; |
d82b35186 pm qos infrastruc... |
125 |
|
abe98ec2d PM QoS: Generaliz... |
126 |
switch (c->type) { |
5f279845f pm_qos: Reimpleme... |
127 |
case PM_QOS_MIN: |
abe98ec2d PM QoS: Generaliz... |
128 |
return plist_first(&c->list)->prio; |
d82b35186 pm qos infrastruc... |
129 |
|
5f279845f pm_qos: Reimpleme... |
130 |
case PM_QOS_MAX: |
abe98ec2d PM QoS: Generaliz... |
131 |
return plist_last(&c->list)->prio; |
d82b35186 pm qos infrastruc... |
132 |
|
5f279845f pm_qos: Reimpleme... |
133 134 135 136 137 |
default: /* runtime check for not using enum */ BUG(); } } |
b66213cdb PM QoS: Add globa... |
138 |
s32 pm_qos_read_value(struct pm_qos_constraints *c) |
333c5ae99 idle governor: Av... |
139 |
{ |
abe98ec2d PM QoS: Generaliz... |
140 |
return c->target_value; |
333c5ae99 idle governor: Av... |
141 |
} |
abe98ec2d PM QoS: Generaliz... |
142 |
static inline void pm_qos_set_value(struct pm_qos_constraints *c, s32 value) |
333c5ae99 idle governor: Av... |
143 |
{ |
abe98ec2d PM QoS: Generaliz... |
144 |
c->target_value = value; |
333c5ae99 idle governor: Av... |
145 |
} |
abe98ec2d PM QoS: Generaliz... |
146 147 148 149 150 151 152 153 154 155 156 157 158 |
/** * pm_qos_update_target - manages the constraints list and calls the notifiers * if needed * @c: constraints data struct * @node: request to add to the list, to update or to remove * @action: action to take on the constraints list * @value: value of the request to add or update * * This function returns 1 if the aggregated constraint value has changed, 0 * otherwise. */ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, enum pm_qos_req_action action, int value) |
d82b35186 pm qos infrastruc... |
159 |
{ |
d82b35186 pm qos infrastruc... |
160 |
unsigned long flags; |
abe98ec2d PM QoS: Generaliz... |
161 |
int prev_value, curr_value, new_value; |
d82b35186 pm qos infrastruc... |
162 163 |
spin_lock_irqsave(&pm_qos_lock, flags); |
abe98ec2d PM QoS: Generaliz... |
164 165 166 167 168 169 170 171 172 173 174 |
prev_value = pm_qos_get_value(c); if (value == PM_QOS_DEFAULT_VALUE) new_value = c->default_value; else new_value = value; switch (action) { case PM_QOS_REMOVE_REQ: plist_del(node, &c->list); break; case PM_QOS_UPDATE_REQ: |
5f279845f pm_qos: Reimpleme... |
175 176 177 178 179 |
/* * to change the list, we atomically remove, reinit * with new value and add, then see if the extremal * changed */ |
abe98ec2d PM QoS: Generaliz... |
180 181 182 183 184 185 186 187 |
plist_del(node, &c->list); case PM_QOS_ADD_REQ: plist_node_init(node, new_value); plist_add(node, &c->list); break; default: /* no action */ ; |
d82b35186 pm qos infrastruc... |
188 |
} |
abe98ec2d PM QoS: Generaliz... |
189 190 191 |
curr_value = pm_qos_get_value(c); pm_qos_set_value(c, curr_value); |
d82b35186 pm qos infrastruc... |
192 |
spin_unlock_irqrestore(&pm_qos_lock, flags); |
abe98ec2d PM QoS: Generaliz... |
193 194 |
if (prev_value != curr_value) { blocking_notifier_call_chain(c->notifiers, |
5f279845f pm_qos: Reimpleme... |
195 196 |
(unsigned long)curr_value, NULL); |
abe98ec2d PM QoS: Generaliz... |
197 198 199 200 |
return 1; } else { return 0; } |
d82b35186 pm qos infrastruc... |
201 |
} |
d82b35186 pm qos infrastruc... |
202 |
/** |
ed77134bf PM QOS update |
203 |
* pm_qos_request - returns current system wide qos expectation |
d82b35186 pm qos infrastruc... |
204 205 |
* @pm_qos_class: identification of which qos value is requested * |
333c5ae99 idle governor: Av... |
206 |
* This function returns the current target value. |
d82b35186 pm qos infrastruc... |
207 |
*/ |
ed77134bf PM QOS update |
208 |
int pm_qos_request(int pm_qos_class) |
d82b35186 pm qos infrastruc... |
209 |
{ |
abe98ec2d PM QoS: Generaliz... |
210 |
return pm_qos_read_value(pm_qos_array[pm_qos_class]->constraints); |
d82b35186 pm qos infrastruc... |
211 |
} |
ed77134bf PM QOS update |
212 |
EXPORT_SYMBOL_GPL(pm_qos_request); |
d82b35186 pm qos infrastruc... |
213 |
|
cc7499861 PM QoS: Minor cle... |
214 |
int pm_qos_request_active(struct pm_qos_request *req) |
82f682514 pm_qos: Get rid o... |
215 216 217 218 |
{ return req->pm_qos_class != 0; } EXPORT_SYMBOL_GPL(pm_qos_request_active); |
d82b35186 pm qos infrastruc... |
219 |
/** |
ed77134bf PM QOS update |
220 |
* pm_qos_add_request - inserts new qos request into the list |
cc7499861 PM QoS: Minor cle... |
221 |
* @req: pointer to a preallocated handle |
25cc69ec3 PM QoS: Fix inlin... |
222 |
* @pm_qos_class: identifies which list of qos request to use |
d82b35186 pm qos infrastruc... |
223 224 225 |
* @value: defines the qos request * * This function inserts a new entry in the pm_qos_class list of requested qos |
bf1db69fb pm_qos: spelling ... |
226 |
* performance characteristics. It recomputes the aggregate QoS expectations |
cc7499861 PM QoS: Minor cle... |
227 |
* for the pm_qos_class of parameters and initializes the pm_qos_request |
25cc69ec3 PM QoS: Fix inlin... |
228 229 |
* handle. Caller needs to save this handle for later use in updates and * removal. |
d82b35186 pm qos infrastruc... |
230 |
*/ |
25cc69ec3 PM QoS: Fix inlin... |
231 |
|
cc7499861 PM QoS: Minor cle... |
232 |
void pm_qos_add_request(struct pm_qos_request *req, |
82f682514 pm_qos: Get rid o... |
233 |
int pm_qos_class, s32 value) |
d82b35186 pm qos infrastruc... |
234 |
{ |
abe98ec2d PM QoS: Generaliz... |
235 236 |
if (!req) /*guard against callers passing in null */ return; |
d82b35186 pm qos infrastruc... |
237 |
|
cc7499861 PM QoS: Minor cle... |
238 |
if (pm_qos_request_active(req)) { |
82f682514 pm_qos: Get rid o... |
239 240 241 242 |
WARN(1, KERN_ERR "pm_qos_add_request() called for already added request "); return; } |
cc7499861 PM QoS: Minor cle... |
243 |
req->pm_qos_class = pm_qos_class; |
abe98ec2d PM QoS: Generaliz... |
244 245 |
pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, &req->node, PM_QOS_ADD_REQ, value); |
d82b35186 pm qos infrastruc... |
246 |
} |
ed77134bf PM QOS update |
247 |
EXPORT_SYMBOL_GPL(pm_qos_add_request); |
d82b35186 pm qos infrastruc... |
248 249 |
/** |
ed77134bf PM QOS update |
250 |
* pm_qos_update_request - modifies an existing qos request |
cc7499861 PM QoS: Minor cle... |
251 |
* @req : handle to list element holding a pm_qos request to use |
d82b35186 pm qos infrastruc... |
252 253 |
* @value: defines the qos request * |
ed77134bf PM QOS update |
254 |
* Updates an existing qos request for the pm_qos_class of parameters along |
d82b35186 pm qos infrastruc... |
255 256 |
* with updating the target pm_qos_class value. * |
ed77134bf PM QOS update |
257 |
* Attempts are made to make this code callable on hot code paths. |
d82b35186 pm qos infrastruc... |
258 |
*/ |
cc7499861 PM QoS: Minor cle... |
259 |
void pm_qos_update_request(struct pm_qos_request *req, |
5f279845f pm_qos: Reimpleme... |
260 |
s32 new_value) |
d82b35186 pm qos infrastruc... |
261 |
{ |
cc7499861 PM QoS: Minor cle... |
262 |
if (!req) /*guard against callers passing in null */ |
5f279845f pm_qos: Reimpleme... |
263 |
return; |
cc7499861 PM QoS: Minor cle... |
264 |
if (!pm_qos_request_active(req)) { |
82f682514 pm_qos: Get rid o... |
265 266 267 268 |
WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object "); return; } |
abe98ec2d PM QoS: Generaliz... |
269 270 271 272 |
if (new_value != req->node.prio) pm_qos_update_target( pm_qos_array[req->pm_qos_class]->constraints, &req->node, PM_QOS_UPDATE_REQ, new_value); |
d82b35186 pm qos infrastruc... |
273 |
} |
ed77134bf PM QOS update |
274 |
EXPORT_SYMBOL_GPL(pm_qos_update_request); |
d82b35186 pm qos infrastruc... |
275 276 |
/** |
ed77134bf PM QOS update |
277 |
* pm_qos_remove_request - modifies an existing qos request |
cc7499861 PM QoS: Minor cle... |
278 |
* @req: handle to request list element |
d82b35186 pm qos infrastruc... |
279 |
* |
cc7499861 PM QoS: Minor cle... |
280 |
* Will remove pm qos request from the list of constraints and |
ed77134bf PM QOS update |
281 282 |
* recompute the current target value for the pm_qos_class. Call this * on slow code paths. |
d82b35186 pm qos infrastruc... |
283 |
*/ |
cc7499861 PM QoS: Minor cle... |
284 |
void pm_qos_remove_request(struct pm_qos_request *req) |
d82b35186 pm qos infrastruc... |
285 |
{ |
abe98ec2d PM QoS: Generaliz... |
286 |
if (!req) /*guard against callers passing in null */ |
ed77134bf PM QOS update |
287 288 |
return; /* silent return to keep pcm code cleaner */ |
d82b35186 pm qos infrastruc... |
289 |
|
cc7499861 PM QoS: Minor cle... |
290 |
if (!pm_qos_request_active(req)) { |
82f682514 pm_qos: Get rid o... |
291 292 293 294 |
WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object "); return; } |
abe98ec2d PM QoS: Generaliz... |
295 296 297 |
pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints, &req->node, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); |
cc7499861 PM QoS: Minor cle... |
298 |
memset(req, 0, sizeof(*req)); |
d82b35186 pm qos infrastruc... |
299 |
} |
ed77134bf PM QOS update |
300 |
EXPORT_SYMBOL_GPL(pm_qos_remove_request); |
d82b35186 pm qos infrastruc... |
301 302 303 304 305 306 307 |
/** * pm_qos_add_notifier - sets notification entry for changes to target value * @pm_qos_class: identifies which qos target changes should be notified. * @notifier: notifier block managed by caller. * * will register the notifier into a notification chain that gets called |
bf1db69fb pm_qos: spelling ... |
308 |
* upon changes to the pm_qos_class target value. |
d82b35186 pm qos infrastruc... |
309 |
*/ |
ed77134bf PM QOS update |
310 |
int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier) |
d82b35186 pm qos infrastruc... |
311 312 313 314 |
{ int retval; retval = blocking_notifier_chain_register( |
4e1779baa PM QoS: Reorganiz... |
315 316 |
pm_qos_array[pm_qos_class]->constraints->notifiers, notifier); |
d82b35186 pm qos infrastruc... |
317 318 319 320 321 322 323 324 325 326 327 |
return retval; } EXPORT_SYMBOL_GPL(pm_qos_add_notifier); /** * pm_qos_remove_notifier - deletes notification entry from chain. * @pm_qos_class: identifies which qos target changes are notified. * @notifier: notifier block to be removed. * * will remove the notifier from the notification chain that gets called |
bf1db69fb pm_qos: spelling ... |
328 |
* upon changes to the pm_qos_class target value. |
d82b35186 pm qos infrastruc... |
329 330 331 332 333 334 |
*/ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier) { int retval; retval = blocking_notifier_chain_unregister( |
4e1779baa PM QoS: Reorganiz... |
335 336 |
pm_qos_array[pm_qos_class]->constraints->notifiers, notifier); |
d82b35186 pm qos infrastruc... |
337 338 339 340 |
return retval; } EXPORT_SYMBOL_GPL(pm_qos_remove_notifier); |
4a31a3342 PM QoS: Code reor... |
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
/* User space interface to PM QoS classes via misc devices */ static int register_pm_qos_misc(struct pm_qos_object *qos) { qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR; qos->pm_qos_power_miscdev.name = qos->name; qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops; return misc_register(&qos->pm_qos_power_miscdev); } static int find_pm_qos_object_by_minor(int minor) { int pm_qos_class; for (pm_qos_class = 0; pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) { if (minor == pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor) return pm_qos_class; } return -1; } |
d82b35186 pm qos infrastruc... |
363 364 |
static int pm_qos_power_open(struct inode *inode, struct file *filp) { |
d82b35186 pm qos infrastruc... |
365 366 367 368 |
long pm_qos_class; pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); if (pm_qos_class >= 0) { |
cc7499861 PM QoS: Minor cle... |
369 |
struct pm_qos_request *req = kzalloc(sizeof(*req), GFP_KERNEL); |
82f682514 pm_qos: Get rid o... |
370 371 372 373 374 |
if (!req) return -ENOMEM; pm_qos_add_request(req, pm_qos_class, PM_QOS_DEFAULT_VALUE); filp->private_data = req; |
ed77134bf PM QOS update |
375 |
|
6513fd697 PM / QoS: Remove ... |
376 |
return 0; |
d82b35186 pm qos infrastruc... |
377 |
} |
d82b35186 pm qos infrastruc... |
378 379 380 381 382 |
return -EPERM; } static int pm_qos_power_release(struct inode *inode, struct file *filp) { |
cc7499861 PM QoS: Minor cle... |
383 |
struct pm_qos_request *req; |
d82b35186 pm qos infrastruc... |
384 |
|
82f682514 pm_qos: Get rid o... |
385 |
req = filp->private_data; |
ed77134bf PM QOS update |
386 |
pm_qos_remove_request(req); |
82f682514 pm_qos: Get rid o... |
387 |
kfree(req); |
d82b35186 pm qos infrastruc... |
388 389 390 |
return 0; } |
ed77134bf PM QOS update |
391 |
|
f9b9e806a PM QoS: Make pm_q... |
392 393 394 395 396 |
static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { s32 value; unsigned long flags; |
cc7499861 PM QoS: Minor cle... |
397 |
struct pm_qos_request *req = filp->private_data; |
f9b9e806a PM QoS: Make pm_q... |
398 |
|
cc7499861 PM QoS: Minor cle... |
399 |
if (!req) |
f9b9e806a PM QoS: Make pm_q... |
400 |
return -EINVAL; |
cc7499861 PM QoS: Minor cle... |
401 |
if (!pm_qos_request_active(req)) |
f9b9e806a PM QoS: Make pm_q... |
402 |
return -EINVAL; |
f9b9e806a PM QoS: Make pm_q... |
403 |
spin_lock_irqsave(&pm_qos_lock, flags); |
abe98ec2d PM QoS: Generaliz... |
404 |
value = pm_qos_get_value(pm_qos_array[req->pm_qos_class]->constraints); |
f9b9e806a PM QoS: Make pm_q... |
405 406 407 408 |
spin_unlock_irqrestore(&pm_qos_lock, flags); return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); } |
d82b35186 pm qos infrastruc... |
409 410 411 412 |
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { s32 value; |
cc7499861 PM QoS: Minor cle... |
413 |
struct pm_qos_request *req; |
ed77134bf PM QOS update |
414 415 416 417 |
if (count == sizeof(s32)) { if (copy_from_user(&value, buf, sizeof(s32))) return -EFAULT; |
0775a60ac PM: Fix PM QOS's ... |
418 419 420 421 422 423 |
} else if (count <= 11) { /* ASCII perhaps? */ char ascii_value[11]; unsigned long int ulval; int ret; if (copy_from_user(ascii_value, buf, count)) |
ed77134bf PM QOS update |
424 |
return -EFAULT; |
0775a60ac PM: Fix PM QOS's ... |
425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
if (count > 10) { if (ascii_value[10] == ' ') ascii_value[10] = '\0'; else return -EINVAL; } else { ascii_value[count] = '\0'; } ret = strict_strtoul(ascii_value, 16, &ulval); if (ret) { pr_debug("%s, 0x%lx, 0x%x ", ascii_value, ulval, ret); |
ed77134bf PM QOS update |
439 |
return -EINVAL; |
0775a60ac PM: Fix PM QOS's ... |
440 441 442 |
} value = (s32)lower_32_bits(ulval); } else { |
d82b35186 pm qos infrastruc... |
443 |
return -EINVAL; |
0775a60ac PM: Fix PM QOS's ... |
444 |
} |
d82b35186 pm qos infrastruc... |
445 |
|
cc7499861 PM QoS: Minor cle... |
446 447 |
req = filp->private_data; pm_qos_update_request(req, value); |
ed77134bf PM QOS update |
448 449 |
return count; |
d82b35186 pm qos infrastruc... |
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
} static int __init pm_qos_power_init(void) { int ret = 0; ret = register_pm_qos_misc(&cpu_dma_pm_qos); if (ret < 0) { printk(KERN_ERR "pm_qos_param: cpu_dma_latency setup failed "); return ret; } ret = register_pm_qos_misc(&network_lat_pm_qos); if (ret < 0) { printk(KERN_ERR "pm_qos_param: network_latency setup failed "); return ret; } ret = register_pm_qos_misc(&network_throughput_pm_qos); if (ret < 0) printk(KERN_ERR "pm_qos_param: network_throughput setup failed "); return ret; } late_initcall(pm_qos_power_init); |