qos.c 18.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Devices PM QoS constraints management
 *
 * Copyright (C) 2011 Texas Instruments, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *
 * This module exposes the interface to kernel space for specifying
 * per-device PM QoS dependencies. It provides infrastructure for registration
 * of:
 *
 * Dependents on a QoS value : register requests
 * 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.
20 21 22 23 24 25
 * Watchers can register different types of notification callbacks:
 *  . a per-device notification callback using the dev_pm_qos_*_notifier API.
 *    The notification chain data is stored in the per-device constraint
 *    data struct.
 *  . a system-wide notification callback using the dev_pm_qos_*_global_notifier
 *    API. The notification chain data is stored in a static variable.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *
 * Note about the per-device constraint data struct allocation:
 * . The per-device constraints data struct ptr is tored into the device
 *    dev_pm_info.
 * . To minimize the data usage by the per-device constraints, the data struct
 *   is only allocated at the first call to dev_pm_qos_add_request.
 * . The data is later free'd when the device is removed from the system.
 *  . A global mutex protects the constraints users from the data being
 *     allocated and free'd.
 */

#include <linux/pm_qos.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/mutex.h>
42
#include <linux/export.h>
43
#include <linux/pm_runtime.h>
44

45
#include "power.h"
46 47

static DEFINE_MUTEX(dev_pm_qos_mtx);
48

49 50
static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
/**
 * __dev_pm_qos_flags - Check PM QoS flags for a given device.
 * @dev: Device to check the PM QoS flags for.
 * @mask: Flags to check against.
 *
 * This routine must be called with dev->power.lock held.
 */
enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
{
	struct dev_pm_qos *qos = dev->power.qos;
	struct pm_qos_flags *pqf;
	s32 val;

	if (!qos)
		return PM_QOS_FLAGS_UNDEFINED;

	pqf = &qos->flags;
	if (list_empty(&pqf->list))
		return PM_QOS_FLAGS_UNDEFINED;

	val = pqf->effective_flags & mask;
	if (val)
		return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;

	return PM_QOS_FLAGS_NONE;
}

/**
 * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
 * @dev: Device to check the PM QoS flags for.
 * @mask: Flags to check against.
 */
enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
{
	unsigned long irqflags;
	enum pm_qos_flags_status ret;

	spin_lock_irqsave(&dev->power.lock, irqflags);
	ret = __dev_pm_qos_flags(dev, mask);
	spin_unlock_irqrestore(&dev->power.lock, irqflags);

	return ret;
}

95
/**
96 97 98 99 100 101 102
 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
 * @dev: Device to get the PM QoS constraint value for.
 *
 * This routine must be called with dev->power.lock held.
 */
s32 __dev_pm_qos_read_value(struct device *dev)
{
103
	return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
104 105 106 107
}

/**
 * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
108 109 110 111 112
 * @dev: Device to get the PM QoS constraint value for.
 */
s32 dev_pm_qos_read_value(struct device *dev)
{
	unsigned long flags;
113
	s32 ret;
114 115

	spin_lock_irqsave(&dev->power.lock, flags);
116
	ret = __dev_pm_qos_read_value(dev);
117 118 119 120 121
	spin_unlock_irqrestore(&dev->power.lock, flags);

	return ret;
}

122 123 124 125 126
/**
 * apply_constraint - Add/modify/remove device PM QoS request.
 * @req: Constraint request to apply
 * @action: Action to perform (add/update/remove).
 * @value: Value to assign to the QoS request.
127 128 129 130 131 132
 *
 * Internal function to update the constraints list using the PM QoS core
 * code and if needed call the per-device and the global notification
 * callbacks
 */
static int apply_constraint(struct dev_pm_qos_request *req,
133
			    enum pm_qos_req_action action, s32 value)
134
{
135 136
	struct dev_pm_qos *qos = req->dev->power.qos;
	int ret;
137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
	switch(req->type) {
	case DEV_PM_QOS_LATENCY:
		ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
					   action, value);
		if (ret) {
			value = pm_qos_read_value(&qos->latency);
			blocking_notifier_call_chain(&dev_pm_notifiers,
						     (unsigned long)value,
						     req);
		}
		break;
	case DEV_PM_QOS_FLAGS:
		ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
					  action, value);
		break;
	default:
		ret = -EINVAL;
155 156 157 158
	}

	return ret;
}
159 160 161 162 163 164 165 166 167 168

/*
 * dev_pm_qos_constraints_allocate
 * @dev: device to allocate data for
 *
 * Called at the first call to add_request, for constraint data allocation
 * Must be called with the dev_pm_qos_mtx mutex held
 */
static int dev_pm_qos_constraints_allocate(struct device *dev)
{
169
	struct dev_pm_qos *qos;
170 171 172
	struct pm_qos_constraints *c;
	struct blocking_notifier_head *n;

173 174
	qos = kzalloc(sizeof(*qos), GFP_KERNEL);
	if (!qos)
175 176 177 178
		return -ENOMEM;

	n = kzalloc(sizeof(*n), GFP_KERNEL);
	if (!n) {
179
		kfree(qos);
180 181 182 183
		return -ENOMEM;
	}
	BLOCKING_INIT_NOTIFIER_HEAD(n);

184
	c = &qos->latency;
185 186 187 188 189 190
	plist_head_init(&c->list);
	c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
	c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
	c->type = PM_QOS_MIN;
	c->notifiers = n;

191 192
	INIT_LIST_HEAD(&qos->flags.list);

193
	spin_lock_irq(&dev->power.lock);
194
	dev->power.qos = qos;
195
	spin_unlock_irq(&dev->power.lock);
196 197 198 199 200

	return 0;
}

/**
201
 * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
202 203
 * @dev: target device
 *
204 205
 * Called from the device PM subsystem during device insertion under
 * device_pm_lock().
206 207 208 209
 */
void dev_pm_qos_constraints_init(struct device *dev)
{
	mutex_lock(&dev_pm_qos_mtx);
210
	dev->power.qos = NULL;
211
	dev->power.power_state = PMSG_ON;
212 213 214 215 216 217 218
	mutex_unlock(&dev_pm_qos_mtx);
}

/**
 * dev_pm_qos_constraints_destroy
 * @dev: target device
 *
219
 * Called from the device PM subsystem on device removal under device_pm_lock().
220 221 222
 */
void dev_pm_qos_constraints_destroy(struct device *dev)
{
223
	struct dev_pm_qos *qos;
224
	struct dev_pm_qos_request *req, *tmp;
225
	struct pm_qos_constraints *c;
226
	struct pm_qos_flags *f;
227

228
	/*
229 230
	 * If the device's PM QoS resume latency limit or PM QoS flags have been
	 * exposed to user space, they have to be hidden at this point.
231 232
	 */
	dev_pm_qos_hide_latency_limit(dev);
233
	dev_pm_qos_hide_flags(dev);
234

235 236
	mutex_lock(&dev_pm_qos_mtx);

237
	dev->power.power_state = PMSG_INVALID;
238 239
	qos = dev->power.qos;
	if (!qos)
240
		goto out;
241

242
	/* Flush the constraints lists for the device. */
243
	c = &qos->latency;
244
	plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
245 246 247 248 249 250
		/*
		 * Update constraints list and call the notification
		 * callbacks if needed
		 */
		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
		memset(req, 0, sizeof(*req));
251
	}
252 253 254 255
	f = &qos->flags;
	list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
		apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
		memset(req, 0, sizeof(*req));
256 257
	}

258
	spin_lock_irq(&dev->power.lock);
259
	dev->power.qos = NULL;
260 261 262
	spin_unlock_irq(&dev->power.lock);

	kfree(c->notifiers);
263
	kfree(qos);
264 265

 out:
266 267 268 269 270 271 272
	mutex_unlock(&dev_pm_qos_mtx);
}

/**
 * dev_pm_qos_add_request - inserts new qos request into the list
 * @dev: target device for the constraint
 * @req: pointer to a preallocated handle
273
 * @type: type of the request
274 275 276 277 278 279 280 281 282 283
 * @value: defines the qos request
 *
 * This function inserts a new entry in the device constraints list of
 * requested qos performance characteristics. It recomputes the aggregate
 * QoS expectations of parameters and initializes the dev_pm_qos_request
 * handle.  Caller needs to save this handle for later use in updates and
 * removal.
 *
 * Returns 1 if the aggregated constraint value has changed,
 * 0 if the aggregated constraint value has not changed,
284 285 286
 * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
 * to allocate for data structures, -ENODEV if the device has just been removed
 * from the system.
287 288 289
 *
 * Callers should ensure that the target device is not RPM_SUSPENDED before
 * using this function for requests of type DEV_PM_QOS_FLAGS.
290 291
 */
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
292
			   enum dev_pm_qos_req_type type, s32 value)
293 294 295 296 297 298
{
	int ret = 0;

	if (!dev || !req) /*guard against callers passing in null */
		return -EINVAL;

299 300
	if (WARN(dev_pm_qos_request_active(req),
		 "%s() called for already added request\n", __func__))
301 302 303 304
		return -EINVAL;

	req->dev = dev;

305
	mutex_lock(&dev_pm_qos_mtx);
306

307
	if (!dev->power.qos) {
308 309 310 311 312 313 314 315 316 317 318 319 320 321
		if (dev->power.power_state.event == PM_EVENT_INVALID) {
			/* The device has been removed from the system. */
			req->dev = NULL;
			ret = -ENODEV;
			goto out;
		} else {
			/*
			 * Allocate the constraints data on the first call to
			 * add_request, i.e. only if the data is not already
			 * allocated and if the device has not been removed.
			 */
			ret = dev_pm_qos_constraints_allocate(dev);
		}
	}
322

323 324
	if (!ret) {
		req->type = type;
325
		ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
326
	}
327

328
 out:
329
	mutex_unlock(&dev_pm_qos_mtx);
330

331 332 333 334
	return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);

335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
/**
 * __dev_pm_qos_update_request - Modify an existing device PM QoS request.
 * @req : PM QoS request to modify.
 * @new_value: New value to request.
 */
static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
				       s32 new_value)
{
	s32 curr_value;
	int ret = 0;

	if (!req->dev->power.qos)
		return -ENODEV;

	switch(req->type) {
	case DEV_PM_QOS_LATENCY:
		curr_value = req->data.pnode.prio;
		break;
	case DEV_PM_QOS_FLAGS:
		curr_value = req->data.flr.flags;
		break;
	default:
		return -EINVAL;
	}

	if (curr_value != new_value)
		ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);

	return ret;
}

366 367 368 369 370 371 372 373 374 375 376 377 378 379
/**
 * dev_pm_qos_update_request - modifies an existing qos request
 * @req : handle to list element holding a dev_pm_qos request to use
 * @new_value: defines the qos request
 *
 * Updates an existing dev PM qos request along with updating the
 * target value.
 *
 * Attempts are made to make this code callable on hot code paths.
 *
 * Returns 1 if the aggregated constraint value has changed,
 * 0 if the aggregated constraint value has not changed,
 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
 * removed from the system
380 381 382
 *
 * Callers should ensure that the target device is not RPM_SUSPENDED before
 * using this function for requests of type DEV_PM_QOS_FLAGS.
383
 */
384
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
385
{
386
	int ret;
387 388 389 390

	if (!req) /*guard against callers passing in null */
		return -EINVAL;

391 392
	if (WARN(!dev_pm_qos_request_active(req),
		 "%s() called for unknown object\n", __func__))
393 394 395
		return -EINVAL;

	mutex_lock(&dev_pm_qos_mtx);
396
	ret = __dev_pm_qos_update_request(req, new_value);
397
	mutex_unlock(&dev_pm_qos_mtx);
398

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
	return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);

/**
 * dev_pm_qos_remove_request - modifies an existing qos request
 * @req: handle to request list element
 *
 * Will remove pm qos request from the list of constraints and
 * recompute the current target value. Call this on slow code paths.
 *
 * Returns 1 if the aggregated constraint value has changed,
 * 0 if the aggregated constraint value has not changed,
 * -EINVAL in case of wrong parameters, -ENODEV if the device has been
 * removed from the system
414 415 416
 *
 * Callers should ensure that the target device is not RPM_SUSPENDED before
 * using this function for requests of type DEV_PM_QOS_FLAGS.
417 418 419 420 421 422 423 424
 */
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
{
	int ret = 0;

	if (!req) /*guard against callers passing in null */
		return -EINVAL;

425 426
	if (WARN(!dev_pm_qos_request_active(req),
		 "%s() called for unknown object\n", __func__))
427 428 429 430
		return -EINVAL;

	mutex_lock(&dev_pm_qos_mtx);

431
	if (req->dev->power.qos) {
432 433
		ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
				       PM_QOS_DEFAULT_VALUE);
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
		memset(req, 0, sizeof(*req));
	} else {
		/* Return if the device has been removed */
		ret = -ENODEV;
	}

	mutex_unlock(&dev_pm_qos_mtx);
	return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);

/**
 * dev_pm_qos_add_notifier - sets notification entry for changes to target value
 * of per-device PM QoS constraints
 *
 * @dev: target device for the constraint
 * @notifier: notifier block managed by caller.
 *
 * Will register the notifier into a notification chain that gets called
 * upon changes to the target value for the device.
454 455 456
 *
 * If the device's constraints object doesn't exist when this routine is called,
 * it will be created (or error code will be returned if that fails).
457 458 459
 */
int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
{
460
	int ret = 0;
461 462 463

	mutex_lock(&dev_pm_qos_mtx);

464
	if (!dev->power.qos)
465 466 467 468 469
		ret = dev->power.power_state.event != PM_EVENT_INVALID ?
			dev_pm_qos_constraints_allocate(dev) : -ENODEV;

	if (!ret)
		ret = blocking_notifier_chain_register(
470
				dev->power.qos->latency.notifiers, notifier);
471 472

	mutex_unlock(&dev_pm_qos_mtx);
473
	return ret;
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);

/**
 * dev_pm_qos_remove_notifier - deletes notification for changes to target value
 * of per-device PM QoS constraints
 *
 * @dev: target device for the constraint
 * @notifier: notifier block to be removed.
 *
 * Will remove the notifier from the notification chain that gets called
 * upon changes to the target value.
 */
int dev_pm_qos_remove_notifier(struct device *dev,
			       struct notifier_block *notifier)
{
	int retval = 0;

	mutex_lock(&dev_pm_qos_mtx);

494
	/* Silently return if the constraints object is not present. */
495
	if (dev->power.qos)
496
		retval = blocking_notifier_chain_unregister(
497
				dev->power.qos->latency.notifiers,
498
				notifier);
499 500 501 502 503

	mutex_unlock(&dev_pm_qos_mtx);
	return retval;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533

/**
 * dev_pm_qos_add_global_notifier - sets notification entry for changes to
 * target value of the PM QoS constraints for any device
 *
 * @notifier: notifier block managed by caller.
 *
 * Will register the notifier into a notification chain that gets called
 * upon changes to the target value for any device.
 */
int dev_pm_qos_add_global_notifier(struct notifier_block *notifier)
{
	return blocking_notifier_chain_register(&dev_pm_notifiers, notifier);
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier);

/**
 * dev_pm_qos_remove_global_notifier - deletes notification for changes to
 * target value of PM QoS constraints for any device
 *
 * @notifier: notifier block to be removed.
 *
 * Will remove the notifier from the notification chain that gets called
 * upon changes to the target value for any device.
 */
int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier)
{
	return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
}
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
534 535 536 537 538 539 540 541 542 543 544

/**
 * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor.
 * @dev: Device whose ancestor to add the request for.
 * @req: Pointer to the preallocated handle.
 * @value: Constraint latency value.
 */
int dev_pm_qos_add_ancestor_request(struct device *dev,
				    struct dev_pm_qos_request *req, s32 value)
{
	struct device *ancestor = dev->parent;
545
	int ret = -ENODEV;
546 547 548 549 550

	while (ancestor && !ancestor->power.ignore_children)
		ancestor = ancestor->parent;

	if (ancestor)
551 552
		ret = dev_pm_qos_add_request(ancestor, req,
					     DEV_PM_QOS_LATENCY, value);
553

554
	if (ret < 0)
555 556
		req->dev = NULL;

557
	return ret;
558 559
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
560 561

#ifdef CONFIG_PM_RUNTIME
562 563
static void __dev_pm_qos_drop_user_request(struct device *dev,
					   enum dev_pm_qos_req_type type)
564
{
565 566 567 568 569 570 571 572 573 574
	switch(type) {
	case DEV_PM_QOS_LATENCY:
		dev_pm_qos_remove_request(dev->power.qos->latency_req);
		dev->power.qos->latency_req = NULL;
		break;
	case DEV_PM_QOS_FLAGS:
		dev_pm_qos_remove_request(dev->power.qos->flags_req);
		dev->power.qos->flags_req = NULL;
		break;
	}
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
}

/**
 * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
 * @dev: Device whose PM QoS latency limit is to be exposed to user space.
 * @value: Initial value of the latency limit.
 */
int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
{
	struct dev_pm_qos_request *req;
	int ret;

	if (!device_is_registered(dev) || value < 0)
		return -EINVAL;

590
	if (dev->power.qos && dev->power.qos->latency_req)
591 592 593 594 595 596
		return -EEXIST;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

597
	ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
598 599 600
	if (ret < 0)
		return ret;

601 602
	dev->power.qos->latency_req = req;
	ret = pm_qos_sysfs_add_latency(dev);
603
	if (ret)
604
		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
605 606 607 608 609 610 611 612 613 614 615

	return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);

/**
 * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space.
 * @dev: Device whose PM QoS latency limit is to be hidden from user space.
 */
void dev_pm_qos_hide_latency_limit(struct device *dev)
{
616 617 618
	if (dev->power.qos && dev->power.qos->latency_req) {
		pm_qos_sysfs_remove_latency(dev);
		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
619 620 621
	}
}
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642

/**
 * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space.
 * @dev: Device whose PM QoS flags are to be exposed to user space.
 * @val: Initial values of the flags.
 */
int dev_pm_qos_expose_flags(struct device *dev, s32 val)
{
	struct dev_pm_qos_request *req;
	int ret;

	if (!device_is_registered(dev))
		return -EINVAL;

	if (dev->power.qos && dev->power.qos->flags_req)
		return -EEXIST;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

643
	pm_runtime_get_sync(dev);
644 645
	ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
	if (ret < 0)
646
		goto fail;
647 648 649 650 651 652

	dev->power.qos->flags_req = req;
	ret = pm_qos_sysfs_add_flags(dev);
	if (ret)
		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);

653 654
fail:
	pm_runtime_put(dev);
655 656 657 658 659 660 661 662 663 664 665 666
	return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);

/**
 * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
 * @dev: Device whose PM QoS flags are to be hidden from user space.
 */
void dev_pm_qos_hide_flags(struct device *dev)
{
	if (dev->power.qos && dev->power.qos->flags_req) {
		pm_qos_sysfs_remove_flags(dev);
667
		pm_runtime_get_sync(dev);
668
		__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
669
		pm_runtime_put(dev);
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
	}
}
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);

/**
 * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space.
 * @dev: Device to update the PM QoS flags request for.
 * @mask: Flags to set/clear.
 * @set: Whether to set or clear the flags (true means set).
 */
int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
{
	s32 value;
	int ret;

	if (!dev->power.qos || !dev->power.qos->flags_req)
		return -EINVAL;

	pm_runtime_get_sync(dev);
	mutex_lock(&dev_pm_qos_mtx);

	value = dev_pm_qos_requested_flags(dev);
	if (set)
		value |= mask;
	else
		value &= ~mask;

	ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);

	mutex_unlock(&dev_pm_qos_mtx);
	pm_runtime_put(dev);

	return ret;
}
704
#endif /* CONFIG_PM_RUNTIME */