mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
ACPI and power management fixes for 3.18-rc5
- 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. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJUZhtnAAoJEILEb/54YlRxx1EP/0Rk7pJUHeOMmdyXyY7B+n+f MlXHVMDhskT370fsdTGbpeYb5ATr5kGatfhr+vyDQmBtxdw7lDJxKq54s6kmmIL3 SEMRRb4NtkPsdDE7zq985JmjsrnHtKxC5NjSUwEGxdyyfAZxll4mrZL6RrqXCu44 L+qdVXRffCCrJDXZl5FZUpSZ3ZUc+xTiaDy7ObjLe2bwmzvBOAwS2flBMKxN9X+e khlGdQZ0e9T2Y3IXriHxHMui8OVbkPyYZkW1aubCd0HwuTMP7sebosX/2JWdJOmg q6bGcvPlBwXDRoShlzFO8CN5w5E8fIe0vfPcg9SB3s21S7rJEbYQX/5ytm107aJj Ysv7mcb2dAHG0V3J7hxhkS+7UNPxfk3G+8frxW2UQ6eIDlZkBORIUhGCzeSbIGYM aIKiomN4jGuPeaOkEnKl4RwMlzjuzAs2V06viffbq63eyWBvtHDW8M5bdq901pXp 1jOT7yKqLzOZYqcYaLr3z+IBw/+hfuG/FdCp3uGyFqeHPBNIP3BfFnWm6A6E13b+ aC6gvhQHojT7L2gqIBJ+Qn0EiRWNqwoLk6w6DLDYJna/hYyoXq0BKv+/x2OegItU ENKYVpfmSt3YsEhcTBW4h5IpUvK07o5Oa3nTxen6924Im61dMyaSUDD5DiaqCgXO bVJTsF983hBZGTy0IMX/ =wQxT -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
78646f62db
@ -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.
|
||||
|
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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--;
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
@ -166,8 +166,8 @@ try_again:
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user