Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd2c6191 authored by Eric Moore's avatar Eric Moore Committed by James Bottomley
Browse files

[SCSI] fusion - error handling bug fix's



misc error handling bug fix's
- properly interpret iocstatus returned after task management request
- clear tmState after a failed doorbell
- cleanup mptscsih_taskmgmt_complete

Signed-off-by: default avatarEric Moore <Eric.Moore@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 2ecce492
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -3219,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
	u32 diag1val = 0;
	u32 diag1val = 0;
#endif
#endif


	/* Clear any existing interrupts */
	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);

	if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
	if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) {
		drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
		drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset "
			"address=%p\n",  ioc->name, __FUNCTION__,
			"address=%p\n",  ioc->name, __FUNCTION__,
@@ -3238,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
			        " count=%d\n",
			        " count=%d\n",
				ioc->name, doorbell, count));
				ioc->name, doorbell, count));
			if (doorbell == MPI_IOC_STATE_READY) {
			if (doorbell == MPI_IOC_STATE_READY) {
				return 0;
				return 1;
			}
			}


			/* wait 1 sec */
			/* wait 1 sec */
@@ -3250,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
		return -1;
		return -1;
	}
	}


	/* Clear any existing interrupts */
	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);

	/* Use "Diagnostic reset" method! (only thing available!) */
	/* Use "Diagnostic reset" method! (only thing available!) */
	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);


@@ -3968,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
		}
		}
	} else {
	} else {
		while (--cntdn) {
		while (--cntdn) {
			mdelay (1);
			udelay (1000);
			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
				break;
				break;
@@ -4020,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
				break;
				break;
			mdelay(1);
			udelay (1000);
			count++;
			count++;
		}
		}
	}
	}
+1 −1
Original line number Original line Diff line number Diff line
@@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
		 */
		 */
		dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
		dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
			 ioctl->ioc->name));
			 ioctl->ioc->name));
		mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
		mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP);
	}
	}
	return;
	return;


+145 −150
Original line number Original line Diff line number Diff line
@@ -1536,7 +1536,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
 */
 */


/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
/**
 *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
 *	mptscsih_TMHandler - Generic handler for SCSI Task Management.
 *	Fall through to mpt_HardResetHandler if: not operational, too many
 *	Fall through to mpt_HardResetHandler if: not operational, too many
 *	failed TM requests or handshake failure.
 *	failed TM requests or handshake failure.
@@ -1552,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
 *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
 *	Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
 *	will be active.
 *	will be active.
 *
 *
 *	Returns 0 for SUCCESS or -1 if FAILED.
 *	Returns 0 for SUCCESS, or FAILED.
 */
 **/
int
int
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
{
{
	MPT_ADAPTER	*ioc;
	MPT_ADAPTER	*ioc;
	int		 rc = -1;
	int		 rc = -1;
	int		 doTask = 1;
	u32		 ioc_raw_state;
	u32		 ioc_raw_state;
	unsigned long	 flags;
	unsigned long	 flags;


	/* If FW is being reloaded currently, return success to
	 * the calling function.
	 */
	if (hd == NULL)
		return 0;

	ioc = hd->ioc;
	ioc = hd->ioc;
	if (ioc == NULL) {
		printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
		return FAILED;
	}
	dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
	dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));


	// SJR - CHECKME - Can we avoid this here?
	// SJR - CHECKME - Can we avoid this here?
@@ -1586,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
	spin_unlock_irqrestore(&ioc->diagLock, flags);
	spin_unlock_irqrestore(&ioc->diagLock, flags);


	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
	 *  If we time out and not bus reset, then we return a FAILED status to the caller.
	 *  If we time out and not bus reset, then we return a FAILED status
	 *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
	 *  to the caller.
	 *  The call to mptscsih_tm_pending_wait() will set the pending flag
	 *  if we are
	 *  successful. Otherwise, reload the FW.
	 *  successful. Otherwise, reload the FW.
	 */
	 */
	if (mptscsih_tm_pending_wait(hd) == FAILED) {
	if (mptscsih_tm_pending_wait(hd) == FAILED) {
@@ -1597,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
			   hd->ioc->name, hd->tmPending));
			   hd->ioc->name, hd->tmPending));
			return FAILED;
			return FAILED;
		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target "
			   "Timed out waiting for last TM (%d) to complete! \n",
				"reset: Timed out waiting for last TM (%d) "
			   hd->ioc->name, hd->tmPending));
				"to complete! \n", hd->ioc->name,
				hd->tmPending));
			return FAILED;
			return FAILED;
		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
		} else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
			dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
			   "Timed out waiting for last TM (%d) to complete! \n",
			   "Timed out waiting for last TM (%d) to complete! \n",
			   hd->ioc->name, hd->tmPending));
			   hd->ioc->name, hd->tmPending));
			if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
			return FAILED;
			return FAILED;

			doTask = 0;
		}
		}
	} else {
	} else {
		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
@@ -1616,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
	}
	}


	/* Is operational?
	 */
	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
	ioc_raw_state = mpt_GetIocState(hd->ioc, 0);


#ifdef MPT_DEBUG_RESET
	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
	if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
		printk(MYIOC_s_WARN_FMT
		printk(MYIOC_s_WARN_FMT
			"TM Handler: IOC Not operational(0x%x)!\n",
			"TM Handler for type=%x: IOC Not operational (0x%x)!\n",
			hd->ioc->name, ioc_raw_state);
			ioc->name, type, ioc_raw_state);
		printk(KERN_WARNING " Issuing HardReset!!\n");
		if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0)
			printk((KERN_WARNING "TMHandler: HardReset "
				"FAILED!!\n"));
		return FAILED;
	}
	}
#endif


	if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
	if (ioc_raw_state & MPI_DOORBELL_ACTIVE) {
				&& !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
		printk(MYIOC_s_WARN_FMT
			"TM Handler for type=%x: ioc_state: "
			"DOORBELL_ACTIVE (0x%x)!\n",
			ioc->name, type, ioc_raw_state);
		return FAILED;
	}


	/* Isse the Task Mgmt request.
	/* Isse the Task Mgmt request.
	 */
	 */
	if (hd->hard_resets < -1)
	if (hd->hard_resets < -1)
		hd->hard_resets++;
		hd->hard_resets++;
		rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, ctx2abort, timeout);
		if (rc) {
			printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
		} else {
			dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
		}
	}


	/* Only fall through to the HRH if this is a bus reset
	rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun,
	 */
	    ctx2abort, timeout);
	if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
	if (rc)
		ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
		printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n",
		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
		       hd->ioc->name);
	else
		dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n",
			   hd->ioc->name));
			   hd->ioc->name));
		rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
	}

	/*
	 * Check IOCStatus from TM reply message
	 */
	 if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS)
		rc = FAILED;


	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
	dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));


@@ -1665,7 +1647,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c




/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
/**
 *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
 *	mptscsih_IssueTaskMgmt - Generic send Task Management function.
 *	@hd: Pointer to MPT_SCSI_HOST structure
 *	@hd: Pointer to MPT_SCSI_HOST structure
 *	@type: Task Management type
 *	@type: Task Management type
@@ -1678,9 +1660,9 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c
 *
 *
 *	Not all fields are meaningfull for all task types.
 *	Not all fields are meaningfull for all task types.
 *
 *
 *	Returns 0 for SUCCESS, -999 for "no msg frames",
 *	Returns 0 for SUCCESS, or FAILED.
 *	else other non-zero value returned.
 *
 */
 **/
static int
static int
mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout)
{
{
@@ -1720,32 +1702,52 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i


	pScsiTm->TaskMsgContext = ctx2abort;
	pScsiTm->TaskMsgContext = ctx2abort;


	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) "
			hd->ioc->name, ctx2abort, type));
		"type=%d\n", hd->ioc->name, ctx2abort, type));


	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);


	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
		CAN_SLEEP)) != 0) {
		dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!"
		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
			" (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd,
			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
			hd->ioc, mf, retval));
			hd->ioc, mf));
		goto fail_out;
		mpt_free_msg_frame(hd->ioc, mf);
		return retval;
	}
	}


	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
	if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
		dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
		dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!"
			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
			hd->ioc, mf));
			hd->ioc, mf));
		mpt_free_msg_frame(hd->ioc, mf);
		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
		dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
			 hd->ioc->name));
			 hd->ioc->name));
		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
		retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
		dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n",
			 hd->ioc->name, retval));
		goto fail_out;
	}
	}


	/*
	 * Handle success case, see if theres a non-zero ioc_status.
	 */
	if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS ||
	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED ||
	   hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED)
		retval = 0;
	else
		retval = FAILED;

	return retval;
	return retval;

 fail_out:

	/*
	 * Free task managment mf, and corresponding tm flags
	 */
	mpt_free_msg_frame(hd->ioc, mf);
	hd->tmPending = 0;
	hd->tmState = TM_STATE_NONE;
	return FAILED;
}
}


static int
static int
@@ -1770,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)
 *	(linux scsi_host_template.eh_abort_handler routine)
 *	(linux scsi_host_template.eh_abort_handler routine)
 *
 *
 *	Returns SUCCESS or FAILED.
 *	Returns SUCCESS or FAILED.
 */
 **/
int
int
mptscsih_abort(struct scsi_cmnd * SCpnt)
mptscsih_abort(struct scsi_cmnd * SCpnt)
{
{
@@ -1806,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
		return SUCCESS;
		return SUCCESS;
	}
	}


	if (hd->resetPending) {
	if (hd->resetPending)
		return FAILED;
		return FAILED;
	}


	if (hd->timeouts < -1)
	if (hd->timeouts < -1)
		hd->timeouts++;
		hd->timeouts++;
@@ -1835,9 +1836,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));
		ctx2abort, mptscsih_get_tm_timeout(hd->ioc));


	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
	if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx &&
	    SCpnt->serial_number == sn) {
	    SCpnt->serial_number == sn)
		retval = FAILED;
		retval = FAILED;
	}


	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
	printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
		hd->ioc->name,
		hd->ioc->name,
@@ -1845,11 +1845,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)


	if (retval == 0)
	if (retval == 0)
		return SUCCESS;
		return SUCCESS;

	else
	if(retval != FAILED ) {
		hd->tmPending = 0;
		hd->tmState = TM_STATE_NONE;
	}
		return FAILED;
		return FAILED;
}
}


@@ -1861,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 *	(linux scsi_host_template.eh_dev_reset_handler routine)
 *	(linux scsi_host_template.eh_dev_reset_handler routine)
 *
 *
 *	Returns SUCCESS or FAILED.
 *	Returns SUCCESS or FAILED.
 */
 **/
int
int
mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{
{
@@ -1896,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)


	if (retval == 0)
	if (retval == 0)
		return SUCCESS;
		return SUCCESS;

	else
	if(retval != FAILED ) {
		hd->tmPending = 0;
		hd->tmState = TM_STATE_NONE;
	}
		return FAILED;
		return FAILED;
}
}



/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
/**
 *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
 *	mptscsih_bus_reset - Perform a SCSI BUS_RESET!	new_eh variant
@@ -1912,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 *	(linux scsi_host_template.eh_bus_reset_handler routine)
 *	(linux scsi_host_template.eh_bus_reset_handler routine)
 *
 *
 *	Returns SUCCESS or FAILED.
 *	Returns SUCCESS or FAILED.
 */
 **/
int
int
mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{
{
@@ -1946,11 +1939,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)


	if (retval == 0)
	if (retval == 0)
		return SUCCESS;
		return SUCCESS;

	else
	if(retval != FAILED ) {
		hd->tmPending = 0;
		hd->tmState = TM_STATE_NONE;
	}
		return FAILED;
		return FAILED;
}
}


@@ -2034,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
/**
/**
 *	mptscsih_tm_wait_for_completion - wait for completion of TM task
 *	mptscsih_tm_wait_for_completion - wait for completion of TM task
 *	@hd: Pointer to MPT host structure.
 *	@hd: Pointer to MPT host structure.
 *	@timeout: timeout in seconds
 *
 *
 *	Returns {SUCCESS,FAILED}.
 *	Returns {SUCCESS,FAILED}.
 */
 */
@@ -2108,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code)
 *	load/init time via the mpt_register() API call.
 *	load/init time via the mpt_register() API call.
 *
 *
 *	Returns 1 indicating alloc'd request frame ptr should be freed.
 *	Returns 1 indicating alloc'd request frame ptr should be freed.
 */
 **/
int
int
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
{
@@ -2118,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
	unsigned long		 flags;
	unsigned long		 flags;
	u16			 iocstatus;
	u16			 iocstatus;
	u8			 tmType;
	u8			 tmType;
	u32			 termination_count;


	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
	    ioc->name, mf, mr));
	    ioc->name, mf, mr));
	if (ioc->sh) {
	if (!ioc->sh) {
		/* Depending on the thread, a timer is activated for
		dtmprintk((MYIOC_s_WARN_FMT
		 * the TM request.  Delete this timer on completion of TM.
		    "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name));
		 * Decrement count of outstanding TM requests.
		 */
		hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
	} else {
		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
			ioc->name));
		return 1;
		return 1;
	}
	}


	if (mr == NULL) {
	if (mr == NULL) {
		dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
		dtmprintk((MYIOC_s_WARN_FMT
			ioc->name, mf));
		    "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf));
		return 1;
		return 1;
	} else {
	}

	hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
	pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
	pScsiTmReq = (SCSITaskMgmt_t*)mf;
	pScsiTmReq = (SCSITaskMgmt_t*)mf;

		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
	tmType = pScsiTmReq->TaskType;
	tmType = pScsiTmReq->TaskType;
	iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
	termination_count = le32_to_cpu(pScsiTmReply->TerminationCount);


	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
	if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 &&
	    pScsiTmReply->ResponseCode)
	    pScsiTmReply->ResponseCode)
		mptscsih_taskmgmt_response_code(ioc,
		mptscsih_taskmgmt_response_code(ioc,
		    pScsiTmReply->ResponseCode);
		    pScsiTmReply->ResponseCode);

		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
	DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
	DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);


		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
#if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM)
		hd->tm_iocstatus = iocstatus;
	printk("%s: ha=%d [%d:%d:0] task_type=0x%02X "
		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
	    "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X "
			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
	    "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus,
	    pScsiTmReply->TargetID, pScsiTmReq->TaskType,
	    le16_to_cpu(pScsiTmReply->IOCStatus),
	    le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode,
	    le32_to_cpu(pScsiTmReply->TerminationCount));
#endif
	if (!iocstatus) {
		dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
			hd->abortSCpnt = NULL;
		goto out;
	}

	/* Error?  (anything non-zero?) */
	/* Error?  (anything non-zero?) */
		if (iocstatus) {


	/* clear flags and continue.
	/* clear flags and continue.
	 */
	 */
			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
	switch (tmType) {

	case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
		if (termination_count == 1)
			iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED;
		hd->abortSCpnt = NULL;
		hd->abortSCpnt = NULL;
		break;

	case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:


		/* If an internal command is present
		/* If an internal command is present
		 * or the TM failed - reload the FW.
		 * or the TM failed - reload the FW.
		 * FC FW may respond FAILED to an ABORT
		 * FC FW may respond FAILED to an ABORT
		 */
		 */
			if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
		if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED ||
				if ((hd->cmdPtr) ||
		    hd->cmdPtr)
				    (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
			if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0)
					if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
				printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
						printk((KERN_WARNING
		break;
							" Firmware Reload FAILED!!\n"));
					}
				}
			}
		} else {
			dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));

			hd->abortSCpnt = NULL;


		}
	case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
	default:
		break;
	}
	}


 out:
	spin_lock_irqsave(&ioc->FreeQlock, flags);
	spin_lock_irqsave(&ioc->FreeQlock, flags);
	hd->tmPending = 0;
	hd->tmPending = 0;
	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
	hd->tmState = TM_STATE_NONE;
	hd->tmState = TM_STATE_NONE;
	hd->tm_iocstatus = iocstatus;
	spin_unlock_irqrestore(&ioc->FreeQlock, flags);


	return 1;
	return 1;
}
}