[SCSI] lpfc 8.1.12 : Round 2 of Miscellaneous fixes

Round 2 of Miscellaneous fixes:
 - Ensure we don't prematurely re-enable IRQs in lpfc_sli_abort_fcp_cmpl().
 - Prevent freeing of iocb after IOCB_TIMEDOUT error.
 - Added code to cleanup REG_LOGIN mailbox command when a LOGO is received.
 - Fix offline window where more work can sneak in after clearing work_ha
 - Use target reset instead of LU reset in bus_device_reset_handler
 - Fixed system hangs due to leaked host_lock.
 - Fixed NULL pointer dereference during I/O with LIP.
 - Fixed false iocb timeout.
 - Fixed name server query response handling.
 - Change rport dev_loss_tmo value when user change lpfc HBA's dev_loss_tmo.
 - Fixed a memory leak in lpfc_sli_wake_mbox_wait.
 - Fixed check for dropped frames.
 - Removed hba queue depth calculation based on device PCI IDs
 - Change min cr_count value specified in comment to agree with setting

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 28dbd6b..efd1cf6 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -292,13 +292,13 @@
 }
 
 static void
-lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
+lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
 {
 	struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
 	struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
 	struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
 	struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
-	uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm;
+	uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
 	uint32_t resp_info = fcprsp->rspStatus2;
 	uint32_t scsi_status = fcprsp->rspStatus3;
 	uint32_t *lp;
@@ -360,6 +360,24 @@
 				fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
 
 		/*
+		 * If there is an under run check if under run reported by
+		 * storage array is same as the under run reported by HBA.
+		 * If this is not same, there is a dropped frame.
+		 */
+		if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
+			fcpi_parm &&
+			(cmnd->resid != fcpi_parm)) {
+			lpfc_printf_log(phba, KERN_WARNING,
+				LOG_FCP | LOG_FCP_ERROR,
+				"%d:0735 FCP Read Check Error and Underrun "
+				"Data: x%x x%x x%x x%x\n", phba->brd_no,
+				be32_to_cpu(fcpcmd->fcpDl),
+				cmnd->resid,
+				fcpi_parm, cmnd->cmnd[0]);
+			cmnd->resid = cmnd->request_bufflen;
+			host_status = DID_ERROR;
+		}
+		/*
 		 * The cmnd->underflow is the minimum number of bytes that must
 		 * be transfered for this command.  Provided a sense condition
 		 * is not present, make sure the actual amount transferred is at
@@ -439,7 +457,7 @@
 		switch (lpfc_cmd->status) {
 		case IOSTAT_FCP_RSP_ERROR:
 			/* Call FCP RSP handler to determine result */
-			lpfc_handle_fcp_err(lpfc_cmd);
+			lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
 			break;
 		case IOSTAT_NPORT_BSY:
 		case IOSTAT_FABRIC_BSY:
@@ -673,6 +691,18 @@
 	return (1);
 }
 
+static void
+lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
+			struct lpfc_iocbq *cmdiocbq,
+			struct lpfc_iocbq *rspiocbq)
+{
+	struct lpfc_scsi_buf *lpfc_cmd =
+		(struct lpfc_scsi_buf *) cmdiocbq->context1;
+	if (lpfc_cmd)
+		lpfc_release_scsi_buf(phba, lpfc_cmd);
+	return;
+}
+
 static int
 lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
 		    unsigned  tgt_id, unsigned int lun,
@@ -709,8 +739,9 @@
 				       &phba->sli.ring[phba->sli.fcp_ring],
 				       iocbq, iocbqrsp, lpfc_cmd->timeout);
 	if (ret != IOCB_SUCCESS) {
+		if (ret == IOCB_TIMEDOUT)
+			iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
 		lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
-		ret = FAILED;
 	} else {
 		ret = SUCCESS;
 		lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
@@ -977,7 +1008,7 @@
 }
 
 static int
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
 {
 	struct Scsi_Host *shost = cmnd->device->host;
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
@@ -987,6 +1018,7 @@
 	struct lpfc_nodelist *pnode = rdata->pnode;
 	uint32_t cmd_result = 0, cmd_status = 0;
 	int ret = FAILED;
+	int iocb_status = IOCB_SUCCESS;
 	int cnt, loopcnt;
 
 	lpfc_block_error_handler(cmnd);
@@ -998,7 +1030,7 @@
 	 */
 	while ( 1 ) {
 		if (!pnode)
-			return FAILED;
+			goto out;
 
 		if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
 			spin_unlock_irq(phba->host->host_lock);
@@ -1016,7 +1048,7 @@
 			}
 			pnode = rdata->pnode;
 			if (!pnode)
-				return FAILED;
+				goto out;
 		}
 		if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
 			break;
@@ -1031,7 +1063,7 @@
 	lpfc_cmd->rdata = rdata;
 
 	ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
-					   FCP_LUN_RESET);
+					   FCP_TARGET_RESET);
 	if (!ret)
 		goto out_free_scsi_buf;
 
@@ -1043,16 +1075,21 @@
 		goto out_free_scsi_buf;
 
 	lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
-			"%d:0703 Issue LUN Reset to TGT %d LUN %d "
-			"Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
+			"%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
+			"nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
 			cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
 
-	ret = lpfc_sli_issue_iocb_wait(phba,
+	iocb_status = lpfc_sli_issue_iocb_wait(phba,
 				       &phba->sli.ring[phba->sli.fcp_ring],
 				       iocbq, iocbqrsp, lpfc_cmd->timeout);
-	if (ret == IOCB_SUCCESS)
-		ret = SUCCESS;
 
+	if (iocb_status == IOCB_TIMEDOUT)
+		iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
+
+	if (iocb_status == IOCB_SUCCESS)
+		ret = SUCCESS;
+	else
+		ret = iocb_status;
 
 	cmd_result = iocbqrsp->iocb.un.ulpWord[4];
 	cmd_status = iocbqrsp->iocb.ulpStatus;
@@ -1090,18 +1127,19 @@
 
 	if (cnt) {
 		lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-			"%d:0719 LUN Reset I/O flush failure: cnt x%x\n",
+			"%d:0719 device reset I/O flush failure: cnt x%x\n",
 			phba->brd_no, cnt);
 		ret = FAILED;
 	}
 
 out_free_scsi_buf:
-	lpfc_release_scsi_buf(phba, lpfc_cmd);
-
+	if (iocb_status != IOCB_TIMEDOUT) {
+		lpfc_release_scsi_buf(phba, lpfc_cmd);
+	}
 	lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-			"%d:0713 SCSI layer issued LUN reset (%d, %d) "
-			"Data: x%x x%x x%x\n",
-			phba->brd_no, cmnd->device->id,cmnd->device->lun,
+			"%d:0713 SCSI layer issued device reset (%d, %d) "
+			"return x%x status x%x result x%x\n",
+			phba->brd_no, cmnd->device->id, cmnd->device->lun,
 			ret, cmd_status, cmd_result);
 
 out:
@@ -1110,7 +1148,7 @@
 }
 
 static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
 {
 	struct Scsi_Host *shost = cmnd->device->host;
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
@@ -1155,13 +1193,17 @@
 				"%d:0700 Bus Reset on target %d failed\n",
 				phba->brd_no, i);
 			err_count++;
+			break;
 		}
 	}
 
+	if (ret != IOCB_TIMEDOUT)
+		lpfc_release_scsi_buf(phba, lpfc_cmd);
+
 	if (err_count == 0)
 		ret = SUCCESS;
-
-	lpfc_release_scsi_buf(phba, lpfc_cmd);
+	else
+		ret = FAILED;
 
 	/*
 	 * All outstanding txcmplq I/Os should have been aborted by
@@ -1302,8 +1344,8 @@
 	.info			= lpfc_info,
 	.queuecommand		= lpfc_queuecommand,
 	.eh_abort_handler	= lpfc_abort_handler,
-	.eh_device_reset_handler= lpfc_reset_lun_handler,
-	.eh_bus_reset_handler	= lpfc_reset_bus_handler,
+	.eh_device_reset_handler= lpfc_device_reset_handler,
+	.eh_bus_reset_handler	= lpfc_bus_reset_handler,
 	.slave_alloc		= lpfc_slave_alloc,
 	.slave_configure	= lpfc_slave_configure,
 	.slave_destroy		= lpfc_slave_destroy,