mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branches 'pm-sleep', 'pm-powercap' and 'pm-tools'
Merge updates related to system sleep support, two updates of the intel_rapl power capping driver, and a pm-graph utility fix for 7.2-rc1: - Add sysctl interface for DPM watchdog timeouts (Tzung-Bi Shih) - Use complete() instead of complete_all() in device_pm_sleep_init() to avoid a false-positive warning from lockdep_assert_RT_in_threaded_ctx() when CONFIG_PROVE_RAW_LOCK_NESTING is enabled (Jiakai Xu) - Use a flexible array for CRC uncompressed buffers during hibernation image saving (Rosen Penev) - Make the LZ4 algorithm available for hibernation compression (l1rox3) - Move the preallocate_image() call during hibernation after the "prepare" phase of the "freeze" transition (Matthew Leach) - Fix a memory leak in rapl_add_package_cpuslocked() in the intel_rapl power capping driver and use sysfs_emit() in cpumask_show() in that driver (Sumeet Pawnikar, Yury Norov) - Fix ValueError when parsing incomplete device properties in the pm-graph utility (Gongwei Li) * pm-sleep: PM: dpm_watchdog: Add sysctl interface for DPM watchdog timeouts PM: hibernate: Use flexible array for CRC uncompressed buffers PM: hibernate: make LZ4 available for hibernation compression PM: sleep: Use complete() in device_pm_sleep_init() PM: hibernate: call preallocate_image() after freeze prepare * pm-powercap: powercap: intel_rapl: Use sysfs_emit() in cpumask_show() powercap: intel_rapl: Fix memory leak in rapl_add_package_cpuslocked() * pm-tools: PM: tools: pm-graph: fix ValueError when parsing incomplete device properties
This commit is contained in:
commit
5ca48f6f2a
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <trace/events/power.h>
|
||||
|
|
@ -115,7 +116,7 @@ void device_pm_sleep_init(struct device *dev)
|
|||
dev->power.is_noirq_suspended = false;
|
||||
dev->power.is_late_suspended = false;
|
||||
init_completion(&dev->power.completion);
|
||||
complete_all(&dev->power.completion);
|
||||
complete(&dev->power.completion);
|
||||
dev->power.wakeup = NULL;
|
||||
INIT_LIST_HEAD(&dev->power.entry);
|
||||
}
|
||||
|
|
@ -252,6 +253,10 @@ static void dpm_wait(struct device *dev, bool async)
|
|||
if (!dev)
|
||||
return;
|
||||
|
||||
/* Devices with no PM support don't use the completion. */
|
||||
if (dev->power.no_pm)
|
||||
return;
|
||||
|
||||
if (async || (pm_async_enabled && dev->power.async_suspend))
|
||||
wait_for_completion(&dev->power.completion);
|
||||
}
|
||||
|
|
@ -527,6 +532,58 @@ module_param(dpm_watchdog_all_cpu_backtrace, bool, 0644);
|
|||
MODULE_PARM_DESC(dpm_watchdog_all_cpu_backtrace,
|
||||
"Backtrace all CPUs on DPM watchdog timeout");
|
||||
|
||||
static unsigned int __read_mostly dpm_watchdog_timeout = CONFIG_DPM_WATCHDOG_TIMEOUT;
|
||||
static unsigned int __read_mostly dpm_watchdog_warning_timeout =
|
||||
CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
|
||||
static const unsigned int dpm_watchdog_timeout_max = CONFIG_DPM_WATCHDOG_TIMEOUT;
|
||||
|
||||
static int proc_dodpm_watchdog_timeout_secs(const struct ctl_table *table,
|
||||
int write, void *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct ctl_table ctl = *table;
|
||||
unsigned int val = dpm_watchdog_timeout;
|
||||
int ret;
|
||||
|
||||
ctl.data = &val;
|
||||
ret = proc_douintvec_minmax(&ctl, write, buffer, lenp, ppos);
|
||||
if (ret || !write)
|
||||
return ret;
|
||||
|
||||
if (val < dpm_watchdog_warning_timeout)
|
||||
dpm_watchdog_warning_timeout = val;
|
||||
dpm_watchdog_timeout = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ctl_table dpm_watchdog_sysctls[] = {
|
||||
{
|
||||
.procname = "dpm_watchdog_timeout_secs",
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dodpm_watchdog_timeout_secs,
|
||||
.extra1 = SYSCTL_ONE,
|
||||
.extra2 = (void *)&dpm_watchdog_timeout_max,
|
||||
},
|
||||
{
|
||||
.procname = "dpm_watchdog_warning_timeout_secs",
|
||||
.data = &dpm_watchdog_warning_timeout,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_douintvec_minmax,
|
||||
.extra1 = SYSCTL_ONE,
|
||||
.extra2 = (void *)&dpm_watchdog_timeout,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init dpm_watchdog_sysctl_init(void)
|
||||
{
|
||||
register_sysctl_init("kernel", dpm_watchdog_sysctls);
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(dpm_watchdog_sysctl_init);
|
||||
|
||||
/**
|
||||
* dpm_watchdog_handler - Driver suspend / resume watchdog handler.
|
||||
* @t: The timer that PM watchdog depends on.
|
||||
|
|
@ -552,9 +609,9 @@ static void dpm_watchdog_handler(struct timer_list *t)
|
|||
dev_driver_string(wd->dev), dev_name(wd->dev));
|
||||
}
|
||||
|
||||
time_left = CONFIG_DPM_WATCHDOG_TIMEOUT - CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
|
||||
time_left = dpm_watchdog_timeout - dpm_watchdog_warning_timeout;
|
||||
dev_warn(wd->dev, "**** DPM device timeout after %u seconds; %u seconds until panic ****\n",
|
||||
CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT, time_left);
|
||||
dpm_watchdog_warning_timeout, time_left);
|
||||
show_stack(wd->tsk, NULL, KERN_WARNING);
|
||||
|
||||
wd->fatal = true;
|
||||
|
|
@ -572,11 +629,11 @@ static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
|
|||
|
||||
wd->dev = dev;
|
||||
wd->tsk = current;
|
||||
wd->fatal = CONFIG_DPM_WATCHDOG_TIMEOUT == CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
|
||||
wd->fatal = dpm_watchdog_timeout == dpm_watchdog_warning_timeout;
|
||||
|
||||
timer_setup_on_stack(timer, dpm_watchdog_handler, 0);
|
||||
/* use same timeout value for both suspend and resume */
|
||||
timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_WARNING_TIMEOUT;
|
||||
timer->expires = jiffies + HZ * dpm_watchdog_warning_timeout;
|
||||
add_timer(timer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1441,7 +1441,7 @@ static ssize_t cpumask_show(struct device *dev,
|
|||
}
|
||||
cpus_read_unlock();
|
||||
|
||||
ret = cpumap_print_to_pagebuf(true, buf, cpu_mask);
|
||||
ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpu_mask));
|
||||
|
||||
free_cpumask_var(cpu_mask);
|
||||
|
||||
|
|
@ -1770,7 +1770,8 @@ struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *pr
|
|||
topology_physical_package_id(id) : topology_logical_die_id(id);
|
||||
if ((int)(rp->id) < 0) {
|
||||
pr_err("topology_logical_(package/die)_id() returned a negative value");
|
||||
return ERR_PTR(-EINVAL);
|
||||
ret = -EINVAL;
|
||||
goto err_free_package;
|
||||
}
|
||||
rp->lead_cpu = id;
|
||||
if (!rapl_msrs_are_pkg_scope() && topology_max_dies_per_package() > 1)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ config HIBERNATION
|
|||
select CRC32
|
||||
select CRYPTO
|
||||
select CRYPTO_LZO
|
||||
select CRYPTO_LZ4
|
||||
help
|
||||
Enable the suspend to disk (STD) functionality, which is usually
|
||||
called "hibernation" in user interfaces. STD checkpoints the
|
||||
|
|
|
|||
|
|
@ -392,23 +392,6 @@ static int create_image(int platform_mode)
|
|||
return error;
|
||||
}
|
||||
|
||||
static void shrink_shmem_memory(void)
|
||||
{
|
||||
struct sysinfo info;
|
||||
unsigned long nr_shmem_pages, nr_freed_pages;
|
||||
|
||||
si_meminfo(&info);
|
||||
nr_shmem_pages = info.sharedram; /* current page count used for shmem */
|
||||
/*
|
||||
* The intent is to reclaim all shmem pages. Though shrink_all_memory() can
|
||||
* only reclaim about half of them, it's enough for creating the hibernation
|
||||
* image.
|
||||
*/
|
||||
nr_freed_pages = shrink_all_memory(nr_shmem_pages);
|
||||
pr_debug("requested to reclaim %lu shmem pages, actually freed %lu pages\n",
|
||||
nr_shmem_pages, nr_freed_pages);
|
||||
}
|
||||
|
||||
/**
|
||||
* hibernation_snapshot - Quiesce devices and create a hibernation image.
|
||||
* @platform_mode: If set, use platform driver to prepare for the transition.
|
||||
|
|
@ -425,14 +408,9 @@ int hibernation_snapshot(int platform_mode)
|
|||
if (error)
|
||||
goto Close;
|
||||
|
||||
/* Preallocate image memory before shutting down devices. */
|
||||
error = hibernate_preallocate_memory();
|
||||
if (error)
|
||||
goto Close;
|
||||
|
||||
error = freeze_kernel_threads();
|
||||
if (error)
|
||||
goto Cleanup;
|
||||
goto Close;
|
||||
|
||||
if (hibernation_test(TEST_FREEZER)) {
|
||||
|
||||
|
|
@ -445,19 +423,13 @@ int hibernation_snapshot(int platform_mode)
|
|||
}
|
||||
|
||||
error = dpm_prepare(PMSG_FREEZE);
|
||||
if (error) {
|
||||
dpm_complete(PMSG_RECOVER);
|
||||
goto Thaw;
|
||||
}
|
||||
if (error)
|
||||
goto Complete;
|
||||
|
||||
/*
|
||||
* Device drivers may move lots of data to shmem in dpm_prepare(). The shmem
|
||||
* pages will use lots of system memory, causing hibernation image creation
|
||||
* fail due to insufficient free memory.
|
||||
* This call is to force flush the shmem pages to swap disk and reclaim
|
||||
* the system memory so that image creation can succeed.
|
||||
*/
|
||||
shrink_shmem_memory();
|
||||
/* Preallocate image memory before shutting down devices. */
|
||||
error = hibernate_preallocate_memory();
|
||||
if (error)
|
||||
goto Complete;
|
||||
|
||||
console_suspend_all();
|
||||
pm_restrict_gfp_mask();
|
||||
|
|
@ -492,10 +464,10 @@ int hibernation_snapshot(int platform_mode)
|
|||
platform_end(platform_mode);
|
||||
return error;
|
||||
|
||||
Complete:
|
||||
dpm_complete(PMSG_RECOVER);
|
||||
Thaw:
|
||||
thaw_kernel_threads();
|
||||
Cleanup:
|
||||
swsusp_free();
|
||||
goto Close;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -570,29 +570,23 @@ struct crc_data {
|
|||
wait_queue_head_t done; /* crc update done */
|
||||
u32 *crc32; /* points to handle's crc32 */
|
||||
size_t **unc_len; /* uncompressed lengths */
|
||||
unsigned char **unc; /* uncompressed data */
|
||||
unsigned char *unc[]; /* uncompressed data */
|
||||
};
|
||||
|
||||
static struct crc_data *alloc_crc_data(int nr_threads)
|
||||
{
|
||||
struct crc_data *crc;
|
||||
|
||||
crc = kzalloc_obj(*crc);
|
||||
crc = kzalloc_flex(*crc, unc, nr_threads);
|
||||
if (!crc)
|
||||
return NULL;
|
||||
|
||||
crc->unc = kcalloc(nr_threads, sizeof(*crc->unc), GFP_KERNEL);
|
||||
if (!crc->unc)
|
||||
goto err_free_crc;
|
||||
|
||||
crc->unc_len = kzalloc_objs(*crc->unc_len, nr_threads);
|
||||
if (!crc->unc_len)
|
||||
goto err_free_unc;
|
||||
goto err_free_crc;
|
||||
|
||||
return crc;
|
||||
|
||||
err_free_unc:
|
||||
kfree(crc->unc);
|
||||
err_free_crc:
|
||||
kfree(crc);
|
||||
return NULL;
|
||||
|
|
@ -607,7 +601,6 @@ static void free_crc_data(struct crc_data *crc)
|
|||
kthread_stop(crc->thr);
|
||||
|
||||
kfree(crc->unc_len);
|
||||
kfree(crc->unc);
|
||||
kfree(crc);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3155,7 +3155,7 @@ class TestProps:
|
|||
dev = f[0]
|
||||
props[dev] = DevProps()
|
||||
props[dev].altname = f[1]
|
||||
if int(f[2]):
|
||||
if len(f) > 2 and f[2] and int(f[2]):
|
||||
props[dev].isasync = True
|
||||
else:
|
||||
props[dev].isasync = False
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user