summaryrefslogtreecommitdiff
path: root/drivers/scsi/snic/snic_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/snic/snic_scsi.c')
-rw-r--r--drivers/scsi/snic/snic_scsi.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c
index 2c7b4c321cbe..abada16b375b 100644
--- a/drivers/scsi/snic/snic_scsi.c
+++ b/drivers/scsi/snic/snic_scsi.c
@@ -221,11 +221,15 @@ snic_queue_icmnd_req(struct snic *snic,
pa, /* sense buffer pa */
SCSI_SENSE_BUFFERSIZE);
+ atomic64_inc(&snic->s_stats.io.active);
ret = snic_queue_wq_desc(snic, rqi->req, rqi->req_len);
- if (ret)
+ if (ret) {
+ atomic64_dec(&snic->s_stats.io.active);
SNIC_HOST_ERR(snic->shost,
"QIcmnd: Queuing Icmnd Failed. ret = %d\n",
ret);
+ } else
+ snic_stats_update_active_ios(&snic->s_stats);
return ret;
} /* end of snic_queue_icmnd_req */
@@ -361,8 +365,7 @@ snic_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc)
if (ret) {
SNIC_HOST_ERR(shost, "Failed to Q, Scsi Req w/ err %d.\n", ret);
ret = SCSI_MLQUEUE_HOST_BUSY;
- } else
- snic_stats_update_active_ios(&snic->s_stats);
+ }
atomic_dec(&snic->ios_inflight);
@@ -598,6 +601,12 @@ snic_icmnd_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
sc->device->lun, sc, sc->cmnd[0], snic_cmd_tag(sc),
CMD_FLAGS(sc), rqi);
+ if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) {
+ spin_unlock_irqrestore(io_lock, flags);
+
+ return;
+ }
+
SNIC_BUG_ON(rqi != (struct snic_req_info *)ctx);
WARN_ON_ONCE(req);
if (!rqi) {
@@ -779,6 +788,11 @@ snic_process_itmf_cmpl(struct snic *snic,
io_lock = snic_io_lock_hash(snic, sc);
spin_lock_irqsave(io_lock, flags);
+ if (CMD_FLAGS(sc) & SNIC_HOST_RESET_CMD_TERM) {
+ spin_unlock_irqrestore(io_lock, flags);
+
+ return ret;
+ }
rqi = (struct snic_req_info *) CMD_SP(sc);
WARN_ON_ONCE(!rqi);
@@ -1001,10 +1015,11 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
unsigned long flags, gflags;
int ret = 0;
+ snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
SNIC_HOST_INFO(snic->shost,
- "reset_cmpl:HBA Reset Completion received.\n");
+ "reset_cmpl:Tag %d ctx %lx cmpl status %s HBA Reset Completion received.\n",
+ cmnd_id, ctx, snic_io_status_to_str(hdr_stat));
- snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
SNIC_SCSI_DBG(snic->shost,
"reset_cmpl: type = %x, hdr_stat = %x, cmnd_id = %x, hid = %x, ctx = %lx\n",
typ, hdr_stat, cmnd_id, hid, ctx);
@@ -1012,6 +1027,9 @@ snic_hba_reset_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
/* spl case, host reset issued through ioctl */
if (cmnd_id == SCSI_NO_TAG) {
rqi = (struct snic_req_info *) ctx;
+ SNIC_HOST_INFO(snic->shost,
+ "reset_cmpl:Tag %d ctx %lx cmpl stat %s\n",
+ cmnd_id, ctx, snic_io_status_to_str(hdr_stat));
sc = rqi->sc;
goto ioctl_hba_rst;
@@ -1038,6 +1056,10 @@ ioctl_hba_rst:
return ret;
}
+ SNIC_HOST_INFO(snic->shost,
+ "reset_cmpl: sc %p rqi %p Tag %d flags 0x%llx\n",
+ sc, rqi, cmnd_id, CMD_FLAGS(sc));
+
io_lock = snic_io_lock_hash(snic, sc);
spin_lock_irqsave(io_lock, flags);
@@ -1454,11 +1476,19 @@ snic_abort_finish(struct snic *snic, struct scsi_cmnd *sc)
case SNIC_STAT_IO_SUCCESS:
case SNIC_STAT_IO_NOT_FOUND:
ret = SUCCESS;
+ /*
+ * If abort path doesn't call scsi_done(),
+ * the # IO timeouts == 2, will cause the LUN offline.
+ * Call scsi_done to complete the IO.
+ */
+ sc->result = (DID_ERROR << 16);
+ sc->scsi_done(sc);
break;
default:
/* Firmware completed abort with error */
ret = FAILED;
+ rqi = NULL;
break;
}
@@ -1554,6 +1584,7 @@ snic_send_abort_and_wait(struct snic *snic, struct scsi_cmnd *sc)
/* Now Queue the abort command to firmware */
ret = snic_queue_abort_req(snic, rqi, sc, tmf);
if (ret) {
+ atomic64_inc(&snic->s_stats.abts.q_fail);
SNIC_HOST_ERR(snic->shost,
"send_abt_cmd: IO w/ Tag 0x%x fail w/ err %d flags 0x%llx\n",
tag, ret, CMD_FLAGS(sc));
@@ -1830,6 +1861,9 @@ snic_dr_clean_single_req(struct snic *snic,
snic_release_req_buf(snic, rqi, sc);
+ sc->result = (DID_ERROR << 16);
+ sc->scsi_done(sc);
+
ret = 0;
return ret;
@@ -2384,6 +2418,13 @@ snic_cmpl_pending_tmreq(struct snic *snic, struct scsi_cmnd *sc)
"Completing Pending TM Req sc %p, state %s flags 0x%llx\n",
sc, snic_io_status_to_str(CMD_STATE(sc)), CMD_FLAGS(sc));
+ /*
+ * CASE : FW didn't post itmf completion due to PCIe Errors.
+ * Marking the abort status as Success to call scsi completion
+ * in snic_abort_finish()
+ */
+ CMD_ABTS_STATUS(sc) = SNIC_STAT_IO_SUCCESS;
+
rqi = (struct snic_req_info *) CMD_SP(sc);
if (!rqi)
return;
@@ -2459,8 +2500,9 @@ snic_scsi_cleanup(struct snic *snic, int ex_tag)
cleanup:
sc->result = DID_TRANSPORT_DISRUPTED << 16;
SNIC_HOST_INFO(snic->shost,
- "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p. rqi %p duration %llu msecs\n",
- sc, rqi, (jiffies - st_time));
+ "sc_clean: DID_TRANSPORT_DISRUPTED for sc %p, Tag %d flags 0x%llx rqi %p duration %u msecs\n",
+ sc, sc->request->tag, CMD_FLAGS(sc), rqi,
+ jiffies_to_msecs(jiffies - st_time));
/* Update IO stats */
snic_stats_update_io_cmpl(&snic->s_stats);