[SCSI] aacraid: Track command ownership in driver
authorMark Haverkamp <markh@osdl.org>
Mon, 27 Mar 2006 17:43:40 +0000 (09:43 -0800)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Thu, 13 Apr 2006 15:13:17 +0000 (10:13 -0500)
Received from Mark Salyzyn

The loss of the ownership flags, despite their flaws, in the scsi
command were sorely missed and are reinstated more accurately in the
aacraid driver to track commands and permit us to properly handle error
recovery actions.

Signed-off-by: Mark Haverkamp <markh@osdl.org>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/linit.c

index a1e4730..31319d0 100644 (file)
@@ -387,6 +387,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
        struct scsi_cmnd * scsicmd;
 
        scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
        dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
        if (fibptr == NULL)
@@ -453,8 +454,10 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS) 
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
+       }
                
        printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
        aac_fib_complete(cmd_fibcontext);
@@ -907,6 +910,7 @@ static void io_callback(void *context, struct fib * fibptr)
        u32 cid;
 
        scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
        cid = scmd_id(scsicmd);
@@ -1151,8 +1155,10 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS) 
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
+       }
                
        printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
        /*
@@ -1318,8 +1324,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS)
-       {
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
        }
 
@@ -1341,6 +1347,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
        struct scsi_cmnd *cmd;
 
        cmd = context;
+       cmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
        dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", 
                                smp_processor_id(), jiffies));
@@ -1386,12 +1393,12 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
        unsigned long flags;
 
        /*
-        * Wait for all commands to complete to this specific
-        * target (block).
+        * Wait for all outstanding queued commands to complete to this
+        * specific target (block).
         */
        spin_lock_irqsave(&sdev->list_lock, flags);
        list_for_each_entry(cmd, &sdev->cmd_list, list)
-               if (cmd != scsicmd && cmd->serial_number != 0) {
+               if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
                        ++active;
                        break;
                }
@@ -1434,8 +1441,10 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS)
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
+       }
 
        printk(KERN_WARNING 
                "aac_synchronize: aac_fib_send failed with status: %d.\n", status);
@@ -1458,7 +1467,6 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
        struct Scsi_Host *host = scsicmd->device->host;
        struct aac_dev *dev = (struct aac_dev *)host->hostdata;
        struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
-       int ret;
        
        /*
         *      If the bus, id or lun is out of range, return fail
@@ -1729,24 +1737,19 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                         *      containers to /dev/sd device names
                         */
                         
-                       spin_unlock_irq(host->host_lock);
                        if (scsicmd->request->rq_disk)
                                strlcpy(fsa_dev_ptr[cid].devname,
                                scsicmd->request->rq_disk->disk_name,
                                min(sizeof(fsa_dev_ptr[cid].devname),
                                sizeof(scsicmd->request->rq_disk->disk_name) + 1));
-                       ret = aac_read(scsicmd, cid);
-                       spin_lock_irq(host->host_lock);
-                       return ret;
+
+                       return aac_read(scsicmd, cid);
 
                case WRITE_6:
                case WRITE_10:
                case WRITE_12:
                case WRITE_16:
-                       spin_unlock_irq(host->host_lock);
-                       ret = aac_write(scsicmd, cid);
-                       spin_lock_irq(host->host_lock);
-                       return ret;
+                       return aac_write(scsicmd, cid);
 
                case SYNCHRONIZE_CACHE:
                        /* Issue FIB to tell Firmware to flush it's cache */
@@ -1891,6 +1894,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
        struct scsi_cmnd *scsicmd;
 
        scsicmd = (struct scsi_cmnd *) context;
+       scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
        if (fibptr == NULL)
@@ -2162,7 +2166,8 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
        /*
         *      Check that the command queued to the controller
         */
-       if (status == -EINPROGRESS){
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
                return 0;
        }
 
index fcf046c..51c96ca 100644 (file)
@@ -1770,6 +1770,11 @@ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
 }
 
 struct scsi_cmnd;
+/* SCp.phase values */
+#define AAC_OWNER_MIDLEVEL     0x101
+#define AAC_OWNER_LOWLEVEL     0x102
+#define AAC_OWNER_ERROR_HANDLER        0x103
+#define AAC_OWNER_FIRMWARE     0x106
 
 const char *aac_driverinfo(struct Scsi_Host *);
 struct fib *aac_fib_alloc(struct aac_dev *dev);
index 7203307..9f3cc7b 100644 (file)
@@ -243,6 +243,7 @@ static struct aac_driver_ident aac_drivers[] = {
 static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
        cmd->scsi_done = done;
+       cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
        return (aac_scsi_cmd(cmd) ? FAILED : 0);
 } 
 
@@ -471,7 +472,8 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
                __shost_for_each_device(dev, host) {
                        spin_lock_irqsave(&dev->list_lock, flags);
                        list_for_each_entry(command, &dev->cmd_list, list) {
-                               if (command->serial_number) {
+                               if ((command != cmd) &&
+                                   (command->SCp.phase == AAC_OWNER_FIRMWARE)) {
                                        active++;
                                        break;
                                }