diff options
Diffstat (limited to 'drivers/message')
| -rw-r--r-- | drivers/message/fusion/mptbase.c | 177 | ||||
| -rw-r--r-- | drivers/message/fusion/mptbase.h | 5 | ||||
| -rw-r--r-- | drivers/message/fusion/mptctl.c | 181 | ||||
| -rw-r--r-- | drivers/message/fusion/mptfc.c | 22 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 55 | ||||
| -rw-r--r-- | drivers/message/fusion/mptsas.h | 2 | ||||
| -rw-r--r-- | drivers/message/fusion/mptscsih.c | 27 | ||||
| -rw-r--r-- | drivers/message/fusion/mptspi.c | 10 | 
8 files changed, 370 insertions, 109 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5382b5a44af..a6a57011ba6 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -5064,7 +5064,7 @@ mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode)  		if (!timeleft) {  			printk(KERN_DEBUG "%s: Issuing Reset from %s!!\n",  			    ioc->name, __func__); -			mpt_HardResetHandler(ioc, CAN_SLEEP); +			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  			mpt_free_msg_frame(ioc, mf);  		}  		goto out; @@ -6456,10 +6456,15 @@ out:  		issue_hard_reset = 0;  		printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",  		    ioc->name, __func__); -		mpt_HardResetHandler(ioc, CAN_SLEEP); +		if (retry_count == 0) { +			if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0) +				retry_count++; +		} else +			mpt_HardResetHandler(ioc, CAN_SLEEP); +  		mpt_free_msg_frame(ioc, mf);  		/* attempt one retry for a timed out command */ -		if (!retry_count) { +		if (retry_count < 2) {  			printk(MYIOC_s_INFO_FMT  			    "Attempting Retry Config request"  			    " type 0x%x, page 0x%x," @@ -6904,6 +6909,172 @@ mpt_halt_firmware(MPT_ADAPTER *ioc)  }  EXPORT_SYMBOL(mpt_halt_firmware); +/** + *	mpt_SoftResetHandler - Issues a less expensive reset + *	@ioc: Pointer to MPT_ADAPTER structure + *	@sleepFlag: Indicates if sleep or schedule must be called. + + * + *	Returns 0 for SUCCESS or -1 if FAILED. + * + *	Message Unit Reset - instructs the IOC to reset the Reply Post and + *	Free FIFO's. All the Message Frames on Reply Free FIFO are discarded. + *	All posted buffers are freed, and event notification is turned off. + *	IOC doesnt reply to any outstanding request. This will transfer IOC + *	to READY state. + **/ +int +mpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) +{ +	int		 rc; +	int		 ii; +	u8		 cb_idx; +	unsigned long	 flags; +	u32		 ioc_state; +	unsigned long	 time_count; + +	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n", +		ioc->name)); + +	ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK; + +	if (mpt_fwfault_debug) +		mpt_halt_firmware(ioc); + +	if (ioc_state == MPI_IOC_STATE_FAULT || +	    ioc_state == MPI_IOC_STATE_RESET) { +		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT +		    "skipping, either in FAULT or RESET state!\n", ioc->name)); +		return -1; +	} + +	if (ioc->bus_type == FC) { +		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT +		    "skipping, because the bus type is FC!\n", ioc->name)); +		return -1; +	} + +	spin_lock_irqsave(&ioc->taskmgmt_lock, flags); +	if (ioc->ioc_reset_in_progress) { +		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); +		return -1; +	} +	ioc->ioc_reset_in_progress = 1; +	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + +	rc = -1; + +	for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { +		if (MptResetHandlers[cb_idx]) +			mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); +	} + +	spin_lock_irqsave(&ioc->taskmgmt_lock, flags); +	if (ioc->taskmgmt_in_progress) { +		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); +		return -1; +	} +	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); +	/* Disable reply interrupts (also blocks FreeQ) */ +	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); +	ioc->active = 0; +	time_count = jiffies; + +	rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); + +	for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { +		if (MptResetHandlers[cb_idx]) +			mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET); +	} + +	if (rc) +		goto out; + +	ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK; +	if (ioc_state != MPI_IOC_STATE_READY) +		goto out; + +	for (ii = 0; ii < 5; ii++) { +		/* Get IOC facts! Allow 5 retries */ +		rc = GetIocFacts(ioc, sleepFlag, +			MPT_HOSTEVENT_IOC_RECOVER); +		if (rc == 0) +			break; +		if (sleepFlag == CAN_SLEEP) +			msleep(100); +		else +			mdelay(100); +	} +	if (ii == 5) +		goto out; + +	rc = PrimeIocFifos(ioc); +	if (rc != 0) +		goto out; + +	rc = SendIocInit(ioc, sleepFlag); +	if (rc != 0) +		goto out; + +	rc = SendEventNotification(ioc, 1, sleepFlag); +	if (rc != 0) +		goto out; + +	if (ioc->hard_resets < -1) +		ioc->hard_resets++; + +	/* +	 * At this point, we know soft reset succeeded. +	 */ + +	ioc->active = 1; +	CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); + + out: +	spin_lock_irqsave(&ioc->taskmgmt_lock, flags); +	ioc->ioc_reset_in_progress = 0; +	ioc->taskmgmt_quiesce_io = 0; +	ioc->taskmgmt_in_progress = 0; +	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + +	if (ioc->active) {	/* otherwise, hard reset coming */ +		for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { +			if (MptResetHandlers[cb_idx]) +				mpt_signal_reset(cb_idx, ioc, +					MPT_IOC_POST_RESET); +		} +	} + +	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT +		"SoftResetHandler: completed (%d seconds): %s\n", +		ioc->name, jiffies_to_msecs(jiffies - time_count)/1000, +		((rc == 0) ? "SUCCESS" : "FAILED"))); + +	return rc; +} + +/** + *	mpt_Soft_Hard_ResetHandler - Try less expensive reset + *	@ioc: Pointer to MPT_ADAPTER structure + *	@sleepFlag: Indicates if sleep or schedule must be called. + + * + *	Returns 0 for SUCCESS or -1 if FAILED. + *	Try for softreset first, only if it fails go for expensive + *	HardReset. + **/ +int +mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { +	int ret = -1; + +	ret = mpt_SoftResetHandler(ioc, sleepFlag); +	if (ret == 0) +		return ret; +	ret = mpt_HardResetHandler(ioc, sleepFlag); +	return ret; +} +EXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler); +  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/  /*   *	Reset Handling diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 9718c8f2e95..b613eb3d470 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -76,8 +76,8 @@  #define COPYRIGHT	"Copyright (c) 1999-2008 " MODULEAUTHOR  #endif -#define MPT_LINUX_VERSION_COMMON	"3.04.14" -#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.14" +#define MPT_LINUX_VERSION_COMMON	"3.04.15" +#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.04.15"  #define WHAT_MAGIC_STRING		"@" "(" "#" ")"  #define show_mptmod_ver(s,ver)  \ @@ -940,6 +940,7 @@ extern int	 mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp);  extern u32	 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked);  extern void	 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);  extern int	 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag); +extern int	 mpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag);  extern int	 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);  extern int	 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);  extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index caa8f568a41..f06b29193b4 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -128,7 +128,6 @@ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags  		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);  static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,  		struct buflist *buflist, MPT_ADAPTER *ioc); -static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function);  /*   * Reset Handler cleanup function @@ -275,45 +274,6 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)  	return 1;  } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_timeout_expired - * - * Expecting an interrupt, however timed out. - * - */ -static void -mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) -{ -	unsigned long flags; - -	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n", -		ioc->name, __func__)); - -	if (mpt_fwfault_debug) -		mpt_halt_firmware(ioc); - -	spin_lock_irqsave(&ioc->taskmgmt_lock, flags); -	if (ioc->ioc_reset_in_progress) { -		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); -		CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) -		mpt_free_msg_frame(ioc, mf); -		return; -	} -	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); - - -	if (!mptctl_bus_reset(ioc, mf->u.hdr.Function)) -		return; - -	/* Issue a reset for this device. -	 * The IOC is not responding. -	 */ -	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", -		 ioc->name)); -	CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) -	mpt_HardResetHandler(ioc, CAN_SLEEP); -	mpt_free_msg_frame(ioc, mf); -}  static int  mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) @@ -343,12 +303,8 @@ mptctl_taskmgmt_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)  	return 0;  } -/* mptctl_bus_reset - * - * Bus reset code. - * - */ -static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function) +static int +mptctl_do_taskmgmt(MPT_ADAPTER *ioc, u8 tm_type, u8 bus_id, u8 target_id)  {  	MPT_FRAME_HDR	*mf;  	SCSITaskMgmt_t	*pScsiTm; @@ -359,13 +315,6 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  	unsigned long	 time_count;  	u16		 iocstatus; -	/* bus reset is only good for SCSI IO, RAID PASSTHRU */ -	if (!(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || -		function == MPI_FUNCTION_SCSI_IO_REQUEST)) { -		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT -			"TaskMgmt, not SCSI_IO!!\n", ioc->name)); -		return -EPERM; -	}  	mutex_lock(&ioc->taskmgmt_cmds.mutex);  	if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) { @@ -375,15 +324,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  	retval = 0; -	/* Send request -	 */  	mf = mpt_get_msg_frame(mptctl_taskmgmt_id, ioc);  	if (mf == NULL) { -		dtmprintk(ioc, printk(MYIOC_s_WARN_FMT -			"TaskMgmt, no msg frames!!\n", ioc->name)); +		dtmprintk(ioc, +			printk(MYIOC_s_WARN_FMT "TaskMgmt, no msg frames!!\n", +			ioc->name));  		mpt_clear_taskmgmt_in_progress_flag(ioc);  		retval = -ENOMEM; -		goto mptctl_bus_reset_done; +		goto tm_done;  	}  	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n", @@ -392,10 +340,13 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  	pScsiTm = (SCSITaskMgmt_t *) mf;  	memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));  	pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT; -	pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; -	pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; -	pScsiTm->TargetID = 0; -	pScsiTm->Bus = 0; +	pScsiTm->TaskType = tm_type; +	if ((tm_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && +		(ioc->bus_type == FC)) +		pScsiTm->MsgFlags = +				MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION; +	pScsiTm->TargetID = target_id; +	pScsiTm->Bus = bus_id;  	pScsiTm->ChainOffset = 0;  	pScsiTm->Reserved = 0;  	pScsiTm->Reserved1 = 0; @@ -413,17 +364,16 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  		timeout = 30;  		break;  	case SPI: -	default: -		timeout = 2; +		default: +		timeout = 10;  		break;  	} -	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT -		"TaskMgmt type=%d timeout=%ld\n", -		ioc->name, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, timeout)); +	dtmprintk(ioc, +		printk(MYIOC_s_DEBUG_FMT "TaskMgmt type=%d timeout=%ld\n", +		ioc->name, tm_type, timeout));  	INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status) -	CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)  	time_count = jiffies;  	if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) &&  	    (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) @@ -432,17 +382,20 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  		retval = mpt_send_handshake_request(mptctl_taskmgmt_id, ioc,  		    sizeof(SCSITaskMgmt_t), (u32 *)pScsiTm, CAN_SLEEP);  		if (retval != 0) { -			dfailprintk(ioc, printk(MYIOC_s_ERR_FMT +			dfailprintk(ioc, +				printk(MYIOC_s_ERR_FMT  				"TaskMgmt send_handshake FAILED!"  				" (ioc %p, mf %p, rc=%d) \n", ioc->name,  				ioc, mf, retval)); +			mpt_free_msg_frame(ioc, mf);  			mpt_clear_taskmgmt_in_progress_flag(ioc); -			goto mptctl_bus_reset_done; +			goto tm_done;  		}  	}  	/* Now wait for the command to complete */  	ii = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done, timeout*HZ); +  	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {  		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT  		    "TaskMgmt failed\n", ioc->name)); @@ -452,14 +405,14 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  			retval = 0;  		else  			retval = -1; /* return failure */ -		goto mptctl_bus_reset_done; +		goto tm_done;  	}  	if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {  		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT  		    "TaskMgmt failed\n", ioc->name));  		retval = -1; /* return failure */ -		goto mptctl_bus_reset_done; +		goto tm_done;  	}  	pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply; @@ -467,7 +420,7 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  	    "TaskMgmt fw_channel = %d, fw_id = %d, task_type=0x%02X, "  	    "iocstatus=0x%04X\n\tloginfo=0x%08X, response_code=0x%02X, "  	    "term_cmnds=%d\n", ioc->name, pScsiTmReply->Bus, -	    pScsiTmReply->TargetID, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, +	    pScsiTmReply->TargetID, tm_type,  	    le16_to_cpu(pScsiTmReply->IOCStatus),  	    le32_to_cpu(pScsiTmReply->IOCLogInfo),  	    pScsiTmReply->ResponseCode, @@ -485,13 +438,71 @@ static int mptctl_bus_reset(MPT_ADAPTER *ioc, u8 function)  		retval = -1; /* return failure */  	} - - mptctl_bus_reset_done: + tm_done:  	mutex_unlock(&ioc->taskmgmt_cmds.mutex);  	CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)  	return retval;  } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* mptctl_timeout_expired + * + * Expecting an interrupt, however timed out. + * + */ +static void +mptctl_timeout_expired(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) +{ +	unsigned long flags; +	int ret_val = -1; +	SCSIIORequest_t *scsi_req = (SCSIIORequest_t *) mf; +	u8 function = mf->u.hdr.Function; + +	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": %s\n", +		ioc->name, __func__)); + +	if (mpt_fwfault_debug) +		mpt_halt_firmware(ioc); + +	spin_lock_irqsave(&ioc->taskmgmt_lock, flags); +	if (ioc->ioc_reset_in_progress) { +		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); +		CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) +		mpt_free_msg_frame(ioc, mf); +		return; +	} +	spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); + + +	CLEAR_MGMT_PENDING_STATUS(ioc->ioctl_cmds.status) + +	if (ioc->bus_type == SAS) { +		if (function == MPI_FUNCTION_SCSI_IO_REQUEST) +			ret_val = mptctl_do_taskmgmt(ioc, +				MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, +				scsi_req->Bus, scsi_req->TargetID); +		else if (function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) +			ret_val = mptctl_do_taskmgmt(ioc, +				MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, +				scsi_req->Bus, 0); +		if (!ret_val) +			return; +	} else { +		if ((function == MPI_FUNCTION_SCSI_IO_REQUEST) || +			(function == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) +			ret_val = mptctl_do_taskmgmt(ioc, +				MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, +				scsi_req->Bus, 0); +		if (!ret_val) +			return; +	} + +	dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling Reset! \n", +		 ioc->name)); +	mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); +	mpt_free_msg_frame(ioc, mf); +} +  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/  /* mptctl_ioc_reset @@ -1318,6 +1329,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)  	if (ioc->sh) {  		shost_for_each_device(sdev, ioc->sh) {  			vdevice = sdev->hostdata; +			if (vdevice == NULL || vdevice->vtarget == NULL) +				continue;  			if (vdevice->vtarget->tflags &  			    MPT_TARGET_FLAGS_RAID_COMPONENT)  				continue; @@ -1439,6 +1452,8 @@ mptctl_gettargetinfo (unsigned long arg)  			if (!maxWordsLeft)  				continue;  			vdevice = sdev->hostdata; +			if (vdevice == NULL || vdevice->vtarget == NULL) +				continue;  			if (vdevice->vtarget->tflags &  			    MPT_TARGET_FLAGS_RAID_COMPONENT)  				continue; @@ -1967,6 +1982,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)  				struct scsi_target *starget = scsi_target(sdev);  				VirtTarget *vtarget = starget->hostdata; +				if (vtarget == NULL) +					continue; +  				if ((pScsiReq->TargetID == vtarget->id) &&  				    (pScsiReq->Bus == vtarget->channel) &&  				    (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) @@ -2991,6 +3009,14 @@ static int __init mptctl_init(void)  	}  	mptctl_taskmgmt_id = mpt_register(mptctl_taskmgmt_reply, MPTCTL_DRIVER); +	if (!mptctl_taskmgmt_id || mptctl_taskmgmt_id >= MPT_MAX_PROTOCOL_DRIVERS) { +		printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); +		mpt_deregister(mptctl_id); +		misc_deregister(&mptctl_miscdev); +		err = -EBUSY; +		goto out_fail; +	} +  	mpt_reset_register(mptctl_id, mptctl_ioc_reset);  	mpt_event_register(mptctl_id, mptctl_event_process); @@ -3010,12 +3036,15 @@ static void mptctl_exit(void)  	printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",  			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor); +	/* De-register event handler from base module */ +	mpt_event_deregister(mptctl_id); +  	/* De-register reset handler from base module */  	mpt_reset_deregister(mptctl_id);  	/* De-register callback handler from base module */ +	mpt_deregister(mptctl_taskmgmt_id);  	mpt_deregister(mptctl_id); -	mpt_reset_deregister(mptctl_taskmgmt_id);          mpt_device_driver_deregister(MPTCTL_DRIVER); diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 33f7256055b..b5f03ad8156 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -482,6 +482,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)  				if (vtarget) {  					vtarget->id = pg0->CurrentTargetID;  					vtarget->channel = pg0->CurrentBus; +					vtarget->deleted = 0;  				}  			}  			*((struct mptfc_rport_info **)rport->dd_data) = ri; @@ -1092,6 +1093,8 @@ mptfc_setup_reset(struct work_struct *work)  		container_of(work, MPT_ADAPTER, fc_setup_reset_work);  	u64			pn;  	struct mptfc_rport_info *ri; +	struct scsi_target      *starget; +	VirtTarget              *vtarget;  	/* reset about to happen, delete (block) all rports */  	list_for_each_entry(ri, &ioc->fc_rports, list) { @@ -1099,6 +1102,12 @@ mptfc_setup_reset(struct work_struct *work)  			ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;  			fc_remote_port_delete(ri->rport);	/* won't sleep */  			ri->rport = NULL; +			starget = ri->starget; +			if (starget) { +				vtarget = starget->hostdata; +				if (vtarget) +					vtarget->deleted = 1; +			}  			pn = (u64)ri->pg0.WWPN.High << 32 |  			     (u64)ri->pg0.WWPN.Low; @@ -1119,6 +1128,8 @@ mptfc_rescan_devices(struct work_struct *work)  	int			ii;  	u64			pn;  	struct mptfc_rport_info *ri; +	struct scsi_target      *starget; +	VirtTarget              *vtarget;  	/* start by tagging all ports as missing */  	list_for_each_entry(ri, &ioc->fc_rports, list) { @@ -1146,6 +1157,12 @@ mptfc_rescan_devices(struct work_struct *work)  				       MPT_RPORT_INFO_FLAGS_MISSING);  			fc_remote_port_delete(ri->rport);	/* won't sleep */  			ri->rport = NULL; +			starget = ri->starget; +			if (starget) { +				vtarget = starget->hostdata; +				if (vtarget) +					vtarget->deleted = 1; +			}  			pn = (u64)ri->pg0.WWPN.High << 32 |  			     (u64)ri->pg0.WWPN.Low; @@ -1358,6 +1375,9 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)  	unsigned long flags;  	int rc=1; +	if (ioc->bus_type != FC) +		return 0; +  	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",  			ioc->name, event)); @@ -1396,7 +1416,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)  	unsigned long	flags;  	rc = mptscsih_ioc_reset(ioc,reset_phase); -	if (rc == 0) +	if ((ioc->bus_type != FC) || (!rc))  		return rc; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 76687126b57..ac000e83db0 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1894,7 +1894,7 @@ static struct scsi_host_template mptsas_driver_template = {  	.module				= THIS_MODULE,  	.proc_name			= "mptsas",  	.proc_info			= mptscsih_proc_info, -	.name				= "MPT SPI Host", +	.name				= "MPT SAS Host",  	.info				= mptscsih_info,  	.queuecommand			= mptsas_qcmd,  	.target_alloc			= mptsas_target_alloc, @@ -2038,11 +2038,13 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)  	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,  			10 * HZ); -	if (!timeleft) { -		/* On timeout reset the board */ +	if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { +		error = -ETIME;  		mpt_free_msg_frame(ioc, mf); -		mpt_HardResetHandler(ioc, CAN_SLEEP); -		error = -ETIMEDOUT; +		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET) +			goto out_unlock; +		if (!timeleft) +			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  		goto out_unlock;  	} @@ -2223,11 +2225,14 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,  	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);  	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); -	if (!timeleft) { -		printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__); -		/* On timeout reset the board */ -		mpt_HardResetHandler(ioc, CAN_SLEEP); -		ret = -ETIMEDOUT; +	if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { +		ret = -ETIME; +		mpt_free_msg_frame(ioc, mf); +		mf = NULL; +		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET) +			goto unmap; +		if (!timeleft) +			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  		goto unmap;  	}  	mf = NULL; @@ -2518,6 +2523,12 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,  	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;  	error = mpt_config(ioc, &cfg); + +	if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { +		error = -ENODEV; +		goto out_free_consistent; +	} +  	if (error)  		goto out_free_consistent; @@ -2594,14 +2605,14 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,  	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;  	error = mpt_config(ioc, &cfg); -	if (error) -		goto out_free_consistent; - -	if (!buffer->NumPhys) { +	if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {  		error = -ENODEV;  		goto out_free_consistent;  	} +	if (error) +		goto out_free_consistent; +  	/* save config data */  	port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;  	port_info->phy_info = kcalloc(port_info->num_phys, @@ -2677,7 +2688,7 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,  	if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {  		error = -ENODEV; -		goto out; +		goto out_free_consistent;  	}  	if (error) @@ -2833,7 +2844,7 @@ mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,  		if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)  			goto out_free;  		if (!timeleft) -			mpt_HardResetHandler(ioc, CAN_SLEEP); +			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  		goto out_free;  	} @@ -4098,6 +4109,7 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)  	cfg.pageAddr = (channel << 8) + id;  	cfg.cfghdr.hdr = &hdr;  	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; +	cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;  	if (mpt_config(ioc, &cfg) != 0)  		goto out; @@ -4717,7 +4729,7 @@ mptsas_broadcast_primative_work(struct fw_event_work *fw_event)  	if (issue_reset) {  		printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",  		    ioc->name, __func__); -		mpt_HardResetHandler(ioc, CAN_SLEEP); +		mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  	}  	mptsas_free_fw_event(ioc, fw_event);  } @@ -4779,6 +4791,9 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)  	struct fw_event_work *fw_event;  	unsigned long delay; +	if (ioc->bus_type != SAS) +		return 0; +  	/* events turned off due to host reset or driver unloading */  	if (ioc->fw_events_off)  		return 0; @@ -5073,6 +5088,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)  	struct mptsas_portinfo *p, *n;  	int i; +	if (!ioc->sh) { +		printk(MYIOC_s_INFO_FMT "IOC is in Target mode\n", ioc->name); +		mpt_detach(pdev); +		return; +	} +  	mptsas_shutdown(pdev);  	mptsas_del_device_components(ioc); diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index 953c2bfcf6a..7b249edbda7 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h @@ -110,7 +110,7 @@ struct fw_event_work {  	MPT_ADAPTER	*ioc;  	u32			event;  	u8			retries; -	u8			event_data[1]; +	u8			__attribute__((aligned(4))) event_data[1];  };  struct mptsas_discovery_event { diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 6796597dcee..7bd4c0fc23c 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1149,11 +1149,6 @@ mptscsih_remove(struct pci_dev *pdev)  	MPT_SCSI_HOST		*hd;  	int sz1; -	if(!host) { -		mpt_detach(pdev); -		return; -	} -  	scsi_remove_host(host);  	if((hd = shost_priv(host)) == NULL) @@ -1711,7 +1706,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun,  	if (issue_hard_reset) {  		printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",  			ioc->name, __func__); -		retval = mpt_HardResetHandler(ioc, CAN_SLEEP); +		retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  		mpt_free_msg_frame(ioc, mf);  	} @@ -1728,6 +1723,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc)  	case FC:  		return 40;  	case SAS: +		return 30;  	case SPI:  	default:  		return 10; @@ -1777,7 +1773,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)  		    ioc->name, SCpnt));  		SCpnt->result = DID_NO_CONNECT << 16;  		SCpnt->scsi_done(SCpnt); -		retval = 0; +		retval = SUCCESS;  		goto out;  	} @@ -1792,6 +1788,17 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)  		goto out;  	} +	/* Task aborts are not supported for volumes. +	 */ +	if (vdevice->vtarget->raidVolume) { +		dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT +		    "task abort: raid volume (sc=%p)\n", +		    ioc->name, SCpnt)); +		SCpnt->result = DID_RESET << 16; +		retval = FAILED; +		goto out; +	} +  	/* Find this command  	 */  	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { @@ -1991,7 +1998,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)  	/*  If our attempts to reset the host failed, then return a failed  	 *  status.  The host will be taken off line by the SCSI mid-layer.  	 */ -    retval = mpt_HardResetHandler(ioc, CAN_SLEEP); +    retval = mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  	if (retval < 0)  		status = FAILED;  	else @@ -2344,6 +2351,8 @@ mptscsih_slave_destroy(struct scsi_device *sdev)  	starget = scsi_target(sdev);  	vtarget = starget->hostdata;  	vdevice = sdev->hostdata; +	if (!vdevice) +		return;  	mptscsih_search_running_cmds(hd, vdevice);  	vtarget->num_luns--; @@ -3040,7 +3049,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)  		if (!timeleft) {  			printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n",  			    ioc->name, __func__); -			mpt_HardResetHandler(ioc, CAN_SLEEP); +			mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);  			mpt_free_msg_frame(ioc, mf);  		}  		goto out; diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index e44365193fd..1abaa5d01ae 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -210,6 +210,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target,  	target->maxOffset = offset;  	target->maxWidth = width; +	spi_min_period(scsi_target(sdev)) = factor; +	spi_max_offset(scsi_target(sdev)) = offset; +	spi_max_width(scsi_target(sdev)) = width; +  	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;  	/* Disable unused features. @@ -558,6 +562,7 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget,  	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;  	cfg.dir = 0;  	cfg.pageAddr = starget->id; +	cfg.timeout = 60;  	if (mpt_config(ioc, &cfg)) {  		starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name); @@ -1152,6 +1157,9 @@ mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)  	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;  	struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); +	if (ioc->bus_type != SPI) +		return 0; +  	if (hd && event ==  MPI_EVENT_INTEGRATED_RAID) {  		int reason  			= (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; @@ -1283,6 +1291,8 @@ mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)  	int rc;  	rc = mptscsih_ioc_reset(ioc, reset_phase); +	if ((ioc->bus_type != SPI) || (!rc)) +		return rc;  	/* only try to do a renegotiation if we're properly set up  	 * if we get an ioc fault on bringup, ioc->sh will be NULL */  |