Skip to content

Commit 833db72

Browse files
committed
Merge tag 'pm-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "These make the power management of PCI devices with ACPI companions more straightforwad, add support for inefficient operating performance points to the Energy model and make cpufreq handle them as appropriate, rearrange the handling of cpuidle during system PM transitions, update a few cpufreq drivers and intel_idle, fix assorded issues and clean up code in multiple places. Specifics: - Add support for inefficient operating performance points to the Energy Model and modify cpufreq to use them properly (Vincent Donnefort). - Rearrange the DTPM framework code to simplify it and make it easier to follow (Daniel Lezcano). - Fix power intialization in DTPM (Daniel Lezcano). - Add CPU load consideration when estimating the instaneous power consumption in DTPM (Daniel Lezcano). - Fix cpu->pstate.turbo_freq initialization in intel_pstate (Zhang Rui). - Make intel_pstate process HWP Guaranteed change notifications from the processor (Srinivas Pandruvada). - Fix typo in cpufreq.h (Rafael Wysocki). - Fix tegra driver to handle BPMP errors properly (Mikko Perttunen). - Fix the parameter usage of the newly added perf-domain API (Hector Yuan). - Minor cleanups to cppc, vexpress and s3c244x drivers (Han Wang, Guenter Roeck, and Arnd Bergmann). - Fix kobject memory leaks in cpuidle error paths (Anel Orazgaliyeva). - Make intel_idle enable interrupts before entering C1 on some Xeon processor models (Artem Bityutskiy). - Clean up hib_wait_io() (Falla Coulibaly). - Fix sparse warnings in hibernation-related code (Anders Roxell). - Use vzalloc() and kzalloc() instead of their open-coded equivalents in hibernation-related code (Cai Huoqing). - Prevent user space from crashing the kernel by attempting to restore the system state from a swap partition in use (Ye Bin). - Do not let "syscore" devices runtime-suspend during system PM transitions (Rafael Wysocki). - Do not pause cpuidle in the suspend-to-idle path (Rafael Wysocki). - Pause cpuidle later and resume it earlier during system PM transitions (Rafael Wysocki). - Make system suspend code use valid_state() consistently (Rafael Wysocki). - Add support for enabling wakeup IRQs after invoking the ->runtime_suspend() callback and make two drivers use it (Chunfeng Yun). - Make the association of ACPI device objects with PCI devices more straightforward and simplify the code doing that for all devices in general (Rafael Wysocki). - Eliminate struct pci_platform_pm_ops and handle the both of its users (PCI and Intel MID) directly in the PCI bus code (Rafael Wysocki). - Simplify and clarify ACPI PCI device PM helpers (Rafael Wysocki). - Fix ordering of operations in pci_back_from_sleep() (Rafael Wysocki). - Make exynos-ppmu use hyphens in DT properties (Krzysztof Kozlowski). - Simplify parsing event-type from DT in exynos-ppmu (Krzysztof Kozlowski). - Strengthen check for freq_table in devfreq (Samuel Holland)" * tag 'pm-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (49 commits) cpufreq: Fix parameter in parse_perf_domain() usb: mtu3: enable wake-up interrupt after runtime_suspend called usb: xhci-mtk: enable wake-up interrupt after runtime_suspend called PM / wakeirq: support enabling wake-up irq after runtime_suspend called PM / devfreq: Strengthen check for freq_table devfreq: exynos-ppmu: simplify parsing event-type from DT devfreq: exynos-ppmu: use node names with hyphens cpufreq: intel_pstate: Fix cpu->pstate.turbo_freq initialization PM: suspend: Use valid_state() consistently PM: sleep: Pause cpuidle later and resume it earlier during system transitions PM: suspend: Do not pause cpuidle in the suspend-to-idle path PM: sleep: Do not let "syscore" devices runtime-suspend during system transitions PM: hibernate: Get block device exclusively in swsusp_check() powercap/drivers/dtpm: Fix power limit initialization powercap/drivers/dtpm: Scale the power with the load powercap/drivers/dtpm: Use container_of instead of a private data field powercap/drivers/dtpm: Simplify the dtpm table powercap/drivers/dtpm: Encapsulate even more the code PM: hibernate: swap: Use vzalloc() and kzalloc() PM: hibernate: fix sparse warnings ...
2 parents c0d6586 + bf56b90 commit 833db72

39 files changed

+913
-503
lines changed

drivers/base/power/main.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include <linux/suspend.h>
3333
#include <trace/events/power.h>
3434
#include <linux/cpufreq.h>
35-
#include <linux/cpuidle.h>
3635
#include <linux/devfreq.h>
3736
#include <linux/timer.h>
3837

@@ -747,8 +746,6 @@ void dpm_resume_noirq(pm_message_t state)
747746

748747
resume_device_irqs();
749748
device_wakeup_disarm_wake_irqs();
750-
751-
cpuidle_resume();
752749
}
753750

754751
/**
@@ -1051,7 +1048,7 @@ static void device_complete(struct device *dev, pm_message_t state)
10511048
const char *info = NULL;
10521049

10531050
if (dev->power.syscore)
1054-
return;
1051+
goto out;
10551052

10561053
device_lock(dev);
10571054

@@ -1081,6 +1078,7 @@ static void device_complete(struct device *dev, pm_message_t state)
10811078

10821079
device_unlock(dev);
10831080

1081+
out:
10841082
pm_runtime_put(dev);
10851083
}
10861084

@@ -1336,8 +1334,6 @@ int dpm_suspend_noirq(pm_message_t state)
13361334
{
13371335
int ret;
13381336

1339-
cpuidle_pause();
1340-
13411337
device_wakeup_arm_wake_irqs();
13421338
suspend_device_irqs();
13431339

@@ -1794,9 +1790,6 @@ static int device_prepare(struct device *dev, pm_message_t state)
17941790
int (*callback)(struct device *) = NULL;
17951791
int ret = 0;
17961792

1797-
if (dev->power.syscore)
1798-
return 0;
1799-
18001793
/*
18011794
* If a device's parent goes into runtime suspend at the wrong time,
18021795
* it won't be possible to resume the device. To prevent this we
@@ -1805,6 +1798,9 @@ static int device_prepare(struct device *dev, pm_message_t state)
18051798
*/
18061799
pm_runtime_get_noresume(dev);
18071800

1801+
if (dev->power.syscore)
1802+
return 0;
1803+
18081804
device_lock(dev);
18091805

18101806
dev->power.wakeup_path = false;

drivers/base/power/power.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ extern u64 pm_runtime_active_time(struct device *dev);
2525

2626
#define WAKE_IRQ_DEDICATED_ALLOCATED BIT(0)
2727
#define WAKE_IRQ_DEDICATED_MANAGED BIT(1)
28+
#define WAKE_IRQ_DEDICATED_REVERSE BIT(2)
2829
#define WAKE_IRQ_DEDICATED_MASK (WAKE_IRQ_DEDICATED_ALLOCATED | \
29-
WAKE_IRQ_DEDICATED_MANAGED)
30+
WAKE_IRQ_DEDICATED_MANAGED | \
31+
WAKE_IRQ_DEDICATED_REVERSE)
3032

3133
struct wake_irq {
3234
struct device *dev;
@@ -39,7 +41,8 @@ extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
3941
extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
4042
extern void dev_pm_enable_wake_irq_check(struct device *dev,
4143
bool can_change_status);
42-
extern void dev_pm_disable_wake_irq_check(struct device *dev);
44+
extern void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable);
45+
extern void dev_pm_enable_wake_irq_complete(struct device *dev);
4346

4447
#ifdef CONFIG_PM_SLEEP
4548

drivers/base/power/runtime.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
645645
if (retval)
646646
goto fail;
647647

648+
dev_pm_enable_wake_irq_complete(dev);
649+
648650
no_callback:
649651
__update_runtime_status(dev, RPM_SUSPENDED);
650652
pm_runtime_deactivate_timer(dev);
@@ -690,7 +692,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
690692
return retval;
691693

692694
fail:
693-
dev_pm_disable_wake_irq_check(dev);
695+
dev_pm_disable_wake_irq_check(dev, true);
694696
__update_runtime_status(dev, RPM_ACTIVE);
695697
dev->power.deferred_resume = false;
696698
wake_up_all(&dev->power.wait_queue);
@@ -873,7 +875,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
873875

874876
callback = RPM_GET_CALLBACK(dev, runtime_resume);
875877

876-
dev_pm_disable_wake_irq_check(dev);
878+
dev_pm_disable_wake_irq_check(dev, false);
877879
retval = rpm_callback(callback, dev);
878880
if (retval) {
879881
__update_runtime_status(dev, RPM_SUSPENDED);

drivers/base/power/wakeirq.c

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -142,24 +142,7 @@ static irqreturn_t handle_threaded_wake_irq(int irq, void *_wirq)
142142
return IRQ_HANDLED;
143143
}
144144

145-
/**
146-
* dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
147-
* @dev: Device entry
148-
* @irq: Device wake-up interrupt
149-
*
150-
* Unless your hardware has separate wake-up interrupts in addition
151-
* to the device IO interrupts, you don't need this.
152-
*
153-
* Sets up a threaded interrupt handler for a device that has
154-
* a dedicated wake-up interrupt in addition to the device IO
155-
* interrupt.
156-
*
157-
* The interrupt starts disabled, and needs to be managed for
158-
* the device by the bus code or the device driver using
159-
* dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq()
160-
* functions.
161-
*/
162-
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
145+
static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)
163146
{
164147
struct wake_irq *wirq;
165148
int err;
@@ -197,7 +180,7 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
197180
if (err)
198181
goto err_free_irq;
199182

200-
wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
183+
wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag;
201184

202185
return err;
203186

@@ -210,8 +193,57 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
210193

211194
return err;
212195
}
196+
197+
198+
/**
199+
* dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
200+
* @dev: Device entry
201+
* @irq: Device wake-up interrupt
202+
*
203+
* Unless your hardware has separate wake-up interrupts in addition
204+
* to the device IO interrupts, you don't need this.
205+
*
206+
* Sets up a threaded interrupt handler for a device that has
207+
* a dedicated wake-up interrupt in addition to the device IO
208+
* interrupt.
209+
*
210+
* The interrupt starts disabled, and needs to be managed for
211+
* the device by the bus code or the device driver using
212+
* dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
213+
* functions.
214+
*/
215+
int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
216+
{
217+
return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);
218+
}
213219
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
214220

221+
/**
222+
* dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt
223+
* with reverse enable ordering
224+
* @dev: Device entry
225+
* @irq: Device wake-up interrupt
226+
*
227+
* Unless your hardware has separate wake-up interrupts in addition
228+
* to the device IO interrupts, you don't need this.
229+
*
230+
* Sets up a threaded interrupt handler for a device that has a dedicated
231+
* wake-up interrupt in addition to the device IO interrupt. It sets
232+
* the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()
233+
* to enable dedicated wake-up interrupt after running the runtime suspend
234+
* callback for @dev.
235+
*
236+
* The interrupt starts disabled, and needs to be managed for
237+
* the device by the bus code or the device driver using
238+
* dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
239+
* functions.
240+
*/
241+
int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
242+
{
243+
return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);
244+
}
245+
EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
246+
215247
/**
216248
* dev_pm_enable_wake_irq - Enable device wake-up interrupt
217249
* @dev: Device
@@ -282,27 +314,54 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
282314
return;
283315

284316
enable:
285-
enable_irq(wirq->irq);
317+
if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
318+
enable_irq(wirq->irq);
286319
}
287320

288321
/**
289322
* dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
290323
* @dev: Device
324+
* @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE
291325
*
292326
* Disables wake-up interrupt conditionally based on status.
293327
* Should be only called from rpm_suspend() and rpm_resume() path.
294328
*/
295-
void dev_pm_disable_wake_irq_check(struct device *dev)
329+
void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
296330
{
297331
struct wake_irq *wirq = dev->power.wakeirq;
298332

299333
if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
300334
return;
301335

336+
if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
337+
return;
338+
302339
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
303340
disable_irq_nosync(wirq->irq);
304341
}
305342

343+
/**
344+
* dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before
345+
* @dev: Device using the wake IRQ
346+
*
347+
* Enable wake IRQ conditionally based on status, mainly used if want to
348+
* enable wake IRQ after running ->runtime_suspend() which depends on
349+
* WAKE_IRQ_DEDICATED_REVERSE.
350+
*
351+
* Should be only called from rpm_suspend() path.
352+
*/
353+
void dev_pm_enable_wake_irq_complete(struct device *dev)
354+
{
355+
struct wake_irq *wirq = dev->power.wakeirq;
356+
357+
if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
358+
return;
359+
360+
if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&
361+
wirq->status & WAKE_IRQ_DEDICATED_REVERSE)
362+
enable_irq(wirq->irq);
363+
}
364+
306365
/**
307366
* dev_pm_arm_wake_irq - Arm device wake-up
308367
* @wirq: Device wake-up interrupt

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,8 @@ static unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
470470
if (policy->cached_target_freq == target_freq)
471471
index = policy->cached_resolved_idx;
472472
else
473-
index = cpufreq_table_find_index_dl(policy, target_freq);
473+
index = cpufreq_table_find_index_dl(policy, target_freq,
474+
false);
474475

475476
entry = &policy->freq_table[index];
476477
next_freq = entry->frequency;

drivers/cpufreq/amd_freq_sensitivity.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
9191
unsigned int index;
9292

9393
index = cpufreq_table_find_index_h(policy,
94-
policy->cur - 1);
94+
policy->cur - 1,
95+
relation & CPUFREQ_RELATION_E);
9596
freq_next = policy->freq_table[index].frequency;
9697
}
9798

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,8 +741,6 @@ static int __init cppc_cpufreq_init(void)
741741
if ((acpi_disabled) || !acpi_cpc_valid())
742742
return -ENODEV;
743743

744-
INIT_LIST_HEAD(&cpu_data_list);
745-
746744
cppc_check_hisi_workaround();
747745
cppc_freq_invariance_init();
748746

drivers/cpufreq/cpufreq.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ static unsigned int __resolve_freq(struct cpufreq_policy *policy,
554554
unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy,
555555
unsigned int target_freq)
556556
{
557-
return __resolve_freq(policy, target_freq, CPUFREQ_RELATION_L);
557+
return __resolve_freq(policy, target_freq, CPUFREQ_RELATION_LE);
558558
}
559559
EXPORT_SYMBOL_GPL(cpufreq_driver_resolve_freq);
560560

@@ -2260,8 +2260,16 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
22602260
!(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS))
22612261
return 0;
22622262

2263-
if (cpufreq_driver->target)
2263+
if (cpufreq_driver->target) {
2264+
/*
2265+
* If the driver hasn't setup a single inefficient frequency,
2266+
* it's unlikely it knows how to decode CPUFREQ_RELATION_E.
2267+
*/
2268+
if (!policy->efficiencies_available)
2269+
relation &= ~CPUFREQ_RELATION_E;
2270+
22642271
return cpufreq_driver->target(policy, target_freq, relation);
2272+
}
22652273

22662274
if (!cpufreq_driver->target_index)
22672275
return -EINVAL;
@@ -2523,8 +2531,15 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
25232531
if (ret)
25242532
return ret;
25252533

2534+
/*
2535+
* Resolve policy min/max to available frequencies. It ensures
2536+
* no frequency resolution will neither overshoot the requested maximum
2537+
* nor undershoot the requested minimum.
2538+
*/
25262539
policy->min = new_data.min;
25272540
policy->max = new_data.max;
2541+
policy->min = __resolve_freq(policy, policy->min, CPUFREQ_RELATION_L);
2542+
policy->max = __resolve_freq(policy, policy->max, CPUFREQ_RELATION_H);
25282543
trace_cpu_frequency_limits(policy);
25292544

25302545
policy->cached_target_freq = UINT_MAX;

drivers/cpufreq/cpufreq_conservative.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
111111
if (requested_freq > policy->max)
112112
requested_freq = policy->max;
113113

114-
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_H);
114+
__cpufreq_driver_target(policy, requested_freq,
115+
CPUFREQ_RELATION_HE);
115116
dbs_info->requested_freq = requested_freq;
116117
goto out;
117118
}
@@ -134,7 +135,8 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
134135
else
135136
requested_freq = policy->min;
136137

137-
__cpufreq_driver_target(policy, requested_freq, CPUFREQ_RELATION_L);
138+
__cpufreq_driver_target(policy, requested_freq,
139+
CPUFREQ_RELATION_LE);
138140
dbs_info->requested_freq = requested_freq;
139141
}
140142

0 commit comments

Comments
 (0)