From 374fa3cf07fa196040063166a55166b1a279f6bd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:26:08 -0500 Subject: [PATCH] Import 2.3.11pre1 --- Makefile | 2 +- arch/i386/kernel/irq.c | 4 +- arch/i386/kernel/mca.c | 21 ++- arch/i386/kernel/setup.c | 26 +++- drivers/char/pc_keyb.c | 3 - drivers/char/vt.c | 2 +- fs/buffer.c | 1 + include/linux/ioport.h | 72 ++++----- kernel/ksyms.c | 6 +- kernel/resource.c | 308 +++++++++++++++++---------------------- mm/swapfile.c | 4 +- 11 files changed, 205 insertions(+), 244 deletions(-) diff --git a/Makefile b/Makefile index 5a6f7620471b..d5cddb14f0c8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 3 -SUBLEVEL = 10 +SUBLEVEL = 11 EXTRAVERSION = ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index ea218fe45214..9dc24667bc70 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -1099,9 +1099,7 @@ __initfunc(void init_IRQ(void)) /* IPI vector for APIC spurious interrupts */ set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); -#endif - request_region(0x20,0x20,"pic1"); - request_region(0xa0,0x20,"pic2"); +#endif /* * Set the clock to 100 Hz, we already have a valid diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index 8bfd7fa4543c..a47a0c2092b6 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -210,6 +210,18 @@ static void mca_configure_adapter_status(int slot) { /*--------------------------------------------------------------------*/ +struct resource mca_standard_resources[] = { + { "system control port B (MCA)", 0x60, 0x60 }, + { "arbitration (MCA)", 0x90, 0x90 }, + { "card Select Feedback (MCA)", 0x91, 0x91 }, + { "system Control port A (MCA)", 0x92, 0x92 }, + { "system board setup (MCA)", 0x94, 0x94 }, + { "POS (MCA)", 0x96, 0x97 }, + { "POS (MCA)", 0x100, 0x107 } +}; + +#define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource)) + __initfunc(void mca_init(void)) { unsigned int i, j; @@ -319,13 +331,8 @@ __initfunc(void mca_init(void)) restore_flags(flags); - request_region(0x60,0x01,"system control port B (MCA)"); - request_region(0x90,0x01,"arbitration (MCA)"); - request_region(0x91,0x01,"card Select Feedback (MCA)"); - request_region(0x92,0x01,"system Control port A (MCA)"); - request_region(0x94,0x01,"system board setup (MCA)"); - request_region(0x96,0x02,"POS (MCA)"); - request_region(0x100,0x08,"POS (MCA)"); + for (i = 0; i < MCA_STANDARD_RESOURCES; i++) + request_resource(&pci_io_resource, mca_standard_resources + i); #ifdef CONFIG_PROC_FS mca_do_proc_init(); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index c0721b4825ab..20160e173ba9 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -249,12 +249,30 @@ visws_get_board_type_and_rev(void) static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; +struct resource standard_resources[] = { + { "dma1", 0x00, 0x1f }, + { "pic1", 0x20, 0x3f }, + { "timer", 0x40, 0x5f }, + { "keyboard", 0x60, 0x6f }, + { "dma page reg", 0x80, 0x8f }, + { "pic2", 0xa0, 0xbf }, + { "dma2", 0xc0, 0xdf }, + { "fpu", 0xf0, 0xff } +}; + +/* For demonstration purposes only.. */ +#define keyboard_resources (standard_resources+3) +struct resource kbd_status_resource = { "status", 0x60, 0x60 }; + +#define STANDARD_RESOURCES (sizeof(standard_resources)/sizeof(struct resource)) + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { unsigned long memory_start, memory_end; char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; + int i; #ifdef CONFIG_VISWS visws_get_board_type_and_rev(); @@ -368,11 +386,9 @@ __initfunc(void setup_arch(char **cmdline_p, #endif /* request I/O space for devices used on all i[345]86 PCs */ - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); - request_region(0xf0,0x10,"fpu"); + for (i = 0; i < STANDARD_RESOURCES; i++) + request_resource(&pci_io_resource, standard_resources+i); + request_resource(keyboard_resources, &kbd_status_resource); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c index fc570b886117..1b83e5f069f4 100644 --- a/drivers/char/pc_keyb.c +++ b/drivers/char/pc_keyb.c @@ -690,9 +690,6 @@ static char * __init initialize_kbd(void) void __init pckbd_init_hw(void) { - /* Get the keyboard controller registers (incomplete decode) */ - request_region(0x60, 16, "keyboard"); - /* Flush any pending input. */ kbd_clear_input(); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index b7f51e2f34de..47b4a1e26aa2 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -670,7 +670,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KDSIGACCEPT: { extern int spawnpid, spawnsig; - if (!perm) + if (!perm || !capable(CAP_KILL)) return -EPERM; if (arg < 1 || arg > _NSIG || arg == SIGKILL) return -EINVAL; diff --git a/fs/buffer.c b/fs/buffer.c index 108b385eaa4e..ba5013c9e1e5 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1270,6 +1270,7 @@ int block_flushpage(struct inode *inode, struct page *page, unsigned long offset mark_buffer_clean(bh); clear_bit(BH_Uptodate, &bh->b_state); clear_bit(BH_Mapped, &bh->b_state); + clear_bit(BH_Req, &bh->b_state); bh->b_blocknr = 0; atomic_dec(&bh->b_count); } diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 2f729f96b256..597b3ebce505 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -2,56 +2,44 @@ * ioport.h Definitions of routines for detecting, reserving and * allocating system resources. * - * Authors: Donald Becker (becker@cesdis.gsfc.nasa.gov) - * David Hinds (dhinds@zen.stanford.edu) + * Authors: Linus Torvalds */ #ifndef _LINUX_IOPORT_H #define _LINUX_IOPORT_H -#define RES_IO 0 -#define RES_MEM 1 +/* + * Resources are tree-like, allowing + * nesting etc.. + */ +struct resource { + const char *name; + unsigned long start, end; + unsigned long flags; + struct resource *parent, *sibling, *child; +}; + +extern struct resource pci_io_resource; +extern struct resource pci_mem_resource; extern void reserve_setup(char *str, int *ints); +extern int get_resource_list(struct resource *, char *buf, int size); -extern struct resource_entry *iolist, *memlist; - -extern int get_resource_list(int class, char *buf); -extern int check_resource(int class, - unsigned long from, unsigned long extent); -extern void request_resource(int class, - unsigned long from, unsigned long extent, - const char *name); -extern void release_resource(int class, - unsigned long from, unsigned long extent); -extern unsigned long occupy_resource(int class, - unsigned long base, unsigned long end, - unsigned long num, unsigned long align, - const char *name); -extern void vacate_resource(int class, - unsigned long from, unsigned long extent); - -#define get_ioport_list(buf) get_resource_list(RES_IO, buf) -#define get_mem_list(buf) get_resource_list(RES_MEM, buf) - -#define HAVE_PORTRESERVE -/* - * Call check_region() before probing for your hardware. - * Once you have found you hardware, register it with request_region(). - * If you unload the driver, use release_region to free ports. - */ -#define check_region(f,e) check_resource(RES_IO,f,e) -#define request_region(f,e,n) request_resource(RES_IO,f,e,n) -#define release_region(f,e) release_resource(RES_IO,f,e) -#define occupy_region(b,e,n,a,s) occupy_resource(RES_IO,b,e,n,a,s) -#define vacate_region(f,e) vacate_resource(RES_IO,f,e) - -#define HAVE_MEMRESERVE -#define check_mem_region(f,e) check_resource(RES_MEM,f,e) -#define request_mem_region(f,e,n) request_resource(RES_MEM,f,e,n) -#define release_mem_region(f,e) release_resource(RES_MEM,f,e) -#define occupy_mem_region(b,e,n,a,s) occupy_resource(RES_MEM,b,e,n,a,s) -#define vacate_mem_region(f,e) vacate_resource(RES_MEM,f,e) +extern int request_resource(struct resource *root, struct resource *new); +extern int release_resource(struct resource *new); + +/* Convenience shorthand with allocation */ +#define request_region(start,n,name) __request_region(&pci_io_resource, (start), (n), (name)) +extern struct resource * __request_region(struct resource *, unsigned long start, unsigned long n, const char *name); + +/* Compatibility cruft */ +#define check_region(start,n) __check_region(&pci_io_resource, (start), (n)) +#define release_region(start,n) __release_region(&pci_io_resource, (start), (n)) +extern int __check_region(struct resource *, unsigned long, unsigned long); +extern void __release_region(struct resource *, unsigned long, unsigned long); + +#define get_ioport_list(buf) get_resource_list(&pci_io_resource, buf, PAGE_SIZE) +#define get_mem_list(buf) get_resource_list(&pci_mem_resource, buf, PAGE_SIZE) #define HAVE_AUTOIRQ extern void autoirq_setup(int waittime); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 798015eaaf23..4b4155e47fc0 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -308,11 +308,11 @@ EXPORT_SYMBOL(enable_hlt); #endif /* resource handling */ -EXPORT_SYMBOL(check_resource); EXPORT_SYMBOL(request_resource); EXPORT_SYMBOL(release_resource); -EXPORT_SYMBOL(occupy_resource); -EXPORT_SYMBOL(vacate_resource); +EXPORT_SYMBOL(__request_region); +EXPORT_SYMBOL(__check_region); +EXPORT_SYMBOL(__release_region); /* process management */ EXPORT_SYMBOL(__wake_up); diff --git a/kernel/resource.c b/kernel/resource.c index 4c672c6b0113..b0e5327898b7 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1,232 +1,184 @@ /* * linux/kernel/resource.c * - * Copyright (C) 1995, 1999 Linus Torvalds - * David Hinds + * Copyright (C) 1999 Linus Torvalds * - * Kernel resource management - * - * We now distinguish between claiming space for devices (using the - * 'occupy' and 'vacate' calls), and associating a resource with a - * device driver (with the 'request', 'release', and 'check' calls). - * A resource can be claimed even if there is no associated driver - * (by occupying with name=NULL). Vacating a resource makes it - * available for other dynamically configured devices. + * Arbitrary resource management. */ #include #include #include #include +#include -#define RSRC_TABLE_SIZE 128 - -struct resource_entry { - u_long from, num; - const char *name; - struct resource_entry *next; -}; - -struct resource_entry res_list[] = { - { 0, 0, NULL, NULL }, /* IO */ - { 0, 0, NULL, NULL } /* mem */ -}; - -static struct resource_entry rsrc_table[RSRC_TABLE_SIZE]; +struct resource pci_io_resource = { "PCI IO", 0x0000, 0xFFFF }; +struct resource pci_mem_resource = { "PCI mem", 0x00000000, 0xFFFFFFFF }; /* * This generates reports for /proc/ioports and /proc/memory */ -int get_resource_list(int class, char *buf) +static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - int len = 0; - char *fmt = (class == RES_IO) ? - "%04lx-%04lx : %s\n" : "%08lx-%08lx : %s\n"; - - for (p = root->next; (p) && (len < 4000); p = p->next) - len += sprintf(buf+len, fmt, p->from, p->from+p->num-1, - (p->name ? p->name : "occupied")); - if (p) - len += sprintf(buf+len, "4K limit reached!\n"); - return len; + if (offset < 0) + offset = 0; + + while (entry) { + const char *name = entry->name; + unsigned long from, to; + + if ((int) (end-buf) < 80) + return buf; + + from = entry->start; + to = entry->end; + if (!name) + name = ""; + + buf += sprintf(buf, fmt + offset, from, to, name); + if (entry->child) + buf = do_resource_list(entry->child, fmt, offset-2, buf, end); + entry = entry->sibling; + } + + return buf; } -/* - * Basics: find a matching resource entry, or find an insertion point - */ -static struct resource_entry * -find_match(struct resource_entry *root, u_long from, u_long num) +int get_resource_list(struct resource *root, char *buf, int size) { - struct resource_entry *p; - for (p = root; p; p = p->next) - if ((p->from == from) && (p->num == num)) - return p; - return NULL; -} + char *fmt; + + fmt = " %08lx-%08lx : %s\n"; + if (root == &pci_io_resource) + fmt = " %04lx-%04lx : %s\n"; + return do_resource_list(root->child, fmt, 8, buf, buf + size) - buf; +} -static struct resource_entry * -find_gap(struct resource_entry *root, u_long from, u_long num) +int request_resource(struct resource *root, struct resource *new) { - struct resource_entry *p; - if (from > from+num-1) - return NULL; - for (p = root; ; p = p->next) { - if ((p != root) && (p->from+p->num-1 >= from)) { - p = NULL; - break; + unsigned long start = new->start; + unsigned long end = new->end; + struct resource *tmp, **p; + + if (end < start) + return -EINVAL; + if (start < root->start) + return -EINVAL; + if (end > root->end) + return -EINVAL; + p = &root->child; + for (;;) { + tmp = *p; + if (!tmp || tmp->start > end) { + new->sibling = tmp; + *p = new; + new->parent = root; + return 0; } - if ((p->next == NULL) || (p->next->from > from+num-1)) - break; + p = &tmp->sibling; + if (tmp->end < start) + continue; + return -EBUSY; } - return p; } -/* - * Call this from a driver to assert ownership of a resource - */ -void request_resource(int class, unsigned long from, - unsigned long num, const char *name) +int release_resource(struct resource *old) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - long flags; - int i; + struct resource *tmp, **p; - p = find_match(root, from, num); - if (p) { - p->name = name; - return; - } - - save_flags(flags); - cli(); - for (i = 0; i < RSRC_TABLE_SIZE; i++) - if (rsrc_table[i].num == 0) + p = &old->parent->child; + for (;;) { + tmp = *p; + if (!tmp) break; - if (i == RSRC_TABLE_SIZE) - printk("warning: resource table is full\n"); - else { - p = find_gap(root, from, num); - if (p == NULL) { - restore_flags(flags); - return; + if (tmp == old) { + *p = tmp->sibling; + old->parent = NULL; + return 0; } - rsrc_table[i].name = name; - rsrc_table[i].from = from; - rsrc_table[i].num = num; - rsrc_table[i].next = p->next; - p->next = &rsrc_table[i]; + p = &tmp->sibling; } - restore_flags(flags); + return -EINVAL; } -/* - * Call these when a driver is unloaded but the device remains - */ -void release_resource(int class, unsigned long from, unsigned long num) +struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - p = find_match(root, from, num); - if (p) p->name = NULL; + struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL); + + if (res) { + memset(res, 0, sizeof(*res)); + res->name = name; + res->start = start; + res->end = start + n - 1; + if (request_resource(parent, res) != 0) { + kfree(res); + res = NULL; + } + } + return res; } /* - * Call these to check a region for conflicts before probing + * Compatibility cruft. + * + * Check-region returns non-zero if something already exists. + * + * Release-region releases an anonymous region that matches + * the IO port range. */ -int check_resource(int class, unsigned long from, unsigned long num) +int __check_region(struct resource *parent, unsigned long start, unsigned long n) { - struct resource_entry *root = &res_list[class]; - struct resource_entry *p; - p = find_match(root, from, num); - if (p != NULL) - return (p->name != NULL) ? -EBUSY : 0; - return (find_gap(root, from, num) == NULL) ? -EBUSY : 0; + struct resource * res; + + res = __request_region(parent, start, n, "check-region"); + if (!res) + return -EBUSY; + + release_resource(res); + return 0; } -/* - * Call this to claim a resource for a piece of hardware - */ -unsigned long occupy_resource(int class, unsigned long base, - unsigned long end, unsigned long num, - unsigned long align, const char *name) +void __release_region(struct resource *parent, unsigned long start, unsigned long n) { - struct resource_entry *root = &res_list[class]; - unsigned long from = 0, till; - unsigned long flags; - int i; - struct resource_entry *p, *q; + struct resource **p; + unsigned long end; - if ((base > end-1) || (num > end - base)) - return 0; + p = &parent->child; + end = start + n - 1; - for (i = 0; i < RSRC_TABLE_SIZE; i++) - if (rsrc_table[i].num == 0) - break; - if (i == RSRC_TABLE_SIZE) - return 0; - - save_flags(flags); - cli(); - /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */ - for (p = root; p != NULL; p = q) { - q = p->next; - /* Find window in list */ - from = (p->from+p->num + align-1) & ~(align-1); - till = (q == NULL) ? (0 - align) : q->from; - /* printk(" %08lx:%08lx", from, till); */ - /* Clip window with base and end */ - if (from < base) from = base; - if (till > end) till = end; - /* See if result is large enougth */ - if ((from < till) && (from + num < till)) - break; - } - /* printk("\r\n"); */ - restore_flags(flags); - - if (p == NULL) - return 0; - - rsrc_table[i].name = name; - rsrc_table[i].from = from; - rsrc_table[i].num = num; - rsrc_table[i].next = p->next; - p->next = &rsrc_table[i]; - return from; -} + for (;;) { + struct resource *tmp = *p; -/* - * Call this when a resource becomes available for other hardware - */ -void vacate_resource(int class, unsigned long from, unsigned long num) -{ - struct resource_entry *root = &res_list[class]; - struct resource_entry *p, *q; - long flags; - - save_flags(flags); - cli(); - for (p = root; ; p = q) { - q = p->next; - if (q == NULL) + if (!tmp) break; - if ((q->from == from) && (q->num == num)) { - q->num = 0; - p->next = q->next; + if (tmp->start == start && tmp->end == end) { + *p = tmp->sibling; break; } + p = &tmp->sibling; } - restore_flags(flags); } -/* Called from init/main.c to reserve IO ports. */ +/* + * Called from init/main.c to reserve IO ports. + */ +#define MAXRESERVE 4 void __init reserve_setup(char *str, int *ints) { int i; - - for (i = 1; i < ints[0]; i += 2) - request_region(ints[i], ints[i+1], "reserved"); + static int reserved = 0; + static struct resource reserve[MAXRESERVE]; + + for (i = 1; i < ints[0]; i += 2) { + int x = reserved; + if (x < MAXRESERVE) { + struct resource *res = reserve + x; + res->name = "reserved"; + res->start = ints[i]; + res->end = res->start + ints[i] - 1; + res->child = NULL; + if (request_resource(&pci_io_resource, res) == 0) + reserved = x+1; + } + } } diff --git a/mm/swapfile.c b/mm/swapfile.c index ce18f34f5d4e..f43a2ed4a210 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -661,7 +661,9 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags) else p->swap_map[page] = SWAP_MAP_BAD; } - nr_good_pages = swap_header->info.last_page - i; + nr_good_pages = swap_header->info.last_page - + swap_header->info.nr_badpages - + 1 /* header page */; lock_map_size = (p->max + 7) / 8; if (error) goto bad_swap; -- 2.39.5