static void hib_unplug_cores(void) { int i = 0; hib_warn("unplug cores\n"); #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG mutex_lock(&hp_onoff_mutex); #endif for (i = (num_possible_cpus() - 1); i > 0 && num_online_cpus() > HIB_MULTIIO_CORES; i--) { if (cpu_online(i)) { int err; hib_log("cpu %d down...\n", i); err = cpu_down(i); if (err < 0) { hib_warn("cpu %d down...failed(%d)\n", i, err); } else { hib_log("cpu %d down...done\n", i, err); } } } #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG mutex_unlock(&hp_onoff_mutex); #endif }
int swsusp_helper_pm_restore_noirq(struct device *device) { int id, ret = 0, retall = 0; hib_log("[%s] enter...\n", __func__); BUG_ON(!initialized); for (id = ID_M_BEGIN; id < ID_M_END; id++) { if (restore_noirq_func_table[id].func != NULL) { hib_warn("exec func %d:0x%p !\n", restore_noirq_func_table[id].id, restore_noirq_func_table[id].func); if (id != restore_noirq_func_table[id].id) { hib_err("exec func fail: func id miss-matched (%d/%d) !\n", id, restore_noirq_func_table[id].id); continue; } ret = restore_noirq_func_table[id].func(restore_noirq_func_table[id].device); if (ret != 0) { hib_warn("exec func fail: func id(%d), err code %d !\n", restore_noirq_func_table[id].id, ret); retall = ret; } } } return retall; }
/* en: 1 enable, en: 0 disable */ static void hib_hotplug_mode(int en) { static int g_hp_disable = 0; if (en) { if (1 == g_hp_disable) { hib_warn("enable hotplug\n"); #if defined(CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG) || defined(CONFIG_CPU_FREQ_DEFAULT_GOV_BALANCE) hp_set_dynamic_cpu_hotplug_enable(1); #else hps_set_enabled(1); #endif g_hp_disable = 0; } } else if (!en) { if (0 == g_hp_disable) { hib_warn("disable hotplug\n"); #if defined(CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG) || defined(CONFIG_CPU_FREQ_DEFAULT_GOV_BALANCE) hp_set_dynamic_cpu_hotplug_enable(0); #else hps_set_enabled(0); #endif hib_unplug_cores(); g_hp_disable = 1; } } }
static void hib_ftrace_buffer(int en) { #if defined(CONFIG_MTK_SCHED_TRACERS) int fterr = 0; hib_warn("%s ftrace mode\n", (en ? "enable" : "disable")); fterr = resize_ring_buffer_for_hibernation(en); if (fterr < 0) hib_warn("calling resize_ring_buffer_for_hibernation() failed (%d)\n", fterr); #endif }
/* NOTICE: this function MUST be called under autosleep_lock (in autosleep.c) is locked!! */ int mtk_hibernate_via_autosleep(suspend_state_t *autosleep_state) { int err = 0; hib_log("entering hibernation state(%d)\n", *autosleep_state); err = hibernate(); if (err) { hib_warn ("@@@@@@@@@@@@@@@@@@@@@@@@@\n@@_Hibernation Failed_@@@\n@@@@@@@@@@@@@@@@@@@@@@@@@\n"); /* enhanced error handling */ #ifdef CONFIG_TOI_ENHANCE if (toi_hibernate_fatalerror()) { kernel_power_off(); kernel_halt(); BUG(); } #endif if (hibernation_failed_action == HIB_FAILED_TO_SHUTDOWN) { kernel_power_off(); kernel_halt(); BUG(); } else if (hibernation_failed_action == HIB_FAILED_TO_S2RAM) { hib_warn("hibernation failed: so changing state(%d->%d) err(%d)\n", *autosleep_state, PM_SUSPEND_MEM, err); if (++hib_failed_cnt >= MAX_HIB_FAILED_CNT) hibernation_failed_action = HIB_FAILED_TO_SHUTDOWN; hibernate_recover(); *autosleep_state = PM_SUSPEND_MEM; pm_wake_lock("IPOD_HIB_WAKELOCK"); system_is_hibernating = false; } else { hib_err("@@@@@@@@@@@@@@@@@@\n@_FATAL ERROR !!!_\n@@@@@@@@@@@@@@@@@@@\n"); BUG(); } } else { if (hybrid_sleep_mode()) { hib_warn("hybrid sleep mode so changing state(%d->%d)\n", *autosleep_state, PM_SUSPEND_MEM); *autosleep_state = PM_SUSPEND_MEM; /* continue suspend to ram if hybrid sleep mode */ } else { hib_warn("hibernation succeeded: so changing state(%d->%d) err(%d)\n", *autosleep_state, PM_SUSPEND_ON, err); hibernate_restore(); *autosleep_state = PM_SUSPEND_ON; /* if this is not set, it will recursively do hibernating!! */ } hib_failed_cnt = 0; pm_wake_lock("IPOD_HIB_WAKELOCK"); system_is_hibernating = false; } return err; }
int register_swsusp_restore_noirq_func(unsigned int id, swsusp_cb_func_t func, struct device *device) { int ret = 0; swsusp_cb_func_info *info_ptr; BUG_ON(!initialized); if ((id >= MAX_CB_FUNCS) || (func == NULL)) { hib_err("register func fail: func_id: %d!\n", id); return E_PARAM; } info_ptr = &(restore_noirq_func_table[id]); if (info_ptr->func == NULL) { info_ptr->id = id; info_ptr->func = func; info_ptr->device = device; hib_warn("reg. func %d:0x%p with device %s%p\n", restore_noirq_func_table[id].id, restore_noirq_func_table[id].func, (device == NULL) ? " " : "0x", restore_noirq_func_table[id].device); } else hib_err("register func fail: func(%d) already registered!\n", id); return ret; }
static void hibernate_restore(void) { hib_ftrace_buffer(1); hib_hotplug_mode(1); hib_warn("start trigger ipod\n"); }
/* en: 1 enable, en: 0 disable */ static void hib_hotplug_mode(int en) { static int g_hp_disable; if (en) { if (1 == g_hp_disable) { hib_warn("enable hotplug\n"); hp_set_dynamic_cpu_hotplug_enable(1); g_hp_disable = 0; } } else if (!en) { if (0 == g_hp_disable) { hib_warn("disable hotplug\n"); hp_set_dynamic_cpu_hotplug_enable(0); hib_unplug_cores(); g_hp_disable = 1; } } }
/* called by echo "disk" > /sys/power/state */ int mtk_hibernate(void) { int err = 0; hib_log("entering hibernation\n"); err = hibernate(); if (err) { hib_warn ("@@@@@@@@@@@@@@@@@@@@@@@@@\n@@_Hibernation Failed_@@@\n@@@@@@@@@@@@@@@@@@@@@@@@@\n"); /* enhanced error handling */ #ifdef CONFIG_TOI_ENHANCE if (toi_hibernate_fatalerror()) { kernel_power_off(); kernel_halt(); BUG(); } #endif if (hibernation_failed_action == HIB_FAILED_TO_SHUTDOWN) { kernel_power_off(); kernel_halt(); BUG(); } else if (hibernation_failed_action == HIB_FAILED_TO_S2RAM) { hib_warn("hibernation failed, suspend to ram instead!\n"); if (++hib_failed_cnt >= MAX_HIB_FAILED_CNT) hibernation_failed_action = HIB_FAILED_TO_SHUTDOWN; hibernate_recover(); pm_wake_lock("IPOD_HIB_WAKELOCK"); system_is_hibernating = false; } else { hib_err("@@@@@@@@@@@@@@@@@@\n@_FATAL ERROR !!!_\n@@@@@@@@@@@@@@@@@@@\n"); BUG(); } } else { if (!hybrid_sleep_mode()) { hibernate_restore(); } hib_failed_cnt = 0; pm_wake_lock("IPOD_HIB_WAKELOCK"); system_is_hibernating = false; } return err; }
// NOTICE: this function MUST be called under autosleep_lock (in autosleep.c) is locked!! int mtk_hibernate_via_autosleep(suspend_state_t *autosleep_state) { int err = 0; hib_log("entering hibernation state(%d)\n", *autosleep_state); err = hibernate(); if (err) { hib_warn("@@@@@@@@@@@@@@@@@@@@@@@@@\n@@_Hibernation Failed_@@@\n@@@@@@@@@@@@@@@@@@@@@@@@@\n"); if (hibernation_failed_action == HIB_FAILED_TO_SHUTDOWN) { kernel_power_off(); kernel_halt(); BUG(); } else if (hibernation_failed_action == HIB_FAILED_TO_S2RAM) { hib_warn("hibernation failed: so changing state(%d->%d) err(%d)\n", *autosleep_state, PM_SUSPEND_MEM, err); if (++hib_failed_cnt >= MAX_HIB_FAILED_CNT) hibernation_failed_action = HIB_FAILED_TO_SHUTDOWN; // userspace recover if hibernation failed usr_recover_func(NULL); *autosleep_state = PM_SUSPEND_MEM; system_is_hibernating = false; } else { hib_err("@@@@@@@@@@@@@@@@@@\n@_FATAL ERROR !!!_\n@@@@@@@@@@@@@@@@@@@\n"); BUG(); } } else { if (hybrid_sleep_mode()) { hib_warn("hybrid sleep mode so changing state(%d->%d)\n", *autosleep_state, PM_SUSPEND_MEM); *autosleep_state = PM_SUSPEND_MEM; //continue suspend to ram if hybrid sleep mode } else { hib_warn("hibernation succeeded: so changing state(%d->%d) err(%d) \n", *autosleep_state, PM_SUSPEND_ON, err); hib_warn("start trigger ipod\n"); //usr_bootanim_start(NULL); //schedule_delayed_work(&usr_restore_work, HZ*0.05); usr_restore_func(NULL); *autosleep_state = PM_SUSPEND_ON; // if this is not set, it will recursively do hibernating!! } hib_failed_cnt = 0; pm_wake_lock("IPOD_HIB_WAKELOCK"); system_is_hibernating = false; } return err; }
int bad_memory_status(void) { struct zone *zone; unsigned long free_pages, min_pages; for_each_populated_zone(zone) { if (!strcmp(zone->name, "Normal")) { free_pages = zone_page_state(zone, NR_FREE_PAGES); min_pages = min_wmark_pages(zone); if (free_pages < (min_pages + HIB_PAGE_FREE_DELTA)) { hib_warn("abort hibernate due to %s memory status: (%lu:%lu)\n", zone->name, free_pages, min_pages); return -1; } else { hib_warn("%s memory status: (%lu:%lu)\n", zone->name, free_pages, min_pages); } } } return 0; }
// called by echo "disk" > /sys/power/state int mtk_hibernate(void) { int err = 0; hib_log("entering hibernation\n"); err = hibernate(); if (err) { hib_warn("@@@@@@@@@@@@@@@@@@@@@@@@@\n@@_Hibernation Failed_@@@\n@@@@@@@@@@@@@@@@@@@@@@@@@\n"); if (hibernation_failed_action == HIB_FAILED_TO_SHUTDOWN) { kernel_power_off(); kernel_halt(); BUG(); } else if (hibernation_failed_action == HIB_FAILED_TO_S2RAM) { hib_warn("hibernation failed, suspend to ram instead!\n"); if (++hib_failed_cnt >= MAX_HIB_FAILED_CNT) hibernation_failed_action = HIB_FAILED_TO_SHUTDOWN; // userspace recover if hibernation failed usr_recover_func(NULL); system_is_hibernating = false; } else { hib_err("@@@@@@@@@@@@@@@@@@\n@_FATAL ERROR !!!_\n@@@@@@@@@@@@@@@@@@@\n"); BUG(); } } else { if (!hybrid_sleep_mode()) { hib_warn("start trigger ipod\n"); //schedule_delayed_work(&usr_bootanim_start_work, HZ*1.0); //schedule_delayed_work(&usr_restore_work, HZ*0.05); //usr_bootanim_start(NULL); usr_restore_func(NULL); } hib_failed_cnt = 0; pm_wake_lock("IPOD_HIB_WAKELOCK"); system_is_hibernating = false; } return err; }
int unregister_swsusp_restore_noirq_func(unsigned int id) { int ret = 0; swsusp_cb_func_info *info_ptr; if (id >= MAX_CB_FUNCS) { hib_err("register func fail: func_id: %d!\n", id); return E_PARAM; } info_ptr = &(restore_noirq_func_table[id]); if (info_ptr->func != NULL) { info_ptr->id = -1; info_ptr->func = NULL; info_ptr->device = NULL; } else hib_warn("register func fail: func(%d) already unregistered!\n", id); return ret; }
int swsusp_helper_pm_restore_noirq(struct device *device) { int id, ret = 0, retall = 0; hib_log("[%s] enter...\n", __func__); for (id = ID_M_BEGIN; id < ID_M_END; id++) { if (restore_noirq_func_table[id].func != NULL) { ret = restore_noirq_func_table[id].func(restore_noirq_func_table[id].device); if (ret != 0) { hib_warn("exec func fail: func id(%d), err code %d !\n", restore_noirq_func_table[id].id, ret); retall = ret; } } } return retall; }
int exec_swsusp_restore_noirq_func(unsigned int id) { swsusp_cb_func_t func; struct device *device = NULL; int ret = 0; if (id >= MAX_CB_FUNCS) { hib_err("exec func fail: invalid func id(%d)!\n", id); return E_PARAM; } func = restore_noirq_func_table[id].func; device = restore_noirq_func_table[id].device; if (func != NULL) { ret = func(device); } else { ret = E_NO_EXIST; hib_warn("exec func fail: func id(%d) not register!\n", id); } return ret; }
int register_swsusp_restore_noirq_func(unsigned int id, swsusp_cb_func_t func, struct device *device) { int ret = 0; swsusp_cb_func_info *info_ptr; if ((id >= MAX_CB_FUNCS) || (func == NULL)) { hib_err("register func fail: func_id: %d!\n", id); return E_PARAM; } info_ptr = &(restore_noirq_func_table[id]); if (info_ptr->func == NULL) { info_ptr->id = id; info_ptr->func = func; info_ptr->device = device; if (device == NULL) hib_warn("register func(%d:0x%p) with device NULL\n", id, func); } else hib_err("register func fail: func(%d) already registered!\n", id); return ret; }