Commit 17d2d71c authored by Linus Torvalds's avatar Linus Torvalds

pl15a fixes the buffer cache growing problem, adds emulation for a

few unimportant floating point instructions (i287 instructions that
are No-Ops on the i387, so "emulating" them is easy :^) and fixes a
silly bug when mmap'ing stuff write-only.  It also fixes a buggy lock
in the networking.
parent a4c5b0f7
VERSION = 0.99
PATCHLEVEL = 15
ALPHA =
ALPHA = a
all: Version zImage
......
......@@ -17,6 +17,9 @@
#include "control_w.h"
static void fnop(void)
{
}
void fclex(void)
{
......@@ -47,9 +50,16 @@ void finit()
FPU_entry_eip = ip_offset = 0;
}
/*
* These are nops on the i387..
*/
#define feni fnop
#define fdisi fnop
#define fsetpm fnop
static FUNC const finit_table[] = {
Un_impl, Un_impl, fclex, finit,
Un_impl, FPU_illegal, FPU_illegal, FPU_illegal
feni, fdisi, fclex, finit,
fsetpm, FPU_illegal, FPU_illegal, FPU_illegal
};
void finit_()
......@@ -75,11 +85,6 @@ void fstsw_()
}
static void fnop(void)
{
}
static FUNC const fp_nop_table[] = {
fnop, FPU_illegal, FPU_illegal, FPU_illegal,
FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
......
......@@ -1800,12 +1800,11 @@ int paste_selection(struct tty_struct *tty)
if (! *bp)
return 0;
unblank_screen();
while (*bp)
{
while (*bp) {
put_tty_queue(*bp, &tty->read_q);
bp++;
TTY_READ_FLUSH(tty);
}
TTY_READ_FLUSH(tty);
return 0;
}
......
......@@ -550,6 +550,9 @@ int tty_ioctl(struct inode * inode, struct file * file,
return set_selection(arg);
case 3:
return paste_selection(tty);
case 4:
unblank_screen();
return 0;
#endif /* CONFIG_SELECTION */
default:
return -EINVAL;
......
......@@ -136,6 +136,8 @@ static struct blist blacklist[] =
{"SEAGATE", "ST296","921"}, /* Responds to all lun */
{"SONY","CD-ROM CDU-541","4.3d"},
{"TANDBERG","TDC 3600","U07"}, /* Locks up if polled for lun != 0 */
{"TEAC","CD-ROM","1.06"}, /* causes failed REQUEST SENSE on lun 1 for seagate
* controller, which causes SCSI code to reset bus.*/
{"TEXEL","CD-ROM","1.06"}, /* causes failed REQUEST SENSE on lun 1 for seagate
* controller, which causes SCSI code to reset bus.*/
{NULL, NULL, NULL}};
......
......@@ -956,7 +956,11 @@ int shrink_buffers(unsigned int priority)
bh = free_list;
i = nr_buffers >> priority;
for ( ; i-- > 0 ; bh = bh->b_next_free) {
if (bh->b_count || !bh->b_this_page)
if (bh->b_count) {
put_last_free(bh);
continue;
}
if (!bh->b_this_page)
continue;
if (bh->b_lock)
if (priority)
......@@ -975,6 +979,29 @@ int shrink_buffers(unsigned int priority)
return 0;
}
void show_buffers(void)
{
struct buffer_head * bh;
int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0;
printk("Buffer memory: %6dkB\n",buffermem>>10);
printk("Buffer heads: %6d\n",nr_buffer_heads);
printk("Buffer blocks: %6d\n",nr_buffers);
bh = free_list;
do {
found++;
if (bh->b_lock)
locked++;
if (bh->b_dirt)
dirty++;
if (bh->b_count)
used++, lastused = found;
bh = bh->b_next_free;
} while (bh != free_list);
printk("Buffer mem: %d buffers, %d used (last=%d), %d locked, %d dirty\n",
found, used, lastused, locked, dirty);
}
/*
* This initializes the initial buffer free list. nr_buffers is set
* to one less the actual number of buffers, as a sop to backwards
......
......@@ -69,10 +69,11 @@ void ext2_discard_prealloc (struct inode * inode)
{
#ifdef EXT2_PREALLOCATE
if (inode->u.ext2_i.i_prealloc_count) {
int i = inode->u.ext2_i.i_prealloc_count;
inode->u.ext2_i.i_prealloc_count = 0;
ext2_free_blocks (inode->i_sb,
inode->u.ext2_i.i_prealloc_block,
inode->u.ext2_i.i_prealloc_count);
inode->u.ext2_i.i_prealloc_count = 0;
i);
}
#endif
}
......
#ifndef _ASM_IO_H
#define _ASM_IO_H
/*
* This file contains the definitions for the x86 IO instructions
* inb/inw/inl/outb/outw/outl and the "string versions" of the same
* (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
* versions of the single-IO instructions (inb_p/inw_p/..).
*
* This file is not meant to be obfuscating: it's just complicated
* to (a) handle it all in a way that makes gcc able to optimize it
* as well as possible and (b) trying to avoid writing the same thing
* over and over again with slight variations and possibly making a
* mistake somewhere.
*/
/*
* Thanks to James van Artsdalen for a better timing-fix than
* the two short jumps: using outb's to a nonexistent port seems
......
......@@ -326,6 +326,17 @@ static void parse_options(char *line)
envp_init[envs+1] = NULL;
}
static void copy_options(char * to, char * from)
{
char c = ' ';
do {
if (c == ' ' && !memcmp("mem=", from, 4))
memory_end = simple_strtoul(from+4, &from, 0);
c = *(to++) = *(from++);
} while (c);
}
static void copro_timeout(void)
{
fpu_error = 1;
......@@ -351,7 +362,7 @@ asmlinkage void start_kernel(void)
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= PAGE_MASK;
ramdisk_size = RAMDISK_SIZE;
strcpy(command_line,COMMAND_LINE);
copy_options(command_line,COMMAND_LINE);
#ifdef CONFIG_MAX_16M
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
......
......@@ -981,9 +981,6 @@ void show_mem(void)
printk("Free pages: %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10));
printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10));
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
printk("Buffer memory: %6dkB\n",buffermem>>10);
printk("Buffer heads: %6d\n",nr_buffer_heads);
printk("Buffer blocks: %6d\n",nr_buffers);
i = high_memory >> PAGE_SHIFT;
while (i-- > 0) {
total++;
......@@ -998,6 +995,7 @@ void show_mem(void)
printk("%d free pages\n",free);
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
show_buffers();
}
/*
......
......@@ -113,9 +113,9 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
mask |= PAGE_READONLY;
if (prot & PROT_WRITE)
if ((flags & MAP_TYPE) == MAP_PRIVATE)
mask |= PAGE_COW;
mask |= PAGE_COPY;
else
mask |= PAGE_RW;
mask |= PAGE_SHARED;
if (!mask)
return -EINVAL;
......
......@@ -193,81 +193,49 @@ ip_addr_match(unsigned long me, unsigned long him)
/* Check the address for our address, broadcasts, etc. */
int
chk_addr(unsigned long addr)
int chk_addr(unsigned long addr)
{
struct device *dev;
unsigned long dst;
DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
dst = ntohl(addr);
/* Accept both `all ones' and `all zeros' as BROADCAST. */
if (dst == INADDR_ANY || dst == INADDR_BROADCAST) {
DPRINTF((DBG_DEV, "BROADCAST\n"));
return(IS_BROADCAST);
}
struct device *dev;
unsigned long mask;
/* Accept all of the `loopback' class A net. */
if ((dst & IN_CLASSA_NET) == 0x7F000000L) {
DPRINTF((DBG_DEV, "LOOPBACK\n"));
/* Accept both `all ones' and `all zeros' as BROADCAST. */
if (addr == INADDR_ANY || addr == INADDR_BROADCAST)
return IS_BROADCAST;
/*
* We force `loopback' to be equal to MY_ADDR.
*/
return(IS_MYADDR);
/* return(IS_LOOPBACK); */
}
mask = get_mask(addr);
/* OK, now check the interface addresses. */
for (dev = dev_base; dev != NULL; dev = dev->next) {
if (!(dev->flags&IFF_UP))
continue;
if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
return(IS_MYADDR);
/* Is it the exact IP address? */
if (addr == dev->pa_addr) {
DPRINTF((DBG_DEV, "MYADDR\n"));
return(IS_MYADDR);
}
/* Accept all of the `loopback' class A net. */
if ((addr & mask) == htonl(0x7F000000L))
return IS_MYADDR;
/* Nope. Check for a subnetwork broadcast. */
if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask)) {
if ((addr & ~dev->pa_mask) == 0) {
DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
return(IS_BROADCAST);
/* OK, now check the interface addresses. */
for (dev = dev_base; dev != NULL; dev = dev->next) {
if (!(dev->flags & IFF_UP))
continue;
if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
return IS_MYADDR;
/* Is it the exact IP address? */
if (addr == dev->pa_addr)
return IS_MYADDR;
/* Is it our broadcast address? */
if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
return IS_BROADCAST;
/* Nope. Check for a subnetwork broadcast. */
if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0) {
if ((addr & ~dev->pa_mask) == 0)
return IS_BROADCAST;
if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
return IS_BROADCAST;
}
if (((addr & ~dev->pa_mask) | dev->pa_mask)
== INADDR_BROADCAST) {
DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
return(IS_BROADCAST);
/* Nope. Check for Network broadcast. */
if (((addr ^ dev->pa_addr) & mask) == 0) {
if ((addr & ~mask) == 0)
return IS_BROADCAST;
if ((addr & ~mask) == ~mask)
return IS_BROADCAST;
}
}
/* Nope. Check for Network broadcast. */
if(IN_CLASSA(dst)) {
if( addr == (dev->pa_addr | 0xffffff00)) {
DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
else if(IN_CLASSB(dst)) {
if( addr == (dev->pa_addr | 0xffff0000)) {
DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
else { /* IN_CLASSC */
if( addr == (dev->pa_addr | 0xff000000)) {
DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
return(IS_BROADCAST);
}
}
}
DPRINTF((DBG_DEV, "NONE\n"));
return(0); /* no match at all */
return 0; /* no match at all */
}
......
......@@ -764,7 +764,6 @@ static struct sk_buff *ip_glue(struct ipq *qp)
skb->len = (len - qp->maclen);
skb->h.raw = skb->data;
skb->free = 1;
skb->lock = 1;
/* Copy the original MAC and IP headers into the new buffer. */
ptr = (unsigned char *) skb->h.raw;
......
......@@ -78,6 +78,7 @@ extern void ip_queue_xmit(struct sock *sk,
struct device *dev, struct sk_buff *skb,
int free);
extern void ip_retransmit(struct sock *sk, int all);
extern void ip_do_retransmit(struct sock *sk, int all);
extern int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen);
extern int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
......
......@@ -115,7 +115,7 @@ raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
/* Now we need to copy this into memory. */
skb->sk = sk;
skb->len = len + skb->ip_hdr->ihl*sizeof(long);
skb->h.raw = skb->ip_hdr;
skb->h.raw = (unsigned char *) skb->ip_hdr;
skb->dev = dev;
skb->saddr = daddr;
skb->daddr = saddr;
......
......@@ -124,6 +124,7 @@ extern int tcp_rcv(struct sk_buff *skb, struct device *dev,
extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern void tcp_send_probe0(struct sock *sk);
extern void tcp_enqueue_partial(struct sk_buff *, struct sock *);
extern struct sk_buff * tcp_dequeue_partial(struct sock *);
......
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