For host reset we need to wait for all pending command to complete; there might be more than one command queued and we'll need to wait for all of them. So split off the host reset functionality from sym_eh_handler() and add a wait loop for all commands. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> --- drivers/scsi/sym53c8xx_2/sym_glue.c | 42 ++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index dafdab5869fa..86cba915b62d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -563,7 +563,27 @@ static void sym53c8xx_timer(struct timer_list *t) #define SYM_EH_ABORT 0 #define SYM_EH_DEVICE_RESET 1 #define SYM_EH_BUS_RESET 2 -#define SYM_EH_HOST_RESET 3 + +static int sym_eh_wait_for_commands(struct Scsi_Host *shost) +{ + struct sym_data *sym_data = shost_priv(shost); + struct sym_hcb *np = sym_data->ncb; + int rval = SUCCESS, count = 10; /* 5 seconds */ + + /* Wait for any queued commands to complete */ + spin_lock_irq(shost->host_lock); + while (!sym_que_empty(&np->busy_ccbq)) { + if (--count == 0) { + rval = FAILED; + break; + } + spin_unlock_irq(shost->host_lock); + msleep(500); + spin_lock_irq(shost->host_lock); + } + spin_unlock_irq(shost->host_lock); + return rval; +} /* * Generic method for our eh processing. @@ -605,11 +625,6 @@ static int sym_eh_handler(struct Scsi_Host *shost, int op, sym_reset_scsi_bus(np, 1); sts = 0; break; - case SYM_EH_HOST_RESET: - sym_reset_scsi_bus(np, 0); - sym_start_up(shost, 1); - sts = 0; - break; default: break; } @@ -677,6 +692,10 @@ static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd) struct Scsi_Host *shost = cmd->device->host; struct sym_data *sym_data = shost_priv(shost); struct pci_dev *pdev = sym_data->pdev; + struct sym_hcb *np = sym_data->ncb; + int rval = SUCCESS; + + shost_printk(KERN_WARNING, shost, "HOST RESET operation started\n"); /* We may be in an error condition because the PCI bus * went down. In this case, we need to wait until the @@ -710,7 +729,16 @@ static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd) return SCSI_FAILED; } - return sym_eh_handler(shost, SYM_EH_HOST_RESET, "HOST RESET", cmd); + spin_lock_irq(shost->host_lock); + sym_reset_scsi_bus(np, 0); + sym_start_up(shost, 1); + spin_unlock_irq(shost->host_lock); + + rval = sym_eh_wait_for_commands(shost); + + shost_printk(KERN_WARNING, shost, "HOST RESET operation %s.\n", + rval == SUCCESS ? "complete" : "failed"); + return rval; } /* -- 2.29.2