static int __init swsusp_helper_init(void)
{
	int ret;

	hib_log("[%s] enter...\n", __func__);

	/* init restore_noirq callback function table */
	memset((void *)restore_noirq_func_table, 0, sizeof(restore_noirq_func_table));

	ret = platform_device_register(&swsusp_helper_device);
	if (ret) {
		hib_err("swsusp_helper_device register fail(%d)\n", ret);
		return ret;
	}

	ret = platform_driver_register(&swsusp_helper_driver);
	if (ret) {
		hib_err("swsusp_helper_driver register fail(%d)\n", ret);
		return ret;
	}

	ret = register_pm_notifier(&swsusp_pm_notifier_block);
	if (ret)
		hib_err("failed to register PM notifier %d\n", ret);

	initialized = 1;
	return 0;
}
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;
}
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;

}
Example #4
0
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;
}
/* 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;
}
Example #6
0
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;
}
/* 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;
}
// trigger userspace recover for hibernation failed
static void usr_recover_func(struct work_struct *data)
{
    static char *envp[] = {
        "HOME=/data",
        "TERM=vt100",
        "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin",
        NULL };
    static char *argv[] = {
        HIB_USRPROGRAM,
        "--mode=recover",
        NULL, NULL, NULL, NULL, NULL, NULL
    };
    int retval;

    hib_log("call userspace program '%s %s'\n", argv[0],argv[1]);
    retval = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
    if (retval && retval != 256)
        hib_err("Failed to launch userspace program '%s %s': "
               "Error %d\n", argv[0], argv[1], retval);
}
Example #10
0
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;
}
// 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;
}