]> git.hungrycats.org Git - linux/commitdiff
Update 53c700 error handling
authorJames Bottomley <jejb@malley.(none)>
Sat, 22 Feb 2003 04:15:24 +0000 (22:15 -0600)
committerJames Bottomley <jejb@raven.il.steeleye.com>
Sat, 22 Feb 2003 04:15:24 +0000 (22:15 -0600)
drivers/scsi/53c700.c
drivers/scsi/53c700.h

index 6a0b7bafd96a02918768c73485310a1d97b17cd1..3bee66f8aa35d8a27ca3f140a51a91aac1721455 100644 (file)
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/completion.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <asm/dma.h>
@@ -325,6 +326,7 @@ NCR_700_detect(Scsi_Host_Template *tpnt,
        host->max_lun = NCR_700_MAX_LUNS;
        host->unique_id = hostdata->base;
        host->base = hostdata->base;
+       hostdata->eh_complete = NULL;
        host->hostdata[0] = (unsigned long)hostdata;
        /* kick the chip */
        NCR_700_writeb(0xff, host, CTEST9_REG);
@@ -1525,6 +1527,9 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs)
 
                        hostdata->state = NCR_700_HOST_FREE;
                        hostdata->cmd = NULL;
+                       /* signal back if this was an eh induced reset */
+                       if(hostdata->eh_complete != NULL)
+                               complete(hostdata->eh_complete);
                        goto out_unlock;
                } else if(sstat0 & SELECTION_TIMEOUT) {
                        DEBUG(("scsi%d: (%d:%d) selection timeout\n",
@@ -1949,10 +1954,27 @@ NCR_700_abort(Scsi_Cmnd * SCp)
 STATIC int
 NCR_700_bus_reset(Scsi_Cmnd * SCp)
 {
+       DECLARE_COMPLETION(complete);
+       struct NCR_700_Host_Parameters *hostdata = 
+               (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
+
        printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
               SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
        print_command(SCp->cmnd);
+       /* In theory, eh_complete should always be null because the
+        * eh is single threaded, but just in case we're handling a
+        * reset via sg or something */
+       while(hostdata->eh_complete != NULL) {
+               spin_unlock_irq(SCp->device->host->host_lock);
+               schedule_timeout(HZ/10);
+               spin_lock_irq(SCp->device->host->host_lock);
+       }
+       hostdata->eh_complete = &complete;
        NCR_700_internal_bus_reset(SCp->device->host);
+       spin_unlock_irq(SCp->device->host->host_lock);
+       wait_for_completion(&complete);
+       spin_lock_irq(SCp->device->host->host_lock);
+       hostdata->eh_complete = NULL;
        return SUCCESS;
 }
 
index 8ff887ff8bd9aaade4ad62b91d78a792957bcfc8..c839cc02b5969b31fe95e082229cd6ed122ab51a 100644 (file)
@@ -205,6 +205,12 @@ struct NCR_700_Host_Parameters {
 
        /* Free list, singly linked by ITL_forw elements */
        struct NCR_700_command_slot *free_list;
+       /* Completion for waited for ops, like reset, abort or
+        * device reset.
+        *
+        * NOTE: relies on single threading in the error handler to
+        * have only one outstanding at once */
+       struct completion *eh_complete;
 };
 
 /*