Example #1
0
static inline int snapshot_restore(int platform_suspend)
{
	int error;

	mutex_lock(&pm_mutex);
	pm_prepare_console();
	if (platform_suspend) {
		error = platform_prepare();
		if (error)
			goto Finish;
	}
	suspend_console();
	error = device_suspend(PMSG_PRETHAW);
	if (error)
		goto Resume_devices;

	error = disable_nonboot_cpus();
	if (!error)
		error = swsusp_resume();

	enable_nonboot_cpus();
 Resume_devices:
	if (platform_suspend)
		platform_finish();

	device_resume();
	resume_console();
 Finish:
	pm_restore_console();
	mutex_unlock(&pm_mutex);
	return error;
}
Example #2
0
static int suspend_prepare(u32 state)
{
	int error = 0;

	if (!pm_ops || !pm_ops->enter)
		return -EPERM;

	pm_prepare_console();

	if (freeze_processes()) {
		error = -EAGAIN;
		goto Thaw;
	}

	if (pm_ops->prepare) {
		if ((error = pm_ops->prepare(state)))
			goto Thaw;
	}

	if ((error = device_suspend(state)))
		goto Finish;
	return 0;
 Finish:
	if (pm_ops->finish)
		pm_ops->finish(state);
 Thaw:
	thaw_processes();
	pm_restore_console();
	return error;
}
Example #3
0
/**
 *	suspend_devices_and_enter - suspend devices and enter the desired system sleep
 *			  state.
 *	@state:		  state to enter
 */
int suspend_devices_and_enter(suspend_state_t state)
{
	int error;

	if (!pm_ops)
		return -ENOSYS;

	if (pm_ops->set_target) {
		error = pm_ops->set_target(state);
		if (error)
			return error;
	}
	suspend_console();
	error = device_suspend(PMSG_SUSPEND);
	if (error) {
		printk(KERN_ERR "Some devices failed to suspend\n");
		goto Resume_console;
	}
	if (pm_ops->prepare) {
		error = pm_ops->prepare(state);
		if (error)
			goto Resume_devices;
	}
	error = disable_nonboot_cpus();
	if (!error)
		suspend_enter(state);

	enable_nonboot_cpus();
	pm_finish(state);
 Resume_devices:
	device_resume();
 Resume_console:
	resume_console();
	return error;
}
static int prepare(void)
{
	int error;

	pm_prepare_console();

	sys_sync();
	if (freeze_processes()) {
		error = -EBUSY;
		goto Thaw;
	}

	if (pm_disk_mode == PM_DISK_PLATFORM) {
		if (pm_ops && pm_ops->prepare) {
			if ((error = pm_ops->prepare(PM_SUSPEND_DISK)))
				goto Thaw;
		}
	}

	/* Free memory before shutting down devices. */
	free_some_memory();

	if ((error = device_suspend(PM_SUSPEND_DISK)))
		goto Finish;

	return 0;
 Finish:
	platform_finish();
 Thaw:
	thaw_processes();
	pm_restore_console();
	return error;
}
Example #5
0
/**
 *	suspend_devices_and_enter - suspend devices and enter the desired system
 *				    sleep state.
 *	@state:		  state to enter
 */
int suspend_devices_and_enter(suspend_state_t state)
{
	int error, ftrace_save;

	if (!suspend_ops)
		return -ENOSYS;

	if (suspend_ops->begin) {
		error = suspend_ops->begin(state);
		if (error)
			goto Close;
	}
	suspend_console();
	ftrace_save = __ftrace_enabled_save();
	suspend_test_start();
	error = device_suspend(PMSG_SUSPEND);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to suspend\n");
		goto Recover_platform;
	}
	suspend_test_finish("suspend devices");
	if (suspend_test(TEST_DEVICES))
		goto Recover_platform;

	if (suspend_ops->prepare) {
		error = suspend_ops->prepare();
		if (error)
			goto Resume_devices;
	}

	if (suspend_test(TEST_PLATFORM))
		goto Finish;

	error = disable_nonboot_cpus();
	if (!error && !suspend_test(TEST_CPUS))
		suspend_enter(state);

	enable_nonboot_cpus();
 Finish:
	if (suspend_ops->finish)
		suspend_ops->finish();
 Resume_devices:
	suspend_test_start();
	device_resume(PMSG_RESUME);
	suspend_test_finish("resume devices");
	__ftrace_enabled_restore(ftrace_save);
	resume_console();
 Close:
	if (suspend_ops->end)
		suspend_ops->end();
	return error;

 Recover_platform:
	if (suspend_ops->recover)
		suspend_ops->recover();
	goto Resume_devices;
}
Example #6
0
int hibernation_platform_enter(void)
{
	int error;

	if (!hibernation_ops)
		return -ENOSYS;

	/*
	 * We have cancelled the power transition by running
	 * hibernation_ops->finish() before saving the image, so we should let
	 * the firmware know that we're going to enter the sleep state after all
	 */
	error = hibernation_ops->begin();
	if (error)
		goto Close;

	suspend_console();
	error = device_suspend(PMSG_HIBERNATE);
	if (error) {
		if (hibernation_ops->recover)
			hibernation_ops->recover();
		goto Resume_devices;
	}

	error = hibernation_ops->prepare();
	if (error)
		goto Resume_devices;

	error = disable_nonboot_cpus();
	if (error)
		goto Finish;

	device_pm_lock();
	local_irq_disable();
	error = device_power_down(PMSG_HIBERNATE);
	if (!error) {
		hibernation_ops->enter();
		/* We should never get here */
		while (1);
	}
	local_irq_enable();
	device_pm_unlock();

	/*
	 * We don't need to reenable the nonboot CPUs or resume consoles, since
	 * the system is going to be halted anyway.
	 */
 Finish:
	hibernation_ops->finish();
 Resume_devices:
	device_resume(PMSG_RESTORE);
	resume_console();
 Close:
	hibernation_ops->end();
	return error;
}
Example #7
0
static void suspend_devices(int pm_policy)
{
	int i;

	for (i = 0; i < device_count; i++) {
		int idx = device_policy_list[i];

		device_retval[i] = device_suspend(&device_list[idx], pm_policy);
	}
}
Example #8
0
static READ32_HANDLER( FlipCount_r )
{
	crystal_state *state = space->machine().driver_data<crystal_state>();

#ifdef IDLE_LOOP_SPEEDUP
	UINT32 IntPend = space->read_dword(0x01800c0c);
	state->m_FlipCntRead++;
	if (state->m_FlipCntRead >= 16 && !IntPend && state->m_FlipCount != 0)
		device_suspend(state->m_maincpu, SUSPEND_REASON_SPIN, 1);
#endif
	return ((UINT32) state->m_FlipCount) << 16;
}
Example #9
0
int pm_suspend_disk(void)
{
	int error;

	error = prepare_processes();
	if (error)
		return error;

	if (pm_disk_mode == PM_DISK_TESTPROC)
		return 0;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error) {
		resume_console();
		printk("Some devices failed to suspend\n");
		goto Thaw;
	}

	if (pm_disk_mode == PM_DISK_TEST) {
		printk("swsusp debug: Waiting for 5 seconds.\n");
		mdelay(5000);
		goto Done;
	}

	pr_debug("PM: snapshotting memory.\n");
	in_suspend = 1;
	if ((error = swsusp_suspend()))
		goto Done;

	if (in_suspend) {
		device_resume();
		resume_console();
		pr_debug("PM: writing image.\n");
		error = swsusp_write();
		if (!error)
			power_down(pm_disk_mode);
		else {
			swsusp_free();
			goto Thaw;
		}
	} else {
		pr_debug("PM: Image restored successfully.\n");
	}

	swsusp_free();
 Done:
	device_resume();
	resume_console();
 Thaw:
	unprepare_processes();
	return error;
}
static int suspend_prepare(suspend_state_t state)
{
	int error = 0;
	unsigned int free_pages;

	if (!pm_ops || !pm_ops->enter)
		return -EPERM;

	pm_prepare_console();

	disable_nonboot_cpus();

	if (num_online_cpus() != 1) {
		error = -EPERM;
		goto Enable_cpu;
	}

	if (freeze_processes()) {
		error = -EAGAIN;
		goto Thaw;
	}

	if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) {
		pr_debug("PM: free some memory\n");
		shrink_all_memory(FREE_PAGE_NUMBER - free_pages);
		if (nr_free_pages() < FREE_PAGE_NUMBER) {
			error = -ENOMEM;
			printk(KERN_ERR "PM: No enough memory\n");
			goto Thaw;
		}
	}

	if (pm_ops->prepare) {
		if ((error = pm_ops->prepare(state)))
			goto Thaw;
	}

	if ((error = device_suspend(PMSG_SUSPEND))) {
		printk(KERN_ERR "Some devices failed to suspend\n");
		goto Finish;
	}
	return 0;
 Finish:
	if (pm_ops->finish)
		pm_ops->finish(state);
 Thaw:
	thaw_processes();
 Enable_cpu:
	enable_nonboot_cpus();
	pm_restore_console();
	return error;
}
Example #11
0
int hibernation_snapshot(int platform_mode)
{
	int error;

	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		return error;

	error = platform_begin(platform_mode);
	if (error)
		goto Close;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error)
		goto Recover_platform;

	if (hibernation_test(TEST_DEVICES))
		goto Recover_platform;

	error = platform_pre_snapshot(platform_mode);
	if (error || hibernation_test(TEST_PLATFORM))
		goto Finish;

	error = disable_nonboot_cpus();
	if (!error) {
		if (hibernation_test(TEST_CPUS))
			goto Enable_cpus;

		if (hibernation_testmode(HIBERNATION_TEST))
			goto Enable_cpus;

		error = create_image(platform_mode);
		/* Control returns here after successful restore */
	}
 Enable_cpus:
	enable_nonboot_cpus();
 Finish:
	platform_finish(platform_mode);
 Resume_devices:
	device_resume(in_suspend ?
		(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
	resume_console();
 Close:
	platform_end(platform_mode);
	return error;

 Recover_platform:
	platform_recover(platform_mode);
	goto Resume_devices;
}
Example #12
0
File: ngp.c Project: poliva/mame-rr
void ngp_state::machine_reset()
{
	m_old_to3 = 0;
	m_tlcs900 = machine().device( "maincpu" );
	m_z80 = machine().device( "soundcpu" );
	m_t6w28 = machine().device( "t6w28" );
	m_dac_l = machine().device( "dac_l" );
	m_dac_r = machine().device( "dac_r" );
	m_k1ge = machine().device( "k1ge" );

	device_suspend( m_z80, SUSPEND_REASON_HALT, 1 );
	device_set_input_line( m_z80, 0, CLEAR_LINE );
}
Example #13
0
/*
 * test_dev_suspend
 *	make test call to device_suspend and
 *	if that call is successful then make
 *	a call to device_resume
 */
static int test_dev_suspend() {
	int error = 0;

	error = device_suspend(SUSPEND_SAVE_STATE);
	if (error)
		printk("tbase: Failed on device suspend call\n");
	else {
		printk("tbase: Successful on device suspend call\n");
		device_resume();
	}

	error = device_suspend(SUSPEND_DISABLE);
        if (error)
                printk("tbase: Failed on device suspend call\n");
        else {
                printk("tbase: Successful on device suspend call\n");
                device_resume();
        }

	return error;

}
Example #14
0
static int suspend_prepare(suspend_state_t state)
{
	int error;
	unsigned int free_pages;

	if (!pm_ops || !pm_ops->enter)
		return -EPERM;

	pm_prepare_console();

	if (freeze_processes()) {
		error = -EAGAIN;
		goto Thaw;
	}

	if ((free_pages = global_page_state(NR_FREE_PAGES))
			< FREE_PAGE_NUMBER) {
		pr_debug("PM: free some memory\n");
		shrink_all_memory(FREE_PAGE_NUMBER - free_pages);
		if (nr_free_pages() < FREE_PAGE_NUMBER) {
			error = -ENOMEM;
			printk(KERN_ERR "PM: No enough memory\n");
			goto Thaw;
		}
	}

	if (pm_ops->prepare) {
		if ((error = pm_ops->prepare(state)))
			goto Thaw;
	}

	suspend_console();
	error = device_suspend(PMSG_SUSPEND);
	if (error) {
		printk(KERN_ERR "Some devices failed to suspend\n");
		goto Resume_devices;
	}
	error = disable_nonboot_cpus();
	if (!error)
		return 0;

	enable_nonboot_cpus();
 Resume_devices:
	pm_finish(state);
	device_resume();
	resume_console();
 Thaw:
	thaw_processes();
	pm_restore_console();
	return error;
}
static void do_suspend(void)
{
	int err;
	int cancelled = 1;

	shutting_down = SHUTDOWN_SUSPEND;

#ifdef CONFIG_PREEMPT
	/* If the kernel is preemptible, we need to freeze all the processes
	   to prevent them from being in the middle of a pagetable update
	   during suspend. */
	err = freeze_processes();
	if (err) {
		printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
		return;
	}
#endif

	err = device_suspend(PMSG_SUSPEND);
	if (err) {
		printk(KERN_ERR "xen suspend: device_suspend %d\n", err);
		goto out;
	}

	printk("suspending xenbus...\n");
	/* XXX use normal device tree? */
	xenbus_suspend();

	err = stop_machine(xen_suspend, &cancelled, &cpumask_of_cpu(0));
	if (err) {
		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
		goto out;
	}

	if (!cancelled) {
		xen_arch_resume();
		xenbus_resume();
	} else
		xenbus_suspend_cancel();

	device_resume(PMSG_RESUME);

	/* Make sure timer events get retriggered on all CPUs */
	clock_was_set();
out:
#ifdef CONFIG_PREEMPT
	thaw_processes();
#endif
	shutting_down = SHUTDOWN_INVALID;
}
Example #16
0
int hibernation_snapshot(int platform_mode)
{
	int error;

	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		return error;

	error = platform_start(platform_mode);
	if (error)
		return error;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error)
		goto Resume_console;

	error = platform_pre_snapshot(platform_mode);
	if (error)
		goto Resume_devices;

	error = disable_nonboot_cpus();
	if (!error) {
		if (hibernation_mode != HIBERNATION_TEST) {
			in_suspend = 1;
			error = create_image(platform_mode);
			/* Control returns here after successful restore */
		} else {
			printk("swsusp debug: Waiting for 5 seconds.\n");
			mdelay(5000);
		}
	}
	enable_nonboot_cpus();
 Resume_devices:
	platform_finish(platform_mode);
	device_resume();
 Resume_console:
	resume_console();
	return error;
}
Example #17
0
int pm_suspend_disk(void)
{
	int error;

	error = prepare_processes();
	if (error)
		return error;

	error = device_suspend(PMSG_FREEZE);
	if (error) {
		printk("Some devices failed to suspend\n");
		unprepare_processes();
		return error;
	}

	pr_debug("PM: snapshotting memory.\n");
	in_suspend = 1;
	if ((error = swsusp_suspend()))
		goto Done;

	if (in_suspend) {
		pr_debug("PM: writing image.\n");
		error = swsusp_write();
		if (!error)
			power_down(pm_disk_mode);
		else {
		/* swsusp_write can not fail in device_resume,
		   no need to do second device_resume */
			swsusp_free();
			unprepare_processes();
			return error;
		}
	} else
		pr_debug("PM: Image restored successfully.\n");

	swsusp_free();
 Done:
	device_resume();
	unprepare_processes();
	return error;
}
Example #18
0
/**
 *	suspend_devices_and_enter - suspend devices and enter the desired system
 *				    sleep state.
 *	@state:		  state to enter
 */
int suspend_devices_and_enter(suspend_state_t state)
{
	int error;

	if (!suspend_ops)
		return -ENOSYS;

	if (suspend_ops->begin) {
		error = suspend_ops->begin(state);
		if (error)
			goto Close;
	}
	suspend_console();
	suspend_test_start();
	error = device_suspend(PMSG_SUSPEND);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to suspend\n");
		goto Recover_platform;
	}
	suspend_test_finish("suspend devices");
	if (suspend_test(TEST_DEVICES))
		goto Recover_platform;

	suspend_enter(state);

 Resume_devices:
	suspend_test_start();
	device_resume(PMSG_RESUME);
	suspend_test_finish("resume devices");
	resume_console();
 Close:
	if (suspend_ops->end)
		suspend_ops->end();
	return error;

 Recover_platform:
	if (suspend_ops->recover)
		suspend_ops->recover();
	goto Resume_devices;
}
Example #19
0
static inline int snapshot_suspend(int platform_suspend)
{
	int error;

	mutex_lock(&pm_mutex);
	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		goto Finish;

	if (platform_suspend) {
		error = platform_prepare();
		if (error)
			goto Finish;
	}
	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error)
		goto Resume_devices;

	error = disable_nonboot_cpus();
	if (!error) {
		in_suspend = 1;
		error = swsusp_suspend();
	}
	enable_nonboot_cpus();
 Resume_devices:
	if (platform_suspend)
		platform_finish();

	device_resume();
	resume_console();
 Finish:
	mutex_unlock(&pm_mutex);
	return error;
}
Example #20
0
int hibernation_restore(int platform_mode)
{
	int error;

	pm_prepare_console();
	suspend_console();
	error = device_suspend(PMSG_PRETHAW);
	if (error)
		goto Finish;

	error = platform_pre_restore(platform_mode);
	if (!error) {
		error = disable_nonboot_cpus();
		if (!error)
			error = swsusp_resume();
		enable_nonboot_cpus();
	}
	platform_restore_cleanup(platform_mode);
	device_resume();
 Finish:
	resume_console();
	pm_restore_console();
	return error;
}
Example #21
0
int hibernation_restore(int platform_mode)
{
	int error;

	pm_prepare_console();
	suspend_console();
	error = device_suspend(PMSG_QUIESCE);
	if (error)
		goto Finish;

	error = platform_pre_restore(platform_mode);
	if (!error) {
		error = disable_nonboot_cpus();
		if (!error)
			error = resume_target_kernel();
		enable_nonboot_cpus();
	}
	platform_restore_cleanup(platform_mode);
	device_resume(PMSG_RECOVER);
 Finish:
	resume_console();
	pm_restore_console();
	return error;
}
Example #22
0
static int software_resume(void)
{
	int error;

	down(&pm_sem);
	if (!swsusp_resume_device) {
		if (!strlen(resume_file)) {
			up(&pm_sem);
			return -ENOENT;
		}
		swsusp_resume_device = name_to_dev_t(resume_file);
		pr_debug("swsusp: Resume From Partition %s\n", resume_file);
	} else {
		pr_debug("swsusp: Resume From Partition %d:%d\n",
			 MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
	}

	if (noresume) {
		/**
		 * FIXME: If noresume is specified, we need to find the partition
		 * and reset it back to normal swap space.
		 */
		up(&pm_sem);
		return 0;
	}

	pr_debug("PM: Checking swsusp image.\n");

	if ((error = swsusp_check()))
		goto Done;

	pr_debug("PM: Preparing processes for restore.\n");

	if ((error = prepare_processes())) {
		swsusp_close();
		goto Done;
	}

	pr_debug("PM: Reading swsusp image.\n");

	if ((error = swsusp_read()))
		goto Cleanup;

	pr_debug("PM: Preparing devices for restore.\n");

	if ((error = device_suspend(PMSG_FREEZE))) {
		printk("Some devices failed to suspend\n");
		goto Free;
	}

	mb();

	pr_debug("PM: Restoring saved image.\n");
	swsusp_resume();
	pr_debug("PM: Restore failed, recovering.n");
	device_resume();
 Free:
	swsusp_free();
 Cleanup:
	unprepare_processes();
 Done:
	/* For success case, the suspend path will release the lock */
	up(&pm_sem);
	pr_debug("PM: Resume from disk failed.\n");
	return 0;
}
Example #23
0
static int software_resume(void)
{
	int error;

	mutex_lock(&pm_mutex);
	if (!swsusp_resume_device) {
		if (!strlen(resume_file)) {
			mutex_unlock(&pm_mutex);
			return -ENOENT;
		}
		swsusp_resume_device = name_to_dev_t(resume_file);
		pr_debug("swsusp: Resume From Partition %s\n", resume_file);
	} else {
		pr_debug("swsusp: Resume From Partition %d:%d\n",
			 MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
	}

	if (noresume) {
		/**
		 * FIXME: If noresume is specified, we need to find the partition
		 * and reset it back to normal swap space.
		 */
		mutex_unlock(&pm_mutex);
		return 0;
	}

	pr_debug("PM: Checking swsusp image.\n");
	error = swsusp_check();
	if (error)
		goto Unlock;

	error = create_basic_memory_bitmaps();
	if (error)
		goto Unlock;

	pr_debug("PM: Preparing processes for restore.\n");
	error = prepare_processes();
	if (error) {
		swsusp_close();
		goto Done;
	}

	pr_debug("PM: Reading swsusp image.\n");

	error = swsusp_read();
	if (error) {
		swsusp_free();
		goto Thaw;
	}

	pr_debug("PM: Preparing devices for restore.\n");

	suspend_console();
	error = device_suspend(PMSG_PRETHAW);
	if (error)
		goto Free;

	error = disable_nonboot_cpus();
	if (!error)
		swsusp_resume();

	enable_nonboot_cpus();
 Free:
	swsusp_free();
	device_resume();
	resume_console();
 Thaw:
	printk(KERN_ERR "PM: Restore failed, recovering.\n");
	unprepare_processes();
 Done:
	free_basic_memory_bitmaps();
	/* For success case, the suspend path will release the lock */
 Unlock:
	mutex_unlock(&pm_mutex);
	pr_debug("PM: Resume from disk failed.\n");
	return 0;
}
Example #24
0
static int snapshot_ioctl(struct inode *inode, struct file *filp,
                          unsigned int cmd, unsigned long arg)
{
    int error = 0;
    struct snapshot_data *data;
    loff_t offset, avail;

    if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
        return -ENOTTY;
    if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
        return -ENOTTY;
    if (!capable(CAP_SYS_ADMIN))
        return -EPERM;

    data = filp->private_data;

    switch (cmd) {

    case SNAPSHOT_FREEZE:
        if (data->frozen)
            break;
        down(&pm_sem);
        disable_nonboot_cpus();
        if (freeze_processes()) {
            thaw_processes();
            enable_nonboot_cpus();
            error = -EBUSY;
        }
        up(&pm_sem);
        if (!error)
            data->frozen = 1;
        break;

    case SNAPSHOT_UNFREEZE:
        if (!data->frozen)
            break;
        down(&pm_sem);
        thaw_processes();
        enable_nonboot_cpus();
        up(&pm_sem);
        data->frozen = 0;
        break;

    case SNAPSHOT_ATOMIC_SNAPSHOT:
        if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
            error = -EPERM;
            break;
        }
        down(&pm_sem);
        /* Free memory before shutting down devices. */
        error = swsusp_shrink_memory();
        if (!error) {
            error = device_suspend(PMSG_FREEZE);
            if (!error) {
                in_suspend = 1;
                error = swsusp_suspend();
                device_resume();
            }
        }
        up(&pm_sem);
        if (!error)
            error = put_user(in_suspend, (unsigned int __user *)arg);
        if (!error)
            data->ready = 1;
        break;

    case SNAPSHOT_ATOMIC_RESTORE:
        if (data->mode != O_WRONLY || !data->frozen ||
                !snapshot_image_loaded(&data->handle)) {
            error = -EPERM;
            break;
        }
        down(&pm_sem);
        pm_prepare_console();
        error = device_suspend(PMSG_FREEZE);
        if (!error) {
            error = swsusp_resume();
            device_resume();
        }
        pm_restore_console();
        up(&pm_sem);
        break;

    case SNAPSHOT_FREE:
        swsusp_free();
        memset(&data->handle, 0, sizeof(struct snapshot_handle));
        data->ready = 0;
        break;

    case SNAPSHOT_SET_IMAGE_SIZE:
        image_size = arg;
        break;

    case SNAPSHOT_AVAIL_SWAP:
        avail = count_swap_pages(data->swap, 1);
        avail <<= PAGE_SHIFT;
        error = put_user(avail, (loff_t __user *)arg);
        break;

    case SNAPSHOT_GET_SWAP_PAGE:
        if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
            error = -ENODEV;
            break;
        }
        if (!data->bitmap) {
            data->bitmap = alloc_bitmap(count_swap_pages(data->swap, 0));
            if (!data->bitmap) {
                error = -ENOMEM;
                break;
            }
        }
        offset = alloc_swap_page(data->swap, data->bitmap);
        if (offset) {
            offset <<= PAGE_SHIFT;
            error = put_user(offset, (loff_t __user *)arg);
        } else {
            error = -ENOSPC;
        }
        break;

    case SNAPSHOT_FREE_SWAP_PAGES:
        if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
            error = -ENODEV;
            break;
        }
        free_all_swap_pages(data->swap, data->bitmap);
        free_bitmap(data->bitmap);
        data->bitmap = NULL;
        break;

    case SNAPSHOT_SET_SWAP_FILE:
        if (!data->bitmap) {
            /*
             * User space encodes device types as two-byte values,
             * so we need to recode them
             */
            if (old_decode_dev(arg)) {
                data->swap = swap_type_of(old_decode_dev(arg));
                if (data->swap < 0)
                    error = -ENODEV;
            } else {
                data->swap = -1;
                error = -EINVAL;
            }
        } else {
            error = -EPERM;
        }
        break;

    case SNAPSHOT_S2RAM:
        if (!data->frozen) {
            error = -EPERM;
            break;
        }

        if (down_trylock(&pm_sem)) {
            error = -EBUSY;
            break;
        }

        if (pm_ops->prepare) {
            error = pm_ops->prepare(PM_SUSPEND_MEM);
            if (error)
                goto OutS3;
        }

        /* Put devices to sleep */
        error = device_suspend(PMSG_SUSPEND);
        if (error) {
            printk(KERN_ERR "Failed to suspend some devices.\n");
        } else {
            /* Enter S3, system is already frozen */
            suspend_enter(PM_SUSPEND_MEM);

            /* Wake up devices */
            device_resume();
        }

        if (pm_ops->finish)
            pm_ops->finish(PM_SUSPEND_MEM);

OutS3:
        up(&pm_sem);
        break;

    default:
        error = -ENOTTY;

    }

    return error;
}
Example #25
0
/* Called from process context */
static int drivers_suspend(void)
{
	return device_suspend(4);
}
Example #26
0
static int snapshot_ioctl(struct inode *inode, struct file *filp,
                          unsigned int cmd, unsigned long arg)
{
	int error = 0;
	struct snapshot_data *data;
	loff_t avail;
	sector_t offset;

	if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
		return -ENOTTY;
	if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
		return -ENOTTY;
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	data = filp->private_data;

	switch (cmd) {

	case SNAPSHOT_FREEZE:
		if (data->frozen)
			break;
		mutex_lock(&pm_mutex);
		if (freeze_processes()) {
			thaw_processes();
			error = -EBUSY;
		}
		mutex_unlock(&pm_mutex);
		if (!error)
			data->frozen = 1;
		break;

	case SNAPSHOT_UNFREEZE:
		if (!data->frozen || data->ready)
			break;
		mutex_lock(&pm_mutex);
		thaw_processes();
		mutex_unlock(&pm_mutex);
		data->frozen = 0;
		break;

	case SNAPSHOT_ATOMIC_SNAPSHOT:
		if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
			error = -EPERM;
			break;
		}
		error = snapshot_suspend(data->platform_suspend);
		if (!error)
			error = put_user(in_suspend, (unsigned int __user *)arg);
		if (!error)
			data->ready = 1;
		break;

	case SNAPSHOT_ATOMIC_RESTORE:
		snapshot_write_finalize(&data->handle);
		if (data->mode != O_WRONLY || !data->frozen ||
		    !snapshot_image_loaded(&data->handle)) {
			error = -EPERM;
			break;
		}
		error = snapshot_restore(data->platform_suspend);
		break;

	case SNAPSHOT_FREE:
		swsusp_free();
		memset(&data->handle, 0, sizeof(struct snapshot_handle));
		data->ready = 0;
		break;

	case SNAPSHOT_SET_IMAGE_SIZE:
		image_size = arg;
		break;

	case SNAPSHOT_AVAIL_SWAP:
		avail = count_swap_pages(data->swap, 1);
		avail <<= PAGE_SHIFT;
		error = put_user(avail, (loff_t __user *)arg);
		break;

	case SNAPSHOT_GET_SWAP_PAGE:
		if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
			error = -ENODEV;
			break;
		}
		offset = alloc_swapdev_block(data->swap);
		if (offset) {
			offset <<= PAGE_SHIFT;
			error = put_user(offset, (sector_t __user *)arg);
		} else {
			error = -ENOSPC;
		}
		break;

	case SNAPSHOT_FREE_SWAP_PAGES:
		if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
			error = -ENODEV;
			break;
		}
		free_all_swap_pages(data->swap);
		break;

	case SNAPSHOT_SET_SWAP_FILE:
		if (!swsusp_swap_in_use()) {
			/*
			 * User space encodes device types as two-byte values,
			 * so we need to recode them
			 */
			if (old_decode_dev(arg)) {
				data->swap = swap_type_of(old_decode_dev(arg),
							0, NULL);
				if (data->swap < 0)
					error = -ENODEV;
			} else {
				data->swap = -1;
				error = -EINVAL;
			}
		} else {
			error = -EPERM;
		}
		break;

	case SNAPSHOT_S2RAM:
		if (!pm_ops) {
			error = -ENOSYS;
			break;
		}

		if (!data->frozen) {
			error = -EPERM;
			break;
		}

		if (!mutex_trylock(&pm_mutex)) {
			error = -EBUSY;
			break;
		}

		if (pm_ops->prepare) {
			error = pm_ops->prepare(PM_SUSPEND_MEM);
			if (error)
				goto OutS3;
		}

		/* Put devices to sleep */
		suspend_console();
		error = device_suspend(PMSG_SUSPEND);
		if (error) {
			printk(KERN_ERR "Failed to suspend some devices.\n");
		} else {
			error = disable_nonboot_cpus();
			if (!error) {
				/* Enter S3, system is already frozen */
				suspend_enter(PM_SUSPEND_MEM);
				enable_nonboot_cpus();
			}
			/* Wake up devices */
			device_resume();
		}
		resume_console();
		if (pm_ops->finish)
			pm_ops->finish(PM_SUSPEND_MEM);

 OutS3:
		mutex_unlock(&pm_mutex);
		break;

	case SNAPSHOT_PMOPS:
		error = -EINVAL;

		switch (arg) {

		case PMOPS_PREPARE:
			if (hibernation_ops) {
				data->platform_suspend = 1;
				error = 0;
			} else {
				error = -ENOSYS;
			}
			break;

		case PMOPS_ENTER:
			if (data->platform_suspend) {
				kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
				error = hibernation_ops->enter();
			}
			break;

		case PMOPS_FINISH:
			if (data->platform_suspend)
				error = 0;

			break;

		default:
			printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);

		}
		break;

	case SNAPSHOT_SET_SWAP_AREA:
		if (swsusp_swap_in_use()) {
			error = -EPERM;
		} else {
			struct resume_swap_area swap_area;
			dev_t swdev;

			error = copy_from_user(&swap_area, (void __user *)arg,
					sizeof(struct resume_swap_area));
			if (error) {
				error = -EFAULT;
				break;
			}

			/*
			 * User space encodes device types as two-byte values,
			 * so we need to recode them
			 */
			swdev = old_decode_dev(swap_area.dev);
			if (swdev) {
				offset = swap_area.offset;
				data->swap = swap_type_of(swdev, offset, NULL);
				if (data->swap < 0)
					error = -ENODEV;
			} else {
				data->swap = -1;
				error = -EINVAL;
			}
		}
		break;

	default:
		error = -ENOTTY;

	}

	return error;
}
Example #27
0
int pm_suspend_disk(void)
{
	int error;

	error = prepare_processes();
	if (error)
		return error;

	if (pm_disk_mode == PM_DISK_TESTPROC) {
		printk("swsusp debug: Waiting for 5 seconds.\n");
		mdelay(5000);
		goto Thaw;
	}
	/* Allocate memory management structures */
	error = create_basic_memory_bitmaps();
	if (error)
		goto Thaw;

	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		goto Finish;

	error = platform_prepare();
	if (error)
		goto Finish;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to suspend\n");
		goto Resume_devices;
	}
	error = disable_nonboot_cpus();
	if (error)
		goto Enable_cpus;

	if (pm_disk_mode == PM_DISK_TEST) {
		printk("swsusp debug: Waiting for 5 seconds.\n");
		mdelay(5000);
		goto Enable_cpus;
	}

	pr_debug("PM: snapshotting memory.\n");
	in_suspend = 1;
	error = swsusp_suspend();
	if (error)
		goto Enable_cpus;

	if (in_suspend) {
		enable_nonboot_cpus();
		platform_finish();
		device_resume();
		resume_console();
		pr_debug("PM: writing image.\n");
		error = swsusp_write();
		if (!error)
			power_down(pm_disk_mode);
		else {
			swsusp_free();
			goto Finish;
		}
	} else {
		pr_debug("PM: Image restored successfully.\n");
	}

	swsusp_free();
 Enable_cpus:
	enable_nonboot_cpus();
 Resume_devices:
	platform_finish();
	device_resume();
	resume_console();
 Finish:
	free_basic_memory_bitmaps();
 Thaw:
	unprepare_processes();
	return error;
}