patch-2.0.36 linux/drivers/scsi/in2000.c
Next file: linux/drivers/scsi/in2000.h
Previous file: linux/drivers/scsi/hosts.c
Back to the patch index
Back to the overall index
- Lines: 337
- Date:
Sun Nov 15 10:33:09 1998
- Orig file:
v2.0.35/linux/drivers/scsi/in2000.c
- Orig date:
Mon Jul 13 13:46:35 1998
diff -u --recursive --new-file v2.0.35/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
@@ -122,28 +122,12 @@
#include "sd.h"
#include "hosts.h"
-
-#define IN2000_VERSION "1.32"
-#define IN2000_DATE "28/March/1998"
-
-/*
- * Note - the following defines have been moved to 'in2000.h':
- *
- * PROC_INTERFACE
- * PROC_STATISTICS
- * SYNC_DEBUG
- * DEBUGGING_ON
- * DEBUG_DEFAULTS
- * FAST_READ_IO
- * FAST_WRITE_IO
- *
- */
-
+#define IN2000_VERSION "1.33"
+#define IN2000_DATE "26/August/1998"
#include "in2000.h"
-
/*
* 'setup_strings' is a single string used to pass operating parameters and
* settings from the kernel/module command-line to the driver. 'setup_args[]'
@@ -403,6 +387,10 @@
cmd->SCp.Status = ILLEGAL_STATUS_BYTE;
+/* We need to disable interrupts before messing with the input
+ * queue and calling in2000_execute().
+ */
+
save_flags(flags);
cli();
@@ -442,20 +430,19 @@
* already connected, we give up immediately. Otherwise, look through
* the input_Q, using the first command we find that's intended
* for a currently non-busy target/lun.
+ * Note that this function is always called with interrupts already
+ * disabled (either from in2000_queuecommand() or in2000_intr()).
*/
static void in2000_execute (struct Scsi_Host *instance)
{
struct IN2000_hostdata *hostdata;
Scsi_Cmnd *cmd, *prev;
-unsigned long flags;
int i;
unsigned short *sp;
unsigned short f;
unsigned short flushbuf[16];
- save_flags(flags);
- cli();
hostdata = (struct IN2000_hostdata *)instance->hostdata;
DB(DB_EXECUTE,printk("EX("))
@@ -464,7 +451,6 @@
DB(DB_EXECUTE,printk(")EX-0 "))
- restore_flags(flags);
return;
}
@@ -488,7 +474,6 @@
DB(DB_EXECUTE,printk(")EX-1 "))
- restore_flags(flags);
return;
}
@@ -716,7 +701,6 @@
DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
- restore_flags(flags);
}
@@ -841,15 +825,10 @@
}
-/* It appears that the Linux interrupt dispatcher calls this
- * function in a non-reentrant fashion. What that means to us
- * is that we can use an SA_INTERRUPT type of interrupt (which
- * is faster), and do an sti() right away to let timer, serial,
- * etc. ints happen.
- *
- * WHOA! Wait a minute, pardner! Does this hold when more than
- * one card has been detected?? I doubt it. Maybe better
- * re-think the multiple card capability....
+/* We need to use spin_lock_irqsave() & spin_unlock_irqrestore() in this
+ * function in order to work in an SMP environment. (I'd be surprised
+ * if the driver is ever used by anyone on a real multi-CPU motherboard,
+ * but it _does_ need to be able to compile and run in an SMP kernel.)
*/
static void in2000_intr (int irqnum, void * dev_id, struct pt_regs *ptregs)
@@ -857,12 +836,12 @@
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata;
Scsi_Cmnd *patch, *cmd;
-unsigned long flags;
uchar asr, sr, phs, id, lun, *ucp, msg;
int i,j;
unsigned long length;
unsigned short *sp;
unsigned short f;
+unsigned long flags;
for (instance = instance_list; instance; instance = instance->next) {
if (instance->irq == irqnum)
@@ -874,10 +853,9 @@
}
hostdata = (struct IN2000_hostdata *)instance->hostdata;
-/* OK - it should now be safe to re-enable system interrupts */
+/* Get the spin_lock and disable further ints, for SMP */
- save_flags(flags);
- sti();
+ CLISPIN_LOCK(flags);
#ifdef PROC_STATISTICS
hostdata->int_cnt++;
@@ -1013,7 +991,9 @@
}
write1_io(0, IO_LED_OFF);
- restore_flags(flags);
+
+/* release the SMP spin_lock and restore irq state */
+ CLISPIN_UNLOCK(flags);
return;
}
@@ -1029,7 +1009,9 @@
if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) {
printk("\nNR:wd-intr-1\n");
write1_io(0, IO_LED_OFF);
- restore_flags(flags);
+
+/* release the SMP spin_lock and restore irq state */
+ CLISPIN_UNLOCK(flags);
return;
}
@@ -1095,7 +1077,6 @@
case CSR_TIMEOUT:
DB(DB_INTR,printk("TIMEOUT"))
- cli();
if (hostdata->state == S_RUNNING_LEVEL2)
hostdata->connected = NULL;
else {
@@ -1113,7 +1094,6 @@
* are commands waiting to be executed.
*/
- sti();
in2000_execute(instance);
break;
@@ -1121,7 +1101,6 @@
/* Note: this interrupt should not occur in a LEVEL2 command */
case CSR_SELECT:
- cli();
DB(DB_INTR,printk("SELECT"))
hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
CHECK_NULL(cmd,"csr_select")
@@ -1211,7 +1190,6 @@
case CSR_SRV_REQ |PHS_MESS_IN:
DB(DB_INTR,printk("MSG_IN="))
- cli();
msg = read_1_byte(hostdata);
sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */
@@ -1360,7 +1338,6 @@
/* Note: this interrupt will occur only after a LEVEL2 command */
case CSR_SEL_XFER_DONE:
- cli();
/* Make sure that reselection is enabled at this point - it may
* have been turned off for the command that just completed.
@@ -1387,7 +1364,6 @@
* there are commands waiting to be executed.
*/
- sti();
in2000_execute(instance);
}
else {
@@ -1446,7 +1422,6 @@
* so we treat it as a normal command-complete-disconnect.
*/
- cli();
/* Make sure that reselection is enabled at this point - it may
* have been turned off for the command that just completed.
@@ -1456,6 +1431,9 @@
if (cmd == NULL) {
printk(" - Already disconnected! ");
hostdata->state = S_UNCONNECTED;
+
+/* release the SMP spin_lock and restore irq state */
+ CLISPIN_UNLOCK(flags);
return;
}
DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
@@ -1472,13 +1450,11 @@
* there are commands waiting to be executed.
*/
- sti();
in2000_execute(instance);
break;
case CSR_DISC:
- cli();
/* Make sure that reselection is enabled at this point - it may
* have been turned off for the command that just completed.
@@ -1523,7 +1499,6 @@
* there are commands waiting to be executed.
*/
- sti();
in2000_execute(instance);
break;
@@ -1531,8 +1506,6 @@
case CSR_RESEL_AM:
DB(DB_INTR,printk("RESEL"))
- cli();
-
/* First we have to make sure this reselection didn't */
/* happen during Arbitration/Selection of some other device. */
/* If yes, put losing command back on top of input_Q. */
@@ -1632,10 +1605,12 @@
}
write1_io(0, IO_LED_OFF);
- restore_flags(flags);
DB(DB_INTR,printk("} "))
+/* release the SMP spin_lock and restore irq state */
+ CLISPIN_UNLOCK(flags);
+
}
@@ -1823,7 +1798,6 @@
cmd->result = DID_ABORT << 16;
cmd->scsi_done(cmd);
-/* sti();*/
in2000_execute (instance);
restore_flags(flags);
@@ -1854,7 +1828,6 @@
* broke.
*/
-/* sti();*/
in2000_execute (instance);
restore_flags(flags);
@@ -1872,7 +1845,7 @@
static char setup_used[MAX_SETUP_ARGS];
static int done_setup = 0;
-void in2000_setup (char *str, int *ints)
+in2000__INITFUNC( void in2000_setup (char *str, int *ints) )
{
int i;
char *p1,*p2;
@@ -1904,7 +1877,7 @@
/* check_setup_args() returns index if key found, 0 if not
*/
-static int check_setup_args(char *key, int *flags, int *val, char *buf)
+in2000__INITFUNC( static int check_setup_args(char *key, int *flags, int *val, char *buf) )
{
int x;
char *cp;
@@ -1936,21 +1909,21 @@
* special macros declared in 'asm/io.h'. We use readb() and readl()
* when reading from the card's BIOS area in in2000_detect().
*/
-static const unsigned int *bios_tab[] = {
+static const unsigned int *bios_tab[] in2000__INITDATA = {
(unsigned int *)0xc8000,
(unsigned int *)0xd0000,
(unsigned int *)0xd8000,
0
};
-static const unsigned short base_tab[] = {
+static const unsigned short base_tab[] in2000__INITDATA = {
0x220,
0x200,
0x110,
0x100,
};
-static const int int_tab[] = {
+static const int int_tab[] in2000__INITDATA = {
15,
14,
11,
@@ -1958,7 +1931,7 @@
};
-int in2000_detect(Scsi_Host_Template * tpnt)
+in2000__INITFUNC( int in2000_detect(Scsi_Host_Template * tpnt) )
{
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov