From db597605821fccc49876705aea5db5443d67e53e Mon Sep 17 00:00:00 2001 From: Tina Ruchandani Date: Thu, 30 Oct 2014 11:04:53 -0700 Subject: [PATCH 01/10] PM / Hibernate: Migrate to ktime_t This patch migrates swsusp_show_speed and its callers to using ktime_t instead of 'struct timeval' which suffers from the y2038 problem. Changes to swsusp_show_speed: - use ktime_t for start and stop times - pass start and stop times by value Calling functions affected: - load_image - load_image_lzo - save_image - save_image_lzo - hibernate_preallocate_memory Design decisions: - use ktime_t to preserve same granularity of reporting as before - use centisecs logic as before to avoid 'div by zero' issues caused by using seconds and nanoseconds directly - use monotonic time (ktime_get()) since we only care about elapsed time. Signed-off-by: Tina Ruchandani Suggested-by: Arnd Bergmann Reviewed-by: Arnd Bergmann Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- kernel/power/hibernate.c | 14 ++++++-------- kernel/power/power.h | 3 +-- kernel/power/snapshot.c | 9 +++++---- kernel/power/swap.c | 41 ++++++++++++++++++++-------------------- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 1f35a3478f3c..2329daae5255 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "power.h" @@ -232,20 +233,17 @@ static void platform_recover(int platform_mode) * @nr_pages: Number of memory pages processed between @start and @stop. * @msg: Additional diagnostic message to print. */ -void swsusp_show_speed(struct timeval *start, struct timeval *stop, - unsigned nr_pages, char *msg) +void swsusp_show_speed(ktime_t start, ktime_t stop, + unsigned nr_pages, char *msg) { + ktime_t diff; u64 elapsed_centisecs64; unsigned int centisecs; unsigned int k; unsigned int kps; - elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start); - /* - * If "(s64)elapsed_centisecs64 < 0", it will print long elapsed time, - * it is obvious enough for what went wrong. - */ - do_div(elapsed_centisecs64, NSEC_PER_SEC / 100); + diff = ktime_sub(stop, start); + elapsed_centisecs64 = ktime_divns(diff, 10*NSEC_PER_MSEC); centisecs = elapsed_centisecs64; if (centisecs == 0) centisecs = 1; /* avoid div-by-zero */ diff --git a/kernel/power/power.h b/kernel/power/power.h index 2df883a9d3cb..ce9b8328a689 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -174,8 +174,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain); struct timeval; /* kernel/power/swsusp.c */ -extern void swsusp_show_speed(struct timeval *, struct timeval *, - unsigned int, char *); +extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *); #ifdef CONFIG_SUSPEND /* kernel/power/suspend.c */ diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 791a61892bb5..0c40c16174b4 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1576,11 +1577,11 @@ int hibernate_preallocate_memory(void) struct zone *zone; unsigned long saveable, size, max_size, count, highmem, pages = 0; unsigned long alloc, save_highmem, pages_highmem, avail_normal; - struct timeval start, stop; + ktime_t start, stop; int error; printk(KERN_INFO "PM: Preallocating image memory... "); - do_gettimeofday(&start); + start = ktime_get(); error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY); if (error) @@ -1709,9 +1710,9 @@ int hibernate_preallocate_memory(void) free_unnecessary_pages(); out: - do_gettimeofday(&stop); + stop = ktime_get(); printk(KERN_CONT "done (allocated %lu pages)\n", pages); - swsusp_show_speed(&start, &stop, pages, "Allocated"); + swsusp_show_speed(start, stop, pages, "Allocated"); return 0; diff --git a/kernel/power/swap.c b/kernel/power/swap.c index aaa3261dea5d..2c9d6d50a816 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "power.h" @@ -445,8 +446,8 @@ static int save_image(struct swap_map_handle *handle, int nr_pages; int err2; struct bio *bio; - struct timeval start; - struct timeval stop; + ktime_t start; + ktime_t stop; printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n", nr_to_write); @@ -455,7 +456,7 @@ static int save_image(struct swap_map_handle *handle, m = 1; nr_pages = 0; bio = NULL; - do_gettimeofday(&start); + start = ktime_get(); while (1) { ret = snapshot_read_next(snapshot); if (ret <= 0) @@ -469,12 +470,12 @@ static int save_image(struct swap_map_handle *handle, nr_pages++; } err2 = hib_wait_on_bio_chain(&bio); - do_gettimeofday(&stop); + stop = ktime_get(); if (!ret) ret = err2; if (!ret) printk(KERN_INFO "PM: Image saving done.\n"); - swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); + swsusp_show_speed(start, stop, nr_to_write, "Wrote"); return ret; } @@ -580,8 +581,8 @@ static int save_image_lzo(struct swap_map_handle *handle, int nr_pages; int err2; struct bio *bio; - struct timeval start; - struct timeval stop; + ktime_t start; + ktime_t stop; size_t off; unsigned thr, run_threads, nr_threads; unsigned char *page = NULL; @@ -674,7 +675,7 @@ static int save_image_lzo(struct swap_map_handle *handle, m = 1; nr_pages = 0; bio = NULL; - do_gettimeofday(&start); + start = ktime_get(); for (;;) { for (thr = 0; thr < nr_threads; thr++) { for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) { @@ -759,12 +760,12 @@ static int save_image_lzo(struct swap_map_handle *handle, out_finish: err2 = hib_wait_on_bio_chain(&bio); - do_gettimeofday(&stop); + stop = ktime_get(); if (!ret) ret = err2; if (!ret) printk(KERN_INFO "PM: Image saving done.\n"); - swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); + swsusp_show_speed(start, stop, nr_to_write, "Wrote"); out_clean: if (crc) { if (crc->thr) @@ -965,8 +966,8 @@ static int load_image(struct swap_map_handle *handle, { unsigned int m; int ret = 0; - struct timeval start; - struct timeval stop; + ktime_t start; + ktime_t stop; struct bio *bio; int err2; unsigned nr_pages; @@ -978,7 +979,7 @@ static int load_image(struct swap_map_handle *handle, m = 1; nr_pages = 0; bio = NULL; - do_gettimeofday(&start); + start = ktime_get(); for ( ; ; ) { ret = snapshot_write_next(snapshot); if (ret <= 0) @@ -996,7 +997,7 @@ static int load_image(struct swap_map_handle *handle, nr_pages++; } err2 = hib_wait_on_bio_chain(&bio); - do_gettimeofday(&stop); + stop = ktime_get(); if (!ret) ret = err2; if (!ret) { @@ -1005,7 +1006,7 @@ static int load_image(struct swap_map_handle *handle, if (!snapshot_image_loaded(snapshot)) ret = -ENODATA; } - swsusp_show_speed(&start, &stop, nr_to_read, "Read"); + swsusp_show_speed(start, stop, nr_to_read, "Read"); return ret; } @@ -1067,8 +1068,8 @@ static int load_image_lzo(struct swap_map_handle *handle, int ret = 0; int eof = 0; struct bio *bio; - struct timeval start; - struct timeval stop; + ktime_t start; + ktime_t stop; unsigned nr_pages; size_t off; unsigned i, thr, run_threads, nr_threads; @@ -1190,7 +1191,7 @@ static int load_image_lzo(struct swap_map_handle *handle, m = 1; nr_pages = 0; bio = NULL; - do_gettimeofday(&start); + start = ktime_get(); ret = snapshot_write_next(snapshot); if (ret <= 0) @@ -1343,7 +1344,7 @@ out_finish: wait_event(crc->done, atomic_read(&crc->stop)); atomic_set(&crc->stop, 0); } - do_gettimeofday(&stop); + stop = ktime_get(); if (!ret) { printk(KERN_INFO "PM: Image loading done.\n"); snapshot_write_finalize(snapshot); @@ -1359,7 +1360,7 @@ out_finish: } } } - swsusp_show_speed(&start, &stop, nr_to_read, "Read"); + swsusp_show_speed(start, stop, nr_to_read, "Read"); out_clean: for (i = 0; i < ring_size; i++) free_page((unsigned long)page[i]); From 895b31f3b6b800b8f46569391f2396b1f221c602 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:37:39 +0100 Subject: [PATCH 02/10] PM / Domains: Make genpd parameter of pm_genpd_present() const The PM domain pointed to by the genpd parameter is never modified. Signed-off-by: Geert Uytterhoeven Acked-by: Kevin Hilman Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 40bc2f4072cc..28d6e8bf746c 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -753,9 +753,9 @@ static inline void genpd_power_off_work_fn(struct work_struct *work) {} * pm_genpd_present - Check if the given PM domain has been initialized. * @genpd: PM domain to check. */ -static bool pm_genpd_present(struct generic_pm_domain *genpd) +static bool pm_genpd_present(const struct generic_pm_domain *genpd) { - struct generic_pm_domain *gpd; + const struct generic_pm_domain *gpd; if (IS_ERR_OR_NULL(genpd)) return false; From c8f0ea45169c57f36e6d8c4dcf7ccf09de7f1c2c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:39:19 +0100 Subject: [PATCH 03/10] PM / Domains: Extract code to power off/on a PM domain PM domains are powered on/off from various places. Some callers do latency measurements, others don't. Consolidate using two helper functions, which always measure the latencies, and update the stored latencies when needed. Other minor changes: - Use pr_warn() instead of pr_warning(), - There's no need to check genpd->name, %s handles NULL pointers fine, - Make the warning format strings identical, to save memory. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Reviewed-by: Kevin Hilman Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 101 +++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 28d6e8bf746c..1d1f5cc4293d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -151,6 +151,59 @@ static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd) genpd->cpuidle_data->idle_state->exit_latency = usecs64; } +static int genpd_power_on(struct generic_pm_domain *genpd) +{ + ktime_t time_start; + s64 elapsed_ns; + int ret; + + if (!genpd->power_on) + return 0; + + time_start = ktime_get(); + ret = genpd->power_on(genpd); + if (ret) + return ret; + + elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); + if (elapsed_ns <= genpd->power_on_latency_ns) + return ret; + + genpd->power_on_latency_ns = elapsed_ns; + genpd->max_off_time_changed = true; + genpd_recalc_cpu_exit_latency(genpd); + pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", + genpd->name, "on", elapsed_ns); + + return ret; +} + +static int genpd_power_off(struct generic_pm_domain *genpd) +{ + ktime_t time_start; + s64 elapsed_ns; + int ret; + + if (!genpd->power_off) + return 0; + + time_start = ktime_get(); + ret = genpd->power_off(genpd); + if (ret == -EBUSY) + return ret; + + elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); + if (elapsed_ns <= genpd->power_off_latency_ns) + return ret; + + genpd->power_off_latency_ns = elapsed_ns; + genpd->max_off_time_changed = true; + pr_warn("%s: Power-%s latency exceeded, new value %lld ns\n", + genpd->name, "off", elapsed_ns); + + return ret; +} + /** * __pm_genpd_poweron - Restore power to a given PM domain and its masters. * @genpd: PM domain to power up. @@ -222,25 +275,9 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd) } } - if (genpd->power_on) { - ktime_t time_start = ktime_get(); - s64 elapsed_ns; - - ret = genpd->power_on(genpd); - if (ret) - goto err; - - elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - if (elapsed_ns > genpd->power_on_latency_ns) { - genpd->power_on_latency_ns = elapsed_ns; - genpd->max_off_time_changed = true; - genpd_recalc_cpu_exit_latency(genpd); - if (genpd->name) - pr_warning("%s: Power-on latency exceeded, " - "new value %lld ns\n", genpd->name, - elapsed_ns); - } - } + ret = genpd_power_on(genpd); + if (ret) + goto err; out: genpd_set_active(genpd); @@ -529,16 +566,11 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) } if (genpd->power_off) { - ktime_t time_start; - s64 elapsed_ns; - if (atomic_read(&genpd->sd_count) > 0) { ret = -EBUSY; goto out; } - time_start = ktime_get(); - /* * If sd_count > 0 at this point, one of the subdomains hasn't * managed to call pm_genpd_poweron() for the master yet after @@ -547,21 +579,11 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) * the pm_genpd_poweron() restore power for us (this shouldn't * happen very often). */ - ret = genpd->power_off(genpd); + ret = genpd_power_off(genpd); if (ret == -EBUSY) { genpd_set_active(genpd); goto out; } - - elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - if (elapsed_ns > genpd->power_off_latency_ns) { - genpd->power_off_latency_ns = elapsed_ns; - genpd->max_off_time_changed = true; - if (genpd->name) - pr_warning("%s: Power-off latency exceeded, " - "new value %lld ns\n", genpd->name, - elapsed_ns); - } } genpd->status = GPD_STATE_POWER_OFF; @@ -796,8 +818,7 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd) || atomic_read(&genpd->sd_count) > 0) return; - if (genpd->power_off) - genpd->power_off(genpd); + genpd_power_off(genpd); genpd->status = GPD_STATE_POWER_OFF; @@ -828,8 +849,7 @@ static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd) genpd_sd_counter_inc(link->master); } - if (genpd->power_on) - genpd->power_on(genpd); + genpd_power_on(genpd); genpd->status = GPD_STATE_ACTIVE; } @@ -1251,8 +1271,7 @@ static int pm_genpd_restore_noirq(struct device *dev) * If the domain was off before the hibernation, make * sure it will be off going forward. */ - if (genpd->power_off) - genpd->power_off(genpd); + genpd_power_off(genpd); return 0; } From 00e7c295968d74f4dbb00aef8334fafe788e3c89 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 14 Nov 2014 08:41:32 +0100 Subject: [PATCH 04/10] PM / Domains: Move struct pm_domain_data to pm_domain.h The definition of the struct pm_domain_data better belongs in the header for the PM domains, let's move it there. Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 6 +----- include/linux/pm_domain.h | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/pm.h b/include/linux/pm.h index 383fd68aaee1..45e3e78c1e3a 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -538,11 +538,7 @@ enum rpm_request { }; struct wakeup_source; - -struct pm_domain_data { - struct list_head list_node; - struct device *dev; -}; +struct pm_domain_data; struct pm_subsys_data { spinlock_t lock; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 73e938b7e937..86689b59ce5b 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -98,6 +98,11 @@ struct gpd_timing_data { bool cached_stop_ok; }; +struct pm_domain_data { + struct list_head list_node; + struct device *dev; +}; + struct generic_pm_domain_data { struct pm_domain_data base; struct gpd_timing_data td; From 6c45de0d51a3d93267ee100bff8c4632b1d49e8f Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 16 Nov 2014 14:18:28 +0100 Subject: [PATCH 05/10] PM / hibernate: Deletion of an unnecessary check before the function call "vfree" The vfree() function performs also input parameter validation. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Rafael J. Wysocki --- kernel/power/swap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 2c9d6d50a816..570aff817543 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -1375,7 +1375,7 @@ out_clean: kthread_stop(data[thr].thr); vfree(data); } - if (page) vfree(page); + vfree(page); return ret; } From 2ed127697eb1376645cbcfa08a13dda157233c9d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 17 Nov 2014 16:19:10 +0100 Subject: [PATCH 06/10] PM / Domains: Power on the PM domain right after attach completes Vast amount of platform drivers which enables runtime PM, don't invoke a pm_runtime_get_sync() while probing their devices. Instead, once they have turned on their PM resourses during ->probe() and are ready to handle I/O, these invokes pm_runtime_set_active() to synchronize its state towards the runtime PM core. From the runtime PM point of view this behavior is perfectly acceptable, but we encounter probe failures if their corresponding devices resides in the generic PM domain. The issues are observed for those devices, which requires its PM domain to stay powered during ->probe() since that's not being controlled. While using the generic OF-based PM domain look-up, a device's PM domain will be attached during the probe sequence. For this path, let's fix the probe failures, by simply power on the PM domain right after when it's been attached to the device. The generic PM domain stays powered until all of its devices becomes runtime PM enabled and runtime PM suspended. The old SOCs which makes use of the generic PM domain but don't use the generic OF-based PM domain look-up, will not be affected from this change. Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 3989eb63d538..1bfb54ce60e8 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2235,6 +2235,7 @@ int genpd_dev_pm_attach(struct device *dev) } dev->pm_domain->detach = genpd_dev_pm_detach; + pm_genpd_poweron(pd); return 0; } From c11f6f5bb1e07db79c4c97d768b32b63378c69e0 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 1 Dec 2014 12:50:21 +0100 Subject: [PATCH 07/10] PM / Domains: Initial PM clock support for genpd It's quite common for PM domains to use PM clocks. Typically from SOC specific code, the per device PM clock list is created and pm_clk_suspend|resume() are invoked to handle clock gating/ungating. A step towards consolidation is to integrate PM clock support into genpd, which is what this patch does. In this initial step, the calls to the pm_clk_suspend|resume() are handled within genpd, but the per device PM clock list still needs to be created from SOC specific code. It seems reasonable to have gendp to handle that as well, but that left to future patches to address. It's not every users of genpd that are keen on using PM clocks, thus we need to provide this a configuration option for genpd. Therefore let's add flag field in the genpd struct to keep this information and define a new GENDP_FLAG_PM_CLK bit for it. Signed-off-by: Ulf Hansson Acked-by: Geert Uytterhoeven Acked-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 7 +++++++ include/linux/pm_domain.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 1bfb54ce60e8..5d7b7548873a 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1948,6 +1949,12 @@ void pm_genpd_init(struct generic_pm_domain *genpd, genpd->domain.ops.complete = pm_genpd_complete; genpd->dev_ops.save_state = pm_genpd_default_save_state; genpd->dev_ops.restore_state = pm_genpd_default_restore_state; + + if (genpd->flags & GENPD_FLAG_PM_CLK) { + genpd->dev_ops.stop = pm_clk_suspend; + genpd->dev_ops.start = pm_clk_resume; + } + mutex_lock(&gpd_list_lock); list_add(&genpd->gpd_list_node, &gpd_list); mutex_unlock(&gpd_list_lock); diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 9d254e25f866..1dd6c7f64166 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -17,6 +17,9 @@ #include #include +/* Defines used for the flags field in the struct generic_pm_domain */ +#define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */ + enum gpd_status { GPD_STATE_ACTIVE = 0, /* PM domain is active */ GPD_STATE_WAIT_MASTER, /* PM domain's master is being waited for */ @@ -76,6 +79,7 @@ struct generic_pm_domain { struct device *dev); void (*detach_dev)(struct generic_pm_domain *domain, struct device *dev); + unsigned int flags; /* Bit field of configs for genpd */ }; static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd) From 9c6a97362954555d666da0ca16ab7d50b1ec84c4 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 1 Dec 2014 12:50:22 +0100 Subject: [PATCH 08/10] ARM: shmobile: Convert to genpd flags for PM clocks for r8a7779 Instead of using the dev_ops ->stop|start() callbacks for genpd, let's convert to use genpd's flag field and set it to GENPD_FLAG_PM_CLK. Signed-off-by: Ulf Hansson Acked-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/pm-r8a7779.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c index 82fe3d7f9662..44a74c4c5a01 100644 --- a/arch/arm/mach-shmobile/pm-r8a7779.c +++ b/arch/arm/mach-shmobile/pm-r8a7779.c @@ -83,9 +83,8 @@ static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd) { struct generic_pm_domain *genpd = &r8a7779_pd->genpd; + genpd->flags = GENPD_FLAG_PM_CLK; pm_genpd_init(genpd, NULL, false); - genpd->dev_ops.stop = pm_clk_suspend; - genpd->dev_ops.start = pm_clk_resume; genpd->dev_ops.active_wakeup = pd_active_wakeup; genpd->power_off = pd_power_down; genpd->power_on = pd_power_up; From cffa91380d6dd29befe7608e052693698b78dc9c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 1 Dec 2014 12:50:23 +0100 Subject: [PATCH 09/10] ARM: shmobile: Convert to genpd flags for PM clocks for R-mobile Instead of using the dev_ops ->stop|start() callbacks for genpd, let's convert to use genpd's flag field and set it to GENPD_FLAG_PM_CLK. Signed-off-by: Ulf Hansson Acked-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-shmobile/pm-rmobile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index 717e6413d29c..6f7d56ecf969 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -106,9 +106,8 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) struct generic_pm_domain *genpd = &rmobile_pd->genpd; struct dev_power_governor *gov = rmobile_pd->gov; + genpd->flags = GENPD_FLAG_PM_CLK; pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); - genpd->dev_ops.stop = pm_clk_suspend; - genpd->dev_ops.start = pm_clk_resume; genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; genpd->power_off = rmobile_pd_power_down; genpd->power_on = rmobile_pd_power_up; From 16b7c275c055cc36218404b5d147be7f76575087 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Mon, 1 Dec 2014 09:39:22 -0500 Subject: [PATCH 10/10] tools: cpupower: fix return checks for sysfs_get_idlestate_count() Red Hat and Fedora use a bug reporting tool that gathers data about "broken" systems called sosreport. Among other things, it includes the output of 'cpupower idle-info'. Executing 'cpupower idle-info' on a system that has cpuidle disabled via 'cpuidle.off=1' results in a 300 second hang in the cpupower application. ie) [root@intel-brickland-05]# cpupower idle-info Could not determine cpuidle driver Analyzing CPU 0: Number of idle states: -19 [hang] The problem is that the cpupower code only checks for a zero return from sysfs_get_idlestate_count(). The function can return -ENODEV (-19) as above. This patch fixes callers to sysfs_get_idlestate_count() to check the right return values. Signed-off-by: Prarit Bhargava Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki --- tools/power/cpupower/utils/cpuidle-info.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index 75e66de7e7a7..458d69b444ad 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -22,13 +22,13 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) { - unsigned int idlestates, idlestate; + int idlestates, idlestate; char *tmp; printf(_ ("Analyzing CPU %d:\n"), cpu); idlestates = sysfs_get_idlestate_count(cpu); - if (idlestates == 0) { + if (idlestates < 1) { printf(_("CPU %u: No idle states\n"), cpu); return; } @@ -100,10 +100,10 @@ static void cpuidle_general_output(void) static void proc_cpuidle_cpu_output(unsigned int cpu) { long max_allowed_cstate = 2000000000; - unsigned int cstate, cstates; + int cstate, cstates; cstates = sysfs_get_idlestate_count(cpu); - if (cstates == 0) { + if (cstates < 1) { printf(_("CPU %u: No C-states info\n"), cpu); return; }