diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-06 19:17:30 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-06 19:17:30 -0400 |
| commit | 0ede470030a35847a8b213bbdafb29d77bca76da (patch) | |
| tree | 7e2f224ce89938b91d383fc79cfe1f772c3ec99b /kernel/power | |
| parent | 88b42a4883a7783972c8fc607e60bd3f027e24de (diff) | |
| parent | fdd64ed54eeba6b8619b36dcc7cb6442f2c6da0c (diff) | |
Merge branch 'pm-sleep'
* pm-sleep:
PM / hibernate: Iterate over set bits instead of PFNs in swsusp_free()
PM / sleep: new suspend_resume trace event for console resume
PM / sleep: Update test_suspend option documentation
PM / sleep: Enhance test_suspend option with repeat capability
PM / sleep: Support freeze as test_suspend option
PM / sysfs: avoid shadowing variables
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/snapshot.c | 54 | ||||
| -rw-r--r-- | kernel/power/suspend.c | 2 | ||||
| -rw-r--r-- | kernel/power/suspend_test.c | 32 |
3 files changed, 70 insertions, 18 deletions
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f1604d8cf489..791a61892bb5 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
| @@ -725,6 +725,14 @@ static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn) | |||
| 725 | clear_bit(bit, addr); | 725 | clear_bit(bit, addr); |
| 726 | } | 726 | } |
| 727 | 727 | ||
| 728 | static void memory_bm_clear_current(struct memory_bitmap *bm) | ||
| 729 | { | ||
| 730 | int bit; | ||
| 731 | |||
| 732 | bit = max(bm->cur.node_bit - 1, 0); | ||
| 733 | clear_bit(bit, bm->cur.node->data); | ||
| 734 | } | ||
| 735 | |||
| 728 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) | 736 | static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn) |
| 729 | { | 737 | { |
| 730 | void *addr; | 738 | void *addr; |
| @@ -1333,23 +1341,39 @@ static struct memory_bitmap copy_bm; | |||
| 1333 | 1341 | ||
| 1334 | void swsusp_free(void) | 1342 | void swsusp_free(void) |
| 1335 | { | 1343 | { |
| 1336 | struct zone *zone; | 1344 | unsigned long fb_pfn, fr_pfn; |
| 1337 | unsigned long pfn, max_zone_pfn; | ||
| 1338 | 1345 | ||
| 1339 | for_each_populated_zone(zone) { | 1346 | if (!forbidden_pages_map || !free_pages_map) |
| 1340 | max_zone_pfn = zone_end_pfn(zone); | 1347 | goto out; |
| 1341 | for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) | 1348 | |
| 1342 | if (pfn_valid(pfn)) { | 1349 | memory_bm_position_reset(forbidden_pages_map); |
| 1343 | struct page *page = pfn_to_page(pfn); | 1350 | memory_bm_position_reset(free_pages_map); |
| 1344 | 1351 | ||
| 1345 | if (swsusp_page_is_forbidden(page) && | 1352 | loop: |
| 1346 | swsusp_page_is_free(page)) { | 1353 | fr_pfn = memory_bm_next_pfn(free_pages_map); |
| 1347 | swsusp_unset_page_forbidden(page); | 1354 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); |
| 1348 | swsusp_unset_page_free(page); | 1355 | |
| 1349 | __free_page(page); | 1356 | /* |
| 1350 | } | 1357 | * Find the next bit set in both bitmaps. This is guaranteed to |
| 1351 | } | 1358 | * terminate when fb_pfn == fr_pfn == BM_END_OF_MAP. |
| 1359 | */ | ||
| 1360 | do { | ||
| 1361 | if (fb_pfn < fr_pfn) | ||
| 1362 | fb_pfn = memory_bm_next_pfn(forbidden_pages_map); | ||
| 1363 | if (fr_pfn < fb_pfn) | ||
| 1364 | fr_pfn = memory_bm_next_pfn(free_pages_map); | ||
| 1365 | } while (fb_pfn != fr_pfn); | ||
| 1366 | |||
| 1367 | if (fr_pfn != BM_END_OF_MAP && pfn_valid(fr_pfn)) { | ||
| 1368 | struct page *page = pfn_to_page(fr_pfn); | ||
| 1369 | |||
| 1370 | memory_bm_clear_current(forbidden_pages_map); | ||
| 1371 | memory_bm_clear_current(free_pages_map); | ||
| 1372 | __free_page(page); | ||
| 1373 | goto loop; | ||
| 1352 | } | 1374 | } |
| 1375 | |||
| 1376 | out: | ||
| 1353 | nr_copy_pages = 0; | 1377 | nr_copy_pages = 0; |
| 1354 | nr_meta_pages = 0; | 1378 | nr_meta_pages = 0; |
| 1355 | restore_pblist = NULL; | 1379 | restore_pblist = NULL; |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 18c62195660f..e837dd6783c6 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
| @@ -361,7 +361,9 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
| 361 | suspend_test_start(); | 361 | suspend_test_start(); |
| 362 | dpm_resume_end(PMSG_RESUME); | 362 | dpm_resume_end(PMSG_RESUME); |
| 363 | suspend_test_finish("resume devices"); | 363 | suspend_test_finish("resume devices"); |
| 364 | trace_suspend_resume(TPS("resume_console"), state, true); | ||
| 364 | resume_console(); | 365 | resume_console(); |
| 366 | trace_suspend_resume(TPS("resume_console"), state, false); | ||
| 365 | 367 | ||
| 366 | Close: | 368 | Close: |
| 367 | platform_suspend_end(state); | 369 | platform_suspend_end(state); |
diff --git a/kernel/power/suspend_test.c b/kernel/power/suspend_test.c index bd91bc177c93..084452e34a12 100644 --- a/kernel/power/suspend_test.c +++ b/kernel/power/suspend_test.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #define TEST_SUSPEND_SECONDS 10 | 22 | #define TEST_SUSPEND_SECONDS 10 |
| 23 | 23 | ||
| 24 | static unsigned long suspend_test_start_time; | 24 | static unsigned long suspend_test_start_time; |
| 25 | static u32 test_repeat_count_max = 1; | ||
| 26 | static u32 test_repeat_count_current; | ||
| 25 | 27 | ||
| 26 | void suspend_test_start(void) | 28 | void suspend_test_start(void) |
| 27 | { | 29 | { |
| @@ -74,6 +76,7 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) | |||
| 74 | int status; | 76 | int status; |
| 75 | 77 | ||
| 76 | /* this may fail if the RTC hasn't been initialized */ | 78 | /* this may fail if the RTC hasn't been initialized */ |
| 79 | repeat: | ||
| 77 | status = rtc_read_time(rtc, &alm.time); | 80 | status = rtc_read_time(rtc, &alm.time); |
| 78 | if (status < 0) { | 81 | if (status < 0) { |
| 79 | printk(err_readtime, dev_name(&rtc->dev), status); | 82 | printk(err_readtime, dev_name(&rtc->dev), status); |
| @@ -100,10 +103,21 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) | |||
| 100 | if (state == PM_SUSPEND_STANDBY) { | 103 | if (state == PM_SUSPEND_STANDBY) { |
| 101 | printk(info_test, pm_states[state]); | 104 | printk(info_test, pm_states[state]); |
| 102 | status = pm_suspend(state); | 105 | status = pm_suspend(state); |
| 106 | if (status < 0) | ||
| 107 | state = PM_SUSPEND_FREEZE; | ||
| 103 | } | 108 | } |
| 109 | if (state == PM_SUSPEND_FREEZE) { | ||
| 110 | printk(info_test, pm_states[state]); | ||
| 111 | status = pm_suspend(state); | ||
| 112 | } | ||
| 113 | |||
| 104 | if (status < 0) | 114 | if (status < 0) |
| 105 | printk(err_suspend, status); | 115 | printk(err_suspend, status); |
| 106 | 116 | ||
| 117 | test_repeat_count_current++; | ||
| 118 | if (test_repeat_count_current < test_repeat_count_max) | ||
| 119 | goto repeat; | ||
| 120 | |||
| 107 | /* Some platforms can't detect that the alarm triggered the | 121 | /* Some platforms can't detect that the alarm triggered the |
| 108 | * wakeup, or (accordingly) disable it after it afterwards. | 122 | * wakeup, or (accordingly) disable it after it afterwards. |
| 109 | * It's supposed to give oneshot behavior; cope. | 123 | * It's supposed to give oneshot behavior; cope. |
| @@ -137,16 +151,28 @@ static char warn_bad_state[] __initdata = | |||
| 137 | static int __init setup_test_suspend(char *value) | 151 | static int __init setup_test_suspend(char *value) |
| 138 | { | 152 | { |
| 139 | int i; | 153 | int i; |
| 154 | char *repeat; | ||
| 155 | char *suspend_type; | ||
| 140 | 156 | ||
| 141 | /* "=mem" ==> "mem" */ | 157 | /* example : "=mem[,N]" ==> "mem[,N]" */ |
| 142 | value++; | 158 | value++; |
| 159 | suspend_type = strsep(&value, ","); | ||
| 160 | if (!suspend_type) | ||
| 161 | return 0; | ||
| 162 | |||
| 163 | repeat = strsep(&value, ","); | ||
| 164 | if (repeat) { | ||
| 165 | if (kstrtou32(repeat, 0, &test_repeat_count_max)) | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 143 | for (i = 0; pm_labels[i]; i++) | 169 | for (i = 0; pm_labels[i]; i++) |
| 144 | if (!strcmp(pm_labels[i], value)) { | 170 | if (!strcmp(pm_labels[i], suspend_type)) { |
| 145 | test_state_label = pm_labels[i]; | 171 | test_state_label = pm_labels[i]; |
| 146 | return 0; | 172 | return 0; |
| 147 | } | 173 | } |
| 148 | 174 | ||
| 149 | printk(warn_bad_state, value); | 175 | printk(warn_bad_state, suspend_type); |
| 150 | return 0; | 176 | return 0; |
| 151 | } | 177 | } |
| 152 | __setup("test_suspend", setup_test_suspend); | 178 | __setup("test_suspend", setup_test_suspend); |
