⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mptscsih.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (ioc->bus_type != SAS)		return;	/* Not supported for hidden raid components	 */	if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)		return;	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {		dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: no msg frames!!\n",		    ioc->name,__FUNCTION__));		return;	}	SEPMsg = (SEPRequest_t *)mf;	SEPMsg->Function = MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;	SEPMsg->Bus = vtarget->channel;	SEPMsg->TargetID = vtarget->id;	SEPMsg->Action = MPI_SEP_REQ_ACTION_WRITE_STATUS;	SEPMsg->SlotStatus = SlotStatus;	devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT	    "Sending SEP cmd=%x channel=%d id=%d\n",	    ioc->name, SlotStatus, SEPMsg->Bus, SEPMsg->TargetID));	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);}#ifdef CONFIG_FUSION_LOGGING/** *	mptscsih_info_scsiio - debug print info on reply frame *	@ioc: Pointer to MPT_ADAPTER structure *	@sc: original scsi cmnd pointer *	@pScsiReply: Pointer to MPT reply frame * *	MPT_DEBUG_REPLY needs to be enabled to obtain this info * *	Refer to lsi/mpi.h. **/static voidmptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pScsiReply){	char	*desc = NULL;	char	*desc1 = NULL;	u16	ioc_status;	u8	skey, asc, ascq;	ioc_status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;	switch (ioc_status) {	case MPI_IOCSTATUS_SUCCESS:		desc = "success";		break;	case MPI_IOCSTATUS_SCSI_INVALID_BUS:		desc = "invalid bus";		break;	case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:		desc = "invalid target_id";		break;	case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:		desc = "device not there";		break;	case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		desc = "data overrun";		break;	case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		desc = "data underrun";		break;	case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		desc = "I/O data error";		break;	case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:		desc = "protocol error";		break;	case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:		desc = "task terminated";		break;	case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:		desc = "residual mismatch";		break;	case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:		desc = "task management failed";		break;	case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		desc = "IOC terminated";		break;	case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		desc = "ext terminated";		break;	default:		desc = "";		break;	}	switch (pScsiReply->SCSIStatus)	{	case MPI_SCSI_STATUS_SUCCESS:		desc1 = "success";		break;	case MPI_SCSI_STATUS_CHECK_CONDITION:		desc1 = "check condition";		break;	case MPI_SCSI_STATUS_CONDITION_MET:		desc1 = "condition met";		break;	case MPI_SCSI_STATUS_BUSY:		desc1 = "busy";		break;	case MPI_SCSI_STATUS_INTERMEDIATE:		desc1 = "intermediate";		break;	case MPI_SCSI_STATUS_INTERMEDIATE_CONDMET:		desc1 = "intermediate condmet";		break;	case MPI_SCSI_STATUS_RESERVATION_CONFLICT:		desc1 = "reservation conflict";		break;	case MPI_SCSI_STATUS_COMMAND_TERMINATED:		desc1 = "command terminated";		break;	case MPI_SCSI_STATUS_TASK_SET_FULL:		desc1 = "task set full";		break;	case MPI_SCSI_STATUS_ACA_ACTIVE:		desc1 = "aca active";		break;	case MPI_SCSI_STATUS_FCPEXT_DEVICE_LOGGED_OUT:		desc1 = "fcpext device logged out";		break;	case MPI_SCSI_STATUS_FCPEXT_NO_LINK:		desc1 = "fcpext no link";		break;	case MPI_SCSI_STATUS_FCPEXT_UNASSIGNED:		desc1 = "fcpext unassigned";		break;	default:		desc1 = "";		break;	}	scsi_print_command(sc);	printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n",	    ioc->name, pScsiReply->Bus, pScsiReply->TargetID);	printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, "	    "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow,	    scsi_get_resid(sc));	printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, "	    "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag),	    le32_to_cpu(pScsiReply->TransferCount), sc->result);	printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), "	    "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n",	    ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus,	    pScsiReply->SCSIState);	if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {		skey = sc->sense_buffer[2] & 0x0F;		asc = sc->sense_buffer[12];		ascq = sc->sense_buffer[13];		printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: "		    "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq);	}	/*	 *  Look for + dump FCP ResponseInfo[]!	 */	if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&	    pScsiReply->ResponseInfo)		printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n",		    ioc->name, le32_to_cpu(pScsiReply->ResponseInfo));}#endif/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptscsih_io_done - Main SCSI IO callback routine registered to *	Fusion MPT (base) driver *	@ioc: Pointer to MPT_ADAPTER structure *	@mf: Pointer to original MPT request frame *	@r: Pointer to MPT reply frame (NULL if TurboReply) * *	This routine is called from mpt.c::mpt_interrupt() at the completion *	of any SCSI IO request. *	This routine is registered with the Fusion MPT (base) driver at driver *	load/init time via the mpt_register() API call. * *	Returns 1 indicating alloc'd request frame ptr should be freed. */intmptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr){	struct scsi_cmnd	*sc;	MPT_SCSI_HOST	*hd;	SCSIIORequest_t	*pScsiReq;	SCSIIOReply_t	*pScsiReply;	u16		 req_idx, req_idx_MR;	VirtDevice	 *vdevice;	VirtTarget	 *vtarget;	hd = shost_priv(ioc->sh);	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);	req_idx_MR = (mr != NULL) ?	    le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx;	if ((req_idx != req_idx_MR) ||	    (mf->u.frame.linkage.arg1 == 0xdeadbeaf)) {		printk(MYIOC_s_ERR_FMT "Received a mf that was already freed\n",		    ioc->name);		printk (MYIOC_s_ERR_FMT		    "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n",		    ioc->name, req_idx, req_idx_MR, mf, mr,		    mptscsih_get_scsi_lookup(ioc, req_idx_MR));		return 0;	}	sc = mptscsih_getclear_scsi_lookup(ioc, req_idx);	if (sc == NULL) {		MPIHeader_t *hdr = (MPIHeader_t *)mf;		/* Remark: writeSDP1 will use the ScsiDoneCtx		 * If a SCSI I/O cmd, device disabled by OS and		 * completion done. Cannot touch sc struct. Just free mem.		 */		if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)			printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",			ioc->name);		mptscsih_freeChainBuffers(ioc, req_idx);		return 1;	}	if ((unsigned char *)mf != sc->host_scribble) {		mptscsih_freeChainBuffers(ioc, req_idx);		return 1;	}	sc->host_scribble = NULL;	sc->result = DID_OK << 16;		/* Set default reply as OK */	pScsiReq = (SCSIIORequest_t *) mf;	pScsiReply = (SCSIIOReply_t *) mr;	if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){		dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT			"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",			ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));	}else{		dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT			"ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",			ioc->name, mf, mr, sc, req_idx));	}	if (pScsiReply == NULL) {		/* special context reply handling */		;	} else {		u32	 xfer_cnt;		u16	 status;		u8	 scsi_state, scsi_status;		u32	 log_info;		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;		scsi_state = pScsiReply->SCSIState;		scsi_status = pScsiReply->SCSIStatus;		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);		scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);		log_info = le32_to_cpu(pScsiReply->IOCLogInfo);		/*		 *  if we get a data underrun indication, yet no data was		 *  transferred and the SCSI status indicates that the		 *  command was never started, change the data underrun		 *  to success		 */		if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&		    (scsi_status == MPI_SCSI_STATUS_BUSY ||		     scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT ||		     scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) {			status = MPI_IOCSTATUS_SUCCESS;		}		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)			mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);		/*		 *  Look for + dump FCP ResponseInfo[]!		 */		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID &&		    pScsiReply->ResponseInfo) {			printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] "			"FCP_ResponseInfo=%08xh\n", ioc->name,			sc->device->host->host_no, sc->device->channel,			sc->device->id, sc->device->lun,			le32_to_cpu(pScsiReply->ResponseInfo));		}		switch(status) {		case MPI_IOCSTATUS_BUSY:			/* 0x0002 */			/* CHECKME!			 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)			 * But not: DID_BUS_BUSY lest one risk			 * killing interrupt handler:-(			 */			sc->result = SAM_STAT_BUSY;			break;		case MPI_IOCSTATUS_SCSI_INVALID_BUS:		/* 0x0041 */		case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:	/* 0x0042 */			sc->result = DID_BAD_TARGET << 16;			break;		case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:	/* 0x0043 */			/* Spoof to SCSI Selection Timeout! */			if (ioc->bus_type != FC)				sc->result = DID_NO_CONNECT << 16;			/* else fibre, just stall until rescan event */			else				sc->result = DID_REQUEUE << 16;			if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)				hd->sel_timeout[pScsiReq->TargetID]++;			vdevice = sc->device->hostdata;			if (!vdevice)				break;			vtarget = vdevice->vtarget;			if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) {				mptscsih_issue_sep_command(ioc, vtarget,				    MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED);				vtarget->tflags &= ~MPT_TARGET_FLAGS_LED_ON;			}			break;		case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:		/* 0x004B */			if ( ioc->bus_type == SAS ) {				u16 ioc_status = le16_to_cpu(pScsiReply->IOCStatus);				if (ioc_status & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {					if ((log_info & SAS_LOGINFO_MASK)					    == SAS_LOGINFO_NEXUS_LOSS) {						sc->result = (DID_BUS_BUSY << 16);						break;					}				}			} else if (ioc->bus_type == FC) {				/*				 * The FC IOC may kill a request for variety of				 * reasons, some of which may be recovered by a				 * retry, some which are unlikely to be				 * recovered. Return DID_ERROR instead of				 * DID_RESET to permit retry of the command,				 * just not an infinite number of them				 */				sc->result = DID_ERROR << 16;				break;			}			/*			 * Allow non-SAS & non-NEXUS_LOSS to drop into below code			 */		case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:	/* 0x0048 */		case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:		/* 0x004C */			/* Linux handles an unsolicited DID_RESET better			 * than an unsolicited DID_ABORT.			 */			sc->result = DID_RESET << 16;			break;		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */			scsi_set_resid(sc, scsi_bufflen(sc) - xfer_cnt);			if((xfer_cnt==0)||(sc->underflow > xfer_cnt))				sc->result=DID_SOFT_ERROR << 16;			else /* Sufficient data transfer occurred */				sc->result = (DID_OK << 16) | scsi_status;			dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT			    "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n",			    ioc->name, sc->result, sc->device->channel, sc->device->id));			break;		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */			/*			 *  Do upfront check for valid SenseData and give it			 *  precedence!			 */			sc->result = (DID_OK << 16) | scsi_status;			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {				/* Have already saved the status and sense data				 */				;			} else {				if (xfer_cnt < sc->underflow) {					if (scsi_status == SAM_STAT_BUSY)						sc->result = SAM_STAT_BUSY;					else						sc->result = DID_SOFT_ERROR << 16;				}				if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {					/* What to do?				 	*/					sc->result = DID_SOFT_ERROR << 16;				}				else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {					/*  Not real sure here either...  */					sc->result = DID_RESET << 16;				}			}			dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT			    "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",			    ioc->name, sc->underflow));			dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT			    "  ActBytesXferd=%02xh\n", ioc->name, xfer_cnt));			/* Report Queue Full			 */			if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)				mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);			break;		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */			scsi_set_resid(sc, 0);		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */			sc->result = (DID_OK << 16) | scsi_status;			if (scsi_state == 0) {				;			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {				/*				 * If running against circa 200003dd 909 MPT f/w,				 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL				 * (QUEUE_FULL) returned from device! --> get 0x0000?128				 * and with SenseBytes set to 0.				 */				if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)					mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);			}			else if (scsi_state &			         (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)			   ) {				/*				 * What to do?				 */				sc->result = DID_SOFT_ERROR << 16;			}			else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {				/*  Not real sure here either...  */				sc->result = DID_RESET << 16;			}			else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -