Skip to content

Commit 7680d45

Browse files
committed
Merge branches 'pm-cpuidle', 'pm-sleep' and 'pm-domains'
Merge cpuidle changes, updates related to system sleep amd generic power domains code fixes for 6.2-rc1: - Improve kernel messages printed by the cpuidle PCI driver (Ulf Hansson). - Make the DT cpuidle driver return the correct number of parsed idle states, clean it up and clarify a comment in it (Ulf Hansson). - Modify the tasks freezing code to avoid using pr_cont() and refine an error message printed by it (Rafael Wysocki). - Make the hibernation core code complain about memory map mismatches during resume to help diagnostics (Xueqin Luo). - Fix mistake in a kerneldoc comment in the hibernation code (xiongxin). - Reverse the order of performance and enabling operations in the generic power domains code (Abel Vesa). - Power off[on] domains in hibernate .freeze[thaw]_noirq hook of in the generic power domains code (Abel Vesa). - Consolidate genpd_restore_noirq() and genpd_resume_noirq() (Shawn Guo). - Pass generic PM noirq hooks to genpd_finish_suspend() (Shawn Guo). - Drop generic power domain status manipulation during hibernate restore (Shawn Guo). * pm-cpuidle: cpuidle: dt: Clarify a comment and simplify code in dt_init_idle_driver() cpuidle: dt: Return the correct numbers of parsed idle states cpuidle: psci: Extend information in log about OSI/PC mode * pm-sleep: PM: sleep: Refine error message in try_to_freeze_tasks() PM: sleep: Avoid using pr_cont() in the tasks freezing code PM: hibernate: Complain about memory map mismatches during resume PM: hibernate: Fix mistake in kerneldoc comment * pm-domains: PM: domains: Reverse the order of performance and enabling ops PM: domains: Power off[on] domain in hibernate .freeze[thaw]_noirq hook PM: domains: Consolidate genpd_restore_noirq() and genpd_resume_noirq() PM: domains: Pass generic PM noirq hooks to genpd_finish_suspend() PM: domains: Drop genpd status manipulation for hibernate restore
4 parents 173c6c5 + cb51aee + 96d4b8e + ae8ac19 commit 7680d45

6 files changed

Lines changed: 82 additions & 121 deletions

File tree

drivers/base/power/domain.c

Lines changed: 57 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -939,8 +939,8 @@ static int genpd_runtime_suspend(struct device *dev)
939939
return 0;
940940

941941
genpd_lock(genpd);
942-
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
943942
genpd_power_off(genpd, true, 0);
943+
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
944944
genpd_unlock(genpd);
945945

946946
return 0;
@@ -978,9 +978,8 @@ static int genpd_runtime_resume(struct device *dev)
978978
goto out;
979979

980980
genpd_lock(genpd);
981+
genpd_restore_performance_state(dev, gpd_data->rpm_pstate);
981982
ret = genpd_power_on(genpd, 0);
982-
if (!ret)
983-
genpd_restore_performance_state(dev, gpd_data->rpm_pstate);
984983
genpd_unlock(genpd);
985984

986985
if (ret)
@@ -1018,8 +1017,8 @@ static int genpd_runtime_resume(struct device *dev)
10181017
err_poweroff:
10191018
if (!pm_runtime_is_irq_safe(dev) || genpd_is_irq_safe(genpd)) {
10201019
genpd_lock(genpd);
1021-
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
10221020
genpd_power_off(genpd, true, 0);
1021+
gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
10231022
genpd_unlock(genpd);
10241023
}
10251024

@@ -1189,12 +1188,15 @@ static int genpd_prepare(struct device *dev)
11891188
* genpd_finish_suspend - Completion of suspend or hibernation of device in an
11901189
* I/O pm domain.
11911190
* @dev: Device to suspend.
1192-
* @poweroff: Specifies if this is a poweroff_noirq or suspend_noirq callback.
1191+
* @suspend_noirq: Generic suspend_noirq callback.
1192+
* @resume_noirq: Generic resume_noirq callback.
11931193
*
11941194
* Stop the device and remove power from the domain if all devices in it have
11951195
* been stopped.
11961196
*/
1197-
static int genpd_finish_suspend(struct device *dev, bool poweroff)
1197+
static int genpd_finish_suspend(struct device *dev,
1198+
int (*suspend_noirq)(struct device *dev),
1199+
int (*resume_noirq)(struct device *dev))
11981200
{
11991201
struct generic_pm_domain *genpd;
12001202
int ret = 0;
@@ -1203,10 +1205,7 @@ static int genpd_finish_suspend(struct device *dev, bool poweroff)
12031205
if (IS_ERR(genpd))
12041206
return -EINVAL;
12051207

1206-
if (poweroff)
1207-
ret = pm_generic_poweroff_noirq(dev);
1208-
else
1209-
ret = pm_generic_suspend_noirq(dev);
1208+
ret = suspend_noirq(dev);
12101209
if (ret)
12111210
return ret;
12121211

@@ -1217,10 +1216,7 @@ static int genpd_finish_suspend(struct device *dev, bool poweroff)
12171216
!pm_runtime_status_suspended(dev)) {
12181217
ret = genpd_stop_dev(genpd, dev);
12191218
if (ret) {
1220-
if (poweroff)
1221-
pm_generic_restore_noirq(dev);
1222-
else
1223-
pm_generic_resume_noirq(dev);
1219+
resume_noirq(dev);
12241220
return ret;
12251221
}
12261222
}
@@ -1244,16 +1240,20 @@ static int genpd_suspend_noirq(struct device *dev)
12441240
{
12451241
dev_dbg(dev, "%s()\n", __func__);
12461242

1247-
return genpd_finish_suspend(dev, false);
1243+
return genpd_finish_suspend(dev,
1244+
pm_generic_suspend_noirq,
1245+
pm_generic_resume_noirq);
12481246
}
12491247

12501248
/**
1251-
* genpd_resume_noirq - Start of resume of device in an I/O PM domain.
1249+
* genpd_finish_resume - Completion of resume of device in an I/O PM domain.
12521250
* @dev: Device to resume.
1251+
* @resume_noirq: Generic resume_noirq callback.
12531252
*
12541253
* Restore power to the device's PM domain, if necessary, and start the device.
12551254
*/
1256-
static int genpd_resume_noirq(struct device *dev)
1255+
static int genpd_finish_resume(struct device *dev,
1256+
int (*resume_noirq)(struct device *dev))
12571257
{
12581258
struct generic_pm_domain *genpd;
12591259
int ret;
@@ -1265,7 +1265,7 @@ static int genpd_resume_noirq(struct device *dev)
12651265
return -EINVAL;
12661266

12671267
if (device_wakeup_path(dev) && genpd_is_active_wakeup(genpd))
1268-
return pm_generic_resume_noirq(dev);
1268+
return resume_noirq(dev);
12691269

12701270
genpd_lock(genpd);
12711271
genpd_sync_power_on(genpd, true, 0);
@@ -1282,6 +1282,19 @@ static int genpd_resume_noirq(struct device *dev)
12821282
return pm_generic_resume_noirq(dev);
12831283
}
12841284

1285+
/**
1286+
* genpd_resume_noirq - Start of resume of device in an I/O PM domain.
1287+
* @dev: Device to resume.
1288+
*
1289+
* Restore power to the device's PM domain, if necessary, and start the device.
1290+
*/
1291+
static int genpd_resume_noirq(struct device *dev)
1292+
{
1293+
dev_dbg(dev, "%s()\n", __func__);
1294+
1295+
return genpd_finish_resume(dev, pm_generic_resume_noirq);
1296+
}
1297+
12851298
/**
12861299
* genpd_freeze_noirq - Completion of freezing a device in an I/O PM domain.
12871300
* @dev: Device to freeze.
@@ -1293,24 +1306,11 @@ static int genpd_resume_noirq(struct device *dev)
12931306
*/
12941307
static int genpd_freeze_noirq(struct device *dev)
12951308
{
1296-
const struct generic_pm_domain *genpd;
1297-
int ret = 0;
1298-
12991309
dev_dbg(dev, "%s()\n", __func__);
13001310

1301-
genpd = dev_to_genpd(dev);
1302-
if (IS_ERR(genpd))
1303-
return -EINVAL;
1304-
1305-
ret = pm_generic_freeze_noirq(dev);
1306-
if (ret)
1307-
return ret;
1308-
1309-
if (genpd->dev_ops.stop && genpd->dev_ops.start &&
1310-
!pm_runtime_status_suspended(dev))
1311-
ret = genpd_stop_dev(genpd, dev);
1312-
1313-
return ret;
1311+
return genpd_finish_suspend(dev,
1312+
pm_generic_freeze_noirq,
1313+
pm_generic_thaw_noirq);
13141314
}
13151315

13161316
/**
@@ -1322,23 +1322,9 @@ static int genpd_freeze_noirq(struct device *dev)
13221322
*/
13231323
static int genpd_thaw_noirq(struct device *dev)
13241324
{
1325-
const struct generic_pm_domain *genpd;
1326-
int ret = 0;
1327-
13281325
dev_dbg(dev, "%s()\n", __func__);
13291326

1330-
genpd = dev_to_genpd(dev);
1331-
if (IS_ERR(genpd))
1332-
return -EINVAL;
1333-
1334-
if (genpd->dev_ops.stop && genpd->dev_ops.start &&
1335-
!pm_runtime_status_suspended(dev)) {
1336-
ret = genpd_start_dev(genpd, dev);
1337-
if (ret)
1338-
return ret;
1339-
}
1340-
1341-
return pm_generic_thaw_noirq(dev);
1327+
return genpd_finish_resume(dev, pm_generic_thaw_noirq);
13421328
}
13431329

13441330
/**
@@ -1353,7 +1339,9 @@ static int genpd_poweroff_noirq(struct device *dev)
13531339
{
13541340
dev_dbg(dev, "%s()\n", __func__);
13551341

1356-
return genpd_finish_suspend(dev, true);
1342+
return genpd_finish_suspend(dev,
1343+
pm_generic_poweroff_noirq,
1344+
pm_generic_restore_noirq);
13571345
}
13581346

13591347
/**
@@ -1365,40 +1353,9 @@ static int genpd_poweroff_noirq(struct device *dev)
13651353
*/
13661354
static int genpd_restore_noirq(struct device *dev)
13671355
{
1368-
struct generic_pm_domain *genpd;
1369-
int ret = 0;
1370-
13711356
dev_dbg(dev, "%s()\n", __func__);
13721357

1373-
genpd = dev_to_genpd(dev);
1374-
if (IS_ERR(genpd))
1375-
return -EINVAL;
1376-
1377-
/*
1378-
* At this point suspended_count == 0 means we are being run for the
1379-
* first time for the given domain in the present cycle.
1380-
*/
1381-
genpd_lock(genpd);
1382-
if (genpd->suspended_count++ == 0) {
1383-
/*
1384-
* The boot kernel might put the domain into arbitrary state,
1385-
* so make it appear as powered off to genpd_sync_power_on(),
1386-
* so that it tries to power it on in case it was really off.
1387-
*/
1388-
genpd->status = GENPD_STATE_OFF;
1389-
}
1390-
1391-
genpd_sync_power_on(genpd, true, 0);
1392-
genpd_unlock(genpd);
1393-
1394-
if (genpd->dev_ops.stop && genpd->dev_ops.start &&
1395-
!pm_runtime_status_suspended(dev)) {
1396-
ret = genpd_start_dev(genpd, dev);
1397-
if (ret)
1398-
return ret;
1399-
}
1400-
1401-
return pm_generic_restore_noirq(dev);
1358+
return genpd_finish_resume(dev, pm_generic_restore_noirq);
14021359
}
14031360

14041361
/**
@@ -2749,17 +2706,6 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
27492706
dev->pm_domain->detach = genpd_dev_pm_detach;
27502707
dev->pm_domain->sync = genpd_dev_pm_sync;
27512708

2752-
if (power_on) {
2753-
genpd_lock(pd);
2754-
ret = genpd_power_on(pd, 0);
2755-
genpd_unlock(pd);
2756-
}
2757-
2758-
if (ret) {
2759-
genpd_remove_device(pd, dev);
2760-
return -EPROBE_DEFER;
2761-
}
2762-
27632709
/* Set the default performance state */
27642710
pstate = of_get_required_opp_performance_state(dev->of_node, index);
27652711
if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) {
@@ -2771,6 +2717,24 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
27712717
goto err;
27722718
dev_gpd_data(dev)->default_pstate = pstate;
27732719
}
2720+
2721+
if (power_on) {
2722+
genpd_lock(pd);
2723+
ret = genpd_power_on(pd, 0);
2724+
genpd_unlock(pd);
2725+
}
2726+
2727+
if (ret) {
2728+
/* Drop the default performance state */
2729+
if (dev_gpd_data(dev)->default_pstate) {
2730+
dev_pm_genpd_set_performance_state(dev, 0);
2731+
dev_gpd_data(dev)->default_pstate = 0;
2732+
}
2733+
2734+
genpd_remove_device(pd, dev);
2735+
return -EPROBE_DEFER;
2736+
}
2737+
27742738
return 1;
27752739

27762740
err:

drivers/cpuidle/cpuidle-psci-domain.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
181181
if (ret)
182182
goto remove_pd;
183183

184-
pr_info("Initialized CPU PM domain topology\n");
184+
pr_info("Initialized CPU PM domain topology using %s mode\n",
185+
use_osi ? "OSI" : "PC");
185186
return 0;
186187

187188
put_node:

drivers/cpuidle/dt_idle_states.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -211,18 +211,15 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
211211
of_node_put(cpu_node);
212212
if (err)
213213
return err;
214-
/*
215-
* Update the driver state count only if some valid DT idle states
216-
* were detected
217-
*/
218-
if (i)
219-
drv->state_count = state_idx;
214+
215+
/* Set the number of total supported idle states. */
216+
drv->state_count = state_idx;
220217

221218
/*
222219
* Return the number of present and valid DT idle states, which can
223220
* also be 0 on platforms with missing DT idle states or legacy DT
224221
* configuration predating the DT idle states bindings.
225222
*/
226-
return i;
223+
return state_idx - start_idx;
227224
}
228225
EXPORT_SYMBOL_GPL(dt_init_idle_driver);

kernel/power/process.c

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;
2727

2828
static int try_to_freeze_tasks(bool user_only)
2929
{
30+
const char *what = user_only ? "user space processes" :
31+
"remaining freezable tasks";
3032
struct task_struct *g, *p;
3133
unsigned long end_time;
3234
unsigned int todo;
@@ -36,6 +38,8 @@ static int try_to_freeze_tasks(bool user_only)
3638
bool wakeup = false;
3739
int sleep_usecs = USEC_PER_MSEC;
3840

41+
pr_info("Freezing %s\n", what);
42+
3943
start = ktime_get_boottime();
4044

4145
end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
@@ -82,9 +86,8 @@ static int try_to_freeze_tasks(bool user_only)
8286
elapsed_msecs = ktime_to_ms(elapsed);
8387

8488
if (todo) {
85-
pr_cont("\n");
86-
pr_err("Freezing of tasks %s after %d.%03d seconds "
87-
"(%d tasks refusing to freeze, wq_busy=%d):\n",
89+
pr_err("Freezing %s %s after %d.%03d seconds "
90+
"(%d tasks refusing to freeze, wq_busy=%d):\n", what,
8891
wakeup ? "aborted" : "failed",
8992
elapsed_msecs / 1000, elapsed_msecs % 1000,
9093
todo - wq_busy, wq_busy);
@@ -101,8 +104,8 @@ static int try_to_freeze_tasks(bool user_only)
101104
read_unlock(&tasklist_lock);
102105
}
103106
} else {
104-
pr_cont("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
105-
elapsed_msecs % 1000);
107+
pr_info("Freezing %s completed (elapsed %d.%03d seconds)\n",
108+
what, elapsed_msecs / 1000, elapsed_msecs % 1000);
106109
}
107110

108111
return todo ? -EBUSY : 0;
@@ -130,14 +133,11 @@ int freeze_processes(void)
130133
static_branch_inc(&freezer_active);
131134

132135
pm_wakeup_clear(0);
133-
pr_info("Freezing user space processes ... ");
134136
pm_freezing = true;
135137
error = try_to_freeze_tasks(true);
136-
if (!error) {
138+
if (!error)
137139
__usermodehelper_set_disable_depth(UMH_DISABLED);
138-
pr_cont("done.");
139-
}
140-
pr_cont("\n");
140+
141141
BUG_ON(in_atomic());
142142

143143
/*
@@ -166,14 +166,9 @@ int freeze_kernel_threads(void)
166166
{
167167
int error;
168168

169-
pr_info("Freezing remaining freezable tasks ... ");
170-
171169
pm_nosig_freezing = true;
172170
error = try_to_freeze_tasks(false);
173-
if (!error)
174-
pr_cont("done.");
175171

176-
pr_cont("\n");
177172
BUG_ON(in_atomic());
178173

179174
if (error)

0 commit comments

Comments
 (0)