Commit 374fa3cf authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.11pre1

parent 96278de6
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/)
......
......@@ -1100,8 +1100,6 @@ __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");
/*
* Set the clock to 100 Hz, we already have a valid
......
......@@ -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();
......
......@@ -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)
......
......@@ -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();
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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);
......
/*
* 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 <linux/sched.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/malloc.h>
#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 = "<BAD>";
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);
}
/*
* Call these when a driver is unloaded but the device remains
*/
void release_resource(int class, unsigned long from, unsigned long num)
{
struct resource_entry *root = &res_list[class];
struct resource_entry *p;
p = find_match(root, from, num);
if (p) p->name = NULL;
return -EINVAL;
}
/*
* Call these to check a region for conflicts before probing
*/
int check_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 != NULL)
return (p->name != NULL) ? -EBUSY : 0;
return (find_gap(root, from, num) == NULL) ? -EBUSY : 0;
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 this to claim a resource for a piece of hardware
* Compatibility cruft.
*
* Check-region returns non-zero if something already exists.
*
* Release-region releases an anonymous region that matches
* the IO port range.
*/
unsigned long occupy_resource(int class, unsigned long base,
unsigned long end, unsigned long num,
unsigned long align, const char *name)
int __check_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 * res;
if ((base > end-1) || (num > end - base))
return 0;
res = __request_region(parent, start, n, "check-region");
if (!res)
return -EBUSY;
for (i = 0; i < RSRC_TABLE_SIZE; i++)
if (rsrc_table[i].num == 0)
break;
if (i == RSRC_TABLE_SIZE)
release_resource(res);
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);
void __release_region(struct resource *parent, unsigned long start, unsigned long n)
{
struct resource **p;
unsigned long end;
if (p == NULL)
return 0;
p = &parent->child;
end = start + n - 1;
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;
}
}
}
......@@ -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;
......
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