Commit 78646f62dbaba99ab0ae50afbe8c2d1876cb4d33

Authored by Linus Torvalds

Merge tag 'pm+acpi-3.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI and power management fixes from Rafael Wysocki:
 "These are three regression fixes, two recent (generic power domains,
  suspend-to-idle) and one older (cpufreq), an ACPI blacklist entry for
  one more machine having problems with Windows 8 compatibility, a minor
  cpufreq driver fix (cpufreq-dt) and a fixup for new callback
  definitions (generic power domains).

  Specifics:

   - Fix a crash in the suspend-to-idle code path introduced by a recent
     commit that forgot to check a pointer against NULL before
     dereferencing it (Dmitry Eremin-Solenikov).

   - Fix a boot crash on Exynos5 introduced by a recent commit making
     that platform use generic Device Tree bindings for power domains
     which exposed a weakness in the generic power domains framework
     leading to that crash (Ulf Hansson).

   - Fix a crash during system resume on systems where cpufreq depends
     on Operation Performance Points (OPP) for functionality, but
     CONFIG_OPP is not set.  This leads the cpufreq driver registration
     to fail, but the resume code attempts to restore the pre-suspend
     cpufreq configuration (which does not exist) nevertheless and
     crashes.  From Geert Uytterhoeven.

   - Add a new ACPI blacklist entry for Dell Vostro 3546 that has
     problems if it is reported as Windows 8 compatible to the BIOS
     (Adam Lee).

   - Fix swapped arguments in an error message in the cpufreq-dt driver
     (Abhilash Kesavan).

   - Fix up the prototypes of new callbacks in struct generic_pm_domain
     to make them more useful.  Users of those callbacks will be added
     in 3.19 and it's better for them to be based on the correct struct
     definition in mainline from the start.  From Ulf Hansson and Kevin
     Hilman"

* tag 'pm+acpi-3.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM / Domains: Fix initial default state of the need_restore flag
  PM / sleep: Fix entering suspend-to-IDLE if no freeze_oops is set
  PM / Domains: Change prototype for the attach and detach callbacks
  cpufreq: Avoid crash in resume on SMP without OPP
  cpufreq: cpufreq-dt: Fix arguments in clock failure error message
  ACPI / blacklist: blacklist Win8 OSI for Dell Vostro 3546

Showing 6 changed files Side-by-side Diff

drivers/acpi/blacklist.c
... ... @@ -290,6 +290,14 @@
290 290 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
291 291 },
292 292 },
  293 + {
  294 + .callback = dmi_disable_osi_win8,
  295 + .ident = "Dell Vostro 3546",
  296 + .matches = {
  297 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  298 + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
  299 + },
  300 + },
293 301  
294 302 /*
295 303 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
drivers/base/power/domain.c
... ... @@ -361,9 +361,19 @@
361 361 struct device *dev = pdd->dev;
362 362 int ret = 0;
363 363  
364   - if (gpd_data->need_restore)
  364 + if (gpd_data->need_restore > 0)
365 365 return 0;
366 366  
  367 + /*
  368 + * If the value of the need_restore flag is still unknown at this point,
  369 + * we trust that pm_genpd_poweroff() has verified that the device is
  370 + * already runtime PM suspended.
  371 + */
  372 + if (gpd_data->need_restore < 0) {
  373 + gpd_data->need_restore = 1;
  374 + return 0;
  375 + }
  376 +
367 377 mutex_unlock(&genpd->lock);
368 378  
369 379 genpd_start_dev(genpd, dev);
... ... @@ -373,7 +383,7 @@
373 383 mutex_lock(&genpd->lock);
374 384  
375 385 if (!ret)
376   - gpd_data->need_restore = true;
  386 + gpd_data->need_restore = 1;
377 387  
378 388 return ret;
379 389 }
380 390  
381 391  
... ... @@ -389,12 +399,17 @@
389 399 {
390 400 struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
391 401 struct device *dev = pdd->dev;
392   - bool need_restore = gpd_data->need_restore;
  402 + int need_restore = gpd_data->need_restore;
393 403  
394   - gpd_data->need_restore = false;
  404 + gpd_data->need_restore = 0;
395 405 mutex_unlock(&genpd->lock);
396 406  
397 407 genpd_start_dev(genpd, dev);
  408 +
  409 + /*
  410 + * Call genpd_restore_dev() for recently added devices too (need_restore
  411 + * is negative then).
  412 + */
398 413 if (need_restore)
399 414 genpd_restore_dev(genpd, dev);
400 415  
... ... @@ -603,6 +618,7 @@
603 618 static int pm_genpd_runtime_suspend(struct device *dev)
604 619 {
605 620 struct generic_pm_domain *genpd;
  621 + struct generic_pm_domain_data *gpd_data;
606 622 bool (*stop_ok)(struct device *__dev);
607 623 int ret;
608 624  
... ... @@ -628,6 +644,16 @@
628 644 return 0;
629 645  
630 646 mutex_lock(&genpd->lock);
  647 +
  648 + /*
  649 + * If we have an unknown state of the need_restore flag, it means none
  650 + * of the runtime PM callbacks has been invoked yet. Let's update the
  651 + * flag to reflect that the current state is active.
  652 + */
  653 + gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
  654 + if (gpd_data->need_restore < 0)
  655 + gpd_data->need_restore = 0;
  656 +
631 657 genpd->in_progress++;
632 658 pm_genpd_poweroff(genpd);
633 659 genpd->in_progress--;
634 660  
... ... @@ -1437,12 +1463,12 @@
1437 1463 spin_unlock_irq(&dev->power.lock);
1438 1464  
1439 1465 if (genpd->attach_dev)
1440   - genpd->attach_dev(dev);
  1466 + genpd->attach_dev(genpd, dev);
1441 1467  
1442 1468 mutex_lock(&gpd_data->lock);
1443 1469 gpd_data->base.dev = dev;
1444 1470 list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
1445   - gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
  1471 + gpd_data->need_restore = -1;
1446 1472 gpd_data->td.constraint_changed = true;
1447 1473 gpd_data->td.effective_constraint_ns = -1;
1448 1474 mutex_unlock(&gpd_data->lock);
... ... @@ -1499,7 +1525,7 @@
1499 1525 genpd->max_off_time_changed = true;
1500 1526  
1501 1527 if (genpd->detach_dev)
1502   - genpd->detach_dev(dev);
  1528 + genpd->detach_dev(genpd, dev);
1503 1529  
1504 1530 spin_lock_irq(&dev->power.lock);
1505 1531  
... ... @@ -1546,7 +1572,7 @@
1546 1572  
1547 1573 psd = dev_to_psd(dev);
1548 1574 if (psd && psd->domain_data)
1549   - to_gpd_data(psd->domain_data)->need_restore = val;
  1575 + to_gpd_data(psd->domain_data)->need_restore = val ? 1 : 0;
1550 1576  
1551 1577 spin_unlock_irqrestore(&dev->power.lock, flags);
1552 1578 }
drivers/cpufreq/cpufreq-dt.c
... ... @@ -166,8 +166,8 @@
166 166 if (ret == -EPROBE_DEFER)
167 167 dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu);
168 168 else
169   - dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", ret,
170   - cpu);
  169 + dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu,
  170 + ret);
171 171 } else {
172 172 *cdev = cpu_dev;
173 173 *creg = cpu_reg;
drivers/cpufreq/cpufreq.c
... ... @@ -1022,7 +1022,8 @@
1022 1022  
1023 1023 read_unlock_irqrestore(&cpufreq_driver_lock, flags);
1024 1024  
1025   - policy->governor = NULL;
  1025 + if (policy)
  1026 + policy->governor = NULL;
1026 1027  
1027 1028 return policy;
1028 1029 }
include/linux/pm_domain.h
... ... @@ -72,8 +72,10 @@
72 72 bool max_off_time_changed;
73 73 bool cached_power_down_ok;
74 74 struct gpd_cpuidle_data *cpuidle_data;
75   - void (*attach_dev)(struct device *dev);
76   - void (*detach_dev)(struct device *dev);
  75 + int (*attach_dev)(struct generic_pm_domain *domain,
  76 + struct device *dev);
  77 + void (*detach_dev)(struct generic_pm_domain *domain,
  78 + struct device *dev);
77 79 };
78 80  
79 81 static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
... ... @@ -104,7 +106,7 @@
104 106 struct notifier_block nb;
105 107 struct mutex lock;
106 108 unsigned int refcount;
107   - bool need_restore;
  109 + int need_restore;
108 110 };
109 111  
110 112 #ifdef CONFIG_PM_GENERIC_DOMAINS
kernel/power/suspend.c
... ... @@ -146,7 +146,7 @@
146 146  
147 147 static int platform_suspend_prepare_late(suspend_state_t state)
148 148 {
149   - return state == PM_SUSPEND_FREEZE && freeze_ops->prepare ?
  149 + return state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->prepare ?
150 150 freeze_ops->prepare() : 0;
151 151 }
152 152  
... ... @@ -164,7 +164,7 @@
164 164  
165 165 static void platform_resume_early(suspend_state_t state)
166 166 {
167   - if (state == PM_SUSPEND_FREEZE && freeze_ops->restore)
  167 + if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->restore)
168 168 freeze_ops->restore();
169 169 }
170 170