Blame view

kernel/pm_qos_params.c 12.4 KB
d82b35186   Mark Gross   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   Mark Gross   PM QOS update
5
   * Dependents on a QoS value : register requests
d82b35186   Mark Gross   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   Mark Gross   PM QOS update
17
   * There are lists of pm_qos_objects each one wrapping requests, notifiers
d82b35186   Mark Gross   pm qos infrastruc...
18
   *
ed77134bf   Mark Gross   PM QOS update
19
   * User mode requests on a QOS parameter register themselves to the
d82b35186   Mark Gross   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   Mark Gross   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   Mark Gross   pm qos infrastruc...
25
26
   * pointer or exits the pm_qos_object will get an opportunity to clean up.
   *
bf1db69fb   Richard Hughes   pm_qos: spelling ...
27
   * Mark Gross <mgross@linux.intel.com>
d82b35186   Mark Gross   pm qos infrastruc...
28
   */
ed77134bf   Mark Gross   PM QOS update
29
  /*#define DEBUG*/
d82b35186   Mark Gross   pm qos infrastruc...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  #include <linux/pm_qos_params.h>
  #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>
  
  #include <linux/uaccess.h>
  
  /*
ed77134bf   Mark Gross   PM QOS update
45
   * locking rule: all changes to requests or notifiers lists
d82b35186   Mark Gross   pm qos infrastruc...
46
47
48
   * 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
   */
5f279845f   James Bottomley   pm_qos: Reimpleme...
49
50
51
52
  enum pm_qos_type {
  	PM_QOS_MAX,		/* return the largest value */
  	PM_QOS_MIN		/* return the smallest value */
  };
d82b35186   Mark Gross   pm qos infrastruc...
53
54
  
  struct pm_qos_object {
5f279845f   James Bottomley   pm_qos: Reimpleme...
55
  	struct plist_head requests;
d82b35186   Mark Gross   pm qos infrastruc...
56
57
58
59
  	struct blocking_notifier_head *notifiers;
  	struct miscdevice pm_qos_power_miscdev;
  	char *name;
  	s32 default_value;
5f279845f   James Bottomley   pm_qos: Reimpleme...
60
  	enum pm_qos_type type;
d82b35186   Mark Gross   pm qos infrastruc...
61
  };
5f279845f   James Bottomley   pm_qos: Reimpleme...
62
  static DEFINE_SPINLOCK(pm_qos_lock);
d82b35186   Mark Gross   pm qos infrastruc...
63
64
65
  static struct pm_qos_object null_pm_qos;
  static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
  static struct pm_qos_object cpu_dma_pm_qos = {
5f279845f   James Bottomley   pm_qos: Reimpleme...
66
  	.requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests, pm_qos_lock),
d82b35186   Mark Gross   pm qos infrastruc...
67
68
69
  	.notifiers = &cpu_dma_lat_notifier,
  	.name = "cpu_dma_latency",
  	.default_value = 2000 * USEC_PER_SEC,
5f279845f   James Bottomley   pm_qos: Reimpleme...
70
  	.type = PM_QOS_MIN,
d82b35186   Mark Gross   pm qos infrastruc...
71
72
73
74
  };
  
  static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
  static struct pm_qos_object network_lat_pm_qos = {
5f279845f   James Bottomley   pm_qos: Reimpleme...
75
  	.requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests, pm_qos_lock),
d82b35186   Mark Gross   pm qos infrastruc...
76
77
78
  	.notifiers = &network_lat_notifier,
  	.name = "network_latency",
  	.default_value = 2000 * USEC_PER_SEC,
5f279845f   James Bottomley   pm_qos: Reimpleme...
79
  	.type = PM_QOS_MIN
d82b35186   Mark Gross   pm qos infrastruc...
80
81
82
83
84
  };
  
  
  static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
  static struct pm_qos_object network_throughput_pm_qos = {
5f279845f   James Bottomley   pm_qos: Reimpleme...
85
  	.requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests, pm_qos_lock),
d82b35186   Mark Gross   pm qos infrastruc...
86
87
88
  	.notifiers = &network_throughput_notifier,
  	.name = "network_throughput",
  	.default_value = 0,
5f279845f   James Bottomley   pm_qos: Reimpleme...
89
  	.type = PM_QOS_MAX,
d82b35186   Mark Gross   pm qos infrastruc...
90
91
92
93
94
95
96
97
98
  };
  
  
  static struct pm_qos_object *pm_qos_array[] = {
  	&null_pm_qos,
  	&cpu_dma_pm_qos,
  	&network_lat_pm_qos,
  	&network_throughput_pm_qos
  };
d82b35186   Mark Gross   pm qos infrastruc...
99
100
  static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
  		size_t count, loff_t *f_pos);
f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
101
102
  static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
  		size_t count, loff_t *f_pos);
d82b35186   Mark Gross   pm qos infrastruc...
103
104
105
106
107
  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   Thomas Renninger   PM QoS: Make pm_q...
108
  	.read = pm_qos_power_read,
d82b35186   Mark Gross   pm qos infrastruc...
109
110
  	.open = pm_qos_power_open,
  	.release = pm_qos_power_release,
6038f373a   Arnd Bergmann   llseek: automatic...
111
  	.llseek = noop_llseek,
d82b35186   Mark Gross   pm qos infrastruc...
112
  };
5f279845f   James Bottomley   pm_qos: Reimpleme...
113
114
  /* unlocked internal variant */
  static inline int pm_qos_get_value(struct pm_qos_object *o)
d82b35186   Mark Gross   pm qos infrastruc...
115
  {
5f279845f   James Bottomley   pm_qos: Reimpleme...
116
117
  	if (plist_head_empty(&o->requests))
  		return o->default_value;
d82b35186   Mark Gross   pm qos infrastruc...
118

5f279845f   James Bottomley   pm_qos: Reimpleme...
119
120
  	switch (o->type) {
  	case PM_QOS_MIN:
00fafcda1   Colin Cross   PM / PM QoS: Fix ...
121
  		return plist_first(&o->requests)->prio;
d82b35186   Mark Gross   pm qos infrastruc...
122

5f279845f   James Bottomley   pm_qos: Reimpleme...
123
  	case PM_QOS_MAX:
00fafcda1   Colin Cross   PM / PM QoS: Fix ...
124
  		return plist_last(&o->requests)->prio;
d82b35186   Mark Gross   pm qos infrastruc...
125

5f279845f   James Bottomley   pm_qos: Reimpleme...
126
127
128
129
130
131
132
133
  	default:
  		/* runtime check for not using enum */
  		BUG();
  	}
  }
  
  static void update_target(struct pm_qos_object *o, struct plist_node *node,
  			  int del, int value)
d82b35186   Mark Gross   pm qos infrastruc...
134
  {
d82b35186   Mark Gross   pm qos infrastruc...
135
  	unsigned long flags;
5f279845f   James Bottomley   pm_qos: Reimpleme...
136
  	int prev_value, curr_value;
d82b35186   Mark Gross   pm qos infrastruc...
137
138
  
  	spin_lock_irqsave(&pm_qos_lock, flags);
5f279845f   James Bottomley   pm_qos: Reimpleme...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  	prev_value = pm_qos_get_value(o);
  	/* PM_QOS_DEFAULT_VALUE is a signal that the value is unchanged */
  	if (value != PM_QOS_DEFAULT_VALUE) {
  		/*
  		 * to change the list, we atomically remove, reinit
  		 * with new value and add, then see if the extremal
  		 * changed
  		 */
  		plist_del(node, &o->requests);
  		plist_node_init(node, value);
  		plist_add(node, &o->requests);
  	} else if (del) {
  		plist_del(node, &o->requests);
  	} else {
  		plist_add(node, &o->requests);
d82b35186   Mark Gross   pm qos infrastruc...
154
  	}
5f279845f   James Bottomley   pm_qos: Reimpleme...
155
  	curr_value = pm_qos_get_value(o);
d82b35186   Mark Gross   pm qos infrastruc...
156
  	spin_unlock_irqrestore(&pm_qos_lock, flags);
5f279845f   James Bottomley   pm_qos: Reimpleme...
157
158
159
160
  	if (prev_value != curr_value)
  		blocking_notifier_call_chain(o->notifiers,
  					     (unsigned long)curr_value,
  					     NULL);
d82b35186   Mark Gross   pm qos infrastruc...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  }
  
  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;
  }
  
  /**
ed77134bf   Mark Gross   PM QOS update
186
   * pm_qos_request - returns current system wide qos expectation
d82b35186   Mark Gross   pm qos infrastruc...
187
188
189
190
   * @pm_qos_class: identification of which qos value is requested
   *
   * This function returns the current target value in an atomic manner.
   */
ed77134bf   Mark Gross   PM QOS update
191
  int pm_qos_request(int pm_qos_class)
d82b35186   Mark Gross   pm qos infrastruc...
192
  {
5f279845f   James Bottomley   pm_qos: Reimpleme...
193
194
195
196
197
198
199
200
  	unsigned long flags;
  	int value;
  
  	spin_lock_irqsave(&pm_qos_lock, flags);
  	value = pm_qos_get_value(pm_qos_array[pm_qos_class]);
  	spin_unlock_irqrestore(&pm_qos_lock, flags);
  
  	return value;
d82b35186   Mark Gross   pm qos infrastruc...
201
  }
ed77134bf   Mark Gross   PM QOS update
202
  EXPORT_SYMBOL_GPL(pm_qos_request);
d82b35186   Mark Gross   pm qos infrastruc...
203

82f682514   James Bottomley   pm_qos: Get rid o...
204
205
206
207
208
  int pm_qos_request_active(struct pm_qos_request_list *req)
  {
  	return req->pm_qos_class != 0;
  }
  EXPORT_SYMBOL_GPL(pm_qos_request_active);
d82b35186   Mark Gross   pm qos infrastruc...
209
  /**
ed77134bf   Mark Gross   PM QOS update
210
   * pm_qos_add_request - inserts new qos request into the list
25cc69ec3   Saravana Kannan   PM QoS: Fix inlin...
211
212
   * @dep: pointer to a preallocated handle
   * @pm_qos_class: identifies which list of qos request to use
d82b35186   Mark Gross   pm qos infrastruc...
213
214
215
   * @value: defines the qos request
   *
   * This function inserts a new entry in the pm_qos_class list of requested qos
bf1db69fb   Richard Hughes   pm_qos: spelling ...
216
   * performance characteristics.  It recomputes the aggregate QoS expectations
25cc69ec3   Saravana Kannan   PM QoS: Fix inlin...
217
218
219
   * for the pm_qos_class of parameters and initializes the pm_qos_request_list
   * handle.  Caller needs to save this handle for later use in updates and
   * removal.
d82b35186   Mark Gross   pm qos infrastruc...
220
   */
25cc69ec3   Saravana Kannan   PM QoS: Fix inlin...
221

82f682514   James Bottomley   pm_qos: Get rid o...
222
223
  void pm_qos_add_request(struct pm_qos_request_list *dep,
  			int pm_qos_class, s32 value)
d82b35186   Mark Gross   pm qos infrastruc...
224
  {
82f682514   James Bottomley   pm_qos: Get rid o...
225
226
  	struct pm_qos_object *o =  pm_qos_array[pm_qos_class];
  	int new_value;
d82b35186   Mark Gross   pm qos infrastruc...
227

82f682514   James Bottomley   pm_qos: Get rid o...
228
229
230
231
232
233
234
235
236
237
238
239
  	if (pm_qos_request_active(dep)) {
  		WARN(1, KERN_ERR "pm_qos_add_request() called for already added request
  ");
  		return;
  	}
  	if (value == PM_QOS_DEFAULT_VALUE)
  		new_value = o->default_value;
  	else
  		new_value = value;
  	plist_node_init(&dep->list, new_value);
  	dep->pm_qos_class = pm_qos_class;
  	update_target(o, &dep->list, 0, PM_QOS_DEFAULT_VALUE);
d82b35186   Mark Gross   pm qos infrastruc...
240
  }
ed77134bf   Mark Gross   PM QOS update
241
  EXPORT_SYMBOL_GPL(pm_qos_add_request);
d82b35186   Mark Gross   pm qos infrastruc...
242
243
  
  /**
ed77134bf   Mark Gross   PM QOS update
244
245
   * pm_qos_update_request - modifies an existing qos request
   * @pm_qos_req : handle to list element holding a pm_qos request to use
d82b35186   Mark Gross   pm qos infrastruc...
246
247
   * @value: defines the qos request
   *
ed77134bf   Mark Gross   PM QOS update
248
   * Updates an existing qos request for the pm_qos_class of parameters along
d82b35186   Mark Gross   pm qos infrastruc...
249
250
   * with updating the target pm_qos_class value.
   *
ed77134bf   Mark Gross   PM QOS update
251
   * Attempts are made to make this code callable on hot code paths.
d82b35186   Mark Gross   pm qos infrastruc...
252
   */
ed77134bf   Mark Gross   PM QOS update
253
  void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
5f279845f   James Bottomley   pm_qos: Reimpleme...
254
  			   s32 new_value)
d82b35186   Mark Gross   pm qos infrastruc...
255
  {
ed77134bf   Mark Gross   PM QOS update
256
  	s32 temp;
5f279845f   James Bottomley   pm_qos: Reimpleme...
257
  	struct pm_qos_object *o;
d82b35186   Mark Gross   pm qos infrastruc...
258

5f279845f   James Bottomley   pm_qos: Reimpleme...
259
260
  	if (!pm_qos_req) /*guard against callers passing in null */
  		return;
82f682514   James Bottomley   pm_qos: Get rid o...
261
262
263
264
265
  	if (!pm_qos_request_active(pm_qos_req)) {
  		WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object
  ");
  		return;
  	}
5f279845f   James Bottomley   pm_qos: Reimpleme...
266
267
268
269
270
271
272
273
274
  	o = pm_qos_array[pm_qos_req->pm_qos_class];
  
  	if (new_value == PM_QOS_DEFAULT_VALUE)
  		temp = o->default_value;
  	else
  		temp = new_value;
  
  	if (temp != pm_qos_req->list.prio)
  		update_target(o, &pm_qos_req->list, 0, temp);
d82b35186   Mark Gross   pm qos infrastruc...
275
  }
ed77134bf   Mark Gross   PM QOS update
276
  EXPORT_SYMBOL_GPL(pm_qos_update_request);
d82b35186   Mark Gross   pm qos infrastruc...
277
278
  
  /**
ed77134bf   Mark Gross   PM QOS update
279
280
   * pm_qos_remove_request - modifies an existing qos request
   * @pm_qos_req: handle to request list element
d82b35186   Mark Gross   pm qos infrastruc...
281
   *
ed77134bf   Mark Gross   PM QOS update
282
283
284
   * Will remove pm qos request from the list of requests and
   * recompute the current target value for the pm_qos_class.  Call this
   * on slow code paths.
d82b35186   Mark Gross   pm qos infrastruc...
285
   */
ed77134bf   Mark Gross   PM QOS update
286
  void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
d82b35186   Mark Gross   pm qos infrastruc...
287
  {
5f279845f   James Bottomley   pm_qos: Reimpleme...
288
  	struct pm_qos_object *o;
ed77134bf   Mark Gross   PM QOS update
289
290
291
292
  
  	if (pm_qos_req == NULL)
  		return;
  		/* silent return to keep pcm code cleaner */
d82b35186   Mark Gross   pm qos infrastruc...
293

82f682514   James Bottomley   pm_qos: Get rid o...
294
295
296
297
298
  	if (!pm_qos_request_active(pm_qos_req)) {
  		WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object
  ");
  		return;
  	}
5f279845f   James Bottomley   pm_qos: Reimpleme...
299
300
  	o = pm_qos_array[pm_qos_req->pm_qos_class];
  	update_target(o, &pm_qos_req->list, 1, PM_QOS_DEFAULT_VALUE);
82f682514   James Bottomley   pm_qos: Get rid o...
301
  	memset(pm_qos_req, 0, sizeof(*pm_qos_req));
d82b35186   Mark Gross   pm qos infrastruc...
302
  }
ed77134bf   Mark Gross   PM QOS update
303
  EXPORT_SYMBOL_GPL(pm_qos_remove_request);
d82b35186   Mark Gross   pm qos infrastruc...
304
305
306
307
308
309
310
  
  /**
   * 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   Richard Hughes   pm_qos: spelling ...
311
   * upon changes to the pm_qos_class target value.
d82b35186   Mark Gross   pm qos infrastruc...
312
   */
ed77134bf   Mark Gross   PM QOS update
313
  int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
d82b35186   Mark Gross   pm qos infrastruc...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  {
  	int retval;
  
  	retval = blocking_notifier_chain_register(
  			pm_qos_array[pm_qos_class]->notifiers, notifier);
  
  	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   Richard Hughes   pm_qos: spelling ...
330
   * upon changes to the pm_qos_class target value.
d82b35186   Mark Gross   pm qos infrastruc...
331
332
333
334
335
336
337
338
339
340
341
   */
  int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
  {
  	int retval;
  
  	retval = blocking_notifier_chain_unregister(
  			pm_qos_array[pm_qos_class]->notifiers, notifier);
  
  	return retval;
  }
  EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
d82b35186   Mark Gross   pm qos infrastruc...
342
343
  static int pm_qos_power_open(struct inode *inode, struct file *filp)
  {
d82b35186   Mark Gross   pm qos infrastruc...
344
345
346
347
  	long pm_qos_class;
  
  	pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
  	if (pm_qos_class >= 0) {
bac1e74db   David Alan Gilbert   PM QoS: Fix kzall...
348
                 struct pm_qos_request_list *req = kzalloc(sizeof(*req), GFP_KERNEL);
82f682514   James Bottomley   pm_qos: Get rid o...
349
350
351
352
353
  		if (!req)
  			return -ENOMEM;
  
  		pm_qos_add_request(req, pm_qos_class, PM_QOS_DEFAULT_VALUE);
  		filp->private_data = req;
ed77134bf   Mark Gross   PM QOS update
354
355
  
  		if (filp->private_data)
d82b35186   Mark Gross   pm qos infrastruc...
356
357
  			return 0;
  	}
d82b35186   Mark Gross   pm qos infrastruc...
358
359
360
361
362
  	return -EPERM;
  }
  
  static int pm_qos_power_release(struct inode *inode, struct file *filp)
  {
ed77134bf   Mark Gross   PM QOS update
363
  	struct pm_qos_request_list *req;
d82b35186   Mark Gross   pm qos infrastruc...
364

82f682514   James Bottomley   pm_qos: Get rid o...
365
  	req = filp->private_data;
ed77134bf   Mark Gross   PM QOS update
366
  	pm_qos_remove_request(req);
82f682514   James Bottomley   pm_qos: Get rid o...
367
  	kfree(req);
d82b35186   Mark Gross   pm qos infrastruc...
368
369
370
  
  	return 0;
  }
ed77134bf   Mark Gross   PM QOS update
371

f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
372
373
374
375
376
377
  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;
  	struct pm_qos_object *o;
6eab04a87   Justin P. Mattock   treewide: remove ...
378
  	struct pm_qos_request_list *pm_qos_req = filp->private_data;
f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
379
380
381
382
383
384
385
386
387
388
389
390
391
  
  	if (!pm_qos_req)
  		return -EINVAL;
  	if (!pm_qos_request_active(pm_qos_req))
  		return -EINVAL;
  
  	o = pm_qos_array[pm_qos_req->pm_qos_class];
  	spin_lock_irqsave(&pm_qos_lock, flags);
  	value = pm_qos_get_value(o);
  	spin_unlock_irqrestore(&pm_qos_lock, flags);
  
  	return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
  }
d82b35186   Mark Gross   pm qos infrastruc...
392
393
394
395
  static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
  		size_t count, loff_t *f_pos)
  {
  	s32 value;
ed77134bf   Mark Gross   PM QOS update
396
397
398
399
400
401
402
403
404
405
  	int x;
  	char ascii_value[11];
  	struct pm_qos_request_list *pm_qos_req;
  
  	if (count == sizeof(s32)) {
  		if (copy_from_user(&value, buf, sizeof(s32)))
  			return -EFAULT;
  	} else if (count == 11) { /* len('0x12345678/0') */
  		if (copy_from_user(ascii_value, buf, 11))
  			return -EFAULT;
0109c2c48   mark gross   PM QoS: Correct p...
406
407
  		if (strlen(ascii_value) != 10)
  			return -EINVAL;
ed77134bf   Mark Gross   PM QOS update
408
409
410
  		x = sscanf(ascii_value, "%x", &value);
  		if (x != 1)
  			return -EINVAL;
0109c2c48   mark gross   PM QoS: Correct p...
411
412
  		pr_debug("%s, %d, 0x%x
  ", ascii_value, x, value);
ed77134bf   Mark Gross   PM QOS update
413
  	} else
d82b35186   Mark Gross   pm qos infrastruc...
414
  		return -EINVAL;
d82b35186   Mark Gross   pm qos infrastruc...
415

99a51792d   Joe Perches   kernel/pm_qos_par...
416
  	pm_qos_req = filp->private_data;
ed77134bf   Mark Gross   PM QOS update
417
418
419
  	pm_qos_update_request(pm_qos_req, value);
  
  	return count;
d82b35186   Mark Gross   pm qos infrastruc...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
  }
  
  
  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);