Commit d72fb463 authored by Pavel Machek's avatar Pavel Machek Committed by Linus Torvalds

[PATCH] swsusp: cleanup

 - use list_for_each in head_of_free_region
 - cleanups from 2.4
 - fix for usb
 - kill broken queueing
parent 455980ab
......@@ -45,6 +45,7 @@ restrictions referred to are that the relevant option is valid if:
SERIAL Serial support is enabled.
SMP The kernel is an SMP kernel.
SOUND Appropriate sound system support is enabled.
SWSUSP Software suspension is enabled.
V4L Video For Linux support is enabled.
VGA The VGA console has been enabled.
VT Virtual terminal support is enabled.
......@@ -392,6 +393,8 @@ running once the system is up.
initial RAM disk.
nointroute [IA-64]
noresume [SWSUSP] Disables resume and restore original swap space.
no-scroll [VGA]
......@@ -519,6 +522,8 @@ running once the system is up.
reserve= [KNL,BUGS] force the kernel to ignore some iomem area.
resume= [SWSUSP] specify the partition device for software suspension.
riscom8= [HW,SERIAL]
ro [KNL] Mount root device read-only on boot.
......
......@@ -262,7 +262,6 @@ ENTRY(saved_esp) .long 0
ENTRY(saved_magic) .long 0
ENTRY(saved_magic2) .long 0
ENTRY(saved_videomode) .long 0
ALIGN
# saved registers
......
......@@ -168,6 +168,8 @@ void __init visws_get_board_type_and_rev(void);
static int disable_x86_serial_nr __initdata = 1;
static int disable_x86_fxsr __initdata = 0;
unsigned long saved_videomode;
extern unsigned long saved_videomode;
/*
......@@ -684,10 +686,8 @@ void __init setup_arch(char **cmdline_p)
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
apm_info.bios = APM_BIOS_INFO;
#ifdef CONFIG_ACPI_SLEEP
saved_videomode = VIDEO_MODE;
printk("Video mode to be used for restore is %lx\n", saved_videomode);
#endif
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
......
......@@ -709,11 +709,9 @@ acpi_system_write_sleep (
if (!system->states[state])
return_VALUE(-ENODEV);
#ifdef CONFIG_SOFTWARE_SUSPEND
if (state == 4) {
/* We are working from process context, that's why we may call it directly. */
do_software_suspend();
software_suspend();
return_VALUE(count);
}
#endif
......
......@@ -4220,14 +4220,15 @@ static int __init floppy_setup(char *str)
static int have_no_fdc= -ENODEV;
static struct device device_floppy;
static struct device device_floppy = {
name: "floppy",
bus_id: "03?0",
};
int __init floppy_init(void)
{
int i,unit,drive;
strcpy(device_floppy.name, "floppy");
strcpy(device_floppy.bus_id, "03?0");
register_sys_device(&device_floppy);
raw_cmd = NULL;
......
......@@ -577,7 +577,9 @@ static int loop_thread(void *data)
daemonize();
sprintf(current->comm, "loop%d", lo->lo_number);
current->flags |= PF_IOTHREAD;
current->flags |= PF_IOTHREAD; /* loop can be used in an encrypted device
hence, it mustn't be stopped at all because it could
be indirectly used during suspension */
spin_lock_irq(&current->sigmask_lock);
sigfillset(&current->blocked);
......
......@@ -25,6 +25,7 @@
#endif
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/suspend.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
......@@ -1064,6 +1065,8 @@ static int usb_hub_thread(void *__hub)
/* Send me a signal to get me die (for debugging) */
do {
usb_hub_events();
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
} while (!signal_pending(current));
......
......@@ -122,8 +122,6 @@ void unlock_buffer(struct buffer_head *bh)
wake_up_buffer(bh);
}
DECLARE_TASK_QUEUE(tq_bdflush);
/*
* Block until a buffer comes unlocked. This doesn't stop it
* from becoming locked again - you have to lock it yourself
......
......@@ -226,7 +226,6 @@ int kjournald(void *arg)
journal->j_commit_interval / HZ);
list_add(&journal->j_all_journals, &all_journals);
current->flags |= PF_KERNTHREAD;
/* And now, wait forever for commit wakeup events. */
while (1) {
if (journal->j_flags & JFS_UNMOUNT)
......
......@@ -1888,7 +1888,6 @@ static int reiserfs_journal_commit_thread(void *nullp) {
spin_unlock_irq(&current->sigmask_lock);
sprintf(current->comm, "kreiserfsd") ;
current->flags |= PF_KERNTHREAD;
lock_kernel() ;
while(1) {
......
#ifndef __ASM_I386_SUSPEND_H
#define __ASM_I386_SUSPEND_H
#endif
/*
* Copyright 2001-2002 Pavel Machek <pavel@suse.cz>
* Based on code
* Copyright 2001 Patrick Mochel <mochel@osdl.org>
*/
#if defined(SUSPEND_C) || defined(ACPI_C)
#include <asm/desc.h>
#include <asm/i387.h>
......@@ -225,7 +220,6 @@ static inline void restore_processor_context (void)
do_fpu_end();
}
#endif
#ifdef SUSPEND_C
/* Local variables for do_magic */
static int loop __nosavedata = 0;
......
#ifndef _LINUX_SWSUSP_H
#define _LINUX_SWSUSP_H
#if defined(SUSPEND_C) || defined(ACPI_C)
#include <asm/suspend.h>
#endif
#include <linux/swap.h>
#include <linux/notifier.h>
#include <linux/config.h>
......
......@@ -66,7 +66,7 @@ typedef struct list_head task_queue;
#define DECLARE_TASK_QUEUE(q) LIST_HEAD(q)
#define TQ_ACTIVE(q) (!list_empty(&q))
extern task_queue tq_timer, tq_immediate, tq_bdflush;
extern task_queue tq_timer, tq_immediate;
/*
* To implement your own list of active bottom halfs, use the following
......
/*
* linux/kernel/swsusp.c
* linux/kernel/suspend.c
*
* This file is to realize architecture-independent
* machine suspend feature using pretty near only high-level routines
......@@ -34,13 +34,6 @@
* For TODOs,FIXMEs also look in Documentation/swsusp.txt
*/
/*
* TODO:
*
* - we should launch a kernel_thread to process suspend request, cleaning up
* bdflush from this task. (check apm.c for something similar).
*/
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/swapctl.h>
......@@ -65,6 +58,7 @@
#include <linux/swap.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/buffer_head.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
......@@ -78,7 +72,7 @@ unsigned char software_suspend_enabled = 0;
we probably do not take enough locks for switching consoles, etc,
so bad things might happen.
*/
#ifndef CONFIG_VT
#if !defined(CONFIG_VT) || !defined(CONFIG_VT_CONSOLE)
#undef SUSPEND_CONSOLE
#endif
......@@ -152,7 +146,7 @@ static const char *name_resume = "Resume Machine: ";
#define DEBUG_DEFAULT 1
#undef DEBUG_PROCESS
#undef DEBUG_SLOW
#define TEST_SWSUSP 0 /* Set to 1 to reboot instead of halt machine after suspension */
#define TEST_SWSUSP 1 /* Set to 1 to reboot instead of halt machine after suspension */
#ifdef DEBUG_DEFAULT
#define PRINTD(func, f, a...) \
......@@ -775,7 +769,10 @@ void suspend_power_down(void)
machine_restart(NULL);
else
#endif
{
device_shutdown();
machine_power_off();
}
printk(KERN_EMERG "%sProbably not capable for powerdown. System halted.\n", name_suspend);
machine_halt();
......@@ -783,9 +780,6 @@ void suspend_power_down(void)
/* NOTREACHED */
}
/* forward decl */
void do_software_suspend(void);
/*
* Magic happens here
*/
......@@ -822,7 +816,6 @@ static void do_magic_resume_2(void)
#ifdef SUSPEND_CONSOLE
update_screen(fg_console); /* Hmm, is this the problem? */
#endif
suspend_tq.routine = (void *)do_software_suspend;
}
static void do_magic_suspend_1(void)
......@@ -851,7 +844,6 @@ static void do_magic_suspend_2(void)
drivers_resume(RESUME_PHASE1);
spin_unlock_irq(&suspend_pagedir_lock);
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
suspend_tq.routine = (void *)do_software_suspend;
printk(KERN_WARNING "%sLeaving do_magic_suspend_2...\n", name_suspend);
}
......@@ -859,43 +851,38 @@ static void do_magic_suspend_2(void)
#include <asm/suspend.h>
/*
* This function is triggered using process bdflush. We try to swap out as
* much as we can then make a copy of the occupied pages in memory so we can
* make a copy of kernel state atomically, the I/O needed by saving won't
* bother us anymore.
* We try to swap out as much as we can then make a copy of the
* occupied pages in memory so we can make a copy of kernel state
* atomically, the I/O needed by saving won't bother us anymore.
*/
void do_software_suspend(void)
{
arch_prepare_suspend();
if (!prepare_suspend_console()) {
if (!prepare_suspend_processes()) {
free_some_memory();
/* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway.
*
* We sync here -- so you have consistent filesystem state when things go wrong.
* -- so that noone writes to disk after we do atomic copy of data.
*/
PRINTS("Syncing disks before copy\n");
do_suspend_sync();
if(drivers_suspend()==0)
do_magic(0); /* This function returns after machine woken up from resume */
PRINTR("Restarting processes...\n");
thaw_processes();
}
if (prepare_suspend_console())
printk( "Can't allocate a console... proceeding\n");
if (!prepare_suspend_processes()) {
free_some_memory();
/* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway.
*
* We sync here -- so you have consistent filesystem state when things go wrong.
* -- so that noone writes to disk after we do atomic copy of data.
*/
PRINTS("Syncing disks before copy\n");
do_suspend_sync();
if(drivers_suspend()==0)
do_magic(0); /* This function returns after machine woken up from resume */
PRINTR("Restarting processes...\n");
thaw_processes();
}
software_suspend_enabled = 1;
MDELAY(1000);
restore_console ();
}
struct tq_struct suspend_tq =
{ routine: (void *)(void *)do_software_suspend,
data: 0 };
/*
* This is the trigger function, we must queue ourself since we
* can be called from interrupt && bdflush context is needed
* This is main interface to the outside world. It needs to be
* called from process context.
*/
void software_suspend(void)
{
......@@ -903,8 +890,8 @@ void software_suspend(void)
return;
software_suspend_enabled = 0;
queue_task(&suspend_tq, &tq_bdflush);
wakeup_bdflush();
BUG_ON(in_interrupt());
do_software_suspend();
}
/* More restore stuff */
......@@ -1123,6 +1110,7 @@ static int resume_try_to_read(const char * specialfile, int noresume)
pagedir_order = get_bitmask_order(nr_pgdir_pages);
error = -ENOMEM;
free_page((unsigned long) cur);
pagedir_nosave = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
if(!pagedir_nosave)
goto resume_read_error;
......
......@@ -247,42 +247,26 @@ static struct page * rmqueue(zone_t *zone, unsigned int order)
}
#ifdef CONFIG_SOFTWARE_SUSPEND
int is_head_of_free_region(struct page *p)
int is_head_of_free_region(struct page *page)
{
pg_data_t *pgdat = pgdat_list;
unsigned type;
unsigned long flags;
for (type=0;type < MAX_NR_ZONES; type++) {
zone_t *zone = pgdat->node_zones + type;
int order = MAX_ORDER - 1;
free_area_t *area;
struct list_head *head, *curr;
spin_lock_irqsave(&zone->lock, flags); /* Should not matter as we need quiescent system for suspend anyway, but... */
do {
area = zone->free_area + order;
head = &area->free_list;
curr = head;
zone_t *zone = page_zone(page);
unsigned long flags;
int order;
list_t *curr;
for(;;) {
if(!curr) {
// printk("FIXME: this should not happen but it does!!!");
break;
}
if(p != memlist_entry(curr, struct page, list)) {
curr = memlist_next(curr);
if (curr == head)
break;
continue;
}
/*
* Should not matter as we need quiescent system for
* suspend anyway, but...
*/
spin_lock_irqsave(&zone->lock, flags);
for (order = MAX_ORDER - 1; order >= 0; --order)
list_for_each(curr, &zone->free_area[order].free_list)
if (page == list_entry(curr, struct page, list)) {
spin_unlock_irqrestore(&zone->lock, flags);
return 1 << order;
}
} while(order--);
spin_unlock_irqrestore(&zone->lock, flags);
}
return 0;
spin_unlock_irqrestore(&zone->lock, flags);
return 0;
}
#endif /* CONFIG_SOFTWARE_SUSPEND */
......
......@@ -91,7 +91,7 @@ static int __pdflush(struct pdflush_work *my_work)
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
current->flags |= PF_FLUSHER | PF_KERNTHREAD;
current->flags |= PF_FLUSHER;
my_work->fn = NULL;
my_work->who = current;
......@@ -106,11 +106,8 @@ static int __pdflush(struct pdflush_work *my_work)
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irq(&pdflush_lock);
#ifdef CONFIG_SOFTWARE_SUSPEND
run_task_queue(&tq_bdflush);
if (current->flags & PF_FREEZE)
refrigerator(PF_IOTHREAD);
#endif
schedule();
if (my_work->fn)
......
......@@ -791,7 +791,7 @@ int kswapd(void *unused)
* us from recursively trying to free more memory as we're
* trying to free the first piece of memory in the first place).
*/
tsk->flags |= PF_MEMALLOC | PF_KERNTHREAD;
tsk->flags |= PF_MEMALLOC;
/*
* Kswapd main loop.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment