Commit c3347054 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.51

parent 2d8ead33
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 50 SUBLEVEL = 51
ARCH = i386 ARCH = i386
......
This diff is collapsed.
...@@ -212,7 +212,7 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, ...@@ -212,7 +212,7 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
if (reset) if (reset)
return; return;
if (!controller_ready(drive, head)) { if (!controller_ready(drive, head)) {
special_op[drive] += reset = 1; reset = 1;
return; return;
} }
SET_INTR(intr_addr); SET_INTR(intr_addr);
...@@ -311,7 +311,7 @@ static void identify_intr(void) ...@@ -311,7 +311,7 @@ static void identify_intr(void)
/* In fact, we should probably do a reset in any case in */ /* In fact, we should probably do a reset in any case in */
/* case we changed the geometry */ /* case we changed the geometry */
if (!strncmp(id.model, "QUANTUM", 7)) if (!strncmp(id.model, "QUANTUM", 7))
special_op[dev] += reset = 1; reset = 1;
/* flush remaining 384 (reserved/undefined) ID bytes: */ /* flush remaining 384 (reserved/undefined) ID bytes: */
insw(HD_DATA,(char *)&id,sizeof(id)/2); insw(HD_DATA,(char *)&id,sizeof(id)/2);
...@@ -439,7 +439,7 @@ static void bad_rw_intr(void) ...@@ -439,7 +439,7 @@ static void bad_rw_intr(void)
end_request(0); end_request(0);
special_op[dev] += recalibrate[dev] = 1; special_op[dev] += recalibrate[dev] = 1;
} else if (CURRENT->errors % RESET_FREQ == 0) } else if (CURRENT->errors % RESET_FREQ == 0)
special_op[dev] += reset = 1; reset = 1;
else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
special_op[dev] += recalibrate[dev] = 1; special_op[dev] += recalibrate[dev] = 1;
/* Otherwise just retry */ /* Otherwise just retry */
...@@ -644,7 +644,7 @@ static void hd_times_out(void) ...@@ -644,7 +644,7 @@ static void hd_times_out(void)
sti(); sti();
if (!CURRENT) if (!CURRENT)
return; return;
special_op [DEVICE_NR(CURRENT->dev)] += reset = 1; reset = 1;
printk(KERN_DEBUG "HD timeout\n"); printk(KERN_DEBUG "HD timeout\n");
cli(); cli();
if (++CURRENT->errors >= MAX_ERRORS) { if (++CURRENT->errors >= MAX_ERRORS) {
...@@ -701,7 +701,6 @@ static void hd_request(void) ...@@ -701,7 +701,6 @@ static void hd_request(void)
#endif #endif
if (!unmask_intr[dev]) if (!unmask_intr[dev])
cli(); cli();
if (special_op[dev]) { /* we use "special_op" to reduce overhead on r/w */
if (reset) { if (reset) {
int i; int i;
...@@ -711,6 +710,7 @@ static void hd_request(void) ...@@ -711,6 +710,7 @@ static void hd_request(void)
reset_hd(); reset_hd();
return; return;
} }
if (special_op[dev]) { /* we use "special_op" to reduce overhead on r/w */
if (recalibrate[dev]) { if (recalibrate[dev]) {
recalibrate[dev] = 0; recalibrate[dev] = 0;
hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
......
...@@ -188,20 +188,18 @@ static void i596_interrupt(int reg_ptr); ...@@ -188,20 +188,18 @@ static void i596_interrupt(int reg_ptr);
static int i596_close(struct device *dev); static int i596_close(struct device *dev);
static struct enet_statistics *i596_get_stats(struct device *dev); static struct enet_statistics *i596_get_stats(struct device *dev);
static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd); static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd);
static void i596_cleanup_cmd(struct i596_private *lp);
static void print_eth(char *); static void print_eth(char *);
#ifdef HAVE_MULTICAST #ifdef HAVE_MULTICAST
static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
#endif #endif
static inline void static inline void
init_rx_bufs(struct device *dev) init_rx_bufs(struct device *dev)
{ {
struct i596_private *lp = (struct i596_private *)dev->priv; struct i596_private *lp = (struct i596_private *)dev->priv;
int i; int i;
int boguscnt = 50; int boguscnt = 100;
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
if (i596_debug > 1) printk ("%s: init_rx_bufs.\n", dev->name); if (i596_debug > 1) printk ("%s: init_rx_bufs.\n", dev->name);
...@@ -249,7 +247,7 @@ init_i596_mem(struct device *dev) ...@@ -249,7 +247,7 @@ init_i596_mem(struct device *dev)
{ {
struct i596_private *lp = (struct i596_private *)dev->priv; struct i596_private *lp = (struct i596_private *)dev->priv;
short ioaddr = dev->base_addr; short ioaddr = dev->base_addr;
int boguscnt = 50; int boguscnt = 100;
/* change the scp address */ /* change the scp address */
outw(0, ioaddr); outw(0, ioaddr);
...@@ -295,8 +293,16 @@ init_i596_mem(struct device *dev) ...@@ -295,8 +293,16 @@ init_i596_mem(struct device *dev)
init_rx_bufs(dev); init_rx_bufs(dev);
return; boguscnt=200;
while (lp->scb.status, lp->scb.command)
if (--boguscnt == 0)
{
printk("i82596 init timed out with status %4.4x, cmd %4.4x.\n",
lp->scb.status, lp->scb.command);
break;
}
return;
} }
static inline int static inline int
...@@ -361,77 +367,11 @@ i596_rx(struct device *dev) ...@@ -361,77 +367,11 @@ i596_rx(struct device *dev)
return 0; return 0;
} }
static inline void
static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd) i596_cleanup_cmd(struct i596_private *lp)
{
struct i596_private *lp = (struct i596_private *)dev->priv;
int ioaddr = dev->base_addr;
unsigned long flags;
int boguscnt = 50;
if (i596_debug > 4) printk ("i596_add_cmd\n");
cmd->status = 0;
cmd->command |= (CMD_EOL|CMD_INTR);
cmd->next = (struct i596_cmd *) -1;
save_flags(flags);
cli();
if (lp->cmd_head != (struct i596_cmd *) -1)
lp->cmd_tail->next = cmd;
else
{
lp->cmd_head=cmd;
while (lp->scb.status, lp->scb.command)
if (--boguscnt == 0)
{
printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n",
lp->scb.status, lp->scb.command);
break;
}
lp->scb.cmd = cmd;
lp->scb.command = CUC_START;
outw (0, ioaddr+4);
}
lp->cmd_tail=cmd;
lp->cmd_backlog++;
lp->cmd_head=lp->scb.cmd;
restore_flags(flags);
if (lp->cmd_backlog > 8)
{
int tickssofar = jiffies - lp->last_cmd;
if (tickssofar < 10)
return;
printk("%s: command unit timed out, status resetting.\n",
dev->name);
boguscnt = 50;
while (lp->scb.status, lp->scb.command)
if (--boguscnt == 0)
{
printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n",
lp->scb.status, lp->scb.command);
break;
}
lp->scb.command=CUC_ABORT|RX_ABORT;
outw(0, ioaddr+4);
i596_cleanup_cmd(lp);
i596_rx(dev);
init_i596_mem(dev);
}
}
static void i596_cleanup_cmd(struct i596_private *lp)
{ {
struct i596_cmd *ptr; struct i596_cmd *ptr;
int boguscnt = 50; int boguscnt = 100;
if (i596_debug > 4) printk ("i596_cleanup_cmd\n"); if (i596_debug > 4) printk ("i596_cleanup_cmd\n");
...@@ -482,8 +422,96 @@ static void i596_cleanup_cmd(struct i596_private *lp) ...@@ -482,8 +422,96 @@ static void i596_cleanup_cmd(struct i596_private *lp)
lp->scb.cmd = lp->cmd_head; lp->scb.cmd = lp->cmd_head;
} }
static inline void
i596_reset(struct device *dev, struct i596_private *lp, int ioaddr)
{
int boguscnt = 100;
if (i596_debug > 4) printk ("i596_reset\n");
while (lp->scb.status, lp->scb.command)
if (--boguscnt == 0)
{
printk("i596_reset timed out with status %4.4x, cmd %4.4x.\n",
lp->scb.status, lp->scb.command);
break;
}
dev->start=0;
dev->tbusy=1;
lp->scb.command=CUC_ABORT|RX_ABORT;
outw(0, ioaddr+4);
/* wait for shutdown */
boguscnt = 400;
while ((lp->scb.status, lp->scb.command) || lp->scb.command)
if (--boguscnt == 0)
{
printk("i596_reset 2 timed out with status %4.4x, cmd %4.4x.\n",
lp->scb.status, lp->scb.command);
break;
}
i596_cleanup_cmd(lp);
i596_rx(dev);
dev->start=1;
dev->tbusy=0;
dev->interrupt=0;
init_i596_mem(dev);
}
static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd)
{
struct i596_private *lp = (struct i596_private *)dev->priv;
int ioaddr = dev->base_addr;
unsigned long flags;
int boguscnt = 100;
if (i596_debug > 4) printk ("i596_add_cmd\n");
cmd->status = 0;
cmd->command |= (CMD_EOL|CMD_INTR);
cmd->next = (struct i596_cmd *) -1;
save_flags(flags);
cli();
if (lp->cmd_head != (struct i596_cmd *) -1)
lp->cmd_tail->next = cmd;
else
{
lp->cmd_head=cmd;
while (lp->scb.status, lp->scb.command)
if (--boguscnt == 0)
{
printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n",
lp->scb.status, lp->scb.command);
break;
}
lp->scb.cmd = cmd;
lp->scb.command = CUC_START;
outw (0, ioaddr+4);
}
lp->cmd_tail=cmd;
lp->cmd_backlog++;
lp->cmd_head=lp->scb.cmd;
restore_flags(flags);
if (lp->cmd_backlog > 16)
{
int tickssofar = jiffies - lp->last_cmd;
if (tickssofar < 25) return;
printk("%s: command unit timed out, status resetting.\n", dev->name);
i596_reset(dev, lp, ioaddr);
}
}
static int static int
i596_open(struct device *dev) i596_open(struct device *dev)
...@@ -528,13 +556,9 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -528,13 +556,9 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev)
/* Try to restart the adaptor */ /* Try to restart the adaptor */
if (lp->last_restart == lp->stats.tx_packets) { if (lp->last_restart == lp->stats.tx_packets) {
if (i596_debug > 1) printk ("Resetting board.\n"); if (i596_debug > 1) printk ("Resetting board.\n");
/* Shutdown and restart */
lp->scb.command=CUC_ABORT|RX_ABORT; /* Shutdown and restart */
outw(0, ioaddr+4); i596_reset(dev,lp, ioaddr);
i596_cleanup_cmd(lp);
init_i596_mem(dev);
} else { } else {
/* Issue a channel attention signal */ /* Issue a channel attention signal */
if (i596_debug > 1) printk ("Kicking board.\n"); if (i596_debug > 1) printk ("Kicking board.\n");
...@@ -605,7 +629,6 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev) ...@@ -605,7 +629,6 @@ i596_start_xmit(struct sk_buff *skb, struct device *dev)
return 0; return 0;
} }
static void print_eth(char *add) static void print_eth(char *add)
{ {
...@@ -676,7 +699,6 @@ unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end) ...@@ -676,7 +699,6 @@ unsigned long apricot_init(unsigned long mem_start, unsigned long mem_end)
return mem_start; return mem_start;
} }
static void static void
i596_interrupt(int reg_ptr) i596_interrupt(int reg_ptr)
{ {
...@@ -684,7 +706,7 @@ i596_interrupt(int reg_ptr) ...@@ -684,7 +706,7 @@ i596_interrupt(int reg_ptr)
struct device *dev = (struct device *)(irq2dev_map[irq]); struct device *dev = (struct device *)(irq2dev_map[irq]);
struct i596_private *lp; struct i596_private *lp;
short ioaddr; short ioaddr;
int boguscnt = 100; int boguscnt = 200;
unsigned short status, ack_cmd=0; unsigned short status, ack_cmd=0;
if (dev == NULL) { if (dev == NULL) {
......
...@@ -72,7 +72,7 @@ have on-board buffer memory needed to support the slower shared memory mode.) ...@@ -72,7 +72,7 @@ have on-board buffer memory needed to support the slower shared memory mode.)
Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA Most ISA boards have jumpered settings for the I/O base, IRQ line, and DMA
channel. This driver probes the likely base addresses: channel. This driver probes the likely base addresses:
{0x300, 0x320, 0x340, 0x360}. {0x300, 0x320, 0x340, 0x360}.
After the board is found it generates an DMA-timeout interrupt and uses After the board is found it generates a DMA-timeout interrupt and uses
autoIRQ to find the IRQ line. The DMA channel can be set with the low bits autoIRQ to find the IRQ line. The DMA channel can be set with the low bits
of the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is of the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is
probed for by enabling each free DMA channel in turn and checking if probed for by enabling each free DMA channel in turn and checking if
...@@ -102,14 +102,14 @@ statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to ...@@ -102,14 +102,14 @@ statically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to
avoid the administrative overhead. For the Rx side this avoids dynamically avoid the administrative overhead. For the Rx side this avoids dynamically
allocating full-sized buffers "just in case", at the expense of a allocating full-sized buffers "just in case", at the expense of a
memory-to-memory data copy for each packet received. For most systems this memory-to-memory data copy for each packet received. For most systems this
is an good tradeoff: the Rx buffer will always be in low memory, the copy is a good tradeoff: the Rx buffer will always be in low memory, the copy
is inexpensive, and it primes the cache for later packet processing. For Tx is inexpensive, and it primes the cache for later packet processing. For Tx
the buffers are only used when needed as low-memory bounce buffers. the buffers are only used when needed as low-memory bounce buffers.
IIIB. 16M memory limitations. IIIB. 16M memory limitations.
For the ISA bus master mode all structures used directly by the LANCE, For the ISA bus master mode all structures used directly by the LANCE,
the initialization block, Rx and Tx rings, and data buffers, must be the initialization block, Rx and Tx rings, and data buffers, must be
accessable from the ISA bus, i.e. in the lower 16M of real memory. accessible from the ISA bus, i.e. in the lower 16M of real memory.
This is a problem for current Linux kernels on >16M machines. The network This is a problem for current Linux kernels on >16M machines. The network
devices are initialized after memory initialization, and the kernel doles out devices are initialized after memory initialization, and the kernel doles out
memory from the top of memory downward. The current solution is to have a memory from the top of memory downward. The current solution is to have a
...@@ -237,7 +237,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs); ...@@ -237,7 +237,7 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
/* This lance probe is unlike the other board probes in 1.0.*. The LANCE may /* This lance probe is unlike the other board probes in 1.0.*. The LANCE may
have to allocate a contiguous low-memory region for bounce buffers. have to allocate a contiguous low-memory region for bounce buffers.
This requirement is satified by having the lance initialization occur before the This requirement is satisfied by having the lance initialization occur before the
memory management system is started, and thus well before the other probes. */ memory management system is started, and thus well before the other probes. */
unsigned long lance_init(unsigned long mem_start, unsigned long mem_end) unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
{ {
...@@ -737,7 +737,7 @@ lance_interrupt(int reg_ptr) ...@@ -737,7 +737,7 @@ lance_interrupt(int reg_ptr)
lp->tx_ring[entry].base = 0; lp->tx_ring[entry].base = 0;
if (status & 0x40000000) { /* There was an major error, log it. */ if (status & 0x40000000) { /* There was a major error, log it. */
int err_status = lp->tx_ring[entry].misc; int err_status = lp->tx_ring[entry].misc;
lp->stats.tx_errors++; lp->stats.tx_errors++;
if (err_status & 0x0400) lp->stats.tx_aborted_errors++; if (err_status & 0x0400) lp->stats.tx_aborted_errors++;
...@@ -808,7 +808,7 @@ lance_rx(struct device *dev) ...@@ -808,7 +808,7 @@ lance_rx(struct device *dev)
int status = lp->rx_ring[entry].base >> 24; int status = lp->rx_ring[entry].base >> 24;
if (status != 0x03) { /* There was an error. */ if (status != 0x03) { /* There was an error. */
/* There is an tricky error noted by John Murphy, /* There is a tricky error noted by John Murphy,
<murf@perftech.com> to Russ Nelson: Even with full-sized <murf@perftech.com> to Russ Nelson: Even with full-sized
buffers it's possible for a jabber packet to use two buffers it's possible for a jabber packet to use two
buffers, with only the last correctly noting the error. */ buffers, with only the last correctly noting the error. */
......
...@@ -20,10 +20,19 @@ ...@@ -20,10 +20,19 @@
* General Public License for more details. * General Public License for more details.
* *
* $Id: aha152x.c,v 1.2 1994/07/03 12:56:36 root Exp $ * $Id: aha152x.c,v 1.4 1994/09/12 11:33:01 root Exp $
* *
* $Log: aha152x.c,v $ * $Log: aha152x.c,v $
* Revision 1.4 1994/09/12 11:33:01 root
* - irqaction to request_irq
* - abortion updated
*
* Revision 1.3 1994/08/04 13:53:05 root
* - updates for mid-level-driver changes
* - accept unexpected BUSFREE phase as error condition
* - parity check now configurable
*
* Revision 1.2 1994/07/03 12:56:36 root * Revision 1.2 1994/07/03 12:56:36 root
* - cleaned up debugging code * - cleaned up debugging code
* - more tweaking on reset delays * - more tweaking on reset delays
...@@ -133,19 +142,20 @@ ...@@ -133,19 +142,20 @@
AUTOCONF : use configuration the controller reports (only 152x) AUTOCONF : use configuration the controller reports (only 152x)
IRQ : override interrupt channel (9,10,11 or 12) (default 11) IRQ : override interrupt channel (9,10,11 or 12) (default 11)
SCSI_ID : override scsiid of AIC-6260 (0-7) (default 7) SCSI_ID : override scsiid of AIC-6260 (0-7) (default 7)
RECONNECT : override target dis-/reconnection/multiple outstanding commands RECONNECT : override target dis-/reconnection/multiple outstanding commands (default on)
PARITY : override parity check (default on)
SKIP_BIOSTEST : Don't test for BIOS signature (AHA-1510 or disabled BIOS) SKIP_BIOSTEST : Don't test for BIOS signature (AHA-1510 or disabled BIOS)
PORTBASE : Force port base. Don't try to probe PORTBASE : Force port base. Don't try to probe
LILO COMMAND LINE OPTIONS: LILO COMMAND LINE OPTIONS:
aha152x=<PORTBASE>,<IRQ>,<SCSI-ID>,<RECONNECT> aha152x=<PORTBASE>[,<IRQ>[,<SCSI-ID>[,<RECONNECT>[,<PARITY>]]]]
The normal configuration can be overridden by specifying a command line. The normal configuration can be overridden by specifying a command line.
When you do this, the BIOS test is skipped. Entered values have to be When you do this, the BIOS test is skipped. Entered values have to be
valid (known). Don't use values that aren't support under normal operation. valid (known). Don't use values that aren't support under normal operation.
If you think that you need other value: contact me. If you think that you need other values: contact me.
REFERENCES USED: REFERENCES USED:
...@@ -175,7 +185,7 @@ ...@@ -175,7 +185,7 @@
#include <asm/io.h> #include <asm/io.h>
#include "../block/blk.h" #include "../block/blk.h"
#include "scsi.h" #include "scsi.h"
#include "sd.h" /* Reqd for biosparam definition */ #include "sd.h"
#include "hosts.h" #include "hosts.h"
#include "constants.h" #include "constants.h"
#include <asm/system.h> #include <asm/system.h>
...@@ -201,6 +211,9 @@ ...@@ -201,6 +211,9 @@
#if !defined(RECONNECT) #if !defined(RECONNECT)
#error undefined RECONNECT; define AUTOCONF or RECONNECT #error undefined RECONNECT; define AUTOCONF or RECONNECT
#endif #endif
#if !defined(PARITY)
#error undefined PARITY; define AUTOCONF or PARITY
#endif
#endif #endif
/* I use this when I'm looking for weird bugs */ /* I use this when I'm looking for weird bugs */
...@@ -250,6 +263,7 @@ static char *aha152x_id = AHA152X_REVID; ...@@ -250,6 +263,7 @@ static char *aha152x_id = AHA152X_REVID;
static int port_base = 0; static int port_base = 0;
static int this_host = 0; static int this_host = 0;
static int can_disconnect = 0; static int can_disconnect = 0;
static int can_doparity = 0;
static int commands = 0; static int commands = 0;
/* set by aha152x_setup according to the command line */ /* set by aha152x_setup according to the command line */
...@@ -258,6 +272,7 @@ static int setup_portbase = 0; ...@@ -258,6 +272,7 @@ static int setup_portbase = 0;
static int setup_irq = 0; static int setup_irq = 0;
static int setup_scsiid = 0; static int setup_scsiid = 0;
static int setup_reconnect = 0; static int setup_reconnect = 0;
static int setup_doparity = 0;
static char *setup_str = (char *)NULL; static char *setup_str = (char *)NULL;
...@@ -474,13 +489,11 @@ void aha152x_setup( char *str, int *ints) ...@@ -474,13 +489,11 @@ void aha152x_setup( char *str, int *ints)
setup_called=ints[0]; setup_called=ints[0];
setup_str=str; setup_str=str;
if(ints[0] != 4) setup_portbase = ints[0] >= 1 ? ints[1] : 0x340;
return; setup_irq = ints[0] >= 2 ? ints[2] : 11;
setup_scsiid = ints[0] >= 3 ? ints[3] : 7;
setup_portbase = ints[1]; setup_reconnect = ints[0] >= 4 ? ints[4] : 1;
setup_irq = ints[2]; setup_doparity = ints[0] >= 5 ? ints[5] : 1;
setup_scsiid = ints[3];
setup_reconnect = ints[4];
} }
/* /*
...@@ -514,10 +527,10 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -514,10 +527,10 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
{ {
printk("aha152x: processing commandline: "); printk("aha152x: processing commandline: ");
if(setup_called!=4) if(setup_called>5)
{ {
printk("\naha152x: %s\n", setup_str ); printk("\naha152x: %s\n", setup_str );
printk("aha152x: usage: aha152x=<PORTBASE>,<IRQ>,<SCSI ID>,<RECONNECT>\n"); printk("aha152x: usage: aha152x=<PORTBASE>[,<IRQ>[,<SCSI ID>[,<RECONNECT>[,<PARITY>]]]]\n");
panic("aha152x panics in line %d", __LINE__); panic("aha152x panics in line %d", __LINE__);
} }
...@@ -525,6 +538,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -525,6 +538,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
interrupt_level = setup_irq; interrupt_level = setup_irq;
this_host = setup_scsiid; this_host = setup_scsiid;
can_disconnect = setup_reconnect; can_disconnect = setup_reconnect;
can_doparity = setup_doparity;
for( i=0; i<PORT_COUNT && (port_base != ports[i]); i++) for( i=0; i<PORT_COUNT && (port_base != ports[i]); i++)
; ;
...@@ -561,6 +575,12 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -561,6 +575,12 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
printk("reconnect %d should be 0 or 1\n", can_disconnect); printk("reconnect %d should be 0 or 1\n", can_disconnect);
panic("aha152x panics in line %d", __LINE__); panic("aha152x panics in line %d", __LINE__);
} }
if( (can_doparity < 0) || (can_doparity > 1) )
{
printk("parity %d should be 0 or 1\n", can_doparity);
panic("aha152x panics in line %d", __LINE__);
}
printk("ok\n"); printk("ok\n");
} }
else else
...@@ -605,6 +625,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -605,6 +625,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
interrupt_level = ints[conf.cf_irq]; interrupt_level = ints[conf.cf_irq];
this_host = conf.cf_id; this_host = conf.cf_id;
can_disconnect = conf.cf_tardisc; can_disconnect = conf.cf_tardisc;
can_doparity = !conf.cf_parity;
printk("auto configuration: ok, "); printk("auto configuration: ok, ");
...@@ -621,6 +642,10 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -621,6 +642,10 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
#if defined(RECONNECT) #if defined(RECONNECT)
can_disconnect=RECONNECT; can_disconnect=RECONNECT;
#endif #endif
#if defined(PARITY)
can_doparity=PARITY;
#endif
} }
printk("detection complete\n"); printk("detection complete\n");
...@@ -661,8 +686,12 @@ int aha152x_detect(Scsi_Host_Template * tpnt) ...@@ -661,8 +686,12 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
aha152x_reset(NULL); aha152x_reset(NULL);
printk("aha152x: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d, reconnect=%s, parity=enabled\n", printk("aha152x: vital data: PORTBASE=0x%03x, IRQ=%d, SCSI ID=%d, reconnect=%s, parity=%s\n",
port_base, interrupt_level, this_host, can_disconnect ? "enabled" : "disabled" ); port_base,
interrupt_level,
this_host,
can_disconnect ? "enabled" : "disabled",
can_doparity ? "enabled" : "disabled");
snarf_region(port_base, TEST-SCSISEQ); /* Register */ snarf_region(port_base, TEST-SCSISEQ); /* Register */
...@@ -809,7 +838,10 @@ int aha152x_abort( Scsi_Cmnd *SCpnt) ...@@ -809,7 +838,10 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
return SCSI_ABORT_SUCCESS; return SCSI_ABORT_SUCCESS;
} }
if (current_SC) if (!current_SC && TESTLO(SSTAT1, BUSFREE))
printk("bus busy w/o current command, ");
if (current_SC==SCpnt)
if( TESTLO(SSTAT1, BUSFREE) ) { if( TESTLO(SSTAT1, BUSFREE) ) {
/* fail abortion, if current command is on the bus */ /* fail abortion, if current command is on the bus */
sti(); sti();
...@@ -831,10 +863,8 @@ int aha152x_abort( Scsi_Cmnd *SCpnt) ...@@ -831,10 +863,8 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble) prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
; ;
if(ptr && TESTLO(SSTAT1, BUSFREE) ) if(ptr)
printk("bus busy but no current command, "); if( TESTHI(SSTAT1, BUSFREE) )
if(ptr && TESTHI(SSTAT1, BUSFREE) )
{ {
/* dequeue */ /* dequeue */
if(prev) if(prev)
...@@ -863,10 +893,14 @@ int aha152x_abort( Scsi_Cmnd *SCpnt) ...@@ -863,10 +893,14 @@ int aha152x_abort( Scsi_Cmnd *SCpnt)
sleep_on( &abortion_complete ); sleep_on( &abortion_complete );
return abort_result; return abort_result;
} }
else else {
printk("aha152x: bus busy but no current command\n"); /* fail abortion, if we can't abort the disconnected command */
sti();
return SCSI_ABORT_BUSY;
}
/* command wasn't found */ /* command wasn't found */
printk("command not found\n");
sti(); sti();
return SCSI_ABORT_NOT_RUNNING; return SCSI_ABORT_NOT_RUNNING;
} }
...@@ -1189,7 +1223,7 @@ void aha152x_intr( int irqno ) ...@@ -1189,7 +1223,7 @@ void aha152x_intr( int irqno )
sti(); sti();
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENPHASEMIS ); SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
#if defined(DEBUG_RACE) #if defined(DEBUG_RACE)
leave_driver("(reselected) intr"); leave_driver("(reselected) intr");
#endif #endif
...@@ -1221,7 +1255,7 @@ void aha152x_intr( int irqno ) ...@@ -1221,7 +1255,7 @@ void aha152x_intr( int irqno )
SETPORT( SCSIID, (this_host << OID_) | current_SC->target ); SETPORT( SCSIID, (this_host << OID_) | current_SC->target );
/* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */ /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
SETPORT( SXFRCTL1, ENSPCHK|ENSTIMER); SETPORT( SXFRCTL1, can_doparity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
/* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) ); SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) );
...@@ -1305,7 +1339,7 @@ void aha152x_intr( int irqno ) ...@@ -1305,7 +1339,7 @@ void aha152x_intr( int irqno )
SETPORT( SCSISIG, P_MSGO ); SETPORT( SCSISIG, P_MSGO );
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENREQINIT ); SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
SETBITS( DMACNTRL0, INTEN); SETBITS( DMACNTRL0, INTEN);
return; return;
} }
...@@ -1397,7 +1431,7 @@ void aha152x_intr( int irqno ) ...@@ -1397,7 +1431,7 @@ void aha152x_intr( int irqno )
CLRBITS( SXFRCTL0, ENDMA); CLRBITS( SXFRCTL0, ENDMA);
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT ); SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE );
/* wait for data latch to become ready or a phase change */ /* wait for data latch to become ready or a phase change */
while( TESTLO( DMASTAT, INTSTAT ) ) while( TESTLO( DMASTAT, INTSTAT ) )
...@@ -1456,7 +1490,7 @@ void aha152x_intr( int irqno ) ...@@ -1456,7 +1490,7 @@ void aha152x_intr( int irqno )
/* missing phase raises INTSTAT */ /* missing phase raises INTSTAT */
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENPHASEMIS ); SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
#if defined(DEBUG_CMD) #if defined(DEBUG_CMD)
printk("waiting, "); printk("waiting, ");
...@@ -1673,7 +1707,7 @@ void aha152x_intr( int irqno ) ...@@ -1673,7 +1707,7 @@ void aha152x_intr( int irqno )
SETPORT( SXFRCTL0, CH1); SETPORT( SXFRCTL0, CH1);
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENREQINIT ); SETPORT( SIMODE1, ENREQINIT|ENBUSFREE );
if( TESTHI( SSTAT1, PHASEMIS ) ) if( TESTHI( SSTAT1, PHASEMIS ) )
printk("aha152x: passing STATUS phase"); printk("aha152x: passing STATUS phase");
...@@ -1870,7 +1904,7 @@ void aha152x_intr( int irqno ) ...@@ -1870,7 +1904,7 @@ void aha152x_intr( int irqno )
SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1); SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENPHASEMIS ); SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
/* while current buffer is not empty or /* while current buffer is not empty or
there are more buffers to transfer */ there are more buffers to transfer */
...@@ -2027,7 +2061,7 @@ void aha152x_intr( int irqno ) ...@@ -2027,7 +2061,7 @@ void aha152x_intr( int irqno )
SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 ); SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 );
SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0); SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);
SETPORT( SCSISEQ, disconnected_SC ? ENRESELI : 0 ); SETPORT(SCSISEQ, disconnected_SC ? ENRESELI : 0 );
SETBITS( DMACNTRL0, INTEN ); SETBITS( DMACNTRL0, INTEN );
...@@ -2046,7 +2080,7 @@ void aha152x_intr( int irqno ) ...@@ -2046,7 +2080,7 @@ void aha152x_intr( int irqno )
current_SC->SCp.phase |= 1<<16 ; current_SC->SCp.phase |= 1<<16 ;
SETPORT( SIMODE0, 0 ); SETPORT( SIMODE0, 0 );
SETPORT( SIMODE1, ENPHASEMIS ); SETPORT( SIMODE1, ENPHASEMIS|ENBUSFREE );
#if defined(DEBUG_INTR) #if defined(DEBUG_INTR)
disp_enintr(); disp_enintr();
#endif #endif
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define _AHA152X_H #define _AHA152X_H
/* /*
* $Id: aha152x.h,v 1.2 1994/07/03 13:01:47 root Exp $ * $Id: aha152x.h,v 1.4 1994/09/12 11:32:41 root Exp $
*/ */
#include "../block/blk.h" #include "../block/blk.h"
...@@ -22,7 +22,7 @@ int aha152x_biosparam(Disk *, int, int*); ...@@ -22,7 +22,7 @@ int aha152x_biosparam(Disk *, int, int*);
(unless we support more than 1 cmd_per_lun this should do) */ (unless we support more than 1 cmd_per_lun this should do) */
#define AHA152X_MAXQUEUE 7 #define AHA152X_MAXQUEUE 7
#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.2 $" #define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.4 $"
/* Initial value of Scsi_Host entry */ /* Initial value of Scsi_Host entry */
#define AHA152X { /* next */ NULL, \ #define AHA152X { /* next */ NULL, \
......
...@@ -260,11 +260,9 @@ static inline void borken_wait(void) { ...@@ -260,11 +260,9 @@ static inline void borken_wait(void) {
register int count; register int count;
for (count = borken_calibration; count && (STATUS & STAT_REQ); for (count = borken_calibration; count && (STATUS & STAT_REQ);
--count); --count);
if (count)
#if (DEBUG & DEBUG_BORKEN) #if (DEBUG & DEBUG_BORKEN)
if (count)
printk("scsi%d : borken timeout\n", hostno); printk("scsi%d : borken timeout\n", hostno);
#else
;
#endif #endif
} }
......
...@@ -19,7 +19,7 @@ extern int *blksize_size[]; ...@@ -19,7 +19,7 @@ extern int *blksize_size[];
int block_write(struct inode * inode, struct file * filp, char * buf, int count) int block_write(struct inode * inode, struct file * filp, char * buf, int count)
{ {
int blocksize, blocksize_bits, i, j; int blocksize, blocksize_bits, i, j, buffercount,write_error;
int block, blocks; int block, blocks;
loff_t offset; loff_t offset;
int chars; int chars;
...@@ -29,9 +29,10 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -29,9 +29,10 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
int blocks_per_cluster; int blocks_per_cluster;
unsigned int size; unsigned int size;
unsigned int dev; unsigned int dev;
struct buffer_head * bh; struct buffer_head * bh, *bufferlist[NBUF];
register char * p; register char * p;
write_error = buffercount = 0;
dev = inode->i_rdev; dev = inode->i_rdev;
if ( is_read_only( inode->i_rdev )) if ( is_read_only( inode->i_rdev ))
return -EPERM; return -EPERM;
...@@ -118,13 +119,35 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count) ...@@ -118,13 +119,35 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
buf += chars; buf += chars;
bh->b_uptodate = 1; bh->b_uptodate = 1;
mark_buffer_dirty(bh, 0); mark_buffer_dirty(bh, 0);
if (filp->f_flags & O_SYNC) { if (filp->f_flags & O_SYNC)
ll_rw_block(WRITE, 1, &bh); bufferlist[buffercount++] = bh;
wait_on_buffer(bh); else
}
brelse(bh); brelse(bh);
if (buffercount == NBUF){
ll_rw_block(WRITE, buffercount, bufferlist);
for(i=0; i<buffercount; i++){
wait_on_buffer(bufferlist[i]);
if (!bufferlist[i]->b_uptodate)
write_error=1;
brelse(bufferlist[i]);
}
buffercount=0;
}
if(write_error)
break;
}
if ( buffercount ){
ll_rw_block(WRITE, buffercount, bufferlist);
for(i=0; i<buffercount; i++){
wait_on_buffer(bufferlist[i]);
if (!bufferlist[i]->b_uptodate)
write_error=1;
brelse(bufferlist[i]);
}
} }
filp->f_reada = 1; filp->f_reada = 1;
if(write_error)
return -EIO;
return written; return written;
} }
......
...@@ -4,13 +4,15 @@ ...@@ -4,13 +4,15 @@
* Provide support for fcntl()'s F_GETLK, F_SETLK, and F_SETLKW calls. * Provide support for fcntl()'s F_GETLK, F_SETLK, and F_SETLKW calls.
* Doug Evans, 92Aug07, dje@sspiff.uucp. * Doug Evans, 92Aug07, dje@sspiff.uucp.
* *
* FIXME: two things aren't handled yet: * Deadlock Detection added by Kelly Carmichael, kelly@[142.24.8.65]
* - deadlock detection/avoidance (of dubious merit, but since it's in * September 17, 1994.
* the definition, I guess it should be provided eventually) *
* FIXME: one thing isn't handled yet:
* - mandatory locks (requires lots of changes elsewhere) * - mandatory locks (requires lots of changes elsewhere)
* *
* Edited by Kai Petzke, wpp@marie.physik.tu-berlin.de * Edited by Kai Petzke, wpp@marie.physik.tu-berlin.de
*/ */
#define DEADLOCK_DETECTION
#include <asm/segment.h> #include <asm/segment.h>
...@@ -30,6 +32,9 @@ static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd) ...@@ -30,6 +32,9 @@ static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd)
static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl, static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl,
unsigned int fd); unsigned int fd);
static void free_lock(struct file_lock **fl); static void free_lock(struct file_lock **fl);
#ifdef DEADLOCK_DETECTION
int locks_deadlocked(int my_pid,int blocked_pid);
#endif
static struct file_lock file_lock_table[NR_FILE_LOCKS]; static struct file_lock file_lock_table[NR_FILE_LOCKS];
static struct file_lock *file_lock_free_list; static struct file_lock *file_lock_free_list;
...@@ -145,11 +150,13 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) ...@@ -145,11 +150,13 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
/* /*
* File is locked by another process. If this is * File is locked by another process. If this is
* F_SETLKW wait for the lock to be released. * F_SETLKW wait for the lock to be released.
* FIXME: We need to check for deadlocks here.
*/ */
if (cmd == F_SETLKW) { if (cmd == F_SETLKW) {
if (current->signal & ~current->blocked) if (current->signal & ~current->blocked)
return -ERESTARTSYS; return -ERESTARTSYS;
#ifdef DEADLOCK_DETECTION
if (locks_deadlocked(file_lock.fl_owner->pid,fl->fl_owner->pid)) return -EDEADLOCK;
#endif
interruptible_sleep_on(&fl->fl_wait); interruptible_sleep_on(&fl->fl_wait);
if (current->signal & ~current->blocked) if (current->signal & ~current->blocked)
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -166,6 +173,36 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) ...@@ -166,6 +173,36 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
return lock_it(filp, &file_lock, fd); return lock_it(filp, &file_lock, fd);
} }
#ifdef DEADLOCK_DETECTION
/*
* This function tests for deadlock condition before putting a process to sleep
* this detection scheme is recursive... we may need some test as to make it
* exit if the function gets stuck due to bad lock data.
*/
int locks_deadlocked(int my_pid,int blocked_pid)
{
int ret_val;
struct wait_queue *dlock_wait;
struct file_lock *fl;
for (fl = &file_lock_table[0]; fl < file_lock_table + NR_FILE_LOCKS - 1; fl++) {
if (fl->fl_owner == NULL) continue; /* not a used lock */
if (fl->fl_owner->pid != my_pid) continue;
if (fl->fl_wait == NULL) continue; /* no queues */
dlock_wait = fl->fl_wait;
do {
if (dlock_wait->task != NULL) {
if (dlock_wait->task->pid == blocked_pid) return -EDEADLOCK;
ret_val = locks_deadlocked(dlock_wait->task->pid,blocked_pid);
if (ret_val) return -EDEADLOCK;
}
dlock_wait = dlock_wait->next;
} while (dlock_wait != fl->fl_wait);
}
return 0;
}
#endif
/* /*
* This function is called when the file is closed. * This function is called when the file is closed.
*/ */
......
...@@ -482,7 +482,7 @@ __asm__("cld\n\t" \ ...@@ -482,7 +482,7 @@ __asm__("cld\n\t" \
#define memset(s, c, count) \ #define memset(s, c, count) \
(__builtin_constant_p(c) ? \ (__builtin_constant_p(c) ? \
__constant_c_x_memset((s),(0x01010101*(unsigned char)c),(count)) : \ __constant_c_x_memset((s),(0x01010101UL*(unsigned char)c),(count)) : \
__memset((s),(c),(count))) __memset((s),(c),(count)))
/* /*
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#define FDGETDRVSTAT 22 /* get drive state */ #define FDGETDRVSTAT 22 /* get drive state */
#define FDPOLLDRVSTAT 23 /* get drive state */ #define FDPOLLDRVSTAT 23 /* get drive state */
#define FDGETFDCSTAT 25 /* get fdc state */ #define FDGETFDCSTAT 25 /* get fdc state */
#define FDWERRORCLR 27 /* clear write error and badness information */
#define FDWERRORGET 28 /* get write error and badness information */
#define FDRESET 24 /* reset FDC */ #define FDRESET 24 /* reset FDC */
#define FD_RESET_IF_NEEDED 0 #define FD_RESET_IF_NEEDED 0
...@@ -51,7 +53,7 @@ ...@@ -51,7 +53,7 @@
#define FD_2M 0x4 #define FD_2M 0x4
#define FD_SIZECODEMASK 0x38 #define FD_SIZECODEMASK 0x38
#define FD_SIZECODE(floppy) (((( (floppy)->rate ) & FD_SIZECODEMASK) >> 3)+ 2) #define FD_SIZECODE(floppy) (((((floppy)->rate&FD_SIZECODEMASK)>> 3)+ 2) %8)
#define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \ #define FD_SECTSIZE(floppy) ( (floppy)->rate & FD_2M ? \
512 : 128 << FD_SIZECODE(floppy) ) 512 : 128 << FD_SIZECODE(floppy) )
#define FD_PERP 0x40 #define FD_PERP 0x40
...@@ -170,6 +172,27 @@ struct floppy_drive_struct { ...@@ -170,6 +172,27 @@ struct floppy_drive_struct {
int fd_device; int fd_device;
int last_checked; /* when was the drive last checked for a disk change? */ int last_checked; /* when was the drive last checked for a disk change? */
};
struct floppy_write_errors {
/* Write error logging.
*
* These fields can be cleared with the FDWERRORCLR ioctl.
* Only writes that were attempted but failed due to a physical media
* error are logged. write(2) calls that fail and return an error code
* to the user process are not counted.
*/
unsigned int write_errors; /* number of physical write errors encountered */
/* position of first and last write errors */
unsigned long first_error_sector;
int first_error_generation;
unsigned long last_error_sector;
int last_error_generation;
unsigned int badness; /* highest retry count for a read or write operation */
}; };
struct floppy_fdc_state { struct floppy_fdc_state {
......
...@@ -428,6 +428,13 @@ void merge_segments(struct vm_area_struct *mpnt) ...@@ -428,6 +428,13 @@ void merge_segments(struct vm_area_struct *mpnt)
*/ */
prev->vm_end = mpnt->vm_end; prev->vm_end = mpnt->vm_end;
prev->vm_next = mpnt->vm_next; prev->vm_next = mpnt->vm_next;
if (mpnt->vm_ops && mpnt->vm_ops->close) {
mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start;
mpnt->vm_start = mpnt->vm_end;
mpnt->vm_ops->close(mpnt);
}
if (mpnt->vm_inode)
mpnt->vm_inode->i_count--;
kfree_s(mpnt, sizeof(*mpnt)); kfree_s(mpnt, sizeof(*mpnt));
mpnt = prev; mpnt = prev;
} }
......
...@@ -107,17 +107,32 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma, ...@@ -107,17 +107,32 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma,
unsigned long start, unsigned long end, unsigned long start, unsigned long end,
int newflags, int prot) int newflags, int prot)
{ {
int error; struct vm_area_struct * left, * right;
unsigned long tmpflags, tmpprot;
tmpflags = vma->vm_flags; left = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
tmpprot = vma->vm_page_prot; if (!left)
return -ENOMEM;
right = (struct vm_area_struct *) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
if (!right) {
kfree(left);
return -ENOMEM;
}
*left = *vma;
*right = *vma;
left->vm_end = start;
vma->vm_start = start;
vma->vm_end = end;
right->vm_start = end;
vma->vm_offset += vma->vm_start - left->vm_start;
right->vm_offset += right->vm_start - left->vm_start;
vma->vm_flags = newflags; vma->vm_flags = newflags;
vma->vm_page_prot = prot; vma->vm_page_prot = prot;
error = mprotect_fixup_end(vma, end, tmpflags, tmpprot); if (vma->vm_inode)
if (!error) vma->vm_inode->i_count += 2;
error = mprotect_fixup_start(vma, start, tmpflags, tmpprot); insert_vm_struct(current, left);
return error; insert_vm_struct(current, right);
merge_segments(current->mm->mmap);
return 0;
} }
static int mprotect_fixup(struct vm_area_struct * vma, static int mprotect_fixup(struct vm_area_struct * vma,
...@@ -155,7 +170,7 @@ static int mprotect_fixup(struct vm_area_struct * vma, ...@@ -155,7 +170,7 @@ static int mprotect_fixup(struct vm_area_struct * vma,
asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot) asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot)
{ {
unsigned long end; unsigned long end, tmp;
struct vm_area_struct * vma; struct vm_area_struct * vma;
if (start & ~PAGE_MASK) if (start & ~PAGE_MASK)
...@@ -188,12 +203,15 @@ asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot) ...@@ -188,12 +203,15 @@ asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot)
if (vma->vm_end >= end) if (vma->vm_end >= end)
return mprotect_fixup(vma, start, end, newflags); return mprotect_fixup(vma, start, end, newflags);
error = mprotect_fixup(vma, start, vma->vm_end, newflags); tmp = vma->vm_end;
error = mprotect_fixup(vma, start, tmp, newflags);
if (error) if (error)
return error; return error;
start = vma->vm_end; start = tmp;
if (vma->vm_end <= start) {
vma = vma->vm_next; vma = vma->vm_next;
if (!vma || vma->vm_start != start) if (!vma || vma->vm_start != start)
return -EFAULT; return -EFAULT;
} }
}
} }
...@@ -74,28 +74,6 @@ struct rarp_table ...@@ -74,28 +74,6 @@ struct rarp_table
struct rarp_table *rarp_tables = NULL; struct rarp_table *rarp_tables = NULL;
/*
* This structure defines an ethernet arp header, which is the same header
* that is used for rarp.
*/
struct arphdr
{
unsigned short ar_hrd; /* format of hardware address */
unsigned short ar_pro; /* format of protocol address */
unsigned char ar_hln; /* length of hardware address */
unsigned char ar_pln; /* length of protocol address */
unsigned short ar_op; /* ARP opcode (command) */
#if 0
/*
* Ethernet looks like this : This bit is variable sized however...
*/
unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
unsigned char ar_sip[4]; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
unsigned char ar_tip[4]; /* target IP address */
#endif
};
static struct packet_type rarp_packet_type = static struct packet_type rarp_packet_type =
{ {
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
* Matt Dillon : More TCP improvements and RST bug fixes * Matt Dillon : More TCP improvements and RST bug fixes
* Matt Dillon : Yet more small nasties remove from the TCP code * Matt Dillon : Yet more small nasties remove from the TCP code
* (Be very nice to this man if tcp finally works 100%) 8) * (Be very nice to this man if tcp finally works 100%) 8)
* Alan Cox : BSD accept sematics. * Alan Cox : BSD accept semantics.
* *
* *
* To Fix: * To Fix:
......
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