ncr5380: Implement new eh_bus_reset_handler
authorFinn Thain <fthain@telegraphics.com.au>
Sun, 3 Jan 2016 05:06:03 +0000 (16:06 +1100)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 7 Jan 2016 02:43:08 +0000 (21:43 -0500)
NCR5380.c lacks a sane eh_bus_reset_handler. The atari_NCR5380.c code is
much better but it should not throw out the issue queue (that would be
a host reset) and it neglects to set the result code for commands that it
throws out. Fix these bugs and keep the two core drivers in sync.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/NCR5380.c
drivers/scsi/atari_NCR5380.c

index 32355b62808b51da799c761504db944012931ddf..b46e0879b4d6d2179cfd189c8d3b2f7b6b369822 100644 (file)
@@ -2482,18 +2482,66 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
 {
        struct Scsi_Host *instance = cmd->device->host;
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
+       int i;
        unsigned long flags;
+       struct NCR5380_cmd *ncmd;
 
        spin_lock_irqsave(&hostdata->lock, flags);
 
 #if (NDEBUG & NDEBUG_ANY)
-       scmd_printk(KERN_INFO, cmd, "performing bus reset\n");
+       scmd_printk(KERN_INFO, cmd, __func__);
 #endif
        NCR5380_dprint(NDEBUG_ANY, instance);
        NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
        do_reset(instance);
 
+       /* reset NCR registers */
+       NCR5380_write(MODE_REG, MR_BASE);
+       NCR5380_write(TARGET_COMMAND_REG, 0);
+       NCR5380_write(SELECT_ENABLE_REG, 0);
+
+       /* After the reset, there are no more connected or disconnected commands
+        * and no busy units; so clear the low-level status here to avoid
+        * conflicts when the mid-level code tries to wake up the affected
+        * commands!
+        */
+
+       hostdata->selecting = NULL;
+
+       list_for_each_entry(ncmd, &hostdata->disconnected, list) {
+               struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
+
+               set_host_byte(cmd, DID_RESET);
+               cmd->scsi_done(cmd);
+       }
+
+       list_for_each_entry(ncmd, &hostdata->autosense, list) {
+               struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
+
+               set_host_byte(cmd, DID_RESET);
+               cmd->scsi_done(cmd);
+       }
+
+       if (hostdata->connected) {
+               set_host_byte(hostdata->connected, DID_RESET);
+               complete_cmd(instance, hostdata->connected);
+               hostdata->connected = NULL;
+       }
+
+       if (hostdata->sensing) {
+               set_host_byte(hostdata->connected, DID_RESET);
+               complete_cmd(instance, hostdata->sensing);
+               hostdata->sensing = NULL;
+       }
+
+       for (i = 0; i < 8; ++i)
+               hostdata->busy[i] = 0;
+#ifdef REAL_DMA
+       hostdata->dma_len = 0;
+#endif
+
+       queue_work(hostdata->work_q, &hostdata->main_task);
        spin_unlock_irqrestore(&hostdata->lock, flags);
 
        return SUCCESS;
index 4a88a7a355eba946fa185e76b25e267d14d3c709..d6717610a65e544ccef9cab92c33e09b3f0a2174 100644 (file)
@@ -2694,11 +2694,12 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
        int i;
        unsigned long flags;
+       struct NCR5380_cmd *ncmd;
 
        spin_lock_irqsave(&hostdata->lock, flags);
 
 #if (NDEBUG & NDEBUG_ANY)
-       scmd_printk(KERN_INFO, cmd, "performing bus reset\n");
+       scmd_printk(KERN_INFO, cmd, __func__);
 #endif
        NCR5380_dprint(NDEBUG_ANY, instance);
        NCR5380_dprint_phase(NDEBUG_ANY, instance);
@@ -2718,26 +2719,31 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
 
        hostdata->selecting = NULL;
 
-       if (hostdata->connected)
-               dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n");
-       hostdata->connected = NULL;
+       list_for_each_entry(ncmd, &hostdata->disconnected, list) {
+               struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
 
-       if (hostdata->sensing) {
-               complete_cmd(instance, hostdata->sensing);
-               hostdata->sensing = NULL;
+               set_host_byte(cmd, DID_RESET);
+               cmd->scsi_done(cmd);
        }
 
-       if (!list_empty(&hostdata->autosense))
-               dsprintk(NDEBUG_ABORT, instance, "reset aborted autosense list\n");
-       INIT_LIST_HEAD(&hostdata->autosense);
+       list_for_each_entry(ncmd, &hostdata->autosense, list) {
+               struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
 
-       if (!list_empty(&hostdata->unissued))
-               dsprintk(NDEBUG_ABORT, instance, "reset aborted unissued list\n");
-       INIT_LIST_HEAD(&hostdata->unissued);
+               set_host_byte(cmd, DID_RESET);
+               cmd->scsi_done(cmd);
+       }
 
-       if (!list_empty(&hostdata->disconnected))
-               dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected list\n");
-       INIT_LIST_HEAD(&hostdata->disconnected);
+       if (hostdata->connected) {
+               set_host_byte(hostdata->connected, DID_RESET);
+               complete_cmd(instance, hostdata->connected);
+               hostdata->connected = NULL;
+       }
+
+       if (hostdata->sensing) {
+               set_host_byte(hostdata->connected, DID_RESET);
+               complete_cmd(instance, hostdata->sensing);
+               hostdata->sensing = NULL;
+       }
 
 #ifdef SUPPORT_TAGS
        free_all_tags(hostdata);
@@ -2748,6 +2754,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
        hostdata->dma_len = 0;
 #endif
 
+       queue_work(hostdata->work_q, &hostdata->main_task);
        maybe_release_dma_irq(instance);
        spin_unlock_irqrestore(&hostdata->lock, flags);