diff mbox series

[2/4] sym53c8xx_2: split off host reset from sym_eh_handler()

Message ID 20210819090716.94049-3-hare@suse.de
State New
Headers show
Series sym53c8xx_2: Fixes for SCSI EH rework | expand

Commit Message

Hannes Reinecke Aug. 19, 2021, 9:07 a.m. UTC
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@suse.de>
---
 drivers/scsi/sym53c8xx_2/sym_glue.c | 42 ++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 7 deletions(-)
diff mbox series

Patch

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;
 }
 
 /*