@@ -585,13 +585,12 @@ static int sym_eh_wait_for_commands(struct Scsi_Host *shost)
}
/*
- * Generic method for our eh processing.
- * The 'op' argument tells what we have to do.
+ * Error handlers called from the eh thread (one thread per HBA).
*/
-static int sym_eh_handler(struct Scsi_Host *shost, int op,
- char *opname, struct scsi_cmnd *cmd)
+static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
{
struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
+ struct Scsi_Host *shost = cmd->device->host;
struct sym_data *sym_data = shost_priv(shost);
struct sym_hcb *np = sym_data->ncb;
SYM_QUEHEAD *qp;
@@ -599,7 +598,7 @@ static int sym_eh_handler(struct Scsi_Host *shost, int op,
int sts = -1;
struct completion eh_done;
- scmd_printk(KERN_WARNING, cmd, "%s operation started\n", opname);
+ scmd_printk(KERN_WARNING, cmd, "ABORT operation started\n");
spin_lock_irq(shost->host_lock);
/* This one is queued in some place -> to wait for completion */
@@ -611,19 +610,7 @@ static int sym_eh_handler(struct Scsi_Host *shost, int op,
}
}
- /* Try to proceed the operation we have been asked for */
- sts = -1;
- switch(op) {
- case SYM_EH_ABORT:
- sts = sym_abort_scsiio(np, cmd, 1);
- break;
- case SYM_EH_DEVICE_RESET:
- sts = sym_reset_scsi_target(np, cmd->device->id);
- break;
- default:
- break;
- }
-
+ sts = sym_abort_scsiio(np, cmd, 1);
/* On error, restore everything and cross fingers :) */
if (sts)
cmd_queued = 0;
@@ -640,35 +627,60 @@ static int sym_eh_handler(struct Scsi_Host *shost, int op,
spin_unlock_irq(shost->host_lock);
}
- dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
+ dev_warn(&cmd->device->sdev_gendev, "ABORT operation %s.\n",
sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
return sts ? SCSI_FAILED : SCSI_SUCCESS;
}
-
-/*
- * Error handlers called from the eh thread (one thread per HBA).
- */
-static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
+static int sym53c8xx_eh_target_reset_handler(struct scsi_cmnd *cmd)
{
- struct Scsi_Host *shost = cmd->device->host;
+ struct scsi_target *starget = scsi_target(cmd->device);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_data *sym_data = shost_priv(shost);
struct pci_dev *pdev = sym_data->pdev;
+ struct sym_hcb *np = sym_data->ncb;
+ SYM_QUEHEAD *qp;
+ int sts;
+ struct completion eh_done;
+ starget_printk(KERN_WARNING, starget,
+ "TARGET RESET operation started\n");
+
+ /*
+ * Escalate to host reset if the PCI bus went down
+ */
if (pci_channel_offline(pdev))
- return FAILED;
- return sym_eh_handler(shost, SYM_EH_ABORT, "ABORT", cmd);
-}
+ return SCSI_FAILED;
-static int sym53c8xx_eh_device_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;
+ spin_lock_irq(shost->host_lock);
+ sts = sym_reset_scsi_target(np, starget->id);
+ if (!sts) {
+ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
+ struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb,
+ link_ccbq);
+ struct scsi_cmnd *cmd = cp->cmd;
+ struct sym_ucmd *ucmd;
+
+ if (!cmd || cmd->device->channel != starget->channel ||
+ cmd->device->id != starget->id)
+ continue;
- if (pci_channel_offline(pdev))
- return FAILED;
- return sym_eh_handler(shost, SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+ ucmd = SYM_UCMD_PTR(cmd);
+ init_completion(&eh_done);
+ ucmd->eh_done = &eh_done;
+ spin_unlock_irq(shost->host_lock);
+ if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
+ ucmd->eh_done = NULL;
+ sts = -2;
+ }
+ spin_lock_irq(shost->host_lock);
+ }
+ }
+ spin_unlock_irq(shost->host_lock);
+
+ starget_printk(KERN_WARNING, starget, "TARGET RESET operation %s.\n",
+ sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
+ return SCSI_SUCCESS;
}
static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd)
@@ -1699,7 +1711,7 @@ static struct scsi_host_template sym2_template = {
.slave_configure = sym53c8xx_slave_configure,
.slave_destroy = sym53c8xx_slave_destroy,
.eh_abort_handler = sym53c8xx_eh_abort_handler,
- .eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,
+ .eh_target_reset_handler = sym53c8xx_eh_target_reset_handler,
.eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler,
.eh_host_reset_handler = sym53c8xx_eh_host_reset_handler,
.this_id = 7,
Split off the combined abort and device reset handling into distinct functions. And the current device reset handler really is a target reset, so rename it. Signed-off-by: Hannes Reinecke <hare@suse.com> --- drivers/scsi/sym53c8xx_2/sym_glue.c | 86 ++++++++++++++++------------- 1 file changed, 49 insertions(+), 37 deletions(-)