aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-18 23:28:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-18 23:28:33 -0500
commitc0f486fde3f353232c1cc2fd4d62783ac782a467 (patch)
tree600d222f6d9e975d88ab774aa9d8e5ea9109b08f /drivers/base
parent385336e321c41b5174055c0194b60c19a27cc5c5 (diff)
parent2ec1c17cadd0b994732f292d4bc49fc3a05d85a4 (diff)
Merge tag 'pm+acpi-3.19-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more ACPI and power management updates from Rafael Wysocki: "These are regression fixes (leds-gpio, ACPI backlight driver, operating performance points library, ACPI device enumeration messages, cpupower tool), other bug fixes (ACPI EC driver, ACPI device PM), some cleanups in the operating performance points (OPP) framework, continuation of CONFIG_PM_RUNTIME elimination, a couple of minor intel_pstate driver changes, a new MAINTAINERS entry for it and an ACPI fan driver change needed for better support of thermal management in user space. Specifics: - Fix a regression in leds-gpio introduced by a recent commit that inadvertently changed the name of one of the properties used by the driver (Fabio Estevam). - Fix a regression in the ACPI backlight driver introduced by a recent fix that missed one special case that had to be taken into account (Aaron Lu). - Drop the level of some new kernel messages from the ACPI core introduced by a recent commit to KERN_DEBUG which they should have used from the start and drop some other unuseful KERN_ERR messages printed by ACPI (Rafael J Wysocki). - Revert an incorrect commit modifying the cpupower tool (Prarit Bhargava). - Fix two regressions introduced by recent commits in the OPP library and clean up some existing minor issues in that code (Viresh Kumar). - Continue to replace CONFIG_PM_RUNTIME with CONFIG_PM throughout the tree (or drop it where that can be done) in order to make it possible to eliminate CONFIG_PM_RUNTIME (Rafael J Wysocki, Ulf Hansson, Ludovic Desroches). There will be one more "CONFIG_PM_RUNTIME removal" batch after this one, because some new uses of it have been introduced during the current merge window, but that should be sufficient to finally get rid of it. - Make the ACPI EC driver more robust against race conditions related to GPE handler installation failures (Lv Zheng). - Prevent the ACPI device PM core code from attempting to disable GPEs that it has not enabled which confuses ACPICA and makes it report errors unnecessarily (Rafael J Wysocki). - Add a "force" command line switch to the intel_pstate driver to make it possible to override the blacklisting of some systems in that driver if needed (Ethan Zhao). - Improve intel_pstate code documentation and add a MAINTAINERS entry for it (Kristen Carlson Accardi). - Make the ACPI fan driver create cooling device interfaces witn names that reflect the IDs of the ACPI device objects they are associated with, except for "generic" ACPI fans (PNP ID "PNP0C0B"). That's necessary for user space thermal management tools to be able to connect the fans with the parts of the system they are supposed to be cooling properly. From Srinivas Pandruvada" * tag 'pm+acpi-3.19-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (32 commits) MAINTAINERS: add entry for intel_pstate ACPI / video: update the skip case for acpi_video_device_in_dod() power / PM: Eliminate CONFIG_PM_RUNTIME NFC / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM SCSI / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM ACPI / EC: Fix unexpected ec_remove_handlers() invocations Revert "tools: cpupower: fix return checks for sysfs_get_idlestate_count()" tracing / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM x86 / PM: Replace CONFIG_PM_RUNTIME in io_apic.c PM: Remove the SET_PM_RUNTIME_PM_OPS() macro mmc: atmel-mci: use SET_RUNTIME_PM_OPS() macro PM / Kconfig: Replace PM_RUNTIME with PM in dependencies ARM / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM sound / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM phy / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM video / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM tty / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM spi: Replace CONFIG_PM_RUNTIME with CONFIG_PM ACPI / PM: Do not disable wakeup GPEs that have not been enabled ACPI / utils: Drop error messages from acpi_evaluate_reference() ...
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/opp.c78
1 files changed, 44 insertions, 34 deletions
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 2d195f3a1998..d24dd614a0bd 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -84,7 +84,11 @@ struct dev_pm_opp {
84 * 84 *
85 * This is an internal data structure maintaining the link to opps attached to 85 * This is an internal data structure maintaining the link to opps attached to
86 * a device. This structure is not meant to be shared to users as it is 86 * a device. This structure is not meant to be shared to users as it is
87 * meant for book keeping and private to OPP library 87 * meant for book keeping and private to OPP library.
88 *
89 * Because the opp structures can be used from both rcu and srcu readers, we
90 * need to wait for the grace period of both of them before freeing any
91 * resources. And so we have used kfree_rcu() from within call_srcu() handlers.
88 */ 92 */
89struct device_opp { 93struct device_opp {
90 struct list_head node; 94 struct list_head node;
@@ -382,12 +386,34 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
382} 386}
383EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); 387EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
384 388
389static struct device_opp *add_device_opp(struct device *dev)
390{
391 struct device_opp *dev_opp;
392
393 /*
394 * Allocate a new device OPP table. In the infrequent case where a new
395 * device is needed to be added, we pay this penalty.
396 */
397 dev_opp = kzalloc(sizeof(*dev_opp), GFP_KERNEL);
398 if (!dev_opp)
399 return NULL;
400
401 dev_opp->dev = dev;
402 srcu_init_notifier_head(&dev_opp->srcu_head);
403 INIT_LIST_HEAD(&dev_opp->opp_list);
404
405 /* Secure the device list modification */
406 list_add_rcu(&dev_opp->node, &dev_opp_list);
407 return dev_opp;
408}
409
385static int dev_pm_opp_add_dynamic(struct device *dev, unsigned long freq, 410static int dev_pm_opp_add_dynamic(struct device *dev, unsigned long freq,
386 unsigned long u_volt, bool dynamic) 411 unsigned long u_volt, bool dynamic)
387{ 412{
388 struct device_opp *dev_opp = NULL; 413 struct device_opp *dev_opp = NULL;
389 struct dev_pm_opp *opp, *new_opp; 414 struct dev_pm_opp *opp, *new_opp;
390 struct list_head *head; 415 struct list_head *head;
416 int ret;
391 417
392 /* allocate new OPP node */ 418 /* allocate new OPP node */
393 new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL); 419 new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
@@ -400,7 +426,6 @@ static int dev_pm_opp_add_dynamic(struct device *dev, unsigned long freq,
400 mutex_lock(&dev_opp_list_lock); 426 mutex_lock(&dev_opp_list_lock);
401 427
402 /* populate the opp table */ 428 /* populate the opp table */
403 new_opp->dev_opp = dev_opp;
404 new_opp->rate = freq; 429 new_opp->rate = freq;
405 new_opp->u_volt = u_volt; 430 new_opp->u_volt = u_volt;
406 new_opp->available = true; 431 new_opp->available = true;
@@ -409,27 +434,12 @@ static int dev_pm_opp_add_dynamic(struct device *dev, unsigned long freq,
409 /* Check for existing list for 'dev' */ 434 /* Check for existing list for 'dev' */
410 dev_opp = find_device_opp(dev); 435 dev_opp = find_device_opp(dev);
411 if (IS_ERR(dev_opp)) { 436 if (IS_ERR(dev_opp)) {
412 /* 437 dev_opp = add_device_opp(dev);
413 * Allocate a new device OPP table. In the infrequent case
414 * where a new device is needed to be added, we pay this
415 * penalty.
416 */
417 dev_opp = kzalloc(sizeof(struct device_opp), GFP_KERNEL);
418 if (!dev_opp) { 438 if (!dev_opp) {
419 mutex_unlock(&dev_opp_list_lock); 439 ret = -ENOMEM;
420 kfree(new_opp); 440 goto free_opp;
421 dev_warn(dev,
422 "%s: Unable to create device OPP structure\n",
423 __func__);
424 return -ENOMEM;
425 } 441 }
426 442
427 dev_opp->dev = dev;
428 srcu_init_notifier_head(&dev_opp->srcu_head);
429 INIT_LIST_HEAD(&dev_opp->opp_list);
430
431 /* Secure the device list modification */
432 list_add_rcu(&dev_opp->node, &dev_opp_list);
433 head = &dev_opp->opp_list; 443 head = &dev_opp->opp_list;
434 goto list_add; 444 goto list_add;
435 } 445 }
@@ -448,18 +458,17 @@ static int dev_pm_opp_add_dynamic(struct device *dev, unsigned long freq,
448 458
449 /* Duplicate OPPs ? */ 459 /* Duplicate OPPs ? */
450 if (new_opp->rate == opp->rate) { 460 if (new_opp->rate == opp->rate) {
451 int ret = opp->available && new_opp->u_volt == opp->u_volt ? 461 ret = opp->available && new_opp->u_volt == opp->u_volt ?
452 0 : -EEXIST; 462 0 : -EEXIST;
453 463
454 dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n", 464 dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
455 __func__, opp->rate, opp->u_volt, opp->available, 465 __func__, opp->rate, opp->u_volt, opp->available,
456 new_opp->rate, new_opp->u_volt, new_opp->available); 466 new_opp->rate, new_opp->u_volt, new_opp->available);
457 mutex_unlock(&dev_opp_list_lock); 467 goto free_opp;
458 kfree(new_opp);
459 return ret;
460 } 468 }
461 469
462list_add: 470list_add:
471 new_opp->dev_opp = dev_opp;
463 list_add_rcu(&new_opp->node, head); 472 list_add_rcu(&new_opp->node, head);
464 mutex_unlock(&dev_opp_list_lock); 473 mutex_unlock(&dev_opp_list_lock);
465 474
@@ -469,6 +478,11 @@ list_add:
469 */ 478 */
470 srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp); 479 srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
471 return 0; 480 return 0;
481
482free_opp:
483 mutex_unlock(&dev_opp_list_lock);
484 kfree(new_opp);
485 return ret;
472} 486}
473 487
474/** 488/**
@@ -511,10 +525,11 @@ static void kfree_device_rcu(struct rcu_head *head)
511{ 525{
512 struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head); 526 struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
513 527
514 kfree(device_opp); 528 kfree_rcu(device_opp, rcu_head);
515} 529}
516 530
517void __dev_pm_opp_remove(struct device_opp *dev_opp, struct dev_pm_opp *opp) 531static void __dev_pm_opp_remove(struct device_opp *dev_opp,
532 struct dev_pm_opp *opp)
518{ 533{
519 /* 534 /*
520 * Notify the changes in the availability of the operable 535 * Notify the changes in the availability of the operable
@@ -592,7 +607,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
592static int opp_set_availability(struct device *dev, unsigned long freq, 607static int opp_set_availability(struct device *dev, unsigned long freq,
593 bool availability_req) 608 bool availability_req)
594{ 609{
595 struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV); 610 struct device_opp *dev_opp;
596 struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); 611 struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
597 int r = 0; 612 int r = 0;
598 613
@@ -606,12 +621,7 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
606 mutex_lock(&dev_opp_list_lock); 621 mutex_lock(&dev_opp_list_lock);
607 622
608 /* Find the device_opp */ 623 /* Find the device_opp */
609 list_for_each_entry(tmp_dev_opp, &dev_opp_list, node) { 624 dev_opp = find_device_opp(dev);
610 if (dev == tmp_dev_opp->dev) {
611 dev_opp = tmp_dev_opp;
612 break;
613 }
614 }
615 if (IS_ERR(dev_opp)) { 625 if (IS_ERR(dev_opp)) {
616 r = PTR_ERR(dev_opp); 626 r = PTR_ERR(dev_opp);
617 dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); 627 dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
@@ -768,7 +778,7 @@ EXPORT_SYMBOL_GPL(of_init_opp_table);
768 */ 778 */
769void of_free_opp_table(struct device *dev) 779void of_free_opp_table(struct device *dev)
770{ 780{
771 struct device_opp *dev_opp = find_device_opp(dev); 781 struct device_opp *dev_opp;
772 struct dev_pm_opp *opp, *tmp; 782 struct dev_pm_opp *opp, *tmp;
773 783
774 /* Check for existing list for 'dev' */ 784 /* Check for existing list for 'dev' */