Commit 9d9ddb4b authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.77

parent 3d2cce92
......@@ -1198,6 +1198,7 @@ N: Greg Wettstein
E: greg@wind.rmcc.com
D: Filesystem valid flag for MINIX filesystem.
D: Minor kernel debugging.
D: Development and maintenance of sysklogd.
D: Monitoring of development kernels for long-term stability.
D: Early implementations of Linux in a commercial environment.
S: Dr. Greg Wettstein, Ph.D.
......
Video Mode Selection Support 2.4
Video Mode Selection Support 2.5
(c) 1995, 1996 Martin Mares, <mj@k332.feld.cvut.cz>
--------------------------------------------------------------------------------
......@@ -222,3 +222,4 @@ this must be done manually -- no autodetection mechanisms are available.
these changes. Unfortunately, screen contents retaining works
only with some loaders now.
Added a Tseng 132x60 mode.
2.5 (19-Mar-96) Fixed a VESA mode scanning bug introduced in 2.4.
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 76
SUBLEVEL = 77
ARCH = i386
......
!
! Display adapter & video mode setup, version 2.4 (18-Mar-96)
! Display adapter & video mode setup, version 2.5 (19-Mar-96)
!
! Copyright (C) 1995, 1996 Martin Mares <mj@k332.feld.cvut.cz>
! Based on the original setup.S code (C) Linus Torvalds
......@@ -753,13 +753,13 @@ vesa_modes:
mov di,bp
cmp ax,#0x004f ! Successful?
jnz ret0
cmp (di+0x400),#0x4556
cmp (di+0x200),#0x4556
jnz ret0
cmp (di+0x402),#0x4153
cmp (di+0x202),#0x4153
jnz ret0
mov [card_name],#vesa_name ! Set name to "VESA VGA"
push gs
lgs si,(di+0x40e) ! GS:SI=mode list
lgs si,(di+0x20e) ! GS:SI=mode list
mov cx,#128 ! Iteration limit
vesa1: seg gs ! Get next mode in the list
lodsw
......
......@@ -232,8 +232,10 @@ static const char * getmodel(int x86, int model)
switch (x86) {
case 4:
p = i486model(model);
break;
case 5:
p = i586model(model);
break;
}
if (p)
return p;
......@@ -255,7 +257,9 @@ int get_cpuinfo(char * buffer)
#ifdef __SMP__
int n;
#define CD(X) (cpu_data[n].(X))
#define CD(X) (cpu_data[n].X)
/* SMP has the wrong name for loops_per_sec */
#define loops_per_sec udelay_val
#define CPUN n
for ( n = 0 ; n < 32 ; n++ ) {
......
......@@ -3168,6 +3168,10 @@ cleanup_module(void)
printk("Can't unregister cdu31a\n");
return;
}
if (cdu31a_irq > 0)
free_irq(cdu31a_irq, NULL);
release_region(cdu31a_port,4);
printk("cdu31a module released.\n");
}
......
......@@ -60,6 +60,7 @@
17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
07 July 1995 Modifications by Andrew J. Kroll
Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
*/
#include <linux/module.h>
......@@ -1181,6 +1182,7 @@ int mcd_init(void)
}
if (check_region(mcd_port, 4)) {
unregister_blkdev(MAJOR_NR, "mcd");
printk("Init failed, I/O port (%X) already in use\n",
mcd_port);
return -EIO;
......@@ -1204,6 +1206,7 @@ int mcd_init(void)
if (count >= 2000000) {
printk("Init failed. No mcd device at 0x%x irq %d\n",
mcd_port, mcd_irq);
unregister_blkdev(MAJOR_NR, "mcd");
return -EIO;
}
count = inb(MCDPORT(0)); /* pick up the status */
......@@ -1211,13 +1214,16 @@ int mcd_init(void)
outb(MCMD_GET_VERSION,MCDPORT(0));
for(count=0;count<3;count++)
if(getValue(result+count)) {
unregister_blkdev(MAJOR_NR, "mcd");
printk("mitsumi get version failed at 0x%d\n",
mcd_port);
return -EIO;
}
if (result[0] == result[1] && result[1] == result[2])
if (result[0] == result[1] && result[1] == result[2]) {
unregister_blkdev(MAJOR_NR, "mcd");
return -EIO;
}
printk("Mitsumi status, type and version : %02X %c %x ",
result[0],result[1],result[2]);
......@@ -1239,6 +1245,7 @@ int mcd_init(void)
if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL))
{
printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
unregister_blkdev(MAJOR_NR, "mcd");
return -EIO;
}
request_region(mcd_port, 4,"mcd");
......
......@@ -1383,8 +1383,10 @@ static int con_write(struct tty_struct * tty, int from_user,
disable_bh(CONSOLE_BH);
while (!tty->stopped && count) {
enable_bh(CONSOLE_BH);
c = from_user ? get_user(buf) : *buf;
buf++; n++; count--;
disable_bh(CONSOLE_BH);
if (utf) {
/* Combine UTF-8 into Unicode */
......
......@@ -30,7 +30,7 @@
# FDC_82078SL - If you have a 82078SL, define this.
FTAPE_OPT = -DVERIFY_HEADERS -DNR_BUFFERS=3 -DCLK_48MHZ=1 \
-DFDC_82078SL -DNO_TRACE
-DNO_TRACE
# If you're using a non-standard floppy disk controller for the
# tape drive, enable one (only!) of the following lines and set
......
......@@ -602,6 +602,7 @@ int lp_init(void)
{
int offset = 0;
int count = 0;
int failed = 0;
if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
printk("lp: unable to get major %d\n", LP_MAJOR);
......@@ -623,13 +624,25 @@ int lp_init(void)
if (specified) {
if (lp_probe(offset) <= 0) {
printk(KERN_INFO "lp%d: Not found\n", offset);
return -EIO;
failed++;
} else
count++;
}
}
/* Successful specified devices increase count
* Unsuccessful specified devices increase failed
*/
if (count)
return 0;
if (failed) {
printk(KERN_INFO "lp: No override devices found.\n");
unregister_chrdev(LP_MAJOR,"lp");
return -EIO;
}
/* Only get here if there were no specified devices. To continue
* would be silly since the above code has scribbled all over the
* probe list.
*/
#endif
/* take on all known port values */
for (offset = 0; offset < LP_NO; offset++) {
......
......@@ -809,6 +809,17 @@ static void NCR5380_init (struct Scsi_Host *instance, int flags) {
hostdata->connected = NULL;
hostdata->issue_queue = NULL;
hostdata->disconnected_queue = NULL;
#ifdef NCR5380_STATS
for (i = 0; i < 8; ++i) {
hostdata->time_read[i] = 0;
hostdata->time_write[i] = 0;
hostdata->bytes_read[i] = 0;
hostdata->bytes_write[i] = 0;
}
hostdata->timebase = 0;
hostdata->pendingw = 0;
hostdata->pendingr = 0;
#endif
/* The CHECK code seems to break the 53C400. Will check it later maybe */
if (flags & FLAG_NCR53C400)
......@@ -916,6 +927,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) {
#if (NDEBUG & NDEBUG_NO_WRITE)
switch (cmd->cmnd[0]) {
case WRITE:
case WRITE_6:
case WRITE_10:
printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n",
instance->host_no);
......@@ -925,6 +937,34 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) {
}
#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
#ifdef NCR5380_STATS
# if 0
if (!hostdata->connected && !hostdata->issue_queue &&
!hostdata->disconnected_queue) {
hostdata->timebase = jiffies;
}
# endif
# ifdef NCR5380_STAT_LIMIT
if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
# endif
switch (cmd->cmnd[0])
{
case WRITE:
case WRITE_6:
case WRITE_10:
hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase);
hostdata->bytes_write[cmd->target] += cmd->request_bufflen;
hostdata->pendingw++;
break;
case READ:
case READ_6:
case READ_10:
hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase);
hostdata->bytes_read[cmd->target] += cmd->request_bufflen;
hostdata->pendingr++;
break;
}
#endif
/*
* We use the host_scribble field as a pointer to the next command
......@@ -1224,6 +1264,32 @@ static void NCR5380_intr (int irq, void *dev_id, struct pt_regs * regs) {
} while (!done);
}
#ifdef NCR5380_STATS
static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd)
{
# ifdef NCR5380_STAT_LIMIT
if (cmd->request_bufflen > NCR5380_STAT_LIMIT)
# endif
switch (cmd->cmnd[0])
{
case WRITE:
case WRITE_6:
case WRITE_10:
hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);
/*hostdata->bytes_write[cmd->target] += cmd->request_bufflen;*/
hostdata->pendingw--;
break;
case READ:
case READ_6:
case READ_10:
hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);
/*hostdata->bytes_read[cmd->target] += cmd->request_bufflen;*/
hostdata->pendingr--;
break;
}
}
#endif
/*
* Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
* int tag);
......@@ -1469,6 +1535,9 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
return -1;
}
cmd->result = DID_BAD_TARGET << 16;
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
#if (NDEBUG & NDEBUG_SELECTION)
......@@ -2321,6 +2390,9 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) {
#if (NDEBUG & NDEBUG_LINKED)
printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n",
instance->host_no, cmd->target, cmd->lun);
#endif
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd);
cmd = hostdata->connected;
......@@ -2387,9 +2459,13 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) {
#if (NDEBUG & NDEBUG_QUEUES)
printk("scsi%d : REQUEST SENSE added to head of issue queue\n",instance->host_no);
#endif
} else
} else {
#endif /* def AUTOSENSE */
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd);
}
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
/*
......@@ -2557,6 +2633,9 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) {
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
hostdata->connected = NULL;
cmd->result = DID_ERROR << 16;
#ifdef NCR5380_STATS
collect_stats(hostdata, cmd);
#endif
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return;
......@@ -2841,7 +2920,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) {
cli();
NCR5380_setup(instance);
#if (NDEBUG & NDEBUG_ABORT)
printk("scsi%d : abort called\n", instance->host_no);
printk(" basr 0x%X, sr 0x%X\n",
......
......@@ -265,6 +265,15 @@ struct NCR5380_hostdata {
unsigned long time_expires; /* in jiffies, set prior to sleeping */
struct Scsi_Host *next_timer;
#endif
#ifdef NCR5380_STATS
unsigned timebase; /* Base for time calcs */
long time_read[8]; /* time to do reads */
long time_write[8]; /* time to do writes */
unsigned long bytes_read[8]; /* bytes read */
unsigned long bytes_write[8]; /* byytes written */
unsigned pendingr;
unsigned pendingw;
#endif
};
#ifdef __KERNEL__
......
......@@ -44,3 +44,49 @@ This driver works as a module.
Kevin Lentin
K.Lentin@cs.monash.edu.au
REAME file for the Linux g_NCR5380 driver.
(c) 1993 Drew Eckhard
NCR53c400 extensions (c) 1994,1995,1996 Kevin Lentin
This file documents the NCR53c400 extensions by Kevin Lentin and some
enhancements to the NCR5380 core.
This driver supports both NCR5380 and NCR53c400 cards in port or memory
mapped modes. Currently this driver can only support one of those mapping
modes at a time but it does support both of these chips at the same time.
The next release of this driver will support port & memory mapped cards at
the same time. It should be able to handle multiple different cards in the
same machine.
The drivers/scsi/Makefile has an override in it for the most common
NCR53c400 card, the Trantor T130B in its default configuration:
Port: 0x350
IRQ : 5
The NCR53c400 does not support DMA but it does have Pseudo-DMA which is
supported by the driver.
If the default configuration does not work for you, you can use the kernel
command lines (eg using the lilo append command):
ncr5380=port,irq,dma
ncr53c400=port,irq
or
ncr5380=base,irq,dma
ncr53c400=base,irq
The driver does not probe for any addresses or ports other than those in
the OVERRIDE or given to the kernel as above.
This driver provides some information on what it has detected in
/proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot
time. More info to come in the future.
When NCR53c400 support is compiled in, BIOS paramaters will be returned by
the driver (the raw 5380 driver does not and I don't plan to fiddle with
it!).
This driver works as a module.
Kevin Lentin
K.Lentin@cs.monash.edu.au
......@@ -65,6 +65,8 @@
#define NCR53C400_PSEUDO_DMA 1
#define PSEUDO_DMA
#define NCR53C400
#define NCR5380_STATS
#undef NCR5380_STAT_LIMIT
#endif
#if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM)
#error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet)
......@@ -238,8 +240,8 @@ int generic_NCR5380_detect(Scsi_Host_Template * tpnt) {
return count;
}
const char * generic_NCR5380_info (void) {
static const char string[]="Generic NCR5380/53C400 Info";
const char * generic_NCR5380_info (struct Scsi_Host* host) {
static const char string[]="Generic NCR5380/53C400 Driver";
return string;
}
......@@ -285,40 +287,6 @@ int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip)
}
#endif
int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
{
int len = 0;
struct Scsi_Host *scsi_ptr;
for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
if (scsi_ptr->host_no == hostno)
break;
len += sprintf(buffer+len, "SCSI host number %d : %s\n", scsi_ptr->host_no, scsi_ptr->hostt->name);
len += sprintf(buffer+len, "Generic NCR5380 driver version %d\n", GENERIC_NCR5380_PUBLIC_RELEASE);
len += sprintf(buffer+len, "NCR5380 driver core version %d\n", NCR5380_PUBLIC_RELEASE);
#ifdef NCR53C400
len += sprintf(buffer+len, "NCR53C400 driver extension version %d\n", NCR53C400_PUBLIC_RELEASE);
len += sprintf(buffer+len, "NCR53C400 card%s detected\n", (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not");
# if NCR53C400_PSEUDO_DMA
len += sprintf(buffer+len, "NCR53C400 pseudo DMA being used\n");
# endif
#else
len += sprintf(buffer+len, "NO NCR53C400 driver extensions\n");
#endif
len += sprintf(buffer+len, "Using %s mapping at %s 0x%x, ", STRVAL(NCR5380_map_config), STRVAL(NCR5380_map_name), scsi_ptr->NCR5380_instance_name);
if (scsi_ptr->irq == IRQ_NONE)
len += sprintf(buffer+len, "interrupts disabled\n");
else
len += sprintf(buffer+len, "on interrupt %d\n", scsi_ptr->irq);
*start = buffer + offset;
len -= offset;
if (len > length)
len = length;
return len;
}
#if NCR53C400_PSEUDO_DMA
static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, int len)
{
......@@ -564,6 +532,169 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
#endif /* PSEUDO_DMA */
#include "NCR5380.c"
#define PRINTP(x) len += sprintf(buffer+len, x)
#define ANDP ,
static int sprint_opcode(char* buffer, int len, int opcode) {
int start = len;
PRINTP("0x%02x " ANDP opcode);
return len-start;
}
static int sprint_command (char* buffer, int len, unsigned char *command) {
int i,s,start=len;
len += sprint_opcode(buffer, len, command[0]);
for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
PRINTP("%02x " ANDP command[i]);
PRINTP("\n");
return len-start;
}
static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
int start = len;
PRINTP("destination target %d, lun %d\n" ANDP
cmd->host->host_no ANDP
cmd->target ANDP
cmd->lun);
PRINTP(" command = ");
len += sprint_command (buffer, len, cmd->cmnd);
return len-start;
}
const char *const scsi_device_types[] =
{
"Direct-Access ",
"Sequential-Access",
"Printer ",
"Processor ",
"WORM ",
"CD-ROM ",
"Scanner ",
"Optical Device ",
"Medium Changer ",
"Communications "
};
#define MAX_SCSI_DEVICE_CODE sizeof(scsi_device_types)/sizeof(char*)
int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
{
int len = 0;
NCR5380_local_declare();
unsigned char status;
int i;
struct Scsi_Host *scsi_ptr;
Scsi_Device *dev;
Scsi_Cmnd *ptr;
struct NCR5380_hostdata *hostdata;
cli();
for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
if (scsi_ptr->host_no == hostno)
break;
NCR5380_setup(scsi_ptr);
hostdata = (struct NCR5380_hostdata *)scsi_ptr->hostdata;
PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
#ifdef NCR53C400
PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
PRINTP("NCR53C400 card%s detected\n" ANDP (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not");
# if NCR53C400_PSEUDO_DMA
PRINTP("NCR53C400 pseudo DMA used\n");
# endif
#else
PRINTP("NO NCR53C400 driver extensions\n");
#endif
PRINTP("Using %s mapping at %s 0x%x, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
if (scsi_ptr->irq == IRQ_NONE)
PRINTP("no interrupt\n");
else
PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
#ifdef NCR5380_STATS
if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
PRINTP("There are commands pending, transfer rates may be crud\n");
if (hostdata->pendingr)
PRINTP(" %d pending reads" ANDP hostdata->pendingr);
if (hostdata->pendingw)
PRINTP(" %d pending writes" ANDP hostdata->pendingw);
if (hostdata->pendingr || hostdata->pendingw)
PRINTP("\n");
for (dev = scsi_devices; dev; dev=dev->next) {
if (dev->host == scsi_ptr) {
unsigned long br = hostdata->bytes_read[dev->id];
unsigned long bw = hostdata->bytes_write[dev->id];
long tr = hostdata->time_read[dev->id] / HZ;
long tw = hostdata->time_write[dev->id] / HZ;
PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int)dev->type] : "Unknown");
for (i=0; i<8; i++)
if (dev->vendor[i] >= 0x20)
*(buffer+(len++)) = dev->vendor[i];
*(buffer+(len++)) = ' ';
for (i=0; i<16; i++)
if (dev->model[i] >= 0x20)
*(buffer+(len++)) = dev->model[i];
*(buffer+(len++)) = ' ';
for (i=0; i<4; i++)
if (dev->rev[i] >= 0x20)
*(buffer+(len++)) = dev->rev[i];
*(buffer+(len++)) = ' ';
PRINTP("\n%10d kb read in %5d secs" ANDP br/1024 ANDP tr);
if (tr)
PRINTP(" @ %5d bps" ANDP br / tr);
PRINTP("\n%10d kb written in %5d secs" ANDP bw/1024 ANDP tw);
if (tw)
PRINTP(" @ %5d bps" ANDP bw / tw);
PRINTP("\n");
}
}
#endif
status = NCR5380_read(STATUS_REG);
if (!(status & SR_REQ))
PRINTP("REQ not asserted, phase unknown.\n");
else {
for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
(phases[i].value != (status & PHASE_MASK)); ++i)
;
PRINTP("Phase %s\n" ANDP phases[i].name);
}
if (!hostdata->connected) {
PRINTP("No currently connected command\n");
} else {
len += sprint_Scsi_Cmnd (buffer, len, (Scsi_Cmnd *) hostdata->connected);
}
PRINTP("issue_queue\n");
for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;
ptr = (Scsi_Cmnd *) ptr->host_scribble)
len += sprint_Scsi_Cmnd (buffer, len, ptr);
PRINTP("disconnected_queue\n");
for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
ptr = (Scsi_Cmnd *) ptr->host_scribble)
len += sprint_Scsi_Cmnd (buffer, len, ptr);
*start = buffer + offset;
len -= offset;
if (len > length)
len = length;
sti();
return len;
}
#undef PRINTP
#undef ANDP
#ifdef MODULE
/* Eventually this will go into an include file, but this will be later */
Scsi_Host_Template driver_template = GENERIC_NCR5380;
......
......@@ -47,6 +47,7 @@ int generic_NCR5380_detect(Scsi_Host_Template *);
int generic_NCR5380_release_resources(struct Scsi_Host *);
int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int generic_NCR5380_reset(Scsi_Cmnd *);
const char* generic_NCR5380_info(struct Scsi_Host *);
#ifdef BIOSPARAM
int generic_NCR5380_biosparam(Disk *, kdev_t, int *);
#endif
......
......@@ -418,7 +418,6 @@ ask_int_choice (int mask, char *macro,
{
for (i = 0; i < OPT_LAST; i++)
if (!(DISABLED_OPTIONS & B (i)))
if (mask == B (i))
{
unsigned int j;
......@@ -778,7 +777,7 @@ ask_parameters (void)
"Check from manual of the card");
ask_int_choice (B (OPT_SB), "SB_MPU_IRQ",
"SB MPU401 IRQ (Jazz16 and ES1688)",
"SB MPU401 IRQ (Jazz16, SM Wave and ES1688)",
FMT_INT,
-1,
"Check from manual of the card");
......
......@@ -590,7 +590,6 @@ static int rename_same_dir(struct inode *old_dir,char *old_name,int old_len,
mark_buffer_dirty(old_bh, 1);
/* update binary info for conversion, i_attrs */
if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
msdos_read_inode(old_inode);
MSDOS_I(old_inode)->i_attrs = is_hid
? (MSDOS_I(old_inode)->i_attrs | ATTR_HIDDEN)
: (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
......
......@@ -27,6 +27,9 @@
* Martin Mares : Code cleanup.
* Martin Mares : (2.1) BOOTP and RARP made configuration options.
* Martin Mares : Server hostname generation fixed.
* Gerd Knorr : Fixed wired inode handling
* Martin Mares : (2.2) "0.0.0.0" addresses from command line ignored.
* Martin Mares : RARP replies not tested for server address.
*
*
* Known bugs and caveats:
......@@ -128,7 +131,7 @@ static int nfs_port; /* Port to connect to for NFS service */
/* Yes, we use sys_socket, but there's no include file for it */
extern asmlinkage int sys_socket(int family, int type, int protocol);
/***************************************************************************
......@@ -302,12 +305,6 @@ static int root_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet
kfree_skb(skb, FREE_READ);
return 0;
}
/* Discard packets which are not from specified server. */
if (server.sin_addr.s_addr != INADDR_NONE &&
server.sin_addr.s_addr != sip) {
kfree_skb(skb, FREE_READ);
return 0;
}
/*
* The packet is what we were looking for. Setup the global
......@@ -1170,7 +1167,7 @@ static void root_nfs_ip_config(char *addrs)
while (ip && *ip) {
if ((cp = strchr(ip, ':')))
*cp++ = '\0';
if (strlen(ip) > 0) {
if (strlen(ip) > 0 && strcmp(ip, "0.0.0.0")) {
switch (num) {
case 0:
myaddr.sin_addr.s_addr = in_aton(ip);
......@@ -1361,8 +1358,8 @@ int nfs_root_init(char *nfsname, char *nfsaddrs)
***************************************************************************/
static struct file nfs_file; /* File descriptor containing socket */
static struct inode nfs_inode; /* Inode containing socket */
static struct file *nfs_file;
static struct inode *nfs_sock_inode; /* Inode containing socket */
static int *rpc_packet = NULL; /* RPC packet */
......@@ -1371,63 +1368,28 @@ static int *rpc_packet = NULL; /* RPC packet */
*/
static int root_nfs_open(void)
{
struct file *filp;
/* Open the socket */
if ((nfs_data.fd = sys_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
printk(KERN_ERR "Root-NFS: Cannot open UDP socket!\n");
return -1;
}
/*
* Copy the file and inode data area so that we can remove the
* file lateron without killing the socket. After all this the
* closing routine just needs to remove the file pointer from the
* init-task descriptor.
*/
filp = current->files->fd[nfs_data.fd];
memcpy(&nfs_file, filp, sizeof(struct file));
nfs_file.f_next = nfs_file.f_prev = NULL;
current->files->fd[nfs_data.fd] = &nfs_file;
filp->f_count = 0; /* Free the file descriptor */
memcpy(&nfs_inode, nfs_file.f_inode, sizeof(struct inode));
nfs_inode.i_hash_next = nfs_inode.i_hash_prev = NULL;
nfs_inode.i_next = nfs_inode.i_prev = NULL;
clear_inode(nfs_file.f_inode);
nfs_file.f_inode = &nfs_inode;
nfs_inode.u.socket_i.inode = &nfs_inode;
nfs_file.private_data = NULL;
nfs_file = current->files->fd[nfs_data.fd];
nfs_sock_inode = nfs_file->f_inode;
/* keep socket open. Do we need really this ? */
/* nfs_file->f_count++; */
return 0;
}
/*
* Close the UDP file descriptor. The main part of preserving the socket
* has already been done after opening it. Now we have to remove the file
* descriptor from the init task.
* Close the UDP file descriptor. If nfs_read_super is successful, it
* increases the reference count, so we can simply close the file, and
* the socket keeps open.
*/
static void root_nfs_close(int close_all)
{
/* Remove the file from the list of open files */
current->files->fd[nfs_data.fd] = NULL;
if (current->files->count > 0)
current->files->count--;
/* Clear memory used by the RPC packet */
if (rpc_packet != NULL)
kfree_s(rpc_packet, nfs_data.wsize + 1024);
/*
* In case of an error we also have to close the socket again
* (sigh)
*/
if (close_all) {
nfs_inode.u.socket_i.inode = NULL; /* The inode is already
* cleared */
if (nfs_file.f_op->release)
nfs_file.f_op->release(&nfs_inode, &nfs_file);
}
sys_close(nfs_data.fd);
}
......@@ -1441,14 +1403,15 @@ static int root_nfs_bind(void)
struct sockaddr_in *sin = &myaddr;
int i;
if (nfs_inode.u.socket_i.ops->bind) {
if (nfs_sock_inode->u.socket_i.ops->bind) {
for (i = 0; i < NPORTS && res < 0; i++) {
sin->sin_port = htons(port++);
if (port > ENDPORT) {
port = STARTPORT;
}
res = nfs_inode.u.socket_i.ops->bind(&nfs_inode.u.socket_i,
(struct sockaddr *)sin, sizeof(struct sockaddr_in));
res = nfs_sock_inode->u.socket_i.ops->bind
(&nfs_sock_inode->u.socket_i,
(struct sockaddr *)sin, sizeof(struct sockaddr_in));
}
}
if (res < 0) {
......@@ -1468,11 +1431,10 @@ static int root_nfs_bind(void)
*/
static int *root_nfs_call(int *end)
{
struct file *filp;
struct socket *sock;
int dummylen;
static struct nfs_server s = {
&nfs_file, /* struct file * */
0, /* struct file * */
0, /* struct rsock * */
{
0, "",
......@@ -1486,8 +1448,8 @@ static int *root_nfs_call(int *end)
3 * HZ, 60 * HZ, 30 * HZ, 60 * HZ, "\0"
};
filp = &nfs_file;
sock = &((filp->f_inode)->u.socket_i);
s.file = nfs_file;
sock = &((nfs_file->f_inode)->u.socket_i);
/* extract the other end of the socket into s->toaddr */
sock->ops->getname(sock, &(s.toaddr), &dummylen, 1);
......@@ -1495,7 +1457,7 @@ static int *root_nfs_call(int *end)
((struct sockaddr_in *) &s.toaddr)->sin_family = server.sin_family;
((struct sockaddr_in *) &s.toaddr)->sin_addr.s_addr = server.sin_addr.s_addr;
s.rsock = rpc_makesock(filp);
s.rsock = rpc_makesock(nfs_file);
s.flags = nfs_data.flags;
s.rsize = nfs_data.rsize;
s.wsize = nfs_data.wsize;
......@@ -1507,12 +1469,13 @@ static int *root_nfs_call(int *end)
* First connect the UDP socket to a server port, then send the
* packet out, and finally check wether the answer is OK.
*/
if (nfs_inode.u.socket_i.ops->connect &&
nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
(struct sockaddr *) &server,
sizeof(struct sockaddr_in),
nfs_file.f_flags) < 0)
return NULL;
if (nfs_sock_inode->u.socket_i.ops->connect &&
nfs_sock_inode->u.socket_i.ops->connect
(&nfs_sock_inode->u.socket_i,
(struct sockaddr *) &server,
sizeof(struct sockaddr_in),
nfs_file->f_flags) < 0)
return NULL;
if (nfs_rpc_call(&s, rpc_packet, end, nfs_data.wsize) < 0)
return NULL;
return rpc_verify(rpc_packet);
......@@ -1643,11 +1606,12 @@ static int root_nfs_do_mount(struct super_block *sb)
/* First connect to the nfsd port on the server */
server.sin_port = htons(nfs_port);
nfs_data.addr = server;
if (nfs_inode.u.socket_i.ops->connect &&
nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
(struct sockaddr *) &server,
sizeof(struct sockaddr_in),
nfs_file.f_flags) < 0) {
if (nfs_sock_inode->u.socket_i.ops->connect &&
nfs_sock_inode->u.socket_i.ops->connect
(&nfs_sock_inode->u.socket_i,
(struct sockaddr *) &server,
sizeof(struct sockaddr_in),
nfs_file->f_flags) < 0) {
root_nfs_close(1);
return -1;
}
......
......@@ -194,6 +194,7 @@ static int get_kstat(char * buffer)
{
int i, len;
unsigned sum = 0;
extern unsigned long total_forks;
for (i = 0 ; i < NR_IRQS ; i++)
sum += kstat.interrupts[i];
......@@ -230,9 +231,11 @@ static int get_kstat(char * buffer)
len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
len += sprintf(buffer + len,
"\nctxt %u\n"
"btime %lu\n",
"btime %lu\n"
"processes %lu\n",
kstat.context_swtch,
xtime.tv_sec - jiffies / HZ);
xtime.tv_sec - jiffies / HZ,
total_forks);
return len;
}
......
#ifndef __ARCH_I386_ATOMIC__
#define __ARCH_I386_ATOMIC__
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
*/
/*
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
* not some alias that contains the same information.
*/
#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
typedef int atomic_t;
extern __inline__ void atomic_add(atomic_t i, atomic_t * v)
{
unsigned long temp;
__asm__ __volatile__(
"\n1:\t"
"ldl_l %0,%1\n\t"
"addl %0,%2,%0\n\t"
"stl_c %0,%1\n\t"
"beq %0,1b\n"
"2:"
:"=&r" (temp),
"=m" (__atomic_fool_gcc(v))
:"Ir" (i),
"m" (__atomic_fool_gcc(v)));
}
extern __inline__ void atomic_sub(atomic_t i, atomic_t * v)
{
unsigned long temp;
__asm__ __volatile__(
"\n1:\t"
"ldl_l %0,%1\n\t"
"subl %0,%2,%0\n\t"
"stl_c %0,%1\n\t"
"beq %0,1b\n"
"2:"
:"=&r" (temp),
"=m" (__atomic_fool_gcc(v))
:"Ir" (i),
"m" (__atomic_fool_gcc(v)));
}
#define atomic_inc(v) atomic_add(1,(v))
#define atomic_dec(v) atomic_sub(1,(v))
#endif
#ifndef __ARCH_I386_ATOMIC__
#define __ARCH_I386_ATOMIC__
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
*/
#ifdef __SMP__
#define LOCK "lock ; "
#else
#define LOCK ""
#endif
/*
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
* not some alias that contains the same information.
*/
#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
typedef int atomic_t;
static __inline__ void atomic_add(atomic_t i, atomic_t *v)
{
__asm__ __volatile__(
LOCK "addl %1,%0"
:"=m" (__atomic_fool_gcc(v))
:"ir" (i), "m" (__atomic_fool_gcc(v)));
}
static __inline__ void atomic_sub(atomic_t i, atomic_t *v)
{
__asm__ __volatile__(
LOCK "subl %1,%0"
:"=m" (__atomic_fool_gcc(v))
:"ir" (i), "m" (__atomic_fool_gcc(v)));
}
static __inline__ void atomic_inc(atomic_t *v)
{
__asm__ __volatile__(
LOCK "incl %0"
:"=m" (__atomic_fool_gcc(v))
:"m" (__atomic_fool_gcc(v)));
}
static __inline__ void atomic_dec(atomic_t *v)
{
__asm__ __volatile__(
LOCK "decl %0"
:"=m" (__atomic_fool_gcc(v))
:"m" (__atomic_fool_gcc(v)));
}
#endif
......@@ -9,7 +9,9 @@
/*
* System setup and hardware bug flags..
* [Note we don't test the 386 multiply bug or popad bug]
*/
extern char hard_math;
extern char x86; /* lower 4 bits */
extern char x86_vendor_id[13];
......@@ -18,8 +20,9 @@ extern char x86_mask; /* lower 4 bits */
extern int x86_capability; /* field of flags */
extern int fdiv_bug;
extern char ignore_irq13;
extern char wp_works_ok; /* doesn't work on a 386 */
extern char wp_works_ok; /* doesn't work on a 386 */
extern char hlt_works_ok; /* problems on some 486Dx4's and old 386's */
extern int have_cpuid; /* We have a CPUID */
/*
* Bus types (default is ISA, but people can check others with these..)
......
......@@ -232,7 +232,6 @@ extern void dev_queue_xmit(struct sk_buff *skb, struct device *dev,
#define HAVE_NETIF_RX 1
extern void netif_rx(struct sk_buff *skb);
extern void dev_transmit(void);
extern int in_net_bh(void);
extern void net_bh(void);
extern void dev_tint(struct device *dev);
extern int dev_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
......
......@@ -55,6 +55,8 @@
#include <linux/igmp.h>
#include <asm/atomic.h>
/* Think big (also on some systems a byte is faster) */
#define SOCK_ARRAY_SIZE 256
......@@ -149,8 +151,8 @@ struct tcp_opt
struct sock
{
struct options *opt;
volatile unsigned long wmem_alloc;
volatile unsigned long rmem_alloc;
atomic_t wmem_alloc;
atomic_t rmem_alloc;
unsigned long allocation; /* Allocation mode */
__u32 write_seq;
__u32 sent_seq;
......@@ -484,14 +486,10 @@ extern struct sk_buff *sock_alloc_send_skb(struct sock *skb,
extern __inline__ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
unsigned long flags;
if(sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
if (sk->rmem_alloc + skb->truesize >= sk->rcvbuf)
return -ENOMEM;
save_flags(flags);
cli();
sk->rmem_alloc+=skb->truesize;
atomic_add(skb->truesize, &sk->rmem_alloc);
skb->sk=sk;
restore_flags(flags);
skb_queue_tail(&sk->receive_queue,skb);
if(!sk->dead)
sk->data_ready(sk,skb->len);
......
......@@ -28,6 +28,7 @@
int nr_tasks=1;
int nr_running=1;
unsigned long int total_forks=0; /* Handle normal Linux uptimes. */
static inline int find_empty_process(void)
{
......@@ -269,6 +270,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
p->exit_signal = clone_flags & CSIGNAL;
p->counter = current->counter >> 1;
wake_up_process(p); /* do this last, just in case */
++total_forks;
return p->pid;
bad_fork_cleanup_sighand:
......
......@@ -886,7 +886,7 @@ static inline void do_it_virt(struct task_struct * p, unsigned long ticks)
unsigned long it_virt = p->it_virt_value;
if (it_virt) {
if (it_virt < ticks) {
if (it_virt <= ticks) {
it_virt = ticks + p->it_virt_incr;
send_sig(SIGVTALRM, p, 1);
}
......@@ -899,7 +899,7 @@ static inline void do_it_prof(struct task_struct * p, unsigned long ticks)
unsigned long it_prof = p->it_prof_value;
if (it_prof) {
if (it_prof < ticks) {
if (it_prof <= ticks) {
it_prof = ticks + p->it_prof_incr;
send_sig(SIGPROF, p, 1);
}
......
......@@ -493,12 +493,36 @@ static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long
* Tries to write a shared mapped page to its backing store. May return -EIO
* if the disk is full.
*/
static inline int do_write_page(struct inode * inode, struct file * file,
const char * page, unsigned long offset)
{
int old_fs, retval;
unsigned long size;
size = offset + PAGE_SIZE;
/* refuse to extend file size.. */
if (S_ISREG(inode->i_mode)) {
if (size > inode->i_size)
size = inode->i_size;
/* Ho humm.. We should have tested for this earlier */
if (size < offset)
return -EIO;
}
size -= offset;
old_fs = get_fs();
set_fs(KERNEL_DS);
retval = -EIO;
if (size == file->f_op->write(inode, file, (const char *) page, size))
retval = 0;
set_fs(old_fs);
return retval;
}
static int filemap_write_page(struct vm_area_struct * vma,
unsigned long offset,
unsigned long page)
{
int old_fs;
unsigned long size, result;
int result;
struct file file;
struct inode * inode;
struct buffer_head * bh;
......@@ -518,29 +542,17 @@ static int filemap_write_page(struct vm_area_struct * vma,
file.f_op = inode->i_op->default_file_ops;
if (!file.f_op->write)
return -EIO;
size = offset + PAGE_SIZE;
/* refuse to extend file size.. */
if (S_ISREG(inode->i_mode)) {
if (size > inode->i_size)
size = inode->i_size;
/* Ho humm.. We should have tested for this earlier */
if (size < offset)
return -EIO;
}
size -= offset;
file.f_mode = 3;
file.f_flags = 0;
file.f_count = 1;
file.f_inode = inode;
file.f_pos = offset;
file.f_reada = 0;
old_fs = get_fs();
set_fs(KERNEL_DS);
result = file.f_op->write(inode, &file, (const char *) page, size);
set_fs(old_fs);
if (result != size)
return -EIO;
return 0;
down(&inode->i_sem);
result = do_write_page(inode, &file, (const char *) page, offset);
up(&inode->i_sem);
return result;
}
......
......@@ -1791,7 +1791,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int n
if(sk->debug)
printk("SK %p: Loop back.\n", sk);
/* loop back */
sk->wmem_alloc-=skb->truesize;
atomic_sub(skb->truesize, &sk->wmem_alloc);
ddp_dl->datalink_header(ddp_dl, skb, dev->dev_addr);
skb->sk = NULL;
skb->mac.raw=skb->data;
......
......@@ -377,7 +377,7 @@ static void ax25_send_to_raw(struct sock *sk, struct sk_buff *skb, int proto)
return;
copy->sk = sk;
sk->rmem_alloc += copy->truesize;
atomic_add(copy->truesize, &sk->rmem_alloc);
skb_queue_tail(&sk->receive_queue, copy);
if (!sk->dead)
sk->data_ready(sk, skb->len);
......@@ -1727,7 +1727,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
skb_pull(skb, 2);
skb_queue_tail(&sk->receive_queue, skb);
skb->sk = sk;
sk->rmem_alloc += skb->truesize;
atomic_add(skb->truesize, &sk->rmem_alloc);
if (!sk->dead)
sk->data_ready(sk, skb->len);
}
......
......@@ -95,7 +95,7 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
if (ax25->sk != NULL) {
skbn->sk = ax25->sk;
ax25->sk->rmem_alloc += skbn->truesize;
atomic_add(skbn->truesize, &ax25->sk->rmem_alloc);
}
/* get first fragment from queue */
......
......@@ -215,7 +215,7 @@ void ax25_send_control(ax25_cb *ax25, int frametype, int poll_bit, int type)
if (ax25->sk != NULL) {
skb->sk = ax25->sk;
ax25->sk->wmem_alloc += skb->truesize;
atomic_add(skb->truesize, &ax25->sk->wmem_alloc);
}
/* Assume a response - address structure for DTE */
......@@ -498,7 +498,7 @@ void ax25_kiss_cmd(ax25_cb *ax25, unsigned char cmd, unsigned char param)
if (ax25->sk != NULL) {
skb->sk = ax25->sk;
ax25->sk->wmem_alloc += skb->truesize;
atomic_add(skb->truesize, &ax25->sk->wmem_alloc);
}
skb->protocol = htons(ETH_P_AX25);
......
......@@ -79,7 +79,7 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
lock_sock(sk);
restart:
while(skb_peek(&sk->receive_queue) == NULL) /* No data */
while(skb_queue_empty(&sk->receive_queue)) /* No data */
{
/* Socket errors? */
error = sock_error(sk);
......@@ -142,14 +142,12 @@ void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
save_flags(flags);
cli();
skb->users--;
if(skb->users>0)
{
restore_flags(flags);
return;
if(skb->users <= 0) {
/* See if it needs destroying */
/* Been dequeued by someone - ie it's read */
if(!skb->next && !skb->prev)
kfree_skb(skb,FREE_READ);
}
/* See if it needs destroying */
if(!skb->next && !skb->prev) /* Been dequeued by someone - ie it's read */
kfree_skb(skb,FREE_READ);
restore_flags(flags);
release_sock(sk);
}
......
......@@ -536,19 +536,6 @@ void dev_transmit(void)
***********************************************************************************/
/*
* This is a single non-reentrant routine which takes the received packet
* queue and throws it at the networking layers in the hope that something
* useful will emerge.
*/
volatile unsigned long in_bh = 0; /* Non-reentrant remember */
int in_net_bh() /* Used by timer.c */
{
return(in_bh==0?0:1);
}
/*
* When we are called the queue is ready to grab, the interrupts are
* on and hardware can interrupt and queue to the receive queue a we
......@@ -559,18 +546,10 @@ int in_net_bh() /* Used by timer.c */
void net_bh(void)
{
struct sk_buff *skb;
struct packet_type *ptype;
struct packet_type *pt_prev;
unsigned short type;
/*
* Atomically check and mark our BUSY state.
*/
if (set_bit(1, (void*)&in_bh))
return;
/*
* Can we send anything now? We want to clear the
* decks for any more sends that get done as we
......@@ -586,19 +565,23 @@ void net_bh(void)
* that from the device which does a mark_bh() just after
*/
cli();
/*
* While the queue is not empty
* While the queue is not empty..
*
* Note that the queue never shrinks due to
* an interrupt, so we can do this test without
* disabling interrupts.
*/
while((skb=__skb_dequeue(&backlog))!=NULL)
{
while (!skb_queue_empty(&backlog)) {
struct sk_buff * skb = backlog.next;
/*
* We have a packet. Therefore the queue has shrunk
*/
cli();
__skb_unlink(skb, &backlog);
backlog_size--;
sti();
/*
......@@ -681,15 +664,11 @@ void net_bh(void)
#ifdef XMIT_EVERY
dev_transmit();
#endif
cli();
} /* End of queue loop */
/*
* We have emptied the queue
*/
in_bh = 0;
sti();
/*
* One last output flush.
......
......@@ -57,23 +57,23 @@
* Resource tracking variables
*/
unsigned long net_skbcount = 0;
unsigned long net_locked = 0;
unsigned long net_allocs = 0;
unsigned long net_fails = 0;
unsigned long net_free_locked = 0;
atomic_t net_skbcount = 0;
atomic_t net_locked = 0;
atomic_t net_allocs = 0;
atomic_t net_fails = 0;
atomic_t net_free_locked = 0;
extern unsigned long ip_frag_mem;
extern atomic_t ip_frag_mem;
void show_net_buffers(void)
{
printk("Networking buffers in use : %lu\n",net_skbcount);
printk("Network buffers locked by drivers : %lu\n",net_locked);
printk("Total network buffer allocations : %lu\n",net_allocs);
printk("Total failed network buffer allocs : %lu\n",net_fails);
printk("Total free while locked events : %lu\n",net_free_locked);
printk("Networking buffers in use : %u\n",net_skbcount);
printk("Network buffers locked by drivers : %u\n",net_locked);
printk("Total network buffer allocations : %u\n",net_allocs);
printk("Total failed network buffer allocs : %u\n",net_fails);
printk("Total free while locked events : %u\n",net_free_locked);
#ifdef CONFIG_INET
printk("IP fragment buffer size : %lu\n",ip_frag_mem);
printk("IP fragment buffer size : %u\n",ip_frag_mem);
#endif
}
......@@ -614,27 +614,24 @@ void kfree_skb(struct sk_buff *skb, int rw)
skb->destructor(skb);
if (skb->sk)
{
if(skb->sk->prot!=NULL)
struct sock * sk = skb->sk;
if(sk->prot!=NULL)
{
if (rw)
sock_rfree(skb->sk, skb);
sock_rfree(sk, skb);
else
sock_wfree(skb->sk, skb);
sock_wfree(sk, skb);
}
else
{
unsigned long flags;
/* Non INET - default wmalloc/rmalloc handler */
save_flags(flags);
cli();
if (rw)
skb->sk->rmem_alloc-=skb->truesize;
else
skb->sk->wmem_alloc-=skb->truesize;
restore_flags(flags);
if(!skb->sk->dead)
skb->sk->write_space(skb->sk);
atomic_sub(skb->truesize, &sk->rmem_alloc);
else {
atomic_sub(skb->truesize, &sk->wmem_alloc);
if(!sk->dead)
sk->write_space(sk);
}
kfree_skbmem(skb);
}
}
......@@ -760,7 +757,6 @@ void kfree_skbmem(struct sk_buff *skb)
struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
{
unsigned long flags;
struct sk_buff *n;
IS_SKB(skb);
......@@ -771,12 +767,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
n->count = 1;
if (skb->data_skb)
skb = skb->data_skb;
save_flags(flags);
cli();
skb->count++;
net_allocs++;
net_skbcount++;
restore_flags(flags);
atomic_inc(&skb->count);
atomic_inc(&net_allocs);
atomic_inc(&net_skbcount);
n->data_skb = skb;
n->next = n->prev = n->link3 = NULL;
n->list = NULL;
......
......@@ -324,50 +324,32 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
return(0);
}
struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
{
if (sk)
{
if (sk->wmem_alloc + size < sk->sndbuf || force)
{
struct sk_buff * c = alloc_skb(size, priority);
if (c)
{
unsigned long flags;
save_flags(flags);
cli();
sk->wmem_alloc+= c->truesize;
restore_flags(flags); /* was sti(); */
}
return c;
if (sk) {
if (force || sk->wmem_alloc + size < sk->sndbuf) {
struct sk_buff * skb = alloc_skb(size, priority);
if (skb)
atomic_add(skb->truesize, &sk->wmem_alloc);
return skb;
}
return(NULL);
return NULL;
}
return(alloc_skb(size, priority));
return alloc_skb(size, priority);
}
struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
{
if (sk)
{
if (sk->rmem_alloc + size < sk->rcvbuf || force)
{
struct sk_buff *c = alloc_skb(size, priority);
if (c)
{
unsigned long flags;
save_flags(flags);
cli();
sk->rmem_alloc += c->truesize;
restore_flags(flags); /* was sti(); */
}
return(c);
if (sk) {
if (force || sk->rmem_alloc + size < sk->rcvbuf) {
struct sk_buff *skb = alloc_skb(size, priority);
if (skb)
atomic_add(skb->truesize, &sk->rmem_alloc);
return skb;
}
return(NULL);
return NULL;
}
return(alloc_skb(size, priority));
return alloc_skb(size, priority);
}
......@@ -396,7 +378,7 @@ unsigned long sock_wspace(struct sock *sk)
return(0);
if (sk->wmem_alloc >= sk->sndbuf)
return(0);
return(sk->sndbuf-sk->wmem_alloc );
return sk->sndbuf - sk->wmem_alloc;
}
return(0);
}
......@@ -411,14 +393,9 @@ void sock_wfree(struct sock *sk, struct sk_buff *skb)
kfree_skbmem(skb);
if (sk)
{
unsigned long flags;
save_flags(flags);
cli();
sk->wmem_alloc -= s;
restore_flags(flags);
atomic_sub(s, &sk->wmem_alloc);
/* In case it might be waiting for more memory. */
sk->write_space(sk);
return;
}
}
......@@ -432,11 +409,7 @@ void sock_rfree(struct sock *sk, struct sk_buff *skb)
kfree_skbmem(skb);
if (sk)
{
unsigned long flags;
save_flags(flags);
cli();
sk->rmem_alloc -= s;
restore_flags(flags);
atomic_sub(s, &sk->rmem_alloc);
}
}
......
......@@ -410,7 +410,8 @@ void destroy_sock(struct sock *sk)
{
/* this should never happen. */
/* actually it can if an ack has just been sent. */
printk("Socket destroy delayed\n");
printk("Socket destroy delayed (r=%d w=%d)\n",
sk->rmem_alloc, sk->wmem_alloc);
sk->destroy = 1;
sk->ack_backlog = 0;
release_sock(sk);
......
......@@ -45,7 +45,7 @@
static struct ipq *ipqueue = NULL; /* IP fragment queue */
unsigned long ip_frag_mem = 0; /* Memory used for fragments */
atomic_t ip_frag_mem = 0; /* Memory used for fragments */
/*
* Memory Tracking Functions
......@@ -53,34 +53,22 @@ unsigned long ip_frag_mem = 0; /* Memory used for fragments */
extern __inline__ void frag_kfree_skb(struct sk_buff *skb, int type)
{
unsigned long flags;
save_flags(flags);
cli();
ip_frag_mem-=skb->truesize;
restore_flags(flags);
atomic_sub(skb->truesize, &ip_frag_mem);
kfree_skb(skb,type);
}
extern __inline__ void frag_kfree_s(void *ptr, int len)
{
unsigned long flags;
save_flags(flags);
cli();
ip_frag_mem-=len;
restore_flags(flags);
atomic_sub(len, &ip_frag_mem);
kfree_s(ptr,len);
}
extern __inline__ void *frag_kmalloc(int size, int pri)
{
unsigned long flags;
void *vp=kmalloc(size,pri);
if(!vp)
return NULL;
save_flags(flags);
cli();
ip_frag_mem+=size;
restore_flags(flags);
atomic_add(size, &ip_frag_mem);
return vp;
}
......@@ -623,7 +611,6 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i
struct sk_buff *skb2;
int left, mtu, hlen, len;
int offset;
unsigned long flags;
/*
* Point into the IP datagram header.
......@@ -730,14 +717,11 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i
* it might possess
*/
save_flags(flags);
if (sk)
{
cli();
sk->wmem_alloc += skb2->truesize;
atomic_add(skb2->truesize, &sk->wmem_alloc);
skb2->sk=sk;
}
restore_flags(flags);
skb2->raddr = skb->raddr; /* For rebuild_header - must be here */
/*
......
......@@ -108,7 +108,7 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of
timer_active=timer_active2;
timer_expires=sp->timer.expires;
}
len += sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d %d\n",
len += sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08X:%08X %02X:%08lX %08X %d %d\n",
i, src, srcp, dest, destp, sp->state,
format==0?sp->write_seq-sp->rcv_ack_seq:sp->wmem_alloc,
format==0?sp->acked_seq-sp->copied_seq:sp->rmem_alloc,
......
......@@ -1595,7 +1595,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
*/
skb->sk=sk;
sk->rmem_alloc += skb->truesize;
atomic_add(skb->truesize, &sk->rmem_alloc);
/*
* We should now do header prediction.
......@@ -1773,7 +1773,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
if(sk->debug)
printk("Doing a BSD time wait\n");
tcp_statistics.TcpEstabResets++;
sk->rmem_alloc -= skb->truesize;
atomic_sub(skb->truesize, &sk->rmem_alloc);
skb->sk = NULL;
sk->err=ECONNRESET;
tcp_set_state(sk, TCP_CLOSE);
......@@ -1783,7 +1783,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
if (sk && sk->state==TCP_LISTEN)
{
skb->sk = sk;
sk->rmem_alloc += skb->truesize;
atomic_add(skb->truesize, &sk->rmem_alloc);
tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000);
return 0;
}
......@@ -1847,12 +1847,18 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
* now drop it (we must process the ack first to avoid
* deadlock cases).
*/
#if 0
/*
* Is this test really a good idea? We should
* throw away packets that aren't in order, not
* new packets.
*/
if (sk->rmem_alloc >= sk->rcvbuf)
{
kfree_skb(skb, FREE_READ);
return(0);
}
#endif
/*
......
......@@ -738,8 +738,8 @@ void tcp_send_synack(struct sock * newsk, struct sock * sk, struct sk_buff * skb
* Charge the sock_buff to newsk.
*/
sk->rmem_alloc -= skb->truesize;
newsk->rmem_alloc += skb->truesize;
atomic_sub(skb->truesize, &sk->rmem_alloc);
atomic_add(skb->truesize, &newsk->rmem_alloc);
skb_queue_tail(&sk->receive_queue,skb);
sk->ack_backlog++;
......
......@@ -593,7 +593,7 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
*/
if(skb->sk)
{
skb->sk->wmem_alloc-=skb->truesize;
atomic_sub(skb->truesize, &skb->sk->wmem_alloc);
skb->sk=NULL;
}
/*
......@@ -608,7 +608,7 @@ static int ipxitf_send(ipx_interface *intrfc, struct sk_buff *skb, char *node)
{
if (!send_to_wire && skb->sk)
{
skb->sk->wmem_alloc-=skb->truesize;
atomic_sub(skb->truesize, &skb->sk->wmem_alloc);
skb->sk=NULL;
}
ipxitf_demux_socket(intrfc, skb, send_to_wire);
......
......@@ -43,11 +43,11 @@ do
echo "failed. Clean up yourself."
break
fi
if [ "`find $sourcedir '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
if [ "`find $sourcedir -follow '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
then
echo "Aborting. Reject files found."
break
fi
# Remove backup files
find $sourcedir '(' -name '*.orig' -o -name '.*.orig' ')' -print | xargs rm -f
find $sourcedir -follow '(' -name '*.orig' -o -name '.*.orig' ')' -print | xargs rm -f
done
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