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

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

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c
@@ -61,10 +61,13 @@
 
 #include "cpqfcTS.h"
 
+#include <linux/config.h>  
 #include <linux/module.h>
 /* Embedded module documentation macros - see module.h */
 MODULE_AUTHOR("Compaq Computer Corporation");
 MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA");
+  
+int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, unsigned int reset_flags);
 
 // This struct was originally defined in 
 // /usr/src/linux/include/linux/proc_fs.h
@@ -312,7 +315,6 @@
       HostAdapter->max_id =  0;   // incremented as devices log in    
       HostAdapter->max_lun = CPQFCTS_MAX_LUN;         // LUNs per FC device
       HostAdapter->max_channel = CPQFCTS_MAX_CHANNEL; // multiple busses?
-      HostAdapter->hostt->use_new_eh_code = 1; // new error handling
       
       // get the pointer to our HBA specific data... (one for
       // each HBA on the PCI bus(ses)).
@@ -410,9 +412,12 @@
 	// 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);
       }
       
       NumberOfAdapters++; 
@@ -454,7 +459,7 @@
   Scsi_Cmnd *ScsiPassThruCmnd;
   unsigned long flags;
 
-  ENTER("cpqfcTS_ioctl");
+  printk(" Enter cpqfcTS_ioctl ");
   
   // can we find an FC device mapping to this SCSI target?
   DumCmnd.channel = ScsiDev->channel;		// For searching
@@ -472,6 +477,7 @@
  
   else  // we know what FC device to operate on...
   {
+    printk("ioctl CMND %d", Cmnd);
     switch (Cmnd) 
     {
       // Passthrough provides a mechanism to bypass the RAID
@@ -653,6 +659,17 @@
         put_user(pLoggedInPort->u.ucWWN[i], 
 		&((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
         break;
+
+
+      case SCSI_IOCTL_FC_TDR:
+          
+        result = cpqfcTS_TargetDeviceReset( ScsiDev, 0);
+
+        break;
+
+
+
+
     default:
       result = -EINVAL;
       break;
@@ -1347,13 +1364,20 @@
 
 int cpqfcTS_abort(Scsi_Cmnd *Cmnd)
 {
+	printk(" cpqfcTS_abort called?? \n");
+ 	return 0;
+}
+ 
+int cpqfcTS_eh_abort(Scsi_Cmnd *Cmnd)
+{
+
   struct Scsi_Host *HostAdapter = Cmnd->host;
   // get the pointer to our Scsi layer HBA buffer  
   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
   int i;
-  ENTER("cpqfcTS_abort");
+  ENTER("cpqfcTS_eh_abort");
 
   Cmnd->result = DID_ABORT <<16;  // assume we'll find it
 
@@ -1439,28 +1463,116 @@
 Done:
   
 //    panic("_abort");
-  LEAVE("cpqfcTS_abort");
+  LEAVE("cpqfcTS_eh_abort");
   return 0;  // (see scsi.h)
 }    
 
 
+// FCP-SCSI Target Device Reset
+// See dpANS Fibre Channel Protocol for SCSI
+// X3.269-199X revision 12, pg 25
+
+int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, 
+                               unsigned int reset_flags)
+{
+  int timeout = 10*HZ;
+  int retries = 1;
+  char scsi_cdb[12];
+  unsigned long flags;
+  int result;
+  Scsi_Cmnd * SCpnt;
+  Scsi_Device * SDpnt;
 
 
-// To be done...	
-int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
-{
-  int return_status = SUCCESS;
+  // printk("   ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags);
 
-  ENTER("cpqfcTS_reset");
+  if (ScsiDev->host->eh_active) return FAILED;
 
+  memset( scsi_cdb, 0, sizeof( scsi_cdb));
 
-            
+  scsi_cdb[0] = RELEASE;
 
-  LEAVE("cpqfcTS_reset");
-  return return_status;
-}    
+  spin_lock_irqsave(&io_request_lock, flags);
 
+  SCpnt = scsi_allocate_device(NULL, ScsiDev, 1);
+  {
+    struct semaphore sem = MUTEX_LOCKED;
+        
+    SCpnt->SCp.buffers_residual = FCP_TARGET_RESET;
 
+	SCpnt->request.sem = &sem;
+	scsi_do_cmd(SCpnt,  scsi_cdb, NULL,  0, my_ioctl_done,  timeout, retries);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	down(&sem);
+    spin_lock_irqsave(&io_request_lock, flags);
+    SCpnt->request.sem = NULL;
+  }
+    
+/*
+      if(driver_byte(SCpnt->result) != 0)
+	  switch(SCpnt->sense_buffer[2] & 0xf) {
+	case ILLEGAL_REQUEST:
+	    if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0;
+	    else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
+	    break;
+	case NOT_READY: // This happens if there is no disc in drive 
+	    if(dev->removable && (cmd[0] != TEST_UNIT_READY)){
+		printk(KERN_INFO "Device not ready.  Make sure there is a disc in the drive.\n");
+		break;
+	    }
+	case UNIT_ATTENTION:
+	    if (dev->removable){
+		dev->changed = 1;
+		SCpnt->result = 0; // This is no longer considered an error
+		// gag this error, VFS will log it anyway /axboe 
+		// printk(KERN_INFO "Disc change detected.\n"); 
+		break;
+	    };
+	default: // Fall through for non-removable media
+	    printk("SCSI error: host %d id %d lun %d return code = %x\n",
+		   dev->host->host_no,
+		   dev->id,
+		   dev->lun,
+		   SCpnt->result);
+	    printk("\tSense class %x, sense error %x, extended sense %x\n",
+		   sense_class(SCpnt->sense_buffer[0]),
+		   sense_error(SCpnt->sense_buffer[0]),
+		   SCpnt->sense_buffer[2] & 0xf);
+	    
+      };
+*/    
+  result = SCpnt->result;
+
+  SDpnt = SCpnt->device;
+  scsi_release_command(SCpnt);
+  SCpnt = NULL;
+
+  if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
+	(*SDpnt->scsi_request_fn)();
+
+  wake_up(&SDpnt->device_wait);
+  spin_unlock_irqrestore(&io_request_lock, flags);
+  // printk("   LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS \n");
+  return SUCCESS;
+}
+
+
+int cpqfcTS_eh_device_reset(Scsi_Cmnd *Cmnd)
+{
+  Scsi_Device *SDpnt = Cmnd->device;
+  // printk("   ENTERING cpqfcTS_eh_device_reset() \n");
+  return cpqfcTS_TargetDeviceReset( SDpnt, 0);
+}
+
+	
+int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
+{
+
+  ENTER("cpqfcTS_reset");
+
+  LEAVE("cpqfcTS_reset");
+  return SCSI_RESET_ERROR;      /* Bus Reset Not supported */
+}
 
 /* This function determines the bios parameters for a given
    harddisk. These tend to be numbers that are made up by the
@@ -1805,7 +1917,7 @@
 
 #ifdef MODULE
 
-Scsi_Host_Template driver_template = CPQFCTS;
+static Scsi_Host_Template driver_template = CPQFCTS;
 
 #include "scsi_module.c"
 

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