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 <ruchandani.tina@gmail.com> Suggested-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Родитель
0df1f2487d
Коммит
db59760582
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/syscore_ops.h>
|
#include <linux/syscore_ops.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/genhd.h>
|
#include <linux/genhd.h>
|
||||||
|
#include <linux/ktime.h>
|
||||||
#include <trace/events/power.h>
|
#include <trace/events/power.h>
|
||||||
|
|
||||||
#include "power.h"
|
#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.
|
* @nr_pages: Number of memory pages processed between @start and @stop.
|
||||||
* @msg: Additional diagnostic message to print.
|
* @msg: Additional diagnostic message to print.
|
||||||
*/
|
*/
|
||||||
void swsusp_show_speed(struct timeval *start, struct timeval *stop,
|
void swsusp_show_speed(ktime_t start, ktime_t stop,
|
||||||
unsigned nr_pages, char *msg)
|
unsigned nr_pages, char *msg)
|
||||||
{
|
{
|
||||||
|
ktime_t diff;
|
||||||
u64 elapsed_centisecs64;
|
u64 elapsed_centisecs64;
|
||||||
unsigned int centisecs;
|
unsigned int centisecs;
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
unsigned int kps;
|
unsigned int kps;
|
||||||
|
|
||||||
elapsed_centisecs64 = timeval_to_ns(stop) - timeval_to_ns(start);
|
diff = ktime_sub(stop, start);
|
||||||
/*
|
elapsed_centisecs64 = ktime_divns(diff, 10*NSEC_PER_MSEC);
|
||||||
* 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);
|
|
||||||
centisecs = elapsed_centisecs64;
|
centisecs = elapsed_centisecs64;
|
||||||
if (centisecs == 0)
|
if (centisecs == 0)
|
||||||
centisecs = 1; /* avoid div-by-zero */
|
centisecs = 1; /* avoid div-by-zero */
|
||||||
|
|
|
@ -174,8 +174,7 @@ extern int hib_wait_on_bio_chain(struct bio **bio_chain);
|
||||||
|
|
||||||
struct timeval;
|
struct timeval;
|
||||||
/* kernel/power/swsusp.c */
|
/* kernel/power/swsusp.c */
|
||||||
extern void swsusp_show_speed(struct timeval *, struct timeval *,
|
extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *);
|
||||||
unsigned int, char *);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
/* kernel/power/suspend.c */
|
/* kernel/power/suspend.c */
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
#include <linux/ktime.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
@ -1576,11 +1577,11 @@ int hibernate_preallocate_memory(void)
|
||||||
struct zone *zone;
|
struct zone *zone;
|
||||||
unsigned long saveable, size, max_size, count, highmem, pages = 0;
|
unsigned long saveable, size, max_size, count, highmem, pages = 0;
|
||||||
unsigned long alloc, save_highmem, pages_highmem, avail_normal;
|
unsigned long alloc, save_highmem, pages_highmem, avail_normal;
|
||||||
struct timeval start, stop;
|
ktime_t start, stop;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
printk(KERN_INFO "PM: Preallocating image memory... ");
|
printk(KERN_INFO "PM: Preallocating image memory... ");
|
||||||
do_gettimeofday(&start);
|
start = ktime_get();
|
||||||
|
|
||||||
error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY);
|
error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -1709,9 +1710,9 @@ int hibernate_preallocate_memory(void)
|
||||||
free_unnecessary_pages();
|
free_unnecessary_pages();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
do_gettimeofday(&stop);
|
stop = ktime_get();
|
||||||
printk(KERN_CONT "done (allocated %lu pages)\n", pages);
|
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;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
|
#include <linux/ktime.h>
|
||||||
|
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
|
@ -445,8 +446,8 @@ static int save_image(struct swap_map_handle *handle,
|
||||||
int nr_pages;
|
int nr_pages;
|
||||||
int err2;
|
int err2;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct timeval start;
|
ktime_t start;
|
||||||
struct timeval stop;
|
ktime_t stop;
|
||||||
|
|
||||||
printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n",
|
printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n",
|
||||||
nr_to_write);
|
nr_to_write);
|
||||||
|
@ -455,7 +456,7 @@ static int save_image(struct swap_map_handle *handle,
|
||||||
m = 1;
|
m = 1;
|
||||||
nr_pages = 0;
|
nr_pages = 0;
|
||||||
bio = NULL;
|
bio = NULL;
|
||||||
do_gettimeofday(&start);
|
start = ktime_get();
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = snapshot_read_next(snapshot);
|
ret = snapshot_read_next(snapshot);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
|
@ -469,12 +470,12 @@ static int save_image(struct swap_map_handle *handle,
|
||||||
nr_pages++;
|
nr_pages++;
|
||||||
}
|
}
|
||||||
err2 = hib_wait_on_bio_chain(&bio);
|
err2 = hib_wait_on_bio_chain(&bio);
|
||||||
do_gettimeofday(&stop);
|
stop = ktime_get();
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = err2;
|
ret = err2;
|
||||||
if (!ret)
|
if (!ret)
|
||||||
printk(KERN_INFO "PM: Image saving done.\n");
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,8 +581,8 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
||||||
int nr_pages;
|
int nr_pages;
|
||||||
int err2;
|
int err2;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct timeval start;
|
ktime_t start;
|
||||||
struct timeval stop;
|
ktime_t stop;
|
||||||
size_t off;
|
size_t off;
|
||||||
unsigned thr, run_threads, nr_threads;
|
unsigned thr, run_threads, nr_threads;
|
||||||
unsigned char *page = NULL;
|
unsigned char *page = NULL;
|
||||||
|
@ -674,7 +675,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
|
||||||
m = 1;
|
m = 1;
|
||||||
nr_pages = 0;
|
nr_pages = 0;
|
||||||
bio = NULL;
|
bio = NULL;
|
||||||
do_gettimeofday(&start);
|
start = ktime_get();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (thr = 0; thr < nr_threads; thr++) {
|
for (thr = 0; thr < nr_threads; thr++) {
|
||||||
for (off = 0; off < LZO_UNC_SIZE; off += PAGE_SIZE) {
|
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:
|
out_finish:
|
||||||
err2 = hib_wait_on_bio_chain(&bio);
|
err2 = hib_wait_on_bio_chain(&bio);
|
||||||
do_gettimeofday(&stop);
|
stop = ktime_get();
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = err2;
|
ret = err2;
|
||||||
if (!ret)
|
if (!ret)
|
||||||
printk(KERN_INFO "PM: Image saving done.\n");
|
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:
|
out_clean:
|
||||||
if (crc) {
|
if (crc) {
|
||||||
if (crc->thr)
|
if (crc->thr)
|
||||||
|
@ -965,8 +966,8 @@ static int load_image(struct swap_map_handle *handle,
|
||||||
{
|
{
|
||||||
unsigned int m;
|
unsigned int m;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct timeval start;
|
ktime_t start;
|
||||||
struct timeval stop;
|
ktime_t stop;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
int err2;
|
int err2;
|
||||||
unsigned nr_pages;
|
unsigned nr_pages;
|
||||||
|
@ -978,7 +979,7 @@ static int load_image(struct swap_map_handle *handle,
|
||||||
m = 1;
|
m = 1;
|
||||||
nr_pages = 0;
|
nr_pages = 0;
|
||||||
bio = NULL;
|
bio = NULL;
|
||||||
do_gettimeofday(&start);
|
start = ktime_get();
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
ret = snapshot_write_next(snapshot);
|
ret = snapshot_write_next(snapshot);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
|
@ -996,7 +997,7 @@ static int load_image(struct swap_map_handle *handle,
|
||||||
nr_pages++;
|
nr_pages++;
|
||||||
}
|
}
|
||||||
err2 = hib_wait_on_bio_chain(&bio);
|
err2 = hib_wait_on_bio_chain(&bio);
|
||||||
do_gettimeofday(&stop);
|
stop = ktime_get();
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = err2;
|
ret = err2;
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
@ -1005,7 +1006,7 @@ static int load_image(struct swap_map_handle *handle,
|
||||||
if (!snapshot_image_loaded(snapshot))
|
if (!snapshot_image_loaded(snapshot))
|
||||||
ret = -ENODATA;
|
ret = -ENODATA;
|
||||||
}
|
}
|
||||||
swsusp_show_speed(&start, &stop, nr_to_read, "Read");
|
swsusp_show_speed(start, stop, nr_to_read, "Read");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,8 +1068,8 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int eof = 0;
|
int eof = 0;
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
struct timeval start;
|
ktime_t start;
|
||||||
struct timeval stop;
|
ktime_t stop;
|
||||||
unsigned nr_pages;
|
unsigned nr_pages;
|
||||||
size_t off;
|
size_t off;
|
||||||
unsigned i, thr, run_threads, nr_threads;
|
unsigned i, thr, run_threads, nr_threads;
|
||||||
|
@ -1190,7 +1191,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
|
||||||
m = 1;
|
m = 1;
|
||||||
nr_pages = 0;
|
nr_pages = 0;
|
||||||
bio = NULL;
|
bio = NULL;
|
||||||
do_gettimeofday(&start);
|
start = ktime_get();
|
||||||
|
|
||||||
ret = snapshot_write_next(snapshot);
|
ret = snapshot_write_next(snapshot);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
|
@ -1343,7 +1344,7 @@ out_finish:
|
||||||
wait_event(crc->done, atomic_read(&crc->stop));
|
wait_event(crc->done, atomic_read(&crc->stop));
|
||||||
atomic_set(&crc->stop, 0);
|
atomic_set(&crc->stop, 0);
|
||||||
}
|
}
|
||||||
do_gettimeofday(&stop);
|
stop = ktime_get();
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
printk(KERN_INFO "PM: Image loading done.\n");
|
printk(KERN_INFO "PM: Image loading done.\n");
|
||||||
snapshot_write_finalize(snapshot);
|
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:
|
out_clean:
|
||||||
for (i = 0; i < ring_size; i++)
|
for (i = 0; i < ring_size; i++)
|
||||||
free_page((unsigned long)page[i]);
|
free_page((unsigned long)page[i]);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче