Commit ee5028bb authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.7pre9

parent 44d548e4
......@@ -17,6 +17,9 @@
* Removed unnecessary code duplication for little endian machines
* and excessive __inline__s.
* Andi Kleen, 1997
*
* Major simplications and cleanup - we only need to do the metadata, because
* we can depend on generic_block_fdatasync() to sync the data blocks.
*/
#include <asm/uaccess.h>
......@@ -32,8 +35,8 @@
#include <linux/locks.h>
#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
#define blocksize (EXT2_BLOCK_SIZE(inode->i_sb))
#define addr_per_block (EXT2_ADDR_PER_BLOCK(inode->i_sb))
static int sync_indirect(struct inode * inode, u32 * block, int wait)
{
......@@ -41,23 +44,23 @@ static int sync_indirect(struct inode * inode, u32 * block, int wait)
if (!*block)
return 0;
bh = get_hash_table (inode->i_dev, le32_to_cpu(*block), blocksize);
bh = get_hash_table(inode->i_dev, le32_to_cpu(*block), blocksize);
if (!bh)
return 0;
if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
brelse (bh);
brelse(bh);
return -1;
}
if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
brelse (bh);
brelse(bh);
return 0;
}
ll_rw_block (WRITE, 1, &bh);
ll_rw_block(WRITE, 1, &bh);
bh->b_count--;
return 0;
}
static int sync_iblock (struct inode * inode, u32 * iblock,
static int sync_iblock(struct inode * inode, u32 * iblock,
struct buffer_head ** bh, int wait)
{
int rc, tmp;
......@@ -69,51 +72,47 @@ static int sync_iblock (struct inode * inode, u32 * iblock,
rc = sync_indirect(inode, iblock, wait);
if (rc)
return rc;
*bh = bread (inode->i_dev, tmp, blocksize);
*bh = bread(inode->i_dev, tmp, blocksize);
if (!*bh)
return -1;
return 0;
}
static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
static int sync_dindirect(struct inode * inode, u32 * diblock, int wait)
{
int i;
struct buffer_head * dind_bh;
int rc, err = 0;
rc = sync_iblock (inode, diblock, &dind_bh, wait);
rc = sync_iblock(inode, diblock, &dind_bh, wait);
if (rc || !dind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_indirect(inode,
((u32 *) dind_bh->b_data) + i,
wait);
rc = sync_indirect(inode, ((u32 *) dind_bh->b_data) + i, wait);
if (rc)
err = rc;
}
brelse (dind_bh);
brelse(dind_bh);
return err;
}
static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
static int sync_tindirect(struct inode * inode, u32 * tiblock, int wait)
{
int i;
struct buffer_head * tind_bh;
int rc, err = 0;
rc = sync_iblock (inode, tiblock, &tind_bh, wait);
rc = sync_iblock(inode, tiblock, &tind_bh, wait);
if (rc || !tind_bh)
return rc;
for (i = 0; i < addr_per_block; i++) {
rc = sync_dindirect(inode,
((u32 *) tind_bh->b_data) + i,
wait);
rc = sync_dindirect(inode, ((u32 *) tind_bh->b_data) + i, wait);
if (rc)
err = rc;
}
brelse (tind_bh);
brelse(tind_bh);
return err;
}
......@@ -137,15 +136,15 @@ int ext2_sync_file(struct file * file, struct dentry *dentry)
for (wait=0; wait<=1; wait++)
{
err |= sync_indirect (inode,
inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
err |= sync_indirect(inode,
inode->u.ext2_i.i_data+EXT2_IND_BLOCK,
wait);
err |= sync_dindirect(inode,
inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
wait);
err |= sync_tindirect(inode,
inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
wait);
err |= sync_dindirect (inode,
inode->u.ext2_i.i_data+EXT2_DIND_BLOCK,
wait);
err |= sync_tindirect (inode,
inode->u.ext2_i.i_data+EXT2_TIND_BLOCK,
wait);
}
skip:
err |= ext2_sync_inode (inode);
......
......@@ -1326,6 +1326,9 @@ static long get_root_array(char * page, int type, char **start,
case PROC_IOPORTS:
return get_ioport_list(page);
case PROC_MEMORY:
return get_mem_list(page);
#ifdef CONFIG_BLK_DEV_MD
case PROC_MD:
return get_md_status(page);
......
......@@ -621,6 +621,11 @@ static struct proc_dir_entry proc_root_ioports = {
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
static struct proc_dir_entry proc_root_memory = {
PROC_MEMORY, 6, "memory",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
static struct proc_dir_entry proc_root_cmdline = {
PROC_CMDLINE, 7, "cmdline",
S_IFREG | S_IRUGO, 1, 0, 0,
......@@ -709,6 +714,7 @@ __initfunc(void proc_root_init(void))
proc_register(&proc_root, &proc_root_fs);
proc_register(&proc_root, &proc_root_dma);
proc_register(&proc_root, &proc_root_ioports);
proc_register(&proc_root, &proc_root_memory);
proc_register(&proc_root, &proc_root_cmdline);
#ifdef CONFIG_RTC
proc_register(&proc_root, &proc_root_rtc);
......
......@@ -234,30 +234,13 @@ struct buffer_head {
typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *);
static inline int buffer_uptodate(struct buffer_head * bh)
{
return test_bit(BH_Uptodate, &bh->b_state);
}
static inline int buffer_dirty(struct buffer_head * bh)
{
return test_bit(BH_Dirty, &bh->b_state);
}
static inline int buffer_locked(struct buffer_head * bh)
{
return test_bit(BH_Lock, &bh->b_state);
}
static inline int buffer_req(struct buffer_head * bh)
{
return test_bit(BH_Req, &bh->b_state);
}
#define __buffer_state(bh, state) (((bh)->b_state & (1UL << BH_##state)) != 0)
static inline int buffer_protected(struct buffer_head * bh)
{
return test_bit(BH_Protected, &bh->b_state);
}
#define buffer_uptodate(bh) __buffer_state(bh,Uptodate)
#define buffer_dirty(bh) __buffer_state(bh,Dirty)
#define buffer_locked(bh) __buffer_state(bh,Lock)
#define buffer_req(bh) __buffer_state(bh,Req)
#define buffer_protected(bh) __buffer_state(bh,Protected)
#define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data))
#define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags)
......
/*
* portio.h Definitions of routines for detecting, reserving and
* ioport.h Definitions of routines for detecting, reserving and
* allocating system resources.
*
* Version: 0.01 8/30/93
*
* Author: Donald Becker (becker@super.org)
* Authors: Donald Becker (becker@cesdis.gsfc.nasa.gov)
* David Hinds (dhinds@zen.stanford.edu)
*/
#ifndef _LINUX_PORTIO_H
#define _LINUX_PORTIO_H
#ifndef _LINUX_IOPORT_H
#define _LINUX_IOPORT_H
#define RES_IO 0
#define RES_MEM 1
extern void reserve_setup(char *str, int *ints);
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
/*
......@@ -16,20 +40,21 @@
* Once you have found you hardware, register it with request_region().
* If you unload the driver, use release_region to free ports.
*/
extern void reserve_setup(char *str, int *ints);
extern int check_region(unsigned long from, unsigned long extent);
extern void request_region(unsigned long from, unsigned long extent,const char *name);
extern void release_region(unsigned long from, unsigned long extent);
extern int get_ioport_list(char *);
#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)
#ifdef __sparc__
extern unsigned long occupy_region(unsigned long base, unsigned long end,
unsigned long num, unsigned int align,
const char *name);
#endif
#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)
#define HAVE_AUTOIRQ
extern void autoirq_setup(int waittime);
extern int autoirq_report(int waittime);
#endif /* _LINUX_PORTIO_H */
#endif /* _LINUX_IOPORT_H */
......@@ -37,6 +37,7 @@ enum root_directory_inos {
PROC_KSYMS,
PROC_DMA,
PROC_IOPORTS,
PROC_MEMORY,
PROC_PROFILE, /* whether enabled or not */
PROC_CMDLINE,
PROC_SYS,
......
......@@ -300,10 +300,12 @@ EXPORT_SYMBOL(disable_hlt);
EXPORT_SYMBOL(enable_hlt);
#endif
/* IO port handling */
EXPORT_SYMBOL(check_region);
EXPORT_SYMBOL(request_region);
EXPORT_SYMBOL(release_region);
/* resource handling */
EXPORT_SYMBOL(check_resource);
EXPORT_SYMBOL(request_resource);
EXPORT_SYMBOL(release_resource);
EXPORT_SYMBOL(occupy_resource);
EXPORT_SYMBOL(vacate_resource);
/* process management */
EXPORT_SYMBOL(__wake_up);
......
/*
* linux/kernel/resource.c
*
* Copyright (C) 1995 Linus Torvalds
* David Hinds
* Copyright (C) 1995, 1999 Linus Torvalds
* David Hinds
*
* Kernel io-region resource management
* 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.
*/
#include <linux/sched.h>
......@@ -12,47 +19,59 @@
#include <linux/ioport.h>
#include <linux/init.h>
#define IOTABLE_SIZE 128
#define RSRC_TABLE_SIZE 128
typedef struct resource_entry_t {
struct resource_entry {
u_long from, num;
const char *name;
struct resource_entry_t *next;
} resource_entry_t;
struct resource_entry *next;
};
static resource_entry_t iolist = { 0, 0, "", NULL };
struct resource_entry res_list[] = {
{ 0, 0, NULL, NULL }, /* IO */
{ 0, 0, NULL, NULL } /* mem */
};
static resource_entry_t iotable[IOTABLE_SIZE];
static struct resource_entry rsrc_table[RSRC_TABLE_SIZE];
/*
* This generates the report for /proc/ioports
* This generates reports for /proc/ioports and /proc/memory
*/
int get_ioport_list(char *buf)
int get_resource_list(int class, char *buf)
{
resource_entry_t *p;
struct resource_entry *root = &res_list[class];
struct resource_entry *p;
int len = 0;
for (p = iolist.next; (p) && (len < 4000); p = p->next)
len += sprintf(buf+len, "%04lx-%04lx : %s\n",
p->from, p->from+p->num-1, p->name);
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;
}
/*
* The workhorse function: find where to put a new entry
* Basics: find a matching resource entry, or find an insertion point
*/
static resource_entry_t *find_gap(resource_entry_t *root,
u_long from, u_long num)
static struct resource_entry *
find_match(struct resource_entry *root, u_long from, u_long num)
{
unsigned long flags;
resource_entry_t *p;
struct resource_entry *p;
for (p = root; p; p = p->next)
if ((p->from == from) && (p->num == num))
return p;
return NULL;
}
static struct resource_entry *
find_gap(struct resource_entry *root, u_long from, u_long num)
{
struct resource_entry *p;
if (from > from+num-1)
return NULL;
save_flags(flags);
cli();
for (p = root; ; p = p->next) {
if ((p != root) && (p->from+p->num-1 >= from)) {
p = NULL;
......@@ -61,123 +80,147 @@ static resource_entry_t *find_gap(resource_entry_t *root,
if ((p->next == NULL) || (p->next->from > from+num-1))
break;
}
restore_flags(flags);
return p;
}
/*
* Call this from the device driver to register the ioport region.
* Call this from a driver to assert ownership of a resource
*/
void request_region(unsigned long from, unsigned long num, const char *name)
void request_resource(int class, unsigned long from,
unsigned long num, const char *name)
{
resource_entry_t *p;
struct resource_entry *root = &res_list[class];
struct resource_entry *p;
long flags;
int i;
for (i = 0; i < IOTABLE_SIZE; i++)
if (iotable[i].num == 0)
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)
break;
if (i == IOTABLE_SIZE)
printk("warning: ioport table is full\n");
if (i == RSRC_TABLE_SIZE)
printk("warning: resource table is full\n");
else {
p = find_gap(&iolist, from, num);
if (p == NULL)
p = find_gap(root, from, num);
if (p == NULL) {
restore_flags(flags);
return;
iotable[i].name = name;
iotable[i].from = from;
iotable[i].num = num;
iotable[i].next = p->next;
p->next = &iotable[i];
return;
}
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];
}
restore_flags(flags);
}
/*
* Call this when the device driver is unloaded
* Call these when a driver is unloaded but the device remains
*/
void release_region(unsigned long from, unsigned long num)
void release_resource(int class, unsigned long from, unsigned long num)
{
resource_entry_t *p, *q;
for (p = &iolist; ; p = q) {
q = p->next;
if (q == NULL)
break;
if ((q->from == from) && (q->num == num)) {
q->num = 0;
p->next = q->next;
return;
}
}
struct resource_entry *root = &res_list[class];
struct resource_entry *p;
p = find_match(root, from, num);
if (p) p->name = NULL;
}
/*
* Call this to check the ioport region before probing
* Call these to check a region for conflicts before probing
*/
int check_region(unsigned long from, unsigned long num)
int check_resource(int class, unsigned long from, unsigned long num)
{
return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
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;
}
#ifdef __sparc__ /* Why to carry unused code on other architectures? */
/*
* This is for architectures with MMU-managed ports (sparc).
* Call this to claim a resource for a piece of hardware
*/
unsigned long occupy_region(unsigned long base, unsigned long end,
unsigned long num, unsigned int align, const char *name)
unsigned long occupy_resource(int class, unsigned long base,
unsigned long end, unsigned long num,
unsigned long align, const char *name)
{
struct resource_entry *root = &res_list[class];
unsigned long from = 0, till;
unsigned long flags;
int i;
resource_entry_t *p; /* Scanning ptr */
resource_entry_t *p1; /* === p->next */
resource_entry_t *s; /* Found slot */
struct resource_entry *p, *q;
if (base > end-1)
return 0;
if (num > end - base)
if ((base > end-1) || (num > end - base))
return 0;
for (i = 0; i < IOTABLE_SIZE; i++)
if (iotable[i].num == 0)
for (i = 0; i < RSRC_TABLE_SIZE; i++)
if (rsrc_table[i].num == 0)
break;
if (i == IOTABLE_SIZE) {
/* Driver prints a warning typically. */
if (i == RSRC_TABLE_SIZE)
return 0;
}
save_flags(flags);
cli();
/* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
s = NULL;
for (p = &iolist; p != NULL; p = p1) {
p1 = p->next;
for (p = root; p != NULL; p = q) {
q = p->next;
/* Find window in list */
from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
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) {
s = p;
if ((from < till) && (from + num < till))
break;
}
}
/* printk("\r\n"); */
restore_flags(flags);
if (s == NULL)
if (p == NULL)
return 0;
iotable[i].name = name;
iotable[i].from = from;
iotable[i].num = num;
iotable[i].next = s->next;
s->next = &iotable[i];
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;
}
#endif
/*
* 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)
break;
if ((q->from == from) && (q->num == num)) {
q->num = 0;
p->next = q->next;
break;
}
}
restore_flags(flags);
}
/* Called from init/main.c to reserve IO ports. */
void __init reserve_setup(char *str, int *ints)
......
......@@ -359,7 +359,7 @@ static int writeout_one_page(struct page *page)
bh = head;
do {
if (buffer_locked(bh) || !buffer_dirty(bh))
if (buffer_locked(bh) || !buffer_dirty(bh) || !buffer_uptodate(bh))
continue;
bh->b_flushtime = 0;
......@@ -376,7 +376,7 @@ static int waitfor_one_page(struct page *page)
bh = head;
do {
wait_on_buffer(bh);
if (!buffer_uptodate(bh))
if (buffer_req(bh) && !buffer_uptodate(bh))
error = -EIO;
} while ((bh = bh->b_this_page) != head);
return error;
......
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