diff options
author | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 09:48:20 +0200 |
---|---|---|
committer | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 14:02:16 +0200 |
commit | 2489007e7d740ccbc3e0a202914e243ad5178787 (patch) | |
tree | b8e6380ea7b1da63474ad68a5dba997e01146043 /kernel/power | |
parent | 5f67568eb31e3a813c7c52461dcf66ade15fc2e7 (diff) | |
download | kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.zip kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.gz kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.bz2 |
merge opensource jb u5
Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2
Diffstat (limited to 'kernel/power')
-rw-r--r-- | kernel/power/Kconfig | 17 | ||||
-rw-r--r-- | kernel/power/earlysuspend.c | 21 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 66 | ||||
-rw-r--r-- | kernel/power/main.c | 24 | ||||
-rw-r--r-- | kernel/power/power.h | 1 | ||||
-rw-r--r-- | kernel/power/swap.c | 29 | ||||
-rw-r--r-- | kernel/power/wakelock.c | 29 |
7 files changed, 179 insertions, 8 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 56afb61..9fda331 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -26,6 +26,15 @@ config PM_WATCHDOG_TIMEOUT Enable PM watchdog timer to catch lockup during early_suspend, late_resume and suspend_finish. +config FAST_BOOT + bool "Force suspend and show fake turn off which is same with suspend" + depends on SUSPEND + default n + ---help--- + This allows you go to suspend instead to turn off. If this is + done, it goes to wake up instead to turn on. This works with power + source. + config HAS_WAKELOCK bool @@ -152,6 +161,14 @@ config FULL_PAGE_RECLAIM dramatically decreased and small size of hibernation snapshot image has benefit for fast booting. +config FAST_RESUME + bool "Using fast resume during Suspend-to-Disk" + depends on HIBERNATION + ---help--- + software_resume() function which triggers hibernation restore is + called faster on booting time by introducing new initcalls. This has + benefit for fast booting on hibernation + config PM_STD_PARTITION string "Default resume partition" depends on HIBERNATION diff --git a/kernel/power/earlysuspend.c b/kernel/power/earlysuspend.c index 1c293ce..e6303fd 100644 --- a/kernel/power/earlysuspend.c +++ b/kernel/power/earlysuspend.c @@ -20,6 +20,9 @@ #include <linux/syscalls.h> /* sys_sync */ #include <linux/wakelock.h> #include <linux/workqueue.h> +#ifdef CONFIG_ZRAM_FOR_ANDROID +#include <asm/atomic.h> +#endif /* CONFIG_ZRAM_FOR_ANDROID */ #include "power.h" @@ -29,6 +32,11 @@ enum { DEBUG_VERBOSE = 1U << 3, }; static int debug_mask = DEBUG_USER_STATE; +#ifdef CONFIG_ZRAM_FOR_ANDROID +atomic_t optimize_comp_on = ATOMIC_INIT(0); +EXPORT_SYMBOL(optimize_comp_on); +#endif /* CONFIG_ZRAM_FOR_ANDROID */ + module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); static DEFINE_MUTEX(early_suspend_lock); @@ -94,6 +102,9 @@ static void early_suspend(struct work_struct *work) mutex_lock(&early_suspend_lock); spin_lock_irqsave(&state_lock, irqflags); +#ifdef CONFIG_ZRAM_FOR_ANDROID + atomic_set(&optimize_comp_on, 1); +#endif /* CONFIG_ZRAM_FOR_ANDROID */ if (state == SUSPEND_REQUESTED) state |= SUSPENDED; else @@ -145,6 +156,9 @@ static void late_resume(struct work_struct *work) mutex_lock(&early_suspend_lock); spin_lock_irqsave(&state_lock, irqflags); +#ifdef CONFIG_ZRAM_FOR_ANDROID + atomic_set(&optimize_comp_on, 0); +#endif /* CONFIG_ZRAM_FOR_ANDROID */ if (state == SUSPENDED) state &= ~SUSPENDED; else @@ -174,6 +188,9 @@ abort: pm_wd_del_timer(&timer); } +#ifdef CONFIG_FAST_BOOT +extern bool fake_shut_down; +#endif void request_suspend_state(suspend_state_t new_state) { unsigned long irqflags; @@ -198,6 +215,10 @@ void request_suspend_state(suspend_state_t new_state) state |= SUSPEND_REQUESTED; queue_work(suspend_work_queue, &early_suspend_work); } else if (old_sleep && new_state == PM_SUSPEND_ON) { +#ifdef CONFIG_FAST_BOOT + if (fake_shut_down) + fake_shut_down = false; +#endif state &= ~SUSPEND_REQUESTED; wake_lock(&main_wake_lock); queue_work(suspend_work_queue, &late_resume_work); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 8884c27..c260280 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -14,6 +14,7 @@ #include <linux/reboot.h> #include <linux/string.h> #include <linux/device.h> +#include <linux/async.h> #include <linux/kmod.h> #include <linux/delay.h> #include <linux/fs.h> @@ -24,13 +25,16 @@ #include <linux/freezer.h> #include <linux/gfp.h> #include <linux/syscore_ops.h> +#include <linux/ctype.h> +#include <linux/genhd.h> #include <scsi/scsi_scan.h> #include "power.h" static int nocompress = 0; -static int noresume = 0; +int noresume; +static int resume_wait = 0; static char resume_file[256] = CONFIG_PM_STD_PARTITION; dev_t swsusp_resume_device; sector_t swsusp_resume_block; @@ -727,12 +731,30 @@ static int software_resume(void) /* Check if the device is there */ swsusp_resume_device = name_to_dev_t(resume_file); + + /* + * name_to_dev_t is ineffective to verify parition if resume_file is in + * integer format. (e.g. major:minor) + */ + if (isdigit(resume_file[0]) && resume_wait) { + int partno; + while (!get_gendisk(swsusp_resume_device, &partno)) + msleep(10); + } + if (!swsusp_resume_device) { /* * Some device discovery might still be in progress; we need * to wait for this to finish. */ wait_for_device_probe(); + + if (resume_wait) { + while ((swsusp_resume_device = name_to_dev_t(resume_file)) == 0) + msleep(10); + async_synchronize_full(); + } + /* * We can't depend on SCSI devices being available after loading * one of their modules until scsi_complete_async_scans() is @@ -810,7 +832,11 @@ close_finish: goto Finish; } +#ifdef CONFIG_FAST_RESUME +resume_initcall(software_resume); +#else late_initcall(software_resume); +#endif static const char * const hibernation_modes[] = { @@ -1002,11 +1028,42 @@ static ssize_t reserved_size_store(struct kobject *kobj, power_attr(reserved_size); +#ifdef CONFIG_FAST_RESUME +static ssize_t noresume_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", noresume); +} + +static ssize_t noresume_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t n) +{ + if (sscanf(buf, "%d", &noresume) == 1) { + noresume = !!noresume; + if (noresume) { + if (!swsusp_resume_device) + swsusp_resume_device = + name_to_dev_t(resume_file); + swsusp_check(); + swsusp_close(FMODE_READ); + } + return n; + } + + return -EINVAL; +} + +power_attr(noresume); +#endif + static struct attribute * g[] = { &disk_attr.attr, &resume_attr.attr, &image_size_attr.attr, &reserved_size_attr.attr, +#ifdef CONFIG_FAST_RESUME + &noresume_attr.attr, +#endif NULL, }; @@ -1061,7 +1118,14 @@ static int __init noresume_setup(char *str) return 1; } +static int __init resumewait_setup(char *str) +{ + resume_wait = 1; + return 1; +} + __setup("noresume", noresume_setup); __setup("resume_offset=", resume_offset_setup); __setup("resume=", resume_setup); __setup("hibernate=", hibernate_setup); +__setup("resumewait=", resumewait_setup); diff --git a/kernel/power/main.c b/kernel/power/main.c index 7f6987f..9c54ff7 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -190,6 +190,12 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr, #endif return (s - buf); } +#ifdef CONFIG_FAST_BOOT +bool fake_shut_down = false; +EXPORT_SYMBOL(fake_shut_down); + +extern void wakelock_force_suspend(void); +#endif static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) @@ -220,15 +226,29 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr, if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) break; } - if (state < PM_SUSPEND_MAX && *s) + +#ifdef CONFIG_FAST_BOOT + if (len == 4 && !strncmp(buf, "dmem", len)) { + pr_info("%s: fake shut down!!!\n", __func__); + fake_shut_down = true; + state = PM_SUSPEND_MEM; + } +#endif + + if (state < PM_SUSPEND_MAX && *s) { #ifdef CONFIG_EARLYSUSPEND if (state == PM_SUSPEND_ON || valid_state(state)) { error = 0; request_suspend_state(state); } +#ifdef CONFIG_FAST_BOOT + if (fake_shut_down) + wakelock_force_suspend(); +#endif #else error = enter_state(state); #endif + } #endif Exit: @@ -683,7 +703,7 @@ static ssize_t mali_lock_store(struct kobject *kobj, mali_lock_cnt = mali_dvfs_bottom_lock_pop(); if (mali_lock_cnt == 0) mali_lock_val = 0; - } else if (val > 0 && val < 4) { /* lock with level */ + } else if (val > 0 && val < 5) { /* lock with level */ mali_lock_cnt = mali_dvfs_bottom_lock_push(val); if (mali_lock_val < val) mali_lock_val = val; diff --git a/kernel/power/power.h b/kernel/power/power.h index 474d75b..fac1ce8 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -72,6 +72,7 @@ static struct kobj_attribute _name##_attr = { \ .store = _name##_store, \ } +extern int noresume; /* Preferred image size in bytes (default 500 MB) */ extern unsigned long image_size; /* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */ diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 7c97c3a..2a2dc30 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -372,6 +372,15 @@ static int swap_writer_finish(struct swap_map_handle *handle, LZO_HEADER, PAGE_SIZE) #define LZO_CMP_SIZE (LZO_CMP_PAGES * PAGE_SIZE) +/* + * lzo experimental compression ratio. + * When compression is used for hibernation, swap size is not required for worst + * case. So we use an experimental compression ratio. If the swap size is not + * enough, then alloc_swapdev_block() return fails and hibernation codes handle + * the error well. + */ +#define LZO_RATIO(x) ((x) / 2) + /** * save_image - save the suspend image data */ @@ -437,7 +446,7 @@ static int save_image_lzo(struct swap_map_handle *handle, struct bio *bio; struct timeval start; struct timeval stop; - size_t off, unc_len, cmp_len; + size_t off, unc_len, cmp_len, total; unsigned char *unc, *cmp, *wrk, *page; page = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); @@ -477,6 +486,7 @@ static int save_image_lzo(struct swap_map_handle *handle, if (!m) m = 1; nr_pages = 0; + total = 0; bio = NULL; do_gettimeofday(&start); for (;;) { @@ -529,6 +539,7 @@ static int save_image_lzo(struct swap_map_handle *handle, if (ret) goto out_finish; } + total += DIV_ROUND_UP(LZO_HEADER + cmp_len, PAGE_SIZE); } out_finish: @@ -541,6 +552,11 @@ out_finish: else printk(KERN_CONT "\n"); swsusp_show_speed(&start, &stop, nr_to_write, "Wrote"); + pr_info("PM: %lu->%lu kbytes, %d%% compressed\n", + nr_to_write * PAGE_SIZE / 1024, + total * PAGE_SIZE / 1024, + 100 - ((total * 100) / nr_to_write)); + image_size = total * PAGE_SIZE; vfree(cmp); vfree(unc); @@ -564,8 +580,8 @@ static int enough_swap(unsigned int nr_pages, unsigned int flags) pr_debug("PM: Free swap pages: %u\n", free_swap); - required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ? - nr_pages : (nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1); + required = PAGES_FOR_IO + ((flags & SF_NOCOMPRESS_MODE) ? nr_pages : + LZO_RATIO((nr_pages * LZO_CMP_PAGES) / LZO_UNC_PAGES + 1)); return free_swap > required; } @@ -943,8 +959,11 @@ int swsusp_check(void) if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) { memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); /* Reset swap signature now */ - error = hib_bio_write_page(swsusp_resume_block, - swsusp_header, NULL); +#if defined(CONFIG_FAST_RESUME) && defined(CONFIG_SLP) + if (noresume) +#endif + error = hib_bio_write_page(swsusp_resume_block, + swsusp_header, NULL); } else { error = -EINVAL; } diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c index b2e149a..104f6dc 100644 --- a/kernel/power/wakelock.c +++ b/kernel/power/wakelock.c @@ -22,6 +22,9 @@ #ifdef CONFIG_WAKELOCK_STAT #include <linux/proc_fs.h> #endif +#ifdef CONFIG_FAST_BOOT +#include <linux/delay.h> +#endif #include "power.h" enum { @@ -250,11 +253,18 @@ static long has_wake_lock_locked(int type) } return max_timeout; } +#ifdef CONFIG_FAST_BOOT +extern bool fake_shut_down; +#endif long has_wake_lock(int type) { long ret; unsigned long irqflags; +#ifdef CONFIG_FAST_BOOT + if (fake_shut_down) + return 0; +#endif spin_lock_irqsave(&list_lock, irqflags); ret = has_wake_lock_locked(type); if (ret && (debug_mask & DEBUG_WAKEUP) && type == WAKE_LOCK_SUSPEND) @@ -558,6 +568,25 @@ int wake_lock_active(struct wake_lock *lock) } EXPORT_SYMBOL(wake_lock_active); +#ifdef CONFIG_FAST_BOOT +void wakelock_force_suspend(void) +{ + static int cnt; + + if (cnt > 0) { + pr_info("%s: duplicated\n", __func__); + return; + } + cnt++; + + msleep(3000); + pr_info("%s: fake shut down\n", __func__); + queue_work(suspend_work_queue, &suspend_work); + + cnt = 0; +} +#endif + static int wakelock_stats_open(struct inode *inode, struct file *file) { return single_open(file, wakelock_stats_show, NULL); |