Skip to content

Commit

Permalink
Merge tag 'pm+acpi-3.18-rc5' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  • Loading branch information
torvalds committed Nov 14, 2014
2 parents f720d7d + 3168949 commit 78646f6
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 16 deletions.
8 changes: 8 additions & 0 deletions drivers/acpi/blacklist.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
},
},
{
.callback = dmi_disable_osi_win8,
.ident = "Dell Vostro 3546",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
},
},

/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
Expand Down
42 changes: 34 additions & 8 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,19 @@ static int __pm_genpd_save_device(struct pm_domain_data *pdd,
struct device *dev = pdd->dev;
int ret = 0;

if (gpd_data->need_restore)
if (gpd_data->need_restore > 0)
return 0;

/*
* If the value of the need_restore flag is still unknown at this point,
* we trust that pm_genpd_poweroff() has verified that the device is
* already runtime PM suspended.
*/
if (gpd_data->need_restore < 0) {
gpd_data->need_restore = 1;
return 0;
}

mutex_unlock(&genpd->lock);

genpd_start_dev(genpd, dev);
Expand All @@ -373,7 +383,7 @@ static int __pm_genpd_save_device(struct pm_domain_data *pdd,
mutex_lock(&genpd->lock);

if (!ret)
gpd_data->need_restore = true;
gpd_data->need_restore = 1;

return ret;
}
Expand All @@ -389,12 +399,17 @@ static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
{
struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
struct device *dev = pdd->dev;
bool need_restore = gpd_data->need_restore;
int need_restore = gpd_data->need_restore;

gpd_data->need_restore = false;
gpd_data->need_restore = 0;
mutex_unlock(&genpd->lock);

genpd_start_dev(genpd, dev);

/*
* Call genpd_restore_dev() for recently added devices too (need_restore
* is negative then).
*/
if (need_restore)
genpd_restore_dev(genpd, dev);

Expand Down Expand Up @@ -603,6 +618,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
static int pm_genpd_runtime_suspend(struct device *dev)
{
struct generic_pm_domain *genpd;
struct generic_pm_domain_data *gpd_data;
bool (*stop_ok)(struct device *__dev);
int ret;

Expand All @@ -628,6 +644,16 @@ static int pm_genpd_runtime_suspend(struct device *dev)
return 0;

mutex_lock(&genpd->lock);

/*
* If we have an unknown state of the need_restore flag, it means none
* of the runtime PM callbacks has been invoked yet. Let's update the
* flag to reflect that the current state is active.
*/
gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
if (gpd_data->need_restore < 0)
gpd_data->need_restore = 0;

genpd->in_progress++;
pm_genpd_poweroff(genpd);
genpd->in_progress--;
Expand Down Expand Up @@ -1437,12 +1463,12 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
spin_unlock_irq(&dev->power.lock);

if (genpd->attach_dev)
genpd->attach_dev(dev);
genpd->attach_dev(genpd, dev);

mutex_lock(&gpd_data->lock);
gpd_data->base.dev = dev;
list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
gpd_data->need_restore = -1;
gpd_data->td.constraint_changed = true;
gpd_data->td.effective_constraint_ns = -1;
mutex_unlock(&gpd_data->lock);
Expand Down Expand Up @@ -1499,7 +1525,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
genpd->max_off_time_changed = true;

if (genpd->detach_dev)
genpd->detach_dev(dev);
genpd->detach_dev(genpd, dev);

spin_lock_irq(&dev->power.lock);

Expand Down Expand Up @@ -1546,7 +1572,7 @@ void pm_genpd_dev_need_restore(struct device *dev, bool val)

psd = dev_to_psd(dev);
if (psd && psd->domain_data)
to_gpd_data(psd->domain_data)->need_restore = val;
to_gpd_data(psd->domain_data)->need_restore = val ? 1 : 0;

spin_unlock_irqrestore(&dev->power.lock, flags);
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/cpufreq/cpufreq-dt.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ static int allocate_resources(int cpu, struct device **cdev,
if (ret == -EPROBE_DEFER)
dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu);
else
dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", ret,
cpu);
dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu,
ret);
} else {
*cdev = cpu_dev;
*creg = cpu_reg;
Expand Down
3 changes: 2 additions & 1 deletion drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)

read_unlock_irqrestore(&cpufreq_driver_lock, flags);

policy->governor = NULL;
if (policy)
policy->governor = NULL;

return policy;
}
Expand Down
8 changes: 5 additions & 3 deletions include/linux/pm_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ struct generic_pm_domain {
bool max_off_time_changed;
bool cached_power_down_ok;
struct gpd_cpuidle_data *cpuidle_data;
void (*attach_dev)(struct device *dev);
void (*detach_dev)(struct device *dev);
int (*attach_dev)(struct generic_pm_domain *domain,
struct device *dev);
void (*detach_dev)(struct generic_pm_domain *domain,
struct device *dev);
};

static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
Expand Down Expand Up @@ -104,7 +106,7 @@ struct generic_pm_domain_data {
struct notifier_block nb;
struct mutex lock;
unsigned int refcount;
bool need_restore;
int need_restore;
};

#ifdef CONFIG_PM_GENERIC_DOMAINS
Expand Down
4 changes: 2 additions & 2 deletions kernel/power/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static int platform_suspend_prepare(suspend_state_t state)

static int platform_suspend_prepare_late(suspend_state_t state)
{
return state == PM_SUSPEND_FREEZE && freeze_ops->prepare ?
return state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->prepare ?
freeze_ops->prepare() : 0;
}

Expand All @@ -164,7 +164,7 @@ static void platform_resume_noirq(suspend_state_t state)

static void platform_resume_early(suspend_state_t state)
{
if (state == PM_SUSPEND_FREEZE && freeze_ops->restore)
if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->restore)
freeze_ops->restore();
}

Expand Down

0 comments on commit 78646f6

Please sign in to comment.