summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/message/fusion/mptfc.c94
-rw-r--r--drivers/message/fusion/mptscsih.c55
-rw-r--r--drivers/message/fusion/mptscsih.h1
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c32
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c127
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc.h1
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_hwi.c14
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c94
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c42
-rw-r--r--drivers/scsi/ips.c18
-rw-r--r--drivers/scsi/megaraid.c42
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c57
-rw-r--r--drivers/scsi/pmcraid.c60
-rw-r--r--drivers/scsi/qedf/qedf.h5
-rw-r--r--drivers/scsi/qedf/qedf_io.c75
-rw-r--r--drivers/scsi/qedf/qedf_main.c19
-rw-r--r--drivers/scsi/qla1280.c42
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c189
18 files changed, 572 insertions, 395 deletions
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 22e7779a332b..aa6bb764df3e 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -183,73 +183,109 @@ static struct fc_function_template mptfc_transport_functions = {
};
static int
-mptfc_block_error_handler(struct scsi_cmnd *SCpnt,
- int (*func)(struct scsi_cmnd *SCpnt),
- const char *caller)
+mptfc_block_error_handler(struct fc_rport *rport)
{
MPT_SCSI_HOST *hd;
- struct scsi_device *sdev = SCpnt->device;
- struct Scsi_Host *shost = sdev->host;
- struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
+ struct Scsi_Host *shost = rport_to_shost(rport);
unsigned long flags;
int ready;
- MPT_ADAPTER *ioc;
+ MPT_ADAPTER *ioc;
int loops = 40; /* seconds */
- hd = shost_priv(SCpnt->device->host);
+ hd = shost_priv(shost);
ioc = hd->ioc;
spin_lock_irqsave(shost->host_lock, flags);
while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY
|| (loops > 0 && ioc->active == 0)) {
spin_unlock_irqrestore(shost->host_lock, flags);
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "mptfc_block_error_handler.%d: %d:%llu, port status is "
- "%x, active flag %d, deferring %s recovery.\n",
+ "mptfc_block_error_handler.%d: %s, port status is "
+ "%x, active flag %d, deferring recovery.\n",
ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun,
- ready, ioc->active, caller));
+ dev_name(&rport->dev), ready, ioc->active));
msleep(1000);
spin_lock_irqsave(shost->host_lock, flags);
loops --;
}
spin_unlock_irqrestore(shost->host_lock, flags);
- if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata
- || ioc->active == 0) {
+ if (ready == DID_NO_CONNECT || ioc->active == 0) {
dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "%s.%d: %d:%llu, failing recovery, "
- "port state %x, active %d, vdevice %p.\n", caller,
+ "mpt_block_error_handler.%d: %s, failing recovery, "
+ "port state %x, active %d.\n",
ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun, ready,
- ioc->active, SCpnt->device->hostdata));
+ dev_name(&rport->dev), ready, ioc->active));
return FAILED;
}
- dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT
- "%s.%d: %d:%llu, executing recovery.\n", caller,
- ioc->name, ioc->sh->host_no,
- SCpnt->device->id, SCpnt->device->lun));
- return (*func)(SCpnt);
+ return SUCCESS;
}
static int
mptfc_abort(struct scsi_cmnd *SCpnt)
{
- return
- mptfc_block_error_handler(SCpnt, mptscsih_abort, __func__);
+ struct Scsi_Host *shost = SCpnt->device->host;
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
+ int rtn;
+
+ rtn = mptfc_block_error_handler(rport);
+ if (rtn == SUCCESS) {
+ dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+ "%s.%d: %d:%llu, executing recovery.\n", __func__,
+ hd->ioc->name, shost->host_no,
+ SCpnt->device->id, SCpnt->device->lun));
+ rtn = mptscsih_abort(SCpnt);
+ }
+ return rtn;
}
static int
mptfc_dev_reset(struct scsi_cmnd *SCpnt)
{
- return
- mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __func__);
+ struct Scsi_Host *shost = SCpnt->device->host;
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
+ int rtn;
+
+ rtn = mptfc_block_error_handler(rport);
+ if (rtn == SUCCESS) {
+ dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+ "%s.%d: %d:%llu, executing recovery.\n", __func__,
+ hd->ioc->name, shost->host_no,
+ SCpnt->device->id, SCpnt->device->lun));
+ rtn = mptscsih_dev_reset(SCpnt);
+ }
+ return rtn;
}
static int
mptfc_bus_reset(struct scsi_cmnd *SCpnt)
{
- return
- mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __func__);
+ struct Scsi_Host *shost = SCpnt->device->host;
+ MPT_SCSI_HOST __maybe_unused *hd = shost_priv(shost);
+ int channel = SCpnt->device->channel;
+ struct mptfc_rport_info *ri;
+ int rtn;
+
+ list_for_each_entry(ri, &hd->ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ VirtTarget *vtarget = ri->starget->hostdata;
+
+ if (!vtarget || vtarget->channel != channel)
+ continue;
+ rtn = fc_block_rport(ri->rport);
+ if (rtn != 0)
+ break;
+ }
+ }
+ if (rtn == 0) {
+ dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT
+ "%s.%d: %d:%llu, executing recovery.\n", __func__,
+ hd->ioc->name, shost->host_no,
+ SCpnt->device->id, SCpnt->device->lun));
+ rtn = mptscsih_bus_reset(SCpnt);
+ }
+ return rtn;
}
static void
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 2bc17087d17d..9080a73b4ea6 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1793,7 +1793,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
+ * mptscsih_dev_reset - Perform a SCSI LOGICAL_UNIT_RESET!
* @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
*
* (linux scsi_host_template.eh_dev_reset_handler routine)
@@ -1811,6 +1811,58 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
/* If we can't locate our host adapter structure, return FAILED status.
*/
if ((hd = shost_priv(SCpnt->device->host)) == NULL){
+ printk(KERN_ERR MYNAM ": lun reset: "
+ "Can't locate host! (sc=%p)\n", SCpnt);
+ return FAILED;
+ }
+
+ ioc = hd->ioc;
+ printk(MYIOC_s_INFO_FMT "attempting lun reset! (sc=%p)\n",
+ ioc->name, SCpnt);
+ scsi_print_command(SCpnt);
+
+ vdevice = SCpnt->device->hostdata;
+ if (!vdevice || !vdevice->vtarget) {
+ retval = 0;
+ goto out;
+ }
+
+ retval = mptscsih_IssueTaskMgmt(hd,
+ MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET,
+ vdevice->vtarget->channel,
+ vdevice->vtarget->id, vdevice->lun, 0,
+ mptscsih_get_tm_timeout(ioc));
+
+ out:
+ printk (MYIOC_s_INFO_FMT "lun reset: %s (sc=%p)\n",
+ ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt);
+
+ if (retval == 0)
+ return SUCCESS;
+ else
+ return FAILED;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_target_reset - Perform a SCSI TARGET_RESET!
+ * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
+ *
+ * (linux scsi_host_template.eh_target_reset_handler routine)
+ *
+ * Returns SUCCESS or FAILED.
+ **/
+int
+mptscsih_target_reset(struct scsi_cmnd * SCpnt)
+{
+ MPT_SCSI_HOST *hd;
+ int retval;
+ VirtDevice *vdevice;
+ MPT_ADAPTER *ioc;
+
+ /* If we can't locate our host adapter structure, return FAILED status.
+ */
+ if ((hd = shost_priv(SCpnt->device->host)) == NULL){
printk(KERN_ERR MYNAM ": target reset: "
"Can't locate host! (sc=%p)\n", SCpnt);
return FAILED;
@@ -3256,6 +3308,7 @@ EXPORT_SYMBOL(mptscsih_slave_destroy);
EXPORT_SYMBOL(mptscsih_slave_configure);
EXPORT_SYMBOL(mptscsih_abort);
EXPORT_SYMBOL(mptscsih_dev_reset);
+EXPORT_SYMBOL(mptscsih_target_reset);
EXPORT_SYMBOL(mptscsih_bus_reset);
EXPORT_SYMBOL(mptscsih_host_reset);
EXPORT_SYMBOL(mptscsih_bios_param);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index a22c5eaf703c..e3d92c392673 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -120,6 +120,7 @@ extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
+extern int mptscsih_target_reset(struct scsi_cmnd * SCpnt);
extern int mptscsih_bus_reset(struct scsi_cmnd * SCpnt);
extern int mptscsih_host_reset(struct scsi_cmnd *SCpnt);
extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index f2f3405cdec5..b3075a022d99 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -536,13 +536,18 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
struct scsi_cmnd *cmd;
cmd = scb->io_ctx;
- ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
- scsi_dma_unmap(cmd);
+ if (cmd) {
+ ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
+ scsi_dma_unmap(cmd);
+ }
}
/******************************** Macros **************************************/
-#define BUILD_SCSIID(ahd, cmd) \
- (((scmd_id(cmd) << TID_SHIFT) & TID) | (ahd)->our_id)
+static inline unsigned int ahd_build_scsiid(struct ahd_softc *ahd,
+ struct scsi_device *sdev)
+{
+ return ((sdev_id(sdev) << TID_SHIFT) & TID) | (ahd)->our_id;
+}
/*
* Return a string describing the driver.
@@ -811,14 +816,14 @@ ahd_linux_dev_reset(struct scsi_cmnd *cmd)
tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
cmd->device->id, &tstate);
- reset_scb->io_ctx = cmd;
+ reset_scb->io_ctx = NULL;
reset_scb->platform_data->dev = dev;
reset_scb->sg_count = 0;
ahd_set_residual(reset_scb, 0);
ahd_set_sense_residual(reset_scb, 0);
reset_scb->platform_data->xfer_len = 0;
reset_scb->hscb->control = 0;
- reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd);
+ reset_scb->hscb->scsiid = ahd_build_scsiid(ahd, cmd->device);
reset_scb->hscb->lun = cmd->device->lun;
reset_scb->hscb->cdb_len = 0;
reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET;
@@ -1577,7 +1582,7 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
* Fill out basics of the HSCB.
*/
hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahd, cmd);
+ hscb->scsiid = ahd_build_scsiid(ahd, cmd->device);
hscb->lun = cmd->device->lun;
scb->hscb->task_management = 0;
mask = SCB_GET_TARGET_MASK(ahd, scb);
@@ -1766,9 +1771,16 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
dev = scb->platform_data->dev;
dev->active--;
dev->openings++;
- if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
- cmd->result &= ~(CAM_DEV_QFRZN << 16);
- dev->qfrozen--;
+ if (cmd) {
+ if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
+ cmd->result &= ~(CAM_DEV_QFRZN << 16);
+ dev->qfrozen--;
+ }
+ } else if (scb->flags & SCB_DEVICE_RESET) {
+ if (ahd->platform_data->eh_done)
+ complete(ahd->platform_data->eh_done);
+ ahd_free_scb(ahd, scb);
+ return;
}
ahd_linux_unmap_scb(ahd, scb);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index d3b1082654d5..4ae0a1c4d374 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -366,7 +366,8 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
struct scsi_cmnd *cmd);
static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
static void ahc_linux_release_simq(struct ahc_softc *ahc);
-static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
+static int ahc_linux_queue_recovery_cmd(struct scsi_device *sdev,
+ struct scsi_cmnd *cmd);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo);
@@ -728,7 +729,7 @@ ahc_linux_abort(struct scsi_cmnd *cmd)
{
int error;
- error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);
+ error = ahc_linux_queue_recovery_cmd(cmd->device, cmd);
if (error != SUCCESS)
printk("aic7xxx_abort returns 0x%x\n", error);
return (error);
@@ -742,7 +743,7 @@ ahc_linux_dev_reset(struct scsi_cmnd *cmd)
{
int error;
- error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
+ error = ahc_linux_queue_recovery_cmd(cmd->device, NULL);
if (error != SUCCESS)
printk("aic7xxx_dev_reset returns 0x%x\n", error);
return (error);
@@ -798,11 +799,18 @@ struct scsi_host_template aic7xxx_driver_template = {
/**************************** Tasklet Handler *********************************/
-/******************************** Macros **************************************/
-#define BUILD_SCSIID(ahc, cmd) \
- ((((cmd)->device->id << TID_SHIFT) & TID) \
- | (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \
- | (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB))
+
+static inline unsigned int ahc_build_scsiid(struct ahc_softc *ahc,
+ struct scsi_device *sdev)
+{
+ unsigned int scsiid = (sdev->id << TID_SHIFT) & TID;
+
+ if (sdev->channel == 0)
+ scsiid |= ahc->our_id;
+ else
+ scsiid |= ahc->our_id_b | TWIN_CHNLB;
+ return scsiid;
+}
/******************************** Bus DMA *************************************/
int
@@ -1457,7 +1465,7 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
* Fill out basics of the HSCB.
*/
hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahc, cmd);
+ hscb->scsiid = ahc_build_scsiid(ahc, cmd->device);
hscb->lun = cmd->device->lun;
mask = SCB_GET_TARGET_MASK(ahc, scb);
tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
@@ -2029,11 +2037,12 @@ ahc_linux_release_simq(struct ahc_softc *ahc)
}
static int
-ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
+ahc_linux_queue_recovery_cmd(struct scsi_device *sdev,
+ struct scsi_cmnd *cmd)
{
struct ahc_softc *ahc;
struct ahc_linux_device *dev;
- struct scb *pending_scb;
+ struct scb *pending_scb = NULL, *scb;
u_int saved_scbptr;
u_int active_scb_index;
u_int last_phase;
@@ -2046,18 +2055,19 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int disconnected;
unsigned long flags;
- pending_scb = NULL;
paused = FALSE;
wait = FALSE;
- ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
+ ahc = *(struct ahc_softc **)sdev->host->hostdata;
- scmd_printk(KERN_INFO, cmd, "Attempting to queue a%s message\n",
- flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
+ sdev_printk(KERN_INFO, sdev, "Attempting to queue a%s message\n",
+ cmd ? "n ABORT" : " TARGET RESET");
- printk("CDB:");
- for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
- printk(" 0x%x", cmd->cmnd[cdb_byte]);
- printk("\n");
+ if (cmd) {
+ printk("CDB:");
+ for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
+ printk(" 0x%x", cmd->cmnd[cdb_byte]);
+ printk("\n");
+ }
ahc_lock(ahc, &flags);
@@ -2068,7 +2078,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* at all, and the system wanted us to just abort the
* command, return success.
*/
- dev = scsi_transport_device_data(cmd->device);
+ dev = scsi_transport_device_data(sdev);
if (dev == NULL) {
/*
@@ -2076,13 +2086,12 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* so we must not still own the command.
*/
printk("%s:%d:%d:%d: Is not an active device\n",
- ahc_name(ahc), cmd->device->channel, cmd->device->id,
- (u8)cmd->device->lun);
+ ahc_name(ahc), sdev->channel, sdev->id, (u8)sdev->lun);
retval = SUCCESS;
goto no_cmd;
}
- if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
+ if (cmd && (dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
&& ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
cmd->device->channel + 'A',
(u8)cmd->device->lun,
@@ -2097,25 +2106,28 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
/*
* See if we can find a matching cmd in the pending list.
*/
- LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
- if (pending_scb->io_ctx == cmd)
- break;
- }
-
- if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
-
+ if (cmd) {
+ LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
+ if (scb->io_ctx == cmd) {
+ pending_scb = scb;
+ break;
+ }
+ }
+ } else {
/* Any SCB for this device will do for a target reset */
- LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
- if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
- scmd_channel(cmd) + 'A',
+ LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
+ if (ahc_match_scb(ahc, scb, sdev->id,
+ sdev->channel + 'A',
CAM_LUN_WILDCARD,
- SCB_LIST_NULL, ROLE_INITIATOR))
+ SCB_LIST_NULL, ROLE_INITIATOR)) {
+ pending_scb = scb;
break;
+ }
}
}
if (pending_scb == NULL) {
- scmd_printk(KERN_INFO, cmd, "Command not found\n");
+ sdev_printk(KERN_INFO, sdev, "Command not found\n");
goto no_cmd;
}
@@ -2146,22 +2158,22 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
ahc_dump_card_state(ahc);
disconnected = TRUE;
- if (flag == SCB_ABORT) {
- if (ahc_search_qinfifo(ahc, cmd->device->id,
- cmd->device->channel + 'A',
- cmd->device->lun,
+ if (cmd) {
+ if (ahc_search_qinfifo(ahc, sdev->id,
+ sdev->channel + 'A',
+ sdev->lun,
pending_scb->hscb->tag,
ROLE_INITIATOR, CAM_REQ_ABORTED,
SEARCH_COMPLETE) > 0) {
printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
- ahc_name(ahc), cmd->device->channel,
- cmd->device->id, (u8)cmd->device->lun);
+ ahc_name(ahc), sdev->channel,
+ sdev->id, (u8)sdev->lun);
retval = SUCCESS;
goto done;
}
- } else if (ahc_search_qinfifo(ahc, cmd->device->id,
- cmd->device->channel + 'A',
- cmd->device->lun,
+ } else if (ahc_search_qinfifo(ahc, sdev->id,
+ sdev->channel + 'A',
+ sdev->lun,
pending_scb->hscb->tag,
ROLE_INITIATOR, /*status*/0,
SEARCH_COUNT) > 0) {
@@ -2174,7 +2186,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
bus_scb = ahc_lookup_scb(ahc, ahc_inb(ahc, SCB_TAG));
if (bus_scb == pending_scb)
disconnected = FALSE;
- else if (flag != SCB_ABORT
+ else if (!cmd
&& ahc_inb(ahc, SAVED_SCSIID) == pending_scb->hscb->scsiid
&& ahc_inb(ahc, SAVED_LUN) == SCB_GET_LUN(pending_scb))
disconnected = FALSE;
@@ -2194,18 +2206,18 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
if (last_phase != P_BUSFREE
&& (pending_scb->hscb->tag == active_scb_index
- || (flag == SCB_DEVICE_RESET
- && SCSIID_TARGET(ahc, saved_scsiid) == scmd_id(cmd)))) {
+ || (!cmd && SCSIID_TARGET(ahc, saved_scsiid) == sdev->id))) {
/*
* We're active on the bus, so assert ATN
* and hope that the target responds.
*/
pending_scb = ahc_lookup_scb(ahc, active_scb_index);
- pending_scb->flags |= SCB_RECOVERY_SCB|flag;
+ pending_scb->flags |= SCB_RECOVERY_SCB;
+ pending_scb->flags |= cmd ? SCB_ABORT : SCB_DEVICE_RESET;
ahc_outb(ahc, MSG_OUT, HOST_MSG);
ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
- scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
+ sdev_printk(KERN_INFO, sdev, "Device is active, asserting ATN\n");
wait = TRUE;
} else if (disconnected) {
@@ -2226,7 +2238,8 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* an unsolicited reselection occurred.
*/
pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
- pending_scb->flags |= SCB_RECOVERY_SCB|flag;
+ pending_scb->flags |= SCB_RECOVERY_SCB;
+ pending_scb->flags |= cmd ? SCB_ABORT : SCB_DEVICE_RESET;
/*
* Remove any cached copy of this SCB in the
@@ -2235,9 +2248,9 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* same element in the SCB, SCB_NEXT, for
* both the qinfifo and the disconnected list.
*/
- ahc_search_disc_list(ahc, cmd->device->id,
- cmd->device->channel + 'A',
- cmd->device->lun, pending_scb->hscb->tag,
+ ahc_search_disc_list(ahc, sdev->id,
+ sdev->channel + 'A',
+ sdev->lun, pending_scb->hscb->tag,
/*stop_on_first*/TRUE,
/*remove*/TRUE,
/*save_state*/FALSE);
@@ -2260,9 +2273,9 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* so we are the next SCB for this target
* to run.
*/
- ahc_search_qinfifo(ahc, cmd->device->id,
- cmd->device->channel + 'A',
- cmd->device->lun, SCB_LIST_NULL,
+ ahc_search_qinfifo(ahc, sdev->id,
+ sdev->channel + 'A',
+ (u8)sdev->lun, SCB_LIST_NULL,
ROLE_INITIATOR, CAM_REQUEUE_REQ,
SEARCH_COMPLETE);
ahc_qinfifo_requeue_tail(ahc, pending_scb);
@@ -2271,7 +2284,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
printk("Device is disconnected, re-queuing SCB\n");
wait = TRUE;
} else {
- scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
+ sdev_printk(KERN_INFO, sdev, "Unable to deliver message\n");
retval = FAILED;
goto done;
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 046247420cfa..7e74f77da14f 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -384,6 +384,7 @@ struct bnx2fc_rport {
};
struct bnx2fc_mp_req {
+ u64 tm_lun;
u8 tm_flags;
u32 req_len;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index 776544385598..090d436bcef8 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -1709,7 +1709,8 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
struct fcoe_cached_sge_ctx *cached_sge;
struct fcoe_ext_mul_sges_ctx *sgl;
int dev_type = tgt->dev_type;
- u64 *fcp_cmnd;
+ struct fcp_cmnd *fcp_cmnd;
+ u64 *raw_fcp_cmnd;
u64 tmp_fcp_cmnd[4];
u32 context_id;
int cnt, i;
@@ -1778,16 +1779,19 @@ void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
task->txwr_rxrd.union_ctx.tx_seq.ctx.seq_cnt = 1;
/* Fill FCP_CMND IU */
- fcp_cmnd = (u64 *)
+ fcp_cmnd = (struct fcp_cmnd *)&tmp_fcp_cmnd;
+ bnx2fc_build_fcp_cmnd(io_req, fcp_cmnd);
+ int_to_scsilun(sc_cmd->device->lun, &fcp_cmnd->fc_lun);
+ memcpy(fcp_cmnd->fc_cdb, sc_cmd->cmnd, sc_cmd->cmd_len);
+ raw_fcp_cmnd = (u64 *)
task->txwr_rxrd.union_ctx.fcp_cmd.opaque;
- bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
/* swap fcp_cmnd */
cnt = sizeof(struct fcp_cmnd) / sizeof(u64);
for (i = 0; i < cnt; i++) {
- *fcp_cmnd = cpu_to_be64(tmp_fcp_cmnd[i]);
- fcp_cmnd++;
+ *raw_fcp_cmnd = cpu_to_be64(tmp_fcp_cmnd[i]);
+ raw_fcp_cmnd++;
}
/* Rx Write Tx Read */
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index b42a9accb832..33057908f147 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -656,10 +656,9 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
return SUCCESS;
}
-static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
+static int bnx2fc_initiate_tmf(struct fc_lport *lport, struct fc_rport *rport,
+ u64 tm_lun, u8 tm_flags)
{
- struct fc_lport *lport;
- struct fc_rport *rport;
struct fc_rport_libfc_priv *rp;
struct fcoe_port *port;
struct bnx2fc_interface *interface;
@@ -668,7 +667,6 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
struct bnx2fc_mp_req *tm_req;
struct fcoe_task_ctx_entry *task;
struct fcoe_task_ctx_entry *task_page;
- struct Scsi_Host *host = sc_cmd->device->host;
struct fc_frame_header *fc_hdr;
struct fcp_cmnd *fcp_cmnd;
int task_idx, index;
@@ -677,8 +675,6 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
u32 sid, did;
unsigned long start = jiffies;
- lport = shost_priv(host);
- rport = starget_to_rport(scsi_target(sc_cmd->device));
port = lport_priv(lport);
interface = port->priv;
@@ -689,7 +685,7 @@ static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
}
rp = rport->dd_data;
- rc = fc_block_scsi_eh(sc_cmd);
+ rc = fc_block_rport(rport);
if (rc)
return rc;
@@ -718,7 +714,7 @@ retry_tmf:
goto retry_tmf;
}
/* Initialize rest of io_req fields */
- io_req->sc_cmd = sc_cmd;
+ io_req->sc_cmd = NULL;
io_req->port = port;
io_req->tgt = tgt;
@@ -736,11 +732,13 @@ retry_tmf:
/* Set TM flags */
io_req->io_req_flags = 0;
tm_req->tm_flags = tm_flags;
+ tm_req->tm_lun = tm_lun;
/* Fill FCP_CMND */
bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)tm_req->req_buf);
fcp_cmnd = (struct fcp_cmnd *)tm_req->req_buf;
- memset(fcp_cmnd->fc_cdb, 0, sc_cmd->cmd_len);
+ int_to_scsilun(tm_lun, &fcp_cmnd->fc_lun);
+ memset(fcp_cmnd->fc_cdb, 0, BNX2FC_MAX_CMD_LEN);
fcp_cmnd->fc_dl = 0;
/* Fill FC header */
@@ -763,8 +761,6 @@ retry_tmf:
task = &(task_page[index]);
bnx2fc_init_mp_task(io_req, task);
- bnx2fc_priv(sc_cmd)->io_req = io_req;
-
/* Obtain free SQ entry */
spin_lock_bh(&tgt->tgt_lock);
bnx2fc_add_2_sq(tgt, xid);
@@ -1062,7 +1058,10 @@ cleanup_err:
*/
int bnx2fc_eh_target_reset(struct scsi_cmnd *sc_cmd)
{
- return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_TGT_RESET);
+ struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+ struct fc_lport *lport = shost_priv(rport_to_shost(rport));
+
+ return bnx2fc_initiate_tmf(lport, rport, 0, FCP_TMF_TGT_RESET);
}
/**
@@ -1075,7 +1074,11 @@ int bnx2fc_eh_target_reset(struct scsi_cmnd *sc_cmd)
*/
int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
{
- return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
+ struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+ struct fc_lport *lport = shost_priv(rport_to_shost(rport));
+
+ return bnx2fc_initiate_tmf(lport, rport, sc_cmd->device->lun,
+ FCP_TMF_LUN_RESET);
}
static int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req)
@@ -1450,10 +1453,9 @@ io_compl:
static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req)
{
- struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
struct bnx2fc_rport *tgt = io_req->tgt;
struct bnx2fc_cmd *cmd, *tmp;
- u64 tm_lun = sc_cmd->device->lun;
+ struct bnx2fc_mp_req *tm_req = &io_req->mp_req;
u64 lun;
int rc = 0;
@@ -1465,8 +1467,10 @@ static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req)
*/
list_for_each_entry_safe(cmd, tmp, &tgt->active_cmd_queue, link) {
BNX2FC_TGT_DBG(tgt, "LUN RST cmpl: scan for pending IOs\n");
+ if (!cmd->sc_cmd)
+ continue;
lun = cmd->sc_cmd->device->lun;
- if (lun == tm_lun) {
+ if (lun == tm_req->tm_lun) {
/* Initiate ABTS on this cmd */
if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
&cmd->req_flags)) {
@@ -1570,31 +1574,36 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
printk(KERN_ERR PFX "tmf's fc_hdr r_ctl = 0x%x\n",
fc_hdr->fh_r_ctl);
}
- if (!bnx2fc_priv(sc_cmd)->io_req) {
- printk(KERN_ERR PFX "tm_compl: io_req is NULL\n");
- return;
- }
- switch (io_req->fcp_status) {
- case FC_GOOD:
- if (io_req->cdb_status == 0) {
- /* Good IO completion */
- sc_cmd->result = DID_OK << 16;
- } else {
- /* Transport status is good, SCSI status not good */
- sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+ if (sc_cmd) {
+ if (!bnx2fc_priv(sc_cmd)->io_req) {
+ printk(KERN_ERR PFX "tm_compl: io_req is NULL\n");
+ return;
+ }
+ switch (io_req->fcp_status) {
+ case FC_GOOD:
+ if (io_req->cdb_status == 0) {
+ /* Good IO completion */
+ sc_cmd->result = DID_OK << 16;
+ } else {
+ /* Transport status is good, SCSI status not good */
+ sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+ }
+ if (io_req->fcp_resid)
+ scsi_set_resid(sc_cmd, io_req->fcp_resid);
+ break;
+
+ default:
+ BNX2FC_IO_DBG(io_req, "process_tm_compl: fcp_status = %d\n",
+ io_req->fcp_status);
+ break;
}
- if (io_req->fcp_resid)
- scsi_set_resid(sc_cmd, io_req->fcp_resid);
- break;
- default:
- BNX2FC_IO_DBG(io_req, "process_tm_compl: fcp_status = %d\n",
- io_req->fcp_status);
- break;
- }
+ sc_cmd = io_req->sc_cmd;
+ io_req->sc_cmd = NULL;
- sc_cmd = io_req->sc_cmd;
- io_req->sc_cmd = NULL;
+ bnx2fc_priv(sc_cmd)->io_req = NULL;
+ scsi_done(sc_cmd);
+ }
/* check if the io_req exists in tgt's tmf_q */
if (io_req->on_tmf_queue) {
@@ -1607,9 +1616,6 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
return;
}
- bnx2fc_priv(sc_cmd)->io_req = NULL;
- scsi_done(sc_cmd);
-
kref_put(&io_req->refcount, bnx2fc_cmd_release);
if (io_req->wait_for_abts_comp) {
BNX2FC_IO_DBG(io_req, "tm_compl - wake up the waiter\n");
@@ -1738,15 +1744,9 @@ static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req)
void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
struct fcp_cmnd *fcp_cmnd)
{
- struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
-
memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
- int_to_scsilun(sc_cmd->device->lun, &fcp_cmnd->fc_lun);
-
fcp_cmnd->fc_dl = htonl(io_req->data_xfer_len);
- memcpy(fcp_cmnd->fc_cdb, sc_cmd->cmnd, sc_cmd->cmd_len);
-
fcp_cmnd->fc_cmdref = 0;
fcp_cmnd->fc_pri_ta = 0;
fcp_cmnd->fc_tm_flags = io_req->mp_req.tm_flags;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 122b79db79e3..92c440f2e3a7 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2996,18 +2996,6 @@ static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data)
}
/**
- * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
- * @sdev: scsi device struct
- * @data: return code
- *
- **/
-static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
-{
- unsigned long *rc = data;
- *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_TGT_RESET);
-}
-
-/**
* ibmvfc_eh_target_reset_handler - Reset the target
* @cmd: scsi command struct
*
@@ -3016,22 +3004,38 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
**/
static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
{
- struct scsi_device *sdev = cmd->device;
- struct ibmvfc_host *vhost = shost_priv(sdev->host);
- struct scsi_target *starget = scsi_target(sdev);
+ struct scsi_target *starget = scsi_target(cmd->device);
+ struct fc_rport *rport = starget_to_rport(starget);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct ibmvfc_host *vhost = shost_priv(shost);
int block_rc;
int reset_rc = 0;
int rc = FAILED;
unsigned long cancel_rc = 0;
+ bool tgt_reset = false;
ENTER;
- block_rc = fc_block_scsi_eh(cmd);
+ block_rc = fc_block_rport(rport);
ibmvfc_wait_while_resetting(vhost);
if (block_rc != FAST_IO_FAIL) {
- starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
- reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, shost) {
+ if ((sdev->channel != starget->channel) ||
+ (sdev->id != starget->id))
+ continue;
+
+ cancel_rc |= ibmvfc_cancel_all(sdev,
+ IBMVFC_TMF_TGT_RESET);
+ if (!tgt_reset) {
+ reset_rc = ibmvfc_reset_device(sdev,
+ IBMVFC_TARGET_RESET, "target");
+ tgt_reset = true;
+ }
+ }
} else
- starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset);
+ starget_for_each_device(starget, &cancel_rc,
+ ibmvfc_dev_cancel_all_noreset);
if (!cancel_rc && !reset_rc)
rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index bb206509265e..10cf5775a939 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -835,7 +835,6 @@ static int __ips_eh_reset(struct scsi_cmnd *SC)
int i;
ips_ha_t *ha;
ips_scb_t *scb;
- ips_copp_wait_item_t *item;
METHOD_TRACE("ips_eh_reset", 1);
@@ -860,23 +859,6 @@ static int __ips_eh_reset(struct scsi_cmnd *SC)
if (!ha->active)
return (FAILED);
- /* See if the command is on the copp queue */
- item = ha->copp_waitlist.head;
- while ((item) && (item->scsi_cmd != SC))
- item = item->next;
-
- if (item) {
- /* Found it */
- ips_removeq_copp(&ha->copp_waitlist, item);
- return (SUCCESS);
- }
-
- /* See if the command is on the wait queue */
- if (ips_removeq_wait(&ha->scb_waitlist, SC)) {
- /* command not sent yet */
- return (SUCCESS);
- }
-
/* An explanation for the casual observer: */
/* Part of the function of a RAID controller is automatic error */
/* detection and recovery. As such, the only problem that physically */
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index e92f1a73cc9b..329c3da88416 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -1898,7 +1898,7 @@ megaraid_reset(struct scsi_cmnd *cmd)
spin_lock_irq(&adapter->lock);
- rval = megaraid_abort_and_reset(adapter, cmd, SCB_RESET);
+ rval = megaraid_abort_and_reset(adapter, NULL, SCB_RESET);
/*
* This is required here to complete any completed requests
@@ -1937,7 +1937,7 @@ megaraid_abort_and_reset(adapter_t *adapter, struct scsi_cmnd *cmd, int aor)
scb = list_entry(pos, scb_t, list);
- if (scb->cmd == cmd) { /* Found command */
+ if (!cmd || scb->cmd == cmd) { /* Found command */
scb->state |= aor;
@@ -1956,31 +1956,23 @@ megaraid_abort_and_reset(adapter_t *adapter, struct scsi_cmnd *cmd, int aor)
return FAILED;
}
- else {
-
- /*
- * Not yet issued! Remove from the pending
- * list
- */
- dev_warn(&adapter->dev->dev,
- "%s-[%x], driver owner\n",
- (aor==SCB_ABORT) ? "ABORTING":"RESET",
- scb->idx);
-
- mega_free_scb(adapter, scb);
-
- if( aor == SCB_ABORT ) {
- cmd->result = (DID_ABORT << 16);
- }
- else {
- cmd->result = (DID_RESET << 16);
- }
+ /*
+ * Not yet issued! Remove from the pending
+ * list
+ */
+ dev_warn(&adapter->dev->dev,
+ "%s-[%x], driver owner\n",
+ (cmd) ? "ABORTING":"RESET",
+ scb->idx);
+ mega_free_scb(adapter, scb);
+ if (cmd) {
+ cmd->result = (DID_ABORT << 16);
list_add_tail(SCSI_LIST(cmd),
- &adapter->completed_list);
-
- return SUCCESS;
+ &adapter->completed_list);
}
+
+ return SUCCESS;
}
}
@@ -4114,8 +4106,6 @@ static const struct scsi_host_template megaraid_template = {
.sg_tablesize = MAX_SGLIST,
.cmd_per_lun = DEF_CMD_PER_LUN,
.eh_abort_handler = megaraid_abort,
- .eh_device_reset_handler = megaraid_reset,
- .eh_bus_reset_handler = megaraid_reset,
.eh_host_reset_handler = megaraid_reset,
.no_write_same = 1,
.cmd_size = sizeof(struct megaraid_cmd_priv),
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index 89ba015c5d7e..040031eb0c12 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -4012,20 +4012,45 @@ static inline void mpi3mr_setup_divert_ws(struct mpi3mr_ioc *mrioc,
* mpi3mr_eh_host_reset - Host reset error handling callback
* @scmd: SCSI command reference
*
- * Issue controller reset if the scmd is for a Physical Device,
- * if the scmd is for RAID volume, then wait for
- * MPI3MR_RAID_ERRREC_RESET_TIMEOUT and checke whether any
- * pending I/Os prior to issuing reset to the controller.
+ * Issue controller reset
*
* Return: SUCCESS of successful reset else FAILED
*/
static int mpi3mr_eh_host_reset(struct scsi_cmnd *scmd)
{
struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host);
+ int retval = FAILED, ret;
+
+ ret = mpi3mr_soft_reset_handler(mrioc,
+ MPI3MR_RESET_FROM_EH_HOS, 1);
+ if (ret)
+ goto out;
+
+ retval = SUCCESS;
+out:
+ sdev_printk(KERN_INFO, scmd->device,
+ "Host reset is %s for scmd(%p)\n",
+ ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+ return retval;
+}
+
+/**
+ * mpi3mr_eh_bus_reset - Bus reset error handling callback
+ * @scmd: SCSI command reference
+ *
+ * Checks whether pending I/Os are present for the RAID volume;
+ * if not there's no need to reset the adapter.
+ *
+ * Return: SUCCESS of successful reset else FAILED
+ */
+static int mpi3mr_eh_bus_reset(struct scsi_cmnd *scmd)
+{
+ struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host);
struct mpi3mr_stgt_priv_data *stgt_priv_data;
struct mpi3mr_sdev_priv_data *sdev_priv_data;
u8 dev_type = MPI3_DEVICE_DEVFORM_VD;
- int retval = FAILED, ret;
+ int retval = FAILED;
sdev_priv_data = scmd->device->hostdata;
if (sdev_priv_data && sdev_priv_data->tgt_priv_data) {
@@ -4035,25 +4060,16 @@ static int mpi3mr_eh_host_reset(struct scsi_cmnd *scmd)
if (dev_type == MPI3_DEVICE_DEVFORM_VD) {
mpi3mr_wait_for_host_io(mrioc,
- MPI3MR_RAID_ERRREC_RESET_TIMEOUT);
- if (!mpi3mr_get_fw_pending_ios(mrioc)) {
+ MPI3MR_RAID_ERRREC_RESET_TIMEOUT);
+ if (!mpi3mr_get_fw_pending_ios(mrioc))
retval = SUCCESS;
- goto out;
- }
}
+ if (retval == FAILED)
+ mpi3mr_print_pending_host_io(mrioc);
- mpi3mr_print_pending_host_io(mrioc);
- ret = mpi3mr_soft_reset_handler(mrioc,
- MPI3MR_RESET_FROM_EH_HOS, 1);
- if (ret)
- goto out;
-
- retval = SUCCESS;
-out:
sdev_printk(KERN_INFO, scmd->device,
- "Host reset is %s for scmd(%p)\n",
- ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
+ "Bus reset is %s for scmd(%p)\n",
+ ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
return retval;
}
@@ -4900,6 +4916,7 @@ static const struct scsi_host_template mpi3mr_driver_template = {
.change_queue_depth = mpi3mr_change_queue_depth,
.eh_device_reset_handler = mpi3mr_eh_dev_reset,
.eh_target_reset_handler = mpi3mr_eh_target_reset,
+ .eh_bus_reset_handler = mpi3mr_eh_bus_reset,
.eh_host_reset_handler = mpi3mr_eh_host_reset,
.bios_param = mpi3mr_bios_param,
.map_queues = mpi3mr_map_queues,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 50dc30051f22..a831b34c08a4 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -2691,7 +2691,7 @@ static int pmcraid_error_handler(struct pmcraid_cmd *cmd)
* SUCCESS / FAILED
*/
static int pmcraid_reset_device(
- struct scsi_cmnd *scsi_cmd,
+ struct scsi_device *scsi_dev,
unsigned long timeout,
u8 modifier)
{
@@ -2703,11 +2703,11 @@ static int pmcraid_reset_device(
u32 ioasc;
pinstance =
- (struct pmcraid_instance *)scsi_cmd->device->host->hostdata;
- res = scsi_cmd->device->hostdata;
+ (struct pmcraid_instance *)scsi_dev->host->hostdata;
+ res = scsi_dev->hostdata;
if (!res) {
- sdev_printk(KERN_ERR, scsi_cmd->device,
+ sdev_printk(KERN_ERR, scsi_dev,
"reset_device: NULL resource pointer\n");
return FAILED;
}
@@ -3018,25 +3018,67 @@ static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd)
{
scmd_printk(KERN_INFO, scmd,
"resetting device due to an I/O command timeout.\n");
- return pmcraid_reset_device(scmd,
+ return pmcraid_reset_device(scmd->device,
PMCRAID_INTERNAL_TIMEOUT,
RESET_DEVICE_LUN);
}
static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd)
{
- scmd_printk(KERN_INFO, scmd,
+ struct Scsi_Host *host = scmd->device->host;
+ struct pmcraid_instance *pinstance =
+ (struct pmcraid_instance *)host->hostdata;
+ struct pmcraid_resource_entry *res = NULL;
+ struct pmcraid_resource_entry *temp;
+ struct scsi_device *sdev = NULL;
+ unsigned long lock_flags;
+
+ /*
+ * The reset device code insists on us passing down
+ * a device, so grab the first device on the bus.
+ */
+ spin_lock_irqsave(&pinstance->resource_lock, lock_flags);
+ list_for_each_entry(temp, &pinstance->used_res_q, queue) {
+ if (scmd->device->channel == PMCRAID_VSET_BUS_ID &&
+ RES_IS_VSET(temp->cfg_entry)) {
+ res = temp;
+ break;
+ } else if (scmd->device->channel == PMCRAID_PHYS_BUS_ID &&
+ RES_IS_GSCSI(temp->cfg_entry)) {
+ res = temp;
+ break;
+ }
+ }
+ if (res)
+ sdev = res->scsi_dev;
+ spin_unlock_irqrestore(&pinstance->resource_lock, lock_flags);
+ if (!sdev)
+ return FAILED;
+
+ sdev_printk(KERN_INFO, sdev,
"Doing bus reset due to an I/O command timeout.\n");
- return pmcraid_reset_device(scmd,
+ return pmcraid_reset_device(sdev,
PMCRAID_RESET_BUS_TIMEOUT,
RESET_DEVICE_BUS);
}
static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd)
{
- scmd_printk(KERN_INFO, scmd,
+ struct Scsi_Host *shost = scmd->device->host;
+ struct scsi_device *scsi_dev = NULL, *tmp;
+
+ shost_for_each_device(tmp, shost) {
+ if ((tmp->channel == scmd->device->channel) &&
+ (tmp->id == scmd->device->id)) {
+ scsi_dev = tmp;
+ break;
+ }
+ }
+ if (!scsi_dev)
+ return FAILED;
+ sdev_printk(KERN_INFO, scsi_dev,
"Doing target reset due to an I/O command timeout.\n");
- return pmcraid_reset_device(scmd,
+ return pmcraid_reset_device(scsi_dev,
PMCRAID_INTERNAL_TIMEOUT,
RESET_DEVICE_TARGET);
}
diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index 1619cc33034f..5058e01b65a2 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -112,6 +112,7 @@ struct qedf_ioreq {
#define QEDF_CMD_ERR_SCSI_DONE 0x5
u8 io_req_flags;
uint8_t tm_flags;
+ u64 tm_lun;
struct qedf_rport *fcport;
#define QEDF_CMD_ST_INACTIVE 0
#define QEDFC_CMD_ST_IO_ACTIVE 1
@@ -497,7 +498,7 @@ extern void qedf_process_warning_compl(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
extern void qedf_process_error_detect(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
-extern void qedf_flush_active_ios(struct qedf_rport *fcport, int lun);
+extern void qedf_flush_active_ios(struct qedf_rport *fcport, u64 lun);
extern void qedf_release_cmd(struct kref *ref);
extern int qedf_initiate_abts(struct qedf_ioreq *io_req,
bool return_scsi_cmd_on_abts);
@@ -522,7 +523,7 @@ extern int qedf_initiate_cleanup(struct qedf_ioreq *io_req,
bool return_scsi_cmd_on_abts);
extern void qedf_process_cleanup_compl(struct qedf_ctx *qedf,
struct fcoe_cqe *cqe, struct qedf_ioreq *io_req);
-extern int qedf_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags);
+extern int qedf_initiate_tmf(struct fc_rport *rport, u64 lun, u8 tm_flags);
extern void qedf_process_tmf_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
struct qedf_ioreq *io_req);
extern void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe);
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index 10fe3383855c..bf921caaf6ae 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -546,7 +546,7 @@ static int qedf_build_bd_list_from_sg(struct qedf_ioreq *io_req)
}
static void qedf_build_fcp_cmnd(struct qedf_ioreq *io_req,
- struct fcp_cmnd *fcp_cmnd)
+ struct fcp_cmnd *fcp_cmnd)
{
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
@@ -554,8 +554,12 @@ static void qedf_build_fcp_cmnd(struct qedf_ioreq *io_req,
memset(fcp_cmnd, 0, FCP_CMND_LEN);
/* 8 bytes: SCSI LUN info */
- int_to_scsilun(sc_cmd->device->lun,
- (struct scsi_lun *)&fcp_cmnd->fc_lun);
+ if (io_req->cmd_type == QEDF_TASK_MGMT_CMD)
+ int_to_scsilun(io_req->tm_lun,
+ (struct scsi_lun *)&fcp_cmnd->fc_lun);
+ else
+ int_to_scsilun(sc_cmd->device->lun,
+ (struct scsi_lun *)&fcp_cmnd->fc_lun);
/* 4 bytes: flag info */
fcp_cmnd->fc_pri_ta = 0;
@@ -1095,7 +1099,7 @@ static void qedf_parse_fcp_rsp(struct qedf_ioreq *io_req,
}
/* The sense buffer can be NULL for TMF commands */
- if (sc_cmd->sense_buffer) {
+ if (sc_cmd && sc_cmd->sense_buffer) {
memset(sc_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
if (fcp_sns_len)
memcpy(sc_cmd->sense_buffer, sense_data,
@@ -1580,7 +1584,7 @@ static void qedf_flush_els_req(struct qedf_ctx *qedf,
/* A value of -1 for lun is a wild card that means flush all
* active SCSI I/Os for the target.
*/
-void qedf_flush_active_ios(struct qedf_rport *fcport, int lun)
+void qedf_flush_active_ios(struct qedf_rport *fcport, u64 lun)
{
struct qedf_ioreq *io_req;
struct qedf_ctx *qedf;
@@ -1768,10 +1772,6 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun)
kref_put(&io_req->refcount, qedf_release_cmd);
continue;
}
- if (lun > -1) {
- if (io_req->lun != lun)
- continue;
- }
/*
* Use kref_get_unless_zero in the unlikely case the command
@@ -2287,7 +2287,7 @@ void qedf_process_cleanup_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
complete(&io_req->cleanup_done);
}
-static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
+static int qedf_execute_tmf(struct qedf_rport *fcport, u64 tm_lun,
uint8_t tm_flags)
{
struct qedf_ioreq *io_req;
@@ -2297,17 +2297,10 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
int rc = 0;
uint16_t xid;
int tmo = 0;
- int lun = 0;
unsigned long flags;
struct fcoe_wqe *sqe;
u16 sqe_idx;
- if (!sc_cmd) {
- QEDF_ERR(&qedf->dbg_ctx, "sc_cmd is NULL\n");
- return FAILED;
- }
-
- lun = (int)sc_cmd->device->lun;
if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) {
QEDF_ERR(&(qedf->dbg_ctx), "fcport not offloaded\n");
rc = FAILED;
@@ -2327,7 +2320,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
qedf->target_resets++;
/* Initialize rest of io_req fields */
- io_req->sc_cmd = sc_cmd;
+ io_req->sc_cmd = NULL;
io_req->fcport = fcport;
io_req->cmd_type = QEDF_TASK_MGMT_CMD;
@@ -2341,6 +2334,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
/* Default is to return a SCSI command when an error occurs */
io_req->return_scsi_cmd_on_abts = false;
+ io_req->tm_lun = tm_lun;
/* Obtain exchange id */
xid = io_req->xid;
@@ -2395,7 +2389,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
if (tm_flags == FCP_TMF_LUN_RESET)
- qedf_flush_active_ios(fcport, lun);
+ qedf_flush_active_ios(fcport, tm_lun);
else
qedf_flush_active_ios(fcport, -1);
@@ -2410,23 +2404,18 @@ no_flush:
return rc;
}
-int qedf_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
+int qedf_initiate_tmf(struct fc_rport *rport, u64 lun, u8 tm_flags)
{
- struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
struct fc_rport_libfc_priv *rp = rport->dd_data;
struct qedf_rport *fcport = (struct qedf_rport *)&rp[1];
- struct qedf_ctx *qedf;
- struct fc_lport *lport = shost_priv(sc_cmd->device->host);
+ struct qedf_ctx *qedf = fcport->qedf;
+ struct fc_lport *lport = rp->local_port;
int rc = SUCCESS;
- int rval;
- struct qedf_ioreq *io_req = NULL;
- int ref_cnt = 0;
struct fc_rport_priv *rdata = fcport->rdata;
QEDF_ERR(NULL,
- "tm_flags 0x%x sc_cmd %p op = 0x%02x target_id = 0x%x lun=%d\n",
- tm_flags, sc_cmd, sc_cmd->cmd_len ? sc_cmd->cmnd[0] : 0xff,
- rport->scsi_target_id, (int)sc_cmd->device->lun);
+ "tm_flags 0x%x target_id = 0x%x lun=%llu\n",
+ tm_flags, rport->scsi_target_id, lun);
if (!rdata || !kref_get_unless_zero(&rdata->kref)) {
QEDF_ERR(NULL, "stale rport\n");
@@ -2437,33 +2426,10 @@ int qedf_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
(tm_flags == FCP_TMF_TGT_RESET) ? "TARGET RESET" :
"LUN RESET");
- if (qedf_priv(sc_cmd)->io_req) {
- io_req = qedf_priv(sc_cmd)->io_req;
- ref_cnt = kref_read(&io_req->refcount);
- QEDF_ERR(NULL,
- "orig io_req = %p xid = 0x%x ref_cnt = %d.\n",
- io_req, io_req->xid, ref_cnt);
- }
-
- rval = fc_remote_port_chkready(rport);
- if (rval) {
- QEDF_ERR(NULL, "device_reset rport not ready\n");
- rc = FAILED;
- goto tmf_err;
- }
-
- rc = fc_block_scsi_eh(sc_cmd);
+ rc = fc_block_rport(rport);
if (rc)
goto tmf_err;
- if (!fcport) {
- QEDF_ERR(NULL, "device_reset: rport is NULL\n");
- rc = FAILED;
- goto tmf_err;
- }
-
- qedf = fcport->qedf;
-
if (!qedf) {
QEDF_ERR(NULL, "qedf is NULL.\n");
rc = FAILED;
@@ -2500,7 +2466,7 @@ int qedf_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
goto tmf_err;
}
- rc = qedf_execute_tmf(fcport, sc_cmd, tm_flags);
+ rc = qedf_execute_tmf(fcport, lun, tm_flags);
tmf_err:
kref_put(&rdata->kref, fc_rport_destroy);
@@ -2517,7 +2483,6 @@ void qedf_process_tmf_compl(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
fcp_rsp = &cqe->cqe_info.rsp_info;
qedf_parse_fcp_rsp(io_req, fcp_rsp);
- io_req->sc_cmd = NULL;
complete(&io_req->tm_done);
}
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 91f3f1d7098e..a58353b7b4e8 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -774,7 +774,7 @@ static int qedf_eh_abort(struct scsi_cmnd *sc_cmd)
goto drop_rdata_kref;
}
- rc = fc_block_scsi_eh(sc_cmd);
+ rc = fc_block_rport(rport);
if (rc)
goto drop_rdata_kref;
@@ -858,18 +858,19 @@ out:
static int qedf_eh_target_reset(struct scsi_cmnd *sc_cmd)
{
- QEDF_ERR(NULL, "%d:0:%d:%lld: TARGET RESET Issued...",
- sc_cmd->device->host->host_no, sc_cmd->device->id,
- sc_cmd->device->lun);
- return qedf_initiate_tmf(sc_cmd, FCP_TMF_TGT_RESET);
+ struct scsi_target *starget = scsi_target(sc_cmd->device);
+ struct fc_rport *rport = starget_to_rport(starget);
+
+ QEDF_ERR(NULL, "TARGET RESET Issued...");
+ return qedf_initiate_tmf(rport, 0, FCP_TMF_TGT_RESET);
}
static int qedf_eh_device_reset(struct scsi_cmnd *sc_cmd)
{
- QEDF_ERR(NULL, "%d:0:%d:%lld: LUN RESET Issued... ",
- sc_cmd->device->host->host_no, sc_cmd->device->id,
- sc_cmd->device->lun);
- return qedf_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
+ struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+
+ QEDF_ERR(NULL, "LUN RESET Issued...\n");
+ return qedf_initiate_tmf(rport, sc_cmd->device->lun, FCP_TMF_LUN_RESET);
}
bool qedf_wait_for_upload(struct qedf_ctx *qedf)
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 6e5e89aaa283..27bce80262c2 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -716,7 +716,6 @@ enum action {
ABORT_COMMAND,
DEVICE_RESET,
BUS_RESET,
- ADAPTER_RESET,
};
@@ -898,22 +897,9 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
}
break;
- case ADAPTER_RESET:
default:
- if (qla1280_verbose) {
- printk(KERN_INFO
- "scsi(%ld): Issued ADAPTER RESET\n",
- ha->host_no);
- printk(KERN_INFO "scsi(%ld): I/O processing will "
- "continue automatically\n", ha->host_no);
- }
- ha->flags.reset_active = 1;
-
- if (qla1280_abort_isp(ha) != 0) { /* it's dead */
- result = FAILED;
- }
-
- ha->flags.reset_active = 0;
+ dprintk(1, "RESET invalid action %d\n", action);
+ return FAILED;
}
/*
@@ -1011,11 +997,27 @@ qla1280_eh_bus_reset(struct scsi_cmnd *cmd)
static int
qla1280_eh_adapter_reset(struct scsi_cmnd *cmd)
{
- int rc;
+ int rc = SUCCESS;
+ struct Scsi_Host *shost = cmd->device->host;
+ struct scsi_qla_host *ha = (struct scsi_qla_host *)shost->hostdata;
- spin_lock_irq(cmd->device->host->host_lock);
- rc = qla1280_error_action(cmd, ADAPTER_RESET);
- spin_unlock_irq(cmd->device->host->host_lock);
+ spin_lock_irq(shost->host_lock);
+ if (qla1280_verbose) {
+ printk(KERN_INFO
+ "scsi(%ld): Issued ADAPTER RESET\n",
+ ha->host_no);
+ printk(KERN_INFO "scsi(%ld): I/O processing will "
+ "continue automatically\n", ha->host_no);
+ }
+ ha->flags.reset_active = 1;
+
+ if (qla1280_abort_isp(ha) != 0) { /* it's dead */
+ rc = FAILED;
+ }
+
+ ha->flags.reset_active = 0;
+
+ spin_unlock_irq(shost->host_lock);
return rc;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 17491ba10439..a2560cc807d3 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -559,14 +559,15 @@ 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
/*
* Generic method for our eh processing.
* The 'op' argument tells what we have to do.
*/
-static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
+/*
+ * Error handlers called from the eh thread (one thread per HBA).
+ */
+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;
@@ -578,37 +579,13 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
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");
- /* We may be in an error condition because the PCI bus
- * went down. In this case, we need to wait until the
- * PCI bus is reset, the card is reset, and only then
- * proceed with the scsi error recovery. There's no
- * point in hurrying; take a leisurely wait.
+ /*
+ * Escalate to host reset if the PCI bus went down
*/
-#define WAIT_FOR_PCI_RECOVERY 35
- if (pci_channel_offline(pdev)) {
- int finished_reset = 0;
- init_completion(&eh_done);
- spin_lock_irq(shost->host_lock);
- /* Make sure we didn't race */
- if (pci_channel_offline(pdev)) {
- BUG_ON(sym_data->io_reset);
- sym_data->io_reset = &eh_done;
- } else {
- finished_reset = 1;
- }
- spin_unlock_irq(shost->host_lock);
- if (!finished_reset)
- finished_reset = wait_for_completion_timeout
- (sym_data->io_reset,
- WAIT_FOR_PCI_RECOVERY*HZ);
- spin_lock_irq(shost->host_lock);
- sym_data->io_reset = NULL;
- spin_unlock_irq(shost->host_lock);
- if (!finished_reset)
- return SCSI_FAILED;
- }
+ if (pci_channel_offline(pdev))
+ return SCSI_FAILED;
spin_lock_irq(shost->host_lock);
/* This one is queued in some place -> to wait for completion */
@@ -620,28 +597,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
}
}
- /* 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;
- case SYM_EH_BUS_RESET:
- 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;
- }
-
+ sts = sym_abort_scsiio(np, cmd, 1);
/* On error, restore everything and cross fingers :) */
if (sts)
cmd_queued = 0;
@@ -658,33 +614,130 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
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)
{
- return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
-}
+ 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;
-static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
-{
- return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+ 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 SCSI_FAILED;
+
+ 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;
+
+ 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)
{
- return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", 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;
+
+ scmd_printk(KERN_WARNING, cmd, "BUS RESET operation started\n");
+
+ /*
+ * Escalate to host reset if the PCI bus went down
+ */
+ if (pci_channel_offline(pdev))
+ return SCSI_FAILED;
+
+ spin_lock_irq(shost->host_lock);
+ sym_reset_scsi_bus(np, 1);
+ spin_unlock_irq(shost->host_lock);
+
+ dev_warn(&cmd->device->sdev_gendev, "BUS RESET operation complete.\n");
+ return SCSI_SUCCESS;
}
static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
{
- return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", 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;
+ struct completion eh_done;
+ int finished_reset = 1;
+
+ 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
+ * PCI bus is reset, the card is reset, and only then
+ * proceed with the scsi error recovery. There's no
+ * point in hurrying; take a leisurely wait.
+ */
+#define WAIT_FOR_PCI_RECOVERY 35
+ if (pci_channel_offline(pdev)) {
+ init_completion(&eh_done);
+ spin_lock_irq(shost->host_lock);
+ /* Make sure we didn't race */
+ if (pci_channel_offline(pdev)) {
+ BUG_ON(sym_data->io_reset);
+ sym_data->io_reset = &eh_done;
+ finished_reset = 0;
+ }
+ spin_unlock_irq(shost->host_lock);
+ if (!finished_reset)
+ finished_reset = wait_for_completion_timeout
+ (sym_data->io_reset,
+ WAIT_FOR_PCI_RECOVERY*HZ);
+ spin_lock_irq(shost->host_lock);
+ sym_data->io_reset = NULL;
+ spin_unlock_irq(shost->host_lock);
+ }
+
+ if (finished_reset) {
+ sym_reset_scsi_bus(np, 0);
+ sym_start_up(shost, 1);
+ }
+
+ shost_printk(KERN_WARNING, shost, "HOST RESET operation %s.\n",
+ finished_reset==1 ? "complete" : "failed");
+ return finished_reset ? SCSI_SUCCESS : SCSI_FAILED;
}
/*
@@ -1635,7 +1688,7 @@ static const 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,