diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e1b550664bab..f71467f6ada4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -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); } diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index a8dd02dff0a0..1006d183d508 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -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) diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 05337f437cca..530c897311d4 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -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 diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index af8d07bafe02..d2479c69d71a 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -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; } diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 2e64869bb5a0..b28233b8d00e 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -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); } diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py index 1555b51a7d55..f6d172254829 100755 --- a/tools/power/pm-graph/sleepgraph.py +++ b/tools/power/pm-graph/sleepgraph.py @@ -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