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

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