Skip to content

Commit e37720e

Browse files
committed
Merge tag 'pm-fixes-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "These fix a recently exposed issue in the PCI device wakeup code and one older problem related to PCI device wakeup that has been reported recently, modify one more piece of computations in intel_pstate to get rid of a rounding error, fix a possible race in the schedutil cpufreq governor, fix the device PM QoS sysfs interface to correctly handle invalid user input, fix return values of two probe routines in devfreq drivers and constify an attribute_group structure in devfreq. Specifics: - Avoid clearing the PCI PME Enable bit for devices as a result of config space restoration which confuses AML executed afterward and causes wakeup events to be lost on some systems (Rafael Wysocki). - Fix the native PCIe PME interrupts handling in the cases when the PME IRQ is set up as a system wakeup one so that runtime PM remote wakeup works as expected after system resume on systems where that happens (Rafael Wysocki). - Fix the device PM QoS sysfs interface to handle invalid user input correctly instead of using an unititialized variable value as the latency tolerance for the device at hand (Dan Carpenter). - Get rid of one more rounding error from intel_pstate computations (Srinivas Pandruvada). - Fix the schedutil cpufreq governor to prevent it from possibly accessing unititialized data structures from governor callbacks in some cases on systems when multiple CPUs share a single cpufreq policy object (Vikram Mulukutla). - Fix the return values of probe routines in two devfreq drivers (Gustavo Silva). - Constify an attribute_group structure in devfreq (Arvind Yadav)" * tag 'pm-fixes-4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PCI / PM: Fix native PME handling during system suspend/resume PCI / PM: Restore PME Enable after config space restoration cpufreq: schedutil: Fix sugov_start() versus sugov_update_shared() race PM / QoS: return -EINVAL for bogus strings cpufreq: intel_pstate: Fix ratio setting for min_perf_pct PM / devfreq: constify attribute_group structures. PM / devfreq: tegra: fix error return code in tegra_devfreq_probe() PM / devfreq: rk3399_dmc: fix error return code in rk3399_dmcfreq_probe()
2 parents 867eacd + 6df609b commit e37720e

File tree

10 files changed

+39
-37
lines changed

10 files changed

+39
-37
lines changed

drivers/base/power/sysfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ static ssize_t pm_qos_latency_tolerance_store(struct device *dev,
272272
value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
273273
else if (!strcmp(buf, "any") || !strcmp(buf, "any\n"))
274274
value = PM_QOS_LATENCY_ANY;
275+
else
276+
return -EINVAL;
275277
}
276278
ret = dev_pm_qos_update_user_latency_tolerance(dev, value);
277279
return ret < 0 ? ret : n;

drivers/cpufreq/intel_pstate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ static int min_perf_pct_min(void)
572572
int turbo_pstate = cpu->pstate.turbo_pstate;
573573

574574
return turbo_pstate ?
575-
DIV_ROUND_UP(cpu->pstate.min_pstate * 100, turbo_pstate) : 0;
575+
(cpu->pstate.min_pstate * 100 / turbo_pstate) : 0;
576576
}
577577

578578
static s16 intel_pstate_get_epb(struct cpudata *cpu_data)

drivers/devfreq/governor_userspace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static struct attribute *dev_entries[] = {
8686
&dev_attr_set_freq.attr,
8787
NULL,
8888
};
89-
static struct attribute_group dev_attr_group = {
89+
static const struct attribute_group dev_attr_group = {
9090
.name = "userspace",
9191
.attrs = dev_entries,
9292
};

drivers/devfreq/rk3399_dmc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,9 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
336336

337337
irq = platform_get_irq(pdev, 0);
338338
if (irq < 0) {
339-
dev_err(&pdev->dev, "Cannot get the dmc interrupt resource\n");
340-
return -EINVAL;
339+
dev_err(&pdev->dev,
340+
"Cannot get the dmc interrupt resource: %d\n", irq);
341+
return irq;
341342
}
342343
data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL);
343344
if (!data)

drivers/devfreq/tegra-devfreq.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -688,9 +688,9 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
688688
}
689689

690690
irq = platform_get_irq(pdev, 0);
691-
if (irq <= 0) {
692-
dev_err(&pdev->dev, "Failed to get IRQ\n");
693-
return -ENODEV;
691+
if (irq < 0) {
692+
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
693+
return irq;
694694
}
695695

696696
platform_set_drvdata(pdev, tegra);

drivers/pci/pci-driver.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)
511511
}
512512

513513
pci_restore_state(pci_dev);
514+
pci_pme_restore(pci_dev);
514515
return 0;
515516
}
516517

@@ -522,6 +523,7 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
522523
{
523524
pci_power_up(pci_dev);
524525
pci_restore_state(pci_dev);
526+
pci_pme_restore(pci_dev);
525527
pci_fixup_device(pci_fixup_resume_early, pci_dev);
526528
}
527529

drivers/pci/pci.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,7 +1801,11 @@ static void __pci_pme_active(struct pci_dev *dev, bool enable)
18011801
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
18021802
}
18031803

1804-
static void pci_pme_restore(struct pci_dev *dev)
1804+
/**
1805+
* pci_pme_restore - Restore PME configuration after config space restore.
1806+
* @dev: PCI device to update.
1807+
*/
1808+
void pci_pme_restore(struct pci_dev *dev)
18051809
{
18061810
u16 pmcsr;
18071811

@@ -1811,6 +1815,7 @@ static void pci_pme_restore(struct pci_dev *dev)
18111815
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
18121816
if (dev->wakeup_prepared) {
18131817
pmcsr |= PCI_PM_CTRL_PME_ENABLE;
1818+
pmcsr &= ~PCI_PM_CTRL_PME_STATUS;
18141819
} else {
18151820
pmcsr &= ~PCI_PM_CTRL_PME_ENABLE;
18161821
pmcsr |= PCI_PM_CTRL_PME_STATUS;
@@ -1907,14 +1912,9 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
19071912
{
19081913
int ret = 0;
19091914

1910-
/*
1911-
* Don't do the same thing twice in a row for one device, but restore
1912-
* PME Enable in case it has been updated by config space restoration.
1913-
*/
1914-
if (!!enable == !!dev->wakeup_prepared) {
1915-
pci_pme_restore(dev);
1915+
/* Don't do the same thing twice in a row for one device. */
1916+
if (!!enable == !!dev->wakeup_prepared)
19161917
return 0;
1917-
}
19181918

19191919
/*
19201920
* According to "PCI System Architecture" 4th ed. by Tom Shanley & Don

drivers/pci/pci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ void pci_power_up(struct pci_dev *dev);
7171
void pci_disable_enabled_device(struct pci_dev *dev);
7272
int pci_finish_runtime_suspend(struct pci_dev *dev);
7373
int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
74+
void pci_pme_restore(struct pci_dev *dev);
7475
bool pci_dev_keep_suspended(struct pci_dev *dev);
7576
void pci_dev_complete_resume(struct pci_dev *pci_dev);
7677
void pci_config_pm_runtime_get(struct pci_dev *dev);

drivers/pci/pcie/pme.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,11 @@ static int __init pcie_pme_setup(char *str)
4040
}
4141
__setup("pcie_pme=", pcie_pme_setup);
4242

43-
enum pme_suspend_level {
44-
PME_SUSPEND_NONE = 0,
45-
PME_SUSPEND_WAKEUP,
46-
PME_SUSPEND_NOIRQ,
47-
};
48-
4943
struct pcie_pme_service_data {
5044
spinlock_t lock;
5145
struct pcie_device *srv;
5246
struct work_struct work;
53-
enum pme_suspend_level suspend_level;
47+
bool noirq; /* If set, keep the PME interrupt disabled. */
5448
};
5549

5650
/**
@@ -228,7 +222,7 @@ static void pcie_pme_work_fn(struct work_struct *work)
228222
spin_lock_irq(&data->lock);
229223

230224
for (;;) {
231-
if (data->suspend_level != PME_SUSPEND_NONE)
225+
if (data->noirq)
232226
break;
233227

234228
pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta);
@@ -255,7 +249,7 @@ static void pcie_pme_work_fn(struct work_struct *work)
255249
spin_lock_irq(&data->lock);
256250
}
257251

258-
if (data->suspend_level == PME_SUSPEND_NONE)
252+
if (!data->noirq)
259253
pcie_pme_interrupt_enable(port, true);
260254

261255
spin_unlock_irq(&data->lock);
@@ -378,7 +372,7 @@ static int pcie_pme_suspend(struct pcie_device *srv)
378372
{
379373
struct pcie_pme_service_data *data = get_service_data(srv);
380374
struct pci_dev *port = srv->port;
381-
bool wakeup, wake_irq_enabled = false;
375+
bool wakeup;
382376
int ret;
383377

384378
if (device_may_wakeup(&port->dev)) {
@@ -388,19 +382,16 @@ static int pcie_pme_suspend(struct pcie_device *srv)
388382
wakeup = pcie_pme_check_wakeup(port->subordinate);
389383
up_read(&pci_bus_sem);
390384
}
391-
spin_lock_irq(&data->lock);
392385
if (wakeup) {
393386
ret = enable_irq_wake(srv->irq);
394-
if (ret == 0) {
395-
data->suspend_level = PME_SUSPEND_WAKEUP;
396-
wake_irq_enabled = true;
397-
}
398-
}
399-
if (!wake_irq_enabled) {
400-
pcie_pme_interrupt_enable(port, false);
401-
pcie_clear_root_pme_status(port);
402-
data->suspend_level = PME_SUSPEND_NOIRQ;
387+
if (!ret)
388+
return 0;
403389
}
390+
391+
spin_lock_irq(&data->lock);
392+
pcie_pme_interrupt_enable(port, false);
393+
pcie_clear_root_pme_status(port);
394+
data->noirq = true;
404395
spin_unlock_irq(&data->lock);
405396

406397
synchronize_irq(srv->irq);
@@ -417,15 +408,15 @@ static int pcie_pme_resume(struct pcie_device *srv)
417408
struct pcie_pme_service_data *data = get_service_data(srv);
418409

419410
spin_lock_irq(&data->lock);
420-
if (data->suspend_level == PME_SUSPEND_NOIRQ) {
411+
if (data->noirq) {
421412
struct pci_dev *port = srv->port;
422413

423414
pcie_clear_root_pme_status(port);
424415
pcie_pme_interrupt_enable(port, true);
416+
data->noirq = false;
425417
} else {
426418
disable_irq_wake(srv->irq);
427419
}
428-
data->suspend_level = PME_SUSPEND_NONE;
429420
spin_unlock_irq(&data->lock);
430421

431422
return 0;

kernel/sched/cpufreq_schedutil.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,11 @@ static int sugov_start(struct cpufreq_policy *policy)
610610
sg_cpu->sg_policy = sg_policy;
611611
sg_cpu->flags = SCHED_CPUFREQ_RT;
612612
sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
613+
}
614+
615+
for_each_cpu(cpu, policy->cpus) {
616+
struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
617+
613618
cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
614619
policy_is_shared(policy) ?
615620
sugov_update_shared :

0 commit comments

Comments
 (0)