patch-2.4.9 linux/drivers/scsi/cpqfcTSinit.c

Next file: linux/drivers/scsi/cpqfcTSstructs.h
Previous file: linux/drivers/scsi/cpqfc.Readme
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.8/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c
@@ -41,7 +41,9 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>  // request_region() prototype
 #include <linux/vmalloc.h> // ioremap()
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
 #include <linux/completion.h>
+#endif
 #ifdef __alpha__
 #define __KERNEL_SYSCALLS__
 #endif
@@ -55,6 +57,7 @@
 #include "hosts.h"
 #include "cpqfcTSchip.h"
 #include "cpqfcTSstructs.h"
+#include "cpqfcTStrigger.h"
 
 #include "cpqfcTS.h"
 
@@ -88,7 +91,17 @@
 
 #endif
 
-
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
+#  define CPQFC_DECLARE_COMPLETION(x) DECLARE_COMPLETION(x)
+#  define CPQFC_WAITING waiting
+#  define CPQFC_COMPLETE(x) complete(x)
+#  define CPQFC_WAIT_FOR_COMPLETION(x) wait_for_completion(x);
+#else
+#  define CPQFC_DECLARE_COMPLETION(x) DECLARE_MUTEX_LOCKED(x)
+#  define CPQFC_WAITING sem
+#  define CPQFC_COMPLETE(x) up(x)
+#  define CPQFC_WAIT_FOR_COMPLETION(x) down(x)
+#endif
 
 /* local function to load our per-HBA (local) data for chip
    registers, FC link state, all FC exchanges, etc.
@@ -227,6 +240,8 @@
              
   cpqfcHBAdata->notify_wt = &sem;
 
+  /* must unlock before kernel_thread(), for it may cause a reschedule. */
+  spin_unlock_irq(&io_request_lock);
   kernel_thread((int (*)(void *))cpqfcTSWorkerThread, 
                           (void *) HostAdapter, 0);
   /*
@@ -234,6 +249,7 @@
 
    */
   down (&sem);
+  spin_lock_irq(&io_request_lock);
   cpqfcHBAdata->notify_wt = NULL;
 
   LEAVE("launch_FC_worker_thread");
@@ -417,13 +433,14 @@
 	// 3.028     LILP received, link up, FLOGI starts
 	// slowest(worst) case, measured on 1Gb Finisar GT analyzer
 	
-	int wait_time;
-	unsigned long flags=0;
- 
-        spin_unlock_irqrestore(&io_request_lock, flags);
-        for( wait_time = jiffies + 4*HZ; wait_time > jiffies; )
-	  schedule();  // (our worker task needs to run)
-	spin_lock_irqsave(&io_request_lock, flags);
+	unsigned long stop_time;
+
+        spin_unlock_irq(&io_request_lock);
+	stop_time = jiffies + 4*HZ;
+        while ( time_before(jiffies, stop_time) ) 
+	  	schedule();  // (our worker task needs to run)
+
+	spin_lock_irq(&io_request_lock);
       }
       
       NumberOfAdapters++; 
@@ -435,7 +452,6 @@
   return NumberOfAdapters;
 }
 
-
 static void my_ioctl_done (Scsi_Cmnd * SCpnt)
 {
     struct request * req;
@@ -443,9 +459,8 @@
     req = &SCpnt->request;
     req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
   
-    if (req->waiting != NULL) {
-	complete(req->waiting);
-    }
+    if (req->CPQFC_WAITING != NULL)
+	CPQFC_COMPLETE(req->CPQFC_WAITING);
 }   
 
 
@@ -463,7 +478,6 @@
   cpqfc_passthru_t *vendor_cmd;
   Scsi_Device *SDpnt;
   Scsi_Cmnd *ScsiPassThruCmnd;
-  unsigned long flags;
 
   ENTER("cpqfcTS_ioctl ");
   
@@ -560,30 +574,25 @@
         ScsiPassThruCmnd->SCp.phase = vendor_cmd->bus;
 	ScsiPassThruCmnd->SCp.have_data_in = vendor_cmd->pdrive;
 
-
-
         // We copy the scheme used by scsi.c to submit commands
 	// to our own HBA.  We do this in order to stall the
 	// thread calling the IOCTL until it completes, and use
 	// the same "_quecommand" function for synchronizing
 	// FC Link events with our "worker thread".
-	
-        spin_lock_irqsave(&io_request_lock, flags);
+
         {
-          DECLARE_COMPLETION(wait);
-          ScsiPassThruCmnd->request.waiting = &wait;
+          CPQFC_DECLARE_COMPLETION(wait);
+          ScsiPassThruCmnd->request.CPQFC_WAITING = &wait;
           // eventually gets us to our own _quecommand routine
           scsi_do_cmd( ScsiPassThruCmnd, &vendor_cmd->cdb[0], 
 	       buf, 
 	       vendor_cmd->len, 
 	       my_ioctl_done, 
 	       10*HZ, 1);// timeout,retries
-          spin_unlock_irqrestore(&io_request_lock, flags);
           // Other I/Os can now resume; we wait for our ioctl
 	  // command to complete
-	  wait_for_completion(&wait);
-          spin_lock_irqsave(&io_request_lock, flags);
-          ScsiPassThruCmnd->request.waiting = NULL;
+	  CPQFC_WAIT_FOR_COMPLETION(&wait);
+          ScsiPassThruCmnd->request.CPQFC_WAITING = NULL;
         }
 	
         result = ScsiPassThruCmnd->result;
@@ -603,7 +612,6 @@
         //  (*SDpnt->scsi_request_fn)();
 
         wake_up(&SDpnt->scpnt_wait);
-        spin_unlock_irqrestore(&io_request_lock, flags);
 
 	// need to pass data back to user (space)?
 	if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) &&
@@ -613,7 +621,7 @@
 
         if( buf) 
 	  kfree( buf);
-	
+
         return result;
       }
       
@@ -1262,6 +1270,11 @@
 //    printk(" @Q bad targ cmnd %p@ ", Cmnd);
       QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
     }
+    else if (Cmnd->lun >= CPQFCTS_MAX_LUN)
+    {
+      printk(KERN_WARNING "cpqfc: Invalid LUN: %d\n", Cmnd->lun);
+      QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
+    } 
 
     else  // we know what FC device to send to...
     {
@@ -1486,7 +1499,6 @@
   int timeout = 10*HZ;
   int retries = 1;
   char scsi_cdb[12];
-  unsigned long flags;
   int result;
   Scsi_Cmnd * SCpnt;
   Scsi_Device * SDpnt;
@@ -1500,21 +1512,17 @@
 
   scsi_cdb[0] = RELEASE;
 
-  spin_lock_irqsave(&io_request_lock, flags);
-
   // allocate with wait = true, interruptible = false 
   SCpnt = scsi_allocate_device(ScsiDev, 1, 0);
   {
-    DECLARE_COMPLETION(wait);
+    CPQFC_DECLARE_COMPLETION(wait);
         
     SCpnt->SCp.buffers_residual = FCP_TARGET_RESET;
 
-	SCpnt->request.waiting = &wait;
+	SCpnt->request.CPQFC_WAITING = &wait;
 	scsi_do_cmd(SCpnt,  scsi_cdb, NULL,  0, my_ioctl_done,  timeout, retries);
-	spin_unlock_irqrestore(&io_request_lock, flags);
-	wait_for_completion(&wait);
-    spin_lock_irqsave(&io_request_lock, flags);
-    SCpnt->request.waiting = NULL;
+	CPQFC_WAIT_FOR_COMPLETION(&wait);
+	SCpnt->request.CPQFC_WAITING = NULL;
   }
     
 /*
@@ -1560,7 +1568,6 @@
   // 	(*SDpnt->scsi_request_fn)();
 
   wake_up(&SDpnt->scpnt_wait);
-  spin_unlock_irqrestore(&io_request_lock, flags);
   // printk("   LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS \n");
   return SUCCESS;
 }
@@ -1568,9 +1575,13 @@
 
 int cpqfcTS_eh_device_reset(Scsi_Cmnd *Cmnd)
 {
+  int retval;
   Scsi_Device *SDpnt = Cmnd->device;
   // printk("   ENTERING cpqfcTS_eh_device_reset() \n");
-  return cpqfcTS_TargetDeviceReset( SDpnt, 0);
+  spin_unlock_irq(&io_request_lock);
+  retval = cpqfcTS_TargetDeviceReset( SDpnt, 0);
+  spin_lock_irq(&io_request_lock);
+  return retval;
 }
 
 	

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)